diff --git a/.vite/deps/_metadata.json b/.vite/deps/_metadata.json new file mode 100644 index 0000000..f84cc69 --- /dev/null +++ b/.vite/deps/_metadata.json @@ -0,0 +1,8 @@ +{ + "hash": "d30f2833", + "configHash": "e49d25ea", + "lockfileHash": "e3b0c442", + "browserHash": "f22e7dd7", + "optimized": {}, + "chunks": {} +} \ No newline at end of file diff --git a/.vite/deps/package.json b/.vite/deps/package.json new file mode 100644 index 0000000..3dbc1ca --- /dev/null +++ b/.vite/deps/package.json @@ -0,0 +1,3 @@ +{ + "type": "module" +} diff --git a/src/App.vue b/src/App.vue index 56ca6a2..35066ee 100644 --- a/src/App.vue +++ b/src/App.vue @@ -5,16 +5,14 @@ import TheAdminPanel from './components/TheAdminPanel.vue' import TheSocketConnectionState from './components/TheSocketConnectionState.vue' import TheDahboard from './TheDahboard.vue' import Toaster from '@/components/elements/Toaster.vue' -import { socketConnected } from "@/socket"; -import { darkModeEnabled } from "@/settings.js" - +import { socketConnected } from '@/socket' +import { darkModeEnabled } from '@/settings.js' onMounted(() => { if (darkModeEnabled.value) { document.getElementsByTagName('body')[0].classList.add('dark') } }) - \ No newline at end of file + + diff --git a/src/components/TheLiveLogsActivityGraph.vue b/src/components/TheLiveLogsActivityGraph.vue index a56c33e..5151497 100644 --- a/src/components/TheLiveLogsActivityGraph.vue +++ b/src/components/TheLiveLogsActivityGraph.vue @@ -1,84 +1,92 @@ \ No newline at end of file + diff --git a/src/components/ThePlayerGrid.vue b/src/components/ThePlayerGrid.vue index d00170f..3aa2c21 100644 --- a/src/components/ThePlayerGrid.vue +++ b/src/components/ThePlayerGrid.vue @@ -1,58 +1,60 @@ \ No newline at end of file + diff --git a/src/components/TheScores.vue b/src/components/TheScores.vue index 69f9618..f899de7 100644 --- a/src/components/TheScores.vue +++ b/src/components/TheScores.vue @@ -1,25 +1,29 @@ diff --git a/src/components/elements/Modal.vue b/src/components/elements/Modal.vue index cbcce56..82050ed 100644 --- a/src/components/elements/Modal.vue +++ b/src/components/elements/Modal.vue @@ -1,23 +1,23 @@ \ No newline at end of file + diff --git a/src/components/elements/Toast.vue b/src/components/elements/Toast.vue index 892177f..8294518 100644 --- a/src/components/elements/Toast.vue +++ b/src/components/elements/Toast.vue @@ -82,7 +82,10 @@ onMounted(() => { > -
+
{{ props.message }}
@@ -94,4 +97,4 @@ onMounted(() => {
- \ No newline at end of file + diff --git a/src/components/elements/Toaster.vue b/src/components/elements/Toaster.vue index 880991d..3b0958a 100644 --- a/src/components/elements/Toaster.vue +++ b/src/components/elements/Toaster.vue @@ -44,4 +44,4 @@ function remove(toast_id) { opacity: 0; transform: translateX(10px); } - \ No newline at end of file + diff --git a/src/components/elements/ToggleSwitch.vue b/src/components/elements/ToggleSwitch.vue index ca6e02c..9b3b7a0 100644 --- a/src/components/elements/ToggleSwitch.vue +++ b/src/components/elements/ToggleSwitch.vue @@ -1,12 +1,12 @@ - + \ No newline at end of file + diff --git a/src/components/scoreViews/TheFullScreenScoreGrid.vue b/src/components/scoreViews/TheFullScreenScoreGrid.vue index 57c17ca..8cc1f17 100644 --- a/src/components/scoreViews/TheFullScreenScoreGrid.vue +++ b/src/components/scoreViews/TheFullScreenScoreGrid.vue @@ -1,251 +1,291 @@ \ No newline at end of file + + +
+
+ + + Task {{ task_index + 1 }} + {{ task.name }} + + + + + +
+ + +
+ + + + + + {{ progress.email.split('@')[0] }} + @{{ progress.email.split('@')[1] }} + + + + + + + + + + + + + + + +
+
+ + diff --git a/src/components/scoreViews/TheScoreTable.vue b/src/components/scoreViews/TheScoreTable.vue index 78b9cce..841cba5 100644 --- a/src/components/scoreViews/TheScoreTable.vue +++ b/src/components/scoreViews/TheScoreTable.vue @@ -1,186 +1,288 @@ + + + diff --git a/src/main.js b/src/main.js index a3a8657..271d3cc 100644 --- a/src/main.js +++ b/src/main.js @@ -1,13 +1,13 @@ import './assets/main.css' -import VueApexCharts from "vue3-apexcharts"; +import VueApexCharts from 'vue3-apexcharts' import { createApp, ref } from '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" -import Alert from "@/components/elements/Alert.vue" +import Modal from '@/components/elements/Modal.vue' +import Loading from '@/components/elements/Loading.vue' +import Alert from '@/components/elements/Alert.vue' const app = createApp(App) app.component('FontAwesomeIcon', FontAwesomeIcon) @@ -16,4 +16,4 @@ app.component('Loading', Loading) app.component('Alert', Alert) app.use(VueApexCharts) -app.mount('#app') \ No newline at end of file +app.mount('#app') diff --git a/src/router.js b/src/router.js index 5f485eb..29a31da 100644 --- a/src/router.js +++ b/src/router.js @@ -1,34 +1,59 @@ - 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 }, + { 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, + 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' } - } -}) \ No newline at end of file + 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' } + } +}) diff --git a/src/settings.js b/src/settings.js index 32c2866..49df187 100644 --- a/src/settings.js +++ b/src/settings.js @@ -3,4 +3,4 @@ import { ref, computed } from 'vue' export const darkModeOn = ref(true) export const darkModeEnabled = computed(() => darkModeOn.value) -export const fullscreenModeOn = ref(false) \ No newline at end of file +export const fullscreenModeOn = ref(false) diff --git a/src/socket.js b/src/socket.js index 00ca537..9ed39f5 100644 --- a/src/socket.js +++ b/src/socket.js @@ -1,9 +1,9 @@ -import { reactive, computed } from "vue"; -import { io } from "socket.io-client"; +import { reactive, computed } from 'vue' +import { io } from 'socket.io-client' import debounce from 'lodash.debounce' // "undefined" means the URL will be computed from the `window.location` object -const URL = process.env.NODE_ENV === "production" ? undefined : "http://localhost:40001"; +const URL = process.env.NODE_ENV === 'production' ? undefined : 'http://localhost:40001' const MAX_LIVE_LOG = 30 const initial_state = { @@ -17,27 +17,27 @@ const initial_state = { exercises: [], selected_exercises: [], progresses: {}, - diagnostic: {}, + diagnostic: {} } -const state = reactive({ ...initial_state }); -const connectionState = reactive({ +const state = reactive({ ...initial_state }) +const connectionState = reactive({ connected: false, - zmq_last_time: false, + zmq_last_time: false }) - const socket = io(URL, { autoConnect: true -}); - +}) /* Public */ /* ------ */ export const exercises = computed(() => state.exercises) export const selected_exercises = computed(() => state.selected_exercises) -export const active_exercises = computed(() => state.exercises.filter((exercise) => state.selected_exercises.includes(exercise.uuid))) +export const active_exercises = computed(() => + state.exercises.filter((exercise) => state.selected_exercises.includes(exercise.uuid)) +) export const progresses = computed(() => state.progresses) export const notifications = computed(() => state.notificationEvents) export const notificationCounter = computed(() => state.notificationCounter) @@ -52,7 +52,7 @@ export const socketConnected = computed(() => connectionState.connected) export const zmqLastTime = computed(() => connectionState.zmq_last_time) export function resetState() { - Object.assign(state, initial_state); + Object.assign(state, initial_state) } export function fullReload() { @@ -67,7 +67,7 @@ export function setCompletedState(completed, user_id, exec_uuid, task_uuid) { const payload = { user_id: user_id, exercise_uuid: exec_uuid, - task_uuid: task_uuid, + task_uuid: task_uuid } sendCompletedState(completed, payload) } @@ -87,7 +87,7 @@ export function resetLiveLogs() { export function changeExerciseSelection(exec_uuid, state_enabled) { const payload = { exercise_uuid: exec_uuid, - selected: state_enabled, + selected: state_enabled } sendChangeExerciseSelection(payload) } @@ -103,7 +103,8 @@ export function toggleApiQueryMode(enabled) { export function remediateSetting(setting) { sendRemediateSetting(setting, (result) => { if (result.success) { - state.diagnostic['settings'][setting].value = state.diagnostic['settings'][setting].expected_value + state.diagnostic['settings'][setting].value = + state.diagnostic['settings'][setting].expected_value } else { state.diagnostic['settings'][setting].error = true state.diagnostic['settings'][setting].errorMessage = result.message @@ -111,79 +112,77 @@ export function remediateSetting(setting) { }) } -export const debouncedGetProgress = debounce(getProgress, 200, {leading: true}) -export const debouncedGetDiangostic = debounce(getDiangostic, 1000, {leading: true}) - +export const debouncedGetProgress = debounce(getProgress, 200, { leading: true }) +export const debouncedGetDiangostic = debounce(getDiangostic, 1000, { leading: true }) /* Private */ /* ------- */ function getExercises() { - socket.emit("get_exercises", (all_exercises) => { + socket.emit('get_exercises', (all_exercises) => { state.exercises = all_exercises }) } function getSelectedExercises() { - socket.emit("get_selected_exercises", (all_selected_exercises) => { + socket.emit('get_selected_exercises', (all_selected_exercises) => { state.selected_exercises = all_selected_exercises }) } function getNotifications() { - socket.emit("get_notifications", (all_notifications) => { + socket.emit('get_notifications', (all_notifications) => { state.notificationEvents = all_notifications }) } function getProgress() { - socket.emit("get_progress", (all_progress) => { + socket.emit('get_progress', (all_progress) => { state.progresses = all_progress }) } function getUsersActivity() { - socket.emit("get_users_activity", (user_activity_bundle) => { + socket.emit('get_users_activity', (user_activity_bundle) => { state.userActivity = user_activity_bundle.activity state.userActivityConfig = user_activity_bundle.config - }); + }) } - function getDiangostic() { state.diagnostic = {} - socket.emit("get_diagnostic", (diagnostic) => { + socket.emit('get_diagnostic', (diagnostic) => { state.diagnostic = diagnostic }) } function sendCompletedState(completed, payload) { - const event_name = !completed ? "mark_task_completed": "mark_task_incomplete" + const event_name = !completed ? 'mark_task_completed' : 'mark_task_incomplete' socket.emit(event_name, payload, () => { getProgress() }) } function sendResetAllExerciseProgress() { - socket.emit("reset_all_exercise_progress", () => { + socket.emit('reset_all_exercise_progress', () => { getProgress() }) } function sendResetAll() { - socket.emit("reset_all", () => { + socket.emit('reset_all', () => { getProgress() }) } function sendResetLiveLogs() { - socket.emit("reset_notifications", () => { + socket.emit('reset_notifications', () => { getNotifications() }) } function sendChangeExerciseSelection(payload) { - socket.emit("change_exercise_selection", payload, () => { + socket.emit('change_exercise_selection', payload, () => { getSelectedExercises() }) } @@ -192,68 +191,68 @@ function sendToggleVerboseMode(enabled) { const payload = { verbose: enabled } - socket.emit("toggle_verbose_mode", payload, () => {}) + socket.emit('toggle_verbose_mode', payload, () => {}) } function sendToggleApiQueryMode(enabled) { const payload = { apiquery: enabled } - socket.emit("toggle_apiquery_mode", payload, () => {}) + socket.emit('toggle_apiquery_mode', payload, () => {}) } function sendRemediateSetting(setting, cb) { const payload = { name: setting } - socket.emit("remediate_setting", payload, (result) => { + socket.emit('remediate_setting', payload, (result) => { cb(result) }) } /* Event listener */ -socket.on("connect", () => { - connectionState.connected = true; -}); +socket.on('connect', () => { + connectionState.connected = true +}) -socket.on("disconnect", () => { - connectionState.connected = false; -}); +socket.on('disconnect', () => { + connectionState.connected = false +}) -socket.on("notification", (message) => { +socket.on('notification', (message) => { state.notificationCounter += 1 if (message.is_api_request) { state.notificationAPICounter += 1 } addLimited(state.notificationEvents, message, MAX_LIVE_LOG) -}); +}) -socket.on("new_user", (new_user) => { +socket.on('new_user', (new_user) => { debouncedGetProgress() -}); +}) -socket.on("refresh_score", (new_user) => { +socket.on('refresh_score', (new_user) => { debouncedGetProgress() -}); +}) -socket.on("keep_alive", (keep_alive) => { +socket.on('keep_alive', (keep_alive) => { connectionState.zmq_last_time = keep_alive['zmq_last_time'] -}); +}) -socket.on("update_notification_history", (notification_history_bundle) => { +socket.on('update_notification_history', (notification_history_bundle) => { state.notificationHistory = notification_history_bundle.history state.notificationHistoryConfig = notification_history_bundle.config -}); +}) -socket.on("update_users_activity", (user_activity_bundle) => { +socket.on('update_users_activity', (user_activity_bundle) => { state.userActivity = user_activity_bundle.activity state.userActivityConfig = user_activity_bundle.config -}); +}) function addLimited(target, message, maxCount) { target.unshift(message) if (target.length > maxCount) { target.length = maxCount } -} \ No newline at end of file +} diff --git a/src/utils.js b/src/utils.js index 9c2734f..ea6fc56 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1,20 +1,20 @@ -import { computed, ref } from "vue" +import { computed, ref } from 'vue' let toastID = 0 export const toastBuffer = ref([]) export const allToasts = computed(() => toastBuffer.value) export function toast(toast) { - toastID += 1 - toast.id = toastID - toastBuffer.value.push(toast) + toastID += 1 + toast.id = toastID + toastBuffer.value.push(toast) } export function removeToast(id) { - toastBuffer.value = toastBuffer.value.filter((toast) => toast.id != 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, - }) -} \ No newline at end of file + toast({ + variant: response.success ? 'success' : 'danger', + message: String(response.message), + title: response.title + }) +}