StreamList.vue 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. <script setup lang="tsx">
  2. import type { CustomRenderArgs, StdTableColumn } from '@uozi-admin/curd'
  3. import type { EnvGroup } from '@/api/env_group'
  4. import type { Stream } from '@/api/stream'
  5. import type { JSXElements } from '@/types'
  6. import { actualFieldRender, datetimeRender, StdTable } from '@uozi-admin/curd'
  7. import { Badge, message } from 'ant-design-vue'
  8. import env_group from '@/api/env_group'
  9. import stream from '@/api/stream'
  10. import EnvGroupTabs from '@/components/EnvGroupTabs'
  11. import StdBatchEdit from '@/components/StdDesign/StdDataDisplay/StdBatchEdit.vue'
  12. import { ConfigStatus } from '@/constants'
  13. import InspectConfig from '@/views/config/InspectConfig.vue'
  14. import envGroupColumns from '@/views/environments/group/columns'
  15. import StreamDuplicate from '@/views/stream/components/StreamDuplicate.vue'
  16. const columns: StdTableColumn[] = [{
  17. title: () => $gettext('Name'),
  18. dataIndex: 'name',
  19. sorter: true,
  20. pure: true,
  21. edit: {
  22. type: 'input',
  23. },
  24. search: true,
  25. width: 150,
  26. }, {
  27. title: () => $gettext('Node Group'),
  28. dataIndex: 'env_group_id',
  29. customRender: actualFieldRender('env_group.name'),
  30. edit: {
  31. type: 'selector',
  32. selector: {
  33. getListApi: env_group.getList,
  34. columns: envGroupColumns,
  35. valueKey: 'id',
  36. displayKey: 'name',
  37. selectionType: 'radio',
  38. },
  39. },
  40. sorter: true,
  41. pure: true,
  42. width: 150,
  43. }, {
  44. title: () => $gettext('Status'),
  45. dataIndex: 'status',
  46. customRender: (args: CustomRenderArgs) => {
  47. const template: JSXElements = []
  48. const { text } = args
  49. if (text === ConfigStatus.Enabled) {
  50. template.push(<Badge status="success" />)
  51. template.push(h('span', $gettext('Enabled')))
  52. }
  53. else if (text === ConfigStatus.Disabled) {
  54. template.push(<Badge status="warning" />)
  55. template.push(h('span', $gettext('Disabled')))
  56. }
  57. return h('div', template)
  58. },
  59. sorter: true,
  60. pure: true,
  61. width: 200,
  62. }, {
  63. title: () => $gettext('Updated at'),
  64. dataIndex: 'modified_at',
  65. customRender: datetimeRender,
  66. sorter: true,
  67. pure: true,
  68. width: 200,
  69. }, {
  70. title: () => $gettext('Actions'),
  71. dataIndex: 'actions',
  72. width: 250,
  73. fixed: 'right',
  74. }]
  75. const table = ref()
  76. const inspect_config = ref()
  77. function enable(name: string) {
  78. stream.enable(name).then(() => {
  79. message.success($gettext('Enabled successfully'))
  80. table.value?.get_list()
  81. inspect_config.value?.test()
  82. }).catch(r => {
  83. message.error($gettext('Failed to enable %{msg}', { msg: r.message ?? '' }), 10)
  84. })
  85. }
  86. function disable(name: string) {
  87. stream.disable(name).then(() => {
  88. message.success($gettext('Disabled successfully'))
  89. table.value?.get_list()
  90. inspect_config.value?.test()
  91. }).catch(r => {
  92. message.error($gettext('Failed to disable %{msg}', { msg: r.message ?? '' }))
  93. })
  94. }
  95. function destroy(stream_name: string) {
  96. stream.destroy(stream_name).then(() => {
  97. table.value.get_list()
  98. message.success($gettext('Delete stream: %{stream_name}', { stream_name }))
  99. inspect_config.value?.test()
  100. })
  101. }
  102. const showDuplicator = ref(false)
  103. const target = ref('')
  104. function handle_click_duplicate(name: string) {
  105. showDuplicator.value = true
  106. target.value = name
  107. }
  108. const route = useRoute()
  109. const envGroupId = ref(Number.parseInt(route.query.env_group_id as string) || 0)
  110. const envGroups = ref([]) as Ref<EnvGroup[]>
  111. onMounted(async () => {
  112. let page = 1
  113. while (true) {
  114. try {
  115. const { data, pagination } = await env_group.getList({ page })
  116. if (!data || !pagination)
  117. return
  118. envGroups.value.push(...data)
  119. if (data.length < pagination?.per_page) {
  120. return
  121. }
  122. page++
  123. }
  124. catch {
  125. return
  126. }
  127. }
  128. })
  129. watch(route, () => {
  130. inspect_config.value?.test()
  131. })
  132. const showAddStream = ref(false)
  133. const name = ref('')
  134. function add() {
  135. showAddStream.value = true
  136. name.value = ''
  137. }
  138. function handleAddStream() {
  139. stream.save(name.value, { name: name.value, content: 'server\t{\n\n}' }).then(() => {
  140. showAddStream.value = false
  141. table.value?.get_list()
  142. message.success($gettext('Added successfully'))
  143. })
  144. }
  145. const stdBatchEditRef = useTemplateRef('stdBatchEditRef')
  146. async function handleClickBatchEdit(batchColumns: StdTableColumn[], selectedRowKeys: string[], selectedRows: Stream[]) {
  147. stdBatchEditRef.value?.showModal(batchColumns, selectedRowKeys, selectedRows)
  148. }
  149. function handleBatchUpdated() {
  150. table.value?.get_list()
  151. table.value?.resetSelection()
  152. }
  153. </script>
  154. <template>
  155. <ACard :title="$gettext('Manage Streams')">
  156. <template #extra>
  157. <div class="flex items-center cursor-default">
  158. <a class="mr-4" @click="add">{{ $gettext('Add') }}</a>
  159. </div>
  160. </template>
  161. <InspectConfig ref="inspect_config" />
  162. <EnvGroupTabs v-model:active-key="envGroupId" :env-groups="envGroups" />
  163. <StdTable
  164. ref="table"
  165. :get-list-api="stream.getList"
  166. :columns="columns"
  167. :table-props="{
  168. rowKey: 'name',
  169. }"
  170. disable-delete
  171. disable-view
  172. :scroll-x="800"
  173. :get-params="{
  174. env_group_id: envGroupId,
  175. }"
  176. @edit-item="record => $router.push({
  177. path: `/streams/${encodeURIComponent(record.name)}`,
  178. })"
  179. @click-batch-modify="handleClickBatchEdit"
  180. >
  181. <template #afterActions="{ record }">
  182. <AButton
  183. v-if="record.enabled"
  184. type="link"
  185. size="small"
  186. @click="disable(record.name)"
  187. >
  188. {{ $gettext('Disable') }}
  189. </AButton>
  190. <AButton
  191. v-else
  192. type="link"
  193. size="small"
  194. @click="enable(record.name)"
  195. >
  196. {{ $gettext('Enable') }}
  197. </AButton>
  198. <AButton
  199. type="link"
  200. size="small"
  201. @click="handle_click_duplicate(record.name)"
  202. >
  203. {{ $gettext('Duplicate') }}
  204. </AButton>
  205. <APopconfirm
  206. :cancel-text="$gettext('No')"
  207. :ok-text="$gettext('OK')"
  208. :title="$gettext('Are you sure you want to delete?')"
  209. :disabled="record.enabled"
  210. @confirm="destroy(record.name)"
  211. >
  212. <AButton
  213. type="link"
  214. size="small"
  215. :disabled="record.enabled"
  216. >
  217. {{ $gettext('Delete') }}
  218. </AButton>
  219. </APopconfirm>
  220. </template>
  221. </StdTable>
  222. <AModal
  223. v-model:open="showAddStream"
  224. :title="$gettext('Add Stream')"
  225. :mask="false"
  226. @ok="handleAddStream"
  227. >
  228. <AForm layout="vertical">
  229. <AFormItem :label="$gettext('Name')">
  230. <AInput v-model:value="name" />
  231. </AFormItem>
  232. </AForm>
  233. </AModal>
  234. <StreamDuplicate
  235. v-model:visible="showDuplicator"
  236. :name="target"
  237. @duplicated="() => table.get_list()"
  238. />
  239. <StdBatchEdit
  240. ref="stdBatchEditRef"
  241. :api="stream"
  242. :columns="columns"
  243. @save="handleBatchUpdated"
  244. />
  245. </ACard>
  246. </template>
  247. <style scoped>
  248. </style>