Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,20 @@ FEATURE_MARKETPLACE_ENABLED=true # Marketplace browsing (disabled)
FEATURE_FILES_PANEL_ENABLED=true # Uploaded/session files panel
FEATURE_CHAT_HISTORY_ENABLED=false # Previous chat history list
FEATURE_COMPLIANCE_LEVELS_ENABLED=false # Compliance level filtering for MCP servers and data sources
FEATURE_SPLASH_SCREEN_ENABLED=false # Startup splash screen for displaying policies and information

# (Adjust above to stage rollouts. For a bare-bones chat set them all to false.)

#############################################
# Configuration File Names
# Override the default names for configuration files.
# Useful for testing or managing multiple configurations.
#############################################
# SPLASH_CONFIG_FILE=splash-config.json # Splash screen configuration file name
# MCP_CONFIG_FILE=mcp.json # MCP servers configuration file name
# LLM_CONFIG_FILE=llmconfig.yml # LLM models configuration file name
# HELP_CONFIG_FILE=help-config.json # Help page configuration file name


# ths might be need for mcp serves to know where to download the files.
# CHATUI_BACKEND_BASE_URL=http://127.0.0.1:8000
Expand Down
8 changes: 8 additions & 0 deletions backend/modules/config/config_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,13 @@ class AppSettings(BaseSettings):
# Banner settings
banner_enabled: bool = False

# Splash screen settings
feature_splash_screen_enabled: bool = Field(
False,
description="Enable startup splash screen for displaying policies and information",
validation_alias=AliasChoices("FEATURE_SPLASH_SCREEN_ENABLED", "SPLASH_SCREEN_ENABLED"),
)

# Agent settings
# Renamed to feature_agent_mode_available to align with other FEATURE_* flags.
feature_agent_mode_available: bool = Field(
Expand Down Expand Up @@ -293,6 +300,7 @@ def agent_mode_available(self) -> bool:
help_config_file: str = Field(default="help-config.json", validation_alias="HELP_CONFIG_FILE")
messages_config_file: str = Field(default="messages.txt", validation_alias="MESSAGES_CONFIG_FILE")
tool_approvals_config_file: str = Field(default="tool-approvals.json", validation_alias="TOOL_APPROVALS_CONFIG_FILE")
splash_config_file: str = Field(default="splash-config.json", validation_alias="SPLASH_CONFIG_FILE")

# Config directory paths
app_config_overrides: str = Field(default="config/overrides", validation_alias="APP_CONFIG_OVERRIDES")
Expand Down
89 changes: 88 additions & 1 deletion backend/routes/config_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,8 @@ async def get_config(
"marketplace": app_settings.feature_marketplace_enabled,
"files_panel": app_settings.feature_files_panel_enabled,
"chat_history": app_settings.feature_chat_history_enabled,
"compliance_levels": app_settings.feature_compliance_levels_enabled
"compliance_levels": app_settings.feature_compliance_levels_enabled,
"splash_screen": app_settings.feature_splash_screen_enabled
}
}

Expand Down Expand Up @@ -340,6 +341,92 @@ async def get_compliance_levels(current_user: str = Depends(get_current_user)):
}


@router.get("/splash")
async def get_splash_config(current_user: str = Depends(get_current_user)):
"""Get splash screen configuration."""
config_manager = app_factory.get_config_manager()
app_settings = config_manager.app_settings

# Check if splash screen feature is enabled
if not app_settings.feature_splash_screen_enabled:
return {
"enabled": False,
"title": "",
"messages": [],
"dismissible": True,
"require_accept": False,
"dismiss_duration_days": 30,
"accept_button_text": "Accept",
"dismiss_button_text": "Dismiss",
"show_on_every_visit": False
}

# Read splash screen configuration
splash_config = {}
import json
splash_config_filename = app_settings.splash_config_file
splash_paths = []
try:
# Reuse config manager search logic
try:
splash_paths = config_manager._search_paths(splash_config_filename) # type: ignore[attr-defined]
except AttributeError:
# Fallback minimal search if method renamed/removed
from pathlib import Path
backend_root = Path(__file__).parent.parent
project_root = backend_root.parent
splash_paths = [
project_root / "config" / "overrides" / splash_config_filename,
project_root / "config" / "defaults" / splash_config_filename,
backend_root / "configfilesadmin" / splash_config_filename,
backend_root / "configfiles" / splash_config_filename,
backend_root / splash_config_filename,
project_root / splash_config_filename,
]

found_path = None
for p in splash_paths:
if p.exists():
found_path = p
break
if found_path:
with open(found_path, "r", encoding="utf-8") as f:
splash_config = json.load(f)
logger.info(f"Loaded splash config from {found_path}")
else:
logger.info(
"Splash config not found in any of these locations: %s",
[str(p) for p in splash_paths]
)
# Return default disabled config
splash_config = {
"enabled": False,
"title": "",
"messages": [],
"dismissible": True,
"require_accept": False,
"dismiss_duration_days": 30,
"accept_button_text": "Accept",
"dismiss_button_text": "Dismiss",
"show_on_every_visit": False
}
except Exception as e:
logger.warning(f"Error loading splash config: {e}")
splash_config = {
"enabled": False,
"title": "",
"messages": [],
"dismissible": True,
"require_accept": False,
"dismiss_duration_days": 30,
"accept_button_text": "Accept",
"dismiss_button_text": "Dismiss",
"show_on_every_visit": False
}

return splash_config


# @router.get("/sessions")
# async def get_session_info(current_user: str = Depends(get_current_user)):
# """Get session information for the current user."""
Expand Down
16 changes: 16 additions & 0 deletions config/defaults/splash-config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"enabled": false,
"title": "Welcome to Chat UI",
"messages": [
{
"type": "text",
"content": "Welcome! Please review our policies before continuing."
}
],
"dismissible": true,
"require_accept": false,
"dismiss_duration_days": 30,
"accept_button_text": "Accept",
"dismiss_button_text": "Dismiss",
"show_on_every_visit": false
}
36 changes: 36 additions & 0 deletions config/overrides/splash-config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"enabled": true,
"title": "Important Policies and Information",
"messages": [
{
"type": "heading",
"content": "Cookie Policy"
},
{
"type": "text",
"content": "This application uses cookies to enhance your experience and maintain your session. By continuing to use this application, you consent to our use of cookies."
},
{
"type": "heading",
"content": "Acceptable Use Policy"
},
{
"type": "text",
"content": "This system is for authorized use only. Users must comply with all applicable policies and regulations. Unauthorized access or misuse of this system may result in disciplinary action and/or legal prosecution."
},
{
"type": "heading",
"content": "Data Privacy"
},
{
"type": "text",
"content": "Your conversations and data are processed in accordance with our privacy policy. Please do not share sensitive or confidential information unless explicitly authorized."
}
],
"dismissible": true,
"require_accept": false,
"dismiss_duration_days": 30,
"accept_button_text": "I Accept",
"dismiss_button_text": "Close",
"show_on_every_visit": false
}
59 changes: 59 additions & 0 deletions docs/02_admin_guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ To customize your instance, you will place your own versions of the configuratio
* **`llmconfig.yml`**: Defines the list of available Large Language Models and their connection details.
* **`compliance-levels.json`**: Defines the security compliance levels (e.g., Public, Internal, HIPAA) and the rules for how they can interact.
* **`help-config.json`**: Populates the content of the "Help" modal in the user interface.
* **`splash-config.json`**: Configures the startup splash screen for displaying policies and information to users.
* **`messages.txt`**: Defines the text for system-wide banner messages that can be displayed to all users.

### Customizing the Help Modal (`help-config.json`)
Expand Down Expand Up @@ -51,6 +52,64 @@ The file consists of a title and a list of sections, each with a title and conte
}
```

### Configuring the Splash Screen (`splash-config.json`)

The splash screen feature allows you to display important policies and information to users when they first access the application. This is commonly used for displaying cookie policies, acceptable use policies, and other legal or organizational information.

* **Location**: Place your custom file at `config/overrides/splash-config.json`.
* **Feature Flag**: Enable the splash screen by setting `FEATURE_SPLASH_SCREEN_ENABLED=true` in your `.env` file.

The splash screen supports two operational modes:

1. **Accept Mode** (`require_accept: true`): Users must explicitly click "I Accept" to proceed. The close (X) button is hidden.
2. **Dismiss Mode** (`require_accept: false`): Users can dismiss the screen by clicking "Close" or the X button in the header.

User dismissals are tracked in the browser's local storage and will not show again until the configured duration expires (default: 30 days).

**Example `splash-config.json`:**
```json
{
"enabled": true,
"title": "Important Policies and Information",
"messages": [
{
"type": "heading",
"content": "Cookie Policy"
},
{
"type": "text",
"content": "This application uses cookies to enhance your experience and maintain your session. By continuing to use this application, you consent to our use of cookies."
},
{
"type": "heading",
"content": "Acceptable Use Policy"
},
{
"type": "text",
"content": "This system is for authorized use only. Users must comply with all applicable policies and regulations. Unauthorized access or misuse of this system may result in disciplinary action and/or legal prosecution."
}
],
"dismissible": true,
"require_accept": true,
"dismiss_duration_days": 30,
"accept_button_text": "I Accept",
"dismiss_button_text": "Close",
"show_on_every_visit": false
}
```

**Configuration Fields:**

* **`enabled`**: (boolean) Whether the splash screen is shown. Must be `true` and `FEATURE_SPLASH_SCREEN_ENABLED=true` in `.env`.
* **`title`**: (string) The title displayed at the top of the splash screen modal.
* **`messages`**: (array) A list of message objects. Each message has a `type` (`"heading"` or `"text"`) and `content` (string).
* **`dismissible`**: (boolean) Whether users can dismiss the splash screen.
* **`require_accept`**: (boolean) If `true`, users must click the accept button. If `false`, users can dismiss casually.
* **`dismiss_duration_days`**: (number) Number of days before showing the splash screen again after dismissal.
* **`accept_button_text`**: (string) Text for the accept button (shown when `require_accept` is `true`).
* **`dismiss_button_text`**: (string) Text for the dismiss button (shown when `require_accept` is `false`).
* **`show_on_every_visit`**: (boolean) If `true`, the splash screen will show every time, ignoring dismissal tracking.

### The `.env` File

This file is crucial for setting up your instance. Start by copying the example file:
Expand Down
25 changes: 25 additions & 0 deletions frontend/src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import LogViewer from './components/LogViewer' // Import LogViewer
import FeedbackButton from './components/FeedbackButton'
import FileManagerPanel from './components/FileManagerPanel'
import FilesPage from './components/FilesPage'
import SplashScreen from './components/SplashScreen'

function ChatInterface() {
const [toolsPanelOpen, setToolsPanelOpen] = useState(false)
Expand Down Expand Up @@ -174,11 +175,35 @@ function AppRoutes() {
}

function App() {
const [splashConfig, setSplashConfig] = useState(null)

// Fetch splash screen configuration on app load
useEffect(() => {
const fetchSplashConfig = async () => {
try {
const response = await fetch('/api/splash')
if (response.ok) {
const config = await response.json()
setSplashConfig(config)
} else {
console.warn('Failed to fetch splash configuration')
setSplashConfig({ enabled: false })
}
} catch (error) {
console.error('Error fetching splash configuration:', error)
setSplashConfig({ enabled: false })
}
}

fetchSplashConfig()
}, [])

return (
<Router>
<WSProvider>
<ChatProvider>
<MarketplaceProvider>
<SplashScreen config={splashConfig} />
<AppRoutes />
</MarketplaceProvider>
</ChatProvider>
Expand Down
Loading
Loading