From 947a07cf3e86d9332135bb65d99c3c67a7a99ab1 Mon Sep 17 00:00:00 2001 From: TheZoker Date: Mon, 27 Feb 2023 22:13:34 +0000 Subject: [PATCH 01/13] Transform CategorizationRenderer from class to functional --- .../categorization/CategorizationRenderer.tsx | 114 +++++++++--------- 1 file changed, 54 insertions(+), 60 deletions(-) diff --git a/packages/vanilla-renderers/src/complex/categorization/CategorizationRenderer.tsx b/packages/vanilla-renderers/src/complex/categorization/CategorizationRenderer.tsx index ada4ffc417..534ed10644 100644 --- a/packages/vanilla-renderers/src/complex/categorization/CategorizationRenderer.tsx +++ b/packages/vanilla-renderers/src/complex/categorization/CategorizationRenderer.tsx @@ -22,10 +22,9 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -import React from 'react'; +import React, { useState } from 'react'; import type { Categorization, Category, LayoutProps } from '@jsonforms/core'; import { - RendererComponent, TranslateProps, withJsonFormsLayoutProps, withTranslateProps, @@ -40,70 +39,65 @@ export interface CategorizationState { selectedCategory: Category; } -class CategorizationRenderer extends RendererComponent< - LayoutProps & VanillaRendererProps & TranslateProps, - CategorizationState -> { - onCategorySelected = (category: Category) => () => { - return this.setState({ selectedCategory: category }); - }; - - /** - * @inheritDoc - */ - render() { - const { uischema, visible, getStyleAsClassName, t } = this.props; - const categorization = uischema as Categorization; - const classNames = getStyleAsClassName('categorization'); - const masterClassNames = getStyleAsClassName('categorization.master'); - const detailClassNames = getStyleAsClassName('categorization.detail'); - const selectedCategory = this.findCategory(categorization); - const subcategoriesClassName = getStyleAsClassName( - 'category.subcategories' - ); - const groupClassName = getStyleAsClassName('category.group'); - - return ( - - ); - } - - private findCategory(categorization: Categorization): Category { +export const CategorizationRenderer = ({ + uischema, + schema, + path, + t, + visible, + getStyleAsClassName, +}: LayoutProps & VanillaRendererProps & TranslateProps) => { + const findCategory = (categorization: Categorization): Category => { const category = categorization.elements[0]; - if (this.state && this.state.selectedCategory) { - return this.state.selectedCategory; - } - if (isCategorization(category)) { - return this.findCategory(category); + return findCategory(category); } return category; - } -} + }; + + const categorization = uischema as Categorization; + const classNames = getStyleAsClassName('categorization'); + const masterClassNames = getStyleAsClassName('categorization.master'); + const detailClassNames = getStyleAsClassName('categorization.detail'); + const subcategoriesClassName = getStyleAsClassName('category.subcategories'); + const groupClassName = getStyleAsClassName('category.group'); + + const [selectedCategory, setSelectedCategory] = useState( + findCategory(categorization) + ); + + const onCategorySelected = (category: Category) => () => { + return setSelectedCategory(category); + }; + + return ( + + ); +}; export default withVanillaControlProps( withTranslateProps(withJsonFormsLayoutProps(CategorizationRenderer)) From 7c744c0b2162c3a866034dea65058cced9195e2a Mon Sep 17 00:00:00 2001 From: Florian Gareis Date: Mon, 3 Jul 2023 23:46:29 +0000 Subject: [PATCH 02/13] Add useEffect reset selected category on change --- .../src/complex/categorization/CategorizationRenderer.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/vanilla-renderers/src/complex/categorization/CategorizationRenderer.tsx b/packages/vanilla-renderers/src/complex/categorization/CategorizationRenderer.tsx index 534ed10644..c98c7990d3 100644 --- a/packages/vanilla-renderers/src/complex/categorization/CategorizationRenderer.tsx +++ b/packages/vanilla-renderers/src/complex/categorization/CategorizationRenderer.tsx @@ -22,7 +22,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -import React, { useState } from 'react'; +import React, { useEffect, useState } from 'react'; import type { Categorization, Category, LayoutProps } from '@jsonforms/core'; import { TranslateProps, @@ -64,6 +64,10 @@ export const CategorizationRenderer = ({ const subcategoriesClassName = getStyleAsClassName('category.subcategories'); const groupClassName = getStyleAsClassName('category.group'); + useEffect(() => { + setSelectedCategory(findCategory(categorization)); + }, [uischema, schema]); + const [selectedCategory, setSelectedCategory] = useState( findCategory(categorization) ); From 1f6df07e6d79853944e616799b91b761b6f3d2bf Mon Sep 17 00:00:00 2001 From: Florian Gareis Date: Tue, 4 Jul 2023 00:05:51 +0000 Subject: [PATCH 03/13] Add test --- .../renderers/CategorizationRenderer.test.tsx | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/packages/vanilla-renderers/test/renderers/CategorizationRenderer.test.tsx b/packages/vanilla-renderers/test/renderers/CategorizationRenderer.test.tsx index 2f92951286..34a47f89c2 100644 --- a/packages/vanilla-renderers/test/renderers/CategorizationRenderer.test.tsx +++ b/packages/vanilla-renderers/test/renderers/CategorizationRenderer.test.tsx @@ -386,4 +386,39 @@ describe('Categorization renderer', () => { const div: HTMLDivElement = wrapper.find('.categorization').getDOMNode(); expect(div.hidden).toBe(false); }); + + test('reset selected category on schema change', () => { + const uischema: Categorization = { + type: 'Categorization', + label: '', + elements: [ + { + type: 'Category', + label: 'B', + elements: [], + }, + ], + }; + const core = initCore(fixture.schema, fixture.uischema, fixture.data); + + wrapper = mount( + + + + ); + + let firstItem = wrapper.find('li').at(0); + firstItem.simulate('click'); + expect(firstItem.hasClass('selected')).toBe(true); + + core.uischema = uischema; + wrapper.setProps({ initState: { renderers: vanillaRenderers, core } }); + wrapper.update(); + + firstItem = wrapper.find('li').at(0); + expect(firstItem.hasClass('selected')).toBe(false); + }); }); From ae5842faa555e8ad6db4f945b2b8177ca237bb10 Mon Sep 17 00:00:00 2001 From: Florian Gareis Date: Tue, 18 Jul 2023 09:05:59 +0000 Subject: [PATCH 04/13] Add more feature to renderer --- .../categorization/CategorizationRenderer.tsx | 73 ++++++++++++------- packages/vanilla-renderers/src/index.ts | 6 ++ packages/vanilla-renderers/src/util/index.tsx | 17 ++++- 3 files changed, 66 insertions(+), 30 deletions(-) diff --git a/packages/vanilla-renderers/src/complex/categorization/CategorizationRenderer.tsx b/packages/vanilla-renderers/src/complex/categorization/CategorizationRenderer.tsx index c98c7990d3..5ea2bdd566 100644 --- a/packages/vanilla-renderers/src/complex/categorization/CategorizationRenderer.tsx +++ b/packages/vanilla-renderers/src/complex/categorization/CategorizationRenderer.tsx @@ -22,8 +22,9 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -import React, { useEffect, useState } from 'react'; +import React, { useMemo, useState } from 'react'; import type { Categorization, Category, LayoutProps } from '@jsonforms/core'; +import { isVisible } from '@jsonforms/core'; import { TranslateProps, withJsonFormsLayoutProps, @@ -31,49 +32,66 @@ import { } from '@jsonforms/react'; import { CategorizationList } from './CategorizationList'; import { SingleCategory } from './SingleCategory'; -import { isCategorization } from './tester'; import { withVanillaControlProps } from '../../util'; -import type { VanillaRendererProps } from '../../index'; +import type { AjvProps, VanillaRendererProps } from '../../index'; +import { withAjvProps } from '../../index'; export interface CategorizationState { selectedCategory: Category; } +interface CategorizationProps { + selected?: number; + onChange?(selected: number, prevSelected: number): void; +} + export const CategorizationRenderer = ({ + data, uischema, schema, path, + selected, t, visible, getStyleAsClassName, -}: LayoutProps & VanillaRendererProps & TranslateProps) => { - const findCategory = (categorization: Categorization): Category => { - const category = categorization.elements[0]; - - if (isCategorization(category)) { - return findCategory(category); - } - - return category; - }; - + onChange, + ajv, +}: LayoutProps & + VanillaRendererProps & + TranslateProps & + CategorizationProps & + AjvProps) => { const categorization = uischema as Categorization; + const categories = useMemo( + () => + categorization.elements.filter((category: Category) => + isVisible(category, data, undefined, ajv) + ), + [categorization, data, ajv] + ) as [Category]; const classNames = getStyleAsClassName('categorization'); const masterClassNames = getStyleAsClassName('categorization.master'); const detailClassNames = getStyleAsClassName('categorization.detail'); const subcategoriesClassName = getStyleAsClassName('category.subcategories'); const groupClassName = getStyleAsClassName('category.group'); - useEffect(() => { - setSelectedCategory(findCategory(categorization)); - }, [uischema, schema]); + const [previousCategorization, setPreviousCategorization] = + useState(uischema as Categorization); + const [activeCategory, setActiveCategory] = useState(selected ?? 0); - const [selectedCategory, setSelectedCategory] = useState( - findCategory(categorization) - ); + const safeCategory = + activeCategory >= categorization.elements.length ? 0 : activeCategory; - const onCategorySelected = (category: Category) => () => { - return setSelectedCategory(category); + if (categorization !== previousCategorization) { + setActiveCategory(0); + setPreviousCategorization(categorization); + } + + const onCategorySelected = (categoryIndex: number) => () => { + if (onChange) { + return onChange(categoryIndex, safeCategory); + } + return setActiveCategory(categoryIndex); }; return ( @@ -84,7 +102,7 @@ export const CategorizationRenderer = ({
); }; -export default withVanillaControlProps( - withTranslateProps(withJsonFormsLayoutProps(CategorizationRenderer)) +export default withAjvProps( + withVanillaControlProps( + withTranslateProps(withJsonFormsLayoutProps(CategorizationRenderer)) + ) ); diff --git a/packages/vanilla-renderers/src/index.ts b/packages/vanilla-renderers/src/index.ts index bdd518bfc9..95aa5020d9 100644 --- a/packages/vanilla-renderers/src/index.ts +++ b/packages/vanilla-renderers/src/index.ts @@ -22,6 +22,8 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +import Ajv from 'ajv'; + import { RankedTester } from '@jsonforms/core'; import { @@ -102,6 +104,10 @@ export interface VanillaRendererProps extends WithClassname { getStyleAsClassName?(string: string, ...args: any[]): string; } +export interface AjvProps { + ajv: Ajv; +} + export interface WithChildren { children: any; } diff --git a/packages/vanilla-renderers/src/util/index.tsx b/packages/vanilla-renderers/src/util/index.tsx index 511ee2f5f1..3562b647ae 100644 --- a/packages/vanilla-renderers/src/util/index.tsx +++ b/packages/vanilla-renderers/src/util/index.tsx @@ -25,10 +25,8 @@ export * from './i18nDefaults'; import React, { ComponentType, useMemo } from 'react'; import isEmpty from 'lodash/isEmpty'; -import { +import type { ControlElement, - convertToValidClassName, - getConfig, JsonFormsState, OwnPropsOfCell, OwnPropsOfControl, @@ -37,9 +35,10 @@ import { StatePropsOfCell, StatePropsOfControl, } from '@jsonforms/core'; +import { convertToValidClassName, getAjv, getConfig } from '@jsonforms/core'; import { useJsonForms } from '@jsonforms/react'; import { getStyle, getStyleAsClassName } from '../reducers'; -import { VanillaRendererProps } from '../index'; +import type { AjvProps, VanillaRendererProps } from '../index'; import { findStyle, findStyleAsClassName } from '../reducers/styling'; import { useStyles } from '../styles'; @@ -240,6 +239,16 @@ const withVanillaCellPropsForType = ); }; +export const withAjvProps =

( + Component: ComponentType +) => + function WithAjvProps(props: P) { + const ctx = useJsonForms(); + const ajv = getAjv({ jsonforms: { ...ctx } }); + + return ; + }; + export const withVanillaCellProps = withVanillaCellPropsForType('control.input'); From 2f9600a7a958fa05e7551cfbf0ad783caaeeabbc Mon Sep 17 00:00:00 2001 From: Florian Gareis Date: Wed, 13 Sep 2023 23:32:59 +0000 Subject: [PATCH 05/13] Use index instead of category --- .../src/complex/categorization/CategorizationList.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/vanilla-renderers/src/complex/categorization/CategorizationList.tsx b/packages/vanilla-renderers/src/complex/categorization/CategorizationList.tsx index 7f53925b48..1c07193712 100644 --- a/packages/vanilla-renderers/src/complex/categorization/CategorizationList.tsx +++ b/packages/vanilla-renderers/src/complex/categorization/CategorizationList.tsx @@ -85,7 +85,7 @@ export const CategorizationList = ({ return (

  • {categoryLabels[idx]} From 5a8bdd688be2d1f1884292b228eaf0f28eb8c524 Mon Sep 17 00:00:00 2001 From: Florian Gareis Date: Sat, 23 Sep 2023 00:10:06 +0000 Subject: [PATCH 06/13] Replace withAjvProps and remove categorization --- .../categorization/CategorizationList.tsx | 15 ++++++--------- .../categorization/CategorizationRenderer.tsx | 18 ++++++++---------- 2 files changed, 14 insertions(+), 19 deletions(-) diff --git a/packages/vanilla-renderers/src/complex/categorization/CategorizationList.tsx b/packages/vanilla-renderers/src/complex/categorization/CategorizationList.tsx index 1c07193712..20b4a2369d 100644 --- a/packages/vanilla-renderers/src/complex/categorization/CategorizationList.tsx +++ b/packages/vanilla-renderers/src/complex/categorization/CategorizationList.tsx @@ -24,7 +24,6 @@ */ import React, { useMemo } from 'react'; import { - Categorization, Category, deriveLabelForUISchemaElement, Translator, @@ -37,7 +36,7 @@ const getCategoryClassName = ( ): string => (selectedCategory === category ? 'selected' : ''); export interface CategorizationProps { - categorization: Categorization; + filteredCategories: [Category]; selectedCategory: Category; depth: number; onSelect: any; @@ -47,8 +46,8 @@ export interface CategorizationProps { } export const CategorizationList = ({ - categorization, selectedCategory, + filteredCategories, depth, onSelect, subcategoriesClassName, @@ -57,22 +56,20 @@ export const CategorizationList = ({ }: CategorizationProps) => { const categoryLabels = useMemo( () => - categorization.elements.map((cat) => - deriveLabelForUISchemaElement(cat, t) - ), - [categorization, t] + filteredCategories.map((cat) => deriveLabelForUISchemaElement(cat, t)), + [filteredCategories, t] ); return (
      - {categorization.elements.map((category, idx) => { + {filteredCategories.map((category, idx) => { if (isCategorization(category)) { return (
    • {categoryLabels[idx]} { + const ajv = useJsonForms().core.ajv; const categorization = uischema as Categorization; - const categories = useMemo( + const filteredCategories = useMemo( () => categorization.elements.filter((category: Category) => isVisible(category, data, undefined, ajv) @@ -101,8 +101,8 @@ export const CategorizationRenderer = ({ >
      Date: Sat, 11 Nov 2023 14:21:42 +0000 Subject: [PATCH 07/13] Move logic from index into seperate file --- .../categorization/CategorizationRenderer.tsx | 2 +- packages/vanilla-renderers/src/index.ts | 115 ------------------ packages/vanilla-renderers/src/util/index.ts | 27 ++++ .../src/util/{index.tsx => props.tsx} | 38 +++++- .../vanilla-renderers/src/util/renderer.ts | 104 ++++++++++++++++ 5 files changed, 168 insertions(+), 118 deletions(-) create mode 100644 packages/vanilla-renderers/src/util/index.ts rename packages/vanilla-renderers/src/util/{index.tsx => props.tsx} (89%) create mode 100644 packages/vanilla-renderers/src/util/renderer.ts diff --git a/packages/vanilla-renderers/src/complex/categorization/CategorizationRenderer.tsx b/packages/vanilla-renderers/src/complex/categorization/CategorizationRenderer.tsx index f010d59d6e..740d502fcd 100644 --- a/packages/vanilla-renderers/src/complex/categorization/CategorizationRenderer.tsx +++ b/packages/vanilla-renderers/src/complex/categorization/CategorizationRenderer.tsx @@ -34,7 +34,7 @@ import { import { CategorizationList } from './CategorizationList'; import { SingleCategory } from './SingleCategory'; import { withVanillaControlProps } from '../../util'; -import type { AjvProps, VanillaRendererProps } from '../../index'; +import type { AjvProps, VanillaRendererProps } from '../../util'; export interface CategorizationState { selectedCategory: Category; diff --git a/packages/vanilla-renderers/src/index.ts b/packages/vanilla-renderers/src/index.ts index 95aa5020d9..ee0d8b0236 100644 --- a/packages/vanilla-renderers/src/index.ts +++ b/packages/vanilla-renderers/src/index.ts @@ -22,95 +22,6 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -import Ajv from 'ajv'; - -import { RankedTester } from '@jsonforms/core'; - -import { - BooleanCell, - booleanCellTester, - DateCell, - dateCellTester, - dateTimeCellTester, - EnumCell, - enumCellTester, - IntegerCell, - integerCellTester, - NumberCell, - numberCellTester, - SliderCell, - sliderCellTester, - TextAreaCell, - textAreaCellTester, - TextCell, - textCellTester, - TimeCell, - timeCellTester, -} from './cells'; - -import { - InputControl, - inputControlTester, - RadioGroupControl, - radioGroupControlTester, - OneOfRadioGroupControl, - oneOfRadioGroupControlTester, -} from './controls'; - -import { - ArrayControl, - arrayControlTester, - Categorization, - categorizationTester, - LabelRenderer, - labelRendererTester, - TableArrayControl, - tableArrayControlTester, -} from './complex'; - -import { - GroupLayout, - groupTester, - HorizontalLayout, - horizontalLayoutTester, - VerticalLayout, - verticalLayoutTester, -} from './layouts'; -import DateTimeCell from './cells/DateTimeCell'; - -export interface WithClassname { - className?: string; -} - -/** - * Additional renderer props specific to vanilla renderers. - */ -export interface VanillaRendererProps extends WithClassname { - classNames?: { [className: string]: string }; - /** - * Returns all classes associated with the given style. - * @param {string} string the style name - * @param args any additional args necessary to calculate the classes - * @returns {string[]} array of class names - */ - getStyle?(string: string, ...args: any[]): string[]; - - /** - * Returns all classes associated with the given style as a single class name. - * @param {string} string the style name - * @param args any additional args necessary to calculate the classes - * @returns {string[]} array of class names - */ - getStyleAsClassName?(string: string, ...args: any[]): string; -} - -export interface AjvProps { - ajv: Ajv; -} - -export interface WithChildren { - children: any; -} export * from './actions'; export * from './controls'; @@ -120,29 +31,3 @@ export * from './layouts'; export * from './reducers'; export * from './util'; export * from './styles'; - -export const vanillaRenderers: { tester: RankedTester; renderer: any }[] = [ - { tester: inputControlTester, renderer: InputControl }, - { tester: radioGroupControlTester, renderer: RadioGroupControl }, - { tester: oneOfRadioGroupControlTester, renderer: OneOfRadioGroupControl }, - { tester: arrayControlTester, renderer: ArrayControl }, - { tester: labelRendererTester, renderer: LabelRenderer }, - { tester: categorizationTester, renderer: Categorization }, - { tester: tableArrayControlTester, renderer: TableArrayControl }, - { tester: groupTester, renderer: GroupLayout }, - { tester: verticalLayoutTester, renderer: VerticalLayout }, - { tester: horizontalLayoutTester, renderer: HorizontalLayout }, -]; - -export const vanillaCells: { tester: RankedTester; cell: any }[] = [ - { tester: booleanCellTester, cell: BooleanCell }, - { tester: dateCellTester, cell: DateCell }, - { tester: dateTimeCellTester, cell: DateTimeCell }, - { tester: enumCellTester, cell: EnumCell }, - { tester: integerCellTester, cell: IntegerCell }, - { tester: numberCellTester, cell: NumberCell }, - { tester: sliderCellTester, cell: SliderCell }, - { tester: textAreaCellTester, cell: TextAreaCell }, - { tester: textCellTester, cell: TextCell }, - { tester: timeCellTester, cell: TimeCell }, -]; diff --git a/packages/vanilla-renderers/src/util/index.ts b/packages/vanilla-renderers/src/util/index.ts new file mode 100644 index 0000000000..63997b7f84 --- /dev/null +++ b/packages/vanilla-renderers/src/util/index.ts @@ -0,0 +1,27 @@ +/* + The MIT License + + Copyright (c) 2017-2019 EclipseSource Munich + https://github.com/eclipsesource/jsonforms + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ +export * from './i18nDefaults'; +export * from './props'; +export * from './renderer'; diff --git a/packages/vanilla-renderers/src/util/index.tsx b/packages/vanilla-renderers/src/util/props.tsx similarity index 89% rename from packages/vanilla-renderers/src/util/index.tsx rename to packages/vanilla-renderers/src/util/props.tsx index 3562b647ae..52a398331d 100644 --- a/packages/vanilla-renderers/src/util/index.tsx +++ b/packages/vanilla-renderers/src/util/props.tsx @@ -22,7 +22,8 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -export * from './i18nDefaults'; + +import Ajv from 'ajv'; import React, { ComponentType, useMemo } from 'react'; import isEmpty from 'lodash/isEmpty'; import type { @@ -38,10 +39,43 @@ import type { import { convertToValidClassName, getAjv, getConfig } from '@jsonforms/core'; import { useJsonForms } from '@jsonforms/react'; import { getStyle, getStyleAsClassName } from '../reducers'; -import type { AjvProps, VanillaRendererProps } from '../index'; import { findStyle, findStyleAsClassName } from '../reducers/styling'; import { useStyles } from '../styles'; +export interface WithClassname { + className?: string; +} + +export interface AjvProps { + ajv: Ajv; +} + +export interface WithChildren { + children: any; +} + +/** + * Additional renderer props specific to vanilla renderers. + */ +export interface VanillaRendererProps extends WithClassname { + classNames?: { [className: string]: string }; + /** + * Returns all classes associated with the given style. + * @param {string} string the style name + * @param args any additional args necessary to calculate the classes + * @returns {string[]} array of class names + */ + getStyle?(string: string, ...args: any[]): string[]; + + /** + * Returns all classes associated with the given style as a single class name. + * @param {string} string the style name + * @param args any additional args necessary to calculate the classes + * @returns {string[]} array of class names + */ + getStyleAsClassName?(string: string, ...args: any[]): string; +} + /** * Add vanilla props to the return value of calling the given * mapStateToProps function. diff --git a/packages/vanilla-renderers/src/util/renderer.ts b/packages/vanilla-renderers/src/util/renderer.ts new file mode 100644 index 0000000000..315999a662 --- /dev/null +++ b/packages/vanilla-renderers/src/util/renderer.ts @@ -0,0 +1,104 @@ +/* + The MIT License + + Copyright (c) 2017-2019 EclipseSource Munich + https://github.com/eclipsesource/jsonforms + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +import { RankedTester } from '@jsonforms/core'; + +import { + BooleanCell, + booleanCellTester, + DateCell, + dateCellTester, + dateTimeCellTester, + EnumCell, + enumCellTester, + IntegerCell, + integerCellTester, + NumberCell, + numberCellTester, + SliderCell, + sliderCellTester, + TextAreaCell, + textAreaCellTester, + TextCell, + textCellTester, + TimeCell, + timeCellTester, +} from '../cells'; + +import { + InputControl, + inputControlTester, + RadioGroupControl, + radioGroupControlTester, + OneOfRadioGroupControl, + oneOfRadioGroupControlTester, +} from '../controls'; + +import { + ArrayControl, + arrayControlTester, + Categorization, + categorizationTester, + LabelRenderer, + labelRendererTester, + TableArrayControl, + tableArrayControlTester, +} from '../complex'; + +import { + GroupLayout, + groupTester, + HorizontalLayout, + horizontalLayoutTester, + VerticalLayout, + verticalLayoutTester, +} from '../layouts'; +import DateTimeCell from '../cells/DateTimeCell'; + +export const vanillaRenderers: { tester: RankedTester; renderer: any }[] = [ + { tester: inputControlTester, renderer: InputControl }, + { tester: radioGroupControlTester, renderer: RadioGroupControl }, + { tester: oneOfRadioGroupControlTester, renderer: OneOfRadioGroupControl }, + { tester: arrayControlTester, renderer: ArrayControl }, + { tester: labelRendererTester, renderer: LabelRenderer }, + { tester: categorizationTester, renderer: Categorization }, + { tester: tableArrayControlTester, renderer: TableArrayControl }, + { tester: groupTester, renderer: GroupLayout }, + { tester: verticalLayoutTester, renderer: VerticalLayout }, + { tester: horizontalLayoutTester, renderer: HorizontalLayout }, +]; + +export const vanillaCells: { tester: RankedTester; cell: any }[] = [ + { tester: booleanCellTester, cell: BooleanCell }, + { tester: dateCellTester, cell: DateCell }, + { tester: dateTimeCellTester, cell: DateTimeCell }, + { tester: enumCellTester, cell: EnumCell }, + { tester: integerCellTester, cell: IntegerCell }, + { tester: numberCellTester, cell: NumberCell }, + { tester: sliderCellTester, cell: SliderCell }, + { tester: textAreaCellTester, cell: TextAreaCell }, + { tester: textCellTester, cell: TextCell }, + { tester: timeCellTester, cell: TimeCell }, +]; From 1bc44c322c1eb01ed32278a410128432a52c81a9 Mon Sep 17 00:00:00 2001 From: Florian Gareis Date: Mon, 13 Nov 2023 15:12:57 +0000 Subject: [PATCH 08/13] Adjust according to review --- .../categorization/CategorizationList.tsx | 15 +++++++----- .../categorization/CategorizationRenderer.tsx | 23 ++++++++++--------- 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/packages/vanilla-renderers/src/complex/categorization/CategorizationList.tsx b/packages/vanilla-renderers/src/complex/categorization/CategorizationList.tsx index 20b4a2369d..b19dacf10d 100644 --- a/packages/vanilla-renderers/src/complex/categorization/CategorizationList.tsx +++ b/packages/vanilla-renderers/src/complex/categorization/CategorizationList.tsx @@ -25,6 +25,7 @@ import React, { useMemo } from 'react'; import { Category, + Categorization, deriveLabelForUISchemaElement, Translator, } from '@jsonforms/core'; @@ -36,7 +37,7 @@ const getCategoryClassName = ( ): string => (selectedCategory === category ? 'selected' : ''); export interface CategorizationProps { - filteredCategories: [Category]; + filteredCategorization: (Category | Categorization)[]; selectedCategory: Category; depth: number; onSelect: any; @@ -47,7 +48,7 @@ export interface CategorizationProps { export const CategorizationList = ({ selectedCategory, - filteredCategories, + filteredCategorization, depth, onSelect, subcategoriesClassName, @@ -56,20 +57,22 @@ export const CategorizationList = ({ }: CategorizationProps) => { const categoryLabels = useMemo( () => - filteredCategories.map((cat) => deriveLabelForUISchemaElement(cat, t)), - [filteredCategories, t] + filteredCategorization.map((cat) => + deriveLabelForUISchemaElement(cat, t) + ), + [filteredCategorization, t] ); return (
        - {filteredCategories.map((category, idx) => { + {filteredCategorization.map((category, idx) => { if (isCategorization(category)) { return (
      • {categoryLabels[idx]} { - const ajv = useJsonForms().core.ajv; const categorization = uischema as Categorization; - const filteredCategories = useMemo( + const filteredCategorization = useMemo( () => - categorization.elements.filter((category: Category) => + categorization.elements.filter((category: Category | Categorization) => isVisible(category, data, undefined, ajv) ), [categorization, data, ajv] - ) as [Category]; + ) as (Category | Categorization)[]; const classNames = getStyleAsClassName('categorization'); const masterClassNames = getStyleAsClassName('categorization.master'); const detailClassNames = getStyleAsClassName('categorization.detail'); @@ -101,8 +100,8 @@ export const CategorizationRenderer = ({ >
        Date: Mon, 13 Nov 2023 18:56:50 +0000 Subject: [PATCH 09/13] Move filter logic to list file --- .../categorization/CategorizationList.tsx | 30 ++++++++++++------- .../categorization/CategorizationRenderer.tsx | 16 +++++----- 2 files changed, 27 insertions(+), 19 deletions(-) diff --git a/packages/vanilla-renderers/src/complex/categorization/CategorizationList.tsx b/packages/vanilla-renderers/src/complex/categorization/CategorizationList.tsx index b19dacf10d..bd4c321c54 100644 --- a/packages/vanilla-renderers/src/complex/categorization/CategorizationList.tsx +++ b/packages/vanilla-renderers/src/complex/categorization/CategorizationList.tsx @@ -28,8 +28,10 @@ import { Categorization, deriveLabelForUISchemaElement, Translator, + isVisible, } from '@jsonforms/core'; import { isCategorization } from './tester'; +import { AjvProps } from '../../util'; const getCategoryClassName = ( category: Category, @@ -37,9 +39,10 @@ const getCategoryClassName = ( ): string => (selectedCategory === category ? 'selected' : ''); export interface CategorizationProps { - filteredCategorization: (Category | Categorization)[]; + elements: (Category | Categorization)[]; selectedCategory: Category; depth: number; + data: any; onSelect: any; subcategoriesClassName: string; groupClassName: string; @@ -48,31 +51,38 @@ export interface CategorizationProps { export const CategorizationList = ({ selectedCategory, - filteredCategorization, + elements, + data, depth, onSelect, subcategoriesClassName, groupClassName, t, -}: CategorizationProps) => { + ajv, +}: CategorizationProps & AjvProps) => { + const filteredElements = elements.filter( + (category: Category | Categorization) => { + isVisible(category, data, undefined, ajv); + } + ); + const categoryLabels = useMemo( - () => - filteredCategorization.map((cat) => - deriveLabelForUISchemaElement(cat, t) - ), - [filteredCategorization, t] + () => filteredElements.map((cat) => deriveLabelForUISchemaElement(cat, t)), + [filteredElements, t] ); return (
          - {filteredCategorization.map((category, idx) => { + {filteredElements.map((category, idx) => { if (isCategorization(category)) { return (
        • {categoryLabels[idx]} { const categorization = uischema as Categorization; - const filteredCategorization = useMemo( - () => - categorization.elements.filter((category: Category | Categorization) => - isVisible(category, data, undefined, ajv) - ), + const elements = useMemo( + () => categorization.elements, [categorization, data, ajv] ) as (Category | Categorization)[]; const classNames = getStyleAsClassName('categorization'); @@ -100,8 +96,10 @@ export const CategorizationRenderer = ({ >
          Date: Tue, 14 Nov 2023 10:04:19 +0000 Subject: [PATCH 10/13] Move renderer directly into the src folder --- packages/vanilla-renderers/src/index.ts | 1 + packages/vanilla-renderers/src/{util => }/renderer.ts | 10 +++++----- packages/vanilla-renderers/src/util/index.ts | 1 - 3 files changed, 6 insertions(+), 6 deletions(-) rename packages/vanilla-renderers/src/{util => }/renderer.ts (96%) diff --git a/packages/vanilla-renderers/src/index.ts b/packages/vanilla-renderers/src/index.ts index ee0d8b0236..0c78a49acb 100644 --- a/packages/vanilla-renderers/src/index.ts +++ b/packages/vanilla-renderers/src/index.ts @@ -31,3 +31,4 @@ export * from './layouts'; export * from './reducers'; export * from './util'; export * from './styles'; +export * from './renderer'; diff --git a/packages/vanilla-renderers/src/util/renderer.ts b/packages/vanilla-renderers/src/renderer.ts similarity index 96% rename from packages/vanilla-renderers/src/util/renderer.ts rename to packages/vanilla-renderers/src/renderer.ts index 315999a662..4837dbbab6 100644 --- a/packages/vanilla-renderers/src/util/renderer.ts +++ b/packages/vanilla-renderers/src/renderer.ts @@ -45,7 +45,7 @@ import { textCellTester, TimeCell, timeCellTester, -} from '../cells'; +} from './cells'; import { InputControl, @@ -54,7 +54,7 @@ import { radioGroupControlTester, OneOfRadioGroupControl, oneOfRadioGroupControlTester, -} from '../controls'; +} from './controls'; import { ArrayControl, @@ -65,7 +65,7 @@ import { labelRendererTester, TableArrayControl, tableArrayControlTester, -} from '../complex'; +} from './complex'; import { GroupLayout, @@ -74,8 +74,8 @@ import { horizontalLayoutTester, VerticalLayout, verticalLayoutTester, -} from '../layouts'; -import DateTimeCell from '../cells/DateTimeCell'; +} from './layouts'; +import DateTimeCell from './cells/DateTimeCell'; export const vanillaRenderers: { tester: RankedTester; renderer: any }[] = [ { tester: inputControlTester, renderer: InputControl }, diff --git a/packages/vanilla-renderers/src/util/index.ts b/packages/vanilla-renderers/src/util/index.ts index 63997b7f84..919de7ea85 100644 --- a/packages/vanilla-renderers/src/util/index.ts +++ b/packages/vanilla-renderers/src/util/index.ts @@ -24,4 +24,3 @@ */ export * from './i18nDefaults'; export * from './props'; -export * from './renderer'; From fe50da9af66fb33dd61eb9c48cf4334f3c923841 Mon Sep 17 00:00:00 2001 From: Florian Gareis Date: Tue, 14 Nov 2023 10:04:45 +0000 Subject: [PATCH 11/13] Fix useMemo() --- .../src/complex/categorization/CategorizationList.tsx | 10 +++++----- .../complex/categorization/CategorizationRenderer.tsx | 7 ++----- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/packages/vanilla-renderers/src/complex/categorization/CategorizationList.tsx b/packages/vanilla-renderers/src/complex/categorization/CategorizationList.tsx index bd4c321c54..b723413fa2 100644 --- a/packages/vanilla-renderers/src/complex/categorization/CategorizationList.tsx +++ b/packages/vanilla-renderers/src/complex/categorization/CategorizationList.tsx @@ -60,11 +60,11 @@ export const CategorizationList = ({ t, ajv, }: CategorizationProps & AjvProps) => { - const filteredElements = elements.filter( - (category: Category | Categorization) => { - isVisible(category, data, undefined, ajv); - } - ); + const filteredElements = useMemo(() => { + return elements.filter((category: Category | Categorization) => + isVisible(category, data, undefined, ajv) + ); + }, [elements, data, ajv]); const categoryLabels = useMemo( () => filteredElements.map((cat) => deriveLabelForUISchemaElement(cat, t)), diff --git a/packages/vanilla-renderers/src/complex/categorization/CategorizationRenderer.tsx b/packages/vanilla-renderers/src/complex/categorization/CategorizationRenderer.tsx index 95eabe2d72..47bcb5f370 100644 --- a/packages/vanilla-renderers/src/complex/categorization/CategorizationRenderer.tsx +++ b/packages/vanilla-renderers/src/complex/categorization/CategorizationRenderer.tsx @@ -22,7 +22,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -import React, { useMemo, useState } from 'react'; +import React, { useState } from 'react'; import type { Categorization, Category, LayoutProps } from '@jsonforms/core'; import { TranslateProps, @@ -60,10 +60,7 @@ export const CategorizationRenderer = ({ CategorizationProps & AjvProps) => { const categorization = uischema as Categorization; - const elements = useMemo( - () => categorization.elements, - [categorization, data, ajv] - ) as (Category | Categorization)[]; + const elements = categorization.elements as (Category | Categorization)[]; const classNames = getStyleAsClassName('categorization'); const masterClassNames = getStyleAsClassName('categorization.master'); const detailClassNames = getStyleAsClassName('categorization.detail'); From 967fbbb4f82653beb7a8d51c75afc04249bb4f7f Mon Sep 17 00:00:00 2001 From: Florian Gareis Date: Tue, 12 Dec 2023 14:37:04 +0000 Subject: [PATCH 12/13] Fix test --- .../renderers/CategorizationRenderer.test.tsx | 57 +++++++++++++------ 1 file changed, 41 insertions(+), 16 deletions(-) diff --git a/packages/vanilla-renderers/test/renderers/CategorizationRenderer.test.tsx b/packages/vanilla-renderers/test/renderers/CategorizationRenderer.test.tsx index 34a47f89c2..ed552bebe0 100644 --- a/packages/vanilla-renderers/test/renderers/CategorizationRenderer.test.tsx +++ b/packages/vanilla-renderers/test/renderers/CategorizationRenderer.test.tsx @@ -30,7 +30,7 @@ import { JsonSchema, Layout, } from '@jsonforms/core'; -import { JsonFormsStateProvider } from '@jsonforms/react'; +import { JsonForms, JsonFormsStateProvider } from '@jsonforms/react'; import Adapter from '@wojtekmaj/enzyme-adapter-react-17'; import Enzyme, { mount, ReactWrapper } from 'enzyme'; import CategorizationRenderer, { @@ -388,37 +388,62 @@ describe('Categorization renderer', () => { }); test('reset selected category on schema change', () => { - const uischema: Categorization = { + const oldUischema: Categorization = { type: 'Categorization', label: '', elements: [ + { + type: 'Category', + label: 'A', + elements: [], + }, { type: 'Category', label: 'B', elements: [], }, + { + type: 'Category', + label: 'C', + elements: [], + }, + ], + }; + const newUischema: Categorization = { + type: 'Categorization', + label: '', + elements: [ + { + type: 'Category', + label: 'A', + elements: [], + }, + { + type: 'Category', + label: 'C', + elements: [], + }, ], }; - const core = initCore(fixture.schema, fixture.uischema, fixture.data); wrapper = mount( - - - + ); - let firstItem = wrapper.find('li').at(0); - firstItem.simulate('click'); - expect(firstItem.hasClass('selected')).toBe(true); + let secondItem = wrapper.find('li').at(1); + secondItem.simulate('click'); + secondItem = wrapper.find('li').at(1); + expect(secondItem.hasClass('selected')).toBe(true); - core.uischema = uischema; - wrapper.setProps({ initState: { renderers: vanillaRenderers, core } }); + wrapper.setProps({ uischema: newUischema }); wrapper.update(); - firstItem = wrapper.find('li').at(0); - expect(firstItem.hasClass('selected')).toBe(false); + secondItem = wrapper.find('li').at(1); + expect(secondItem.hasClass('selected')).toBe(false); }); }); From 1d1863b0d6861319b70456d97cfe18515396820d Mon Sep 17 00:00:00 2001 From: Stefan Dirix Date: Mon, 22 Jan 2024 16:33:18 +0100 Subject: [PATCH 13/13] apply review comments --- packages/vanilla-renderers/src/index.ts | 2 +- packages/vanilla-renderers/src/{renderer.ts => renderers.ts} | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename packages/vanilla-renderers/src/{renderer.ts => renderers.ts} (98%) diff --git a/packages/vanilla-renderers/src/index.ts b/packages/vanilla-renderers/src/index.ts index 0c78a49acb..18ad3c941e 100644 --- a/packages/vanilla-renderers/src/index.ts +++ b/packages/vanilla-renderers/src/index.ts @@ -31,4 +31,4 @@ export * from './layouts'; export * from './reducers'; export * from './util'; export * from './styles'; -export * from './renderer'; +export * from './renderers'; diff --git a/packages/vanilla-renderers/src/renderer.ts b/packages/vanilla-renderers/src/renderers.ts similarity index 98% rename from packages/vanilla-renderers/src/renderer.ts rename to packages/vanilla-renderers/src/renderers.ts index 4837dbbab6..a432d5db47 100644 --- a/packages/vanilla-renderers/src/renderer.ts +++ b/packages/vanilla-renderers/src/renderers.ts @@ -30,6 +30,7 @@ import { booleanCellTester, DateCell, dateCellTester, + DateTimeCell, dateTimeCellTester, EnumCell, enumCellTester, @@ -75,7 +76,6 @@ import { VerticalLayout, verticalLayoutTester, } from './layouts'; -import DateTimeCell from './cells/DateTimeCell'; export const vanillaRenderers: { tester: RankedTester; renderer: any }[] = [ { tester: inputControlTester, renderer: InputControl },