Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
a11fa47
core: frontend: Add a vue-tsc type-check script and bump TypeScript t…
Williangalvani Aug 6, 2026
397d643
core: frontend: fix vuex-module-decorators typing under TypeScript 5
Williangalvani Jul 8, 2026
cfca3e6
core: frontend: fix asset module shim type errors
Williangalvani Jul 8, 2026
cdd1519
core: frontend: fix calibration preflight lookup object typing
Williangalvani Jul 8, 2026
70851a0
core: frontend: type VersionCard image prop as Version
Williangalvani Jul 8, 2026
2580ffc
core: frontend: fix QueryTarget.BestMatching typo in zenoh queries
Williangalvani Jul 8, 2026
9c7c7fa
core: frontend: remove broken v-bind="attrs" in Network skeleton loader
Williangalvani Jul 8, 2026
07604b3
frontend: fix vue type augmentation resolution under bundler moduleRe…
Williangalvani Jul 8, 2026
504d7b3
frontend: add third-party type declarations for type-checking
Williangalvani Jul 8, 2026
0499bfe
frontend: fix missing globals, namespaced imports and Dictionary type
Williangalvani Jul 8, 2026
b1e3977
frontend: correctly type GpsTrayMenu fix_type enum access
Williangalvani Jul 8, 2026
b45f54d
frontend: type serial udev_properties as a string map
Williangalvani Jul 8, 2026
c9d3d09
frontend: fix extension memory/disk metric typing
Williangalvani Jul 8, 2026
339099f
frontend: use :input-value on array-mode v-checkboxes
Williangalvani Jul 8, 2026
c092f71
frontend: annotate implicit-any params and narrow caught axios errors
Williangalvani Jul 8, 2026
279ca33
frontend: guard optional progress totals and nullable image sha
Williangalvani Jul 8, 2026
7b3b754
frontend: fix null-safety and numeric handling in vehicle setup views
Williangalvani Jul 8, 2026
35de858
frontend: resolve vue/types/options augmentation for the router/vueti…
Williangalvani Jul 8, 2026
b5c034f
frontend: fix WeakRef deref, banner return type and metadata cast
Williangalvani Jul 8, 2026
5d349d5
frontend: type vue-tour $tours and drop this from a param default
Williangalvani Jul 8, 2026
6a08f70
frontend: correct DHCP details return type and Wizard ref/bind types
Williangalvani Jul 8, 2026
221aab0
frontend: type servo param keys, model annotations and frame name lookup
Williangalvani Jul 8, 2026
bcef289
frontend: type cytoscape elements, layout and style in ZenohNetwork
Williangalvani Jul 8, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified core/frontend/bun.lockb
Binary file not shown.
5 changes: 4 additions & 1 deletion core/frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"build": "NODE_ENV=production vite build",
"serve": "echo 'This is a preview server for testing the built website. Please use `dev` command over `serve`.\nStarting preview server in 5 seconds..\n';sleep 5; vite preview",
"lint": "eslint --max-warnings=0 --ext .js,.vue --ignore-path .gitignore --ignore-pattern src/components/vue-tour src && stylelint 'src/**/*.{vue,css,scss}'",
"type-check": "vue-tsc --noEmit",
"lint:css": "stylelint 'src/**/*.{vue,css,scss}'",
"lint:css:fix": "stylelint 'src/**/*.{vue,css,scss}' --fix"
},
Expand Down Expand Up @@ -77,6 +78,7 @@
"wifi-qr-code-generator": "^1.1.1"
},
"devDependencies": {
"@types/three": "0.156.0",
"@typescript-eslint/eslint-plugin": "^5.51.0",
"@typescript-eslint/parser": "^5.51.0",
"@vitejs/plugin-vue": "^1.6.1",
Expand All @@ -96,14 +98,15 @@
"stylelint-config-recommended-vue": "^1.6.1",
"stylelint-config-standard": "^40.0.0",
"stylelint-config-standard-scss": "^17.0.0",
"typescript": "~4.9.5",
"typescript": "5.4.5",
"unplugin-vue-components": "^0.25.2",
"vite": "3",
"vite-plugin-compression": "^0.5.1",
"vite-plugin-pwa": "^0.16.5",
"vite-plugin-wasm": "^3.4.1",
"vue-cli-plugin-vuetify": "~2.4.1",
"vue-template-babel-compiler": "^2.0.0",
"vue-tsc": "2.0.29",
"vuetify-loader": "^1.7.0",
"workbox-build": "7.0.0"
}
Expand Down
4 changes: 2 additions & 2 deletions core/frontend/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@
<v-checkbox
v-for="(name, index) in topWidgetsName"
:key="index"
v-model="selected_widgets"
:input-value="selected_widgets"
:label="name"
:value="name"
class="pa-0 pl-3 ma-0"
@change="settings.user_top_widgets = selected_widgets"
@change="selected_widgets = $event; settings.user_top_widgets = $event"
/>
</v-list>
</v-card>
Expand Down
2 changes: 1 addition & 1 deletion core/frontend/src/components/app/VehicleBanner.vue
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ export default Vue.extend({
}
},
async load_company_logo() {
this.logo_image = (await bag.getData('vehicle.logo_image_path'))?.url as (string | undefined)
this.logo_image = (await bag.getData('vehicle.logo_image_path'))?.url as string | undefined ?? null
if (this.logo_image && !this.logo_image.startsWith('/')) {
this.logo_image = `/${this.vehicle_image}`
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,8 @@ import { OneMoreTime } from '@/one-more-time'
import autopilot from '@/store/autopilot_manager'
import system_information from '@/store/system-information'
import { SerialEndpoint } from '@/types/autopilot'
import { Dictionary, JSONValue } from '@/types/common'
import { Dictionary } from '@/types/common'
import { UdevProperties } from '@/types/system-information/serial'
import back_axios from '@/utils/api'
import { isIpAddress } from '@/utils/pattern_validators'

Expand All @@ -119,7 +120,7 @@ export default Vue.extend({
G: 'Serial 6',
H: 'Serial 7',
I: 'Serial 8',
},
} as Record<string, string>,
ports: {} as Dictionary<string | undefined>,
fetch_autopilot_serial_config_task: new OneMoreTime({ delay: 10000, disposeWith: this }),
fetch_serial_task: new OneMoreTime({ delay: 10000, disposeWith: this }),
Expand Down Expand Up @@ -166,7 +167,7 @@ export default Vue.extend({
const names = [device, driver, serial].filter((name) => name !== undefined)
return names.join(' - ')
},
deviceInfo(path: string): JSONValue {
deviceInfo(path: string): UdevProperties {
return system_information.serial?.ports?.find((port) => port.by_path === path)?.udev_properties ?? {}
},
update_ports(new_ports: SerialEndpoint[]) {
Expand Down
4 changes: 2 additions & 2 deletions core/frontend/src/components/bridges/BridgeCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,9 @@
</p>
<p class="subtitle-1 text-center ma-0">
Info:
{{ bridgeSerialInfo.serial_info.udev_properties["ID_VENDOR"] }}
{{ bridgeSerialInfo.serial_info.udev_properties?.["ID_VENDOR"] }}
/
{{ bridgeSerialInfo.serial_info.udev_properties["ID_MODEL"] }}
{{ bridgeSerialInfo.serial_info.udev_properties?.["ID_MODEL"] }}
</p>
</div></span>
</v-tooltip>
Expand Down
10 changes: 8 additions & 2 deletions core/frontend/src/components/bridges/BridgeCreationDialog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@
no-data-text="No serial ports available"
:loading="updating_serial_ports"
item-text="name"
:item-value="(item) => item.by_path ? item.by_path : item.name"
:item-disabled="(item) => item.current_user !== null"
:item-value="serial_port_value"
:item-disabled="is_serial_port_in_use"
dense
>
<template #item="{ item }">
Expand Down Expand Up @@ -272,6 +272,12 @@ export default Vue.extend({
const creation_date = new Date(creation_time)
return `${formatDistanceToNow(creation_time)} ago (${creation_date.toLocaleTimeString()})`
},
serial_port_value(item: SerialPortInfo): string {
return item.by_path ? item.by_path : item.name
},
is_serial_port_in_use(item: SerialPortInfo): boolean {
return item.current_user !== null
},
validate_required_field(input: string | number): (true | string) {
const string_input = String(input)
return isNotEmpty(string_input) ? true : 'Required field.'
Expand Down
2 changes: 1 addition & 1 deletion core/frontend/src/components/cloud/CloudTrayMenu.vue
Original file line number Diff line number Diff line change
Expand Up @@ -448,7 +448,7 @@ export default Vue.extend({

try {
const receiver = await this.file_sync_session.get(topic, {
target: QueryTarget.BestMatching,
target: QueryTarget.BEST_MATCHING,
})

if (!receiver) {
Expand Down
2 changes: 1 addition & 1 deletion core/frontend/src/components/ethernet/InterfaceCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,7 @@ export default Vue.extend({
this.loading_leases = true
try {
const response = await ethernet.getDHCPServerDetails(this.adapter.name)
this.dhcp_server_details = response.data[this.adapter.name] as DHCPServerDetails
this.dhcp_server_details = response[this.adapter.name]
this.dhcp_server_details.leases = this.dhcp_server_details?.leases.map((lease: DHCPServerLease) => ({
...lease,
expires_at: lease.expires_at ? new Date(lease.expires_at) : undefined,
Expand Down
26 changes: 14 additions & 12 deletions core/frontend/src/components/health/GpsTrayMenu.vue
Original file line number Diff line number Diff line change
Expand Up @@ -82,12 +82,9 @@ import Vue, { markRaw } from 'vue'

import mavlink2rest from '@/libs/MAVLink2Rest'
import Listener from '@/libs/MAVLink2Rest/Listener'
import { Type } from '@/libs/MAVLink2Rest/mavlink2rest-ts/messages/mavlink2rest'
import { GpsFixType } from '@/libs/MAVLink2Rest/mavlink2rest-ts/messages/mavlink2rest-enum'
import {
GlobalPositionInt,
Gps2Raw,
GpsRawInt,
} from '@/libs/MAVLink2Rest/mavlink2rest-ts/messages/mavlink2rest-message'
import { Message } from '@/libs/MAVLink2Rest/mavlink2rest-ts/messages/mavlink2rest-message'
import autopilot_data from '@/store/autopilot'

export default Vue.extend({
Expand All @@ -104,12 +101,17 @@ export default Vue.extend({
time_limit_message: 20000,
last_message_date: undefined as undefined | Date,
gps_detected: false,
global_position_int: undefined as undefined | GlobalPositionInt,
gps_raw_int: undefined as undefined | GpsRawInt,
global_position_int: undefined as undefined | Message.GlobalPositionInt,
gps_raw_int: undefined as undefined | Message.GpsRawInt | Message.Gps2Raw,
listeners: [] as Listener[],
}
},
computed: {
fix_type(): GpsFixType | undefined {
// mavlink2rest wraps enum fields as { type: <enum> } at runtime.
const fix_type = this.gps_raw_int?.fix_type as Type<GpsFixType> | undefined
return fix_type?.type
},
values():
Array<
{
Expand Down Expand Up @@ -211,7 +213,7 @@ export default Vue.extend({
return this.gps_detected
},
connection_description(): string {
switch (this.gps_raw_int?.fix_type?.type) {
switch (this.fix_type) {
case GpsFixType.GPS_FIX_TYPE_NO_GPS:
return 'No GPS connection'
case GpsFixType.GPS_FIX_TYPE_NO_FIX:
Expand All @@ -235,7 +237,7 @@ export default Vue.extend({
}
},
number_color(): string {
switch (this.gps_raw_int?.fix_type?.type) {
switch (this.fix_type) {
case GpsFixType.GPS_FIX_TYPE_NO_FIX:
return 'warning'
case GpsFixType.GPS_FIX_TYPE_2D_FIX:
Expand Down Expand Up @@ -276,7 +278,7 @@ export default Vue.extend({
}

this.last_message_date = new Date()
this.global_position_int = message?.message as GlobalPositionInt
this.global_position_int = message?.message as Message.GlobalPositionInt
}).setFrequency(0)),
)

Expand All @@ -288,8 +290,8 @@ export default Vue.extend({
}

this.last_message_date = new Date()
this.gps_raw_int = message?.message as GpsRawInt | Gps2Raw
this.gps_detected = this.gps_raw_int?.fix_type?.type !== GpsFixType.GPS_FIX_TYPE_NO_GPS
this.gps_raw_int = message?.message as Message.GpsRawInt | Message.Gps2Raw
this.gps_detected = this.fix_type !== GpsFixType.GPS_FIX_TYPE_NO_GPS
}).setFrequency(0)),
)
},
Expand Down
12 changes: 8 additions & 4 deletions core/frontend/src/components/kraken/BackAlleyTab.vue
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,11 @@
style="height: 30px !important;"
>
<v-checkbox
v-model="filter_by_selected_companies"
:input-value="filter_by_selected_companies"
:label="company"
:value="company"
class="pa-0 pl-3 ma-0"
@change="filter_by_selected_companies = $event"
/>
</v-card-text>
</div>
Expand All @@ -85,10 +86,11 @@
<template #default="{ item }">
<v-card-text class="pt-2">
<v-checkbox
v-model="filter_by_selected_companies"
:input-value="filter_by_selected_companies"
:label="item"
:value="item"
class="pa-0 pl-3 ma-0"
@change="filter_by_selected_companies = $event"
/>
</v-card-text>
</template>
Expand All @@ -113,10 +115,11 @@
style="height: 30px !important;"
>
<v-checkbox
v-model="filter_by_selected_types"
:input-value="filter_by_selected_types"
:label="category"
:value="category"
class="pa-0 pl-3 ma-0"
@change="filter_by_selected_types = $event"
/>
</v-card-text>
</div>
Expand All @@ -129,10 +132,11 @@
<template #default="{ item }">
<v-card-text class="pt-2">
<v-checkbox
v-model="filter_by_selected_types"
:input-value="filter_by_selected_types"
:label="item"
:value="item"
class="pa-0 pl-3 ma-0"
@change="filter_by_selected_types = $event"
/>
</v-card-text>
</template>
Expand Down
2 changes: 1 addition & 1 deletion core/frontend/src/components/kraken/KrakenManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,7 @@ export async function finalizeExtension(
*/
export async function getHistoricalLogsForExtension(identifier: string, timeout: number): Promise<any | null> {
const queryKey = `kraken/extension/logs/request?extension_name=${identifier}`
return await zenoh.query(queryKey, QueryTarget.BestMatching, timeout)
return await zenoh.query(queryKey, QueryTarget.BEST_MATCHING, timeout)
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,8 @@
v-if="loading || extension.enabled && !container"
size="20px"
/>
<strong v-else-if="getMemoryUsage()?.toFixed">
{{ prettifySize(getMemoryUsage() * getMemoryLimit() * 100) }} /
{{ prettifySize(getMemoryLimit() * total_memory * 0.01) }}
<strong v-else-if="memory_usage_text">
{{ memory_usage_text }}
</strong>
<strong v-else>
N/A
Expand All @@ -129,9 +128,8 @@
v-if="loading || extension.enabled && !container"
size="20px"
/>
<strong v-else-if="getDiskUsage()?.toFixed">
{{ prettifySize(getDiskUsage() * main_disk_size * 0.01) }} /
{{ prettifySize(main_disk_size) }}
<strong v-else-if="disk_usage_text">
{{ disk_usage_text }}
</strong>
<strong v-else>
N/A
Expand Down Expand Up @@ -260,7 +258,7 @@ export default Vue.extend({
default: false,
},
metrics: {
type: Object as PropType<{cpu: number, memory: string}>,
type: Object as PropType<{ cpu: number, memory: number | string, disk: number | string }>,
required: true,
},
container: {
Expand Down Expand Up @@ -296,6 +294,21 @@ export default Vue.extend({
const value = this.main_disk?.total_space_B ?? 0
return value / 1024 // Move to kB
},
memory_usage_text(): string | null {
const usage = this.getMemoryUsage()
const limit = this.getMemoryLimit()
if (typeof usage !== 'number' || limit === undefined || this.total_memory === undefined) {
return null
}
return `${this.prettifySize(usage * limit * 100)} / ${this.prettifySize(limit * this.total_memory * 0.01)}`
},
disk_usage_text(): string | null {
const usage = this.getDiskUsage()
if (typeof usage !== 'number') {
return null
}
return `${this.prettifySize(usage * this.main_disk_size * 0.01)} / ${this.prettifySize(this.main_disk_size)}`
},
buttonBgColor() {
return settings.is_dark_theme ? '#20455e' : '#BDE0F0'
},
Expand Down Expand Up @@ -343,10 +356,10 @@ export default Vue.extend({
getCpuUsage(): number {
return this.metrics?.cpu
},
getMemoryUsage(): string {
getMemoryUsage(): number | string {
return this.metrics?.memory
},
getDiskUsage(): string {
getDiskUsage(): number | string {
return this.metrics?.disk
},
getMemoryLimit(): number | undefined {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,8 @@ export default Vue.extend({

this.fetchManifestsSources()
} catch (error) {
if (error.response?.status === 502) {
const axios_error = error as { response?: { status?: number } }
if (axios_error.response?.status === 502) {
this.is_operation_url_invalid = true
return
}
Expand Down Expand Up @@ -356,7 +357,8 @@ export default Vue.extend({

this.fetchManifestsSources()
} catch (error) {
if (error.response?.status === 502) {
const axios_error = error as { response?: { status?: number } }
if (axios_error.response?.status === 502) {
this.is_operation_url_invalid = true
return
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,14 @@
<v-checkbox
v-for="(key, keyvalue) in param.bitmask"
:key="keyvalue"
v-model="selected_bitflags"
:input-value="selected_bitflags"
dense
hide-details
:loading="waiting_for_param_update"
:label="key"
:value="2 ** keyvalue"
:disabled="disabled"
@change="selected_bitflags = $event"
/>
</template>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
:sort-by="'name'"
disable-sort
:custom-filter="() => true"
:item-class="(value) => value.item?.readonly ? undefined : 'hand-cursor'"
@click:row="(value) => editParam(value.item)"
:item-class="rowClass"
@click:row="onRowClick"
>
<v-progress-linear
slot="progress"
Expand Down Expand Up @@ -247,6 +247,12 @@ export default Vue.extend({
this.edited_param = param
this.edit_dialog = true
},
rowClass(value: { item?: Parameter }): string | undefined {
return value.item?.readonly ? undefined : 'hand-cursor'
},
onRowClick(value: { item: Parameter }) {
this.editParam(value.item)
},
printMark(item: Fuse.FuseResult<Record<string, string>>, key: string): string {
const name = item.item[key]
const indices_array = item?.matches?.find((i: Fuse.FuseResultMatch) => i.key === key)?.indices ?? []
Expand Down
Loading
Loading