Skip to content

Commit e5f27dd

Browse files
authored
Merge pull request #455
feat(22339): Remove hardcoded uiSchema from UI * chore(22339): update openAPI specs and stubs * feat(22339): remove the hardcoded uiSchema * feat(22339): add uiSchema defaults * feat(22339): extract uiSchema from adapter config * fix(22339): fix default uiSchema * fix(22339): fix adapter uiSchema * fix(22339): fix adapter uiSchema * test(22339): fix mocks * refactor(22339): refactor the handling of required uiSchema properties * test(22339): add test
1 parent 0795a77 commit e5f27dd

File tree

17 files changed

+5304
-273
lines changed

17 files changed

+5304
-273
lines changed

ext/hivemq-edge-openapi-2024.5.yaml

Lines changed: 5155 additions & 0 deletions
Large diffs are not rendered by default.

hivemq-edge/src/frontend/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
"lint:prettier:write": "prettier --write .",
1212
"lint:stylelint": "stylelint './src/**/*.css'",
1313
"lint:all": "eslint src --ext ts,tsx --report-unused-disable-directives --max-warnings 0 && prettier --check .",
14-
"dev:openAPI": "openapi --input '../../../../hivemq-edge/ext/hivemq-edge-openapi-2024.4.yaml' -o ./src/api/__generated__ -c axios --name HiveMqClient --exportSchemas true",
14+
"dev:openAPI": "openapi --input '../../../../hivemq-edge/ext/hivemq-edge-openapi-2024.5.yaml' -o ./src/api/__generated__ -c axios --name HiveMqClient --exportSchemas true",
1515
"dev:chakra:types": "chakra-cli tokens './src/modules/Theme/themeHiveMQ.ts' --out 'node_modules/.pnpm/@[email protected]/node_modules/@chakra-ui/styled-system/dist/theming.types.d.ts'",
1616
"cypress:open": "cypress open",
1717
"cypress:open:component": "cypress open --component --browser chrome",

hivemq-edge/src/frontend/src/api/__generated__/models/ProtocolAdapter.ts

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

hivemq-edge/src/frontend/src/api/__generated__/schemas/$ProtocolAdapter.ts

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

hivemq-edge/src/frontend/src/api/hooks/useProtocolAdapters/__handlers__/index.ts

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,43 @@
1-
import { Adapter, AdaptersList, JsonNode, ProtocolAdapter, ProtocolAdaptersList, Status } from '@/api/__generated__'
21
import { http, HttpResponse } from 'msw'
2+
import { UiSchema } from '@rjsf/utils'
3+
34
import { MOCK_TOPIC_REF1, MOCK_TOPIC_REF2 } from '@/__test-utils__/react-flow/topics.ts'
45
import { MOCK_ADAPTER_ID } from '@/__test-utils__/mocks.ts'
6+
import { Adapter, AdaptersList, JsonNode, ProtocolAdapter, ProtocolAdaptersList, Status } from '@/api/__generated__'
7+
8+
export const mockUISchema: UiSchema = {
9+
'ui:tabs': [
10+
{
11+
id: 'coreFields',
12+
title: 'Settings',
13+
properties: ['id'],
14+
},
15+
{
16+
id: 'subFields',
17+
title: 'Subscription',
18+
properties: ['subscriptions'],
19+
},
20+
{
21+
id: 'publishing',
22+
title: 'Publishing',
23+
properties: ['maxPollingErrorsBeforeRemoval', 'pollingIntervalMillis', 'minValue', 'maxValue'],
24+
},
25+
],
26+
'ui:submitButtonOptions': {
27+
norender: true,
28+
},
29+
id: {
30+
'ui:disabled': false,
31+
},
32+
subscriptions: {
33+
items: {
34+
'ui:order': ['destination', 'qos', '*'],
35+
'ui:collapsable': {
36+
titleKey: 'destination',
37+
},
38+
},
39+
},
40+
}
541

642
export const mockJSONSchema: JsonNode = {
743
$schema: 'https://json-schema.org/draft/2020-12/schema',
@@ -65,6 +101,7 @@ export const mockProtocolAdapter: ProtocolAdapter = {
65101
logoUrl: 'http://localhost:8080/images/hivemq-icon.png',
66102
author: 'HiveMQ',
67103
configSchema: mockJSONSchema,
104+
uiSchema: mockUISchema,
68105
installed: true,
69106
category: {
70107
description: 'Industrial, typically field bus protocols.',

hivemq-edge/src/frontend/src/modules/ProtocolAdapters/components/drawers/AdapterInstanceDrawer.tsx

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
11
import { FC, useMemo } from 'react'
2+
import { useTranslation } from 'react-i18next'
3+
import { useParams } from 'react-router-dom'
4+
import { IChangeEvent } from '@rjsf/core'
5+
import { RJSFSchema } from '@rjsf/utils'
6+
import { RJSFValidationError } from '@rjsf/utils/src/types.ts'
7+
import Form from '@rjsf/chakra-ui'
28
import {
39
Button,
410
Drawer,
@@ -13,11 +19,6 @@ import {
1319
Image,
1420
Text,
1521
} from '@chakra-ui/react'
16-
import { useTranslation } from 'react-i18next'
17-
import { useParams } from 'react-router-dom'
18-
import { IChangeEvent } from '@rjsf/core'
19-
import { RJSFSchema } from '@rjsf/utils'
20-
import Form from '@rjsf/chakra-ui'
2122

2223
import { Adapter, ApiError, ProtocolAdapter } from '@/api/__generated__'
2324
import { useGetAdapterTypes } from '@/api/hooks/useProtocolAdapters/useGetAdapterTypes.ts'
@@ -29,9 +30,8 @@ import { ObjectFieldTemplate } from '@/components/rjsf/ObjectFieldTemplate.tsx'
2930
import { BaseInputTemplate } from '@/components/rjsf/BaseInputTemplate.tsx'
3031
import { ArrayFieldTemplate } from '@/components/rjsf/ArrayFieldTemplate.tsx'
3132
import { ArrayFieldItemTemplate } from '@/components/rjsf/ArrayFieldItemTemplate.tsx'
32-
import useGetUiSchema from '../../hooks/useGetUISchema.ts'
33-
import { customFormatsValidator, customValidate } from '../../utils/validation-utils.ts'
34-
import { RJSFValidationError } from '@rjsf/utils/src/types.ts'
33+
import { customFormatsValidator, customValidate } from '@/modules/ProtocolAdapters/utils/validation-utils.ts'
34+
import { getRequiredUiSchema } from '@/modules/ProtocolAdapters/utils/uiSchema.utils.ts'
3535

3636
interface AdapterInstanceDrawerProps {
3737
adapterType?: string
@@ -56,18 +56,22 @@ const AdapterInstanceDrawer: FC<AdapterInstanceDrawerProps> = ({
5656
const { data: allAdapters } = useListProtocolAdapters()
5757
const { adapterId } = useParams()
5858

59-
const { schema, name, logo } = useMemo(() => {
59+
const { schema, uiSchema, name, logo } = useMemo(() => {
6060
const adapter: ProtocolAdapter | undefined = data?.items?.find((e) => e.id === adapterType)
61-
const { configSchema } = adapter || {}
62-
return { schema: configSchema, name: adapter?.name, logo: adapter?.logoUrl }
63-
}, [data, adapterType])
61+
const { configSchema, uiSchema } = adapter || {}
62+
return {
63+
schema: configSchema,
64+
name: adapter?.name,
65+
logo: adapter?.logoUrl,
66+
uiSchema: getRequiredUiSchema(uiSchema, isNewAdapter),
67+
}
68+
}, [data?.items, isNewAdapter, adapterType])
6469

6570
const defaultValues = useMemo(() => {
6671
if (isNewAdapter || !adapterId) return undefined
6772
const { config } = allAdapters?.find((e) => e.id === adapterId) || {}
6873
return config
6974
}, [allAdapters, adapterId, isNewAdapter])
70-
const uiSchema = useGetUiSchema(isNewAdapter)
7175

7276
const onValidate = (data: IChangeEvent<Adapter, RJSFSchema>) => {
7377
if (data.formData) onSubmit(data.formData)

hivemq-edge/src/frontend/src/modules/ProtocolAdapters/hooks/useGetUISchema.spec.ts

Lines changed: 0 additions & 22 deletions
This file was deleted.

hivemq-edge/src/frontend/src/modules/ProtocolAdapters/hooks/useGetUISchema.ts

Lines changed: 0 additions & 127 deletions
This file was deleted.
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { describe, expect } from 'vitest'
2+
3+
import { getRequiredUiSchema } from '@/modules/ProtocolAdapters/utils/uiSchema.utils.ts'
4+
import { UiSchema } from '@rjsf/utils'
5+
6+
describe('getRequiredUiSchema', () => {
7+
it('should return the mandatory properties ', () => {
8+
expect(getRequiredUiSchema(undefined, true)).toStrictEqual(
9+
expect.objectContaining({
10+
id: {
11+
'ui:disabled': false,
12+
},
13+
'ui:submitButtonOptions': {
14+
norender: true,
15+
},
16+
})
17+
)
18+
expect(getRequiredUiSchema(undefined, false)).toStrictEqual(
19+
expect.objectContaining({
20+
id: {
21+
'ui:disabled': true,
22+
},
23+
'ui:submitButtonOptions': {
24+
norender: true,
25+
},
26+
})
27+
)
28+
})
29+
30+
it('should merge adapter with mandatory properties', () => {
31+
const uiSchema: UiSchema = {
32+
id: {
33+
'ui:disabled': true,
34+
title: 'new title',
35+
},
36+
'ui:submitButtonOptions': {
37+
norender: false,
38+
submitText: 'Submit',
39+
},
40+
test: {
41+
'ui:disabled': true,
42+
},
43+
}
44+
45+
expect(getRequiredUiSchema(uiSchema, true)).toStrictEqual({
46+
test: {
47+
'ui:disabled': true,
48+
},
49+
id: {
50+
title: 'new title',
51+
'ui:disabled': false,
52+
},
53+
'ui:submitButtonOptions': {
54+
norender: true,
55+
submitText: 'Submit',
56+
},
57+
})
58+
})
59+
})
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { UiSchema } from '@rjsf/utils'
2+
3+
export const getRequiredUiSchema = (uiSchema: UiSchema | undefined, isNewAdapter: boolean): UiSchema => {
4+
const { ['ui:submitButtonOptions']: submitButtonOptions, id, ...rest } = uiSchema || {}
5+
return {
6+
'ui:submitButtonOptions': {
7+
// required to relocate the submit button outside the form
8+
...submitButtonOptions,
9+
norender: true,
10+
},
11+
id: {
12+
// required to prevent custom validation when editing an existing adapter
13+
...id,
14+
'ui:disabled': !isNewAdapter,
15+
},
16+
...rest,
17+
}
18+
}

0 commit comments

Comments
 (0)