From a19cc3fa4044444eb0d0ac3e20af770a404db662 Mon Sep 17 00:00:00 2001 From: vincenzocaruso Date: Wed, 25 Mar 2026 15:11:00 -0700 Subject: [PATCH 1/4] add aria label to missing tables --- .../deviceProperties/devicePropertiesPerInterface.tsx | 1 + .../deviceSettings/deviceSettingsPerInterface.tsx | 1 + .../shared/resizeDetailsList/resizableDetailsList.tsx | 10 ++++++++-- src/app/shared/utils/credentialStorage.ts | 8 +++----- src/localization/locales/en.json | 7 +++++-- src/localization/resourceKeys.ts | 11 +++++++---- 6 files changed, 25 insertions(+), 13 deletions(-) diff --git a/src/app/devices/pnp/components/deviceProperties/devicePropertiesPerInterface.tsx b/src/app/devices/pnp/components/deviceProperties/devicePropertiesPerInterface.tsx index 4f9cadde..9b0ebf2c 100644 --- a/src/app/devices/pnp/components/deviceProperties/devicePropertiesPerInterface.tsx +++ b/src/app/devices/pnp/components/deviceProperties/devicePropertiesPerInterface.tsx @@ -143,6 +143,7 @@ export const DevicePropertiesPerInterface: React.FC = items={props.twinAndSchema} columns={getColumns()} layoutMode={DetailsListLayoutMode.justified} + ariaLabel={t(ResourceKeys.deviceProperties.propertiesTableAriaLabel)} /> {showOverlay && } {createReportedValuePanel()} diff --git a/src/app/devices/pnp/components/deviceSettings/deviceSettingsPerInterface.tsx b/src/app/devices/pnp/components/deviceSettings/deviceSettingsPerInterface.tsx index f9f424dd..7cff106d 100644 --- a/src/app/devices/pnp/components/deviceSettings/deviceSettingsPerInterface.tsx +++ b/src/app/devices/pnp/components/deviceSettings/deviceSettingsPerInterface.tsx @@ -271,6 +271,7 @@ export const DeviceSettingsPerInterface: React.FC {createReportedValuePanel()} {showOverlay && } diff --git a/src/app/shared/resizeDetailsList/resizableDetailsList.tsx b/src/app/shared/resizeDetailsList/resizableDetailsList.tsx index c81c8439..4cb5dd71 100644 --- a/src/app/shared/resizeDetailsList/resizableDetailsList.tsx +++ b/src/app/shared/resizeDetailsList/resizableDetailsList.tsx @@ -8,10 +8,14 @@ import { ColumnActionsMode, ContextualMenu, DetailsList, IColumn, IContextualMen import { ResizeDetailsListDialog } from './dialog'; import { ResourceKeys } from '../../../localization/resourceKeys'; -export const ResizableDetailsList: React.FC = props => { +export interface ResizableDetailsListProps extends IDetailsListProps { + ariaLabel?: string; +} + +export const ResizableDetailsList: React.FC = props => { const { t } = useTranslation(); const { ariaLabelForSelectionColumn, ariaLabelForSelectAllCheckbox, checkButtonAriaLabel, - items, columns, selection, selectionMode, layoutMode, checkboxVisibility, className, onRenderItemColumn } = props; + items, columns, selection, selectionMode, layoutMode, checkboxVisibility, className, onRenderItemColumn, ariaLabel, ...restProps } = props; const [ isDialogHidden, setIsDialogHidden] = React.useState(true); const [ contextualMenuProps, setContextualMenuProps] = React.useState(undefined); @@ -60,6 +64,8 @@ export const ResizableDetailsList: React.FC = props => { selection={selection} selectionMode={selectionMode} onRenderItemColumn={onRenderItemColumn} + ariaLabelForGrid={ariaLabel || t(ResourceKeys.resizableDetailsList.defaultAriaLabel)} + {...restProps} /> {contextualMenuProps && } => { const serialized = JSON.stringify(value); - const credentialsApi = getCredentialsInterface(); try { + const credentialsApi = getCredentialsInterface(); const isAvailable = await credentialsApi.isEncryptionAvailable(); if (isAvailable) { await credentialsApi.store(CONN_STRINGS_KEY, serialized); @@ -38,9 +38,8 @@ export const storeConnectionStrings = async (value: ConnectionStringWithExpiry[] * with automatic migration from localStorage if needed. */ export const getConnectionStrings = async (): Promise => { - const credentialsApi = getCredentialsInterface(); - try { + const credentialsApi = getCredentialsInterface(); const isAvailable = await credentialsApi.isEncryptionAvailable(); if (isAvailable) { const encrypted = await credentialsApi.get(CONN_STRINGS_KEY); @@ -74,9 +73,8 @@ export const getConnectionStrings = async (): Promise => { - const credentialsApi = getCredentialsInterface(); - try { + const credentialsApi = getCredentialsInterface(); await credentialsApi.delete(CONN_STRINGS_KEY); } catch (error) { // tslint:disable-next-line: no-console diff --git a/src/localization/locales/en.json b/src/localization/locales/en.json index 4bf2e951..7a3bd510 100644 --- a/src/localization/locales/en.json +++ b/src/localization/locales/en.json @@ -50,7 +50,8 @@ "buttons": { "resize": "Resize", "cancel": "Cancel" - } + }, + "defaultAriaLabel": "Data table" }, "header": { "applicationName": "Azure IoT Explorer", @@ -481,6 +482,7 @@ }, "headerText": "Read-only properties", "noProperties": "ComponentName {{componentName}} contains no read-only property definitions", + "propertiesTableAriaLabel": "Device properties table with name, value, schema, and unit columns", "columns": { "name": "Name (Display Name / Description)", "value": "Value", @@ -525,7 +527,8 @@ }, "panel": { "title": "Reported value" - } + }, + "writablePropertiesTableAriaLabel": "Writable properties table with name, schema, unit, desired value, and reported value columns" }, "deviceCommands": { "command" : { diff --git a/src/localization/resourceKeys.ts b/src/localization/resourceKeys.ts index aad7ace9..6dce9570 100644 --- a/src/localization/resourceKeys.ts +++ b/src/localization/resourceKeys.ts @@ -1,5 +1,5 @@ -//// This code is generated by a tool -/* tslint:disable */ +//// This code is generated by a tool +/* tslint:disable */ export class ResourceKeys { public static authentication = { authSelection : { @@ -676,6 +676,7 @@ export class ResourceKeys { }, headerText : "deviceProperties.headerText", noProperties : "deviceProperties.noProperties", + propertiesTableAriaLabel : "deviceProperties.propertiesTableAriaLabel", }; public static deviceSettings = { ackStatus : { @@ -711,6 +712,7 @@ export class ResourceKeys { panel : { title : "deviceSettings.panel.title", }, + writablePropertiesTableAriaLabel : "deviceSettings.writablePropertiesTableAriaLabel", }; public static deviceTwin = { command : { @@ -1008,6 +1010,7 @@ export class ResourceKeys { subText : "resizableDetailsList.content.subText", title : "resizableDetailsList.content.title", }, + defaultAriaLabel : "resizableDetailsList.defaultAriaLabel", }; public static settings = { close : "settings.close", @@ -1056,5 +1059,5 @@ export class ResourceKeys { open : "template.collapse.open", }, }; -} -/* tslint:enable */ +} +/* tslint:enable */ From 1414bd7b0a205b4fe4388860c018cf074375be01 Mon Sep 17 00:00:00 2001 From: vincenzocaruso Date: Wed, 25 Mar 2026 16:41:37 -0700 Subject: [PATCH 2/4] updated snapshot --- .../__snapshots__/devicePropertiesPerInterface.spec.tsx.snap | 1 + .../__snapshots__/deviceSettingsPerInterface.spec.tsx.snap | 1 + .../__snapshots__/resizableDetailsList.spec.tsx.snap | 1 + 3 files changed, 3 insertions(+) diff --git a/src/app/devices/pnp/components/deviceProperties/__snapshots__/devicePropertiesPerInterface.spec.tsx.snap b/src/app/devices/pnp/components/deviceProperties/__snapshots__/devicePropertiesPerInterface.spec.tsx.snap index 958840bc..d320d0e2 100644 --- a/src/app/devices/pnp/components/deviceProperties/__snapshots__/devicePropertiesPerInterface.spec.tsx.snap +++ b/src/app/devices/pnp/components/deviceProperties/__snapshots__/devicePropertiesPerInterface.spec.tsx.snap @@ -8,6 +8,7 @@ exports[`devicePropertiesPerInterface matches snapshot 1`] = ` className="list-detail pnp-properties" > Date: Wed, 25 Mar 2026 18:33:35 -0700 Subject: [PATCH 3/4] fixed snapshot --- .../__snapshots__/devicePropertiesPerInterface.spec.tsx.snap | 2 +- .../__snapshots__/deviceSettingsPerInterface.spec.tsx.snap | 2 +- .../__snapshots__/resizableDetailsList.spec.tsx.snap | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/app/devices/pnp/components/deviceProperties/__snapshots__/devicePropertiesPerInterface.spec.tsx.snap b/src/app/devices/pnp/components/deviceProperties/__snapshots__/devicePropertiesPerInterface.spec.tsx.snap index d320d0e2..2d72ec61 100644 --- a/src/app/devices/pnp/components/deviceProperties/__snapshots__/devicePropertiesPerInterface.spec.tsx.snap +++ b/src/app/devices/pnp/components/deviceProperties/__snapshots__/devicePropertiesPerInterface.spec.tsx.snap @@ -8,7 +8,7 @@ exports[`devicePropertiesPerInterface matches snapshot 1`] = ` className="list-detail pnp-properties" > Date: Thu, 26 Mar 2026 11:13:43 -0700 Subject: [PATCH 4/4] fix rendering problem in case of malformed pnp template --- .../devices/shared/components/simpleReportedSection.tsx | 7 +++++-- src/localization/resourceKeys.ts | 8 ++++---- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/app/devices/shared/components/simpleReportedSection.tsx b/src/app/devices/shared/components/simpleReportedSection.tsx index a740731d..8f1440f3 100644 --- a/src/app/devices/shared/components/simpleReportedSection.tsx +++ b/src/app/devices/shared/components/simpleReportedSection.tsx @@ -3,7 +3,7 @@ * Licensed under the MIT License **********************************************************/ import * as React from 'react'; -import { Validator, ValidationError } from 'jsonschema'; +import { Validator, ValidationError, ValidatorResult } from 'jsonschema'; import { Label } from '@fluentui/react'; import { useTranslation } from 'react-i18next'; import { ParsedJsonSchema } from '../../../api/models/interfaceJsonParserOutput'; @@ -13,7 +13,10 @@ import { ResourceKeys } from '../../../../localization/resourceKeys'; // tslint:disable-next-line: cyclomatic-complexity export const RenderSimplyTypeValue = (twin: any, schema: ParsedJsonSchema, displayValue: any, desired: boolean=false) => { // tslint:disable-line:no-any const validator = new Validator(); - const result = validator.validate(twin, schema); + let result: ValidatorResult | undefined; + if((schema as any)['$id'] || (schema as any)['id']){ + result = validator.validate(twin, schema); + } const getDisplayValue = () => { if (typeof(twin) === 'object') { const twinCopy = { diff --git a/src/localization/resourceKeys.ts b/src/localization/resourceKeys.ts index 6dce9570..187baf9b 100644 --- a/src/localization/resourceKeys.ts +++ b/src/localization/resourceKeys.ts @@ -1,5 +1,5 @@ -//// This code is generated by a tool -/* tslint:disable */ +//// This code is generated by a tool +/* tslint:disable */ export class ResourceKeys { public static authentication = { authSelection : { @@ -1059,5 +1059,5 @@ export class ResourceKeys { open : "template.collapse.open", }, }; -} -/* tslint:enable */ +} +/* tslint:enable */