@headless-adminapp/app 1.1.10 → 1.2.0

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.
Files changed (38) hide show
  1. package/board/BoardColumnDataResolver.js +33 -1
  2. package/board/context.d.ts +1 -0
  3. package/board/hooks/useQuickFilter.d.ts +1 -0
  4. package/board/hooks/useQuickFilter.js +20 -0
  5. package/board/types.d.ts +2 -0
  6. package/builders/CommandBuilder/DefaultCommandBuilder.js +5 -0
  7. package/builders/CommandBuilder/ViewCommandBuilder.d.ts +5 -0
  8. package/builders/CommandBuilder/ViewCommandBuilder.js +84 -3
  9. package/builders/DefineViewExperience.d.ts +1 -1
  10. package/builders/SchemaExperienceBuilder.d.ts +1 -1
  11. package/builders/utils.js +2 -1
  12. package/calendar/CalendarProvider.d.ts +8 -0
  13. package/calendar/CalendarProvider.js +18 -0
  14. package/calendar/hooks/useDeleteEvent.d.ts +1 -0
  15. package/calendar/hooks/useDeleteEvent.js +54 -0
  16. package/calendar/hooks/useOpenDetailDialog.d.ts +2 -0
  17. package/calendar/hooks/useOpenDetailDialog.js +61 -0
  18. package/calendar/types.d.ts +25 -6
  19. package/components/ScrollView/index.js +9 -8
  20. package/dataform/DataFormProvider/getRecord.d.ts +10 -1
  21. package/dataform/DataFormProvider/getRecord.js +38 -28
  22. package/dataform/DataFormProvider/utils.d.ts +1 -1
  23. package/dataform/DataFormProvider/utils.js +1 -1
  24. package/dataform/utils/index.d.ts +14 -1
  25. package/dataform/utils/index.js +45 -7
  26. package/dataform/utils/saveRecord.d.ts +36 -1
  27. package/dataform/utils/saveRecord.js +38 -9
  28. package/datagrid/DataGridProvider/DataResolver.js +22 -2
  29. package/datagrid/DataGridProvider/index.js +2 -0
  30. package/datagrid/DataGridProvider/utils.d.ts +2 -1
  31. package/datagrid/DataGridProvider/utils.js +38 -3
  32. package/datagrid/context.d.ts +1 -0
  33. package/datagrid/hooks/useQuickFilter.d.ts +1 -0
  34. package/datagrid/hooks/useQuickFilter.js +20 -0
  35. package/package.json +2 -2
  36. package/recordset/RecordSetProvider.js +1 -1
  37. package/recordset/hooks/useRecordSetResult.js +1 -0
  38. package/transport/hooks/useRetriveRecords.js +9 -2
@@ -2,24 +2,56 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.DataResolver = DataResolver;
4
4
  const react_1 = require("react");
5
+ const auth_1 = require("../auth");
5
6
  const hooks_1 = require("../hooks");
6
7
  const mutable_1 = require("../mutable");
7
8
  const useRetriveRecords_1 = require("../transport/hooks/useRetriveRecords");
8
9
  const context_1 = require("./context");
9
10
  const useBoardColumnConfig_1 = require("./hooks/useBoardColumnConfig");
10
11
  const useBoardConfig_1 = require("./hooks/useBoardConfig");
12
+ const useQuickFilter_1 = require("./hooks/useQuickFilter");
11
13
  const useSearchText_1 = require("./hooks/useSearchText");
12
14
  const MAX_RECORDS = 10000;
13
15
  function DataResolver() {
14
16
  const { schema, sorting, projection: { columns, expand }, } = (0, useBoardConfig_1.useBoardConfig)();
15
17
  const [searchText] = (0, useSearchText_1.useSearchText)();
18
+ const [quickFilter, quickFilterValues] = (0, useQuickFilter_1.useQuickFilter)();
19
+ const authSession = (0, auth_1.useAuthSession)();
16
20
  const { filter, maxRecords = MAX_RECORDS } = (0, useBoardColumnConfig_1.useBoardColumnConfig)();
17
21
  const setState = (0, mutable_1.useContextSetValue)(context_1.BoardColumnContext);
18
22
  const [search] = (0, hooks_1.useDebouncedValue)(searchText, 500);
23
+ const quickFilterResults = (0, react_1.useMemo)(() => {
24
+ if (!quickFilter) {
25
+ return null;
26
+ }
27
+ if (!quickFilterValues) {
28
+ return null;
29
+ }
30
+ return quickFilter.resolver(quickFilterValues, authSession);
31
+ }, [authSession, quickFilter, quickFilterValues]);
32
+ const mergedFilter = (0, react_1.useMemo)(() => {
33
+ const filters = [];
34
+ if (filter) {
35
+ filters.push(filter);
36
+ }
37
+ if (quickFilterResults) {
38
+ filters.push(quickFilterResults);
39
+ }
40
+ if (filters.length === 0) {
41
+ return null;
42
+ }
43
+ if (filters.length === 1) {
44
+ return filters[0];
45
+ }
46
+ return {
47
+ type: 'and',
48
+ filters,
49
+ };
50
+ }, [filter, quickFilterResults]);
19
51
  const { fetchNextPage, data, hasNextPage, isFetching, isFetchingNextPage, queryKey, } = (0, useRetriveRecords_1.useRetriveRecords)({
20
52
  columns,
21
53
  expand,
22
- filter,
54
+ filter: mergedFilter,
23
55
  maxRecords,
24
56
  schema,
25
57
  search,
@@ -4,6 +4,7 @@ import { BoardColumnConfig, BoardConfig } from './types';
4
4
  export interface BoardContextState<S extends SchemaAttributes = SchemaAttributes> {
5
5
  config: BoardConfig<S>;
6
6
  searchText: string;
7
+ quickFilterValues: Record<string, unknown>;
7
8
  }
8
9
  export interface BoardColumnContextState<S extends SchemaAttributes = SchemaAttributes> {
9
10
  config: BoardColumnConfig;
@@ -0,0 +1 @@
1
+ export declare function useQuickFilter(): readonly [import("@headless-adminapp/core/experience/view/QuickFilter").QuickFilter<import("@headless-adminapp/core/schema").SchemaAttributes> | undefined, Record<string, unknown>, (key: string, value: unknown) => void];
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useQuickFilter = useQuickFilter;
4
+ const react_1 = require("react");
5
+ const context_1 = require("../../mutable/context");
6
+ const context_2 = require("../context");
7
+ function useQuickFilter() {
8
+ const quickFilter = (0, context_1.useContextSelector)(context_2.BoardContext, (state) => state.config.quickFilter);
9
+ const values = (0, context_1.useContextSelector)(context_2.BoardContext, (state) => state.quickFilterValues);
10
+ const _setValue = (0, context_1.useContextSetValue)(context_2.BoardContext);
11
+ const setValue = (0, react_1.useCallback)((key, value) => {
12
+ _setValue((state) => ({
13
+ quickFilterValues: {
14
+ ...state.quickFilterValues,
15
+ [key]: value,
16
+ },
17
+ }));
18
+ }, [_setValue]);
19
+ return [quickFilter, values, setValue];
20
+ }
package/board/types.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { CommandContextBase } from '@headless-adminapp/core/experience/command';
2
2
  import { SortingState, View } from '@headless-adminapp/core/experience/view';
3
+ import { QuickFilter } from '@headless-adminapp/core/experience/view/QuickFilter';
3
4
  import { Schema, SchemaAttributes } from '@headless-adminapp/core/schema';
4
5
  import { Filter } from '@headless-adminapp/core/transport';
5
6
  import { FC } from 'react';
@@ -48,4 +49,5 @@ export interface BoardConfig<S extends SchemaAttributes = SchemaAttributes> {
48
49
  emptyMessage?: string;
49
50
  minColumnWidth?: number;
50
51
  maxColumnWidth?: number;
52
+ quickFilter?: QuickFilter;
51
53
  }
@@ -34,6 +34,11 @@ var DefaultCommandBuilder;
34
34
  text: strings.new,
35
35
  localizedTexts: extractLocalizedStrings(localizedSrings, (x) => x.new),
36
36
  }),
37
+ ViewCommandBuilder_1.ViewCommandBuilder.createNewRecordForVirtualCommand({
38
+ Icon: icons.New,
39
+ text: strings.new,
40
+ localizedTexts: extractLocalizedStrings(localizedSrings, (x) => x.new),
41
+ }),
37
42
  ViewCommandBuilder_1.ViewCommandBuilder.createEditRecordCommand({
38
43
  Icon: icons.Edit,
39
44
  text: strings.edit,
@@ -15,6 +15,11 @@ export declare namespace ViewCommandBuilder {
15
15
  text: string;
16
16
  localizedTexts?: Record<string, string>;
17
17
  }): EntityMainGridCommandItemExperience;
18
+ function createNewRecordForVirtualCommand({ Icon, text, localizedTexts, }: {
19
+ Icon: Icon;
20
+ text: string;
21
+ localizedTexts?: Record<string, string>;
22
+ }): EntityMainGridCommandItemExperience;
18
23
  function createEditRecordCommand({ Icon, text, localizedTexts, }: {
19
24
  Icon: Icon;
20
25
  text: string;
@@ -86,6 +86,54 @@ var ViewCommandBuilder;
86
86
  };
87
87
  }
88
88
  ViewCommandBuilder.createNewRecordCommand = createNewRecordCommand;
89
+ function createNewRecordForVirtualCommand({ Icon, text, localizedTexts, }) {
90
+ return {
91
+ type: 'button',
92
+ Icon,
93
+ text,
94
+ localizedText: localizedTexts,
95
+ onClick: async (context) => {
96
+ if (!context.primaryControl.schema.baseSchemaLogicalNames?.length) {
97
+ return;
98
+ }
99
+ const data = await context.utility.openPromptDialog({
100
+ title: 'Select type',
101
+ attributes: {
102
+ type: {
103
+ type: 'choice',
104
+ label: 'Select type',
105
+ string: true,
106
+ required: true,
107
+ options: context.primaryControl.schema.baseSchemaLogicalNames?.map((x) => {
108
+ const schema = context.stores.schemaStore.getSchema(x);
109
+ return {
110
+ value: x,
111
+ label: schema.label,
112
+ };
113
+ }),
114
+ },
115
+ },
116
+ defaultValues: {},
117
+ });
118
+ if (!data) {
119
+ return;
120
+ }
121
+ context.navigation.openForm({
122
+ logicalName: data.type,
123
+ });
124
+ },
125
+ hidden: (context) => {
126
+ if (EnabledRules.IsPhysicalSchema(context)) {
127
+ return true;
128
+ }
129
+ if (!context.primaryControl.schema.baseSchemaLogicalNames?.length) {
130
+ return true;
131
+ }
132
+ return false;
133
+ },
134
+ };
135
+ }
136
+ ViewCommandBuilder.createNewRecordForVirtualCommand = createNewRecordForVirtualCommand;
89
137
  function createEditRecordCommand({ Icon, text, localizedTexts, }) {
90
138
  return {
91
139
  type: 'button',
@@ -94,11 +142,35 @@ var ViewCommandBuilder;
94
142
  localizedText: localizedTexts,
95
143
  isContextMenu: true,
96
144
  onClick: (context) => {
97
- context.primaryControl.openRecord(context.primaryControl.selectedIds[0], context.primaryControl.schema.logicalName);
145
+ if (EnabledRules.IsPhysicalSchema(context)) {
146
+ context.primaryControl.openRecord(context.primaryControl.selectedIds[0], context.primaryControl.schema.logicalName);
147
+ }
148
+ else {
149
+ if (!context.primaryControl.schema.virtualLogicalNameAttribute) {
150
+ return;
151
+ }
152
+ const logicalName = context.primaryControl.selectedRecords[0][context.primaryControl.schema.virtualLogicalNameAttribute];
153
+ if (!logicalName) {
154
+ return;
155
+ }
156
+ context.primaryControl.openRecord(context.primaryControl.selectedIds[0], logicalName);
157
+ }
98
158
  },
99
159
  hidden: [
100
160
  (context) => !EnabledRules.HasSingleRecordSelected(context),
101
- (context) => !EnabledRules.IsPhysicalSchema(context),
161
+ (context) => {
162
+ if (EnabledRules.IsPhysicalSchema(context)) {
163
+ return false;
164
+ }
165
+ if (!context.primaryControl.schema.virtualLogicalNameAttribute) {
166
+ return true;
167
+ }
168
+ const logicalName = context.primaryControl.selectedRecords[0][context.primaryControl.schema.virtualLogicalNameAttribute];
169
+ if (!logicalName) {
170
+ return true;
171
+ }
172
+ return false;
173
+ },
102
174
  ],
103
175
  };
104
176
  }
@@ -115,7 +187,16 @@ var ViewCommandBuilder;
115
187
  },
116
188
  hidden: [
117
189
  (context) => !EnabledRules.HasSingleRecordSelected(context),
118
- (context) => EnabledRules.IsPhysicalSchema(context),
190
+ (context) => {
191
+ if (EnabledRules.IsPhysicalSchema(context)) {
192
+ return true;
193
+ }
194
+ if (context.primaryControl.schema.virtualLogicalNameAttribute ||
195
+ context.primaryControl.schema.baseSchemaLogicalName) {
196
+ return true;
197
+ }
198
+ return false;
199
+ },
119
200
  ],
120
201
  };
121
202
  }
@@ -1,7 +1,7 @@
1
1
  import type { ViewColumn as $ViewColumn, ViewExperience as $ViewExperience } from '@headless-adminapp/core/experience/view';
2
2
  import type { SchemaAttributes } from '@headless-adminapp/core/schema';
3
3
  export declare namespace DefineViewExperience {
4
- export type Experience<S extends SchemaAttributes = SchemaAttributes> = Pick<$ViewExperience<S>, 'filter' | 'defaultSorting' | 'card'> & {
4
+ export type Experience<S extends SchemaAttributes = SchemaAttributes> = Pick<$ViewExperience<S>, 'filter' | 'defaultSorting' | 'card' | 'quickFilter'> & {
5
5
  grid: GridView<S>;
6
6
  };
7
7
  type GridView<S extends SchemaAttributes = SchemaAttributes> = {
@@ -39,7 +39,7 @@ export declare class SchemaExperienceBuilder<S extends SchemaAttributes = Schema
39
39
  private readonly defaults?;
40
40
  private readonly options?;
41
41
  constructor(schema: Schema<S>, defaults?: SchemaExperienceBuilderDefaults | undefined, options?: SchemaExperienceBuilderOptions | undefined);
42
- defineViewExperience(viewExperience: Pick<DefineViewExperience.Experience<S>, 'filter' | 'defaultSorting'> & {
42
+ defineViewExperience(viewExperience: Pick<DefineViewExperience.Experience<S>, 'filter' | 'defaultSorting' | 'quickFilter'> & {
43
43
  grid?: DefineViewExperience.Experience<S>['grid'];
44
44
  card?: DefineViewExperience.Experience<S>['card'];
45
45
  }): ViewExperience<S>;
package/builders/utils.js CHANGED
@@ -162,7 +162,8 @@ async function retriveRecords({ gridColumns, dataService, schema, search, view,
162
162
  search,
163
163
  columns: columns,
164
164
  expand,
165
- filter: (0, utils_1.mergeConditions)(schema, view.experience.filter, extraFilter, columnFilters, schemaStore),
165
+ filter: (0, utils_1.mergeConditions)(schema, view.experience.filter, extraFilter, null, // quickFilterResults
166
+ columnFilters, schemaStore),
166
167
  skip,
167
168
  limit,
168
169
  sort: sorting,
@@ -0,0 +1,8 @@
1
+ import { SchemaAttributes } from '@headless-adminapp/core/schema';
2
+ import { PropsWithChildren } from 'react';
3
+ import { CalendarConfig } from './types';
4
+ interface CalendarProviderProps<SA1 extends SchemaAttributes = SchemaAttributes, SA2 extends SchemaAttributes = SchemaAttributes, SA3 extends SchemaAttributes = SchemaAttributes> {
5
+ config: CalendarConfig<SA1, SA2, SA3>;
6
+ }
7
+ export declare function CalendarProvider<SA1 extends SchemaAttributes = SchemaAttributes, SA2 extends SchemaAttributes = SchemaAttributes, SA3 extends SchemaAttributes = SchemaAttributes>(props: Readonly<PropsWithChildren<CalendarProviderProps<SA1, SA2, SA3>>>): import("react/jsx-runtime").JSX.Element;
8
+ export {};
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CalendarProvider = CalendarProvider;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_1 = require("react");
6
+ const mutable_1 = require("../mutable");
7
+ const context_1 = require("./context");
8
+ function CalendarProvider(props) {
9
+ const contextValue = (0, mutable_1.useCreateContextStore)({
10
+ config: props.config,
11
+ });
12
+ (0, react_1.useEffect)(() => {
13
+ contextValue.setValue({
14
+ config: props.config,
15
+ });
16
+ }, [contextValue, props.config]);
17
+ return ((0, jsx_runtime_1.jsx)(context_1.CalendarContext.Provider, { value: contextValue, children: props.children }));
18
+ }
@@ -0,0 +1 @@
1
+ export declare function useDeleteEvent(): (id: string) => Promise<void>;
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useDeleteEvent = useDeleteEvent;
4
+ const dialog_1 = require("@headless-adminapp/app/dialog");
5
+ const progress_indicator_1 = require("@headless-adminapp/app/progress-indicator");
6
+ const toast_notification_1 = require("@headless-adminapp/app/toast-notification");
7
+ const react_query_1 = require("@tanstack/react-query");
8
+ const react_1 = require("react");
9
+ const useConfig_1 = require("./useConfig");
10
+ function useDeleteEvent() {
11
+ const openConfirmDialog = (0, dialog_1.useOpenConfirmDialog)();
12
+ const openToastNotification = (0, toast_notification_1.useOpenToastNotification)();
13
+ const { hideProgressIndicator, showProgressIndicator } = (0, progress_indicator_1.useProgressIndicator)();
14
+ const config = (0, useConfig_1.useConfig)();
15
+ const queryClient = (0, react_query_1.useQueryClient)();
16
+ const deleteEvent = (0, react_1.useCallback)(async (id) => {
17
+ try {
18
+ if (!config.deleteEvent) {
19
+ throw new Error('Delete event function is not defined.');
20
+ }
21
+ const confirmResult = await openConfirmDialog({
22
+ title: 'Delete Event',
23
+ text: 'Are you sure you want to delete this event?',
24
+ });
25
+ if (!confirmResult?.confirmed) {
26
+ return;
27
+ }
28
+ showProgressIndicator('Deleting event...');
29
+ await config.deleteEvent(id);
30
+ await queryClient.invalidateQueries({
31
+ queryKey: ['calendar-events'],
32
+ });
33
+ close();
34
+ }
35
+ catch (error) {
36
+ openToastNotification({
37
+ title: 'Error',
38
+ text: error.message,
39
+ type: 'error',
40
+ });
41
+ }
42
+ finally {
43
+ hideProgressIndicator();
44
+ }
45
+ }, [
46
+ config,
47
+ hideProgressIndicator,
48
+ openConfirmDialog,
49
+ openToastNotification,
50
+ queryClient,
51
+ showProgressIndicator,
52
+ ]);
53
+ return deleteEvent;
54
+ }
@@ -0,0 +1,2 @@
1
+ import { SchemaAttributes } from '@headless-adminapp/core/schema';
2
+ export declare function useOpenDetailDialog<SA1 extends SchemaAttributes = SchemaAttributes, SA2 extends SchemaAttributes = SchemaAttributes>(DialogComponent: React.ComponentType<any>): (values: unknown) => void;
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useOpenDetailDialog = useOpenDetailDialog;
4
+ const react_query_1 = require("@tanstack/react-query");
5
+ const useOpenDialog_1 = require("../../dialog/hooks/useOpenDialog");
6
+ const useOpenToastNotification_1 = require("../../toast-notification/hooks/useOpenToastNotification");
7
+ const useConfig_1 = require("./useConfig");
8
+ function useOpenDetailDialog(DialogComponent) {
9
+ const openDialog = (0, useOpenDialog_1.useOpenDialog)();
10
+ const openToastNotification = (0, useOpenToastNotification_1.useOpenToastNotification)();
11
+ const config = (0, useConfig_1.useConfig)();
12
+ const queryClient = (0, react_query_1.useQueryClient)();
13
+ function openEventDetailModel(values) {
14
+ const { close } = openDialog({
15
+ type: 'custom',
16
+ Component: DialogComponent,
17
+ props: {
18
+ onDismiss: () => {
19
+ close();
20
+ },
21
+ config,
22
+ values,
23
+ onSubmit: async (data) => {
24
+ if (!config.saveEvent) {
25
+ return;
26
+ }
27
+ try {
28
+ const { id, end, start, title, allDay, description, ...rest } = data.values;
29
+ await config.saveEvent({
30
+ event: {
31
+ id,
32
+ title,
33
+ start: start ? new Date(start) : null,
34
+ end: end ? new Date(end) : null,
35
+ allDay: allDay ?? false,
36
+ description,
37
+ ...rest,
38
+ },
39
+ modifiedValues: data.modifiedValues,
40
+ });
41
+ await queryClient.invalidateQueries({
42
+ queryKey: ['calendar-events'],
43
+ });
44
+ close();
45
+ }
46
+ catch (error) {
47
+ openToastNotification({
48
+ title: 'Error',
49
+ text: error.message,
50
+ type: 'error',
51
+ });
52
+ }
53
+ },
54
+ onCancel: () => {
55
+ close();
56
+ },
57
+ },
58
+ });
59
+ }
60
+ return openEventDetailModel;
61
+ }
@@ -1,5 +1,7 @@
1
1
  import { AuthSession } from '@headless-adminapp/core/experience/auth';
2
+ import { OpenFormOptions } from '@headless-adminapp/core/experience/command';
2
3
  import { InferredSchemaType, SchemaAttributes } from '@headless-adminapp/core/schema';
4
+ import { InternalRouteResolver, RouterInstance } from '../route/context';
3
5
  export interface CalendarEvent {
4
6
  id: string;
5
7
  title: string;
@@ -28,18 +30,35 @@ export type CalendarEventSaveFn<SA1 extends SchemaAttributes = SchemaAttributes,
28
30
  export interface CalendarConfig<SA1 extends SchemaAttributes = SchemaAttributes, SA2 extends SchemaAttributes = SchemaAttributes, SA3 extends SchemaAttributes = SchemaAttributes> {
29
31
  eventsResolver: CalendarEventsResolverFn<SA3>;
30
32
  eventResolver?: CalendarEventResolverFn;
31
- saveEvent: CalendarEventSaveFn<SA1, SA2>;
33
+ saveEvent?: CalendarEventSaveFn<SA1, SA2>;
32
34
  beforeDescriptionAttributes?: SA1;
33
35
  afterDescriptionAttributes?: SA2;
34
36
  filterAttributes?: SA3;
35
37
  defaultFilter?: InferredSchemaType<SA3>;
36
- openRecord?: (id: string) => void;
37
- deleteEvent: (id: string) => Promise<void>;
38
+ deleteEvent?: (id: string) => Promise<void>;
38
39
  title: string;
39
40
  description: string;
40
41
  eventLabel: string;
41
- disableCreate?: boolean;
42
- disableEdit?: boolean;
43
- disableDelete?: boolean;
44
42
  disableAllDay?: boolean;
43
+ createOptions?: {
44
+ mode: 'dialog';
45
+ } | {
46
+ mode: 'custom';
47
+ allowQuickCreate?: boolean;
48
+ onClick: (defaultValues: Record<string, unknown>, options: {
49
+ router: RouterInstance;
50
+ routeResolver: InternalRouteResolver;
51
+ openForm: (options: OpenFormOptions) => void;
52
+ }) => void;
53
+ };
54
+ editOptions?: {
55
+ mode: 'dialog';
56
+ } | {
57
+ mode: 'custom';
58
+ onClick: (event: CalendarEvent, options: {
59
+ router: RouterInstance;
60
+ routeResolver: InternalRouteResolver;
61
+ openForm: (options: OpenFormOptions) => void;
62
+ }) => void;
63
+ };
45
64
  }
@@ -15,20 +15,21 @@ const ScrollView = ({ children, className, rtl, autoHide, onScroll, shadowEffect
15
15
  const [isTop, setIsTop] = (0, react_1.useState)(true);
16
16
  const [isBottom, setIsBottom] = (0, react_1.useState)(false);
17
17
  const handleScroll = (event) => {
18
- const div = event.target;
19
- const remainingSpace = getReaminingSpace(div);
20
- const _isTop = div.scrollTop === 0;
21
- const _isBottom = remainingSpace <= 0;
18
+ if (onScroll) {
19
+ onScroll(event);
20
+ }
21
+ };
22
+ const handleOnUpdate = (values) => {
23
+ const remainingSpace = values.scrollHeight - values.scrollTop - values.clientHeight;
24
+ const _isTop = values.scrollTop === 0;
25
+ const _isBottom = remainingSpace <= 10;
22
26
  if (isTop !== _isTop) {
23
27
  setIsTop(_isTop);
24
28
  }
25
29
  if (isBottom !== _isBottom) {
26
30
  setIsBottom(_isBottom);
27
31
  }
28
- if (onScroll) {
29
- onScroll(event);
30
- }
31
32
  };
32
- return ((0, jsx_runtime_1.jsx)(react_custom_scrollbars_2_1.Scrollbars, { autoHide: autoHide, className: (0, clsx_1.default)(className, 'hdl-scrollbar', rtl && 'rtl', shadowEffect && !isTop && 'hdl-scrollbar-shadow-top', shadowEffect && !isBottom && 'hdl-scrollbar-shadow-bottom'), onScroll: handleScroll, children: children }));
33
+ return ((0, jsx_runtime_1.jsx)(react_custom_scrollbars_2_1.Scrollbars, { autoHide: autoHide, className: (0, clsx_1.default)(className, 'hdl-scrollbar', rtl && 'rtl', shadowEffect && !isTop && 'hdl-scrollbar-shadow-top', shadowEffect && !isBottom && 'hdl-scrollbar-shadow-bottom'), onScroll: handleScroll, onUpdate: handleOnUpdate, children: children }));
33
34
  };
34
35
  exports.ScrollView = ScrollView;
@@ -1,3 +1,12 @@
1
- import { SchemaAttributes } from '@headless-adminapp/core/schema';
1
+ import { SectionEditableGridControl } from '@headless-adminapp/core/experience/form';
2
+ import { InferredSchemaType, SchemaAttributes } from '@headless-adminapp/core/schema';
3
+ import { ISchemaStore } from '@headless-adminapp/core/store';
4
+ import { IDataService } from '@headless-adminapp/core/transport';
2
5
  import { RetriveRecordFnOptions } from './types';
3
6
  export declare function getRecord<SA extends SchemaAttributes = SchemaAttributes>({ recordId, dataService, form, schema, columns, schemaStore, }: RetriveRecordFnOptions<SA>): Promise<import("@headless-adminapp/core/transport").Data<SA> | null>;
7
+ export declare function getEditableSubgridRecords({ dataService, schemaStore, control, recordId, }: {
8
+ dataService: IDataService;
9
+ schemaStore: ISchemaStore;
10
+ control: SectionEditableGridControl<SchemaAttributes>;
11
+ recordId: string;
12
+ }): Promise<import("@headless-adminapp/core/transport").Data<InferredSchemaType<SchemaAttributes>>[]>;
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getRecord = getRecord;
4
+ exports.getEditableSubgridRecords = getEditableSubgridRecords;
4
5
  const transport_1 = require("@headless-adminapp/core/transport");
5
6
  const utils_1 = require("./utils");
6
7
  async function getRecord({ recordId, dataService, form, schema, columns, schemaStore, }) {
@@ -20,37 +21,46 @@ async function getRecord({ recordId, dataService, form, schema, columns, schemaS
20
21
  const controls = (0, utils_1.getControls)(form);
21
22
  const editableGridControls = controls.filter((control) => control.type === 'editablegrid');
22
23
  for (const control of editableGridControls) {
23
- if (control.type !== 'editablegrid') {
24
+ if (!control.alias) {
24
25
  continue;
25
26
  }
26
- const controlSchema = schemaStore.getSchema(control.logicalName);
27
- const records = await dataService.retriveRecords({
28
- logicalName: controlSchema.logicalName,
29
- filter: {
30
- type: 'and',
31
- conditions: [
32
- {
33
- field: control.referenceAttribute,
34
- operator: 'eq',
35
- value: recordId,
36
- },
37
- ],
38
- },
39
- sort: [
40
- {
41
- field: controlSchema.createdAtAttribute ?? controlSchema.idAttribute,
42
- order: 'asc',
43
- },
44
- ],
45
- limit: 5000,
46
- search: '',
47
- columns: [
48
- controlSchema.idAttribute,
49
- control.referenceAttribute,
50
- ...control.attributes,
51
- ],
27
+ const records = await getEditableSubgridRecords({
28
+ dataService,
29
+ control,
30
+ schemaStore,
31
+ recordId,
52
32
  });
53
- record[control.attributeName] = records.records;
33
+ record[control.alias] = records;
54
34
  }
55
35
  return record;
56
36
  }
37
+ async function getEditableSubgridRecords({ dataService, schemaStore, control, recordId, }) {
38
+ const controlSchema = schemaStore.getSchema(control.logicalName);
39
+ const result = await dataService.retriveRecords({
40
+ logicalName: controlSchema.logicalName,
41
+ filter: {
42
+ type: 'and',
43
+ conditions: [
44
+ {
45
+ field: control.associatedAttribute,
46
+ operator: 'eq',
47
+ value: recordId,
48
+ },
49
+ ],
50
+ },
51
+ sort: control.sort ?? [
52
+ {
53
+ field: controlSchema.createdAtAttribute ?? controlSchema.idAttribute,
54
+ order: 'asc',
55
+ },
56
+ ],
57
+ limit: 5000,
58
+ search: '',
59
+ columns: [
60
+ controlSchema.idAttribute,
61
+ control.associatedAttribute,
62
+ ...control.controls.map((x) => typeof x === 'string' ? x : x.attributeName),
63
+ ],
64
+ });
65
+ return result.records;
66
+ }
@@ -7,7 +7,7 @@ export declare function getControls<SA extends SchemaAttributes>(form: Form<SA>)
7
7
  export declare function getColumns<SA extends SchemaAttributes>(form: Form<SA>, schema: Schema<SA>): (keyof SA)[];
8
8
  export declare function transformFormInternal<SA extends SchemaAttributes>(form: Form<SA>): DataFormContextState<SA>['formInternal'];
9
9
  export declare function getIsFieldDisabled<S extends SchemaAttributes = SchemaAttributes>({ attribute, isFormReadonly, disabledFields, control, }: {
10
- attribute: AttributeBase;
10
+ attribute: AttributeBase | null;
11
11
  isFormReadonly: boolean | undefined;
12
12
  disabledFields: Record<string, boolean>;
13
13
  control: Section<S>['controls'][0];
@@ -76,7 +76,7 @@ function getIsFieldDisabled({ attribute, isFormReadonly, disabledFields, control
76
76
  else if ('disabled' in control && control.disabled !== undefined) {
77
77
  disabled = control.disabled;
78
78
  }
79
- else if (attribute.readonly !== undefined) {
79
+ else if (attribute && attribute.readonly !== undefined) {
80
80
  disabled = attribute.readonly;
81
81
  }
82
82
  }
@@ -1,5 +1,5 @@
1
1
  import type { Attribute } from '@headless-adminapp/core/attributes';
2
- import { Form } from '@headless-adminapp/core/experience/form';
2
+ import { Form, SectionEditableGridControl } from '@headless-adminapp/core/experience/form';
3
3
  import { InferredSchemaType, Schema, SchemaAttributes } from '@headless-adminapp/core/schema';
4
4
  import { ISchemaStore } from '@headless-adminapp/core/store';
5
5
  import { Nullable } from '@headless-adminapp/core/types';
@@ -28,6 +28,19 @@ interface FormValidatorOptions<A extends SchemaAttributes = SchemaAttributes> {
28
28
  }
29
29
  type FormValidator = (<A extends SchemaAttributes = SchemaAttributes>(options: FormValidatorOptions<A>) => (values: Record<string, any>, context: any, options: any) => Promise<ResolverResult<{}>>) & MemoizedFunction;
30
30
  export declare const formValidator: FormValidator;
31
+ interface EditableSubgridFormValidatorOptions<A extends SchemaAttributes = SchemaAttributes> {
32
+ schema: Schema<A>;
33
+ control: SectionEditableGridControl<A>;
34
+ language: string;
35
+ formReadOnly?: boolean;
36
+ readonlyAttributes?: string[];
37
+ strings: FormValidationStringSet;
38
+ schemaStore: ISchemaStore;
39
+ region: string;
40
+ alias: string;
41
+ }
42
+ type EditableSubgridFormValidator = (<A extends SchemaAttributes = SchemaAttributes>(options: EditableSubgridFormValidatorOptions<A>) => (values: Record<string, any>, context: any, options: any) => Promise<ResolverResult<{}>>) & MemoizedFunction;
43
+ export declare const editableSubgridFormValidator: EditableSubgridFormValidator;
31
44
  export declare const generateValidationSchema: (<A extends SchemaAttributes = SchemaAttributes>({ columns, editableGrids, language, schema, strings, readonlyAttributes, region, }: {
32
45
  schema: Schema<A>;
33
46
  columns: string[];
@@ -23,7 +23,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
23
23
  return result;
24
24
  };
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
- exports.generateAttributeValidationSchema = exports.generateValidationSchema = exports.formValidator = exports.saveRecord = void 0;
26
+ exports.generateAttributeValidationSchema = exports.generateValidationSchema = exports.editableSubgridFormValidator = exports.formValidator = exports.saveRecord = void 0;
27
27
  exports.getInitialValues = getInitialValues;
28
28
  const phone_1 = require("@headless-adminapp/app/utils/phone");
29
29
  const yup_1 = require("@hookform/resolvers/yup");
@@ -35,10 +35,10 @@ var saveRecord_1 = require("./saveRecord");
35
35
  Object.defineProperty(exports, "saveRecord", { enumerable: true, get: function () { return saveRecord_1.saveRecord; } });
36
36
  function getInitialValues({ cloneRecord, form, record, recordId, schema, defaultParameters, }) {
37
37
  const formColumns = (0, utils_1.getColumns)(form, schema);
38
- const editableGridControls = (0, utils_1.getControls)(form).filter((control) => control.type === 'editablegrid');
38
+ const editableGridControls = (0, utils_1.getControls)(form).filter((control) => control.type === 'editablegrid' && control.alias !== false);
39
39
  const allColumns = [
40
40
  ...formColumns,
41
- ...editableGridControls.map((x) => x.attributeName),
41
+ ...editableGridControls.map((x) => x.alias),
42
42
  ];
43
43
  if (!recordId && !record && form.experience.cloneAttributes && cloneRecord) {
44
44
  const cloneAttributesObj = form.experience.cloneAttributes.reduce((acc, item) => {
@@ -116,7 +116,7 @@ exports.formValidator = (0, lodash_1.memoize)(function formValidator({ form, sch
116
116
  }
117
117
  return true;
118
118
  });
119
- const editableGridControls = activeControls.filter((control) => control.type === 'editablegrid');
119
+ const editableGridControls = activeControls.filter((control) => control.type === 'editablegrid' && control.alias !== false);
120
120
  const columns = Array.from(new Set([
121
121
  schema.primaryAttribute,
122
122
  ...activeControls
@@ -125,14 +125,14 @@ exports.formValidator = (0, lodash_1.memoize)(function formValidator({ form, sch
125
125
  ]));
126
126
  validator = (0, exports.generateValidationSchema)({
127
127
  editableGrids: editableGridControls.map((control) => {
128
- if (control.type !== 'editablegrid') {
128
+ if (control.type !== 'editablegrid' || control.alias === false) {
129
129
  throw new Error('Invalid control type');
130
130
  }
131
131
  const schema = schemaStore.getSchema(control.logicalName);
132
132
  return {
133
- columns: control.attributes,
133
+ columns: control.controls.map((x) => typeof x === 'string' ? x : x.attributeName),
134
134
  schema: schema,
135
- attributeName: control.attributeName,
135
+ attributeName: control.alias,
136
136
  required: control.required,
137
137
  };
138
138
  }),
@@ -156,6 +156,44 @@ exports.formValidator = (0, lodash_1.memoize)(function formValidator({ form, sch
156
156
  readonlyAttributes,
157
157
  formReadOnly,
158
158
  }));
159
+ exports.editableSubgridFormValidator = (0, lodash_1.memoize)(function formValidator({ schema, readonlyAttributes, formReadOnly, schemaStore, language, strings, region, control, alias, }) {
160
+ return async (values, context, options) => {
161
+ let validator = yup.object().shape({});
162
+ if (!formReadOnly) {
163
+ const controlSchema = schemaStore.getSchema(control.logicalName);
164
+ const columns = [];
165
+ validator = (0, exports.generateValidationSchema)({
166
+ editableGrids: [
167
+ {
168
+ columns: control.controls.map((x) => typeof x === 'string'
169
+ ? x
170
+ : x.attributeName),
171
+ schema: controlSchema,
172
+ attributeName: alias,
173
+ required: control.required,
174
+ },
175
+ ],
176
+ schema,
177
+ columns,
178
+ language,
179
+ strings,
180
+ readonlyAttributes,
181
+ region,
182
+ });
183
+ }
184
+ const resolver = (0, yup_1.yupResolver)(validator);
185
+ const result = await resolver(values, context, options);
186
+ return result;
187
+ };
188
+ }, ({ language, schema, strings, readonlyAttributes, formReadOnly, alias, control, }) => JSON.stringify({
189
+ schema,
190
+ language,
191
+ strings,
192
+ readonlyAttributes,
193
+ formReadOnly,
194
+ alias,
195
+ control,
196
+ }));
159
197
  exports.generateValidationSchema = (0, lodash_1.memoize)(function generateValidationSchema({ columns, editableGrids, language, schema, strings, readonlyAttributes, region, }) {
160
198
  return yup.object().shape({
161
199
  ...columns.reduce((acc, column) => {
@@ -1,5 +1,5 @@
1
1
  import { Id } from '@headless-adminapp/core';
2
- import { Form } from '@headless-adminapp/core/experience/form';
2
+ import { Form, SectionEditableGridControl } from '@headless-adminapp/core/experience/form';
3
3
  import { InferredSchemaType, Schema, SchemaAttributes } from '@headless-adminapp/core/schema';
4
4
  import { ISchemaStore } from '@headless-adminapp/core/store';
5
5
  import { IDataService } from '@headless-adminapp/core/transport';
@@ -25,3 +25,38 @@ export interface SaveRecordFnOptions<S extends SchemaAttributes = SchemaAttribut
25
25
  }
26
26
  export type SaveRecordFn = (options: SaveRecordFnOptions) => Promise<SaveRecordResult>;
27
27
  export declare function saveRecord({ values, form, schema, dataService, initialValues, record, schemaStore, }: SaveRecordFnOptions): Promise<SaveRecordResult>;
28
+ interface SaveEditableGridControlOptions {
29
+ recordId: string;
30
+ control: SectionEditableGridControl;
31
+ schemaStore: ISchemaStore;
32
+ values: any;
33
+ initialValues: any;
34
+ dataService: IDataService;
35
+ alias: string;
36
+ }
37
+ export type SaveEditableGridResult = {
38
+ success: true;
39
+ updated: number;
40
+ created: number;
41
+ } | {
42
+ success: false;
43
+ title?: string;
44
+ message: string;
45
+ isError: boolean;
46
+ };
47
+ export declare function saveEditableGridControl({ recordId, control, schemaStore, values, initialValues, dataService, alias, }: SaveEditableGridControlOptions): Promise<{
48
+ success: boolean;
49
+ title: string;
50
+ message: string;
51
+ isError: boolean;
52
+ updated?: undefined;
53
+ created?: undefined;
54
+ } | {
55
+ success: boolean;
56
+ updated: number;
57
+ created: number;
58
+ title?: undefined;
59
+ message?: undefined;
60
+ isError?: undefined;
61
+ }>;
62
+ export {};
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getModifiedValues = getModifiedValues;
4
4
  exports.saveRecord = saveRecord;
5
+ exports.saveEditableGridControl = saveEditableGridControl;
5
6
  const utils_1 = require("../../dataform/DataFormProvider/utils");
6
7
  function getModifiedValues(initialValues, values, exclude) {
7
8
  const keys = Object.keys(values);
@@ -30,11 +31,11 @@ async function executeOperation(operation, dataService) {
30
31
  await dataService.deleteRecord(operation.logicalName, operation.id);
31
32
  }
32
33
  }
33
- function generateSubgridUpdateOperation({ recordId, control, schemaStore, values, initialValues, }) {
34
+ function generateSubgridUpdateOperation({ recordId, control, schemaStore, values, initialValues, alias, }) {
34
35
  const operations = [];
35
36
  const gridSchema = schemaStore.getSchema(control.logicalName);
36
- const gridRows = values[control.attributeName];
37
- const initialGridRows = initialValues[control.attributeName];
37
+ const gridRows = values[alias];
38
+ const initialGridRows = initialValues[alias];
38
39
  const newRows = gridRows.filter((x) => !x[gridSchema.idAttribute]);
39
40
  const updatedRows = gridRows.filter((x) => x[gridSchema.idAttribute]);
40
41
  const deletedIds = initialGridRows
@@ -46,9 +47,10 @@ function generateSubgridUpdateOperation({ recordId, control, schemaStore, values
46
47
  logicalName: control.logicalName,
47
48
  data: {
48
49
  ...row,
49
- [control.referenceAttribute]: {
50
+ [control.associatedAttribute]: {
50
51
  id: recordId,
51
52
  },
53
+ [gridSchema.idAttribute]: undefined,
52
54
  },
53
55
  });
54
56
  }
@@ -79,15 +81,15 @@ function generateSubgridUpdateOperation({ recordId, control, schemaStore, values
79
81
  }
80
82
  async function createRecord({ values, form, schema, dataService, }) {
81
83
  const controls = (0, utils_1.getControls)(form);
82
- const editableGridControls = controls.filter((control) => control.type === 'editablegrid');
84
+ const editableGridControls = controls.filter((control) => control.type === 'editablegrid' && control.alias);
83
85
  const result = await dataService.createRecord(schema.logicalName, values);
84
86
  const recordId = result.id;
85
87
  for (const control of editableGridControls) {
86
- const gridRows = values[control.attributeName];
88
+ const gridRows = values[control.alias];
87
89
  for (const row of gridRows) {
88
90
  await dataService.createRecord(control.logicalName, {
89
91
  ...row,
90
- [control.referenceAttribute]: {
92
+ [control.associatedAttribute]: {
91
93
  id: recordId,
92
94
  },
93
95
  });
@@ -97,8 +99,8 @@ async function createRecord({ values, form, schema, dataService, }) {
97
99
  }
98
100
  async function updateRecord({ recordId, values, form, schema, dataService, initialValues, schemaStore, }) {
99
101
  const controls = (0, utils_1.getControls)(form);
100
- const editableGridControls = controls.filter((control) => control.type === 'editablegrid');
101
- const modifiedValues = getModifiedValues(initialValues, values, editableGridControls.map((x) => x.attributeName));
102
+ const editableGridControls = controls.filter((control) => control.type === 'editablegrid' && control.alias);
103
+ const modifiedValues = getModifiedValues(initialValues, values, editableGridControls.map((x) => x.alias));
102
104
  const operations = [];
103
105
  if (Object.keys(modifiedValues).length) {
104
106
  operations.push({
@@ -115,6 +117,7 @@ async function updateRecord({ recordId, values, form, schema, dataService, initi
115
117
  schemaStore,
116
118
  initialValues,
117
119
  values,
120
+ alias: control.alias,
118
121
  }));
119
122
  }
120
123
  if (!operations.length) {
@@ -161,3 +164,29 @@ async function saveRecord({ values, form, schema, dataService, initialValues, re
161
164
  recordId,
162
165
  };
163
166
  }
167
+ async function saveEditableGridControl({ recordId, control, schemaStore, values, initialValues, dataService, alias, }) {
168
+ const operations = generateSubgridUpdateOperation({
169
+ recordId,
170
+ control,
171
+ schemaStore,
172
+ initialValues,
173
+ values,
174
+ alias,
175
+ });
176
+ if (!operations.length) {
177
+ return {
178
+ success: false,
179
+ title: 'No changes',
180
+ message: 'No changes made to the record',
181
+ isError: false,
182
+ };
183
+ }
184
+ for (const operation of operations) {
185
+ await executeOperation(operation, dataService);
186
+ }
187
+ return {
188
+ success: true,
189
+ updated: operations.filter((x) => x.type === 'update').length,
190
+ created: operations.filter((x) => x.type === 'create').length,
191
+ };
192
+ }
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.DataResolver = DataResolver;
4
4
  const react_1 = require("react");
5
+ const auth_1 = require("../../auth");
5
6
  const hooks_1 = require("../../hooks");
6
7
  const useDebouncedValue_1 = require("../../hooks/useDebouncedValue");
7
8
  const useMetadata_1 = require("../../metadata/hooks/useMetadata");
@@ -10,6 +11,7 @@ const useRetriveRecords_1 = require("../../transport/hooks/useRetriveRecords");
10
11
  const context_2 = require("../context");
11
12
  const hooks_2 = require("../hooks");
12
13
  const useGridDisabled_1 = require("../hooks/useGridDisabled");
14
+ const useQuickFilter_1 = require("../hooks/useQuickFilter");
13
15
  const utils_1 = require("./utils");
14
16
  function DataResolver() {
15
17
  const schema = (0, hooks_2.useDataGridSchema)();
@@ -22,6 +24,8 @@ function DataResolver() {
22
24
  const maxRecords = (0, hooks_2.useMaxRecords)();
23
25
  const [selectedIds] = (0, hooks_2.useGridSelection)();
24
26
  const disabled = (0, useGridDisabled_1.useGridDisabled)();
27
+ const [quickFilter, quickFilterValues] = (0, useQuickFilter_1.useQuickFilter)();
28
+ const authSession = (0, auth_1.useAuthSession)();
25
29
  const { schemaStore } = (0, useMetadata_1.useMetadata)();
26
30
  const selectedIdsRef = (0, react_1.useRef)(selectedIds);
27
31
  selectedIdsRef.current = selectedIds;
@@ -37,9 +41,25 @@ function DataResolver() {
37
41
  const expand = (0, react_1.useMemo)(() => isMobile
38
42
  ? (0, utils_1.collectCardExpandedKeys)({ cardView: view.experience.card })
39
43
  : (0, utils_1.collectExpandedKeys)(gridColumns), [gridColumns, isMobile, view.experience.card]);
44
+ const quickFilterResults = (0, react_1.useMemo)(() => {
45
+ if (!quickFilter) {
46
+ return null;
47
+ }
48
+ if (!quickFilterValues) {
49
+ return null;
50
+ }
51
+ return quickFilter.resolver(quickFilterValues, authSession);
52
+ }, [authSession, quickFilter, quickFilterValues]);
40
53
  const filter = (0, react_1.useMemo)(() => {
41
- return (0, utils_1.mergeConditions)(schema, view.experience.filter, extraFilter, columnFilters, schemaStore);
42
- }, [columnFilters, extraFilter, schema, schemaStore, view.experience.filter]);
54
+ return (0, utils_1.mergeConditions)(schema, view.experience.filter, extraFilter, quickFilterResults, columnFilters, schemaStore);
55
+ }, [
56
+ columnFilters,
57
+ extraFilter,
58
+ schema,
59
+ schemaStore,
60
+ view.experience.filter,
61
+ quickFilterResults,
62
+ ]);
43
63
  const { fetchNextPage, data, hasNextPage, isFetching, isFetchingNextPage, queryKey, } = (0, useRetriveRecords_1.useRetriveRecords)({
44
64
  columns,
45
65
  expand,
@@ -28,6 +28,7 @@ function DataGridProvider(props) {
28
28
  searchText: '',
29
29
  selectedIds: [],
30
30
  sorting: props.view.experience.defaultSorting ?? [],
31
+ quickFilterValues: props.view.experience.quickFilter?.defaultValues ?? {},
31
32
  view: props.view,
32
33
  commands: props.commands,
33
34
  columns: (0, transformViewColumns_1.transformViewColumns)(props.view.logicalName, props.view.experience.grid.columns, schemaStore, language),
@@ -52,6 +53,7 @@ function DataGridProvider(props) {
52
53
  searchText: '',
53
54
  selectedIds: [],
54
55
  sorting: props.view.experience.defaultSorting ?? [],
56
+ quickFilterValues: props.view.experience.quickFilter?.defaultValues ?? {},
55
57
  columns: (0, transformViewColumns_1.transformViewColumns)(props.view.logicalName, props.view.experience.grid.columns, schemaStore, language),
56
58
  maxRecords: props.maxRecords,
57
59
  });
@@ -4,7 +4,8 @@ import { ISchemaStore } from '@headless-adminapp/core/store';
4
4
  import { Filter } from '@headless-adminapp/core/transport';
5
5
  import { TransformedViewColumn } from '../context';
6
6
  export declare function transformColumnFilter<S extends SchemaAttributes = SchemaAttributes>(filter: Partial<Record<string, ColumnCondition>>, schema: Schema<S>, schemaStore: ISchemaStore): Record<string, ColumnCondition> | null;
7
- export declare function mergeConditions<S extends SchemaAttributes = SchemaAttributes>(schema: Schema<S>, filter: Filter | null | undefined, extraFilter: Filter | null | undefined, columnFilters: Partial<Record<string, ColumnCondition>> | undefined, schemaStore: ISchemaStore): Filter | null;
7
+ export declare function mergeConditions<S extends SchemaAttributes = SchemaAttributes>(schema: Schema<S>, filter: Filter | null | undefined, extraFilter: Filter | null | undefined, quickFilterResults: Filter | null | undefined, columnFilters: Partial<Record<string, ColumnCondition>> | undefined, schemaStore: ISchemaStore): Filter | null;
8
+ export declare function simplyfyFilter(filter: Filter): Filter | null;
8
9
  export declare function collectExpandedKeys(columns: TransformedViewColumn<SchemaAttributes>[]): Record<string, string[]>;
9
10
  export declare function collectGridColumns<S extends SchemaAttributes = SchemaAttributes>({ gridColumns, schema, }: {
10
11
  gridColumns: TransformedViewColumn<S>[];
@@ -5,6 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.transformColumnFilter = transformColumnFilter;
7
7
  exports.mergeConditions = mergeConditions;
8
+ exports.simplyfyFilter = simplyfyFilter;
8
9
  exports.collectExpandedKeys = collectExpandedKeys;
9
10
  exports.collectGridColumns = collectGridColumns;
10
11
  exports.collectCardColumns = collectCardColumns;
@@ -77,7 +78,7 @@ function transformColumnFilter(filter, schema, schemaStore) {
77
78
  }
78
79
  return transformedResult;
79
80
  }
80
- function mergeConditions(schema, filter, extraFilter, columnFilters, schemaStore) {
81
+ function mergeConditions(schema, filter, extraFilter, quickFilterResults, columnFilters, schemaStore) {
81
82
  const filters = [];
82
83
  if (filter) {
83
84
  filters.push(filter);
@@ -85,6 +86,9 @@ function mergeConditions(schema, filter, extraFilter, columnFilters, schemaStore
85
86
  if (extraFilter) {
86
87
  filters.push(extraFilter);
87
88
  }
89
+ if (quickFilterResults) {
90
+ filters.push(quickFilterResults);
91
+ }
88
92
  if (columnFilters) {
89
93
  const transformedColumnFilters = transformColumnFilter(columnFilters, schema, schemaStore);
90
94
  if (transformedColumnFilters) {
@@ -105,11 +109,42 @@ function mergeConditions(schema, filter, extraFilter, columnFilters, schemaStore
105
109
  return null;
106
110
  }
107
111
  if (filters.length === 1) {
108
- return filters[0];
112
+ return simplyfyFilter(filters[0]);
109
113
  }
110
- return {
114
+ return simplyfyFilter({
111
115
  type: 'and',
112
116
  filters: filters,
117
+ });
118
+ }
119
+ function simplyfyFilter(filter) {
120
+ const conditions = filter.conditions ?? [];
121
+ const filters = [];
122
+ if (filter.filters) {
123
+ for (const f of filter.filters) {
124
+ const _f = simplyfyFilter(f);
125
+ if (!_f) {
126
+ continue;
127
+ }
128
+ if (_f.type !== filter.type) {
129
+ filters.push(_f);
130
+ }
131
+ else {
132
+ if (_f.conditions) {
133
+ conditions.push(..._f.conditions);
134
+ }
135
+ if (_f.filters) {
136
+ filters.push(..._f.filters);
137
+ }
138
+ }
139
+ }
140
+ }
141
+ if (conditions.length === 0 && filters.length === 0) {
142
+ return null;
143
+ }
144
+ return {
145
+ type: filter.type,
146
+ conditions: conditions,
147
+ filters: filters,
113
148
  };
114
149
  }
115
150
  function collectExpandedKeys(columns) {
@@ -23,6 +23,7 @@ export interface GridContextState<S extends SchemaAttributes = SchemaAttributes,
23
23
  searchText: string;
24
24
  columnFilters: Partial<Record<keyof S, ColumnCondition>>;
25
25
  sorting: SortingState<S>;
26
+ quickFilterValues: Record<string, unknown>;
26
27
  selectedIds: string[];
27
28
  data: RetriveRecordsResult<InferredSchemaType<S>> | null;
28
29
  dataState: {
@@ -0,0 +1 @@
1
+ export declare function useQuickFilter(): readonly [import("@headless-adminapp/core/experience/view/QuickFilter").QuickFilter<import("@headless-adminapp/core/schema").SchemaAttributes> | undefined, Record<string, unknown>, (key: string, value: unknown) => void];
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useQuickFilter = useQuickFilter;
4
+ const react_1 = require("react");
5
+ const context_1 = require("../../mutable/context");
6
+ const context_2 = require("../context");
7
+ function useQuickFilter() {
8
+ const quickFilter = (0, context_1.useContextSelector)(context_2.GridContext, (state) => state.view.experience.quickFilter);
9
+ const values = (0, context_1.useContextSelector)(context_2.GridContext, (state) => state.quickFilterValues);
10
+ const _setValue = (0, context_1.useContextSetValue)(context_2.GridContext);
11
+ const setValue = (0, react_1.useCallback)((key, value) => {
12
+ _setValue((state) => ({
13
+ quickFilterValues: {
14
+ ...state.quickFilterValues,
15
+ [key]: value,
16
+ },
17
+ }));
18
+ }, [_setValue]);
19
+ return [quickFilter, values, setValue];
20
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@headless-adminapp/app",
3
- "version": "1.1.10",
3
+ "version": "1.2.0",
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": "3920cedff7216fb37b07dff95c50499c0f56f57c"
39
+ "gitHead": "3c59cbbf000e71e39b81c9440a71363b729e6e3c"
40
40
  }
@@ -28,7 +28,7 @@ const CardViewSetter = () => {
28
28
  return;
29
29
  }
30
30
  experienceStore
31
- .getViewLookupV2(logicalName)
31
+ .getPublicView(logicalName)
32
32
  .then((view) => {
33
33
  setValue({
34
34
  cardView: view.experience.card,
@@ -29,6 +29,7 @@ function useRecordSetResult() {
29
29
  ...(cardView.secondaryColumns ?? [])
30
30
  .filter((x) => !x.expandedKey)
31
31
  .map((x) => x.name),
32
+ ...(cardView.rightColumn ?? []).map((x) => x.name),
32
33
  ])).filter(Boolean);
33
34
  }, [cardView]);
34
35
  const { isPending, data, error } = (0, react_query_1.useQuery)({
@@ -7,6 +7,7 @@ exports.useRetriveRecords = useRetriveRecords;
7
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
+ const utils_1 = require("../../datagrid/DataGridProvider/utils");
10
11
  const ROWS_PER_PAGE = 100;
11
12
  const MAX_RECORDS = 10000;
12
13
  function useRetrieveRecordsKey({ schema, search, filter, sorting, columns, expand, maxRecords, }) {
@@ -125,10 +126,16 @@ function useRetriveRecordsInternal(queryKey, { columns, expand, filter, maxRecor
125
126
  };
126
127
  }
127
128
  function useRetriveRecords({ columns, expand, filter, maxRecords, schema, search, sorting, disabled, }) {
129
+ const _filter = (0, react_1.useMemo)(() => {
130
+ if (!filter) {
131
+ return null;
132
+ }
133
+ return (0, utils_1.simplyfyFilter)(filter);
134
+ }, [filter]);
128
135
  const queryKey = useRetrieveRecordsKey({
129
136
  columns,
130
137
  expand,
131
- filter,
138
+ filter: _filter,
132
139
  maxRecords,
133
140
  schema,
134
141
  search,
@@ -137,7 +144,7 @@ function useRetriveRecords({ columns, expand, filter, maxRecords, schema, search
137
144
  const query = useRetriveRecordsInternal(queryKey, {
138
145
  columns,
139
146
  expand,
140
- filter,
147
+ filter: _filter,
141
148
  maxRecords,
142
149
  schema,
143
150
  search,