@headless-adminapp/app 1.1.0 → 1.1.5

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.
@@ -5,12 +5,13 @@ import type { SchemaAttributes } from '@headless-adminapp/core/schema';
5
5
  export declare namespace DefineFormExperience {
6
6
  export type Experience<S extends SchemaAttributes = SchemaAttributes> = (Pick<$FormExperience<S>, 'useHookFn' | 'relatedItems' | 'processFlow' | 'cloneAttributes' | 'defaultValues' | 'includeAttributes' | 'headerControls'> & {
7
7
  tabs: Tab<S>[];
8
- }) | (keyof S)[];
8
+ }) | SectionControl<S>[];
9
9
  export function resolveExperience<S extends SchemaAttributes = SchemaAttributes>(v: Experience<S>): $FormExperience<S>;
10
- type Tab<S extends SchemaAttributes = SchemaAttributes> = Pick<$Tab<S>, 'label' | 'localizedLabels' | 'name'> & ({
11
- tabColumns: TabColumn<S>[];
10
+ type Tab<S extends SchemaAttributes = SchemaAttributes> = Pick<$Tab<S>, 'label' | 'localizedLabels' | 'name'> & {
12
11
  columnCount?: $Tab<S>['columnCount'];
13
12
  columnWidths?: $Tab<S>['columnWidths'];
13
+ } & ({
14
+ tabColumns: TabColumn<S>[];
14
15
  } | {
15
16
  sections: Section<S>[];
16
17
  } | {
@@ -41,13 +41,12 @@ var DefineFormExperience;
41
41
  name: v.name,
42
42
  localizedLabels: v.localizedLabels,
43
43
  };
44
+ tab.columnCount = v.columnCount ?? 2;
45
+ tab.columnWidths = v.columnWidths;
44
46
  if ('tabColumns' in v) {
45
- tab.columnCount = v.columnCount ?? 2;
46
- tab.columnWidths = v.columnWidths;
47
47
  tab.tabColumns = v.tabColumns.map(resolveTabColumn);
48
48
  }
49
49
  else if ('sections' in v) {
50
- tab.columnCount = 2;
51
50
  tab.tabColumns = [
52
51
  {
53
52
  sections: v.sections.map(resolveSection),
@@ -55,7 +54,6 @@ var DefineFormExperience;
55
54
  ];
56
55
  }
57
56
  else if ('controls' in v) {
58
- tab.columnCount = 2;
59
57
  tab.tabColumns = [
60
58
  {
61
59
  sections: [
@@ -16,7 +16,7 @@ export interface CalendarEventsResolverFnOptions<SA extends SchemaAttributes = S
16
16
  auth: AuthSession | null;
17
17
  }
18
18
  export type CalendarEventsResolverFn<SA extends SchemaAttributes = SchemaAttributes> = (options: CalendarEventsResolverFnOptions<SA>) => Promise<CalendarEvent[]>;
19
- export type CalendarEventResolverFn<T extends CalendarEvent = CalendarEvent> = (id: string) => Promise<T>;
19
+ export type CalendarEventResolverFn<T extends CalendarEvent = CalendarEvent> = (id: string) => Promise<Partial<T>>;
20
20
  export type CalendarEventSaveData<SA1 extends SchemaAttributes = SchemaAttributes, SA2 extends SchemaAttributes = SchemaAttributes> = Omit<CalendarEvent, 'id'> & {
21
21
  id?: CalendarEvent['id'];
22
22
  } & InferredSchemaType<SA1> & InferredSchemaType<SA2>;
@@ -1,27 +1,27 @@
1
+ import { Id } from '@headless-adminapp/core';
1
2
  import { Form } from '@headless-adminapp/core/experience/form';
2
3
  import { InferredSchemaType, Schema, SchemaAttributes } from '@headless-adminapp/core/schema';
3
4
  import { ISchemaStore } from '@headless-adminapp/core/store';
4
5
  import { IDataService } from '@headless-adminapp/core/transport';
5
6
  import { Nullable } from '@headless-adminapp/core/types';
6
7
  export declare function getModifiedValues(initialValues: any, values: any, exclude?: string[]): Record<string, any>;
7
- type SaveRecordResult = {
8
+ export type SaveRecordResult = {
8
9
  success: true;
9
- recordId: string;
10
+ recordId: Id;
10
11
  } | {
11
12
  success: false;
12
13
  title?: string;
13
14
  message: string;
14
15
  isError: boolean;
15
16
  };
16
- export interface SaveRecordFnOptions {
17
+ export interface SaveRecordFnOptions<S extends SchemaAttributes = SchemaAttributes> {
17
18
  values: any;
18
- form: Form<SchemaAttributes>;
19
- record: InferredSchemaType<SchemaAttributes> | undefined;
20
- initialValues: Nullable<InferredSchemaType<SchemaAttributes>>;
21
- schema: Schema<SchemaAttributes>;
19
+ form: Form<S>;
20
+ record: InferredSchemaType<S> | undefined;
21
+ initialValues: Nullable<InferredSchemaType<S>>;
22
+ schema: Schema<S>;
22
23
  dataService: IDataService;
23
24
  schemaStore: ISchemaStore;
24
25
  }
25
26
  export type SaveRecordFn = (options: SaveRecordFnOptions) => Promise<SaveRecordResult>;
26
27
  export declare function saveRecord({ values, form, schema, dataService, initialValues, record, schemaStore, }: SaveRecordFnOptions): Promise<SaveRecordResult>;
27
- export {};
@@ -81,7 +81,7 @@ async function createRecord({ values, form, schema, dataService, }) {
81
81
  const controls = (0, utils_1.getControls)(form);
82
82
  const editableGridControls = controls.filter((control) => control.type === 'editablegrid');
83
83
  const result = await dataService.createRecord(schema.logicalName, values);
84
- const recordId = result[schema.idAttribute];
84
+ const recordId = result.id;
85
85
  for (const control of editableGridControls) {
86
86
  const gridRows = values[control.attributeName];
87
87
  for (const row of gridRows) {
@@ -11,7 +11,6 @@ const context_2 = require("../context");
11
11
  const hooks_2 = require("../hooks");
12
12
  const useGridDisabled_1 = require("../hooks/useGridDisabled");
13
13
  const utils_1 = require("./utils");
14
- const MAX_RECORDS = 10000;
15
14
  function DataResolver() {
16
15
  const schema = (0, hooks_2.useDataGridSchema)();
17
16
  const view = (0, hooks_2.useSelectedView)();
@@ -20,7 +19,7 @@ function DataResolver() {
20
19
  const extraFilter = (0, hooks_2.useGridExtraFilter)();
21
20
  const [columnFilters] = (0, hooks_2.useGridColumnFilter)();
22
21
  const gridColumns = (0, hooks_2.useGridColumns)();
23
- const maxRecords = (0, hooks_2.useMaxRecords)() ?? MAX_RECORDS;
22
+ const maxRecords = (0, hooks_2.useMaxRecords)();
24
23
  const [selectedIds] = (0, hooks_2.useGridSelection)();
25
24
  const disabled = (0, useGridDisabled_1.useGridDisabled)();
26
25
  const { schemaStore } = (0, useMetadata_1.useMetadata)();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@headless-adminapp/app",
3
- "version": "1.1.0",
3
+ "version": "1.1.5",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -36,5 +36,5 @@
36
36
  "uuid": "11.0.3",
37
37
  "yup": "^1.4.0"
38
38
  },
39
- "gitHead": "a244ac890d3abda779c8f41c3cd51031381c062c"
39
+ "gitHead": "76976de5e79eb752b80bb090de8228392851f0cc"
40
40
  }
@@ -9,7 +9,7 @@ interface UseRetriveRecordProps<S extends SchemaAttributes = SchemaAttributes> {
9
9
  sorting?: SortingState<S>;
10
10
  columns: string[];
11
11
  expand?: Partial<Record<string, string[]>>;
12
- maxRecords: number;
12
+ maxRecords?: number;
13
13
  disabled?: boolean;
14
14
  }
15
15
  export declare function useRetrieveRecordsKey<S extends SchemaAttributes = SchemaAttributes>({ schema, search, filter, sorting, columns, expand, maxRecords, }: UseRetriveRecordProps<S>): QueryKey;
@@ -8,6 +8,7 @@ const transport_1 = require("@headless-adminapp/app/transport");
8
8
  const react_query_1 = require("@tanstack/react-query");
9
9
  const react_1 = require("react");
10
10
  const ROWS_PER_PAGE = 100;
11
+ const MAX_RECORDS = 10000;
11
12
  function useRetrieveRecordsKey({ schema, search, filter, sorting, columns, expand, maxRecords, }) {
12
13
  const queryKey = (0, react_1.useMemo)(() => [
13
14
  'data',
@@ -54,8 +55,9 @@ function useRetriveRecordsInternal(queryKey, { columns, expand, filter, maxRecor
54
55
  const params = queryContext.pageParam ?? {
55
56
  pageIndex: 0,
56
57
  };
58
+ const _maxRecords = maxRecords ?? MAX_RECORDS;
57
59
  const skip = params.pageIndex * ROWS_PER_PAGE;
58
- const limit = Math.min(ROWS_PER_PAGE, Math.max(0, maxRecords - skip));
60
+ const limit = Math.min(ROWS_PER_PAGE, Math.max(0, _maxRecords - skip));
59
61
  if (limit <= 0) {
60
62
  return {
61
63
  params: params,
@@ -3,6 +3,7 @@ interface AttributeFormattedValueStringsSet {
3
3
  yes: string;
4
4
  no: string;
5
5
  }
6
+ export declare function formatDuration(value: number | null): string;
6
7
  export declare function getAttributeFormattedValue<A extends Attribute = Attribute>(attribute: Attribute, value: InferredAttributeType<A> | null | undefined, options?: {
7
8
  maxCount?: number;
8
9
  strings?: AttributeFormattedValueStringsSet;
@@ -3,6 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.formatDuration = formatDuration;
6
7
  exports.getAttributeFormattedValue = getAttributeFormattedValue;
7
8
  const dayjs_1 = __importDefault(require("dayjs"));
8
9
  const timezone_1 = __importDefault(require("dayjs/plugin/timezone"));
@@ -104,11 +105,56 @@ function getAttributeMoneyFormattedValue(value, options) {
104
105
  currencyDisplay,
105
106
  }).format(value);
106
107
  }
108
+ function getAttributeNumberFormattedValue(attribute, value, options) {
109
+ if (attribute.format === 'duration') {
110
+ return formatDuration(value);
111
+ }
112
+ if (attribute.format === 'time') {
113
+ return (0, dayjs_1.default)()
114
+ .startOf('day')
115
+ .add(value, 'minutes')
116
+ .format(options?.timeFormat ?? defaultTimeFormat);
117
+ }
118
+ return new Intl.NumberFormat(options?.locale).format(value);
119
+ }
120
+ function formatDuration(value) {
121
+ if (!value) {
122
+ return '';
123
+ }
124
+ // No decimal, if value is decimal, round to nearest whole number
125
+ // 1 - 1 minute
126
+ // 2-59 minutes -> 2-59 minutes
127
+ // 90 minutes -> 1.5 hours
128
+ // more than a day -> 1 day, 1.5 days, 2 days, etc.
129
+ // check if value has decimal
130
+ if (value % 1 !== 0) {
131
+ // round to nearest whole number
132
+ value = Math.round(value);
133
+ }
134
+ if (!value) {
135
+ return '';
136
+ }
137
+ if (value === 1) {
138
+ return '1 minute';
139
+ }
140
+ if (value < 60) {
141
+ return `${value} minutes`;
142
+ }
143
+ if (value === 60) {
144
+ return '1 hour';
145
+ }
146
+ if (value < 1440) {
147
+ return `${Number((value / 60).toFixed(2))} hours`;
148
+ }
149
+ if (value === 1440) {
150
+ return '1 day';
151
+ }
152
+ return `${Number((value / 1440).toFixed(2))} days`;
153
+ }
107
154
  function getAttributeFormattedValue(attribute, value, options) {
108
155
  if (value === null || value === undefined) {
109
156
  return null;
110
157
  }
111
- const locale = options?.locale ?? defaultLocale;
112
158
  const region = options?.region ?? 'US';
113
159
  switch (attribute.type) {
114
160
  case 'boolean':
@@ -128,7 +174,7 @@ function getAttributeFormattedValue(attribute, value, options) {
128
174
  case 'money':
129
175
  return getAttributeMoneyFormattedValue(value, options);
130
176
  case 'number':
131
- return new Intl.NumberFormat(locale).format(value);
177
+ return getAttributeNumberFormattedValue(attribute, value, options);
132
178
  case 'attachment':
133
179
  return getAttributeAttachmentFormattedValue(value);
134
180
  case 'string':