Browse Source

WIP: Improve TagsManager styling & workflow

remotes/philippdormann/main
Nelson Chan 4 years ago
parent
commit
6cd22bf4ac
  1. 12
      src/components/Tag.vue
  2. 140
      src/components/TagsManager.vue
  3. 17
      src/pages/EditMonitor.vue

12
src/components/Tag.vue

@ -1,5 +1,10 @@
<template> <template>
<div class="m-2 py-1 px-3 rounded d-inline-flex" :style="{ backgroundColor: item.color }">{{ displayText }}<span class="ps-1 btn-remove" @click="remove(item.id)"><font-awesome-icon icon="times" /></span></div> <div class="tag-wrapper m-2 py-1 px-3 rounded d-inline-flex" :style="{ backgroundColor: item.color }">
{{ displayText }}
<span class="ps-1 btn-remove" @click="remove(item.id)">
<font-awesome-icon icon="times" />
</span>
</div>
</template> </template>
<script> <script>
@ -27,8 +32,13 @@ export default {
</script> </script>
<style scoped> <style scoped>
.tag-wrapper {
color: white;
}
.btn-remove { .btn-remove {
font-size: 0.9em; font-size: 0.9em;
line-height: 24px;
opacity: 0.3; opacity: 0.3;
} }

140
src/components/TagsManager.vue

@ -1,7 +1,7 @@
<template> <template>
<div> <div>
<h4 class="mb-3">{{ $t("Tags") }}</h4> <h4 class="mb-3">{{ $t("Tags") }}</h4>
<div class="mb-3 form-control disabled p-1 rounded-1"> <div class="mb-3 p-1">
<tag <tag
v-for="item in selectedTags" v-for="item in selectedTags"
:key="item.id" :key="item.id"
@ -10,31 +10,77 @@
/> />
</div> </div>
<div> <div>
<select <vue-multiselect
id="snewDraftTagName"
v-model="newDraftTag.select" v-model="newDraftTag.select"
class="form-select mb-2" class="mb-2"
required :options="tagOptions"
:multiple="false"
:searchable="true"
placeholder="Add..."
track-by="id"
label="name"
> >
<option value="0" disabled selected>{{ $t("Add...") }}</option> <template #option="{ option }">
<option v-for="tag in tags" :key="tag.id" :value="tag.id"> <div class="mx-2 py-1 px-3 rounded d-inline-flex"
{{ tag.name }} style="margin-top: -5px; margin-bottom: -5px; height: 24px;"
</option> :style="{ color: option.color ? 'white' : 'var(--bs-body-color)', backgroundColor: option.color + ' !important' }"
<option value="-1">{{ $t("New...") }}</option> >
</select> <span>
<div v-show="newDraftTag.select == -1" class="d-flex mb-2"> {{ option.name }}</span>
</div>
</template>
<template #singleLabel="{ option }">
<div class="py-1 px-3 rounded d-inline-flex"
style="height: 24px;"
:style="{ color: option.color ? 'white' : 'var(--bs-body-color)', backgroundColor: option.color + ' !important' }"
>
<span>{{ option.name }}</span>
</div>
</template>
</vue-multiselect>
<div v-if="newDraftTag.select?.id == -1" class="d-flex mb-2">
<div class="w-50 pe-2"> <div class="w-50 pe-2">
<input class="form-control" placeholder="name" /> <input v-model="newDraftTag.name" class="form-control" :class="{'is-invalid': newDraftTag.nameInvalid}" placeholder="name" />
<div class="invalid-feedback">
Tag with this name already exist.
</div>
</div> </div>
<div class="w-50 ps-2"> <div class="w-50 ps-2">
<input class="form-control" placeholder="color" /> <vue-multiselect
v-model="newDraftTag.color"
:options="colorOptions"
:multiple="false"
:searchable="true"
placeholder="color"
track-by="color"
label="name"
select-label=""
deselect-label=""
>
<template #option="{ option }">
<div class="mx-2 py-1 px-3 rounded d-inline-flex"
style="height: 24px; color: white;"
:style="{ backgroundColor: option.color + ' !important' }"
>
<span>{{ option.name }}</span>
</div>
</template>
<template #singleLabel="{ option }">
<div class="py-1 px-3 rounded d-inline-flex"
style="height: 24px; color: white;"
:style="{ backgroundColor: option.color + ' !important' }"
>
<span>{{ option.name }}</span>
</div>
</template>
</vue-multiselect>
</div> </div>
</div> </div>
<input class="form-control mb-2" placeholder="value (optional)" /> <input v-model="newDraftTag.value" class="form-control mb-2" placeholder="value (optional)" />
<div class="mb-2"> <div class="mb-2">
<button <button
class="btn btn-secondary float-end" class="btn btn-secondary float-end"
:disabled="processing" :class="{ disabled: processing || newDraftTag.invalid }"
> >
{{ $t("Add") }} {{ $t("Add") }}
</button> </button>
@ -66,21 +112,71 @@ export default {
return { return {
processing: false, processing: false,
newTags: [], newTags: [],
newDraftTag: { select: 0 }, removeTags: [],
selectedTags: this.preSelectedTags, newDraftTag: {
name: null,
select: null,
color: null,
value: "",
invalid: false,
nameInvalid: false,
},
}; };
}, },
computed: {
tagOptions() {
return [
...this.tags,
{ name: this.$t("New..."),
id: -1 },
]
},
selectedTags() {
return this.preSelectedTags.concat(this.newTags).filter(tag => !this.removeTags.includes(tag.id));
},
colorOptions() {
return [
{ name: this.$t("Gray"),
color: "#4B5563" },
{ name: this.$t("Red"),
color: "#DC2626" },
{ name: this.$t("Orange"),
color: "#D97706" },
{ name: this.$t("Green"),
color: "#059669" },
{ name: this.$t("Blue"),
color: "#2563EB" },
{ name: this.$t("Indigo"),
color: "#4F46E5" },
{ name: this.$t("Purple"),
color: "#7C3AED" },
{ name: this.$t("Pink"),
color: "#DB2777" },
]
}
},
watch: { watch: {
preSelectedTags(gotTags) { "newDraftTag.name": function (newName) {
if (gotTags.length > 0 && this.selectedTags.length === 0) { this.newDraftTag.name = newName.trim();
this.selectedTags = gotTags; this.validateDraftTag();
}
}, },
}, },
methods: { methods: {
removeTag(id) { removeTag(id) {
console.log(id + " not implemented yet"); console.log(id + " not implemented yet");
}, },
validateDraftTag() {
if (this.tags.filter(tag => tag.name === this.newDraftTag.name).length > 0) {
this.newDraftTag.nameInvalid = true;
this.newDraftTag.invalid = true;
} else if (this.newDraftTag.color == null) {
this.newDraftTag.nameInvalid = false;
this.newDraftTag.invalid = true;
} else {
this.newDraftTag.invalid = false;
this.newDraftTag.nameInvalid = false;
}
},
}, },
}; };
</script> </script>

17
src/pages/EditMonitor.vue

@ -358,6 +358,8 @@ export default {
.multiselect__tags { .multiselect__tags {
border-radius: 1.5rem; border-radius: 1.5rem;
border: 1px solid #ced4da; border: 1px solid #ced4da;
min-height: 38px;
padding: 6px 40px 0 8px;
} }
.multiselect--active .multiselect__tags { .multiselect--active .multiselect__tags {
@ -374,9 +376,24 @@ export default {
.multiselect__tag { .multiselect__tag {
border-radius: 50rem; border-radius: 50rem;
margin-bottom: 0;
padding: 6px 26px 6px 10px;
background: $primary !important; background: $primary !important;
} }
.multiselect__placeholder {
font-size: 1rem;
padding-left: 6px;
padding-top: 0;
padding-bottom: 0;
margin-bottom: 0;
}
.multiselect__input, .multiselect__single {
line-height: 14px;
margin-bottom: 0;
}
.dark { .dark {
.multiselect__tag { .multiselect__tag {
color: $dark-font-color2; color: $dark-font-color2;

Loading…
Cancel
Save