+
{{ $t("Title") }}:
+
-
{{ $t("Content") }}:
-
-
- {{ $t("markdownSupported") }}
-
-
-
+
{{ $t("Content") }}:
+
+
+ {{ $t("markdownSupported") }}
+
+
+
-
-
- {{ $t("Date Created") }}: {{ $root.datetime(incident.createdDate) }} ({{ dateFromNow(incident.createdDate) }})
-
- {{ $t("Last Updated") }}: {{ $root.datetime(incident.lastUpdatedDate) }} ({{ dateFromNow(incident.lastUpdatedDate) }})
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+ {{ $t("Date Created") }}: {{ $root.datetime(incidentItem.createdDate) }} ({{ dateFromNow(incidentItem.createdDate) }})
+
+ {{ $t("Last Updated") }}: {{ $root.datetime(incidentItem.lastUpdatedDate) }} ({{ dateFromNow(incidentItem.lastUpdatedDate) }})
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
@@ -370,18 +372,18 @@ import "prismjs/components/prism-css";
import "prismjs/themes/prism-tomorrow.css"; // import syntax highlighting styles
import ImageCropUpload from "vue-image-crop-upload";
// import Prism Editor
+import DOMPurify from "dompurify";
+import { marked } from "marked";
+import VueMultiselect from "vue-multiselect";
import { PrismEditor } from "vue-prism-editor";
import "vue-prism-editor/dist/prismeditor.min.css"; // import the styles somewhere
import { useToast } from "vue-toastification";
-import { marked } from "marked";
-import DOMPurify from "dompurify";
import Confirm from "../components/Confirm.vue";
-import PublicGroupList from "../components/PublicGroupList.vue";
import MaintenanceTime from "../components/MaintenanceTime.vue";
-import { getResBaseURL } from "../util-frontend";
-import { STATUS_PAGE_ALL_DOWN, STATUS_PAGE_ALL_UP, STATUS_PAGE_MAINTENANCE, STATUS_PAGE_PARTIAL_DOWN, UP, MAINTENANCE } from "../util.ts";
+import PublicGroupList from "../components/PublicGroupList.vue";
import Tag from "../components/Tag.vue";
-import VueMultiselect from "vue-multiselect";
+import { getResBaseURL } from "../util-frontend";
+import { MAINTENANCE, STATUS_PAGE_ALL_DOWN, STATUS_PAGE_ALL_UP, STATUS_PAGE_MAINTENANCE, STATUS_PAGE_PARTIAL_DOWN, UP } from "../util.ts";
const toast = useToast();
dayjs.extend(duration);
@@ -434,10 +436,12 @@ export default {
slug: null,
enableEditMode: false,
enableEditIncidentMode: false,
+ editIncidentIndex: -1,
hasToken: false,
config: {},
selectedMonitor: null,
incident: null,
+ incidentList: [],
previousIncident: null,
showImageCropUpload: false,
imgDataUrl: "/icon.svg",
@@ -508,10 +512,6 @@ export default {
return this.enableEditMode && this.$root.socket.connected;
},
- editIncidentMode() {
- return this.enableEditIncidentMode;
- },
-
isPublished() {
return this.config.published;
},
@@ -525,10 +525,6 @@ export default {
return {};
},
- incidentClass() {
- return "bg-" + this.incident.style;
- },
-
maintenanceClass() {
return "bg-maintenance";
},
@@ -577,14 +573,6 @@ export default {
return this.overallStatus === STATUS_PAGE_MAINTENANCE;
},
- incidentHTML() {
- if (this.incident.content != null) {
- return DOMPurify.sanitize(marked(this.incident.content));
- } else {
- return "";
- }
- },
-
descriptionHTML() {
if (this.config.description != null) {
return DOMPurify.sanitize(marked(this.config.description));
@@ -710,7 +698,7 @@ export default {
this.imgDataUrl = this.config.icon;
}
- this.incident = res.data.incident;
+ this.incidentList = res.data.incidentList;
this.maintenanceList = res.data.maintenanceList;
this.$root.publicGroupList = res.data.publicGroupList;
@@ -952,17 +940,31 @@ export default {
* @returns {void}
*/
createIncident() {
- this.enableEditIncidentMode = true;
+ const incidentListLength = this.incidentList.length - 1;
+ // if not contain id we assume it wasn't save and if cancel it's will lost all contents
+ if (this.incidentList.some(item => !item.id)) {
+ this.$root.toastError("Please input title and content");
+ return;
+ } else {
+ this.enableEditIncidentMode = true;
+ const incident = {
+ title: "",
+ content: "",
+ style: "primary",
+ };
- if (this.incident) {
- this.previousIncident = this.incident;
+ this.incidentList.push(incident);
+ this.incident = incident;
}
- this.incident = {
- title: "",
- content: "",
- style: "primary",
- };
+ this.editIncidentIndex = incidentListLength + 1;
+
+ // scroll previous into view,cause new not created
+ const lastIncidentRef = this.$refs?.[`incident-${incidentListLength}`]?.[0];
+ lastIncidentRef && lastIncidentRef.scrollIntoView({
+ behavior: "smooth",
+ block: "start",
+ });
},
/**
@@ -979,7 +981,7 @@ export default {
if (res.ok) {
this.enableEditIncidentMode = false;
- this.incident = res.incident;
+ this.incidentList[this.editIncidentIndex] = res.incident;
} else {
this.$root.toastError(res.msg);
}
@@ -990,10 +992,13 @@ export default {
/**
* Click Edit Button
+ * @param {number} index index of incedentList
* @returns {void}
*/
- editIncident() {
+ editIncident(index) {
this.enableEditIncidentMode = true;
+ this.incident = this.incidentList[index];
+ this.editIncidentIndex = index;
this.previousIncident = Object.assign({}, this.incident);
},
@@ -1005,18 +1010,28 @@ export default {
this.enableEditIncidentMode = false;
if (this.previousIncident) {
- this.incident = this.previousIncident;
+ this.incidentList[this.editIncidentIndex] = this.previousIncident;
this.previousIncident = null;
}
+
+ // a new incident cancel should remove them
+ if (!this.incident?.id) {
+ this.incidentList.splice(this.editIncidentIndex, 1);
+ }
+ this.incident = null;
+ this.editIncidentIndex = -1;
},
/**
- * Unpin the incident
+ * Unpin the incident with id
+ * @param {number} index of incident
* @returns {void}
*/
- unpinIncident() {
- this.$root.getSocket().emit("unpinIncident", this.slug, () => {
+ unpinIncident(index) {
+ const incident = this.incidentList[index];
+ this.$root.getSocket().emit("unpinIncident", this.slug, incident, () => {
this.incident = null;
+ this.incidentList.splice(index, 1);
});
},
@@ -1051,6 +1066,37 @@ export default {
}
},
+
+ /**
+ * Generate sanitized HTML from maintenance description
+ * @param {number} index Text to sanitize
+ * @returns {string} Sanitized HTML
+ */
+ incidentClass(index) {
+ return "bg-" + this.incidentList[index].style;
+ },
+
+ /**
+ * Generate sanitized HTML from incident description
+ * @param {number} index Text to sanitize
+ * @returns {string} Sanitized HTML
+ */
+ incidentHTML(index) {
+ if (this.incidentList[index].content != null) {
+ return DOMPurify.sanitize(marked(this.incidentList[index].content));
+ } else {
+ return "";
+ }
+ },
+
+ /**
+ * Generate sanitized HTML from incident description
+ * @param {number} index Text to sanitize
+ * @returns {string} Sanitized HTML
+ */
+ editIncidentMode(index) {
+ return this.enableEditIncidentMode && this.editIncidentIndex === index;
+ },
}
};