diff --git a/ping-viewer-next-frontend/bun.lockb b/ping-viewer-next-frontend/bun.lockb index 7afa9c45..7c5491fd 100755 Binary files a/ping-viewer-next-frontend/bun.lockb and b/ping-viewer-next-frontend/bun.lockb differ diff --git a/ping-viewer-next-frontend/package.json b/ping-viewer-next-frontend/package.json index 9e005eb1..ffb6b4a9 100644 --- a/ping-viewer-next-frontend/package.json +++ b/ping-viewer-next-frontend/package.json @@ -12,11 +12,11 @@ "core-js": "^3.39.0", "roboto-fontface": "^0.10.0", "vue": "3.5.8", - "vuetify": "^3.7.4" + "vuetify": "^3.7.6" }, "devDependencies": { "@biomejs/biome": "1.9.2", - "@vitejs/plugin-vue": "^5.1.5", + "@vitejs/plugin-vue": "^5.2.1", "autoprefixer": "^10.4.20", "eslint": "^8.57.1", "eslint-config-standard": "^17.1.0", @@ -25,18 +25,18 @@ "eslint-plugin-n": "^16.6.2", "eslint-plugin-node": "^11.1.0", "eslint-plugin-promise": "^6.6.0", - "eslint-plugin-vue": "^9.31.0", - "pinia": "^2.2.6", + "eslint-plugin-vue": "^9.32.0", + "pinia": "^2.3.0", "postcss": "^8.4.49", "sass": "1.77.6", - "tailwindcss": "^3.4.14", + "tailwindcss": "^3.4.17", "unplugin-auto-import": "^0.17.8", - "unplugin-fonts": "^1.1.1", - "unplugin-vue-components": "^0.27.4", - "unplugin-vue-router": "^0.10.8", + "unplugin-fonts": "^1.3.1", + "unplugin-vue-components": "^0.27.5", + "unplugin-vue-router": "^0.10.9", "vite": "^5.4.11", "vite-plugin-vue-layouts": "^0.11.0", "vite-plugin-vuetify": "^2.0.4", - "vue-router": "^4.4.5" + "vue-router": "^4.5.0" } } diff --git a/ping-viewer-next-frontend/src/App.vue b/ping-viewer-next-frontend/src/App.vue index 1eb1676c..7644dd33 100644 --- a/ping-viewer-next-frontend/src/App.vue +++ b/ping-viewer-next-frontend/src/App.vue @@ -1,163 +1,411 @@ +const showRecordingsMenu = ref(false); + +const formatRecordingDate = (timestamp) => { + return new Date(timestamp).toLocaleString(); +}; + +const formatRecordingDetails = (recording) => { + if (!recording.settings) return ''; + + const details = []; + if (recording.deviceType === 'Ping360') { + if (recording.settings.startAngle !== undefined) { + details.push(`${recording.settings.startAngle}° - ${recording.settings.endAngle}°`); + } + if (recording.settings.currentRange) { + details.push(`${recording.settings.currentRange}m range`); + } + } else { + if (recording.settings.maxDepth) { + details.push(`${recording.settings.maxDepth}m depth`); + } + } + return details.join(' | '); +}; + +const deleteRecording = (recording) => { + const index = recordings.value.findIndex((r) => r.id === recording.id); + if (index !== -1) { + recordings.value.splice(index, 1); + // Also remove from localStorage if you're storing them there + saveRecordingsToStorage(); + } +}; + +const clearRecordings = () => { + recordings.value = []; + saveRecordingsToStorage(); +}; + +const saveRecordingsToStorage = () => { + try { + localStorage.setItem('sonar-recordings', JSON.stringify(recordings.value)); + } catch (error) { + console.error('Error saving recordings to storage:', error); + } +}; + +// Add these watchers to handle menu state +watch(isSpeedDialOpen, (newValue) => { + if (newValue) { + showRecordingsMenu.value = false; + } +}); + +watch(isMenuOpen, (newValue) => { + if (newValue) { + showRecordingsMenu.value = false; + } +}); + +watch(showRecordingsMenu, (newValue) => { + if (newValue) { + isSpeedDialOpen.value = false; + isMenuOpen.value = false; + } +}); + + + \ No newline at end of file diff --git a/ping-viewer-next-frontend/src/components/ConnectionManager.vue b/ping-viewer-next-frontend/src/components/ConnectionManager.vue new file mode 100644 index 00000000..e7ddebad --- /dev/null +++ b/ping-viewer-next-frontend/src/components/ConnectionManager.vue @@ -0,0 +1,345 @@ + + + + + \ No newline at end of file diff --git a/ping-viewer-next-frontend/src/components/utils/ServerConnection.vue b/ping-viewer-next-frontend/src/components/utils/ServerConnection.vue index 7f080f24..74234e2b 100644 --- a/ping-viewer-next-frontend/src/components/utils/ServerConnection.vue +++ b/ping-viewer-next-frontend/src/components/utils/ServerConnection.vue @@ -1,94 +1,88 @@ - - \ No newline at end of file + + + \ No newline at end of file diff --git a/ping-viewer-next-frontend/src/components/utils/VisualSettings.vue b/ping-viewer-next-frontend/src/components/utils/VisualSettings.vue index cf551ad0..3b90bfdf 100644 --- a/ping-viewer-next-frontend/src/components/utils/VisualSettings.vue +++ b/ping-viewer-next-frontend/src/components/utils/VisualSettings.vue @@ -1,180 +1,223 @@ - \ No newline at end of file diff --git a/ping-viewer-next-frontend/src/components/views/ReplayView.vue b/ping-viewer-next-frontend/src/components/views/ReplayView.vue index ae5bf116..2554e6d8 100644 --- a/ping-viewer-next-frontend/src/components/views/ReplayView.vue +++ b/ping-viewer-next-frontend/src/components/views/ReplayView.vue @@ -1,33 +1,24 @@ - - \ No newline at end of file + +defineExpose({ + updateCurrentDeviceData, + onDataLoaded, +}); + + + \ No newline at end of file diff --git a/ping-viewer-next-frontend/src/components/widgets/DataPlayer.vue b/ping-viewer-next-frontend/src/components/widgets/DataPlayer.vue index e46bfae9..c1f278bf 100644 --- a/ping-viewer-next-frontend/src/components/widgets/DataPlayer.vue +++ b/ping-viewer-next-frontend/src/components/widgets/DataPlayer.vue @@ -1,58 +1,42 @@ - - \ No newline at end of file +} + \ No newline at end of file diff --git a/ping-viewer-next-frontend/src/components/widgets/sonar1d/Ping1DLoader.vue b/ping-viewer-next-frontend/src/components/widgets/sonar1d/Ping1DLoader.vue index 14607444..44713ebf 100644 --- a/ping-viewer-next-frontend/src/components/widgets/sonar1d/Ping1DLoader.vue +++ b/ping-viewer-next-frontend/src/components/widgets/sonar1d/Ping1DLoader.vue @@ -17,10 +17,16 @@ > {{ isFreeze ? 'mdi-play' : 'mdi-pause' }} + + mdi-cog + + + { } }; +const openSettings = async () => { + isSettingsOpen.value = true; +}; + onMounted(() => { connectWebSocket(); }); diff --git a/ping-viewer-next-frontend/src/components/widgets/sonar1d/Ping1DSettings.vue b/ping-viewer-next-frontend/src/components/widgets/sonar1d/Ping1DSettings.vue index 9e25e6db..5a75542e 100644 --- a/ping-viewer-next-frontend/src/components/widgets/sonar1d/Ping1DSettings.vue +++ b/ping-viewer-next-frontend/src/components/widgets/sonar1d/Ping1DSettings.vue @@ -1,13 +1,6 @@ diff --git a/ping-viewer-next-frontend/src/components/widgets/sonar360/Ping360Loader.vue b/ping-viewer-next-frontend/src/components/widgets/sonar360/Ping360Loader.vue index f317e152..b0f1b2a6 100644 --- a/ping-viewer-next-frontend/src/components/widgets/sonar360/Ping360Loader.vue +++ b/ping-viewer-next-frontend/src/components/widgets/sonar360/Ping360Loader.vue @@ -18,14 +18,21 @@ > {{ isFreeze ? 'mdi-play' : 'mdi-pause' }} + + mdi-cog + + + + { + if (!socket.value || socket.value.readyState !== WebSocket.OPEN) { + console.error('WebSocket is not connected'); + return; + } + + const configRequest = { + command: 'ModifyDevice', + module: 'DeviceManager', + payload: { + uuid: props.device.id, // Using the device id from props + modify: 'GetPing360Config', + }, + }; + + socket.value.send(JSON.stringify(configRequest)); + if (props.debug) { + console.debug('Sent GetPing360Config request:', configRequest); + } +}; + const connectWebSocket = () => { if (socket.value) return; @@ -198,6 +227,7 @@ const connectWebSocket = () => { socket.value.onopen = () => { connectionStatus.value = 'Connected'; + sendGetConfigRequest(); }; socket.value.onmessage = (event) => { @@ -207,9 +237,11 @@ const connectWebSocket = () => { console.debug('Ping360 data:', parsedData); } - if (parsedData.DeviceConfig?.ConfigAcknowledge?.modify?.SetPing360Config) { - const config = parsedData.DeviceConfig.ConfigAcknowledge.modify.SetPing360Config; + const config = + parsedData.DeviceConfig?.ConfigAcknowledge?.modify?.SetPing360Config || + parsedData.DeviceConfig?.Ping360Config; + if (config) { const SAMPLE_PERIOD_TICK_DURATION = 25e-9; currentRange.value = Math.round( (config.sample_period * SAMPLE_PERIOD_TICK_DURATION * config.number_of_samples * 1500) / 2 @@ -284,6 +316,10 @@ const handleRangeChange = (newRange) => { currentRange.value = newRange; }; +const openSettings = async () => { + isSettingsOpen.value = true; +}; + watch( () => props.websocketUrl, (newUrl, oldUrl) => { @@ -301,9 +337,6 @@ watch(yawAngle, (newYaw) => { }); onMounted(async () => { - if (props.showControls && settingsRef.value?.fetchCurrentSettings) { - await settingsRef.value.fetchCurrentSettings(); - } connectWebSocket(); }); diff --git a/ping-viewer-next-frontend/src/components/widgets/sonar360/Ping360Settings.vue b/ping-viewer-next-frontend/src/components/widgets/sonar360/Ping360Settings.vue index 471cdc68..fd8afbf8 100644 --- a/ping-viewer-next-frontend/src/components/widgets/sonar360/Ping360Settings.vue +++ b/ping-viewer-next-frontend/src/components/widgets/sonar360/Ping360Settings.vue @@ -1,10 +1,4 @@