Merge pull request #2489 from mathiash98/mathiash98/clone-monitor

Feature: Clone existing monitor
This commit is contained in:
Louis Lam 2023-02-25 17:10:56 +08:00 committed by GitHub
commit 487eae71c7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 67 additions and 6 deletions

View File

@ -18,9 +18,15 @@
</template> </template>
<script> <script>
/**
* @typedef {import('./TagsManager.vue').Tag} Tag
*/
export default { export default {
props: { props: {
/** Object representing tag */ /** Object representing tag
* @type {Tag}
*/
item: { item: {
type: Object, type: Object,
required: true, required: true,
@ -32,7 +38,7 @@ export default {
}, },
/** /**
* Size of tag * Size of tag
* @values normal, small * @type {"normal" | "small"}
*/ */
size: { size: {
type: String, type: String,

View File

@ -134,13 +134,27 @@ import { colorOptions } from "../util-frontend";
import Tag from "../components/Tag.vue"; import Tag from "../components/Tag.vue";
const toast = useToast(); const toast = useToast();
/**
* @typedef Tag
* @type {object}
* @property {number | undefined} id
* @property {number | undefined} monitor_id
* @property {number | undefined} tag_id
* @property {string} value
* @property {string} name
* @property {string} color
* @property {boolean | undefined} new
*/
export default { export default {
components: { components: {
Tag, Tag,
VueMultiselect, VueMultiselect,
}, },
props: { props: {
/** Array of tags to be pre-selected */ /** Array of tags to be pre-selected
* @type {Tag[]}
*/
preSelectedTags: { preSelectedTags: {
type: Array, type: Array,
default: () => [], default: () => [],
@ -148,10 +162,14 @@ export default {
}, },
data() { data() {
return { return {
/** @type {Modal | null} */
modal: null, modal: null,
/** @type {Tag[]} */
existingTags: [], existingTags: [],
processing: false, processing: false,
/** @type {Tag[]} */
newTags: [], newTags: [],
/** @type {Tag[]} */
deleteTags: [], deleteTags: [],
newDraftTag: { newDraftTag: {
name: null, name: null,

View File

@ -3,6 +3,9 @@ import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
// Add Free Font Awesome Icons // Add Free Font Awesome Icons
// https://fontawesome.com/v5.15/icons?d=gallery&p=2&s=solid&m=free // https://fontawesome.com/v5.15/icons?d=gallery&p=2&s=solid&m=free
// In order to add an icon, you have to:
// 1) add the icon name in the import statement below;
// 2) add the icon name to the library.add() statement below.
import { import {
faArrowAltCircleUp, faArrowAltCircleUp,
faCog, faCog,
@ -45,6 +48,7 @@ import {
faHeartbeat, faHeartbeat,
faFilter, faFilter,
faInfoCircle, faInfoCircle,
faClone,
} from "@fortawesome/free-solid-svg-icons"; } from "@fortawesome/free-solid-svg-icons";
library.add( library.add(
@ -90,6 +94,7 @@ library.add(
faHeartbeat, faHeartbeat,
faFilter, faFilter,
faInfoCircle, faInfoCircle,
faClone,
); );
export { FontAwesomeIcon }; export { FontAwesomeIcon };

View File

@ -439,6 +439,9 @@
"uninstalling": "Uninstalling", "uninstalling": "Uninstalling",
"confirmUninstallPlugin": "Are you sure want to uninstall this plugin?", "confirmUninstallPlugin": "Are you sure want to uninstall this plugin?",
"notificationRegional": "Regional", "notificationRegional": "Regional",
"Clone Monitor": "Clone Monitor",
"Clone": "Clone",
"cloneOf": "Clone of {0}",
"smtp": "Email (SMTP)", "smtp": "Email (SMTP)",
"secureOptionNone": "None / STARTTLS (25, 587)", "secureOptionNone": "None / STARTTLS (25, 587)",
"secureOptionTLS": "TLS (465)", "secureOptionTLS": "TLS (465)",

View File

@ -30,6 +30,9 @@
<router-link :to=" '/edit/' + monitor.id " class="btn btn-normal"> <router-link :to=" '/edit/' + monitor.id " class="btn btn-normal">
<font-awesome-icon icon="edit" /> {{ $t("Edit") }} <font-awesome-icon icon="edit" /> {{ $t("Edit") }}
</router-link> </router-link>
<router-link :to=" '/clone/' + monitor.id " class="btn btn-normal">
<font-awesome-icon icon="clone" /> {{ $t("Clone") }}
</router-link>
<button class="btn btn-danger" @click="deleteDialog"> <button class="btn btn-danger" @click="deleteDialog">
<font-awesome-icon icon="trash" /> {{ $t("Delete") }} <font-awesome-icon icon="trash" /> {{ $t("Delete") }}
</button> </button>

View File

@ -682,13 +682,23 @@ export default {
}, },
pageName() { pageName() {
return this.$t((this.isAdd) ? "Add New Monitor" : "Edit"); let name = "Add New Monitor";
if (this.isClone) {
name = "Clone Monitor";
} else if (this.isEdit) {
name = "Edit";
}
return this.$t(name);
}, },
isAdd() { isAdd() {
return this.$route.path === "/add"; return this.$route.path === "/add";
}, },
isClone() {
return this.$route.path.startsWith("/clone");
},
isEdit() { isEdit() {
return this.$route.path.startsWith("/edit"); return this.$route.path.startsWith("/edit");
}, },
@ -906,11 +916,23 @@ message HealthCheckResponse {
this.monitor.notificationIDList[this.$root.notificationList[i].id] = true; this.monitor.notificationIDList[this.$root.notificationList[i].id] = true;
} }
} }
} else if (this.isEdit) { } else if (this.isEdit || this.isClone) {
this.$root.getSocket().emit("getMonitor", this.$route.params.id, (res) => { this.$root.getSocket().emit("getMonitor", this.$route.params.id, (res) => {
if (res.ok) { if (res.ok) {
this.monitor = res.monitor; this.monitor = res.monitor;
if (this.isClone) {
/*
* Cloning a monitor will include properties that can not be posted to backend
* as they are not valid columns in the SQLite table.
*/
this.monitor.id = undefined; // Remove id when cloning as we want a new id
this.monitor.includeSensitiveData = undefined;
this.monitor.maintenance = undefined;
this.monitor.name = this.$t("cloneOf", [ this.monitor.name ]);
this.monitor.tags = undefined; // FIXME: Cloning tags does not work yet
}
// Handling for monitors that are created before 1.7.0 // Handling for monitors that are created before 1.7.0
if (this.monitor.retryInterval === 0) { if (this.monitor.retryInterval === 0) {
this.monitor.retryInterval = this.monitor.interval; this.monitor.retryInterval = this.monitor.interval;
@ -981,7 +1003,7 @@ message HealthCheckResponse {
this.monitor.url = this.monitor.url.trim(); this.monitor.url = this.monitor.url.trim();
} }
if (this.isAdd) { if (this.isAdd || this.isClone) {
this.$root.add(this.monitor, async (res) => { this.$root.add(this.monitor, async (res) => {
if (res.ok) { if (res.ok) {

View File

@ -67,6 +67,10 @@ const routes = [
}, },
], ],
}, },
{
path: "/clone/:id",
component: EditMonitor,
},
{ {
path: "/add", path: "/add",
component: EditMonitor, component: EditMonitor,