Compare commits

..

36 Commits

Author SHA1 Message Date
wh1te909
20d534eab0 Release 0.101.31 2023-10-01 17:36:52 +00:00
wh1te909
0d87f5afee bump version 2023-10-01 17:36:39 +00:00
wh1te909
1b83c3c5d6 fix tooltip 2023-10-01 17:36:11 +00:00
wh1te909
1b2286c4f8 Release 0.101.30 2023-09-30 21:59:09 +00:00
wh1te909
34233fde2f bump version 2023-09-30 21:58:51 +00:00
wh1te909
e95dd5f6e7 use node 18 2023-09-30 21:57:37 +00:00
wh1te909
901e6986a0 update reqs 2023-09-30 21:56:24 +00:00
wh1te909
aa78929743 update reqs 2023-09-11 02:50:40 +00:00
wh1te909
8207f30234 Release 0.101.29 2023-08-30 04:10:11 +00:00
wh1te909
1879977b83 bump version [skip ci] 2023-08-30 04:09:53 +00:00
wh1te909
b4de579a74 fix lint 2023-08-29 20:42:23 +00:00
wh1te909
23f15ff9e5 feat: add reset all check status amidaware/tacticalrmm#1615 2023-08-29 20:21:22 +00:00
wh1te909
498e038bbb update reqs 2023-08-29 20:19:35 +00:00
wh1te909
bb1f1c19cf wording 2023-08-21 21:30:21 +00:00
Dan
74e3aa4e46 Merge pull request #12 from silversword411/develop
Fixing main view removing blank space along bottom
2023-08-21 14:28:28 -07:00
silversword411
07a8e3ebcb Clarifying TRMM agent 2023-08-21 09:28:23 -04:00
silversword411
89966dd006 Fixing main view removing blank space along bottom 2023-08-18 02:39:43 -04:00
wh1te909
68036f6837 Release 0.101.28 2023-08-14 06:39:49 +00:00
wh1te909
45ac82b1dd bump version 2023-08-14 06:39:31 +00:00
wh1te909
d94e5c7965 update reqs 2023-08-11 07:07:00 +00:00
wh1te909
e0c1b3199a update reqs 2023-08-06 23:01:46 +00:00
sadnub
fdbbdf7394 make it so the script manager doesn't close if escape is pressed on script editor 2023-08-05 09:54:14 -04:00
wh1te909
03fae45ac5 Release 0.101.25 2023-07-04 18:49:46 +00:00
wh1te909
346670e8ea bump version 2023-07-04 18:49:28 +00:00
wh1te909
e030efaecf bump dev ver 2023-07-03 23:32:40 +00:00
wh1te909
b8a4f9fe74 update reqs 2023-07-03 23:32:09 +00:00
wh1te909
f963b51d70 update quasar 2023-07-01 16:48:03 +00:00
wh1te909
feacb19cf9 bump dev version 2023-06-30 20:30:52 +00:00
wh1te909
7ce2c1e969 node 18 2023-06-30 20:26:30 +00:00
wh1te909
d1defcef4a update reqs 2023-06-30 20:26:21 +00:00
Dan
e674b4fa5d Merge pull request #9 from silversword411/develop
Adding customizable columns to script manager table
2023-06-07 11:59:29 -07:00
sadnub
b08a5a6c2d fix light mode colors 2023-06-06 16:17:09 -04:00
sadnub
9fa1d7209f fix duplicate columns on script manager close and open 2023-06-06 15:42:06 -04:00
Dan
2adfccfa1d Merge pull request #10 from dinger1986/develop
Update InitialSetup.vue
2023-06-06 11:51:01 -07:00
silversword411
04766efcd0 tactical-table and script manager table for column selection 2023-06-06 12:38:53 -04:00
dinger1986
4babb937f6 Update InitialSetup.vue 2023-06-01 21:37:06 +00:00
14 changed files with 1054 additions and 1143 deletions

View File

@@ -15,7 +15,7 @@ jobs:
- uses: actions/setup-node@v3 - uses: actions/setup-node@v3
with: with:
node-version: 16 node-version: 18
- run: touch env-config.js - run: touch env-config.js
@@ -32,4 +32,3 @@ jobs:
uses: softprops/action-gh-release@v1 uses: softprops/action-gh-release@v1
with: with:
files: trmm-web-${{github.ref_name}}.tar.gz files: trmm-web-${{github.ref_name}}.tar.gz

View File

@@ -13,7 +13,7 @@ jobs:
- uses: actions/setup-node@v3 - uses: actions/setup-node@v3
with: with:
node-version: 16 node-version: 18
- run: npm install - run: npm install
- name: Run Prettier formatting - name: Run Prettier formatting

1921
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{ {
"name": "web", "name": "web",
"version": "0.101.22", "version": "0.101.31",
"private": true, "private": true,
"productName": "Tactical RMM", "productName": "Tactical RMM",
"scripts": { "scripts": {
@@ -10,31 +10,31 @@
"format": "prettier --write \"**/*.{js,ts,vue,,html,md,json}\" --ignore-path .gitignore" "format": "prettier --write \"**/*.{js,ts,vue,,html,md,json}\" --ignore-path .gitignore"
}, },
"dependencies": { "dependencies": {
"@quasar/extras": "1.16.4", "@quasar/extras": "1.16.7",
"apexcharts": "3.40.0", "apexcharts": "3.41.1",
"axios": "1.4.0", "axios": "1.5.1",
"dotenv": "16.0.3", "dotenv": "16.3.1",
"qrcode.vue": "3.4.0", "qrcode.vue": "3.4.1",
"quasar": "2.12.0", "quasar": "2.12.7",
"vue": "3.2.47", "vue": "3.3.4",
"vue3-ace-editor": "2.2.2", "vue3-ace-editor": "2.2.3",
"vue3-apexcharts": "1.4.1", "vue3-apexcharts": "1.4.4",
"vuedraggable": "4.1.0", "vuedraggable": "4.1.0",
"vue-router": "4.1.6", "vue-router": "4.2.5",
"vuex": "4.1.0" "vuex": "4.1.0"
}, },
"devDependencies": { "devDependencies": {
"@quasar/cli": "^2.2.1", "@quasar/cli": "2.3.0",
"@intlify/unplugin-vue-i18n": "^0.10.0", "@intlify/unplugin-vue-i18n": "1.4.0",
"@quasar/app-vite": "^1.4.3", "@quasar/app-vite": "1.6.2",
"@types/node": "^20.2.4", "@types/node": "20.8.0",
"@typescript-eslint/eslint-plugin": "^5.59.7", "@typescript-eslint/eslint-plugin": "6.7.3",
"@typescript-eslint/parser": "^5.59.7", "@typescript-eslint/parser": "6.7.3",
"autoprefixer": "10.4.14", "autoprefixer": "10.4.16",
"eslint": "8.41.0", "eslint": "8.50.0",
"eslint-config-prettier": "8.8.0", "eslint-config-prettier": "9.0.0",
"eslint-plugin-vue": "8.7.1", "eslint-plugin-vue": "8.7.1",
"prettier": "2.8.8", "prettier": "3.0.3",
"typescript": "5.0.4" "typescript": "5.2.2"
} }
} }

View File

@@ -31,6 +31,11 @@ export async function resetCheck(id) {
return data; return data;
} }
export async function resetAllChecksStatus(agent_id) {
const { data } = await axios.post(`${baseUrl}/${agent_id}/resetall/`);
return data;
}
export async function runAgentChecks(agent_id) { export async function runAgentChecks(agent_id) {
const { data } = await axios.post(`${baseUrl}/${agent_id}/run/`); const { data } = await axios.post(`${baseUrl}/${agent_id}/run/`);
return data; return data;

View File

@@ -119,6 +119,16 @@
no-caps no-caps
icon="play_arrow" icon="play_arrow"
@click="runChecks" @click="runChecks"
class="q-mr-md"
/>
<q-btn
label="Reset All Checks Status"
dense
flat
push
no-caps
icon="restart_alt"
@click="resetAllChecks"
/> />
</template> </template>
@@ -415,6 +425,7 @@ import {
updateCheck, updateCheck,
removeCheck, removeCheck,
resetCheck, resetCheck,
resetAllChecksStatus,
runAgentChecks, runAgentChecks,
} from "@/api/checks"; } from "@/api/checks";
import { fetchAgentChecks } from "@/api/agents"; import { fetchAgentChecks } from "@/api/agents";
@@ -572,7 +583,7 @@ export default {
notifySuccess(result); notifySuccess(result);
refreshDashboard( refreshDashboard(
false /* clearTreeSelected */, false /* clearTreeSelected */,
false /* clearSubTable */ false /* clearSubTable */,
); );
} catch (e) { } catch (e) {
console.error(e); console.error(e);
@@ -580,6 +591,27 @@ export default {
loading.value = false; loading.value = false;
} }
function resetAllChecks() {
console.info(selectedAgent.value);
$q.dialog({
title: "Are you sure?",
message: "Reset all checks status",
cancel: true,
ok: { label: "Reset", color: "negative" },
persistent: true,
}).onOk(async () => {
loading.value = true;
try {
const result = await resetAllChecksStatus(selectedAgent.value);
await getChecks();
notifySuccess(result);
} catch (e) {
console.error(e);
}
loading.value = false;
});
}
function showEventInfo(data) { function showEventInfo(data) {
$q.dialog({ $q.dialog({
component: EventLogCheckOutput, component: EventLogCheckOutput,
@@ -674,6 +706,7 @@ export default {
formatDate, formatDate,
getAlertSeverity, getAlertSeverity,
runChecks, runChecks,
resetAllChecks,
// dialogs // dialogs
showScriptOutput, showScriptOutput,

View File

@@ -3,7 +3,7 @@
ref="dialogRef" ref="dialogRef"
@hide="onDialogHide" @hide="onDialogHide"
persistent persistent
@keydown.esc="onDialogHide" @keydown.esc.stop="onDialogHide"
:maximized="maximized" :maximized="maximized"
> >
<q-card <q-card
@@ -173,8 +173,7 @@
>Setting this value on the script model will always override >Setting this value on the script model will always override
any 'Run As User' checkboxes in the UI and force this script 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 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 user is logged in, the script will run as SYSTEM.
be returned.
</q-tooltip> </q-tooltip>
</q-checkbox> </q-checkbox>
<q-input <q-input
@@ -353,7 +352,7 @@ export default {
downloadScript(script.value.id, { with_snippets: props.readonly }).then( downloadScript(script.value.id, { with_snippets: props.readonly }).then(
(r) => { (r) => {
script.value.script_body = r.code; script.value.script_body = r.code;
} },
); );
async function submitForm() { async function submitForm() {

View File

@@ -286,15 +286,10 @@
</template> </template>
</q-tree> </q-tree>
</div> </div>
<q-table <tactical-table
v-if="tableView" v-if="tableView"
dense dense
:table-class="{
'table-bgcolor': !$q.dark.isActive,
'table-bgcolor-dark': $q.dark.isActive,
}"
:style="{ 'max-height': `${$q.screen.height - 182}px` }" :style="{ 'max-height': `${$q.screen.height - 182}px` }"
class="tbl-sticky"
:rows="visibleScripts" :rows="visibleScripts"
:columns="columns" :columns="columns"
:loading="loading" :loading="loading"
@@ -304,6 +299,7 @@
binary-state-sort binary-state-sort
virtual-scroll virtual-scroll
:rows-per-page-options="[0]" :rows-per-page-options="[0]"
column-select
> >
<template v-slot:header-cell-favorite="props"> <template v-slot:header-cell-favorite="props">
<q-th :props="props" auto-width> <q-th :props="props" auto-width>
@@ -425,7 +421,7 @@
</q-list> </q-list>
</q-menu> </q-menu>
<!-- favorite --> <!-- favorite -->
<q-td> <q-td key="favorite" :props="props">
<q-icon <q-icon
v-if="props.row.favorite" v-if="props.row.favorite"
color="yellow-8" color="yellow-8"
@@ -434,7 +430,7 @@
/> />
</q-td> </q-td>
<!-- shell icon --> <!-- shell icon -->
<q-td> <q-td key="shell" :props="props">
<q-icon <q-icon
v-if="props.row.shell === 'powershell'" v-if="props.row.shell === 'powershell'"
name="mdi-powershell" name="mdi-powershell"
@@ -469,7 +465,7 @@
</q-icon> </q-icon>
</q-td> </q-td>
<!-- supported platforms --> <!-- supported platforms -->
<q-td> <q-td key="supported_platforms" :props="props">
<q-badge <q-badge
v-if=" v-if="
!props.row.supported_platforms || !props.row.supported_platforms ||
@@ -487,7 +483,11 @@
> >
</q-td> </q-td>
<!-- name --> <!-- name -->
<q-td :style="{ color: props.row.hidden ? 'grey' : '' }"> <q-td
key="name"
:props="props"
:style="{ color: props.row.hidden ? 'grey' : '' }"
>
{{ truncateText(props.row.name, 50) }} {{ truncateText(props.row.name, 50) }}
<q-tooltip <q-tooltip
v-if="props.row.name.length >= 50" v-if="props.row.name.length >= 50"
@@ -497,7 +497,7 @@
</q-tooltip> </q-tooltip>
</q-td> </q-td>
<!-- args --> <!-- args -->
<q-td> <q-td key="args" :props="props">
<span v-if="props.row.args.length > 0"> <span v-if="props.row.args.length > 0">
{{ truncateText(props.row.args.toString(), 30) }} {{ truncateText(props.row.args.toString(), 30) }}
<q-tooltip <q-tooltip
@@ -509,8 +509,8 @@
</span> </span>
</q-td> </q-td>
<q-td>{{ props.row.category }}</q-td> <q-td key="category" :props="props">{{ props.row.category }}</q-td>
<q-td> <q-td key="desc" :props="props">
{{ truncateText(props.row.description, 30) }} {{ truncateText(props.row.description, 30) }}
<q-tooltip <q-tooltip
v-if="props.row.description.length >= 30" v-if="props.row.description.length >= 30"
@@ -518,10 +518,13 @@
>{{ props.row.description }}</q-tooltip >{{ props.row.description }}</q-tooltip
> >
</q-td> </q-td>
<q-td>{{ props.row.default_timeout }}</q-td> <q-td key="default_timeout" :props="props">{{
props.row.default_timeout
}}</q-td>
<q-td></q-td>
</q-tr> </q-tr>
</template> </template>
</q-table> </tactical-table>
</q-card> </q-card>
</q-dialog> </q-dialog>
</template> </template>
@@ -545,12 +548,13 @@ import { notifySuccess } from "@/utils/notify";
import ScriptUploadModal from "@/components/scripts/ScriptUploadModal.vue"; import ScriptUploadModal from "@/components/scripts/ScriptUploadModal.vue";
import ScriptFormModal from "@/components/scripts/ScriptFormModal.vue"; import ScriptFormModal from "@/components/scripts/ScriptFormModal.vue";
import ScriptSnippets from "@/components/scripts/ScriptSnippets.vue"; import ScriptSnippets from "@/components/scripts/ScriptSnippets.vue";
import TacticalTable from "@/components/ui/TacticalTable.vue";
// static data // static data
const columns = [ const columns = [
{ {
name: "favorite", name: "favorite",
label: "", label: "Favorites",
field: "favorite", field: "favorite",
align: "left", align: "left",
sortable: true, sortable: true,
@@ -608,6 +612,9 @@ const columns = [
export default { export default {
name: "ScriptManager", name: "ScriptManager",
components: {
TacticalTable,
},
emits: [...useDialogPluginComponent.emits], emits: [...useDialogPluginComponent.emits],
setup() { setup() {
// setup vuex store // setup vuex store

View File

@@ -0,0 +1,107 @@
<template>
<q-table
:columns="localColumns"
:visible-columns="visibleColumns"
:table-class="{
'table-bgcolor': !$q.dark.isActive,
'table-bgcolor-dark': $q.dark.isActive,
'column-bgcolor-dark': $q.dark.isActive && columnSelect,
'column-bgcolor': !$q.dark.isActive && columnSelect,
'sticky-header-right-column': columnSelect,
'tbl-sticky': !columnSelect,
}"
v-bind="$attrs"
>
<template v-for="(_, slot) in $slots" v-slot:[slot]="scope">
<slot :name="slot" v-bind="scope || {}" />
</template>
<template v-slot:header-cell-columnSelect="props">
<q-th :props="props" auto-width>
<q-btn dense flat icon="more_horiz">
<q-menu>
<q-option-group
v-model="visibleColumns"
:options="columnOptions"
type="checkbox"
/>
</q-menu>
</q-btn>
</q-th>
</template>
</q-table>
</template>
<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({
inheritAttrs: false,
});
</script>
<script setup lang="ts">
import { ref } from "vue";
import { type QTableColumn } from "quasar";
const props = withDefaults(
defineProps<{
columns: QTableColumn[];
columnSelect?: boolean;
excludeColumns?: string[];
}>(),
{ columnSelect: false, excludeColumns: () => ["columnSelect"] }
);
// save a non-reactive copy of columns to modify
const localColumns: QTableColumn[] = Object.assign([], props.columns);
if (props.columnSelect)
localColumns.push({
name: "columnSelect",
label: "Column Select",
field: "columnSelect",
});
const visibleColumns = ref(localColumns.map((column) => column.name));
const columnOptions = ref(
localColumns
.filter((column) => !props.excludeColumns.includes(column.name))
.map((column) => ({ label: column.label, value: column.name }))
);
</script>
<style lang="sass">
.column-bgcolor-dark
td:last-child
/* bg color is important for td; just specify one */
background-color: #1d1d1d
.column-bgcolor
td:last-child
/* bg color is important for td; just specify one */
background-color: #ffffff
.sticky-header-right-column
tr th
position: sticky
/* higher than z-index for td below */
z-index: 2
/* this will be the loading indicator */
thead tr:last-child th
/* height of all previous header rows */
top: 48px
/* highest z-index */
z-index: 3
thead tr:last-child th
top: 0
z-index: 1
tr:last-child th:last-child
/* highest z-index */
z-index: 3
td:last-child
z-index: 1
td:last-child, th:last-child
position: sticky
right: 0
/* prevent scrolling behind sticky top row on focus */
tbody
/* height of all previous header rows */
scroll-margin-top: 48px
</style>

View File

@@ -4,7 +4,7 @@ export const GOARCH_ARM64 = "arm64";
export const GOARCH_ARM32 = "arm"; export const GOARCH_ARM32 = "arm";
export const runAsUserToolTip = export const runAsUserToolTip =
"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."; "Run in the context of the logged in user. If no user is logged in, the script will run as SYSTEM";
export const envVarsLabel = export const envVarsLabel =
"Environment vars (press Enter after typing each key=value pair)"; "Environment vars (press Enter after typing each key=value pair)";

View File

@@ -74,7 +74,7 @@
:color="dash_negative_color" :color="dash_negative_color"
text-color="black" text-color="black"
icon="warning" icon="warning"
>Certificate expires in {{ daysUntilCertExpires }} days</q-chip >SSL certificate expires in {{ daysUntilCertExpires }} days</q-chip
> >
</q-toolbar-title> </q-toolbar-title>
<!-- temp dark mode toggle --> <!-- temp dark mode toggle -->
@@ -288,7 +288,7 @@ export default {
if (!token.value) { if (!token.value) {
console.log( console.log(
"Access token is null or invalid, not setting up WebSocket" "Access token is null or invalid, not setting up WebSocket",
); );
return; return;
} }
@@ -325,10 +325,13 @@ export default {
const poll = ref(null); const poll = ref(null);
function livePoll() { function livePoll() {
poll.value = setInterval(() => { poll.value = setInterval(
store.dispatch("checkVer"); () => {
store.dispatch("getDashInfo", false); store.dispatch("checkVer");
}, 60 * 4 * 1000); store.dispatch("getDashInfo", false);
},
60 * 4 * 1000,
);
} }
const updateAvailable = computed(() => { const updateAvailable = computed(() => {

View File

@@ -13,7 +13,7 @@
> >
<q-spinner size="40px" color="primary" /> <q-spinner size="40px" color="primary" />
</div> </div>
<div v-else class="q-pa-sm q-gutter-sm scroll" style="height: 85vh"> <div v-else class="q-pa-sm q-gutter-sm scroll" style="height: 85vh; overflow: initial;">
<q-list dense class="rounded-borders"> <q-list dense class="rounded-borders">
<q-item <q-item
clickable clickable

View File

@@ -4,8 +4,17 @@
<div class="col"></div> <div class="col"></div>
<div class="col"> <div class="col">
<q-card> <q-card>
<q-card-actions align="center">
<q-btn
label="Getting Started"
color="info"
class="full-width"
href="https://docs.tacticalrmm.com/guide_gettingstarted/"
target="_blank"
/>
</q-card-actions>
<q-card-section class="row items-center"> <q-card-section class="row items-center">
<div class="text-h6">Initial Setup</div> <div class="text-h5 text-weight-bold">Initial Setup</div>
</q-card-section> </q-card-section>
<q-form @submit.prevent="finish"> <q-form @submit.prevent="finish">
<q-card-section> <q-card-section>

View File

@@ -2,7 +2,7 @@
<div> <div>
<q-bar> <q-bar>
<span class="text-caption"> <span class="text-caption">
Agent Status: TRMM Agent Status:
<q-badge :color="statusColor" :label="status" /> <q-badge :color="statusColor" :label="status" />
</span> </span>
<q-space /> <q-space />