Compare commits
	
		
			36 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					20d534eab0 | ||
| 
						 | 
					0d87f5afee | ||
| 
						 | 
					1b83c3c5d6 | ||
| 
						 | 
					1b2286c4f8 | ||
| 
						 | 
					34233fde2f | ||
| 
						 | 
					e95dd5f6e7 | ||
| 
						 | 
					901e6986a0 | ||
| 
						 | 
					aa78929743 | ||
| 
						 | 
					8207f30234 | ||
| 
						 | 
					1879977b83 | ||
| 
						 | 
					b4de579a74 | ||
| 
						 | 
					23f15ff9e5 | ||
| 
						 | 
					498e038bbb | ||
| 
						 | 
					bb1f1c19cf | ||
| 
						 | 
					74e3aa4e46 | ||
| 
						 | 
					07a8e3ebcb | ||
| 
						 | 
					89966dd006 | ||
| 
						 | 
					68036f6837 | ||
| 
						 | 
					45ac82b1dd | ||
| 
						 | 
					d94e5c7965 | ||
| 
						 | 
					e0c1b3199a | ||
| 
						 | 
					fdbbdf7394 | ||
| 
						 | 
					03fae45ac5 | ||
| 
						 | 
					346670e8ea | ||
| 
						 | 
					e030efaecf | ||
| 
						 | 
					b8a4f9fe74 | ||
| 
						 | 
					f963b51d70 | ||
| 
						 | 
					feacb19cf9 | ||
| 
						 | 
					7ce2c1e969 | ||
| 
						 | 
					d1defcef4a | ||
| 
						 | 
					e674b4fa5d | ||
| 
						 | 
					b08a5a6c2d | ||
| 
						 | 
					9fa1d7209f | ||
| 
						 | 
					2adfccfa1d | ||
| 
						 | 
					04766efcd0 | ||
| 
						 | 
					4babb937f6 | 
							
								
								
									
										3
									
								
								.github/workflows/build-release.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.github/workflows/build-release.yml
									
									
									
									
										vendored
									
									
								
							@@ -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
 | 
				
			||||||
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										2
									
								
								.github/workflows/frontend-linting.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/frontend-linting.yml
									
									
									
									
										vendored
									
									
								
							@@ -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
									
									
									
								
							
							
						
						
									
										1921
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										46
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										46
									
								
								package.json
									
									
									
									
									
								
							@@ -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"
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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() {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										107
									
								
								src/components/ui/TacticalTable.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										107
									
								
								src/components/ui/TacticalTable.vue
									
									
									
									
									
										Normal 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>
 | 
				
			||||||
@@ -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)";
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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(() => {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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 />
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user