@xen-orchestra/web-core 0.27.0 → 0.28.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 (75) hide show
  1. package/lib/components/card/VtsCardRowKeyValue.vue +1 -0
  2. package/lib/components/cell-object/VtsCellObject.vue +1 -2
  3. package/lib/components/console/VtsActionsConsole.vue +3 -9
  4. package/lib/components/copy-button/VtsCopyButton.vue +1 -3
  5. package/lib/components/dropdown/DropdownTitle.vue +3 -3
  6. package/lib/components/icon/VtsIcon.vue +32 -76
  7. package/lib/components/input-wrapper/VtsInputWrapper.vue +2 -2
  8. package/lib/components/layout/VtsLayoutSidebar.vue +1 -2
  9. package/lib/components/menu/MenuItem.vue +4 -5
  10. package/lib/components/menu/MenuTrigger.vue +3 -3
  11. package/lib/components/object-icon/VtsObjectIcon.vue +2 -2
  12. package/lib/components/resources/VtsResource.vue +3 -3
  13. package/lib/components/select/VtsSelect.vue +4 -5
  14. package/lib/components/table/ColumnTitle.vue +11 -12
  15. package/lib/components/task/VtsQuickTaskButton.vue +1 -2
  16. package/lib/components/tree/VtsTreeLoadingItem.vue +3 -3
  17. package/lib/components/ui/alarm-item/UiAlarmItem.vue +1 -2
  18. package/lib/components/ui/alert/UiAlert.vue +14 -13
  19. package/lib/components/ui/button/UiButton.vue +4 -5
  20. package/lib/components/ui/button-icon/UiButtonIcon.vue +3 -3
  21. package/lib/components/ui/checkbox/UiCheckbox.vue +2 -9
  22. package/lib/components/ui/chip/ChipIcon.vue +3 -3
  23. package/lib/components/ui/chip/ChipRemoveIcon.vue +1 -2
  24. package/lib/components/ui/chip/UiChip.vue +2 -2
  25. package/lib/components/ui/circle-progress-bar/UiCircleProgressBar.vue +7 -4
  26. package/lib/components/ui/donut-chart/UiDonutChart.vue +30 -17
  27. package/lib/components/ui/dropdown/UiDropdown.vue +5 -7
  28. package/lib/components/ui/dropdown-button/UiDropdownButton.vue +4 -5
  29. package/lib/components/ui/head-bar/UiHeadBar.vue +6 -11
  30. package/lib/components/ui/info/UiInfo.vue +14 -20
  31. package/lib/components/ui/input/UiInput.vue +6 -7
  32. package/lib/components/ui/label/UiLabel.vue +3 -3
  33. package/lib/components/ui/legend/UiLegend.vue +3 -3
  34. package/lib/components/ui/legend-title/UiLegendTitle.vue +7 -3
  35. package/lib/components/ui/link/UiLink.vue +4 -5
  36. package/lib/components/ui/log-entry-viewer/UiLogEntryViewer.vue +6 -2
  37. package/lib/components/ui/object-link/UiObjectLink.vue +4 -4
  38. package/lib/components/ui/query-search-bar/UiQuerySearchBar.vue +3 -4
  39. package/lib/components/ui/quick-task-item/UiQuickTaskItem.vue +3 -4
  40. package/lib/components/ui/radio-button/UiRadioButton.vue +1 -2
  41. package/lib/components/ui/table-pagination/PaginationButton.vue +2 -25
  42. package/lib/components/ui/table-pagination/UiTablePagination.vue +41 -20
  43. package/lib/components/ui/tag/UiTag.vue +3 -3
  44. package/lib/components/ui/text-area/UiTextarea.vue +2 -2
  45. package/lib/components/ui/toaster/UiToaster.vue +15 -13
  46. package/lib/components/ui/tree-item-label/UiTreeItemLabel.vue +4 -5
  47. package/lib/composables/pagination.composable.ts +5 -0
  48. package/lib/i18n.ts +4 -0
  49. package/lib/icons/fa-icons.ts +48 -2
  50. package/lib/icons/index.ts +4 -0
  51. package/lib/icons/legacy-icons.ts +10 -0
  52. package/lib/icons/object-icons.ts +1 -1
  53. package/lib/layouts/CoreLayout.vue +1 -2
  54. package/lib/locales/cs.json +29 -10
  55. package/lib/locales/de.json +70 -7
  56. package/lib/locales/en.json +22 -0
  57. package/lib/locales/es.json +3 -3
  58. package/lib/locales/fr.json +22 -0
  59. package/lib/locales/it.json +17 -5
  60. package/lib/locales/nl.json +28 -10
  61. package/lib/locales/pt_BR.json +67 -0
  62. package/lib/locales/sv.json +17 -0
  63. package/lib/packages/icon/DisplayIcon.vue +1 -0
  64. package/lib/packages/progress/README.md +62 -0
  65. package/lib/packages/progress/types.ts +19 -0
  66. package/lib/packages/progress/use-progress-group.ts +68 -0
  67. package/lib/packages/progress/use-progress.ts +22 -0
  68. package/lib/packages/threshold/README.md +30 -0
  69. package/lib/packages/threshold/type.ts +3 -0
  70. package/lib/packages/threshold/use-threshold.ts +19 -0
  71. package/lib/types/object-icon.type.ts +0 -40
  72. package/package.json +1 -1
  73. package/lib/components/icon/NewVtsIcon.vue +0 -49
  74. package/lib/components/ui/complex-icon/UiComplexIcon.vue +0 -45
  75. package/lib/components/ui/object-icon/UiObjectIcon.vue +0 -251
@@ -0,0 +1,22 @@
1
+ import type { Progress } from './types.ts'
2
+ import { computed, type MaybeRefOrGetter, toValue } from 'vue'
3
+
4
+ export function useProgress(rawCurrent: MaybeRefOrGetter<number>, rawTotal: MaybeRefOrGetter<number>): Progress {
5
+ const current = computed(() => toValue(rawCurrent))
6
+
7
+ const total = computed(() => toValue(rawTotal))
8
+
9
+ const percentage = computed(() => (total.value === 0 ? 0 : (current.value / total.value) * 100))
10
+
11
+ const percentageCap = computed(() => Math.max(100, Math.ceil(percentage.value / 100) * 100))
12
+
13
+ const fillWidth = computed(() => `${(percentage.value / percentageCap.value) * 100}%`)
14
+
15
+ return {
16
+ current,
17
+ total,
18
+ percentage,
19
+ fillWidth,
20
+ percentageCap,
21
+ }
22
+ }
@@ -0,0 +1,30 @@
1
+ # `useThreshold`
2
+
3
+ `useThreshold` composable allows defining payloads for different thresholds.
4
+
5
+ It returns the payload of the highest matching threshold for that value.
6
+
7
+ ## Arguments
8
+
9
+ | Argument | Type | Required | Description |
10
+ | -------------- | -------------------------------------------------------------------- | :------: | ------------------------------------- |
11
+ | `currentValue` | `MaybeRefOrGetter<number>` | ✓ | The value to check against thresholds |
12
+ | `config` | `MaybeRefOrGetter<Record<number, TPayload> & { default: TPayload }>` | ✓ | The thresholds configuration |
13
+
14
+ ## Returns
15
+
16
+ `ComputedRef<{ value: number | undefined; payload: TPayload }>`
17
+
18
+ ## Example
19
+
20
+ ```ts
21
+ const threshold = useThreshold(value, {
22
+ 50: 'orange',
23
+ 100: 'red',
24
+ default: 'green',
25
+ })
26
+
27
+ // value = 20 → threshold = { value: undefined, payload: 'green' }
28
+ // value = 70 → threshold = { value: 50, payload: 'orange' }
29
+ // value = 130 → threshold = { value: 100, payload: 'red' }
30
+ ```
@@ -0,0 +1,3 @@
1
+ export type ThresholdConfig<TPayload> = Record<number, TPayload> & { default: TPayload }
2
+
3
+ export type ThresholdResult<TPayload> = { value: number | undefined; payload: TPayload }
@@ -0,0 +1,19 @@
1
+ import type { ThresholdConfig, ThresholdResult } from '@core/packages/threshold/type.ts'
2
+ import { computed, type ComputedRef, type MaybeRefOrGetter, toValue } from 'vue'
3
+
4
+ export function useThreshold<TPayload>(
5
+ rawCurrentValue: MaybeRefOrGetter<number>,
6
+ rawConfig: MaybeRefOrGetter<ThresholdConfig<TPayload>>
7
+ ): ComputedRef<ThresholdResult<TPayload>> {
8
+ const currentValue = computed(() => toValue(rawCurrentValue))
9
+
10
+ const config = computed(() => toValue(rawConfig))
11
+
12
+ return computed(
13
+ () =>
14
+ Object.entries(config.value)
15
+ .map(([value, payload]) => ({ value: value === 'default' ? -Infinity : Number(value), payload }))
16
+ .sort((a, b) => b.value - a.value)
17
+ .find(threshold => currentValue.value >= threshold.value)!
18
+ )
19
+ }
@@ -1,43 +1,3 @@
1
- import type { IconDefinition } from '@fortawesome/fontawesome-common-types'
2
-
3
- export type ObjectIconSize = 'extra-small' | 'small' | 'medium'
4
-
5
1
  export type VmState = 'running' | 'halted' | 'paused' | 'suspended'
6
2
 
7
3
  export type HostState = 'running' | 'halted' | 'maintenance'
8
-
9
- export type SrState = 'connected' | 'partially-connected' | 'disconnected'
10
-
11
- export type BackupRepositoryState = 'connected' | 'disconnected'
12
-
13
- export type NetworkState = 'connected' | 'disconnected'
14
-
15
- export type SupportedStateByType = {
16
- host: HostState
17
- vm: VmState
18
- sr: SrState
19
- 'backup-repository': BackupRepositoryState
20
- network: NetworkState
21
- }
22
-
23
- export type SupportedType = keyof SupportedStateByType
24
-
25
- export type SupportedState<TType extends SupportedType> = SupportedStateByType[TType]
26
-
27
- export type StatusConfig = {
28
- icon: IconDefinition
29
- color: `--${string}`
30
- translate: {
31
- x: [number, number, number]
32
- y: [number, number, number]
33
- }
34
- }
35
-
36
- export type TypeConfig<TType extends SupportedType> = {
37
- mainIcon: IconDefinition
38
- states: Record<SupportedState<TType>, StatusConfig>
39
- }
40
-
41
- export type ObjectIconConfig = {
42
- [K in SupportedType]: TypeConfig<K>
43
- }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@xen-orchestra/web-core",
3
3
  "type": "module",
4
- "version": "0.27.0",
4
+ "version": "0.28.0",
5
5
  "private": false,
6
6
  "exports": {
7
7
  "./*": {
@@ -1,49 +0,0 @@
1
- <template>
2
- <DisplayIcon v-if="icon" class="vts-icon" :class="className" :icon />
3
- </template>
4
-
5
- <script lang="ts" setup>
6
- import { type IconName, icons } from '@core/icons'
7
- import { DisplayIcon } from '@core/packages/icon'
8
- import { toVariants } from '@core/utils/to-variants.util.ts'
9
- import { computed } from 'vue'
10
-
11
- export type IconSize = 'small' | 'medium' | 'large' | 'current'
12
-
13
- const { size, name } = defineProps<{
14
- size: IconSize
15
- name: IconName
16
- }>()
17
-
18
- const className = computed(() =>
19
- toVariants({
20
- size: size === 'current' ? undefined : size,
21
- })
22
- )
23
-
24
- const icon = computed(() => {
25
- const icon = icons[name]
26
-
27
- if (icon === undefined) {
28
- console.warn(`Icon "${name}" not found.`)
29
- }
30
-
31
- return icon
32
- })
33
- </script>
34
-
35
- <style lang="postcss" scoped>
36
- .vts-icon {
37
- &.size--small {
38
- font-size: 1.2rem;
39
- }
40
-
41
- &.size--medium {
42
- font-size: 1.6rem;
43
- }
44
-
45
- &.size--large {
46
- font-size: 2rem;
47
- }
48
- }
49
- </style>
@@ -1,45 +0,0 @@
1
- <!-- v2 -->
2
- <template>
3
- <FontAwesomeLayers :class="toVariants({ size })" class="ui-complex-icon">
4
- <slot />
5
- </FontAwesomeLayers>
6
- </template>
7
-
8
- <script lang="ts" setup>
9
- import { toVariants } from '@core/utils/to-variants.util'
10
- import { FontAwesomeLayers } from '@fortawesome/vue-fontawesome'
11
-
12
- defineProps<{
13
- size: 'small' | 'medium' | 'large'
14
- }>()
15
- </script>
16
-
17
- <style lang="postcss" scoped>
18
- .ui-complex-icon {
19
- :nth-child(2) {
20
- font-size: 0.5em;
21
- transform: translate(100%, 80%);
22
-
23
- :deep(path) {
24
- stroke: var(--color-neutral-background-primary);
25
- stroke-width: 100px;
26
- stroke-linejoin: round;
27
- paint-order: stroke;
28
- }
29
- }
30
-
31
- /*SIZE VARIANTS*/
32
-
33
- &.size--small {
34
- font-size: 1.2rem;
35
- }
36
-
37
- &.size--medium {
38
- font-size: 1.6rem;
39
- }
40
-
41
- &.size--large {
42
- font-size: 2rem;
43
- }
44
- }
45
- </style>
@@ -1,251 +0,0 @@
1
- <!-- VM v2 -->
2
- <!-- Host v2 -->
3
- <!-- SR v2 -->
4
- <!-- Backup Repository v2 -->
5
- <!-- Network v2 -->
6
- <template>
7
- <FontAwesomeLayers :class="[toVariants({ size }), { muted: stateConfig === undefined }]" class="ui-object-icon">
8
- <VtsIcon :icon="mainIcon" accent="current" />
9
- <VtsIcon :icon="stateIcon" accent="current" :style="stateIconStyle" class="state" />
10
- </FontAwesomeLayers>
11
- </template>
12
-
13
- <script generic="TType extends SupportedType" lang="ts" setup>
14
- import VtsIcon from '@core/components/icon/VtsIcon.vue'
15
- import type { ObjectIconConfig, SupportedState, SupportedType } from '@core/types/object-icon.type'
16
- import { toVariants } from '@core/utils/to-variants.util'
17
- import {
18
- faCheckCircle,
19
- faCircleMinus,
20
- faCircleXmark,
21
- faDatabase,
22
- faDisplay,
23
- faMoon,
24
- faNetworkWired,
25
- faPause,
26
- faPlay,
27
- faServer,
28
- faStop,
29
- faTriangleExclamation,
30
- faWarehouse,
31
- } from '@fortawesome/free-solid-svg-icons'
32
- import { FontAwesomeLayers } from '@fortawesome/vue-fontawesome'
33
- import { computed } from 'vue'
34
-
35
- export type ObjectIconSize = 'small' | 'medium' | 'large'
36
-
37
- const props = withDefaults(
38
- defineProps<{
39
- type: TType
40
- size: ObjectIconSize
41
- state?: SupportedState<TType> | 'disabled'
42
- }>(),
43
- { state: 'disabled' }
44
- )
45
-
46
- const config: ObjectIconConfig = {
47
- vm: {
48
- mainIcon: faDisplay,
49
- states: {
50
- running: {
51
- icon: faPlay,
52
- color: '--color-success-item-base',
53
- translate: {
54
- x: [100, 132, 148],
55
- y: [65, 75, 90],
56
- },
57
- },
58
- halted: {
59
- icon: faStop,
60
- color: '--color-danger-item-base',
61
- translate: {
62
- x: [100, 136, 144],
63
- y: [65, 75, 90],
64
- },
65
- },
66
- suspended: {
67
- icon: faMoon,
68
- color: '--color-info-item-base',
69
- translate: {
70
- x: [88, 130, 140],
71
- y: [65, 75, 90],
72
- },
73
- },
74
- paused: {
75
- icon: faPause,
76
- color: '--color-info-item-active',
77
- translate: {
78
- x: [110, 154, 170],
79
- y: [65, 75, 90],
80
- },
81
- },
82
- },
83
- },
84
- host: {
85
- mainIcon: faServer,
86
- states: {
87
- running: {
88
- icon: faPlay,
89
- color: '--color-success-item-base',
90
- translate: {
91
- x: [82, 122, 136],
92
- y: [66, 70, 90],
93
- },
94
- },
95
- halted: {
96
- icon: faStop,
97
- color: '--color-danger-item-base',
98
- translate: {
99
- x: [90, 122, 134],
100
- y: [65, 72, 85],
101
- },
102
- },
103
- maintenance: {
104
- icon: faTriangleExclamation,
105
- color: '--color-warning-item-base',
106
- translate: {
107
- x: [60, 88, 100],
108
- y: [68, 72, 82],
109
- },
110
- },
111
- },
112
- },
113
- sr: {
114
- mainIcon: faDatabase,
115
- states: {
116
- connected: {
117
- icon: faCheckCircle,
118
- color: '--color-success-item-base',
119
- translate: {
120
- x: [60, 90, 100],
121
- y: [65, 75, 90],
122
- },
123
- },
124
- 'partially-connected': {
125
- icon: faCircleMinus,
126
- color: '--color-warning-item-base',
127
- translate: {
128
- x: [60, 90, 100],
129
- y: [65, 75, 90],
130
- },
131
- },
132
- disconnected: {
133
- icon: faCircleXmark,
134
- color: '--color-danger-item-base',
135
- translate: {
136
- x: [60, 90, 100],
137
- y: [65, 75, 90],
138
- },
139
- },
140
- },
141
- },
142
- 'backup-repository': {
143
- mainIcon: faWarehouse,
144
- states: {
145
- connected: {
146
- icon: faCheckCircle,
147
- color: '--color-success-item-base',
148
- translate: {
149
- x: [112, 130, 162],
150
- y: [74, 78, 102],
151
- },
152
- },
153
- disconnected: {
154
- icon: faCircleXmark,
155
- color: '--color-danger-item-base',
156
- translate: {
157
- x: [112, 130, 162],
158
- y: [74, 78, 102],
159
- },
160
- },
161
- },
162
- },
163
- network: {
164
- mainIcon: faNetworkWired,
165
- states: {
166
- connected: {
167
- icon: faCheckCircle,
168
- color: '--color-success-item-base',
169
- translate: {
170
- x: [84, 110, 128],
171
- y: [66, 72, 88],
172
- },
173
- },
174
- disconnected: {
175
- icon: faCircleXmark,
176
- color: '--color-danger-item-base',
177
- translate: {
178
- x: [84, 110, 128],
179
- y: [66, 72, 88],
180
- },
181
- },
182
- },
183
- },
184
- }
185
-
186
- const mainIcon = computed(() => config[props.type].mainIcon)
187
- const stateConfig = computed(() => (props.state === 'disabled' ? undefined : config[props.type].states[props.state]))
188
- const stateIcon = computed(() => stateConfig.value?.icon)
189
-
190
- const stateIconStyle = computed(() => {
191
- if (stateConfig.value === undefined) {
192
- return undefined
193
- }
194
-
195
- let translateIndex: number
196
-
197
- if (props.size === 'small') {
198
- translateIndex = 0
199
- } else if (props.size === 'large') {
200
- translateIndex = 2
201
- } else {
202
- translateIndex = 1
203
- }
204
-
205
- return {
206
- color: `var(${stateConfig.value.color})`,
207
- '--state-icon-translate-x': `${stateConfig.value.translate.x[translateIndex]}%`,
208
- '--state-icon-translate-y': `${stateConfig.value.translate.y[translateIndex]}%`,
209
- }
210
- })
211
- </script>
212
-
213
- <style lang="postcss" scoped>
214
- .ui-object-icon {
215
- flex-shrink: 0;
216
-
217
- &.muted {
218
- color: var(--color-neutral-txt-secondary);
219
- }
220
-
221
- .state {
222
- transform: translate(var(--state-icon-translate-x), var(--state-icon-translate-y));
223
- }
224
-
225
- /* SIZE VARIANTS */
226
-
227
- &.size--small {
228
- font-size: 0.8rem;
229
-
230
- .state {
231
- font-size: 0.75em;
232
- }
233
- }
234
-
235
- &.size--medium {
236
- font-size: 1.6rem;
237
-
238
- .state {
239
- font-size: 0.625em;
240
- }
241
- }
242
-
243
- &.size--large {
244
- font-size: 2.4rem;
245
-
246
- .state {
247
- font-size: 0.5em;
248
- }
249
- }
250
- }
251
- </style>