Skip to content

Commit 9f0634e

Browse files
feat: NETRIS2 parser
1 parent d035df9 commit 9f0634e

37 files changed

+6507
-2923
lines changed

app/app.config.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,15 @@ export default defineAppConfig({
1010
link: ['cursor-pointer'],
1111
},
1212
},
13+
tabs: {
14+
slots: {
15+
trigger: ['cursor-pointer'],
16+
},
17+
},
18+
accordion: {
19+
slots: {
20+
trigger: ['cursor-pointer'],
21+
},
22+
},
1323
},
1424
})

app/app.vue

Lines changed: 62 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
<script setup lang="ts">
2+
import type { BreadcrumbItem } from '@nuxt/ui'
3+
24
useHead({
35
title: 'Home',
46
titleTemplate: 'WIKA IIoT Toolbox - %s',
@@ -9,22 +11,79 @@ useHead({
911
},
1012
],
1113
})
14+
15+
const { widget, category } = useWidget()
16+
17+
watch(widget, (newWidget) => {
18+
if (newWidget) {
19+
useHead({
20+
title: newWidget.name,
21+
})
22+
}
23+
else {
24+
useHead({
25+
title: 'Home',
26+
})
27+
}
28+
})
29+
30+
const breadcrumbs = computed<BreadcrumbItem[] | null>(() => {
31+
if (!category.value) {
32+
return null
33+
}
34+
const items = [] as BreadcrumbItem[]
35+
36+
items.push({
37+
label: category.value.name,
38+
icon: category.value.icon,
39+
to: category.value.to,
40+
})
41+
42+
if (widget.value) {
43+
items.push({
44+
label: widget.value.name,
45+
to: widget.value.to,
46+
})
47+
}
48+
return items
49+
})
1250
</script>
1351

1452
<template>
1553
<UApp>
1654
<div class="flex w-dvw h-dvh">
1755
<Sidebar
18-
class="h-full w-64 hidden md:flex"
56+
class="h-full w-64 hidden md:flex flex-shrink-0"
1957
/>
2058
<USeparator
2159
orientation="vertical"
2260
class="h-full"
2361
color="primary"
2462
/>
25-
<div class="flex flex-col grow h-full overflow-hidden px-4 py-2 gap-2">
63+
<div class="flex flex-col grow h-full overflow-hidden px-4 py-2 gap-2 min-w-0">
2664
<Header class="w-full my-2" />
27-
<NuxtPage />
65+
<div
66+
v-if="breadcrumbs"
67+
>
68+
<UBreadcrumb
69+
v-if="breadcrumbs"
70+
:items="breadcrumbs"
71+
/>
72+
<span
73+
class="text-muted text-sm font-mono"
74+
>
75+
{{ widget?.description ?? category!.description }}
76+
</span>
77+
</div>
78+
<UCard
79+
class="flex flex-col overflow-y-auto grow max-w-full"
80+
variant="soft"
81+
:ui="{
82+
body: 'p-2 px-2 sm:p-4 sm:px-6 grow',
83+
}"
84+
>
85+
<NuxtPage />
86+
</UCard>
2887
</div>
2988
</div>
3089
</UApp>

app/assets/css/main.css

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
@import "tailwindcss";
22
@import "@nuxt/ui";
3+
@plugin "@tailwindcss/typography";
4+
@config "./tailwind.config.js";
35

46
:root {
57

app/assets/css/tailwind.config.js

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/** @type {import('tailwindcss').Config} */
2+
module.exports = {
3+
theme: {
4+
extend: {
5+
typography: () => ({
6+
wika: {
7+
css: {
8+
'--tw-prose-body': 'var(--ui-text)',
9+
'--tw-prose-headings': 'var(--ui-text-highlighted)',
10+
'--tw-prose-lead': 'var(--ui-text-toned)',
11+
'--tw-prose-links': 'var(--ui-text-highlighted)',
12+
'--tw-prose-bold': 'var(--ui-text-highlighted)',
13+
'--tw-prose-counters': 'var(--ui-text-muted)',
14+
'--tw-prose-bullets': 'var(--ui-text-dimmed)',
15+
'--tw-prose-hr': 'var(--ui-border)',
16+
'--tw-prose-quotes': 'var(--ui-text-highlighted)',
17+
'--tw-prose-quote-borders': 'var(--ui-border-accented)',
18+
'--tw-prose-captions': 'var(--ui-text-muted)',
19+
'--tw-prose-kbd': 'var(--ui-text-highlighted)',
20+
'--tw-prose-kbd-shadows': 'var(--ui-bg-elevated)',
21+
'--tw-prose-code': 'var(--ui-text-highlighted)',
22+
'--tw-prose-pre-code': 'var(--ui-bg-inverted)',
23+
'--tw-prose-pre-bg': 'var(--ui-bg-accented)',
24+
'--tw-prose-th-borders': 'var(--ui-border-accented)',
25+
'--tw-prose-td-borders': 'var(--ui-border)',
26+
// For -invert- use the same as above so Tailwind handles color scheme automatically
27+
'--tw-prose-invert-body': 'var(--tw-prose-body)',
28+
'--tw-prose-invert-headings': 'var(--tw-prose-headings)',
29+
'--tw-prose-invert-lead': 'var(--tw-prose-lead)',
30+
'--tw-prose-invert-links': 'var(--tw-prose-links)',
31+
'--tw-prose-invert-bold': 'var(--tw-prose-bold)',
32+
'--tw-prose-invert-counters': 'var(--tw-prose-counters)',
33+
'--tw-prose-invert-bullets': 'var(--tw-prose-bullets)',
34+
'--tw-prose-invert-hr': 'var(--tw-prose-hr)',
35+
'--tw-prose-invert-quotes': 'var(--tw-prose-quotes)',
36+
'--tw-prose-invert-quote-borders': 'var(--tw-prose-quote-borders)',
37+
'--tw-prose-invert-captions': 'var(--tw-prose-captions)',
38+
'--tw-prose-invert-kbd': 'var(--tw-prose-kbd)',
39+
'--tw-prose-invert-kbd-shadows': 'var(--tw-prose-kbd-shadows)',
40+
'--tw-prose-invert-code': 'var(--tw-prose-code)',
41+
'--tw-prose-invert-pre-code': 'var(--tw-prose-pre-code)',
42+
'--tw-prose-invert-pre-bg': 'var(--tw-prose-pre-bg)',
43+
'--tw-prose-invert-th-borders': 'var(--tw-prose-th-borders)',
44+
'--tw-prose-invert-td-borders': 'var(--tw-prose-td-borders)',
45+
},
46+
},
47+
}),
48+
},
49+
},
50+
}

app/components/Code.vue

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<script setup lang="ts">
2+
type Props = {
3+
code: string
4+
}
5+
6+
defineProps<Props>()
7+
8+
const toast = useToast()
9+
10+
const {
11+
copy,
12+
} = useClipboard()
13+
14+
function copyToClipboard(text: string) {
15+
toast.clear()
16+
copy(text).then(() => {
17+
toast.add({
18+
title: 'Copied to clipboard',
19+
color: 'primary',
20+
icon: 'mdi:check',
21+
duration: 1500,
22+
})
23+
}).catch(() => {
24+
toast.add({
25+
title: 'Failed to copy',
26+
color: 'error',
27+
icon: 'mdi:alert',
28+
duration: 1500,
29+
})
30+
})
31+
}
32+
</script>
33+
34+
<template>
35+
<div class="relative w-full overflow-x-auto">
36+
<pre class="bg-elevated rounded p-2 text-xs text-default overflow-x-auto max-w-full">
37+
{{ code }}
38+
</pre>
39+
<UButton
40+
size="xs"
41+
color="primary"
42+
variant="soft"
43+
class="absolute top-2 right-2"
44+
icon="mdi:content-copy"
45+
@click="copyToClipboard(code)"
46+
/>
47+
</div>
48+
</template>

app/components/Decoder.vue

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
<script setup lang="ts">
2+
type Decoder = (input: { bytes: string, fPort: number }) => { data: object, warnings?: string[] } | { errors: string[] }
3+
4+
type OutputSuccess = { data: object, warnings?: string[] }
5+
type OutputFailure = { errors: string[] }
6+
type OutputWarnings = string[]
7+
type OutputErrors = string[]
8+
type Output = OutputSuccess | OutputFailure
9+
10+
type Props = {
11+
decodeHexUplink: Decoder
12+
}
13+
14+
const props = defineProps<Props>()
15+
16+
const hexString = useRouteQuery('hexString', '')
17+
18+
const decodeError = ref<OutputErrors | undefined>(undefined)
19+
const decodeWarning = ref<OutputWarnings | undefined>(undefined)
20+
const decodedResult = ref<Output | undefined>(undefined)
21+
const decodedData = computed<object | unknown[] | undefined>(() => {
22+
if (!decodedResult.value) return undefined
23+
if ('data' in decodedResult.value) {
24+
return decodedResult.value.data
25+
}
26+
return undefined
27+
})
28+
29+
function decodeHexString() {
30+
if (!hexString.value) {
31+
decodedResult.value = undefined
32+
decodeError.value = undefined
33+
return
34+
}
35+
decodeError.value = undefined
36+
// Use parser's decodeHexUplink for hex string
37+
// roundingDecimals is now handled outside, so do not set it here
38+
const result = props.decodeHexUplink({ bytes: hexString.value, fPort: 1 })
39+
decodedResult.value = result
40+
if ('errors' in result) {
41+
decodeError.value = result.errors as OutputErrors
42+
}
43+
else {
44+
decodeError.value = undefined
45+
}
46+
47+
if ('warnings' in result) {
48+
decodeWarning.value = result.warnings as OutputWarnings
49+
}
50+
else {
51+
decodeWarning.value = undefined
52+
}
53+
}
54+
watch(hexString, () => decodeHexString(), {
55+
immediate: true,
56+
})
57+
58+
defineExpose({
59+
decodeHexString,
60+
})
61+
</script>
62+
63+
<template>
64+
<TabLayout>
65+
<div class="flex flex-col w-full h-full gap-4">
66+
<div class="flex flex-col gap-2 grow">
67+
<UFormField label="Hexstring">
68+
<UTextarea
69+
v-model="hexString"
70+
class="max-w-96 w-full font-mono"
71+
:maxrows="3"
72+
73+
autoresize
74+
placeholder="Paste your hex string here"
75+
/>
76+
</UFormField>
77+
</div>
78+
</div>
79+
<template
80+
v-if="decodedResult"
81+
#aside
82+
>
83+
<DisplayResult
84+
:data="decodedData"
85+
:errors="decodeError"
86+
:warnings="decodeWarning"
87+
label="Decoded JSON"
88+
/>
89+
</template>
90+
</TabLayout>
91+
</template>

app/components/DisplayResult.vue

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<script setup lang="ts">
2+
type Props = {
3+
data?: object | unknown[]
4+
warnings?: string[]
5+
errors?: string[]
6+
label?: string
7+
}
8+
9+
const props = defineProps<Props>()
10+
11+
const stringifiedResult = computed(() => {
12+
return props.data ? JSON.stringify(props.data, null, 2) : ''
13+
})
14+
</script>
15+
16+
<template>
17+
<div class="flex flex-col overflow-x-auto">
18+
<label class="text-sm font-medium text-toned">{{ label ?? 'Result' }}</label>
19+
<Code
20+
v-if="data"
21+
class="w-full"
22+
:code="stringifiedResult"
23+
/>
24+
<div
25+
v-if="(errors && errors.length) || (warnings && warnings.length)"
26+
class="flex flex-col gap-1 mt-2"
27+
>
28+
<div
29+
v-if="errors && errors.length"
30+
class="text-error text-xs"
31+
>
32+
<span class="font-semibold">Errors:</span>
33+
<ul class="list-disc pl-5">
34+
<li
35+
v-for="(err, idx) in errors"
36+
:key="'err-' + idx"
37+
>
38+
{{ err }}
39+
</li>
40+
</ul>
41+
</div>
42+
<div
43+
v-if="warnings && warnings.length"
44+
class="text-warning text-xs"
45+
>
46+
<span class="font-semibold">Warnings:</span>
47+
<ul class="list-disc pl-5">
48+
<li
49+
v-for="(warn, idx) in warnings"
50+
:key="'warn-' + idx"
51+
>
52+
{{ warn }}
53+
</li>
54+
</ul>
55+
</div>
56+
</div>
57+
</div>
58+
</template>

0 commit comments

Comments
 (0)