From fda1838c21d715b526478d9d172b7c83ff4981e5 Mon Sep 17 00:00:00 2001 From: LukasBoll Date: Mon, 25 Oct 2021 16:59:04 +0200 Subject: [PATCH 1/9] path to array --- .../src/layouts/array-layout.renderer.ts | 4 +- .../src/other/master-detail/master.ts | 8 ++-- .../src/other/table.renderer.ts | 2 +- packages/angular/src/abstract-control.ts | 2 +- packages/angular/src/base.renderer.ts | 2 +- packages/core/src/actions/actions.ts | 4 +- packages/core/src/reducers/core.ts | 20 ++++----- packages/core/src/reducers/reducers.ts | 6 +-- packages/core/src/reducers/uischemas.ts | 4 +- packages/core/src/testers/testers.ts | 6 +-- packages/core/src/util/combinators.ts | 2 +- packages/core/src/util/path.ts | 33 +++++++++----- packages/core/src/util/renderer.ts | 40 ++++++++--------- packages/core/src/util/resolvers.ts | 4 +- packages/core/src/util/runtime.ts | 14 +++--- packages/core/src/util/util.ts | 2 +- packages/example/src/util.tsx | 4 +- packages/examples/src/person.ts | 4 +- .../MaterialListWithDetailRenderer.tsx | 5 ++- .../src/complex/CombinatorProperties.tsx | 2 +- .../material/src/complex/DeleteDialog.tsx | 2 +- .../complex/MaterialArrayControlRenderer.tsx | 9 ++-- .../src/complex/MaterialEnumArrayRenderer.tsx | 6 ++- .../src/complex/MaterialTableControl.tsx | 44 +++++++++++-------- .../material/src/complex/TableToolbar.tsx | 4 +- .../material/src/layouts/ArrayToolbar.tsx | 5 ++- .../src/layouts/ExpandPanelRenderer.tsx | 29 ++++++------ .../src/layouts/MaterialArrayLayout.tsx | 10 ++--- .../layouts/MaterialArrayLayoutRenderer.tsx | 4 +- packages/material/src/util/datejs.ts | 4 +- packages/material/src/util/debounce.ts | 2 +- packages/material/src/util/layout.tsx | 2 +- packages/react/src/JsonForms.tsx | 4 +- .../vanilla/src/complex/TableArrayControl.tsx | 25 ++++++----- .../src/complex/array/ArrayControl.tsx | 6 +-- .../complex/categorization/SingleCategory.tsx | 2 +- packages/vanilla/src/layouts/util.tsx | 4 +- packages/vue/vue/src/jsonFormsCompositions.ts | 4 +- 38 files changed, 182 insertions(+), 152 deletions(-) diff --git a/packages/angular-material/src/layouts/array-layout.renderer.ts b/packages/angular-material/src/layouts/array-layout.renderer.ts index 3b7cd8250..7c9f7d9ab 100644 --- a/packages/angular-material/src/layouts/array-layout.renderer.ts +++ b/packages/angular-material/src/layouts/array-layout.renderer.ts @@ -129,8 +129,8 @@ export class ArrayLayoutRenderer removeTooltip: string; removeAriaLabel: string; noData: boolean; - addItem: (path: string, value: any) => () => void; - removeItems: (path: string, toDelete: number[]) => () => void; + addItem: (path: string[], value: any) => () => void; + removeItems: (path: string[], toDelete: number[]) => () => void; uischemas: { tester: UISchemaTester; uischema: UISchemaElement; diff --git a/packages/angular-material/src/other/master-detail/master.ts b/packages/angular-material/src/other/master-detail/master.ts index 8d4663dd0..3d451aade 100644 --- a/packages/angular-material/src/other/master-detail/master.ts +++ b/packages/angular-material/src/other/master-detail/master.ts @@ -46,7 +46,7 @@ import { const keywords = ['#', 'properties', 'items']; -export const removeSchemaKeywords = (path: string) => { +export const removeSchemaKeywords = (path: string[]) => { return path .split('/') .filter(s => !some(keywords, key => key === s)) @@ -141,9 +141,9 @@ export class MasterListComponent extends JsonFormsArrayControl { masterItems: any[]; selectedItem: any; selectedItemIdx: number; - addItem: (path: string, value: any) => () => void; - removeItems: (path: string, toDelete: number[]) => () => void; - propsPath: string; + addItem: (path: string[], value: any) => () => void; + removeItems: (path: string[], toDelete: number[]) => () => void; + propsPath: string[]; highlightedIdx: number; constructor(jsonformsService: JsonFormsAngularService, private changeDetectorRef: ChangeDetectorRef) { diff --git a/packages/angular-material/src/other/table.renderer.ts b/packages/angular-material/src/other/table.renderer.ts index 9a02df430..3dbbf28e0 100644 --- a/packages/angular-material/src/other/table.renderer.ts +++ b/packages/angular-material/src/other/table.renderer.ts @@ -97,7 +97,7 @@ export class TableRenderer extends JsonFormsArrayControl { } generateCells = ( schema: JsonSchema, - rowPath: string + rowPath: string[] ): ColumnDescription[] => { if (schema.type === 'object') { return this.getValidColumnProps(schema).map(prop => { diff --git a/packages/angular/src/abstract-control.ts b/packages/angular/src/abstract-control.ts index 251a6a5ae..122c90c71 100644 --- a/packages/angular/src/abstract-control.ts +++ b/packages/angular/src/abstract-control.ts @@ -63,7 +63,7 @@ export abstract class JsonFormsAbstractControl< rootSchema: JsonSchema; enabled: boolean; hidden: boolean; - propsPath: string; + propsPath: string[]; constructor(protected jsonFormsService: JsonFormsAngularService) { super(); diff --git a/packages/angular/src/base.renderer.ts b/packages/angular/src/base.renderer.ts index 2c080dc67..359573d1c 100644 --- a/packages/angular/src/base.renderer.ts +++ b/packages/angular/src/base.renderer.ts @@ -33,7 +33,7 @@ import { export class JsonFormsBaseRenderer { @Input() uischema: T; @Input() schema: JsonSchema; - @Input() path: string; + @Input() path: string[]; protected getOwnProps(): OwnPropsOfRenderer { return { diff --git a/packages/core/src/actions/actions.ts b/packages/core/src/actions/actions.ts index ddd7fe54a..0f86972b8 100644 --- a/packages/core/src/actions/actions.ts +++ b/packages/core/src/actions/actions.ts @@ -71,7 +71,7 @@ export type CoreActions = export interface UpdateAction { type: 'jsonforms/UPDATE'; - path: string; + path: string[]; updater(existingData?: any): any; } @@ -166,7 +166,7 @@ export const setAjv = (ajv: AJV) => ({ }); export const update = ( - path: string, + path: string[], updater: (existingData: any) => any ): UpdateAction => ({ type: UPDATE_DATA, diff --git a/packages/core/src/reducers/core.ts b/packages/core/src/reducers/core.ts index b6c5ce546..f82156513 100644 --- a/packages/core/src/reducers/core.ts +++ b/packages/core/src/reducers/core.ts @@ -44,7 +44,7 @@ import { UPDATE_CORE, UpdateCoreAction } from '../actions'; -import { createAjv, Reducer } from '../util'; +import { contains, createAjv, Reducer } from '../util'; import { JsonSchema, UISchemaElement } from '../models'; export const validate = (validator: ValidateFunction | undefined, data: any): ErrorObject[] => { @@ -230,7 +230,7 @@ export const coreReducer: Reducer = ( case UPDATE_DATA: { if (action.path === undefined || action.path === null) { return state; - } else if (action.path === '') { + } else if (action.path === []) { // empty path is ok const result = action.updater(cloneDeep(state.data)); const errors = validate(state.validator, result); @@ -333,9 +333,9 @@ export const getControlPath = (error: ErrorObject) => { } export const errorsAt = ( - instancePath: string, + instancePath: string[], schema: JsonSchema, - matchPath: (path: string) => boolean + matchPath: (path: string[]) => boolean ) => (errors: ErrorObject[]): ErrorObject[] => { // Get data paths of oneOf and anyOf errors to later determine whether an error occurred inside a subschema of oneOf or anyOf. const combinatorPaths = filter( @@ -360,7 +360,7 @@ export const errorsAt = ( // because the parent schema can never match the property schema (e.g. for 'required' checks). const parentSchema: JsonSchema | undefined = error.parentSchema; if (result && !isObjectSchema(parentSchema) - && combinatorPaths.findIndex(p => instancePath.startsWith(p)) !== -1) { + && combinatorPaths.findIndex(p => contains(instancePath,p)) !== -1) { result = result && isEqual(parentSchema, schema); } return result; @@ -388,13 +388,13 @@ const isObjectSchema = (schema?: JsonSchema): boolean => { const filteredErrorKeywords = ['additionalProperties', 'allOf', 'anyOf', 'oneOf']; const getErrorsAt = ( - instancePath: string, + instancePath: string[], schema: JsonSchema, - matchPath: (path: string) => boolean + matchPath: (path: string[]) => boolean ) => (state: JsonFormsCore): ErrorObject[] => errorsAt(instancePath, schema, matchPath)(state.validationMode === 'ValidateAndHide' ? [] : state.errors); -export const errorAt = (instancePath: string, schema: JsonSchema) => +export const errorAt = (instancePath: string[], schema: JsonSchema) => getErrorsAt(instancePath, schema, path => path === instancePath); -export const subErrorsAt = (instancePath: string, schema: JsonSchema) => - getErrorsAt(instancePath, schema, path => path.startsWith(instancePath)); +export const subErrorsAt = (instancePath: string[], schema: JsonSchema) => + getErrorsAt(instancePath, schema, path => contains(path,instancePath)); diff --git a/packages/core/src/reducers/reducers.ts b/packages/core/src/reducers/reducers.ts index 38dd2f87a..e44276784 100644 --- a/packages/core/src/reducers/reducers.ts +++ b/packages/core/src/reducers/reducers.ts @@ -91,7 +91,7 @@ export const findUISchema = ( uischemas: JsonFormsUISchemaRegistryEntry[], schema: JsonSchema, schemaPath: string, - path: string, + path: string[], fallbackLayoutType = 'VerticalLayout', control?: ControlElement, rootSchema?: JsonSchema @@ -121,7 +121,7 @@ export const findUISchema = ( return uiSchema; }; -export const getErrorAt = (instancePath: string, schema: JsonSchema) => ( +export const getErrorAt = (instancePath: string[], schema: JsonSchema) => ( state: JsonFormsState ) => { return errorAt(instancePath, schema)(state.jsonforms.core); @@ -129,7 +129,7 @@ export const getErrorAt = (instancePath: string, schema: JsonSchema) => ( export { errorsAt, getControlPath }; -export const getSubErrorsAt = (instancePath: string, schema: JsonSchema) => ( +export const getSubErrorsAt = (instancePath: string[], schema: JsonSchema) => ( state: JsonFormsState ) => subErrorsAt(instancePath, schema)(state.jsonforms.core); diff --git a/packages/core/src/reducers/uischemas.ts b/packages/core/src/reducers/uischemas.ts index 3ebe2e230..632cdd9fa 100644 --- a/packages/core/src/reducers/uischemas.ts +++ b/packages/core/src/reducers/uischemas.ts @@ -33,7 +33,7 @@ import { Reducer } from '../util'; export type UISchemaTester = ( schema: JsonSchema, schemaPath: string, - path: string + path: string[] ) => number; export interface JsonFormsUISchemaRegistryEntry { @@ -64,7 +64,7 @@ export const findMatchingUISchema = ( ) => ( jsonSchema: JsonSchema, schemaPath: string, - path: string + path: string[] ): UISchemaElement => { const match = maxBy(state, entry => entry.tester(jsonSchema, schemaPath, path) diff --git a/packages/core/src/testers/testers.ts b/packages/core/src/testers/testers.ts index 6790b6193..004454d98 100644 --- a/packages/core/src/testers/testers.ts +++ b/packages/core/src/testers/testers.ts @@ -96,7 +96,7 @@ export const schemaMatches = ( }; export const schemaSubPathMatches = ( - subPath: string, + subPath: string[], predicate: (schema: JsonSchema) => boolean ): Tester => (uischema: UISchemaElement, schema: JsonSchema): boolean => { if (isEmpty(uischema) || !isControl(uischema)) { @@ -382,7 +382,7 @@ export const isObjectArray = and( schemaMatches( schema => hasType(schema, 'array') && !Array.isArray(schema.items) // we don't care about tuples ), - schemaSubPathMatches('items', schema => hasType(schema, 'object')) + schemaSubPathMatches(['items'], schema => hasType(schema, 'object')) ); /** @@ -481,7 +481,7 @@ export const isPrimitiveArrayControl = and( schemaMatches( schema => deriveTypes(schema).length !== 0 && !Array.isArray(schema.items) // we don't care about tuples ), - schemaSubPathMatches('items', schema => { + schemaSubPathMatches(['items'], schema => { const types = deriveTypes(schema); return ( types.length === 1 && diff --git a/packages/core/src/util/combinators.ts b/packages/core/src/util/combinators.ts index c89496f5d..25ea71d7f 100644 --- a/packages/core/src/util/combinators.ts +++ b/packages/core/src/util/combinators.ts @@ -70,7 +70,7 @@ export const createCombinatorRenderInfos = ( rootSchema: JsonSchema, keyword: CombinatorKeyword, control: ControlElement, - path: string, + path: string[], uischemas: JsonFormsUISchemaRegistryEntry[] ): CombinatorSubSchemaRenderInfo[] => combinatorSubSchemas.map((subSchema, subSchemaIndex) => ({ diff --git a/packages/core/src/util/path.ts b/packages/core/src/util/path.ts index 24b4ebd8a..52d3331b6 100644 --- a/packages/core/src/util/path.ts +++ b/packages/core/src/util/path.ts @@ -27,18 +27,15 @@ import isEmpty from 'lodash/isEmpty'; import range from 'lodash/range'; import { Scopable } from '../models'; -export const compose = (path1: string, path2: string) => { +export const compose = (path1: string[], path2: string[]) => { let p1 = path1; - if (!isEmpty(path1) && !isEmpty(path2) && !path2.startsWith('[')) { - p1 = path1 + '.'; - } if (isEmpty(p1)) { return path2; } else if (isEmpty(path2)) { return p1; } else { - return `${p1}${path2}`; + return p1.concat(path2); } }; @@ -75,16 +72,32 @@ export const toDataPathSegments = (schemaPath: string): string[] => { * @param {string} schemaPath the schema path to be converted * @returns {string} the path without schema-specific keywords */ -export const toDataPath = (schemaPath: string): string => { - return toDataPathSegments(schemaPath).join('.'); +export const toDataPath = (schemaPath: string): string[] => { + return toDataPathSegments(schemaPath); }; -export const composeWithUi = (scopableUi: Scopable, path: string): string => { +export const composeWithUi = (scopableUi: Scopable, path: string[]): string[] => { const segments = toDataPathSegments(scopableUi.scope); if (isEmpty(segments) && path === undefined) { - return ''; + return []; } - return isEmpty(segments) ? path : compose(path, segments.join('.')); + return isEmpty(segments) ? path : compose(path, segments); }; + +export const toId = (path: string[]): string=>{ + return path.join(''); +} + +export const contains = (path1: string[], path2: string[]):boolean =>{ + if(path1.length{ + if (path1[i]!==value){ + return false; + } + }) + return true; +} \ No newline at end of file diff --git a/packages/core/src/util/renderer.ts b/packages/core/src/util/renderer.ts index 0677029a2..fee0482eb 100644 --- a/packages/core/src/util/renderer.ts +++ b/packages/core/src/util/renderer.ts @@ -208,7 +208,7 @@ export interface OwnPropsOfRenderer { * path can not be inferred via the UI schema element as * it is the case with nested controls. */ - path?: string; + path?: string[]; renderers?: JsonFormsRendererRegistryEntry[]; @@ -267,7 +267,7 @@ export interface StatePropsOfRenderer { /** * Instance path the data is written to, in case of a control. */ - path: string; + path: string[]; /** * All available renderers. @@ -348,7 +348,7 @@ export interface DispatchPropsOfControl { * @param {string} path the path to the data to be updated * @param {any} value the new value that should be written to the given path */ - handleChange(path: string, value: any): void; + handleChange(path: string[], value: any): void; } /** @@ -556,7 +556,7 @@ export const mapStateToMasterListItemProps = ( ); }) : undefined; - const childPath = composePaths(path, `${index}`); + const childPath = composePaths(path, [`${index}`]); const childData = Resolve.data(getData(state), childPath); const childLabel = firstPrimitiveProp ? childData[firstPrimitiveProp] : ''; @@ -578,10 +578,10 @@ export interface StatePropsOfControlWithDetail extends StatePropsOfControl { export interface OwnPropsOfMasterListItem { index: number; selected: boolean; - path: string; + path: string[]; schema: JsonSchema; handleSelect(index: number): () => void; - removeItem(path: string, value: number): () => void; + removeItem(path: string[], value: number): () => void; } export interface StatePropsOfMasterItem extends OwnPropsOfMasterListItem { @@ -653,10 +653,10 @@ export const mapStateToArrayControlProps = ( * Dispatch props of a table control */ export interface DispatchPropsOfArrayControl { - addItem(path: string, value: any): () => void; - removeItems?(path: string, toDelete: number[]): () => void; - moveUp?(path: string, toMove: number): () => void; - moveDown?(path: string, toMove: number): () => void; + addItem(path: string[], value: any): () => void; + removeItems?(path: string[], toDelete: number[]): () => void; + moveUp?(path: string[], toMove: number): () => void; + moveDown?(path: string[], toMove: number): () => void; } /** @@ -668,19 +668,19 @@ export interface DispatchPropsOfArrayControl { export const mapDispatchToArrayControlProps = ( dispatch: Dispatch ): DispatchPropsOfArrayControl => ({ - addItem: (path: string, value: any) => () => { + addItem: (path: string[], value: any) => () => { dispatch( update(path, array => { if (array === undefined || array === null) { return [value]; } - + array.push(value); return array; }) ); }, - removeItems: (path: string, toDelete: number[]) => () => { + removeItems: (path: string[], toDelete: number[]) => () => { dispatch( update(path, array => { toDelete @@ -710,14 +710,14 @@ export const mapDispatchToArrayControlProps = ( }); export interface DispatchPropsOfMultiEnumControl { - addItem: (path: string, value: any) => void; - removeItem?: (path: string, toDelete: any) => void; + addItem: (path: string[], value: any) => void; + removeItem?: (path: string[], toDelete: any) => void; } export const mapDispatchToMultiEnumProps = ( dispatch: Dispatch ): DispatchPropsOfMultiEnumControl => ({ - addItem: (path: string, value: any) => { + addItem: (path: string[], value: any) => { dispatch( update(path, data => { if (data === undefined || data === null) { @@ -728,7 +728,7 @@ export const mapDispatchToMultiEnumProps = ( }) ); }, - removeItem: (path: string, toDelete: any) => { + removeItem: (path: string[], toDelete: any) => { dispatch( update(path, data => { const indexInData = data.indexOf(toDelete); @@ -749,12 +749,12 @@ export interface ArrayControlProps export const layoutDefaultProps: { visible: boolean; enabled: boolean; - path: string; + path: string[]; direction: 'row' | 'column'; } = { visible: true, enabled: true, - path: '', + path: [], direction: 'column' }; @@ -856,7 +856,7 @@ export const controlDefaultProps = { export interface StatePropsOfCombinator extends OwnPropsOfControl { rootSchema: JsonSchema; - path: string; + path: string[]; id: string; indexOfFittingSchema: number; uischemas: JsonFormsUISchemaRegistryEntry[]; diff --git a/packages/core/src/util/resolvers.ts b/packages/core/src/util/resolvers.ts index 9be6c1f30..f38422e49 100644 --- a/packages/core/src/util/resolvers.ts +++ b/packages/core/src/util/resolvers.ts @@ -41,11 +41,11 @@ const isArraySchema = (schema: JsonSchema): boolean => { return schema.type === 'array' && schema.items !== undefined; }; -export const resolveData = (instance: any, dataPath: string): any => { +export const resolveData = (instance: any, dataPath: string[]): any => { if (isEmpty(dataPath)) { return instance; } - const dataPathSegments = dataPath.split('.'); + const dataPathSegments = dataPath; return dataPathSegments .map(segment => decodeURIComponent(segment)) diff --git a/packages/core/src/util/runtime.ts b/packages/core/src/util/runtime.ts index d636f4c70..c6fdbd9a3 100644 --- a/packages/core/src/util/runtime.ts +++ b/packages/core/src/util/runtime.ts @@ -54,14 +54,14 @@ const isSchemaCondition = ( condition: Condition ): condition is SchemaBasedCondition => has(condition, 'schema'); -const getConditionScope = (condition: Scopable, path: string): string => { +const getConditionScope = (condition: Scopable, path: string[]): string[] => { return composeWithUi(condition, path); }; const evaluateCondition = ( data: any, condition: Condition, - path: string, + path: string[], ajv: Ajv ): boolean => { if (isAndCondition(condition)) { @@ -89,7 +89,7 @@ const evaluateCondition = ( const isRuleFulfilled = ( uischema: UISchemaElement, data: any, - path: string, + path: string[], ajv: Ajv ): boolean => { const condition = uischema.rule.condition; @@ -99,7 +99,7 @@ const isRuleFulfilled = ( export const evalVisibility = ( uischema: UISchemaElement, data: any, - path: string = undefined, + path: string[] = undefined, ajv: Ajv ): boolean => { const fulfilled = isRuleFulfilled(uischema, data, path, ajv); @@ -118,7 +118,7 @@ export const evalVisibility = ( export const evalEnablement = ( uischema: UISchemaElement, data: any, - path: string = undefined, + path: string[] = undefined, ajv: Ajv ): boolean => { const fulfilled = isRuleFulfilled(uischema, data, path, ajv); @@ -159,7 +159,7 @@ export const hasEnableRule = (uischema: UISchemaElement): boolean => { export const isVisible = ( uischema: UISchemaElement, data: any, - path: string = undefined, + path: string[] = undefined, ajv: Ajv ): boolean => { if (uischema.rule) { @@ -172,7 +172,7 @@ export const isVisible = ( export const isEnabled = ( uischema: UISchemaElement, data: any, - path: string = undefined, + path: string[] = undefined, ajv: Ajv ): boolean => { if (uischema.rule) { diff --git a/packages/core/src/util/util.ts b/packages/core/src/util/util.ts index 946d5b54d..c1a9a2459 100644 --- a/packages/core/src/util/util.ts +++ b/packages/core/src/util/util.ts @@ -101,7 +101,7 @@ export const Resolve: { schemaPath: string, rootSchema?: JsonSchema ): JsonSchema; - data(data: any, path: string): any; + data(data: any, path: string[]): any; } = { schema: resolveSchema, data: resolveData diff --git a/packages/example/src/util.tsx b/packages/example/src/util.tsx index 7d4037f4e..2ad32b9e1 100644 --- a/packages/example/src/util.tsx +++ b/packages/example/src/util.tsx @@ -206,14 +206,14 @@ export const enhanceExample: (