@headless-adminapp/fluent 1.4.4 → 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.
@@ -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
- loockupStrings: {
5
+ lookupStrings: {
6
6
  newRecord: string;
7
7
  noRecordsFound: string;
8
8
  };
@@ -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
- loockupStrings: {
11
+ lookupStrings: {
12
12
  newRecord: 'New Record',
13
13
  noRecordsFound: 'No records found',
14
14
  },
@@ -139,7 +139,18 @@ function createCurrencyAxisFormatter(locale) {
139
139
  if (!info) {
140
140
  return '';
141
141
  }
142
- return (0, exports.formatCurrency)(locale, info.value, 0) + info.symbol;
142
+ let maxDigit = 0;
143
+ if (info.symbol) {
144
+ if (Math.abs(info.value) < 10) {
145
+ maxDigit = 2;
146
+ }
147
+ else if (Math.abs(info.value) < 100) {
148
+ maxDigit = 1;
149
+ }
150
+ }
151
+ return ((0, exports.formatCurrency)(locale, info.value, {
152
+ maxDigit,
153
+ }) + info.symbol);
143
154
  };
144
155
  }
145
156
  function createCategoryAxisFormatter(options) {
@@ -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), experienceStore: experienceStore, allowNavigation: allowNavigation, allowNewRecord: allowNewRecord, skeleton: skeleton }));
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 { loockupStrings } = (0, AppStringContext_1.useAppStrings)();
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: loockupStrings.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: () => {
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: loockupStrings.newRecord }) })] }))] }), !!value && ((0, jsx_runtime_1.jsx)("div", { style: {
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 { loockupStrings } = (0, AppStringContext_1.useAppStrings)();
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: loockupStrings.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: loockupStrings.newRecord }) })] }))] }), (0, jsx_runtime_1.jsx)("div", { ref: tagGroupContainerRef, style: {
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 { loockupStrings } = (0, AppStringContext_1.useAppStrings)();
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: loockupStrings.noRecordsFound }) }))] }), !!value && ((0, jsx_runtime_1.jsx)("div", { style: {
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>> | undefined;
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.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": "ca80572e64d16eafd78c1e511c0f15b563af51e5"
55
+ "gitHead": "89d91fe63da3aae42fc34482cc90c1e12963810b"
56
56
  }