@xen-orchestra/web-core 0.35.1 → 0.37.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.
- package/lib/components/console/VtsRemoteConsole.vue +1 -1
- package/lib/components/copy-button/VtsCopyButton.vue +1 -1
- package/lib/components/layout/VtsLayoutSidebar.vue +1 -1
- package/lib/components/quick-info-card/VtsQuickInfoCard.vue +1 -1
- package/lib/components/relative-time/VtsRelativeTime.vue +2 -3
- package/lib/components/select/VtsSelect.vue +1 -1
- package/lib/components/state-hero/VtsStateHero.vue +20 -10
- package/lib/components/table/VtsRow.vue +26 -0
- package/lib/components/table/VtsTable.vue +99 -42
- package/lib/components/table/cells/VtsCollapsedListCell.vue +59 -0
- package/lib/components/table/cells/VtsHeaderCell.vue +31 -0
- package/lib/components/table/cells/VtsLinkCell.vue +33 -0
- package/lib/components/table/cells/VtsNumberCell.vue +21 -0
- package/lib/components/{size-progress-cell/VtsSizeProgressCell.vue → table/cells/VtsProgressBarCell.vue} +8 -5
- package/lib/components/table/cells/VtsStatusCell.vue +69 -0
- package/lib/components/table/cells/VtsTagCell.vue +24 -0
- package/lib/components/table/cells/VtsTextCell.vue +32 -0
- package/lib/components/table/cells/VtsTruncatedTextCell.vue +64 -0
- package/lib/components/task/VtsQuickTaskButton.vue +1 -1
- package/lib/components/tree/VtsTreeLine.vue +1 -1
- package/lib/components/ui/alert/UiAlert.vue +1 -1
- package/lib/components/ui/button/UiButton.vue +4 -2
- package/lib/components/ui/button-icon/UiButtonIcon.vue +12 -11
- package/lib/components/ui/column-header/UiColumnHeader.vue +22 -0
- package/lib/components/ui/info/UiInfo.vue +5 -1
- package/lib/components/ui/input/UiInput.vue +3 -2
- package/lib/components/ui/link/UiLink.vue +5 -0
- package/lib/components/ui/log-entry-viewer/UiLogEntryViewer.vue +1 -1
- package/lib/components/ui/query-search-bar/UiQuerySearchBar.vue +2 -2
- package/lib/components/ui/table-cell/UiTableCell.vue +41 -0
- package/lib/components/ui/table-pagination/PaginationButton.vue +1 -1
- package/lib/components/ui/task-item/UiTaskItem.vue +229 -0
- package/lib/components/ui/task-list/UiTaskList.vue +31 -0
- package/lib/components/ui/toaster/UiToaster.vue +1 -1
- package/lib/components/ui/top-bottom-table/UiTopBottomTable.vue +6 -2
- package/lib/components/ui/tree-item-label/UiTreeItemLabel.vue +1 -7
- package/lib/composables/pagination.composable.ts +16 -1
- package/lib/composables/relative-time.composable.ts +8 -61
- package/lib/composables/table-state.composable.ts +56 -0
- package/lib/composables/tree-filter.composable.ts +2 -2
- package/lib/icons/fa-icons.ts +2 -0
- package/lib/icons/object-icons.ts +1 -1
- package/lib/locales/en.json +26 -1
- package/lib/locales/fr.json +26 -1
- package/lib/packages/form-select/use-form-select-controller.ts +1 -0
- package/lib/packages/table/README.md +53 -308
- package/lib/packages/table/define-column.ts +7 -0
- package/lib/packages/table/define-columns.ts +104 -50
- package/lib/packages/table/index.ts +3 -11
- package/lib/packages/table/types.ts +10 -0
- package/lib/{composables/tree.composable.md → packages/tree/README.md} +28 -23
- package/lib/{composables → packages}/tree/branch-definition.ts +9 -4
- package/lib/{composables → packages}/tree/branch.ts +15 -20
- package/lib/{composables → packages}/tree/build-nodes.ts +5 -5
- package/lib/{composables → packages}/tree/define-branch.ts +8 -4
- package/lib/{composables → packages}/tree/define-leaf.ts +8 -3
- package/lib/{composables → packages}/tree/define-tree.ts +10 -5
- package/lib/{composables → packages}/tree/leaf-definition.ts +1 -1
- package/lib/{composables → packages}/tree/leaf.ts +3 -3
- package/lib/{composables → packages}/tree/tree-node-base.ts +18 -3
- package/lib/{composables → packages}/tree/tree-node-definition-base.ts +4 -2
- package/lib/{composables → packages}/tree/types.ts +11 -9
- package/lib/{composables/tree.composable.ts → packages/tree/use-tree.ts} +24 -11
- package/lib/tables/column-definitions/address-column.ts +4 -0
- package/lib/tables/column-definitions/button-column.ts +35 -0
- package/lib/tables/column-definitions/button-icon-column.ts +30 -0
- package/lib/tables/column-definitions/collapsed-list-column.ts +12 -0
- package/lib/tables/column-definitions/date-column.ts +34 -0
- package/lib/tables/column-definitions/info-column.ts +12 -0
- package/lib/tables/column-definitions/input-column.ts +32 -0
- package/lib/tables/column-definitions/link-column.ts +14 -0
- package/lib/tables/column-definitions/literal-column.ts +9 -0
- package/lib/tables/column-definitions/number-column.ts +10 -0
- package/lib/tables/column-definitions/percent-column.ts +15 -0
- package/lib/tables/column-definitions/progress-bar-column.ts +10 -0
- package/lib/tables/column-definitions/select-column.ts +12 -0
- package/lib/tables/column-definitions/select-item-column.ts +8 -0
- package/lib/tables/column-definitions/status-column.ts +16 -0
- package/lib/tables/column-definitions/tag-column.ts +11 -0
- package/lib/tables/column-definitions/text-column.ts +11 -0
- package/lib/tables/column-definitions/truncated-text-column.ts +10 -0
- package/lib/tables/column-sets/backup-issue-columns.ts +15 -0
- package/lib/tables/column-sets/backup-job-columns.ts +23 -0
- package/lib/tables/column-sets/backup-job-schedule-columns.ts +21 -0
- package/lib/tables/column-sets/backup-log-columns.ts +19 -0
- package/lib/tables/column-sets/host-columns.ts +19 -0
- package/lib/tables/column-sets/network-columns.ts +22 -0
- package/lib/tables/column-sets/new-vm-network-columns.ts +24 -0
- package/lib/tables/column-sets/new-vm-sr-columns.ts +33 -0
- package/lib/tables/column-sets/patch-columns.ts +13 -0
- package/lib/tables/column-sets/pif-columns.ts +23 -0
- package/lib/tables/column-sets/server-columns.ts +18 -0
- package/lib/tables/column-sets/sr-columns.ts +20 -0
- package/lib/tables/column-sets/vdi-columns.ts +21 -0
- package/lib/tables/column-sets/vif-columns.ts +23 -0
- package/lib/tables/column-sets/vm-columns.ts +21 -0
- package/lib/tables/helpers/render-body-cell.ts +4 -0
- package/lib/tables/helpers/render-head-cell.ts +6 -0
- package/lib/tables/helpers/render-loading-cell.ts +5 -0
- package/lib/tables/types.ts +7 -0
- package/lib/utils/size.util.ts +5 -9
- package/package.json +1 -1
- package/lib/components/data-table/VtsDataTable.vue +0 -70
- package/lib/components/table/ColumnTitle.vue +0 -152
- package/lib/packages/table/apply-extensions.ts +0 -26
- package/lib/packages/table/define-renderer/define-table-cell-renderer.ts +0 -27
- package/lib/packages/table/define-renderer/define-table-renderer.ts +0 -47
- package/lib/packages/table/define-renderer/define-table-row-renderer.ts +0 -29
- package/lib/packages/table/define-renderer/define-table-section-renderer.ts +0 -29
- package/lib/packages/table/define-table/define-multi-source-table.ts +0 -39
- package/lib/packages/table/define-table/define-table.ts +0 -13
- package/lib/packages/table/define-table/define-typed-table.ts +0 -18
- package/lib/packages/table/transform-sources.ts +0 -13
- package/lib/packages/table/types/extensions.ts +0 -16
- package/lib/packages/table/types/index.ts +0 -47
- package/lib/packages/table/types/table-cell.ts +0 -18
- package/lib/packages/table/types/table-row.ts +0 -20
- package/lib/packages/table/types/table-section.ts +0 -19
- package/lib/packages/table/types/table.ts +0 -28
- package/lib/types/button.type.ts +0 -3
|
@@ -50,12 +50,13 @@ This option allows you to customize the label of the selected nodes.
|
|
|
50
50
|
## `LeafDefinition`
|
|
51
51
|
|
|
52
52
|
```ts
|
|
53
|
-
new LeafDefinition(data)
|
|
54
|
-
new LeafDefinition(data, options)
|
|
53
|
+
new LeafDefinition(treeId, data)
|
|
54
|
+
new LeafDefinition(treeId, data, options)
|
|
55
55
|
```
|
|
56
56
|
|
|
57
57
|
| | Required | Type | Default | |
|
|
58
58
|
| ----------------------- | :------------------: | ---------------------------------------------------- | --------------------------------------- | -------------------------------------------------------------------------------------- |
|
|
59
|
+
| `treeId` | ✓ | `string` | | identifier for tree this node belongs to |
|
|
59
60
|
| `data` | ✓ | `TData` | | data to be stored in the node |
|
|
60
61
|
| `options.discriminator` | | `string` | `undefined` | discriminator for the node when you mix different data types (see Discriminator below) |
|
|
61
62
|
| `options.predicate` | | `(node: TreeNode) => boolean \| undefined` | `undefined` | filter function (see Filtering below) |
|
|
@@ -66,7 +67,7 @@ new LeafDefinition(data, options)
|
|
|
66
67
|
### Example
|
|
67
68
|
|
|
68
69
|
```ts
|
|
69
|
-
const definition = new LeafDefinition({ id: 1, label: 'John Doe', age: 30 })
|
|
70
|
+
const definition = new LeafDefinition('users', { id: 1, label: 'John Doe', age: 30 })
|
|
70
71
|
```
|
|
71
72
|
|
|
72
73
|
## `BranchDefinition`
|
|
@@ -74,8 +75,8 @@ const definition = new LeafDefinition({ id: 1, label: 'John Doe', age: 30 })
|
|
|
74
75
|
A `BranchDefinition` is very similar to a `LeafDefinition`, but it contains a collection of children definitions.
|
|
75
76
|
|
|
76
77
|
```ts
|
|
77
|
-
new BranchDefinition(data, children)
|
|
78
|
-
new BranchDefinition(data, options, children)
|
|
78
|
+
new BranchDefinition(treeId, data, children)
|
|
79
|
+
new BranchDefinition(treeId, data, options, children)
|
|
79
80
|
```
|
|
80
81
|
|
|
81
82
|
| | | Type | Default | |
|
|
@@ -86,9 +87,9 @@ new BranchDefinition(data, options, children)
|
|
|
86
87
|
### Example
|
|
87
88
|
|
|
88
89
|
```ts
|
|
89
|
-
const definition = new BranchDefinition({ id: 'smithes', name: 'The Smithes' }, [
|
|
90
|
-
new LeafDefinition({ id: 'jd-1', name: 'John Smith', age: 30 }),
|
|
91
|
-
new LeafDefinition({ id: 'jd-2', name: 'Jane Smith', age: 28 }),
|
|
90
|
+
const definition = new BranchDefinition('users', { id: 'smithes', name: 'The Smithes' }, [
|
|
91
|
+
new LeafDefinition('users', { id: 'jd-1', name: 'John Smith', age: 30 }),
|
|
92
|
+
new LeafDefinition('users', { id: 'jd-2', name: 'Jane Smith', age: 28 }),
|
|
92
93
|
])
|
|
93
94
|
```
|
|
94
95
|
|
|
@@ -101,8 +102,8 @@ mix different types of nodes at the same collection depth.
|
|
|
101
102
|
|
|
102
103
|
```ts
|
|
103
104
|
const definitions = [
|
|
104
|
-
new LeafDefinition({ id: 'jd-1', label: 'John Doe', age: 30 }),
|
|
105
|
-
new LeafDefinition({ id: 'rx-1', label: 'Rex', breed: 'Golden Retriever' }),
|
|
105
|
+
new LeafDefinition('family', { id: 'jd-1', label: 'John Doe', age: 30 }),
|
|
106
|
+
new LeafDefinition('family', { id: 'rx-1', label: 'Rex', breed: 'Golden Retriever' }),
|
|
106
107
|
]
|
|
107
108
|
|
|
108
109
|
const { nodes } = useTree(definitions)
|
|
@@ -116,8 +117,8 @@ nodes.value.forEach(node => {
|
|
|
116
117
|
|
|
117
118
|
```ts
|
|
118
119
|
const definitions = [
|
|
119
|
-
new LeafDefinition({ id: 'jd-1', label: 'John Doe', age: 30 }, { discriminator: 'person' }),
|
|
120
|
-
new LeafDefinition({ id: 'rx-1', label: 'Rex', breed: 'Golden Retriever' }, { discriminator: 'animal' }),
|
|
120
|
+
new LeafDefinition('family', { id: 'jd-1', label: 'John Doe', age: 30 }, { discriminator: 'person' }),
|
|
121
|
+
new LeafDefinition('family', { id: 'rx-1', label: 'Rex', breed: 'Golden Retriever' }, { discriminator: 'animal' }),
|
|
121
122
|
]
|
|
122
123
|
|
|
123
124
|
const { nodes } = useTree(definitions)
|
|
@@ -138,8 +139,8 @@ the `isBranch` property will serve the same purpose.
|
|
|
138
139
|
|
|
139
140
|
```ts
|
|
140
141
|
const definitions = [
|
|
141
|
-
new LeafDefinition({ id: 'jd-1', label: 'John Doe', age: 30 }),
|
|
142
|
-
new BranchDefinition({ id: 'dogs', label: 'Dogs', legs: 4 }, [
|
|
142
|
+
new LeafDefinition('family', { id: 'jd-1', label: 'John Doe', age: 30 }),
|
|
143
|
+
new BranchDefinition('family', { id: 'dogs', label: 'Dogs', legs: 4 }, [
|
|
143
144
|
/* ... */
|
|
144
145
|
]),
|
|
145
146
|
]
|
|
@@ -254,7 +255,9 @@ const families = [
|
|
|
254
255
|
You can use the `defineTree` helper this way:
|
|
255
256
|
|
|
256
257
|
```ts
|
|
257
|
-
const definitions = defineTree(families, family =>
|
|
258
|
+
const definitions = defineTree('family', families, family =>
|
|
259
|
+
defineTree('member', family.members, member => defineTree('animal', member.animals))
|
|
260
|
+
)
|
|
258
261
|
```
|
|
259
262
|
|
|
260
263
|
This is the equivalent of the following code:
|
|
@@ -263,12 +266,14 @@ This is the equivalent of the following code:
|
|
|
263
266
|
const definitions = families.map(
|
|
264
267
|
family =>
|
|
265
268
|
new BranchDefinition(
|
|
269
|
+
'family',
|
|
266
270
|
family,
|
|
267
271
|
family.members.map(
|
|
268
272
|
member =>
|
|
269
273
|
new BranchDefinition(
|
|
274
|
+
'member',
|
|
270
275
|
member,
|
|
271
|
-
member.animals.map(animal => new LeafDefinition(animal))
|
|
276
|
+
member.animals.map('animal', animal => new LeafDefinition(animal))
|
|
272
277
|
)
|
|
273
278
|
)
|
|
274
279
|
)
|
|
@@ -287,12 +292,12 @@ const entries = [
|
|
|
287
292
|
{ uuid: 'jd-2', name: 'Jane Doe' },
|
|
288
293
|
]
|
|
289
294
|
|
|
290
|
-
const definitionsA = defineTree(entries, {
|
|
295
|
+
const definitionsA = defineTree('user', entries, {
|
|
291
296
|
getId: 'uuid',
|
|
292
297
|
getLabel: 'name',
|
|
293
298
|
})
|
|
294
299
|
|
|
295
|
-
const definitionsB = defineTree(entries, {
|
|
300
|
+
const definitionsB = defineTree('user', entries, {
|
|
296
301
|
getId: entry => entry.uuid,
|
|
297
302
|
getLabel: entry => entry.name,
|
|
298
303
|
})
|
|
@@ -394,8 +399,8 @@ Here are the rules to determine whether a node is visible or not.
|
|
|
394
399
|
</template>
|
|
395
400
|
|
|
396
401
|
<script lang="ts" setup>
|
|
397
|
-
const familyDefinitions = defineTree(families, ({ members }) =>
|
|
398
|
-
defineTree(members, ({ animals }) => defineTree(animals))
|
|
402
|
+
const familyDefinitions = defineTree('family', families, ({ members }) =>
|
|
403
|
+
defineTree('member', members, ({ animals }) => defineTree('animal', animals))
|
|
399
404
|
)
|
|
400
405
|
|
|
401
406
|
const { nodes } = useTree(familyDefinitions)
|
|
@@ -448,7 +453,7 @@ Here are the rules to determine whether a node is visible or not.
|
|
|
448
453
|
</template>
|
|
449
454
|
|
|
450
455
|
<script lang="ts" setup>
|
|
451
|
-
const definitions = defineTree(families, ({ members }) => defineTree(members))
|
|
456
|
+
const definitions = defineTree('family', families, ({ members }) => defineTree('member', members))
|
|
452
457
|
|
|
453
458
|
const { nodes } = useTree(definitions, { allowMultiSelect: true })
|
|
454
459
|
</script>
|
|
@@ -517,8 +522,8 @@ Here are the rules to determine whether a node is visible or not.
|
|
|
517
522
|
return !filterValue ? undefined : label.toLocaleLowerCase().includes(filterValue)
|
|
518
523
|
}
|
|
519
524
|
|
|
520
|
-
const definitions = defineTree(families, { predicate }, ({ members }) =>
|
|
521
|
-
defineTree(members, { predicate }, ({ animals }) => defineTree(animals, { predicate }))
|
|
525
|
+
const definitions = defineTree('family', families, { predicate }, ({ members }) =>
|
|
526
|
+
defineTree('member', members, { predicate }, ({ animals }) => defineTree('animal', animals, { predicate }))
|
|
522
527
|
)
|
|
523
528
|
|
|
524
529
|
const { nodes } = useTree(definitions, { expand: false })
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { TreeNodeDefinitionBase } from '@core/
|
|
2
|
-
import type { TreeNodeDefinition, TreeNodeOptions } from '@core/
|
|
1
|
+
import { TreeNodeDefinitionBase } from '@core/packages/tree/tree-node-definition-base'
|
|
2
|
+
import type { TreeNodeDefinition, TreeNodeOptions } from '@core/packages/tree/types'
|
|
3
3
|
|
|
4
4
|
export class BranchDefinition<
|
|
5
5
|
TData extends object = any,
|
|
@@ -9,8 +9,13 @@ export class BranchDefinition<
|
|
|
9
9
|
readonly isBranch = true
|
|
10
10
|
children: TChildDefinition[]
|
|
11
11
|
|
|
12
|
-
constructor(
|
|
13
|
-
|
|
12
|
+
constructor(
|
|
13
|
+
treeId: string,
|
|
14
|
+
data: TData,
|
|
15
|
+
options: TreeNodeOptions<TData, TDiscriminator>,
|
|
16
|
+
children: TChildDefinition[]
|
|
17
|
+
) {
|
|
18
|
+
super(treeId, data, options)
|
|
14
19
|
|
|
15
20
|
this.children = children
|
|
16
21
|
}
|
|
@@ -1,11 +1,5 @@
|
|
|
1
|
-
import { TreeNodeBase } from '@core/
|
|
2
|
-
import type {
|
|
3
|
-
BranchStatuses,
|
|
4
|
-
ChildTreeGetter,
|
|
5
|
-
TreeContext,
|
|
6
|
-
TreeNode,
|
|
7
|
-
TreeNodeOptions,
|
|
8
|
-
} from '@core/composables/tree/types'
|
|
1
|
+
import { TreeNodeBase } from '@core/packages/tree/tree-node-base'
|
|
2
|
+
import type { BranchStatuses, ChildTreeGetter, TreeContext, TreeNode, TreeNodeOptions } from '@core/packages/tree/types'
|
|
9
3
|
|
|
10
4
|
export class Branch<
|
|
11
5
|
TData extends object = any,
|
|
@@ -16,6 +10,7 @@ export class Branch<
|
|
|
16
10
|
readonly rawChildren: TChildNode[]
|
|
17
11
|
|
|
18
12
|
constructor(
|
|
13
|
+
treeId: string,
|
|
19
14
|
data: TData,
|
|
20
15
|
parent: Branch | undefined,
|
|
21
16
|
context: TreeContext,
|
|
@@ -23,7 +18,7 @@ export class Branch<
|
|
|
23
18
|
options: TreeNodeOptions<TData, TDiscriminator> | undefined,
|
|
24
19
|
getChildTree: ChildTreeGetter<TData, TChildNode, TDiscriminator>
|
|
25
20
|
) {
|
|
26
|
-
super(data, parent, context, depth, options)
|
|
21
|
+
super(treeId, data, parent, context, depth, options)
|
|
27
22
|
this.rawChildren = getChildTree(this)
|
|
28
23
|
}
|
|
29
24
|
|
|
@@ -48,7 +43,7 @@ export class Branch<
|
|
|
48
43
|
}
|
|
49
44
|
|
|
50
45
|
get isExcluded() {
|
|
51
|
-
if (this.parent?.
|
|
46
|
+
if (this.parent?.isCollapsed === true) {
|
|
52
47
|
return true
|
|
53
48
|
}
|
|
54
49
|
|
|
@@ -59,8 +54,8 @@ export class Branch<
|
|
|
59
54
|
return this.failsFilterDownwards
|
|
60
55
|
}
|
|
61
56
|
|
|
62
|
-
get
|
|
63
|
-
return this.context.
|
|
57
|
+
get isCollapsed() {
|
|
58
|
+
return this.context.collapsedIds.has(this.id)
|
|
64
59
|
}
|
|
65
60
|
|
|
66
61
|
get areChildrenFullySelected(): boolean {
|
|
@@ -92,7 +87,7 @@ export class Branch<
|
|
|
92
87
|
matches: this.passesFilter === true,
|
|
93
88
|
'selected-partial': this.context.allowMultiSelect && this.areChildrenPartiallySelected,
|
|
94
89
|
'selected-full': this.context.allowMultiSelect && this.areChildrenFullySelected,
|
|
95
|
-
|
|
90
|
+
collapsed: this.isCollapsed,
|
|
96
91
|
}
|
|
97
92
|
}
|
|
98
93
|
|
|
@@ -101,21 +96,21 @@ export class Branch<
|
|
|
101
96
|
return this.areChildrenFullySelected ? 'all' : this.areChildrenPartiallySelected ? 'some' : 'none'
|
|
102
97
|
}
|
|
103
98
|
|
|
104
|
-
|
|
105
|
-
const
|
|
99
|
+
toggleCollapse(forcedValue?: boolean, recursive?: boolean) {
|
|
100
|
+
const nextCollapsed = forcedValue ?? !this.isCollapsed
|
|
106
101
|
|
|
107
|
-
if (
|
|
108
|
-
this.context.
|
|
102
|
+
if (nextCollapsed) {
|
|
103
|
+
this.context.collapsedIds.add(this.id)
|
|
109
104
|
} else {
|
|
110
|
-
this.context.
|
|
105
|
+
this.context.collapsedIds.delete(this.id)
|
|
111
106
|
}
|
|
112
107
|
|
|
113
|
-
const shouldPropagate = recursive ??
|
|
108
|
+
const shouldPropagate = recursive ?? nextCollapsed
|
|
114
109
|
|
|
115
110
|
if (shouldPropagate) {
|
|
116
111
|
this.rawChildren.forEach(child => {
|
|
117
112
|
if (child.isBranch) {
|
|
118
|
-
child.
|
|
113
|
+
child.toggleCollapse(nextCollapsed, recursive)
|
|
119
114
|
}
|
|
120
115
|
})
|
|
121
116
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { Branch } from '@core/
|
|
2
|
-
import { Leaf } from '@core/
|
|
3
|
-
import type { DefinitionToTreeNode, TreeContext, TreeNode, TreeNodeDefinition } from '@core/
|
|
1
|
+
import { Branch } from '@core/packages/tree/branch'
|
|
2
|
+
import { Leaf } from '@core/packages/tree/leaf'
|
|
3
|
+
import type { DefinitionToTreeNode, TreeContext, TreeNode, TreeNodeDefinition } from '@core/packages/tree/types'
|
|
4
4
|
|
|
5
5
|
export function buildNodes<TDefinition extends TreeNodeDefinition, TTreeNode extends DefinitionToTreeNode<TDefinition>>(
|
|
6
6
|
definitions: TDefinition[],
|
|
@@ -9,10 +9,10 @@ export function buildNodes<TDefinition extends TreeNodeDefinition, TTreeNode ext
|
|
|
9
9
|
function create(definitions: TreeNodeDefinition[], parent: Branch | undefined, depth: number): TreeNode[] {
|
|
10
10
|
return definitions.map(definition =>
|
|
11
11
|
definition.isBranch
|
|
12
|
-
? new Branch(definition.data, parent, context, depth, definition.options, thisBranch =>
|
|
12
|
+
? new Branch(definition.treeId, definition.data, parent, context, depth, definition.options, thisBranch =>
|
|
13
13
|
create(definition.children, thisBranch, depth + 1)
|
|
14
14
|
)
|
|
15
|
-
: new Leaf(definition.data, parent, context, depth, definition.options)
|
|
15
|
+
: new Leaf(definition.treeId, definition.data, parent, context, depth, definition.options)
|
|
16
16
|
)
|
|
17
17
|
}
|
|
18
18
|
|
|
@@ -1,17 +1,21 @@
|
|
|
1
|
-
import { BranchDefinition } from '@core/
|
|
2
|
-
import type { Identifiable, Labeled, TreeNodeDefinition, TreeNodeOptions } from '@core/
|
|
1
|
+
import { BranchDefinition } from '@core/packages/tree/branch-definition'
|
|
2
|
+
import type { Identifiable, Labeled, TreeNodeDefinition, TreeNodeOptions } from '@core/packages/tree/types'
|
|
3
3
|
|
|
4
4
|
export function defineBranch<
|
|
5
5
|
TData extends Identifiable & Labeled,
|
|
6
6
|
TChildDefinition extends TreeNodeDefinition,
|
|
7
7
|
const TDiscriminator,
|
|
8
|
-
>(data: TData, children: TChildDefinition[]): BranchDefinition<TData, TChildDefinition, TDiscriminator>
|
|
8
|
+
>(treeId: string, data: TData, children: TChildDefinition[]): BranchDefinition<TData, TChildDefinition, TDiscriminator>
|
|
9
|
+
|
|
9
10
|
export function defineBranch<TData extends object, TChildDefinition extends TreeNodeDefinition, const TDiscriminator>(
|
|
11
|
+
treeId: string,
|
|
10
12
|
data: TData,
|
|
11
13
|
options: TreeNodeOptions<TData, TDiscriminator>,
|
|
12
14
|
children: TChildDefinition[]
|
|
13
15
|
): BranchDefinition<TData, TChildDefinition, TDiscriminator>
|
|
16
|
+
|
|
14
17
|
export function defineBranch<TData extends object, TChildDefinition extends TreeNodeDefinition, const TDiscriminator>(
|
|
18
|
+
treeId: string,
|
|
15
19
|
data: TData,
|
|
16
20
|
optionsOrChildren: TreeNodeOptions<TData, TDiscriminator> | TChildDefinition[],
|
|
17
21
|
childrenOrNone?: TChildDefinition[]
|
|
@@ -19,5 +23,5 @@ export function defineBranch<TData extends object, TChildDefinition extends Tree
|
|
|
19
23
|
const options = Array.isArray(optionsOrChildren) ? ({} as TreeNodeOptions<TData, TDiscriminator>) : optionsOrChildren
|
|
20
24
|
const children = Array.isArray(optionsOrChildren) ? optionsOrChildren : childrenOrNone!
|
|
21
25
|
|
|
22
|
-
return new BranchDefinition(data, options, children)
|
|
26
|
+
return new BranchDefinition(treeId, data, options, children)
|
|
23
27
|
}
|
|
@@ -1,16 +1,21 @@
|
|
|
1
|
-
import { LeafDefinition } from '@core/
|
|
2
|
-
import type { Identifiable, Labeled, TreeNodeOptions } from '@core/
|
|
1
|
+
import { LeafDefinition } from '@core/packages/tree/leaf-definition'
|
|
2
|
+
import type { Identifiable, Labeled, TreeNodeOptions } from '@core/packages/tree/types'
|
|
3
3
|
|
|
4
4
|
export function defineLeaf<TData extends Identifiable & Labeled, const TDiscriminator>(
|
|
5
|
+
treeId: string,
|
|
5
6
|
data: TData
|
|
6
7
|
): LeafDefinition<TData, TDiscriminator>
|
|
8
|
+
|
|
7
9
|
export function defineLeaf<TData extends object, const TDiscriminator>(
|
|
10
|
+
treeId: string,
|
|
8
11
|
data: TData,
|
|
9
12
|
options: TreeNodeOptions<TData, TDiscriminator>
|
|
10
13
|
): LeafDefinition<TData, TDiscriminator>
|
|
14
|
+
|
|
11
15
|
export function defineLeaf<TData extends object, const TDiscriminator>(
|
|
16
|
+
treeId: string,
|
|
12
17
|
data: TData,
|
|
13
18
|
options?: TreeNodeOptions<TData, TDiscriminator>
|
|
14
19
|
): LeafDefinition<TData, TDiscriminator> {
|
|
15
|
-
return new LeafDefinition(data, options ?? ({} as TreeNodeOptions<TData, TDiscriminator>))
|
|
20
|
+
return new LeafDefinition(treeId, data, options ?? ({} as TreeNodeOptions<TData, TDiscriminator>))
|
|
16
21
|
}
|
|
@@ -1,20 +1,22 @@
|
|
|
1
|
-
import { BranchDefinition } from '@core/
|
|
2
|
-
import { LeafDefinition } from '@core/
|
|
1
|
+
import { BranchDefinition } from '@core/packages/tree/branch-definition'
|
|
2
|
+
import { LeafDefinition } from '@core/packages/tree/leaf-definition'
|
|
3
3
|
import type {
|
|
4
4
|
ChildTreeDefinitionGetter,
|
|
5
5
|
Identifiable,
|
|
6
6
|
Labeled,
|
|
7
7
|
TreeNodeDefinition,
|
|
8
8
|
TreeNodeOptions,
|
|
9
|
-
} from '@core/
|
|
9
|
+
} from '@core/packages/tree/types'
|
|
10
10
|
|
|
11
11
|
// Overload 1: Leaf with no options
|
|
12
12
|
export function defineTree<TData extends Identifiable & Labeled, const TDiscriminator = any>(
|
|
13
|
+
treeId: string,
|
|
13
14
|
entries: TData[]
|
|
14
15
|
): LeafDefinition<TData, TDiscriminator>[]
|
|
15
16
|
|
|
16
17
|
// Overload 2: Leaf with options
|
|
17
18
|
export function defineTree<TData extends object, const TDiscriminator = any>(
|
|
19
|
+
treeId: string,
|
|
18
20
|
entries: TData[],
|
|
19
21
|
options: TreeNodeOptions<TData, TDiscriminator>
|
|
20
22
|
): LeafDefinition<TData, TDiscriminator>[]
|
|
@@ -25,6 +27,7 @@ export function defineTree<
|
|
|
25
27
|
TChildDefinition extends TreeNodeDefinition,
|
|
26
28
|
const TDiscriminator = any,
|
|
27
29
|
>(
|
|
30
|
+
treeId: string,
|
|
28
31
|
entries: TData[],
|
|
29
32
|
getChildTree: ChildTreeDefinitionGetter<TData, TChildDefinition>
|
|
30
33
|
): BranchDefinition<TData, TChildDefinition, TDiscriminator>[]
|
|
@@ -35,6 +38,7 @@ export function defineTree<
|
|
|
35
38
|
TChildDefinition extends TreeNodeDefinition = TreeNodeDefinition,
|
|
36
39
|
const TDiscriminator = any,
|
|
37
40
|
>(
|
|
41
|
+
treeId: string,
|
|
38
42
|
entries: TData[],
|
|
39
43
|
options: TreeNodeOptions<TData, TDiscriminator>,
|
|
40
44
|
getChildTree: ChildTreeDefinitionGetter<TData, TChildDefinition>
|
|
@@ -46,6 +50,7 @@ export function defineTree<
|
|
|
46
50
|
TChildDefinition extends TreeNodeDefinition = TreeNodeDefinition,
|
|
47
51
|
const TDiscriminator = any,
|
|
48
52
|
>(
|
|
53
|
+
treeId: string,
|
|
49
54
|
entries: TData[],
|
|
50
55
|
optionsOrGetChildTree?: TreeNodeOptions<TData, TDiscriminator> | ChildTreeDefinitionGetter<TData, TChildDefinition>,
|
|
51
56
|
getChildTreeOrNone?: ChildTreeDefinitionGetter<TData, TChildDefinition>
|
|
@@ -58,8 +63,8 @@ export function defineTree<
|
|
|
58
63
|
const getChildTree = typeof optionsOrGetChildTree === 'function' ? optionsOrGetChildTree : getChildTreeOrNone
|
|
59
64
|
|
|
60
65
|
if (getChildTree !== undefined) {
|
|
61
|
-
return entries.map(data => new BranchDefinition(data, options, getChildTree(data)))
|
|
66
|
+
return entries.map(data => new BranchDefinition(treeId, data, options, getChildTree(data)))
|
|
62
67
|
}
|
|
63
68
|
|
|
64
|
-
return entries.map(data => new LeafDefinition(data, options))
|
|
69
|
+
return entries.map(data => new LeafDefinition(treeId, data, options))
|
|
65
70
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { TreeNodeDefinitionBase } from '@core/
|
|
1
|
+
import { TreeNodeDefinitionBase } from '@core/packages/tree/tree-node-definition-base'
|
|
2
2
|
|
|
3
3
|
export class LeafDefinition<TData extends object = any, const TDiscriminator = any> extends TreeNodeDefinitionBase<
|
|
4
4
|
TData,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { TreeNodeBase } from '@core/
|
|
2
|
-
import type { LeafStatuses } from '@core/
|
|
1
|
+
import { TreeNodeBase } from '@core/packages/tree/tree-node-base'
|
|
2
|
+
import type { LeafStatuses } from '@core/packages/tree/types'
|
|
3
3
|
|
|
4
4
|
export class Leaf<TData extends object = any, const TDiscriminator = any> extends TreeNodeBase<TData, TDiscriminator> {
|
|
5
5
|
readonly isBranch = false
|
|
@@ -13,7 +13,7 @@ export class Leaf<TData extends object = any, const TDiscriminator = any> extend
|
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
get isExcluded() {
|
|
16
|
-
if (this.parent?.
|
|
16
|
+
if (this.parent?.isCollapsed === true) {
|
|
17
17
|
return true
|
|
18
18
|
}
|
|
19
19
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { Branch } from '@core/
|
|
2
|
-
import type { Identifiable, Labeled, TreeContext, TreeNodeId, TreeNodeOptions } from '@core/
|
|
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
|
|
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/
|
|
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/
|
|
2
|
-
import type { BranchDefinition } from '@core/
|
|
3
|
-
import type { Leaf } from '@core/
|
|
4
|
-
import type { LeafDefinition } from '@core/
|
|
5
|
-
import type { TreeNodeBase } from '@core/
|
|
6
|
-
import { useTree } from '@core/
|
|
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
|
-
|
|
66
|
+
collapsedIds: Set<TreeNodeId>
|
|
66
67
|
activeId: TreeNodeId | undefined
|
|
67
68
|
}
|
|
68
69
|
|
|
69
70
|
export type UseTreeOptions = {
|
|
70
71
|
allowMultiSelect?: boolean
|
|
71
|
-
|
|
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
|
-
|
|
93
|
+
collapsed: boolean
|
|
92
94
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { buildNodes } from '@core/
|
|
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/
|
|
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
|
|
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
|
-
|
|
23
|
+
collapsedIds,
|
|
24
24
|
activeId,
|
|
25
|
-
})
|
|
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.
|
|
31
|
-
nodes.forEach(node => node.isBranch && node.
|
|
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
|
-
|
|
56
|
-
|
|
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
|
+
}))
|