@abgov/jsonforms-components 2.21.0 → 2.21.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.esm.js CHANGED
@@ -5,7 +5,7 @@ import { GoAFormItem, GoAInput, GoATextArea, GoACallout, GoAInputDate, GoAInputD
5
5
  import styled from 'styled-components';
6
6
  import axios from 'axios';
7
7
  import get$1 from 'lodash/get';
8
- import { rankWith, isStringControl, and, optionIs, uiTypeIs, isDateControl, isNumberControl, isIntegerControl, isDateTimeControl, isTimeControl, isEnumControl, isBooleanControl, getAjv, isVisible, getControlPath, toDataPath, isEnabled, deriveLabelForUISchemaElement, schemaTypeIs, formatIs, createDefaultValue, or, isObjectArrayControl, isPrimitiveArrayControl, Paths, schemaMatches, hasType, isControl, isCategorization, isLayout } from '@jsonforms/core';
8
+ import { rankWith, isStringControl, and, optionIs, uiTypeIs, isDateControl, isNumberControl, isIntegerControl, isDateTimeControl, isTimeControl, isEnumControl, isBooleanControl, getAjv, isVisible, toDataPath, isEnabled, deriveLabelForUISchemaElement, schemaTypeIs, formatIs, createDefaultValue, or, isObjectArrayControl, isPrimitiveArrayControl, Paths, schemaMatches, hasType, isControl, isCategorization, isLayout } from '@jsonforms/core';
9
9
  import { withJsonFormsControlProps, withJsonFormsEnumProps, withTranslateProps, JsonFormsDispatch, useJsonForms, withJsonFormsLayoutProps, withJsonFormsArrayLayoutProps, withJsonFormsAllOfProps, withJsonFormsCellProps } from '@jsonforms/react';
10
10
  import * as _$a from 'lodash';
11
11
  import { isEqual, isEmpty as isEmpty$1, isObject as isObject$f } from 'lodash';
@@ -7509,26 +7509,31 @@ const FormStepperReviewer = props => {
7509
7509
  };
7510
7510
  const FormStepperReviewControl = withAjvProps(withTranslateProps(withJsonFormsLayoutProps(FormStepperReviewer)));
7511
7511
 
7512
- const isErrorPathIncluded = (errorPaths, path) => {
7513
- return errorPaths.some(ePath => {
7514
- /**
7515
- * case A: errorPaths: [name] path: [name]
7516
- *
7517
- * case B: errorPath: [name] path: [name.firstName]
7518
- * */
7519
- return ePath === path || path.startsWith(ePath + '.');
7520
- });
7521
- };
7522
7512
  function isNumber(value) {
7523
7513
  return value != null && value !== '' && !isNaN(Number(value.toString()));
7524
7514
  }
7525
- const getIncompletePaths = (ajv, scopes) => {
7526
- var _a;
7527
- const requiredErrorPaths = (_a = ajv === null || ajv === void 0 ? void 0 : ajv.errors) === null || _a === void 0 ? void 0 : _a.filter(e => e.keyword === 'required' || e.keyword === 'minLength' || e.keyword === 'minItems' || e.keyword === 'errorMessage').map(e => {
7528
- return getControlPath(e);
7529
- });
7530
- const _scopes = scopes.map(scope => toDataPath(scope)).filter(path => requiredErrorPaths && isErrorPathIncluded(requiredErrorPaths, path));
7531
- return _scopes;
7515
+ const getIncompletePaths = (ajv, schema, data, scopes) => {
7516
+ var _a, _b, _c, _d;
7517
+ const incomplete = [];
7518
+ for (const scope of scopes) {
7519
+ const path = toDataPath(scope);
7520
+ const value = get$1(data, path);
7521
+ const schemaPath = path.split('.');
7522
+ let currentSchema = schema;
7523
+ for (const key of schemaPath) {
7524
+ if (!currentSchema || !currentSchema.properties || !currentSchema.properties[key]) {
7525
+ currentSchema = null;
7526
+ break;
7527
+ }
7528
+ currentSchema = currentSchema.properties[key];
7529
+ }
7530
+ const isRequired = schemaPath.length > 1 ? (_c = (_b = (_a = schema === null || schema === void 0 ? void 0 : schema.properties) === null || _a === void 0 ? void 0 : _a[schemaPath[0]]) === null || _b === void 0 ? void 0 : _b.required) === null || _c === void 0 ? void 0 : _c.includes(schemaPath[1]) : (_d = schema === null || schema === void 0 ? void 0 : schema.required) === null || _d === void 0 ? void 0 : _d.includes(path);
7531
+ const hasMinLength = (currentSchema === null || currentSchema === void 0 ? void 0 : currentSchema.minLength) !== undefined;
7532
+ if (isRequired && (value === undefined || value === null || value === '') || hasMinLength && typeof value === 'string' && value.length < currentSchema.minLength) {
7533
+ incomplete.push(path);
7534
+ }
7535
+ }
7536
+ return incomplete;
7532
7537
  };
7533
7538
  const subErrorInParent = (error, paths) => {
7534
7539
  /*
@@ -7556,6 +7561,10 @@ const getErrorsInScopes = (errors, scopes) => {
7556
7561
  return dataPaths.includes(e.instancePath) || subErrorInParent(e, dataPaths);
7557
7562
  });
7558
7563
  };
7564
+ const hasDataInScopes = (data, scopes) => {
7565
+ const dataPaths = scopes.map(s => toDataPath(s));
7566
+ return dataPaths.map(p => get$1(data, p)).some(data => data !== undefined);
7567
+ };
7559
7568
  const getLocalStorageKeyPrefix = () => {
7560
7569
  return window.location.href + '_' + new Date().toISOString().slice(0, 10);
7561
7570
  };
@@ -7645,15 +7654,21 @@ const stepperReducer = (state, action) => {
7645
7654
  const {
7646
7655
  id,
7647
7656
  ajv,
7648
- errors
7657
+ errors = [],
7658
+ schema,
7659
+ data
7649
7660
  } = action.payload;
7650
- if (id === state.categories.length || id === state.categories.length + 1) {
7661
+ if (id >= state.categories.length) {
7651
7662
  return Object.assign({}, state);
7652
7663
  }
7653
- /*
7654
- ctx.core.errors only includes required errors when the fields are touched. In this case, we still ajv to figure out the required errors at the very beginning.
7655
- */
7656
- const incompletePaths = getIncompletePaths(ajv, ((_a = state.categories[id]) === null || _a === void 0 ? void 0 : _a.scopes) || []);
7664
+ if (schema && typeof schema === 'object') {
7665
+ try {
7666
+ ajv.validate(schema, data);
7667
+ } catch (err) {
7668
+ console.warn('AJV validation error:', err);
7669
+ }
7670
+ }
7671
+ const incompletePaths = getIncompletePaths(ajv, schema, data, ((_a = state.categories[id]) === null || _a === void 0 ? void 0 : _a.scopes) || []);
7657
7672
  const errorsInCategory = getErrorsInScopes(errors, ((_b = state.categories[id]) === null || _b === void 0 ? void 0 : _b.scopes) || []);
7658
7673
  if (state.categories[id]) {
7659
7674
  state.categories[id].isCompleted = (incompletePaths === null || incompletePaths === void 0 ? void 0 : incompletePaths.length) === 0;
@@ -7665,7 +7680,7 @@ const stepperReducer = (state, action) => {
7665
7680
  case 'validate/form':
7666
7681
  {
7667
7682
  const {
7668
- errors
7683
+ errors = []
7669
7684
  } = action.payload;
7670
7685
  state.isValid = errors.length === 0;
7671
7686
  return Object.assign({}, state);
@@ -7691,7 +7706,6 @@ const createStepperContextInitData = props => {
7691
7706
  schema,
7692
7707
  ajv,
7693
7708
  t,
7694
- visible,
7695
7709
  path
7696
7710
  } = props;
7697
7711
  const categorization = uischema;
@@ -7700,17 +7714,22 @@ const createStepperContextInitData = props => {
7700
7714
  const isCacheStatus = (_b = uischema.options) === null || _b === void 0 ? void 0 : _b.cacheStatus;
7701
7715
  /* istanbul ignore next */
7702
7716
  const cachedStatus = isCacheStatus && getIsVisitFromLocalStorage() || [];
7717
+ ajv.validate(schema, data);
7703
7718
  const categories = (_c = categorization.elements) === null || _c === void 0 ? void 0 : _c.map((c, id) => {
7704
7719
  const scopes = pickPropertyValues(c, 'scope', 'ListWithDetail');
7705
- const incompletePaths = getIncompletePaths(ajv, scopes) || [];
7720
+ const incompletePaths = getIncompletePaths(ajv, schema, data, scopes);
7721
+ const hasAnyData = hasDataInScopes(data, scopes);
7722
+ const isVisited = isCacheStatus ? cachedStatus.at(id) : hasAnyData;
7723
+ const isCompleted = isVisited && incompletePaths.length === 0;
7724
+ const isValid = isCompleted;
7706
7725
  return {
7707
7726
  id,
7708
7727
  label: deriveLabelForUISchemaElement(c, t),
7709
7728
  scopes,
7710
7729
  /* istanbul ignore next */
7711
- isVisited: isCacheStatus ? cachedStatus.at(id) : false,
7712
- isCompleted: (incompletePaths === null || incompletePaths === void 0 ? void 0 : incompletePaths.length) === 0,
7713
- isValid: (incompletePaths === null || incompletePaths === void 0 ? void 0 : incompletePaths.length) === 0,
7730
+ isVisited,
7731
+ isCompleted,
7732
+ isValid,
7714
7733
  uischema: c,
7715
7734
  showReviewPageLink: props.withBackReviewBtn || false,
7716
7735
  isEnabled: isEnabled(c, data, '', ajv),
@@ -7793,7 +7812,9 @@ const JsonFormsStepperContextProvider = ({
7793
7812
  payload: {
7794
7813
  errors: (_a = ctx === null || ctx === void 0 ? void 0 : ctx.core) === null || _a === void 0 ? void 0 : _a.errors,
7795
7814
  id,
7796
- ajv
7815
+ ajv,
7816
+ schema,
7817
+ data
7797
7818
  }
7798
7819
  });
7799
7820
  },
@@ -7807,7 +7828,9 @@ const JsonFormsStepperContextProvider = ({
7807
7828
  payload: {
7808
7829
  errors: (_b = ctx === null || ctx === void 0 ? void 0 : ctx.core) === null || _b === void 0 ? void 0 : _b.errors,
7809
7830
  id: i,
7810
- ajv
7831
+ ajv,
7832
+ schema,
7833
+ data
7811
7834
  }
7812
7835
  });
7813
7836
  }
@@ -7834,7 +7857,7 @@ const JsonFormsStepperContextProvider = ({
7834
7857
  });
7835
7858
  }
7836
7859
  };
7837
- }, [stepperDispatch, stepperState, (_b = ctx.core) === null || _b === void 0 ? void 0 : _b.errors, ajv]);
7860
+ }, [stepperDispatch, stepperState, (_b = ctx.core) === null || _b === void 0 ? void 0 : _b.errors, ajv, schema, data]);
7838
7861
  /* istanbul ignore next */
7839
7862
  useEffect(() => {
7840
7863
  const handleBeforeUnload = () => {
@@ -11812,6 +11835,9 @@ const FullNameDobControl = props => {
11812
11835
 
11813
11836
  const FullNameDobReviewControl = props => {
11814
11837
  var _a, _b, _c, _d;
11838
+ const {
11839
+ data
11840
+ } = props;
11815
11841
  return jsxs(Fragment, {
11816
11842
  children: [jsxs(GoAGrid, {
11817
11843
  minChildWidth: "0ch",
@@ -11819,6 +11845,7 @@ const FullNameDobReviewControl = props => {
11819
11845
  mb: "m",
11820
11846
  children: [jsx(GoAFormItem, {
11821
11847
  label: "First name",
11848
+ error: (data === null || data === void 0 ? void 0 : data.firstName) === undefined ? 'First name is required' : '',
11822
11849
  requirement: "required",
11823
11850
  children: jsx(TextWrapDiv, {
11824
11851
  children: jsx("div", {
@@ -11836,6 +11863,7 @@ const FullNameDobReviewControl = props => {
11836
11863
  })
11837
11864
  }), jsx(GoAFormItem, {
11838
11865
  label: "Last name",
11866
+ error: (data === null || data === void 0 ? void 0 : data.lastName) === undefined ? 'Last name is required' : '',
11839
11867
  requirement: "required",
11840
11868
  children: jsx(TextWrapDiv, {
11841
11869
  children: jsx("div", {
@@ -11849,6 +11877,7 @@ const FullNameDobReviewControl = props => {
11849
11877
  gap: "s",
11850
11878
  children: jsx(GoAFormItem, {
11851
11879
  label: "Date of birth",
11880
+ error: (data === null || data === void 0 ? void 0 : data.dateOfBirth) === undefined ? 'Date of birth is required' : '',
11852
11881
  requirement: "required",
11853
11882
  children: jsx(TextWrapDiv, {
11854
11883
  children: jsx("div", {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abgov/jsonforms-components",
3
- "version": "2.21.0",
3
+ "version": "2.21.2",
4
4
  "license": "Apache-2.0",
5
5
  "description": "Government of Alberta - React renderers for JSON Forms based on the design system.",
6
6
  "repository": "https://github.com/GovAlta/adsp-monorepo",
@@ -18,6 +18,8 @@ export type StepperAction = {
18
18
  errors?: ErrorObject[];
19
19
  id: number;
20
20
  ajv: Ajv;
21
+ schema: any;
22
+ data: any;
21
23
  };
22
24
  } | {
23
25
  type: 'validate/form';
@@ -1,6 +1,6 @@
1
1
  import Ajv, { ErrorObject } from 'ajv';
2
2
  export declare const isErrorPathIncluded: (errorPaths: string[], path: string) => boolean;
3
- export declare const getIncompletePaths: (ajv: Ajv, scopes: string[]) => string[];
3
+ export declare const getIncompletePaths: (ajv: Ajv, schema: any, data: any, scopes: string[]) => string[];
4
4
  export declare const subErrorInParent: (error: ErrorObject, paths: string[]) => boolean;
5
5
  export declare const getErrorsInScopes: (errors: ErrorObject[], scopes: string[]) => ErrorObject[];
6
6
  export declare const hasDataInScopes: (data: object, scopes: string[]) => boolean;