@headless-adminapp/app 0.0.17-alpha.56 → 0.0.17-alpha.59

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.
@@ -15,7 +15,7 @@ const InitialValueResolver_1 = require("./InitialValueResolver");
15
15
  const ReadonlyInfoResolver_1 = require("./ReadonlyInfoResolver");
16
16
  function DataFormProvider(props) {
17
17
  const { schemaStore } = (0, useMetadata_1.useMetadata)();
18
- const { language } = (0, useLocale_1.useLocale)();
18
+ const { language, region } = (0, useLocale_1.useLocale)();
19
19
  const formValidationStrings = (0, FormValidationStringContext_1.useFormValidationStrings)();
20
20
  const [formReadOnly, setFormReadOnly] = (0, react_1.useState)(false); // A trick to provide readOnly info to formInstance
21
21
  const formInstance = (0, react_hook_form_1.useForm)({
@@ -28,6 +28,7 @@ function DataFormProvider(props) {
28
28
  schema: props.schema,
29
29
  strings: formValidationStrings,
30
30
  formReadOnly,
31
+ region,
31
32
  }),
32
33
  shouldUnregister: false,
33
34
  });
@@ -11,6 +11,7 @@ exports.useFormSave = useFormSave;
11
11
  // Wrapper - Loader, response message
12
12
  // Core - Extract modified fields, prepare operations, perform operations
13
13
  const route_1 = require("@headless-adminapp/app/route");
14
+ const app_1 = require("@headless-adminapp/core/experience/app");
14
15
  const react_query_1 = require("@tanstack/react-query");
15
16
  const react_1 = require("react");
16
17
  const react_hook_form_1 = require("react-hook-form");
@@ -35,6 +36,7 @@ function useFormSave() {
35
36
  const dataService = (0, transport_1.useDataService)();
36
37
  const { showProgressIndicator, hideProgressIndicator } = (0, useProgressIndicator_1.useProgressIndicator)();
37
38
  const openToastNotification = (0, useOpenToastNotification_1.useOpenToastNotification)();
39
+ const routeResolver = (0, route_1.useRouteResolver)();
38
40
  const client = (0, react_query_1.useQueryClient)();
39
41
  const router = (0, route_1.useRouter)();
40
42
  function showMessageAfterSave({ isCreatedMode }) {
@@ -81,12 +83,17 @@ function useFormSave() {
81
83
  });
82
84
  return;
83
85
  }
84
- // invalidateQueriesAfterSave({
85
- // client,
86
- // });
87
- if (mode === 'save' && record) {
88
- await refresh();
89
- // client.invalidateQueries({ queryKey: ['data', 'retriveRecord'] });
86
+ if (mode === 'save') {
87
+ if (record) {
88
+ await refresh();
89
+ }
90
+ else {
91
+ router.replace(routeResolver({
92
+ type: app_1.PageType.EntityForm,
93
+ logicalName: schema.logicalName,
94
+ id: result.recordId,
95
+ }));
96
+ }
90
97
  }
91
98
  else {
92
99
  await client.invalidateQueries({
@@ -99,14 +106,6 @@ function useFormSave() {
99
106
  await client.invalidateQueries({
100
107
  queryKey: ['data', 'retriveRecords'],
101
108
  });
102
- // redirectAfterSave({
103
- // navigation,
104
- // isCreatedMode: !context.state.record,
105
- // recordId: result.recordId,
106
- // reset: form.reset,
107
- // logicalName: schema.logicalName,
108
- // mode,
109
- // });
110
109
  showMessageAfterSave({
111
110
  isCreatedMode: !record,
112
111
  });
@@ -24,10 +24,11 @@ interface FormValidatorOptions<A extends SchemaAttributes = SchemaAttributes> {
24
24
  readonlyAttributes?: string[];
25
25
  strings: FormValidationStringSet;
26
26
  schemaStore: ISchemaStore;
27
+ region: string;
27
28
  }
28
29
  type FormValidator = (<A extends SchemaAttributes = SchemaAttributes>(options: FormValidatorOptions<A>) => (values: Record<string, any>, context: any, options: any) => Promise<ResolverResult<{}>>) & MemoizedFunction;
29
30
  export declare const formValidator: FormValidator;
30
- export declare const generateValidationSchema: (<A extends SchemaAttributes = SchemaAttributes>({ columns, editableGrids, language, schema, strings, readonlyAttributes, }: {
31
+ export declare const generateValidationSchema: (<A extends SchemaAttributes = SchemaAttributes>({ columns, editableGrids, language, schema, strings, readonlyAttributes, region, }: {
31
32
  schema: Schema<A>;
32
33
  columns: string[];
33
34
  readonlyAttributes?: string[];
@@ -39,9 +40,10 @@ export declare const generateValidationSchema: (<A extends SchemaAttributes = Sc
39
40
  }> | undefined;
40
41
  language: string;
41
42
  strings: FormValidationStringSet;
43
+ region: string;
42
44
  }) => yup.ObjectSchema<{
43
45
  [x: string]: any;
44
46
  }, yup.AnyObject, {
45
47
  [x: string]: any;
46
48
  }, "">) & MemoizedFunction;
47
- export declare const generateAttributeValidationSchema: ((attribute: Attribute, language: string, strings: FormValidationStringSet) => yup.Schema<any, any, any, "">) & MemoizedFunction;
49
+ export declare const generateAttributeValidationSchema: ((attribute: Attribute, language: string, strings: FormValidationStringSet, region: string) => yup.Schema<any, any, any, "">) & MemoizedFunction;
@@ -25,6 +25,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
26
  exports.generateAttributeValidationSchema = exports.generateValidationSchema = exports.formValidator = exports.saveRecord = void 0;
27
27
  exports.getInitialValues = getInitialValues;
28
+ const phone_1 = require("@headless-adminapp/app/utils/phone");
28
29
  const yup_1 = require("@hookform/resolvers/yup");
29
30
  const lodash_1 = require("lodash");
30
31
  const yup = __importStar(require("yup"));
@@ -96,7 +97,7 @@ function getInitialValues({ cloneRecord, form, record, recordId, schema, default
96
97
  };
97
98
  }, {});
98
99
  }
99
- exports.formValidator = (0, lodash_1.memoize)(function formValidator({ form, schema, readonlyAttributes, formReadOnly, schemaStore, language, strings, }) {
100
+ exports.formValidator = (0, lodash_1.memoize)(function formValidator({ form, schema, readonlyAttributes, formReadOnly, schemaStore, language, strings, region, }) {
100
101
  return async (values, context, options) => {
101
102
  let validator = yup.object().shape({});
102
103
  if (!formReadOnly) {
@@ -140,6 +141,7 @@ exports.formValidator = (0, lodash_1.memoize)(function formValidator({ form, sch
140
141
  language,
141
142
  strings,
142
143
  readonlyAttributes,
144
+ region,
143
145
  });
144
146
  }
145
147
  const resolver = (0, yup_1.yupResolver)(validator);
@@ -154,14 +156,14 @@ exports.formValidator = (0, lodash_1.memoize)(function formValidator({ form, sch
154
156
  readonlyAttributes,
155
157
  formReadOnly,
156
158
  }));
157
- exports.generateValidationSchema = (0, lodash_1.memoize)(function generateValidationSchema({ columns, editableGrids, language, schema, strings, readonlyAttributes, }) {
159
+ exports.generateValidationSchema = (0, lodash_1.memoize)(function generateValidationSchema({ columns, editableGrids, language, schema, strings, readonlyAttributes, region, }) {
158
160
  return yup.object().shape({
159
161
  ...columns.reduce((acc, column) => {
160
162
  if (readonlyAttributes?.includes(column)) {
161
163
  return acc;
162
164
  }
163
165
  const attribute = schema.attributes[column];
164
- const validationSchema = (0, exports.generateAttributeValidationSchema)(attribute, language, strings);
166
+ const validationSchema = (0, exports.generateAttributeValidationSchema)(attribute, language, strings, region);
165
167
  return {
166
168
  ...acc,
167
169
  [column]: validationSchema,
@@ -173,7 +175,7 @@ exports.generateValidationSchema = (0, lodash_1.memoize)(function generateValida
173
175
  .of(yup.object().shape({
174
176
  ...grid.columns.reduce((acc, column) => {
175
177
  const attribute = grid.schema.attributes[column];
176
- const validationSchema = (0, exports.generateAttributeValidationSchema)(attribute, language, strings);
178
+ const validationSchema = (0, exports.generateAttributeValidationSchema)(attribute, language, strings, region);
177
179
  return {
178
180
  ...acc,
179
181
  [column]: validationSchema,
@@ -190,13 +192,14 @@ exports.generateValidationSchema = (0, lodash_1.memoize)(function generateValida
190
192
  return acc;
191
193
  }, {}),
192
194
  });
193
- }, ({ columns, editableGrids, language, schema, strings, readonlyAttributes }) => JSON.stringify({
195
+ }, ({ columns, editableGrids, language, schema, strings, readonlyAttributes, region, }) => JSON.stringify({
194
196
  schema,
195
197
  columns,
196
198
  editableGrids,
197
199
  language,
198
200
  strings,
199
201
  readonlyAttributes,
202
+ region,
200
203
  }));
201
204
  function createAttributeValidationSchema(attribute) {
202
205
  let validationSchema;
@@ -224,7 +227,7 @@ function extendAttributeRequiredValidationSchema({ attribute, validationSchema,
224
227
  }
225
228
  return validationSchema;
226
229
  }
227
- function extendAttributeValidationSchema({ attribute, validationSchema, label, strings, }) {
230
+ function extendAttributeValidationSchema({ attribute, validationSchema, label, strings, region, }) {
228
231
  switch (attribute.type) {
229
232
  case 'string':
230
233
  validationSchema = extendAttributeStringValidationSchema({
@@ -232,6 +235,7 @@ function extendAttributeValidationSchema({ attribute, validationSchema, label, s
232
235
  validationSchema: validationSchema,
233
236
  label,
234
237
  strings,
238
+ region,
235
239
  });
236
240
  break;
237
241
  case 'attachments':
@@ -247,7 +251,7 @@ function extendAttributeValidationSchema({ attribute, validationSchema, label, s
247
251
  }
248
252
  return validationSchema;
249
253
  }
250
- function extendAttributeStringValidationSchema({ attribute, validationSchema, label, strings, }) {
254
+ function extendAttributeStringValidationSchema({ attribute, validationSchema, label, strings, region, }) {
251
255
  if (attribute.maxLength) {
252
256
  // extend the validation schema with the max length
253
257
  validationSchema = validationSchema.max(attribute.maxLength, `${label}: ${strings.maxLength}`);
@@ -266,7 +270,16 @@ function extendAttributeStringValidationSchema({ attribute, validationSchema, la
266
270
  }
267
271
  else if (attribute.format === 'phone') {
268
272
  // extend the validation schema with the phone format
269
- validationSchema = validationSchema.matches(/^(\+\d{1,2}\s?)?\d{10}$/, `${label}: ${strings.invalidPhoneNumber}`);
273
+ validationSchema = validationSchema.test({
274
+ message: `${label}: ${strings.invalidPhoneNumber}`,
275
+ test: (value) => {
276
+ if (!value) {
277
+ return true;
278
+ }
279
+ const phoneNumber = (0, phone_1.parsePhoneNumber)(value, region);
280
+ return phoneNumber.isValid;
281
+ },
282
+ });
270
283
  }
271
284
  return validationSchema;
272
285
  }
@@ -286,7 +299,7 @@ function extendAttributeAttachmentsValidationSchema({ attribute, validationSchem
286
299
  }
287
300
  return validationSchema;
288
301
  }
289
- exports.generateAttributeValidationSchema = (0, lodash_1.memoize)(function generateAttributeValidationSchema(attribute, language, strings) {
302
+ exports.generateAttributeValidationSchema = (0, lodash_1.memoize)(function generateAttributeValidationSchema(attribute, language, strings, region) {
290
303
  let validationSchema = createAttributeValidationSchema(attribute);
291
304
  const label = (0, utils_1.localizedLabel)(language, attribute);
292
305
  validationSchema = extendAttributeRequiredValidationSchema({
@@ -300,6 +313,7 @@ exports.generateAttributeValidationSchema = (0, lodash_1.memoize)(function gener
300
313
  validationSchema,
301
314
  label,
302
315
  strings,
316
+ region,
303
317
  });
304
318
  validationSchema = validationSchema.transform((value) => {
305
319
  if (value === '') {
@@ -8,6 +8,7 @@ const context_1 = require("../../mutable/context");
8
8
  const useRetriveRecords_1 = require("../../transport/hooks/useRetriveRecords");
9
9
  const context_2 = require("../context");
10
10
  const hooks_1 = require("../hooks");
11
+ const useGridDisabled_1 = require("../hooks/useGridDisabled");
11
12
  const utils_1 = require("./utils");
12
13
  const MAX_RECORDS = 10000;
13
14
  function DataResolver() {
@@ -20,6 +21,7 @@ function DataResolver() {
20
21
  const gridColumns = (0, hooks_1.useGridColumns)();
21
22
  const maxRecords = (0, hooks_1.useMaxRecords)() ?? MAX_RECORDS;
22
23
  const [selectedIds] = (0, hooks_1.useGridSelection)();
24
+ const disabled = (0, useGridDisabled_1.useGridDisabled)();
23
25
  const { schemaStore } = (0, useMetadata_1.useMetadata)();
24
26
  const selectedIdsRef = (0, react_1.useRef)(selectedIds);
25
27
  selectedIdsRef.current = selectedIds;
@@ -57,6 +59,7 @@ function DataResolver() {
57
59
  schema,
58
60
  search,
59
61
  sorting,
62
+ disabled,
60
63
  });
61
64
  (0, react_1.useEffect)(() => {
62
65
  setState({
@@ -19,5 +19,6 @@ export interface DataGridProviderProps<S extends SchemaAttributes = SchemaAttrib
19
19
  };
20
20
  allowViewSelection?: boolean;
21
21
  maxRecords?: number;
22
+ disabled?: boolean;
22
23
  }
23
24
  export declare function DataGridProvider<S extends SchemaAttributes = SchemaAttributes, CommandContext extends EntityMainGridCommandContext | EntitySubGridCommandContext = EntityMainGridCommandContext>(props: PropsWithChildren<DataGridProviderProps<S, CommandContext>>): import("react/jsx-runtime").JSX.Element;
@@ -44,6 +44,7 @@ function DataGridProvider(props) {
44
44
  allowViewSelection: props.allowViewSelection ?? false,
45
45
  maxRecords: props.maxRecords,
46
46
  associated: props.associated,
47
+ disabled: props.disabled ?? false,
47
48
  });
48
49
  (0, react_1.useEffect)(() => {
49
50
  contextValue.setValue({
@@ -78,5 +79,10 @@ function DataGridProvider(props) {
78
79
  associated: props.associated,
79
80
  });
80
81
  }, [props.isSubGrid, props.associated, contextValue]);
82
+ (0, react_1.useEffect)(() => {
83
+ contextValue.setValue({
84
+ disabled: props.disabled ?? false,
85
+ });
86
+ }, [props.disabled, contextValue]);
81
87
  return ((0, jsx_runtime_1.jsxs)(context_2.GridContext.Provider, { value: contextValue, children: [(0, jsx_runtime_1.jsx)(DataResolver_1.DataResolver, {}), props.children] }));
82
88
  }
@@ -13,6 +13,7 @@ export interface GridContextState<S extends SchemaAttributes = SchemaAttributes,
13
13
  extraFilter?: Filter;
14
14
  commands?: CommandItemExperience<CommandContext>[][];
15
15
  maxRecords?: number;
16
+ disabled?: boolean;
16
17
  associated?: false | {
17
18
  logicalName: string;
18
19
  id: string;
@@ -0,0 +1 @@
1
+ export declare function useGridDisabled(): boolean | undefined;
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useGridDisabled = useGridDisabled;
4
+ const mutable_1 = require("../../mutable");
5
+ const context_1 = require("../context");
6
+ function useGridDisabled() {
7
+ return (0, mutable_1.useContextSelector)(context_1.GridContext, (state) => state.disabled);
8
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@headless-adminapp/app",
3
- "version": "0.0.17-alpha.56",
3
+ "version": "0.0.17-alpha.59",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -27,11 +27,12 @@
27
27
  "dayjs": "^1.11.13",
28
28
  "exceljs": "^4.4.0",
29
29
  "json-to-csv-export": "^2.1.1",
30
+ "libphonenumber-js": "1.11.20",
30
31
  "lodash": "^4.17.21",
31
32
  "react-custom-scrollbars-2": "^4.5.0",
32
33
  "react-hook-form": "7.52.2",
33
34
  "uuid": "11.0.3",
34
35
  "yup": "^1.4.0"
35
36
  },
36
- "gitHead": "f9d26e133d9298174cde57f72a5d719d8320c667"
37
+ "gitHead": "813d07729a10a5613b46f012ba4b24bcaab384dc"
37
38
  }
@@ -10,10 +10,11 @@ interface UseRetriveRecordProps<S extends SchemaAttributes = SchemaAttributes> {
10
10
  columns: string[];
11
11
  expand?: Partial<Record<string, string[]>>;
12
12
  maxRecords: number;
13
+ disabled?: boolean;
13
14
  }
14
15
  export declare function useRetrieveRecordsKey<S extends SchemaAttributes = SchemaAttributes>({ schema, search, filter, sorting, columns, expand, maxRecords, }: UseRetriveRecordProps<S>): (string | number | string[] | Filter | Partial<Record<string, string[]>> | SortingState<S> | null | undefined)[];
15
16
  export declare function useClearDataExceptFirstPage(queryKey: QueryKey): void;
16
- export declare function useRetriveRecords<S extends SchemaAttributes = SchemaAttributes>(queryKey: QueryKey, { columns, expand, filter, maxRecords, schema, search, sorting, }: UseRetriveRecordProps): {
17
+ export declare function useRetriveRecords<S extends SchemaAttributes = SchemaAttributes>(queryKey: QueryKey, { columns, expand, filter, maxRecords, schema, search, sorting, disabled, }: UseRetriveRecordProps): {
17
18
  data: {
18
19
  logicalName: string;
19
20
  count: number;
@@ -41,7 +41,7 @@ function useClearDataExceptFirstPage(queryKey) {
41
41
  };
42
42
  }, [queryClient, queryKey]);
43
43
  }
44
- function useRetriveRecords(queryKey, { columns, expand, filter, maxRecords, schema, search, sorting, }) {
44
+ function useRetriveRecords(queryKey, { columns, expand, filter, maxRecords, schema, search, sorting, disabled, }) {
45
45
  const dataService = (0, transport_1.useDataService)();
46
46
  const { data, isFetching, hasNextPage, fetchNextPage, isFetchingNextPage } = (0, react_query_1.useInfiniteQuery)({
47
47
  queryKey: queryKey,
@@ -88,6 +88,7 @@ function useRetriveRecords(queryKey, { columns, expand, filter, maxRecords, sche
88
88
  initialPageParam: {
89
89
  pageIndex: 0,
90
90
  },
91
+ enabled: !disabled,
91
92
  });
92
93
  const finalData = (0, react_1.useMemo)(() => {
93
94
  if (!data?.pages.length) {
@@ -13,5 +13,6 @@ export declare function getAttributeFormattedValue<A extends Attribute = Attribu
13
13
  currencySign?: 'accounting' | 'standard';
14
14
  currencyDisplay?: 'symbol' | 'narrowSymbol' | 'code';
15
15
  timezone?: string;
16
+ region?: string;
16
17
  }): string | null;
17
18
  export {};
@@ -7,6 +7,7 @@ exports.getAttributeFormattedValue = getAttributeFormattedValue;
7
7
  const dayjs_1 = __importDefault(require("dayjs"));
8
8
  const timezone_1 = __importDefault(require("dayjs/plugin/timezone"));
9
9
  const utc_1 = __importDefault(require("dayjs/plugin/utc"));
10
+ const phone_1 = require("./phone");
10
11
  dayjs_1.default.extend(utc_1.default);
11
12
  dayjs_1.default.extend(timezone_1.default);
12
13
  const defaultAttributeFormattedValueStrings = {
@@ -108,6 +109,7 @@ function getAttributeFormattedValue(attribute, value, options) {
108
109
  return null;
109
110
  }
110
111
  const locale = options?.locale ?? defaultLocale;
112
+ const region = options?.region ?? 'US';
111
113
  switch (attribute.type) {
112
114
  case 'boolean':
113
115
  return getAttributeBooleanFormattedValue(attribute, value, options);
@@ -129,6 +131,13 @@ function getAttributeFormattedValue(attribute, value, options) {
129
131
  return new Intl.NumberFormat(locale).format(value);
130
132
  case 'attachment':
131
133
  return getAttributeAttachmentFormattedValue(value);
134
+ case 'string':
135
+ if (attribute.format === 'phone' && typeof value === 'string') {
136
+ return (0, phone_1.parsePhoneNumber)(value, region).formattedNationalValue;
137
+ }
138
+ return typeof value === 'object'
139
+ ? JSON.stringify(value)
140
+ : value;
132
141
  default:
133
142
  return typeof value === 'object'
134
143
  ? JSON.stringify(value)
@@ -0,0 +1,13 @@
1
+ export declare function parsePhoneNumber(input: string, defaultCountry?: string): {
2
+ formattedInternationalValue: string;
3
+ formattedNationalValue: string;
4
+ rawValue: string;
5
+ isValid: boolean;
6
+ uri: string;
7
+ } | {
8
+ formattedInternationalValue: string;
9
+ formattedNationalValue: string;
10
+ rawValue: string;
11
+ isValid: boolean;
12
+ uri: null;
13
+ };
package/utils/phone.js ADDED
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parsePhoneNumber = parsePhoneNumber;
4
+ const libphonenumber_js_1 = require("libphonenumber-js");
5
+ function parsePhoneNumber(input, defaultCountry) {
6
+ try {
7
+ const phoneNumber = (0, libphonenumber_js_1.parsePhoneNumberWithError)(input, defaultCountry);
8
+ let rawValue = String(phoneNumber.number);
9
+ if (phoneNumber.ext) {
10
+ rawValue += ';ext=' + phoneNumber.ext;
11
+ }
12
+ let formattedNational = phoneNumber.formatInternational();
13
+ if (defaultCountry && defaultCountry === phoneNumber.country) {
14
+ formattedNational = phoneNumber.formatNational();
15
+ }
16
+ return {
17
+ formattedInternationalValue: phoneNumber.formatInternational(),
18
+ formattedNationalValue: formattedNational,
19
+ rawValue: rawValue,
20
+ isValid: phoneNumber.isPossible(),
21
+ uri: phoneNumber.getURI(),
22
+ };
23
+ }
24
+ catch (error) {
25
+ return {
26
+ formattedInternationalValue: input,
27
+ formattedNationalValue: input,
28
+ rawValue: input,
29
+ isValid: false,
30
+ uri: null,
31
+ };
32
+ }
33
+ }