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>
<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>
<script>
@ -27,8 +32,13 @@ export default {
</script>
<style scoped>
.tag-wrapper {
color: white;
}
.btn-remove {
font-size: 0.9em;
line-height: 24px;
opacity: 0.3;
}

140
src/components/TagsManager.vue

@ -1,7 +1,7 @@
<template>
<div>
<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
v-for="item in selectedTags"
:key="item.id"
@ -10,31 +10,77 @@
/>
</div>
<div>
<select
id="snewDraftTagName"
<vue-multiselect
v-model="newDraftTag.select"
class="form-select mb-2"
required
class="mb-2"
:options="tagOptions"
:multiple="false"
:searchable="true"
placeholder="Add..."
track-by="id"
label="name"
>
<option value="0" disabled selected>{{ $t("Add...") }}</option>
<option v-for="tag in tags" :key="tag.id" :value="tag.id">
{{ tag.name }}
</option>
<option value="-1">{{ $t("New...") }}</option>
</select>
<div v-show="newDraftTag.select == -1" class="d-flex mb-2">
<template #option="{ option }">
<div class="mx-2 py-1 px-3 rounded d-inline-flex"
style="margin-top: -5px; margin-bottom: -5px; height: 24px;"
:style="{ color: option.color ? 'white' : 'var(--bs-body-color)', 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;"
: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">
<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 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>
<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">
<button
class="btn btn-secondary float-end"
:disabled="processing"
:class="{ disabled: processing || newDraftTag.invalid }"
>
{{ $t("Add") }}
</button>
@ -66,21 +112,71 @@ export default {
return {
processing: false,
newTags: [],
newDraftTag: { select: 0 },
selectedTags: this.preSelectedTags,
removeTags: [],
newDraftTag: {
name: null,
select: null,
color: null,
value: "",
invalid: false,
nameInvalid: false,
},
};
},
watch: {
preSelectedTags(gotTags) {
if (gotTags.length > 0 && this.selectedTags.length === 0) {
this.selectedTags = gotTags;
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: {
"newDraftTag.name": function (newName) {
this.newDraftTag.name = newName.trim();
this.validateDraftTag();
},
},
methods: {
removeTag(id) {
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>

17
src/pages/EditMonitor.vue

@ -358,6 +358,8 @@ export default {
.multiselect__tags {
border-radius: 1.5rem;
border: 1px solid #ced4da;
min-height: 38px;
padding: 6px 40px 0 8px;
}
.multiselect--active .multiselect__tags {
@ -374,9 +376,24 @@ export default {
.multiselect__tag {
border-radius: 50rem;
margin-bottom: 0;
padding: 6px 26px 6px 10px;
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 {
.multiselect__tag {
color: $dark-font-color2;

Loading…
Cancel
Save