fix: store menu 404, logger crash, platform detection, and sidebar UX
All checks were successful
All checks were successful
- Fix store menu API URL (/store/menu/render/store, not /store/core/...) - Fix storeLog/merchantLog fallback to console object instead of console.log - Embed platform_id/platform_code in store JWT from URL context at login - Use token_platform_id in store menu endpoint with DB fallback for old tokens - Add "Menu unavailable" warning in sidebar fallback for all three frontends - Standardize admin section default to all-open (consistent with store/merchant) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -95,8 +95,10 @@ async def get_rendered_store_menu(
|
|||||||
# Get the store from the JWT token's store context
|
# Get the store from the JWT token's store context
|
||||||
store = store_service.get_store_by_id(db, current_user.token_store_id)
|
store = store_service.get_store_by_id(db, current_user.token_store_id)
|
||||||
|
|
||||||
# Resolve the store's platform via service layer
|
# Platform from JWT (set at login from URL context), fall back to DB for old tokens
|
||||||
platform_id = menu_service.get_store_primary_platform_id(db, store.id)
|
platform_id = current_user.token_platform_id
|
||||||
|
if platform_id is None:
|
||||||
|
platform_id = menu_service.get_store_primary_platform_id(db, store.id)
|
||||||
|
|
||||||
# Get filtered menu with platform visibility and store_code interpolation
|
# Get filtered menu with platform visibility and store_code interpolation
|
||||||
menu = menu_service.get_menu_for_rendering(
|
menu = menu_service.get_menu_for_rendering(
|
||||||
|
|||||||
@@ -214,7 +214,7 @@ function data() {
|
|||||||
// Initialize openSections for new sections (default: first section open)
|
// Initialize openSections for new sections (default: first section open)
|
||||||
if (this.openSections[section.id] === undefined) {
|
if (this.openSections[section.id] === undefined) {
|
||||||
// Default: first section open, rest closed
|
// Default: first section open, rest closed
|
||||||
this.openSections[section.id] = (sections.indexOf(section) === 0);
|
this.openSections[section.id] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
console.debug('Menu config loaded:', this.visibleMenuItems.size, 'items');
|
console.debug('Menu config loaded:', this.visibleMenuItems.size, 'items');
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// Use centralized logger (guarded: log-config.js loads with defer, so it may not be ready yet)
|
// Use centralized logger (guarded: log-config.js loads with defer, so it may not be ready yet)
|
||||||
const merchantLog = (window.LogConfig && window.LogConfig.log) || console.log;
|
const merchantLog = (window.LogConfig && window.LogConfig.log) || console;
|
||||||
|
|
||||||
console.log('[MERCHANT INIT-ALPINE] Loading...');
|
console.log('[MERCHANT INIT-ALPINE] Loading...');
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// Use centralized logger (guarded: log-config.js loads with defer, so it may not be ready yet)
|
// Use centralized logger (guarded: log-config.js loads with defer, so it may not be ready yet)
|
||||||
const storeLog = (window.LogConfig && window.LogConfig.log) || console.log;
|
const storeLog = (window.LogConfig && window.LogConfig.log) || console;
|
||||||
|
|
||||||
console.log('[STORE INIT-ALPINE] Loading...');
|
console.log('[STORE INIT-ALPINE] Loading...');
|
||||||
|
|
||||||
@@ -129,7 +129,7 @@ function data() {
|
|||||||
|
|
||||||
this.menuLoading = true;
|
this.menuLoading = true;
|
||||||
try {
|
try {
|
||||||
this.menuData = await apiClient.get('/store/core/menu/render/store');
|
this.menuData = await apiClient.get('/store/menu/render/store');
|
||||||
// Initialize section open state from response
|
// Initialize section open state from response
|
||||||
for (const section of (this.menuData?.sections || [])) {
|
for (const section of (this.menuData?.sections || [])) {
|
||||||
if (this.openSections[section.id] === undefined) {
|
if (this.openSections[section.id] === undefined) {
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ from app.modules.tenancy.models.user_password_reset_token import (
|
|||||||
UserPasswordResetToken, # noqa: API-007
|
UserPasswordResetToken, # noqa: API-007
|
||||||
)
|
)
|
||||||
from app.modules.tenancy.services.user_auth_service import user_auth_service
|
from app.modules.tenancy.services.user_auth_service import user_auth_service
|
||||||
|
from middleware.platform_context import get_current_platform
|
||||||
from middleware.store_context import get_current_store
|
from middleware.store_context import get_current_store
|
||||||
from models.schema.auth import LogoutResponse, StoreUserResponse, UserContext, UserLogin
|
from models.schema.auth import LogoutResponse, StoreUserResponse, UserContext, UserLogin
|
||||||
|
|
||||||
@@ -110,12 +111,19 @@ def store_login(
|
|||||||
f"for store {store.store_code} as {store_role}"
|
f"for store {store.store_code} as {store_role}"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Get platform from URL context (middleware-detected)
|
||||||
|
platform = get_current_platform(request)
|
||||||
|
platform_id = platform.id if platform else None
|
||||||
|
platform_code = platform.code if platform else None
|
||||||
|
|
||||||
# Create store-scoped access token with store information
|
# Create store-scoped access token with store information
|
||||||
token_data = auth_service.auth_manager.create_access_token(
|
token_data = auth_service.auth_manager.create_access_token(
|
||||||
user=user,
|
user=user,
|
||||||
store_id=store.id,
|
store_id=store.id,
|
||||||
store_code=store.store_code,
|
store_code=store.store_code,
|
||||||
store_role=store_role,
|
store_role=store_role,
|
||||||
|
platform_id=platform_id,
|
||||||
|
platform_code=platform_code,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Set HTTP-only cookie for browser navigation
|
# Set HTTP-only cookie for browser navigation
|
||||||
|
|||||||
@@ -88,7 +88,11 @@
|
|||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p class="px-6 py-3 text-xs text-gray-400">Loading menu...</p>
|
<div class="px-6 mt-4">
|
||||||
|
<p class="text-xs text-gray-400 dark:text-gray-500">
|
||||||
|
Menu unavailable. Showing default items only.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endmacro %}
|
{% endmacro %}
|
||||||
|
|||||||
@@ -86,7 +86,7 @@
|
|||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Fallback: static dashboard link (if menu API fails) -->
|
<!-- Fallback: static dashboard link + warning (if menu API fails) -->
|
||||||
<div x-show="!menuLoading && !menuData" x-cloak>
|
<div x-show="!menuLoading && !menuData" x-cloak>
|
||||||
<ul class="mt-6">
|
<ul class="mt-6">
|
||||||
<li class="relative px-6 py-3">
|
<li class="relative px-6 py-3">
|
||||||
@@ -99,6 +99,11 @@
|
|||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
<div class="px-6 mt-4">
|
||||||
|
<p class="text-xs text-gray-400 dark:text-gray-500">
|
||||||
|
Menu unavailable. Showing default items only.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endmacro %}
|
{% endmacro %}
|
||||||
|
|||||||
@@ -86,7 +86,7 @@
|
|||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Fallback: static dashboard link (if menu API fails) -->
|
<!-- Fallback: static dashboard link + warning (if menu API fails) -->
|
||||||
<div x-show="!menuLoading && !menuData" x-cloak>
|
<div x-show="!menuLoading && !menuData" x-cloak>
|
||||||
<ul class="mt-6">
|
<ul class="mt-6">
|
||||||
<li class="relative px-6 py-3">
|
<li class="relative px-6 py-3">
|
||||||
@@ -99,6 +99,11 @@
|
|||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
<div class="px-6 mt-4">
|
||||||
|
<p class="text-xs text-gray-400 dark:text-gray-500">
|
||||||
|
Menu unavailable. Showing default items only.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Quick Actions (static, outside dynamic menu) -->
|
<!-- Quick Actions (static, outside dynamic menu) -->
|
||||||
|
|||||||
Reference in New Issue
Block a user