chg: [front] Removed daisyUI dependency
This commit is contained in:
parent
014f55a2c4
commit
77238fabe9
17 changed files with 608 additions and 234 deletions
45
package-lock.json
generated
45
package-lock.json
generated
|
@ -23,7 +23,6 @@
|
||||||
"@vitejs/plugin-vue": "^5.0.5",
|
"@vitejs/plugin-vue": "^5.0.5",
|
||||||
"@vue/eslint-config-prettier": "^9.0.0",
|
"@vue/eslint-config-prettier": "^9.0.0",
|
||||||
"autoprefixer": "^10.4.19",
|
"autoprefixer": "^10.4.19",
|
||||||
"daisyui": "^4.12.10",
|
|
||||||
"eslint": "^8.57.0",
|
"eslint": "^8.57.0",
|
||||||
"eslint-plugin-vue": "^9.23.0",
|
"eslint-plugin-vue": "^9.23.0",
|
||||||
"postcss": "^8.4.38",
|
"postcss": "^8.4.38",
|
||||||
|
@ -1444,16 +1443,6 @@
|
||||||
"node": ">= 8"
|
"node": ">= 8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/css-selector-tokenizer": {
|
|
||||||
"version": "0.8.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.8.0.tgz",
|
|
||||||
"integrity": "sha512-Jd6Ig3/pe62/qe5SBPTN8h8LeUg/pT4lLgtavPf7updwwHpvFzxvOQBHYj2LZDMjUnBzgvIUSjRcf6oT5HzHFg==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"cssesc": "^3.0.0",
|
|
||||||
"fastparse": "^1.1.2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/cssesc": {
|
"node_modules/cssesc": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
|
||||||
|
@ -1471,34 +1460,6 @@
|
||||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
|
||||||
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="
|
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="
|
||||||
},
|
},
|
||||||
"node_modules/culori": {
|
|
||||||
"version": "3.3.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/culori/-/culori-3.3.0.tgz",
|
|
||||||
"integrity": "sha512-pHJg+jbuFsCjz9iclQBqyL3B2HLCBF71BwVNujUYEvCeQMvV97R59MNK3R2+jgJ3a1fcZgI9B3vYgz8lzr/BFQ==",
|
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
|
||||||
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/daisyui": {
|
|
||||||
"version": "4.12.10",
|
|
||||||
"resolved": "https://registry.npmjs.org/daisyui/-/daisyui-4.12.10.tgz",
|
|
||||||
"integrity": "sha512-jp1RAuzbHhGdXmn957Z2XsTZStXGHzFfF0FgIOZj3Wv9sH7OZgLfXTRZNfKVYxltGUOBsG1kbWAdF5SrqjebvA==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"css-selector-tokenizer": "^0.8",
|
|
||||||
"culori": "^3",
|
|
||||||
"picocolors": "^1",
|
|
||||||
"postcss-js": "^4"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=16.9.0"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"type": "opencollective",
|
|
||||||
"url": "https://opencollective.com/daisyui"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/debug": {
|
"node_modules/debug": {
|
||||||
"version": "4.3.5",
|
"version": "4.3.5",
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz",
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz",
|
||||||
|
@ -1919,12 +1880,6 @@
|
||||||
"integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
|
"integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/fastparse": {
|
|
||||||
"version": "1.1.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.2.tgz",
|
|
||||||
"integrity": "sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"node_modules/fastq": {
|
"node_modules/fastq": {
|
||||||
"version": "1.17.1",
|
"version": "1.17.1",
|
||||||
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz",
|
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz",
|
||||||
|
|
|
@ -26,7 +26,6 @@
|
||||||
"@vitejs/plugin-vue": "^5.0.5",
|
"@vitejs/plugin-vue": "^5.0.5",
|
||||||
"@vue/eslint-config-prettier": "^9.0.0",
|
"@vue/eslint-config-prettier": "^9.0.0",
|
||||||
"autoprefixer": "^10.4.19",
|
"autoprefixer": "^10.4.19",
|
||||||
"daisyui": "^4.12.10",
|
|
||||||
"eslint": "^8.57.0",
|
"eslint": "^8.57.0",
|
||||||
"eslint-plugin-vue": "^9.23.0",
|
"eslint-plugin-vue": "^9.23.0",
|
||||||
"postcss": "^8.4.38",
|
"postcss": "^8.4.38",
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
@tailwind base;
|
@import "tailwindcss/base";
|
||||||
@tailwind components;
|
@import "tailwindcss/components";
|
||||||
@tailwind utilities;
|
@import "tailwindcss/utilities";
|
||||||
|
|
||||||
|
@import "./styled-components/toggle.css";
|
||||||
|
@import "./styled-components/button.css";
|
||||||
|
@import "./styled-components/transitions.css";
|
||||||
|
|
83
src/assets/styled-components/button.css
Normal file
83
src/assets/styled-components/button.css
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
@apply px-2 py-1 font-semibold rounded border text-nowrap select-none;
|
||||||
|
@apply transition-all duration-75;
|
||||||
|
@apply border-slate-300;
|
||||||
|
|
||||||
|
&.btn-sm {
|
||||||
|
@apply px-1 py-0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.btn-xs {
|
||||||
|
@apply px-0.5 py-0;
|
||||||
|
@apply text-sm;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.btn-lg {
|
||||||
|
@apply px-3 py-1;
|
||||||
|
@apply text-lg;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.btn:not(:disabled) {
|
||||||
|
@apply hover:bg-slate-200 hover:border-slate-300;
|
||||||
|
@apply active:scale-90
|
||||||
|
}
|
||||||
|
|
||||||
|
&.btn:disabled {
|
||||||
|
@apply cursor-not-allowed opacity-60;
|
||||||
|
}
|
||||||
|
&.btn-primary:not(:disabled) {
|
||||||
|
@apply border-none;
|
||||||
|
@apply bg-blue-600 text-white hover:bg-blue-700;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.btn-info:not(:disabled) {
|
||||||
|
@apply border-none;
|
||||||
|
@apply bg-blue-500 text-white hover:bg-blue-600;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.btn-danger:not(:disabled) {
|
||||||
|
@apply border-none;
|
||||||
|
@apply bg-red-600 text-white hover:bg-red-700;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.btn-success:not(:disabled) {
|
||||||
|
@apply border-none;
|
||||||
|
@apply bg-green-600 text-white hover:bg-green-700;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.btn-warning:not(:disabled) {
|
||||||
|
@apply border-none;
|
||||||
|
@apply bg-amber-600 text-white hover:bg-amber-700;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.btn-outline-primary:not(:disabled) {
|
||||||
|
@apply hover:bg-blue-600 hover:border-blue-700 hover:text-white;
|
||||||
|
@apply border-blue-700 hover:border-blue-800
|
||||||
|
}
|
||||||
|
|
||||||
|
&.btn-outline-info:not(:disabled) {
|
||||||
|
@apply hover:bg-blue-500 hover:border-blue-700 hover:text-white;
|
||||||
|
@apply border-blue-700 hover:border-blue-800
|
||||||
|
}
|
||||||
|
|
||||||
|
&.btn-outline-danger:not(:disabled) {
|
||||||
|
@apply hover:bg-red-500 hover:border-red-700 hover:text-white;
|
||||||
|
@apply border-red-700 hover:border-red-800
|
||||||
|
}
|
||||||
|
|
||||||
|
&.btn-outline-success:not(:disabled) {
|
||||||
|
@apply hover:bg-green-500 hover:border-green-700 hover:text-white;
|
||||||
|
@apply border-green-700 hover:border-green-800
|
||||||
|
}
|
||||||
|
|
||||||
|
&.btn-outline-warning:not(:disabled) {
|
||||||
|
@apply hover:bg-amber-500 hover:border-amber-700 hover:text-white;
|
||||||
|
@apply border-amber-700 hover:border-amber-800
|
||||||
|
}
|
||||||
|
|
||||||
|
&.btn-link:not(:disabled) {
|
||||||
|
@apply border-none;
|
||||||
|
@apply hover:bg-transparent hover:border-transparent hover:text-inherit;
|
||||||
|
}
|
||||||
|
}
|
0
src/assets/styled-components/modal.css
Normal file
0
src/assets/styled-components/modal.css
Normal file
78
src/assets/styled-components/toggle.css
Normal file
78
src/assets/styled-components/toggle.css
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
.toggle:where(.dark, .dark *) {
|
||||||
|
--tglbg: theme(colors.slate.800) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toggle {
|
||||||
|
--tglbg: theme(colors.slate.200);
|
||||||
|
--animation-input: 0.2s;
|
||||||
|
--handleoffset: 1.5rem;
|
||||||
|
--handleoffsetcalculator: calc(var(--handleoffset) * -1);
|
||||||
|
--togglehandleborder: 0 0;
|
||||||
|
@apply h-6 w-12 rounded-3xl cursor-pointer appearance-none border border-current bg-current;
|
||||||
|
transition:
|
||||||
|
background,
|
||||||
|
box-shadow var(--animation-input, 0.2s) ease-out;
|
||||||
|
box-shadow:
|
||||||
|
var(--handleoffsetcalculator) 0 0 2px var(--tglbg) inset,
|
||||||
|
0 0 0 2px var(--tglbg) inset,
|
||||||
|
var(--togglehandleborder);
|
||||||
|
@apply text-slate-500;
|
||||||
|
&:focus-visible {
|
||||||
|
@apply outline outline-2 outline-offset-2;
|
||||||
|
}
|
||||||
|
&:hover {
|
||||||
|
@apply bg-current;
|
||||||
|
}
|
||||||
|
&:checked,
|
||||||
|
&[aria-checked="true"] {
|
||||||
|
background-image: none;
|
||||||
|
--handleoffsetcalculator: var(--handleoffset);
|
||||||
|
}
|
||||||
|
&:indeterminate {
|
||||||
|
box-shadow:
|
||||||
|
calc(var(--handleoffset) / 2) 0 0 2px var(--tglbg) inset,
|
||||||
|
calc(var(--handleoffset) / -2) 0 0 2px var(--tglbg) inset,
|
||||||
|
0 0 0 2px var(--tglbg) inset;
|
||||||
|
}
|
||||||
|
&:disabled {
|
||||||
|
@apply cursor-not-allowed bg-transparent opacity-30;
|
||||||
|
--togglehandleborder: 0 0 0 3px #000 inset,
|
||||||
|
var(--handleoffsetcalculator) 0 0 3px #000 inset;
|
||||||
|
}
|
||||||
|
&.toggle-success {
|
||||||
|
&:focus-visible {
|
||||||
|
@apply outline-green-400;
|
||||||
|
}
|
||||||
|
&:checked,
|
||||||
|
&[aria-checked="true"] {
|
||||||
|
@apply border-green-500 bg-green-400 text-slate-900 border-opacity-10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&.toggle-warning {
|
||||||
|
&:focus-visible {
|
||||||
|
@apply outline-amber-400;
|
||||||
|
}
|
||||||
|
&:checked,
|
||||||
|
&[aria-checked="true"] {
|
||||||
|
@apply border-amber-500 bg-amber-400 text-slate-900 border-opacity-10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&.toggle-info {
|
||||||
|
&:focus-visible {
|
||||||
|
@apply outline-blue-400;
|
||||||
|
}
|
||||||
|
&:checked,
|
||||||
|
&[aria-checked="true"] {
|
||||||
|
@apply border-blue-500 bg-blue-400 text-slate-900 border-opacity-10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&.toggle-danger {
|
||||||
|
&:focus-visible {
|
||||||
|
@apply outline-red-400;
|
||||||
|
}
|
||||||
|
&:checked,
|
||||||
|
&[aria-checked="true"] {
|
||||||
|
@apply border-red-500 bg-red-400 text-slate-900 border-opacity-10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
27
src/assets/styled-components/transitions.css
Normal file
27
src/assets/styled-components/transitions.css
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
.slide-fade-enter-active {
|
||||||
|
transition: all 0.2s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slide-fade-leave-active {
|
||||||
|
transition: all 0.2s cubic-bezier(1, 0.5, 0.8, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.slide-fade-enter-from,
|
||||||
|
.slide-fade-leave-to {
|
||||||
|
transform: translateX(20px);
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slide-fade-reverse-enter-active {
|
||||||
|
transition: all 0.2s cubic-bezier(1, 0.5, 0.8, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.slide-fade-reverse-leave-active {
|
||||||
|
transition: all 0.2s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slide-fade-reverse-enter-from,
|
||||||
|
.slide-fade-reverse-leave-to {
|
||||||
|
transform: translateX(-20px);
|
||||||
|
opacity: 0;
|
||||||
|
}
|
|
@ -20,8 +20,9 @@
|
||||||
remediateSetting(setting)
|
remediateSetting(setting)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const showModal = ref(false)
|
||||||
function showTheModal() {
|
function showTheModal() {
|
||||||
admin_modal.value.showModal()
|
showModal.value = true
|
||||||
clickedButtons.value = []
|
clickedButtons.value = []
|
||||||
debouncedGetDiangostic()
|
debouncedGetDiangostic()
|
||||||
}
|
}
|
||||||
|
@ -30,176 +31,169 @@
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<button
|
<button
|
||||||
@click="showTheModal()"
|
@click="showTheModal()"
|
||||||
class="px-2 py-1 rounded-md focus-outline font-semibold bg-blue-600 text-slate-200 hover:bg-blue-700"
|
class="btn btn-primary"
|
||||||
>
|
>
|
||||||
<FontAwesomeIcon :icon="faScrewdriverWrench" class="mr-1"></FontAwesomeIcon>
|
<FontAwesomeIcon :icon="faScrewdriverWrench" class="mr-1"></FontAwesomeIcon>
|
||||||
Admin panel
|
Admin panel
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<dialog ref="admin_modal" class="modal">
|
<Modal :showModal="showModal" @modal-close="showModal = false">
|
||||||
<div class="modal-box w-11/12 max-w-6xl top-24 absolute bg-slate-200 dark:bg-slate-600 text-slate-700 dark:text-slate-200">
|
<template #header>
|
||||||
<h2 class="text-2xl font-bold">
|
<h2 class="text-2xl font-bold">
|
||||||
<FontAwesomeIcon :icon="faScrewdriverWrench" class=""></FontAwesomeIcon>
|
<FontAwesomeIcon :icon="faScrewdriverWrench" class=""></FontAwesomeIcon>
|
||||||
Admin panel
|
Admin panel
|
||||||
</h2>
|
</h2>
|
||||||
<div class="modal-action">
|
</template>
|
||||||
<form method="dialog">
|
<template #body>
|
||||||
<button class="btn btn-sm btn-circle btn-ghost absolute right-2 top-2">✕</button>
|
<div class="dark:text-slate-700 text-slate-700">
|
||||||
</form>
|
<div class="flex mb-5 gap-2">
|
||||||
</div>
|
<button
|
||||||
<div>
|
@click="fullReload()"
|
||||||
|
class="h-10 min-h-10 font-semibold btn-info btn gap-1"
|
||||||
<div class="flex mb-5 gap-2">
|
|
||||||
<button
|
|
||||||
@click="fullReload()"
|
|
||||||
class="h-10 min-h-10 px-2 py-1 font-semibold bg-blue-600 text-slate-200 hover:bg-blue-700 btn btn-sm gap-1"
|
|
||||||
>
|
|
||||||
<FontAwesomeIcon :icon="faRotate" size="lg" fixed-width></FontAwesomeIcon>
|
|
||||||
Full refresh
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
@click="resetAllExerciseProgress()"
|
|
||||||
class="h-10 min-h-10 px-2 py-1 font-semibold bg-red-600 text-slate-200 hover:bg-red-700 btn btn-sm gap-1"
|
|
||||||
>
|
|
||||||
<FontAwesomeIcon :icon="faTrash" size="lg" fixed-width></FontAwesomeIcon>
|
|
||||||
Reset All Exercises
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
@click="resetAll()"
|
|
||||||
class="h-10 min-h-10 px-2 py-1 font-semibold bg-red-600 text-slate-200 hover:bg-red-700 btn btn-sm gap-1"
|
|
||||||
>
|
|
||||||
<FontAwesomeIcon :icon="faTrash" size="lg" fixed-width></FontAwesomeIcon>
|
|
||||||
Reset All
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
@click="resetLiveLogs()"
|
|
||||||
class="h-10 min-h-10 px-2 py-1 font-semibold bg-amber-600 text-slate-200 hover:bg-amber-700 btn btn-sm gap-1"
|
|
||||||
>
|
|
||||||
<FontAwesomeIcon :icon="faBan" size="lg"> fixed-width</FontAwesomeIcon>
|
|
||||||
Clear Live Logs
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h3 class="text-lg font-semibold">
|
|
||||||
<FontAwesomeIcon :icon="faGraduationCap" class="mr-1"></FontAwesomeIcon>
|
|
||||||
Selected Exercises
|
|
||||||
</h3>
|
|
||||||
<div
|
|
||||||
v-for="(exercise) in exercises"
|
|
||||||
:key="exercise.name"
|
|
||||||
class="form-control pl-3"
|
|
||||||
>
|
>
|
||||||
<label class="label cursor-pointer justify-start">
|
<FontAwesomeIcon :icon="faRotate" size="lg" fixed-width></FontAwesomeIcon>
|
||||||
<input
|
Full refresh
|
||||||
@change="changeSelectionState($event.target.checked, exercise.uuid)"
|
</button>
|
||||||
type="checkbox"
|
<button
|
||||||
:checked="selected_exercises.includes(exercise.uuid)"
|
@click="resetAllExerciseProgress()"
|
||||||
:value="exercise.uuid"
|
class="h-10 min-h-10 font-semibold btn-danger btn gap-1"
|
||||||
:class="`checkbox ${selected_exercises.includes(exercise.uuid) ? 'checkbox-success' : ''} [--fallback-bc:#94a3b8]`"
|
>
|
||||||
/>
|
<FontAwesomeIcon :icon="faTrash" size="lg" fixed-width></FontAwesomeIcon>
|
||||||
<span class="font-mono font-semibold text-base ml-3">{{ exercise.name }}</span>
|
Reset All Exercises
|
||||||
</label>
|
</button>
|
||||||
</div>
|
<button
|
||||||
|
@click="resetAll()"
|
||||||
|
class="h-10 min-h-10 font-semibold btn-danger btn gap-1"
|
||||||
|
>
|
||||||
|
<FontAwesomeIcon :icon="faTrash" size="lg" fixed-width></FontAwesomeIcon>
|
||||||
|
Reset All
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
@click="resetLiveLogs()"
|
||||||
|
class="h-10 min-h-10 font-semibold btn-warning btn gap-1"
|
||||||
|
>
|
||||||
|
<FontAwesomeIcon :icon="faBan" size="lg"> fixed-width</FontAwesomeIcon>
|
||||||
|
Clear Live Logs
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
<h3 class="text-lg font-semibold mt-4">
|
<h3 class="text-lg font-semibold">
|
||||||
<FontAwesomeIcon :icon="faSuitcaseMedical" class="mr-1"></FontAwesomeIcon>
|
<FontAwesomeIcon :icon="faGraduationCap" class="mr-1"></FontAwesomeIcon>
|
||||||
Diagnostic
|
Selected Exercises
|
||||||
</h3>
|
</h3>
|
||||||
<h4 class="font-semibold ml-1 my-3">
|
<div
|
||||||
<strong>MISP Status:</strong>
|
v-for="(exercise) in exercises"
|
||||||
<span class="ml-2">
|
:key="exercise.name"
|
||||||
<span :class="{
|
class="form-control pl-3"
|
||||||
'rounded-lg py-1 px-2': true,
|
>
|
||||||
'dark:bg-neutral-800 bg-neutral-400 text-slate-800 dark:text-slate-200': diagnosticLoading,
|
<label class="label cursor-pointer justify-start">
|
||||||
'dark:bg-green-700 bg-green-500 text-slate-800 dark:text-slate-200': !diagnosticLoading && isMISPOnline,
|
<input
|
||||||
'dark:bg-red-700 bg-red-700 text-slate-200 dark:text-slate-200': !diagnosticLoading && !isMISPOnline,
|
@change="changeSelectionState($event.target.checked, exercise.uuid)"
|
||||||
}">
|
type="checkbox"
|
||||||
<span v-if="diagnosticLoading" class="loading loading-dots loading-sm h-4 inline-block align-middle"></span>
|
:checked="selected_exercises.includes(exercise.uuid)"
|
||||||
<span v-else class="font-bold">
|
:value="exercise.uuid"
|
||||||
{{ !isMISPOnline ? 'Unreachable' : `Online (${diagnostic['version']['version']})` }}
|
:class="`checkbox ${selected_exercises.includes(exercise.uuid) ? 'checkbox-success' : ''} [--fallback-bc:#94a3b8]`"
|
||||||
</span>
|
/>
|
||||||
</span>
|
<span class="font-mono font-semibold text-base ml-3">{{ exercise.name }}</span>
|
||||||
</span>
|
</label>
|
||||||
</h4>
|
</div>
|
||||||
<h4 class="font-semibold ml-1 my-3">
|
|
||||||
<strong>ZMQ Status:</strong>
|
|
||||||
<span class="ml-2">
|
|
||||||
<span :class="{
|
|
||||||
'rounded-lg py-1 px-2': true,
|
|
||||||
'dark:bg-neutral-800 bg-neutral-400 text-slate-800 dark:text-slate-200': diagnosticLoading,
|
|
||||||
'dark:bg-green-700 bg-green-500 text-slate-800 dark:text-slate-200': !diagnosticLoading && isZMQActive,
|
|
||||||
'dark:bg-red-700 bg-red-700 text-slate-200 dark:text-slate-200': !diagnosticLoading && !isZMQActive,
|
|
||||||
}">
|
|
||||||
<span v-if="diagnosticLoading" class="loading loading-dots loading-sm h-4 inline-block align-middle"></span>
|
|
||||||
<span v-else class="font-bold">
|
|
||||||
{{ !isZMQActive ? 'No message received yet' : `ZMQ Active (${ZMQMessageCount} messages)` }}
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
</h4>
|
|
||||||
|
|
||||||
<template v-if="diagnosticLoading || isMISPOnline">
|
<h3 class="text-lg font-semibold mt-4">
|
||||||
<h4 class="font-semibold ml-1"><strong>MISP Settings:</strong></h4>
|
<FontAwesomeIcon :icon="faSuitcaseMedical" class="mr-1"></FontAwesomeIcon>
|
||||||
<div class="ml-3">
|
Diagnostic
|
||||||
<div v-if="diagnosticLoading" class="flex justify-center">
|
</h3>
|
||||||
<span class="loading loading-dots loading-lg"></span>
|
<h4 class="font-semibold ml-1 my-3">
|
||||||
</div>
|
<strong>MISP Status:</strong>
|
||||||
<table v-else class="bg-white dark:bg-slate-700 rounded-lg shadow-xl w-full mt-2">
|
<span class="ml-2">
|
||||||
<thead>
|
<span :class="{
|
||||||
<tr>
|
'rounded-lg py-1 px-2 inline-flex': true,
|
||||||
<th class="border-b border-slate-200 dark:border-slate-600 p-2 text-left">Setting</th>
|
'dark:bg-neutral-800 bg-neutral-400 text-slate-800 dark:text-slate-200': diagnosticLoading,
|
||||||
<th class="border-b border-slate-200 dark:border-slate-600 p-2 text-left">Value</th>
|
'dark:bg-green-700 bg-green-500 text-slate-800 dark:text-slate-200': !diagnosticLoading && isMISPOnline,
|
||||||
<th class="border-b border-slate-200 dark:border-slate-600 p-2 text-left">Expected Value</th>
|
'dark:bg-red-700 bg-red-700 text-slate-200 dark:text-slate-200': !diagnosticLoading && !isMISPOnline,
|
||||||
<th class="border-b border-slate-200 dark:border-slate-600 p-2 text-center">Action</th>
|
}">
|
||||||
</tr>
|
<Loading v-if="diagnosticLoading" class="inline-block text-xl"></Loading>
|
||||||
</thead>
|
<span v-else class="font-bold">
|
||||||
<tbody>
|
{{ !isMISPOnline ? 'Unreachable' : `Online (${diagnostic['version']['version']})` }}
|
||||||
<tr
|
</span>
|
||||||
v-for="(settingValues, setting) in diagnostic['settings']"
|
</span>
|
||||||
:key="setting"
|
</span>
|
||||||
>
|
</h4>
|
||||||
<td class="font-mono font-semibold text-base px-2">{{ setting }}</td>
|
<h4 class="font-semibold ml-1 my-3">
|
||||||
<td
|
<strong>ZMQ Status:</strong>
|
||||||
:class="`font-mono text-base tracking-tight px-2 ${settingValues.expected_value != settingValues.value ? 'text-red-600 dark:text-red-600' : ''}`"
|
<span class="ml-2">
|
||||||
>
|
<span :class="{
|
||||||
<i v-if="settingValues.value === undefined || settingValues.value === null" class="text-nowrap">- none -</i>
|
'rounded-lg py-1 px-2 inline-flex': true,
|
||||||
{{ settingValues.value }}
|
'dark:bg-neutral-800 bg-neutral-400 text-slate-800 dark:text-slate-200': diagnosticLoading,
|
||||||
</td>
|
'dark:bg-green-700 bg-green-500 text-slate-800 dark:text-slate-200': !diagnosticLoading && isZMQActive,
|
||||||
<td class="font-mono text-base tracking-tight px-2">{{ settingValues.expected_value }}</td>
|
'dark:bg-red-700 bg-red-700 text-slate-200 dark:text-slate-200': !diagnosticLoading && !isZMQActive,
|
||||||
<td class="px-2 text-center">
|
}">
|
||||||
<span v-if="settingValues.error === true"
|
<Loading v-if="diagnosticLoading" class="inline-block text-xl"></Loading>
|
||||||
class="text-red-600 dark:text-red-600"
|
<span v-else class="font-bold">
|
||||||
>Error: {{ settingValues.errorMessage }}</span>
|
{{ !isZMQActive ? 'No message received yet' : `ZMQ Active (${ZMQMessageCount} messages)` }}
|
||||||
<button
|
</span>
|
||||||
v-else-if="settingValues.expected_value != settingValues.value"
|
</span>
|
||||||
@click="clickedButtons.push(setting) && settingHandler(setting)"
|
</span>
|
||||||
:disabled="clickedButtons.includes(setting)"
|
</h4>
|
||||||
class="h-8 min-h-8 px-2 font-semibold bg-green-600 text-slate-200 hover:bg-green-700 btn gap-1"
|
|
||||||
>
|
|
||||||
<template v-if="!clickedButtons.includes(setting)">
|
|
||||||
<FontAwesomeIcon :icon="faHammer" size="sm" fixed-width></FontAwesomeIcon>
|
|
||||||
Remediate
|
|
||||||
</template>
|
|
||||||
<template v-else>
|
|
||||||
<span class="loading loading-dots loading-sm"></span>
|
|
||||||
</template>
|
|
||||||
</button>
|
|
||||||
<span v-else class="text-base font-bold text-green-600 dark:text-green-600">
|
|
||||||
<FontAwesomeIcon :icon="faCheck" class=""></FontAwesomeIcon>
|
|
||||||
OK
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
</div>
|
<template v-if="diagnosticLoading || isMISPOnline">
|
||||||
|
<h4 class="font-semibold ml-1"><strong>MISP Settings:</strong></h4>
|
||||||
|
<div class="ml-3">
|
||||||
|
<div v-if="diagnosticLoading" class="flex justify-center">
|
||||||
|
<Loading class="text-3xl"></Loading>
|
||||||
</div>
|
</div>
|
||||||
<form method="dialog" class="modal-backdrop backdrop-blur">
|
<table v-else class="bg-white dark:bg-slate-700 dark:text-slate-100 text-slate-700 rounded-lg shadow-xl w-full mt-2">
|
||||||
<button>close</button>
|
<thead>
|
||||||
</form>
|
<tr>
|
||||||
</dialog>
|
<th class="border-b border-slate-200 dark:border-slate-600 p-2 text-left">Setting</th>
|
||||||
|
<th class="border-b border-slate-200 dark:border-slate-600 p-2 text-left">Value</th>
|
||||||
|
<th class="border-b border-slate-200 dark:border-slate-600 p-2 text-left">Expected Value</th>
|
||||||
|
<th class="border-b border-slate-200 dark:border-slate-600 p-2 text-center">Action</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr
|
||||||
|
v-for="(settingValues, setting) in diagnostic['settings']"
|
||||||
|
:key="setting"
|
||||||
|
>
|
||||||
|
<td class="font-mono font-semibold text-base px-2">{{ setting }}</td>
|
||||||
|
<td
|
||||||
|
:class="`font-mono text-base tracking-tight px-2 ${settingValues.expected_value != settingValues.value ? 'text-red-600 dark:text-red-600' : ''}`"
|
||||||
|
>
|
||||||
|
<i v-if="settingValues.value === undefined || settingValues.value === null" class="text-nowrap">- none -</i>
|
||||||
|
{{ settingValues.value }}
|
||||||
|
</td>
|
||||||
|
<td class="font-mono text-base tracking-tight px-2">{{ settingValues.expected_value }}</td>
|
||||||
|
<td class="px-2 text-center">
|
||||||
|
<span v-if="settingValues.error === true"
|
||||||
|
class="text-red-600 dark:text-red-600"
|
||||||
|
>Error: {{ settingValues.errorMessage }}</span>
|
||||||
|
<button
|
||||||
|
v-else-if="settingValues.expected_value != settingValues.value"
|
||||||
|
@click="clickedButtons.push(setting) && settingHandler(setting)"
|
||||||
|
:disabled="clickedButtons.includes(setting)"
|
||||||
|
class="h-8 min-h-8 px-2 font-semibold bg-green-600 text-slate-200 hover:bg-green-700 btn gap-1"
|
||||||
|
>
|
||||||
|
<template v-if="!clickedButtons.includes(setting)">
|
||||||
|
<FontAwesomeIcon :icon="faHammer" size="sm" fixed-width></FontAwesomeIcon>
|
||||||
|
Remediate
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<Loading class="text-xl"></Loading>
|
||||||
|
</template>
|
||||||
|
</button>
|
||||||
|
<span v-else class="text-base font-bold text-green-600 dark:text-green-600">
|
||||||
|
<FontAwesomeIcon :icon="faCheck" class=""></FontAwesomeIcon>
|
||||||
|
OK
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</Modal>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
|
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
|
||||||
import { faSignal, faCloud, faCog, faUsers, faCircle } from '@fortawesome/free-solid-svg-icons'
|
import { faSignal, faCloud, faCog, faUsers, faCircle } from '@fortawesome/free-solid-svg-icons'
|
||||||
import TheLiveLogsActivityGraphVue from "./TheLiveLogsActivityGraph.vue";
|
import TheLiveLogsActivityGraphVue from "./TheLiveLogsActivityGraph.vue";
|
||||||
|
import ToggleSwitch from "@/components/elements/ToggleSwitch.vue"
|
||||||
|
|
||||||
|
|
||||||
const verbose = ref(false)
|
const verbose = ref(false)
|
||||||
|
@ -60,13 +61,13 @@
|
||||||
</span>
|
</span>
|
||||||
<span class="flex items-center">
|
<span class="flex items-center">
|
||||||
<label class="mr-1 flex items-center cursor-pointer text-slate-700 dark:text-slate-300">
|
<label class="mr-1 flex items-center cursor-pointer text-slate-700 dark:text-slate-300">
|
||||||
<input type="checkbox" class="toggle toggle-warning [--fallback-su:#22c55e] mr-1" :checked="verbose" @change="verbose = !verbose"/>
|
<input type="checkbox" class="toggle toggle-warning mr-1" :checked="verbose" @change="verbose = !verbose"/>
|
||||||
Verbose
|
Verbose
|
||||||
</label>
|
</label>
|
||||||
</span>
|
</span>
|
||||||
<span class="flex items-center">
|
<span class="flex items-center">
|
||||||
<label class="mr-1 flex items-center cursor-pointer text-slate-700 dark:text-slate-300">
|
<label class="mr-1 flex items-center cursor-pointer text-slate-700 dark:text-slate-300">
|
||||||
<input type="checkbox" class="toggle toggle-success [--fallback-su:#22c55e] mr-1" :checked="api_query" @change="api_query = !api_query"/>
|
<input type="checkbox" class="toggle toggle-success mr-1" :checked="api_query" @change="api_query = !api_query"/>
|
||||||
<FontAwesomeIcon :icon="faCog" size="sm" :mask="faCloud" transform="shrink-7 left-1" class="mr-1"></FontAwesomeIcon>
|
<FontAwesomeIcon :icon="faCog" size="sm" :mask="faCloud" transform="shrink-7 left-1" class="mr-1"></FontAwesomeIcon>
|
||||||
API Queries
|
API Queries
|
||||||
</label>
|
</label>
|
||||||
|
|
|
@ -23,9 +23,9 @@
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
@click="darkMode = !darkMode"
|
@click="darkMode = !darkMode"
|
||||||
:checked="darkMode"
|
:checked="darkMode"
|
||||||
class="toggle theme-controller bg-slate-400 col-span-2 col-start-1 row-start-1 [--tglbg:#e2e8f0]" />
|
class="toggle theme-controller bg-slate-500 col-span-2 col-start-1 row-start-1 [--tglbg:#e2e8f0] dark:[--tglbg:#1d232a]" />
|
||||||
<svg
|
<svg
|
||||||
class="stroke-base-100 fill-base-100 col-start-1 row-start-1"
|
class="stroke-slate-800 dark:stroke-slate-100 fill-slate-800 dark:fill-slate-100 col-start-1 row-start-1"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
width="14"
|
width="14"
|
||||||
height="14"
|
height="14"
|
||||||
|
@ -40,7 +40,7 @@
|
||||||
d="M12 1v2M12 21v2M4.2 4.2l1.4 1.4M18.4 18.4l1.4 1.4M1 12h2M21 12h2M4.2 19.8l1.4-1.4M18.4 5.6l1.4-1.4" />
|
d="M12 1v2M12 21v2M4.2 4.2l1.4 1.4M18.4 18.4l1.4 1.4M1 12h2M21 12h2M4.2 19.8l1.4-1.4M18.4 5.6l1.4-1.4" />
|
||||||
</svg>
|
</svg>
|
||||||
<svg
|
<svg
|
||||||
class="stroke-base-100 fill-base-100 col-start-2 row-start-1"
|
class="dark:stroke-slate-800 stroke-slate-700 dark:fill-slate-800 fill-slate-700 col-start-2 row-start-1"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
width="14"
|
width="14"
|
||||||
height="14"
|
height="14"
|
||||||
|
@ -55,3 +55,41 @@
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.toggle {
|
||||||
|
--animation-input: 0.2s;
|
||||||
|
--handleoffset: 1.5rem;
|
||||||
|
--handleoffsetcalculator: calc(var(--handleoffset) * -1);
|
||||||
|
--togglehandleborder: 0 0;
|
||||||
|
@apply h-6 w-12 rounded-3xl cursor-pointer appearance-none border border-current bg-current;
|
||||||
|
transition:
|
||||||
|
background,
|
||||||
|
box-shadow var(--animation-input, 0.2s) ease-out;
|
||||||
|
box-shadow:
|
||||||
|
var(--handleoffsetcalculator) 0 0 2px var(--tglbg) inset,
|
||||||
|
0 0 0 2px var(--tglbg) inset,
|
||||||
|
var(--togglehandleborder);
|
||||||
|
&:focus-visible {
|
||||||
|
@apply outline outline-2 outline-offset-2;
|
||||||
|
}
|
||||||
|
&:hover {
|
||||||
|
@apply bg-current;
|
||||||
|
}
|
||||||
|
&:checked,
|
||||||
|
&[aria-checked="true"] {
|
||||||
|
background-image: none;
|
||||||
|
--handleoffsetcalculator: var(--handleoffset);
|
||||||
|
}
|
||||||
|
&:indeterminate {
|
||||||
|
box-shadow:
|
||||||
|
calc(var(--handleoffset) / 2) 0 0 2px var(--tglbg) inset,
|
||||||
|
calc(var(--handleoffset) / -2) 0 0 2px var(--tglbg) inset,
|
||||||
|
0 0 0 2px var(--tglbg) inset;
|
||||||
|
}
|
||||||
|
&:disabled {
|
||||||
|
@apply cursor-not-allowed bg-transparent opacity-30;
|
||||||
|
--togglehandleborder: 0 0 0 3px #000 inset,
|
||||||
|
var(--handleoffsetcalculator) 0 0 3px #000 inset;
|
||||||
|
}
|
||||||
|
}</style>
|
7
src/components/elements/Loading.vue
Normal file
7
src/components/elements/Loading.vue
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
<script setup>
|
||||||
|
import { faSpinner } from '@fortawesome/free-solid-svg-icons'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<FontAwesomeIcon :icon="faSpinner" class="fa-spin" fixed-width></FontAwesomeIcon>
|
||||||
|
</template>
|
72
src/components/elements/Modal.vue
Normal file
72
src/components/elements/Modal.vue
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
<script setup>
|
||||||
|
import { ref, watch } from "vue";
|
||||||
|
import { faTimes } from '@fortawesome/free-solid-svg-icons'
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
showModal: Boolean,
|
||||||
|
});
|
||||||
|
|
||||||
|
const dialog = ref(null)
|
||||||
|
|
||||||
|
const emit = defineEmits(["modal-close"]);
|
||||||
|
|
||||||
|
function closeModal() {
|
||||||
|
emit('modal-close')
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Teleport to="body">
|
||||||
|
<div>
|
||||||
|
<Transition>
|
||||||
|
<div
|
||||||
|
v-if="props.showModal"
|
||||||
|
class="fixed w-4/6 top-20 left-2/4 -translate-x-1/2 rounded-lg border border-slate-800 shadow-lg z-50"
|
||||||
|
>
|
||||||
|
<Teleport to="body">
|
||||||
|
<div
|
||||||
|
@click.stop="closeModal()"
|
||||||
|
class="bg-white/30 backdrop-blur-sm fixed top-0 bottom-0 left-0 right-0 z-40 cursor-pointer"
|
||||||
|
></div>
|
||||||
|
</Teleport>
|
||||||
|
<div class="flex px-4 py-3 bg-slate-700 rounded-t-lg border-b border-slate-800">
|
||||||
|
<h2 class="text-white font-semibold text-lg">
|
||||||
|
<slot name="header"></slot>
|
||||||
|
</h2>
|
||||||
|
<span class="ml-auto text-xl">
|
||||||
|
<button @click.stop="closeModal()"
|
||||||
|
class="hover:text-slate-200 hover:dark:text-slate-50 hover:bg-slate-200/20 rounded-full p-1"
|
||||||
|
>
|
||||||
|
<FontAwesomeIcon :icon="faTimes" class="fa-fw"></FontAwesomeIcon>
|
||||||
|
</button>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="px-4 py-3 bg-slate-100">
|
||||||
|
<slot name="body"></slot>
|
||||||
|
</div>
|
||||||
|
<div class="px-4 py-3 bg-slate-100 rounded-b-lg">
|
||||||
|
<slot name="footer">
|
||||||
|
<div class="flex flex-row-reverse">
|
||||||
|
<button class="btn btn-primary btn-lg" @click.stop="closeModal()">Ok</button>
|
||||||
|
</div>
|
||||||
|
</slot>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Transition>
|
||||||
|
</div>
|
||||||
|
</Teleport>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.v-enter-active {
|
||||||
|
@apply transition duration-150 ease-out;
|
||||||
|
}
|
||||||
|
.v-leave-active {
|
||||||
|
@apply transition duration-150 ease-in;
|
||||||
|
}
|
||||||
|
.v-enter-from,
|
||||||
|
.v-leave-to {
|
||||||
|
@apply scale-90;
|
||||||
|
@apply opacity-0;
|
||||||
|
}
|
||||||
|
</style>
|
58
src/components/elements/ToggleSwitch.vue
Normal file
58
src/components/elements/ToggleSwitch.vue
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
<script setup>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<label class="grid cursor-pointer place-items-center">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
class="toggle theme-controller bg-slate-500 col-span-2 col-start-1 row-start-1 [--tglbg:#e2e8f0] dark:[--tglbg:#1d232a]" />
|
||||||
|
</label>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.toggle {
|
||||||
|
--animation-input: 0.2s;
|
||||||
|
--handleoffset: 1.5rem;
|
||||||
|
--handleoffsetcalculator: calc(var(--handleoffset) * -1);
|
||||||
|
--togglehandleborder: 0 0;
|
||||||
|
@apply h-6 w-12 rounded-3xl cursor-pointer appearance-none border border-current bg-current;
|
||||||
|
transition:
|
||||||
|
background,
|
||||||
|
box-shadow var(--animation-input, 0.2s) ease-out;
|
||||||
|
box-shadow:
|
||||||
|
var(--handleoffsetcalculator) 0 0 2px var(--tglbg) inset,
|
||||||
|
0 0 0 2px var(--tglbg) inset,
|
||||||
|
var(--togglehandleborder);
|
||||||
|
&:focus-visible {
|
||||||
|
@apply outline outline-2 outline-offset-2;
|
||||||
|
}
|
||||||
|
&:hover {
|
||||||
|
@apply bg-current;
|
||||||
|
}
|
||||||
|
&:checked,
|
||||||
|
&[aria-checked="true"] {
|
||||||
|
background-image: none;
|
||||||
|
--handleoffsetcalculator: var(--handleoffset);
|
||||||
|
}
|
||||||
|
&:indeterminate {
|
||||||
|
box-shadow:
|
||||||
|
calc(var(--handleoffset) / 2) 0 0 2px var(--tglbg) inset,
|
||||||
|
calc(var(--handleoffset) / -2) 0 0 2px var(--tglbg) inset,
|
||||||
|
0 0 0 2px var(--tglbg) inset;
|
||||||
|
}
|
||||||
|
&:disabled {
|
||||||
|
@apply cursor-not-allowed bg-transparent opacity-30;
|
||||||
|
--togglehandleborder: 0 0 0 3px #000 inset,
|
||||||
|
var(--handleoffsetcalculator) 0 0 3px #000 inset;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-success {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* backward compatibility */
|
||||||
|
.toggle-mark {
|
||||||
|
@apply hidden;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -4,7 +4,14 @@ import VueApexCharts from "vue3-apexcharts";
|
||||||
import { createApp } from 'vue'
|
import { createApp } from 'vue'
|
||||||
import App from './App.vue'
|
import App from './App.vue'
|
||||||
|
|
||||||
|
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
|
||||||
|
import Modal from "@/components/elements/Modal.vue"
|
||||||
|
import Loading from "@/components/elements/Loading.vue"
|
||||||
|
|
||||||
const app = createApp(App)
|
const app = createApp(App)
|
||||||
|
app.component('FontAwesomeIcon', FontAwesomeIcon)
|
||||||
|
app.component('Modal', Modal)
|
||||||
|
app.component('Loading', Loading)
|
||||||
app.use(VueApexCharts)
|
app.use(VueApexCharts)
|
||||||
|
|
||||||
app.mount('#app')
|
app.mount('#app')
|
34
src/router.js
Normal file
34
src/router.js
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
|
||||||
|
import { createWebHistory, createRouter } from 'vue-router'
|
||||||
|
|
||||||
|
const routes = [
|
||||||
|
{ path: '/', component: ScenarioList },
|
||||||
|
{ path: '/scenarios/index', name: 'Scenario Index', component: ScenarioList, meta: { requiresScenarioSelection: false }, },
|
||||||
|
{ path: '/scenarios/add', name: 'New Scenario', component: ScenarioNew, meta: { requiresScenarioSelection: false }, },
|
||||||
|
{ path: '/scenarios/overview/:uuid?', name: 'Scenario Overview', component: ScenarioOverview, meta: { requiresScenarioSelection: true }, props: true },
|
||||||
|
{ path: '/scenarios/designer/:uuid?', name: 'Scenario Designer', component: ScenarioDesigner, meta: { requiresScenarioSelection: true }, props: true },
|
||||||
|
{ path: '/injects/tester/:uuid?', name: 'Inject Tester', component: InjectTester, props: true },
|
||||||
|
]
|
||||||
|
|
||||||
|
const router = createRouter({
|
||||||
|
history: createWebHistory(),
|
||||||
|
routes,
|
||||||
|
})
|
||||||
|
|
||||||
|
router.beforeEach(async (to, from) => {
|
||||||
|
if (to.path === '/') {
|
||||||
|
return { path: '/scenarios/index' }
|
||||||
|
}
|
||||||
|
if (!hasScenarios()) {
|
||||||
|
fetchScenarios()
|
||||||
|
}
|
||||||
|
if (from.name == undefined && ['Scenario Overview', 'Scenario Designer'].includes(to.name) && to?.params?.uuid !== undefined) {
|
||||||
|
store.selected_scenario = to.params.uuid
|
||||||
|
}
|
||||||
|
if (to?.meta?.requiresScenarioSelection === true && store.selected_scenario === null) {
|
||||||
|
return { path: '/scenarios/index' }
|
||||||
|
}
|
||||||
|
if (to.matched.length == 0) {
|
||||||
|
return { path: '/scenarios/index' }
|
||||||
|
}
|
||||||
|
})
|
17
src/utils.js
Normal file
17
src/utils.js
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
let toastID = 0
|
||||||
|
export const toastBuffer = ref([])
|
||||||
|
export function toast(toast) {
|
||||||
|
toastID += 1
|
||||||
|
toast.id = toastID
|
||||||
|
toastBuffer.value.push(toast)
|
||||||
|
}
|
||||||
|
export function removeToast(id) {
|
||||||
|
toastBuffer.value = toastBuffer.value.filter((toast) => toast.id != id)
|
||||||
|
}
|
||||||
|
export function ajaxFeedback(response) {
|
||||||
|
toast({
|
||||||
|
variant: response.success ? 'success' : 'danger',
|
||||||
|
message: String(response.message),
|
||||||
|
title: response.title,
|
||||||
|
})
|
||||||
|
}
|
|
@ -23,17 +23,17 @@ export default {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
require('daisyui'),
|
// require('daisyui'),
|
||||||
],
|
],
|
||||||
darkMode: ['selector'],
|
darkMode: ['selector'],
|
||||||
daisyui: {
|
// daisyui: {
|
||||||
themes: false, // false: only light + dark | true: all themes | array: specific themes like this ["light", "dark", "cupcake"]
|
// themes: false, // false: only light + dark | true: all themes | array: specific themes like this ["light", "dark", "cupcake"]
|
||||||
darkTheme: "dark", // name of one of the included themes for dark mode
|
// darkTheme: "dark", // name of one of the included themes for dark mode
|
||||||
base: false, // applies background color and foreground color for root element by default
|
// base: false, // applies background color and foreground color for root element by default
|
||||||
styled: true, // include daisyUI colors and design decisions for all components
|
// styled: true, // include daisyUI colors and design decisions for all components
|
||||||
utils: false, // adds responsive and modifier utility classes
|
// utils: false, // adds responsive and modifier utility classes
|
||||||
prefix: "", // prefix for daisyUI classnames (components, modifiers and responsive class names. Not colors)
|
// prefix: "", // prefix for daisyUI classnames (components, modifiers and responsive class names. Not colors)
|
||||||
logs: false, // Shows info about daisyUI version and used config in the console when building your CSS
|
// logs: false, // Shows info about daisyUI version and used config in the console when building your CSS
|
||||||
themeRoot: ":root", // The element that receives theme color CSS variables
|
// themeRoot: ":root", // The element that receives theme color CSS variables
|
||||||
},
|
// },
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue