ConfigList.vue 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. <script setup lang="ts">
  2. import { StdTable } from '@uozi-admin/curd'
  3. import config from '@/api/config'
  4. import FooterToolBar from '@/components/FooterToolbar'
  5. import { useBreadcrumbs } from '@/composables/useBreadcrumbs'
  6. import { isProtectedPath } from '@/views/config/configUtils'
  7. import Delete from './components/Delete.vue'
  8. import Mkdir from './components/Mkdir.vue'
  9. import Rename from './components/Rename.vue'
  10. import configColumns from './configColumns'
  11. import InspectConfig from './InspectConfig.vue'
  12. const table = useTemplateRef('table')
  13. const route = useRoute()
  14. const router = useRouter()
  15. const basePath = computed(() => {
  16. let dir = route?.query?.dir ?? ''
  17. if (dir)
  18. dir += '/'
  19. return dir as string
  20. })
  21. const getParams = computed(() => {
  22. return {
  23. dir: basePath.value,
  24. }
  25. })
  26. const update = ref(1)
  27. watch(getParams, () => {
  28. update.value++
  29. })
  30. const refInspectConfig = useTemplateRef('refInspectConfig')
  31. const breadcrumbs = useBreadcrumbs()
  32. function updateBreadcrumbs() {
  33. const filteredPath = basePath.value
  34. .split('/')
  35. .filter(v => v)
  36. let accumulatedPath = ''
  37. const path = filteredPath.map((segment, index) => {
  38. const decodedSegment = decodeURIComponent(segment)
  39. if (index === 0) {
  40. accumulatedPath = segment
  41. }
  42. else {
  43. accumulatedPath = `${accumulatedPath}/${segment}`
  44. }
  45. return {
  46. name: 'Manage Configs',
  47. translatedName: () => decodedSegment,
  48. path: '/config',
  49. query: {
  50. dir: accumulatedPath,
  51. },
  52. hasChildren: false,
  53. }
  54. })
  55. breadcrumbs.value = [{
  56. name: 'Dashboard',
  57. translatedName: () => $gettext('Dashboard'),
  58. path: '/dashboard',
  59. hasChildren: false,
  60. }, {
  61. name: 'Manage Configs',
  62. translatedName: () => $gettext('Manage Configs'),
  63. path: '/config',
  64. hasChildren: false,
  65. }, ...path]
  66. }
  67. onMounted(() => {
  68. updateBreadcrumbs()
  69. })
  70. watch(route, () => {
  71. refInspectConfig.value?.test()
  72. updateBreadcrumbs()
  73. })
  74. function goBack() {
  75. const pathSegments = basePath.value.split('/').slice(0, -2)
  76. const encodedPath = pathSegments.length > 0 ? pathSegments.join('/') : ''
  77. router.push({
  78. path: '/config',
  79. query: {
  80. dir: encodedPath || undefined,
  81. },
  82. })
  83. }
  84. const refMkdir = useTemplateRef('refMkdir')
  85. const refRename = useTemplateRef('refRename')
  86. const refDelete = useTemplateRef('refDelete')
  87. // Check if a file/directory is protected
  88. function isProtected(name: string) {
  89. return isProtectedPath(name)
  90. }
  91. </script>
  92. <template>
  93. <ACard :title="$gettext('Configurations')">
  94. <template #extra>
  95. <AButton
  96. v-if="basePath"
  97. type="link"
  98. size="small"
  99. @click="goBack"
  100. >
  101. {{ $gettext('Back') }}
  102. </AButton>
  103. <AButton
  104. type="link"
  105. size="small"
  106. @click="router.push({
  107. path: '/config/add',
  108. query: { basePath: basePath || undefined },
  109. })"
  110. >
  111. {{ $gettext('Create File') }}
  112. </AButton>
  113. <AButton
  114. type="link"
  115. size="small"
  116. @click="() => refMkdir?.open(basePath)"
  117. >
  118. {{ $gettext('Create Folder') }}
  119. </AButton>
  120. </template>
  121. <InspectConfig ref="refInspectConfig" />
  122. <StdTable
  123. :key="update"
  124. ref="table"
  125. :get-list-api="config.getList"
  126. :columns="configColumns"
  127. disable-delete
  128. disable-view
  129. row-key="name"
  130. :custom-query-params="getParams"
  131. disable-router-query
  132. disable-edit
  133. :scroll-x="880"
  134. >
  135. <template #beforeActions="{ record }">
  136. <AButton
  137. type="link"
  138. size="small"
  139. @click="() => {
  140. if (!record.is_dir) {
  141. router.push({
  142. path: `/config/${encodeURIComponent(record.name)}/edit`,
  143. query: {
  144. basePath,
  145. },
  146. })
  147. }
  148. else {
  149. let encodedPath = '';
  150. if (basePath) {
  151. encodedPath = basePath;
  152. }
  153. encodedPath += encodeURIComponent(record.name);
  154. router.push({
  155. query: {
  156. dir: encodedPath,
  157. },
  158. })
  159. }
  160. }"
  161. >
  162. {{ $gettext('Modify') }}
  163. </AButton>
  164. <AButton
  165. v-if="!isProtected(record.name)"
  166. type="link"
  167. size="small"
  168. @click="() => refRename?.open(basePath, record.name, record.is_dir)"
  169. >
  170. {{ $gettext('Rename') }}
  171. </AButton>
  172. <AButton
  173. v-if="!isProtected(record.name)"
  174. type="link"
  175. size="small"
  176. danger
  177. @click="() => refDelete?.open(basePath, record.name, record.is_dir)"
  178. >
  179. {{ $gettext('Delete') }}
  180. </AButton>
  181. </template>
  182. </StdTable>
  183. <Mkdir
  184. ref="refMkdir"
  185. @created="() => table?.refresh()"
  186. />
  187. <Rename
  188. ref="refRename"
  189. @renamed="() => table?.refresh()"
  190. />
  191. <Delete
  192. ref="refDelete"
  193. @deleted="() => table?.refresh()"
  194. />
  195. <FooterToolBar v-if="basePath">
  196. <AButton @click="goBack">
  197. {{ $gettext('Back') }}
  198. </AButton>
  199. </FooterToolBar>
  200. </ACard>
  201. </template>
  202. <style scoped>
  203. </style>