mirror of
https://github.com/0xJacky/nginx-ui.git
synced 2025-05-11 02:15:48 +02:00
feat: better breadcrumbs for config list and editor; add filename filter for configurations list.
This commit is contained in:
parent
53ae1a1ef9
commit
5dd2c8f931
8 changed files with 147 additions and 12 deletions
|
@ -8,9 +8,11 @@ import (
|
|||
"github.com/gin-gonic/gin"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func GetConfigs(c *gin.Context) {
|
||||
name := c.Query("name")
|
||||
orderBy := c.Query("order_by")
|
||||
sort := c.DefaultQuery("sort", "desc")
|
||||
dir := c.DefaultQuery("dir", "/")
|
||||
|
@ -28,6 +30,10 @@ func GetConfigs(c *gin.Context) {
|
|||
file := configFiles[i]
|
||||
fileInfo, _ := file.Info()
|
||||
|
||||
if name != "" && !strings.Contains(file.Name(), name) {
|
||||
continue
|
||||
}
|
||||
|
||||
switch mode := fileInfo.Mode(); {
|
||||
case mode.IsRegular(): // regular file, not a hidden file
|
||||
if "." == file.Name()[0:1] {
|
||||
|
|
|
@ -1,17 +1,13 @@
|
|||
<script setup lang="ts">
|
||||
interface bread {
|
||||
name: string
|
||||
translatedName: () => string
|
||||
path: string
|
||||
hasChildren?: boolean
|
||||
}
|
||||
import type { Bread } from '@/components/Breadcrumb/types'
|
||||
import { useBreadcrumbs } from '@/composables/useBreadcrumbs'
|
||||
|
||||
const name = ref()
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
|
||||
const breadList = computed(() => {
|
||||
const result: bread[] = []
|
||||
const computedBreadList = computed(() => {
|
||||
const result: Bread[] = []
|
||||
|
||||
name.value = route.meta.name
|
||||
|
||||
|
@ -36,6 +32,16 @@ const breadList = computed(() => {
|
|||
|
||||
return result
|
||||
})
|
||||
|
||||
const breadList = useBreadcrumbs()
|
||||
|
||||
onMounted(() => {
|
||||
breadList.value = computedBreadList.value
|
||||
})
|
||||
|
||||
watch(route, () => {
|
||||
breadList.value = computedBreadList.value
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@ -46,7 +52,7 @@ const breadList = computed(() => {
|
|||
>
|
||||
<RouterLink
|
||||
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() }}
|
||||
</RouterLink>
|
||||
|
|
9
app/src/components/Breadcrumb/types.d.ts
vendored
Normal file
9
app/src/components/Breadcrumb/types.d.ts
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
import {LocationQueryRaw} from "vue-router";
|
||||
|
||||
export interface Bread {
|
||||
name: string
|
||||
translatedName: () => string
|
||||
path?: string
|
||||
query?: LocationQueryRaw
|
||||
hasChildren?: boolean
|
||||
}
|
5
app/src/composables/useBreadcrumbs.ts
Normal file
5
app/src/composables/useBreadcrumbs.ts
Normal file
|
@ -0,0 +1,5 @@
|
|||
import type { Bread } from '@/components/Breadcrumb/types'
|
||||
|
||||
export const useBreadcrumbs = () => {
|
||||
return inject('breadList') as Ref<Bread[]>
|
||||
}
|
|
@ -28,6 +28,10 @@ const { server_name } = storeToRefs(useSettingsStore())
|
|||
settings.get_server_name().then(r => {
|
||||
server_name.value = r.name
|
||||
})
|
||||
|
||||
const breadList = ref([])
|
||||
|
||||
provide('breadList', breadList)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
<script setup lang="ts">
|
||||
import StdTable from '@/components/StdDesign/StdDataDisplay/StdTable.vue'
|
||||
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 InspectConfig from '@/views/config/InspectConfig.vue'
|
||||
import { useBreadcrumbs } from '@/composables/useBreadcrumbs'
|
||||
|
||||
const table = ref()
|
||||
const route = useRoute()
|
||||
|
@ -30,9 +31,44 @@ watch(getParams, () => {
|
|||
})
|
||||
|
||||
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, () => {
|
||||
refInspectConfig.value?.test()
|
||||
updateBreadcrumbs()
|
||||
})
|
||||
|
||||
function goBack() {
|
||||
|
@ -62,7 +98,6 @@ function goBack() {
|
|||
:api="config"
|
||||
:columns="configColumns"
|
||||
disable-delete
|
||||
disable-search
|
||||
disable-view
|
||||
row-key="name"
|
||||
:get-params="getParams"
|
||||
|
|
|
@ -9,6 +9,7 @@ import ngx from '@/api/ngx'
|
|||
import InspectConfig from '@/views/config/InspectConfig.vue'
|
||||
import ChatGPT from '@/components/ChatGPT/ChatGPT.vue'
|
||||
import type { ChatComplicationMessage } from '@/api/openai'
|
||||
import { useBreadcrumbs } from '@/composables/useBreadcrumbs'
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
|
@ -43,17 +44,51 @@ const newPath = computed(() => [nginxConfigBase.value, basePath.value, data.valu
|
|||
.join('/'))
|
||||
|
||||
const relativePath = computed(() => (route.params.name as string[]).join('/'))
|
||||
const breadcrumbs = useBreadcrumbs()
|
||||
|
||||
async function init() {
|
||||
const { name } = route.params
|
||||
|
||||
data.value.name = name?.[name?.length - 1] ?? ''
|
||||
origName.value = data.value.name
|
||||
if (data.value.name) {
|
||||
if (!addMode.value) {
|
||||
config.get(relativePath.value).then(r => {
|
||||
data.value = r
|
||||
historyChatgptRecord.value = r.chatgpt_messages
|
||||
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 => {
|
||||
message.error(r.message ?? $gettext('Server error'))
|
||||
})
|
||||
|
@ -62,6 +97,37 @@ async function init() {
|
|||
data.value.content = ''
|
||||
historyChatgptRecord.value = []
|
||||
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,
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,12 +2,16 @@ import { h } from 'vue'
|
|||
import type { customRender } from '@/components/StdDesign/StdDataDisplay/StdTableTransformer'
|
||||
import { datetime } from '@/components/StdDesign/StdDataDisplay/StdTableTransformer'
|
||||
import type { JSXElements } from '@/components/StdDesign/types'
|
||||
import { input } from '@/components/StdDesign/StdDataEntry'
|
||||
|
||||
const configColumns = [{
|
||||
title: () => $gettext('Name'),
|
||||
dataIndex: 'name',
|
||||
sorter: true,
|
||||
pithy: true,
|
||||
search: {
|
||||
type: input,
|
||||
},
|
||||
}, {
|
||||
title: () => $gettext('Type'),
|
||||
dataIndex: 'is_dir',
|
Loading…
Add table
Add a link
Reference in a new issue