mirror of
https://github.com/knadh/listmonk.git
synced 2025-10-09 23:06:36 +08:00
123 lines
2.9 KiB
Vue
123 lines
2.9 KiB
Vue
<template>
|
|
<div class="field list-selector">
|
|
<div :class="['list-tags', ...classes]">
|
|
<b-taglist>
|
|
<b-tag v-for="l in selectedItems"
|
|
:key="l.id"
|
|
:class="l.subscriptionStatus"
|
|
:closable="true"
|
|
:data-id="l.id"
|
|
@close="removeList(l.id)" class="list">
|
|
{{ l.name }} <sup>{{ l.subscriptionStatus }}</sup>
|
|
</b-tag>
|
|
</b-taglist>
|
|
</div>
|
|
|
|
<b-field :message="message"
|
|
:label="label + (selectedItems ? ` (${selectedItems.length})` : '')"
|
|
label-position="on-border">
|
|
<b-autocomplete
|
|
v-model="query"
|
|
:placeholder="placeholder"
|
|
clearable
|
|
dropdown-position="top"
|
|
:disabled="all.length === 0"
|
|
:keep-first="true"
|
|
:clear-on-select="true"
|
|
:open-on-focus="true"
|
|
:data="filteredLists"
|
|
@select="selectList"
|
|
field="name">
|
|
</b-autocomplete>
|
|
</b-field>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import Vue from 'vue';
|
|
|
|
export default {
|
|
name: 'ListSelector',
|
|
|
|
props: {
|
|
label: String,
|
|
placeholder: String,
|
|
message: String,
|
|
required: Boolean,
|
|
disabled: Boolean,
|
|
classes: {
|
|
type: Array,
|
|
default: () => [],
|
|
},
|
|
selected: {
|
|
type: Array,
|
|
default: () => [],
|
|
},
|
|
all: {
|
|
type: Array,
|
|
default: () => [],
|
|
},
|
|
},
|
|
|
|
data() {
|
|
return {
|
|
query: '',
|
|
selectedItems: [],
|
|
};
|
|
},
|
|
|
|
methods: {
|
|
selectList(l) {
|
|
if (!l) {
|
|
return;
|
|
}
|
|
this.selectedItems.push(l);
|
|
this.query = '';
|
|
|
|
// Propagate the items to the parent's v-model binding.
|
|
Vue.nextTick(() => {
|
|
this.$emit('input', this.selectedItems);
|
|
});
|
|
},
|
|
|
|
removeList(id) {
|
|
this.selectedItems = this.selectedItems.filter((l) => l.id !== id);
|
|
|
|
// Propagate the items to the parent's v-model binding.
|
|
Vue.nextTick(() => {
|
|
this.$emit('input', this.selectedItems);
|
|
});
|
|
},
|
|
},
|
|
|
|
computed: {
|
|
// Return the list of unselected lists.
|
|
filteredLists() {
|
|
// Get a map of IDs of the user subscriptions. eg: {1: true, 2: true};
|
|
const subIDs = this.selectedItems.reduce((obj, item) => ({ ...obj, [item.id]: true }), {});
|
|
|
|
// Filter lists from the global lists whose IDs are not in the user's
|
|
// subscribed ist.
|
|
const q = this.query.toLowerCase();
|
|
return this.$props.all.filter(
|
|
(l) => (!(l.id in subIDs) && l.name.toLowerCase().indexOf(q) >= 0),
|
|
);
|
|
},
|
|
},
|
|
|
|
watch: {
|
|
// This is required to update the array of lists to propagate from parent
|
|
// components and "react" on the selector.
|
|
selected() {
|
|
// Deep-copy.
|
|
this.selectedItems = JSON.parse(JSON.stringify(this.selected));
|
|
},
|
|
},
|
|
|
|
mounted() {
|
|
if (this.selected) {
|
|
this.selectedItems = JSON.parse(JSON.stringify(this.selected));
|
|
}
|
|
},
|
|
};
|
|
</script>
|