gateway/docs/frontend_options_usage.md
2025-12-07 23:51:05 +01:00

6.5 KiB

Frontend Options Usage Guide

Overview

The frontend_options attribute in Pydantic Field definitions supports two formats for providing options to frontend select/multiselect fields:

  1. Static List: Predefined list of options
  2. String Reference: Dynamic options fetched from the Options API

Type System

The type system is defined in gateway/modules/shared/frontendOptionsTypes.py:

from modules.shared.frontendOptionsTypes import FrontendOptions, OptionItem

# FrontendOptions is Union[List[OptionItem], str]
# OptionItem is Dict[str, Any] with "value" and "label" keys

Format 1: Static List

Use static lists for fixed, predefined options that don't change based on user context.

Example

from pydantic import Field
from typing import List

language: str = Field(
    default="en",
    description="Preferred language",
    json_schema_extra={
        "frontend_type": "select",
        "frontend_readonly": False,
        "frontend_required": True,
        "frontend_options": [
            {"value": "en", "label": {"en": "English", "fr": "Anglais"}},
            {"value": "fr", "label": {"en": "Français", "fr": "Français"}},
            {"value": "de", "label": {"en": "Deutsch", "fr": "Allemand"}},
        ]
    }
)

When to Use Static Lists

  • Options are fixed constants (e.g., enum values)
  • Options don't require database queries
  • Options are the same for all users
  • Options are simple and don't change frequently

Format 2: String Reference

Use string references for dynamic options that come from the database or are context-aware.

Example

from pydantic import Field
from typing import List

roleLabels: List[str] = Field(
    default_factory=list,
    description="List of role labels",
    json_schema_extra={
        "frontend_type": "multiselect",
        "frontend_readonly": False,
        "frontend_required": True,
        "frontend_options": "user.role"  # String reference
    }
)

When to Use String References

  • Options come from the database (e.g., user connections)
  • Options are context-aware (filtered by current user's permissions)
  • Options need centralized management
  • Options may change frequently
  • Options depend on user context or permissions

Frontend Integration

When the frontend encounters a string reference:

  1. Detect: Check if frontend_options is a string (not a list)
  2. Fetch: Call GET /api/options/{optionsName} (e.g., /api/options/user.role)
  3. Use: Use the returned options for the select/multiselect field

Example Frontend Code:

// Pseudocode
if (typeof field.frontend_options === 'string') {
    // Dynamic options - fetch from API
    const options = await fetch(`/api/options/${field.frontend_options}`);
    return options;
} else {
    // Static options - use directly
    return field.frontend_options;
}

Available Option Names

Option Name Description Context-Aware
user.role Standard role options (sysadmin, admin, user, viewer) No
auth.authority Authentication authority options (local, google, msft) No
connection.status Connection status options (active, inactive, expired, error) No
user.connection User's connections (fetched from database) Yes (requires currentUser)

Utility Functions

The frontendOptionsTypes module provides utility functions:

from modules.shared.frontendOptionsTypes import (
    isStringReference,
    isStaticList,
    validateFrontendOptions,
    getOptionsName,
    getStaticOptions
)

# Check format
if isStringReference(frontend_options):
    optionsName = getOptionsName(frontend_options)
    # Fetch from API: /api/options/{optionsName}
elif isStaticList(frontend_options):
    options = getStaticOptions(frontend_options)
    # Use directly

# Validate format
if not validateFrontendOptions(frontend_options):
    raise ValueError("Invalid frontend_options format")

Validation

The validateFrontendOptions() function ensures:

  1. String References: Non-empty string
  2. Static Lists:
    • List of dictionaries
    • Each dictionary has "value" and "label" keys
    • "label" is a dictionary (multilingual labels)

Examples in Codebase

Static List Example

# datamodelUam.py - Language field
language: str = Field(
    default="en",
    json_schema_extra={
        "frontend_options": [
            {"value": "en", "label": {"en": "English", "fr": "Anglais"}},
            {"value": "fr", "label": {"en": "Français", "fr": "Français"}},
        ]
    }
)

String Reference Example

# datamodelUam.py - Role labels field
roleLabels: List[str] = Field(
    default_factory=list,
    json_schema_extra={
        "frontend_options": "user.role"  # Dynamic - fetched from API
    }
)

Mixed Example

# datamodelRbac.py - AccessRule model
roleLabel: str = Field(
    json_schema_extra={
        "frontend_options": "user.role"  # String reference
    }
)

context: AccessRuleContext = Field(
    json_schema_extra={
        "frontend_options": [  # Static list
            {"value": "DATA", "label": {"en": "Data", "fr": "Données"}},
            {"value": "UI", "label": {"en": "UI", "fr": "Interface"}},
            {"value": "RESOURCE", "label": {"en": "Resource", "fr": "Ressource"}}
        ]
    }
)

Best Practices

  1. Use Static Lists for:

    • Enum values
    • Fixed constants
    • Simple options that don't change
  2. Use String References for:

    • Database-driven options
    • Context-aware options
    • Options that need centralized management
  3. Always validate frontend_options format when processing

  4. Document which format is used and why in field descriptions

  5. Frontend: Always check the type before using options

Migration Guide

If you have existing static lists that should become dynamic:

  1. Create Options Provider: Add option logic to gateway/modules/features/options/mainOptions.py
  2. Register Option Name: Add to getAvailableOptionsNames() function
  3. Update Field: Change frontend_options from list to string reference
  4. Update Frontend: Ensure frontend handles string references correctly

See Also

  • gateway/modules/shared/frontendOptionsTypes.py - Type definitions and utilities
  • gateway/modules/features/options/mainOptions.py - Options API implementation
  • gateway/modules/routes/routeOptions.py - Options API endpoints
  • wiki/appdoc/doc_security_role_based_access.md - RBAC documentation with frontend_options examples