start removing tasks rework
This commit is contained in:
@@ -261,7 +261,7 @@
|
||||
<q-td v-else-if="props.row.task_result.status === 'passing'">
|
||||
<q-icon
|
||||
style="font-size: 1.3rem"
|
||||
:color="dashPositiveColor"
|
||||
:color="dash_positive_color"
|
||||
name="check_circle"
|
||||
>
|
||||
<q-tooltip>Passing</q-tooltip>
|
||||
@@ -271,7 +271,7 @@
|
||||
<q-icon
|
||||
v-if="props.row.alert_severity === 'info'"
|
||||
style="font-size: 1.3rem"
|
||||
:color="dashInfoColor"
|
||||
:color="dash_info_color"
|
||||
name="info"
|
||||
>
|
||||
<q-tooltip>Informational</q-tooltip>
|
||||
@@ -279,7 +279,7 @@
|
||||
<q-icon
|
||||
v-else-if="props.row.alert_severity === 'warning'"
|
||||
style="font-size: 1.3rem"
|
||||
:color="dashWarningColor"
|
||||
:color="dash_warning_color"
|
||||
name="warning"
|
||||
>
|
||||
<q-tooltip>Warning</q-tooltip>
|
||||
@@ -287,7 +287,7 @@
|
||||
<q-icon
|
||||
v-else
|
||||
style="font-size: 1.3rem"
|
||||
:color="dashNegativeColor"
|
||||
:color="dash_negative_color"
|
||||
name="error"
|
||||
>
|
||||
<q-tooltip>Error</q-tooltip>
|
||||
@@ -342,7 +342,7 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
<script>
|
||||
// composition imports
|
||||
import { ref, computed, watch, onMounted } from "vue";
|
||||
import { useStore } from "vuex";
|
||||
@@ -409,16 +409,19 @@ const columns = [
|
||||
},
|
||||
];
|
||||
|
||||
export default {
|
||||
name: "AutomatedTasksTab",
|
||||
setup() {
|
||||
// setup vuex
|
||||
const store = useStore();
|
||||
const selectedAgent = computed(() => store.state.selectedRow);
|
||||
const tabHeight = computed(() => store.state.tabHeight);
|
||||
const agentPlatform = computed(() => store.state.agentPlatform);
|
||||
const dashWarningColor = computed(() => store.state.dash_warning_color);
|
||||
const dashNegativeColor = computed(() => store.state.dash_negative_color);
|
||||
const dashPositiveColor = computed(() => store.state.dash_positive_color);
|
||||
const dashInfoColor = computed(() => store.state.dash_info_color);
|
||||
const formatDate = computed(() => store.getters.formatDate);
|
||||
const dash_info_color = computed(() => store.state.dash_info_color);
|
||||
const dash_positive_color = computed(() => store.state.dash_positive_color);
|
||||
const dash_negative_color = computed(() => store.state.dash_negative_color);
|
||||
const dash_warning_color = computed(() => store.state.dash_warning_color);
|
||||
|
||||
// setup quasar
|
||||
const $q = useQuasar();
|
||||
@@ -505,9 +508,7 @@ function showAddTask() {
|
||||
$q.dialog({
|
||||
component: AutomatedTaskForm,
|
||||
componentProps: {
|
||||
type: "agent",
|
||||
parent: selectedAgent.value,
|
||||
plat: agentPlatform.value,
|
||||
parent: { agent: selectedAgent.value },
|
||||
},
|
||||
}).onOk(() => {
|
||||
getTasks();
|
||||
@@ -521,9 +522,7 @@ function showEditTask(task) {
|
||||
component: AutomatedTaskForm,
|
||||
componentProps: {
|
||||
task: task,
|
||||
type: "agent",
|
||||
parent: selectedAgent.value,
|
||||
plat: agentPlatform.value,
|
||||
parent: { agent: selectedAgent.value },
|
||||
},
|
||||
}).onOk(() => {
|
||||
getTasks();
|
||||
@@ -548,4 +547,36 @@ watch(selectedAgent, (newValue) => {
|
||||
onMounted(() => {
|
||||
if (selectedAgent.value) getTasks();
|
||||
});
|
||||
|
||||
return {
|
||||
// reactive data
|
||||
tasks,
|
||||
loading,
|
||||
pagination,
|
||||
selectedAgent,
|
||||
tabHeight,
|
||||
agentPlatform,
|
||||
dash_info_color,
|
||||
dash_positive_color,
|
||||
dash_warning_color,
|
||||
dash_negative_color,
|
||||
|
||||
// non-reactive data
|
||||
columns,
|
||||
|
||||
// methods
|
||||
formatDate,
|
||||
getTasks,
|
||||
editTask,
|
||||
runWinTask,
|
||||
deleteTask,
|
||||
showAddTask,
|
||||
showEditTask,
|
||||
showScriptOutput,
|
||||
|
||||
// helpers
|
||||
truncateText,
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -293,8 +293,7 @@ export default {
|
||||
.dialog({
|
||||
component: AutomatedTaskForm,
|
||||
componentProps: {
|
||||
parent: this.selectedPolicy,
|
||||
type: "policy",
|
||||
parent: { policy: this.selectedPolicy },
|
||||
},
|
||||
})
|
||||
.onOk(this.getTasks);
|
||||
@@ -305,8 +304,7 @@ export default {
|
||||
component: AutomatedTaskForm,
|
||||
componentProps: {
|
||||
task: task,
|
||||
parent: this.selectedPolicy,
|
||||
type: "policy",
|
||||
parent: { policy: this.selectedPolicy },
|
||||
},
|
||||
})
|
||||
.onOk(this.getTasks);
|
||||
|
||||
@@ -1,394 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="row">
|
||||
<div class="text-subtitle2">Server Tasks</div>
|
||||
<q-space />
|
||||
<q-btn
|
||||
size="sm"
|
||||
color="grey-5"
|
||||
icon="fas fa-plus"
|
||||
text-color="black"
|
||||
label="Add Server Task"
|
||||
@click="addServerTask"
|
||||
/>
|
||||
</div>
|
||||
<q-separator />
|
||||
<q-table
|
||||
dense
|
||||
:rows="tasks"
|
||||
:columns="columns"
|
||||
:pagination="{ rowsPerPage: 0, sortBy: 'name', descending: true }"
|
||||
row-key="id"
|
||||
binary-state-sort
|
||||
hide-pagination
|
||||
virtual-scroll
|
||||
:rows-per-page-options="[0]"
|
||||
no-data-label="No Server Tasks added yet"
|
||||
>
|
||||
<template v-slot:header-cell-enabled="props">
|
||||
<q-th auto-width :props="props">
|
||||
<q-icon name="power_settings_new" size="1.5em">
|
||||
<q-tooltip>Enabled</q-tooltip>
|
||||
</q-icon>
|
||||
</q-th>
|
||||
</template>
|
||||
|
||||
<template v-slot:header-cell-smsalert="props">
|
||||
<q-th auto-width :props="props">
|
||||
<q-icon name="phone_android" size="1.5em">
|
||||
<q-tooltip>SMS Alert</q-tooltip>
|
||||
</q-icon>
|
||||
</q-th>
|
||||
</template>
|
||||
|
||||
<template v-slot:header-cell-emailalert="props">
|
||||
<q-th auto-width :props="props">
|
||||
<q-icon name="email" size="1.5em">
|
||||
<q-tooltip>Email Alert</q-tooltip>
|
||||
</q-icon>
|
||||
</q-th>
|
||||
</template>
|
||||
|
||||
<template v-slot:header-cell-dashboardalert="props">
|
||||
<q-th auto-width :props="props">
|
||||
<q-icon name="notifications" size="1.5em">
|
||||
<q-tooltip>Dashboard Alert</q-tooltip>
|
||||
</q-icon>
|
||||
</q-th>
|
||||
</template>
|
||||
|
||||
<template v-slot:header-cell-status="props">
|
||||
<q-th auto-width :props="props"></q-th>
|
||||
</template>
|
||||
|
||||
<!-- body slots -->
|
||||
<template v-slot:body="props">
|
||||
<q-tr
|
||||
:props="props"
|
||||
class="cursor-pointer"
|
||||
@dblclick="editServerTask(props.row)"
|
||||
>
|
||||
<!-- context menu -->
|
||||
<q-menu context-menu>
|
||||
<q-list dense style="min-width: 200px">
|
||||
<q-item
|
||||
clickable
|
||||
v-close-popup
|
||||
@click="editServerTask(props.row)"
|
||||
>
|
||||
<q-item-section side>
|
||||
<q-icon name="edit" />
|
||||
</q-item-section>
|
||||
<q-item-section>Edit</q-item-section>
|
||||
</q-item>
|
||||
<q-item
|
||||
clickable
|
||||
v-close-popup
|
||||
@click="deleteServerTask(props.row)"
|
||||
>
|
||||
<q-item-section side>
|
||||
<q-icon name="delete" />
|
||||
</q-item-section>
|
||||
<q-item-section>Delete</q-item-section>
|
||||
</q-item>
|
||||
|
||||
<q-separator />
|
||||
|
||||
<q-item
|
||||
clickable
|
||||
v-close-popup
|
||||
@click="executeServerTask(props.row)"
|
||||
>
|
||||
<q-item-section side>
|
||||
<q-icon name="play_arrow" />
|
||||
</q-item-section>
|
||||
<q-item-section>Run Server Task</q-item-section>
|
||||
</q-item>
|
||||
|
||||
<q-separator />
|
||||
|
||||
<q-item clickable v-close-popup>
|
||||
<q-item-section>Close</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
</q-menu>
|
||||
<!-- enabled -->
|
||||
<q-td>
|
||||
<q-checkbox
|
||||
dense
|
||||
v-model="props.row.enabled"
|
||||
@update:model-value="
|
||||
editTask(props.row.id, { enabled: props.row.enabled })
|
||||
"
|
||||
/>
|
||||
</q-td>
|
||||
<!-- text alert -->
|
||||
<q-td>
|
||||
<q-checkbox
|
||||
dense
|
||||
v-model="props.row.text_alert"
|
||||
@update:model-value="
|
||||
editTask(props.row.id, { text_alert: props.row.text_alert })
|
||||
"
|
||||
/>
|
||||
</q-td>
|
||||
<!-- email alert -->
|
||||
<q-td>
|
||||
<q-checkbox
|
||||
dense
|
||||
v-model="props.row.email_alert"
|
||||
@update:model-value="
|
||||
editTask(props.row.id, { email_alert: props.row.email_alert })
|
||||
"
|
||||
/>
|
||||
</q-td>
|
||||
<!-- dashboard alert -->
|
||||
<q-td>
|
||||
<q-checkbox
|
||||
dense
|
||||
v-model="props.row.dashboard_alert"
|
||||
@update:model-value="
|
||||
editTask(props.row.id, {
|
||||
dashboard_alert: props.row.dashboard_alert,
|
||||
})
|
||||
"
|
||||
/>
|
||||
</q-td>
|
||||
<!-- status icon -->
|
||||
<q-td v-if="Object.keys(props.row.task_result).length === 0"></q-td>
|
||||
<q-td v-else-if="props.row.task_result.status === 'passing'">
|
||||
<q-icon
|
||||
style="font-size: 1.3rem"
|
||||
:color="dashPositiveColor"
|
||||
name="check_circle"
|
||||
>
|
||||
<q-tooltip>Passing</q-tooltip>
|
||||
</q-icon>
|
||||
</q-td>
|
||||
<q-td v-else-if="props.row.task_result.status === 'failing'">
|
||||
<q-icon
|
||||
v-if="props.row.alert_severity === 'info'"
|
||||
style="font-size: 1.3rem"
|
||||
:color="dashInfoColor"
|
||||
name="info"
|
||||
>
|
||||
<q-tooltip>Informational</q-tooltip>
|
||||
</q-icon>
|
||||
<q-icon
|
||||
v-else-if="props.row.alert_severity === 'warning'"
|
||||
style="font-size: 1.3rem"
|
||||
:color="dashWarningColor"
|
||||
name="warning"
|
||||
>
|
||||
<q-tooltip>Warning</q-tooltip>
|
||||
</q-icon>
|
||||
<q-icon
|
||||
v-else
|
||||
style="font-size: 1.3rem"
|
||||
:color="dashNegativeColor"
|
||||
name="error"
|
||||
>
|
||||
<q-tooltip>Error</q-tooltip>
|
||||
</q-icon>
|
||||
</q-td>
|
||||
<q-td v-else></q-td>
|
||||
<!-- name -->
|
||||
<q-td>{{ props.row.name }}</q-td>
|
||||
<!-- schedule -->
|
||||
<q-td>{{
|
||||
props.row.crontab_schedule ? props.row.crontab_schedule : "Manual"
|
||||
}}</q-td>
|
||||
<!-- more info -->
|
||||
<q-td
|
||||
v-if="
|
||||
props.row.task_result.retcode !== null ||
|
||||
props.row.task_result.stdout ||
|
||||
props.row.task_result.stderr
|
||||
"
|
||||
>
|
||||
<span
|
||||
style="cursor: pointer; text-decoration: underline"
|
||||
class="text-primary"
|
||||
@click="showScriptOutput(props.row)"
|
||||
>output</span
|
||||
>
|
||||
</q-td>
|
||||
<q-td v-else>Awaiting output</q-td>
|
||||
<!-- last run -->
|
||||
<q-td v-if="props.row.task_result.last_run">{{
|
||||
formatDate(props.row.task_result.last_run)
|
||||
}}</q-td>
|
||||
<q-td v-else>Has not run yet</q-td>
|
||||
</q-tr>
|
||||
</template>
|
||||
</q-table>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
// composition imports
|
||||
import { ref, computed, onMounted } from "vue";
|
||||
import { useStore } from "vuex";
|
||||
import { QTableColumn, useQuasar } from "quasar";
|
||||
import { fetchServerTasks, removeServerTask, runServerTask } from "@/api/core";
|
||||
import { updateTask } from "@/api/tasks";
|
||||
import { notifyError, notifySuccess } from "@/utils/notify";
|
||||
|
||||
// ui imports
|
||||
import AutomatedTaskForm from "@/components/tasks/AutomatedTaskForm.vue";
|
||||
import ScriptOutput from "@/components/checks/ScriptOutput.vue";
|
||||
|
||||
// types
|
||||
import type { AutomatedTask } from "@/types/tasks";
|
||||
|
||||
// setup quasar
|
||||
const $q = useQuasar();
|
||||
|
||||
const store = useStore();
|
||||
|
||||
const dashWarningColor = computed(() => store.state.dash_warning_color);
|
||||
const dashNegativeColor = computed(() => store.state.dash_negative_color);
|
||||
const dashPositiveColor = computed(() => store.state.dash_positive_color);
|
||||
const dashInfoColor = computed(() => store.state.dash_info_color);
|
||||
const formatDate = computed(() => store.getters.formatDate);
|
||||
|
||||
const tasks = ref([] as AutomatedTask[]);
|
||||
|
||||
const columns: QTableColumn[] = [
|
||||
{ name: "enabled", align: "left", field: "enabled", label: "" },
|
||||
{ name: "smsalert", field: "text_alert", align: "left", label: "" },
|
||||
{ name: "emailalert", field: "email_alert", align: "left", label: "" },
|
||||
{
|
||||
name: "dashboardalert",
|
||||
field: "dashboard_alert",
|
||||
align: "left",
|
||||
label: "",
|
||||
},
|
||||
{ name: "status", field: "status", align: "left", label: "" },
|
||||
{
|
||||
name: "name",
|
||||
label: "Name",
|
||||
field: "name",
|
||||
align: "left",
|
||||
sortable: true,
|
||||
},
|
||||
{
|
||||
name: "crontab_schedule",
|
||||
label: "Schedule",
|
||||
field: "crontab_schedule",
|
||||
align: "left",
|
||||
sortable: true,
|
||||
},
|
||||
{
|
||||
name: "moreinfo",
|
||||
label: "More Info",
|
||||
field: "more_info",
|
||||
align: "left",
|
||||
sortable: true,
|
||||
},
|
||||
{
|
||||
name: "datetime",
|
||||
label: "Last Run Time",
|
||||
field: "last_run",
|
||||
align: "left",
|
||||
sortable: true,
|
||||
},
|
||||
];
|
||||
|
||||
async function getServerTasks() {
|
||||
$q.loading.show();
|
||||
try {
|
||||
const result = await fetchServerTasks();
|
||||
tasks.value = result;
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
|
||||
$q.loading.hide();
|
||||
}
|
||||
|
||||
function addServerTask() {
|
||||
$q.dialog({
|
||||
component: AutomatedTaskForm,
|
||||
componentProps: {
|
||||
type: "server",
|
||||
},
|
||||
}).onOk(getServerTasks);
|
||||
}
|
||||
|
||||
function editServerTask(task: AutomatedTask) {
|
||||
$q.dialog({
|
||||
component: AutomatedTaskForm,
|
||||
componentProps: {
|
||||
task: task,
|
||||
type: "server",
|
||||
},
|
||||
}).onOk(getServerTasks);
|
||||
}
|
||||
|
||||
async function executeServerTask(task: AutomatedTask) {
|
||||
try {
|
||||
const result = await runServerTask(task.id);
|
||||
|
||||
$q.dialog({
|
||||
component: ScriptOutput,
|
||||
componentProps: {
|
||||
scriptInfo: {
|
||||
stdout: result.output,
|
||||
execution_time: result.execution_time,
|
||||
stderr: "",
|
||||
},
|
||||
},
|
||||
});
|
||||
} catch {
|
||||
notifyError("Unable to run task");
|
||||
}
|
||||
}
|
||||
|
||||
function showScriptOutput(task: AutomatedTask) {
|
||||
$q.dialog({
|
||||
component: ScriptOutput,
|
||||
componentProps: {
|
||||
scriptInfo: task.task_result,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function deleteServerTask(task: AutomatedTask) {
|
||||
$q.dialog({
|
||||
title: `Delete Server Task: ${task.name}?`,
|
||||
cancel: true,
|
||||
ok: { label: "Delete", color: "negative" },
|
||||
}).onOk(async () => {
|
||||
$q.loading.show();
|
||||
|
||||
try {
|
||||
await removeServerTask(task.id);
|
||||
await getServerTasks();
|
||||
notifySuccess(`Server Task: ${task.name} was deleted!`);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
|
||||
$q.loading.hide();
|
||||
});
|
||||
}
|
||||
|
||||
interface EditTaskRequest {
|
||||
text_alert?: boolean;
|
||||
email_alert?: boolean;
|
||||
dashboard_alert?: boolean;
|
||||
enabled?: boolean;
|
||||
}
|
||||
|
||||
async function editTask(task_id: number, data: EditTaskRequest) {
|
||||
try {
|
||||
const result = await updateTask(task_id, data);
|
||||
notifySuccess(result);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(getServerTasks);
|
||||
</script>
|
||||
@@ -13,7 +13,6 @@
|
||||
<q-tab name="webhooks" label="Web Hooks" />
|
||||
<q-tab name="retention" label="Retention" />
|
||||
<q-tab name="apikeys" label="API Keys" />
|
||||
<!-- <q-tab name="tasks" label="Server Tasks" /> -->
|
||||
<!-- <q-tab name="openai" label="Open AI" /> -->
|
||||
</q-tabs>
|
||||
</template>
|
||||
@@ -616,9 +615,6 @@
|
||||
</q-input>
|
||||
</q-card-section>
|
||||
</q-tab-panel> -->
|
||||
<!-- <q-tab-panel name="tasks">
|
||||
<ServerTasksTable />
|
||||
</q-tab-panel> -->
|
||||
</q-tab-panels>
|
||||
</q-scroll-area>
|
||||
<q-card-section class="row items-center">
|
||||
@@ -663,7 +659,6 @@ import CustomFields from "@/components/modals/coresettings/CustomFields.vue";
|
||||
import KeyStoreTable from "@/components/modals/coresettings/KeyStoreTable.vue";
|
||||
import URLActionsTable from "@/components/modals/coresettings/URLActionsTable.vue";
|
||||
import APIKeysTable from "@/components/core/APIKeysTable.vue";
|
||||
// import ServerTasksTable from "@/components/core/ServerTasksTable.vue";
|
||||
|
||||
export default {
|
||||
name: "EditCoreSettings",
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<q-bar>
|
||||
{{
|
||||
task
|
||||
? `Editing Automated Task: ${localTask.name}`
|
||||
? `Editing Automated Task: ${task.name}`
|
||||
: "Adding Automated Task"
|
||||
}}
|
||||
<q-space />
|
||||
@@ -29,32 +29,32 @@
|
||||
:rules="[(val) => !!val || '*Required']"
|
||||
filled
|
||||
dense
|
||||
v-model="localTask.name"
|
||||
v-model="state.name"
|
||||
label="Descriptive name of task"
|
||||
hide-bottom-space
|
||||
/>
|
||||
</q-card-section>
|
||||
<q-card-section v-if="type !== 'server'">
|
||||
<q-card-section>
|
||||
<q-checkbox
|
||||
dense
|
||||
label="Collector Task"
|
||||
v-model="collector"
|
||||
class="q-pb-sm"
|
||||
@update:model-value="
|
||||
localTask.custom_field = undefined;
|
||||
localTask.collector_all_output = false;
|
||||
state.custom_field = null;
|
||||
state.collector_all_output = false;
|
||||
"
|
||||
/>
|
||||
<tactical-dropdown
|
||||
v-if="collector"
|
||||
:rules="[(val: number) => !!val || '*Required']"
|
||||
v-model="localTask.custom_field"
|
||||
:rules="[(val) => !!val || '*Required']"
|
||||
v-model="state.custom_field"
|
||||
:options="customFieldOptions"
|
||||
label="Custom Field to update"
|
||||
filled
|
||||
mapOptions
|
||||
:hint="
|
||||
localTask.collector_all_output
|
||||
state.collector_all_output
|
||||
? 'All script output will be saved to custom field selected'
|
||||
: 'The last line of script output will be saved to custom field selected'
|
||||
"
|
||||
@@ -64,18 +64,18 @@
|
||||
v-if="collector"
|
||||
dense
|
||||
label="Save all output"
|
||||
v-model="localTask.collector_all_output"
|
||||
v-model="state.collector_all_output"
|
||||
class="q-py-sm"
|
||||
/>
|
||||
</q-card-section>
|
||||
<q-card-section>
|
||||
<tactical-dropdown
|
||||
v-model="localTask.alert_severity"
|
||||
v-model="state.alert_severity"
|
||||
:options="severityOptions"
|
||||
label="Alert Severity"
|
||||
filled
|
||||
mapOptions
|
||||
:rules="[(val: string) => !!val || '*Required']"
|
||||
:rules="[(val) => !!val || '*Required']"
|
||||
/>
|
||||
</q-card-section>
|
||||
</q-form>
|
||||
@@ -106,7 +106,7 @@
|
||||
class="col-3"
|
||||
label="Select script"
|
||||
v-model="script"
|
||||
:options="filterByPlatformOptions"
|
||||
:options="scriptOptions"
|
||||
filled
|
||||
mapOptions
|
||||
filterable
|
||||
@@ -170,7 +170,7 @@
|
||||
label="Timeout (seconds)"
|
||||
/>
|
||||
<q-option-group
|
||||
v-if="actionType === 'cmd' && type !== 'server'"
|
||||
v-if="actionType === 'cmd'"
|
||||
class="col-2 q-pl-sm"
|
||||
inline
|
||||
v-model="shell"
|
||||
@@ -195,7 +195,7 @@
|
||||
<q-checkbox
|
||||
class="float-right"
|
||||
label="Continue on Errors"
|
||||
v-model="localTask.continue_on_error"
|
||||
v-model="state.continue_on_error"
|
||||
dense
|
||||
>
|
||||
<q-tooltip>Continue task if an action fails</q-tooltip>
|
||||
@@ -206,7 +206,7 @@
|
||||
class="q-list"
|
||||
handle=".handle"
|
||||
ghost-class="ghost"
|
||||
v-model="localTask.actions"
|
||||
v-model="state.actions"
|
||||
item-key="index"
|
||||
>
|
||||
<template v-slot:item="{ index, element }">
|
||||
@@ -238,7 +238,6 @@
|
||||
<q-icon size="sm" name="terminal" color="primary" />
|
||||
|
||||
<q-icon
|
||||
v-if="type !== 'server'"
|
||||
size="sm"
|
||||
:name="
|
||||
element.shell === 'cmd'
|
||||
@@ -247,12 +246,6 @@
|
||||
"
|
||||
color="primary"
|
||||
/>
|
||||
<q-icon
|
||||
v-else
|
||||
size="sm"
|
||||
name="mdi-bash"
|
||||
color="primary"
|
||||
/>
|
||||
{{ element.command }}
|
||||
</q-item-label>
|
||||
<q-item-label caption>
|
||||
@@ -277,26 +270,14 @@
|
||||
<q-step :name="3" title="Choose Schedule" :error="!isValidStep3">
|
||||
<div class="scroll" style="height: 60vh; max-height: 60vh">
|
||||
<q-form @submit.prevent ref="taskDetailForm">
|
||||
<!-- form for server and linux agents -->
|
||||
<q-card-section v-if="type === 'server'">
|
||||
<q-input
|
||||
v-model="localTask.crontab_schedule"
|
||||
label="Crontab Schedule"
|
||||
dense
|
||||
inline
|
||||
hint="The schedule portion of a crontab entry. i.e. * * * 1 *. Leave blank for manual"
|
||||
/>
|
||||
</q-card-section>
|
||||
<!-- form for policy and windows agents-->
|
||||
<div v-else>
|
||||
<q-card-section>
|
||||
<q-option-group
|
||||
v-model="localTask.task_type"
|
||||
v-model="state.task_type"
|
||||
label="Task run type"
|
||||
:options="agentTaskTypeOptions"
|
||||
:options="taskTypeOptions"
|
||||
dense
|
||||
inline
|
||||
@update:model-value="taskDetailForm?.resetValidation()"
|
||||
@update:model-value="$refs.taskDetailForm.resetValidation()"
|
||||
/>
|
||||
</q-card-section>
|
||||
|
||||
@@ -304,7 +285,7 @@
|
||||
<q-card-section
|
||||
v-if="
|
||||
['runonce', 'daily', 'weekly', 'monthly'].includes(
|
||||
localTask.task_type,
|
||||
state.task_type,
|
||||
)
|
||||
"
|
||||
class="row"
|
||||
@@ -317,7 +298,7 @@
|
||||
label="Start time"
|
||||
stack-label
|
||||
filled
|
||||
v-model="localTask.run_time_date"
|
||||
v-model="state.run_time_date"
|
||||
hint="Agent timezone will be used"
|
||||
:rules="[(val) => !!val || '*Required']"
|
||||
/>
|
||||
@@ -330,32 +311,29 @@
|
||||
stack-label
|
||||
label="Expires on"
|
||||
filled
|
||||
v-model="localTask.expire_date"
|
||||
v-model="state.expire_date"
|
||||
hint="Agent timezone will be used"
|
||||
/>
|
||||
</q-card-section>
|
||||
|
||||
<q-card-section
|
||||
v-if="
|
||||
localTask.task_type === 'onboarding' ||
|
||||
localTask.task_type === 'runonce'
|
||||
state.task_type === 'onboarding' ||
|
||||
state.task_type === 'runonce'
|
||||
"
|
||||
class="row"
|
||||
>
|
||||
<span v-if="localTask.task_type === 'onboarding'"
|
||||
<span v-if="state.task_type === 'onboarding'"
|
||||
>This task will run as soon as it's created on the
|
||||
agent.</span
|
||||
>
|
||||
<span v-else-if="localTask.task_type === 'runonce'"
|
||||
<span v-else-if="state.task_type === 'runonce'"
|
||||
>Start Time must be in the future for run once tasks.</span
|
||||
>
|
||||
</q-card-section>
|
||||
|
||||
<!-- daily options -->
|
||||
<q-card-section
|
||||
v-if="localTask.task_type === 'daily'"
|
||||
class="row"
|
||||
>
|
||||
<q-card-section v-if="state.task_type === 'daily'" class="row">
|
||||
<!-- daily interval -->
|
||||
<q-input
|
||||
:rules="[
|
||||
@@ -367,7 +345,7 @@
|
||||
dense
|
||||
type="number"
|
||||
label="Run every"
|
||||
v-model.number="localTask.daily_interval"
|
||||
v-model.number="state.daily_interval"
|
||||
filled
|
||||
class="col-6 q-pa-sm"
|
||||
>
|
||||
@@ -379,10 +357,7 @@
|
||||
</q-card-section>
|
||||
|
||||
<!-- weekly options -->
|
||||
<q-card-section
|
||||
v-if="localTask.task_type === 'weekly'"
|
||||
class="row"
|
||||
>
|
||||
<q-card-section v-if="state.task_type === 'weekly'" class="row">
|
||||
<!-- weekly interval -->
|
||||
<q-input
|
||||
:rules="[
|
||||
@@ -394,7 +369,7 @@
|
||||
class="col-6 q-pa-sm"
|
||||
dense
|
||||
label="Run every"
|
||||
v-model="localTask.weekly_interval"
|
||||
v-model="state.weekly_interval"
|
||||
filled
|
||||
>
|
||||
<template v-slot:append>
|
||||
@@ -408,23 +383,18 @@
|
||||
<!-- day of week input -->
|
||||
Run on Days:
|
||||
<q-option-group
|
||||
:rules="[
|
||||
(val: number[]) => val.length > 0 || '*Required',
|
||||
]"
|
||||
:rules="[(val) => val.length > 0 || '*Required']"
|
||||
inline
|
||||
dense
|
||||
:options="dayOfWeekOptions"
|
||||
type="checkbox"
|
||||
v-model="localTask.run_time_bit_weekdays"
|
||||
v-model="state.run_time_bit_weekdays"
|
||||
/>
|
||||
</div>
|
||||
</q-card-section>
|
||||
|
||||
<!-- monthly options -->
|
||||
<q-card-section
|
||||
v-if="localTask.task_type === 'monthly'"
|
||||
class="row"
|
||||
>
|
||||
<q-card-section v-if="state.task_type === 'monthly'" class="row">
|
||||
<!-- type of monthly schedule -->
|
||||
<q-option-group
|
||||
class="col-12 q-pa-sm"
|
||||
@@ -443,7 +413,7 @@
|
||||
filled
|
||||
dense
|
||||
options-dense
|
||||
v-model="localTask.monthly_months_of_year"
|
||||
v-model="state.monthly_months_of_year"
|
||||
:options="monthOptions"
|
||||
label="Run on Months"
|
||||
multiple
|
||||
@@ -494,7 +464,7 @@
|
||||
filled
|
||||
dense
|
||||
options-dense
|
||||
v-model="localTask.monthly_days_of_month"
|
||||
v-model="state.monthly_days_of_month"
|
||||
:options="dayOfMonthOptions"
|
||||
label="Run on Days"
|
||||
multiple
|
||||
@@ -547,7 +517,7 @@
|
||||
filled
|
||||
dense
|
||||
options-dense
|
||||
v-model="localTask.monthly_weeks_of_month"
|
||||
v-model="state.monthly_weeks_of_month"
|
||||
:options="weekOptions"
|
||||
label="Run on weeks"
|
||||
multiple
|
||||
@@ -580,7 +550,7 @@
|
||||
filled
|
||||
dense
|
||||
options-dense
|
||||
v-model="localTask.run_time_bit_weekdays"
|
||||
v-model="state.run_time_bit_weekdays"
|
||||
:options="dayOfWeekOptions"
|
||||
label="Run on days"
|
||||
multiple
|
||||
@@ -626,9 +596,9 @@
|
||||
|
||||
<q-card-section
|
||||
v-if="
|
||||
localTask.task_type !== 'checkfailure' &&
|
||||
localTask.task_type !== 'manual' &&
|
||||
localTask.task_type !== 'onboarding'
|
||||
state.task_type !== 'checkfailure' &&
|
||||
state.task_type !== 'manual' &&
|
||||
state.task_type !== 'onboarding'
|
||||
"
|
||||
class="row"
|
||||
>
|
||||
@@ -638,7 +608,7 @@
|
||||
dense
|
||||
label="Repeat task every"
|
||||
filled
|
||||
v-model="localTask.task_repetition_interval"
|
||||
v-model="state.task_repetition_interval"
|
||||
placeholder="e.g. 30m (30 minutes) or 1h (1 hour)"
|
||||
lazy-rules
|
||||
:rules="[
|
||||
@@ -650,34 +620,33 @@
|
||||
/>
|
||||
|
||||
<q-input
|
||||
:disable="!localTask.task_repetition_interval"
|
||||
:disable="!state.task_repetition_interval"
|
||||
class="col-6 q-pa-sm"
|
||||
dense
|
||||
label="Task repeat duration"
|
||||
filled
|
||||
v-model="localTask.task_repetition_duration"
|
||||
v-model="state.task_repetition_duration"
|
||||
placeholder="e.g. 6h (6 hours) or 1d (1 day)"
|
||||
lazy-rules
|
||||
:rules="[
|
||||
(val: string) =>
|
||||
(val) =>
|
||||
validateTimePeriod(val) ||
|
||||
'Valid values are 1-3 digits followed by (D|d|H|h|M|m|S|s)',
|
||||
(val: string) =>
|
||||
localTask.task_repetition_interval ? !!val : true, // field is required if repetition interval is set
|
||||
(val: string) =>
|
||||
(val) => (state.task_repetition_interval ? !!val : true), // field is required if repetition interval is set
|
||||
(val) =>
|
||||
convertPeriodToSeconds(val) >=
|
||||
convertPeriodToSeconds(
|
||||
localTask?.task_repetition_interval,
|
||||
state.task_repetition_interval,
|
||||
) ||
|
||||
'Repetition duration must be greater than repetition interval',
|
||||
]"
|
||||
/>
|
||||
|
||||
<q-checkbox
|
||||
:disable="!localTask.task_repetition_interval"
|
||||
:disable="!state.task_repetition_interval"
|
||||
class="col-6 q-pa-sm"
|
||||
dense
|
||||
v-model="localTask.stop_task_at_duration_end"
|
||||
v-model="state.stop_task_at_duration_end"
|
||||
label="Stop all tasks at the end of duration"
|
||||
/>
|
||||
<div class="col-6"></div>
|
||||
@@ -687,7 +656,7 @@
|
||||
dense
|
||||
label="Random task delay"
|
||||
filled
|
||||
v-model="localTask.random_task_delay"
|
||||
v-model="state.random_task_delay"
|
||||
placeholder="e.g. 2m (2 minutes) or 1h (1 hour)"
|
||||
lazy-rules
|
||||
:rules="[
|
||||
@@ -699,20 +668,20 @@
|
||||
/>
|
||||
<div class="col-6"></div>
|
||||
<q-checkbox
|
||||
:disable="!localTask.expire_date"
|
||||
:disable="!state.expire_date"
|
||||
class="col-6 q-pa-sm"
|
||||
dense
|
||||
v-model="localTask.remove_if_not_scheduled"
|
||||
v-model="state.remove_if_not_scheduled"
|
||||
label="Delete task if not scheduled for 30 days"
|
||||
>
|
||||
<q-tooltip>Must set an expire date</q-tooltip>
|
||||
</q-checkbox>
|
||||
<div class="col-6"></div>
|
||||
<q-checkbox
|
||||
:disable="localTask.task_type === 'runonce'"
|
||||
:disable="state.task_type === 'runonce'"
|
||||
class="col-6 q-pa-sm"
|
||||
dense
|
||||
v-model="localTask.run_asap_after_missed"
|
||||
v-model="state.run_asap_after_missed"
|
||||
label="Run task ASAP after a scheduled start is missed"
|
||||
/>
|
||||
|
||||
@@ -722,7 +691,7 @@
|
||||
class="col-6 q-pa-sm"
|
||||
label="Task instance policy"
|
||||
:options="taskInstancePolicyOptions"
|
||||
v-model="localTask.task_instance_policy"
|
||||
v-model="state.task_instance_policy"
|
||||
filled
|
||||
mapOptions
|
||||
/>
|
||||
@@ -730,13 +699,13 @@
|
||||
|
||||
<!-- check failure options -->
|
||||
<q-card-section
|
||||
v-else-if="localTask.task_type === 'checkfailure'"
|
||||
v-else-if="state.task_type === 'checkfailure'"
|
||||
class="row"
|
||||
>
|
||||
<tactical-dropdown
|
||||
class="col-6 q-pa-sm"
|
||||
:rules="[(val: number) => !!val || '*Required']"
|
||||
v-model="localTask.assigned_check"
|
||||
:rules="[(val) => !!val || '*Required']"
|
||||
v-model="state.assigned_check"
|
||||
filled
|
||||
:options="checkOptions"
|
||||
label="Select Check"
|
||||
@@ -744,7 +713,6 @@
|
||||
filterable
|
||||
/>
|
||||
</q-card-section>
|
||||
</div>
|
||||
</q-form>
|
||||
</div>
|
||||
</q-step>
|
||||
@@ -754,13 +722,18 @@
|
||||
<q-btn
|
||||
v-if="step > 1"
|
||||
label="Back"
|
||||
@click="stepper?.previous()"
|
||||
@click="$refs.stepper.previous()"
|
||||
color="primary"
|
||||
flat
|
||||
/>
|
||||
<q-btn
|
||||
v-if="step < 3"
|
||||
@click="validateStep(step === 1 ? taskGeneralForm : null, stepper)"
|
||||
@click="
|
||||
validateStep(
|
||||
step === 1 ? $refs.taskGeneralForm : undefined,
|
||||
$refs.stepper,
|
||||
)
|
||||
"
|
||||
color="primary"
|
||||
label="Next"
|
||||
flat
|
||||
@@ -769,7 +742,7 @@
|
||||
v-else
|
||||
:label="task ? 'Edit Task' : 'Add Task'"
|
||||
color="primary"
|
||||
@click="validateStep(taskDetailForm, stepper)"
|
||||
@click="validateStep($refs.taskDetailForm, $refs.stepper)"
|
||||
:loading="loading"
|
||||
flat
|
||||
dense
|
||||
@@ -780,10 +753,10 @@
|
||||
</q-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
<script>
|
||||
// composition imports
|
||||
import { ref, watch, onMounted, reactive } from "vue";
|
||||
import { QForm, QStepper, useDialogPluginComponent } from "quasar";
|
||||
import { ref, watch, onMounted, defineComponent } from "vue";
|
||||
import { useDialogPluginComponent } from "quasar";
|
||||
import draggable from "vuedraggable";
|
||||
import { saveTask, updateTask } from "@/api/tasks";
|
||||
import { useScriptDropdown } from "@/composables/scripts";
|
||||
@@ -797,21 +770,11 @@ import {
|
||||
convertToBitArray,
|
||||
convertFromBitArray,
|
||||
formatDateInputField,
|
||||
copyObjectWithoutKeys,
|
||||
} from "@/utils/format";
|
||||
|
||||
// ui imports
|
||||
import TacticalDropdown from "@/components/ui/TacticalDropdown.vue";
|
||||
|
||||
// type
|
||||
import type {
|
||||
AutomatedTask,
|
||||
AutomatedTaskAction,
|
||||
AutomatedTaskForDB,
|
||||
AutomatedTaskCommandActionShellType,
|
||||
} from "@/types/tasks";
|
||||
import type { AgentPlatformType } from "@/types/agents";
|
||||
|
||||
// static data
|
||||
const severityOptions = [
|
||||
{ label: "Informational", value: "info" },
|
||||
@@ -819,7 +782,7 @@ const severityOptions = [
|
||||
{ label: "Error", value: "error" },
|
||||
];
|
||||
|
||||
const agentTaskTypeOptions = [
|
||||
const taskTypeOptions = [
|
||||
{ label: "Daily", value: "daily" },
|
||||
{ label: "Weekly", value: "weekly" },
|
||||
{ label: "Monthly", value: "monthly" },
|
||||
@@ -880,87 +843,69 @@ const taskInstancePolicyOptions = [
|
||||
{ label: "Stop Existing", value: 3 },
|
||||
];
|
||||
|
||||
// emits
|
||||
defineEmits([...useDialogPluginComponent.emits]);
|
||||
|
||||
// props
|
||||
const props = defineProps<{
|
||||
parent?: number | string; // parent policy or agent for task
|
||||
type: "agent" | "policy" | "server";
|
||||
task?: AutomatedTaskForDB; // only for editing
|
||||
plat?: AgentPlatformType; // filters scripts options base on plat
|
||||
}>();
|
||||
|
||||
export default defineComponent({
|
||||
components: { TacticalDropdown, draggable },
|
||||
name: "AddAutomatedTask",
|
||||
emits: [...useDialogPluginComponent.emits],
|
||||
props: {
|
||||
parent: Object, // parent policy or agent for task
|
||||
task: Object, // only for editing
|
||||
},
|
||||
setup(props) {
|
||||
// setup quasar dialog
|
||||
const { dialogRef, onDialogHide, onDialogOK } = useDialogPluginComponent();
|
||||
|
||||
// setup dropdowns
|
||||
const {
|
||||
script,
|
||||
scriptName,
|
||||
scriptOptions,
|
||||
plat,
|
||||
filterByPlatformOptions,
|
||||
defaultTimeout,
|
||||
defaultArgs,
|
||||
defaultEnvVars,
|
||||
scriptName,
|
||||
} = useScriptDropdown({
|
||||
onMount: true,
|
||||
});
|
||||
|
||||
// set plat
|
||||
plat.value =
|
||||
props.type === "policy"
|
||||
? undefined // get all scripts
|
||||
: props.type === "server"
|
||||
? "linux" // get only linux scripts for server
|
||||
: props.plat; // filter scripts based on supported plat
|
||||
|
||||
// set defaultTimeout to 30
|
||||
defaultTimeout.value = 30;
|
||||
|
||||
const { checkOptions, getCheckOptions } = useCheckDropdown();
|
||||
const { checkOptions, getCheckOptions } = useCheckDropdown(...props.parent);
|
||||
const { customFieldOptions } = useCustomFieldDropdown({ onMount: true });
|
||||
|
||||
// add task logic
|
||||
const localTask: AutomatedTask = props.task
|
||||
? reactive(Object.assign({}, processTaskDatafromDB(props.task)))
|
||||
: (reactive({
|
||||
id: 0,
|
||||
policy: props.type === "policy" ? props.parent : undefined,
|
||||
agent: props.type === "agent" ? props.parent : undefined,
|
||||
server_task: props.type === "server",
|
||||
crontab_schedule: "",
|
||||
actions: [] as AutomatedTaskAction[],
|
||||
assigned_check: undefined,
|
||||
custom_field: undefined,
|
||||
name: "",
|
||||
expire_date: undefined,
|
||||
const task = props.task
|
||||
? ref(Object.assign({}, props.task))
|
||||
: ref({
|
||||
...props.parent,
|
||||
actions: [],
|
||||
assigned_check: null,
|
||||
custom_field: null,
|
||||
name: null,
|
||||
expire_date: null,
|
||||
run_time_date: formatDateInputField(Date.now()),
|
||||
run_time_bit_weekdays: [] as number[],
|
||||
run_time_bit_weekdays: [],
|
||||
weekly_interval: 1,
|
||||
daily_interval: 1,
|
||||
monthly_months_of_year: [] as number[],
|
||||
monthly_days_of_month: [] as number[],
|
||||
monthly_weeks_of_month: [] as number[],
|
||||
monthly_months_of_year: [],
|
||||
monthly_days_of_month: [],
|
||||
monthly_weeks_of_month: [],
|
||||
task_instance_policy: 0,
|
||||
task_repetition_interval: undefined,
|
||||
task_repetition_duration: undefined,
|
||||
task_repetition_interval: null,
|
||||
task_repetition_duration: null,
|
||||
stop_task_at_duration_end: false,
|
||||
random_task_delay: undefined,
|
||||
random_task_delay: null,
|
||||
remove_if_not_scheduled: false,
|
||||
run_asap_after_missed: true,
|
||||
task_type: "daily",
|
||||
alert_severity: "info",
|
||||
collector_all_output: false,
|
||||
continue_on_error: true,
|
||||
}) as AutomatedTask);
|
||||
});
|
||||
|
||||
const actionType = ref("script");
|
||||
const command = ref("");
|
||||
const shell = ref<AutomatedTaskCommandActionShellType>(
|
||||
props.type !== "server" ? "cmd" : "bash",
|
||||
);
|
||||
const shell = ref("cmd");
|
||||
const monthlyType = ref("days");
|
||||
const collector = ref(false);
|
||||
const loading = ref(false);
|
||||
@@ -970,21 +915,21 @@ const loading = ref(false);
|
||||
// if all months is selected or cleared it will either clear the monthly_months_of_year array or add all options to it.
|
||||
const allMonthsCheckbox = ref(false);
|
||||
function toggleMonths() {
|
||||
localTask.monthly_months_of_year = allMonthsCheckbox.value
|
||||
task.value.monthly_months_of_year = allMonthsCheckbox.value
|
||||
? monthOptions.map((month) => month.value)
|
||||
: [];
|
||||
}
|
||||
|
||||
const allMonthDaysCheckbox = ref(false);
|
||||
function toggleMonthDays() {
|
||||
localTask.monthly_days_of_month = allMonthDaysCheckbox.value
|
||||
task.value.monthly_days_of_month = allMonthDaysCheckbox.value
|
||||
? dayOfMonthOptions.map((day) => day.value)
|
||||
: [];
|
||||
}
|
||||
|
||||
const allWeekDaysCheckbox = ref(false);
|
||||
function toggleWeekDays() {
|
||||
localTask.run_time_bit_weekdays = allWeekDaysCheckbox.value
|
||||
task.value.run_time_bit_weekdays = allWeekDaysCheckbox.value
|
||||
? dayOfWeekOptions.map((day) => day.value)
|
||||
: [];
|
||||
}
|
||||
@@ -1006,8 +951,7 @@ function addAction() {
|
||||
}
|
||||
|
||||
if (actionType.value === "script") {
|
||||
if (script.value)
|
||||
localTask.actions.push({
|
||||
task.value.actions.push({
|
||||
type: "script",
|
||||
name: scriptName.value,
|
||||
script: script.value,
|
||||
@@ -1016,7 +960,7 @@ function addAction() {
|
||||
env_vars: defaultEnvVars.value,
|
||||
});
|
||||
} else if (actionType.value === "cmd") {
|
||||
localTask.actions.push({
|
||||
task.value.actions.push({
|
||||
type: "cmd",
|
||||
command: command.value,
|
||||
shell: shell.value,
|
||||
@@ -1025,56 +969,50 @@ function addAction() {
|
||||
}
|
||||
|
||||
// clear fields after add
|
||||
script.value = undefined;
|
||||
script.value = null;
|
||||
defaultArgs.value = [];
|
||||
defaultEnvVars.value = [];
|
||||
defaultTimeout.value = 30;
|
||||
command.value = "";
|
||||
}
|
||||
|
||||
function removeAction(index: number) {
|
||||
localTask.actions.splice(index, 1);
|
||||
function removeAction(index) {
|
||||
task.value.actions.splice(index, 1);
|
||||
}
|
||||
|
||||
// runs whenever task data is saved
|
||||
function processTaskDataforDB(taskData: AutomatedTask): AutomatedTaskForDB {
|
||||
function processTaskDataforDB(taskData) {
|
||||
// copy data
|
||||
let data = Object.assign({}, taskData);
|
||||
|
||||
// converts fields from arrays to integers
|
||||
const run_time_bit_weekdays =
|
||||
data.run_time_bit_weekdays =
|
||||
taskData.run_time_bit_weekdays.length > 0
|
||||
? convertFromBitArray(taskData.run_time_bit_weekdays)
|
||||
: undefined;
|
||||
: null;
|
||||
|
||||
const monthly_months_of_year =
|
||||
data.monthly_months_of_year =
|
||||
taskData.monthly_months_of_year.length > 0
|
||||
? convertFromBitArray(taskData.monthly_months_of_year)
|
||||
: undefined;
|
||||
: null;
|
||||
|
||||
const monthly_days_of_month =
|
||||
data.monthly_days_of_month =
|
||||
taskData.monthly_days_of_month.length > 0
|
||||
? convertFromBitArray(taskData.monthly_days_of_month)
|
||||
: undefined;
|
||||
: null;
|
||||
|
||||
const monthly_weeks_of_month =
|
||||
data.monthly_weeks_of_month =
|
||||
taskData.monthly_weeks_of_month.length > 0
|
||||
? convertFromBitArray(taskData.monthly_weeks_of_month)
|
||||
: undefined;
|
||||
: null;
|
||||
|
||||
let data = {
|
||||
...taskData,
|
||||
...{
|
||||
run_time_bit_weekdays,
|
||||
monthly_months_of_year,
|
||||
monthly_days_of_month,
|
||||
monthly_weeks_of_month,
|
||||
},
|
||||
} as AutomatedTaskForDB;
|
||||
// Add Z back to run_time_date and expires_date
|
||||
if (!taskData.server_task) data.run_time_date += "Z";
|
||||
data.run_time_date += "Z";
|
||||
|
||||
if (taskData.expire_date) data.expire_date += "Z";
|
||||
|
||||
// change task type if monthly day of week is set
|
||||
if (taskData.task_type === "monthly" && monthlyType.value === "weeks") {
|
||||
if (task.value.task_type === "monthly" && monthlyType.value === "weeks") {
|
||||
data.task_type = "monthlydow";
|
||||
}
|
||||
|
||||
@@ -1082,56 +1020,46 @@ function processTaskDataforDB(taskData: AutomatedTask): AutomatedTaskForDB {
|
||||
}
|
||||
|
||||
// runs when editing a task to convert values to be compatible with quasar
|
||||
function processTaskDatafromDB(task: AutomatedTaskForDB) {
|
||||
const convertedTask = copyObjectWithoutKeys(task, [
|
||||
"run_time_bit_weekdays",
|
||||
"monthly_months_of_year",
|
||||
"monthly_days_of_month",
|
||||
"monthly_weeks_of_month",
|
||||
]) as AutomatedTask;
|
||||
|
||||
function processTaskDatafromDB() {
|
||||
// converts fields from integers to arrays
|
||||
convertedTask.run_time_bit_weekdays = task.run_time_bit_weekdays
|
||||
? convertToBitArray(task.run_time_bit_weekdays)
|
||||
task.value.run_time_bit_weekdays = task.value.run_time_bit_weekdays
|
||||
? convertToBitArray(task.value.run_time_bit_weekdays)
|
||||
: [];
|
||||
convertedTask.monthly_months_of_year = task.monthly_months_of_year
|
||||
? convertToBitArray(task.monthly_months_of_year)
|
||||
task.value.monthly_months_of_year = task.value.monthly_months_of_year
|
||||
? convertToBitArray(task.value.monthly_months_of_year)
|
||||
: [];
|
||||
convertedTask.monthly_days_of_month = task.monthly_days_of_month
|
||||
? convertToBitArray(task.monthly_days_of_month)
|
||||
task.value.monthly_days_of_month = task.value.monthly_days_of_month
|
||||
? convertToBitArray(task.value.monthly_days_of_month)
|
||||
: [];
|
||||
convertedTask.monthly_weeks_of_month = task.monthly_weeks_of_month
|
||||
? convertToBitArray(task.monthly_weeks_of_month)
|
||||
task.value.monthly_weeks_of_month = task.value.monthly_weeks_of_month
|
||||
? convertToBitArray(task.value.monthly_weeks_of_month)
|
||||
: [];
|
||||
|
||||
// remove milliseconds and Z to work with native date input
|
||||
if (!task.server_task)
|
||||
convertedTask.run_time_date = formatDateInputField(
|
||||
convertedTask.run_time_date,
|
||||
task.value.run_time_date = formatDateInputField(
|
||||
task.value.run_time_date,
|
||||
true,
|
||||
);
|
||||
|
||||
if (convertedTask.expire_date)
|
||||
convertedTask.expire_date = formatDateInputField(
|
||||
convertedTask.expire_date,
|
||||
if (task.value.expire_date)
|
||||
task.value.expire_date = formatDateInputField(
|
||||
task.value.expire_date,
|
||||
true,
|
||||
);
|
||||
|
||||
// set task type if monthlydow is being used
|
||||
if (task.task_type === "monthlydow") {
|
||||
convertedTask.task_type = "monthly";
|
||||
if (task.value.task_type === "monthlydow") {
|
||||
task.value.task_type = "monthly";
|
||||
monthlyType.value = "weeks";
|
||||
}
|
||||
|
||||
return convertedTask;
|
||||
}
|
||||
|
||||
async function submit() {
|
||||
loading.value = true;
|
||||
try {
|
||||
const result = props.task
|
||||
? await updateTask(localTask.id, processTaskDataforDB(localTask))
|
||||
: await saveTask(processTaskDataforDB(localTask));
|
||||
? await updateTask(task.value.id, processTaskDataforDB(task.value))
|
||||
: await saveTask(processTaskDataforDB(task.value));
|
||||
notifySuccess(result);
|
||||
onDialogOK();
|
||||
} catch (e) {
|
||||
@@ -1140,23 +1068,26 @@ async function submit() {
|
||||
loading.value = false;
|
||||
}
|
||||
|
||||
// format task data to match what quasar expects if editing
|
||||
if (props.task) processTaskDatafromDB();
|
||||
|
||||
watch(
|
||||
() => localTask.task_type,
|
||||
() => task.value.task_type,
|
||||
() => {
|
||||
localTask.assigned_check = undefined;
|
||||
localTask.run_time_bit_weekdays = [];
|
||||
localTask.remove_if_not_scheduled = false;
|
||||
localTask.task_repetition_interval = undefined;
|
||||
localTask.task_repetition_duration = undefined;
|
||||
localTask.stop_task_at_duration_end = false;
|
||||
localTask.random_task_delay = undefined;
|
||||
localTask.weekly_interval = 1;
|
||||
localTask.daily_interval = 1;
|
||||
localTask.monthly_months_of_year = [];
|
||||
localTask.monthly_days_of_month = [];
|
||||
localTask.monthly_weeks_of_month = [];
|
||||
localTask.task_instance_policy = 0;
|
||||
localTask.expire_date = undefined;
|
||||
task.value.assigned_check = null;
|
||||
task.value.run_time_bit_weekdays = [];
|
||||
task.value.remove_if_not_scheduled = false;
|
||||
task.value.task_repetition_interval = null;
|
||||
task.value.task_repetition_duration = null;
|
||||
task.value.stop_task_at_duration_end = false;
|
||||
task.value.random_task_delay = null;
|
||||
task.value.weekly_interval = 1;
|
||||
task.value.daily_interval = 1;
|
||||
task.value.monthly_months_of_year = [];
|
||||
task.value.monthly_days_of_month = [];
|
||||
task.value.monthly_weeks_of_month = [];
|
||||
task.value.task_instance_policy = 0;
|
||||
task.value.expire_date = null;
|
||||
},
|
||||
);
|
||||
|
||||
@@ -1164,19 +1095,14 @@ watch(
|
||||
if (props.task && props.task.custom_field) collector.value = true;
|
||||
|
||||
// stepper logic
|
||||
const taskGeneralForm = ref<InstanceType<typeof QForm> | null>(null);
|
||||
const taskDetailForm = ref<InstanceType<typeof QForm> | null>(null);
|
||||
const stepper = ref<InstanceType<typeof QStepper> | null>(null);
|
||||
const step = ref(1);
|
||||
const isValidStep1 = ref(true);
|
||||
const isValidStep2 = ref(true);
|
||||
const isValidStep3 = ref(true);
|
||||
|
||||
function validateStep(form: QForm | null, stepper: QStepper | null) {
|
||||
if (!stepper) return;
|
||||
|
||||
function validateStep(form, stepper) {
|
||||
if (step.value === 2) {
|
||||
if (localTask.actions.length > 0) {
|
||||
if (task.value.actions.length > 0) {
|
||||
isValidStep2.value = true;
|
||||
stepper.next();
|
||||
return;
|
||||
@@ -1186,7 +1112,7 @@ function validateStep(form: QForm | null, stepper: QStepper | null) {
|
||||
|
||||
// steps 1 or 3
|
||||
} else {
|
||||
form?.validate().then((result: boolean) => {
|
||||
form.validate().then((result) => {
|
||||
if (step.value === 1) {
|
||||
isValidStep1.value = result;
|
||||
if (result) stepper.next();
|
||||
@@ -1199,7 +1125,59 @@ function validateStep(form: QForm | null, stepper: QStepper | null) {
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
if (props.type !== "server") getCheckOptions({ [props.type]: props.parent });
|
||||
getCheckOptions(props.parent);
|
||||
});
|
||||
|
||||
return {
|
||||
// reactive data
|
||||
state: task,
|
||||
script,
|
||||
defaultTimeout,
|
||||
defaultArgs,
|
||||
defaultEnvVars,
|
||||
actionType,
|
||||
command,
|
||||
shell,
|
||||
allMonthsCheckbox,
|
||||
allMonthDaysCheckbox,
|
||||
allWeekDaysCheckbox,
|
||||
collector,
|
||||
monthlyType,
|
||||
loading,
|
||||
step,
|
||||
isValidStep1,
|
||||
isValidStep2,
|
||||
isValidStep3,
|
||||
scriptOptions,
|
||||
checkOptions,
|
||||
customFieldOptions,
|
||||
|
||||
// non-reactive data
|
||||
validateTimePeriod,
|
||||
convertPeriodToSeconds,
|
||||
severityOptions,
|
||||
dayOfWeekOptions,
|
||||
dayOfMonthOptions,
|
||||
weekOptions,
|
||||
monthOptions,
|
||||
taskTypeOptions,
|
||||
taskInstancePolicyOptions,
|
||||
envVarsLabel,
|
||||
|
||||
// methods
|
||||
submit,
|
||||
validateStep,
|
||||
addAction,
|
||||
removeAction,
|
||||
toggleMonths,
|
||||
toggleMonthDays,
|
||||
toggleWeekDays,
|
||||
|
||||
// quasar dialog
|
||||
dialogRef,
|
||||
onDialogHide,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
@@ -192,7 +192,6 @@ export function formatCustomFieldOptions(
|
||||
// For a flat list, simply format the options based on the "name" property
|
||||
return _formatOptions(data, { label: "name", flat: true });
|
||||
} else {
|
||||
console.log(data);
|
||||
// Predefined categories for organizing the custom fields
|
||||
const categories = ["Client", "Site", "Agent"];
|
||||
const options: Option[] = [];
|
||||
@@ -200,7 +199,6 @@ export function formatCustomFieldOptions(
|
||||
categories.forEach((cat) => {
|
||||
// Add a category header as an option
|
||||
options.push({ category: cat, label: cat, value: cat });
|
||||
console.log(cat);
|
||||
|
||||
// Filter and map the custom fields that match the current category
|
||||
const matchingFields = data
|
||||
|
||||
Reference in New Issue
Block a user