mirror of
https://gitlab.com/wgp/dougal/software.git
synced 2025-12-06 10:27:09 +00:00
Add dialogue to edit event labels.
This assumes that adding or removing labels is a relatively common action to do on an event and provides a quicker and simpler mechanism than bringing up the full event dialogue. This is meant to be invoked from a context menu action or similar.
This commit is contained in:
208
lib/www/client/source/src/components/event-edit-labels.vue
Normal file
208
lib/www/client/source/src/components/event-edit-labels.vue
Normal file
@@ -0,0 +1,208 @@
|
||||
<template>
|
||||
<v-dialog
|
||||
:value="value"
|
||||
@input="(e) => $emit('input', e)"
|
||||
max-width="600"
|
||||
>
|
||||
<v-card>
|
||||
<v-toolbar
|
||||
flat
|
||||
color="transparent"
|
||||
>
|
||||
<v-toolbar-title>Event labels</v-toolbar-title>
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn
|
||||
icon
|
||||
@click="$refs.search.focus()"
|
||||
>
|
||||
<v-icon>mdi-magnify</v-icon>
|
||||
</v-btn>
|
||||
</v-toolbar>
|
||||
|
||||
<v-container class="py-0">
|
||||
<v-row
|
||||
align="center"
|
||||
justify="start"
|
||||
>
|
||||
<v-col
|
||||
v-for="(item, i) in selection"
|
||||
:key="item.text"
|
||||
class="shrink"
|
||||
>
|
||||
<v-chip
|
||||
:disabled="loading"
|
||||
small
|
||||
:color="item.colour"
|
||||
:title="item.title"
|
||||
close
|
||||
@click:close="selection.splice(i, 1)"
|
||||
>
|
||||
<v-icon
|
||||
left
|
||||
v-text="item.icon"
|
||||
></v-icon>
|
||||
{{ item.text }}
|
||||
</v-chip>
|
||||
</v-col>
|
||||
|
||||
<v-col v-if="!allSelected"
|
||||
cols="12"
|
||||
>
|
||||
<v-text-field
|
||||
ref="search"
|
||||
v-model="search"
|
||||
full-width
|
||||
hide-details
|
||||
label="Search"
|
||||
single-line
|
||||
></v-text-field>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-container>
|
||||
|
||||
<v-divider v-if="!allSelected"></v-divider>
|
||||
|
||||
<v-list dense style="max-height:600px;overflow-y:auto;">
|
||||
<template v-for="item in categories">
|
||||
<v-list-item v-if="!selection.find(i => i.text == item.text)"
|
||||
dense
|
||||
:key="item.text"
|
||||
:disabled="loading"
|
||||
@click="selection.push(item)"
|
||||
>
|
||||
<v-list-item-avatar
|
||||
class="my-0"
|
||||
width="12ex"
|
||||
>
|
||||
<v-chip
|
||||
x-small
|
||||
:color="item.colour"
|
||||
:title="item.title"
|
||||
>{{item.text}}</v-chip>
|
||||
</v-list-item-avatar>
|
||||
<v-list-item-title v-text="item.title"></v-list-item-title>
|
||||
</v-list-item>
|
||||
</template>
|
||||
</v-list>
|
||||
|
||||
<v-divider></v-divider>
|
||||
|
||||
<v-card-actions>
|
||||
<v-btn
|
||||
:loading="loading"
|
||||
color="warning"
|
||||
text
|
||||
@click="close"
|
||||
>
|
||||
Cancel
|
||||
</v-btn>
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn
|
||||
:disabled="!dirty"
|
||||
:loading="loading"
|
||||
color="primary"
|
||||
text
|
||||
@click="save"
|
||||
>
|
||||
Save
|
||||
</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
function stringSort (a, b) {
|
||||
return a == b
|
||||
? 0
|
||||
: a < b
|
||||
? -1
|
||||
: +1;
|
||||
}
|
||||
|
||||
export default {
|
||||
name: 'DougalEventEditLabels',
|
||||
|
||||
props: {
|
||||
value: { default: false },
|
||||
labels: { type: Object },
|
||||
selected: {type: Array },
|
||||
loading: { type: Boolean, default: false }
|
||||
},
|
||||
|
||||
data: () => ({
|
||||
dialog: false,
|
||||
search: '',
|
||||
selection: [],
|
||||
}),
|
||||
|
||||
computed: {
|
||||
allSelected () {
|
||||
return this.selection.length === this.items.length
|
||||
},
|
||||
|
||||
dirty () {
|
||||
// Checks if the arrays have the same elements
|
||||
return !this.selection.every(i => this.selected.includes(i.text)) ||
|
||||
!this.selected.every(i => this.selection.find(j => j.text==i));
|
||||
},
|
||||
|
||||
categories () {
|
||||
const search = this.search.toLowerCase()
|
||||
|
||||
if (!search) return this.items
|
||||
|
||||
return this.items.filter(item => {
|
||||
const text = item.text.toLowerCase();
|
||||
const title = item.title.toLowerCase();
|
||||
|
||||
return text.includes(search) || title.includes(search);
|
||||
}).sort( (a, b) => stringSort(a.text, b.text) )
|
||||
},
|
||||
|
||||
items () {
|
||||
return Object.keys(this.labels).map(this.labelToItem);
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
value () {
|
||||
this.dialog = this.value;
|
||||
if (this.dialog) {
|
||||
this.$nextTick(() => this.$refs.search?.focus());
|
||||
}
|
||||
},
|
||||
|
||||
selected () {
|
||||
this.selection = this.selected.map(this.labelToItem)
|
||||
},
|
||||
|
||||
selection () {
|
||||
this.search = '';
|
||||
this.$refs.search?.focus();
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
labelToItem (k) {
|
||||
return {
|
||||
text: k,
|
||||
icon: this.labels[k].view?.icon,
|
||||
colour: this.labels[k].view?.colour,
|
||||
title: this.labels[k].view?.description
|
||||
};
|
||||
},
|
||||
|
||||
close () {
|
||||
this.selection = this.selected.map(this.labelToItem)
|
||||
this.$emit("input", false);
|
||||
},
|
||||
|
||||
save () {
|
||||
this.$emit("selectionChanged", {labels: this.selection.map(i => i.text)});
|
||||
this.$emit("input", false);
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
@@ -44,6 +44,14 @@
|
||||
>
|
||||
</dougal-event-edit>
|
||||
|
||||
<dougal-event-edit-labels v-if="writeaccess"
|
||||
v-model="eventLabelsDialog"
|
||||
:labels="userLabels"
|
||||
:selected="contextMenuItem ? contextMenuItem.labels||[] : []"
|
||||
@selectionChanged="(data) => patchEvent(contextMenuItem.id, data)"
|
||||
>
|
||||
</dougal-event-edit-labels>
|
||||
|
||||
<v-menu v-if="$route.params.sequence">
|
||||
<template v-slot:activator="{on, attrs}">
|
||||
<v-btn class="ml-5" small v-on="on" v-bind="attrs">
|
||||
@@ -179,6 +187,7 @@ tr.align-top td:not(.align-default) {
|
||||
import { mapActions, mapGetters, mapState } from 'vuex';
|
||||
import DougalContextMenu from '@/components/context-menu';
|
||||
import DougalEventEdit from '@/components/event-edit'
|
||||
import DougalEventEditLabels from '@/components/event-edit-labels'
|
||||
import DougalEventEditHistory from '@/components/event-edit-history'
|
||||
|
||||
function ArraysEqual (a, b) {
|
||||
@@ -198,6 +207,7 @@ export default {
|
||||
|
||||
components: {
|
||||
DougalEventEdit,
|
||||
DougalEventEditLabels,
|
||||
DougalEventEditHistory,
|
||||
DougalContextMenu
|
||||
},
|
||||
@@ -235,6 +245,7 @@ export default {
|
||||
filter: "",
|
||||
eventCount: null,
|
||||
eventDialog: false,
|
||||
eventLabelsDialog: false,
|
||||
defaultEventTimestamp: null,
|
||||
presetRemarks: null,
|
||||
remarksMenu: null,
|
||||
|
||||
Reference in New Issue
Block a user