From 57af38101ccaa096a4389253c4ae2f290312d688 Mon Sep 17 00:00:00 2001 From: Dave Bosley Date: Wed, 19 Aug 2020 12:31:12 -0600 Subject: [PATCH 1/3] always reuse AJV instance from store --- .../src/other/label.renderer.ts | 5 +-- packages/core/src/reducers/core.ts | 1 + packages/core/src/reducers/index.ts | 6 +++- packages/core/src/util/cell.ts | 6 ++-- packages/core/src/util/index.ts | 10 +++--- packages/core/src/util/renderer.ts | 25 ++++++++----- packages/core/src/util/runtime.ts | 35 +++++++++++-------- .../layouts/MaterialCategorizationLayout.tsx | 5 +-- .../MaterialCategorizationStepperLayout.tsx | 5 +-- 9 files changed, 61 insertions(+), 37 deletions(-) diff --git a/packages/angular-material/src/other/label.renderer.ts b/packages/angular-material/src/other/label.renderer.ts index 9bec46855..a0bb076e7 100644 --- a/packages/angular-material/src/other/label.renderer.ts +++ b/packages/angular-material/src/other/label.renderer.ts @@ -35,7 +35,8 @@ import { OwnPropsOfRenderer, RankedTester, rankWith, - uiTypeIs + uiTypeIs, + getOrCreateAjv } from '@jsonforms/core'; import { Subscription } from 'rxjs'; @@ -46,7 +47,7 @@ const mapStateToProps = ( const visible = ownProps.visible !== undefined ? ownProps.visible - : isVisible(ownProps.uischema, getData(state)); + : isVisible(ownProps.uischema, getData(state), undefined, getOrCreateAjv(state)); return { visible diff --git a/packages/core/src/reducers/core.ts b/packages/core/src/reducers/core.ts index a9234c379..03093ec74 100644 --- a/packages/core/src/reducers/core.ts +++ b/packages/core/src/reducers/core.ts @@ -283,6 +283,7 @@ export const coreReducer = ( export const extractData = (state: JsonFormsCore) => get(state, 'data'); export const extractSchema = (state: JsonFormsCore) => get(state, 'schema'); export const extractUiSchema = (state: JsonFormsCore) => get(state, 'uischema'); +export const extractOrCreateAjv = (state: JsonFormsCore) => getOrCreateAjv(state); export const errorsAt = ( instancePath: string, diff --git a/packages/core/src/reducers/index.ts b/packages/core/src/reducers/index.ts index d2053df64..44fb42ded 100644 --- a/packages/core/src/reducers/index.ts +++ b/packages/core/src/reducers/index.ts @@ -32,6 +32,7 @@ import { extractRefParserOptions, extractSchema, extractUiSchema, + extractOrCreateAjv, subErrorsAt, ValidationMode } from './core'; @@ -63,6 +64,7 @@ import RefParser from 'json-schema-ref-parser'; import { cellReducer } from './cells'; import { configReducer } from './config'; import get from 'lodash/get'; +import { Ajv } from 'ajv'; export { rendererReducer, @@ -98,6 +100,9 @@ export const getUiSchema = (state: JsonFormsState): UISchemaElement => extractUiSchema(get(state, 'jsonforms.core')); export const getRefParserOptions = (state: JsonFormsState): RefParser.Options => extractRefParserOptions(get(state, 'jsonforms.core')); +export const getOrCreateAjv = ( + state: JsonFormsState +): Ajv => extractOrCreateAjv(get(state, 'jsonforms.core')); export const getDefaultData = ( state: JsonFormsState ): JsonFormsDefaultDataRegistryEntry[] => @@ -108,7 +113,6 @@ export const getRenderers = ( export const getCells = ( state: JsonFormsState ): JsonFormsCellRendererRegistryEntry[] => get(state, 'jsonforms.cells'); - /** * Finds a registered UI schema to use, if any. * @param schema the JSON schema describing the data to be rendered diff --git a/packages/core/src/util/cell.ts b/packages/core/src/util/cell.ts index 89e37e0cd..ba8fe6661 100644 --- a/packages/core/src/util/cell.ts +++ b/packages/core/src/util/cell.ts @@ -24,7 +24,7 @@ */ import isEmpty from 'lodash/isEmpty'; import union from 'lodash/union'; -import { getConfig, getData, getErrorAt, getSchema } from '../reducers'; +import { getConfig, getData, getErrorAt, getSchema, getOrCreateAjv } from '../reducers'; import { formatErrorMessage, isEnabled, @@ -107,12 +107,12 @@ export const mapStateToCellProps = ( const visible = ownProps.visible !== undefined ? ownProps.visible - : isVisible(uischema, rootData); + : isVisible(uischema, rootData, undefined, getOrCreateAjv(state)); const readOnly = state.jsonforms.readOnly; const enabled = !readOnly && (ownProps.enabled !== undefined ? ownProps.enabled - : isEnabled(uischema, rootData)); + : isEnabled(uischema, rootData, undefined, getOrCreateAjv(state))); const errors = formatErrorMessage( union(getErrorAt(path, schema)(state).map(error => error.message)) ); diff --git a/packages/core/src/util/index.ts b/packages/core/src/util/index.ts index 33c98ee30..e106bf4e8 100644 --- a/packages/core/src/util/index.ts +++ b/packages/core/src/util/index.ts @@ -35,6 +35,8 @@ import { toDataPathSegments } from './path'; import { isEnabled, isVisible } from './runtime'; +import { Ajv } from 'ajv'; +import { createAjv } from './validator'; export { createCleanLabel, createLabelDescriptionFrom } from './label'; @@ -132,11 +134,11 @@ export { composePaths, composeWithUi, Paths, toDataPath }; // Runtime -- const Runtime = { - isEnabled(uischema: UISchemaElement, data: any): boolean { - return isEnabled(uischema, data); + isEnabled(uischema: UISchemaElement, data: any, ajv: Ajv = createAjv()): boolean { + return isEnabled(uischema, data,undefined, ajv); }, - isVisible(uischema: UISchemaElement, data: any): boolean { - return isVisible(uischema, data); + isVisible(uischema: UISchemaElement, data: any, ajv: Ajv = createAjv()): boolean { + return isVisible(uischema, data, undefined, ajv); } }; export { isEnabled, isVisible, Runtime, deriveTypes, hasType }; diff --git a/packages/core/src/util/renderer.ts b/packages/core/src/util/renderer.ts index b58db691e..beba4b7cb 100644 --- a/packages/core/src/util/renderer.ts +++ b/packages/core/src/util/renderer.ts @@ -38,7 +38,8 @@ import { getSchema, getSubErrorsAt, getUiSchema, - UISchemaTester + UISchemaTester, + getOrCreateAjv } from '../reducers'; import { RankedTester } from '../testers'; import { JsonSchema } from '../models/jsonSchema'; @@ -58,7 +59,7 @@ import { resolveSubSchemas } from '../util'; import { update, CoreActions } from '../actions'; -import { ErrorObject } from 'ajv'; +import { ErrorObject, Ajv } from 'ajv'; import { JsonFormsState } from '../store'; import { AnyAction, Dispatch } from 'redux'; import { JsonFormsRendererRegistryEntry } from '../reducers/renderers'; @@ -274,6 +275,12 @@ export interface StatePropsOfRenderer { */ cells?: JsonFormsCellRendererRegistryEntry[]; + + /** + * AJV instance from core state. + */ + + ajv?: Ajv; } /** @@ -395,12 +402,12 @@ export const mapStateToControlProps = ( const path = composeWithUi(uischema, ownProps.path); const visible: boolean = ownProps.visible === undefined || hasShowRule(uischema) - ? isVisible(uischema, rootData, ownProps.path) + ? isVisible(uischema, rootData, ownProps.path, getOrCreateAjv(state)) : ownProps.visible; const readOnly = state.jsonforms.readOnly; const enabled: boolean = !readOnly && (ownProps.enabled === undefined || hasEnableRule(uischema) - ? isEnabled(uischema, rootData, ownProps.path) + ? isEnabled(uischema, rootData, ownProps.path, getOrCreateAjv(state) ) : ownProps.enabled); const controlElement = uischema as ControlElement; const id = ownProps.id; @@ -702,15 +709,16 @@ export const mapStateToLayoutProps = ( ownProps: OwnPropsOfLayout ): LayoutProps => { const rootData = getData(state); + const ajv = getOrCreateAjv(state); const { uischema } = ownProps; const visible: boolean = ownProps.visible === undefined || hasShowRule(uischema) - ? isVisible(ownProps.uischema, rootData, ownProps.path) + ? isVisible(ownProps.uischema, rootData, ownProps.path, getOrCreateAjv(state)) : ownProps.visible; const readOnly = state.jsonforms.readOnly; const enabled: boolean = !readOnly && (ownProps.enabled === undefined || hasEnableRule(uischema) - ? isEnabled(ownProps.uischema, rootData, ownProps.path) + ? isEnabled(ownProps.uischema, rootData, ownProps.path, getOrCreateAjv(state)) : ownProps.enabled); const data = Resolve.data(rootData, ownProps.path); @@ -725,7 +733,8 @@ export const mapStateToLayoutProps = ( data, uischema: ownProps.uischema, schema: ownProps.schema, - direction: ownProps.direction || layoutDefaultProps.direction + direction: ownProps.direction || layoutDefaultProps.direction, + ajv }; }; @@ -800,7 +809,7 @@ const mapStateToCombinatorRendererProps = ( ); const visible: boolean = ownProps.visible === undefined || hasShowRule(uischema) - ? isVisible(uischema, getData(state), ownProps.path) + ? isVisible(uischema, getData(state), ownProps.path, getOrCreateAjv(state)) : ownProps.visible; const id = ownProps.id; diff --git a/packages/core/src/util/runtime.ts b/packages/core/src/util/runtime.ts index ad773fb3d..6fc753bac 100644 --- a/packages/core/src/util/runtime.ts +++ b/packages/core/src/util/runtime.ts @@ -36,8 +36,7 @@ import { import { resolveData } from './resolvers'; import { composeWithUi } from './path'; import { createAjv } from './validator'; - -const ajv = createAjv(); +import { Ajv } from 'ajv'; const isOrCondition = (condition: Condition): condition is OrCondition => condition.type === 'OR'; @@ -59,16 +58,17 @@ const getConditionScope = (condition: Scopable, path: string): string => { const evaluateCondition = ( data: any, condition: Condition, - path: string + path: string, + ajv: Ajv ): boolean => { if (isAndCondition(condition)) { return condition.conditions.reduce( - (acc, cur) => acc && evaluateCondition(data, cur, path), + (acc, cur) => acc && evaluateCondition(data, cur, path, ajv), true ); } else if (isOrCondition(condition)) { return condition.conditions.reduce( - (acc, cur) => acc || evaluateCondition(data, cur, path), + (acc, cur) => acc || evaluateCondition(data, cur, path, ajv), false ); } else if (isLeafCondition(condition)) { @@ -86,18 +86,20 @@ const evaluateCondition = ( const isRuleFulfilled = ( uischema: UISchemaElement, data: any, - path: string + path: string, + ajv: Ajv ): boolean => { const condition = uischema.rule.condition; - return evaluateCondition(data, condition, path); + return evaluateCondition(data, condition, path, ajv); }; export const evalVisibility = ( uischema: UISchemaElement, data: any, - path: string = undefined + path: string = undefined, + ajv: Ajv = createAjv() ): boolean => { - const fulfilled = isRuleFulfilled(uischema, data, path); + const fulfilled = isRuleFulfilled(uischema, data, path, ajv); switch (uischema.rule.effect) { case RuleEffect.HIDE: @@ -113,9 +115,10 @@ export const evalVisibility = ( export const evalEnablement = ( uischema: UISchemaElement, data: any, - path: string = undefined + path: string = undefined, + ajv: Ajv = createAjv() ): boolean => { - const fulfilled = isRuleFulfilled(uischema, data, path); + const fulfilled = isRuleFulfilled(uischema, data, path, ajv); switch (uischema.rule.effect) { case RuleEffect.DISABLE: @@ -153,10 +156,11 @@ export const hasEnableRule = (uischema: UISchemaElement): boolean => { export const isVisible = ( uischema: UISchemaElement, data: any, - path: string = undefined + path: string = undefined, + ajv: Ajv = createAjv() ): boolean => { if (uischema.rule) { - return evalVisibility(uischema, data, path); + return evalVisibility(uischema, data, path, ajv); } return true; @@ -165,10 +169,11 @@ export const isVisible = ( export const isEnabled = ( uischema: UISchemaElement, data: any, - path: string = undefined + path: string = undefined, + ajv: Ajv = createAjv() ): boolean => { if (uischema.rule) { - return evalEnablement(uischema, data, path); + return evalEnablement(uischema, data, path, ajv); } return true; diff --git a/packages/material/src/layouts/MaterialCategorizationLayout.tsx b/packages/material/src/layouts/MaterialCategorizationLayout.tsx index 12fe185e6..cc4f1456b 100644 --- a/packages/material/src/layouts/MaterialCategorizationLayout.tsx +++ b/packages/material/src/layouts/MaterialCategorizationLayout.tsx @@ -92,7 +92,8 @@ export class MaterialCategorizationLayoutRenderer extends RendererComponent< uischema, visible, enabled, - selected + selected, + ajv } = this.props; const categorization = uischema as Categorization; const value = this.hasOwnState() ? this.state.activeCategory : selected; @@ -107,7 +108,7 @@ export class MaterialCategorizationLayoutRenderer extends RendererComponent< cells }; const categories = categorization.elements.filter((category: Category) => - isVisible(category, data) + isVisible(category, data, undefined, ajv) ); return ( diff --git a/packages/material/src/layouts/MaterialCategorizationStepperLayout.tsx b/packages/material/src/layouts/MaterialCategorizationStepperLayout.tsx index f574ca9c2..0866b3c44 100644 --- a/packages/material/src/layouts/MaterialCategorizationStepperLayout.tsx +++ b/packages/material/src/layouts/MaterialCategorizationStepperLayout.tsx @@ -82,7 +82,8 @@ export class MaterialCategorizationStepperLayoutRenderer extends RendererCompone uischema, visible, cells, - config + config, + ajv } = this.props; const categorization = uischema as Categorization; const activeCategory = this.state.activeCategory; @@ -108,7 +109,7 @@ export class MaterialCategorizationStepperLayoutRenderer extends RendererCompone cells }; const categories = categorization.elements.filter((category: Category) => - isVisible(category, data) + isVisible(category, data, undefined, ajv) ); return ( From 1cd9a32c228234b213d06537e3e4122476d417d0 Mon Sep 17 00:00:00 2001 From: Dave Bosley Date: Thu, 20 Aug 2020 11:05:26 -0600 Subject: [PATCH 2/3] Changes requested in PR review --- .../src/other/label.renderer.ts | 4 +-- packages/core/src/reducers/core.ts | 2 +- packages/core/src/reducers/index.ts | 6 ++--- packages/core/src/util/cell.ts | 6 ++--- packages/core/src/util/index.ts | 5 ++-- packages/core/src/util/renderer.ts | 26 +++++++------------ .../layouts/MaterialCategorizationLayout.tsx | 8 +++--- .../MaterialCategorizationStepperLayout.tsx | 14 +++++----- packages/material/src/util/layout.tsx | 21 ++++++++++++--- packages/react/src/JsonFormsContext.tsx | 4 ++- 10 files changed, 54 insertions(+), 42 deletions(-) diff --git a/packages/angular-material/src/other/label.renderer.ts b/packages/angular-material/src/other/label.renderer.ts index a0bb076e7..a4c66245b 100644 --- a/packages/angular-material/src/other/label.renderer.ts +++ b/packages/angular-material/src/other/label.renderer.ts @@ -36,7 +36,7 @@ import { RankedTester, rankWith, uiTypeIs, - getOrCreateAjv + getAjv } from '@jsonforms/core'; import { Subscription } from 'rxjs'; @@ -47,7 +47,7 @@ const mapStateToProps = ( const visible = ownProps.visible !== undefined ? ownProps.visible - : isVisible(ownProps.uischema, getData(state), undefined, getOrCreateAjv(state)); + : isVisible(ownProps.uischema, getData(state), undefined, getAjv(state)); return { visible diff --git a/packages/core/src/reducers/core.ts b/packages/core/src/reducers/core.ts index 03093ec74..26f0a46f7 100644 --- a/packages/core/src/reducers/core.ts +++ b/packages/core/src/reducers/core.ts @@ -283,7 +283,7 @@ export const coreReducer = ( export const extractData = (state: JsonFormsCore) => get(state, 'data'); export const extractSchema = (state: JsonFormsCore) => get(state, 'schema'); export const extractUiSchema = (state: JsonFormsCore) => get(state, 'uischema'); -export const extractOrCreateAjv = (state: JsonFormsCore) => getOrCreateAjv(state); +export const extractAjv = (state: JsonFormsCore) => get(state, 'ajv'); export const errorsAt = ( instancePath: string, diff --git a/packages/core/src/reducers/index.ts b/packages/core/src/reducers/index.ts index 44fb42ded..d1a36c2a6 100644 --- a/packages/core/src/reducers/index.ts +++ b/packages/core/src/reducers/index.ts @@ -28,11 +28,11 @@ import { coreReducer, errorAt, errorsAt, + extractAjv, extractData, extractRefParserOptions, extractSchema, extractUiSchema, - extractOrCreateAjv, subErrorsAt, ValidationMode } from './core'; @@ -100,9 +100,9 @@ export const getUiSchema = (state: JsonFormsState): UISchemaElement => extractUiSchema(get(state, 'jsonforms.core')); export const getRefParserOptions = (state: JsonFormsState): RefParser.Options => extractRefParserOptions(get(state, 'jsonforms.core')); -export const getOrCreateAjv = ( +export const getAjv = ( state: JsonFormsState -): Ajv => extractOrCreateAjv(get(state, 'jsonforms.core')); +): Ajv => extractAjv(get(state, 'jsonforms.core')); export const getDefaultData = ( state: JsonFormsState ): JsonFormsDefaultDataRegistryEntry[] => diff --git a/packages/core/src/util/cell.ts b/packages/core/src/util/cell.ts index ba8fe6661..160380831 100644 --- a/packages/core/src/util/cell.ts +++ b/packages/core/src/util/cell.ts @@ -24,7 +24,7 @@ */ import isEmpty from 'lodash/isEmpty'; import union from 'lodash/union'; -import { getConfig, getData, getErrorAt, getSchema, getOrCreateAjv } from '../reducers'; +import { getConfig, getData, getErrorAt, getSchema, getAjv } from '../reducers'; import { formatErrorMessage, isEnabled, @@ -107,12 +107,12 @@ export const mapStateToCellProps = ( const visible = ownProps.visible !== undefined ? ownProps.visible - : isVisible(uischema, rootData, undefined, getOrCreateAjv(state)); + : isVisible(uischema, rootData, undefined, getAjv(state)); const readOnly = state.jsonforms.readOnly; const enabled = !readOnly && (ownProps.enabled !== undefined ? ownProps.enabled - : isEnabled(uischema, rootData, undefined, getOrCreateAjv(state))); + : isEnabled(uischema, rootData, undefined, getAjv(state))); const errors = formatErrorMessage( union(getErrorAt(path, schema)(state).map(error => error.message)) ); diff --git a/packages/core/src/util/index.ts b/packages/core/src/util/index.ts index e106bf4e8..748d9c580 100644 --- a/packages/core/src/util/index.ts +++ b/packages/core/src/util/index.ts @@ -36,7 +36,6 @@ import { } from './path'; import { isEnabled, isVisible } from './runtime'; import { Ajv } from 'ajv'; -import { createAjv } from './validator'; export { createCleanLabel, createLabelDescriptionFrom } from './label'; @@ -134,10 +133,10 @@ export { composePaths, composeWithUi, Paths, toDataPath }; // Runtime -- const Runtime = { - isEnabled(uischema: UISchemaElement, data: any, ajv: Ajv = createAjv()): boolean { + isEnabled(uischema: UISchemaElement, data: any, ajv: Ajv): boolean { return isEnabled(uischema, data,undefined, ajv); }, - isVisible(uischema: UISchemaElement, data: any, ajv: Ajv = createAjv()): boolean { + isVisible(uischema: UISchemaElement, data: any, ajv: Ajv): boolean { return isVisible(uischema, data, undefined, ajv); } }; diff --git a/packages/core/src/util/renderer.ts b/packages/core/src/util/renderer.ts index beba4b7cb..8e1a902f2 100644 --- a/packages/core/src/util/renderer.ts +++ b/packages/core/src/util/renderer.ts @@ -29,6 +29,7 @@ import find from 'lodash/find'; import RefParser from 'json-schema-ref-parser'; import { findUISchema, + getAjv, getCells, getConfig, getData, @@ -38,8 +39,7 @@ import { getSchema, getSubErrorsAt, getUiSchema, - UISchemaTester, - getOrCreateAjv + UISchemaTester } from '../reducers'; import { RankedTester } from '../testers'; import { JsonSchema } from '../models/jsonSchema'; @@ -59,7 +59,7 @@ import { resolveSubSchemas } from '../util'; import { update, CoreActions } from '../actions'; -import { ErrorObject, Ajv } from 'ajv'; +import { ErrorObject } from 'ajv'; import { JsonFormsState } from '../store'; import { AnyAction, Dispatch } from 'redux'; import { JsonFormsRendererRegistryEntry } from '../reducers/renderers'; @@ -275,12 +275,6 @@ export interface StatePropsOfRenderer { */ cells?: JsonFormsCellRendererRegistryEntry[]; - - /** - * AJV instance from core state. - */ - - ajv?: Ajv; } /** @@ -402,12 +396,12 @@ export const mapStateToControlProps = ( const path = composeWithUi(uischema, ownProps.path); const visible: boolean = ownProps.visible === undefined || hasShowRule(uischema) - ? isVisible(uischema, rootData, ownProps.path, getOrCreateAjv(state)) + ? isVisible(uischema, rootData, ownProps.path, getAjv(state)) : ownProps.visible; const readOnly = state.jsonforms.readOnly; const enabled: boolean = !readOnly && (ownProps.enabled === undefined || hasEnableRule(uischema) - ? isEnabled(uischema, rootData, ownProps.path, getOrCreateAjv(state) ) + ? isEnabled(uischema, rootData, ownProps.path, getAjv(state) ) : ownProps.enabled); const controlElement = uischema as ControlElement; const id = ownProps.id; @@ -709,16 +703,15 @@ export const mapStateToLayoutProps = ( ownProps: OwnPropsOfLayout ): LayoutProps => { const rootData = getData(state); - const ajv = getOrCreateAjv(state); const { uischema } = ownProps; const visible: boolean = ownProps.visible === undefined || hasShowRule(uischema) - ? isVisible(ownProps.uischema, rootData, ownProps.path, getOrCreateAjv(state)) + ? isVisible(ownProps.uischema, rootData, ownProps.path, getAjv(state)) : ownProps.visible; const readOnly = state.jsonforms.readOnly; const enabled: boolean = !readOnly && (ownProps.enabled === undefined || hasEnableRule(uischema) - ? isEnabled(ownProps.uischema, rootData, ownProps.path, getOrCreateAjv(state)) + ? isEnabled(ownProps.uischema, rootData, ownProps.path, getAjv(state)) : ownProps.enabled); const data = Resolve.data(rootData, ownProps.path); @@ -733,8 +726,7 @@ export const mapStateToLayoutProps = ( data, uischema: ownProps.uischema, schema: ownProps.schema, - direction: ownProps.direction || layoutDefaultProps.direction, - ajv + direction: ownProps.direction || layoutDefaultProps.direction }; }; @@ -809,7 +801,7 @@ const mapStateToCombinatorRendererProps = ( ); const visible: boolean = ownProps.visible === undefined || hasShowRule(uischema) - ? isVisible(uischema, getData(state), ownProps.path, getOrCreateAjv(state)) + ? isVisible(uischema, getData(state), ownProps.path, getAjv(state)) : ownProps.visible; const id = ownProps.id; diff --git a/packages/material/src/layouts/MaterialCategorizationLayout.tsx b/packages/material/src/layouts/MaterialCategorizationLayout.tsx index cc4f1456b..2f369f866 100644 --- a/packages/material/src/layouts/MaterialCategorizationLayout.tsx +++ b/packages/material/src/layouts/MaterialCategorizationLayout.tsx @@ -39,8 +39,10 @@ import { } from '@jsonforms/core'; import { RendererComponent, withJsonFormsLayoutProps } from '@jsonforms/react'; import { + AjvProps, MaterialLayoutRenderer, - MaterialLayoutRendererProps + MaterialLayoutRendererProps, + withAjvProps } from '../util/layout'; export const isSingleLevelCategorization: Tester = and( @@ -67,7 +69,7 @@ export interface CategorizationState { } export interface MaterialCategorizationLayoutRendererProps - extends StatePropsOfLayout { + extends StatePropsOfLayout, AjvProps { selected?: number; ownState?: boolean; data?: any; @@ -141,4 +143,4 @@ export class MaterialCategorizationLayoutRenderer extends RendererComponent< }; } -export default withJsonFormsLayoutProps(MaterialCategorizationLayoutRenderer); +export default withJsonFormsLayoutProps(withAjvProps(MaterialCategorizationLayoutRenderer)); diff --git a/packages/material/src/layouts/MaterialCategorizationStepperLayout.tsx b/packages/material/src/layouts/MaterialCategorizationStepperLayout.tsx index 0866b3c44..b2b122933 100644 --- a/packages/material/src/layouts/MaterialCategorizationStepperLayout.tsx +++ b/packages/material/src/layouts/MaterialCategorizationStepperLayout.tsx @@ -39,8 +39,10 @@ import { } from '@jsonforms/core'; import { RendererComponent, withJsonFormsLayoutProps } from '@jsonforms/react'; import { + AjvProps, MaterialLayoutRenderer, - MaterialLayoutRendererProps + MaterialLayoutRendererProps, + withAjvProps } from '../util/layout'; export const materialCategorizationStepperTester: RankedTester = rankWith( @@ -57,8 +59,8 @@ export interface CategorizationStepperState { } export interface MaterialCategorizationStepperLayoutRendererProps - extends StatePropsOfLayout { - data: any; + extends StatePropsOfLayout, AjvProps { + data: any; } export class MaterialCategorizationStepperLayoutRenderer extends RendererComponent< @@ -97,7 +99,7 @@ export class MaterialCategorizationStepperLayoutRenderer extends RendererCompone float: 'right' as 'right' }; const buttonStyle = { - marginRight: '1em' + marginRight: '1em' }; const childProps: MaterialLayoutRendererProps = { elements: categorization.elements[activeCategory].elements, @@ -150,6 +152,6 @@ export class MaterialCategorizationStepperLayoutRenderer extends RendererCompone } } -export default withJsonFormsLayoutProps( +export default withJsonFormsLayoutProps(withAjvProps( MaterialCategorizationStepperLayoutRenderer -); +)); diff --git a/packages/material/src/util/layout.tsx b/packages/material/src/util/layout.tsx index 5033557b2..dd0d24cdf 100644 --- a/packages/material/src/util/layout.tsx +++ b/packages/material/src/util/layout.tsx @@ -24,14 +24,17 @@ */ import isEmpty from 'lodash/isEmpty'; import React from 'react'; +import { ComponentType } from 'react'; +import { Ajv } from 'ajv'; import { + getAjv, + JsonFormsCellRendererRegistryEntry, JsonFormsRendererRegistryEntry, JsonSchema, OwnPropsOfRenderer, - UISchemaElement, - JsonFormsCellRendererRegistryEntry + UISchemaElement } from '@jsonforms/core'; -import { areEqual, ResolvedJsonFormsDispatch } from '@jsonforms/react'; +import { areEqual, ResolvedJsonFormsDispatch, useJsonForms } from '@jsonforms/react'; import { Grid, Hidden } from '@material-ui/core'; export const renderLayoutElements = ( @@ -96,3 +99,15 @@ export const MaterialLayoutRenderer = React.memo( }, areEqual ); + +export interface AjvProps { + ajv: Ajv; +} + +export const withAjvProps =

(Component: ComponentType) => + (props: P) => { + const ctx = useJsonForms(); + const ajv = getAjv({jsonforms: {...ctx}}); + + return (); + }; diff --git a/packages/react/src/JsonFormsContext.tsx b/packages/react/src/JsonFormsContext.tsx index 35d5e263e..b6637caaa 100644 --- a/packages/react/src/JsonFormsContext.tsx +++ b/packages/react/src/JsonFormsContext.tsx @@ -367,7 +367,7 @@ const withContextToCellProps = (Component: ComponentType): ComponentType => ({ ctx, props }: JsonFormsStateContext & CellProps) => { const cellProps = ctxToCellProps(ctx, props); - const dispatchProps = ctxDispatchToControlProps(ctx.dispatch) + const dispatchProps = ctxDispatchToControlProps(ctx.dispatch); return (); }; @@ -400,6 +400,7 @@ const withContextToEnumProps = const dispatchProps = ctxDispatchToControlProps(ctx.dispatch); return (); }; + const withContextToOneOfEnumProps = (Component: ComponentType): ComponentType => ({ ctx, props }: JsonFormsStateContext & ControlProps & OwnPropsOfEnum) => { @@ -520,6 +521,7 @@ export const withJsonFormsEnumProps = Component, (prevProps: ControlProps & OwnPropsOfEnum, nextProps: ControlProps & OwnPropsOfEnum) => isEqual(prevProps, nextProps) ))); + export const withJsonFormsOneOfEnumProps = (Component: ComponentType): ComponentType => withJsonFormsContext(withContextToOneOfEnumProps(React.memo( From 5bf26f3e5b4637c51ba02b8920639d9455720c4b Mon Sep 17 00:00:00 2001 From: Stefan Dirix Date: Fri, 21 Aug 2020 16:45:50 +0200 Subject: [PATCH 3/3] Remove default ajv --- packages/core/src/util/runtime.ts | 9 ++-- packages/core/test/util/runtime.test.ts | 47 ++++++++++--------- ...terialCategorizationStepperLayout.test.tsx | 12 +++-- 3 files changed, 35 insertions(+), 33 deletions(-) diff --git a/packages/core/src/util/runtime.ts b/packages/core/src/util/runtime.ts index 6fc753bac..11f2908a3 100644 --- a/packages/core/src/util/runtime.ts +++ b/packages/core/src/util/runtime.ts @@ -35,7 +35,6 @@ import { } from '../models/uischema'; import { resolveData } from './resolvers'; import { composeWithUi } from './path'; -import { createAjv } from './validator'; import { Ajv } from 'ajv'; const isOrCondition = (condition: Condition): condition is OrCondition => @@ -97,7 +96,7 @@ export const evalVisibility = ( uischema: UISchemaElement, data: any, path: string = undefined, - ajv: Ajv = createAjv() + ajv: Ajv ): boolean => { const fulfilled = isRuleFulfilled(uischema, data, path, ajv); @@ -116,7 +115,7 @@ export const evalEnablement = ( uischema: UISchemaElement, data: any, path: string = undefined, - ajv: Ajv = createAjv() + ajv: Ajv ): boolean => { const fulfilled = isRuleFulfilled(uischema, data, path, ajv); @@ -157,7 +156,7 @@ export const isVisible = ( uischema: UISchemaElement, data: any, path: string = undefined, - ajv: Ajv = createAjv() + ajv: Ajv ): boolean => { if (uischema.rule) { return evalVisibility(uischema, data, path, ajv); @@ -170,7 +169,7 @@ export const isEnabled = ( uischema: UISchemaElement, data: any, path: string = undefined, - ajv: Ajv = createAjv() + ajv: Ajv ): boolean => { if (uischema.rule) { return evalEnablement(uischema, data, path, ajv); diff --git a/packages/core/test/util/runtime.test.ts b/packages/core/test/util/runtime.test.ts index be823d3f4..15f9559f6 100644 --- a/packages/core/test/util/runtime.test.ts +++ b/packages/core/test/util/runtime.test.ts @@ -26,6 +26,7 @@ import test from 'ava'; import { AndCondition, ControlElement, + createAjv, LeafCondition, OrCondition, RuleEffect, @@ -51,7 +52,7 @@ test('evalVisibility show valid case', t => { value: 'foo', ruleValue: 'bar' }; - t.is(evalVisibility(uischema, data), true); + t.is(evalVisibility(uischema, data, undefined, createAjv()), true); }); test('evalVisibility show valid case based on AndCondition', t => { @@ -82,7 +83,7 @@ test('evalVisibility show valid case based on AndCondition', t => { ruleValue1: 'bar', ruleValue2: 'foo' }; - t.is(evalVisibility(uischema, data), true); + t.is(evalVisibility(uischema, data, undefined, createAjv()), true); }); test('evalVisibility show invalid case based on AndCondition', t => { @@ -113,7 +114,7 @@ test('evalVisibility show invalid case based on AndCondition', t => { ruleValue1: 'bar', ruleValue2: 'foo' }; - t.is(evalVisibility(uischema, data), false); + t.is(evalVisibility(uischema, data, undefined, createAjv()), false); }); test('evalVisibility show valid case based on OrCondition', t => { @@ -144,7 +145,7 @@ test('evalVisibility show valid case based on OrCondition', t => { ruleValue1: 'bar1', ruleValue2: 'foo' }; - t.is(evalVisibility(uischema, data), true); + t.is(evalVisibility(uischema, data, undefined, createAjv()), true); }); test('evalVisibility show invalid case based on OrCondition', t => { @@ -175,7 +176,7 @@ test('evalVisibility show invalid case based on OrCondition', t => { ruleValue1: 'bar', ruleValue2: 'foo' }; - t.is(evalVisibility(uischema, data), false); + t.is(evalVisibility(uischema, data, undefined, createAjv()), false); }); test('evalVisibility show valid case based on schema condition', t => { @@ -197,7 +198,7 @@ test('evalVisibility show valid case based on schema condition', t => { value: 'foo', ruleValue: 'bar' }; - t.is(evalVisibility(uischema, data), true); + t.is(evalVisibility(uischema, data, undefined, createAjv()), true); }); test('evalVisibility show valid case based on schema condition and enum', t => { @@ -219,9 +220,9 @@ test('evalVisibility show valid case based on schema condition and enum', t => { value: 'foo', ruleValue: 'bar' }; - t.is(evalVisibility(uischema, data), true); - t.is(evalVisibility(uischema, { ...data, ruleValue: 'baz' }), true); - t.is(evalVisibility(uischema, { ...data, ruleValue: 'foo' }), false); + t.is(evalVisibility(uischema, data, undefined, createAjv()), true); + t.is(evalVisibility(uischema, { ...data, ruleValue: 'baz' }, undefined, createAjv()), true); + t.is(evalVisibility(uischema, { ...data, ruleValue: 'foo' }, undefined, createAjv()), false); }); test('evalVisibility show invalid case', t => { @@ -242,7 +243,7 @@ test('evalVisibility show invalid case', t => { value: 'foo', ruleValue: 'foobar' }; - t.deepEqual(evalVisibility(uischema, data), false); + t.deepEqual(evalVisibility(uischema, data, undefined, createAjv()), false); }); test('evalVisibility hide valid case', t => { const leafCondition: LeafCondition = { @@ -262,7 +263,7 @@ test('evalVisibility hide valid case', t => { value: 'foo', ruleValue: 'bar' }; - t.is(evalVisibility(uischema, data), false); + t.is(evalVisibility(uischema, data, undefined, createAjv()), false); }); test('evalVisibility hide invalid case', t => { @@ -283,7 +284,7 @@ test('evalVisibility hide invalid case', t => { value: 'foo', ruleValue: 'foobar' }; - t.is(evalVisibility(uischema, data), true); + t.is(evalVisibility(uischema, data, undefined, createAjv()), true); }); test('evalEnablement enable valid case', t => { @@ -304,7 +305,7 @@ test('evalEnablement enable valid case', t => { value: 'foo', ruleValue: 'bar' }; - t.is(evalEnablement(uischema, data), true); + t.is(evalEnablement(uischema, data, undefined, createAjv()), true); }); test('evalEnablement show valid case based on AndCondition', t => { @@ -335,7 +336,7 @@ test('evalEnablement show valid case based on AndCondition', t => { ruleValue1: 'bar', ruleValue2: 'foo' }; - t.is(evalEnablement(uischema, data), true); + t.is(evalEnablement(uischema, data, undefined, createAjv()), true); }); test('evalEnablement show invalid case based on AndCondition', t => { @@ -366,7 +367,7 @@ test('evalEnablement show invalid case based on AndCondition', t => { ruleValue1: 'bar', ruleValue2: 'foo' }; - t.is(evalEnablement(uischema, data), false); + t.is(evalEnablement(uischema, data, undefined, createAjv()), false); }); test('evalEnablement show valid case based on OrCondition', t => { @@ -397,7 +398,7 @@ test('evalEnablement show valid case based on OrCondition', t => { ruleValue1: 'bar1', ruleValue2: 'foo' }; - t.is(evalEnablement(uischema, data), true); + t.is(evalEnablement(uischema, data, undefined, createAjv()), true); }); test('evalEnablement show invalid case based on OrCondition', t => { @@ -428,7 +429,7 @@ test('evalEnablement show invalid case based on OrCondition', t => { ruleValue1: 'bar', ruleValue2: 'foo' }; - t.is(evalEnablement(uischema, data), false); + t.is(evalEnablement(uischema, data, undefined, createAjv()), false); }); test('evalEnablement enable invalid case', t => { @@ -449,7 +450,7 @@ test('evalEnablement enable invalid case', t => { value: 'foo', ruleValue: 'foobar' }; - t.is(evalEnablement(uischema, data), false); + t.is(evalEnablement(uischema, data, undefined, createAjv()), false); }); test('evalEnablement disable valid case', t => { const leafCondition: LeafCondition = { @@ -469,7 +470,7 @@ test('evalEnablement disable valid case', t => { value: 'foo', ruleValue: 'bar' }; - t.is(evalEnablement(uischema, data), false); + t.is(evalEnablement(uischema, data, undefined, createAjv()), false); }); test('evalEnablement disable invalid case', t => { @@ -490,7 +491,7 @@ test('evalEnablement disable invalid case', t => { value: 'foo', ruleValue: 'foobar' }; - t.is(evalEnablement(uischema, data), true); + t.is(evalEnablement(uischema, data, undefined, createAjv()), true); }); test('evalEnablement disable invalid case based on schema condition', t => { @@ -512,7 +513,7 @@ test('evalEnablement disable invalid case based on schema condition', t => { value: 'foo', ruleValue: 'bar' }; - t.is(evalEnablement(uischema, data), false); - t.is(evalEnablement(uischema, { ...data, ruleValue: 'baz' }), false); - t.is(evalEnablement(uischema, { ...data, ruleValue: 'foo' }), true); + t.is(evalEnablement(uischema, data, undefined, createAjv()), false); + t.is(evalEnablement(uischema, { ...data, ruleValue: 'baz' }, undefined, createAjv()), false); + t.is(evalEnablement(uischema, { ...data, ruleValue: 'foo' }, undefined, createAjv()), true); }); diff --git a/packages/material/test/renderers/MaterialCategorizationStepperLayout.test.tsx b/packages/material/test/renderers/MaterialCategorizationStepperLayout.test.tsx index 9a821d249..c01142fc3 100644 --- a/packages/material/test/renderers/MaterialCategorizationStepperLayout.test.tsx +++ b/packages/material/test/renderers/MaterialCategorizationStepperLayout.test.tsx @@ -378,11 +378,13 @@ describe('Material categorization stepper layout', () => { const store = initJsonFormsStore(fixture); const wrapper = mount( - + + + );