mirror of
https://github.com/jpros/tacticalrmm-web.git
synced 2026-05-05 05:46:12 +00:00
feat: agent deployments #138
This commit is contained in:
130
src/components/Deployment.vue
Normal file
130
src/components/Deployment.vue
Normal file
@@ -0,0 +1,130 @@
|
||||
<template>
|
||||
<q-card style="min-width: 70vw">
|
||||
<q-bar>
|
||||
<q-btn @click="getDeployments" class="q-mr-sm" dense flat push icon="refresh" />
|
||||
<q-space />Manage Deployments
|
||||
<q-space />
|
||||
<q-btn dense flat icon="close" v-close-popup>
|
||||
<q-tooltip content-class="bg-white text-primary" />
|
||||
</q-btn>
|
||||
</q-bar>
|
||||
<div class="row">
|
||||
<div class="q-pa-sm q-ml-sm">
|
||||
<q-btn color="primary" icon="add" label="New" @click="showNewDeployment = true" />
|
||||
</div>
|
||||
</div>
|
||||
<q-separator />
|
||||
<q-card-section>
|
||||
<q-table
|
||||
dense
|
||||
class="audit-mgr-tbl-sticky"
|
||||
binary-state-sort
|
||||
virtual-scroll
|
||||
:data="deployments"
|
||||
:columns="columns"
|
||||
:visible-columns="visibleColumns"
|
||||
row-key="id"
|
||||
:pagination.sync="pagination"
|
||||
no-data-label="No Deployments"
|
||||
>
|
||||
<template slot="body" slot-scope="props" :props="props">
|
||||
<q-tr>
|
||||
<q-td key="client" :props="props">{{ props.row.client_name }}</q-td>
|
||||
<q-td key="site" :props="props">{{ props.row.site_name }}</q-td>
|
||||
<q-td key="mon_type" :props="props">{{ props.row.mon_type }}</q-td>
|
||||
<q-td key="arch" :props="props"
|
||||
><span v-if="props.row.arch === '64'">64 bit</span><span v-else>32 bit</span></q-td
|
||||
>
|
||||
<q-td key="expiry" :props="props">{{ props.row.expiry }}</q-td>
|
||||
<q-td key="flags" :props="props"
|
||||
><q-badge color="grey-8" label="View Flags" />
|
||||
<q-tooltip content-style="font-size: 12px">{{ props.row.install_flags }}</q-tooltip>
|
||||
</q-td>
|
||||
<q-td key="link" :props="props"
|
||||
><q-btn size="sm" color="primary" icon="content_copy" label="Copy" @click="copyLink(props)"
|
||||
/></q-td>
|
||||
<q-td key="delete" :props="props"
|
||||
><q-btn size="sm" color="negative" icon="delete" @click="deleteDeployment(props.row.id)"
|
||||
/></q-td>
|
||||
</q-tr>
|
||||
</template>
|
||||
</q-table>
|
||||
</q-card-section>
|
||||
<q-dialog v-model="showNewDeployment">
|
||||
<NewDeployment @close="showNewDeployment = false" @added="getDeployments" />
|
||||
</q-dialog>
|
||||
</q-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from "axios";
|
||||
import mixins from "@/mixins/mixins";
|
||||
import NewDeployment from "@/components/modals/clients/NewDeployment";
|
||||
import { copyToClipboard } from "quasar";
|
||||
|
||||
export default {
|
||||
name: "Deployment",
|
||||
mixins: [mixins],
|
||||
components: { NewDeployment },
|
||||
data() {
|
||||
return {
|
||||
showNewDeployment: false,
|
||||
deployments: [],
|
||||
columns: [
|
||||
{ name: "id", field: "id" },
|
||||
{ name: "uid", field: "uid" },
|
||||
{ name: "clientid", field: "client_id" },
|
||||
{ name: "siteid", field: "site_id" },
|
||||
{ name: "client", label: "Client", field: "client_name", align: "left", sortable: true },
|
||||
{ name: "site", label: "Site", field: "site_name", align: "left", sortable: true },
|
||||
{ name: "mon_type", label: "Type", field: "mon_type", align: "left", sortable: true },
|
||||
{ name: "arch", label: "Arch", field: "arch", align: "left", sortable: true },
|
||||
{ name: "expiry", label: "Expiry", field: "expiry", align: "left", sortable: true },
|
||||
{ name: "flags", label: "Flags", field: "install_flags", align: "left" },
|
||||
{ name: "link", label: "Download Link", align: "left" },
|
||||
{ name: "delete", label: "Delete", align: "left" },
|
||||
],
|
||||
visibleColumns: ["client", "site", "mon_type", "arch", "expiry", "flags", "link", "delete"],
|
||||
|
||||
pagination: {
|
||||
rowsPerPage: 50,
|
||||
sortBy: "id",
|
||||
descending: true,
|
||||
},
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
getDeployments() {
|
||||
this.$axios.get("/clients/deployments/").then(r => {
|
||||
this.deployments = r.data;
|
||||
});
|
||||
},
|
||||
deleteDeployment(pk) {
|
||||
this.$q
|
||||
.dialog({
|
||||
title: "Delete deployment?",
|
||||
cancel: true,
|
||||
ok: { label: "Delete", color: "negative" },
|
||||
})
|
||||
.onOk(() => {
|
||||
this.$axios
|
||||
.delete(`/clients/${pk}/deployment/`)
|
||||
.then(r => {
|
||||
this.getDeployments();
|
||||
this.notifySuccess("Deployment deleted");
|
||||
})
|
||||
.catch(() => this.notifyError("Something went wrong"));
|
||||
});
|
||||
},
|
||||
copyLink(props) {
|
||||
const api = axios.defaults.baseURL;
|
||||
copyToClipboard(`${api}/clients/${props.row.uid}/deploy/`).then(() => {
|
||||
this.notifySuccess("Link copied to clipboard", 1500);
|
||||
});
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.getDeployments();
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -81,6 +81,9 @@
|
||||
<q-item clickable v-close-popup @click="showInstallAgent = true">
|
||||
<q-item-section>Install Agent</q-item-section>
|
||||
</q-item>
|
||||
<q-item clickable v-close-popup @click="showDeployment = true">
|
||||
<q-item-section>Manage Deployments</q-item-section>
|
||||
</q-item>
|
||||
<q-item clickable v-close-popup @click="showUpdateAgentsModal = true">
|
||||
<q-item-section>Update Agents</q-item-section>
|
||||
</q-item>
|
||||
@@ -211,6 +214,11 @@
|
||||
<q-dialog v-model="showBulkPatchManagement" position="top">
|
||||
<BulkPatchManagement @close="showBulkPatchManagement = false" />
|
||||
</q-dialog>
|
||||
|
||||
<!-- Agent Deployment -->
|
||||
<q-dialog v-model="showDeployment">
|
||||
<Deployment @close="showDeployment = false" />
|
||||
</q-dialog>
|
||||
</q-bar>
|
||||
</div>
|
||||
</template>
|
||||
@@ -234,6 +242,7 @@ import AuditManager from "@/components/AuditManager";
|
||||
import BulkCommand from "@/components/modals/agents/BulkCommand";
|
||||
import BulkScript from "@/components/modals/agents/BulkScript";
|
||||
import BulkPatchManagement from "@/components/modals/agents/BulkPatchManagement";
|
||||
import Deployment from "@/components/Deployment";
|
||||
|
||||
export default {
|
||||
name: "FileBar",
|
||||
@@ -256,6 +265,7 @@ export default {
|
||||
BulkCommand,
|
||||
BulkScript,
|
||||
BulkPatchManagement,
|
||||
Deployment,
|
||||
},
|
||||
props: ["clients"],
|
||||
data() {
|
||||
@@ -276,6 +286,7 @@ export default {
|
||||
showBulkCommand: false,
|
||||
showBulkScript: false,
|
||||
showBulkPatchManagement: false,
|
||||
showDeployment: false,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
|
||||
154
src/components/modals/clients/NewDeployment.vue
Normal file
154
src/components/modals/clients/NewDeployment.vue
Normal file
@@ -0,0 +1,154 @@
|
||||
<template>
|
||||
<q-card style="min-width: 25vw" v-if="loaded">
|
||||
<q-card-section class="row">
|
||||
<q-card-actions align="left">
|
||||
<div class="text-h6">Create a Deployment</div>
|
||||
</q-card-actions>
|
||||
<q-space />
|
||||
<q-card-actions align="right">
|
||||
<q-btn v-close-popup flat round dense icon="close" />
|
||||
</q-card-actions>
|
||||
</q-card-section>
|
||||
<q-card-section>
|
||||
<q-form @submit.prevent="create">
|
||||
<q-card-section v-if="tree !== null" class="q-gutter-sm">
|
||||
<q-select
|
||||
outlined
|
||||
dense
|
||||
options-dense
|
||||
label="Client"
|
||||
v-model="client"
|
||||
:options="Object.keys(tree)"
|
||||
@input="site = sites[0]"
|
||||
/>
|
||||
</q-card-section>
|
||||
<q-card-section class="q-gutter-sm">
|
||||
<q-select dense options-dense outlined label="Site" v-model="site" :options="sites" />
|
||||
</q-card-section>
|
||||
<q-card-section>
|
||||
<div class="q-gutter-sm">
|
||||
<q-radio v-model="agenttype" val="server" label="Server" @input="power = false" />
|
||||
<q-radio v-model="agenttype" val="workstation" label="Workstation" />
|
||||
</div>
|
||||
</q-card-section>
|
||||
<q-card-section>
|
||||
Expiry
|
||||
<div class="q-gutter-sm">
|
||||
<q-input filled v-model="datetime">
|
||||
<template v-slot:prepend>
|
||||
<q-icon name="event" class="cursor-pointer">
|
||||
<q-popup-proxy transition-show="scale" transition-hide="scale">
|
||||
<q-date v-model="datetime" mask="YYYY-MM-DD HH:mm" />
|
||||
</q-popup-proxy>
|
||||
</q-icon>
|
||||
</template>
|
||||
|
||||
<template v-slot:append>
|
||||
<q-icon name="access_time" class="cursor-pointer">
|
||||
<q-popup-proxy transition-show="scale" transition-hide="scale">
|
||||
<q-time v-model="datetime" mask="YYYY-MM-DD HH:mm" />
|
||||
</q-popup-proxy>
|
||||
</q-icon>
|
||||
</template>
|
||||
</q-input>
|
||||
</div>
|
||||
</q-card-section>
|
||||
<q-card-section>
|
||||
<div class="q-gutter-sm">
|
||||
<q-checkbox v-model="rdp" dense label="Enable RDP" />
|
||||
<q-checkbox v-model="ping" dense label="Enable Ping" />
|
||||
<q-checkbox v-model="power" dense v-show="agenttype === 'workstation'" label="Disable sleep/hibernate" />
|
||||
</div>
|
||||
</q-card-section>
|
||||
<q-card-section>
|
||||
OS
|
||||
<div class="q-gutter-sm">
|
||||
<q-radio v-model="arch" val="64" label="64 bit" />
|
||||
<q-radio v-model="arch" val="32" label="32 bit" />
|
||||
</div>
|
||||
</q-card-section>
|
||||
<q-card-actions align="left">
|
||||
<q-btn label="Create" color="primary" type="submit" />
|
||||
</q-card-actions>
|
||||
</q-form>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import mixins from "@/mixins/mixins";
|
||||
import { date } from "quasar";
|
||||
|
||||
export default {
|
||||
name: "NewDeployment",
|
||||
mixins: [mixins],
|
||||
data() {
|
||||
return {
|
||||
datetime: null,
|
||||
loaded: false,
|
||||
tree: {},
|
||||
client: null,
|
||||
site: null,
|
||||
agenttype: "server",
|
||||
power: false,
|
||||
rdp: false,
|
||||
ping: false,
|
||||
arch: "64",
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
create() {
|
||||
const data = {
|
||||
client: this.client,
|
||||
site: this.site,
|
||||
expires: this.datetime,
|
||||
agenttype: this.agenttype,
|
||||
power: this.power ? 1 : 0,
|
||||
rdp: this.rdp ? 1 : 0,
|
||||
ping: this.ping ? 1 : 0,
|
||||
arch: this.arch,
|
||||
};
|
||||
this.$axios
|
||||
.post("/clients/deployments/", data)
|
||||
.then(r => {
|
||||
this.$emit("close");
|
||||
this.$emit("added");
|
||||
this.notifySuccess("Deployment added");
|
||||
})
|
||||
.catch(() => this.notifyError("Something went wrong"));
|
||||
},
|
||||
getCurrentDate() {
|
||||
let d = new Date();
|
||||
d.setDate(d.getDate() + 30);
|
||||
this.datetime = date.formatDate(d, "YYYY-MM-DD HH:mm");
|
||||
},
|
||||
getClientsSites() {
|
||||
this.$q.loading.show();
|
||||
this.$axios
|
||||
.get("/clients/loadclients/")
|
||||
.then(r => {
|
||||
this.tree = r.data;
|
||||
this.client = Object.keys(r.data)[0];
|
||||
this.loaded = true;
|
||||
this.$q.loading.hide();
|
||||
})
|
||||
.catch(() => {
|
||||
this.notifyError("Something went wrong");
|
||||
this.$q.loading.hide();
|
||||
});
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
sites() {
|
||||
if (this.tree !== null && this.client !== null) {
|
||||
this.site = this.tree[this.client][0];
|
||||
return this.tree[this.client];
|
||||
}
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.getCurrentDate();
|
||||
this.getClientsSites();
|
||||
},
|
||||
};
|
||||
</script>
|
||||
Reference in New Issue
Block a user