@xen-orchestra/web-core 0.25.0 → 0.26.1
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/state-hero/VtsStateHero.vue +15 -14
- package/lib/components/ui/alarm-item/UiAlarmItem.vue +9 -8
- package/lib/components/ui/alarm-list/UiAlarmList.vue +2 -0
- package/lib/components/ui/quoteCode/UiQuoteCode.vue +1 -0
- package/lib/locales/cs.json +0 -1
- package/lib/locales/de.json +0 -1
- package/lib/locales/en.json +18 -2
- package/lib/locales/es.json +0 -1
- package/lib/locales/fa.json +0 -1
- package/lib/locales/fr.json +18 -2
- package/lib/locales/nl.json +0 -1
- package/lib/locales/sv.json +0 -1
- package/lib/packages/request/define-request.ts +64 -0
- package/lib/types/http-codes.type.ts +10 -0
- package/lib/types/utility.type.ts +1 -1
- package/lib/utils/date-sorter.utils.ts +12 -0
- package/package.json +2 -1
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
<div :class="[type, { error }]" class="vts-state-hero">
|
|
3
3
|
<UiLoader v-if="busy" class="loader" />
|
|
4
4
|
<img v-else-if="imageSrc" :src="imageSrc" alt="" class="image" />
|
|
5
|
-
<
|
|
5
|
+
<div v-if="slots.default" :class="typoClass" class="content">
|
|
6
6
|
<slot />
|
|
7
|
-
</
|
|
7
|
+
</div>
|
|
8
8
|
</div>
|
|
9
9
|
</template>
|
|
10
10
|
|
|
@@ -14,7 +14,7 @@ import { computed } from 'vue'
|
|
|
14
14
|
|
|
15
15
|
export type StateHeroType = 'page' | 'card' | 'panel' | 'table'
|
|
16
16
|
|
|
17
|
-
const
|
|
17
|
+
const { type, busy, image, noBackground } = defineProps<{
|
|
18
18
|
type: StateHeroType
|
|
19
19
|
busy?: boolean
|
|
20
20
|
image?:
|
|
@@ -27,21 +27,22 @@ const props = defineProps<{
|
|
|
27
27
|
| 'offline'
|
|
28
28
|
| 'all-good'
|
|
29
29
|
| 'all-done'
|
|
30
|
+
noBackground?: boolean
|
|
30
31
|
}>()
|
|
31
32
|
|
|
32
33
|
const slots = defineSlots<{
|
|
33
34
|
default?(): any
|
|
34
35
|
}>()
|
|
35
36
|
|
|
36
|
-
const typoClass = computed(() => (
|
|
37
|
-
const error = computed(() => !
|
|
37
|
+
const typoClass = computed(() => (type === 'page' ? 'typo-h2' : 'typo-h4'))
|
|
38
|
+
const error = computed(() => !noBackground && !busy && image === 'error')
|
|
38
39
|
|
|
39
40
|
const imageSrc = computed(() => {
|
|
40
|
-
if (!
|
|
41
|
+
if (!image) {
|
|
41
42
|
return undefined
|
|
42
43
|
}
|
|
43
44
|
|
|
44
|
-
return new URL(`../../assets/${
|
|
45
|
+
return new URL(`../../assets/${image}.svg`, import.meta.url).href
|
|
45
46
|
})
|
|
46
47
|
</script>
|
|
47
48
|
|
|
@@ -56,13 +57,13 @@ const imageSrc = computed(() => {
|
|
|
56
57
|
&.error {
|
|
57
58
|
background-color: var(--color-danger-background-selected);
|
|
58
59
|
|
|
59
|
-
.
|
|
60
|
+
.content {
|
|
60
61
|
color: var(--color-danger-txt-base);
|
|
61
62
|
}
|
|
62
63
|
}
|
|
63
64
|
|
|
64
65
|
.loader,
|
|
65
|
-
.
|
|
66
|
+
.content {
|
|
66
67
|
color: var(--color-brand-txt-base);
|
|
67
68
|
}
|
|
68
69
|
|
|
@@ -70,14 +71,14 @@ const imageSrc = computed(() => {
|
|
|
70
71
|
order: 2;
|
|
71
72
|
}
|
|
72
73
|
|
|
73
|
-
.
|
|
74
|
+
.content {
|
|
74
75
|
order: 3;
|
|
75
76
|
}
|
|
76
77
|
|
|
77
78
|
&.page {
|
|
78
79
|
gap: 2.4rem;
|
|
79
80
|
|
|
80
|
-
.
|
|
81
|
+
.content {
|
|
81
82
|
order: 3;
|
|
82
83
|
}
|
|
83
84
|
|
|
@@ -96,7 +97,7 @@ const imageSrc = computed(() => {
|
|
|
96
97
|
&.card {
|
|
97
98
|
gap: 2rem;
|
|
98
99
|
|
|
99
|
-
.
|
|
100
|
+
.content {
|
|
100
101
|
order: 3;
|
|
101
102
|
}
|
|
102
103
|
|
|
@@ -117,7 +118,7 @@ const imageSrc = computed(() => {
|
|
|
117
118
|
justify-content: unset;
|
|
118
119
|
padding-top: 8rem;
|
|
119
120
|
|
|
120
|
-
.
|
|
121
|
+
.content {
|
|
121
122
|
order: 1;
|
|
122
123
|
}
|
|
123
124
|
|
|
@@ -136,7 +137,7 @@ const imageSrc = computed(() => {
|
|
|
136
137
|
padding: 4rem;
|
|
137
138
|
gap: 2.4rem;
|
|
138
139
|
|
|
139
|
-
.
|
|
140
|
+
.content {
|
|
140
141
|
order: 3;
|
|
141
142
|
}
|
|
142
143
|
|
|
@@ -11,15 +11,15 @@
|
|
|
11
11
|
:target-scale="2"
|
|
12
12
|
@click="toggleDescription()"
|
|
13
13
|
/>
|
|
14
|
-
<span v-tooltip class="text-ellipsis">
|
|
14
|
+
<span v-tooltip class="label text-ellipsis">
|
|
15
15
|
{{ label }}
|
|
16
16
|
</span>
|
|
17
|
-
<span class="percent">{{ t('n-percent', percent) }}</span>
|
|
17
|
+
<span class="percent">{{ percent ? t('n-percent', percent) : '' }}</span>
|
|
18
18
|
</div>
|
|
19
|
-
<div class="typo-body-regular-small
|
|
19
|
+
<div class="info typo-body-regular-small text-ellipsis">
|
|
20
20
|
<div v-if="slots.link" class="link-container">
|
|
21
21
|
{{ t('on-object') }}
|
|
22
|
-
<span class="object-link">
|
|
22
|
+
<span v-tooltip class="object-link text-ellipsis">
|
|
23
23
|
<slot name="link" />
|
|
24
24
|
</span>
|
|
25
25
|
<span class="interpunct" />
|
|
@@ -69,17 +69,17 @@ const [isDescriptionVisible, toggleDescription] = useToggle(false)
|
|
|
69
69
|
display: flex;
|
|
70
70
|
flex-direction: column;
|
|
71
71
|
padding: 0.8rem 1.2rem;
|
|
72
|
-
border-
|
|
72
|
+
border-bottom: 0.1rem solid var(--color-neutral-border);
|
|
73
73
|
color: var(--color-neutral-txt-primary);
|
|
74
74
|
|
|
75
|
-
&:
|
|
76
|
-
border-
|
|
75
|
+
&:last-child {
|
|
76
|
+
border-bottom: none;
|
|
77
77
|
}
|
|
78
78
|
|
|
79
79
|
.content {
|
|
80
80
|
display: flex;
|
|
81
81
|
justify-content: space-between;
|
|
82
|
-
gap: 0.
|
|
82
|
+
gap: 0.8rem;
|
|
83
83
|
}
|
|
84
84
|
|
|
85
85
|
.label-percent {
|
|
@@ -102,6 +102,7 @@ const [isDescriptionVisible, toggleDescription] = useToggle(false)
|
|
|
102
102
|
.link-container {
|
|
103
103
|
gap: 0.8rem;
|
|
104
104
|
white-space: nowrap;
|
|
105
|
+
min-width: 10rem;
|
|
105
106
|
}
|
|
106
107
|
|
|
107
108
|
.interpunct::before {
|
package/lib/locales/cs.json
CHANGED
|
@@ -550,7 +550,6 @@
|
|
|
550
550
|
"uuid": "UUID",
|
|
551
551
|
"vcpus": "virt. procesor | virt. procesor | virt. procesory",
|
|
552
552
|
"vcpus-assigned": "Přiděleno virt. procesorů",
|
|
553
|
-
"vcpus-used": "využito virt. procesorů",
|
|
554
553
|
"vdi-throughput": "propustnost VDI",
|
|
555
554
|
"vdis": "Virt. disk | Virt. disky | Virt. disků",
|
|
556
555
|
"version": "Verze",
|
package/lib/locales/de.json
CHANGED
package/lib/locales/en.json
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
"2nd-last": "2nd last",
|
|
3
3
|
"3rd-last": "3rd last",
|
|
4
4
|
"about": "About",
|
|
5
|
+
"accept-self-signed-certificates": "Accept self-signed certificates",
|
|
5
6
|
"access-forum": "Access forum",
|
|
6
7
|
"access-xoa": "Access XOA",
|
|
7
8
|
"account-organization-more": "Account, organization & more…",
|
|
@@ -79,7 +80,11 @@
|
|
|
79
80
|
"configuration": "Configuration",
|
|
80
81
|
"confirm-cancel": "Are you sure you want to cancel?",
|
|
81
82
|
"confirm-delete": "You're about to delete {0}",
|
|
83
|
+
"connect": "Connect",
|
|
84
|
+
"connect-another-pool": "Connect another pool",
|
|
85
|
+
"connect-pool": "Connect pool",
|
|
82
86
|
"connected": "Connected",
|
|
87
|
+
"connected-to-ip": "Connected to {ip}",
|
|
83
88
|
"connecting": "Connecting",
|
|
84
89
|
"connection": "Connection",
|
|
85
90
|
"connection-failed": "Connection failed",
|
|
@@ -103,6 +108,7 @@
|
|
|
103
108
|
"core.group": "Group",
|
|
104
109
|
"core.hide": "Hide",
|
|
105
110
|
"core.open": "Open",
|
|
111
|
+
"core.open-in-new-tab": "Open in new tab",
|
|
106
112
|
"core.pagination.all": "All",
|
|
107
113
|
"core.pagination.show-by": "Show by",
|
|
108
114
|
"core.query-search-bar.label": "Search Engine",
|
|
@@ -246,6 +252,7 @@
|
|
|
246
252
|
"ip-address": "IP address",
|
|
247
253
|
"ip-addresses": "IP addresses",
|
|
248
254
|
"ip-mode": "IP mode",
|
|
255
|
+
"ip-port-placeholder": "address[:port]",
|
|
249
256
|
"is-primary-host": "{name} is primary host",
|
|
250
257
|
"iscsi-iqn": "iSCSI IQN",
|
|
251
258
|
"iso-dvd": "ISO/DVD",
|
|
@@ -263,7 +270,7 @@
|
|
|
263
270
|
"job.vm-force-reboot.bad-power-state": "VM must be running or paused",
|
|
264
271
|
"job.vm-force-reboot.in-progress": "Force reboot in progress…",
|
|
265
272
|
"job.vm-force-reboot.missing-vms": "No VM to force reboot",
|
|
266
|
-
"job.vm-force-shutdown.bad-power-state": "VM must be running, suspended or paused",
|
|
273
|
+
"job.vm-force-shutdown.bad-power-state": "VM must be running, suspended, or paused",
|
|
267
274
|
"job.vm-force-shutdown.in-progress": "Force shutdown in progress…",
|
|
268
275
|
"job.vm-force-shutdown.missing-vms": "No VM to force shutdown",
|
|
269
276
|
"job.vm-migrate.bad-power-state": "VM must be running",
|
|
@@ -388,6 +395,7 @@
|
|
|
388
395
|
"on": "On",
|
|
389
396
|
"on-object": "on {object}",
|
|
390
397
|
"open-console-in-new-tab": "Open console in new tab",
|
|
398
|
+
"options": "Options",
|
|
391
399
|
"or": "Or",
|
|
392
400
|
"os-kernel": "OS kernel",
|
|
393
401
|
"os-name": "OS name",
|
|
@@ -406,6 +414,12 @@
|
|
|
406
414
|
"pifs-status": "PIFs status",
|
|
407
415
|
"please-confirm": "Please confirm",
|
|
408
416
|
"pool": "Pool",
|
|
417
|
+
"pool-connection-error-auth-failed": "An error occurred while connecting to the pool. The username or password appears to be incorrect.",
|
|
418
|
+
"pool-connection-error-duplicate": "An error occurred while connecting to the pool. This pool seems to be already connected.",
|
|
419
|
+
"pool-connection-error-host-not-found": "An error occurred while connecting to the pool. The address of this pool does not seem to exist. Please change the IP and try again.",
|
|
420
|
+
"pool-connection-error-invalid-parameters": "An error occurred while connecting to the pool. The parameters provided do not seem valid. Please check the IP address and credentials, then try again.",
|
|
421
|
+
"pool-connection-ip-info": "Provide the primary host’s address of the pool you want to connect to.",
|
|
422
|
+
"pool-connection-success": "You have successfully connected to the pool. You can now find it in your treeview and start managing your hosts and VMs.",
|
|
409
423
|
"pool-cpu-usage": "Pool CPU Usage",
|
|
410
424
|
"pool-management": "Pool management",
|
|
411
425
|
"pool-ram-usage": "Pool RAM Usage",
|
|
@@ -449,6 +463,7 @@
|
|
|
449
463
|
"resource-management": "Resource management",
|
|
450
464
|
"resources-overview": "Resources overview",
|
|
451
465
|
"resume": "Resume",
|
|
466
|
+
"root-by-default": "\"root\" by default.",
|
|
452
467
|
"running-vm": "Running VM | Running VMs",
|
|
453
468
|
"s3-backup-repository": "S3 backup repository",
|
|
454
469
|
"save": "Save",
|
|
@@ -539,6 +554,7 @@
|
|
|
539
554
|
"total-storage-repository": "Total storage repository",
|
|
540
555
|
"total-used": "Total used",
|
|
541
556
|
"total-used:": "Total used:",
|
|
557
|
+
"unable-to-connect-to": "Unable to connect to {ip}",
|
|
542
558
|
"unable-to-connect-to-the-pool": "Unable to connect to the pool",
|
|
543
559
|
"unknown": "Unknown",
|
|
544
560
|
"unlocked": "Unlocked",
|
|
@@ -551,7 +567,6 @@
|
|
|
551
567
|
"uuid": "UUID",
|
|
552
568
|
"vcpus": "vCPU | vCPU | vCPUs",
|
|
553
569
|
"vcpus-assigned": "vCPUs assigned",
|
|
554
|
-
"vcpus-used": "vCPUs used",
|
|
555
570
|
"vdi-throughput": "VDI throughput",
|
|
556
571
|
"vdis": "VDI | VDI | VDIs",
|
|
557
572
|
"version": "Version",
|
|
@@ -566,6 +581,7 @@
|
|
|
566
581
|
"virtualization-boot-settings": "Virtualization & boot settings",
|
|
567
582
|
"virtualization-mode": "Virtualization mode",
|
|
568
583
|
"virtualization-type": "Virtualization type",
|
|
584
|
+
"visit-pool-dashboard": "Visit pool dashboard",
|
|
569
585
|
"vlan": "VLAN",
|
|
570
586
|
"vm": "VM",
|
|
571
587
|
"vm-description": "VM description",
|
package/lib/locales/es.json
CHANGED
package/lib/locales/fa.json
CHANGED
|
@@ -462,7 +462,6 @@
|
|
|
462
462
|
"user-config": "تنظیمات کاربر",
|
|
463
463
|
"uuid": "UUID",
|
|
464
464
|
"vcpus": "CPUمجازی | CPUمجازی | CPUهای مجازی",
|
|
465
|
-
"vcpus-used": "CPUهای مجازی استفاده شده",
|
|
466
465
|
"vdis": "دسکتاپ مجازی | دسکتاپ مجازی | دسکتاپ های مجازی",
|
|
467
466
|
"version": "نسخه",
|
|
468
467
|
"vif": "VIF",
|
package/lib/locales/fr.json
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
"2nd-last": "Avant-dernier",
|
|
3
3
|
"3rd-last": "Avant-avant-dernier",
|
|
4
4
|
"about": "À propos",
|
|
5
|
+
"accept-self-signed-certificates": "Accepter les certificats auto-signés",
|
|
5
6
|
"access-forum": "Accès au forum",
|
|
6
7
|
"access-xoa": "Accéder à la XOA",
|
|
7
8
|
"account-organization-more": "Compte, organisation et plus…",
|
|
@@ -79,7 +80,11 @@
|
|
|
79
80
|
"configuration": "Configuration",
|
|
80
81
|
"confirm-cancel": "Êtes-vous sûr de vouloir annuler ?",
|
|
81
82
|
"confirm-delete": "Vous êtes sur le point de supprimer {0}",
|
|
83
|
+
"connect": "Se connecter",
|
|
84
|
+
"connect-another-pool": "Connecter un autre pool",
|
|
85
|
+
"connect-pool": "Connexion à un pool",
|
|
82
86
|
"connected": "Connecté",
|
|
87
|
+
"connected-to-ip": "Connecté à {ip}",
|
|
83
88
|
"connecting": "Connexion en cours",
|
|
84
89
|
"connection": "Connexion",
|
|
85
90
|
"connection-failed": "Échec de la connexion",
|
|
@@ -103,6 +108,7 @@
|
|
|
103
108
|
"core.group": "Grouper",
|
|
104
109
|
"core.hide": "Masquer",
|
|
105
110
|
"core.open": "Ouvrir",
|
|
111
|
+
"core.open-in-new-tab": "Ouvrir dans un nouvel onglet",
|
|
106
112
|
"core.pagination.all": "Tous",
|
|
107
113
|
"core.pagination.show-by": "Afficher par",
|
|
108
114
|
"core.query-search-bar.label": "Moteur de recherche",
|
|
@@ -246,6 +252,7 @@
|
|
|
246
252
|
"ip-address": "Adresse IP",
|
|
247
253
|
"ip-addresses": "Adresses IP",
|
|
248
254
|
"ip-mode": "Mode IP",
|
|
255
|
+
"ip-port-placeholder": "adresse[:port]",
|
|
249
256
|
"is-primary-host": "{name} est l'hôte primaire",
|
|
250
257
|
"iscsi-iqn": "iSCSI IQN",
|
|
251
258
|
"iso-dvd": "ISO/DVD",
|
|
@@ -388,6 +395,7 @@
|
|
|
388
395
|
"on": "Allumé",
|
|
389
396
|
"on-object": "sur {object}",
|
|
390
397
|
"open-console-in-new-tab": "Ouvrir la console dans un nouvel onglet",
|
|
398
|
+
"options": "Options",
|
|
391
399
|
"or": "Ou",
|
|
392
400
|
"os-kernel": "Noyau de l'OS",
|
|
393
401
|
"os-name": "Nom de l'OS",
|
|
@@ -406,6 +414,12 @@
|
|
|
406
414
|
"pifs-status": "Statut des PIFs",
|
|
407
415
|
"please-confirm": "Veuillez confirmer",
|
|
408
416
|
"pool": "Pool",
|
|
417
|
+
"pool-connection-error-auth-failed": "Une erreur s'est produite lors de la connexion au pool. Le nom d'utilisateur ou le mot de passe semble incorrect.",
|
|
418
|
+
"pool-connection-error-duplicate": "Une erreur s'est produite lors de la connexion au pool. Ce pool semble déjà être connecté.",
|
|
419
|
+
"pool-connection-error-host-not-found": "Une erreur s'est produite lors de la connexion au pool. L'adresse de ce pool semble inexistante. Modifiez l'adresse IP et réessayez.",
|
|
420
|
+
"pool-connection-error-invalid-parameters": "Une erreur s'est produite lors de la connexion au pool. Les paramètres fournis semblent incorrects. Veuillez vérifier les détails de la connexion et réessayer.",
|
|
421
|
+
"pool-connection-ip-info": "Entrez l’adresse de l’hôte primaire du pool auquel vous souhaitez vous connecter.",
|
|
422
|
+
"pool-connection-success": "Vous êtes connecté au pool. Vous pouvez désormais le retrouver dans votre arborescence et commencer à gérer vos hôtes et vos machines virtuelles.",
|
|
409
423
|
"pool-cpu-usage": "Utilisation CPU du Pool",
|
|
410
424
|
"pool-management": "Gestion du Pool",
|
|
411
425
|
"pool-ram-usage": "Utilisation RAM du Pool",
|
|
@@ -425,7 +439,7 @@
|
|
|
425
439
|
"property": "Propriété",
|
|
426
440
|
"protect-from-accidental-deletion": "Protection contre les suppressions accidentelles",
|
|
427
441
|
"protect-from-accidental-shutdown": "Protection contre les extinctions accidentelles",
|
|
428
|
-
"proxy-url": "URL du
|
|
442
|
+
"proxy-url": "URL du Proxy",
|
|
429
443
|
"pxe": "PXE",
|
|
430
444
|
"quick-info": "Informations rapides",
|
|
431
445
|
"ram": "RAM",
|
|
@@ -449,6 +463,7 @@
|
|
|
449
463
|
"resource-management": "Gestion des ressources",
|
|
450
464
|
"resources-overview": "Vue d'ensemble des ressources",
|
|
451
465
|
"resume": "Reprendre",
|
|
466
|
+
"root-by-default": "\"root\" par défaut.",
|
|
452
467
|
"running-vm": "VM en cours d'exécution | VMs en cours d'exécution",
|
|
453
468
|
"s3-backup-repository": "Dépot de sauvegarde S3",
|
|
454
469
|
"save": "Enregistrer",
|
|
@@ -539,6 +554,7 @@
|
|
|
539
554
|
"total-storage-repository": "Total dépot de stockage",
|
|
540
555
|
"total-used": "Total utilisé",
|
|
541
556
|
"total-used:": "Total utilisé :",
|
|
557
|
+
"unable-to-connect-to": "Impossible de se connecter à {ip}",
|
|
542
558
|
"unable-to-connect-to-the-pool": "Impossible de se connecter au Pool",
|
|
543
559
|
"unknown": "Inconnu",
|
|
544
560
|
"unlocked": "Débloqué",
|
|
@@ -551,7 +567,6 @@
|
|
|
551
567
|
"uuid": "UUID",
|
|
552
568
|
"vcpus": "vCPU | vCPU | vCPUs",
|
|
553
569
|
"vcpus-assigned": "vCPUs assignés",
|
|
554
|
-
"vcpus-used": "vCPUs utilisés",
|
|
555
570
|
"vdi-throughput": "Débit du VDI",
|
|
556
571
|
"vdis": "VDI | VDI | VDIs",
|
|
557
572
|
"version": "Version",
|
|
@@ -566,6 +581,7 @@
|
|
|
566
581
|
"virtualization-boot-settings": "Virtualisation & paramètres de démarrage",
|
|
567
582
|
"virtualization-mode": "Mode de virtualisation",
|
|
568
583
|
"virtualization-type": "Type de virtualisation",
|
|
584
|
+
"visit-pool-dashboard": "Visiter le tableau de bord du pool",
|
|
569
585
|
"vlan": "VLAN",
|
|
570
586
|
"vm": "VM",
|
|
571
587
|
"vm-description": "Description de la VM",
|
package/lib/locales/nl.json
CHANGED
package/lib/locales/sv.json
CHANGED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { useTimeoutPoll } from '@vueuse/core'
|
|
2
|
+
import type { MaybeRefOrGetter } from '@vueuse/shared'
|
|
3
|
+
// eslint-disable-next-line import/namespace,import/default,import/no-named-as-default,import/no-named-as-default-member -- https://github.com/pamelafox/ndjson-readablestream/pull/13
|
|
4
|
+
import readNDJSONStream from 'ndjson-readablestream'
|
|
5
|
+
import { computed, isRef, toValue, watch } from 'vue'
|
|
6
|
+
|
|
7
|
+
export function defineRequest<TState>(options: {
|
|
8
|
+
url: string
|
|
9
|
+
state: () => TState
|
|
10
|
+
onDataReceived: (state: TState, data: unknown) => void
|
|
11
|
+
}): () => TState
|
|
12
|
+
|
|
13
|
+
export function defineRequest<TArgs extends any[], TState>(options: {
|
|
14
|
+
url: (...args: TArgs) => string
|
|
15
|
+
state: () => TState
|
|
16
|
+
onDataReceived: (state: TState, data: unknown) => void
|
|
17
|
+
onUrlChange: (state: TState) => void
|
|
18
|
+
}): (...args: { [K in keyof TArgs]: MaybeRefOrGetter<TArgs[K]> }) => TState
|
|
19
|
+
|
|
20
|
+
export function defineRequest<TArgs extends any[], TState>(options: {
|
|
21
|
+
url: string | ((...args: TArgs) => string)
|
|
22
|
+
state: () => TState
|
|
23
|
+
onDataReceived: (state: TState, data: unknown) => void
|
|
24
|
+
onUrlChange?: (state: TState) => void
|
|
25
|
+
}) {
|
|
26
|
+
return function useRequest(...args: { [K in keyof TArgs]: MaybeRefOrGetter<TArgs[K]> }) {
|
|
27
|
+
const urlOption = options.url
|
|
28
|
+
|
|
29
|
+
const url = typeof urlOption === 'function' ? computed(() => urlOption(...(args.map(toValue) as TArgs))) : urlOption
|
|
30
|
+
|
|
31
|
+
const state = options.state()
|
|
32
|
+
|
|
33
|
+
async function execute() {
|
|
34
|
+
const response = await fetch(toValue(url))
|
|
35
|
+
|
|
36
|
+
if (!response.ok) {
|
|
37
|
+
throw new Error(`Failed to fetch: ${response.statusText}`)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (!response.body) {
|
|
41
|
+
throw new Error('Response body is empty')
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
for await (const event of readNDJSONStream(response.body)) {
|
|
45
|
+
options.onDataReceived(state, event)
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const { resume, pause } = useTimeoutPoll(execute, 10000, {
|
|
50
|
+
immediate: true,
|
|
51
|
+
immediateCallback: true,
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
if (isRef(url)) {
|
|
55
|
+
watch(url, () => {
|
|
56
|
+
pause()
|
|
57
|
+
options.onUrlChange?.(state)
|
|
58
|
+
resume()
|
|
59
|
+
})
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return state
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -11,7 +11,7 @@ export type EmptyObject = Record<string, never>
|
|
|
11
11
|
export type StringKeyOf<T> = Extract<keyof T, string>
|
|
12
12
|
|
|
13
13
|
export type KeyOfByValue<T, TValue> =
|
|
14
|
-
T extends Record<PropertyKey,
|
|
14
|
+
T extends Record<PropertyKey, any>
|
|
15
15
|
? keyof {
|
|
16
16
|
[K in keyof T as T[K] extends TValue ? K : never]: T[K]
|
|
17
17
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { KeyOfByValue } from '@core/types/utility.type.ts'
|
|
2
|
+
|
|
3
|
+
type DateLike = Date | string | number
|
|
4
|
+
|
|
5
|
+
export function createDateSorter<T extends object>(key: KeyOfByValue<T, DateLike>) {
|
|
6
|
+
return (a: T, b: T) => {
|
|
7
|
+
const dateA = new Date(a[key] as DateLike)
|
|
8
|
+
const dateB = new Date(b[key] as DateLike)
|
|
9
|
+
|
|
10
|
+
return dateB.getTime() - dateA.getTime()
|
|
11
|
+
}
|
|
12
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xen-orchestra/web-core",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.26.1",
|
|
5
5
|
"private": false,
|
|
6
6
|
"exports": {
|
|
7
7
|
"./*": {
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
"human-format": "^1.2.1",
|
|
27
27
|
"iterable-backoff": "^0.1.0",
|
|
28
28
|
"lodash-es": "^4.17.21",
|
|
29
|
+
"ndjson-readablestream": "^1.2.0",
|
|
29
30
|
"placement.js": "^1.0.0-beta.5",
|
|
30
31
|
"simple-icons": "^14.14.0",
|
|
31
32
|
"vue-echarts": "^6.6.8"
|