Compare commits
	
		
			33 Commits
		
	
	
		
			v0.101.15-
			...
			v0.101.21-
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					3fdd8272f6 | ||
| 
						 | 
					339227bedc | ||
| 
						 | 
					17c7c95cc1 | ||
| 
						 | 
					a3ceb5e81b | ||
| 
						 | 
					679d8cab77 | ||
| 
						 | 
					c4c1474e09 | ||
| 
						 | 
					82677b0b82 | ||
| 
						 | 
					b78af07f11 | ||
| 
						 | 
					24acef19c5 | ||
| 
						 | 
					fee6edb39e | ||
| 
						 | 
					89e7db905d | ||
| 
						 | 
					827e81dcda | ||
| 
						 | 
					6ea3a053f2 | ||
| 
						 | 
					88d297f7c6 | ||
| 
						 | 
					6c57d3e6b1 | ||
| 
						 | 
					0113fbc761 | ||
| 
						 | 
					95df8c1889 | ||
| 
						 | 
					819a364207 | ||
| 
						 | 
					ed2b07fb0b | ||
| 
						 | 
					64ed5e8740 | ||
| 
						 | 
					cdeaa3d9c4 | ||
| 
						 | 
					8c6ac164ba | ||
| 
						 | 
					dc68b16ff2 | ||
| 
						 | 
					a4f15fd05a | ||
| 
						 | 
					176675abd8 | ||
| 
						 | 
					73dc278ac4 | ||
| 
						 | 
					d6b443296b | ||
| 
						 | 
					f3c718d29c | ||
| 
						 | 
					5955af08c7 | ||
| 
						 | 
					dec1ccc98a | ||
| 
						 | 
					a78780b837 | ||
| 
						 | 
					beff8eb10e | ||
| 
						 | 
					c2f21b70dd | 
							
								
								
									
										1756
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										1756
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										32
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										32
									
								
								package.json
									
									
									
									
									
								
							@@ -1,6 +1,6 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
  "name": "web",
 | 
					  "name": "web",
 | 
				
			||||||
  "version": "0.101.15-dev",
 | 
					  "version": "0.101.21-dev",
 | 
				
			||||||
  "private": true,
 | 
					  "private": true,
 | 
				
			||||||
  "productName": "Tactical RMM",
 | 
					  "productName": "Tactical RMM",
 | 
				
			||||||
  "scripts": {
 | 
					  "scripts": {
 | 
				
			||||||
@@ -10,12 +10,12 @@
 | 
				
			|||||||
    "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.15.11",
 | 
					    "@quasar/extras": "1.16.4",
 | 
				
			||||||
    "apexcharts": "3.37.1",
 | 
					    "apexcharts": "3.40.0",
 | 
				
			||||||
    "axios": "1.3.4",
 | 
					    "axios": "1.4.0",
 | 
				
			||||||
    "dotenv": "16.0.3",
 | 
					    "dotenv": "16.0.3",
 | 
				
			||||||
    "qrcode.vue": "3.3.4",
 | 
					    "qrcode.vue": "3.4.0",
 | 
				
			||||||
    "quasar": "2.11.8",
 | 
					    "quasar": "2.12.0",
 | 
				
			||||||
    "vue": "3.2.47",
 | 
					    "vue": "3.2.47",
 | 
				
			||||||
    "vue3-ace-editor": "2.2.2",
 | 
					    "vue3-ace-editor": "2.2.2",
 | 
				
			||||||
    "vue3-apexcharts": "1.4.1",
 | 
					    "vue3-apexcharts": "1.4.1",
 | 
				
			||||||
@@ -24,17 +24,17 @@
 | 
				
			|||||||
    "vuex": "4.1.0"
 | 
					    "vuex": "4.1.0"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "devDependencies": {
 | 
					  "devDependencies": {
 | 
				
			||||||
    "@quasar/cli": "^2.0.0",
 | 
					    "@quasar/cli": "^2.2.1",
 | 
				
			||||||
    "@intlify/unplugin-vue-i18n": "^0.9.2",
 | 
					    "@intlify/unplugin-vue-i18n": "^0.10.0",
 | 
				
			||||||
    "@quasar/app-vite": "^1.2.1",
 | 
					    "@quasar/app-vite": "^1.4.3",
 | 
				
			||||||
    "@types/node": "^18.15.3",
 | 
					    "@types/node": "^20.2.4",
 | 
				
			||||||
    "@typescript-eslint/eslint-plugin": "^5.55.0",
 | 
					    "@typescript-eslint/eslint-plugin": "^5.59.7",
 | 
				
			||||||
    "@typescript-eslint/parser": "^5.55.0",
 | 
					    "@typescript-eslint/parser": "^5.59.7",
 | 
				
			||||||
    "autoprefixer": "10.4.14",
 | 
					    "autoprefixer": "10.4.14",
 | 
				
			||||||
    "eslint": "8.36.0",
 | 
					    "eslint": "8.41.0",
 | 
				
			||||||
    "eslint-config-prettier": "8.7.0",
 | 
					    "eslint-config-prettier": "8.8.0",
 | 
				
			||||||
    "eslint-plugin-vue": "8.7.1",
 | 
					    "eslint-plugin-vue": "8.7.1",
 | 
				
			||||||
    "prettier": "2.8.4",
 | 
					    "prettier": "2.8.8",
 | 
				
			||||||
    "typescript": "4.9.5"
 | 
					    "typescript": "5.0.4"
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -12,6 +12,9 @@ export default {
 | 
				
			|||||||
body
 | 
					body
 | 
				
			||||||
  overflow-y: hidden
 | 
					  overflow-y: hidden
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					a
 | 
				
			||||||
 | 
					  color: #1976D2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.tbl-sticky
 | 
					.tbl-sticky
 | 
				
			||||||
  thead tr th
 | 
					  thead tr th
 | 
				
			||||||
    position: sticky
 | 
					    position: sticky
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -232,3 +232,8 @@ export async function removeAgentNote(pk) {
 | 
				
			|||||||
  const { data } = await axios.delete(`${baseUrl}/notes/${pk}/`);
 | 
					  const { data } = await axios.delete(`${baseUrl}/notes/${pk}/`);
 | 
				
			||||||
  return data;
 | 
					  return data;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export async function wakeUpWOL(agent_id) {
 | 
				
			||||||
 | 
					  const { data } = await axios.post(`${baseUrl}/${agent_id}/wol/`);
 | 
				
			||||||
 | 
					  return data;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -38,3 +38,8 @@ export async function runURLAction(payload) {
 | 
				
			|||||||
    console.error(e);
 | 
					    console.error(e);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export async function generateScript(payload) {
 | 
				
			||||||
 | 
					  const { data } = await axios.post(`${baseUrl}/openai/generate/`, payload);
 | 
				
			||||||
 | 
					  return data;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -211,7 +211,7 @@
 | 
				
			|||||||
              v-if="props.row.maintenance_mode"
 | 
					              v-if="props.row.maintenance_mode"
 | 
				
			||||||
              name="construction"
 | 
					              name="construction"
 | 
				
			||||||
              size="1.2em"
 | 
					              size="1.2em"
 | 
				
			||||||
              color="green"
 | 
					              :color="dash_positive_color"
 | 
				
			||||||
            >
 | 
					            >
 | 
				
			||||||
              <q-tooltip>Maintenance Mode Enabled</q-tooltip>
 | 
					              <q-tooltip>Maintenance Mode Enabled</q-tooltip>
 | 
				
			||||||
            </q-icon>
 | 
					            </q-icon>
 | 
				
			||||||
@@ -219,7 +219,7 @@
 | 
				
			|||||||
              v-else-if="props.row.checks.failing > 0"
 | 
					              v-else-if="props.row.checks.failing > 0"
 | 
				
			||||||
              name="fas fa-check-double"
 | 
					              name="fas fa-check-double"
 | 
				
			||||||
              size="1.2em"
 | 
					              size="1.2em"
 | 
				
			||||||
              color="negative"
 | 
					              :color="dash_negative_color"
 | 
				
			||||||
            >
 | 
					            >
 | 
				
			||||||
              <q-tooltip>Checks failing</q-tooltip>
 | 
					              <q-tooltip>Checks failing</q-tooltip>
 | 
				
			||||||
            </q-icon>
 | 
					            </q-icon>
 | 
				
			||||||
@@ -227,7 +227,7 @@
 | 
				
			|||||||
              v-else-if="props.row.checks.warning > 0"
 | 
					              v-else-if="props.row.checks.warning > 0"
 | 
				
			||||||
              name="fas fa-check-double"
 | 
					              name="fas fa-check-double"
 | 
				
			||||||
              size="1.2em"
 | 
					              size="1.2em"
 | 
				
			||||||
              color="warning"
 | 
					              :color="dash_warning_color"
 | 
				
			||||||
            >
 | 
					            >
 | 
				
			||||||
              <q-tooltip>Checks warning</q-tooltip>
 | 
					              <q-tooltip>Checks warning</q-tooltip>
 | 
				
			||||||
            </q-icon>
 | 
					            </q-icon>
 | 
				
			||||||
@@ -235,7 +235,7 @@
 | 
				
			|||||||
              v-else-if="props.row.checks.info > 0"
 | 
					              v-else-if="props.row.checks.info > 0"
 | 
				
			||||||
              name="fas fa-check-double"
 | 
					              name="fas fa-check-double"
 | 
				
			||||||
              size="1.2em"
 | 
					              size="1.2em"
 | 
				
			||||||
              color="info"
 | 
					              :color="dash_info_color"
 | 
				
			||||||
            >
 | 
					            >
 | 
				
			||||||
              <q-tooltip>Checks info</q-tooltip>
 | 
					              <q-tooltip>Checks info</q-tooltip>
 | 
				
			||||||
            </q-icon>
 | 
					            </q-icon>
 | 
				
			||||||
@@ -243,7 +243,7 @@
 | 
				
			|||||||
              v-else
 | 
					              v-else
 | 
				
			||||||
              name="fas fa-check-double"
 | 
					              name="fas fa-check-double"
 | 
				
			||||||
              size="1.2em"
 | 
					              size="1.2em"
 | 
				
			||||||
              color="positive"
 | 
					              :color="dash_positive_color"
 | 
				
			||||||
            >
 | 
					            >
 | 
				
			||||||
              <q-tooltip>Checks passing</q-tooltip>
 | 
					              <q-tooltip>Checks passing</q-tooltip>
 | 
				
			||||||
            </q-icon>
 | 
					            </q-icon>
 | 
				
			||||||
@@ -279,7 +279,7 @@
 | 
				
			|||||||
              @click="showPendingActionsModal(props.row)"
 | 
					              @click="showPendingActionsModal(props.row)"
 | 
				
			||||||
              name="far fa-clock"
 | 
					              name="far fa-clock"
 | 
				
			||||||
              size="1.4em"
 | 
					              size="1.4em"
 | 
				
			||||||
              color="warning"
 | 
					              :color="dash_warning_color"
 | 
				
			||||||
              class="cursor-pointer"
 | 
					              class="cursor-pointer"
 | 
				
			||||||
            >
 | 
					            >
 | 
				
			||||||
              <q-tooltip
 | 
					              <q-tooltip
 | 
				
			||||||
@@ -303,7 +303,7 @@
 | 
				
			|||||||
              v-if="props.row.status === 'overdue'"
 | 
					              v-if="props.row.status === 'overdue'"
 | 
				
			||||||
              name="fas fa-signal"
 | 
					              name="fas fa-signal"
 | 
				
			||||||
              size="1.2em"
 | 
					              size="1.2em"
 | 
				
			||||||
              color="negative"
 | 
					              :color="dash_negative_color"
 | 
				
			||||||
            >
 | 
					            >
 | 
				
			||||||
              <q-tooltip>Agent overdue</q-tooltip>
 | 
					              <q-tooltip>Agent overdue</q-tooltip>
 | 
				
			||||||
            </q-icon>
 | 
					            </q-icon>
 | 
				
			||||||
@@ -311,11 +311,16 @@
 | 
				
			|||||||
              v-else-if="props.row.status === 'offline'"
 | 
					              v-else-if="props.row.status === 'offline'"
 | 
				
			||||||
              name="fas fa-signal"
 | 
					              name="fas fa-signal"
 | 
				
			||||||
              size="1.2em"
 | 
					              size="1.2em"
 | 
				
			||||||
              color="warning"
 | 
					              :color="dash_warning_color"
 | 
				
			||||||
            >
 | 
					            >
 | 
				
			||||||
              <q-tooltip>Agent offline</q-tooltip>
 | 
					              <q-tooltip>Agent offline</q-tooltip>
 | 
				
			||||||
            </q-icon>
 | 
					            </q-icon>
 | 
				
			||||||
            <q-icon v-else name="fas fa-signal" size="1.2em" color="positive">
 | 
					            <q-icon
 | 
				
			||||||
 | 
					              v-else
 | 
				
			||||||
 | 
					              name="fas fa-signal"
 | 
				
			||||||
 | 
					              size="1.2em"
 | 
				
			||||||
 | 
					              :color="dash_positive_color"
 | 
				
			||||||
 | 
					            >
 | 
				
			||||||
              <q-tooltip>Agent online</q-tooltip>
 | 
					              <q-tooltip>Agent online</q-tooltip>
 | 
				
			||||||
            </q-icon>
 | 
					            </q-icon>
 | 
				
			||||||
          </q-td>
 | 
					          </q-td>
 | 
				
			||||||
@@ -373,6 +378,8 @@ export default {
 | 
				
			|||||||
        "local_ips",
 | 
					        "local_ips",
 | 
				
			||||||
        "make_model",
 | 
					        "make_model",
 | 
				
			||||||
        "physical_disks",
 | 
					        "physical_disks",
 | 
				
			||||||
 | 
					        "custom_fields",
 | 
				
			||||||
 | 
					        "serial_number",
 | 
				
			||||||
      ];
 | 
					      ];
 | 
				
			||||||
      // quasar filter only does visible columns so this is a hack to add hidden columns we want to filter
 | 
					      // quasar filter only does visible columns so this is a hack to add hidden columns we want to filter
 | 
				
			||||||
      // originally I was modifying cols directly but this led to phantom colum so doing it this way now
 | 
					      // originally I was modifying cols directly but this led to phantom colum so doing it this way now
 | 
				
			||||||
@@ -432,7 +439,11 @@ export default {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        // Normal text filter
 | 
					        // Normal text filter
 | 
				
			||||||
        return allColumns.some((col) => {
 | 
					        return allColumns.some((col) => {
 | 
				
			||||||
          const val = cellValue(col, row) + "";
 | 
					          let valObj = cellValue(col, row);
 | 
				
			||||||
 | 
					          if (Array.isArray(valObj)) {
 | 
				
			||||||
 | 
					            valObj = valObj.map((item) => (item.value ? item.value : item));
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					          const val = valObj + "";
 | 
				
			||||||
          const haystack =
 | 
					          const haystack =
 | 
				
			||||||
            val === "undefined" || val === "null" ? "" : val.toLowerCase();
 | 
					            val === "undefined" || val === "null" ? "" : val.toLowerCase();
 | 
				
			||||||
          return haystack.indexOf(search) !== -1;
 | 
					          return haystack.indexOf(search) !== -1;
 | 
				
			||||||
@@ -483,7 +494,9 @@ export default {
 | 
				
			|||||||
      const data = {
 | 
					      const data = {
 | 
				
			||||||
        [db_field]: !alert_action,
 | 
					        [db_field]: !alert_action,
 | 
				
			||||||
      };
 | 
					      };
 | 
				
			||||||
      const alertColor = !alert_action ? "positive" : "info";
 | 
					      const alertColor = !alert_action
 | 
				
			||||||
 | 
					        ? this.dash_positive_color
 | 
				
			||||||
 | 
					        : this.dash_info_color;
 | 
				
			||||||
      this.$axios.put(`/agents/${agent.agent_id}/`, data).then(() => {
 | 
					      this.$axios.put(`/agents/${agent.agent_id}/`, data).then(() => {
 | 
				
			||||||
        this.$q.notify({
 | 
					        this.$q.notify({
 | 
				
			||||||
          color: alertColor,
 | 
					          color: alertColor,
 | 
				
			||||||
@@ -527,7 +540,13 @@ export default {
 | 
				
			|||||||
    },
 | 
					    },
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  computed: {
 | 
					  computed: {
 | 
				
			||||||
    ...mapState(["tableHeight"]),
 | 
					    ...mapState([
 | 
				
			||||||
 | 
					      "tableHeight",
 | 
				
			||||||
 | 
					      "dash_info_color",
 | 
				
			||||||
 | 
					      "dash_positive_color",
 | 
				
			||||||
 | 
					      "dash_negative_color",
 | 
				
			||||||
 | 
					      "dash_warning_color",
 | 
				
			||||||
 | 
					    ]),
 | 
				
			||||||
    agentDblClickAction() {
 | 
					    agentDblClickAction() {
 | 
				
			||||||
      return this.$store.state.agentDblClickAction;
 | 
					      return this.$store.state.agentDblClickAction;
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,7 +3,7 @@
 | 
				
			|||||||
    <q-badge v-if="alertsCount > 0" :color="badgeColor" floating transparent>{{
 | 
					    <q-badge v-if="alertsCount > 0" :color="badgeColor" floating transparent>{{
 | 
				
			||||||
      alertsCountText()
 | 
					      alertsCountText()
 | 
				
			||||||
    }}</q-badge>
 | 
					    }}</q-badge>
 | 
				
			||||||
    <q-menu style="max-height: 30vh">
 | 
					    <q-menu :style="{ 'max-height': `${$q.screen.height - 100}px` }">
 | 
				
			||||||
      <q-list separator>
 | 
					      <q-list separator>
 | 
				
			||||||
        <q-item v-if="alertsCount === 0">No New Alerts</q-item>
 | 
					        <q-item v-if="alertsCount === 0">No New Alerts</q-item>
 | 
				
			||||||
        <q-item v-for="alert in topAlerts" :key="alert.id">
 | 
					        <q-item v-for="alert in topAlerts" :key="alert.id">
 | 
				
			||||||
@@ -59,6 +59,7 @@
 | 
				
			|||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<script>
 | 
					<script>
 | 
				
			||||||
 | 
					import { mapState } from "vuex";
 | 
				
			||||||
import mixins from "@/mixins/mixins";
 | 
					import mixins from "@/mixins/mixins";
 | 
				
			||||||
import AlertsOverview from "@/components/modals/alerts/AlertsOverview.vue";
 | 
					import AlertsOverview from "@/components/modals/alerts/AlertsOverview.vue";
 | 
				
			||||||
import { getTimeLapse } from "@/utils/format";
 | 
					import { getTimeLapse } from "@/utils/format";
 | 
				
			||||||
@@ -75,19 +76,21 @@ export default {
 | 
				
			|||||||
    return {
 | 
					    return {
 | 
				
			||||||
      alertsCount: 0,
 | 
					      alertsCount: 0,
 | 
				
			||||||
      topAlerts: [],
 | 
					      topAlerts: [],
 | 
				
			||||||
      errorColor: "red",
 | 
					 | 
				
			||||||
      warningColor: "orange",
 | 
					 | 
				
			||||||
      infoColor: "blue",
 | 
					 | 
				
			||||||
      poll: null,
 | 
					      poll: null,
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  computed: {
 | 
					  computed: {
 | 
				
			||||||
 | 
					    ...mapState([
 | 
				
			||||||
 | 
					      "dash_info_color",
 | 
				
			||||||
 | 
					      "dash_warning_color",
 | 
				
			||||||
 | 
					      "dash_negative_color",
 | 
				
			||||||
 | 
					    ]),
 | 
				
			||||||
    badgeColor() {
 | 
					    badgeColor() {
 | 
				
			||||||
      const severities = this.topAlerts.map((alert) => alert.severity);
 | 
					      const severities = this.topAlerts.map((alert) => alert.severity);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      if (severities.includes("error")) return this.errorColor;
 | 
					      if (severities.includes("error")) return this.dash_negative_color;
 | 
				
			||||||
      else if (severities.includes("warning")) return this.warningColor;
 | 
					      else if (severities.includes("warning")) return this.dash_warning_color;
 | 
				
			||||||
      else return this.infoColor;
 | 
					      else return this.dash_info_color;
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  methods: {
 | 
					  methods: {
 | 
				
			||||||
@@ -159,9 +162,9 @@ export default {
 | 
				
			|||||||
        });
 | 
					        });
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    alertIconColor(severity) {
 | 
					    alertIconColor(severity) {
 | 
				
			||||||
      if (severity === "error") return this.errorColor;
 | 
					      if (severity === "error") return this.dash_negative_color;
 | 
				
			||||||
      else if (severity === "warning") return this.warningColor;
 | 
					      else if (severity === "warning") return this.dash_warning_color;
 | 
				
			||||||
      else return this.infoColor;
 | 
					      else return this.dash_info_color;
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    alertsCountText() {
 | 
					    alertsCountText() {
 | 
				
			||||||
      if (this.alertsCount > 99) return "99+";
 | 
					      if (this.alertsCount > 99) return "99+";
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -98,6 +98,10 @@
 | 
				
			|||||||
                v-model="localRole.can_reboot_agents"
 | 
					                v-model="localRole.can_reboot_agents"
 | 
				
			||||||
                label="Reboot Agents"
 | 
					                label="Reboot Agents"
 | 
				
			||||||
              />
 | 
					              />
 | 
				
			||||||
 | 
					              <q-checkbox
 | 
				
			||||||
 | 
					                v-model="localRole.can_send_wol"
 | 
				
			||||||
 | 
					                label="Wake-Up (WoL) Agents"
 | 
				
			||||||
 | 
					              />
 | 
				
			||||||
              <q-checkbox
 | 
					              <q-checkbox
 | 
				
			||||||
                v-model="localRole.can_install_agents"
 | 
					                v-model="localRole.can_install_agents"
 | 
				
			||||||
                label="Install Agents"
 | 
					                label="Install Agents"
 | 
				
			||||||
@@ -437,8 +441,8 @@ export default {
 | 
				
			|||||||
          can_run_scripts: false,
 | 
					          can_run_scripts: false,
 | 
				
			||||||
          can_run_bulk: false,
 | 
					          can_run_bulk: false,
 | 
				
			||||||
          can_manage_winsvcs: false,
 | 
					          can_manage_winsvcs: false,
 | 
				
			||||||
          can_recover_agents: false,
 | 
					 | 
				
			||||||
          can_list_agent_history: false,
 | 
					          can_list_agent_history: false,
 | 
				
			||||||
 | 
					          can_send_wol: false,
 | 
				
			||||||
          // software perms
 | 
					          // software perms
 | 
				
			||||||
          can_list_software: false,
 | 
					          can_list_software: false,
 | 
				
			||||||
          can_manage_software: false,
 | 
					          can_manage_software: false,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -146,6 +146,13 @@
 | 
				
			|||||||
      <q-item-section>Run Checks</q-item-section>
 | 
					      <q-item-section>Run Checks</q-item-section>
 | 
				
			||||||
    </q-item>
 | 
					    </q-item>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <q-item clickable v-close-popup @click="wakeUp(agent)">
 | 
				
			||||||
 | 
					      <q-item-section side>
 | 
				
			||||||
 | 
					        <q-icon size="xs" name="offline_bolt" />
 | 
				
			||||||
 | 
					      </q-item-section>
 | 
				
			||||||
 | 
					      <q-item-section>Wake-Up (WoL)</q-item-section>
 | 
				
			||||||
 | 
					    </q-item>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <q-item clickable>
 | 
					    <q-item clickable>
 | 
				
			||||||
      <q-item-section side>
 | 
					      <q-item-section side>
 | 
				
			||||||
        <q-icon size="xs" name="power_settings_new" />
 | 
					        <q-icon size="xs" name="power_settings_new" />
 | 
				
			||||||
@@ -210,6 +217,7 @@ import {
 | 
				
			|||||||
  removeAgent,
 | 
					  removeAgent,
 | 
				
			||||||
  runRemoteBackground,
 | 
					  runRemoteBackground,
 | 
				
			||||||
  runTakeControl,
 | 
					  runTakeControl,
 | 
				
			||||||
 | 
					  wakeUpWOL,
 | 
				
			||||||
} from "@/api/agents";
 | 
					} from "@/api/agents";
 | 
				
			||||||
import { runAgentUpdateScan, runAgentUpdateInstall } from "@/api/winupdates";
 | 
					import { runAgentUpdateScan, runAgentUpdateInstall } from "@/api/winupdates";
 | 
				
			||||||
import { runAgentChecks } from "@/api/checks";
 | 
					import { runAgentChecks } from "@/api/checks";
 | 
				
			||||||
@@ -370,6 +378,15 @@ export default {
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    async function wakeUp(agent) {
 | 
				
			||||||
 | 
					      try {
 | 
				
			||||||
 | 
					        const data = await wakeUpWOL(agent.agent_id);
 | 
				
			||||||
 | 
					        notifySuccess(data);
 | 
				
			||||||
 | 
					      } catch (e) {
 | 
				
			||||||
 | 
					        console.error(e);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    function showRebootLaterModal(agent) {
 | 
					    function showRebootLaterModal(agent) {
 | 
				
			||||||
      $q.dialog({
 | 
					      $q.dialog({
 | 
				
			||||||
        component: RebootLater,
 | 
					        component: RebootLater,
 | 
				
			||||||
@@ -498,6 +515,7 @@ export default {
 | 
				
			|||||||
      showPolicyAdd,
 | 
					      showPolicyAdd,
 | 
				
			||||||
      showAgentRecovery,
 | 
					      showAgentRecovery,
 | 
				
			||||||
      pingAgent,
 | 
					      pingAgent,
 | 
				
			||||||
 | 
					      wakeUp,
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -261,7 +261,7 @@
 | 
				
			|||||||
          <q-td v-else-if="props.row.task_result.status === 'passing'">
 | 
					          <q-td v-else-if="props.row.task_result.status === 'passing'">
 | 
				
			||||||
            <q-icon
 | 
					            <q-icon
 | 
				
			||||||
              style="font-size: 1.3rem"
 | 
					              style="font-size: 1.3rem"
 | 
				
			||||||
              color="positive"
 | 
					              :color="dash_positive_color"
 | 
				
			||||||
              name="check_circle"
 | 
					              name="check_circle"
 | 
				
			||||||
            >
 | 
					            >
 | 
				
			||||||
              <q-tooltip>Passing</q-tooltip>
 | 
					              <q-tooltip>Passing</q-tooltip>
 | 
				
			||||||
@@ -271,7 +271,7 @@
 | 
				
			|||||||
            <q-icon
 | 
					            <q-icon
 | 
				
			||||||
              v-if="props.row.alert_severity === 'info'"
 | 
					              v-if="props.row.alert_severity === 'info'"
 | 
				
			||||||
              style="font-size: 1.3rem"
 | 
					              style="font-size: 1.3rem"
 | 
				
			||||||
              color="info"
 | 
					              :color="dash_info_color"
 | 
				
			||||||
              name="info"
 | 
					              name="info"
 | 
				
			||||||
            >
 | 
					            >
 | 
				
			||||||
              <q-tooltip>Informational</q-tooltip>
 | 
					              <q-tooltip>Informational</q-tooltip>
 | 
				
			||||||
@@ -279,7 +279,7 @@
 | 
				
			|||||||
            <q-icon
 | 
					            <q-icon
 | 
				
			||||||
              v-else-if="props.row.alert_severity === 'warning'"
 | 
					              v-else-if="props.row.alert_severity === 'warning'"
 | 
				
			||||||
              style="font-size: 1.3rem"
 | 
					              style="font-size: 1.3rem"
 | 
				
			||||||
              color="warning"
 | 
					              :color="dash_warning_color"
 | 
				
			||||||
              name="warning"
 | 
					              name="warning"
 | 
				
			||||||
            >
 | 
					            >
 | 
				
			||||||
              <q-tooltip>Warning</q-tooltip>
 | 
					              <q-tooltip>Warning</q-tooltip>
 | 
				
			||||||
@@ -287,7 +287,7 @@
 | 
				
			|||||||
            <q-icon
 | 
					            <q-icon
 | 
				
			||||||
              v-else
 | 
					              v-else
 | 
				
			||||||
              style="font-size: 1.3rem"
 | 
					              style="font-size: 1.3rem"
 | 
				
			||||||
              color="negative"
 | 
					              :color="dash_negative_color"
 | 
				
			||||||
              name="error"
 | 
					              name="error"
 | 
				
			||||||
            >
 | 
					            >
 | 
				
			||||||
              <q-tooltip>Error</q-tooltip>
 | 
					              <q-tooltip>Error</q-tooltip>
 | 
				
			||||||
@@ -418,6 +418,10 @@ export default {
 | 
				
			|||||||
    const tabHeight = computed(() => store.state.tabHeight);
 | 
					    const tabHeight = computed(() => store.state.tabHeight);
 | 
				
			||||||
    const agentPlatform = computed(() => store.state.agentPlatform);
 | 
					    const agentPlatform = computed(() => store.state.agentPlatform);
 | 
				
			||||||
    const formatDate = computed(() => store.getters.formatDate);
 | 
					    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
 | 
					    // setup quasar
 | 
				
			||||||
    const $q = useQuasar();
 | 
					    const $q = useQuasar();
 | 
				
			||||||
@@ -552,6 +556,10 @@ export default {
 | 
				
			|||||||
      selectedAgent,
 | 
					      selectedAgent,
 | 
				
			||||||
      tabHeight,
 | 
					      tabHeight,
 | 
				
			||||||
      agentPlatform,
 | 
					      agentPlatform,
 | 
				
			||||||
 | 
					      dash_info_color,
 | 
				
			||||||
 | 
					      dash_positive_color,
 | 
				
			||||||
 | 
					      dash_warning_color,
 | 
				
			||||||
 | 
					      dash_negative_color,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // non-reactive data
 | 
					      // non-reactive data
 | 
				
			||||||
      columns,
 | 
					      columns,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -301,7 +301,7 @@
 | 
				
			|||||||
          <q-td v-else-if="props.row.check_result.status === 'passing'">
 | 
					          <q-td v-else-if="props.row.check_result.status === 'passing'">
 | 
				
			||||||
            <q-icon
 | 
					            <q-icon
 | 
				
			||||||
              style="font-size: 1.3rem"
 | 
					              style="font-size: 1.3rem"
 | 
				
			||||||
              color="positive"
 | 
					              :color="dash_positive_color"
 | 
				
			||||||
              name="check_circle"
 | 
					              name="check_circle"
 | 
				
			||||||
            >
 | 
					            >
 | 
				
			||||||
              <q-tooltip>Passing</q-tooltip>
 | 
					              <q-tooltip>Passing</q-tooltip>
 | 
				
			||||||
@@ -311,7 +311,7 @@
 | 
				
			|||||||
            <q-icon
 | 
					            <q-icon
 | 
				
			||||||
              v-if="getAlertSeverity(props.row) === 'info'"
 | 
					              v-if="getAlertSeverity(props.row) === 'info'"
 | 
				
			||||||
              style="font-size: 1.3rem"
 | 
					              style="font-size: 1.3rem"
 | 
				
			||||||
              color="info"
 | 
					              :color="dash_info_color"
 | 
				
			||||||
              name="info"
 | 
					              name="info"
 | 
				
			||||||
            >
 | 
					            >
 | 
				
			||||||
              <q-tooltip>Informational</q-tooltip>
 | 
					              <q-tooltip>Informational</q-tooltip>
 | 
				
			||||||
@@ -319,7 +319,7 @@
 | 
				
			|||||||
            <q-icon
 | 
					            <q-icon
 | 
				
			||||||
              v-else-if="getAlertSeverity(props.row) === 'warning'"
 | 
					              v-else-if="getAlertSeverity(props.row) === 'warning'"
 | 
				
			||||||
              style="font-size: 1.3rem"
 | 
					              style="font-size: 1.3rem"
 | 
				
			||||||
              color="warning"
 | 
					              :color="dash_warning_color"
 | 
				
			||||||
              name="warning"
 | 
					              name="warning"
 | 
				
			||||||
            >
 | 
					            >
 | 
				
			||||||
              <q-tooltip>Warning</q-tooltip>
 | 
					              <q-tooltip>Warning</q-tooltip>
 | 
				
			||||||
@@ -327,7 +327,7 @@
 | 
				
			|||||||
            <q-icon
 | 
					            <q-icon
 | 
				
			||||||
              v-else
 | 
					              v-else
 | 
				
			||||||
              style="font-size: 1.3rem"
 | 
					              style="font-size: 1.3rem"
 | 
				
			||||||
              color="negative"
 | 
					              :color="dash_negative_color"
 | 
				
			||||||
              name="error"
 | 
					              name="error"
 | 
				
			||||||
            >
 | 
					            >
 | 
				
			||||||
              <q-tooltip>Error</q-tooltip>
 | 
					              <q-tooltip>Error</q-tooltip>
 | 
				
			||||||
@@ -479,6 +479,10 @@ export default {
 | 
				
			|||||||
    const tabHeight = computed(() => store.state.tabHeight);
 | 
					    const tabHeight = computed(() => store.state.tabHeight);
 | 
				
			||||||
    const agentPlatform = computed(() => store.state.agentPlatform);
 | 
					    const agentPlatform = computed(() => store.state.agentPlatform);
 | 
				
			||||||
    const formatDate = computed(() => store.getters.formatDate);
 | 
					    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
 | 
					    // setup quasar
 | 
				
			||||||
    const $q = useQuasar();
 | 
					    const $q = useQuasar();
 | 
				
			||||||
@@ -653,6 +657,10 @@ export default {
 | 
				
			|||||||
      tabHeight,
 | 
					      tabHeight,
 | 
				
			||||||
      selectedAgent,
 | 
					      selectedAgent,
 | 
				
			||||||
      agentPlatform,
 | 
					      agentPlatform,
 | 
				
			||||||
 | 
					      dash_info_color,
 | 
				
			||||||
 | 
					      dash_positive_color,
 | 
				
			||||||
 | 
					      dash_warning_color,
 | 
				
			||||||
 | 
					      dash_negative_color,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // non-reactive data
 | 
					      // non-reactive data
 | 
				
			||||||
      columns,
 | 
					      columns,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -18,6 +18,33 @@
 | 
				
			|||||||
        icon="refresh"
 | 
					        icon="refresh"
 | 
				
			||||||
        @click="refreshSummary"
 | 
					        @click="refreshSummary"
 | 
				
			||||||
      />
 | 
					      />
 | 
				
			||||||
 | 
					      <q-icon
 | 
				
			||||||
 | 
					        v-if="summary.status === 'overdue'"
 | 
				
			||||||
 | 
					        name="fas fa-signal"
 | 
				
			||||||
 | 
					        size="1.2em"
 | 
				
			||||||
 | 
					        :color="dash_negative_color"
 | 
				
			||||||
 | 
					        class="q-mr-sm"
 | 
				
			||||||
 | 
					      >
 | 
				
			||||||
 | 
					        <q-tooltip>Agent overdue</q-tooltip>
 | 
				
			||||||
 | 
					      </q-icon>
 | 
				
			||||||
 | 
					      <q-icon
 | 
				
			||||||
 | 
					        v-else-if="summary.status === 'offline'"
 | 
				
			||||||
 | 
					        name="fas fa-signal"
 | 
				
			||||||
 | 
					        size="1.2em"
 | 
				
			||||||
 | 
					        :color="dash_warning_color"
 | 
				
			||||||
 | 
					        class="q-mr-sm"
 | 
				
			||||||
 | 
					      >
 | 
				
			||||||
 | 
					        <q-tooltip>Agent offline</q-tooltip>
 | 
				
			||||||
 | 
					      </q-icon>
 | 
				
			||||||
 | 
					      <q-icon
 | 
				
			||||||
 | 
					        v-else
 | 
				
			||||||
 | 
					        name="fas fa-signal"
 | 
				
			||||||
 | 
					        size="1.2em"
 | 
				
			||||||
 | 
					        :color="dash_positive_color"
 | 
				
			||||||
 | 
					        class="q-mr-sm"
 | 
				
			||||||
 | 
					      >
 | 
				
			||||||
 | 
					        <q-tooltip>Agent online</q-tooltip>
 | 
				
			||||||
 | 
					      </q-icon>
 | 
				
			||||||
      <b>{{ summary.hostname }}</b>
 | 
					      <b>{{ summary.hostname }}</b>
 | 
				
			||||||
      <span v-if="summary.maintenance_mode">
 | 
					      <span v-if="summary.maintenance_mode">
 | 
				
			||||||
        • <q-badge color="green"> Maintenance Mode </q-badge>
 | 
					        • <q-badge color="green"> Maintenance Mode </q-badge>
 | 
				
			||||||
@@ -60,7 +87,7 @@
 | 
				
			|||||||
            </q-item-section>
 | 
					            </q-item-section>
 | 
				
			||||||
            <q-item-section>{{ summary.make_model }}</q-item-section>
 | 
					            <q-item-section>{{ summary.make_model }}</q-item-section>
 | 
				
			||||||
          </q-item>
 | 
					          </q-item>
 | 
				
			||||||
          <q-item v-for="(cpu, i) in summary.cpu_model" :key="cpu + i">
 | 
					          <q-item>
 | 
				
			||||||
            <q-item-section avatar>
 | 
					            <q-item-section avatar>
 | 
				
			||||||
              <q-icon name="fas fa-microchip" />
 | 
					              <q-icon name="fas fa-microchip" />
 | 
				
			||||||
            </q-item-section>
 | 
					            </q-item-section>
 | 
				
			||||||
@@ -87,6 +114,13 @@
 | 
				
			|||||||
            </q-item-section>
 | 
					            </q-item-section>
 | 
				
			||||||
            <q-item-section>{{ summary.graphics }}</q-item-section>
 | 
					            <q-item-section>{{ summary.graphics }}</q-item-section>
 | 
				
			||||||
          </q-item>
 | 
					          </q-item>
 | 
				
			||||||
 | 
					          <!-- serial -->
 | 
				
			||||||
 | 
					          <q-item v-if="serial_number">
 | 
				
			||||||
 | 
					            <q-item-section avatar>
 | 
				
			||||||
 | 
					              <q-icon name="fa-solid fa-barcode" />
 | 
				
			||||||
 | 
					            </q-item-section>
 | 
				
			||||||
 | 
					            <q-item-section>{{ serial_number }}</q-item-section>
 | 
				
			||||||
 | 
					          </q-item>
 | 
				
			||||||
          <q-item>
 | 
					          <q-item>
 | 
				
			||||||
            <q-item-section avatar>
 | 
					            <q-item-section avatar>
 | 
				
			||||||
              <q-icon name="fas fa-globe-americas" />
 | 
					              <q-icon name="fas fa-globe-americas" />
 | 
				
			||||||
@@ -110,7 +144,7 @@
 | 
				
			|||||||
              size="lg"
 | 
					              size="lg"
 | 
				
			||||||
              square
 | 
					              square
 | 
				
			||||||
              icon="done"
 | 
					              icon="done"
 | 
				
			||||||
              color="green"
 | 
					              :color="dash_positive_color"
 | 
				
			||||||
              text-color="white"
 | 
					              text-color="white"
 | 
				
			||||||
            />
 | 
					            />
 | 
				
			||||||
            <small>{{ summary.checks.passing }} checks passing</small>
 | 
					            <small>{{ summary.checks.passing }} checks passing</small>
 | 
				
			||||||
@@ -120,7 +154,7 @@
 | 
				
			|||||||
              size="lg"
 | 
					              size="lg"
 | 
				
			||||||
              square
 | 
					              square
 | 
				
			||||||
              icon="cancel"
 | 
					              icon="cancel"
 | 
				
			||||||
              color="red"
 | 
					              :color="dash_negative_color"
 | 
				
			||||||
              text-color="white"
 | 
					              text-color="white"
 | 
				
			||||||
            />
 | 
					            />
 | 
				
			||||||
            <small>{{ summary.checks.failing }} checks failing</small>
 | 
					            <small>{{ summary.checks.failing }} checks failing</small>
 | 
				
			||||||
@@ -130,7 +164,7 @@
 | 
				
			|||||||
              size="lg"
 | 
					              size="lg"
 | 
				
			||||||
              square
 | 
					              square
 | 
				
			||||||
              icon="warning"
 | 
					              icon="warning"
 | 
				
			||||||
              color="warning"
 | 
					              :color="dash_warning_color"
 | 
				
			||||||
              text-color="white"
 | 
					              text-color="white"
 | 
				
			||||||
            />
 | 
					            />
 | 
				
			||||||
            <small>{{ summary.checks.warning }} checks warning</small>
 | 
					            <small>{{ summary.checks.warning }} checks warning</small>
 | 
				
			||||||
@@ -140,7 +174,7 @@
 | 
				
			|||||||
              size="lg"
 | 
					              size="lg"
 | 
				
			||||||
              square
 | 
					              square
 | 
				
			||||||
              icon="info"
 | 
					              icon="info"
 | 
				
			||||||
              color="info"
 | 
					              :color="dash_info_color"
 | 
				
			||||||
              text-color="white"
 | 
					              text-color="white"
 | 
				
			||||||
            />
 | 
					            />
 | 
				
			||||||
            <small>{{ summary.checks.info }} checks info</small>
 | 
					            <small>{{ summary.checks.info }} checks info</small>
 | 
				
			||||||
@@ -158,6 +192,20 @@
 | 
				
			|||||||
          >
 | 
					          >
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
        <div v-else>No checks</div>
 | 
					        <div v-else>No checks</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        <span
 | 
				
			||||||
 | 
					          v-if="customFields.length > 0"
 | 
				
			||||||
 | 
					          class="text-subtitle2 text-bold block q-mt-xl"
 | 
				
			||||||
 | 
					          >Custom Fields</span
 | 
				
			||||||
 | 
					        >
 | 
				
			||||||
 | 
					        <q-list dense>
 | 
				
			||||||
 | 
					          <q-item v-for="(field, i) in customFields" :key="field + i">
 | 
				
			||||||
 | 
					            <q-item-section thumbnail>
 | 
				
			||||||
 | 
					              <q-icon name="fas fa-user" size="xs" />
 | 
				
			||||||
 | 
					            </q-item-section>
 | 
				
			||||||
 | 
					            <q-item-section>{{ field.name }}: {{ field.value }}</q-item-section>
 | 
				
			||||||
 | 
					          </q-item>
 | 
				
			||||||
 | 
					        </q-list>
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
      <div class="col-1"></div>
 | 
					      <div class="col-1"></div>
 | 
				
			||||||
      <!-- right -->
 | 
					      <!-- right -->
 | 
				
			||||||
@@ -193,6 +241,7 @@ import {
 | 
				
			|||||||
  openAgentWindow,
 | 
					  openAgentWindow,
 | 
				
			||||||
} from "@/api/agents";
 | 
					} from "@/api/agents";
 | 
				
			||||||
import { notifySuccess } from "@/utils/notify";
 | 
					import { notifySuccess } from "@/utils/notify";
 | 
				
			||||||
 | 
					import { fetchCustomFields } from "@/api/core";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ui imports
 | 
					// ui imports
 | 
				
			||||||
import AgentActionMenu from "@/components/agents/AgentActionMenu.vue";
 | 
					import AgentActionMenu from "@/components/agents/AgentActionMenu.vue";
 | 
				
			||||||
@@ -207,18 +256,34 @@ export default {
 | 
				
			|||||||
    const store = useStore();
 | 
					    const store = useStore();
 | 
				
			||||||
    const selectedAgent = computed(() => store.state.selectedRow);
 | 
					    const selectedAgent = computed(() => store.state.selectedRow);
 | 
				
			||||||
    const refreshSummaryTab = computed(() => store.state.refreshSummaryTab);
 | 
					    const refreshSummaryTab = computed(() => store.state.refreshSummaryTab);
 | 
				
			||||||
 | 
					    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);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // summary tab logic
 | 
					    // summary tab logic
 | 
				
			||||||
    const summary = ref(null);
 | 
					    const summary = ref(null);
 | 
				
			||||||
 | 
					    const customFieldsDefinitions = ref(null);
 | 
				
			||||||
    const loading = ref(false);
 | 
					    const loading = ref(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const serial_number = computed(() => {
 | 
				
			||||||
 | 
					      return summary.value.wmi_detail.bios?.[0]?.[0]?.SerialNumber;
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const cpu = computed(() => {
 | 
				
			||||||
 | 
					      if (summary.value.cpu_model?.length > 1) {
 | 
				
			||||||
 | 
					        return `${summary.value.cpu_model.length}x ${summary.value.cpu_model[0]}`;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      return summary.value.cpu_model[0];
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    function diskBarColor(percent) {
 | 
					    function diskBarColor(percent) {
 | 
				
			||||||
      if (percent < 80) {
 | 
					      if (percent < 80) {
 | 
				
			||||||
        return "positive";
 | 
					        return dash_positive_color.value;
 | 
				
			||||||
      } else if (percent > 80 && percent < 95) {
 | 
					      } else if (percent > 80 && percent < 95) {
 | 
				
			||||||
        return "warning";
 | 
					        return dash_warning_color.value;
 | 
				
			||||||
      } else {
 | 
					      } else {
 | 
				
			||||||
        return "negative";
 | 
					        return dash_negative_color.value;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -236,9 +301,37 @@ export default {
 | 
				
			|||||||
      return ret;
 | 
					      return ret;
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const customFields = computed(() => {
 | 
				
			||||||
 | 
					      if (!summary.value.custom_fields) {
 | 
				
			||||||
 | 
					        return [];
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      if (!customFieldsDefinitions.value) {
 | 
				
			||||||
 | 
					        return [];
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      const ret = [];
 | 
				
			||||||
 | 
					      for (const customField of summary.value.custom_fields) {
 | 
				
			||||||
 | 
					        const definition = customFieldsDefinitions.value.find(
 | 
				
			||||||
 | 
					          (def) => def.id === customField.field
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        if (
 | 
				
			||||||
 | 
					          definition &&
 | 
				
			||||||
 | 
					          !definition.hide_in_ui &&
 | 
				
			||||||
 | 
					          customField.value?.length > 0
 | 
				
			||||||
 | 
					        ) {
 | 
				
			||||||
 | 
					          ret.push({
 | 
				
			||||||
 | 
					            name: definition.name,
 | 
				
			||||||
 | 
					            value: customField.value,
 | 
				
			||||||
 | 
					          });
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      return ret;
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async function getSummary() {
 | 
					    async function getSummary() {
 | 
				
			||||||
      loading.value = true;
 | 
					      loading.value = true;
 | 
				
			||||||
      summary.value = await fetchAgent(selectedAgent.value);
 | 
					      summary.value = await fetchAgent(selectedAgent.value);
 | 
				
			||||||
 | 
					      customFieldsDefinitions.value = await fetchCustomFields();
 | 
				
			||||||
      store.commit("setRefreshSummaryTab", false);
 | 
					      store.commit("setRefreshSummaryTab", false);
 | 
				
			||||||
      store.commit("setAgentPlatform", summary.value.plat);
 | 
					      store.commit("setAgentPlatform", summary.value.plat);
 | 
				
			||||||
      loading.value = false;
 | 
					      loading.value = false;
 | 
				
			||||||
@@ -246,6 +339,7 @@ export default {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    async function refreshSummary() {
 | 
					    async function refreshSummary() {
 | 
				
			||||||
      loading.value = true;
 | 
					      loading.value = true;
 | 
				
			||||||
 | 
					      summary.value = await fetchAgent(selectedAgent.value);
 | 
				
			||||||
      try {
 | 
					      try {
 | 
				
			||||||
        const result = await refreshAgentWMI(selectedAgent.value);
 | 
					        const result = await refreshAgentWMI(selectedAgent.value);
 | 
				
			||||||
        await getSummary();
 | 
					        await getSummary();
 | 
				
			||||||
@@ -277,9 +371,16 @@ export default {
 | 
				
			|||||||
    return {
 | 
					    return {
 | 
				
			||||||
      // reactive data
 | 
					      // reactive data
 | 
				
			||||||
      summary,
 | 
					      summary,
 | 
				
			||||||
 | 
					      customFields,
 | 
				
			||||||
      loading,
 | 
					      loading,
 | 
				
			||||||
      selectedAgent,
 | 
					      selectedAgent,
 | 
				
			||||||
      disks,
 | 
					      disks,
 | 
				
			||||||
 | 
					      dash_info_color,
 | 
				
			||||||
 | 
					      dash_positive_color,
 | 
				
			||||||
 | 
					      dash_warning_color,
 | 
				
			||||||
 | 
					      dash_negative_color,
 | 
				
			||||||
 | 
					      serial_number,
 | 
				
			||||||
 | 
					      cpu,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // methods
 | 
					      // methods
 | 
				
			||||||
      getSummary,
 | 
					      getSummary,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -128,7 +128,7 @@
 | 
				
			|||||||
            <q-icon
 | 
					            <q-icon
 | 
				
			||||||
              v-else-if="props.row.action === 'ignore'"
 | 
					              v-else-if="props.row.action === 'ignore'"
 | 
				
			||||||
              name="fas fa-check"
 | 
					              name="fas fa-check"
 | 
				
			||||||
              color="negative"
 | 
					              :color="dash_negative_color"
 | 
				
			||||||
            >
 | 
					            >
 | 
				
			||||||
              <q-tooltip>Ignore</q-tooltip>
 | 
					              <q-tooltip>Ignore</q-tooltip>
 | 
				
			||||||
            </q-icon>
 | 
					            </q-icon>
 | 
				
			||||||
@@ -144,7 +144,7 @@
 | 
				
			|||||||
            <q-icon
 | 
					            <q-icon
 | 
				
			||||||
              v-if="props.row.installed"
 | 
					              v-if="props.row.installed"
 | 
				
			||||||
              name="fas fa-check"
 | 
					              name="fas fa-check"
 | 
				
			||||||
              color="positive"
 | 
					              :color="dash_positive_color"
 | 
				
			||||||
            >
 | 
					            >
 | 
				
			||||||
              <q-tooltip>Installed</q-tooltip>
 | 
					              <q-tooltip>Installed</q-tooltip>
 | 
				
			||||||
            </q-icon>
 | 
					            </q-icon>
 | 
				
			||||||
@@ -158,11 +158,15 @@
 | 
				
			|||||||
            <q-icon
 | 
					            <q-icon
 | 
				
			||||||
              v-else-if="props.row.action == 'ignore'"
 | 
					              v-else-if="props.row.action == 'ignore'"
 | 
				
			||||||
              name="fas fa-ban"
 | 
					              name="fas fa-ban"
 | 
				
			||||||
              color="negative"
 | 
					              :color="dash_negative_color"
 | 
				
			||||||
            >
 | 
					            >
 | 
				
			||||||
              <q-tooltip>Ignored</q-tooltip>
 | 
					              <q-tooltip>Ignored</q-tooltip>
 | 
				
			||||||
            </q-icon>
 | 
					            </q-icon>
 | 
				
			||||||
            <q-icon v-else name="fas fa-exclamation" color="warning">
 | 
					            <q-icon
 | 
				
			||||||
 | 
					              v-else
 | 
				
			||||||
 | 
					              name="fas fa-exclamation"
 | 
				
			||||||
 | 
					              :color="dash_warning_color"
 | 
				
			||||||
 | 
					            >
 | 
				
			||||||
              <q-tooltip>Missing</q-tooltip>
 | 
					              <q-tooltip>Missing</q-tooltip>
 | 
				
			||||||
            </q-icon>
 | 
					            </q-icon>
 | 
				
			||||||
          </q-td>
 | 
					          </q-td>
 | 
				
			||||||
@@ -251,6 +255,9 @@ export default {
 | 
				
			|||||||
    const tabHeight = computed(() => store.state.tabHeight);
 | 
					    const tabHeight = computed(() => store.state.tabHeight);
 | 
				
			||||||
    const agentPlatform = computed(() => store.state.agentPlatform);
 | 
					    const agentPlatform = computed(() => store.state.agentPlatform);
 | 
				
			||||||
    const formatDate = computed(() => store.getters.formatDate);
 | 
					    const formatDate = computed(() => store.getters.formatDate);
 | 
				
			||||||
 | 
					    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
 | 
					    // setup quasar
 | 
				
			||||||
    const $q = useQuasar();
 | 
					    const $q = useQuasar();
 | 
				
			||||||
@@ -348,6 +355,9 @@ export default {
 | 
				
			|||||||
      selectedAgent,
 | 
					      selectedAgent,
 | 
				
			||||||
      tabHeight,
 | 
					      tabHeight,
 | 
				
			||||||
      agentPlatform,
 | 
					      agentPlatform,
 | 
				
			||||||
 | 
					      dash_positive_color,
 | 
				
			||||||
 | 
					      dash_warning_color,
 | 
				
			||||||
 | 
					      dash_negative_color,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // non-reactive data
 | 
					      // non-reactive data
 | 
				
			||||||
      columns,
 | 
					      columns,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -217,6 +217,7 @@
 | 
				
			|||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<script>
 | 
					<script>
 | 
				
			||||||
 | 
					import { mapState } from "vuex";
 | 
				
			||||||
import mixins from "@/mixins/mixins";
 | 
					import mixins from "@/mixins/mixins";
 | 
				
			||||||
import PolicyStatus from "@/components/automation/modals/PolicyStatus.vue";
 | 
					import PolicyStatus from "@/components/automation/modals/PolicyStatus.vue";
 | 
				
			||||||
import DiskSpaceCheck from "@/components/checks/DiskSpaceCheck.vue";
 | 
					import DiskSpaceCheck from "@/components/checks/DiskSpaceCheck.vue";
 | 
				
			||||||
@@ -268,6 +269,9 @@ export default {
 | 
				
			|||||||
      if (newValue !== oldValue) this.getChecks();
 | 
					      if (newValue !== oldValue) this.getChecks();
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
 | 
					  computed: {
 | 
				
			||||||
 | 
					    ...mapState(["dash_positive_color", "dash_warning_color"]),
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
  methods: {
 | 
					  methods: {
 | 
				
			||||||
    getChecks() {
 | 
					    getChecks() {
 | 
				
			||||||
      this.$q.loading.show();
 | 
					      this.$q.loading.show();
 | 
				
			||||||
@@ -295,7 +299,9 @@ export default {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
      data.check_alert = true;
 | 
					      data.check_alert = true;
 | 
				
			||||||
      const act = !action ? "enabled" : "disabled";
 | 
					      const act = !action ? "enabled" : "disabled";
 | 
				
			||||||
      const color = !action ? "positive" : "warning";
 | 
					      const color = !action
 | 
				
			||||||
 | 
					        ? this.dash_positive_color
 | 
				
			||||||
 | 
					        : this.dash_warning_color;
 | 
				
			||||||
      this.$axios
 | 
					      this.$axios
 | 
				
			||||||
        .put(`/checks/${id}/`, data)
 | 
					        .put(`/checks/${id}/`, data)
 | 
				
			||||||
        .then(() => {
 | 
					        .then(() => {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -41,7 +41,7 @@
 | 
				
			|||||||
              <q-td v-if="props.row.status === 'passing'">
 | 
					              <q-td v-if="props.row.status === 'passing'">
 | 
				
			||||||
                <q-icon
 | 
					                <q-icon
 | 
				
			||||||
                  style="font-size: 1.3rem"
 | 
					                  style="font-size: 1.3rem"
 | 
				
			||||||
                  color="positive"
 | 
					                  :color="dash_positive_color"
 | 
				
			||||||
                  name="check_circle"
 | 
					                  name="check_circle"
 | 
				
			||||||
                >
 | 
					                >
 | 
				
			||||||
                  <q-tooltip>Passing</q-tooltip>
 | 
					                  <q-tooltip>Passing</q-tooltip>
 | 
				
			||||||
@@ -51,7 +51,7 @@
 | 
				
			|||||||
                <q-icon
 | 
					                <q-icon
 | 
				
			||||||
                  v-if="props.row.alert_severity === 'info'"
 | 
					                  v-if="props.row.alert_severity === 'info'"
 | 
				
			||||||
                  style="font-size: 1.3rem"
 | 
					                  style="font-size: 1.3rem"
 | 
				
			||||||
                  color="info"
 | 
					                  :color="dash_info_color"
 | 
				
			||||||
                  name="info"
 | 
					                  name="info"
 | 
				
			||||||
                >
 | 
					                >
 | 
				
			||||||
                  <q-tooltip>Informational</q-tooltip>
 | 
					                  <q-tooltip>Informational</q-tooltip>
 | 
				
			||||||
@@ -59,7 +59,7 @@
 | 
				
			|||||||
                <q-icon
 | 
					                <q-icon
 | 
				
			||||||
                  v-else-if="props.row.alert_severity === 'warning'"
 | 
					                  v-else-if="props.row.alert_severity === 'warning'"
 | 
				
			||||||
                  style="font-size: 1.3rem"
 | 
					                  style="font-size: 1.3rem"
 | 
				
			||||||
                  color="warning"
 | 
					                  :color="dash_warning_color"
 | 
				
			||||||
                  name="warning"
 | 
					                  name="warning"
 | 
				
			||||||
                >
 | 
					                >
 | 
				
			||||||
                  <q-tooltip>Warning</q-tooltip>
 | 
					                  <q-tooltip>Warning</q-tooltip>
 | 
				
			||||||
@@ -67,7 +67,7 @@
 | 
				
			|||||||
                <q-icon
 | 
					                <q-icon
 | 
				
			||||||
                  v-else
 | 
					                  v-else
 | 
				
			||||||
                  style="font-size: 1.3rem"
 | 
					                  style="font-size: 1.3rem"
 | 
				
			||||||
                  color="negative"
 | 
					                  :color="dash_negative_color"
 | 
				
			||||||
                  name="error"
 | 
					                  name="error"
 | 
				
			||||||
                >
 | 
					                >
 | 
				
			||||||
                  <q-tooltip>Error</q-tooltip>
 | 
					                  <q-tooltip>Error</q-tooltip>
 | 
				
			||||||
@@ -148,7 +148,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
<script>
 | 
					<script>
 | 
				
			||||||
import { computed } from "vue";
 | 
					import { computed } from "vue";
 | 
				
			||||||
import { useStore } from "vuex";
 | 
					import { useStore, mapState } from "vuex";
 | 
				
			||||||
import ScriptOutput from "@/components/checks/ScriptOutput.vue";
 | 
					import ScriptOutput from "@/components/checks/ScriptOutput.vue";
 | 
				
			||||||
import EventLogCheckOutput from "@/components/checks/EventLogCheckOutput.vue";
 | 
					import EventLogCheckOutput from "@/components/checks/EventLogCheckOutput.vue";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -220,6 +220,12 @@ export default {
 | 
				
			|||||||
    };
 | 
					    };
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  computed: {
 | 
					  computed: {
 | 
				
			||||||
 | 
					    ...mapState([
 | 
				
			||||||
 | 
					      "dash_info_color",
 | 
				
			||||||
 | 
					      "dash_positive_color",
 | 
				
			||||||
 | 
					      "dash_negative_color",
 | 
				
			||||||
 | 
					      "dash_warning_color",
 | 
				
			||||||
 | 
					    ]),
 | 
				
			||||||
    title() {
 | 
					    title() {
 | 
				
			||||||
      return !!this.item.readable_desc
 | 
					      return !!this.item.readable_desc
 | 
				
			||||||
        ? this.item.readable_desc + " Status"
 | 
					        ? this.item.readable_desc + " Status"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -304,6 +304,9 @@ export default {
 | 
				
			|||||||
    // setup vuex
 | 
					    // setup vuex
 | 
				
			||||||
    const store = useStore();
 | 
					    const store = useStore();
 | 
				
			||||||
    const formatDate = computed(() => store.getters.formatDate);
 | 
					    const formatDate = computed(() => store.getters.formatDate);
 | 
				
			||||||
 | 
					    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 dropdowns
 | 
					    // setup dropdowns
 | 
				
			||||||
    const { clientOptions, getClientOptions } = useClientDropdown();
 | 
					    const { clientOptions, getClientOptions } = useClientDropdown();
 | 
				
			||||||
@@ -381,12 +384,18 @@ export default {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    function formatActionColor(action) {
 | 
					    function formatActionColor(action) {
 | 
				
			||||||
      if (action === "add") return "success";
 | 
					      switch (action.toLowerCase()) {
 | 
				
			||||||
      else if (action === "agent_install") return "success";
 | 
					        case "modify":
 | 
				
			||||||
      else if (action === "modify") return "warning";
 | 
					          return dash_warning_color.value;
 | 
				
			||||||
      else if (action === "delete") return "negative";
 | 
					        case "add":
 | 
				
			||||||
      else if (action === "failed_login") return "negative";
 | 
					        case "agent_install":
 | 
				
			||||||
      else return "primary";
 | 
					          return dash_positive_color.value;
 | 
				
			||||||
 | 
					        case "delete":
 | 
				
			||||||
 | 
					        case "failed_login":
 | 
				
			||||||
 | 
					          return dash_negative_color.value;
 | 
				
			||||||
 | 
					        default:
 | 
				
			||||||
 | 
					          return "primary";
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // watchers
 | 
					    // watchers
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -68,25 +68,25 @@
 | 
				
			|||||||
        />
 | 
					        />
 | 
				
			||||||
        <q-radio
 | 
					        <q-radio
 | 
				
			||||||
          v-model="logLevelFilter"
 | 
					          v-model="logLevelFilter"
 | 
				
			||||||
          color="cyan"
 | 
					          :color="dash_info_color"
 | 
				
			||||||
          val="info"
 | 
					          val="info"
 | 
				
			||||||
          label="Info"
 | 
					          label="Info"
 | 
				
			||||||
        />
 | 
					        />
 | 
				
			||||||
        <q-radio
 | 
					        <q-radio
 | 
				
			||||||
          v-model="logLevelFilter"
 | 
					          v-model="logLevelFilter"
 | 
				
			||||||
          color="red"
 | 
					          :color="dash_negative_color"
 | 
				
			||||||
          val="critical"
 | 
					          val="critical"
 | 
				
			||||||
          label="Critical"
 | 
					          label="Critical"
 | 
				
			||||||
        />
 | 
					        />
 | 
				
			||||||
        <q-radio
 | 
					        <q-radio
 | 
				
			||||||
          v-model="logLevelFilter"
 | 
					          v-model="logLevelFilter"
 | 
				
			||||||
          color="red"
 | 
					          :color="dash_negative_color"
 | 
				
			||||||
          val="error"
 | 
					          val="error"
 | 
				
			||||||
          label="Error"
 | 
					          label="Error"
 | 
				
			||||||
        />
 | 
					        />
 | 
				
			||||||
        <q-radio
 | 
					        <q-radio
 | 
				
			||||||
          v-model="logLevelFilter"
 | 
					          v-model="logLevelFilter"
 | 
				
			||||||
          color="yellow"
 | 
					          :color="dash_warning_color"
 | 
				
			||||||
          val="warning"
 | 
					          val="warning"
 | 
				
			||||||
          label="Warning"
 | 
					          label="Warning"
 | 
				
			||||||
        />
 | 
					        />
 | 
				
			||||||
@@ -109,7 +109,7 @@
 | 
				
			|||||||
      <template v-slot:top-row>
 | 
					      <template v-slot:top-row>
 | 
				
			||||||
        <q-tr v-if="Array.isArray(debugLog) && debugLog.length === 1000">
 | 
					        <q-tr v-if="Array.isArray(debugLog) && debugLog.length === 1000">
 | 
				
			||||||
          <q-td colspan="100%">
 | 
					          <q-td colspan="100%">
 | 
				
			||||||
            <q-icon name="warning" color="warning" />
 | 
					            <q-icon name="warning" :color="dash_warning_color" />
 | 
				
			||||||
            Results are limited to 1000 rows.
 | 
					            Results are limited to 1000 rows.
 | 
				
			||||||
          </q-td>
 | 
					          </q-td>
 | 
				
			||||||
        </q-tr>
 | 
					        </q-tr>
 | 
				
			||||||
@@ -203,6 +203,10 @@ export default {
 | 
				
			|||||||
    const store = useStore();
 | 
					    const store = useStore();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const formatDate = computed(() => store.getters.formatDate);
 | 
					    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 dropdowns
 | 
					    // setup dropdowns
 | 
				
			||||||
    const { agentOptions, getAgentOptions } = useAgentDropdown();
 | 
					    const { agentOptions, getAgentOptions } = useAgentDropdown();
 | 
				
			||||||
@@ -261,6 +265,10 @@ export default {
 | 
				
			|||||||
      agentOptions,
 | 
					      agentOptions,
 | 
				
			||||||
      loading,
 | 
					      loading,
 | 
				
			||||||
      filter,
 | 
					      filter,
 | 
				
			||||||
 | 
					      dash_info_color,
 | 
				
			||||||
 | 
					      dash_positive_color,
 | 
				
			||||||
 | 
					      dash_warning_color,
 | 
				
			||||||
 | 
					      dash_negative_color,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // non-reactive data
 | 
					      // non-reactive data
 | 
				
			||||||
      columns,
 | 
					      columns,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -94,7 +94,7 @@
 | 
				
			|||||||
                        class="q-pr-sm"
 | 
					                        class="q-pr-sm"
 | 
				
			||||||
                        name="fas fa-signal"
 | 
					                        name="fas fa-signal"
 | 
				
			||||||
                        size="1.2em"
 | 
					                        size="1.2em"
 | 
				
			||||||
                        color="warning"
 | 
					                        :color="dash_warning_color"
 | 
				
			||||||
                      />
 | 
					                      />
 | 
				
			||||||
                      Mark an agent as
 | 
					                      Mark an agent as
 | 
				
			||||||
                      <span class="text-weight-bold">offline</span> if it has
 | 
					                      <span class="text-weight-bold">offline</span> if it has
 | 
				
			||||||
@@ -120,7 +120,7 @@
 | 
				
			|||||||
                        class="q-pr-sm"
 | 
					                        class="q-pr-sm"
 | 
				
			||||||
                        name="fas fa-signal"
 | 
					                        name="fas fa-signal"
 | 
				
			||||||
                        size="1.2em"
 | 
					                        size="1.2em"
 | 
				
			||||||
                        color="negative"
 | 
					                        :color="dash_negative_color"
 | 
				
			||||||
                      />
 | 
					                      />
 | 
				
			||||||
                      Mark an agent as
 | 
					                      Mark an agent as
 | 
				
			||||||
                      <span class="text-weight-bold">overdue</span> if it has
 | 
					                      <span class="text-weight-bold">overdue</span> if it has
 | 
				
			||||||
@@ -373,6 +373,7 @@
 | 
				
			|||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<script>
 | 
					<script>
 | 
				
			||||||
 | 
					import { mapState } from "vuex";
 | 
				
			||||||
import { useDialogPluginComponent } from "quasar";
 | 
					import { useDialogPluginComponent } from "quasar";
 | 
				
			||||||
import mixins from "@/mixins/mixins";
 | 
					import mixins from "@/mixins/mixins";
 | 
				
			||||||
import PatchPolicyForm from "@/components/modals/agents/PatchPolicyForm.vue";
 | 
					import PatchPolicyForm from "@/components/modals/agents/PatchPolicyForm.vue";
 | 
				
			||||||
@@ -549,6 +550,9 @@ export default {
 | 
				
			|||||||
      return result.trimEnd(",");
 | 
					      return result.trimEnd(",");
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
 | 
					  computed: {
 | 
				
			||||||
 | 
					    ...mapState(["dash_warning_color", "dash_negative_color"]),
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
  mounted() {
 | 
					  mounted() {
 | 
				
			||||||
    // Get custom fields
 | 
					    // Get custom fields
 | 
				
			||||||
    this.getCustomFields("agent").then((r) => {
 | 
					    this.getCustomFields("agent").then((r) => {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,6 +12,7 @@
 | 
				
			|||||||
          <q-tab name="urlactions" label="URL Actions" />
 | 
					          <q-tab name="urlactions" label="URL Actions" />
 | 
				
			||||||
          <q-tab name="retention" label="Retention" />
 | 
					          <q-tab name="retention" label="Retention" />
 | 
				
			||||||
          <q-tab name="apikeys" label="API Keys" />
 | 
					          <q-tab name="apikeys" label="API Keys" />
 | 
				
			||||||
 | 
					          <!-- <q-tab name="openai" label="Open AI" /> -->
 | 
				
			||||||
        </q-tabs>
 | 
					        </q-tabs>
 | 
				
			||||||
      </template>
 | 
					      </template>
 | 
				
			||||||
      <template v-slot:after>
 | 
					      <template v-slot:after>
 | 
				
			||||||
@@ -508,6 +509,49 @@
 | 
				
			|||||||
              <q-tab-panel name="apikeys">
 | 
					              <q-tab-panel name="apikeys">
 | 
				
			||||||
                <APIKeysTable />
 | 
					                <APIKeysTable />
 | 
				
			||||||
              </q-tab-panel>
 | 
					              </q-tab-panel>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					              <!-- Open AI -->
 | 
				
			||||||
 | 
					              <!-- <q-tab-panel name="openai">
 | 
				
			||||||
 | 
					                <div class="text-subtitle2">Open AI</div>
 | 
				
			||||||
 | 
					                <q-separator />
 | 
				
			||||||
 | 
					                <q-card-section class="row">
 | 
				
			||||||
 | 
					                  <div class="col-4">API Key:</div>
 | 
				
			||||||
 | 
					                  <div class="col-2"></div>
 | 
				
			||||||
 | 
					                  <q-input
 | 
				
			||||||
 | 
					                    dense
 | 
				
			||||||
 | 
					                    outlined
 | 
				
			||||||
 | 
					                    v-model="settings.open_ai_token"
 | 
				
			||||||
 | 
					                    class="col-6"
 | 
				
			||||||
 | 
					                  />
 | 
				
			||||||
 | 
					                </q-card-section>
 | 
				
			||||||
 | 
					                <q-card-section class="row">
 | 
				
			||||||
 | 
					                  <div class="col-4">Open AI Model:</div>
 | 
				
			||||||
 | 
					                  <div class="col-2"></div>
 | 
				
			||||||
 | 
					                  <q-input
 | 
				
			||||||
 | 
					                    dense
 | 
				
			||||||
 | 
					                    outlined
 | 
				
			||||||
 | 
					                    v-model="settings.open_ai_model"
 | 
				
			||||||
 | 
					                    class="col-6"
 | 
				
			||||||
 | 
					                  >
 | 
				
			||||||
 | 
					                    <template v-slot:after>
 | 
				
			||||||
 | 
					                      <q-btn
 | 
				
			||||||
 | 
					                        round
 | 
				
			||||||
 | 
					                        dense
 | 
				
			||||||
 | 
					                        flat
 | 
				
			||||||
 | 
					                        icon="info"
 | 
				
			||||||
 | 
					                        size="sm"
 | 
				
			||||||
 | 
					                        @click="
 | 
				
			||||||
 | 
					                          openURL(
 | 
				
			||||||
 | 
					                            'https://platform.openai.com/docs/models/overview'
 | 
				
			||||||
 | 
					                          )
 | 
				
			||||||
 | 
					                        "
 | 
				
			||||||
 | 
					                      >
 | 
				
			||||||
 | 
					                        <q-tooltip>Click to see available options</q-tooltip>
 | 
				
			||||||
 | 
					                      </q-btn>
 | 
				
			||||||
 | 
					                    </template>
 | 
				
			||||||
 | 
					                  </q-input>
 | 
				
			||||||
 | 
					                </q-card-section>
 | 
				
			||||||
 | 
					              </q-tab-panel> -->
 | 
				
			||||||
            </q-tab-panels>
 | 
					            </q-tab-panels>
 | 
				
			||||||
          </q-scroll-area>
 | 
					          </q-scroll-area>
 | 
				
			||||||
          <q-card-section class="row items-center">
 | 
					          <q-card-section class="row items-center">
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -82,6 +82,98 @@
 | 
				
			|||||||
                    class="col-4"
 | 
					                    class="col-4"
 | 
				
			||||||
                  />
 | 
					                  />
 | 
				
			||||||
                </q-card-section>
 | 
					                </q-card-section>
 | 
				
			||||||
 | 
					                <q-card-section class="row">
 | 
				
			||||||
 | 
					                  <div class="col-2">Dashboard Info Color:</div>
 | 
				
			||||||
 | 
					                  <div class="col-2"></div>
 | 
				
			||||||
 | 
					                  <q-input
 | 
				
			||||||
 | 
					                    outlined
 | 
				
			||||||
 | 
					                    dense
 | 
				
			||||||
 | 
					                    v-model="dash_info_color"
 | 
				
			||||||
 | 
					                    class="col-8"
 | 
				
			||||||
 | 
					                  >
 | 
				
			||||||
 | 
					                    <template v-slot:after>
 | 
				
			||||||
 | 
					                      <q-btn
 | 
				
			||||||
 | 
					                        round
 | 
				
			||||||
 | 
					                        dense
 | 
				
			||||||
 | 
					                        flat
 | 
				
			||||||
 | 
					                        size="sm"
 | 
				
			||||||
 | 
					                        icon="info"
 | 
				
			||||||
 | 
					                        @click="openURL(quasar_color_url)"
 | 
				
			||||||
 | 
					                      >
 | 
				
			||||||
 | 
					                        <q-tooltip>Click to see color options</q-tooltip>
 | 
				
			||||||
 | 
					                      </q-btn>
 | 
				
			||||||
 | 
					                    </template>
 | 
				
			||||||
 | 
					                  </q-input>
 | 
				
			||||||
 | 
					                </q-card-section>
 | 
				
			||||||
 | 
					                <q-card-section class="row">
 | 
				
			||||||
 | 
					                  <div class="col-2">Dashboard Positive Color:</div>
 | 
				
			||||||
 | 
					                  <div class="col-2"></div>
 | 
				
			||||||
 | 
					                  <q-input
 | 
				
			||||||
 | 
					                    outlined
 | 
				
			||||||
 | 
					                    dense
 | 
				
			||||||
 | 
					                    v-model="dash_positive_color"
 | 
				
			||||||
 | 
					                    class="col-8"
 | 
				
			||||||
 | 
					                  >
 | 
				
			||||||
 | 
					                    <template v-slot:after>
 | 
				
			||||||
 | 
					                      <q-btn
 | 
				
			||||||
 | 
					                        round
 | 
				
			||||||
 | 
					                        dense
 | 
				
			||||||
 | 
					                        flat
 | 
				
			||||||
 | 
					                        size="sm"
 | 
				
			||||||
 | 
					                        icon="info"
 | 
				
			||||||
 | 
					                        @click="openURL(quasar_color_url)"
 | 
				
			||||||
 | 
					                      >
 | 
				
			||||||
 | 
					                        <q-tooltip>Click to see color options</q-tooltip>
 | 
				
			||||||
 | 
					                      </q-btn>
 | 
				
			||||||
 | 
					                    </template>
 | 
				
			||||||
 | 
					                  </q-input>
 | 
				
			||||||
 | 
					                </q-card-section>
 | 
				
			||||||
 | 
					                <q-card-section class="row">
 | 
				
			||||||
 | 
					                  <div class="col-2">Dashboard Negative Color:</div>
 | 
				
			||||||
 | 
					                  <div class="col-2"></div>
 | 
				
			||||||
 | 
					                  <q-input
 | 
				
			||||||
 | 
					                    outlined
 | 
				
			||||||
 | 
					                    dense
 | 
				
			||||||
 | 
					                    v-model="dash_negative_color"
 | 
				
			||||||
 | 
					                    class="col-8"
 | 
				
			||||||
 | 
					                  >
 | 
				
			||||||
 | 
					                    <template v-slot:after>
 | 
				
			||||||
 | 
					                      <q-btn
 | 
				
			||||||
 | 
					                        round
 | 
				
			||||||
 | 
					                        dense
 | 
				
			||||||
 | 
					                        flat
 | 
				
			||||||
 | 
					                        size="sm"
 | 
				
			||||||
 | 
					                        icon="info"
 | 
				
			||||||
 | 
					                        @click="openURL(quasar_color_url)"
 | 
				
			||||||
 | 
					                      >
 | 
				
			||||||
 | 
					                        <q-tooltip>Click to see color options</q-tooltip>
 | 
				
			||||||
 | 
					                      </q-btn>
 | 
				
			||||||
 | 
					                    </template>
 | 
				
			||||||
 | 
					                  </q-input>
 | 
				
			||||||
 | 
					                </q-card-section>
 | 
				
			||||||
 | 
					                <q-card-section class="row">
 | 
				
			||||||
 | 
					                  <div class="col-2">Dashboard Warning Color:</div>
 | 
				
			||||||
 | 
					                  <div class="col-2"></div>
 | 
				
			||||||
 | 
					                  <q-input
 | 
				
			||||||
 | 
					                    outlined
 | 
				
			||||||
 | 
					                    dense
 | 
				
			||||||
 | 
					                    v-model="dash_warning_color"
 | 
				
			||||||
 | 
					                    class="col-8"
 | 
				
			||||||
 | 
					                  >
 | 
				
			||||||
 | 
					                    <template v-slot:after>
 | 
				
			||||||
 | 
					                      <q-btn
 | 
				
			||||||
 | 
					                        round
 | 
				
			||||||
 | 
					                        dense
 | 
				
			||||||
 | 
					                        flat
 | 
				
			||||||
 | 
					                        size="sm"
 | 
				
			||||||
 | 
					                        icon="info"
 | 
				
			||||||
 | 
					                        @click="openURL(quasar_color_url)"
 | 
				
			||||||
 | 
					                      >
 | 
				
			||||||
 | 
					                        <q-tooltip>Click to see color options</q-tooltip>
 | 
				
			||||||
 | 
					                      </q-btn>
 | 
				
			||||||
 | 
					                    </template>
 | 
				
			||||||
 | 
					                  </q-input>
 | 
				
			||||||
 | 
					                </q-card-section>
 | 
				
			||||||
                <q-card-section class="row">
 | 
					                <q-card-section class="row">
 | 
				
			||||||
                  <div class="col-2">Client Sort:</div>
 | 
					                  <div class="col-2">Client Sort:</div>
 | 
				
			||||||
                  <div class="col-2"></div>
 | 
					                  <div class="col-2"></div>
 | 
				
			||||||
@@ -156,9 +248,14 @@ export default {
 | 
				
			|||||||
      tab: "ui",
 | 
					      tab: "ui",
 | 
				
			||||||
      splitterModel: 20,
 | 
					      splitterModel: 20,
 | 
				
			||||||
      loading_bar_color: "",
 | 
					      loading_bar_color: "",
 | 
				
			||||||
 | 
					      dash_info_color: "",
 | 
				
			||||||
 | 
					      dash_positive_color: "",
 | 
				
			||||||
 | 
					      dash_negative_color: "",
 | 
				
			||||||
 | 
					      dash_warning_color: "",
 | 
				
			||||||
      urlActions: [],
 | 
					      urlActions: [],
 | 
				
			||||||
      clear_search_when_switching: true,
 | 
					      clear_search_when_switching: true,
 | 
				
			||||||
      date_format: "",
 | 
					      date_format: "",
 | 
				
			||||||
 | 
					      quasar_color_url: "https://quasar.dev/style/color-palette",
 | 
				
			||||||
      clientTreeSortOptions: [
 | 
					      clientTreeSortOptions: [
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
          label: "Sort alphabetically, moving failing clients to the top",
 | 
					          label: "Sort alphabetically, moving failing clients to the top",
 | 
				
			||||||
@@ -235,6 +332,10 @@ export default {
 | 
				
			|||||||
        this.defaultAgentTblTab = r.data.default_agent_tbl_tab;
 | 
					        this.defaultAgentTblTab = r.data.default_agent_tbl_tab;
 | 
				
			||||||
        this.clientTreeSort = r.data.client_tree_sort;
 | 
					        this.clientTreeSort = r.data.client_tree_sort;
 | 
				
			||||||
        this.loading_bar_color = r.data.loading_bar_color;
 | 
					        this.loading_bar_color = r.data.loading_bar_color;
 | 
				
			||||||
 | 
					        this.dash_info_color = r.data.dash_info_color;
 | 
				
			||||||
 | 
					        this.dash_positive_color = r.data.dash_positive_color;
 | 
				
			||||||
 | 
					        this.dash_negative_color = r.data.dash_negative_color;
 | 
				
			||||||
 | 
					        this.dash_warning_color = r.data.dash_warning_color;
 | 
				
			||||||
        this.clear_search_when_switching = r.data.clear_search_when_switching;
 | 
					        this.clear_search_when_switching = r.data.clear_search_when_switching;
 | 
				
			||||||
        this.date_format = r.data.date_format;
 | 
					        this.date_format = r.data.date_format;
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
@@ -253,6 +354,10 @@ export default {
 | 
				
			|||||||
        default_agent_tbl_tab: this.defaultAgentTblTab,
 | 
					        default_agent_tbl_tab: this.defaultAgentTblTab,
 | 
				
			||||||
        client_tree_sort: this.clientTreeSort,
 | 
					        client_tree_sort: this.clientTreeSort,
 | 
				
			||||||
        loading_bar_color: this.loading_bar_color,
 | 
					        loading_bar_color: this.loading_bar_color,
 | 
				
			||||||
 | 
					        dash_info_color: this.dash_info_color,
 | 
				
			||||||
 | 
					        dash_positive_color: this.dash_positive_color,
 | 
				
			||||||
 | 
					        dash_negative_color: this.dash_negative_color,
 | 
				
			||||||
 | 
					        dash_warning_color: this.dash_warning_color,
 | 
				
			||||||
        clear_search_when_switching: this.clear_search_when_switching,
 | 
					        clear_search_when_switching: this.clear_search_when_switching,
 | 
				
			||||||
        date_format: this.date_format,
 | 
					        date_format: this.date_format,
 | 
				
			||||||
      };
 | 
					      };
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,7 +11,17 @@
 | 
				
			|||||||
      :style="maximized ? '' : 'width: 90vw; max-width: 90vw'"
 | 
					      :style="maximized ? '' : 'width: 90vw; max-width: 90vw'"
 | 
				
			||||||
    >
 | 
					    >
 | 
				
			||||||
      <q-bar>
 | 
					      <q-bar>
 | 
				
			||||||
        {{ title }}
 | 
					        <span class="q-pr-sm">{{ title }}</span>
 | 
				
			||||||
 | 
					        <q-btn
 | 
				
			||||||
 | 
					          v-if="!script && openAIEnabled"
 | 
				
			||||||
 | 
					          size="xs"
 | 
				
			||||||
 | 
					          :disable="loading"
 | 
				
			||||||
 | 
					          dense
 | 
				
			||||||
 | 
					          label="Generate Script"
 | 
				
			||||||
 | 
					          color="primary"
 | 
				
			||||||
 | 
					          no-caps
 | 
				
			||||||
 | 
					          @click="generateScriptOpenAI"
 | 
				
			||||||
 | 
					        />
 | 
				
			||||||
        <q-space />
 | 
					        <q-space />
 | 
				
			||||||
        <q-btn
 | 
					        <q-btn
 | 
				
			||||||
          dense
 | 
					          dense
 | 
				
			||||||
@@ -57,7 +67,23 @@
 | 
				
			|||||||
          ><br />Add one to get rid of this warning. Ignore if windows.
 | 
					          ><br />Add one to get rid of this warning. Ignore if windows.
 | 
				
			||||||
        </q-banner>
 | 
					        </q-banner>
 | 
				
			||||||
        <div class="row q-pa-sm">
 | 
					        <div class="row q-pa-sm">
 | 
				
			||||||
          <div class="col-4 q-gutter-sm q-pr-sm">
 | 
					          <q-scroll-area
 | 
				
			||||||
 | 
					            :thumb-style="{
 | 
				
			||||||
 | 
					              right: '4px',
 | 
				
			||||||
 | 
					              borderRadius: '5px',
 | 
				
			||||||
 | 
					              width: '5px',
 | 
				
			||||||
 | 
					              opacity: 0.75,
 | 
				
			||||||
 | 
					            }"
 | 
				
			||||||
 | 
					            :bar-style="{
 | 
				
			||||||
 | 
					              right: '2px',
 | 
				
			||||||
 | 
					              borderRadius: '9px',
 | 
				
			||||||
 | 
					              width: '9px',
 | 
				
			||||||
 | 
					              opacity: 0.2,
 | 
				
			||||||
 | 
					            }"
 | 
				
			||||||
 | 
					            class="col-4 q-mb-none q-pb-none"
 | 
				
			||||||
 | 
					            :style="{ height: `${maximized ? '82vh' : '64vh'}` }"
 | 
				
			||||||
 | 
					          >
 | 
				
			||||||
 | 
					            <div class="q-gutter-sm q-pr-sm">
 | 
				
			||||||
              <q-input
 | 
					              <q-input
 | 
				
			||||||
                filled
 | 
					                filled
 | 
				
			||||||
                dense
 | 
					                dense
 | 
				
			||||||
@@ -144,11 +170,11 @@
 | 
				
			|||||||
                label="Run As User (Windows only)"
 | 
					                label="Run As User (Windows only)"
 | 
				
			||||||
              >
 | 
					              >
 | 
				
			||||||
                <q-tooltip
 | 
					                <q-tooltip
 | 
				
			||||||
                >Setting this value on the script model will always override any
 | 
					                  >Setting this value on the script model will always override
 | 
				
			||||||
                'Run As User' checkboxes in the UI and force this script to
 | 
					                  any 'Run As User' checkboxes in the UI and force this script
 | 
				
			||||||
                always be run in the context of the logged in user. If no user
 | 
					                  to always be run in the context of the logged in user. If no
 | 
				
			||||||
                is logged in, the script will not run and an error will be
 | 
					                  user is logged in, the script will not run and an error will
 | 
				
			||||||
                returned.
 | 
					                  be returned.
 | 
				
			||||||
                </q-tooltip>
 | 
					                </q-tooltip>
 | 
				
			||||||
              </q-checkbox>
 | 
					              </q-checkbox>
 | 
				
			||||||
              <q-input
 | 
					              <q-input
 | 
				
			||||||
@@ -161,12 +187,13 @@
 | 
				
			|||||||
                :readonly="readonly"
 | 
					                :readonly="readonly"
 | 
				
			||||||
              />
 | 
					              />
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
 | 
					          </q-scroll-area>
 | 
				
			||||||
          <v-ace-editor
 | 
					          <v-ace-editor
 | 
				
			||||||
            v-model:value="formScript.script_body"
 | 
					            v-model:value="formScript.script_body"
 | 
				
			||||||
            class="col-8"
 | 
					            class="col-8"
 | 
				
			||||||
            :lang="lang"
 | 
					            :lang="lang"
 | 
				
			||||||
            :theme="$q.dark.isActive ? 'tomorrow_night_eighties' : 'tomorrow'"
 | 
					            :theme="$q.dark.isActive ? 'tomorrow_night_eighties' : 'tomorrow'"
 | 
				
			||||||
            :style="{ height: `${maximized ? '87vh' : '64vh'}` }"
 | 
					            :style="{ height: `${maximized ? '82vh' : '64vh'}` }"
 | 
				
			||||||
            wrap
 | 
					            wrap
 | 
				
			||||||
            :printMargin="false"
 | 
					            :printMargin="false"
 | 
				
			||||||
            :options="{ fontSize: '14px' }"
 | 
					            :options="{ fontSize: '14px' }"
 | 
				
			||||||
@@ -220,9 +247,11 @@
 | 
				
			|||||||
<script>
 | 
					<script>
 | 
				
			||||||
// composable imports
 | 
					// composable imports
 | 
				
			||||||
import { ref, computed, onMounted } from "vue";
 | 
					import { ref, computed, onMounted } from "vue";
 | 
				
			||||||
 | 
					import { useStore } from "vuex";
 | 
				
			||||||
import { useQuasar, useDialogPluginComponent } from "quasar";
 | 
					import { useQuasar, useDialogPluginComponent } from "quasar";
 | 
				
			||||||
import { saveScript, editScript, downloadScript } from "@/api/scripts";
 | 
					import { saveScript, editScript, downloadScript } from "@/api/scripts";
 | 
				
			||||||
import { useAgentDropdown, agentPlatformOptions } from "@/composables/agents";
 | 
					import { useAgentDropdown, agentPlatformOptions } from "@/composables/agents";
 | 
				
			||||||
 | 
					import { generateScript } from "@/api/core";
 | 
				
			||||||
import { notifySuccess } from "@/utils/notify";
 | 
					import { notifySuccess } from "@/utils/notify";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ui imports
 | 
					// ui imports
 | 
				
			||||||
@@ -266,6 +295,10 @@ export default {
 | 
				
			|||||||
    const { dialogRef, onDialogHide, onDialogOK } = useDialogPluginComponent();
 | 
					    const { dialogRef, onDialogHide, onDialogOK } = useDialogPluginComponent();
 | 
				
			||||||
    const $q = useQuasar();
 | 
					    const $q = useQuasar();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // setup store
 | 
				
			||||||
 | 
					    const store = useStore();
 | 
				
			||||||
 | 
					    const openAIEnabled = computed(() => store.state.openAIIntegrationEnabled);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // setup agent dropdown
 | 
					    // setup agent dropdown
 | 
				
			||||||
    const { agent, agentOptions, getAgentOptions } = useAgentDropdown();
 | 
					    const { agent, agentOptions, getAgentOptions } = useAgentDropdown();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -355,6 +388,23 @@ export default {
 | 
				
			|||||||
      });
 | 
					      });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function generateScriptOpenAI() {
 | 
				
			||||||
 | 
					      $q.dialog({
 | 
				
			||||||
 | 
					        title: "Ask ChatGPT what you need!",
 | 
				
			||||||
 | 
					        prompt: {
 | 
				
			||||||
 | 
					          model: `${lang.value} code that `,
 | 
				
			||||||
 | 
					          type: "text",
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        cancel: true,
 | 
				
			||||||
 | 
					        persistent: true,
 | 
				
			||||||
 | 
					      }).onOk(async (data) => {
 | 
				
			||||||
 | 
					        const completion = await generateScript({
 | 
				
			||||||
 | 
					          prompt: data,
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					        script.value.script_body = completion;
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // component life cycle hooks
 | 
					    // component life cycle hooks
 | 
				
			||||||
    onMounted(async () => {
 | 
					    onMounted(async () => {
 | 
				
			||||||
      agentLoading.value = true;
 | 
					      agentLoading.value = true;
 | 
				
			||||||
@@ -380,10 +430,12 @@ export default {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
      //computed
 | 
					      //computed
 | 
				
			||||||
      title,
 | 
					      title,
 | 
				
			||||||
 | 
					      openAIEnabled,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      //methods
 | 
					      //methods
 | 
				
			||||||
      submitForm,
 | 
					      submitForm,
 | 
				
			||||||
      openTestScriptModal,
 | 
					      openTestScriptModal,
 | 
				
			||||||
 | 
					      generateScriptOpenAI,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // quasar dialog plugin
 | 
					      // quasar dialog plugin
 | 
				
			||||||
      dialogRef,
 | 
					      dialogRef,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,7 +11,17 @@
 | 
				
			|||||||
      :style="maximized ? '' : 'width: 70vw; max-width: 90vw'"
 | 
					      :style="maximized ? '' : 'width: 70vw; max-width: 90vw'"
 | 
				
			||||||
    >
 | 
					    >
 | 
				
			||||||
      <q-bar>
 | 
					      <q-bar>
 | 
				
			||||||
        {{ title }}
 | 
					        <span class="q-pr-sm">{{ title }}</span>
 | 
				
			||||||
 | 
					        <q-btn
 | 
				
			||||||
 | 
					          v-if="!snippet && openAIEnabled"
 | 
				
			||||||
 | 
					          :disable="loading"
 | 
				
			||||||
 | 
					          dense
 | 
				
			||||||
 | 
					          size="xs"
 | 
				
			||||||
 | 
					          label="Generate Script"
 | 
				
			||||||
 | 
					          color="primary"
 | 
				
			||||||
 | 
					          no-caps
 | 
				
			||||||
 | 
					          @click="generateScriptOpenAI"
 | 
				
			||||||
 | 
					        />
 | 
				
			||||||
        <q-space />
 | 
					        <q-space />
 | 
				
			||||||
        <q-btn
 | 
					        <q-btn
 | 
				
			||||||
          dense
 | 
					          dense
 | 
				
			||||||
@@ -97,6 +107,9 @@
 | 
				
			|||||||
<script>
 | 
					<script>
 | 
				
			||||||
// composable imports
 | 
					// composable imports
 | 
				
			||||||
import { ref, computed } from "vue";
 | 
					import { ref, computed } from "vue";
 | 
				
			||||||
 | 
					import { useStore } from "vuex";
 | 
				
			||||||
 | 
					import { useQuasar } from "quasar";
 | 
				
			||||||
 | 
					import { generateScript } from "@/api/core";
 | 
				
			||||||
import { useDialogPluginComponent } from "quasar";
 | 
					import { useDialogPluginComponent } from "quasar";
 | 
				
			||||||
import { saveScriptSnippet, editScriptSnippet } from "@/api/scripts";
 | 
					import { saveScriptSnippet, editScriptSnippet } from "@/api/scripts";
 | 
				
			||||||
import { notifySuccess } from "@/utils/notify";
 | 
					import { notifySuccess } from "@/utils/notify";
 | 
				
			||||||
@@ -128,6 +141,13 @@ export default {
 | 
				
			|||||||
    // setup quasar plugins
 | 
					    // setup quasar plugins
 | 
				
			||||||
    const { dialogRef, onDialogHide, onDialogOK } = useDialogPluginComponent();
 | 
					    const { dialogRef, onDialogHide, onDialogOK } = useDialogPluginComponent();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // setup quasar
 | 
				
			||||||
 | 
					    const $q = useQuasar();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // setup store
 | 
				
			||||||
 | 
					    const store = useStore();
 | 
				
			||||||
 | 
					    const openAIEnabled = computed(() => store.state.openAIIntegrationEnabled);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // snippet form logic
 | 
					    // snippet form logic
 | 
				
			||||||
    const snippet = props.snippet
 | 
					    const snippet = props.snippet
 | 
				
			||||||
      ? ref(Object.assign({}, props.snippet))
 | 
					      ? ref(Object.assign({}, props.snippet))
 | 
				
			||||||
@@ -167,6 +187,23 @@ export default {
 | 
				
			|||||||
      loading.value = false;
 | 
					      loading.value = false;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function generateScriptOpenAI() {
 | 
				
			||||||
 | 
					      $q.dialog({
 | 
				
			||||||
 | 
					        title: "Ask ChatGPT what you need!",
 | 
				
			||||||
 | 
					        prompt: {
 | 
				
			||||||
 | 
					          model: `${lang.value} code that `,
 | 
				
			||||||
 | 
					          type: "text",
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        cancel: true,
 | 
				
			||||||
 | 
					        persistent: true,
 | 
				
			||||||
 | 
					      }).onOk(async (data) => {
 | 
				
			||||||
 | 
					        const completion = await generateScript({
 | 
				
			||||||
 | 
					          prompt: data,
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					        snippet.value.code = completion;
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return {
 | 
					    return {
 | 
				
			||||||
      // reactive data
 | 
					      // reactive data
 | 
				
			||||||
      formSnippet: snippet.value,
 | 
					      formSnippet: snippet.value,
 | 
				
			||||||
@@ -179,9 +216,11 @@ export default {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
      //computed
 | 
					      //computed
 | 
				
			||||||
      title,
 | 
					      title,
 | 
				
			||||||
 | 
					      openAIEnabled,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      //methods
 | 
					      //methods
 | 
				
			||||||
      submitForm,
 | 
					      submitForm,
 | 
				
			||||||
 | 
					      generateScriptOpenAI,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // quasar dialog plugin
 | 
					      // quasar dialog plugin
 | 
				
			||||||
      dialogRef,
 | 
					      dialogRef,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,5 @@
 | 
				
			|||||||
import { ref } from "vue";
 | 
					import { computed, ref } from "vue";
 | 
				
			||||||
 | 
					import { useStore } from "vuex";
 | 
				
			||||||
import { fetchAgents } from "@/api/agents";
 | 
					import { fetchAgents } from "@/api/agents";
 | 
				
			||||||
import { formatAgentOptions } from "@/utils/format";
 | 
					import { formatAgentOptions } from "@/utils/format";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -28,10 +29,12 @@ export function useAgentDropdown() {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function cmdPlaceholder(shell) {
 | 
					export function cmdPlaceholder(shell) {
 | 
				
			||||||
  if (shell === "cmd") return "rmdir /S /Q C:\\Windows\\System32";
 | 
					  const store = useStore();
 | 
				
			||||||
  else if (shell === "powershell")
 | 
					  const placeholders = computed(() => store.state.run_cmd_placeholder_text);
 | 
				
			||||||
    return "Remove-Item -Recurse -Force C:\\Windows\\System32";
 | 
					
 | 
				
			||||||
  else return "rm -rf --no-preserve-root /";
 | 
					  if (shell === "cmd") return placeholders.value.cmd;
 | 
				
			||||||
 | 
					  else if (shell === "powershell") return placeholders.value.powershell;
 | 
				
			||||||
 | 
					  else return placeholders.value.shell;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const agentPlatformOptions = [
 | 
					export const agentPlatformOptions = [
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -56,15 +56,27 @@
 | 
				
			|||||||
          Tactical RMM<span class="text-overline q-ml-sm"
 | 
					          Tactical RMM<span class="text-overline q-ml-sm"
 | 
				
			||||||
            >v{{ currentTRMMVersion }}</span
 | 
					            >v{{ currentTRMMVersion }}</span
 | 
				
			||||||
          >
 | 
					          >
 | 
				
			||||||
          <span class="text-overline q-ml-md" v-if="updateAvailable()"
 | 
					          <!-- update check -->
 | 
				
			||||||
            ><q-badge color="warning"
 | 
					          <q-chip
 | 
				
			||||||
 | 
					            v-if="updateAvailable"
 | 
				
			||||||
 | 
					            class="text-overline q-ml-sm"
 | 
				
			||||||
 | 
					            :color="dash_warning_color"
 | 
				
			||||||
 | 
					            icon="update"
 | 
				
			||||||
 | 
					            dense
 | 
				
			||||||
            ><a :href="latestReleaseURL" target="_blank"
 | 
					            ><a :href="latestReleaseURL" target="_blank"
 | 
				
			||||||
              >v{{ latestTRMMVersion }} available</a
 | 
					              >v{{ latestTRMMVersion }} available</a
 | 
				
			||||||
              ></q-badge
 | 
					            ></q-chip
 | 
				
			||||||
            ></span
 | 
					          >
 | 
				
			||||||
 | 
					          <!-- cert expiring soon check -->
 | 
				
			||||||
 | 
					          <q-chip
 | 
				
			||||||
 | 
					            v-if="daysUntilCertExpires <= 15"
 | 
				
			||||||
 | 
					            dense
 | 
				
			||||||
 | 
					            :color="dash_negative_color"
 | 
				
			||||||
 | 
					            text-color="black"
 | 
				
			||||||
 | 
					            icon="warning"
 | 
				
			||||||
 | 
					            >Certificate expires in {{ daysUntilCertExpires }} days</q-chip
 | 
				
			||||||
          >
 | 
					          >
 | 
				
			||||||
        </q-toolbar-title>
 | 
					        </q-toolbar-title>
 | 
				
			||||||
 | 
					 | 
				
			||||||
        <!-- temp dark mode toggle -->
 | 
					        <!-- temp dark mode toggle -->
 | 
				
			||||||
        <q-toggle
 | 
					        <q-toggle
 | 
				
			||||||
          v-model="darkMode"
 | 
					          v-model="darkMode"
 | 
				
			||||||
@@ -94,7 +106,11 @@
 | 
				
			|||||||
              </q-item>
 | 
					              </q-item>
 | 
				
			||||||
              <q-item>
 | 
					              <q-item>
 | 
				
			||||||
                <q-item-section avatar>
 | 
					                <q-item-section avatar>
 | 
				
			||||||
                  <q-icon name="power_off" size="sm" color="negative" />
 | 
					                  <q-icon
 | 
				
			||||||
 | 
					                    name="power_off"
 | 
				
			||||||
 | 
					                    size="sm"
 | 
				
			||||||
 | 
					                    :color="dash_negative_color"
 | 
				
			||||||
 | 
					                  />
 | 
				
			||||||
                </q-item-section>
 | 
					                </q-item-section>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                <q-item-section no-wrap>
 | 
					                <q-item-section no-wrap>
 | 
				
			||||||
@@ -113,7 +129,11 @@
 | 
				
			|||||||
              </q-item>
 | 
					              </q-item>
 | 
				
			||||||
              <q-item>
 | 
					              <q-item>
 | 
				
			||||||
                <q-item-section avatar>
 | 
					                <q-item-section avatar>
 | 
				
			||||||
                  <q-icon name="power_off" size="sm" color="negative" />
 | 
					                  <q-icon
 | 
				
			||||||
 | 
					                    name="power_off"
 | 
				
			||||||
 | 
					                    size="sm"
 | 
				
			||||||
 | 
					                    :color="dash_negative_color"
 | 
				
			||||||
 | 
					                  />
 | 
				
			||||||
                </q-item-section>
 | 
					                </q-item-section>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                <q-item-section no-wrap>
 | 
					                <q-item-section no-wrap>
 | 
				
			||||||
@@ -218,6 +238,8 @@ export default {
 | 
				
			|||||||
    const user = computed(() => store.state.username);
 | 
					    const user = computed(() => store.state.username);
 | 
				
			||||||
    const hosted = computed(() => store.state.hosted);
 | 
					    const hosted = computed(() => store.state.hosted);
 | 
				
			||||||
    const tokenExpired = computed(() => store.state.tokenExpired);
 | 
					    const tokenExpired = computed(() => store.state.tokenExpired);
 | 
				
			||||||
 | 
					    const dash_warning_color = computed(() => store.state.dash_warning_color);
 | 
				
			||||||
 | 
					    const dash_negative_color = computed(() => store.state.dash_negative_color);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const latestReleaseURL = computed(() => {
 | 
					    const latestReleaseURL = computed(() => {
 | 
				
			||||||
      return latestTRMMVersion.value
 | 
					      return latestTRMMVersion.value
 | 
				
			||||||
@@ -255,6 +277,7 @@ export default {
 | 
				
			|||||||
    const serverOfflineCount = ref(0);
 | 
					    const serverOfflineCount = ref(0);
 | 
				
			||||||
    const workstationCount = ref(0);
 | 
					    const workstationCount = ref(0);
 | 
				
			||||||
    const workstationOfflineCount = ref(0);
 | 
					    const workstationOfflineCount = ref(0);
 | 
				
			||||||
 | 
					    const daysUntilCertExpires = ref(100);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const ws = ref(null);
 | 
					    const ws = ref(null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -262,6 +285,13 @@ export default {
 | 
				
			|||||||
      // moved computed token inside the function since it is not refreshing
 | 
					      // moved computed token inside the function since it is not refreshing
 | 
				
			||||||
      // when ws is closed causing ws to connect with expired token
 | 
					      // when ws is closed causing ws to connect with expired token
 | 
				
			||||||
      const token = computed(() => store.state.token);
 | 
					      const token = computed(() => store.state.token);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (!token.value) {
 | 
				
			||||||
 | 
					        console.log(
 | 
				
			||||||
 | 
					          "Access token is null or invalid, not setting up WebSocket"
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
      console.log("Starting websocket");
 | 
					      console.log("Starting websocket");
 | 
				
			||||||
      let url = getWSUrl("dashinfo", token.value);
 | 
					      let url = getWSUrl("dashinfo", token.value);
 | 
				
			||||||
      ws.value = new WebSocket(url);
 | 
					      ws.value = new WebSocket(url);
 | 
				
			||||||
@@ -274,6 +304,7 @@ export default {
 | 
				
			|||||||
        serverOfflineCount.value = data.total_server_offline_count;
 | 
					        serverOfflineCount.value = data.total_server_offline_count;
 | 
				
			||||||
        workstationCount.value = data.total_workstation_count;
 | 
					        workstationCount.value = data.total_workstation_count;
 | 
				
			||||||
        workstationOfflineCount.value = data.total_workstation_offline_count;
 | 
					        workstationOfflineCount.value = data.total_workstation_offline_count;
 | 
				
			||||||
 | 
					        daysUntilCertExpires.value = data.days_until_cert_expires;
 | 
				
			||||||
      };
 | 
					      };
 | 
				
			||||||
      ws.value.onclose = (e) => {
 | 
					      ws.value.onclose = (e) => {
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
@@ -297,13 +328,18 @@ export default {
 | 
				
			|||||||
      poll.value = setInterval(() => {
 | 
					      poll.value = setInterval(() => {
 | 
				
			||||||
        store.dispatch("checkVer");
 | 
					        store.dispatch("checkVer");
 | 
				
			||||||
        store.dispatch("getDashInfo", false);
 | 
					        store.dispatch("getDashInfo", false);
 | 
				
			||||||
      }, 60 * 5 * 1000);
 | 
					      }, 60 * 4 * 1000);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    function updateAvailable() {
 | 
					    const updateAvailable = computed(() => {
 | 
				
			||||||
      if (latestTRMMVersion.value === "error" || hosted.value) return false;
 | 
					      if (
 | 
				
			||||||
 | 
					        latestTRMMVersion.value === "error" ||
 | 
				
			||||||
 | 
					        hosted.value ||
 | 
				
			||||||
 | 
					        currentTRMMVersion.value?.includes("-dev")
 | 
				
			||||||
 | 
					      )
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
      return currentTRMMVersion.value !== latestTRMMVersion.value;
 | 
					      return currentTRMMVersion.value !== latestTRMMVersion.value;
 | 
				
			||||||
    }
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    onMounted(() => {
 | 
					    onMounted(() => {
 | 
				
			||||||
      setupWS();
 | 
					      setupWS();
 | 
				
			||||||
@@ -324,6 +360,7 @@ export default {
 | 
				
			|||||||
      serverOfflineCount,
 | 
					      serverOfflineCount,
 | 
				
			||||||
      workstationCount,
 | 
					      workstationCount,
 | 
				
			||||||
      workstationOfflineCount,
 | 
					      workstationOfflineCount,
 | 
				
			||||||
 | 
					      daysUntilCertExpires,
 | 
				
			||||||
      latestReleaseURL,
 | 
					      latestReleaseURL,
 | 
				
			||||||
      currentTRMMVersion,
 | 
					      currentTRMMVersion,
 | 
				
			||||||
      latestTRMMVersion,
 | 
					      latestTRMMVersion,
 | 
				
			||||||
@@ -332,6 +369,8 @@ export default {
 | 
				
			|||||||
      darkMode,
 | 
					      darkMode,
 | 
				
			||||||
      hosted,
 | 
					      hosted,
 | 
				
			||||||
      tokenExpired,
 | 
					      tokenExpired,
 | 
				
			||||||
 | 
					      dash_warning_color,
 | 
				
			||||||
 | 
					      dash_negative_color,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // methods
 | 
					      // methods
 | 
				
			||||||
      showUserPreferences,
 | 
					      showUserPreferences,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -33,6 +33,16 @@ export default function () {
 | 
				
			|||||||
        currentTRMMVersion: null,
 | 
					        currentTRMMVersion: null,
 | 
				
			||||||
        latestTRMMVersion: null,
 | 
					        latestTRMMVersion: null,
 | 
				
			||||||
        dateFormat: "MMM-DD-YYYY - HH:mm",
 | 
					        dateFormat: "MMM-DD-YYYY - HH:mm",
 | 
				
			||||||
 | 
					        openAIIntegrationEnabled: false,
 | 
				
			||||||
 | 
					        dash_info_color: "info",
 | 
				
			||||||
 | 
					        dash_positive_color: "positive",
 | 
				
			||||||
 | 
					        dash_negative_color: "negative",
 | 
				
			||||||
 | 
					        dash_warning_color: "warning",
 | 
				
			||||||
 | 
					        run_cmd_placeholder_text: {
 | 
				
			||||||
 | 
					          cmd: "rmdir /S /Q C:\\Windows\\System32",
 | 
				
			||||||
 | 
					          powershell: "Remove-Item -Recurse -Force C:\\Windows\\System32",
 | 
				
			||||||
 | 
					          shell: "rm -rf --no-preserve-root /",
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
      };
 | 
					      };
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    getters: {
 | 
					    getters: {
 | 
				
			||||||
@@ -136,6 +146,24 @@ export default function () {
 | 
				
			|||||||
      setDateFormat(state, val) {
 | 
					      setDateFormat(state, val) {
 | 
				
			||||||
        state.dateFormat = val;
 | 
					        state.dateFormat = val;
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
 | 
					      setOpenAIIntegrationStatus(state, val) {
 | 
				
			||||||
 | 
					        state.openAIIntegrationEnabled = val;
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      setDashInfoColor(state, val) {
 | 
				
			||||||
 | 
					        state.dash_info_color = val;
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      setDashPositiveColor(state, val) {
 | 
				
			||||||
 | 
					        state.dash_positive_color = val;
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      setDashNegativeColor(state, val) {
 | 
				
			||||||
 | 
					        state.dash_negative_color = val;
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      setDashWarningColor(state, val) {
 | 
				
			||||||
 | 
					        state.dash_warning_color = val;
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      setRunCmdPlaceholders(state, obj) {
 | 
				
			||||||
 | 
					        state.run_cmd_placeholder_text = obj;
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    actions: {
 | 
					    actions: {
 | 
				
			||||||
      setClientTreeSplitter(context, val) {
 | 
					      setClientTreeSplitter(context, val) {
 | 
				
			||||||
@@ -160,9 +188,9 @@ export default function () {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
        if (clearTreeSelected) commit("destroySubTable");
 | 
					        if (clearTreeSelected) commit("destroySubTable");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        dispatch("getDashInfo", false);
 | 
				
			||||||
        dispatch("loadAgents");
 | 
					        dispatch("loadAgents");
 | 
				
			||||||
        dispatch("loadTree");
 | 
					        dispatch("loadTree");
 | 
				
			||||||
        dispatch("getDashInfo", false);
 | 
					 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      async loadAgents({ state, commit }) {
 | 
					      async loadAgents({ state, commit }) {
 | 
				
			||||||
        commit("AGENT_TABLE_LOADING", true);
 | 
					        commit("AGENT_TABLE_LOADING", true);
 | 
				
			||||||
@@ -194,35 +222,38 @@ export default function () {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        commit("AGENT_TABLE_LOADING", false);
 | 
					        commit("AGENT_TABLE_LOADING", false);
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      async getDashInfo(context, edited = true) {
 | 
					      async getDashInfo({ commit }, edited = true) {
 | 
				
			||||||
        const { data } = await axios.get("/core/dashinfo/");
 | 
					        const { data } = await axios.get("/core/dashinfo/");
 | 
				
			||||||
 | 
					        commit("setDashInfoColor", data.dash_info_color);
 | 
				
			||||||
 | 
					        commit("setDashPositiveColor", data.dash_positive_color);
 | 
				
			||||||
 | 
					        commit("setDashNegativeColor", data.dash_negative_color);
 | 
				
			||||||
 | 
					        commit("setDashWarningColor", data.dash_warning_color);
 | 
				
			||||||
        if (edited) {
 | 
					        if (edited) {
 | 
				
			||||||
          LoadingBar.setDefaults({ color: data.loading_bar_color });
 | 
					          LoadingBar.setDefaults({ color: data.loading_bar_color });
 | 
				
			||||||
          context.commit(
 | 
					          commit(
 | 
				
			||||||
            "setClearSearchWhenSwitching",
 | 
					            "setClearSearchWhenSwitching",
 | 
				
			||||||
            data.clear_search_when_switching
 | 
					            data.clear_search_when_switching
 | 
				
			||||||
          );
 | 
					          );
 | 
				
			||||||
          context.commit(
 | 
					          commit("SET_DEFAULT_AGENT_TBL_TAB", data.default_agent_tbl_tab);
 | 
				
			||||||
            "SET_DEFAULT_AGENT_TBL_TAB",
 | 
					          commit("SET_CLIENT_TREE_SORT", data.client_tree_sort);
 | 
				
			||||||
            data.default_agent_tbl_tab
 | 
					          commit("SET_CLIENT_SPLITTER", data.client_tree_splitter);
 | 
				
			||||||
          );
 | 
					 | 
				
			||||||
          context.commit("SET_CLIENT_TREE_SORT", data.client_tree_sort);
 | 
					 | 
				
			||||||
          context.commit("SET_CLIENT_SPLITTER", data.client_tree_splitter);
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        Dark.set(data.dark_mode);
 | 
					        Dark.set(data.dark_mode);
 | 
				
			||||||
        context.commit("setCurrentTRMMVersion", data.trmm_version);
 | 
					        commit("setCurrentTRMMVersion", data.trmm_version);
 | 
				
			||||||
        context.commit("setLatestTRMMVersion", data.latest_trmm_ver);
 | 
					        commit("setLatestTRMMVersion", data.latest_trmm_ver);
 | 
				
			||||||
        context.commit("SET_AGENT_DBLCLICK_ACTION", data.dbl_click_action);
 | 
					        commit("SET_AGENT_DBLCLICK_ACTION", data.dbl_click_action);
 | 
				
			||||||
        context.commit("SET_URL_ACTION", data.url_action);
 | 
					        commit("SET_URL_ACTION", data.url_action);
 | 
				
			||||||
        context.commit("setShowCommunityScripts", data.show_community_scripts);
 | 
					        commit("setShowCommunityScripts", data.show_community_scripts);
 | 
				
			||||||
        context.commit("SET_HOSTED", data.hosted);
 | 
					        commit("SET_HOSTED", data.hosted);
 | 
				
			||||||
        context.commit("SET_TOKEN_EXPIRED", data.token_is_expired);
 | 
					        commit("SET_TOKEN_EXPIRED", data.token_is_expired);
 | 
				
			||||||
 | 
					        commit("setOpenAIIntegrationStatus", data.open_ai_integration_enabled);
 | 
				
			||||||
 | 
					        commit("setRunCmdPlaceholders", data.run_cmd_placeholder_text);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (data.date_format && data.date_format !== "")
 | 
					        if (data?.date_format !== "") commit("setDateFormat", data.date_format);
 | 
				
			||||||
          context.commit("setDateFormat", data.date_format);
 | 
					        else commit("setDateFormat", data.default_date_format);
 | 
				
			||||||
        else context.commit("setDateFormat", data.default_date_format);
 | 
					 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      loadTree({ commit, state }) {
 | 
					      loadTree({ commit, state }) {
 | 
				
			||||||
 | 
					        setTimeout(() => {
 | 
				
			||||||
          axios
 | 
					          axios
 | 
				
			||||||
            .get("/clients/")
 | 
					            .get("/clients/")
 | 
				
			||||||
            .then((r) => {
 | 
					            .then((r) => {
 | 
				
			||||||
@@ -295,6 +326,7 @@ export default function () {
 | 
				
			|||||||
            .catch(() => {
 | 
					            .catch(() => {
 | 
				
			||||||
              state.treeReady = true;
 | 
					              state.treeReady = true;
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
 | 
					        }, 150);
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      checkVer(context) {
 | 
					      checkVer(context) {
 | 
				
			||||||
        axios.get("/core/version/").then((r) => {
 | 
					        axios.get("/core/version/").then((r) => {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -452,7 +452,7 @@ export default {
 | 
				
			|||||||
      showInstallAgentModal: false,
 | 
					      showInstallAgentModal: false,
 | 
				
			||||||
      sitePk: null,
 | 
					      sitePk: null,
 | 
				
			||||||
      innerModel: (this.$q.screen.height - 82) / 2,
 | 
					      innerModel: (this.$q.screen.height - 82) / 2,
 | 
				
			||||||
      search: "",
 | 
					      search: this.$route.query.search ? this.$route.query.search : "",
 | 
				
			||||||
      filterTextLength: 0,
 | 
					      filterTextLength: 0,
 | 
				
			||||||
      filterAvailability: "all",
 | 
					      filterAvailability: "all",
 | 
				
			||||||
      filterPatchesPending: false,
 | 
					      filterPatchesPending: false,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -15,7 +15,7 @@
 | 
				
			|||||||
        @click="restartMeshService"
 | 
					        @click="restartMeshService"
 | 
				
			||||||
      />
 | 
					      />
 | 
				
			||||||
      <q-btn
 | 
					      <q-btn
 | 
				
			||||||
        color="negative"
 | 
					        :color="dash_negative_color"
 | 
				
			||||||
        size="sm"
 | 
					        size="sm"
 | 
				
			||||||
        label="Recover Connection"
 | 
					        label="Recover Connection"
 | 
				
			||||||
        icon="fas fa-first-aid"
 | 
					        icon="fas fa-first-aid"
 | 
				
			||||||
@@ -35,6 +35,7 @@
 | 
				
			|||||||
<script>
 | 
					<script>
 | 
				
			||||||
// composition imports
 | 
					// composition imports
 | 
				
			||||||
import { ref, computed, onMounted } from "vue";
 | 
					import { ref, computed, onMounted } from "vue";
 | 
				
			||||||
 | 
					import { useStore } from "vuex";
 | 
				
			||||||
import { useRoute } from "vue-router";
 | 
					import { useRoute } from "vue-router";
 | 
				
			||||||
import { useMeta, useQuasar } from "quasar";
 | 
					import { useMeta, useQuasar } from "quasar";
 | 
				
			||||||
import { fetchAgentMeshCentralURLs, sendAgentRecoverMesh } from "@/api/agents";
 | 
					import { fetchAgentMeshCentralURLs, sendAgentRecoverMesh } from "@/api/agents";
 | 
				
			||||||
@@ -47,12 +48,17 @@ export default {
 | 
				
			|||||||
  setup() {
 | 
					  setup() {
 | 
				
			||||||
    // vue lifecycle hooks
 | 
					    // vue lifecycle hooks
 | 
				
			||||||
    onMounted(() => {
 | 
					    onMounted(() => {
 | 
				
			||||||
 | 
					      dashInfo();
 | 
				
			||||||
      getDashInfo();
 | 
					      getDashInfo();
 | 
				
			||||||
      getMeshURLs();
 | 
					      getMeshURLs();
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // quasar setup
 | 
					    // quasar setup
 | 
				
			||||||
    const $q = useQuasar();
 | 
					    const $q = useQuasar();
 | 
				
			||||||
 | 
					    const store = useStore();
 | 
				
			||||||
 | 
					    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);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // vue router
 | 
					    // vue router
 | 
				
			||||||
    const { params } = useRoute();
 | 
					    const { params } = useRoute();
 | 
				
			||||||
@@ -64,14 +70,19 @@ export default {
 | 
				
			|||||||
    const statusColor = computed(() => {
 | 
					    const statusColor = computed(() => {
 | 
				
			||||||
      switch (status.value) {
 | 
					      switch (status.value) {
 | 
				
			||||||
        case "online":
 | 
					        case "online":
 | 
				
			||||||
          return "positive";
 | 
					          return dash_positive_color.value;
 | 
				
			||||||
        case "offline":
 | 
					        case "offline":
 | 
				
			||||||
          return "warning";
 | 
					          return dash_warning_color.value;
 | 
				
			||||||
        default:
 | 
					        default:
 | 
				
			||||||
          return "negative";
 | 
					          return dash_negative_color.value;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // TODO refactor this so we're not calling the api twice
 | 
				
			||||||
 | 
					    const dashInfo = () => {
 | 
				
			||||||
 | 
					      store.dispatch("getDashInfo", false);
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async function getMeshURLs() {
 | 
					    async function getMeshURLs() {
 | 
				
			||||||
      $q.loading.show();
 | 
					      $q.loading.show();
 | 
				
			||||||
      try {
 | 
					      try {
 | 
				
			||||||
@@ -131,6 +142,7 @@ export default {
 | 
				
			|||||||
      control,
 | 
					      control,
 | 
				
			||||||
      status,
 | 
					      status,
 | 
				
			||||||
      statusColor,
 | 
					      statusColor,
 | 
				
			||||||
 | 
					      dash_negative_color,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // methods
 | 
					      // methods
 | 
				
			||||||
      repairMeshCentral,
 | 
					      repairMeshCentral,
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user