ModulesTable.vue 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. <script setup lang="tsx">
  2. import type { TableColumnType } from 'ant-design-vue'
  3. import type { FilterResetProps } from 'ant-design-vue/es/table/interface'
  4. import { SearchOutlined } from '@ant-design/icons-vue'
  5. import { Button as AButton, Input as AInput } from 'ant-design-vue'
  6. import { useGlobalStore } from '@/pinia'
  7. const globalStore = useGlobalStore()
  8. const { modules } = storeToRefs(globalStore)
  9. const searchText = ref('')
  10. const searchInput = ref<HTMLInputElement>()
  11. function handleSearch(selectedKeys: string[], confirm: () => void) {
  12. confirm()
  13. searchText.value = selectedKeys[0]
  14. }
  15. function handleReset(clearFilters?: (param?: FilterResetProps) => void) {
  16. clearFilters?.({ confirm: true })
  17. searchText.value = ''
  18. }
  19. // Modules columns
  20. const modulesColumns: TableColumnType[] = [
  21. {
  22. title: $gettext('Module'),
  23. dataIndex: 'name',
  24. width: '800px',
  25. filterDropdown: ({ setSelectedKeys, selectedKeys, confirm, clearFilters }) => (
  26. <div style="padding: 8px">
  27. <AInput
  28. ref={searchInput}
  29. value={selectedKeys[0]}
  30. placeholder={$gettext('Search module name')}
  31. style="width: 188px; margin-bottom: 8px; display: block;"
  32. onInput={e => setSelectedKeys(e.target.value ? [e.target.value] : [])}
  33. onPressEnter={() => handleSearch(selectedKeys as string[], confirm)}
  34. class="mb-2"
  35. />
  36. <div class="flex justify-between">
  37. <AButton
  38. type="primary"
  39. onClick={() => handleSearch(selectedKeys as string[], confirm)}
  40. size="small"
  41. class="mr-2"
  42. >
  43. {$gettext('Search')}
  44. </AButton>
  45. <AButton
  46. onClick={() => handleReset(clearFilters)}
  47. size="small"
  48. >
  49. {$gettext('Reset')}
  50. </AButton>
  51. </div>
  52. </div>
  53. ),
  54. filterIcon: filtered => (
  55. <SearchOutlined style={{ color: filtered ? '#1890ff' : undefined }} />
  56. ),
  57. onFilter: (value, record) =>
  58. record.name && record.name.toString().toLowerCase().includes((value as string).toLowerCase()),
  59. onFilterDropdownVisibleChange: visible => {
  60. if (visible) {
  61. setTimeout(() => {
  62. if (searchInput.value) {
  63. searchInput.value.focus()
  64. }
  65. }, 100)
  66. }
  67. },
  68. customRender: args => {
  69. return (
  70. <div>
  71. <div>{args.record.name}</div>
  72. <div class="text-sm text-gray-500">{args.record.params}</div>
  73. </div>
  74. )
  75. },
  76. },
  77. {
  78. title: $gettext('Type'),
  79. dataIndex: 'dynamic',
  80. width: '100px',
  81. filters: [
  82. { text: $gettext('Dynamic'), value: true },
  83. { text: $gettext('Static'), value: false },
  84. ],
  85. onFilter: (value, record) => record.dynamic === value,
  86. customRender: ({ record }) => {
  87. return <span>{record.dynamic ? $gettext('Dynamic') : $gettext('Static')}</span>
  88. },
  89. },
  90. {
  91. title: $gettext('Status'),
  92. dataIndex: 'loaded',
  93. width: '100px',
  94. filters: [
  95. { text: $gettext('Loaded'), value: true },
  96. { text: $gettext('Not Loaded'), value: false },
  97. ],
  98. onFilter: (value, record) => record.loaded === value,
  99. customRender: ({ record }) => {
  100. return <span>{record.loaded ? $gettext('Loaded') : $gettext('Not Loaded')}</span>
  101. },
  102. },
  103. ]
  104. </script>
  105. <template>
  106. <div class="overflow-x-auto">
  107. <ATable
  108. :columns="modulesColumns"
  109. :data-source="modules"
  110. :pagination="false"
  111. size="middle"
  112. :scroll="{ x: '100%' }"
  113. />
  114. </div>
  115. </template>