Compare commits
25 Commits
v0.101.12-
...
v0.101.19-
Author | SHA1 | Date | |
---|---|---|---|
|
95df8c1889 | ||
|
819a364207 | ||
|
ed2b07fb0b | ||
|
64ed5e8740 | ||
|
cdeaa3d9c4 | ||
|
8c6ac164ba | ||
|
dc68b16ff2 | ||
|
a4f15fd05a | ||
|
176675abd8 | ||
|
73dc278ac4 | ||
|
d6b443296b | ||
|
f3c718d29c | ||
|
5955af08c7 | ||
|
dec1ccc98a | ||
|
a78780b837 | ||
|
beff8eb10e | ||
|
c2f21b70dd | ||
|
520145e0e3 | ||
|
6a132187a2 | ||
|
a63a9ccd76 | ||
|
ff1eb791db | ||
|
13bd88b979 | ||
|
5b0c244920 | ||
|
0318a17cac | ||
|
75296ed8ee |
6131
package-lock.json
generated
6131
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
36
package.json
36
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "web",
|
||||
"version": "0.101.12-dev",
|
||||
"version": "0.101.19-dev",
|
||||
"private": true,
|
||||
"productName": "Tactical RMM",
|
||||
"scripts": {
|
||||
@@ -10,13 +10,13 @@
|
||||
"format": "prettier --write \"**/*.{js,ts,vue,,html,md,json}\" --ignore-path .gitignore"
|
||||
},
|
||||
"dependencies": {
|
||||
"@quasar/extras": "1.15.9",
|
||||
"apexcharts": "3.36.3",
|
||||
"axios": "0.27.2",
|
||||
"@quasar/extras": "1.16.3",
|
||||
"apexcharts": "3.40.0",
|
||||
"axios": "1.4.0",
|
||||
"dotenv": "16.0.3",
|
||||
"qrcode.vue": "3.3.3",
|
||||
"quasar": "2.11.5",
|
||||
"vue": "3.2.45",
|
||||
"qrcode.vue": "3.3.4",
|
||||
"quasar": "2.12.0",
|
||||
"vue": "3.2.47",
|
||||
"vue3-ace-editor": "2.2.2",
|
||||
"vue3-apexcharts": "1.4.1",
|
||||
"vuedraggable": "4.1.0",
|
||||
@@ -24,17 +24,17 @@
|
||||
"vuex": "4.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@quasar/cli": "^1.4.0",
|
||||
"@intlify/vite-plugin-vue-i18n": "^6.0.3",
|
||||
"@quasar/app-vite": "^1.2.0",
|
||||
"@types/node": "^18.11.18",
|
||||
"@typescript-eslint/eslint-plugin": "^5.48.2",
|
||||
"@typescript-eslint/parser": "^5.48.2",
|
||||
"autoprefixer": "10.4.13",
|
||||
"eslint": "8.32.0",
|
||||
"eslint-config-prettier": "8.6.0",
|
||||
"@quasar/cli": "^2.1.0",
|
||||
"@intlify/unplugin-vue-i18n": "^0.10.0",
|
||||
"@quasar/app-vite": "^1.3.0",
|
||||
"@types/node": "^18.16.5",
|
||||
"@typescript-eslint/eslint-plugin": "^5.59.2",
|
||||
"@typescript-eslint/parser": "^5.59.2",
|
||||
"autoprefixer": "10.4.14",
|
||||
"eslint": "8.40.0",
|
||||
"eslint-config-prettier": "8.8.0",
|
||||
"eslint-plugin-vue": "8.7.1",
|
||||
"prettier": "2.8.3",
|
||||
"typescript": "4.9.4"
|
||||
"prettier": "2.8.8",
|
||||
"typescript": "5.0.4"
|
||||
}
|
||||
}
|
@@ -38,3 +38,8 @@ export async function runURLAction(payload) {
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
export async function generateScript(payload) {
|
||||
const { data } = await axios.post(`${baseUrl}/openai/generate/`, payload);
|
||||
return data;
|
||||
}
|
||||
|
@@ -373,17 +373,12 @@ export default {
|
||||
"local_ips",
|
||||
"make_model",
|
||||
"physical_disks",
|
||||
"custom_fields"
|
||||
];
|
||||
|
||||
// quasar filter only does visible columns so this is a hack to add hidden columns we want to filter
|
||||
for (const elem of hiddenFields) {
|
||||
if (!cols.find((o) => o.name === elem)) {
|
||||
cols.push({
|
||||
name: elem,
|
||||
field: elem,
|
||||
});
|
||||
}
|
||||
}
|
||||
// originally I was modifying cols directly but this led to phantom colum so doing it this way now
|
||||
// https://github.com/amidaware/tacticalrmm/issues/1264
|
||||
const allColumns = [...cols, ...hiddenFields.map((field) => ({ field }))];
|
||||
|
||||
const lowerTerms = terms ? terms.toLowerCase() : "";
|
||||
let advancedFilter = false;
|
||||
@@ -437,8 +432,12 @@ export default {
|
||||
}
|
||||
|
||||
// Normal text filter
|
||||
return cols.some((col) => {
|
||||
const val = cellValue(col, row) + "";
|
||||
return allColumns.some((col) => {
|
||||
let valObj = cellValue(col, row);
|
||||
if (Array.isArray(valObj)) {
|
||||
valObj = valObj.map((item) => item.value ? item.value : item);
|
||||
}
|
||||
const val = valObj + "";
|
||||
const haystack =
|
||||
val === "undefined" || val === "null" ? "" : val.toLowerCase();
|
||||
return haystack.indexOf(search) !== -1;
|
||||
|
@@ -166,7 +166,7 @@ export default {
|
||||
type: "textarea",
|
||||
isValid: (val) => !!val,
|
||||
},
|
||||
style: "width: 30vw; max-width: 50vw;",
|
||||
style: "width: 90vw; max-width: 90vw",
|
||||
ok: { label: "Add" },
|
||||
cancel: true,
|
||||
}).onOk(async () => {
|
||||
@@ -193,7 +193,7 @@ export default {
|
||||
type: "textarea",
|
||||
isValid: (val) => !!val,
|
||||
},
|
||||
style: "width: 30vw; max-width: 50vw;",
|
||||
style: "width: 90vw; max-width: 90vw",
|
||||
ok: { label: "Save" },
|
||||
cancel: true,
|
||||
}).onOk(async (data) => {
|
||||
|
@@ -158,6 +158,20 @@
|
||||
>
|
||||
</div>
|
||||
<div v-else>No checks</div>
|
||||
|
||||
<span
|
||||
v-if="customFields.length > 0"
|
||||
class="text-subtitle2 text-bold block q-mt-xl"
|
||||
>Custom Fields</span
|
||||
>
|
||||
<q-list dense>
|
||||
<q-item v-for="(field, i) in customFields" :key="field + i">
|
||||
<q-item-section thumbnail>
|
||||
<q-icon name="fas fa-user" size="xs" />
|
||||
</q-item-section>
|
||||
<q-item-section>{{ field.name }}: {{ field.value }}</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
</div>
|
||||
<div class="col-1"></div>
|
||||
<!-- right -->
|
||||
@@ -193,6 +207,7 @@ import {
|
||||
openAgentWindow,
|
||||
} from "@/api/agents";
|
||||
import { notifySuccess } from "@/utils/notify";
|
||||
import { fetchCustomFields } from "@/api/core";
|
||||
|
||||
// ui imports
|
||||
import AgentActionMenu from "@/components/agents/AgentActionMenu.vue";
|
||||
@@ -210,6 +225,7 @@ export default {
|
||||
|
||||
// summary tab logic
|
||||
const summary = ref(null);
|
||||
const customFieldsDefinitions = ref(null);
|
||||
const loading = ref(false);
|
||||
|
||||
function diskBarColor(percent) {
|
||||
@@ -236,9 +252,37 @@ export default {
|
||||
return ret;
|
||||
});
|
||||
|
||||
const customFields = computed(() => {
|
||||
if (!summary.value.custom_fields) {
|
||||
return [];
|
||||
}
|
||||
if (!customFieldsDefinitions.value) {
|
||||
return [];
|
||||
}
|
||||
const ret = [];
|
||||
for (const customField of summary.value.custom_fields) {
|
||||
const definition = customFieldsDefinitions.value.find(
|
||||
(def) => def.id === customField.field
|
||||
);
|
||||
if (
|
||||
definition &&
|
||||
!definition.hide_in_ui &&
|
||||
customField.value?.length > 0
|
||||
) {
|
||||
ret.push({
|
||||
name: definition.name,
|
||||
value: customField.value,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
});
|
||||
|
||||
async function getSummary() {
|
||||
loading.value = true;
|
||||
summary.value = await fetchAgent(selectedAgent.value);
|
||||
customFieldsDefinitions.value = await fetchCustomFields();
|
||||
store.commit("setRefreshSummaryTab", false);
|
||||
store.commit("setAgentPlatform", summary.value.plat);
|
||||
loading.value = false;
|
||||
@@ -277,6 +321,7 @@ export default {
|
||||
return {
|
||||
// reactive data
|
||||
summary,
|
||||
customFields,
|
||||
loading,
|
||||
selectedAgent,
|
||||
disks,
|
||||
|
@@ -12,6 +12,7 @@
|
||||
<q-tab name="urlactions" label="URL Actions" />
|
||||
<q-tab name="retention" label="Retention" />
|
||||
<q-tab name="apikeys" label="API Keys" />
|
||||
<q-tab name="openai" label="Open AI" />
|
||||
</q-tabs>
|
||||
</template>
|
||||
<template v-slot:after>
|
||||
@@ -508,6 +509,49 @@
|
||||
<q-tab-panel name="apikeys">
|
||||
<APIKeysTable />
|
||||
</q-tab-panel>
|
||||
|
||||
<!-- Open AI -->
|
||||
<q-tab-panel name="openai">
|
||||
<div class="text-subtitle2">Open AI</div>
|
||||
<q-separator />
|
||||
<q-card-section class="row">
|
||||
<div class="col-4">API Key:</div>
|
||||
<div class="col-2"></div>
|
||||
<q-input
|
||||
dense
|
||||
outlined
|
||||
v-model="settings.open_ai_token"
|
||||
class="col-6"
|
||||
/>
|
||||
</q-card-section>
|
||||
<q-card-section class="row">
|
||||
<div class="col-4">Open AI Model:</div>
|
||||
<div class="col-2"></div>
|
||||
<q-input
|
||||
dense
|
||||
outlined
|
||||
v-model="settings.open_ai_model"
|
||||
class="col-6"
|
||||
>
|
||||
<template v-slot:after>
|
||||
<q-btn
|
||||
round
|
||||
dense
|
||||
flat
|
||||
icon="info"
|
||||
size="sm"
|
||||
@click="
|
||||
openURL(
|
||||
'https://platform.openai.com/docs/models/overview'
|
||||
)
|
||||
"
|
||||
>
|
||||
<q-tooltip>Click to see available options</q-tooltip>
|
||||
</q-btn>
|
||||
</template>
|
||||
</q-input>
|
||||
</q-card-section>
|
||||
</q-tab-panel>
|
||||
</q-tab-panels>
|
||||
</q-scroll-area>
|
||||
<q-card-section class="row items-center">
|
||||
|
@@ -11,7 +11,17 @@
|
||||
:style="maximized ? '' : 'width: 90vw; max-width: 90vw'"
|
||||
>
|
||||
<q-bar>
|
||||
{{ title }}
|
||||
<span class="q-pr-sm">{{ title }}</span>
|
||||
<q-btn
|
||||
v-if="!script && openAIEnabled"
|
||||
size="xs"
|
||||
:disable="loading"
|
||||
dense
|
||||
label="Generate Script"
|
||||
color="primary"
|
||||
no-caps
|
||||
@click="generateScriptOpenAI"
|
||||
/>
|
||||
<q-space />
|
||||
<q-btn
|
||||
dense
|
||||
@@ -57,116 +67,133 @@
|
||||
><br />Add one to get rid of this warning. Ignore if windows.
|
||||
</q-banner>
|
||||
<div class="row q-pa-sm">
|
||||
<div class="col-4 q-gutter-sm q-pr-sm">
|
||||
<q-input
|
||||
filled
|
||||
dense
|
||||
:readonly="readonly"
|
||||
v-model="formScript.name"
|
||||
label="Name"
|
||||
:rules="[(val) => !!val || '*Required']"
|
||||
hide-bottom-space
|
||||
/>
|
||||
<q-input
|
||||
filled
|
||||
dense
|
||||
:readonly="readonly"
|
||||
v-model="formScript.description"
|
||||
label="Description"
|
||||
/>
|
||||
<q-select
|
||||
:readonly="readonly"
|
||||
options-dense
|
||||
filled
|
||||
dense
|
||||
v-model="formScript.shell"
|
||||
:options="shellOptions"
|
||||
emit-value
|
||||
map-options
|
||||
label="Shell Type"
|
||||
/>
|
||||
<tactical-dropdown
|
||||
v-model="formScript.supported_platforms"
|
||||
:options="agentPlatformOptions"
|
||||
label="Supported Platforms (All supported if blank)"
|
||||
clearable
|
||||
mapOptions
|
||||
filled
|
||||
multiple
|
||||
:readonly="readonly"
|
||||
/>
|
||||
<tactical-dropdown
|
||||
filled
|
||||
v-model="formScript.category"
|
||||
:options="categories"
|
||||
use-input
|
||||
clearable
|
||||
new-value-mode="add-unique"
|
||||
filterable
|
||||
label="Category"
|
||||
:readonly="readonly"
|
||||
hide-bottom-space
|
||||
/>
|
||||
<tactical-dropdown
|
||||
v-model="formScript.args"
|
||||
label="Script Arguments (press Enter after typing each argument)"
|
||||
filled
|
||||
use-input
|
||||
multiple
|
||||
hide-dropdown-icon
|
||||
input-debounce="0"
|
||||
new-value-mode="add"
|
||||
:readonly="readonly"
|
||||
/>
|
||||
<tactical-dropdown
|
||||
v-model="formScript.env_vars"
|
||||
:label="envVarsLabel"
|
||||
filled
|
||||
use-input
|
||||
multiple
|
||||
hide-dropdown-icon
|
||||
input-debounce="0"
|
||||
new-value-mode="add"
|
||||
:readonly="readonly"
|
||||
/>
|
||||
<q-input
|
||||
type="number"
|
||||
filled
|
||||
dense
|
||||
:readonly="readonly"
|
||||
v-model.number="formScript.default_timeout"
|
||||
label="Timeout (seconds)"
|
||||
:rules="[(val) => val >= 5 || 'Minimum is 5']"
|
||||
hide-bottom-space
|
||||
/>
|
||||
<q-checkbox
|
||||
v-model="formScript.run_as_user"
|
||||
label="Run As User (Windows only)"
|
||||
>
|
||||
<q-tooltip
|
||||
>Setting this value on the script model will always override any
|
||||
'Run As User' checkboxes in the UI and force this script to
|
||||
always be run in the context of the logged in user. If no user
|
||||
is logged in, the script will not run and an error will be
|
||||
returned.
|
||||
</q-tooltip>
|
||||
</q-checkbox>
|
||||
<q-input
|
||||
label="Syntax"
|
||||
type="textarea"
|
||||
style="height: 150px; overflow-y: auto; resize: none"
|
||||
v-model="formScript.syntax"
|
||||
dense
|
||||
filled
|
||||
:readonly="readonly"
|
||||
/>
|
||||
</div>
|
||||
<q-scroll-area
|
||||
:thumb-style="{
|
||||
right: '4px',
|
||||
borderRadius: '5px',
|
||||
width: '5px',
|
||||
opacity: 0.75,
|
||||
}"
|
||||
:bar-style="{
|
||||
right: '2px',
|
||||
borderRadius: '9px',
|
||||
width: '9px',
|
||||
opacity: 0.2,
|
||||
}"
|
||||
class="col-4 q-mb-none q-pb-none"
|
||||
:style="{ height: `${maximized ? '82vh' : '64vh'}` }"
|
||||
>
|
||||
<div class="q-gutter-sm q-pr-sm">
|
||||
<q-input
|
||||
filled
|
||||
dense
|
||||
:readonly="readonly"
|
||||
v-model="formScript.name"
|
||||
label="Name"
|
||||
:rules="[(val) => !!val || '*Required']"
|
||||
hide-bottom-space
|
||||
/>
|
||||
<q-input
|
||||
filled
|
||||
dense
|
||||
:readonly="readonly"
|
||||
v-model="formScript.description"
|
||||
label="Description"
|
||||
/>
|
||||
<q-select
|
||||
:readonly="readonly"
|
||||
options-dense
|
||||
filled
|
||||
dense
|
||||
v-model="formScript.shell"
|
||||
:options="shellOptions"
|
||||
emit-value
|
||||
map-options
|
||||
label="Shell Type"
|
||||
/>
|
||||
<tactical-dropdown
|
||||
v-model="formScript.supported_platforms"
|
||||
:options="agentPlatformOptions"
|
||||
label="Supported Platforms (All supported if blank)"
|
||||
clearable
|
||||
mapOptions
|
||||
filled
|
||||
multiple
|
||||
:readonly="readonly"
|
||||
/>
|
||||
<tactical-dropdown
|
||||
filled
|
||||
v-model="formScript.category"
|
||||
:options="categories"
|
||||
use-input
|
||||
clearable
|
||||
new-value-mode="add-unique"
|
||||
filterable
|
||||
label="Category"
|
||||
:readonly="readonly"
|
||||
hide-bottom-space
|
||||
/>
|
||||
<tactical-dropdown
|
||||
v-model="formScript.args"
|
||||
label="Script Arguments (press Enter after typing each argument)"
|
||||
filled
|
||||
use-input
|
||||
multiple
|
||||
hide-dropdown-icon
|
||||
input-debounce="0"
|
||||
new-value-mode="add"
|
||||
:readonly="readonly"
|
||||
/>
|
||||
<tactical-dropdown
|
||||
v-model="formScript.env_vars"
|
||||
:label="envVarsLabel"
|
||||
filled
|
||||
use-input
|
||||
multiple
|
||||
hide-dropdown-icon
|
||||
input-debounce="0"
|
||||
new-value-mode="add"
|
||||
:readonly="readonly"
|
||||
/>
|
||||
<q-input
|
||||
type="number"
|
||||
filled
|
||||
dense
|
||||
:readonly="readonly"
|
||||
v-model.number="formScript.default_timeout"
|
||||
label="Timeout (seconds)"
|
||||
:rules="[(val) => val >= 5 || 'Minimum is 5']"
|
||||
hide-bottom-space
|
||||
/>
|
||||
<q-checkbox
|
||||
v-model="formScript.run_as_user"
|
||||
label="Run As User (Windows only)"
|
||||
>
|
||||
<q-tooltip
|
||||
>Setting this value on the script model will always override
|
||||
any 'Run As User' checkboxes in the UI and force this script
|
||||
to always be run in the context of the logged in user. If no
|
||||
user is logged in, the script will not run and an error will
|
||||
be returned.
|
||||
</q-tooltip>
|
||||
</q-checkbox>
|
||||
<q-input
|
||||
label="Syntax"
|
||||
type="textarea"
|
||||
style="height: 150px; overflow-y: auto; resize: none"
|
||||
v-model="formScript.syntax"
|
||||
dense
|
||||
filled
|
||||
:readonly="readonly"
|
||||
/>
|
||||
</div>
|
||||
</q-scroll-area>
|
||||
<v-ace-editor
|
||||
v-model:value="formScript.script_body"
|
||||
class="col-8"
|
||||
:lang="lang"
|
||||
:theme="$q.dark.isActive ? 'tomorrow_night_eighties' : 'tomorrow'"
|
||||
:style="{ height: `${maximized ? '87vh' : '64vh'}` }"
|
||||
:style="{ height: `${maximized ? '82vh' : '64vh'}` }"
|
||||
wrap
|
||||
:printMargin="false"
|
||||
:options="{ fontSize: '14px' }"
|
||||
@@ -220,9 +247,11 @@
|
||||
<script>
|
||||
// composable imports
|
||||
import { ref, computed, onMounted } from "vue";
|
||||
import { useStore } from "vuex";
|
||||
import { useQuasar, useDialogPluginComponent } from "quasar";
|
||||
import { saveScript, editScript, downloadScript } from "@/api/scripts";
|
||||
import { useAgentDropdown, agentPlatformOptions } from "@/composables/agents";
|
||||
import { generateScript } from "@/api/core";
|
||||
import { notifySuccess } from "@/utils/notify";
|
||||
|
||||
// ui imports
|
||||
@@ -266,6 +295,10 @@ export default {
|
||||
const { dialogRef, onDialogHide, onDialogOK } = useDialogPluginComponent();
|
||||
const $q = useQuasar();
|
||||
|
||||
// setup store
|
||||
const store = useStore();
|
||||
const openAIEnabled = computed(() => store.state.openAIIntegrationEnabled);
|
||||
|
||||
// setup agent dropdown
|
||||
const { agent, agentOptions, getAgentOptions } = useAgentDropdown();
|
||||
|
||||
@@ -355,6 +388,23 @@ export default {
|
||||
});
|
||||
}
|
||||
|
||||
function generateScriptOpenAI() {
|
||||
$q.dialog({
|
||||
title: "Ask ChatGPT what you need!",
|
||||
prompt: {
|
||||
model: `${lang.value} code that `,
|
||||
type: "text",
|
||||
},
|
||||
cancel: true,
|
||||
persistent: true,
|
||||
}).onOk(async (data) => {
|
||||
const completion = await generateScript({
|
||||
prompt: data,
|
||||
});
|
||||
script.value.script_body = completion;
|
||||
});
|
||||
}
|
||||
|
||||
// component life cycle hooks
|
||||
onMounted(async () => {
|
||||
agentLoading.value = true;
|
||||
@@ -380,10 +430,12 @@ export default {
|
||||
|
||||
//computed
|
||||
title,
|
||||
openAIEnabled,
|
||||
|
||||
//methods
|
||||
submitForm,
|
||||
openTestScriptModal,
|
||||
generateScriptOpenAI,
|
||||
|
||||
// quasar dialog plugin
|
||||
dialogRef,
|
||||
|
@@ -11,7 +11,17 @@
|
||||
:style="maximized ? '' : 'width: 70vw; max-width: 90vw'"
|
||||
>
|
||||
<q-bar>
|
||||
{{ title }}
|
||||
<span class="q-pr-sm">{{ title }}</span>
|
||||
<q-btn
|
||||
v-if="!snippet && openAIEnabled"
|
||||
:disable="loading"
|
||||
dense
|
||||
size="xs"
|
||||
label="Generate Script"
|
||||
color="primary"
|
||||
no-caps
|
||||
@click="generateScriptOpenAI"
|
||||
/>
|
||||
<q-space />
|
||||
<q-btn
|
||||
dense
|
||||
@@ -97,6 +107,9 @@
|
||||
<script>
|
||||
// composable imports
|
||||
import { ref, computed } from "vue";
|
||||
import { useStore } from "vuex";
|
||||
import { useQuasar } from "quasar";
|
||||
import { generateScript } from "@/api/core";
|
||||
import { useDialogPluginComponent } from "quasar";
|
||||
import { saveScriptSnippet, editScriptSnippet } from "@/api/scripts";
|
||||
import { notifySuccess } from "@/utils/notify";
|
||||
@@ -128,6 +141,13 @@ export default {
|
||||
// setup quasar plugins
|
||||
const { dialogRef, onDialogHide, onDialogOK } = useDialogPluginComponent();
|
||||
|
||||
// setup quasar
|
||||
const $q = useQuasar();
|
||||
|
||||
// setup store
|
||||
const store = useStore();
|
||||
const openAIEnabled = computed(() => store.state.openAIIntegrationEnabled);
|
||||
|
||||
// snippet form logic
|
||||
const snippet = props.snippet
|
||||
? ref(Object.assign({}, props.snippet))
|
||||
@@ -167,6 +187,23 @@ export default {
|
||||
loading.value = false;
|
||||
}
|
||||
|
||||
function generateScriptOpenAI() {
|
||||
$q.dialog({
|
||||
title: "Ask ChatGPT what you need!",
|
||||
prompt: {
|
||||
model: `${lang.value} code that `,
|
||||
type: "text",
|
||||
},
|
||||
cancel: true,
|
||||
persistent: true,
|
||||
}).onOk(async (data) => {
|
||||
const completion = await generateScript({
|
||||
prompt: data,
|
||||
});
|
||||
snippet.value.code = completion;
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
// reactive data
|
||||
formSnippet: snippet.value,
|
||||
@@ -179,9 +216,11 @@ export default {
|
||||
|
||||
//computed
|
||||
title,
|
||||
openAIEnabled,
|
||||
|
||||
//methods
|
||||
submitForm,
|
||||
generateScriptOpenAI,
|
||||
|
||||
// quasar dialog plugin
|
||||
dialogRef,
|
||||
|
@@ -33,6 +33,7 @@ export default function () {
|
||||
currentTRMMVersion: null,
|
||||
latestTRMMVersion: null,
|
||||
dateFormat: "MMM-DD-YYYY - HH:mm",
|
||||
openAIIntegrationEnabled: false,
|
||||
};
|
||||
},
|
||||
getters: {
|
||||
@@ -136,6 +137,9 @@ export default function () {
|
||||
setDateFormat(state, val) {
|
||||
state.dateFormat = val;
|
||||
},
|
||||
setOpenAIIntegrationStatus(state, val) {
|
||||
state.openAIIntegrationEnabled = val;
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
setClientTreeSplitter(context, val) {
|
||||
@@ -217,6 +221,10 @@ export default function () {
|
||||
context.commit("setShowCommunityScripts", data.show_community_scripts);
|
||||
context.commit("SET_HOSTED", data.hosted);
|
||||
context.commit("SET_TOKEN_EXPIRED", data.token_is_expired);
|
||||
context.commit(
|
||||
"setOpenAIIntegrationStatus",
|
||||
data.open_ai_integration_enabled
|
||||
);
|
||||
|
||||
if (data.date_format && data.date_format !== "")
|
||||
context.commit("setDateFormat", data.date_format);
|
||||
|
@@ -173,6 +173,18 @@
|
||||
</q-menu>
|
||||
</q-item>
|
||||
|
||||
<!-- Bulk Run Checks -->
|
||||
<q-item
|
||||
clickable
|
||||
v-close-popup
|
||||
@click="runChecks(props.node)"
|
||||
>
|
||||
<q-item-section side>
|
||||
<q-icon name="fas fa-check-double" />
|
||||
</q-item-section>
|
||||
<q-item-section>Run Checks</q-item-section>
|
||||
</q-item>
|
||||
|
||||
<q-separator></q-separator>
|
||||
|
||||
<q-item clickable v-close-popup>
|
||||
@@ -440,7 +452,7 @@ export default {
|
||||
showInstallAgentModal: false,
|
||||
sitePk: null,
|
||||
innerModel: (this.$q.screen.height - 82) / 2,
|
||||
search: "",
|
||||
search: (this.$route.query.search ? this.$route.query.search : ""),
|
||||
filterTextLength: 0,
|
||||
filterAvailability: "all",
|
||||
filterPatchesPending: false,
|
||||
@@ -690,6 +702,17 @@ export default {
|
||||
})
|
||||
.onOk(() => this.$store.dispatch("refreshDashboard"));
|
||||
},
|
||||
runChecks(node) {
|
||||
const target = node.children ? "client" : "site";
|
||||
this.$axios
|
||||
.post(`/checks/${target}/${node.id}/csbulkrun/`)
|
||||
.then((r) => {
|
||||
this.notifySuccess(r.data);
|
||||
})
|
||||
.catch((e) => {
|
||||
console.error(e);
|
||||
});
|
||||
},
|
||||
showToggleMaintenance(node) {
|
||||
let data = {
|
||||
id: node.id,
|
||||
|
Reference in New Issue
Block a user