feat: better breadcrumbs for config list and editor; add filename filter for configurations list.

This commit is contained in:
Jacky 2024-07-25 19:26:07 +08:00
parent 53ae1a1ef9
commit 5dd2c8f931
No known key found for this signature in database
GPG key ID: 215C21B10DF38B4D
8 changed files with 147 additions and 12 deletions

View file

@ -8,9 +8,11 @@ import (
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"net/http" "net/http"
"os" "os"
"strings"
) )
func GetConfigs(c *gin.Context) { func GetConfigs(c *gin.Context) {
name := c.Query("name")
orderBy := c.Query("order_by") orderBy := c.Query("order_by")
sort := c.DefaultQuery("sort", "desc") sort := c.DefaultQuery("sort", "desc")
dir := c.DefaultQuery("dir", "/") dir := c.DefaultQuery("dir", "/")
@ -28,6 +30,10 @@ func GetConfigs(c *gin.Context) {
file := configFiles[i] file := configFiles[i]
fileInfo, _ := file.Info() fileInfo, _ := file.Info()
if name != "" && !strings.Contains(file.Name(), name) {
continue
}
switch mode := fileInfo.Mode(); { switch mode := fileInfo.Mode(); {
case mode.IsRegular(): // regular file, not a hidden file case mode.IsRegular(): // regular file, not a hidden file
if "." == file.Name()[0:1] { if "." == file.Name()[0:1] {

View file

@ -1,17 +1,13 @@
<script setup lang="ts"> <script setup lang="ts">
interface bread { import type { Bread } from '@/components/Breadcrumb/types'
name: string import { useBreadcrumbs } from '@/composables/useBreadcrumbs'
translatedName: () => string
path: string
hasChildren?: boolean
}
const name = ref() const name = ref()
const route = useRoute() const route = useRoute()
const router = useRouter() const router = useRouter()
const breadList = computed(() => { const computedBreadList = computed(() => {
const result: bread[] = [] const result: Bread[] = []
name.value = route.meta.name name.value = route.meta.name
@ -36,6 +32,16 @@ const breadList = computed(() => {
return result return result
}) })
const breadList = useBreadcrumbs()
onMounted(() => {
breadList.value = computedBreadList.value
})
watch(route, () => {
breadList.value = computedBreadList.value
})
</script> </script>
<template> <template>
@ -46,7 +52,7 @@ const breadList = computed(() => {
> >
<RouterLink <RouterLink
v-if="index === 0 || !item.hasChildren && index !== breadList.length - 1" v-if="index === 0 || !item.hasChildren && index !== breadList.length - 1"
:to="{ path: item.path === '' ? '/' : item.path }" :to="{ path: item.path === '' ? '/' : item.path, query: item.query }"
> >
{{ item.translatedName() }} {{ item.translatedName() }}
</RouterLink> </RouterLink>

View file

@ -0,0 +1,9 @@
import {LocationQueryRaw} from "vue-router";
export interface Bread {
name: string
translatedName: () => string
path?: string
query?: LocationQueryRaw
hasChildren?: boolean
}

View file

@ -0,0 +1,5 @@
import type { Bread } from '@/components/Breadcrumb/types'
export const useBreadcrumbs = () => {
return inject('breadList') as Ref<Bread[]>
}

View file

@ -28,6 +28,10 @@ const { server_name } = storeToRefs(useSettingsStore())
settings.get_server_name().then(r => { settings.get_server_name().then(r => {
server_name.value = r.name server_name.value = r.name
}) })
const breadList = ref([])
provide('breadList', breadList)
</script> </script>
<template> <template>

View file

@ -1,9 +1,10 @@
<script setup lang="ts"> <script setup lang="ts">
import StdTable from '@/components/StdDesign/StdDataDisplay/StdTable.vue' import StdTable from '@/components/StdDesign/StdDataDisplay/StdTable.vue'
import config from '@/api/config' import config from '@/api/config'
import configColumns from '@/views/config/config' import configColumns from '@/views/config/configColumns'
import FooterToolBar from '@/components/FooterToolbar/FooterToolBar.vue' import FooterToolBar from '@/components/FooterToolbar/FooterToolBar.vue'
import InspectConfig from '@/views/config/InspectConfig.vue' import InspectConfig from '@/views/config/InspectConfig.vue'
import { useBreadcrumbs } from '@/composables/useBreadcrumbs'
const table = ref() const table = ref()
const route = useRoute() const route = useRoute()
@ -30,9 +31,44 @@ watch(getParams, () => {
}) })
const refInspectConfig = ref() const refInspectConfig = ref()
const breadcrumbs = useBreadcrumbs()
function updateBreadcrumbs() {
const path = basePath.value
.split('/')
.filter(v => v)
.map(v => {
return {
name: 'Manage Configs',
translatedName: () => v,
path: '/config',
query: {
dir: v,
},
hasChildren: false,
}
})
breadcrumbs.value = [{
name: 'Dashboard',
translatedName: () => $gettext('Dashboard'),
path: '/dashboard',
hasChildren: false,
}, {
name: 'Manage Configs',
translatedName: () => $gettext('Manage Configs'),
path: '/config',
hasChildren: false,
}, ...path]
}
onMounted(() => {
updateBreadcrumbs()
})
watch(route, () => { watch(route, () => {
refInspectConfig.value?.test() refInspectConfig.value?.test()
updateBreadcrumbs()
}) })
function goBack() { function goBack() {
@ -62,7 +98,6 @@ function goBack() {
:api="config" :api="config"
:columns="configColumns" :columns="configColumns"
disable-delete disable-delete
disable-search
disable-view disable-view
row-key="name" row-key="name"
:get-params="getParams" :get-params="getParams"

View file

@ -9,6 +9,7 @@ import ngx from '@/api/ngx'
import InspectConfig from '@/views/config/InspectConfig.vue' import InspectConfig from '@/views/config/InspectConfig.vue'
import ChatGPT from '@/components/ChatGPT/ChatGPT.vue' import ChatGPT from '@/components/ChatGPT/ChatGPT.vue'
import type { ChatComplicationMessage } from '@/api/openai' import type { ChatComplicationMessage } from '@/api/openai'
import { useBreadcrumbs } from '@/composables/useBreadcrumbs'
const route = useRoute() const route = useRoute()
const router = useRouter() const router = useRouter()
@ -43,17 +44,51 @@ const newPath = computed(() => [nginxConfigBase.value, basePath.value, data.valu
.join('/')) .join('/'))
const relativePath = computed(() => (route.params.name as string[]).join('/')) const relativePath = computed(() => (route.params.name as string[]).join('/'))
const breadcrumbs = useBreadcrumbs()
async function init() { async function init() {
const { name } = route.params const { name } = route.params
data.value.name = name?.[name?.length - 1] ?? '' data.value.name = name?.[name?.length - 1] ?? ''
origName.value = data.value.name origName.value = data.value.name
if (data.value.name) { if (!addMode.value) {
config.get(relativePath.value).then(r => { config.get(relativePath.value).then(r => {
data.value = r data.value = r
historyChatgptRecord.value = r.chatgpt_messages historyChatgptRecord.value = r.chatgpt_messages
modifiedAt.value = r.modified_at modifiedAt.value = r.modified_at
const path = data.value.filepath
.replaceAll(`${nginxConfigBase.value}/`, '')
.replaceAll(data.value.name, '')
.split('/')
.filter(v => v)
.map(v => {
return {
name: 'Manage Configs',
translatedName: () => v,
path: '/config',
query: {
dir: v,
},
hasChildren: false,
}
})
breadcrumbs.value = [{
name: 'Dashboard',
translatedName: () => $gettext('Dashboard'),
path: '/dashboard',
hasChildren: false,
}, {
name: 'Manage Configs',
translatedName: () => $gettext('Manage Configs'),
path: '/config',
hasChildren: false,
}, ...path, {
name: 'Edit Config',
translatedName: () => origName.value,
hasChildren: false,
}]
}).catch(r => { }).catch(r => {
message.error(r.message ?? $gettext('Server error')) message.error(r.message ?? $gettext('Server error'))
}) })
@ -62,6 +97,37 @@ async function init() {
data.value.content = '' data.value.content = ''
historyChatgptRecord.value = [] historyChatgptRecord.value = []
data.value.filepath = '' data.value.filepath = ''
const path = basePath.value
.split('/')
.filter(v => v)
.map(v => {
return {
name: 'Manage Configs',
translatedName: () => v,
path: '/config',
query: {
dir: v,
},
hasChildren: false,
}
})
breadcrumbs.value = [{
name: 'Dashboard',
translatedName: () => $gettext('Dashboard'),
path: '/dashboard',
hasChildren: false,
}, {
name: 'Manage Configs',
translatedName: () => $gettext('Manage Configs'),
path: '/config',
hasChildren: false,
}, ...path, {
name: 'Add Config',
translatedName: () => $gettext('Add Configuration'),
hasChildren: false,
}]
} }
} }

View file

@ -2,12 +2,16 @@ import { h } from 'vue'
import type { customRender } from '@/components/StdDesign/StdDataDisplay/StdTableTransformer' import type { customRender } from '@/components/StdDesign/StdDataDisplay/StdTableTransformer'
import { datetime } from '@/components/StdDesign/StdDataDisplay/StdTableTransformer' import { datetime } from '@/components/StdDesign/StdDataDisplay/StdTableTransformer'
import type { JSXElements } from '@/components/StdDesign/types' import type { JSXElements } from '@/components/StdDesign/types'
import { input } from '@/components/StdDesign/StdDataEntry'
const configColumns = [{ const configColumns = [{
title: () => $gettext('Name'), title: () => $gettext('Name'),
dataIndex: 'name', dataIndex: 'name',
sorter: true, sorter: true,
pithy: true, pithy: true,
search: {
type: input,
},
}, { }, {
title: () => $gettext('Type'), title: () => $gettext('Type'),
dataIndex: 'is_dir', dataIndex: 'is_dir',