mirror of
https://github.com/harvester/harvester-ui-extension.git
synced 2026-10-07 06:36:09 +08:00
Add pkg/harvester components + shell portings - 1
Signed-off-by: Francesco Torchia <francesco.torchia@suse.com>
This commit is contained in:
@@ -0,0 +1,295 @@
|
||||
<script>
|
||||
import Loading from '@shell/components/Loading';
|
||||
import ResourceTable from '@shell/components/ResourceTable';
|
||||
import Masthead from '@shell/components/ResourceList/Masthead';
|
||||
|
||||
import { allHash } from '@shell/utils/promise';
|
||||
import { STATE, AGE, NAME } from '@shell/config/table-headers';
|
||||
import { mapPref, GROUP_RESOURCES } from '@shell/store/prefs';
|
||||
import { NODE } from '@shell/config/types';
|
||||
|
||||
import { PRODUCT_NAME as HARVESTER_PRODUCT } from '../config/harvester';
|
||||
import { CLUSTER_NETWORK } from '../config/query-params';
|
||||
import { HCI } from '../types';
|
||||
|
||||
export default {
|
||||
name: 'ListHarvesterVLANConfigs',
|
||||
|
||||
components: {
|
||||
ResourceTable,
|
||||
Loading,
|
||||
Masthead,
|
||||
},
|
||||
|
||||
async fetch() {
|
||||
const inStore = this.$store.getters['currentProduct'].inStore;
|
||||
|
||||
await allHash({
|
||||
configs: this.$store.dispatch(`${ inStore }/findAll`, { type: HCI.VLAN_CONFIG }),
|
||||
clusterNetworks: this.$store.dispatch(`${ inStore }/findAll`, { type: HCI.CLUSTER_NETWORK }),
|
||||
vlanStatuses: this.$store.dispatch(`${ inStore }/findAll`, { type: HCI.VLAN_STATUS }),
|
||||
nodes: this.$store.dispatch(`${ inStore }/findAll`, { type: NODE })
|
||||
});
|
||||
},
|
||||
|
||||
data() {
|
||||
return { HCI };
|
||||
},
|
||||
|
||||
computed: {
|
||||
groupPreference: mapPref(GROUP_RESOURCES),
|
||||
|
||||
headers() {
|
||||
return [
|
||||
STATE,
|
||||
{
|
||||
...NAME,
|
||||
width: 300,
|
||||
},
|
||||
{
|
||||
name: 'type',
|
||||
labelKey: 'tableHeaders.type',
|
||||
value: 'typeDisplay',
|
||||
getValue: (row) => row.typeDisplay,
|
||||
sort: ['typeDisplay'],
|
||||
},
|
||||
AGE,
|
||||
];
|
||||
},
|
||||
|
||||
rows() {
|
||||
const inStore = this.$store.getters['currentProduct'].inStore;
|
||||
|
||||
const configs = this.$store.getters[`${ inStore }/all`](HCI.VLAN_CONFIG);
|
||||
|
||||
return configs;
|
||||
},
|
||||
|
||||
vlanConfigSchema() {
|
||||
const inStore = this.$store.getters['currentProduct'].inStore;
|
||||
|
||||
return this.$store.getters[`${ inStore }/schemaFor`](HCI.VLAN_CONFIG);
|
||||
},
|
||||
|
||||
clusterNetworkSchema() {
|
||||
const inStore = this.$store.getters['currentProduct'].inStore;
|
||||
|
||||
return this.$store.getters[`${ inStore }/schemaFor`](HCI.CLUSTER_NETWORK);
|
||||
},
|
||||
|
||||
isClusterNetworkCreatable() {
|
||||
return (this.clusterNetworkSchema?.collectionMethods || []).includes('POST');
|
||||
},
|
||||
|
||||
createClusterNetworkLocation() {
|
||||
const location = {
|
||||
name: `${ HARVESTER_PRODUCT }-c-cluster-resource-create`,
|
||||
params: {
|
||||
product: HARVESTER_PRODUCT,
|
||||
resource: HCI.CLUSTER_NETWORK,
|
||||
},
|
||||
};
|
||||
|
||||
return location;
|
||||
},
|
||||
|
||||
clusterNetworkWithoutConfigs() {
|
||||
const inStore = this.$store.getters['currentProduct'].inStore;
|
||||
|
||||
const clusterNetworks = this.$store.getters[`${ inStore }/all`](HCI.CLUSTER_NETWORK);
|
||||
|
||||
const out = clusterNetworks.map((network) => {
|
||||
const hasChild = !!this.rows.find((config) => config?.spec?.clusterNetwork === network.id);
|
||||
|
||||
return {
|
||||
...network,
|
||||
hasChild
|
||||
};
|
||||
});
|
||||
|
||||
return out;
|
||||
},
|
||||
|
||||
rowsWithFakeClusterNetworks() {
|
||||
const fakeRows = this.clusterNetworkWithoutConfigs.map((network) => {
|
||||
return {
|
||||
groupByLabel: network.id,
|
||||
isFake: true,
|
||||
mainRowKey: network.id,
|
||||
nameDisplay: network.id,
|
||||
groupByClusterNetwork: network.id,
|
||||
availableActions: []
|
||||
};
|
||||
});
|
||||
|
||||
return [...this.rows, ...fakeRows];
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
showClusterNetworkActionButton(group) {
|
||||
const inStore = this.$store.getters['currentProduct'].inStore;
|
||||
const clusterNetwork = group.key;
|
||||
|
||||
const resource = this.$store.getters[`${ inStore }/byId`](HCI.CLUSTER_NETWORK, clusterNetwork);
|
||||
|
||||
return !!resource;
|
||||
},
|
||||
|
||||
showClusterNetworkAction(event, group) {
|
||||
const inStore = this.$store.getters['currentProduct'].inStore;
|
||||
const clusterNetwork = group.key;
|
||||
|
||||
const resource = this.$store.getters[`${ inStore }/byId`](HCI.CLUSTER_NETWORK, clusterNetwork);
|
||||
|
||||
this.$store.commit(`action-menu/show`, {
|
||||
resources: [resource],
|
||||
elem: event.target
|
||||
});
|
||||
},
|
||||
|
||||
createVlanConfigLocation(group) {
|
||||
const clusterNetwork = group.key;
|
||||
|
||||
const location = {
|
||||
name: `${ HARVESTER_PRODUCT }-c-cluster-resource-create`,
|
||||
params: {
|
||||
product: HARVESTER_PRODUCT,
|
||||
resource: HCI.VLAN_CONFIG,
|
||||
},
|
||||
};
|
||||
|
||||
location.query = { [CLUSTER_NETWORK]: clusterNetwork };
|
||||
|
||||
return location;
|
||||
},
|
||||
|
||||
slotName(clusterNetwork) {
|
||||
return `main-row:${ clusterNetwork }`;
|
||||
},
|
||||
|
||||
groupLabel(group) {
|
||||
const row = group.rows[0];
|
||||
|
||||
if (row.isFake) {
|
||||
return `${ this.t('harvester.network.clusterNetwork.label') }: ${ row.nameDisplay }`;
|
||||
}
|
||||
|
||||
return `${ this.t('harvester.network.clusterNetwork.label') }: ${ group.key }`;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<Loading v-if="$fetchState.pending" />
|
||||
<div v-else>
|
||||
<Masthead
|
||||
:schema="clusterNetworkSchema"
|
||||
:type-display="t('harvester.clusterNetwork.title')"
|
||||
:resource="HCI.CLUSTER_NETWORK"
|
||||
:create-location="createClusterNetworkLocation"
|
||||
:create-button-label="t('harvester.clusterNetwork.create.button.label')"
|
||||
/>
|
||||
<ResourceTable
|
||||
:rows="rowsWithFakeClusterNetworks"
|
||||
:headers="headers"
|
||||
:groupable="true"
|
||||
:schema="vlanConfigSchema"
|
||||
group-by="groupByClusterNetwork"
|
||||
>
|
||||
<template #header-middle>
|
||||
<div />
|
||||
</template>
|
||||
<template #group-by="{group}">
|
||||
<div class="group-bar">
|
||||
<div class="group-tab">
|
||||
<span>
|
||||
{{ groupLabel(group) }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="right">
|
||||
<router-link
|
||||
v-if="isClusterNetworkCreatable && group.key !== 'mgmt'"
|
||||
class="btn btn-sm role-secondary mr-5"
|
||||
:to="createVlanConfigLocation(group)"
|
||||
>
|
||||
{{ t('harvester.vlanConfig.createNetworkConfig') }}
|
||||
</router-link>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm role-multi-action actions mr-10"
|
||||
:class="{invisible: !showClusterNetworkActionButton(group)}"
|
||||
@click="showClusterNetworkAction($event, group)"
|
||||
>
|
||||
<i class="icon icon-actions" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template
|
||||
v-for="clusterNetwork in clusterNetworkWithoutConfigs"
|
||||
v-slot:[slotName(clusterNetwork.id)]
|
||||
>
|
||||
<tr
|
||||
v-show="!clusterNetwork.hasChild"
|
||||
:key="clusterNetwork.id"
|
||||
class="main-row"
|
||||
>
|
||||
<td
|
||||
class="empty text-center"
|
||||
colspan="12"
|
||||
>
|
||||
{{ clusterNetwork.id === 'mgmt' ? t('harvester.clusterNetwork.mgmt') : t('harvester.clusterNetwork.clusterNetwork') }}
|
||||
</td>
|
||||
</tr>
|
||||
</template>
|
||||
</ResourceTable>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.group-bar {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
|
||||
.right {
|
||||
margin-top: 5px;
|
||||
margin-bottom: 3px;
|
||||
}
|
||||
|
||||
.group-tab {
|
||||
&, &::after {
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
&::after {
|
||||
right: -20px;
|
||||
}
|
||||
|
||||
SPAN {
|
||||
color: var(--body-text) !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss">
|
||||
.col-link-detail {
|
||||
// Avoid 'Create Network Config' button to overlap the namespace tab when resize table to min length
|
||||
min-width: 200px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss">
|
||||
.group-bar .right {
|
||||
display: flex;
|
||||
margin-left: 50px;
|
||||
a {
|
||||
height: 30px;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user