dashboard/shell/edit/fleet.cattle.io.clustergrou...

190 lines
4.7 KiB
Vue

<script>
import { Banner } from '@components/Banner';
import CreateEditView from '@shell/mixins/create-edit-view';
import CruResource from '@shell/components/CruResource';
import Labels from '@shell/components/form/Labels';
import Loading from '@shell/components/Loading';
import MatchExpressions from '@shell/components/form/MatchExpressions';
import NameNsDescription from '@shell/components/form/NameNsDescription';
import { set } from '@shell/utils/object';
import { FLEET } from '@shell/config/types';
import { convert, matching, simplify } from '@shell/utils/selector';
import throttle from 'lodash/throttle';
import { allHash } from '@shell/utils/promise';
export default {
name: 'CruClusterGroup',
emits: ['input'],
inheritAttrs: false,
components: {
Banner,
CruResource,
Labels,
Loading,
MatchExpressions,
NameNsDescription,
},
mixins: [CreateEditView],
async fetch() {
const _hash = {};
if (this.$store.getters['management/schemaFor'](FLEET.CLUSTER)) {
_hash.allClusters = await this.$store.dispatch('management/findAll', { type: FLEET.CLUSTER });
}
if (this.$store.getters['management/schemaFor'](FLEET.WORKSPACE)) {
_hash.allWorkspaces = this.$store.dispatch('management/findAll', { type: FLEET.WORKSPACE });
}
const hash = await allHash(_hash);
this.allClusters = hash.allClusters || [];
this.allWorkspaces = hash.allWorkspaces || [];
if ( !this.value.spec?.selector ) {
this.value.spec = this.value.spec || {};
this.value.spec.selector = {
matchExpressions: [],
matchLabels: {},
};
}
const expressions = convert(
this.value.spec.selector.matchLabels || {},
this.value.spec.selector.matchExpressions || []
);
this.matchChanged(expressions);
},
data() {
return {
allClusters: null,
allWorkspaces: null,
matchingClusters: null,
expressions: null,
};
},
computed: {
FLEET_WORKSPACE() {
return FLEET.WORKSPACE;
},
clustersForWorkspace() {
const namespace = this.value.metadata?.namespace;
if ( !namespace ) {
return [];
}
const workspace = this.$store.getters['management/byId'](FLEET.WORKSPACE, namespace);
if ( workspace ) {
return workspace.clusters;
}
return [];
},
},
watch: { 'value.metadata.namespace': 'updateMatchingClusters' },
methods: {
set,
matchChanged(expressions) {
const { matchLabels, matchExpressions } = simplify(expressions);
set(this, 'expressions', expressions);
set(this, 'value.spec.selector.matchLabels', matchLabels);
set(this, 'value.spec.selector.matchExpressions', matchExpressions);
this.updateMatchingClusters();
},
updateMatchingClusters: throttle(function() {
const all = this.clustersForWorkspace;
const match = matching(all, this.expressions);
const matched = match.length || 0;
const sample = match[0]?.nameDisplay;
this.matchingClusters = {
matched,
total: all.length,
isAll: matched === all.length,
isNone: matched === 0,
sample,
};
}, 250, { leading: true }),
},
};
</script>
<template>
<Loading v-if="$fetchState.pending" />
<CruResource
v-else
:done-route="doneRoute"
:mode="mode"
:resource="value"
:subtypes="[]"
:validation-passed="true"
:errors="errors"
@error="e=>errors = e"
@finish="save"
@cancel="done"
>
<NameNsDescription
v-if="!isView"
:value="value"
:mode="mode"
:namespaced="false"
namespace-label="nameNsDescription.workspace.label"
:namespace-type="FLEET_WORKSPACE"
@update:value="$emit('input', $event)"
/>
<MatchExpressions
:mode="mode"
:value="expressions"
:show-remove="false"
@update:value="matchChanged($event)"
>
<template #header>
<h2 v-t="'fleet.clusterGroup.selector.label'" />
</template>
</MatchExpressions>
<Banner
v-if="matchingClusters"
:color="(matchingClusters.isNone || matchingClusters.isAll ? 'warning' : 'success')"
>
<span
v-if="matchingClusters.isAll"
v-clean-html="t('fleet.clusterGroup.selector.matchesAll', matchingClusters)"
/>
<span
v-else-if="matchingClusters.isNone"
v-clean-html="t('fleet.clusterGroup.selector.matchesNone', matchingClusters)"
/>
<span
v-else
v-clean-html="t('fleet.clusterGroup.selector.matchesSome', matchingClusters)"
/>
</Banner>
<div class="spacer" />
<Labels
default-section-class="mt-20"
:value="value"
:mode="mode"
:display-side-by-side="false"
/>
</CruResource>
</template>