diff --git a/db/patch10.sql b/db/patch10.sql
new file mode 100644
index 000000000..488db1169
--- /dev/null
+++ b/db/patch10.sql
@@ -0,0 +1,19 @@
+-- You should not modify if this have pushed to Github, unless it does serious wrong with the db.
+CREATE TABLE tag (
+ id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
+ name VARCHAR(255) NOT NULL,
+ color VARCHAR(255) NOT NULL,
+ created_date DATETIME DEFAULT (DATETIME('now')) NOT NULL
+);
+
+CREATE TABLE monitor_tag (
+ id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
+ monitor_id INTEGER NOT NULL,
+ tag_id INTEGER NOT NULL,
+ value TEXT,
+ CONSTRAINT FK_tag FOREIGN KEY (tag_id) REFERENCES tag(id) ON DELETE CASCADE ON UPDATE CASCADE,
+ CONSTRAINT FK_monitor FOREIGN KEY (monitor_id) REFERENCES monitor(id) ON DELETE CASCADE ON UPDATE CASCADE
+);
+
+CREATE INDEX monitor_tag_monitor_id_index ON monitor_tag (monitor_id);
+CREATE INDEX monitor_tag_tag_id_index ON monitor_tag (tag_id);
diff --git a/server/database.js b/server/database.js
index 4b3ad443e..7af75423a 100644
--- a/server/database.js
+++ b/server/database.js
@@ -37,7 +37,7 @@ class Database {
* The finally version should be 10 after merged tag feature
* @deprecated Use patchList for any new feature
*/
- static latestVersion = 9;
+ static latestVersion = 10;
static noReject = true;
diff --git a/server/model/monitor.js b/server/model/monitor.js
index 89208a3fd..6c4e17eeb 100644
--- a/server/model/monitor.js
+++ b/server/model/monitor.js
@@ -32,6 +32,8 @@ class Monitor extends BeanModel {
notificationIDList[bean.notification_id] = true;
}
+ const tags = await R.getAll("SELECT mt.*, tag.name, tag.color FROM monitor_tag mt JOIN tag ON mt.tag_id = tag.id WHERE mt.monitor_id = ?", [this.id]);
+
return {
id: this.id,
name: this.name,
@@ -52,6 +54,7 @@ class Monitor extends BeanModel {
dns_resolve_server: this.dns_resolve_server,
dns_last_result: this.dns_last_result,
notificationIDList,
+ tags: tags,
};
}
diff --git a/server/model/tag.js b/server/model/tag.js
new file mode 100644
index 000000000..748280a70
--- /dev/null
+++ b/server/model/tag.js
@@ -0,0 +1,13 @@
+const { BeanModel } = require("redbean-node/dist/bean-model");
+
+class Tag extends BeanModel {
+ toJSON() {
+ return {
+ id: this._id,
+ name: this._name,
+ color: this._color,
+ };
+ }
+}
+
+module.exports = Tag;
diff --git a/server/server.js b/server/server.js
index a0b9a2fbb..003d25ae6 100644
--- a/server/server.js
+++ b/server/server.js
@@ -514,6 +514,22 @@ let indexHTML = fs.readFileSync("./dist/index.html").toString();
}
});
+ socket.on("getMonitorList", async (callback) => {
+ try {
+ checkLogin(socket)
+ await sendMonitorList(socket);
+ callback({
+ ok: true,
+ });
+ } catch (e) {
+ console.error(e)
+ callback({
+ ok: false,
+ msg: e.message,
+ });
+ }
+ });
+
socket.on("getMonitor", async (monitorID, callback) => {
try {
checkLogin(socket)
@@ -608,6 +624,159 @@ let indexHTML = fs.readFileSync("./dist/index.html").toString();
}
});
+ socket.on("getTags", async (callback) => {
+ try {
+ checkLogin(socket)
+
+ const list = await R.findAll("tag")
+
+ callback({
+ ok: true,
+ tags: list.map(bean => bean.toJSON()),
+ });
+
+ } catch (e) {
+ callback({
+ ok: false,
+ msg: e.message,
+ });
+ }
+ });
+
+ socket.on("addTag", async (tag, callback) => {
+ try {
+ checkLogin(socket)
+
+ let bean = R.dispense("tag")
+ bean.name = tag.name
+ bean.color = tag.color
+ await R.store(bean)
+
+ callback({
+ ok: true,
+ tag: await bean.toJSON(),
+ });
+
+ } catch (e) {
+ callback({
+ ok: false,
+ msg: e.message,
+ });
+ }
+ });
+
+ socket.on("editTag", async (tag, callback) => {
+ try {
+ checkLogin(socket)
+
+ let bean = await R.findOne("monitor", " id = ? ", [ tag.id ])
+ bean.name = tag.name
+ bean.color = tag.color
+ await R.store(bean)
+
+ callback({
+ ok: true,
+ tag: await bean.toJSON(),
+ });
+
+ } catch (e) {
+ callback({
+ ok: false,
+ msg: e.message,
+ });
+ }
+ });
+
+ socket.on("deleteTag", async (tagID, callback) => {
+ try {
+ checkLogin(socket)
+
+ await R.exec("DELETE FROM tag WHERE id = ? ", [ tagID ])
+
+ callback({
+ ok: true,
+ msg: "Deleted Successfully.",
+ });
+
+ } catch (e) {
+ callback({
+ ok: false,
+ msg: e.message,
+ });
+ }
+ });
+
+ socket.on("addMonitorTag", async (tagID, monitorID, value, callback) => {
+ try {
+ checkLogin(socket)
+
+ await R.exec("INSERT INTO monitor_tag (tag_id, monitor_id, value) VALUES (?, ?, ?)", [
+ tagID,
+ monitorID,
+ value,
+ ])
+
+ callback({
+ ok: true,
+ msg: "Added Successfully.",
+ });
+
+ } catch (e) {
+ callback({
+ ok: false,
+ msg: e.message,
+ });
+ }
+ });
+
+ socket.on("editMonitorTag", async (tagID, monitorID, value, callback) => {
+ try {
+ checkLogin(socket)
+
+ await R.exec("UPDATE monitor_tag SET value = ? WHERE tag_id = ? AND monitor_id = ?", [
+ value,
+ tagID,
+ monitorID,
+ ])
+
+ callback({
+ ok: true,
+ msg: "Edited Successfully.",
+ });
+
+ } catch (e) {
+ callback({
+ ok: false,
+ msg: e.message,
+ });
+ }
+ });
+
+ socket.on("deleteMonitorTag", async (tagID, monitorID, callback) => {
+ try {
+ checkLogin(socket)
+
+ await R.exec("DELETE FROM monitor_tag WHERE tag_id = ? AND monitor_id = ?", [
+ tagID,
+ monitorID,
+ ])
+
+ // Cleanup unused Tags
+ await R.exec("delete from tag where ( select count(*) from monitor_tag mt where tag.id = mt.tag_id ) = 0");
+
+ callback({
+ ok: true,
+ msg: "Deleted Successfully.",
+ });
+
+ } catch (e) {
+ callback({
+ ok: false,
+ msg: e.message,
+ });
+ }
+ });
+
socket.on("changePassword", async (password, callback) => {
try {
checkLogin(socket)
diff --git a/src/components/MonitorList.vue b/src/components/MonitorList.vue
index e72155891..77097dc12 100644
--- a/src/components/MonitorList.vue
+++ b/src/components/MonitorList.vue
@@ -11,6 +11,9 @@
{{ monitor.url }} TCP Ping {{ monitor.hostname }}:{{ monitor.port }} @@ -213,6 +216,7 @@ import CountUp from "../components/CountUp.vue"; import Uptime from "../components/Uptime.vue"; import Pagination from "v-pagination-3"; const PingChart = defineAsyncComponent(() => import("../components/PingChart.vue")); +import Tag from "../components/Tag.vue"; export default { components: { @@ -224,6 +228,7 @@ export default { Status, Pagination, PingChart, + Tag, }, data() { return { @@ -503,4 +508,12 @@ table { } } +.tags { + margin-bottom: 0.5rem; +} + +.tags > div:first-child { + margin-left: 0 !important; +} + diff --git a/src/pages/EditMonitor.vue b/src/pages/EditMonitor.vue index f98bb7560..d87bb4dd4 100644 --- a/src/pages/EditMonitor.vue +++ b/src/pages/EditMonitor.vue @@ -158,6 +158,10 @@