-
+
+
+ Session {{ groupIndex + 1 }}
+ {{ group.sessionId.split('->')[0]?.split(':').pop() || '' }}
-
-
-
-
- POST vide
-
-
- {{ truncateMethod(message.cwmpMethod) }}
-
-
-
-
-
-
+
+
+
-
-
- {{ formatTimestamp(message.timestamp) }}
-
-
+
+
+
+
+ POST vide
+
+
+ {{ truncateMethod(message.cwmpMethod) }}
+
-
-
-
+
+
+
+
+
+ {{ formatTimestamp(message.timestamp) }}
+
+
+
+
+
@@ -586,16 +644,25 @@ watch(
}
.sequence-row--selected {
- background-color: var(--bs-primary-bg-subtle, #e7f1ff) !important;
- border-left: 3px solid var(--bs-primary, #ff7900) !important;
+ background-color: #e7f1ff !important;
+ outline: 2px solid #0d6efd;
+ outline-offset: -2px;
}
.sequence-row--cpe-to-acs .arrow-line {
- background-color: var(--bs-primary, #ff7900);
+ background-color: #ff7900;
}
.sequence-row--cpe-to-acs .arrow-head {
- border-left-color: var(--bs-primary, #ff7900);
+ border-left-color: #ff7900;
+}
+
+.sequence-row--selected.sequence-row--cpe-to-acs .arrow-line {
+ background-color: #ff7900;
+}
+
+.sequence-row--selected.sequence-row--cpe-to-acs .arrow-head {
+ border-left-color: #ff7900;
}
.sequence-row--acs-to-cpe .arrow-line {
@@ -676,4 +743,39 @@ watch(
.top-sentinel {
min-height: 1px;
}
+
+.session-group {
+ border-left: 3px solid #e9ecef;
+ margin: 8px 4px;
+ border-radius: 6px;
+ background: #fcfcfd;
+ box-shadow: 0 0 0 1px #e9ecef;
+ overflow: hidden;
+}
+
+.session-group:nth-child(odd) {
+ border-left-color: #ff7900;
+}
+
+.session-group:nth-child(even) {
+ border-left-color: #527edb;
+}
+
+.session-label {
+ background: #f1f3f5;
+ border-bottom: 1px solid #e9ecef;
+}
+
+.session-badge {
+ font-size: 0.62rem;
+ font-weight: 700;
+ text-transform: uppercase;
+ letter-spacing: 0.04em;
+ color: #495057;
+}
+
+.session-id {
+ font-size: 0.6rem;
+}
+
diff --git a/inertia/pages/DeviceDetail.vue b/inertia/pages/DeviceDetail.vue
index 051df23..a769fb1 100644
--- a/inertia/pages/DeviceDetail.vue
+++ b/inertia/pages/DeviceDetail.vue
@@ -3,9 +3,6 @@ import { ref } from 'vue'
import { router, Link } from '@inertiajs/vue3'
import { useI18n } from 'vue-i18n'
import TitleBar from '../components/TitleBar.vue'
-import SequenceViewer from '../components/SequenceViewer.vue'
-import InspectorPanel from '../components/InspectorPanel.vue'
-import type { CwmpExchange } from '../composables/useExchangeStream'
const { t } = useI18n()
@@ -19,68 +16,40 @@ const isLoading = ref(false)
const showDeleteConfirm = ref(false)
const isTraced = ref(false)
const tracingAction = ref(false)
-const traceStartedAt = ref
(null)
-const selectedMessage = ref(null)
-// Check if device is already traced
async function checkTraceStatus() {
try {
const response = await fetch('/api/v1/tr069-trace')
if (response.ok) {
const data = await response.json()
- const entries = data.entries || []
- const entry = entries.find((e: any) => e.deviceId === device.identifier)
- isTraced.value = !!entry
- if (entry) {
- traceStartedAt.value = entry.startedAt || new Date().toISOString()
- }
+ isTraced.value = (data.entries || []).some((e: any) => e.deviceId === device.identifier)
}
- } catch {
- // Silently ignore
- }
+ } catch { /* ignore */ }
}
async function toggleTrace() {
tracingAction.value = true
try {
if (isTraced.value) {
- const response = await fetch(`/api/v1/tr069-trace/${encodeURIComponent(device.identifier)}`, {
- method: 'DELETE',
- })
- if (response.ok || response.status === 204) {
- isTraced.value = false
- traceStartedAt.value = null
- selectedMessage.value = null
- }
+ await fetch(`/api/v1/tr069-trace/${encodeURIComponent(device.identifier)}`, { method: 'DELETE' })
+ isTraced.value = false
} else {
const response = await fetch('/api/v1/tr069-trace', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ deviceId: device.identifier }),
})
- if (response.ok) {
- const data = await response.json()
- isTraced.value = true
- traceStartedAt.value = data.entry?.startedAt || new Date().toISOString()
- }
+ if (response.ok) isTraced.value = true
}
- } catch {
- // Silently ignore
- } finally {
- tracingAction.value = false
- }
+ } catch { /* ignore */ }
+ finally { tracingAction.value = false }
}
checkTraceStatus()
-function onMessageSelect(message: CwmpExchange | null) {
- selectedMessage.value = message
-}
-
-function deleteDevice() {
- router.delete(`/devices/${encodeURIComponent(device.identifier)}`, {
- onSuccess: () => router.visit('/devices'),
- })
+async function deleteDevice() {
+ await fetch(`/api/v1/devices/${encodeURIComponent(device.identifier)}`, { method: 'DELETE' })
+ router.visit('/')
}
const showGetModelPopup = ref(false)
const getModelInput = ref('')
@@ -147,8 +116,8 @@ function submitGetModel() {
const estimatedNextConnection = (() => {
const lastPeriodic = device.lastPeriodicInformAt
if (!lastPeriodic) return null
- const allParams = [...(device.properties || []), ...(device.parameters || [])]
- const intervalParam = allParams.find((p: any) => p.name?.includes('PeriodicInformInterval'))
+ const allParams = [...(device.properties || []), ...(device.parameters || [])].filter((p: any) => p && typeof p.name === 'string')
+ const intervalParam = allParams.find((p: any) => p.name.includes('PeriodicInformInterval'))
const intervalSeconds = intervalParam?.value ? parseInt(intervalParam.value, 10) : 0
if (!intervalSeconds || intervalSeconds <= 0) return null
const next = new Date(new Date(lastPeriodic).getTime() + intervalSeconds * 1000)
@@ -157,12 +126,11 @@ const estimatedNextConnection = (() => {
// Check if the device has a ConnectionRequestURL (needed for immediate mode / Refresh)
const hasConnectionRequestUrl = (() => {
- const allParams = [...(device.properties || []), ...(device.parameters || [])]
+ const allParams = [...(device.properties || []), ...(device.parameters || [])].filter((p: any) => p && typeof p.name === 'string')
const crUrl = allParams.find(
(p: any) =>
- p.name &&
- (p.name.endsWith('ManagementServer.ConnectionRequestURL') ||
- p.name.endsWith('.ConnectionRequestURL'))
+ p.name.endsWith('ManagementServer.ConnectionRequestURL') ||
+ p.name.endsWith('.ConnectionRequestURL')
)
return crUrl && crUrl.value && crUrl.value.trim() !== ''
})()
@@ -232,11 +200,6 @@ async function resolveAllProviders() {
Actions
-
-
- Échanges TR-069
-
-
{{ t('titles.commands') }}
@@ -426,7 +389,7 @@ async function resolveAllProviders() {
@@ -440,7 +403,7 @@ async function resolveAllProviders() {
-
+
|
|
{{ prop.type }} |
@@ -454,7 +417,7 @@ async function resolveAllProviders() {
@@ -468,7 +431,7 @@ async function resolveAllProviders() {
-
+
|
|
{{ param.type }} |
@@ -506,44 +469,28 @@ async function resolveAllProviders() {
-
-
-
-
+ Échanges TR-069
+
+
@@ -558,32 +505,6 @@ async function resolveAllProviders() {
-
-
-