@xen-orchestra/web-core 0.35.1 → 0.36.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. package/lib/components/console/VtsRemoteConsole.vue +1 -1
  2. package/lib/components/copy-button/VtsCopyButton.vue +1 -1
  3. package/lib/components/layout/VtsLayoutSidebar.vue +1 -1
  4. package/lib/components/quick-info-card/VtsQuickInfoCard.vue +1 -1
  5. package/lib/components/relative-time/VtsRelativeTime.vue +2 -3
  6. package/lib/components/select/VtsSelect.vue +1 -1
  7. package/lib/components/state-hero/VtsStateHero.vue +20 -10
  8. package/lib/components/table/VtsRow.vue +26 -0
  9. package/lib/components/table/VtsTable.vue +99 -42
  10. package/lib/components/table/cells/VtsCollapsedListCell.vue +59 -0
  11. package/lib/components/table/cells/VtsHeaderCell.vue +31 -0
  12. package/lib/components/table/cells/VtsLinkCell.vue +33 -0
  13. package/lib/components/table/cells/VtsNumberCell.vue +21 -0
  14. package/lib/components/{size-progress-cell/VtsSizeProgressCell.vue → table/cells/VtsProgressBarCell.vue} +8 -5
  15. package/lib/components/table/cells/VtsStatusCell.vue +69 -0
  16. package/lib/components/table/cells/VtsTagCell.vue +24 -0
  17. package/lib/components/table/cells/VtsTextCell.vue +32 -0
  18. package/lib/components/table/cells/VtsTruncatedTextCell.vue +64 -0
  19. package/lib/components/task/VtsQuickTaskButton.vue +1 -1
  20. package/lib/components/tree/VtsTreeLine.vue +1 -1
  21. package/lib/components/ui/alert/UiAlert.vue +1 -1
  22. package/lib/components/ui/button/UiButton.vue +4 -2
  23. package/lib/components/ui/button-icon/UiButtonIcon.vue +12 -11
  24. package/lib/components/ui/column-header/UiColumnHeader.vue +22 -0
  25. package/lib/components/ui/info/UiInfo.vue +5 -1
  26. package/lib/components/ui/input/UiInput.vue +3 -2
  27. package/lib/components/ui/link/UiLink.vue +5 -0
  28. package/lib/components/ui/log-entry-viewer/UiLogEntryViewer.vue +1 -1
  29. package/lib/components/ui/query-search-bar/UiQuerySearchBar.vue +2 -2
  30. package/lib/components/ui/table-cell/UiTableCell.vue +41 -0
  31. package/lib/components/ui/table-pagination/PaginationButton.vue +1 -1
  32. package/lib/components/ui/toaster/UiToaster.vue +1 -1
  33. package/lib/components/ui/top-bottom-table/UiTopBottomTable.vue +6 -2
  34. package/lib/composables/pagination.composable.ts +16 -1
  35. package/lib/composables/relative-time.composable.ts +8 -61
  36. package/lib/composables/table-state.composable.ts +56 -0
  37. package/lib/composables/tree-filter.composable.ts +2 -2
  38. package/lib/icons/fa-icons.ts +2 -0
  39. package/lib/icons/object-icons.ts +1 -1
  40. package/lib/locales/en.json +23 -0
  41. package/lib/locales/fr.json +23 -0
  42. package/lib/packages/form-select/use-form-select-controller.ts +1 -0
  43. package/lib/packages/table/README.md +53 -308
  44. package/lib/packages/table/define-column.ts +7 -0
  45. package/lib/packages/table/define-columns.ts +104 -50
  46. package/lib/packages/table/index.ts +3 -11
  47. package/lib/packages/table/types.ts +10 -0
  48. package/lib/{composables/tree.composable.md → packages/tree/README.md} +28 -23
  49. package/lib/{composables → packages}/tree/branch-definition.ts +9 -4
  50. package/lib/{composables → packages}/tree/branch.ts +15 -20
  51. package/lib/{composables → packages}/tree/build-nodes.ts +5 -5
  52. package/lib/{composables → packages}/tree/define-branch.ts +8 -4
  53. package/lib/{composables → packages}/tree/define-leaf.ts +8 -3
  54. package/lib/{composables → packages}/tree/define-tree.ts +10 -5
  55. package/lib/{composables → packages}/tree/leaf-definition.ts +1 -1
  56. package/lib/{composables → packages}/tree/leaf.ts +3 -3
  57. package/lib/{composables → packages}/tree/tree-node-base.ts +18 -3
  58. package/lib/{composables → packages}/tree/tree-node-definition-base.ts +4 -2
  59. package/lib/{composables → packages}/tree/types.ts +11 -9
  60. package/lib/{composables/tree.composable.ts → packages/tree/use-tree.ts} +24 -11
  61. package/lib/tables/column-definitions/address-column.ts +4 -0
  62. package/lib/tables/column-definitions/button-column.ts +35 -0
  63. package/lib/tables/column-definitions/button-icon-column.ts +30 -0
  64. package/lib/tables/column-definitions/collapsed-list-column.ts +12 -0
  65. package/lib/tables/column-definitions/date-column.ts +34 -0
  66. package/lib/tables/column-definitions/info-column.ts +12 -0
  67. package/lib/tables/column-definitions/input-column.ts +32 -0
  68. package/lib/tables/column-definitions/link-column.ts +14 -0
  69. package/lib/tables/column-definitions/literal-column.ts +9 -0
  70. package/lib/tables/column-definitions/number-column.ts +10 -0
  71. package/lib/tables/column-definitions/percent-column.ts +15 -0
  72. package/lib/tables/column-definitions/progress-bar-column.ts +10 -0
  73. package/lib/tables/column-definitions/select-column.ts +12 -0
  74. package/lib/tables/column-definitions/select-item-column.ts +8 -0
  75. package/lib/tables/column-definitions/status-column.ts +16 -0
  76. package/lib/tables/column-definitions/tag-column.ts +11 -0
  77. package/lib/tables/column-definitions/text-column.ts +11 -0
  78. package/lib/tables/column-definitions/truncated-text-column.ts +10 -0
  79. package/lib/tables/column-sets/backup-issue-columns.ts +15 -0
  80. package/lib/tables/column-sets/backup-job-columns.ts +23 -0
  81. package/lib/tables/column-sets/backup-job-schedule-columns.ts +21 -0
  82. package/lib/tables/column-sets/backup-log-columns.ts +19 -0
  83. package/lib/tables/column-sets/host-columns.ts +19 -0
  84. package/lib/tables/column-sets/network-columns.ts +22 -0
  85. package/lib/tables/column-sets/new-vm-network-columns.ts +24 -0
  86. package/lib/tables/column-sets/new-vm-sr-columns.ts +33 -0
  87. package/lib/tables/column-sets/patch-columns.ts +13 -0
  88. package/lib/tables/column-sets/pif-columns.ts +23 -0
  89. package/lib/tables/column-sets/server-columns.ts +18 -0
  90. package/lib/tables/column-sets/sr-columns.ts +20 -0
  91. package/lib/tables/column-sets/vdi-columns.ts +21 -0
  92. package/lib/tables/column-sets/vif-columns.ts +23 -0
  93. package/lib/tables/column-sets/vm-columns.ts +21 -0
  94. package/lib/tables/helpers/render-body-cell.ts +4 -0
  95. package/lib/tables/helpers/render-head-cell.ts +6 -0
  96. package/lib/tables/helpers/render-loading-cell.ts +5 -0
  97. package/lib/tables/types.ts +7 -0
  98. package/lib/utils/size.util.ts +5 -9
  99. package/package.json +1 -1
  100. package/lib/components/data-table/VtsDataTable.vue +0 -70
  101. package/lib/components/table/ColumnTitle.vue +0 -152
  102. package/lib/packages/table/apply-extensions.ts +0 -26
  103. package/lib/packages/table/define-renderer/define-table-cell-renderer.ts +0 -27
  104. package/lib/packages/table/define-renderer/define-table-renderer.ts +0 -47
  105. package/lib/packages/table/define-renderer/define-table-row-renderer.ts +0 -29
  106. package/lib/packages/table/define-renderer/define-table-section-renderer.ts +0 -29
  107. package/lib/packages/table/define-table/define-multi-source-table.ts +0 -39
  108. package/lib/packages/table/define-table/define-table.ts +0 -13
  109. package/lib/packages/table/define-table/define-typed-table.ts +0 -18
  110. package/lib/packages/table/transform-sources.ts +0 -13
  111. package/lib/packages/table/types/extensions.ts +0 -16
  112. package/lib/packages/table/types/index.ts +0 -47
  113. package/lib/packages/table/types/table-cell.ts +0 -18
  114. package/lib/packages/table/types/table-row.ts +0 -20
  115. package/lib/packages/table/types/table-section.ts +0 -19
  116. package/lib/packages/table/types/table.ts +0 -28
  117. package/lib/types/button.type.ts +0 -3
@@ -1,5 +1,5 @@
1
- import type { Branch } from '@core/composables/tree/branch'
2
- import type { Identifiable, Labeled, TreeContext, TreeNodeId, TreeNodeOptions } from '@core/composables/tree/types'
1
+ import type { Branch } from '@core/packages/tree/branch'
2
+ import type { Identifiable, Labeled, TreeContext, TreeNodeId, TreeNodeOptions } from '@core/packages/tree/types'
3
3
 
4
4
  export abstract class TreeNodeBase<TData extends object = any, TDiscriminator = any> {
5
5
  abstract readonly isBranch: boolean
@@ -7,6 +7,7 @@ export abstract class TreeNodeBase<TData extends object = any, TDiscriminator =
7
7
  abstract isExcluded: boolean
8
8
  abstract statuses: Record<string, boolean>
9
9
 
10
+ readonly treeId: string
10
11
  readonly data: TData
11
12
  readonly depth: number
12
13
  readonly parent: Branch | undefined
@@ -14,12 +15,14 @@ export abstract class TreeNodeBase<TData extends object = any, TDiscriminator =
14
15
  readonly options: TreeNodeOptions<TData, TDiscriminator>
15
16
 
16
17
  constructor(
18
+ treeId: string,
17
19
  data: TData,
18
20
  parent: Branch | undefined,
19
21
  context: TreeContext,
20
22
  depth: number,
21
23
  options?: TreeNodeOptions<TData, TDiscriminator>
22
24
  ) {
25
+ this.treeId = treeId
23
26
  this.data = data
24
27
  this.parent = parent
25
28
  this.context = context
@@ -27,7 +30,7 @@ export abstract class TreeNodeBase<TData extends object = any, TDiscriminator =
27
30
  this.options = options ?? ({} as TreeNodeOptions<TData, TDiscriminator>)
28
31
  }
29
32
 
30
- get id(): TreeNodeId {
33
+ get dataId(): TreeNodeId {
31
34
  if (this.options.getId === undefined) {
32
35
  return (this.data as Identifiable).id
33
36
  }
@@ -39,6 +42,18 @@ export abstract class TreeNodeBase<TData extends object = any, TDiscriminator =
39
42
  return this.data[this.options.getId as keyof TData] as TreeNodeId
40
43
  }
41
44
 
45
+ get id(): TreeNodeId {
46
+ const parts = [this.dataId, this.treeId]
47
+ let currentParent = this.parent
48
+
49
+ while (currentParent) {
50
+ parts.push(currentParent.treeId)
51
+ currentParent = currentParent.parent
52
+ }
53
+
54
+ return parts.reverse().join('.')
55
+ }
56
+
42
57
  get label() {
43
58
  if (this.options.getLabel === undefined) {
44
59
  return (this.data as Labeled).label
@@ -1,11 +1,13 @@
1
- import type { TreeNodeOptions } from '@core/composables/tree/types'
1
+ import type { TreeNodeOptions } from '@core/packages/tree/types'
2
2
 
3
3
  export abstract class TreeNodeDefinitionBase<TData extends object, TDiscriminator> {
4
4
  abstract readonly isBranch: boolean
5
+ readonly treeId: string
5
6
  data: TData
6
7
  options: TreeNodeOptions<TData, TDiscriminator>
7
8
 
8
- constructor(data: TData, options: TreeNodeOptions<TData, TDiscriminator>) {
9
+ constructor(treeId: string, data: TData, options: TreeNodeOptions<TData, TDiscriminator>) {
10
+ this.treeId = treeId
9
11
  this.data = data
10
12
  this.options = options
11
13
  }
@@ -1,9 +1,10 @@
1
- import type { Branch } from '@core/composables/tree/branch'
2
- import type { BranchDefinition } from '@core/composables/tree/branch-definition'
3
- import type { Leaf } from '@core/composables/tree/leaf'
4
- import type { LeafDefinition } from '@core/composables/tree/leaf-definition'
5
- import type { TreeNodeBase } from '@core/composables/tree/tree-node-base'
6
- import { useTree } from '@core/composables/tree.composable'
1
+ import type { Branch } from '@core/packages/tree/branch'
2
+ import type { BranchDefinition } from '@core/packages/tree/branch-definition'
3
+ import type { Leaf } from '@core/packages/tree/leaf'
4
+ import type { LeafDefinition } from '@core/packages/tree/leaf-definition'
5
+ import type { TreeNodeBase } from '@core/packages/tree/tree-node-base'
6
+ import { useTree } from '@core/packages/tree/use-tree'
7
+ import type { Ref } from 'vue'
7
8
 
8
9
  export type TreeNodeId = string | number
9
10
 
@@ -62,13 +63,14 @@ export type ChildTreeDefinitionGetter<TData extends object, TChildDefinition ext
62
63
  export type TreeContext = {
63
64
  allowMultiSelect: boolean
64
65
  selectedIds: Set<TreeNodeId>
65
- expandedIds: Set<TreeNodeId>
66
+ collapsedIds: Set<TreeNodeId>
66
67
  activeId: TreeNodeId | undefined
67
68
  }
68
69
 
69
70
  export type UseTreeOptions = {
70
71
  allowMultiSelect?: boolean
71
- expand?: boolean
72
+ collapse?: boolean
73
+ collapsedIds?: Ref<Set<TreeNodeId>>
72
74
  selectedLabel?:
73
75
  | ((nodes: TreeNode[]) => string)
74
76
  | {
@@ -88,5 +90,5 @@ export type LeafStatuses = {
88
90
  export type BranchStatuses = LeafStatuses & {
89
91
  'selected-partial': boolean
90
92
  'selected-full': boolean
91
- expanded: boolean
93
+ collapsed: boolean
92
94
  }
@@ -1,4 +1,4 @@
1
- import { buildNodes } from '@core/composables/tree/build-nodes'
1
+ import { buildNodes } from '@core/packages/tree/build-nodes'
2
2
  import type {
3
3
  DefinitionToTreeNode,
4
4
  TreeContext,
@@ -6,7 +6,7 @@ import type {
6
6
  TreeNodeDefinition,
7
7
  TreeNodeId,
8
8
  UseTreeOptions,
9
- } from '@core/composables/tree/types'
9
+ } from '@core/packages/tree/types'
10
10
  import { computed, type MaybeRefOrGetter, reactive, ref, toValue } from 'vue'
11
11
 
12
12
  export function useTree<
@@ -14,21 +14,21 @@ export function useTree<
14
14
  TTreeNode extends DefinitionToTreeNode<TDefinition> = DefinitionToTreeNode<TDefinition>,
15
15
  >(definitions: MaybeRefOrGetter<TDefinition[]>, options: UseTreeOptions = {}) {
16
16
  const selectedIds = ref(new Set<TreeNodeId>())
17
- const expandedIds = ref(new Set<TreeNodeId>())
17
+ const collapsedIds = options.collapsedIds ?? ref(new Set<TreeNodeId>())
18
18
  const activeId = ref<TreeNodeId>()
19
19
 
20
20
  const context = reactive({
21
21
  allowMultiSelect: options.allowMultiSelect ?? false,
22
22
  selectedIds,
23
- expandedIds,
23
+ collapsedIds,
24
24
  activeId,
25
- }) as TreeContext
25
+ }) satisfies TreeContext
26
26
 
27
27
  const nodes = computed(() => {
28
28
  const nodes = buildNodes<TDefinition, TTreeNode>(toValue(definitions), context)
29
29
 
30
- if (options.expand !== false) {
31
- nodes.forEach(node => node.isBranch && node.toggleExpand(true, true))
30
+ if (options.collapse) {
31
+ nodes.forEach(node => node.isBranch && node.toggleCollapse(true, true))
32
32
  }
33
33
 
34
34
  return nodes
@@ -52,11 +52,24 @@ export function useTree<
52
52
 
53
53
  const visibleNodes = computed(() => nodes.value.filter(node => !node.isExcluded))
54
54
 
55
- const getNode = (id: TreeNodeId | undefined) => (id !== undefined ? nodesMap.value.get(id) : undefined)
56
- const getNodes = (ids: TreeNodeId[]) => ids.map(getNode).filter(node => node !== undefined) as TreeNode[]
55
+ function getNode(id: TreeNodeId | undefined): TreeNode | undefined {
56
+ if (id === undefined) {
57
+ return undefined
58
+ }
59
+
60
+ return nodesMap.value.get(id)
61
+ }
62
+
63
+ const selectedNodes = computed(() =>
64
+ Array.from(selectedIds.value.values())
65
+ .map(id => getNode(id))
66
+ .filter(node => node !== undefined)
67
+ )
68
+
69
+ const expandedIds = computed(() => Array.from(nodesMap.value.keys()).filter(id => !collapsedIds.value.has(id)))
70
+
71
+ const expandedNodes = computed(() => expandedIds.value.map(id => getNode(id)).filter(node => node !== undefined))
57
72
 
58
- const selectedNodes = computed(() => getNodes(Array.from(selectedIds.value.values())))
59
- const expandedNodes = computed(() => getNodes(Array.from(expandedIds.value.values())))
60
73
  const activeNode = computed(() => getNode(activeId.value))
61
74
 
62
75
  const selectedLabel = computed(() => {
@@ -0,0 +1,4 @@
1
+ import { useCollapsedListColumn } from '@core/tables/column-definitions/collapsed-list-column.ts'
2
+ import type { HeaderConfig } from '@core/tables/types.ts'
3
+
4
+ export const useAddressColumn = (config?: HeaderConfig) => useCollapsedListColumn({ headerIcon: 'fa:at', ...config })
@@ -0,0 +1,35 @@
1
+ import UiButton, {
2
+ type ButtonAccent,
3
+ type ButtonProps,
4
+ type ButtonVariant,
5
+ type ButtonSize,
6
+ } from '@core/components/ui/button/UiButton.vue'
7
+ import { defineColumn } from '@core/packages/table/define-column'
8
+ import { renderBodyCell } from '@core/tables/helpers/render-body-cell'
9
+ import { renderHeadCell } from '@core/tables/helpers/render-head-cell'
10
+ import type { HeaderConfig } from '@core/tables/types.ts'
11
+ import { h, toValue, type MaybeRefOrGetter } from 'vue'
12
+
13
+ type ButtonConfig = {
14
+ buttonAccent?: MaybeRefOrGetter<ButtonAccent>
15
+ buttonVariant?: MaybeRefOrGetter<ButtonVariant>
16
+ buttonSize?: MaybeRefOrGetter<ButtonSize>
17
+ }
18
+
19
+ export const useButtonColumn = defineColumn((config?: HeaderConfig & ButtonConfig) => ({
20
+ renderHead: () => renderHeadCell(config?.headerIcon, config?.headerLabel),
21
+ renderBody: (label: string, onClick: () => void, props?: Partial<ButtonProps>) =>
22
+ renderBodyCell(() =>
23
+ h(
24
+ UiButton,
25
+ {
26
+ accent: toValue(config?.buttonAccent) ?? 'brand',
27
+ variant: toValue(config?.buttonVariant) ?? 'primary',
28
+ size: toValue(config?.buttonSize) ?? 'medium',
29
+ ...props,
30
+ onClick,
31
+ },
32
+ () => label
33
+ )
34
+ ),
35
+ }))
@@ -0,0 +1,30 @@
1
+ import UiButtonIcon, {
2
+ type ButtonIconAccent,
3
+ type ButtonIconSize,
4
+ } from '@core/components/ui/button-icon/UiButtonIcon.vue'
5
+ import UiTableCell from '@core/components/ui/table-cell/UiTableCell.vue'
6
+ import type { IconName } from '@core/icons'
7
+ import { defineColumn } from '@core/packages/table/define-column'
8
+ import { renderHeadCell } from '@core/tables/helpers/render-head-cell'
9
+ import type { HeaderConfig } from '@core/tables/types.ts'
10
+ import { h, toValue, type MaybeRefOrGetter } from 'vue'
11
+
12
+ type ButtonIconConfig = {
13
+ buttonIcon: MaybeRefOrGetter<IconName>
14
+ buttonSize?: MaybeRefOrGetter<ButtonIconSize>
15
+ buttonAccent?: MaybeRefOrGetter<ButtonIconAccent>
16
+ }
17
+
18
+ export const useButtonIconColumn = defineColumn((config: HeaderConfig & ButtonIconConfig) => ({
19
+ renderHead: () => renderHeadCell(config.headerIcon, config.headerLabel),
20
+ renderBody: (onClick: () => void) =>
21
+ h(UiTableCell, { align: 'center', style: 'width: 6rem' }, () =>
22
+ h(UiButtonIcon, {
23
+ icon: toValue(config.buttonIcon),
24
+ accent: toValue(config.buttonAccent) ?? 'brand',
25
+ size: toValue(config.buttonSize) ?? 'small',
26
+ targetScale: 1.5,
27
+ onClick,
28
+ })
29
+ ),
30
+ }))
@@ -0,0 +1,12 @@
1
+ import VtsCollapsedListCell from '@core/components/table/cells/VtsCollapsedListCell.vue'
2
+ import { defineColumn } from '@core/packages/table/define-column.ts'
3
+ import { renderHeadCell } from '@core/tables/helpers/render-head-cell.ts'
4
+ import type { HeaderConfig } from '@core/tables/types.ts'
5
+ import type { MaybeArray } from '@core/types/utility.type.ts'
6
+ import { toArray } from '@core/utils/to-array.utils.ts'
7
+ import { h } from 'vue'
8
+
9
+ export const useCollapsedListColumn = defineColumn((config?: HeaderConfig) => ({
10
+ renderHead: () => renderHeadCell(config?.headerIcon ?? 'fa:square-caret-down', config?.headerLabel),
11
+ renderBody: (items: MaybeArray<string>) => h(VtsCollapsedListCell, { items: toArray(items) }),
12
+ }))
@@ -0,0 +1,34 @@
1
+ import VtsRelativeTime from '@core/components/relative-time/VtsRelativeTime.vue'
2
+ import { defineColumn } from '@core/packages/table/define-column'
3
+ import { renderBodyCell } from '@core/tables/helpers/render-body-cell'
4
+ import { renderHeadCell } from '@core/tables/helpers/render-head-cell'
5
+ import type { HeaderConfig } from '@core/tables/types.ts'
6
+ import type { DateLike } from '@vueuse/shared'
7
+ import { h } from 'vue'
8
+ import { useI18n } from 'vue-i18n'
9
+
10
+ type DateConfig = Pick<Intl.DateTimeFormatOptions, 'dateStyle' | 'timeStyle'>
11
+
12
+ export const useDateColumn = defineColumn((config?: HeaderConfig & DateConfig) => {
13
+ const { d } = useI18n()
14
+
15
+ return {
16
+ renderHead: () => renderHeadCell(config?.headerIcon ?? 'fa:calendar', config?.headerLabel),
17
+ renderBody: (date?: DateLike, options?: { relative?: boolean }) => {
18
+ return renderBodyCell(() => {
19
+ if (date === undefined) {
20
+ return undefined
21
+ }
22
+
23
+ if (options?.relative) {
24
+ return h(VtsRelativeTime, { date })
25
+ }
26
+
27
+ return d(date, {
28
+ dateStyle: config?.dateStyle,
29
+ timeStyle: config?.timeStyle,
30
+ })
31
+ })
32
+ },
33
+ }
34
+ })
@@ -0,0 +1,12 @@
1
+ import type { InfoAccent } from '@core/components/ui/info/UiInfo.vue'
2
+ import UiInfo from '@core/components/ui/info/UiInfo.vue'
3
+ import { defineColumn } from '@core/packages/table/define-column'
4
+ import { renderBodyCell } from '@core/tables/helpers/render-body-cell'
5
+ import { renderHeadCell } from '@core/tables/helpers/render-head-cell'
6
+ import type { HeaderConfig } from '@core/tables/types.ts'
7
+ import { h } from 'vue'
8
+
9
+ export const useInfoColumn = defineColumn((config?: HeaderConfig) => ({
10
+ renderHead: () => renderHeadCell(config?.headerIcon ?? 'fa:square-caret-down', config?.headerLabel),
11
+ renderBody: (label: string, accent: InfoAccent) => renderBodyCell(() => h(UiInfo, { accent }, () => label)),
12
+ }))
@@ -0,0 +1,32 @@
1
+ import UiInput, { type InputType } from '@core/components/ui/input/UiInput.vue'
2
+ import { defineColumn } from '@core/packages/table/define-column'
3
+ import { renderBodyCell } from '@core/tables/helpers/render-body-cell'
4
+ import { renderHeadCell } from '@core/tables/helpers/render-head-cell'
5
+ import type { HeaderConfig } from '@core/tables/types.ts'
6
+ import { h, toValue, type MaybeRefOrGetter, type Ref } from 'vue'
7
+
8
+ type InputConfig = {
9
+ placeholder?: MaybeRefOrGetter<string | undefined>
10
+ type?: MaybeRefOrGetter<InputType | undefined>
11
+ }
12
+
13
+ export const useInputColumn = defineColumn((config?: HeaderConfig & InputConfig) => ({
14
+ renderHead: () =>
15
+ renderHeadCell(
16
+ config?.headerIcon ?? (config?.type === 'number' ? 'fa:hashtag' : 'fa:align-left'),
17
+ config?.headerLabel
18
+ ),
19
+ renderBody: (model: Ref<string | number>, inputProps?: { disabled?: boolean }) =>
20
+ renderBodyCell(() =>
21
+ h(UiInput, {
22
+ accent: 'brand',
23
+ placeholder: toValue(config?.placeholder),
24
+ type: toValue(config?.type),
25
+ ...inputProps,
26
+ modelValue: toValue(model),
27
+ 'onUpdate:modelValue': (value: string | number) => {
28
+ model.value = value
29
+ },
30
+ })
31
+ ),
32
+ }))
@@ -0,0 +1,14 @@
1
+ import VtsLinkCell, { type VtsLinkCellProps } from '@core/components/table/cells/VtsLinkCell.vue'
2
+ import { defineColumn } from '@core/packages/table/define-column'
3
+ import { renderHeadCell } from '@core/tables/helpers/render-head-cell'
4
+ import type { HeaderConfig } from '@core/tables/types.ts'
5
+ import { h } from 'vue'
6
+
7
+ export const useLinkColumn = defineColumn((config?: HeaderConfig) => ({
8
+ renderHead: () => renderHeadCell(config?.headerIcon ?? 'fa:a', config?.headerLabel),
9
+ renderBody: (link: { label: string } & VtsLinkCellProps) => {
10
+ const { label, ...linkCellProps } = link
11
+
12
+ return h(VtsLinkCell, linkCellProps, () => label)
13
+ },
14
+ }))
@@ -0,0 +1,9 @@
1
+ import { defineColumn } from '@core/packages/table/define-column'
2
+ import { renderBodyCell } from '@core/tables/helpers/render-body-cell'
3
+ import { renderHeadCell } from '@core/tables/helpers/render-head-cell'
4
+ import type { HeaderConfig } from '@core/tables/types.ts'
5
+
6
+ export const useLiteralColumn = defineColumn((config?: HeaderConfig) => ({
7
+ renderHead: () => renderHeadCell(config?.headerIcon ?? 'fa:square-caret-down', config?.headerLabel),
8
+ renderBody: (value: any) => renderBodyCell(() => value),
9
+ }))
@@ -0,0 +1,10 @@
1
+ import VtsNumberCell from '@core/components/table/cells/VtsNumberCell.vue'
2
+ import { defineColumn } from '@core/packages/table/define-column'
3
+ import { renderHeadCell } from '@core/tables/helpers/render-head-cell'
4
+ import type { HeaderConfig } from '@core/tables/types.ts'
5
+ import { h } from 'vue'
6
+
7
+ export const useNumberColumn = defineColumn((headerConfig?: HeaderConfig) => ({
8
+ renderHead: () => renderHeadCell(headerConfig?.headerIcon ?? 'fa:hashtag', headerConfig?.headerLabel),
9
+ renderBody: (number?: number | string, unit?: string) => h(VtsNumberCell, { unit }, () => number),
10
+ }))
@@ -0,0 +1,15 @@
1
+ import VtsNumberCell from '@core/components/table/cells/VtsNumberCell.vue'
2
+ import { defineColumn } from '@core/packages/table/define-column'
3
+ import { renderHeadCell } from '@core/tables/helpers/render-head-cell'
4
+ import type { HeaderConfig } from '@core/tables/types.ts'
5
+ import { h } from 'vue'
6
+ import { useI18n } from 'vue-i18n'
7
+
8
+ export const usePercentColumn = defineColumn((headerConfig?: HeaderConfig) => {
9
+ const { n } = useI18n()
10
+
11
+ return {
12
+ renderHead: () => renderHeadCell(headerConfig?.headerIcon ?? 'fa:hashtag', headerConfig?.headerLabel),
13
+ renderBody: (number: number) => h(VtsNumberCell, () => n(number, 'percent')),
14
+ }
15
+ })
@@ -0,0 +1,10 @@
1
+ import VtsProgressBarCell from '@core/components/table/cells/VtsProgressBarCell.vue'
2
+ import { defineColumn } from '@core/packages/table/define-column'
3
+ import { renderHeadCell } from '@core/tables/helpers/render-head-cell'
4
+ import type { HeaderConfig } from '@core/tables/types.ts'
5
+ import { h } from 'vue'
6
+
7
+ export const useProgressBarColumn = defineColumn((config?: HeaderConfig) => ({
8
+ renderHead: () => renderHeadCell(config?.headerIcon ?? 'fa:hashtag', config?.headerLabel),
9
+ renderBody: (current: number, total: number) => h(VtsProgressBarCell, { current, total }),
10
+ }))
@@ -0,0 +1,12 @@
1
+ import VtsSelect from '@core/components/select/VtsSelect.vue'
2
+ import type { FormSelectId } from '@core/packages/form-select/types.ts'
3
+ import { defineColumn } from '@core/packages/table/define-column.ts'
4
+ import { renderBodyCell } from '@core/tables/helpers/render-body-cell'
5
+ import { renderHeadCell } from '@core/tables/helpers/render-head-cell'
6
+ import type { HeaderConfig } from '@core/tables/types.ts'
7
+ import { h } from 'vue'
8
+
9
+ export const useSelectColumn = defineColumn((config?: HeaderConfig) => ({
10
+ renderHead: () => renderHeadCell(config?.headerIcon, config?.headerLabel),
11
+ renderBody: (id: FormSelectId) => renderBodyCell(() => h(VtsSelect, { accent: 'brand', id })),
12
+ }))
@@ -0,0 +1,8 @@
1
+ import { useButtonIconColumn } from '@core/tables/column-definitions/button-icon-column.ts'
2
+ import type { HeaderConfig } from '@core/tables/types.ts'
3
+
4
+ export const useSelectItemColumn = (config?: HeaderConfig) =>
5
+ useButtonIconColumn({
6
+ buttonIcon: 'fa:eye',
7
+ ...config,
8
+ })
@@ -0,0 +1,16 @@
1
+ import VtsStatusCell, { type StatusCellProps } from '@core/components/table/cells/VtsStatusCell.vue'
2
+ import { defineColumn } from '@core/packages/table/define-column'
3
+ import { renderHeadCell } from '@core/tables/helpers/render-head-cell'
4
+ import type { HeaderConfig } from '@core/tables/types.ts'
5
+ import { h } from 'vue'
6
+ import { useI18n } from 'vue-i18n'
7
+
8
+ export const useStatusColumn = defineColumn((config?: HeaderConfig & Omit<StatusCellProps, 'status'>) => {
9
+ const { t } = useI18n()
10
+ const { headerIcon, headerLabel, ...statusCellProps } = config ?? {}
11
+
12
+ return {
13
+ renderHead: () => renderHeadCell(headerIcon ?? 'fa:square-caret-down', headerLabel ?? t('status')),
14
+ renderBody: (status: StatusCellProps['status']) => h(VtsStatusCell, { status, ...statusCellProps }),
15
+ }
16
+ })
@@ -0,0 +1,11 @@
1
+ import VtsTagCell from '@core/components/table/cells/VtsTagCell.vue'
2
+ import { defineColumn } from '@core/packages/table/define-column'
3
+ import { renderHeadCell } from '@core/tables/helpers/render-head-cell'
4
+ import type { HeaderConfig } from '@core/tables/types.ts'
5
+ import type { MaybeArray } from '@core/types/utility.type'
6
+ import { h } from 'vue'
7
+
8
+ export const useTagColumn = defineColumn((config?: HeaderConfig) => ({
9
+ renderHead: () => renderHeadCell(config?.headerIcon ?? 'fa:square-caret-down', config?.headerLabel),
10
+ renderBody: (tag: MaybeArray<string>) => h(VtsTagCell, { tag }),
11
+ }))
@@ -0,0 +1,11 @@
1
+ import type { TextCellProps } from '@core/components/table/cells/VtsTextCell.vue'
2
+ import VtsTextCell from '@core/components/table/cells/VtsTextCell.vue'
3
+ import { defineColumn } from '@core/packages/table/define-column.ts'
4
+ import { renderHeadCell } from '@core/tables/helpers/render-head-cell.ts'
5
+ import type { HeaderConfig } from '@core/tables/types.ts'
6
+ import { h } from 'vue'
7
+
8
+ export const useTextColumn = defineColumn((config?: HeaderConfig) => ({
9
+ renderHead: () => renderHeadCell(config?.headerIcon, config?.headerLabel),
10
+ renderBody: (content: string, props?: TextCellProps) => h(VtsTextCell, props, () => content),
11
+ }))
@@ -0,0 +1,10 @@
1
+ import VtsTruncatedTextCell from '@core/components/table/cells/VtsTruncatedTextCell.vue'
2
+ import { defineColumn } from '@core/packages/table/define-column.ts'
3
+ import { renderHeadCell } from '@core/tables/helpers/render-head-cell.ts'
4
+ import type { HeaderConfig } from '@core/tables/types.ts'
5
+ import { h } from 'vue'
6
+
7
+ export const useTruncatedTextColumn = defineColumn((config?: HeaderConfig & { limit?: number }) => ({
8
+ renderHead: () => renderHeadCell(config?.headerIcon ?? 'fa:align-left', config?.headerLabel),
9
+ renderBody: (content: string) => h(VtsTruncatedTextCell, { content, limit: config?.limit }),
10
+ }))
@@ -0,0 +1,15 @@
1
+ import { defineColumns } from '@core/packages/table/define-columns.ts'
2
+ import { useLinkColumn } from '@core/tables/column-definitions/link-column'
3
+ import { useStatusColumn } from '@core/tables/column-definitions/status-column.ts'
4
+ import { useI18n } from 'vue-i18n'
5
+
6
+ export const useBackupIssueColumns = defineColumns(() => {
7
+ const { t } = useI18n()
8
+
9
+ return {
10
+ job: useLinkColumn({ headerIcon: 'fa:floppy-disk', headerLabel: () => t('job-name') }),
11
+ lastRun: useStatusColumn({ headerIcon: 'fa:square-caret-down', headerLabel: () => t('last') }),
12
+ secondLastRun: useStatusColumn({ headerIcon: 'fa:square-caret-down', headerLabel: () => t('2nd-last') }),
13
+ thirdLastRun: useStatusColumn({ headerIcon: 'fa:square-caret-down', headerLabel: () => t('3rd-last') }),
14
+ }
15
+ })
@@ -0,0 +1,23 @@
1
+ import { defineColumns } from '@core/packages/table/define-columns.ts'
2
+ import { useCollapsedListColumn } from '@core/tables/column-definitions/collapsed-list-column.ts'
3
+ import { useLinkColumn } from '@core/tables/column-definitions/link-column'
4
+ import { useNumberColumn } from '@core/tables/column-definitions/number-column.ts'
5
+ import { useSelectItemColumn } from '@core/tables/column-definitions/select-item-column.ts'
6
+ import { useStatusColumn } from '@core/tables/column-definitions/status-column.ts'
7
+ import { useI18n } from 'vue-i18n'
8
+
9
+ export const useBackupJobColumns = defineColumns(() => {
10
+ const { t } = useI18n()
11
+
12
+ return {
13
+ job: useLinkColumn({ headerLabel: t('job-name') }),
14
+ mode: useCollapsedListColumn({ headerLabel: t('mode') }),
15
+ lastRuns: useStatusColumn({
16
+ headerLabel: t('last-n-runs', { n: 3 }),
17
+ iconOnly: true,
18
+ progressiveSize: true,
19
+ }),
20
+ schedules: useNumberColumn({ headerLabel: t('total-schedules') }),
21
+ selectItem: useSelectItemColumn(),
22
+ }
23
+ })
@@ -0,0 +1,21 @@
1
+ import { defineColumns } from '@core/packages/table/define-columns.ts'
2
+ import { useLinkColumn } from '@core/tables/column-definitions/link-column'
3
+ import { useStatusColumn } from '@core/tables/column-definitions/status-column.ts'
4
+ import { useTextColumn } from '@core/tables/column-definitions/text-column.ts'
5
+ import { useI18n } from 'vue-i18n'
6
+
7
+ export const useBackupJobScheduleColumns = defineColumns(() => {
8
+ const { t } = useI18n()
9
+
10
+ return {
11
+ schedule: useLinkColumn({ headerLabel: () => t('schedule') }),
12
+ id: useTextColumn({ headerLabel: () => t('id'), headerIcon: 'fa:hashtag' }),
13
+ status: useStatusColumn(),
14
+ cronPattern: useTextColumn({ headerLabel: () => t('cron-pattern'), headerIcon: 'fa:clock' }),
15
+ lastThreeRuns: useStatusColumn({
16
+ headerLabel: () => t('last-n-runs', { n: 3 }),
17
+ iconOnly: true,
18
+ progressiveSize: true,
19
+ }),
20
+ }
21
+ })
@@ -0,0 +1,19 @@
1
+ import { defineColumns } from '@core/packages/table/define-columns.ts'
2
+ import { useDateColumn } from '@core/tables/column-definitions/date-column.ts'
3
+ import { useNumberColumn } from '@core/tables/column-definitions/number-column.ts'
4
+ import { useSelectItemColumn } from '@core/tables/column-definitions/select-item-column'
5
+ import { useStatusColumn } from '@core/tables/column-definitions/status-column.ts'
6
+ import { useI18n } from 'vue-i18n'
7
+
8
+ export const useBackupLogsColumns = defineColumns(() => {
9
+ const { t } = useI18n()
10
+
11
+ return {
12
+ startDate: useDateColumn({ headerLabel: () => t('start-date'), dateStyle: 'short', timeStyle: 'medium' }),
13
+ endDate: useDateColumn({ headerLabel: () => t('end-date'), dateStyle: 'short', timeStyle: 'medium' }),
14
+ duration: useNumberColumn({ headerIcon: 'fa:time', headerLabel: () => t('duration') }),
15
+ status: useStatusColumn(),
16
+ transferSize: useNumberColumn({ headerLabel: () => t('transfer-size') }),
17
+ selectItem: useSelectItemColumn(),
18
+ }
19
+ })
@@ -0,0 +1,19 @@
1
+ import { defineColumns } from '@core/packages/table/define-columns.ts'
2
+ import { useAddressColumn } from '@core/tables/column-definitions/address-column.ts'
3
+ import { useLinkColumn } from '@core/tables/column-definitions/link-column'
4
+ import { useSelectItemColumn } from '@core/tables/column-definitions/select-item-column'
5
+ import { useTagColumn } from '@core/tables/column-definitions/tag-column.ts'
6
+ import { useTruncatedTextColumn } from '@core/tables/column-definitions/truncated-text-column'
7
+ import { useI18n } from 'vue-i18n'
8
+
9
+ export const useHostColumns = defineColumns(() => {
10
+ const { t } = useI18n()
11
+
12
+ return {
13
+ host: useLinkColumn({ headerLabel: () => t('host') }),
14
+ description: useTruncatedTextColumn({ headerLabel: () => t('description') }),
15
+ ipAddresses: useAddressColumn({ headerLabel: () => t('ip-addresses') }),
16
+ tags: useTagColumn({ headerLabel: () => t('tags') }),
17
+ selectItem: useSelectItemColumn(),
18
+ }
19
+ })
@@ -0,0 +1,22 @@
1
+ import { defineColumns } from '@core/packages/table/define-columns.ts'
2
+ import { useLinkColumn } from '@core/tables/column-definitions/link-column'
3
+ import { useNumberColumn } from '@core/tables/column-definitions/number-column.ts'
4
+ import { useSelectItemColumn } from '@core/tables/column-definitions/select-item-column'
5
+ import { useStatusColumn } from '@core/tables/column-definitions/status-column.ts'
6
+ import { useTextColumn } from '@core/tables/column-definitions/text-column.ts'
7
+ import { useTruncatedTextColumn } from '@core/tables/column-definitions/truncated-text-column'
8
+ import { useI18n } from 'vue-i18n'
9
+
10
+ export const useNetworkColumns = defineColumns(() => {
11
+ const { t } = useI18n()
12
+
13
+ return {
14
+ network: useLinkColumn({ headerLabel: () => t('name') }),
15
+ description: useTruncatedTextColumn({ headerLabel: () => t('description') }),
16
+ status: useStatusColumn({ headerLabel: () => t('status') }),
17
+ vlan: useNumberColumn({ headerLabel: () => t('vlan') }),
18
+ mtu: useNumberColumn({ headerLabel: () => t('mtu') }),
19
+ defaultLockingMode: useTextColumn({ headerLabel: () => t('default-locking-mode') }),
20
+ selectItem: useSelectItemColumn(),
21
+ }
22
+ })