@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.
- package/board/BoardColumnDataResolver.js +33 -1
- package/board/context.d.ts +1 -0
- package/board/hooks/useQuickFilter.d.ts +1 -0
- package/board/hooks/useQuickFilter.js +20 -0
- package/board/types.d.ts +2 -0
- package/builders/CommandBuilder/DefaultCommandBuilder.js +5 -0
- package/builders/CommandBuilder/ViewCommandBuilder.d.ts +5 -0
- package/builders/CommandBuilder/ViewCommandBuilder.js +84 -3
- package/builders/DefineViewExperience.d.ts +1 -1
- package/builders/SchemaExperienceBuilder.d.ts +1 -1
- package/builders/utils.js +2 -1
- package/calendar/CalendarProvider.d.ts +8 -0
- package/calendar/CalendarProvider.js +18 -0
- package/calendar/hooks/useDeleteEvent.d.ts +1 -0
- package/calendar/hooks/useDeleteEvent.js +54 -0
- package/calendar/hooks/useOpenDetailDialog.d.ts +2 -0
- package/calendar/hooks/useOpenDetailDialog.js +61 -0
- package/calendar/types.d.ts +25 -6
- package/components/ScrollView/index.js +9 -8
- package/dataform/DataFormProvider/getRecord.d.ts +10 -1
- package/dataform/DataFormProvider/getRecord.js +38 -28
- package/dataform/DataFormProvider/utils.d.ts +1 -1
- package/dataform/DataFormProvider/utils.js +1 -1
- package/dataform/utils/index.d.ts +14 -1
- package/dataform/utils/index.js +45 -7
- package/dataform/utils/saveRecord.d.ts +36 -1
- package/dataform/utils/saveRecord.js +38 -9
- package/datagrid/DataGridProvider/DataResolver.js +22 -2
- package/datagrid/DataGridProvider/index.js +2 -0
- package/datagrid/DataGridProvider/utils.d.ts +2 -1
- package/datagrid/DataGridProvider/utils.js +38 -3
- package/datagrid/context.d.ts +1 -0
- package/datagrid/hooks/useQuickFilter.d.ts +1 -0
- package/datagrid/hooks/useQuickFilter.js +20 -0
- package/package.json +2 -2
- package/recordset/RecordSetProvider.js +1 -1
- package/recordset/hooks/useRecordSetResult.js +1 -0
- 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,
|
package/board/context.d.ts
CHANGED
|
@@ -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
|
-
|
|
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) =>
|
|
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) =>
|
|
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,
|
|
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
|
+
}
|
package/calendar/types.d.ts
CHANGED
|
@@ -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
|
|
33
|
+
saveEvent?: CalendarEventSaveFn<SA1, SA2>;
|
|
32
34
|
beforeDescriptionAttributes?: SA1;
|
|
33
35
|
afterDescriptionAttributes?: SA2;
|
|
34
36
|
filterAttributes?: SA3;
|
|
35
37
|
defaultFilter?: InferredSchemaType<SA3>;
|
|
36
|
-
|
|
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
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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 {
|
|
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.
|
|
24
|
+
if (!control.alias) {
|
|
24
25
|
continue;
|
|
25
26
|
}
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
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.
|
|
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[];
|
package/dataform/utils/index.js
CHANGED
|
@@ -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.
|
|
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.
|
|
133
|
+
columns: control.controls.map((x) => typeof x === 'string' ? x : x.attributeName),
|
|
134
134
|
schema: schema,
|
|
135
|
-
attributeName: control.
|
|
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[
|
|
37
|
-
const initialGridRows = initialValues[
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
-
}, [
|
|
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) {
|
package/datagrid/context.d.ts
CHANGED
|
@@ -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.
|
|
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": "
|
|
39
|
+
"gitHead": "3c59cbbf000e71e39b81c9440a71363b729e6e3c"
|
|
40
40
|
}
|
|
@@ -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,
|