Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
陈曦
sub2api
Commits
9792b175
Unverified
Commit
9792b175
authored
Mar 03, 2026
by
Wesley Liddick
Committed by
GitHub
Mar 03, 2026
Browse files
Merge pull request #729 from touwaeriol/pr/fix-admin-menu-visibility
fix(frontend): admin custom menu items not showing in sidebar
parents
b7df7ce5
5ba71cd2
Changes
3
Hide whitespace changes
Inline
Side-by-side
frontend/src/components/layout/AppSidebar.vue
View file @
9792b175
...
@@ -579,7 +579,7 @@ const customMenuItemsForUser = computed(() => {
...
@@ -579,7 +579,7 @@ const customMenuItemsForUser = computed(() => {
})
})
const
customMenuItemsForAdmin
=
computed
(()
=>
{
const
customMenuItemsForAdmin
=
computed
(()
=>
{
const
items
=
a
ppStore
.
cachedPublic
Settings
?
.
custom
_m
enu
_i
tems
??
[]
const
items
=
a
dmin
Settings
Store
.
custom
M
enu
I
tems
??
[]
return
items
return
items
.
filter
((
item
)
=>
item
.
visibility
===
'
admin
'
)
.
filter
((
item
)
=>
item
.
visibility
===
'
admin
'
)
.
sort
((
a
,
b
)
=>
a
.
sort_order
-
b
.
sort_order
)
.
sort
((
a
,
b
)
=>
a
.
sort_order
-
b
.
sort_order
)
...
...
frontend/src/stores/adminSettings.ts
View file @
9792b175
import
{
defineStore
}
from
'
pinia
'
import
{
defineStore
}
from
'
pinia
'
import
{
ref
}
from
'
vue
'
import
{
ref
}
from
'
vue
'
import
{
adminAPI
}
from
'
@/api
'
import
{
adminAPI
}
from
'
@/api
'
import
type
{
CustomMenuItem
}
from
'
@/types
'
export
const
useAdminSettingsStore
=
defineStore
(
'
adminSettings
'
,
()
=>
{
export
const
useAdminSettingsStore
=
defineStore
(
'
adminSettings
'
,
()
=>
{
const
loaded
=
ref
(
false
)
const
loaded
=
ref
(
false
)
...
@@ -43,6 +44,9 @@ export const useAdminSettingsStore = defineStore('adminSettings', () => {
...
@@ -43,6 +44,9 @@ export const useAdminSettingsStore = defineStore('adminSettings', () => {
}
}
}
}
// Custom menu items (all items including admin-only, loaded from admin settings API)
const
customMenuItems
=
ref
<
CustomMenuItem
[]
>
([])
// Default open, but honor cached value to reduce UI flicker on first paint.
// Default open, but honor cached value to reduce UI flicker on first paint.
const
opsMonitoringEnabled
=
ref
(
readCachedBool
(
'
ops_monitoring_enabled_cached
'
,
true
))
const
opsMonitoringEnabled
=
ref
(
readCachedBool
(
'
ops_monitoring_enabled_cached
'
,
true
))
const
opsRealtimeMonitoringEnabled
=
ref
(
readCachedBool
(
'
ops_realtime_monitoring_enabled_cached
'
,
true
))
const
opsRealtimeMonitoringEnabled
=
ref
(
readCachedBool
(
'
ops_realtime_monitoring_enabled_cached
'
,
true
))
...
@@ -64,6 +68,8 @@ export const useAdminSettingsStore = defineStore('adminSettings', () => {
...
@@ -64,6 +68,8 @@ export const useAdminSettingsStore = defineStore('adminSettings', () => {
opsQueryModeDefault
.
value
=
settings
.
ops_query_mode_default
||
'
auto
'
opsQueryModeDefault
.
value
=
settings
.
ops_query_mode_default
||
'
auto
'
writeCachedString
(
'
ops_query_mode_default_cached
'
,
opsQueryModeDefault
.
value
)
writeCachedString
(
'
ops_query_mode_default_cached
'
,
opsQueryModeDefault
.
value
)
customMenuItems
.
value
=
settings
.
custom_menu_items
??
[]
loaded
.
value
=
true
loaded
.
value
=
true
}
catch
(
err
)
{
}
catch
(
err
)
{
// Keep cached/default value: do not "flip" the UI based on a transient fetch failure.
// Keep cached/default value: do not "flip" the UI based on a transient fetch failure.
...
@@ -122,6 +128,7 @@ export const useAdminSettingsStore = defineStore('adminSettings', () => {
...
@@ -122,6 +128,7 @@ export const useAdminSettingsStore = defineStore('adminSettings', () => {
opsMonitoringEnabled
,
opsMonitoringEnabled
,
opsRealtimeMonitoringEnabled
,
opsRealtimeMonitoringEnabled
,
opsQueryModeDefault
,
opsQueryModeDefault
,
customMenuItems
,
fetch
,
fetch
,
setOpsMonitoringEnabledLocal
,
setOpsMonitoringEnabledLocal
,
setOpsRealtimeMonitoringEnabledLocal
,
setOpsRealtimeMonitoringEnabledLocal
,
...
...
frontend/src/views/user/CustomPageView.vue
View file @
9792b175
...
@@ -70,6 +70,7 @@ import { useRoute } from 'vue-router'
...
@@ -70,6 +70,7 @@ import { useRoute } from 'vue-router'
import
{
useI18n
}
from
'
vue-i18n
'
import
{
useI18n
}
from
'
vue-i18n
'
import
{
useAppStore
}
from
'
@/stores
'
import
{
useAppStore
}
from
'
@/stores
'
import
{
useAuthStore
}
from
'
@/stores/auth
'
import
{
useAuthStore
}
from
'
@/stores/auth
'
import
{
useAdminSettingsStore
}
from
'
@/stores/adminSettings
'
import
AppLayout
from
'
@/components/layout/AppLayout.vue
'
import
AppLayout
from
'
@/components/layout/AppLayout.vue
'
import
Icon
from
'
@/components/icons/Icon.vue
'
import
Icon
from
'
@/components/icons/Icon.vue
'
import
{
buildEmbeddedUrl
,
detectTheme
}
from
'
@/utils/embedded-url
'
import
{
buildEmbeddedUrl
,
detectTheme
}
from
'
@/utils/embedded-url
'
...
@@ -78,6 +79,7 @@ const { t } = useI18n()
...
@@ -78,6 +79,7 @@ const { t } = useI18n()
const
route
=
useRoute
()
const
route
=
useRoute
()
const
appStore
=
useAppStore
()
const
appStore
=
useAppStore
()
const
authStore
=
useAuthStore
()
const
authStore
=
useAuthStore
()
const
adminSettingsStore
=
useAdminSettingsStore
()
const
loading
=
ref
(
false
)
const
loading
=
ref
(
false
)
const
pageTheme
=
ref
<
'
light
'
|
'
dark
'
>
(
'
light
'
)
const
pageTheme
=
ref
<
'
light
'
|
'
dark
'
>
(
'
light
'
)
...
@@ -86,8 +88,15 @@ let themeObserver: MutationObserver | null = null
...
@@ -86,8 +88,15 @@ let themeObserver: MutationObserver | null = null
const
menuItemId
=
computed
(()
=>
route
.
params
.
id
as
string
)
const
menuItemId
=
computed
(()
=>
route
.
params
.
id
as
string
)
const
menuItem
=
computed
(()
=>
{
const
menuItem
=
computed
(()
=>
{
const
items
=
appStore
.
cachedPublicSettings
?.
custom_menu_items
??
[]
const
publicItems
=
appStore
.
cachedPublicSettings
?.
custom_menu_items
??
[]
const
found
=
items
.
find
((
item
)
=>
item
.
id
===
menuItemId
.
value
)
??
null
const
adminItems
=
authStore
.
isAdmin
?
(
adminSettingsStore
.
customMenuItems
??
[])
:
[]
const
allItems
=
[...
publicItems
]
for
(
const
item
of
adminItems
)
{
if
(
!
allItems
.
some
((
existing
)
=>
existing
.
id
===
item
.
id
))
{
allItems
.
push
(
item
)
}
}
const
found
=
allItems
.
find
((
item
)
=>
item
.
id
===
menuItemId
.
value
)
??
null
if
(
found
&&
found
.
visibility
===
'
admin
'
&&
!
authStore
.
isAdmin
)
{
if
(
found
&&
found
.
visibility
===
'
admin
'
&&
!
authStore
.
isAdmin
)
{
return
null
return
null
}
}
...
@@ -122,12 +131,20 @@ onMounted(async () => {
...
@@ -122,12 +131,20 @@ onMounted(async () => {
})
})
}
}
if
(
appStore
.
publicSettingsLoaded
)
return
const
promises
:
Promise
<
unknown
>
[]
=
[]
loading
.
value
=
true
if
(
!
appStore
.
publicSettingsLoaded
)
{
try
{
promises
.
push
(
appStore
.
fetchPublicSettings
())
await
appStore
.
fetchPublicSettings
()
}
}
finally
{
if
(
authStore
.
isAdmin
)
{
loading
.
value
=
false
promises
.
push
(
adminSettingsStore
.
fetch
())
}
if
(
promises
.
length
>
0
)
{
loading
.
value
=
true
try
{
await
Promise
.
all
(
promises
)
}
finally
{
loading
.
value
=
false
}
}
}
})
})
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment