swoop-common 2.0.7 → 2.0.8

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.
@@ -243,7 +243,7 @@ const unwrapHydra = (json) => {
243
243
  // Get keys
244
244
  const keys = Object.keys(context);
245
245
  if (keys.length != 3) {
246
- console.log("Unexpected number of keys within hydra context:", keys);
246
+ console.error("Unexpected number of keys within hydra context:", keys);
247
247
  return json;
248
248
  }
249
249
  // Get the key that is not hydra
@@ -251,7 +251,7 @@ const unwrapHydra = (json) => {
251
251
  // Main WILL exist, as there are 3 keys and filter max 2
252
252
  const data = json[main];
253
253
  if (!data) {
254
- console.log("Hydra defined key did not exist within object:", Object.keys(json));
254
+ console.error("Hydra defined key did not exist within object:", Object.keys(json));
255
255
  return json;
256
256
  }
257
257
  return data;
@@ -1,6 +1,11 @@
1
1
  import * as Core from "./generated/core/index";
2
2
  import * as Itinerary from "./generated/itinerary/index";
3
3
  import * as Swoop from "./generated/swoop/index";
4
+ export declare const InternalServices: {
5
+ SwoopService: Swoop.SwoopService;
6
+ CoreService: Core.CoreService;
7
+ ItineraryService: Itinerary.ItineraryService;
8
+ };
4
9
  export declare const init: (opts: {
5
10
  itineraryServiceUrl: string;
6
11
  coreServiceUrl: string;
package/dist/api/init.js CHANGED
@@ -2,6 +2,12 @@ import * as Core from "./generated/core/index";
2
2
  import * as Itinerary from "./generated/itinerary/index";
3
3
  import * as Swoop from "./generated/swoop/index";
4
4
  let initalised = false;
5
+ // For internal use
6
+ export const InternalServices = {
7
+ SwoopService: new Swoop.SwoopService(),
8
+ CoreService: new Core.CoreService(),
9
+ ItineraryService: new Itinerary.ItineraryService(),
10
+ };
5
11
  export const init = (opts) => {
6
12
  // Keeps it consitent
7
13
  if (opts.coreServiceUrl.endsWith("/"))
@@ -1,16 +1,13 @@
1
1
  import React from 'react';
2
2
  import { ComponentPool } from '../registry/types';
3
3
  import { MasterSchema, Stage } from '../schema/formSchemaTypes';
4
- interface Props {
4
+ import { JsonSchema, Layout } from '@jsonforms/core';
5
+ interface BaseProps {
5
6
  /**
6
7
  * This should only be used for the initial values, as this is not truly a controlled component.
7
- * Frequent updates of this can cause significant perfomance dips.
8
+ * Frequent updates of this can cause significant performance dips.
8
9
  */
9
10
  initialData: any;
10
- /**
11
- * The master schema for this template
12
- */
13
- schema: MasterSchema;
14
11
  /**
15
12
  * This should not be fed back into the form.
16
13
  * Instead store it as a ref.
@@ -34,6 +31,36 @@ interface Props {
34
31
  * Should readonly fields be hidden
35
32
  */
36
33
  hideReadonlyFields?: boolean;
34
+ /**
35
+ * Hint at which component is being rendered, some forms may depend on component data
36
+ */
37
+ hintComponentId?: string;
38
+ }
39
+ interface SchemaProps extends BaseProps {
40
+ /**
41
+ * The master schema for this template
42
+ */
43
+ schema: MasterSchema;
44
+ /**
45
+ * These overrides are mutually exclusive with `schema`
46
+ */
47
+ overrideJsonSchema?: never;
48
+ overrideUiSchema?: never;
49
+ }
50
+ interface OverrideProps extends BaseProps {
51
+ /**
52
+ * The master schema for this template is mutually exclusive with overrides
53
+ */
54
+ schema?: never;
55
+ /**
56
+ * Override JSON schema
57
+ */
58
+ overrideJsonSchema: JsonSchema;
59
+ /**
60
+ * Override UI layout schema
61
+ */
62
+ overrideUiSchema: Layout;
37
63
  }
64
+ type Props = SchemaProps | OverrideProps;
38
65
  export declare const StyledFormView: React.FC<Props>;
39
66
  export {};
@@ -5,9 +5,11 @@ import { getComponents } from '../registry/components';
5
5
  import { generateJsonSchema } from '../schema/generate/jsonSchemaGenerate';
6
6
  import { generateUiSchema } from '../schema/generate/uiSchemaGenerate';
7
7
  import { initialisedCheck } from '../../api/init';
8
- export const StyledFormView = ({ initialData, schema, onChange, stage, pool, readonly, hideReadonlyFields }) => {
8
+ import ComponentContext from '../contexts/ComponentContext';
9
+ export const StyledFormView = ({ initialData, schema, onChange, stage, pool, readonly, hideReadonlyFields, hintComponentId, overrideJsonSchema, overrideUiSchema }) => {
9
10
  useEffect(initialisedCheck, []);
10
- const json = generateJsonSchema(schema, stage, hideReadonlyFields);
11
- const ui = generateUiSchema(schema, stage, hideReadonlyFields);
12
- return (React.createElement(JsonForms, { onChange: onChange, data: initialData, schema: json, uischema: ui, renderers: [...materialRenderers, ...getComponents(pool)], readonly: readonly, cells: materialCells }));
11
+ const json = overrideJsonSchema || generateJsonSchema(schema, stage, hideReadonlyFields);
12
+ const ui = overrideUiSchema || generateUiSchema(schema, stage, hideReadonlyFields);
13
+ return (React.createElement(ComponentContext, { componentId: hintComponentId, stage: stage },
14
+ React.createElement(JsonForms, { onChange: onChange, data: initialData, schema: json, uischema: ui, renderers: [...materialRenderers, ...getComponents(pool)], readonly: readonly, cells: materialCells })));
13
15
  };
@@ -0,0 +1,16 @@
1
+ import React from 'react';
2
+ import { DTOComponentRead } from '../../api';
3
+ import { Stage } from '../schema/formSchemaTypes';
4
+ interface Exported {
5
+ component?: DTOComponentRead;
6
+ stage: Stage;
7
+ }
8
+ export declare const CompContext: React.Context<Exported | null>;
9
+ export declare const useCompContext: () => Exported;
10
+ interface Props {
11
+ children: React.ReactNode;
12
+ componentId?: string;
13
+ stage: Stage;
14
+ }
15
+ declare const ComponentContext: React.FC<Props>;
16
+ export default ComponentContext;
@@ -0,0 +1,30 @@
1
+ import React, { createContext, useContext, useEffect, useState } from 'react';
2
+ import { InternalServices } from '../../api/init';
3
+ import { CircularProgress } from "@mui/material";
4
+ export const CompContext = createContext(null);
5
+ export const useCompContext = () => {
6
+ const cont = useContext(CompContext);
7
+ if (!cont)
8
+ throw new Error("useCompContext must be used from within a styled form");
9
+ return cont;
10
+ };
11
+ const ComponentContext = ({ children, componentId, stage }) => {
12
+ const [loading, setLoading] = useState(true);
13
+ const [component, setComponent] = useState();
14
+ useEffect(() => {
15
+ setLoading(true);
16
+ if (!componentId)
17
+ setLoading(false);
18
+ else {
19
+ setLoading(true);
20
+ InternalServices.CoreService.componentGet(componentId)
21
+ .then(setComponent)
22
+ .catch((e) => console.error(e.message))
23
+ .finally(() => setLoading(false));
24
+ }
25
+ }, [componentId]);
26
+ if (loading)
27
+ return React.createElement(CircularProgress, null);
28
+ return (React.createElement(CompContext.Provider, { value: { component, stage } }, children));
29
+ };
30
+ export default ComponentContext;
@@ -7,7 +7,6 @@ import React from "react";
7
7
  */
8
8
  export const useLocalErrors = (path) => {
9
9
  const { core } = useJsonForms();
10
- console.log(core);
11
10
  // Filters out errors for the current scope
12
11
  const local = React.useMemo(() => {
13
12
  var _a;
@@ -1,10 +1,9 @@
1
- import { JsonSchema } from "@jsonforms/core";
2
1
  import { TemplateField } from "../schema/formBuilders/formBuilderJsonSchema";
3
2
  import { JsonSchemaWithXType } from "../types/jsonSchema";
4
3
  /**
5
4
  * If type is not a default json schema type, it is treated as x-type.
6
5
  * E.g. "number" will define the default number field, whereas "address" will define a custom field
7
6
  */
8
- export declare const registerType: (name: string, title: string, schema: JsonSchema, options: JsonSchemaWithXType, optionsRequired: boolean) => void;
7
+ export declare const registerType: (name: string, title: string, schema: JsonSchemaWithXType, options: JsonSchemaWithXType, optionsRequired: boolean) => void;
9
8
  export declare const getAllTypes: () => Array<TemplateField>;
10
9
  export declare const getType: (xType: string) => TemplateField | undefined;
@@ -1,5 +1,5 @@
1
1
  'use client';
2
- import React, { useEffect, useMemo, useState } from 'react';
2
+ import React, { useMemo, useState } from 'react';
3
3
  import { Paper, Typography, TextField, Grid, Divider } from '@mui/material';
4
4
  import { registerComponent } from '../registry/components';
5
5
  import { ComponentPool } from '../registry/types';
@@ -20,11 +20,6 @@ const FormAddress = ({ data, onChange, enabled, label, postcodePattern }) => {
20
20
  onChange('postcode', value);
21
21
  };
22
22
  const hasAddress = useMemo(() => !!(data.line1 || data.line2 || data.city || data.county || data.postcode), [data]);
23
- useEffect(() => {
24
- if (hasAddress) {
25
- console.log('Address updated:', data);
26
- }
27
- }, [hasAddress, data]);
28
23
  return (React.createElement(Paper, { sx: { display: 'flex', flexDirection: 'column', gap: 2, p: 2, mb: 1 }, component: "form", noValidate: true, autoComplete: "off" },
29
24
  React.createElement(Typography, { variant: "h6" }, label),
30
25
  React.createElement(Grid, { container: true, spacing: 2 },
@@ -1,47 +1,45 @@
1
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
- return new (P || (P = Promise))(function (resolve, reject) {
4
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
- step((generator = generator.apply(thisArg, _arguments || [])).next());
8
- });
9
- };
10
- import React, { useEffect, useState } from 'react';
11
- import { useLocalErrors } from '../hooks/errors';
1
+ import { Resolve } from '@jsonforms/core';
2
+ import React from 'react';
3
+ import { Typography, TextField, Autocomplete } from '@mui/material';
12
4
  import { ComponentPool } from '../registry/types';
13
5
  import { registerComponent } from '../registry/components';
14
- import { CoreService } from '../../api/generated/core';
6
+ import { useCompContext } from '../contexts/ComponentContext';
7
+ import { Stage } from '../schema/formSchemaTypes';
8
+ const FormRendererSubsetInstance = ({ data, handleChange, path, label, enabled }) => {
9
+ var _a;
10
+ const context = useCompContext();
11
+ const compData = (_a = context.component) === null || _a === void 0 ? void 0 : _a.componentFields.find(f => { var _a; return f.templateId === ((_a = context.component) === null || _a === void 0 ? void 0 : _a.templateId); });
12
+ if (!compData)
13
+ throw new Error("Subset has been rendered without a component hint");
14
+ const extracted = Resolve.data(compData.data, path);
15
+ if (!extracted)
16
+ throw new Error("Subset missing data");
17
+ const value = Array.isArray(data) ? data[0] || "" : (data !== null && data !== void 0 ? data : "");
18
+ const handleSelectChange = (_event, newValue) => {
19
+ handleChange(path, newValue ? [newValue] : []);
20
+ };
21
+ return (React.createElement(React.Fragment, null,
22
+ React.createElement(Typography, null, label || "Select an option"),
23
+ React.createElement(Autocomplete, { options: extracted, value: value, onChange: handleSelectChange, disabled: !enabled, renderInput: (params) => (React.createElement(TextField, Object.assign({}, params, { variant: "outlined" }))), fullWidth: true })));
24
+ };
15
25
  const FormRendererSubset = ({ data, handleChange, path, label, enabled, schema }) => {
16
- // This needs to know the template and the component id... wip
17
- const componentId = "";
18
- const templateId = "";
19
- const [component, setComponent] = useState();
20
- const getError = useLocalErrors(path);
26
+ var _a;
21
27
  // @ts-ignore
22
- const set = schema['x-set'] || [];
23
- useEffect(() => {
24
- const load = () => __awaiter(void 0, void 0, void 0, function* () {
25
- try {
26
- const comp = yield (new CoreService).componentGet(componentId);
27
- setComponent(comp);
28
- }
29
- catch (err) {
30
- console.error('Error loading component:', err);
31
- }
32
- });
33
- load();
34
- }, [set]);
35
- const compData = component === null || component === void 0 ? void 0 : component.componentFields.find(f => f.templateId === templateId);
36
- // Extract correct data obj, should be array of strings
37
- const extracted = compData === null || compData === void 0 ? void 0 : compData.data; //.evalPath(path)
38
- return React.createElement(React.Fragment, null, "WIP");
39
- /*
40
- return (
41
- <Autocomplete
42
- options={ }>
43
-
44
- </Autocomplete>
45
- )*/
28
+ const enumValues = ((_a = schema.items) === null || _a === void 0 ? void 0 : _a.enum) || [];
29
+ const value = (data && Array.isArray(data)) ? data : [];
30
+ const handleSelectChange = (_event, newValue) => {
31
+ handleChange(path, newValue);
32
+ };
33
+ return (React.createElement(React.Fragment, null,
34
+ React.createElement(Typography, null, label || "Select options"),
35
+ React.createElement(Typography, null, "bettti"),
36
+ React.createElement(Autocomplete, { multiple: true, options: enumValues, value: value, onChange: handleSelectChange, disabled: !enabled, renderInput: (params) => React.createElement(TextField, Object.assign({}, params, { variant: "outlined" })), fullWidth: true })));
37
+ };
38
+ const Decider = (props) => {
39
+ const context = useCompContext();
40
+ if (context.stage === Stage.Comp)
41
+ return FormRendererSubset(props);
42
+ else
43
+ return FormRendererSubsetInstance(props);
46
44
  };
47
- registerComponent("TEMP DONT USE", FormRendererSubset, ComponentPool.FORM);
45
+ registerComponent("stagedEnumComponentLevel", Decider, ComponentPool.FORM);
@@ -1,5 +1,6 @@
1
1
  import { CONSTRAINT_DEFINITIONS } from "../template/constraint";
2
2
  import { getAllTypes } from "../../registry/fields";
3
+ import { Stage } from "../formSchemaTypes";
3
4
  const fields = getAllTypes();
4
5
  const fieldsToTypeDef = fields.map(f => ({
5
6
  "x-type": f.name,
@@ -154,7 +155,20 @@ export const FORM_BUILDER_JSON_SCHEMA = {
154
155
  type: "string",
155
156
  minLength: 1,
156
157
  description: "Field name (used for both label and ID generation)",
157
- }, description: { type: "string" }, required: { type: "boolean", default: false } }, fieldsToOptionsRecord),
158
+ }, description: { type: "string" }, required: { type: "boolean", default: false }, existsFrom: {
159
+ "type": "string",
160
+ "oneOf": Object.keys(Stage).filter((k) => isNaN(+k)).map(s => ({ title: s, const: Stage[s] + "" }))
161
+ }, editableIn: {
162
+ type: "array",
163
+ uniqueItems: true,
164
+ items: {
165
+ type: "string",
166
+ oneOf: Object.keys(Stage).filter((k) => isNaN(+k)).map(s => ({
167
+ title: s,
168
+ const: Stage[s] + ""
169
+ }))
170
+ }
171
+ } }, fieldsToOptionsRecord),
158
172
  required: ["fieldType", "name"],
159
173
  dependencies: {
160
174
  fieldType: {
@@ -31,6 +31,8 @@ const fieldDetailLayout = {
31
31
  { type: "Control", scope: "#/properties/fieldType" },
32
32
  { type: "Control", scope: "#/properties/description" },
33
33
  { type: "Control", scope: "#/properties/required" },
34
+ { type: "Control", scope: "#/properties/existsFrom" },
35
+ { type: "Control", scope: "#/properties/editableIn" },
34
36
  ...generateFieldControlElements(["object", "array"]),
35
37
  {
36
38
  type: "Control",
@@ -192,17 +194,6 @@ export const FORM_BUILDER_UI_SCHEMA = {
192
194
  options: { detail: fieldDetailLayout },
193
195
  },
194
196
  ],
195
- },
196
- {
197
- type: "Group",
198
- label: "IB-Driven Fields",
199
- elements: [
200
- {
201
- type: "Control",
202
- scope: "#/properties/ibFormFields",
203
- options: { detail: fieldDetailLayout },
204
- },
205
- ],
206
- },
197
+ }
207
198
  ],
208
199
  };
@@ -9,7 +9,6 @@ export const generateFormSchema = (data) => {
9
9
  if (!validator(data)) {
10
10
  throw new Error("Data does not conform to a valid form schema");
11
11
  }
12
- console.log(data);
13
12
  return data;
14
13
  }
15
14
  catch (e) {
@@ -10,9 +10,9 @@ export const generateJsonSchema = (formSchema, stage, onlyEditableFields) => {
10
10
  required: [],
11
11
  };
12
12
  formSchema.forEach((s) => {
13
- if (stage < s.existsFrom)
13
+ if (stage < +s.existsFrom)
14
14
  return;
15
- if (onlyEditableFields && !s.editableIn.includes(stage))
15
+ if (onlyEditableFields && !s.editableIn.map(Number).includes(stage))
16
16
  return;
17
17
  const fieldSchema = defaultConverter(s, stage);
18
18
  built.properties[generateFieldId(s.name)] = fieldSchema;
@@ -51,7 +51,7 @@ const defaultConverter = (field, stage, omitTitle, isChild) => {
51
51
  if (child.required)
52
52
  requiredFields.push(fieldId);
53
53
  }
54
- let enumOpts = field.fieldType === "enum" || field.fieldType === "stagedEnum"
54
+ let enumOpts = field.fieldType === "enum"
55
55
  ? (() => {
56
56
  var _a;
57
57
  let enumOptions = (((_a = field.enumOptions) === null || _a === void 0 ? void 0 : _a.enumValues) ||
@@ -61,10 +61,20 @@ const defaultConverter = (field, stage, omitTitle, isChild) => {
61
61
  return enumOptions;
62
62
  })()
63
63
  : undefined;
64
+ let stagedEnumOpts = field.fieldType === "stagedEnum"
65
+ ? (() => {
66
+ var _a;
67
+ let enumOptions = (((_a = field.stagedEnumOptions) === null || _a === void 0 ? void 0 : _a.enumValues) ||
68
+ []);
69
+ if (enumOptions.length === 0)
70
+ enumOptions.push("");
71
+ return enumOptions;
72
+ })()
73
+ : undefined;
64
74
  // Component (probably should change this)
65
75
  let templates = field.fieldType === "componentPicker"
66
76
  ? { "x-templateIds": (_e = field.componentOptions) === null || _e === void 0 ? void 0 : _e.templateIds }
67
77
  : {};
68
78
  let title = omitTitle ? undefined : field.name;
69
- return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, (!isChild && !field.editableIn.includes(stage) && { readOnly: true })), { title, type: schema.schema.type, "x-type": schema.schema["x-type"] }), templates), (schema.schema.type === "object" && { properties })), { required: requiredFields }), (enumOpts && { enum: enumOpts })), (arrayItems && { items: arrayItems })), (field.fieldType === "object" && { properties }));
79
+ return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, (!isChild && !field.editableIn.map(Number).includes(stage) && { readOnly: true })), { title, type: schema.schema.type, "x-type": schema.schema["x-type"] }), templates), (schema.schema.type === "object" && { properties })), { required: requiredFields }), (enumOpts && { enum: enumOpts })), (stagedEnumOpts && { items: { enum: stagedEnumOpts, type: "string" } })), (arrayItems && { items: arrayItems })), (field.fieldType === "object" && { properties }));
70
80
  };
@@ -3,9 +3,9 @@ import { getAllTypes } from "../../registry/fields";
3
3
  export const generateUiSchema = (formSchema, stage, onlyEditableFields) => {
4
4
  const uiSchema = { type: "VerticalLayout", elements: [] };
5
5
  formSchema.forEach((field) => {
6
- if (stage < field.existsFrom)
6
+ if (stage < +field.existsFrom)
7
7
  return;
8
- if (onlyEditableFields && !field.editableIn.includes(stage))
8
+ if (onlyEditableFields && !field.editableIn.map(Number).includes(stage))
9
9
  return;
10
10
  uiSchema.elements.push(uiFieldSchemaFromFieldDefinition(field));
11
11
  });
@@ -40,20 +40,6 @@ registerType("enum", "Dropdown", { type: "string" }, {
40
40
  }
41
41
  }
42
42
  }, true);
43
- registerType("stagedEnum", "Staged Dropdown", {
44
- type: "array",
45
- items: { type: "string" },
46
- }, {
47
- type: "object",
48
- title: "Dropdown Options",
49
- properties: {
50
- enumValues: {
51
- title: "Dropdown Values",
52
- type: "array",
53
- items: { type: "string" },
54
- },
55
- },
56
- }, true);
57
43
  registerType("array", "List", { type: "array" }, {
58
44
  type: "object",
59
45
  title: "List Options",
@@ -65,6 +51,7 @@ registerType("array", "List", { type: "array" }, {
65
51
  },
66
52
  }, true);
67
53
  registerType("stagedEnum", "Staged Dropdown", {
54
+ "x-type": "stagedEnumComponentLevel",
68
55
  type: "array",
69
56
  items: { type: "string" },
70
57
  }, {
@@ -75,7 +62,7 @@ registerType("stagedEnum", "Staged Dropdown", {
75
62
  title: "Dropdown Values",
76
63
  type: "array",
77
64
  items: { type: "string" },
78
- },
65
+ }
79
66
  },
80
67
  }, true);
81
68
  registerType("object", "Group", { type: "object" }, {
@@ -145,23 +132,5 @@ registerType("address", "Address", {
145
132
  },
146
133
  required: ["line1", "city", "postcode"]
147
134
  }, {}, false);
148
- /*
149
- registerType(
150
- "subset",
151
- "Subset",
152
- {
153
- type: "object",
154
- title: "Subset Options",
155
- properties: {
156
- minItems: { type: "integer", minimum: 0 },
157
- maxItems: { type: "integer", minimum: 1 },
158
- uniqueItems: { type: "boolean", default: false },
159
- itemDefinition: { $ref: "#/$defs/arrayItemDefinition" },
160
- },
161
- },
162
- {
163
- },
164
- false
165
- );*/
166
135
  registerType("image", "Image", { type: "string" }, {}, false);
167
136
  registerType("multiline", "Multiline", { type: "string" }, {}, false);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "swoop-common",
3
- "version": "2.0.7",
3
+ "version": "2.0.8",
4
4
  "main": "dist/api/index.js",
5
5
  "types": "dist/api/index.d.ts",
6
6
  "exports": {