dashboard/components/auth/SelectPrincipal.vue

175 lines
3.6 KiB
Vue

<script>
import LabeledSelect from '@/components/form/LabeledSelect';
import Principal from '@/components/auth/Principal';
import debounce from 'lodash/debounce';
import { _EDIT } from '@/config/query-params';
import { NORMAN } from '@/config/types';
export default {
components: {
LabeledSelect,
Principal,
},
props: {
mode: {
type: String,
default: _EDIT,
},
showMyGroupTypes: {
type: Array,
default() {
return ['group'];
},
},
// either 'user' or 'group'
searchGroupTypes: {
type: String,
default: null,
},
retainSelection: {
type: Boolean,
default: false
}
},
async fetch() {
this.principals = await this.$store.dispatch('rancher/findAll', {
type: NORMAN.PRINCIPAL,
opt: { url: '/v3/principals' }
});
this.options = this.suggested;
},
data() {
return {
principals: null,
searchStr: '',
options: [],
newValue: '',
};
},
computed: {
suggested() {
const out = this.principals.filter((x) => {
if ( !x.memberOf ) {
return false;
}
if ( !this.showMyGroupTypes.includes(x.principalType) ) {
return false;
}
return true;
}).map(x => x.id);
return out;
},
},
created() {
this.debouncedSearch = debounce(this.search, 200);
},
methods: {
add(id) {
this.$emit('add', id);
if (!this.retainSelection) {
this.newValue = '';
}
},
onSearch(str, loading, vm) {
str = (str || '').trim();
this.searchStr = str;
if ( str ) {
loading(true);
this.debouncedSearch(str, loading);
} else {
this.search(null, loading);
}
},
async search(str, loading) {
if ( !str ) {
this.options = this.suggested.slice();
loading(false);
return;
}
try {
const res = await this.$store.dispatch('rancher/collectionAction', {
type: NORMAN.PRINCIPAL,
actionName: 'search',
opt: { url: '/v3/principals?action=search' },
body: {
name: str,
principalType: this.searchGroupTypes
}
});
if ( this.searchStr === str ) {
// If not, they've already typed something else
this.options = res.map(x => x.id);
}
} catch (e) {
this.options = [];
} finally {
loading(false);
}
}
}
};
</script>
<template>
<LabeledSelect
v-model="newValue"
:mode="mode"
:label="retainSelection ? `Select Member` : `Add Member`"
placeholder="Start typing to search for principals"
:options="options"
:searchable="true"
:filterable="false"
class="select-principal"
:class="{'retain-selection': retainSelection}"
@input="add"
@search="onSearch"
>
<template v-if="!searchStr && options.length" #list-header>
<li class="pl-10 text-muted">
Your Groups:
</li>
</template>
<template #option="option">
<Principal :key="option.label" :value="option.label" :use-muted="false" />
</template>
<template v-if="retainSelection" #selected-option="option">
<Principal :key="option.label" :value="option.label" :use-muted="false" class="mt-10 mb-10" />
</template>
</LabeledSelect>
</template>
<style lang="scss" scoped>
.select-principal {
&.retain-selection {
min-height: 84px;
&.focused {
.principal {
display: none;
}
}
}
}
</style>