From e1c0c117c2ad15a7dc2e8bee58deaa53f0e528ea Mon Sep 17 00:00:00 2001 From: Samir Boulahtit Date: Mon, 5 Jan 2026 22:46:27 +0100 Subject: [PATCH] fix: resolve settings page icon and 404 errors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Change icon from 'envelope' to 'mail' (envelope not in icons.js) - Add default query param to GET /admin/settings/{key} endpoint - Return AdminSettingDefaultResponse instead of 404 when default provided - Update loadShippingSettings() to use default param for carrier settings 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- app/api/v1/admin/settings.py | 15 ++++++++++++--- app/templates/admin/settings.html | 2 +- models/schema/admin.py | 8 ++++++++ static/admin/js/settings.js | 24 ++++++++++++------------ 4 files changed, 33 insertions(+), 16 deletions(-) diff --git a/app/api/v1/admin/settings.py b/app/api/v1/admin/settings.py index 12bccbfb..8f4bf670 100644 --- a/app/api/v1/admin/settings.py +++ b/app/api/v1/admin/settings.py @@ -24,6 +24,7 @@ from app.services.admin_settings_service import admin_settings_service from models.database.user import User from models.schema.admin import ( AdminSettingCreate, + AdminSettingDefaultResponse, AdminSettingListResponse, AdminSettingResponse, AdminSettingUpdate, @@ -75,16 +76,24 @@ def get_setting_categories( } -@router.get("/{key}", response_model=AdminSettingResponse) +@router.get("/{key}", response_model=AdminSettingResponse | AdminSettingDefaultResponse) def get_setting( key: str, + default: str | None = Query(None, description="Default value if setting not found"), db: Session = Depends(get_db), current_admin: User = Depends(get_current_admin_api), -): - """Get specific setting by key.""" +) -> AdminSettingResponse | AdminSettingDefaultResponse: + """Get specific setting by key. + + If `default` is provided and the setting doesn't exist, returns a response + with the default value instead of 404. + """ setting = admin_settings_service.get_setting_by_key(db, key) if not setting: + if default is not None: + # Return default value without creating the setting + return AdminSettingDefaultResponse(key=key, value=default, exists=False) raise ResourceNotFoundException(resource_type="Setting", identifier=key) return AdminSettingResponse.model_validate(setting) diff --git a/app/templates/admin/settings.html b/app/templates/admin/settings.html index 4a714274..7c9b33c9 100644 --- a/app/templates/admin/settings.html +++ b/app/templates/admin/settings.html @@ -20,7 +20,7 @@ {% call tabs_nav() %} {{ tab_button('display', 'Display', icon='view-grid') }} {{ tab_button('logging', 'Logging', icon='document-text') }} - {{ tab_button('email', 'Email', icon='envelope') }} + {{ tab_button('email', 'Email', icon='mail') }} {{ tab_button('shipping', 'Shipping', icon='truck') }} {{ tab_button('system', 'System', icon='cog') }} {{ tab_button('security', 'Security', icon='shield-check') }} diff --git a/models/schema/admin.py b/models/schema/admin.py index 81b58778..38762e03 100644 --- a/models/schema/admin.py +++ b/models/schema/admin.py @@ -172,6 +172,14 @@ class AdminSettingResponse(BaseModel): model_config = {"from_attributes": True} +class AdminSettingDefaultResponse(BaseModel): + """Response when returning a default value for non-existent setting.""" + + key: str + value: str + exists: bool = False + + class AdminSettingUpdate(BaseModel): """Update admin setting value.""" diff --git a/static/admin/js/settings.js b/static/admin/js/settings.js index a54710b6..e7190e49 100644 --- a/static/admin/js/settings.js +++ b/static/admin/js/settings.js @@ -242,24 +242,24 @@ function adminSettings() { async loadShippingSettings() { try { - // Load each carrier setting - const carriers = ['greco', 'colissimo', 'xpresslogistics']; + // Load each carrier setting with defaults to avoid 404 errors + const carriers = [ + { name: 'greco', default: 'https://dispatchweb.fr/Tracky/Home/' }, + { name: 'colissimo', default: '' }, + { name: 'xpresslogistics', default: '' } + ]; for (const carrier of carriers) { - try { - const key = `carrier_${carrier}_label_url`; - const data = await apiClient.get(`/admin/settings/${key}`); - if (data && data.value) { - this.shippingSettings[key] = data.value; - } - } catch (error) { - // Setting doesn't exist yet, use default - settingsLog.debug(`Setting carrier_${carrier}_label_url not found, using default`); + const key = `carrier_${carrier.name}_label_url`; + // Use default query param to avoid 404 for non-existent settings + const data = await apiClient.get(`/admin/settings/${key}?default=${encodeURIComponent(carrier.default)}`); + if (data && data.value !== undefined) { + this.shippingSettings[key] = data.value; } } settingsLog.info('Shipping settings loaded:', this.shippingSettings); } catch (error) { settingsLog.error('Failed to load shipping settings:', error); - // Don't show error for missing settings, just use defaults + // On error, keep existing defaults } },