clone selectMulti to selectSingle for assignedMember

This commit is contained in:
negue
2021-03-31 00:44:49 +02:00
committed by SabreCat
parent f4feb09fbc
commit 7dbee4caed
3 changed files with 308 additions and 17 deletions

View File

@@ -0,0 +1,291 @@
<template>
<div>
<b-dropdown
ref="dropdown"
class="inline-dropdown select-multi"
:toggle-class="isOpened ? 'active' : null"
@show="wasOpened()"
@hide="hideCallback($event)"
@toggle="openOrClose($event)"
>
<b-dropdown-header>
<div class="mb-2">
<b-form-input
v-model="search"
type="text"
:placeholder="searchPlaceholder"
@keyup.enter="handleSubmit"
/>
</div>
</b-dropdown-header>
<template v-slot:button-content>
<div
v-if="selectedItem !== null"
v-markdown="allItemsMap[selectedItem].name"
class="label"
></div>
</template>
<div
v-if="addNew || availableToSelect.length > 0"
:class="{
'item-group': true,
'add-new': availableToSelect.length === 0 && search !== '',
'scroll': availableToSelect.length > 5
}"
>
<b-dropdown-item-button
v-for="item in availableToSelect"
:key="item.id"
class="ignore-hide multi-item"
:class="{ 'none': item.id === 'none', selectListItem: true }"
@click.prevent.stop="selectItem(item)"
>
<div
v-markdown="item.name"
class="label"
></div>
<div
v-if="item.challenge"
class="addl-text"
>
{{ $t('challenge') }}
</div>
<div
v-else-if="item.addlText"
class="addl-text"
>
{{ item.addlText }}
</div>
</b-dropdown-item-button>
<div
v-if="addNew"
class="hint"
>
{{ $t('pressEnterToAddTag', { tagName: search }) }}
</div>
</div>
</b-dropdown>
</div>
</template>
<style lang="scss">
@import '~@/assets/scss/colors.scss';
$itemHeight: 2rem;
.select-multi {
.dropdown-toggle {
padding-left: 0.75rem;
}
.dropdown-header {
background-color: $gray-700;
padding-bottom: 0;
min-height: 3rem;
}
.dropdown-item, .dropdown-header {
padding-left: 0.75rem;
padding-right: 0.75rem;
}
.none {
cursor: default;
pointer-events: none;
}
.multi-item button {
height: $itemHeight;
display: flex;
.label {
height: 1.5rem;
font-size: 14px;
line-height: 1.71;
flex: 1;
}
.addl-text {
height: 1rem;
font-size: 12px;
font-weight: normal;
font-stretch: normal;
font-style: normal;
line-height: 1.33;
letter-spacing: normal;
text-align: right;
color: $gray-100;
align-self: center;
margin-top: 0.5rem;
margin-bottom: 0.5rem;
margin-right: 0.25rem;
}
&:hover {
.addl-text {
color: $purple-300;
}
}
}
.item-group {
max-height: #{5*$itemHeight};
&.add-new {
height: 30px;
.hint {
display: block;
}
}
&.scroll {
overflow-y: scroll;
}
}
.hint {
display: none;
height: 2rem;
font-size: 12px;
font-weight: normal;
font-stretch: normal;
font-style: normal;
line-height: 1.33;
letter-spacing: normal;
color: $gray-100;
margin-left: 0.75rem;
margin-top: 0.5rem;
}
}
</style>
<script>
import Vue from 'vue';
import markdownDirective from '@/directives/markdown';
export default {
directives: {
markdown: markdownDirective,
},
components: {
},
props: {
addNew: {
type: Boolean,
default: false,
},
allItems: {
type: Array,
},
emptyMessage: {
type: String,
},
pillInvert: {
type: Boolean,
default: false,
},
searchPlaceholder: {
type: String,
},
selectedItem: {
type: String,
},
},
data () {
return {
preventHide: true,
isOpened: false,
selected: this.selectedItem,
search: '',
};
},
computed: {
allItemsMap () {
const obj = {};
this.allItems.forEach(t => {
obj[t.id] = t;
});
return obj;
},
selectedItemAsObject () {
return this.selected ? this.allItemsMap[this.selected] : null;
},
availableToSelect () {
const availableItems = this.allItems.filter(t => t.id !== this.selected);
const searchString = this.search.toLowerCase();
const filteredItems = availableItems.filter(i => i.name.toLowerCase().includes(searchString));
return filteredItems;
},
},
watch: {
selected () {
this.$emit('changed', this.selected);
},
},
created () {
document.addEventListener('keyup', this.handleEsc);
},
beforeDestroy () {
document.removeEventListener('keyup', this.handleEsc);
},
mounted () {
this.$refs.dropdown.clickOutHandler = () => {
this.closeSelectPopup();
};
},
methods: {
closeSelectPopup () {
this.preventHide = false;
this.isOpened = false;
Vue.nextTick(() => {
this.$refs.dropdown.hide();
});
},
openOrClose ($event) {
if (this.isOpened) {
this.closeSelectPopup();
$event.preventDefault();
}
},
closeIfOpen () {
this.closeSelectPopup();
},
selectItem (item) {
this.$emit('toggle', item.id);
},
removeItem () {
this.$emit('toggle', null);
},
hideCallback ($event) {
if (this.preventHide) {
$event.preventDefault();
return;
}
this.isOpened = false;
},
wasOpened () {
this.isOpened = true;
this.preventHide = true;
},
handleEsc (e) {
if (e.keyCode === 27) {
this.closeSelectPopup();
}
},
handleSubmit () {
if (!this.addNew) return;
const { search } = this;
this.$emit('addNew', search);
this.search = '';
},
},
};
</script>