diff --git a/server/server.js b/server/server.js index 5473cecd4..f43008e27 100644 --- a/server/server.js +++ b/server/server.js @@ -941,13 +941,21 @@ let needSetup = false; try { checkLogin(socket); - let bean = await R.findOne("monitor", " id = ? ", [ tag.id ]); + let bean = await R.findOne("tag", " id = ? ", [ tag.id ]); + if (bean == null) { + callback({ + ok: false, + msg: "Tag not found", + }); + return; + } bean.name = tag.name; bean.color = tag.color; await R.store(bean); callback({ ok: true, + msg: "Saved", tag: await bean.toJSON(), }); diff --git a/src/assets/localization.scss b/src/assets/localization.scss index f9a28d8a4..97be37785 100644 --- a/src/assets/localization.scss +++ b/src/assets/localization.scss @@ -2,4 +2,8 @@ html[lang='fa'] { #app { font-family: 'IRANSans', 'Iranian Sans','B Nazanin', 'Tahoma', ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, segoe ui, Roboto, helvetica neue, Arial, noto sans, sans-serif, apple color emoji, segoe ui emoji, segoe ui symbol, noto color emoji; } -} \ No newline at end of file +} + +ul.multiselect__content { + padding-left: 0 !important; +} diff --git a/src/components/Tag.vue b/src/components/Tag.vue index 0325d9900..cbbe0b796 100644 --- a/src/components/Tag.vue +++ b/src/components/Tag.vue @@ -41,7 +41,7 @@ export default { }, computed: { displayText() { - if (this.item.value === "") { + if (this.item.value === "" || this.item.value === undefined) { return this.item.name; } else { return `${this.item.name}: ${this.item.value}`; diff --git a/src/components/TagEditDialog.vue b/src/components/TagEditDialog.vue new file mode 100644 index 000000000..182efcbf3 --- /dev/null +++ b/src/components/TagEditDialog.vue @@ -0,0 +1,377 @@ + + + + + diff --git a/src/components/TagsManager.vue b/src/components/TagsManager.vue index 8481fdfeb..b302cd20f 100644 --- a/src/components/TagsManager.vue +++ b/src/components/TagsManager.vue @@ -130,6 +130,7 @@ import { Modal } from "bootstrap"; import VueMultiselect from "vue-multiselect"; import { useToast } from "vue-toastification"; +import { colorOptions } from "../util-frontend"; import Tag from "../components/Tag.vue"; const toast = useToast(); @@ -176,24 +177,7 @@ export default { return this.preSelectedTags.concat(this.newTags).filter(tag => !this.deleteTags.find(monitorTag => monitorTag.id === 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" }, - ]; + return colorOptions(this); }, validateDraftTag() { let nameInvalid = false; diff --git a/src/components/settings/Tags.vue b/src/components/settings/Tags.vue new file mode 100644 index 000000000..347a6ef29 --- /dev/null +++ b/src/components/settings/Tags.vue @@ -0,0 +1,171 @@ + + + + + diff --git a/src/languages/en.js b/src/languages/en.js index 7a48d0d0c..d35883218 100644 --- a/src/languages/en.js +++ b/src/languages/en.js @@ -74,6 +74,7 @@ export default { Current: "Current", Uptime: "Uptime", "Cert Exp.": "Cert Exp.", + Monitor: "Monitor | Monitors", day: "day | days", "-day": "-day", hour: "hour", @@ -190,6 +191,7 @@ export default { Indigo: "Indigo", Purple: "Purple", Pink: "Pink", + Custom: "Custom", "Search...": "Search...", "Avg. Ping": "Avg. Ping", "Avg. Response": "Avg. Response", @@ -677,4 +679,5 @@ export default { "Specific Monitor Type": "Specific Monitor Type", dataRetentionTimeError: "Retention period must be 0 or greater", infiniteRetention: "Set to 0 for infinite retention.", + confirmDeleteTagMsg: "Are you sure you want to delete this tag? Monitors associated with this tag will not be deleted.", }; diff --git a/src/pages/Settings.vue b/src/pages/Settings.vue index f2dd3475c..f5d32e0eb 100644 --- a/src/pages/Settings.vue +++ b/src/pages/Settings.vue @@ -95,6 +95,9 @@ export default { "reverse-proxy": { title: this.$t("Reverse Proxy"), }, + tags: { + title: this.$t("Tags"), + }, "monitor-history": { title: this.$t("Monitor History"), }, diff --git a/src/router.js b/src/router.js index 380488264..b5b46c307 100644 --- a/src/router.js +++ b/src/router.js @@ -24,6 +24,7 @@ import Appearance from "./components/settings/Appearance.vue"; import General from "./components/settings/General.vue"; const Notifications = () => import("./components/settings/Notifications.vue"); import ReverseProxy from "./components/settings/ReverseProxy.vue"; +import Tags from "./components/settings/Tags.vue"; import MonitorHistory from "./components/settings/MonitorHistory.vue"; const Security = () => import("./components/settings/Security.vue"); import Proxies from "./components/settings/Proxies.vue"; @@ -95,6 +96,10 @@ const routes = [ path: "reverse-proxy", component: ReverseProxy, }, + { + path: "tags", + component: Tags, + }, { path: "monitor-history", component: MonitorHistory, diff --git a/src/util-frontend.js b/src/util-frontend.js index 3323f3279..3ff751fff 100644 --- a/src/util-frontend.js +++ b/src/util-frontend.js @@ -78,3 +78,29 @@ export function getResBaseURL() { return ""; } } + +/** + * Get the tag color options + * Shared between components + * @returns {Object[]} + */ +export function colorOptions(self) { + return [ + { name: self.$t("Gray"), + color: "#4B5563" }, + { name: self.$t("Red"), + color: "#DC2626" }, + { name: self.$t("Orange"), + color: "#D97706" }, + { name: self.$t("Green"), + color: "#059669" }, + { name: self.$t("Blue"), + color: "#2563EB" }, + { name: self.$t("Indigo"), + color: "#4F46E5" }, + { name: self.$t("Purple"), + color: "#7C3AED" }, + { name: self.$t("Pink"), + color: "#DB2777" }, + ]; +}