Browse Source

WIP: Improve styling & validation, use translation

remotes/philippdormann/main
Nelson Chan 4 years ago
parent
commit
8dd61bf55e
  1. 6
      src/components/Tag.vue
  2. 81
      src/components/TagsManager.vue
  3. 1
      src/pages/EditMonitor.vue

6
src/components/Tag.vue

@ -1,7 +1,7 @@
<template> <template>
<div class="tag-wrapper m-2 py-1 px-3 rounded d-inline-flex" :style="{ backgroundColor: item.color }"> <div class="tag-wrapper m-2 py-1 px-3 rounded d-inline-flex" :style="{ backgroundColor: item.color }">
{{ displayText }} {{ displayText }}
<span class="ps-1 btn-remove" @click="remove(item.id)"> <span class="ps-1 btn-remove" @click="remove(item)">
<font-awesome-icon icon="times" /> <font-awesome-icon icon="times" />
</span> </span>
</div> </div>
@ -21,8 +21,8 @@ export default {
}, },
computed: { computed: {
displayText() { displayText() {
if (this.value == "") { if (this.item.value == "") {
return this.name; return this.item.name;
} else { } else {
return `${this.item.name}: ${this.item.value}`; return `${this.item.name}: ${this.item.value}`;
} }

81
src/components/TagsManager.vue

@ -16,14 +16,14 @@
:options="tagOptions" :options="tagOptions"
:multiple="false" :multiple="false"
:searchable="true" :searchable="true"
placeholder="Add..." :placeholder="$t('Add New below or Select...')"
track-by="id" track-by="id"
label="name" label="name"
> >
<template #option="{ option }"> <template #option="{ option }">
<div class="mx-2 py-1 px-3 rounded d-inline-flex" <div class="mx-2 py-1 px-3 rounded d-inline-flex"
style="margin-top: -5px; margin-bottom: -5px; height: 24px;" style="margin-top: -5px; margin-bottom: -5px; height: 24px;"
:style="{ color: option.color ? 'white' : 'var(--bs-body-color)', backgroundColor: option.color + ' !important' }" :style="{ color: textColor(option), backgroundColor: option.color + ' !important' }"
> >
<span> <span>
{{ option.name }}</span> {{ option.name }}</span>
@ -32,17 +32,17 @@
<template #singleLabel="{ option }"> <template #singleLabel="{ option }">
<div class="py-1 px-3 rounded d-inline-flex" <div class="py-1 px-3 rounded d-inline-flex"
style="height: 24px;" style="height: 24px;"
:style="{ color: option.color ? 'white' : 'var(--bs-body-color)', backgroundColor: option.color + ' !important' }" :style="{ color: textColor(option), backgroundColor: option.color + ' !important' }"
> >
<span>{{ option.name }}</span> <span>{{ option.name }}</span>
</div> </div>
</template> </template>
</vue-multiselect> </vue-multiselect>
<div v-if="newDraftTag.select?.id == -1" class="d-flex mb-2"> <div v-if="newDraftTag.select?.id == null" class="d-flex mb-2">
<div class="w-50 pe-2"> <div class="w-50 pe-2">
<input v-model="newDraftTag.name" class="form-control" :class="{'is-invalid': newDraftTag.nameInvalid}" placeholder="name" /> <input v-model="newDraftTag.name" class="form-control" :class="{'is-invalid': newDraftTag.nameInvalid}" placeholder="name" />
<div class="invalid-feedback"> <div class="invalid-feedback">
Tag with this name already exist. {{ $t("Tag with this name already exist.") }}
</div> </div>
</div> </div>
<div class="w-50 ps-2"> <div class="w-50 ps-2">
@ -51,7 +51,7 @@
:options="colorOptions" :options="colorOptions"
:multiple="false" :multiple="false"
:searchable="true" :searchable="true"
placeholder="color" :placeholder="$t('color')"
track-by="color" track-by="color"
label="name" label="name"
select-label="" select-label=""
@ -76,11 +76,12 @@
</vue-multiselect> </vue-multiselect>
</div> </div>
</div> </div>
<input v-model="newDraftTag.value" class="form-control mb-2" placeholder="value (optional)" /> <input v-model="newDraftTag.value" class="form-control mb-2" :placeholder="$t('value (optional)')" />
<div class="mb-2"> <div class="mb-2">
<button <button
class="btn btn-secondary float-end" class="btn btn-secondary float-end"
:class="{ disabled: processing || newDraftTag.invalid }" :disabled="processing || newDraftTag.invalid"
@click="addDraftTag"
> >
{{ $t("Add") }} {{ $t("Add") }}
</button> </button>
@ -118,18 +119,14 @@ export default {
select: null, select: null,
color: null, color: null,
value: "", value: "",
invalid: false, invalid: true,
nameInvalid: false, nameInvalid: false,
}, },
}; };
}, },
computed: { computed: {
tagOptions() { tagOptions() {
return [ return this.tags;
...this.tags,
{ name: this.$t("New..."),
id: -1 },
]
}, },
selectedTags() { selectedTags() {
return this.preSelectedTags.concat(this.newTags).filter(tag => !this.removeTags.includes(tag.id)); return this.preSelectedTags.concat(this.newTags).filter(tag => !this.removeTags.includes(tag.id));
@ -156,27 +153,75 @@ export default {
} }
}, },
watch: { watch: {
"newDraftTag.select": function (newSelected) {
this.newDraftTag.select = newSelected;
this.validateDraftTag();
},
"newDraftTag.name": function (newName) { "newDraftTag.name": function (newName) {
this.newDraftTag.name = newName.trim(); this.newDraftTag.name = newName.trim();
this.validateDraftTag(); this.validateDraftTag();
}, },
"newDraftTag.color": function (newColor) {
this.newDraftTag.color = newColor;
this.validateDraftTag();
},
}, },
methods: { methods: {
removeTag(id) { removeTag(item) {
console.log(id + " not implemented yet"); if (item.new) {
// Undo Adding a new Tag
this.newTags = this.newTags.filter(tag => tag.name != item.name && tag.value != item.value);
} else {
// Remove an Existing Tag
this.removeTags.push(item);
}
}, },
validateDraftTag() { validateDraftTag() {
if (this.tags.filter(tag => tag.name === this.newDraftTag.name).length > 0) { if (this.newDraftTag.select != null) {
// Select an existing tag, no need to validate
this.newDraftTag.invalid = false;
} else if (this.tags.filter(tag => tag.name === this.newDraftTag.name).length > 0) {
// Try to create new tag with existing name
this.newDraftTag.nameInvalid = true; this.newDraftTag.nameInvalid = true;
this.newDraftTag.invalid = true; this.newDraftTag.invalid = true;
} else if (this.newDraftTag.color == null) { } else if (this.newDraftTag.color == null || this.newDraftTag.name === "") {
// Missing form inputs
this.newDraftTag.nameInvalid = false; this.newDraftTag.nameInvalid = false;
this.newDraftTag.invalid = true; this.newDraftTag.invalid = true;
} else { } else {
// Looks valid
this.newDraftTag.invalid = false; this.newDraftTag.invalid = false;
this.newDraftTag.nameInvalid = false; this.newDraftTag.nameInvalid = false;
} }
}, },
textColor(option) {
if (option.color) {
return "white";
} else {
return this.$root.theme === "light" ? "var(--bs-body-color)" : "inherit";
}
},
addDraftTag() {
console.log("Adding Draft Tag: ", this.newDraftTag);
if (this.newDraftTag.select != null) {
// Add an existing Tag
this.newTags.push({
id: this.newDraftTag.select.id,
color: this.newDraftTag.select.color,
name: this.newDraftTag.select.name,
value: this.newDraftTag.value,
new: true,
})
} else {
// Add new Tag
this.newTags.push({
color: this.newDraftTag.color.color,
name: this.newDraftTag.name,
value: this.newDraftTag.value,
new: true,
})
}
}
}, },
}; };
</script> </script>

1
src/pages/EditMonitor.vue

@ -387,6 +387,7 @@ export default {
padding-top: 0; padding-top: 0;
padding-bottom: 0; padding-bottom: 0;
margin-bottom: 0; margin-bottom: 0;
opacity: 0.67;
} }
.multiselect__input, .multiselect__single { .multiselect__input, .multiselect__single {

Loading…
Cancel
Save