-
Notifications
You must be signed in to change notification settings - Fork 270
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(xo-lite/network): implementation of network tab and add network/pif store #8147
base: master
Are you sure you want to change the base?
Conversation
30e475c
to
06a7b52
Compare
"locking-mode": "Mode verouillé", | ||
"locking-mode-default": "Mode verouillé par defaut", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here, maybe the wording can be improved?
BTW, some typos need to be fixed:
"locking-mode": "Mode verouillé", | |
"locking-mode-default": "Mode verouillé par defaut", | |
"locking-mode": "Mode verrouillé", | |
"locking-mode-default": "Mode verrouillé par défaut", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any suggestion ? 😃
<tr v-for="(item, index) in reactiveNetworksWithVLANs" :key="index"> | ||
<td> | ||
<UiCheckbox v-model="item.selected" accent="info" /> | ||
</td> | ||
<td>{{ item.name_label }}</td> | ||
<td>{{ item.name_description }}</td> | ||
<td> | ||
<!-- TODO improvement required --> | ||
<UiInfo v-if="item.status === 'connected'" accent="success"> {{ item.status }}</UiInfo> | ||
<UiInfo v-else-if="item.status === 'disconnected'" accent="danger"> {{ item.status }}</UiInfo> | ||
<UiInfo v-else accent="warning"> {{ item.status }}</UiInfo> | ||
</td> | ||
<td>{{ item.vlan }}</td> | ||
<td>{{ item.MTU }}</td> | ||
<td>{{ item.default_locking_mode }}</td> | ||
</tr> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This <tr>
can be extracted into a child component, for example, a PifRow.vue
component, that will accept a PIF object as a prop and will handle the styling and other things if needed.
See this comment for more explanation, even if it is for XO 6, the song concept remains the same.
32a2c76
to
246f5fb
Compare
bfc7557
to
782a943
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
import { computed } from 'vue' | ||
|
||
const { pif } = defineProps<{ | ||
pif: { status: 'connected' | 'disconnected' | 'partially_connected' } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By convention, I think it would be better to use the kebab-case here:
pif: { status: 'connected' | 'disconnected' | 'partially_connected' } | |
pif: { status: 'connected' | 'disconnected' | 'partially-connected' } |
Remember to update the rest of the code and the usages accordingly.
@xen-orchestra/lite/src/components/pool/network/PoolNetworksPifStatus.vue
Outdated
Show resolved
Hide resolved
@xen-orchestra/lite/src/components/pool/network/PoolNetworksPifStatus.vue
Outdated
Show resolved
Hide resolved
@xen-orchestra/lite/src/components/pool/network/PoolNetworksPifStatus.vue
Outdated
Show resolved
Hide resolved
@@ -42,7 +42,6 @@ const icon = computed(() => iconByAccent[props.accent]) | |||
|
|||
<style lang="postcss" scoped> | |||
.ui-info { | |||
align-items: start; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Be careful when updating the styles of core UI components. This property is useful here to keep the icon properly aligned when the text in the UiInfo
is more than one line long (example here).
However, I agree that in your case, the icon alignment could be better. You can add a class in PoolNetworksPifStatus
and use it to change the alignment, see my comment on the component.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree to be careful when updating core UI components.
But shouldn't we remove align-items: start
and use if we need it? I have a feeling we'll need align-items: center
more often. Since it's the default behavior, no ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, maybe that would be better to handle single line info by default and add an override if necessary. Or we can add a prop for that? @ByScripts
@@ -0,0 +1,24 @@ | |||
<template> | |||
<UiInfo class="text-ellipsis" :accent="statusProps.accent"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Based on my comment on UiInfo
, you can add a class and change the icon alignment here:
<template>
<UiInfo class="pif-status">
</template>
<style lang="postcss" scoped>
.pif-status {
align-items: center;
}
</style>
const { status } = defineProps<{ | ||
status: 'connected' | 'disconnected' | 'partial' | ||
}>() | ||
|
||
const { t } = useI18n() | ||
|
||
type NetworkAccent = 'success' | 'warning' | 'danger' | ||
|
||
const statusMap: Record<string, { text: string; accent: NetworkAccent }> = { | ||
connected: { text: t('connected'), accent: 'success' }, | ||
disconnected: { text: t('disconnected'), accent: 'danger' }, | ||
partial: { text: t('partially-connected'), accent: 'warning' }, | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const { status } = defineProps<{ | |
status: 'connected' | 'disconnected' | 'partial' | |
}>() | |
const { t } = useI18n() | |
type NetworkAccent = 'success' | 'warning' | 'danger' | |
const statusMap: Record<string, { text: string; accent: NetworkAccent }> = { | |
connected: { text: t('connected'), accent: 'success' }, | |
disconnected: { text: t('disconnected'), accent: 'danger' }, | |
partial: { text: t('partially-connected'), accent: 'warning' }, | |
} | |
type Status = 'connected' | 'disconnected' | 'partial' | |
type Accent = 'success' | 'warning' | 'danger' | |
const { status } = defineProps<{ | |
status: Status | |
}>() | |
const { t } = useI18n() | |
const statusMap: Record<Status, { text: string; accent: Accent }> = { | |
connected: { text: t('connected'), accent: 'success' }, | |
disconnected: { text: t('disconnected'), accent: 'danger' }, | |
partial: { text: t('partially-connected'), accent: 'warning' }, | |
} | |
isReady: boolean | ||
}>() | ||
|
||
const reactiveHostInternalNetworks = ref<XenApiNetwork[]>(props.hostInternalNetwork || []) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this is necessary. We can use the prop directly.
const props = defineProps<{ | ||
hostInternalNetwork: XenApiNetwork[] | ||
isReady: boolean | ||
}>() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd suggest simplifying the naming.
Also, remember to use plural if expected data is an array.
const props = defineProps<{ | |
hostInternalNetwork: XenApiNetwork[] | |
isReady: boolean | |
}>() | |
const { networks, isReady } = defineProps<{ | |
networks: XenApiNetwork[] | |
isReady: boolean | |
}>() |
const filteredNetworks = computed(() => { | ||
return searchQuery.value | ||
? reactiveHostInternalNetworks.value.filter(network => | ||
Object.values(network).some(value => String(value).toLowerCase().includes(searchQuery.value.toLowerCase())) | ||
) | ||
: reactiveHostInternalNetworks.value | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd suggest something like that for better readability:
const filteredNetworks = computed(() => { | |
return searchQuery.value | |
? reactiveHostInternalNetworks.value.filter(network => | |
Object.values(network).some(value => String(value).toLowerCase().includes(searchQuery.value.toLowerCase())) | |
) | |
: reactiveHostInternalNetworks.value | |
}) | |
const filteredNetworks = computed(() => { | |
const searchTerm = searchQuery.value.trim().toLocaleLowerCase() | |
if (!searchTerm) { | |
return networks.value | |
} | |
return networks.value.filter(network => | |
Object.values(network).some(value => String(value).toLocaleLowerCase().includes(searchTerm)) | |
) | |
})``` |
const usableRefs = computed(() => reactiveHostInternalNetworks.value.map(item => item.uuid)) | ||
|
||
const { selected, areAllSelected } = useMultiSelect(usableRefs) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const usableRefs = computed(() => reactiveHostInternalNetworks.value.map(item => item.uuid)) | |
const { selected, areAllSelected } = useMultiSelect(usableRefs) | |
const networkUuids = computed(() => networks.value.map(network => network.uuid)) | |
const { selected, areAllSelected } = useMultiSelect(networkUuids) |
<td v-for="column of row.visibleColumns" :key="column.id" class="typo p2-regular"> | ||
<UiCheckbox v-if="column.id === 'checkbox'" v-model="selected" accent="info" :value="row.id" /> | ||
<!-- NEED TO REMOVE `as XenApiNetwork` --> | ||
<div | ||
v-if="column.id === 'name_label' && (row.value as XenApiNetwork).name_label" | ||
v-tooltip="{ placement: 'bottom-end' }" | ||
class="text-ellipsis" | ||
> | ||
{{ (row.value as XenApiNetwork).name_label }} | ||
</div> | ||
<div | ||
v-if="column.id === 'name_description'" | ||
v-tooltip="{ placement: 'bottom-end' }" | ||
class="text-ellipsis" | ||
> | ||
{{ (row.value as XenApiNetwork).name_description }} | ||
</div> | ||
<div v-if="column.id === 'MTU'" v-tooltip="{ placement: 'bottom-end' }" class="text-ellipsis"> | ||
{{ (row.value as XenApiNetwork).MTU }} | ||
</div> | ||
<div | ||
v-if="column.id === 'default_locking_mode'" | ||
v-tooltip="{ placement: 'bottom-end' }" | ||
class="text-ellipsis" | ||
> | ||
{{ (row.value as XenApiNetwork).default_locking_mode }} | ||
</div> | ||
<div v-if="column.id === 'more'"> | ||
<VtsIcon accent="info" :icon="faEllipsis" /> | ||
</div> | ||
</td> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks to the mapping of useTable
, column
already contains the value of the cell, so you can do something like this:
<td v-for="column of row.visibleColumns" :key="column.id" class="typo p2-regular"> | |
<UiCheckbox v-if="column.id === 'checkbox'" v-model="selected" accent="info" :value="row.id" /> | |
<!-- NEED TO REMOVE `as XenApiNetwork` --> | |
<div | |
v-if="column.id === 'name_label' && (row.value as XenApiNetwork).name_label" | |
v-tooltip="{ placement: 'bottom-end' }" | |
class="text-ellipsis" | |
> | |
{{ (row.value as XenApiNetwork).name_label }} | |
</div> | |
<div | |
v-if="column.id === 'name_description'" | |
v-tooltip="{ placement: 'bottom-end' }" | |
class="text-ellipsis" | |
> | |
{{ (row.value as XenApiNetwork).name_description }} | |
</div> | |
<div v-if="column.id === 'MTU'" v-tooltip="{ placement: 'bottom-end' }" class="text-ellipsis"> | |
{{ (row.value as XenApiNetwork).MTU }} | |
</div> | |
<div | |
v-if="column.id === 'default_locking_mode'" | |
v-tooltip="{ placement: 'bottom-end' }" | |
class="text-ellipsis" | |
> | |
{{ (row.value as XenApiNetwork).default_locking_mode }} | |
</div> | |
<div v-if="column.id === 'more'"> | |
<VtsIcon accent="info" :icon="faEllipsis" /> | |
</div> | |
</td> | |
<td v-for="column of row.visibleColumns" :key="column.id" class="typo p2-regular"> | |
<UiCheckbox v-if="column.id === 'checkbox'" v-model="selected" accent="info" :value="row.id" /> | |
<VtsIcon v-else-if="column.id === 'more'" accent="info" :icon="faEllipsis" /> | |
<div | |
v-else | |
v-tooltip="{ placement: 'bottom-end' }" | |
class="text-ellipsis" | |
> | |
{{ column.value }} | |
</div> | |
</td> |
Another possibility is to remove "checkbox" and "more" columns from column definitions and add them manually:
<td v-for="column of row.visibleColumns" :key="column.id" class="typo p2-regular"> | |
<UiCheckbox v-if="column.id === 'checkbox'" v-model="selected" accent="info" :value="row.id" /> | |
<!-- NEED TO REMOVE `as XenApiNetwork` --> | |
<div | |
v-if="column.id === 'name_label' && (row.value as XenApiNetwork).name_label" | |
v-tooltip="{ placement: 'bottom-end' }" | |
class="text-ellipsis" | |
> | |
{{ (row.value as XenApiNetwork).name_label }} | |
</div> | |
<div | |
v-if="column.id === 'name_description'" | |
v-tooltip="{ placement: 'bottom-end' }" | |
class="text-ellipsis" | |
> | |
{{ (row.value as XenApiNetwork).name_description }} | |
</div> | |
<div v-if="column.id === 'MTU'" v-tooltip="{ placement: 'bottom-end' }" class="text-ellipsis"> | |
{{ (row.value as XenApiNetwork).MTU }} | |
</div> | |
<div | |
v-if="column.id === 'default_locking_mode'" | |
v-tooltip="{ placement: 'bottom-end' }" | |
class="text-ellipsis" | |
> | |
{{ (row.value as XenApiNetwork).default_locking_mode }} | |
</div> | |
<div v-if="column.id === 'more'"> | |
<VtsIcon accent="info" :icon="faEllipsis" /> | |
</div> | |
</td> | |
<td> | |
<UiCheckbox v-model="selected" accent="info" :value="row.id" /> | |
</td> | |
<td v-for="column of row.visibleColumns" :key="column.id" class="typo p2-regular"> | |
<div v-tooltip="{ placement: 'bottom-end' }" class="text-ellipsis"> | |
{{ column.value }} | |
</div> | |
</td> | |
<td> | |
<VtsIcon accent="info" :icon="faEllipsis" /> | |
</td> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wonderful !
type networkHeader = 'name_label' | 'name_description' | 'MTU' | 'default_locking_mode' | 'more' | ||
|
||
const headerIcon: Record<networkHeader, { icon: IconDefinition }> = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Types should use PascalCase
type networkHeader = 'name_label' | 'name_description' | 'MTU' | 'default_locking_mode' | 'more' | |
const headerIcon: Record<networkHeader, { icon: IconDefinition }> = { | |
type NetworkHeader = 'name_label' | 'name_description' | 'MTU' | 'default_locking_mode' | 'more' | |
const headerIcon: Record<NetworkHeader, { icon: IconDefinition }> = { |
watchEffect(() => { | ||
if (props.hostInternalNetwork) { | ||
reactiveHostInternalNetworks.value = props.hostInternalNetwork || [] | ||
} | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unneeded
<UiCheckbox v-if="column.id === 'checkbox'" v-model="selected" accent="info" :value="row.id" /> | ||
</div> | ||
<!-- NEED TO REMOVE `as any` --> | ||
<div v-if="column.id === 'name_label'" v-tooltip="{ placement: 'bottom-end' }" class="text-ellipsis"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as previous comment concerning the columns of useTable
const { networksWithVLANs, hostInternalNetworks, isReady } = useNetworkStore().subscribe() | ||
|
||
const reactiveNetworksWithVLANs = ref(networksWithVLANs.value || []) | ||
const reactiveHostInternalNetworks = ref(hostInternalNetworks.value || []) | ||
|
||
watchEffect(() => { | ||
if (networksWithVLANs.value) { | ||
reactiveNetworksWithVLANs.value = networksWithVLANs.value || [] | ||
} | ||
if (hostInternalNetworks.value) { | ||
reactiveHostInternalNetworks.value = hostInternalNetworks.value || [] | ||
} | ||
}) | ||
</script> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unneeded. Data is already reactive.
const { networksWithVLANs, hostInternalNetworks, isReady } = useNetworkStore().subscribe() | |
const reactiveNetworksWithVLANs = ref(networksWithVLANs.value || []) | |
const reactiveHostInternalNetworks = ref(hostInternalNetworks.value || []) | |
watchEffect(() => { | |
if (networksWithVLANs.value) { | |
reactiveNetworksWithVLANs.value = networksWithVLANs.value || [] | |
} | |
if (hostInternalNetworks.value) { | |
reactiveHostInternalNetworks.value = hostInternalNetworks.value || [] | |
} | |
}) | |
</script> | |
const { networksWithVLANs, hostInternalNetworks, isReady } = useNetworkStore().subscribe() | |
</script> |
b67b66c
to
e382bc1
Compare
type Accent = 'success' | 'warning' | 'danger' | ||
|
||
const { status } = defineProps<{ | ||
status?: Status |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why does that prop turn optional?
In case it'd be legitimate, then undefined
status should be handled properly somewhere.
partial: { text: t('partially-connected'), accent: 'warning' }, | ||
} | ||
|
||
const statusProps = computed(() => statusMap[status!]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Exclamation point in TypeScript should be used with caution.
It means "You, as TypeScript, are not able to understand that this variable is defined. But me, as a developer, can assert that it is."
In this case, since the prop is optional, you can't assert that it will be defined, so you can't use an exclamation point here.
Here is an example where !
would be useful:
<template>
<div ref="elm" />
</template>
<script lang="ts" setup>
const elm = ref<HTMLELement | null>(null)
onMounted(() => {
doSomething(elm.value!) // <= Here, we tell TypeScript that we're sure this value is set, although TS can't guess.
})
</script>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok, thanks for the explanation!
</template> | ||
</UiTitle> | ||
<div class="content"> | ||
<UiQuerySearchBar class="table-query" @search="(value: string) => (searchQuery = value)" /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typing is already inferred here.
<UiQuerySearchBar class="table-query" @search="(value: string) => (searchQuery = value)" /> | |
<UiQuerySearchBar class="table-query" @search="value => (searchQuery = value)" /> |
<UiButtonIcon size="small" accent="info" :icon="getHeaderIcon(column.id)" /> | ||
{{ column.label }} | ||
</th> | ||
<ColumnTitle v-else id="networks" :icon="getHeaderIcon(column.id)"> {{ column.label }}</ColumnTitle> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can't use an fixed id
inside a v-for
loop.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it's a mistake
<div v-else-if="column.id === 'status'" class="status"> | ||
<PoolNetworksPifStatus :status="column.value" /> | ||
</div> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this necessary to wrap PoolNetworksPifStatus
in a div
?
Also, that div
has a status
class, but there is no .status
selector in the CSS.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No it's not necessary, it seems to be an oversight :/
networks: { | ||
network: XenApiNetwork | ||
status?: Status | ||
vlan?: string | ||
}[] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a little naming problem here.
Having a networks
prop containing an array of objects where each object has a network
property is really confusing.
It leads to code like network.network.<...>)
which looks wrong.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes.. indeed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you have any suggestions ?
const headerIcon: Record<NetworkHeader, { icon: IconDefinition }> = { | ||
name_label: { icon: faAlignLeft }, | ||
name_description: { icon: faAlignLeft }, | ||
status: { icon: faPowerOff }, | ||
vlan: { icon: faAlignLeft }, | ||
MTU: { icon: faHashtag }, | ||
default_locking_mode: { icon: faCaretDown }, | ||
more: { icon: faEllipsis }, | ||
} | ||
const getHeaderIcon = (status: NetworkHeader) => headerIcon[status].icon |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const headerIcon: Record<NetworkHeader, { icon: IconDefinition }> = { | |
name_label: { icon: faAlignLeft }, | |
name_description: { icon: faAlignLeft }, | |
status: { icon: faPowerOff }, | |
vlan: { icon: faAlignLeft }, | |
MTU: { icon: faHashtag }, | |
default_locking_mode: { icon: faCaretDown }, | |
more: { icon: faEllipsis }, | |
} | |
const getHeaderIcon = (status: NetworkHeader) => headerIcon[status].icon | |
const headerIcon: Record<NetworkHeader, IconDefinition> = { | |
name_label: faAlignLeft, | |
name_description: faAlignLeft, | |
status: faPowerOff, | |
vlan: faAlignLeft, | |
MTU: faHashtag, | |
default_locking_mode: faCaretDown, | |
more: faEllipsis, | |
} | |
const getHeaderIcon = (status: NetworkHeader) => headerIcon[status] |
const hostContext = deps.hostStore.getContext() | ||
const pifContext = deps.pifStore.getContext() | ||
|
||
const PIFsByNetwork = computed(() => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's keep consistency in variable names. (pifContext
/PIFsByNetwork
)
const PIFsByNetwork = computed(() => { | |
const pifsByNetwork = computed(() => { |
{ | ||
network: XenApiNetwork | ||
vlan: string | ||
status: Status | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Redundant typing should be extracted to a type and be reused.
{ | |
network: XenApiNetwork | |
vlan: string | |
status: Status | |
} | |
{ | |
network: XenApiNetwork | |
vlan: string | |
status: Status | |
} |
if (!networksInfoMap.has(network.$ref)) { | ||
networksInfoMap.set(network.$ref, networkWithDetails) | ||
} | ||
networksInfoMap.set(network.$ref, networkWithDetails) | ||
return networkWithDetails |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This part is really not clear.
First, you do the same thing inside the conditional statement than after it.
Also, what is the whole point of the networksInfoMap
here? You store data in it but never seem to use that information anywhere else.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, indeed, it wasn't clear to me at first, so I did several tests and because it worked, nonsense like that remained
function determineStatus(PIFs: XenApiPif[]): Status { | ||
if (PIFs.length === 0) { | ||
return 'disconnected' | ||
} | ||
const currentlyAttached = PIFs.map(PIF => PIF.currently_attached) | ||
if (currentlyAttached.every(Boolean)) { | ||
return 'connected' | ||
} | ||
if (currentlyAttached.some(Boolean)) { | ||
return 'partial' | ||
} | ||
return 'disconnected' | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since you have a pif
store, why did you put this in the network store?
function determineStatus(PIFs: XenApiPif[]): Status { | |
if (PIFs.length === 0) { | |
return 'disconnected' | |
} | |
const currentlyAttached = PIFs.map(PIF => PIF.currently_attached) | |
if (currentlyAttached.every(Boolean)) { | |
return 'connected' | |
} | |
if (currentlyAttached.some(Boolean)) { | |
return 'partial' | |
} | |
return 'disconnected' | |
} | |
function determineStatus(PIFs: XenApiPif[]): Status { | |
if (PIFs.length === 0) { | |
return 'disconnected' | |
} | |
const currentlyAttached = PIFs.map(PIF => PIF.currently_attached) | |
if (currentlyAttached.every(Boolean)) { | |
return 'connected' | |
} | |
if (currentlyAttached.some(Boolean)) { | |
return 'partial' | |
} | |
return 'disconnected' | |
} |
…store and pif store
…ing some improvements
b0f9ba2
to
46db63d
Compare
Description
Implementation of network tab in pool and add network/pifs store to get data
### Screenshot
Checklist
Fixes #007
,See xoa-support#42
,See https://...
)Introduced by
CHANGELOG.unreleased.md
Review process
Notes: