Merge branch 'next' into test-themes

This commit is contained in:
James Read 2025-12-25 01:37:17 +00:00 committed by GitHub
commit 684e12d2b9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 70 additions and 17 deletions

View File

@ -19,7 +19,9 @@
</Header> </Header>
<div id="layout"> <div id="layout">
<Sidebar ref="sidebar" id = "mainnav" v-if="showNavigation" /> <Navigation ref="navigation" id="mainnav" v-if="showNavigation">
<Sidebar ref="sidebar" id = "mainnav" v-if="showNavigation" />
</Navigation>
<div id="content" initial-martial-complete="{{ hasLoaded }}"> <div id="content" initial-martial-complete="{{ hasLoaded }}">
<main title="Main content"> <main title="Main content">
@ -77,6 +79,7 @@
import { ref, onMounted, computed } from 'vue'; import { ref, onMounted, computed } from 'vue';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import Sidebar from 'picocrank/vue/components/Sidebar.vue'; import Sidebar from 'picocrank/vue/components/Sidebar.vue';
import Navigation from 'picocrank/vue/components/Navigation.vue';
import Header from 'picocrank/vue/components/Header.vue'; import Header from 'picocrank/vue/components/Header.vue';
import { HugeiconsIcon } from '@hugeicons/vue' import { HugeiconsIcon } from '@hugeicons/vue'
import { Menu01Icon } from '@hugeicons/core-free-icons' import { Menu01Icon } from '@hugeicons/core-free-icons'
@ -91,6 +94,7 @@ const { t, locale } = useI18n();
const router = useRouter(); const router = useRouter();
const sidebar = ref(null); const sidebar = ref(null);
const navigation = ref(null);
const username = ref('notset'); const username = ref('notset');
const isLoggedIn = ref(false); const isLoggedIn = ref(false);
const serverConnection = ref(true); const serverConnection = ref(true);
@ -181,7 +185,7 @@ function updateHeaderFromInit() {
showLoginLink.value = false showLoginLink.value = false
} }
renderSidebar() renderNavigation()
if (window.initResponse.loginRequired) { if (window.initResponse.loginRequired) {
router.push('/login') router.push('/login')
@ -189,19 +193,19 @@ function updateHeaderFromInit() {
} }
} }
function renderSidebar() { function renderNavigation() {
if (!sidebar.value) { if (!navigation.value) {
return return
} }
const rootDashboards = window.initResponse?.rootDashboards || [] const rootDashboards = window.initResponse?.rootDashboards || []
if (typeof sidebar.value.clear === 'function') { if (typeof navigation.value.clear === 'function') {
sidebar.value.clear() navigation.value.clear()
} }
for (const rootDashboard of rootDashboards) { for (const rootDashboard of rootDashboards) {
sidebar.value.addNavigationLink({ navigation.value.addNavigationLink({
id: rootDashboard, id: rootDashboard,
name: rootDashboard, name: rootDashboard,
title: rootDashboard, title: rootDashboard,
@ -210,15 +214,15 @@ function renderSidebar() {
}) })
} }
sidebar.value.addSeparator() navigation.value.addSeparator()
sidebar.value.addRouterLink('Entities', t('nav.entities')) navigation.value.addRouterLink('Entities', t('nav.entities'))
if (showLogs.value) { if (showLogs.value) {
sidebar.value.addRouterLink('Logs', t('nav.logs')) navigation.value.addRouterLink('Logs', t('nav.logs'))
} }
if (showDiagnostics.value) { if (showDiagnostics.value) {
sidebar.value.addRouterLink('Diagnostics', t('nav.diagnostics')) navigation.value.addRouterLink('Diagnostics', t('nav.diagnostics'))
} }
} }
@ -257,9 +261,9 @@ function changeLanguage() {
languagePreference.value = selectedLanguage.value languagePreference.value = selectedLanguage.value
} }
// Update sidebar with new translations // Update navigation with new translations
if (sidebar.value) { if (navigation.value) {
renderSidebar() renderNavigation()
} }
closeLanguageDialog() closeLanguageDialog()

View File

@ -1,11 +1,13 @@
<template> <template>
<button @click="navigateToDirectory"> <button @click="navigateToDirectory">
{{ component.title }} <span class="icon" v-html="unicodeIcon"></span>
<span class="title">{{ component.title }}</span>
</button> </button>
</template> </template>
<script setup> <script setup>
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
import { computed } from 'vue'
const router = useRouter() const router = useRouter()
@ -16,6 +18,18 @@ const props = defineProps({
} }
}) })
function getUnicodeIcon(icon) {
if (icon === '' || !icon) {
return '&#x1f4c1;' // Default folder icon
} else {
return unescape(icon)
}
}
const unicodeIcon = computed(() => {
return getUnicodeIcon(props.component.icon)
})
function navigateToDirectory() { function navigateToDirectory() {
const params = { title: props.component.title } const params = { title: props.component.title }
@ -34,9 +48,18 @@ function navigateToDirectory() {
} }
button { button {
display: flex;
flex-direction: column;
flex-grow: 1;
justify-content: center;
padding: 0.5em;
box-shadow: 0 0 .6em #aaa; box-shadow: 0 0 .6em #aaa;
background-color: #fff; background-color: #fff;
border-radius: .7em; border-radius: .7em;
border: 1px solid #ccc;
cursor: pointer;
transition: all 0.2s ease;
font-size: .85em;
} }
button:hover { button:hover {
@ -44,16 +67,30 @@ button:hover {
border-color: #999; border-color: #999;
} }
button .icon {
font-size: 3em;
flex-grow: 1;
align-content: center;
}
button .title {
font-weight: 500;
padding: 0.2em;
}
@media (prefers-color-scheme: dark) { @media (prefers-color-scheme: dark) {
button { button {
box-shadow: 0 0 .6em #000; box-shadow: 0 0 .6em #000;
background-color: #111; background-color: #111;
border-color: #000; border-color: #000;
color: #fff;
} }
button:hover { button:hover {
background-color: #222; background-color: #222;
border-color: #000; border-color: #000;
box-shadow: 0 0 6px #444;
color: #fff;
} }
} }

View File

@ -263,10 +263,21 @@ func (h *OAuth2Handler) HandleOAuthCallback(w http.ResponseWriter, r *http.Reque
Timeout: clientSettings.Timeout, Timeout: clientSettings.Timeout,
} }
userinfo := getUserInfo(h.cfg, userInfoClient, h.cfg.AuthOAuth2Providers[registeredState.providerName]) userinfo := getUserInfo(h.cfg, userInfoClient, providerConfig)
h.registeredStates[state].Username = userinfo.Username h.registeredStates[state].Username = userinfo.Username
h.registeredStates[state].Usergroup = userinfo.Usergroup
usergroup := userinfo.Usergroup
if providerConfig != nil && providerConfig.AddToUsergroup != "" {
// Append configured usergroup name if addToUsergroup is set
if usergroup != "" {
usergroup = usergroup + " " + providerConfig.AddToUsergroup
} else {
usergroup = providerConfig.AddToUsergroup
}
}
h.registeredStates[state].Usergroup = usergroup
http.Redirect(w, r, "/", http.StatusFound) http.Redirect(w, r, "/", http.StatusFound)
} }

View File

@ -184,6 +184,7 @@ type OAuth2Provider struct {
InsecureSkipVerify bool `koanf:"insecureSkipVerify"` InsecureSkipVerify bool `koanf:"insecureSkipVerify"`
CallbackTimeout int `koanf:"callbackTimeout"` CallbackTimeout int `koanf:"callbackTimeout"`
CertBundlePath string `koanf:"certBundlePath"` CertBundlePath string `koanf:"certBundlePath"`
AddToUsergroup string `koanf:"addToUsergroup"`
} }
type NavigationLink struct { type NavigationLink struct {