Backend
Django views, is_spa_enabled feature flag, URL mapping, login flow, and template serving for the SPA.
Backend
Architecture Overview
The SPA backend is entirely within livehealthapp (Django/Py2). It handles three responsibilities: controlling which labs get SPA vs. legacy builds via a Redis feature flag, serving the SPA HTML template, and routing login redirects to the correct URL.
System Design Diagram
The is_spa_enabled() Function
Source: labs/cacheFunction.py
This is the central feature flag that controls SPA vs. legacy mode. It's a simple Redis cache lookup:
def is_spa_enabled(lab_id):
"""
Flag will be used to get/set SPA (Single Page App).
"""
if not lab_id:
return False
cache_key = "is_spa_enabled_{lab_id}".format(lab_id=lab_id)
return cache.get(cache_key) or FalseKey Characteristics
| Property | Value |
|---|---|
| Storage | Redis (Django cache backend) |
| Key format | is_spa_enabled_{lab_id} |
| Default | False (absent key = SPA disabled) |
| TTL | No expiry — persists until explicitly deleted |
| Set by | Account creation (selfserved/account_creation/account.py) or manually via Redis CLI |
CrelioDashboardView
Source: livehealth_4/views.py
This is the Django view that serves the SPA HTML:
class CrelioDashboardView(View):
def get(self, request, *args, **kwargs):
lab_id = request.session.get('labId')
is_support_login = request.session.get('isSupportLogin')
if not lab_id or not (is_spa_enabled(lab_id) or is_support_login):
return HttpResponseRedirect('/')
rendered_html = render(
request,
'build_assets/dashboard/build/crelio-dashboard.html'
)
return prepare_favicon_change_response(request, rendered_html)Access Control
| Check | Purpose |
|---|---|
lab_id must exist | Rejects unauthenticated requests |
is_spa_enabled(lab_id) OR is_support_login | Only SPA-enabled labs or support users can access |
Falls back to HttpResponseRedirect('/') | Non-SPA labs hitting /crelio-dashboard/ are sent to the login page |
Support users (isSupportLogin = True) always get access to the SPA, regardless of whether the lab has is_spa_enabled set. This is intentional — support needs the unified view for faster debugging.
Login Flow — URL Resolution
The login flow determines the user's loginURL based on their role and SPA status. This happens in multiple places across the codebase.
Session Helpers
Source: logins/utils/session_helpers.py
The session builder determines where a user lands after login:
# For operations staff
login_url = "/crelio-dashboard/#/operation" if is_spa_enabled(user.labId) else '/waitingList/'
# For accession staff
login_url = "/crelio-dashboard/#/accession/" if is_spa_enabled(user.labId) else "/sample-accession/"
# For finance staff
login_url = "/crelio-dashboard/#/finance/dashboard" if is_spa_enabled(user.labId) else "/finance-new/#/dashboard"
# For registration staff
login_url = "/crelio-dashboard/#/registration/directRegistration" if is_spa_enabled(user.labId) else "/billing/#directRegistration"
# For inventory staff
login_url = "/crelio-dashboard/#/inventory/inventory-dashboard" if is_spa_enabled(user.labId) else "/inventory-v5/"The is_spa_enabled flag is also stored in the session itself for frontend and template access:
# In session_helpers.py - get_lab_user_session()
"is_spa_enabled": is_spa_enabled(getattr(user, "labId_id", False)) or False,SPA URL Mapper
Source: livehealth_4/decorators/utils.py
SPA_URL_MAPPER = {
"/accountOverview/": "/crelio-dashboard/#/admin/account-overview",
"/billing/#directRegistration": "/crelio-dashboard/#/registration/",
"/waitingList/": "/crelio-dashboard/#/operation",
"/finance-new/#/dashboard": "/crelio-dashboard/#/finance/",
"/sample-accession/": "/crelio-dashboard/#/accession/",
"/inventory-v5/": "/crelio-dashboard/#/inventory",
"/crm/dashboard/": "/crelio-dashboard/#/crm",
"/referral-management/": "/crelio-dashboard/#/finance/referral-management/referral-list",
"/adminTestList-v5/#/admin/account-overview": "/crelio-dashboard/#/admin/account-overview"
}This dictionary maps every legacy module URL to its SPA equivalent. It's used by the mapped_spa_url() function during login and lab-switching.
Version Detection — v4 vs v5
Before any SPA logic runs, the system first determines whether the lab is on v4 (legacy app) or v5 (React builds). This is controlled by two session values:
| Condition | Version | UI |
|---|---|---|
reactVersionAccess == 1 | v5 | React single-build modules |
newRegistrationPage == 3 | v5 | React registration and accession builds |
| Neither of the above | v4 | Legacy app |
v5 is the prerequisite for SPA. A lab must be on v5 before it can be SPA-enabled. Labs on v4 always receive the legacy app regardless of the is_spa_enabled flag.
Within v5, the SPA is an additional opt-in controlled by the is_spa_enabled Redis flag:
| Version | is_spa_enabled | What the user gets |
|---|---|---|
| v4 | N/A | Legacy app |
| v5 | False (or absent) | React single-build modules (one HTML per module) |
| v5 | True | SPA — unified crelio-dashboard.html for all modules |
The mapped_spa_url() Function
Source: livehealth_4/decorators/version_decorator.py
This function translates legacy loginURL values to SPA URLs during lab switching. It checks version first, then SPA eligibility:
def mapped_spa_url(session, lab_id, use_spa_routing=False):
if not session or not lab_id:
return "/"
login_url = session.get('loginURL')
react_version_access = session.get("reactVersionAccess")
new_registration_page = session.get("newRegistrationPage")
is_support_login = session.get('isSupportLogin')
# Step 1: Version check — v5 non-SPA builds return URL as-is
# reactVersionAccess == 1 OR newRegistrationPage == 2 → v5 but not SPA-eligible
if any([react_version_access == 1, new_registration_page == 2]):
return login_url
# Step 2: Lab switch with SPA enabled
if use_spa_routing and is_spa_enabled(lab_id):
return SPA_URL_MAPPER.get(login_url) or login_url
# Step 3: Normal login — check if v5 SPA-eligible
# reactVersionAccess == 2 OR newRegistrationPage == 3 → v5 SPA-eligible
if is_spa_enabled(lab_id) and (
react_version_access == 2 or
new_registration_page == 3
) or is_support_login:
return SPA_URL_MAPPER.get(login_url) or login_url
return login_urlDecision Tree
The asset_provider Decorator
Source: livehealth_4/decorators/version_decorator.py
For legacy module views that support multiple build versions (v4 Jinja templates vs. v5 React builds), the asset_provider decorator determines which template to render:
@access_labUser()
@asset_provider("accession")
def sample_accession_v4_view(request, template):
rendered_html = render(request, template, {...})
return prepare_favicon_change_response(request, rendered_html)| Module | Version Key | Version 0-2 | Version 3-4 |
|---|---|---|---|
| Registration | defaultRegistrationPage | Jinja templates | build_assets/dashboard/build/registration.html |
| Accession | defaultRegistrationPage | Jinja templates | build_assets/dashboard/build/accession.html |
| Operations | reactVersionAccess | Jinja templates | build_assets/dashboard/build/operations.html |
| Finance | reactVersionAccess | Jinja templates | build_assets/dashboard/build/finance.html |
The asset_provider handles v4 → v5 template resolution for the legacy single-build mode. It does not handle SPA routing — that's done via the login flow and CrelioDashboardView.
Template Serving — SPA vs. Legacy
| Aspect | SPA Mode | Legacy Single-Build Mode |
|---|---|---|
| Template served | crelio-dashboard.html | registration.html, operations.html, etc. |
| Django views hit | Single CrelioDashboardView | Module-specific views (registration_view_v5, etc.) |
| Module switching | Client-side hash route change | Full browser navigation → Django → new template |
| Static assets | Single JS bundle (with code-split chunks) | Per-module JS bundles |
| Public path | /static/build_assets/CrelioDashboard/build/ | /static/build_assets/dashboard/build/ |
Key Backend Locations
| File | Purpose |
|---|---|
labs/cacheFunction.py | is_spa_enabled() — Redis feature flag lookup |
livehealth_4/views.py | CrelioDashboardView — serves crelio-dashboard.html |
livehealth_4/decorators/version_decorator.py | mapped_spa_url(), asset_provider decorator |
livehealth_4/decorators/utils.py | SPA_URL_MAPPER, ASSET_MAPPER dictionaries |
logins/utils/session_helpers.py | Login URL resolution with is_spa_enabled checks |
logins/views.py | Login view with SPA session setup |
selfserved/account_creation/account.py | Sets is_spa_enabled for newly created labs |