@headless-adminapp/app 1.0.2 → 1.1.2
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 +4 -11
- package/board/types.d.ts +4 -0
- package/builders/CommandBuilder/ViewCommandBuilder.d.ts +14 -1
- package/builders/CommandBuilder/ViewCommandBuilder.js +96 -90
- package/builders/DefineFormExperience.d.ts +4 -3
- package/builders/DefineFormExperience.js +2 -4
- package/builders/SchemaExperienceBuilder.js +3 -2
- package/builders/utils.js +1 -1
- package/calendar/types.d.ts +5 -1
- package/command/types.d.ts +1 -0
- package/command/utils/index.js +3 -0
- package/dataform/utils/saveRecord.d.ts +6 -7
- package/datagrid/DataGridProvider/DataResolver.js +26 -34
- package/datagrid/DataGridProvider/transformViewColumns.js +2 -2
- package/datagrid/DataGridProvider/utils.d.ts +12 -1
- package/datagrid/DataGridProvider/utils.js +42 -0
- package/insights/hooks/index.d.ts +5 -2
- package/insights/hooks/index.js +24 -0
- package/metadata/MetadataProvider.js +1 -1
- package/package.json +2 -2
- package/store/SchemaExperienceStore.js +2 -2
- package/transport/RestDataService/index.d.ts +1 -1
- package/transport/RestDataService/index.js +9 -2
- package/transport/hooks/useCustomActionQuery.d.ts +1 -0
- package/transport/hooks/useCustomActionQuery.js +14 -0
- package/transport/hooks/useRetriveRecords.d.ts +25 -6
- package/transport/hooks/useRetriveRecords.js +55 -14
- package/utils/getAttributeFormattedValue.d.ts +1 -0
- package/utils/getAttributeFormattedValue.js +48 -2
|
@@ -16,7 +16,7 @@ function DataResolver() {
|
|
|
16
16
|
const { filter, maxRecords = MAX_RECORDS } = (0, useBoardColumnConfig_1.useBoardColumnConfig)();
|
|
17
17
|
const setState = (0, mutable_1.useContextSetValue)(context_1.BoardColumnContext);
|
|
18
18
|
const [search] = (0, hooks_1.useDebouncedValue)(searchText, 500);
|
|
19
|
-
const queryKey = (0, useRetriveRecords_1.
|
|
19
|
+
const { fetchNextPage, data, hasNextPage, isFetching, isFetchingNextPage, queryKey, } = (0, useRetriveRecords_1.useRetriveRecords)({
|
|
20
20
|
columns,
|
|
21
21
|
expand,
|
|
22
22
|
filter,
|
|
@@ -26,18 +26,11 @@ function DataResolver() {
|
|
|
26
26
|
sorting,
|
|
27
27
|
});
|
|
28
28
|
(0, useRetriveRecords_1.useClearDataExceptFirstPage)(queryKey);
|
|
29
|
-
const { fetchNextPage, data, hasNextPage, isFetching, isFetchingNextPage } = (0, useRetriveRecords_1.useRetriveRecords)(queryKey, {
|
|
30
|
-
columns,
|
|
31
|
-
expand,
|
|
32
|
-
filter,
|
|
33
|
-
maxRecords,
|
|
34
|
-
schema,
|
|
35
|
-
search,
|
|
36
|
-
sorting,
|
|
37
|
-
});
|
|
38
29
|
(0, react_1.useEffect)(() => {
|
|
39
30
|
setState({
|
|
40
|
-
fetchNextPage:
|
|
31
|
+
fetchNextPage: () => {
|
|
32
|
+
fetchNextPage().catch(console.error);
|
|
33
|
+
},
|
|
41
34
|
});
|
|
42
35
|
}, [fetchNextPage, setState]);
|
|
43
36
|
(0, react_1.useEffect)(() => {
|
package/board/types.d.ts
CHANGED
|
@@ -44,4 +44,8 @@ export interface BoardConfig<S extends SchemaAttributes = SchemaAttributes> {
|
|
|
44
44
|
};
|
|
45
45
|
columnConfigs: BoardColumnConfig[];
|
|
46
46
|
PreviewComponent: BoardColumnCardPreviewFC;
|
|
47
|
+
HeaderComponent?: FC;
|
|
48
|
+
emptyMessage?: string;
|
|
49
|
+
minColumnWidth?: number;
|
|
50
|
+
maxColumnWidth?: number;
|
|
47
51
|
}
|
|
@@ -1,6 +1,13 @@
|
|
|
1
|
-
import { EntityMainGridCommandItemExperience } from '@headless-adminapp/core/experience/view';
|
|
1
|
+
import { EntityMainGridCommandContext, EntityMainGridCommandItemExperience } from '@headless-adminapp/core/experience/view';
|
|
2
2
|
import { Localized } from '@headless-adminapp/core/types';
|
|
3
3
|
import { Icon } from '@headless-adminapp/icons';
|
|
4
|
+
export declare namespace EnabledRules {
|
|
5
|
+
function HasCreatePermisssion(context: EntityMainGridCommandContext): boolean;
|
|
6
|
+
function HasUpdatePermission(context: EntityMainGridCommandContext): boolean;
|
|
7
|
+
function HasDeletePermission(context: EntityMainGridCommandContext): boolean;
|
|
8
|
+
function HasSingleRecordSelected(context: EntityMainGridCommandContext): boolean;
|
|
9
|
+
function HasAtLeastOneRecordSelected(context: EntityMainGridCommandContext): boolean;
|
|
10
|
+
}
|
|
4
11
|
export declare namespace ViewCommandBuilder {
|
|
5
12
|
function createNewRecordCommand({ Icon, text, localizedTexts, }: {
|
|
6
13
|
Icon: Icon;
|
|
@@ -61,3 +68,9 @@ export declare namespace ViewCommandBuilder {
|
|
|
61
68
|
};
|
|
62
69
|
}): EntityMainGridCommandItemExperience;
|
|
63
70
|
}
|
|
71
|
+
export declare function exportRecordsToExcel(context: EntityMainGridCommandContext): Promise<void>;
|
|
72
|
+
export declare function exportRecordsToCSV(context: EntityMainGridCommandContext): Promise<void>;
|
|
73
|
+
export declare function processDeleteRecordRequest(context: EntityMainGridCommandContext, { stringSet, localizedStringSet, }: {
|
|
74
|
+
stringSet: ViewCommandBuilder.DeleteRecordCommandStringSet;
|
|
75
|
+
localizedStringSet?: Localized<ViewCommandBuilder.DeleteRecordCommandStringSet>;
|
|
76
|
+
}): Promise<void>;
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ViewCommandBuilder = void 0;
|
|
3
|
+
exports.ViewCommandBuilder = exports.EnabledRules = void 0;
|
|
4
|
+
exports.exportRecordsToExcel = exportRecordsToExcel;
|
|
5
|
+
exports.exportRecordsToCSV = exportRecordsToCSV;
|
|
6
|
+
exports.processDeleteRecordRequest = processDeleteRecordRequest;
|
|
4
7
|
const utils_1 = require("../utils");
|
|
5
8
|
const utils_2 = require("./utils");
|
|
6
9
|
var EnabledRules;
|
|
@@ -25,7 +28,7 @@ var EnabledRules;
|
|
|
25
28
|
return context.primaryControl.selectedIds.length > 0;
|
|
26
29
|
}
|
|
27
30
|
EnabledRules.HasAtLeastOneRecordSelected = HasAtLeastOneRecordSelected;
|
|
28
|
-
})(EnabledRules || (EnabledRules = {}));
|
|
31
|
+
})(EnabledRules || (exports.EnabledRules = EnabledRules = {}));
|
|
29
32
|
var ViewCommandBuilder;
|
|
30
33
|
(function (ViewCommandBuilder) {
|
|
31
34
|
function createNewRecordCommand({ Icon, text, localizedTexts, }) {
|
|
@@ -92,42 +95,10 @@ var ViewCommandBuilder;
|
|
|
92
95
|
danger: true,
|
|
93
96
|
isContextMenu: true,
|
|
94
97
|
onClick: async (context) => {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
}
|
|
99
|
-
const localizeSelector = (0, utils_2.createLocalizedSelector)(stringSet, localizedStringSet, context.locale.language);
|
|
100
|
-
try {
|
|
101
|
-
const confirmResult = await context.utility.openConfirmDialog({
|
|
102
|
-
title: (0, utils_2.plurialize)(recordIds.length, localizeSelector((s) => s.confirmation.title)),
|
|
103
|
-
text: (0, utils_2.plurialize)(recordIds.length, localizeSelector((s) => s.confirmation.text)),
|
|
104
|
-
cancelButtonLabel: localizeSelector((s) => s.confirmation.buttonCancel),
|
|
105
|
-
confirmButtonLabel: localizeSelector((s) => s.confirmation.buttonConfirm),
|
|
106
|
-
});
|
|
107
|
-
if (!confirmResult?.confirmed) {
|
|
108
|
-
return;
|
|
109
|
-
}
|
|
110
|
-
context.utility.showProgressIndicator((0, utils_2.plurialize)(recordIds.length, localizeSelector((s) => s.status.deleting)) + '...');
|
|
111
|
-
for (const recordId of recordIds) {
|
|
112
|
-
await context.dataService.deleteRecord(context.primaryControl.logicalName, recordId);
|
|
113
|
-
}
|
|
114
|
-
context.utility.showNotification({
|
|
115
|
-
title: (0, utils_2.plurialize)(recordIds.length, localizeSelector((s) => s.successNotification.title)),
|
|
116
|
-
text: (0, utils_2.plurialize)(recordIds.length, localizeSelector((s) => s.successNotification.text)),
|
|
117
|
-
type: 'success',
|
|
118
|
-
});
|
|
119
|
-
context.primaryControl.refresh();
|
|
120
|
-
}
|
|
121
|
-
catch (error) {
|
|
122
|
-
context.utility.showNotification({
|
|
123
|
-
title: localizeSelector((s) => s.errorNotification.title),
|
|
124
|
-
text: error.message,
|
|
125
|
-
type: 'error',
|
|
126
|
-
});
|
|
127
|
-
}
|
|
128
|
-
finally {
|
|
129
|
-
context.utility.hideProgressIndicator();
|
|
130
|
-
}
|
|
98
|
+
await processDeleteRecordRequest(context, {
|
|
99
|
+
stringSet,
|
|
100
|
+
localizedStringSet,
|
|
101
|
+
});
|
|
131
102
|
},
|
|
132
103
|
hidden: [
|
|
133
104
|
(context) => !EnabledRules.HasAtLeastOneRecordSelected(context),
|
|
@@ -161,32 +132,7 @@ var ViewCommandBuilder;
|
|
|
161
132
|
text: excel.text,
|
|
162
133
|
localizedTexts: excel.localizedTexts,
|
|
163
134
|
onClick: async (context) => {
|
|
164
|
-
context
|
|
165
|
-
try {
|
|
166
|
-
const result = await (0, utils_1.retriveRecords)({
|
|
167
|
-
columnFilters: context.primaryControl.columnFilter,
|
|
168
|
-
dataService: context.dataService,
|
|
169
|
-
gridColumns: context.primaryControl.gridColumns,
|
|
170
|
-
schema: context.primaryControl.schema,
|
|
171
|
-
schemaStore: context.stores.schemaStore,
|
|
172
|
-
view: context.primaryControl.view,
|
|
173
|
-
search: context.primaryControl.searchText,
|
|
174
|
-
extraFilter: context.primaryControl.extraFilter,
|
|
175
|
-
sorting: context.primaryControl.sorting,
|
|
176
|
-
skip: 0,
|
|
177
|
-
limit: 5000,
|
|
178
|
-
});
|
|
179
|
-
await (0, utils_1.exportRecordsXLS)({
|
|
180
|
-
fileName: context.primaryControl.view.name + '.xlsx',
|
|
181
|
-
gridColumns: context.primaryControl.gridColumns,
|
|
182
|
-
records: result.records,
|
|
183
|
-
schema: context.primaryControl.schema,
|
|
184
|
-
schemaStore: context.stores.schemaStore,
|
|
185
|
-
});
|
|
186
|
-
}
|
|
187
|
-
finally {
|
|
188
|
-
context.utility.hideProgressIndicator();
|
|
189
|
-
}
|
|
135
|
+
await exportRecordsToExcel(context);
|
|
190
136
|
},
|
|
191
137
|
},
|
|
192
138
|
{
|
|
@@ -194,32 +140,7 @@ var ViewCommandBuilder;
|
|
|
194
140
|
text: csv.text,
|
|
195
141
|
localizedTexts: csv.localizedTexts,
|
|
196
142
|
onClick: async (context) => {
|
|
197
|
-
context
|
|
198
|
-
try {
|
|
199
|
-
const result = await (0, utils_1.retriveRecords)({
|
|
200
|
-
columnFilters: context.primaryControl.columnFilter,
|
|
201
|
-
dataService: context.dataService,
|
|
202
|
-
gridColumns: context.primaryControl.gridColumns,
|
|
203
|
-
schema: context.primaryControl.schema,
|
|
204
|
-
schemaStore: context.stores.schemaStore,
|
|
205
|
-
view: context.primaryControl.view,
|
|
206
|
-
search: context.primaryControl.searchText,
|
|
207
|
-
extraFilter: context.primaryControl.extraFilter,
|
|
208
|
-
sorting: context.primaryControl.sorting,
|
|
209
|
-
skip: 0,
|
|
210
|
-
limit: 5000,
|
|
211
|
-
});
|
|
212
|
-
await (0, utils_1.exportRecordsCSV)({
|
|
213
|
-
fileName: context.primaryControl.view.name + '.csv',
|
|
214
|
-
gridColumns: context.primaryControl.gridColumns,
|
|
215
|
-
records: result.records,
|
|
216
|
-
schema: context.primaryControl.schema,
|
|
217
|
-
schemaStore: context.stores.schemaStore,
|
|
218
|
-
});
|
|
219
|
-
}
|
|
220
|
-
finally {
|
|
221
|
-
context.utility.hideProgressIndicator();
|
|
222
|
-
}
|
|
143
|
+
await exportRecordsToCSV(context);
|
|
223
144
|
},
|
|
224
145
|
},
|
|
225
146
|
],
|
|
@@ -228,3 +149,88 @@ var ViewCommandBuilder;
|
|
|
228
149
|
}
|
|
229
150
|
ViewCommandBuilder.createExportCommand = createExportCommand;
|
|
230
151
|
})(ViewCommandBuilder || (exports.ViewCommandBuilder = ViewCommandBuilder = {}));
|
|
152
|
+
async function retrieveFilteredRecords(context) {
|
|
153
|
+
return (0, utils_1.retriveRecords)({
|
|
154
|
+
columnFilters: context.primaryControl.columnFilter,
|
|
155
|
+
dataService: context.dataService,
|
|
156
|
+
gridColumns: context.primaryControl.gridColumns,
|
|
157
|
+
schema: context.primaryControl.schema,
|
|
158
|
+
schemaStore: context.stores.schemaStore,
|
|
159
|
+
view: context.primaryControl.view,
|
|
160
|
+
search: context.primaryControl.searchText,
|
|
161
|
+
extraFilter: context.primaryControl.extraFilter,
|
|
162
|
+
sorting: context.primaryControl.sorting,
|
|
163
|
+
skip: 0,
|
|
164
|
+
limit: 5000,
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
async function exportRecordsToExcel(context) {
|
|
168
|
+
context.utility.showProgressIndicator('Exporting to Excel...');
|
|
169
|
+
try {
|
|
170
|
+
const result = await retrieveFilteredRecords(context);
|
|
171
|
+
await (0, utils_1.exportRecordsXLS)({
|
|
172
|
+
fileName: context.primaryControl.view.name + '.xlsx',
|
|
173
|
+
gridColumns: context.primaryControl.gridColumns,
|
|
174
|
+
records: result.records,
|
|
175
|
+
schema: context.primaryControl.schema,
|
|
176
|
+
schemaStore: context.stores.schemaStore,
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
finally {
|
|
180
|
+
context.utility.hideProgressIndicator();
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
async function exportRecordsToCSV(context) {
|
|
184
|
+
context.utility.showProgressIndicator('Exporting to CSV...');
|
|
185
|
+
try {
|
|
186
|
+
const result = await retrieveFilteredRecords(context);
|
|
187
|
+
await (0, utils_1.exportRecordsCSV)({
|
|
188
|
+
fileName: context.primaryControl.view.name + '.csv',
|
|
189
|
+
gridColumns: context.primaryControl.gridColumns,
|
|
190
|
+
records: result.records,
|
|
191
|
+
schema: context.primaryControl.schema,
|
|
192
|
+
schemaStore: context.stores.schemaStore,
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
finally {
|
|
196
|
+
context.utility.hideProgressIndicator();
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
async function processDeleteRecordRequest(context, { stringSet, localizedStringSet, }) {
|
|
200
|
+
const recordIds = context.primaryControl.selectedIds;
|
|
201
|
+
if (!recordIds.length) {
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
const localizeSelector = (0, utils_2.createLocalizedSelector)(stringSet, localizedStringSet, context.locale.language);
|
|
205
|
+
try {
|
|
206
|
+
const confirmResult = await context.utility.openConfirmDialog({
|
|
207
|
+
title: (0, utils_2.plurialize)(recordIds.length, localizeSelector((s) => s.confirmation.title)),
|
|
208
|
+
text: (0, utils_2.plurialize)(recordIds.length, localizeSelector((s) => s.confirmation.text)),
|
|
209
|
+
cancelButtonLabel: localizeSelector((s) => s.confirmation.buttonCancel),
|
|
210
|
+
confirmButtonLabel: localizeSelector((s) => s.confirmation.buttonConfirm),
|
|
211
|
+
});
|
|
212
|
+
if (!confirmResult?.confirmed) {
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
context.utility.showProgressIndicator((0, utils_2.plurialize)(recordIds.length, localizeSelector((s) => s.status.deleting)) + '...');
|
|
216
|
+
for (const recordId of recordIds) {
|
|
217
|
+
await context.dataService.deleteRecord(context.primaryControl.logicalName, recordId);
|
|
218
|
+
}
|
|
219
|
+
context.utility.showNotification({
|
|
220
|
+
title: (0, utils_2.plurialize)(recordIds.length, localizeSelector((s) => s.successNotification.title)),
|
|
221
|
+
text: (0, utils_2.plurialize)(recordIds.length, localizeSelector((s) => s.successNotification.text)),
|
|
222
|
+
type: 'success',
|
|
223
|
+
});
|
|
224
|
+
context.primaryControl.refresh();
|
|
225
|
+
}
|
|
226
|
+
catch (error) {
|
|
227
|
+
context.utility.showNotification({
|
|
228
|
+
title: localizeSelector((s) => s.errorNotification.title),
|
|
229
|
+
text: error.message,
|
|
230
|
+
type: 'error',
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
finally {
|
|
234
|
+
context.utility.hideProgressIndicator();
|
|
235
|
+
}
|
|
236
|
+
}
|
|
@@ -5,12 +5,13 @@ import type { SchemaAttributes } from '@headless-adminapp/core/schema';
|
|
|
5
5
|
export declare namespace DefineFormExperience {
|
|
6
6
|
export type Experience<S extends SchemaAttributes = SchemaAttributes> = (Pick<$FormExperience<S>, 'useHookFn' | 'relatedItems' | 'processFlow' | 'cloneAttributes' | 'defaultValues' | 'includeAttributes' | 'headerControls'> & {
|
|
7
7
|
tabs: Tab<S>[];
|
|
8
|
-
}) |
|
|
8
|
+
}) | SectionControl<S>[];
|
|
9
9
|
export function resolveExperience<S extends SchemaAttributes = SchemaAttributes>(v: Experience<S>): $FormExperience<S>;
|
|
10
|
-
type Tab<S extends SchemaAttributes = SchemaAttributes> = Pick<$Tab<S>, 'label' | 'localizedLabels' | 'name'> &
|
|
11
|
-
tabColumns: TabColumn<S>[];
|
|
10
|
+
type Tab<S extends SchemaAttributes = SchemaAttributes> = Pick<$Tab<S>, 'label' | 'localizedLabels' | 'name'> & {
|
|
12
11
|
columnCount?: $Tab<S>['columnCount'];
|
|
13
12
|
columnWidths?: $Tab<S>['columnWidths'];
|
|
13
|
+
} & ({
|
|
14
|
+
tabColumns: TabColumn<S>[];
|
|
14
15
|
} | {
|
|
15
16
|
sections: Section<S>[];
|
|
16
17
|
} | {
|
|
@@ -41,13 +41,12 @@ var DefineFormExperience;
|
|
|
41
41
|
name: v.name,
|
|
42
42
|
localizedLabels: v.localizedLabels,
|
|
43
43
|
};
|
|
44
|
+
tab.columnCount = v.columnCount ?? 2;
|
|
45
|
+
tab.columnWidths = v.columnWidths;
|
|
44
46
|
if ('tabColumns' in v) {
|
|
45
|
-
tab.columnCount = v.columnCount ?? 2;
|
|
46
|
-
tab.columnWidths = v.columnWidths;
|
|
47
47
|
tab.tabColumns = v.tabColumns.map(resolveTabColumn);
|
|
48
48
|
}
|
|
49
49
|
else if ('sections' in v) {
|
|
50
|
-
tab.columnCount = 2;
|
|
51
50
|
tab.tabColumns = [
|
|
52
51
|
{
|
|
53
52
|
sections: v.sections.map(resolveSection),
|
|
@@ -55,7 +54,6 @@ var DefineFormExperience;
|
|
|
55
54
|
];
|
|
56
55
|
}
|
|
57
56
|
else if ('controls' in v) {
|
|
58
|
-
tab.columnCount = 2;
|
|
59
57
|
tab.tabColumns = [
|
|
60
58
|
{
|
|
61
59
|
sections: [
|
|
@@ -142,13 +142,14 @@ class SchemaExperienceBuilder extends BaseSchemaExperienceBuilder {
|
|
|
142
142
|
{
|
|
143
143
|
name: 'general',
|
|
144
144
|
label: 'General',
|
|
145
|
-
columnCount:
|
|
145
|
+
columnCount: 2,
|
|
146
146
|
tabColumns: [
|
|
147
147
|
{
|
|
148
148
|
sections: [
|
|
149
149
|
{
|
|
150
150
|
name: 'general',
|
|
151
151
|
label: 'General',
|
|
152
|
+
hideLabel: true,
|
|
152
153
|
controls: [
|
|
153
154
|
{
|
|
154
155
|
type: 'standard',
|
|
@@ -244,7 +245,7 @@ class SchemaExperienceBuilder extends BaseSchemaExperienceBuilder {
|
|
|
244
245
|
}
|
|
245
246
|
return {
|
|
246
247
|
logicalName: this.logicalName,
|
|
247
|
-
|
|
248
|
+
Icon: experience.Icon,
|
|
248
249
|
defaultQuickCreateFormId: defaultQuickCreateFormId,
|
|
249
250
|
defaultFormId,
|
|
250
251
|
defaultViewId,
|
package/builders/utils.js
CHANGED
|
@@ -35,7 +35,7 @@ const getHeaders = (schema, gridColumns, schemaStore) => {
|
|
|
35
35
|
const lookupSchema = schemaStore.getSchema(entity);
|
|
36
36
|
return `${lookupSchema.attributes[field]?.label} (${schema.attributes[lookup]?.label})`;
|
|
37
37
|
}
|
|
38
|
-
return schema.attributes[column.name]?.label;
|
|
38
|
+
return column.label ?? schema.attributes[column.name]?.label;
|
|
39
39
|
});
|
|
40
40
|
return headers;
|
|
41
41
|
};
|
package/calendar/types.d.ts
CHANGED
|
@@ -16,7 +16,7 @@ export interface CalendarEventsResolverFnOptions<SA extends SchemaAttributes = S
|
|
|
16
16
|
auth: AuthSession | null;
|
|
17
17
|
}
|
|
18
18
|
export type CalendarEventsResolverFn<SA extends SchemaAttributes = SchemaAttributes> = (options: CalendarEventsResolverFnOptions<SA>) => Promise<CalendarEvent[]>;
|
|
19
|
-
export type CalendarEventResolverFn<T extends CalendarEvent = CalendarEvent> = (id: string) => Promise<T
|
|
19
|
+
export type CalendarEventResolverFn<T extends CalendarEvent = CalendarEvent> = (id: string) => Promise<Partial<T>>;
|
|
20
20
|
export type CalendarEventSaveData<SA1 extends SchemaAttributes = SchemaAttributes, SA2 extends SchemaAttributes = SchemaAttributes> = Omit<CalendarEvent, 'id'> & {
|
|
21
21
|
id?: CalendarEvent['id'];
|
|
22
22
|
} & InferredSchemaType<SA1> & InferredSchemaType<SA2>;
|
|
@@ -38,4 +38,8 @@ export interface CalendarConfig<SA1 extends SchemaAttributes = SchemaAttributes,
|
|
|
38
38
|
title: string;
|
|
39
39
|
description: string;
|
|
40
40
|
eventLabel: string;
|
|
41
|
+
disableCreate?: boolean;
|
|
42
|
+
disableEdit?: boolean;
|
|
43
|
+
disableDelete?: boolean;
|
|
44
|
+
disableAllDay?: boolean;
|
|
41
45
|
}
|
package/command/types.d.ts
CHANGED
package/command/utils/index.js
CHANGED
|
@@ -27,6 +27,7 @@ function transformCommand(command, handlerContext) {
|
|
|
27
27
|
isQuickAction: command.isQuickAction,
|
|
28
28
|
danger: command.danger,
|
|
29
29
|
iconPosition: command.iconPosition,
|
|
30
|
+
appearance: command.appearance,
|
|
30
31
|
...transformedProperties(command, handlerContext),
|
|
31
32
|
};
|
|
32
33
|
case 'button':
|
|
@@ -37,6 +38,7 @@ function transformCommand(command, handlerContext) {
|
|
|
37
38
|
danger: command.danger,
|
|
38
39
|
iconPosition: command.iconPosition,
|
|
39
40
|
localizedTexts: command.localizedText,
|
|
41
|
+
appearance: command.appearance,
|
|
40
42
|
...transformedProperties(command, handlerContext),
|
|
41
43
|
};
|
|
42
44
|
case 'menu':
|
|
@@ -46,6 +48,7 @@ function transformCommand(command, handlerContext) {
|
|
|
46
48
|
danger: command.danger,
|
|
47
49
|
localizedTexts: command.localizedTexts,
|
|
48
50
|
iconPosition: command.iconPosition,
|
|
51
|
+
appearance: command.appearance,
|
|
49
52
|
...transformedProperties(command, handlerContext),
|
|
50
53
|
items: command.items.map((item) => transformMenuItems(item, handlerContext)),
|
|
51
54
|
};
|
|
@@ -4,7 +4,7 @@ import { ISchemaStore } from '@headless-adminapp/core/store';
|
|
|
4
4
|
import { IDataService } from '@headless-adminapp/core/transport';
|
|
5
5
|
import { Nullable } from '@headless-adminapp/core/types';
|
|
6
6
|
export declare function getModifiedValues(initialValues: any, values: any, exclude?: string[]): Record<string, any>;
|
|
7
|
-
type SaveRecordResult = {
|
|
7
|
+
export type SaveRecordResult = {
|
|
8
8
|
success: true;
|
|
9
9
|
recordId: string;
|
|
10
10
|
} | {
|
|
@@ -13,15 +13,14 @@ type SaveRecordResult = {
|
|
|
13
13
|
message: string;
|
|
14
14
|
isError: boolean;
|
|
15
15
|
};
|
|
16
|
-
export interface SaveRecordFnOptions {
|
|
16
|
+
export interface SaveRecordFnOptions<S extends SchemaAttributes = SchemaAttributes> {
|
|
17
17
|
values: any;
|
|
18
|
-
form: Form<
|
|
19
|
-
record: InferredSchemaType<
|
|
20
|
-
initialValues: Nullable<InferredSchemaType<
|
|
21
|
-
schema: Schema<
|
|
18
|
+
form: Form<S>;
|
|
19
|
+
record: InferredSchemaType<S> | undefined;
|
|
20
|
+
initialValues: Nullable<InferredSchemaType<S>>;
|
|
21
|
+
schema: Schema<S>;
|
|
22
22
|
dataService: IDataService;
|
|
23
23
|
schemaStore: ISchemaStore;
|
|
24
24
|
}
|
|
25
25
|
export type SaveRecordFn = (options: SaveRecordFnOptions) => Promise<SaveRecordResult>;
|
|
26
26
|
export declare function saveRecord({ values, form, schema, dataService, initialValues, record, schemaStore, }: SaveRecordFnOptions): Promise<SaveRecordResult>;
|
|
27
|
-
export {};
|
|
@@ -2,56 +2,45 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.DataResolver = DataResolver;
|
|
4
4
|
const react_1 = require("react");
|
|
5
|
+
const hooks_1 = require("../../hooks");
|
|
5
6
|
const useDebouncedValue_1 = require("../../hooks/useDebouncedValue");
|
|
6
7
|
const useMetadata_1 = require("../../metadata/hooks/useMetadata");
|
|
7
8
|
const context_1 = require("../../mutable/context");
|
|
8
9
|
const useRetriveRecords_1 = require("../../transport/hooks/useRetriveRecords");
|
|
9
10
|
const context_2 = require("../context");
|
|
10
|
-
const
|
|
11
|
+
const hooks_2 = require("../hooks");
|
|
11
12
|
const useGridDisabled_1 = require("../hooks/useGridDisabled");
|
|
12
13
|
const utils_1 = require("./utils");
|
|
13
|
-
const MAX_RECORDS = 10000;
|
|
14
14
|
function DataResolver() {
|
|
15
|
-
const schema = (0,
|
|
16
|
-
const view = (0,
|
|
17
|
-
const [sorting] = (0,
|
|
18
|
-
const [searchText] = (0,
|
|
19
|
-
const extraFilter = (0,
|
|
20
|
-
const [columnFilters] = (0,
|
|
21
|
-
const gridColumns = (0,
|
|
22
|
-
const maxRecords = (0,
|
|
23
|
-
const [selectedIds] = (0,
|
|
15
|
+
const schema = (0, hooks_2.useDataGridSchema)();
|
|
16
|
+
const view = (0, hooks_2.useSelectedView)();
|
|
17
|
+
const [sorting] = (0, hooks_2.useGridSorting)();
|
|
18
|
+
const [searchText] = (0, hooks_2.useSearchText)();
|
|
19
|
+
const extraFilter = (0, hooks_2.useGridExtraFilter)();
|
|
20
|
+
const [columnFilters] = (0, hooks_2.useGridColumnFilter)();
|
|
21
|
+
const gridColumns = (0, hooks_2.useGridColumns)();
|
|
22
|
+
const maxRecords = (0, hooks_2.useMaxRecords)();
|
|
23
|
+
const [selectedIds] = (0, hooks_2.useGridSelection)();
|
|
24
24
|
const disabled = (0, useGridDisabled_1.useGridDisabled)();
|
|
25
25
|
const { schemaStore } = (0, useMetadata_1.useMetadata)();
|
|
26
26
|
const selectedIdsRef = (0, react_1.useRef)(selectedIds);
|
|
27
27
|
selectedIdsRef.current = selectedIds;
|
|
28
28
|
const setState = (0, context_1.useContextSetValue)(context_2.GridContext);
|
|
29
29
|
const [search] = (0, useDebouncedValue_1.useDebouncedValue)(searchText, 500);
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
const expand = (0, react_1.useMemo)(() => (0, utils_1.collectExpandedKeys)(gridColumns), [gridColumns]);
|
|
30
|
+
const isMobile = (0, hooks_1.useIsMobile)();
|
|
31
|
+
const columns = (0, react_1.useMemo)(() => isMobile
|
|
32
|
+
? (0, utils_1.collectCardColumns)({ cardView: view.experience.card, schema })
|
|
33
|
+
: (0, utils_1.collectGridColumns)({
|
|
34
|
+
gridColumns,
|
|
35
|
+
schema,
|
|
36
|
+
}), [isMobile, view.experience.card, schema, gridColumns]);
|
|
37
|
+
const expand = (0, react_1.useMemo)(() => isMobile
|
|
38
|
+
? (0, utils_1.collectCardExpandedKeys)({ cardView: view.experience.card })
|
|
39
|
+
: (0, utils_1.collectExpandedKeys)(gridColumns), [gridColumns, isMobile, view.experience.card]);
|
|
41
40
|
const filter = (0, react_1.useMemo)(() => {
|
|
42
41
|
return (0, utils_1.mergeConditions)(schema, view.experience.filter, extraFilter, columnFilters, schemaStore);
|
|
43
42
|
}, [columnFilters, extraFilter, schema, schemaStore, view.experience.filter]);
|
|
44
|
-
const queryKey = (0, useRetriveRecords_1.
|
|
45
|
-
columns,
|
|
46
|
-
expand,
|
|
47
|
-
filter,
|
|
48
|
-
maxRecords,
|
|
49
|
-
schema,
|
|
50
|
-
search,
|
|
51
|
-
sorting,
|
|
52
|
-
});
|
|
53
|
-
(0, useRetriveRecords_1.useClearDataExceptFirstPage)(queryKey);
|
|
54
|
-
const { fetchNextPage, data, hasNextPage, isFetching, isFetchingNextPage } = (0, useRetriveRecords_1.useRetriveRecords)(queryKey, {
|
|
43
|
+
const { fetchNextPage, data, hasNextPage, isFetching, isFetchingNextPage, queryKey, } = (0, useRetriveRecords_1.useRetriveRecords)({
|
|
55
44
|
columns,
|
|
56
45
|
expand,
|
|
57
46
|
filter,
|
|
@@ -61,9 +50,12 @@ function DataResolver() {
|
|
|
61
50
|
sorting,
|
|
62
51
|
disabled,
|
|
63
52
|
});
|
|
53
|
+
(0, useRetriveRecords_1.useClearDataExceptFirstPage)(queryKey);
|
|
64
54
|
(0, react_1.useEffect)(() => {
|
|
65
55
|
setState({
|
|
66
|
-
fetchNextPage: () =>
|
|
56
|
+
fetchNextPage: () => {
|
|
57
|
+
fetchNextPage().catch(console.error);
|
|
58
|
+
},
|
|
67
59
|
});
|
|
68
60
|
}, [fetchNextPage, setState]);
|
|
69
61
|
(0, react_1.useEffect)(() => {
|
|
@@ -5,12 +5,12 @@ const utils_1 = require("../../locale/utils");
|
|
|
5
5
|
function transformViewColumns(logicalName, columns, schemaStore, language) {
|
|
6
6
|
const schema = schemaStore.getSchema(logicalName);
|
|
7
7
|
return columns
|
|
8
|
-
.map(column => {
|
|
8
|
+
.map((column) => {
|
|
9
9
|
const attribute = schema.attributes[column.name];
|
|
10
10
|
if (!attribute) {
|
|
11
11
|
return null;
|
|
12
12
|
}
|
|
13
|
-
const label = (0, utils_1.localizedLabel)(language, attribute);
|
|
13
|
+
const label = column.label ?? (0, utils_1.localizedLabel)(language, attribute);
|
|
14
14
|
if (column.expandedKey) {
|
|
15
15
|
if (attribute.type !== 'lookup') {
|
|
16
16
|
return null;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ColumnCondition } from '@headless-adminapp/core/experience/view';
|
|
1
|
+
import { CardView, ColumnCondition } from '@headless-adminapp/core/experience/view';
|
|
2
2
|
import { Schema, SchemaAttributes } from '@headless-adminapp/core/schema';
|
|
3
3
|
import { ISchemaStore } from '@headless-adminapp/core/store';
|
|
4
4
|
import { Filter } from '@headless-adminapp/core/transport';
|
|
@@ -6,3 +6,14 @@ 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
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;
|
|
8
8
|
export declare function collectExpandedKeys(columns: TransformedViewColumn<SchemaAttributes>[]): Record<string, string[]>;
|
|
9
|
+
export declare function collectGridColumns<S extends SchemaAttributes = SchemaAttributes>({ gridColumns, schema, }: {
|
|
10
|
+
gridColumns: TransformedViewColumn<S>[];
|
|
11
|
+
schema: Schema<S>;
|
|
12
|
+
}): (keyof S)[];
|
|
13
|
+
export declare function collectCardColumns<S extends SchemaAttributes = SchemaAttributes>({ cardView, schema, }: {
|
|
14
|
+
cardView: CardView<S>;
|
|
15
|
+
schema: Schema<S>;
|
|
16
|
+
}): string[];
|
|
17
|
+
export declare function collectCardExpandedKeys<S extends SchemaAttributes = SchemaAttributes>({ cardView }: {
|
|
18
|
+
cardView: CardView<S>;
|
|
19
|
+
}): Record<string, string[]> | undefined;
|
|
@@ -6,6 +6,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.transformColumnFilter = transformColumnFilter;
|
|
7
7
|
exports.mergeConditions = mergeConditions;
|
|
8
8
|
exports.collectExpandedKeys = collectExpandedKeys;
|
|
9
|
+
exports.collectGridColumns = collectGridColumns;
|
|
10
|
+
exports.collectCardColumns = collectCardColumns;
|
|
11
|
+
exports.collectCardExpandedKeys = collectCardExpandedKeys;
|
|
9
12
|
const dayjs_1 = __importDefault(require("dayjs"));
|
|
10
13
|
function transformColumnFilter(filter, schema, schemaStore) {
|
|
11
14
|
const transformedResult = Object.entries(filter).reduce((acc, [id, value]) => {
|
|
@@ -122,3 +125,42 @@ function collectExpandedKeys(columns) {
|
|
|
122
125
|
return acc;
|
|
123
126
|
}, {});
|
|
124
127
|
}
|
|
128
|
+
function collectGridColumns({ gridColumns, schema, }) {
|
|
129
|
+
const set = new Set([
|
|
130
|
+
...gridColumns.filter((x) => !x.expandedKey).map((x) => x.name),
|
|
131
|
+
schema.primaryAttribute,
|
|
132
|
+
]);
|
|
133
|
+
if (schema.avatarAttribute) {
|
|
134
|
+
set.add(schema.avatarAttribute);
|
|
135
|
+
}
|
|
136
|
+
return Array.from(set);
|
|
137
|
+
}
|
|
138
|
+
function collectCardColumns({ cardView, schema, }) {
|
|
139
|
+
const set = new Set([
|
|
140
|
+
cardView.primaryColumn,
|
|
141
|
+
...(cardView.secondaryColumns
|
|
142
|
+
?.filter((x) => !x.expandedKey)
|
|
143
|
+
.map((x) => x.name) ?? []),
|
|
144
|
+
...(cardView.rightColumn?.map((x) => x.name) ?? []),
|
|
145
|
+
schema.primaryAttribute,
|
|
146
|
+
]);
|
|
147
|
+
if (cardView.showAvatar &&
|
|
148
|
+
(cardView.avatarColumn || schema.avatarAttribute)) {
|
|
149
|
+
set.add((cardView.avatarColumn ?? schema.avatarAttribute));
|
|
150
|
+
}
|
|
151
|
+
return Array.from(set);
|
|
152
|
+
}
|
|
153
|
+
function collectCardExpandedKeys({ cardView }) {
|
|
154
|
+
return cardView.secondaryColumns
|
|
155
|
+
?.filter((x) => x.expandedKey)
|
|
156
|
+
.reduce((acc, x) => {
|
|
157
|
+
const name = x.name;
|
|
158
|
+
if (!acc[name]) {
|
|
159
|
+
acc[name] = [];
|
|
160
|
+
}
|
|
161
|
+
if (!acc[name].includes(x.expandedKey)) {
|
|
162
|
+
acc[name].push(x.expandedKey);
|
|
163
|
+
}
|
|
164
|
+
return acc;
|
|
165
|
+
}, {});
|
|
166
|
+
}
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
-
import { InsightsState } from '@headless-adminapp/core/experience/insights';
|
|
2
|
-
import { SchemaAttributes } from '@headless-adminapp/core/schema';
|
|
1
|
+
import { InsightConfig, InsightsState } from '@headless-adminapp/core/experience/insights';
|
|
2
|
+
import { InferredSchemaType, SchemaAttributes } from '@headless-adminapp/core/schema';
|
|
3
3
|
export declare function useInsightsState<S extends SchemaAttributes = SchemaAttributes>(): InsightsState<S>;
|
|
4
|
+
export declare function useInsightConfig<S extends SchemaAttributes = SchemaAttributes>(): InsightConfig<S>;
|
|
5
|
+
export declare function useInsightFilterValues<S extends SchemaAttributes = SchemaAttributes>(): InferredSchemaType<S>;
|
|
6
|
+
export declare function useRefreshEventListener(callback: () => any): void;
|
package/insights/hooks/index.js
CHANGED
|
@@ -1,8 +1,32 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.useInsightsState = useInsightsState;
|
|
4
|
+
exports.useInsightConfig = useInsightConfig;
|
|
5
|
+
exports.useInsightFilterValues = useInsightFilterValues;
|
|
6
|
+
exports.useRefreshEventListener = useRefreshEventListener;
|
|
7
|
+
const react_1 = require("react");
|
|
4
8
|
const mutable_1 = require("../../mutable");
|
|
5
9
|
const context_1 = require("../context");
|
|
6
10
|
function useInsightsState() {
|
|
7
11
|
return (0, mutable_1.useContextSelector)(context_1.InsightsContext, (state) => state);
|
|
8
12
|
}
|
|
13
|
+
function useInsightConfig() {
|
|
14
|
+
return (0, mutable_1.useContextSelector)(context_1.InsightsContext, (state) => state.config);
|
|
15
|
+
}
|
|
16
|
+
function useInsightFilterValues() {
|
|
17
|
+
return (0, mutable_1.useContextSelector)(context_1.InsightsContext, (state) => state.filterValues);
|
|
18
|
+
}
|
|
19
|
+
function useRefreshEventListener(callback) {
|
|
20
|
+
const eventManager = (0, mutable_1.useContextSelector)(context_1.InsightsContext, (state) => state.eventManager);
|
|
21
|
+
const callbackRef = (0, react_1.useRef)(callback);
|
|
22
|
+
callbackRef.current = callback;
|
|
23
|
+
(0, react_1.useEffect)(() => {
|
|
24
|
+
const handler = async () => {
|
|
25
|
+
await callbackRef.current();
|
|
26
|
+
};
|
|
27
|
+
eventManager.on('INSIGHT_REFRESH_TRIGGER', handler);
|
|
28
|
+
return () => {
|
|
29
|
+
eventManager.off('INSIGHT_REFRESH_TRIGGER', handler);
|
|
30
|
+
};
|
|
31
|
+
}, [eventManager]);
|
|
32
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@headless-adminapp/app",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.2",
|
|
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": "8d492b1b7266fbb8bba1124a8dc51311f54f8fcb"
|
|
40
40
|
}
|
|
@@ -131,7 +131,7 @@ class SchemaExperienceStore {
|
|
|
131
131
|
async getViewLookupV2(logicalName, viewId) {
|
|
132
132
|
const experience = await this.getExperience(logicalName);
|
|
133
133
|
if (!viewId) {
|
|
134
|
-
viewId = experience.
|
|
134
|
+
viewId = experience.defaultLookupId;
|
|
135
135
|
}
|
|
136
136
|
const view = experience.lookups.find((v) => v.id === viewId);
|
|
137
137
|
if (!view) {
|
|
@@ -221,7 +221,7 @@ class SchemaExperienceStore {
|
|
|
221
221
|
const schemaMetadatas = this.getSchemaMetadataList();
|
|
222
222
|
return schemaMetadatas.map((schemaMetadata) => ({
|
|
223
223
|
...schemaMetadata,
|
|
224
|
-
|
|
224
|
+
Icon: this.experiences[schemaMetadata.logicalName]?.Icon,
|
|
225
225
|
}));
|
|
226
226
|
}
|
|
227
227
|
}
|
|
@@ -20,6 +20,6 @@ export declare class RestDataService implements IDataService {
|
|
|
20
20
|
updateRecord<T>(logicalName: string, id: string, data: Partial<T>): Promise<CreateRecordResult<import("@headless-adminapp/core").Id>>;
|
|
21
21
|
deleteRecord(logicalName: string, id: string): Promise<void>;
|
|
22
22
|
retriveAggregate<Q extends Record<string, AggregateAttribute> = Record<string, AggregateAttribute>>(query: AggregateQuery<Q>): Promise<InferredAggregateQueryResult<Q>[]>;
|
|
23
|
-
customAction<T = unknown>(
|
|
23
|
+
customAction<T = unknown>(actionName: string, payload: unknown): Promise<T>;
|
|
24
24
|
}
|
|
25
25
|
export {};
|
|
@@ -94,8 +94,15 @@ class RestDataService {
|
|
|
94
94
|
});
|
|
95
95
|
return result;
|
|
96
96
|
}
|
|
97
|
-
async customAction(
|
|
98
|
-
|
|
97
|
+
async customAction(actionName, payload) {
|
|
98
|
+
const result = await this.execute({
|
|
99
|
+
type: 'customAction',
|
|
100
|
+
payload: {
|
|
101
|
+
actionName,
|
|
102
|
+
payload,
|
|
103
|
+
},
|
|
104
|
+
});
|
|
105
|
+
return result;
|
|
99
106
|
}
|
|
100
107
|
}
|
|
101
108
|
exports.RestDataService = RestDataService;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function useCustomActionQuery<T = unknown>(actionName: string, payload: unknown): import("@tanstack/react-query").UseQueryResult<T, Error>;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useCustomActionQuery = useCustomActionQuery;
|
|
4
|
+
const react_query_1 = require("@tanstack/react-query");
|
|
5
|
+
const useDataService_1 = require("./useDataService");
|
|
6
|
+
function useCustomActionQuery(actionName, payload) {
|
|
7
|
+
const dataService = (0, useDataService_1.useDataService)();
|
|
8
|
+
return (0, react_query_1.useQuery)({
|
|
9
|
+
queryKey: ['data', 'customAction', actionName, payload],
|
|
10
|
+
queryFn: async () => {
|
|
11
|
+
return dataService.customAction(actionName, payload);
|
|
12
|
+
},
|
|
13
|
+
});
|
|
14
|
+
}
|
|
@@ -4,17 +4,17 @@ import { Filter } from '@headless-adminapp/core/transport';
|
|
|
4
4
|
import { QueryKey } from '@tanstack/react-query';
|
|
5
5
|
interface UseRetriveRecordProps<S extends SchemaAttributes = SchemaAttributes> {
|
|
6
6
|
schema: Schema<S>;
|
|
7
|
-
search
|
|
8
|
-
filter
|
|
9
|
-
sorting
|
|
7
|
+
search?: string;
|
|
8
|
+
filter?: Filter | null;
|
|
9
|
+
sorting?: SortingState<S>;
|
|
10
10
|
columns: string[];
|
|
11
11
|
expand?: Partial<Record<string, string[]>>;
|
|
12
|
-
maxRecords
|
|
12
|
+
maxRecords?: number;
|
|
13
13
|
disabled?: boolean;
|
|
14
14
|
}
|
|
15
|
-
export declare function useRetrieveRecordsKey<S extends SchemaAttributes = SchemaAttributes>({ schema, search, filter, sorting, columns, expand, maxRecords, }: UseRetriveRecordProps<S>):
|
|
15
|
+
export declare function useRetrieveRecordsKey<S extends SchemaAttributes = SchemaAttributes>({ schema, search, filter, sorting, columns, expand, maxRecords, }: UseRetriveRecordProps<S>): QueryKey;
|
|
16
16
|
export declare function useClearDataExceptFirstPage(queryKey: QueryKey): void;
|
|
17
|
-
export declare function
|
|
17
|
+
export declare function useRetriveRecordsInternal<S extends SchemaAttributes = SchemaAttributes>(queryKey: QueryKey, { columns, expand, filter, maxRecords, schema, search, sorting, disabled, }: UseRetriveRecordProps<S>): {
|
|
18
18
|
data: {
|
|
19
19
|
logicalName: string;
|
|
20
20
|
count: number;
|
|
@@ -29,5 +29,24 @@ export declare function useRetriveRecords<S extends SchemaAttributes = SchemaAtt
|
|
|
29
29
|
data: import("@headless-adminapp/core/transport").RetriveRecordsResult<InferredSchemaType<S>>;
|
|
30
30
|
}, unknown>, Error>>;
|
|
31
31
|
isFetchingNextPage: boolean;
|
|
32
|
+
refetch: () => void;
|
|
33
|
+
};
|
|
34
|
+
export declare function useRetriveRecords<S extends SchemaAttributes = SchemaAttributes>({ columns, expand, filter, maxRecords, schema, search, sorting, disabled, }: UseRetriveRecordProps<S>): {
|
|
35
|
+
queryKey: QueryKey;
|
|
36
|
+
data: {
|
|
37
|
+
logicalName: string;
|
|
38
|
+
count: number;
|
|
39
|
+
records: import("@headless-adminapp/core/transport").Data<InferredSchemaType<S>>[];
|
|
40
|
+
} | null;
|
|
41
|
+
isFetching: boolean;
|
|
42
|
+
hasNextPage: boolean;
|
|
43
|
+
fetchNextPage: (options?: import("@tanstack/react-query").FetchNextPageOptions) => Promise<import("@tanstack/react-query").InfiniteQueryObserverResult<import("@tanstack/react-query").InfiniteData<{
|
|
44
|
+
params: {
|
|
45
|
+
pageIndex: number;
|
|
46
|
+
};
|
|
47
|
+
data: import("@headless-adminapp/core/transport").RetriveRecordsResult<InferredSchemaType<S>>;
|
|
48
|
+
}, unknown>, Error>>;
|
|
49
|
+
isFetchingNextPage: boolean;
|
|
50
|
+
refetch: () => void;
|
|
32
51
|
};
|
|
33
52
|
export {};
|
|
@@ -2,11 +2,13 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.useRetrieveRecordsKey = useRetrieveRecordsKey;
|
|
4
4
|
exports.useClearDataExceptFirstPage = useClearDataExceptFirstPage;
|
|
5
|
+
exports.useRetriveRecordsInternal = useRetriveRecordsInternal;
|
|
5
6
|
exports.useRetriveRecords = useRetriveRecords;
|
|
6
7
|
const transport_1 = require("@headless-adminapp/app/transport");
|
|
7
8
|
const react_query_1 = require("@tanstack/react-query");
|
|
8
9
|
const react_1 = require("react");
|
|
9
10
|
const ROWS_PER_PAGE = 100;
|
|
11
|
+
const MAX_RECORDS = 10000;
|
|
10
12
|
function useRetrieveRecordsKey({ schema, search, filter, sorting, columns, expand, maxRecords, }) {
|
|
11
13
|
const queryKey = (0, react_1.useMemo)(() => [
|
|
12
14
|
'data',
|
|
@@ -26,31 +28,36 @@ function useClearDataExceptFirstPage(queryKey) {
|
|
|
26
28
|
(0, react_1.useEffect)(() => {
|
|
27
29
|
return () => {
|
|
28
30
|
// Clear all pages except the first one when the component is unmounted
|
|
29
|
-
queryClient
|
|
30
|
-
if (!oldData) {
|
|
31
|
-
return oldData;
|
|
32
|
-
}
|
|
33
|
-
if (!oldData.pageParams.length || !oldData.pages.length) {
|
|
34
|
-
return oldData;
|
|
35
|
-
}
|
|
36
|
-
return {
|
|
37
|
-
pageParams: [oldData.pageParams[0]],
|
|
38
|
-
pages: [oldData.pages[0]],
|
|
39
|
-
};
|
|
40
|
-
});
|
|
31
|
+
clearDataExceptFirstPage(queryClient, queryKey);
|
|
41
32
|
};
|
|
42
33
|
}, [queryClient, queryKey]);
|
|
43
34
|
}
|
|
44
|
-
function
|
|
35
|
+
function clearDataExceptFirstPage(queryClient, queryKey) {
|
|
36
|
+
queryClient.setQueryData(queryKey, (oldData) => {
|
|
37
|
+
if (!oldData) {
|
|
38
|
+
return oldData;
|
|
39
|
+
}
|
|
40
|
+
if (!oldData.pageParams.length || !oldData.pages.length) {
|
|
41
|
+
return oldData;
|
|
42
|
+
}
|
|
43
|
+
return {
|
|
44
|
+
pageParams: [oldData.pageParams[0]],
|
|
45
|
+
pages: [oldData.pages[0]],
|
|
46
|
+
};
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
function useRetriveRecordsInternal(queryKey, { columns, expand, filter, maxRecords, schema, search, sorting, disabled, }) {
|
|
45
50
|
const dataService = (0, transport_1.useDataService)();
|
|
51
|
+
const queryClient = (0, react_query_1.useQueryClient)();
|
|
46
52
|
const { data, isFetching, hasNextPage, fetchNextPage, isFetchingNextPage } = (0, react_query_1.useInfiniteQuery)({
|
|
47
53
|
queryKey: queryKey,
|
|
48
54
|
queryFn: async (queryContext) => {
|
|
49
55
|
const params = queryContext.pageParam ?? {
|
|
50
56
|
pageIndex: 0,
|
|
51
57
|
};
|
|
58
|
+
const _maxRecords = maxRecords ?? MAX_RECORDS;
|
|
52
59
|
const skip = params.pageIndex * ROWS_PER_PAGE;
|
|
53
|
-
const limit = Math.min(ROWS_PER_PAGE, Math.max(0,
|
|
60
|
+
const limit = Math.min(ROWS_PER_PAGE, Math.max(0, _maxRecords - skip));
|
|
54
61
|
if (limit <= 0) {
|
|
55
62
|
return {
|
|
56
63
|
params: params,
|
|
@@ -100,11 +107,45 @@ function useRetriveRecords(queryKey, { columns, expand, filter, maxRecords, sche
|
|
|
100
107
|
records: data?.pages.map((x) => x.data.records).flat() ?? [],
|
|
101
108
|
};
|
|
102
109
|
}, [data]);
|
|
110
|
+
const refech = (0, react_1.useCallback)(() => {
|
|
111
|
+
clearDataExceptFirstPage(queryClient, queryKey);
|
|
112
|
+
queryClient
|
|
113
|
+
.resetQueries({
|
|
114
|
+
queryKey,
|
|
115
|
+
})
|
|
116
|
+
.catch(console.error);
|
|
117
|
+
}, []);
|
|
103
118
|
return {
|
|
104
119
|
data: finalData,
|
|
105
120
|
isFetching,
|
|
106
121
|
hasNextPage,
|
|
107
122
|
fetchNextPage,
|
|
108
123
|
isFetchingNextPage,
|
|
124
|
+
refetch: refech,
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
function useRetriveRecords({ columns, expand, filter, maxRecords, schema, search, sorting, disabled, }) {
|
|
128
|
+
const queryKey = useRetrieveRecordsKey({
|
|
129
|
+
columns,
|
|
130
|
+
expand,
|
|
131
|
+
filter,
|
|
132
|
+
maxRecords,
|
|
133
|
+
schema,
|
|
134
|
+
search,
|
|
135
|
+
sorting,
|
|
136
|
+
});
|
|
137
|
+
const query = useRetriveRecordsInternal(queryKey, {
|
|
138
|
+
columns,
|
|
139
|
+
expand,
|
|
140
|
+
filter,
|
|
141
|
+
maxRecords,
|
|
142
|
+
schema,
|
|
143
|
+
search,
|
|
144
|
+
sorting,
|
|
145
|
+
disabled,
|
|
146
|
+
});
|
|
147
|
+
return {
|
|
148
|
+
...query,
|
|
149
|
+
queryKey,
|
|
109
150
|
};
|
|
110
151
|
}
|
|
@@ -3,6 +3,7 @@ interface AttributeFormattedValueStringsSet {
|
|
|
3
3
|
yes: string;
|
|
4
4
|
no: string;
|
|
5
5
|
}
|
|
6
|
+
export declare function formatDuration(value: number | null): string;
|
|
6
7
|
export declare function getAttributeFormattedValue<A extends Attribute = Attribute>(attribute: Attribute, value: InferredAttributeType<A> | null | undefined, options?: {
|
|
7
8
|
maxCount?: number;
|
|
8
9
|
strings?: AttributeFormattedValueStringsSet;
|
|
@@ -3,6 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.formatDuration = formatDuration;
|
|
6
7
|
exports.getAttributeFormattedValue = getAttributeFormattedValue;
|
|
7
8
|
const dayjs_1 = __importDefault(require("dayjs"));
|
|
8
9
|
const timezone_1 = __importDefault(require("dayjs/plugin/timezone"));
|
|
@@ -104,11 +105,56 @@ function getAttributeMoneyFormattedValue(value, options) {
|
|
|
104
105
|
currencyDisplay,
|
|
105
106
|
}).format(value);
|
|
106
107
|
}
|
|
108
|
+
function getAttributeNumberFormattedValue(attribute, value, options) {
|
|
109
|
+
if (attribute.format === 'duration') {
|
|
110
|
+
return formatDuration(value);
|
|
111
|
+
}
|
|
112
|
+
if (attribute.format === 'time') {
|
|
113
|
+
return (0, dayjs_1.default)()
|
|
114
|
+
.startOf('day')
|
|
115
|
+
.add(value, 'minutes')
|
|
116
|
+
.format(options?.timeFormat ?? defaultTimeFormat);
|
|
117
|
+
}
|
|
118
|
+
return new Intl.NumberFormat(options?.locale).format(value);
|
|
119
|
+
}
|
|
120
|
+
function formatDuration(value) {
|
|
121
|
+
if (!value) {
|
|
122
|
+
return '';
|
|
123
|
+
}
|
|
124
|
+
// No decimal, if value is decimal, round to nearest whole number
|
|
125
|
+
// 1 - 1 minute
|
|
126
|
+
// 2-59 minutes -> 2-59 minutes
|
|
127
|
+
// 90 minutes -> 1.5 hours
|
|
128
|
+
// more than a day -> 1 day, 1.5 days, 2 days, etc.
|
|
129
|
+
// check if value has decimal
|
|
130
|
+
if (value % 1 !== 0) {
|
|
131
|
+
// round to nearest whole number
|
|
132
|
+
value = Math.round(value);
|
|
133
|
+
}
|
|
134
|
+
if (!value) {
|
|
135
|
+
return '';
|
|
136
|
+
}
|
|
137
|
+
if (value === 1) {
|
|
138
|
+
return '1 minute';
|
|
139
|
+
}
|
|
140
|
+
if (value < 60) {
|
|
141
|
+
return `${value} minutes`;
|
|
142
|
+
}
|
|
143
|
+
if (value === 60) {
|
|
144
|
+
return '1 hour';
|
|
145
|
+
}
|
|
146
|
+
if (value < 1440) {
|
|
147
|
+
return `${Number((value / 60).toFixed(2))} hours`;
|
|
148
|
+
}
|
|
149
|
+
if (value === 1440) {
|
|
150
|
+
return '1 day';
|
|
151
|
+
}
|
|
152
|
+
return `${Number((value / 1440).toFixed(2))} days`;
|
|
153
|
+
}
|
|
107
154
|
function getAttributeFormattedValue(attribute, value, options) {
|
|
108
155
|
if (value === null || value === undefined) {
|
|
109
156
|
return null;
|
|
110
157
|
}
|
|
111
|
-
const locale = options?.locale ?? defaultLocale;
|
|
112
158
|
const region = options?.region ?? 'US';
|
|
113
159
|
switch (attribute.type) {
|
|
114
160
|
case 'boolean':
|
|
@@ -128,7 +174,7 @@ function getAttributeFormattedValue(attribute, value, options) {
|
|
|
128
174
|
case 'money':
|
|
129
175
|
return getAttributeMoneyFormattedValue(value, options);
|
|
130
176
|
case 'number':
|
|
131
|
-
return
|
|
177
|
+
return getAttributeNumberFormattedValue(attribute, value, options);
|
|
132
178
|
case 'attachment':
|
|
133
179
|
return getAttributeAttachmentFormattedValue(value);
|
|
134
180
|
case 'string':
|