swoop-common 1.0.12 → 1.0.14

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/README.md CHANGED
@@ -0,0 +1,174 @@
1
+ # Swoop Template Library
2
+
3
+ This library is used for rendering **Swoop itinerary templates**. It provides tools for defining **custom field types**, registering **custom components**, and rendering templates from a **MasterSchema**. It supports both input mode (for creating templates) and presentation mode (for rendering them for end users). The schema system is stage-aware, enabling precise control over what data is editable or displayed at which stage.
4
+
5
+ > Note: This package is intended for internal use only.
6
+
7
+ ---
8
+
9
+ ## StyledFormView
10
+
11
+ The `StyledFormView` component is the entry point for rendering a full itinerary template. It handles schema parsing and renderer injection based on mode and form stage.
12
+
13
+ ```tsx
14
+ import { StyledFormView } from 'your-form-library';
15
+
16
+ <StyledFormView
17
+ initialData={/* object */}
18
+ schema={/* MasterSchema */}
19
+ onChange={(val) => console.log(val)}
20
+ pool="FORM"
21
+ readonly={false}
22
+ stage="Inst"
23
+ />
24
+ ```
25
+
26
+ ### Props
27
+
28
+ | Name | Type | Description |
29
+ |--------------|-------------------------------|-----------------------------------------------------------------------------|
30
+ | initialData | `any` | Initial values for the template. Should not be updated frequently. |
31
+ | schema | `MasterSchema` | Template definition object. |
32
+ | onChange | `(val: any) => void` | Callback with updated data. |
33
+ | pool | `ComponentPool` | `"FORM"` or `"PRESENTATION"` depending on context. |
34
+ | readonly | `boolean` | Disables inputs if true (only relevant in FORM pool). |
35
+ | stage | `Stage` | Controls which data segment is being rendered. |
36
+
37
+ ### Stages
38
+
39
+ The template system is divided into stages:
40
+
41
+ - **Stage.Comp** – Data stored on the root component, often static (e.g. metadata, titles). Does not include any dynamic or time-based fields.
42
+ - **Stage.Inst** – Instance-specific data (e.g. timings, localized notes). This is the most common stage for editable fields.
43
+ - **Stage.User** – Data unique to individual users (e.g. room number).
44
+
45
+ Each stage builds on the one before it. For example, `Stage.User` includes everything from `Stage.Comp` and `Stage.Inst`. Fields are editable based on the current stage. If a value is defined in two stages, the lower stage will take priority.
46
+
47
+ ---
48
+
49
+ ## Custom Components
50
+
51
+ Custom components define how individual fields render. These can behave like typical form inputs or be used for display-only formatting in the `PRESENTATION` pool.
52
+
53
+ ### Example
54
+
55
+ ```tsx
56
+ const FormExample: React.FC<Props> = ({ text, onChange, getError, label, enabled }) => {
57
+ const [val, setVal] = useState(text);
58
+ const error = getError ? getError("example")?.message : undefined;
59
+ const onChangeDebounced = useMemo(() => debounce(onChange, 300), [onChange]);
60
+
61
+ const update = (value: string) => {
62
+ setVal(value);
63
+ onChangeDebounced(value);
64
+ };
65
+
66
+ return (
67
+ <Paper sx={{ display: 'flex', flexDirection: 'column', gap: 1, p: 2, background: "#CBC3E3", mb: 1 }}>
68
+ {!enabled && "THIS IS DISABLED"}
69
+ <Typography variant='h6'>{label}</Typography>
70
+ <TextField
71
+ label="Example label"
72
+ value={val}
73
+ onChange={(e) => update(e.target.value)}
74
+ error={!!error}
75
+ helperText={error}
76
+ disabled={!enabled}
77
+ />
78
+ </Paper>
79
+ );
80
+ };
81
+
82
+ const FormRendererExample: React.FC<ControlProps> = ({ data, handleChange, path, label, enabled }) => {
83
+ const getError = useLocalErrors(path);
84
+ return (
85
+ <FormExample
86
+ text={data as string}
87
+ onChange={(val) => handleChange(path, val)}
88
+ getError={getError}
89
+ label={label}
90
+ enabled={enabled}
91
+ />
92
+ );
93
+ };
94
+
95
+ registerComponent("example", FormRendererExample, ComponentPool.FORM);
96
+ registerComponent("example", FormRendererExample, ComponentPool.PRESENTATION);
97
+ ```
98
+
99
+ > Important: You **cannot register two components with the same name within the same pool**. You *can* register the same component name across different pools (e.g., `"example"` in both `"FORM"` and `"PRESENTATION"`).
100
+
101
+ ### Presentation Pool
102
+
103
+ The `PRESENTATION` pool is more than just read-only. It is designed for **customer-facing output**, rendering fields in a clean, non-form-like layout for readability and professionalism.
104
+
105
+ ---
106
+
107
+ ## Custom Types
108
+
109
+ Custom field types define what kinds of fields can be used when **building a template**. These appear in the template builder UI as selectable field types and control how data is validated and configured.
110
+
111
+ ### Syntax
112
+
113
+ ```ts
114
+ registerType(
115
+ "typeId", // Unique type string
116
+ "Display Name", // Name shown in template builder
117
+ schema, // JSON Schema defining the data structure
118
+ optionsSchema, // JSON Schema defining configuration data structure
119
+ requiredOptions // boolean: must the options be filled?
120
+ );
121
+ ```
122
+
123
+ ### Example
124
+
125
+ ```ts
126
+ registerType("enum", "Dropdown",
127
+ { type: "array" },
128
+ {
129
+ type: "object",
130
+ title: "Dropdown Options",
131
+ properties: {
132
+ enumValues: {
133
+ title: "Dropdown Values",
134
+ type: "array",
135
+ items: { type: "string" }
136
+ }
137
+ }
138
+ },
139
+ true
140
+ );
141
+ ```
142
+
143
+ This type defines a dropdown field where the values are defined via the `enumValues` property in the template configuration.
144
+
145
+ ### Custom Option Editors
146
+
147
+ If you want to render a **custom options block** (i.e., how the field type's options are displayed in the template editor), you must do the following:
148
+
149
+ 1. In the top-level `optionsSchema` of the type, define `"x-type": "yourTypeName"`
150
+ 2. Create and register a custom component with the name `"yourTypeName"` in the `"FORM"` pool.
151
+
152
+ This component will then be used to render the configuration UI for that field type.
153
+
154
+ ---
155
+
156
+ ## File Locations
157
+
158
+ - **Custom components** must be placed in `src/renderers`. They may be nested within subfolders. All files inside `renderers/` will be automatically imported in the correct order.
159
+ - **Custom types** must be added to `src/default_registration/fields_base.tsx`.
160
+
161
+ No manual import wiring is required beyond placing the file in the correct folder.
162
+
163
+ ---
164
+
165
+ ## Publishing to NPM
166
+
167
+ To publish a new version of the package:
168
+
169
+ ```bash
170
+ npm run build # Compile the package
171
+ npm version patch # Bump the patch version (or use minor/major as needed)
172
+ npm adduser # Log in to NPM (if not already)
173
+ npm publish # Publish the package
174
+ ```
@@ -0,0 +1,4 @@
1
+ export declare const getBaseApiUrl: () => string;
2
+ export declare const getApiToken: () => string;
3
+ export declare const init: (apiUrl: string, apiKey: string) => void;
4
+ export declare const initialisedCheck: () => void;
@@ -0,0 +1,21 @@
1
+ let baseApiUrl = "";
2
+ let apiToken = "";
3
+ let initalised = false;
4
+ export const getBaseApiUrl = () => {
5
+ initialisedCheck();
6
+ return baseApiUrl;
7
+ };
8
+ export const getApiToken = () => {
9
+ initialisedCheck();
10
+ return apiToken;
11
+ };
12
+ export const init = (apiUrl, apiKey) => {
13
+ baseApiUrl = apiUrl;
14
+ apiToken = apiKey;
15
+ initalised = true;
16
+ };
17
+ export const initialisedCheck = () => {
18
+ if (initalised)
19
+ return;
20
+ console.warn("swoop-common has been used without being initialised. The library will continue to work in most cases, but live data requests may fail. Use init() to initialise the library.");
21
+ };
@@ -1,14 +1,17 @@
1
1
  import React from 'react';
2
2
  import "../prebuild/generated/import_generated";
3
3
  import { ComponentPool } from '../registry/types';
4
- import { FormSchema, Stage } from '../schema/formSchemaTypes';
4
+ import { MasterSchema, Stage } from '../schema/formSchemaTypes';
5
5
  interface Props {
6
6
  /**
7
7
  * This should only be used for the initial values, as this is not truly a controlled component.
8
8
  * Frequent updates of this can cause significant perfomance dips.
9
9
  */
10
10
  initialData: any;
11
- schema: FormSchema;
11
+ /**
12
+ * The master schema for this template
13
+ */
14
+ schema: MasterSchema;
12
15
  /**
13
16
  * This should not be fed back into the form.
14
17
  * Instead store it as a ref.
@@ -25,9 +28,8 @@ interface Props {
25
28
  */
26
29
  readonly?: boolean;
27
30
  /**
28
- * Whether to also include mui default renderers
31
+ * The stage at which to render this template
29
32
  */
30
- useMui?: boolean;
31
33
  stage: Stage;
32
34
  }
33
35
  export declare const StyledFormView: React.FC<Props>;
@@ -1,12 +1,14 @@
1
1
  import { JsonForms } from '@jsonforms/react';
2
- import React from 'react';
2
+ import React, { useEffect } from 'react';
3
3
  import { materialCells, materialRenderers } from '@jsonforms/material-renderers';
4
4
  import "../prebuild/generated/import_generated";
5
5
  import { getComponents } from '../registry/components';
6
- import { generateJsonSchema } from '../schema/generate/jsonSchemaGeneratewip';
6
+ import { generateJsonSchema } from '../schema/generate/jsonSchemaGenerate';
7
7
  import { generateUiSchema } from '../schema/generate/uiSchemaGenerate';
8
- export const StyledFormView = ({ initialData, schema, onChange, stage, pool, readonly, useMui }) => {
8
+ import { initialisedCheck } from '../api/state';
9
+ export const StyledFormView = ({ initialData, schema, onChange, stage, pool, readonly }) => {
10
+ useEffect(initialisedCheck, []);
9
11
  const json = generateJsonSchema(schema, stage);
10
12
  const ui = generateUiSchema(schema, stage);
11
- return (React.createElement(JsonForms, { onChange: onChange, data: initialData, schema: json, uischema: ui, renderers: [...(useMui ? materialRenderers : []), ...getComponents(pool)], readonly: readonly, cells: materialCells }));
13
+ return (React.createElement(JsonForms, { onChange: onChange, data: initialData, schema: json, uischema: ui, renderers: [...materialRenderers, ...getComponents(pool)], readonly: readonly, cells: materialCells }));
12
14
  };
package/dist/index.d.ts CHANGED
@@ -1,10 +1,11 @@
1
1
  export { getComponents } from "./registry/components";
2
2
  export { JSONSchemaObject } from "./schema/schema";
3
3
  export { generateUiSchema } from "./schema/generate/uiSchemaGenerate";
4
- export { generateJsonSchema } from "./schema/generate/jsonSchemaGeneratewip";
4
+ export { generateJsonSchema } from "./schema/generate/jsonSchemaGenerate";
5
5
  export * from "./test";
6
6
  export * from "./components/StyledFormView";
7
7
  export * from "./registry/types";
8
- export { FormSchema, Stage } from "./schema/formSchemaTypes";
8
+ export { MasterSchema, Stage } from "./schema/formSchemaTypes";
9
9
  export { FORM_BUILDER_JSON_SCHEMA } from "./schema/formBuilders/formBuilderJsonSchema";
10
10
  export { FORM_BUILDER_UI_SCHEMA } from "./schema/formBuilders/formBuilderUiSchema";
11
+ export { init } from "./api/state";
package/dist/index.js CHANGED
@@ -1,9 +1,10 @@
1
1
  export { getComponents } from "./registry/components";
2
2
  export { generateUiSchema } from "./schema/generate/uiSchemaGenerate";
3
- export { generateJsonSchema } from "./schema/generate/jsonSchemaGeneratewip";
3
+ export { generateJsonSchema } from "./schema/generate/jsonSchemaGenerate";
4
4
  export * from "./test";
5
5
  export * from "./components/StyledFormView";
6
6
  export * from "./registry/types";
7
7
  export { Stage } from "./schema/formSchemaTypes";
8
8
  export { FORM_BUILDER_JSON_SCHEMA } from "./schema/formBuilders/formBuilderJsonSchema";
9
9
  export { FORM_BUILDER_UI_SCHEMA } from "./schema/formBuilders/formBuilderUiSchema";
10
+ export { init } from "./api/state";
@@ -1,6 +1,4 @@
1
1
  import "../../default_registration/fields_base";
2
- import "../../renderers/address/AddressForm";
3
- import "../../renderers/address/AddressPresentation";
4
2
  import "../../renderers/Address";
5
3
  import "../../renderers/ComponentPicker";
6
4
  import "../../renderers/Debug";
@@ -1,8 +1,6 @@
1
1
  // Base field types
2
2
  import "../../default_registration/fields_base";
3
3
  // Custom component renderers
4
- import "../../renderers/address/AddressForm";
5
- import "../../renderers/address/AddressPresentation";
6
4
  import "../../renderers/Address";
7
5
  import "../../renderers/ComponentPicker";
8
6
  import "../../renderers/Debug";
@@ -12,7 +12,7 @@ import { Paper, Typography, Box, TextField, Autocomplete } from '@mui/material';
12
12
  import { useLocalErrors } from '../hooks/errors';
13
13
  import { ComponentPool } from '../registry/types';
14
14
  import { registerComponent } from '../registry/components';
15
- import { BASE_API_URL } from '../api/consts';
15
+ import { getBaseApiUrl } from '../api/state';
16
16
  const FormComponentPicker = ({ components, selectedComponent, onChange, templateIds, getError, label, enabled }) => {
17
17
  const selected = components.find(c => c.id === selectedComponent) || null;
18
18
  return (React.createElement(Paper, { component: "form", sx: { display: 'flex', flexDirection: 'column', gap: 1, p: 2, mb: 1 }, noValidate: true, autoComplete: "off" },
@@ -50,7 +50,7 @@ const FormRendererComponentPicker = ({ data, handleChange, path, label, enabled,
50
50
  };
51
51
  registerComponent("component", FormRendererComponentPicker, ComponentPool.FORM);
52
52
  export const fetchComponents = () => __awaiter(void 0, void 0, void 0, function* () {
53
- const response = yield fetch(`${BASE_API_URL}/core-data-service/v1/components?limit=200`);
53
+ const response = yield fetch(`${getBaseApiUrl()}/core-data-service/v1/components?limit=200`);
54
54
  const data = yield response.json();
55
55
  const componentsByGroup = new Map();
56
56
  (data.data || []).forEach((component) => {
@@ -13,7 +13,7 @@ import { Paper, Typography, Box, TextField, Chip, Autocomplete } from '@mui/mate
13
13
  import { useLocalErrors } from '../hooks/errors';
14
14
  import { registerComponent } from '../registry/components';
15
15
  import { ComponentPool } from '../registry/types';
16
- import { BASE_API_URL } from '../api/consts';
16
+ import { getBaseApiUrl } from '../api/state';
17
17
  const FormTemplatePicker = ({ templates, selectedTemplates, onChange, label, enabled }) => {
18
18
  const selectedValues = templates.filter(t => selectedTemplates.includes(t.id));
19
19
  return (React.createElement(Paper, { component: "form", sx: { display: 'flex', flexDirection: 'column', gap: 2, p: 2, mb: 1 }, noValidate: true, autoComplete: "off" },
@@ -46,7 +46,7 @@ const FormRendererTemplatePicker = ({ data, handleChange, path, label, enabled }
46
46
  };
47
47
  registerComponent("componentOptions", FormRendererTemplatePicker, ComponentPool.FORM);
48
48
  export const fetchTemplates = () => __awaiter(void 0, void 0, void 0, function* () {
49
- const response = yield fetch(`${BASE_API_URL}/core-data-service/v1/templates?limit=2000`);
49
+ const response = yield fetch(`${getBaseApiUrl()}/core-data-service/v1/templates?limit=2000`);
50
50
  if (!response.ok) {
51
51
  throw new Error("Failed to fetch templates");
52
52
  }
@@ -1,10 +1,10 @@
1
- export type FormSchema = Array<FieldDefinition>;
1
+ export type MasterSchema = Array<MasterFieldDefinition>;
2
2
  export declare enum Stage {
3
3
  Comp = 0,
4
4
  Inst = 1,
5
5
  User = 2
6
6
  }
7
- export interface FieldDefinition {
7
+ export interface MasterFieldDefinition {
8
8
  fieldType: string;
9
9
  name: string;
10
10
  description?: string;
@@ -1,3 +1,4 @@
1
- import { FormSchema } from "../formSchemaTypes";
2
- import { JSONSchemaObject } from "../schema";
3
- export declare const generateJsonSchema1: (formSchema: FormSchema) => JSONSchemaObject | undefined;
1
+ import { MasterSchema, Stage } from "../formSchemaTypes";
2
+ import { JsonSchema } from "@jsonforms/core";
3
+ import "../../prebuild/generated/import_generated";
4
+ export declare const generateJsonSchema: (formSchema: MasterSchema, stage: Stage) => JsonSchema | undefined;
@@ -1,150 +1,59 @@
1
+ import { getType } from "../../registry/fields";
1
2
  import { generateFieldId } from "../util";
2
- export const generateJsonSchema1 = (formSchema) => {
3
+ import "../../prebuild/generated/import_generated";
4
+ export const generateJsonSchema = (formSchema, stage) => {
3
5
  // Lazy try catch rn
4
6
  try {
5
- console.log("SRTART");
6
7
  const built = {
7
8
  type: "object",
8
9
  properties: {},
9
10
  required: [],
10
11
  };
11
12
  formSchema.forEach(s => {
12
- const fieldSchema = jsonSchemaFromFieldDefinition(s);
13
+ if (stage < s.existsFrom)
14
+ return;
15
+ const fieldSchema = defaultConverter(s, stage);
13
16
  built.properties[generateFieldId(s.name)] = fieldSchema;
14
17
  if (s.required)
15
18
  built.required.push(generateFieldId(s.name));
16
19
  });
17
- console.log("BI", built);
18
20
  return built;
19
21
  }
20
22
  catch (e) {
21
- console.log("err", e);
23
+ console.error(e);
22
24
  return undefined;
23
25
  }
24
26
  };
25
- const jsonSchemaFromFieldDefinition = (field) => {
26
- switch (field.fieldType) {
27
- case "string":
28
- return jsonSchemaFromStringFieldDefinition(field);
29
- case "number":
30
- return jsonSchemaFromNumberFieldDefinition(field);
31
- case "integer":
32
- return jsonSchemaFromIntegerFieldDefinition(field);
33
- case "boolean":
34
- return jsonSchemaFromBooleanFieldDefinition(field);
35
- case "enum":
36
- return jsonSchemaFromEnumFieldDefinition(field);
37
- case "object":
38
- return jsonSchemaFromObjectFieldDefinition(field);
39
- case "array":
40
- return jsonSchemaFromArrayFieldDefinition(field);
41
- case "address":
42
- return jsonSchemaFromAddressFieldDefinition(field);
43
- case "stagedText":
44
- return jsonSchemaFromStagedTextFieldDefinition(field);
45
- case "liveData":
46
- return jsonSchemaFromLiveDataFieldDefinition(field);
47
- case "component":
48
- return jsonSchemaFromComponentFieldDefinition(field);
49
- default:
50
- throw new Error(`Unsupported field type: ${field.fieldType}`);
51
- }
52
- };
53
- const jsonSchemaFromStringFieldDefinition = (field) => {
54
- var _a;
55
- return Object.assign({ title: field.name, description: field.description, type: "string" }, ((_a = field.stringOptions) !== null && _a !== void 0 ? _a : {}));
56
- };
57
- const jsonSchemaFromNumberFieldDefinition = (field) => {
58
- var _a;
59
- return Object.assign({ title: field.name, description: field.description, type: "number" }, ((_a = field.numberOptions) !== null && _a !== void 0 ? _a : {}));
60
- };
61
- const jsonSchemaFromIntegerFieldDefinition = (field) => {
62
- var _a;
63
- return Object.assign({ title: field.name, description: field.description, type: "integer" }, ((_a = field.numberOptions) !== null && _a !== void 0 ? _a : {}));
64
- };
65
- const jsonSchemaFromBooleanFieldDefinition = (field) => {
66
- return {
67
- title: field.name,
68
- description: field.description,
69
- type: "boolean"
70
- };
71
- };
72
- const jsonSchemaFromEnumFieldDefinition = (field) => {
73
- var _a, _b, _c;
74
- // Temp, errors if invalid enum
75
- if (((_b = (_a = field.enumOptions) === null || _a === void 0 ? void 0 : _a.enumValues) === null || _b === void 0 ? void 0 : _b.length) === 0)
76
- throw new Error("Invalid enum count");
77
- // Hopefully temp.
78
- // The enum is stupid, it errors in jsonschema if it has no options
79
- let opts = ((_c = field.enumOptions) === null || _c === void 0 ? void 0 : _c.enumValues) || [];
80
- if (opts.length === 0)
81
- opts.push("");
82
- return {
83
- title: field.name,
84
- description: field.description,
85
- type: "string",
86
- enum: opts
87
- };
88
- };
89
- const jsonSchemaFromObjectFieldDefinition = (field) => {
90
- var _a, _b;
27
+ const defaultConverter = (field, stage, omitTitle, isChild) => {
28
+ var _a, _b, _c, _d, _e;
29
+ // Default field type
30
+ field.fieldType = (_a = field.fieldType) !== null && _a !== void 0 ? _a : "string";
31
+ let schema = getType(field.fieldType);
32
+ if (!schema)
33
+ throw new Error("tried to generate schema from unknown type: " + field.fieldType + "\nFull object: " + JSON.stringify(field, null, 2));
34
+ const requiredFields = [];
35
+ if (field.required)
36
+ requiredFields.push(field.name);
37
+ // Specific for array
38
+ let arrayItems = field.fieldType === "array" ? defaultConverter((_b = field.arrayOptions) === null || _b === void 0 ? void 0 : _b.itemDefinition, stage, true, true) : undefined;
39
+ // Obj childs
91
40
  const properties = {};
92
- const required = [];
93
- for (const child of (_b = (_a = field.objectOptions) === null || _a === void 0 ? void 0 : _a.properties) !== null && _b !== void 0 ? _b : []) {
41
+ for (const child of (_d = (_c = field.objectOptions) === null || _c === void 0 ? void 0 : _c.properties) !== null && _d !== void 0 ? _d : []) {
94
42
  const fieldId = generateFieldId(child.name);
95
- properties[fieldId] = jsonSchemaFromFieldDefinition(child);
43
+ properties[fieldId] = defaultConverter(child, stage, false, true);
96
44
  if (child.required)
97
- required.push(fieldId);
45
+ requiredFields.push(fieldId);
98
46
  }
99
- return Object.assign({ title: field.name, description: field.description, type: "object", properties }, (required.length > 0 && { required }));
100
- };
101
- const jsonSchemaFromArrayFieldDefinition = (field) => {
102
- var _a, _b;
103
- const items = ((_a = field.arrayOptions) === null || _a === void 0 ? void 0 : _a.itemDefinition)
104
- ? jsonSchemaFromFieldDefinition(field.arrayOptions.itemDefinition)
105
- :
106
- {
107
- type: "string"
108
- };
109
- return Object.assign({ title: field.name, description: field.description, type: "array", items }, ((_b = field.arrayOptions) !== null && _b !== void 0 ? _b : {}));
110
- };
111
- const jsonSchemaFromAddressFieldDefinition = (field) => {
112
- const schema = {
113
- title: field.name,
114
- description: field.description,
115
- type: "object",
116
- "x-type": "address",
117
- properties: {
118
- line1: { type: "string", title: "Address Line 1" },
119
- line2: { type: "string", title: "Address Line 2" },
120
- city: { type: "string", title: "City" },
121
- county: { type: "string", title: "County" },
122
- postcode: {
123
- type: "string",
124
- title: "Postcode",
125
- pattern: "^[A-Z]{1,2}[0-9][0-9A-Z]? ?[0-9][A-Z]{2}$"
126
- },
127
- number: { type: "number", title: "Number" }
128
- },
129
- required: ["line1", "city", "postcode"]
130
- };
131
- return schema;
132
- };
133
- const jsonSchemaFromStagedTextFieldDefinition = (field) => {
134
- return Object.assign({ title: field.name, description: field.description, type: "object", properties: {
135
- website: { type: "string", title: "Website" },
136
- quote: { type: "string", title: "Quote" },
137
- finalItinerary: { type: "string", title: "Final Itinerary" }
138
- } }, (field.required && { required: ["website", "quote", "finalItinerary"] }));
139
- };
140
- const jsonSchemaFromLiveDataFieldDefinition = (field) => {
141
- return Object.assign({ title: field.name, description: field.description, type: "object", properties: {
142
- liveDataId: { type: "string", title: "Live Data ID" }
143
- } }, (field.required && { required: ["liveDataId"] }));
144
- };
145
- const jsonSchemaFromComponentFieldDefinition = (field) => {
146
- var _a, _b;
147
- return Object.assign({ title: field.name, description: field.description, type: "string",
148
- // @ts-ignore
149
- "x-templateIds": (_b = (_a = field.componentOptions) === null || _a === void 0 ? void 0 : _a.templateIds) !== null && _b !== void 0 ? _b : [] }, (field.required && { required: ["componentId"] }));
47
+ // Enum fails if empty, fixes
48
+ let enumOpts = field.fieldType === "enum" ? (() => {
49
+ var _a;
50
+ let enumOptions = (((_a = field.enumOptions) === null || _a === void 0 ? void 0 : _a.enumValues) || []);
51
+ if (enumOptions.length === 0)
52
+ enumOptions.push("");
53
+ return enumOptions;
54
+ })() : undefined;
55
+ // Component (probably should change this)
56
+ let templates = field.fieldType === "componentPicker" ? { "x-templateIds": (_e = field.componentOptions) === null || _e === void 0 ? void 0 : _e.templateIds } : {};
57
+ let title = omitTitle ? undefined : field.name;
58
+ 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 }));
150
59
  };
@@ -1,3 +1,3 @@
1
1
  import { Layout } from "@jsonforms/core";
2
- import { FormSchema, Stage } from "../formSchemaTypes";
3
- export declare const generateUiSchema: (formSchema: FormSchema, stage: Stage) => Layout;
2
+ import { MasterSchema, Stage } from "../formSchemaTypes";
3
+ export declare const generateUiSchema: (formSchema: MasterSchema, stage: Stage) => Layout;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "swoop-common",
3
- "version": "1.0.12",
3
+ "version": "1.0.14",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "files": [
@@ -1 +0,0 @@
1
- export declare const BASE_API_URL = "https://data-api-dev.swoop-adventures.com";
@@ -1,2 +0,0 @@
1
- // temp
2
- export const BASE_API_URL = "https://data-api-dev.swoop-adventures.com";
@@ -1,3 +0,0 @@
1
- import React from 'react';
2
- declare const ErrorRenderer: () => React.JSX.Element;
3
- export default ErrorRenderer;
@@ -1,6 +0,0 @@
1
- import React from 'react';
2
- import { Typography } from '@mui/material';
3
- const ErrorRenderer = () => {
4
- return (React.createElement(Typography, { variant: 'h3' }, "Error loading"));
5
- };
6
- export default ErrorRenderer;
@@ -1 +0,0 @@
1
- export {};
@@ -1,46 +0,0 @@
1
- import React, { useMemo, useState } from 'react';
2
- import { Box, debounce, MenuItem, Paper, TextField, Typography } from '@mui/material';
3
- import { useLocalErrors } from '../../hooks/errors';
4
- import { ComponentPool } from '../../registry/types';
5
- import { registerComponent } from '../../registry/components';
6
- const FormAddress = ({ address, onChange, getError, label, enabled }) => {
7
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
8
- if (!getError)
9
- getError = () => undefined;
10
- const [val, setVal] = useState(address || {
11
- line1: "",
12
- city: "",
13
- postcode: "",
14
- });
15
- // Errors, stored to reduce num of calls for performance
16
- const line1Error = (_a = getError("line1")) === null || _a === void 0 ? void 0 : _a.message;
17
- const line2Error = (_b = getError("line2")) === null || _b === void 0 ? void 0 : _b.message;
18
- const cityError = (_c = getError("city")) === null || _c === void 0 ? void 0 : _c.message;
19
- const postcodeError = (_d = getError("postcode")) === null || _d === void 0 ? void 0 : _d.message;
20
- const numberError = (_e = getError("number")) === null || _e === void 0 ? void 0 : _e.message;
21
- const onChangeDebounced = useMemo(() => debounce(onChange, 300), [onChange]);
22
- const update = (field, value) => {
23
- const newVal = Object.assign(Object.assign({}, val), { [field]: value });
24
- setVal(newVal);
25
- onChangeDebounced(newVal);
26
- };
27
- return (React.createElement(Paper, { component: "form", noValidate: true, autoComplete: "off", sx: { display: 'flex', flexDirection: 'column', gap: 1, p: 2, mb: 1 } },
28
- React.createElement(Typography, { variant: 'h5' }, label),
29
- React.createElement(Box, { sx: { display: 'flex', flexDirection: 'column', gap: 2 } },
30
- React.createElement(TextField, { label: "Line 1", value: (_f = val.line1) !== null && _f !== void 0 ? _f : "", onChange: (e) => update('line1', e.target.value), required: true, error: !!line1Error, helperText: line1Error, disabled: !enabled }),
31
- React.createElement(TextField, { label: "Line 2", value: (_g = val.line2) !== null && _g !== void 0 ? _g : "", onChange: (e) => update('line2', e.target.value), error: !!line2Error, helperText: line2Error, disabled: !enabled })),
32
- React.createElement(TextField, { select: true, label: "City", value: (_h = val.city) !== null && _h !== void 0 ? _h : "London", onChange: (e) => update('city', e.target.value), required: true, fullWidth: true, error: !!cityError, helperText: cityError, disabled: !enabled },
33
- React.createElement(MenuItem, { value: "London" }, "Londonhn"),
34
- React.createElement(MenuItem, { value: "Newcastle" }, "Newcastle"),
35
- React.createElement(MenuItem, { value: "Bristol" }, "Bristol")),
36
- React.createElement(Box, { sx: { display: 'flex', gap: 2 } },
37
- React.createElement(TextField, { label: "Postcode", value: (_j = val.postcode) !== null && _j !== void 0 ? _j : "", onChange: (e) => update('postcode', e.target.value), required: true, error: !!postcodeError, helperText: postcodeError, fullWidth: true, disabled: !enabled }),
38
- React.createElement(TextField, { label: "Number", type: "number", value: (_k = val.number) !== null && _k !== void 0 ? _k : "", onChange: (e) => update('number', +e.target.value), required: true, error: !!numberError, helperText: numberError, fullWidth: true, disabled: !enabled }))));
39
- };
40
- const FormRendererAddress = ({ data, handleChange, path, label, enabled, schema }) => {
41
- const getError = useLocalErrors(path);
42
- console.log("tt", JSON.stringify(schema));
43
- //if(isValidAgainstSchema(schema, data))
44
- return React.createElement(FormAddress, { address: data, label: label, onChange: (addr) => handleChange(path, addr), getError: getError, enabled: enabled });
45
- };
46
- registerComponent("-address", FormRendererAddress, ComponentPool.FORM);
@@ -1 +0,0 @@
1
- export {};
@@ -1,34 +0,0 @@
1
- import React from 'react';
2
- import { Box, Paper, Typography } from '@mui/material';
3
- import { ComponentPool } from '../../registry/types';
4
- import { registerComponent } from '../../registry/components';
5
- const FormAddress = ({ address }) => {
6
- return (React.createElement(Paper, { sx: { display: 'flex', flexDirection: 'column', gap: 1, p: 2, mb: 1 }, elevation: 1 },
7
- React.createElement(Typography, { variant: "h6", gutterBottom: true }, "Addressssssss Details"),
8
- React.createElement(Box, { sx: { display: 'flex', flexDirection: 'column', gap: 0.5 } },
9
- React.createElement(Typography, null,
10
- React.createElement("strong", null, "Line 1:"),
11
- " ", address === null || address === void 0 ? void 0 :
12
- address.line1),
13
- (address === null || address === void 0 ? void 0 : address.line2) && (React.createElement(Typography, null,
14
- React.createElement("strong", null, "Line 2:"),
15
- " ",
16
- address.line2))),
17
- React.createElement(Typography, null,
18
- React.createElement("strong", null, "City:"),
19
- " ", address === null || address === void 0 ? void 0 :
20
- address.city),
21
- React.createElement(Box, { sx: { display: 'flex', gap: 2 } },
22
- React.createElement(Typography, null,
23
- React.createElement("strong", null, "Postcode:"),
24
- " ", address === null || address === void 0 ? void 0 :
25
- address.postcode),
26
- React.createElement(Typography, null,
27
- React.createElement("strong", null, "Number:"),
28
- " ", address === null || address === void 0 ? void 0 :
29
- address.number))));
30
- };
31
- const FormRendererAddress = ({ data }) => {
32
- return React.createElement(FormAddress, { address: data });
33
- };
34
- registerComponent("-address", FormRendererAddress, ComponentPool.PRESENTATION);
@@ -1,4 +0,0 @@
1
- import { FormSchema, Stage } from "../formSchemaTypes";
2
- import { JsonSchema } from "@jsonforms/core";
3
- import "../../prebuild/generated/import_generated";
4
- export declare const generateJsonSchema: (formSchema: FormSchema, stage: Stage) => JsonSchema | undefined;
@@ -1,59 +0,0 @@
1
- import { getType } from "../../registry/fields";
2
- import { generateFieldId } from "../util";
3
- import "../../prebuild/generated/import_generated";
4
- export const generateJsonSchema = (formSchema, stage) => {
5
- // Lazy try catch rn
6
- try {
7
- const built = {
8
- type: "object",
9
- properties: {},
10
- required: [],
11
- };
12
- formSchema.forEach(s => {
13
- if (stage < s.existsFrom)
14
- return;
15
- const fieldSchema = defaultConverter(s, stage);
16
- built.properties[generateFieldId(s.name)] = fieldSchema;
17
- if (s.required)
18
- built.required.push(generateFieldId(s.name));
19
- });
20
- return built;
21
- }
22
- catch (e) {
23
- console.error(e);
24
- return undefined;
25
- }
26
- };
27
- const defaultConverter = (field, stage, omitTitle, isChild) => {
28
- var _a, _b, _c, _d, _e;
29
- // Default field type
30
- field.fieldType = (_a = field.fieldType) !== null && _a !== void 0 ? _a : "string";
31
- let schema = getType(field.fieldType);
32
- if (!schema)
33
- throw new Error("tried to generate schema from unknown type: " + field.fieldType + "\nFull object: " + JSON.stringify(field, null, 2));
34
- const requiredFields = [];
35
- if (field.required)
36
- requiredFields.push(field.name);
37
- // Specific for array
38
- let arrayItems = field.fieldType === "array" ? defaultConverter((_b = field.arrayOptions) === null || _b === void 0 ? void 0 : _b.itemDefinition, stage, true, true) : undefined;
39
- // Obj childs
40
- const properties = {};
41
- for (const child of (_d = (_c = field.objectOptions) === null || _c === void 0 ? void 0 : _c.properties) !== null && _d !== void 0 ? _d : []) {
42
- const fieldId = generateFieldId(child.name);
43
- properties[fieldId] = defaultConverter(child, stage, false, true);
44
- if (child.required)
45
- requiredFields.push(fieldId);
46
- }
47
- // Enum fails if empty, fixes
48
- let enumOpts = field.fieldType === "enum" ? (() => {
49
- var _a;
50
- let enumOptions = (((_a = field.enumOptions) === null || _a === void 0 ? void 0 : _a.enumValues) || []);
51
- if (enumOptions.length === 0)
52
- enumOptions.push("");
53
- return enumOptions;
54
- })() : undefined;
55
- // Component (probably should change this)
56
- let templates = field.fieldType === "componentPicker" ? { "x-templateIds": (_e = field.componentOptions) === null || _e === void 0 ? void 0 : _e.templateIds } : {};
57
- let title = omitTitle ? undefined : field.name;
58
- 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 }));
59
- };