Skip to content

Commit

Permalink
feat(xo-6): implement network view
Browse files Browse the repository at this point in the history
  • Loading branch information
CzechSebastian committed Jan 22, 2025
1 parent 300bb18 commit 87b50f1
Show file tree
Hide file tree
Showing 27 changed files with 1,188 additions and 42 deletions.
6 changes: 0 additions & 6 deletions @xen-orchestra/lite/src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@
"cpu-provisioning": "CPU provisioning",
"cpu-provisioning-warning": "The number of vCPUs allocated exceeds the number of physical CPUs available. System performance could be affected",
"cpu-usage": "CPU usage",
"delete": "Delete",
"delete-vms": "Delete 1 VM | Delete {n} VMs",
"deploy": "Deploy",
"deploy-xoa": "Deploy XOA",
Expand All @@ -58,11 +57,8 @@
"deploy-xoa-status.waiting": "Waiting for XOA to respond…",

"descending": "descending",
"description": "Description",
"dhcp": "DHCP",
"disabled": "Disabled",
"display": "Display",
"dns": "DNS",
"do-you-have-needs": "You have needs and/or expectations? Let us know",
"documentation": "Documentation",
"edit-config": "Edit config",
Expand Down Expand Up @@ -178,7 +174,6 @@
"migrate-n-vms": "Migrate 1 VM | Migrate {n} VMs",
"n-hosts-awaiting-patch": "{n} host is awaiting this patch | {n} hosts are awaiting this patch",
"n-missing": "{n} missing",
"name": "Name",
"netmask": "Netmask",
"network-download": "Download",
"network-throughput": "Network throughput",
Expand All @@ -187,7 +182,6 @@
"news": "News",
"news-name": "{name} news",
"no-alarm-triggered": "No alarm triggered",
"no-result": "No result",
"no-selected-vm-can-be-exported": "No selected VM can be exported",
"no-selected-vm-can-be-migrated": "No selected VM can be migrated",
"no-tasks": "No tasks",
Expand Down
6 changes: 0 additions & 6 deletions @xen-orchestra/lite/src/locales/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@
"cpu-provisioning": "Provisionnement CPU",
"cpu-provisioning-warning": "Le nombre de vCPU alloués dépasse le nombre de CPU physique disponible. Les performances du système pourraient être affectées",
"cpu-usage": "Utilisation CPU",
"delete": "Supprimer",
"delete-vms": "Supprimer 1 VM | Supprimer {n} VMs",
"deploy": "Déployer",
"deploy-xoa": "Déployer XOA",
Expand All @@ -58,10 +57,7 @@
"deploy-xoa-status.waiting": "En attente de réponse de la XOA…",

"descending": "descendant",
"description": "Description",
"dhcp": "DHCP",
"dns": "DNS",
"disabled": "Désactivé",
"display": "Affichage",
"do-you-have-needs": "Vous avez des besoins et/ou des attentes ? Faites le nous savoir",
"documentation": "Documentation",
Expand Down Expand Up @@ -178,7 +174,6 @@
"migrate-n-vms": "Migrer 1 VM | Migrer {n} VMs",
"n-hosts-awaiting-patch": "{n} hôte attend ce patch | {n} hôtes attendent ce patch",
"n-missing": "{n} manquant | {n} manquants",
"name": "Nom",
"netmask": "Masque réseau",
"network-download": "Descendant",
"network-throughput": "Débit du réseau",
Expand All @@ -187,7 +182,6 @@
"news": "Actualités",
"news-name": "Actualités {name}",
"no-alarm-triggered": "Aucune alarme déclenchée",
"no-result": "Aucun résultat",
"no-selected-vm-can-be-exported": "Aucune VM sélectionnée ne peut être exportée",
"no-selected-vm-can-be-migrated": "Aucune VM sélectionnée ne peut être migrée",
"no-tasks": "Aucune tâche",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ const slots = defineSlots<{
.key {
min-width: 12rem;
max-width: 12rem;
overflow-wrap: break-word;
color: var(--color-neutral-txt-secondary);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@ import UiInfo, { type InfoAccent } from '@core/components/ui/info/UiInfo.vue'
import { computed, type ComputedRef } from 'vue'
import { useI18n } from 'vue-i18n'
type ConnectionStatus = 'connected' | 'disconnected' | 'partially-connected' | 'disconnected-from-physical-device'
export type ConnectionStatus =
| 'connected'
| 'disconnected'
| 'partially-connected'
| 'disconnected-from-physical-device'
type ConnectionStatusesMap = Record<ConnectionStatus, { text: string; accent: InfoAccent }>
const { status } = defineProps<{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,9 +107,12 @@ const imageSrc = computed(() => {
gap: 4rem;
justify-content: unset;
padding-top: 8rem;
position: relative;
.text {
order: 1;
position: sticky;
top: 2rem;
}
.loader {
Expand All @@ -120,6 +123,8 @@ const imageSrc = computed(() => {
.image {
order: 2;
width: 80%;
position: sticky;
top: 10rem;
}
}
Expand Down
7 changes: 4 additions & 3 deletions @xen-orchestra/web-core/lib/components/table/ColumnTitle.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
<MenuList :disabled placement="bottom-start" border>
<template #trigger="{ open, isOpen }">
<th
:class="{ interactive, disabled, focus: isOpen }"
:class="[headerClass, { interactive, disabled, focus: isOpen }]"
class="column-header"
@click="ev => (interactive ? open(ev) : noop())"
>
<div class="content">
<span class="label">
<div class="content text-ellipsis">
<span v-tooltip class="label">
<VtsIcon :icon accent="current" />
<slot />
</span>
Expand Down Expand Up @@ -58,6 +58,7 @@ const props = withDefaults(
icon?: IconDefinition
interactive?: boolean
disabled?: boolean
headerClass?: string
}>(),
{
disabled: false,
Expand Down
35 changes: 35 additions & 0 deletions @xen-orchestra/web-core/lib/components/table/VtsDataTable.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<template>
<div class="table-container">
<VtsLoadingHero :disabled="isReady" type="table">
<VtsTable class="table" vertical-border>
<thead>
<slot name="thead" />
</thead>
<tbody>
<slot name="tbody" />
</tbody>
</VtsTable>
</VtsLoadingHero>
<VtsErrorNoDataHero v-if="hasError" type="table" />
<VtsStateHero v-if="noDataMessage" type="table" image="no-data">
{{ noDataMessage }}
</VtsStateHero>
</div>
</template>

<script setup lang="ts">
import VtsErrorNoDataHero from '@core/components/state-hero/VtsErrorNoDataHero.vue'
import VtsLoadingHero from '@core/components/state-hero/VtsLoadingHero.vue'
import VtsStateHero from '@core/components/state-hero/VtsStateHero.vue'
import VtsTable from '@core/components/table/VtsTable.vue'
defineProps<{
isReady?: boolean
hasError?: boolean
noDataMessage?: string
}>()
defineSlots<{
thead(): any
tbody(): any
}>()
</script>
2 changes: 1 addition & 1 deletion @xen-orchestra/web-core/lib/components/ui/card/UiCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ defineSlots<{
.ui-card {
display: flex;
gap: 2.4rem;
padding: 2.4rem;
padding: 1.6rem;
flex-direction: column;
background-color: var(--color-neutral-background-primary);
border: 0.1rem solid var(--color-neutral-border);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ const props = defineProps<{
wrapperAttrs?: LabelHTMLAttributes
}>()

const checkboxModel = defineModel<boolean | undefined>({ default: undefined })
const checkboxModel = defineModel<boolean | undefined | string[]>({ default: undefined })

const slots = defineSlots<{
default?(): any
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ const labelAccent = computed(() => (accent === 'info' ? 'neutral' : accent))
position: relative;
display: flex;
flex-direction: column;
flex: 1;
gap: 0.4rem;

.input {
Expand Down
2 changes: 2 additions & 0 deletions @xen-orchestra/web-core/lib/components/ui/panel/UiPanel.vue
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ const slots = defineSlots<{
flex-direction: column;
border: 0.1rem solid var(--color-neutral-border);
background-color: var(--color-neutral-background-secondary);
position: relative;

.header {
border-bottom: 0.1rem solid var(--color-neutral-border);
Expand All @@ -44,6 +45,7 @@ const slots = defineSlots<{
flex-direction: column;
padding: 0.8rem;
gap: 0.8rem;
height: 100%;
}

&.error {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
</span>
<span class="typo p3-regular label show">{{ $t('core.show-by') }}</span>
<div class="dropdown-wrapper">
<select v-model="pageSize" :disabled class="dropdown typo c3-regular" @change="goToFirstPage">
<select v-model="localPageSize" :disabled="disabled" class="dropdown typo c3-regular" @change="goToFirstPage">
<option v-for="option in pageSizeOptions" :key="option" :value="option" class="typo p2-medium">
{{ option }}
</option>
Expand All @@ -33,7 +33,7 @@ import {
faAngleRight,
} from '@fortawesome/free-solid-svg-icons'
import { useOffsetPagination } from '@vueuse/core'
import { computed, ref, watch } from 'vue'
import { computed, ref, watch, watchEffect } from 'vue'

export type PaginationPayload = {
currentPage: number
Expand All @@ -42,17 +42,42 @@ export type PaginationPayload = {
endIndex: number
}

const { totalItems, disabled = false } = defineProps<{
const {
totalItems,
disabled = false,
currPage,
perPage,
startIndex,
endIndex,
} = defineProps<{
totalItems: number
disabled?: boolean
currPage: number
perPage: number
startIndex: number
endIndex: number
}>()

const emit = defineEmits<{
change: [payload: PaginationPayload]
'update:currPage': [value: number]
'update:per-page': [value: number]
'update:start-index': [value: number]
'update:end-index': [value: number]
}>()

const pageSize = ref(50)
const localPageSize = ref(perPage)
const localCurrentPage = ref(currPage)
const pageSizeOptions = [10, 50, 100, 150, 200]

watch([() => perPage, () => currPage], ([newPerPage, newCurrPage], [oldPerPage, oldCurrPage]) => {
if (newPerPage !== oldPerPage) {
localPageSize.value = newPerPage
}
if (newCurrPage !== oldCurrPage) {
localCurrentPage.value = newCurrPage
}
})
const {
currentPage,
currentPageSize,
Expand All @@ -63,10 +88,11 @@ const {
next: goToNextPage,
} = useOffsetPagination({
total: () => totalItems,
pageSize,
pageSize: localPageSize,
page: localCurrentPage,
})
const startIndex = computed(() => (currentPage.value - 1) * currentPageSize.value + 1)
const endIndex = computed(() => Math.min(currentPage.value * currentPageSize.value, totalItems))
const localStartIndex = computed(() => (currentPage.value - 1) * currentPageSize.value + 1)
const localEndIndex = computed(() => Math.min(currentPage.value * currentPageSize.value, totalItems))

const goToFirstPage = () => {
currentPage.value = 1
Expand All @@ -75,12 +101,19 @@ const goToLastPage = () => {
currentPage.value = pageCount.value
}

watchEffect(() => {
emit('update:currPage', localCurrentPage.value)
emit('update:per-page', localPageSize.value)
emit('update:start-index', localStartIndex.value)
emit('update:end-index', localEndIndex.value)
})

watch([currentPage, currentPageSize], ([newPage, newPageSize]) => {
emit('change', {
currentPage: newPage,
pageSize: newPageSize,
startIndex: startIndex.value,
endIndex: endIndex.value,
startIndex: localStartIndex.value,
endIndex: localEndIndex.value,
})
})
</script>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { computed, ref, unref, type MaybeRef, type Ref } from 'vue'

export default function useMultiSelect<T>(usableIds: MaybeRef<T[]>, selectableIds?: MaybeRef<T[]>) {
const $selected = ref(new Set()) as Ref<Set<T>>

const selected = computed({
get() {
return unref(usableIds).filter(usableId => $selected.value.has(usableId))
},
set(ids: T[]) {
$selected.value = new Set(ids)
},
})

const areAllSelected = computed({
get() {
return (unref(selectableIds) ?? unref(usableIds)).every(id => $selected.value.has(id))
},
set(value: boolean) {
if (value) {
$selected.value = new Set(unref(selectableIds) ?? unref(usableIds))
} else {
$selected.value = new Set()
}
},
})

return {
selected,
areAllSelected,
}
}
Loading

0 comments on commit 87b50f1

Please sign in to comment.