dashboard/shell/components/form/ResourceLabeledSelect.vue

170 lines
5.1 KiB
Vue

<script lang="ts">
import { PropType, defineComponent } from 'vue';
import LabeledSelect from '@shell/components/form/LabeledSelect.vue';
import { PaginationParamFilter } from '@shell/types/store/pagination.types';
import { labelSelectPaginationFunction, LabelSelectPaginationFunctionOptions } from '@shell/components/form/labeled-select-utils/labeled-select.utils';
import { LabelSelectPaginateFnOptions, LabelSelectPaginateFnResponse } from '@shell/types/components/labeledSelect';
import { RESOURCE_LABEL_SELECT_MODE, ResourceLabeledSelectPaginateSettings, ResourceLabeledSelectSettings } from '@shell/types/components/resourceLabeledSelect';
/**
* Convenience wrapper around the LabelSelect component to support pagination
*
* Handles
*
* 1) Conditionally enabling the pagination feature given system settings
* 2) Helper function to fetch the pagination result
*
* A number of ways can be provided to override the conveniences (see props)
*/
export default defineComponent({
name: 'ResourceLabeledSelect',
components: { LabeledSelect },
emits: ['update:value'],
props: {
/**
* Resource to show
*/
resourceType: {
type: String,
required: true
},
inStore: {
type: String,
default: undefined,
},
/**
* Determine if pagination is used via settings (DYNAMIC) or hardcode off
*/
paginateMode: {
type: String as PropType<RESOURCE_LABEL_SELECT_MODE>,
default: RESOURCE_LABEL_SELECT_MODE.DYNAMIC,
},
/**
* Specific settings to use when we're showing all results in the drop down
*/
allResourcesSettings: {
type: Object as PropType<ResourceLabeledSelectSettings>,
default: null,
},
/**
* Specific settings to use when we're showing paginated results in the drop down
*/
paginatedResourceSettings: {
type: Object as PropType<ResourceLabeledSelectPaginateSettings>,
default: null,
},
},
data() {
let validInStore = this.inStore;
if (!validInStore && this.resourceType) {
validInStore = this.$store.getters['currentStore'](this.resourceType);
}
if (!validInStore) {
validInStore = 'cluster';
}
return {
paginate: false,
validInStore,
};
},
async fetch() {
switch (this.paginateMode) {
case RESOURCE_LABEL_SELECT_MODE.ALL_RESOURCES:
this.paginate = false;
break;
case RESOURCE_LABEL_SELECT_MODE.DYNAMIC:
this.paginate = this.$store.getters[`${ this.validInStore }/paginationEnabled`](this.resourceType);
break;
}
if (!this.paginate) {
// The resource won't be paginated and component expects everything up front
await this.$store.dispatch(`${ this.validInStore }/findAll`, { type: this.resourceType });
}
},
computed: {
labelSelectAttributes() {
// This component is a wrapper for LabelSelect, so pass through everything
const allAttrs = {
...this.$attrs, // Attributes (other than props)
...this.$props, // Attributes that are props
};
return this.paginate ? {
...allAttrs,
...this.paginatedResourceSettings?.labelSelectOptions || {}
} : {
...allAttrs,
...this.allResourcesSettings?.labelSelectOptions || {}
};
},
allOfType() {
if (this.$fetchState.pending || this.paginate) {
return [];
}
const all = this.$store.getters[`${ this.validInStore }/all`](this.resourceType);
return this.allResourcesSettings?.updateResources ? this.allResourcesSettings.updateResources(all) : all;
}
},
methods: {
/**
* Make the request to fetch the resource given the state of the label select (filter, page, page size, etc see LabelSelectPaginateFn)
* opts: Typeof LabelSelectPaginateFn
*/
async paginateType(opts: LabelSelectPaginateFnOptions): Promise<LabelSelectPaginateFnResponse> {
if (this.paginatedResourceSettings?.overrideRequest) {
return await this.paginatedResourceSettings.overrideRequest(opts);
}
const { filter } = opts;
const filters = !!filter ? [PaginationParamFilter.createSingleField({
field: 'metadata.name', value: filter, exact: false
})] : [];
const defaultOptions: LabelSelectPaginationFunctionOptions = {
opts,
filters,
type: this.resourceType,
ctx: { getters: this.$store.getters, dispatch: this.$store.dispatch },
sort: [{ asc: true, field: 'metadata.name' }],
store: this.validInStore
};
const options = this.paginatedResourceSettings?.requestSettings ? this.paginatedResourceSettings.requestSettings(defaultOptions) : defaultOptions;
const res = await labelSelectPaginationFunction(options);
return this.paginatedResourceSettings?.updateResources ? {
...res,
page: this.paginatedResourceSettings.updateResources(res.page)
} : res;
},
},
});
</script>
<template>
<LabeledSelect
v-bind="labelSelectAttributes"
:loading="$fetchState.pending"
:options="allOfType"
:paginate="paginateType"
:multiple="$attrs.multiple || false"
@update:value="$emit('update:value', $event)"
/>
</template>