added script cloning functionality

This commit is contained in:
sadnub
2021-07-09 18:47:28 -04:00
parent 00ec2085f7
commit cdc4bbfda1
3 changed files with 183 additions and 178 deletions

View File

@@ -20,7 +20,7 @@
<q-item-label>New Script</q-item-label>
</q-item-section>
</q-item>
<q-item clickable v-close-popup @click="showScriptUploadModal = true">
<q-item clickable v-close-popup @click="uploadScript">
<q-item-section side>
<q-icon size="xs" name="cloud_upload" />
</q-item-section>
@@ -30,30 +30,6 @@
</q-item>
</q-list>
</q-btn-dropdown>
<q-btn
label="View Code"
:disable="!isRowSelected"
dense
flat
push
unelevated
no-caps
icon="remove_red_eye"
@click="viewCode(selectedScript)"
/>
<q-btn
label="Download Script"
:disable="!isRowSelected"
dense
flat
push
unelevated
no-caps
icon="cloud_download"
@click="downloadScript(selectedScript)"
/>
</div>
<div class="row">
<q-btn
dense
flat
@@ -95,13 +71,11 @@
no-connectors
node-key="id"
v-model:expanded="expanded"
@update:selected="nodeSelected"
v-model:selected="selected"
no-results-label="No Scripts Found"
no-nodes-label="No Scripts Found"
>
<template v-slot:header-script="props">
<div :class="props.node.id === props.tree.selected ? 'text-primary' : ''">
<div>
<q-icon v-if="props.node.favorite" color="yellow-8" name="star" size="sm" class="q-px-sm" />
<q-icon v-else color="yellow-8" name="star_outline" size="sm" class="q-px-sm" />
@@ -119,9 +93,16 @@
<span class="q-pl-xs">{{ props.node.description }}</span>
</div>
<!-- Context Menu -->
<!-- context menu -->
<q-menu context-menu>
<q-list dense style="min-width: 200px">
<q-item clickable v-close-popup @click="cloneScript(props.node)">
<q-item-section side>
<q-icon name="content_copy" />
</q-item-section>
<q-item-section>Clone</q-item-section>
</q-item>
<q-item
clickable
v-close-popup
@@ -207,14 +188,17 @@
<template v-slot:no-data> No Scripts Found </template>
<template v-slot:body="props">
<!-- Table View -->
<q-tr
:class="`${rowSelectedClass(props.row.id)} cursor-pointer`"
@click="selectedScript = props.row"
@contextmenu="selectedScript = props.row"
>
<q-tr>
<!-- Context Menu -->
<q-menu context-menu>
<q-list dense style="min-width: 200px">
<q-item clickable v-close-popup @click="cloneScript(props.node)">
<q-item-section side>
<q-icon name="content_copy" />
</q-item-section>
<q-item-section>Clone</q-item-section>
</q-item>
<q-item
clickable
v-close-popup
@@ -314,14 +298,6 @@
</div>
</div>
</q-card>
<q-dialog v-model="showScriptUploadModal">
<ScriptUploadModal
:script="selectedScript"
:categories="categories"
@close="showScriptUploadModal = false"
@add="getScripts"
/>
</q-dialog>
</div>
</template>
@@ -333,17 +309,13 @@ import ScriptFormModal from "@/components/modals/scripts/ScriptFormModal";
export default {
name: "ScriptManager",
components: { ScriptUploadModal },
mixins: [mixins],
data() {
return {
scripts: [],
selectedScript: {},
showScriptUploadModal: false,
search: "",
tableView: true,
expanded: [],
selected: null,
pagination: {
rowsPerPage: 0,
sortBy: "favorite",
@@ -405,7 +377,6 @@ export default {
},
methods: {
getScripts() {
this.clearRow();
this.$axios
.get("/scripts/scripts/")
.then(r => {
@@ -416,9 +387,6 @@ export default {
setShowCommunityScripts(show) {
this.$store.dispatch("setShowCommunityScripts", show);
},
clearRow() {
this.selectedScript = {};
},
viewCode(script) {
this.$q.dialog({
component: ScriptFormModal,
@@ -478,9 +446,6 @@ export default {
return false;
}
},
rowSelectedClass(id) {
if (this.selectedScript.id === id) return this.$q.dark.isActive ? "highlight-dark" : "highlight";
},
favoriteText(isFavorite) {
return isFavorite ? "Remove as Favorite" : "Add as Favorite";
},
@@ -513,16 +478,34 @@ export default {
},
setTableView(view) {
this.tableView = view;
this.selectedScript = {};
this.selected = null;
this.expanded = [];
},
nodeSelected(nodeid) {
if (nodeid) {
this.selectedScript = this.$refs.folderTree.getNodeByKey(nodeid);
} else {
this.selectedScript = {};
}
cloneScript(script) {
this.$q
.dialog({
component: ScriptFormModal,
componentProps: {
script: script,
categories: this.categories,
readonly: false,
clone: true,
},
})
.onOk(() => {
this.getScripts();
});
},
uploadScript() {
this.$q
.dialog({
component: ScriptUploadModal,
componentProps: {
categories: this.categories,
},
})
.onOk(() => {
this.getScripts();
});
},
},
computed: {
@@ -539,9 +522,6 @@ export default {
});
return list;
},
isRowSelected() {
return this.selectedScript.id !== null && this.selectedScript.id !== undefined;
},
tree() {
if (this.tableView || this.visibleScripts.length === 0) {
return [];

View File

@@ -136,7 +136,14 @@ export default {
props: {
script: Object,
categories: !Array,
readonly: Boolean,
readonly: {
type: Boolean,
default: false,
},
clone: {
type: Boolean,
default: false,
},
},
data() {
return {
@@ -164,7 +171,7 @@ export default {
submit() {
this.$q.loading.show();
if (!!this.script) {
if (this.script && !this.clone) {
this.$axios
.put(`/scripts/${this.script.id}/script/`, this.localScript)
.then(r => {
@@ -247,8 +254,12 @@ export default {
return this.localScript.favorite ? "star" : "star_outline";
},
title() {
if (!!this.script) {
return this.readonly ? `Viewing ${this.script.name}` : `Editing ${this.script.name}`;
if (this.script) {
return this.readonly
? `Viewing ${this.script.name}`
: this.clone
? `Copying ${this.script.name}`
: `Editing ${this.script.name}`;
} else {
return "Adding new script";
}
@@ -264,14 +275,14 @@ export default {
},
},
mounted() {
if (!!this.script) {
this.localScript.id = this.script.id;
this.localScript.name = this.script.name;
if (this.script) {
this.localScript.id = this.clone ? null : this.script.id;
this.localScript.name = this.clone ? "Copy of " + this.script.name : this.script.name;
this.localScript.description = this.script.description;
this.localScript.favorite = this.script.favorite;
this.localScript.favorite = this.clone ? false : this.script.favorite;
this.localScript.shell = this.script.shell;
this.localScript.category = this.script.category;
this.localScript.script_type = this.script.script_type;
this.localScript.script_type = this.clone ? "userdefined" : this.script.script_type;
this.localScript.default_timeout = this.script.default_timeout;
this.localScript.args = this.script.args;
this.getCode();

View File

@@ -1,107 +1,109 @@
<template>
<q-card style="width: 40vw">
<q-bar>
Add Script
<q-space />
<q-btn dense flat icon="close" v-close-popup>
<q-tooltip class="bg-white text-primary">Close</q-tooltip>
</q-btn>
</q-bar>
<q-form @submit.prevent="submit">
<q-card-section class="row">
<div class="col-2">Name:</div>
<div class="col-10">
<q-input outlined dense v-model="script.name" :rules="[val => !!val || '*Required']" />
</div>
</q-card-section>
<q-card-section class="row">
<div class="col-2">Description:</div>
<div class="col-10">
<q-input outlined dense v-model="script.description" type="textarea" />
</div>
</q-card-section>
<q-card-section class="row">
<div class="col-2">Category:</div>
<q-select
hint="Press Enter or Tab when adding a new value"
dense
options-dense
class="col-10"
outlined
v-model="script.category"
:options="filterOptions"
use-input
clearable
new-value-mode="add-unique"
debounce="0"
@filter="filterFn"
/>
</q-card-section>
<q-card-section class="row">
<div class="col-2">File Upload:</div>
<div class="col-10">
<q-file
v-model="script.filename"
label="Supported file types: .ps1, .bat, .py"
stack-label
filled
counter
class="full-width"
accept=".ps1, .bat, .py"
>
<template v-slot:prepend>
<q-icon name="attach_file" />
</template>
</q-file>
</div>
</q-card-section>
<q-card-section class="row">
<div class="col-2">Type:</div>
<q-select
dense
options-dense
class="col-10"
outlined
v-model="script.shell"
:options="shellOptions"
emit-value
map-options
/>
</q-card-section>
<q-card-section class="row">
<div class="col-2">Script Arguments:</div>
<q-select
label="(press Enter after typing each argument)"
class="col-10"
filled
v-model="script.args"
use-input
use-chips
multiple
dense
hide-dropdown-icon
input-debounce="0"
new-value-mode="add"
/>
</q-card-section>
<q-card-section class="row">
<div class="col-4">Default Timeout (seconds)</div>
<q-input
type="number"
outlined
dense
class="col-8"
v-model.number="script.default_timeout"
:rules="[val => val >= 5 || 'Minimum is 5']"
/>
</q-card-section>
<q-card-actions>
<q-dialog ref="dialog" @hide="onHide">
<q-card class="q-dialog-plugin" style="width: 40vw">
<q-bar>
Add Script
<q-space />
<q-btn dense flat label="Cancel" v-close-popup />
<q-btn dense flat label="Add" color="primary" type="submit" />
</q-card-actions>
</q-form>
</q-card>
<q-btn dense flat icon="close" v-close-popup>
<q-tooltip class="bg-white text-primary">Close</q-tooltip>
</q-btn>
</q-bar>
<q-form @submit.prevent="submit">
<q-card-section class="row">
<div class="col-2">Name:</div>
<div class="col-10">
<q-input outlined dense v-model="script.name" :rules="[val => !!val || '*Required']" />
</div>
</q-card-section>
<q-card-section class="row">
<div class="col-2">Description:</div>
<div class="col-10">
<q-input outlined dense v-model="script.description" type="textarea" />
</div>
</q-card-section>
<q-card-section class="row">
<div class="col-2">Category:</div>
<q-select
hint="Press Enter or Tab when adding a new value"
dense
options-dense
class="col-10"
outlined
v-model="script.category"
:options="filterOptions"
use-input
clearable
new-value-mode="add-unique"
debounce="0"
@filter="filterFn"
/>
</q-card-section>
<q-card-section class="row">
<div class="col-2">File Upload:</div>
<div class="col-10">
<q-file
v-model="script.filename"
label="Supported file types: .ps1, .bat, .py"
stack-label
filled
counter
class="full-width"
accept=".ps1, .bat, .py"
>
<template v-slot:prepend>
<q-icon name="attach_file" />
</template>
</q-file>
</div>
</q-card-section>
<q-card-section class="row">
<div class="col-2">Type:</div>
<q-select
dense
options-dense
class="col-10"
outlined
v-model="script.shell"
:options="shellOptions"
emit-value
map-options
/>
</q-card-section>
<q-card-section class="row">
<div class="col-2">Script Arguments:</div>
<q-select
label="(press Enter after typing each argument)"
class="col-10"
filled
v-model="script.args"
use-input
use-chips
multiple
dense
hide-dropdown-icon
input-debounce="0"
new-value-mode="add"
/>
</q-card-section>
<q-card-section class="row">
<div class="col-4">Default Timeout (seconds)</div>
<q-input
type="number"
outlined
dense
class="col-8"
v-model.number="script.default_timeout"
:rules="[val => val >= 5 || 'Minimum is 5']"
/>
</q-card-section>
<q-card-actions>
<q-space />
<q-btn dense flat label="Cancel" v-close-popup />
<q-btn dense flat label="Add" color="primary" type="submit" />
</q-card-actions>
</q-form>
</q-card>
</q-dialog>
</template>
<script>
@@ -109,7 +111,7 @@ import mixins from "@/mixins/mixins";
export default {
name: "ScriptModal",
emits: ["add", "close"],
emits: ["ok", "hide", "cancel"],
mixins: [mixins],
props: {
categories: !Array,
@@ -159,8 +161,7 @@ export default {
.post("/scripts/scripts/", formData)
.then(r => {
this.$q.loading.hide();
this.$emit("close");
this.$emit("add");
this.onOk();
this.notifySuccess(r.data);
})
.catch(e => {
@@ -177,6 +178,19 @@ export default {
}
});
},
show() {
this.$refs.dialog.show();
},
hide() {
this.$refs.dialog.hide();
},
onHide() {
this.$emit("hide");
},
onOk() {
this.$emit("ok");
this.hide();
},
},
};
</script>