@headless-adminapp/fluent 1.4.5 → 1.4.6
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/App/AppStringContext.d.ts +1 -1
- package/App/AppStringContext.js +1 -1
- package/PageEntityForm/StandardControl.js +1 -1
- package/form/controls/LookupControl.d.ts +0 -5
- package/form/controls/LookupControl.js +8 -21
- package/form/controls/MultiSelectLookupControl.js +2 -2
- package/form/controls/RegardingControl.js +2 -2
- package/form/controls/useLookupData.d.ts +5 -4
- package/form/controls/useLookupData.js +78 -2
- package/package.json +2 -2
|
@@ -2,7 +2,7 @@ import { CalendarStrings } from '@fluentui/react-datepicker-compat';
|
|
|
2
2
|
import { OperatorStrings } from '@headless-adminapp/app/datagrid/column-filter';
|
|
3
3
|
export interface AppStringSet {
|
|
4
4
|
datePickerStrings: CalendarStrings;
|
|
5
|
-
|
|
5
|
+
lookupStrings: {
|
|
6
6
|
newRecord: string;
|
|
7
7
|
noRecordsFound: string;
|
|
8
8
|
};
|
package/App/AppStringContext.js
CHANGED
|
@@ -8,7 +8,7 @@ const react_1 = require("react");
|
|
|
8
8
|
exports.defaultAppStrings = {
|
|
9
9
|
datePickerStrings: react_datepicker_compat_1.defaultDatePickerStrings,
|
|
10
10
|
operatorStrings: column_filter_1.defaultOperatorStrings,
|
|
11
|
-
|
|
11
|
+
lookupStrings: {
|
|
12
12
|
newRecord: 'New Record',
|
|
13
13
|
noRecordsFound: 'No records found',
|
|
14
14
|
},
|
|
@@ -180,7 +180,7 @@ const StandardControl = (props) => {
|
|
|
180
180
|
}
|
|
181
181
|
case 'lookup': {
|
|
182
182
|
const Control = componentStore_1.componentStore.getComponent('Form.LookupControl') ?? LookupControl_1.LookupControl;
|
|
183
|
-
return ((0, jsx_runtime_1.jsx)(Control, { name: name, value: value, onChange: onChange, onBlur: onBlur, placeholder: placeholder, disabled: isDisabled, dataService: dataService, schema: schemaStore.getSchema(attribute.entity),
|
|
183
|
+
return ((0, jsx_runtime_1.jsx)(Control, { name: name, value: value, onChange: onChange, onBlur: onBlur, placeholder: placeholder, disabled: isDisabled, dataService: dataService, schema: schemaStore.getSchema(attribute.entity), allowNavigation: allowNavigation, allowNewRecord: allowNewRecord, skeleton: skeleton }));
|
|
184
184
|
}
|
|
185
185
|
case 'lookups': {
|
|
186
186
|
const Control = componentStore_1.componentStore.getComponent('Form.MultiSelectLookupControl') ?? MultiSelectLookupControl_1.MultiSelectLookupControl;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { Schema } from '@headless-adminapp/core/schema';
|
|
2
|
-
import { ISchemaExperienceStore } from '@headless-adminapp/core/store';
|
|
3
2
|
import { IDataService } from '@headless-adminapp/core/transport';
|
|
4
3
|
import { ControlProps } from './types';
|
|
5
4
|
export interface LookupOption {
|
|
@@ -14,12 +13,8 @@ export type DataLookup = {
|
|
|
14
13
|
avatar?: string;
|
|
15
14
|
};
|
|
16
15
|
export type LookupControlProps = ControlProps<DataLookup> & {
|
|
17
|
-
async?: boolean;
|
|
18
|
-
lookupKey?: string;
|
|
19
|
-
openRecord?: (id: string) => void;
|
|
20
16
|
dataService: IDataService;
|
|
21
17
|
schema: Schema;
|
|
22
|
-
experienceStore: ISchemaExperienceStore;
|
|
23
18
|
viewId?: string;
|
|
24
19
|
allowNavigation?: boolean;
|
|
25
20
|
allowNewRecord?: boolean;
|
|
@@ -5,6 +5,7 @@ const jsx_runtime_1 = require("react/jsx-runtime");
|
|
|
5
5
|
const react_components_1 = require("@fluentui/react-components");
|
|
6
6
|
const app_1 = require("@headless-adminapp/app/app");
|
|
7
7
|
const hooks_1 = require("@headless-adminapp/app/hooks");
|
|
8
|
+
const useRecentItemStore_1 = require("@headless-adminapp/app/metadata/hooks/useRecentItemStore");
|
|
8
9
|
const hooks_2 = require("@headless-adminapp/app/route/hooks");
|
|
9
10
|
const app_2 = require("@headless-adminapp/core/experience/app");
|
|
10
11
|
const icons_1 = require("@headless-adminapp/icons");
|
|
@@ -37,9 +38,10 @@ const LookupControlMd = ({ value, onChange, id, name, onBlur, onFocus, placehold
|
|
|
37
38
|
const [lookupEnabled, setLookupEnabled] = (0, react_1.useState)(false);
|
|
38
39
|
const [open, setOpen] = (0, react_1.useState)(false);
|
|
39
40
|
const [searchText, setSearchText] = (0, react_1.useState)('');
|
|
40
|
-
const {
|
|
41
|
+
const { lookupStrings } = (0, AppStringContext_1.useAppStrings)();
|
|
41
42
|
const routeResolver = (0, hooks_2.useRouteResolver)();
|
|
42
43
|
const router = (0, hooks_2.useRouter)();
|
|
44
|
+
const recentItemStore = (0, useRecentItemStore_1.useRecentItemStore)();
|
|
43
45
|
const path = (0, react_1.useMemo)(() => {
|
|
44
46
|
if (!value) {
|
|
45
47
|
return '';
|
|
@@ -67,24 +69,6 @@ const LookupControlMd = ({ value, onChange, id, name, onBlur, onFocus, placehold
|
|
|
67
69
|
}, [open]);
|
|
68
70
|
const [debouncedSearchText] = (0, hooks_1.useDebouncedValue)(searchText, 500);
|
|
69
71
|
const styles = useStyles();
|
|
70
|
-
// const useLookupData = useMemo(
|
|
71
|
-
// () =>
|
|
72
|
-
// createUseLookupDataHook({
|
|
73
|
-
// dataResolver: dataResolverRef.current,
|
|
74
|
-
// useLookupQuery: undefined,
|
|
75
|
-
// lookupKey,
|
|
76
|
-
// }),
|
|
77
|
-
// [lookupKey]
|
|
78
|
-
// );
|
|
79
|
-
// const {
|
|
80
|
-
// data,
|
|
81
|
-
// isLoading: loading,
|
|
82
|
-
// isFetching,
|
|
83
|
-
// } = useLookupData({
|
|
84
|
-
// limit: 10,
|
|
85
|
-
// search: async ? debouncedSearchText : '',
|
|
86
|
-
// enabled: lookupEnabled,
|
|
87
|
-
// });
|
|
88
72
|
const { isLoading: isViewLoading, view } = (0, useLookupData_1.useGetLookupView)(schema.logicalName, viewId);
|
|
89
73
|
const { data, isLoading } = (0, useLookupData_1.useLookupData)({
|
|
90
74
|
schema,
|
|
@@ -123,16 +107,19 @@ const LookupControlMd = ({ value, onChange, id, name, onBlur, onFocus, placehold
|
|
|
123
107
|
setSearchText(e.target.value);
|
|
124
108
|
}, onOptionSelect: (e, item) => {
|
|
125
109
|
const _item = data?.records.find((x) => String(x[schema.idAttribute]) === String(item.optionValue));
|
|
110
|
+
if (_item) {
|
|
111
|
+
recentItemStore.addItem((0, useLookupData_1.createLookupRecentKey)(schema.logicalName), _item[schema.idAttribute], _item[schema.idAttribute]);
|
|
112
|
+
}
|
|
126
113
|
handleChange(_item ?? null);
|
|
127
114
|
}, disableAutoFocus: true, onBlur: onBlur, onFocus: onFocus, id: id, autoFocus: autoFocus, children: [data?.records.map((item) => ((0, jsx_runtime_1.jsx)(react_components_1.Option, { value: item[schema.idAttribute], className: (0, react_components_1.mergeClasses)(styles.option), text: item[schema.primaryAttribute], children: view?.experience.card ? ((0, jsx_runtime_1.jsx)(RecordCard_1.RecordCard, { cardView: view.experience.card, record: item, schema: schema })) : item[schema.primaryAttribute] }, item[schema.idAttribute]))), !isLoading && !data?.records.length && ((0, jsx_runtime_1.jsx)("div", { style: {
|
|
128
115
|
paddingInline: react_components_1.tokens.spacingHorizontalL,
|
|
129
116
|
paddingBlock: react_components_1.tokens.spacingVerticalS,
|
|
130
|
-
}, children: (0, jsx_runtime_1.jsx)(react_components_1.Body1, { children:
|
|
117
|
+
}, children: (0, jsx_runtime_1.jsx)(react_components_1.Body1, { children: lookupStrings.noRecordsFound }) })), allowNewRecord && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(react_components_1.Divider, {}), (0, jsx_runtime_1.jsx)("div", { style: { marginTop: react_components_1.tokens.spacingVerticalXXS }, children: (0, jsx_runtime_1.jsx)(react_components_1.ToolbarButton, { style: { fontWeight: 'normal' }, icon: (0, jsx_runtime_1.jsx)(icons_1.Icons.Add, {}), onClick: () => {
|
|
131
118
|
router.push(routeResolver({
|
|
132
119
|
logicalName: schema.logicalName,
|
|
133
120
|
type: app_2.PageType.EntityForm,
|
|
134
121
|
}));
|
|
135
|
-
}, children:
|
|
122
|
+
}, children: lookupStrings.newRecord }) })] }))] }), !!value && ((0, jsx_runtime_1.jsx)("div", { style: {
|
|
136
123
|
position: 'absolute',
|
|
137
124
|
inset: 0,
|
|
138
125
|
alignItems: 'center',
|
|
@@ -35,7 +35,7 @@ const LookupControlMd = ({ value, onChange, id, name, onBlur, onFocus, placehold
|
|
|
35
35
|
const [lookupEnabled, setLookupEnabled] = (0, react_1.useState)(false);
|
|
36
36
|
const [open, setOpen] = (0, react_1.useState)(false);
|
|
37
37
|
const [searchText, setSearchText] = (0, react_1.useState)('');
|
|
38
|
-
const {
|
|
38
|
+
const { lookupStrings } = (0, AppStringContext_1.useAppStrings)();
|
|
39
39
|
(0, react_1.useEffect)(() => {
|
|
40
40
|
if (open)
|
|
41
41
|
setLookupEnabled(true);
|
|
@@ -145,7 +145,7 @@ const LookupControlMd = ({ value, onChange, id, name, onBlur, onFocus, placehold
|
|
|
145
145
|
}, disableAutoFocus: true, onBlur: onBlur, onFocus: onFocus, id: id, autoFocus: autoFocus, children: [data?.records.map((item) => ((0, jsx_runtime_1.jsx)(react_components_1.Option, { value: item[schema.idAttribute], className: (0, react_components_1.mergeClasses)(styles.option), text: item[schema.primaryAttribute], children: (0, jsx_runtime_1.jsx)(RecordCard_1.RecordCard, { cardView: view?.experience.card, record: item, schema: schema }) }, item[schema.idAttribute]))), !isLoading && !data?.records.length && ((0, jsx_runtime_1.jsx)("div", { style: {
|
|
146
146
|
paddingInline: react_components_1.tokens.spacingHorizontalL,
|
|
147
147
|
paddingBlock: react_components_1.tokens.spacingVerticalS,
|
|
148
|
-
}, children: (0, jsx_runtime_1.jsx)(react_components_1.Body1, { children:
|
|
148
|
+
}, children: (0, jsx_runtime_1.jsx)(react_components_1.Body1, { children: lookupStrings.noRecordsFound }) })), allowNewRecord && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(react_components_1.Divider, {}), (0, jsx_runtime_1.jsx)("div", { style: { marginTop: react_components_1.tokens.spacingVerticalXXS }, children: (0, jsx_runtime_1.jsx)(react_components_1.ToolbarButton, { style: { fontWeight: 'normal' }, icon: (0, jsx_runtime_1.jsx)(icons_1.Icons.Add, {}), children: lookupStrings.newRecord }) })] }))] }), (0, jsx_runtime_1.jsx)("div", { ref: tagGroupContainerRef, style: {
|
|
149
149
|
position: 'absolute',
|
|
150
150
|
top: 4,
|
|
151
151
|
left: 0,
|
|
@@ -39,7 +39,7 @@ const LookupControlMd = ({ value, onChange, id, name, onBlur, onFocus, placehold
|
|
|
39
39
|
const [lookupEnabled, setLookupEnabled] = (0, react_1.useState)(false);
|
|
40
40
|
const [open, setOpen] = (0, react_1.useState)(false);
|
|
41
41
|
const [searchText, setSearchText] = (0, react_1.useState)('');
|
|
42
|
-
const {
|
|
42
|
+
const { lookupStrings } = (0, AppStringContext_1.useAppStrings)();
|
|
43
43
|
const routeResolver = (0, hooks_2.useRouteResolver)();
|
|
44
44
|
const router = (0, hooks_2.useRouter)();
|
|
45
45
|
const path = (0, react_1.useMemo)(() => {
|
|
@@ -154,7 +154,7 @@ const LookupControlMd = ({ value, onChange, id, name, onBlur, onFocus, placehold
|
|
|
154
154
|
result.every((item) => !item.data?.records.length) && ((0, jsx_runtime_1.jsx)("div", { style: {
|
|
155
155
|
paddingInline: react_components_1.tokens.spacingHorizontalL,
|
|
156
156
|
paddingBlock: react_components_1.tokens.spacingVerticalS,
|
|
157
|
-
}, children: (0, jsx_runtime_1.jsx)(react_components_1.Body1, { children:
|
|
157
|
+
}, children: (0, jsx_runtime_1.jsx)(react_components_1.Body1, { children: lookupStrings.noRecordsFound }) }))] }), !!value && ((0, jsx_runtime_1.jsx)("div", { style: {
|
|
158
158
|
position: 'absolute',
|
|
159
159
|
inset: 0,
|
|
160
160
|
alignItems: 'center',
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import { ViewExperience } from '@headless-adminapp/core/experience/view';
|
|
2
2
|
import { InferredSchemaType, Schema, SchemaAttributes } from '@headless-adminapp/core/schema';
|
|
3
3
|
import { IDataService, RetriveRecordsResult } from '@headless-adminapp/core/transport';
|
|
4
|
-
interface UseLookupDataOptions {
|
|
4
|
+
interface UseLookupDataOptions<S extends SchemaAttributes = SchemaAttributes> {
|
|
5
5
|
dataService: IDataService;
|
|
6
6
|
searchText?: string;
|
|
7
|
-
schema: Schema
|
|
7
|
+
schema: Schema<S>;
|
|
8
8
|
view: ViewExperience | null | undefined;
|
|
9
9
|
enabled?: boolean;
|
|
10
10
|
}
|
|
11
|
-
export declare function useLookupData<S extends SchemaAttributes = SchemaAttributes>({ schema, view, searchText, dataService, enabled, }: UseLookupDataOptions): {
|
|
12
|
-
data: RetriveRecordsResult<InferredSchemaType<S
|
|
11
|
+
export declare function useLookupData<S extends SchemaAttributes = SchemaAttributes>({ schema, view, searchText, dataService, enabled, }: UseLookupDataOptions<S>): {
|
|
12
|
+
data: RetriveRecordsResult<InferredSchemaType<S>>;
|
|
13
13
|
isLoading: boolean;
|
|
14
14
|
};
|
|
15
15
|
interface UseLookupsDataOptions {
|
|
@@ -26,4 +26,5 @@ export declare function useGetLookupView(logicalName: string, viewId?: string):
|
|
|
26
26
|
isLoading: boolean;
|
|
27
27
|
view: import("@headless-adminapp/core/experience/view").View<SchemaAttributes> | undefined;
|
|
28
28
|
};
|
|
29
|
+
export declare function createLookupRecentKey(logicalName: string): string;
|
|
29
30
|
export {};
|
|
@@ -3,8 +3,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.useLookupData = useLookupData;
|
|
4
4
|
exports.useLookupDatas = useLookupDatas;
|
|
5
5
|
exports.useGetLookupView = useGetLookupView;
|
|
6
|
+
exports.createLookupRecentKey = createLookupRecentKey;
|
|
7
|
+
const utils_1 = require("@headless-adminapp/app/datagrid/DataGridProvider/utils");
|
|
6
8
|
const hooks_1 = require("@headless-adminapp/app/hooks");
|
|
7
9
|
const hooks_2 = require("@headless-adminapp/app/metadata/hooks");
|
|
10
|
+
const useRecentItemStore_1 = require("@headless-adminapp/app/metadata/hooks/useRecentItemStore");
|
|
11
|
+
const useRetriveRecords_1 = require("@headless-adminapp/app/transport/hooks/useRetriveRecords");
|
|
8
12
|
const react_query_1 = require("@tanstack/react-query");
|
|
9
13
|
const react_1 = require("react");
|
|
10
14
|
function extractColumns(schema, view) {
|
|
@@ -44,6 +48,7 @@ function getKey({ schema, view, columns, expand, search, }) {
|
|
|
44
48
|
}
|
|
45
49
|
function useLookupData({ schema, view, searchText, dataService, enabled, }) {
|
|
46
50
|
const [search] = (0, hooks_1.useDebouncedValue)(searchText, 500);
|
|
51
|
+
const recentIds = useLookupRecentIds(createLookupRecentKey(schema.logicalName));
|
|
47
52
|
const columns = (0, react_1.useMemo)(() => {
|
|
48
53
|
return extractColumns(schema, view);
|
|
49
54
|
}, [schema, view]);
|
|
@@ -73,9 +78,63 @@ function useLookupData({ schema, view, searchText, dataService, enabled, }) {
|
|
|
73
78
|
placeholderData: react_query_1.keepPreviousData,
|
|
74
79
|
enabled: enabled ?? false,
|
|
75
80
|
});
|
|
81
|
+
const recentQueryFilter = (0, react_1.useMemo)(() => {
|
|
82
|
+
return (0, utils_1.mergeFilters)(view?.filter, {
|
|
83
|
+
type: 'and',
|
|
84
|
+
conditions: [
|
|
85
|
+
{
|
|
86
|
+
field: schema.idAttribute,
|
|
87
|
+
operator: 'in',
|
|
88
|
+
value: recentIds,
|
|
89
|
+
},
|
|
90
|
+
],
|
|
91
|
+
});
|
|
92
|
+
}, [view?.filter, schema.idAttribute, recentIds]);
|
|
93
|
+
const { data: recentData, isFetching: isRecentFetching } = (0, useRetriveRecords_1.useRetriveRecords)({
|
|
94
|
+
columns,
|
|
95
|
+
expand,
|
|
96
|
+
schema,
|
|
97
|
+
search: '',
|
|
98
|
+
filter: recentQueryFilter,
|
|
99
|
+
disabled: !enabled || !recentIds.length,
|
|
100
|
+
sorting: view?.defaultSorting,
|
|
101
|
+
maxRecords: 5,
|
|
102
|
+
});
|
|
103
|
+
const mergedData = (0, react_1.useMemo)(() => {
|
|
104
|
+
const ids = new Set();
|
|
105
|
+
const items = [];
|
|
106
|
+
const idAttribute = schema.idAttribute;
|
|
107
|
+
if (recentData?.records) {
|
|
108
|
+
for (const id of recentIds) {
|
|
109
|
+
if (ids.has(id)) {
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
const item = recentData.records.find((x) => x[idAttribute] === id);
|
|
113
|
+
if (item) {
|
|
114
|
+
items.push(item);
|
|
115
|
+
ids.add(item[idAttribute]);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
if (data?.records) {
|
|
120
|
+
for (const item of data.records) {
|
|
121
|
+
if (ids.has(item[idAttribute])) {
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
ids.add(item[idAttribute]);
|
|
125
|
+
items.push(item);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
items.length = Math.min(items.length, 5);
|
|
129
|
+
return {
|
|
130
|
+
logicalName: schema.logicalName,
|
|
131
|
+
count: items.length,
|
|
132
|
+
records: items,
|
|
133
|
+
};
|
|
134
|
+
}, [data, recentData, recentIds, schema.idAttribute, schema.logicalName]);
|
|
76
135
|
return {
|
|
77
|
-
data,
|
|
78
|
-
isLoading: isFetching,
|
|
136
|
+
data: mergedData,
|
|
137
|
+
isLoading: isFetching || isRecentFetching,
|
|
79
138
|
};
|
|
80
139
|
}
|
|
81
140
|
function useLookupDatas({ dataService, searchText, enabled, items, }) {
|
|
@@ -131,3 +190,20 @@ function useGetLookupView(logicalName, viewId) {
|
|
|
131
190
|
view: data,
|
|
132
191
|
};
|
|
133
192
|
}
|
|
193
|
+
function useLookupRecentIds(cacheKey) {
|
|
194
|
+
const store = (0, useRecentItemStore_1.useRecentItemStore)();
|
|
195
|
+
const [items, setItems] = (0, react_1.useState)(store.getItems(cacheKey, 5).map((x) => x.value));
|
|
196
|
+
(0, react_1.useEffect)(() => {
|
|
197
|
+
const listener = (newItems) => {
|
|
198
|
+
setItems(newItems.map((x) => x.value));
|
|
199
|
+
};
|
|
200
|
+
store.addListener(cacheKey, listener);
|
|
201
|
+
return () => {
|
|
202
|
+
store.removeListener(cacheKey, listener);
|
|
203
|
+
};
|
|
204
|
+
}, [store, cacheKey]);
|
|
205
|
+
return items;
|
|
206
|
+
}
|
|
207
|
+
function createLookupRecentKey(logicalName) {
|
|
208
|
+
return `lookup-${logicalName}`;
|
|
209
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@headless-adminapp/fluent",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.6",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -52,5 +52,5 @@
|
|
|
52
52
|
"uuid": "11.0.3",
|
|
53
53
|
"yup": "^1.4.0"
|
|
54
54
|
},
|
|
55
|
-
"gitHead": "
|
|
55
|
+
"gitHead": "89d91fe63da3aae42fc34482cc90c1e12963810b"
|
|
56
56
|
}
|