@fctc/widget-logic 5.3.7-beta.15 → 5.3.7-beta.16

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/dist/index.js DELETED
@@ -1,3009 +0,0 @@
1
- "use strict";
2
- var __create = Object.create;
3
- var __defProp = Object.defineProperty;
4
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
- var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
- var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __export = (target, all) => {
9
- for (var name in all)
10
- __defProp(target, name, { get: all[name], enumerable: true });
11
- };
12
- var __copyProps = (to, from, except, desc) => {
13
- if (from && typeof from === "object" || typeof from === "function") {
14
- for (let key of __getOwnPropNames(from))
15
- if (!__hasOwnProp.call(to, key) && key !== except)
16
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
- }
18
- return to;
19
- };
20
- var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
21
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
22
- // If the importer is in node compatibility mode or this is not an ESM
23
- // file that has been converted to a CommonJS file using a Babel-
24
- // compatible transform (i.e. "__esModule" has not been set), then set
25
- // "default" to the CommonJS "module.exports" for node compatibility.
26
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
27
- mod
28
- ));
29
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
30
-
31
- // src/index.ts
32
- var index_exports = {};
33
- __export(index_exports, {
34
- AppProvider: () => AppProvider,
35
- STORAGES: () => STORAGES,
36
- binaryFieldController: () => binaryFieldController,
37
- colorFieldController: () => colorFieldController,
38
- copyLinkButtonController: () => copyLinkButtonController,
39
- countSum: () => countSum,
40
- downLoadBinaryController: () => downLoadBinaryController,
41
- downloadFileController: () => downloadFileController,
42
- durationController: () => durationController,
43
- guessTypeFromUrl: () => guessTypeFromUrl,
44
- isObjectEmpty: () => isObjectEmpty,
45
- languages: () => languages,
46
- many2manyBinaryController: () => many2manyBinaryController,
47
- many2manyFieldController: () => many2manyFieldController,
48
- many2manyTagsController: () => many2manyTagsController,
49
- many2oneButtonController: () => many2oneButtonController,
50
- many2oneFieldController: () => many2oneFieldController,
51
- mergeButtons: () => mergeButtons,
52
- priorityFieldController: () => priorityFieldController,
53
- providerEinvoiceFieldController: () => providerEinvoiceFieldController,
54
- searchController: () => searchController,
55
- setStorageItemAsync: () => setStorageItemAsync,
56
- statusDropdownController: () => statusDropdownController,
57
- tableController: () => tableController,
58
- tableGroupController: () => tableGroupController,
59
- tableHeadController: () => tableHeadController,
60
- useAddEntity: () => import_hooks2.useAddEntity,
61
- useAppProvider: () => useAppProvider,
62
- useButton: () => import_hooks2.useButton,
63
- useCallAction: () => useCallAction,
64
- useChangeOrderPreparationState: () => import_hooks2.useChangeOrderPreparationState,
65
- useChangeStatus: () => import_hooks2.useChangeStatus,
66
- useCheckPayment: () => import_hooks2.useCheckPayment,
67
- useCompany: () => useCompany,
68
- useConfig: () => useConfig,
69
- useCreateEntity: () => import_hooks2.useCreateEntity,
70
- useCreatePosConfig: () => import_hooks2.useCreatePosConfig,
71
- useCreateSession: () => import_hooks2.useCreateSession,
72
- useDebounce: () => useDebounce,
73
- useDelete: () => import_hooks2.useDelete,
74
- useDeleteComment: () => import_hooks2.useDeleteComment,
75
- useDeleteEntity: () => import_hooks2.useDeleteEntity,
76
- useDetail: () => useDetail,
77
- useDuplicateRecord: () => import_hooks2.useDuplicateRecord,
78
- useExecuteImport: () => import_hooks2.useExecuteImport,
79
- useExportExcel: () => import_hooks2.useExportExcel,
80
- useForgotPassword: () => import_hooks2.useForgotPassword,
81
- useForgotPasswordSSO: () => import_hooks2.useForgotPasswordSSO,
82
- useGenSerialNumber: () => import_hooks2.useGenSerialNumber,
83
- useGeneratePaymentQrInfo: () => import_hooks2.useGeneratePaymentQrInfo,
84
- useGet2FAMethods: () => import_hooks2.useGet2FAMethods,
85
- useGetASession: () => import_hooks2.useGetASession,
86
- useGetAccessByCode: () => import_hooks2.useGetAccessByCode,
87
- useGetAction: () => useGetAction,
88
- useGetActionDetail: () => import_hooks2.useGetActionDetail,
89
- useGetAll: () => import_hooks2.useGetAll,
90
- useGetCalendar: () => import_hooks2.useGetCalendar,
91
- useGetComment: () => import_hooks2.useGetComment,
92
- useGetCompanyInfo: () => import_hooks2.useGetCompanyInfo,
93
- useGetConversionRate: () => import_hooks2.useGetConversionRate,
94
- useGetCurrency: () => import_hooks2.useGetCurrency,
95
- useGetCurrentCompany: () => import_hooks2.useGetCurrentCompany,
96
- useGetDetail: () => import_hooks2.useGetDetail,
97
- useGetExternalTabs: () => import_hooks2.useGetExternalTabs,
98
- useGetFieldExport: () => import_hooks2.useGetFieldExport,
99
- useGetFieldOnChange: () => import_hooks2.useGetFieldOnChange,
100
- useGetFileExcel: () => import_hooks2.useGetFileExcel,
101
- useGetFormView: () => import_hooks2.useGetFormView,
102
- useGetGroups: () => import_hooks2.useGetGroups,
103
- useGetList: () => import_hooks2.useGetList,
104
- useGetListCompany: () => import_hooks2.useGetListCompany,
105
- useGetListData: () => import_hooks2.useGetListData,
106
- useGetListMyBankAccount: () => import_hooks2.useGetListMyBankAccount,
107
- useGetMenu: () => import_hooks2.useGetMenu,
108
- useGetOrderLine: () => import_hooks2.useGetOrderLine,
109
- useGetPinCode: () => import_hooks2.useGetPinCode,
110
- useGetPrintReport: () => import_hooks2.useGetPrintReport,
111
- useGetProGressBar: () => import_hooks2.useGetProGressBar,
112
- useGetProfile: () => import_hooks2.useGetProfile,
113
- useGetProvider: () => import_hooks2.useGetProvider,
114
- useGetResequence: () => import_hooks2.useGetResequence,
115
- useGetRowIds: () => useGetRowIds,
116
- useGetSelection: () => import_hooks2.useGetSelection,
117
- useGetSpecification: () => useGetSpecification,
118
- useGetUser: () => import_hooks2.useGetUser,
119
- useGetView: () => import_hooks2.useGetView,
120
- useGrantAccess: () => import_hooks2.useGrantAccess,
121
- useIsValidToken: () => import_hooks2.useIsValidToken,
122
- useListData: () => useListData,
123
- useLoadAction: () => import_hooks2.useLoadAction,
124
- useLoadMessage: () => import_hooks2.useLoadMessage,
125
- useLoginCredential: () => import_hooks2.useLoginCredential,
126
- useLoginSocial: () => import_hooks2.useLoginSocial,
127
- useLogout: () => import_hooks2.useLogout,
128
- useMenu: () => useMenu,
129
- useModel: () => import_hooks2.useModel,
130
- useOdooDataTransform: () => import_hooks2.useOdooDataTransform,
131
- useOnChangeForm: () => import_hooks2.useOnChangeForm,
132
- useParsePreview: () => import_hooks2.useParsePreview,
133
- usePrint: () => import_hooks2.usePrint,
134
- useProfile: () => useProfile,
135
- useReadGroup: () => import_hooks2.useReadGroup,
136
- useRemoveRow: () => import_hooks2.useRemoveRow,
137
- useRemoveTotpSetup: () => import_hooks2.useRemoveTotpSetup,
138
- useRequestSetupTotp: () => import_hooks2.useRequestSetupTotp,
139
- useResetPassword: () => import_hooks2.useResetPassword,
140
- useResetPasswordSSO: () => import_hooks2.useResetPasswordSSO,
141
- useRunAction: () => import_hooks2.useRunAction,
142
- useSave: () => import_hooks2.useSave,
143
- useSendComment: () => import_hooks2.useSendComment,
144
- useSettingsWebRead2fa: () => import_hooks2.useSettingsWebRead2fa,
145
- useSignInSSO: () => import_hooks2.useSignInSSO,
146
- useStorageState: () => useStorageState,
147
- useSwitchLocale: () => import_hooks2.useSwitchLocale,
148
- useUpdatePassword: () => import_hooks2.useUpdatePassword,
149
- useUploadFile: () => import_hooks2.useUploadFile,
150
- useUploadFileExcel: () => import_hooks2.useUploadFileExcel,
151
- useUploadIdFile: () => import_hooks2.useUploadIdFile,
152
- useUploadImage: () => import_hooks2.useUploadImage,
153
- useUser: () => useUser,
154
- useValidateActionToken: () => import_hooks2.useValidateActionToken,
155
- useVerify2FA: () => import_hooks2.useVerify2FA,
156
- useVerifyTotp: () => import_hooks2.useVerifyTotp,
157
- useViewV2: () => useViewV2,
158
- validateAndParseDate: () => validateAndParseDate
159
- });
160
- module.exports = __toCommonJS(index_exports);
161
-
162
- // src/hooks.ts
163
- var import_hooks2 = require("@fctc/interface-logic/hooks");
164
-
165
- // src/hooks/core/use-app-provider.tsx
166
- var import_react8 = require("react");
167
-
168
- // src/hooks/core/use-menu.ts
169
- var import_react3 = require("react");
170
-
171
- // src/hooks/core/use-call-action.ts
172
- var import_react = require("react");
173
-
174
- // src/provider.ts
175
- var provider_exports = {};
176
- __reExport(provider_exports, require("@fctc/interface-logic/provider"));
177
-
178
- // src/hooks/core/use-call-action.ts
179
- var useCallAction = () => {
180
- const { env } = (0, provider_exports.useEnv)();
181
- const { useLoadAction: useLoadAction2, useRunAction: useRunAction2 } = (0, provider_exports.useService)();
182
- const queryLoadAction = useLoadAction2();
183
- const queryRunAction = useRunAction2();
184
- const [actionData, setActionData] = (0, import_react.useState)(
185
- void 0
186
- );
187
- const callAction = (0, import_react.useCallback)(
188
- async ({
189
- aid,
190
- service,
191
- xNode,
192
- context
193
- }) => {
194
- try {
195
- const menuContext = {
196
- ...env?.context,
197
- ...context
198
- };
199
- const loadRes = await queryLoadAction.mutateAsync({
200
- idAction: aid,
201
- context: menuContext,
202
- service,
203
- xNode
204
- });
205
- if (loadRes?.result?.type === "ir.actions.server") {
206
- const runRes = await queryRunAction.mutateAsync({
207
- idAction: aid,
208
- context: menuContext,
209
- service,
210
- xNode
211
- });
212
- setActionData(runRes?.result);
213
- return runRes?.result;
214
- } else {
215
- setActionData(loadRes?.result);
216
- return loadRes?.result;
217
- }
218
- } catch (err) {
219
- console.error("callAction error:", err);
220
- return void 0;
221
- }
222
- },
223
- [env?.context?.lang]
224
- );
225
- return [actionData, callAction];
226
- };
227
-
228
- // src/utils.ts
229
- var utils_exports = {};
230
- __export(utils_exports, {
231
- STORAGES: () => STORAGES,
232
- countSum: () => countSum,
233
- guessTypeFromUrl: () => guessTypeFromUrl,
234
- isObjectEmpty: () => isObjectEmpty,
235
- languages: () => languages,
236
- mergeButtons: () => mergeButtons,
237
- setStorageItemAsync: () => setStorageItemAsync,
238
- useStorageState: () => useStorageState,
239
- validateAndParseDate: () => validateAndParseDate
240
- });
241
-
242
- // src/utils/constants.ts
243
- var languages = [
244
- { id: "vi_VN", name: "VIE" },
245
- { id: "en_US", name: "ENG" }
246
- ];
247
- var isBlobUrl = (url) => url.startsWith("blob:");
248
-
249
- // src/utils/function.ts
250
- var import_react2 = require("react");
251
- var countSum = (data, field) => {
252
- if (!data || !field) return 0;
253
- return data.reduce(
254
- (total, item) => total + (item?.[`${field}_count`] || 0),
255
- 0
256
- );
257
- };
258
- var isObjectEmpty = (obj) => {
259
- return Object.keys(obj).length === 0;
260
- };
261
- function mergeButtons(fields) {
262
- const buttons = fields?.filter((f) => f.type_co === "button");
263
- const others = fields?.filter((f) => f.type_co !== "button");
264
- if (buttons?.length) {
265
- others.push({
266
- type_co: "buttons",
267
- buttons
268
- });
269
- }
270
- return others;
271
- }
272
- var STORAGES = {
273
- TOKEN: "accessToken",
274
- USER_INFO: "USER_INFO"
275
- };
276
- function useAsyncState(initialValue = [true, null]) {
277
- return (0, import_react2.useReducer)(
278
- (_state, action = null) => [false, action],
279
- initialValue
280
- );
281
- }
282
- async function setStorageItemAsync(key, value) {
283
- try {
284
- if (value === null) {
285
- localStorage.removeItem(key);
286
- } else {
287
- localStorage.setItem(key, value);
288
- }
289
- } catch (e) {
290
- console.error("Local storage is unavailable:", e);
291
- }
292
- }
293
- function useStorageState(key) {
294
- const [state, setState] = useAsyncState();
295
- (0, import_react2.useEffect)(() => {
296
- try {
297
- const storedValue = localStorage.getItem(key);
298
- setState(storedValue);
299
- } catch (e) {
300
- console.error("Local storage is unavailable:", e);
301
- }
302
- }, [key]);
303
- const setValue = (0, import_react2.useCallback)(
304
- (value) => {
305
- setState(value);
306
- setStorageItemAsync(key, value);
307
- },
308
- [key]
309
- );
310
- return [state, setValue];
311
- }
312
- var guessTypeFromUrl = (url) => {
313
- const ext = url.split(".").pop()?.toLowerCase();
314
- if (!ext) return null;
315
- const map = {
316
- jpg: "image/jpeg",
317
- jpeg: "image/jpeg",
318
- png: "image/png",
319
- webp: "image/webp",
320
- gif: "image/gif",
321
- svg: "image/svg+xml",
322
- bmp: "image/bmp",
323
- tiff: "image/tiff",
324
- pdf: "application/pdf",
325
- zip: "application/zip",
326
- rar: "application/x-rar-compressed",
327
- xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
328
- xls: "application/vnd.ms-excel",
329
- mp4: "video/mp4",
330
- mov: "video/quicktime"
331
- };
332
- return map[ext] || null;
333
- };
334
-
335
- // src/utils/format-date.ts
336
- var import_moment = __toESM(require("moment"));
337
- var validateAndParseDate = (input, isDateTime = false) => {
338
- if (!input || typeof input !== "string") return null;
339
- const cleanInput = input.replace(/[^0-9-\/:\s]/g, "");
340
- const dateFormat = "YYYY-MM-DD";
341
- const dateTimeFormat = "YYYY-MM-DD HH:mm:ss";
342
- const currentDay = (0, import_moment.default)().format("DD");
343
- const currentMonth = (0, import_moment.default)().format("MM");
344
- const currentYear = (0, import_moment.default)().format("YYYY");
345
- const defaultTime = "00:00:00";
346
- const maxYear = parseInt(currentYear) + 10;
347
- const isValidDate = (day, month, year) => {
348
- const date = (0, import_moment.default)(`${day}-${month}-${year}`, "DD-MM-YYYY", true);
349
- return date.isValid();
350
- };
351
- const isValidTime = (hour, minute = "00", second = "00") => {
352
- const h = parseInt(hour, 10);
353
- const m = parseInt(minute, 10);
354
- const s = parseInt(second, 10);
355
- return h >= 0 && h <= 23 && m >= 0 && m <= 59 && s >= 0 && s <= 59;
356
- };
357
- const formatOutput = (day, month, year, time = defaultTime) => {
358
- let result = (0, import_moment.default)(
359
- `${day}-${month}-${year} ${time}`,
360
- "DD-MM-YYYY HH:mm:ss"
361
- );
362
- if (!result.isValid()) return null;
363
- if (isDateTime) {
364
- result = result.subtract(7, "hours");
365
- return result.format(dateTimeFormat);
366
- }
367
- return result.format(dateFormat);
368
- };
369
- if (isDateTime && input.match(
370
- /^\d{1,2}[\/-]\d{1,2}[\/-]\d{2,4}\s+\d{1,2}(:\d{1,2}(:\d{1,2})?)?$/
371
- )) {
372
- const [datePart, timePart] = input.split(/\s+/);
373
- const dateParts = datePart.split(/[\/-]/);
374
- const timeParts = timePart.split(":");
375
- const day = dateParts[0].padStart(2, "0");
376
- const month = dateParts[1].padStart(2, "0");
377
- const year = dateParts[2].length <= 2 ? `20${dateParts[2].padStart(2, "0")}` : dateParts[2].padStart(4, "0");
378
- const hour = timeParts[0].padStart(2, "0");
379
- const minute = timeParts[1] ? timeParts[1].padStart(2, "0") : "00";
380
- const second = timeParts[2] ? timeParts[2].padStart(2, "0") : "00";
381
- if (isValidDate(day, month, year) && isValidTime(hour, minute, second)) {
382
- let result = (0, import_moment.default)(
383
- `${day}-${month}-${year} ${hour}:${minute}:${second}`,
384
- "DD-MM-YYYY HH:mm:ss"
385
- );
386
- if (!result.isValid()) return null;
387
- result = result.subtract(7, "hours");
388
- return result.format(dateTimeFormat);
389
- }
390
- return null;
391
- }
392
- if (cleanInput.match(/^\d{4}-\d{2}-\d{2}$/)) {
393
- const [year, month, day] = cleanInput.split("-");
394
- if (isValidDate(day, month, year)) {
395
- return formatOutput(day, month, year);
396
- }
397
- return null;
398
- }
399
- if (cleanInput.match(/^\d{1,2}\/\d{1,2}\/\d{2,4}$/)) {
400
- const [day, month, year] = cleanInput.split("/");
401
- const paddedDay = day.padStart(2, "0");
402
- const paddedMonth = month.padStart(2, "0");
403
- const fullYear = year.length <= 2 ? `20${year.padStart(2, "0")}` : year.padStart(4, "0");
404
- if (isValidDate(paddedDay, paddedMonth, fullYear)) {
405
- return formatOutput(paddedDay, paddedMonth, fullYear);
406
- }
407
- return null;
408
- }
409
- if (cleanInput.match(/^\d{1,2}-\d{1,2}-\d{2,4}$/)) {
410
- const [day, month, year] = cleanInput.split("-");
411
- const paddedDay = day.padStart(2, "0");
412
- const paddedMonth = month.padStart(2, "0");
413
- const fullYear = year.length <= 2 ? `20${year.padStart(2, "0")}` : year.padStart(4, "0");
414
- if (isValidDate(paddedDay, paddedMonth, fullYear)) {
415
- return formatOutput(paddedDay, paddedMonth, fullYear);
416
- }
417
- return null;
418
- }
419
- if (cleanInput.match(/^\d{1,2}[\/-]\d{1,2}$/)) {
420
- const [day, month] = cleanInput.split(/[\/-]/);
421
- const paddedDay = day.padStart(2, "0");
422
- const paddedMonth = month.padStart(2, "0");
423
- if (isValidDate(paddedDay, paddedMonth, currentYear)) {
424
- return formatOutput(paddedDay, paddedMonth, currentYear);
425
- }
426
- return null;
427
- }
428
- if (cleanInput.match(/^\d{4}$/)) {
429
- const num = parseInt(cleanInput, 10);
430
- if (num >= 2e3 && num <= maxYear) {
431
- if (isValidDate(currentDay, currentMonth, num.toString())) {
432
- return formatOutput(currentDay, currentMonth, num.toString());
433
- }
434
- return null;
435
- }
436
- const day = cleanInput.slice(0, 2);
437
- const month = cleanInput.slice(2, 4);
438
- if (isValidDate(day, month, currentYear)) {
439
- return formatOutput(day, month, currentYear);
440
- }
441
- return null;
442
- }
443
- if (cleanInput.startsWith("-") && /^\-\d+$/.test(cleanInput)) {
444
- const daysToSubtract = Math.abs(parseInt(cleanInput, 10));
445
- let result = (0, import_moment.default)().subtract(daysToSubtract, "days");
446
- if (isDateTime) {
447
- result = result.subtract(7, "hours");
448
- }
449
- if (result.isValid()) {
450
- return isDateTime ? result.format(dateTimeFormat) : result.format(dateFormat);
451
- }
452
- return null;
453
- }
454
- if (input.match(/^\d{1,2}[^0-9-\/]+\d{1,2}[^0-9-\/]+\d{2,4}.*$/)) {
455
- const parts = input.split(/[^0-9-\/]+/).filter(Boolean);
456
- const day = parts[0].padStart(2, "0");
457
- const month = parts[1].padStart(2, "0");
458
- let year = parts[2];
459
- year = year.length === 2 ? `20${year}` : year.padStart(4, "0");
460
- if (isValidDate(day, month, year)) {
461
- return formatOutput(day, month, year);
462
- }
463
- return null;
464
- }
465
- if (isDateTime) {
466
- if (cleanInput.length === 9) {
467
- const day = cleanInput.slice(0, 2);
468
- const month = cleanInput.slice(2, 4);
469
- const year = cleanInput.slice(4, 8);
470
- const hour = cleanInput.slice(8, 9).padStart(2, "0");
471
- if (isValidDate(day, month, year) && isValidTime(hour)) {
472
- let result = (0, import_moment.default)(
473
- `${day}-${month}-${year} ${hour}:00:00`,
474
- "DD-MM-YYYY HH:mm:ss"
475
- );
476
- if (!result.isValid()) return null;
477
- result = result.subtract(7, "hours");
478
- return result.format(dateTimeFormat);
479
- }
480
- return null;
481
- }
482
- if (cleanInput.length === 10) {
483
- const day = cleanInput.slice(0, 2);
484
- const month = cleanInput.slice(2, 4);
485
- const year = cleanInput.slice(4, 8);
486
- const hour = cleanInput.slice(8, 10);
487
- if (isValidDate(day, month, year) && isValidTime(hour)) {
488
- let result = (0, import_moment.default)(
489
- `${day}-${month}-${year} ${hour}:00:00`,
490
- "DD-MM-YYYY HH:mm:ss"
491
- );
492
- if (!result.isValid()) return null;
493
- result = result.subtract(7, "hours");
494
- return result.format(dateTimeFormat);
495
- }
496
- return null;
497
- }
498
- if (cleanInput.length === 11) {
499
- const day = cleanInput.slice(0, 2);
500
- const month = cleanInput.slice(2, 4);
501
- const year = cleanInput.slice(4, 8);
502
- const hour = cleanInput.slice(8, 10);
503
- const minute = cleanInput.slice(10, 11).padStart(2, "0");
504
- if (isValidDate(day, month, year) && isValidTime(hour, minute)) {
505
- let result = (0, import_moment.default)(
506
- `${day}-${month}-${year} ${hour}:${minute}:00`,
507
- "DD-MM-YYYY HH:mm:ss"
508
- );
509
- if (!result.isValid()) return null;
510
- result = result.subtract(7, "hours");
511
- return result.format(dateTimeFormat);
512
- }
513
- return null;
514
- }
515
- if (cleanInput.length === 12) {
516
- const day = cleanInput.slice(0, 2);
517
- const month = cleanInput.slice(2, 4);
518
- const year = cleanInput.slice(4, 8);
519
- const hour = cleanInput.slice(8, 10);
520
- const minute = cleanInput.slice(10, 12);
521
- if (isValidDate(day, month, year) && isValidTime(hour, minute)) {
522
- let result = (0, import_moment.default)(
523
- `${day}-${month}-${year} ${hour}:${minute}:00`,
524
- "DD-MM-YYYY HH:mm:ss"
525
- );
526
- if (!result.isValid()) return null;
527
- result = result.subtract(7, "hours");
528
- return result.format(dateTimeFormat);
529
- }
530
- return null;
531
- }
532
- if (cleanInput.length === 13) {
533
- const day = cleanInput.slice(0, 2);
534
- const month = cleanInput.slice(2, 4);
535
- const year = cleanInput.slice(4, 8);
536
- const hour = cleanInput.slice(8, 10);
537
- const minute = cleanInput.slice(10, 12);
538
- const second = cleanInput.slice(12, 13).padStart(2, "0");
539
- if (isValidDate(day, month, year) && isValidTime(hour, minute, second)) {
540
- let result = (0, import_moment.default)(
541
- `${day}-${month}-${year} ${hour}:${minute}:${second}`,
542
- "DD-MM-YYYY HH:mm:ss"
543
- );
544
- if (!result.isValid()) return null;
545
- result = result.subtract(7, "hours");
546
- return result.format(dateTimeFormat);
547
- }
548
- return null;
549
- }
550
- if (cleanInput.length === 14) {
551
- const day = cleanInput.slice(0, 2);
552
- const month = cleanInput.slice(2, 4);
553
- const year = cleanInput.slice(4, 8);
554
- const hour = cleanInput.slice(8, 10);
555
- const minute = cleanInput.slice(10, 12);
556
- const second = cleanInput.slice(12, 14);
557
- if (isValidDate(day, month, year) && isValidTime(hour, minute, second)) {
558
- let result = (0, import_moment.default)(
559
- `${day}-${month}-${year} ${hour}:${minute}:${second}`,
560
- "DD-MM-YYYY HH:mm:ss"
561
- );
562
- if (!result.isValid()) return null;
563
- result = result.subtract(7, "hours");
564
- return result.format(dateTimeFormat);
565
- }
566
- return null;
567
- }
568
- }
569
- const len = cleanInput.length;
570
- if (len === 1 || len === 2) {
571
- const paddedDay = cleanInput.padStart(2, "0");
572
- if (isValidDate(paddedDay, currentMonth, currentYear)) {
573
- return formatOutput(paddedDay, currentMonth, currentYear);
574
- }
575
- return null;
576
- }
577
- if (len === 3) {
578
- const day = cleanInput.slice(0, 2);
579
- const month = cleanInput.slice(2, 3).padStart(2, "0");
580
- if (isValidDate(day, month, currentYear)) {
581
- return formatOutput(day, month, currentYear);
582
- }
583
- return null;
584
- }
585
- if (len === 6) {
586
- const day = cleanInput.slice(0, 2);
587
- const month = cleanInput.slice(2, 4);
588
- let year = cleanInput.slice(4, 6);
589
- year = `20${year}`;
590
- if (parseInt(month) > 12) {
591
- if (isValidDate(day, currentMonth, currentYear)) {
592
- return formatOutput(day, currentMonth, currentYear);
593
- }
594
- return null;
595
- }
596
- if (isValidDate(day, month, year)) {
597
- return formatOutput(day, month, year);
598
- }
599
- return null;
600
- }
601
- if (len === 7) {
602
- return null;
603
- }
604
- if (len === 8) {
605
- const day = cleanInput.slice(0, 2);
606
- const month = cleanInput.slice(2, 4);
607
- const year = cleanInput.slice(4, 8);
608
- if (isValidDate(day, month, year)) {
609
- return formatOutput(day, month, year);
610
- }
611
- return null;
612
- }
613
- if (len > 8 && !isDateTime) {
614
- return null;
615
- }
616
- return null;
617
- };
618
-
619
- // src/utils.ts
620
- __reExport(utils_exports, require("@fctc/interface-logic/utils"));
621
-
622
- // src/hooks/core/use-menu.ts
623
- var useMenu = ({
624
- context,
625
- specification,
626
- domain,
627
- defaultService
628
- }) => {
629
- const { useGetMenu: useGetMenu2 } = (0, provider_exports.useService)();
630
- const [action, callAction] = useCallAction();
631
- const [service, setService] = (0, import_react3.useState)("");
632
- const [xNode, setXNode] = (0, import_react3.useState)("");
633
- const menuData = useGetMenu2(
634
- context,
635
- specification,
636
- !!context && !isObjectEmpty(context) && !!context?.uid && !!context?.lang,
637
- domain,
638
- defaultService
639
- );
640
- const [menuId, setMenuId] = (0, import_react3.useState)(void 0);
641
- const handleChangeMenu = async ({
642
- menu,
643
- service: service2,
644
- xNode: xNode2,
645
- context: context2
646
- }) => {
647
- const aidMenu = menu?.action?.external_xml_id || menu?.action?.id?.id;
648
- if (menu) {
649
- setMenuId(menu.id?.toString() ?? "");
650
- }
651
- if (aidMenu) {
652
- const actionResponse = await callAction({
653
- aid: aidMenu,
654
- service: service2 ?? "",
655
- xNode: xNode2,
656
- context: context2
657
- });
658
- setService(service2 ?? "");
659
- setXNode(xNode2 ?? "");
660
- return actionResponse;
661
- }
662
- };
663
- return {
664
- ...menuData,
665
- service,
666
- xNode,
667
- data: menuData?.data,
668
- action: { handleChangeMenu },
669
- state: { menuId, action },
670
- context,
671
- isLoading: menuData.isLoading,
672
- isError: menuData.isError,
673
- error: menuData.error,
674
- refetch: menuData.refetch
675
- };
676
- };
677
-
678
- // src/hooks/core/use-detail.ts
679
- var import_react_query = require("@tanstack/react-query");
680
- var import_react4 = require("react");
681
- var useDetail = (sub) => {
682
- const { setUserInfo, env } = (0, provider_exports.useEnv)();
683
- const { useGetDetail: useGetDetail2 } = (0, provider_exports.useService)();
684
- const fetchGetDetail = useGetDetail2();
685
- const userDetailQuery = (0, import_react_query.useQuery)({
686
- queryKey: ["userDetailQuery", sub],
687
- queryFn: () => {
688
- return fetchGetDetail.mutateAsync({
689
- model: "res.users",
690
- ids: [sub],
691
- specification: { image_256: {} },
692
- service: env?.default_service
693
- });
694
- },
695
- enabled: !!sub
696
- });
697
- (0, import_react4.useEffect)(() => {
698
- if (userDetailQuery.data) {
699
- const userPicture = userDetailQuery.data;
700
- setUserInfo({ ...env?.user, image: userPicture?.[0]?.image_256 });
701
- }
702
- }, [userDetailQuery.isFetched]);
703
- return { ...userDetailQuery };
704
- };
705
-
706
- // src/hooks/core/use-profile.ts
707
- var import_react_query2 = require("@tanstack/react-query");
708
- var import_react5 = require("react");
709
- var useProfile = ({
710
- service,
711
- i18n
712
- }) => {
713
- const { setUid, setLang, setUserInfo, env } = (0, provider_exports.useEnv)();
714
- const { useGetProfile: useGetProfile2 } = (0, provider_exports.useService)();
715
- const getProfile = useGetProfile2(service);
716
- const userInfoQuery = (0, import_react_query2.useQuery)({
717
- queryKey: ["userInfo"],
718
- queryFn: () => getProfile.mutateAsync(),
719
- enabled: isObjectEmpty(env?.user)
720
- });
721
- (0, import_react5.useEffect)(() => {
722
- if (userInfoQuery.data) {
723
- const userInfo = userInfoQuery.data;
724
- utils_exports.sessionStorageUtils.setXNode(userInfo?.x_node);
725
- setUid(userInfo?.sub);
726
- setUserInfo(userInfo);
727
- const userLocale = languages.find((lang) => lang?.id === userInfo?.locale);
728
- setLang(userLocale?.id);
729
- i18n.changeLanguage(userLocale?.id.split("_")[0]);
730
- }
731
- }, [userInfoQuery.isFetched]);
732
- const context = (0, import_react5.useMemo)(() => {
733
- if (userInfoQuery.data?.sub && userInfoQuery.data?.locale) {
734
- return {
735
- uid: Number(userInfoQuery.data.sub),
736
- lang: String(userInfoQuery.data.locale),
737
- tz: "Asia/Saigon"
738
- };
739
- }
740
- return void 0;
741
- }, [userInfoQuery.isFetched]);
742
- if (userInfoQuery.isLoading || !userInfoQuery.data) {
743
- return null;
744
- }
745
- return {
746
- ...userInfoQuery,
747
- context
748
- };
749
- };
750
-
751
- // src/hooks/core/use-user.ts
752
- var useUser = ({ service, i18n }) => {
753
- const userProfile = useProfile({ service, i18n });
754
- const userDetail = useDetail(userProfile?.data?.sub);
755
- return { userProfile, userDetail, context: userProfile?.context };
756
- };
757
-
758
- // src/hooks/core/use-view-v2.ts
759
- var import_react6 = require("react");
760
- var useViewV2 = ({
761
- action,
762
- context,
763
- aid,
764
- service,
765
- xNode
766
- }) => {
767
- const { useGetView: useGetView2 } = (0, provider_exports.useService)();
768
- const viewParams = (0, import_react6.useMemo)(() => {
769
- if (!action || !action?.res_model) {
770
- return void 0;
771
- }
772
- const actionResult = action;
773
- return {
774
- aid,
775
- model: String(actionResult?.res_model),
776
- views: [
777
- ...Array.isArray(actionResult?.views) ? actionResult?.views.map(
778
- (view2) => view2[1] === "list" ? [view2[0], "list"] : view2
779
- ) : [],
780
- [
781
- Array.isArray(actionResult?.search_view_id) ? actionResult?.search_view_id[0] : actionResult?.search_view_id,
782
- "search"
783
- ]
784
- ],
785
- context,
786
- id: isNaN(Number(aid)) ? action?.id : aid,
787
- service,
788
- xNode
789
- };
790
- }, [action, context, aid]);
791
- const view = useGetView2({
792
- viewParams: viewParams ?? {},
793
- enabled: !!viewParams
794
- });
795
- return {
796
- ...view,
797
- context
798
- };
799
- };
800
-
801
- // src/hooks/core/use-company.ts
802
- var import_react_query3 = require("@tanstack/react-query");
803
- var import_react7 = require("react");
804
- var useCompany = ({ service }) => {
805
- const { setCompanies, setDefaultCompany, env } = (0, provider_exports.useEnv)();
806
- const { useGetCurrentCompany: useGetCurrentCompany2, useGetCompanyInfo: useGetCompanyInfo2 } = (0, provider_exports.useService)();
807
- const getCurrentCompany = useGetCurrentCompany2();
808
- const fetchCurrentCompany = async () => {
809
- return await getCurrentCompany.mutateAsync({
810
- service
811
- });
812
- };
813
- const currentCompany = (0, import_react_query3.useQuery)({
814
- queryKey: ["currentCompany"],
815
- queryFn: fetchCurrentCompany,
816
- enabled: !!env?.defaultCompany
817
- });
818
- const current_company_id = (0, import_react7.useMemo)(() => {
819
- return currentCompany.data?.current_company_id;
820
- }, [currentCompany.data]);
821
- (0, import_react7.useEffect)(() => {
822
- if (current_company_id) {
823
- const companyIDs = [current_company_id];
824
- setCompanies(companyIDs);
825
- }
826
- }, [current_company_id]);
827
- const getCompanyInfo = useGetCompanyInfo2();
828
- const companyInfo = (0, import_react_query3.useQuery)({
829
- queryKey: ["companyInfoQuery", current_company_id],
830
- queryFn: () => getCompanyInfo.mutateAsync({
831
- service,
832
- id: Number(current_company_id)
833
- }),
834
- enabled: !!current_company_id
835
- });
836
- (0, import_react7.useEffect)(() => {
837
- if (companyInfo.data) {
838
- const companyInfoData = companyInfo.data;
839
- if (companyInfoData?.length) {
840
- setDefaultCompany(companyInfoData[0]);
841
- }
842
- }
843
- }, [companyInfo.data]);
844
- if (!companyInfo?.data || !currentCompany?.data) return;
845
- return {
846
- currentCompany: { ...currentCompany },
847
- companyInfo: { ...companyInfo }
848
- };
849
- };
850
-
851
- // src/hooks/core/use-app-provider.tsx
852
- var import_jsx_runtime = require("react/jsx-runtime");
853
- var AppProviderInitialValue = {
854
- user: {},
855
- company: {},
856
- action: {},
857
- menu: {},
858
- view: {}
859
- };
860
- var ReactContext = (0, import_react8.createContext)(AppProviderInitialValue);
861
- var AppProvider = ({
862
- children,
863
- menuParams,
864
- aid,
865
- i18n
866
- }) => {
867
- const { env } = (0, provider_exports.useEnv)();
868
- const user = useUser({ service: env.default_service, i18n });
869
- const company = useCompany({ service: env.default_service });
870
- const menuContext = (0, import_react8.useMemo)(() => {
871
- return (0, utils_exports.combineContexts)([
872
- {
873
- ...user?.context,
874
- ...!isObjectEmpty(env?.user) ? { lang: env?.context?.lang } : {},
875
- ...menuParams?.context ?? {}
876
- }
877
- ]);
878
- }, [user?.context, company?.companyInfo?.isFetched, env?.context?.lang]);
879
- const menu = useMenu({
880
- context: {
881
- ...menuContext
882
- },
883
- specification: menuParams?.specification,
884
- domain: menuParams?.domain,
885
- defaultService: env.default_service
886
- });
887
- const action = (0, import_react8.useMemo)(() => {
888
- return menu?.state?.action;
889
- }, [menu?.state?.action, env?.context?.lang]);
890
- const viewContext = (0, import_react8.useMemo)(() => {
891
- return (0, utils_exports.combineContexts)([
892
- menuContext,
893
- { ...(0, utils_exports.evalJSONContext)(action?.context) }
894
- ]);
895
- }, [menuContext, action?.context, env?.context?.lang]);
896
- const view = useViewV2({
897
- action,
898
- context: viewContext,
899
- aid,
900
- service: menu?.service,
901
- xNode: menu?.xNode
902
- });
903
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
904
- ReactContext.Provider,
905
- {
906
- value: {
907
- user,
908
- company,
909
- menu,
910
- action,
911
- view
912
- },
913
- children
914
- }
915
- );
916
- };
917
- var useAppProvider = () => {
918
- const context = (0, import_react8.useContext)(ReactContext);
919
- if (!context) {
920
- return AppProviderInitialValue;
921
- }
922
- return context;
923
- };
924
-
925
- // src/hooks/core/use-config.ts
926
- var import_react9 = require("react");
927
- var useConfig = ({
928
- envConfig,
929
- config,
930
- localStorageUtils,
931
- sessionStorageUtils: sessionStorageUtils2
932
- }) => {
933
- const { setupEnv, setEnvFile } = (0, provider_exports.useEnv)();
934
- (0, import_react9.useEffect)(() => {
935
- try {
936
- setupEnv({
937
- baseUrl: envConfig.baseUrl,
938
- config: envConfig.config,
939
- default_service: "",
940
- localStorageUtils: localStorageUtils && localStorageUtils(),
941
- sessionStorageUtils: localStorageUtils && sessionStorageUtils2()
942
- });
943
- setEnvFile(config);
944
- } catch (error) {
945
- console.error("Error loading env or config:", error);
946
- }
947
- }, [envConfig, config]);
948
- return { envConfig, config };
949
- };
950
-
951
- // src/hooks/core/use-get-action.ts
952
- var useGetAction = ({
953
- aid,
954
- context
955
- }) => {
956
- const { useLoadAction: useLoadAction2, useRunAction: useRunAction2 } = (0, provider_exports.useService)();
957
- const queryLoadAction = useLoadAction2();
958
- const queryRunAction = useRunAction2();
959
- const handleActionResult = (data) => {
960
- if (data && data.result && data.result.views && Array.isArray(data.result.views) && data.result.views.length > 0) {
961
- }
962
- };
963
- const onLoadAction = () => {
964
- queryLoadAction.mutate(
965
- {
966
- idAction: aid,
967
- context
968
- },
969
- {
970
- onSuccess: (data) => {
971
- if (data?.result?.type === "ir.actions.act_window") {
972
- handleActionResult(data);
973
- } else if (data?.result?.type === "ir.actions.server") {
974
- queryRunAction.mutate(
975
- {
976
- idAction: aid,
977
- context
978
- },
979
- {
980
- onSuccess: handleActionResult
981
- }
982
- );
983
- }
984
- }
985
- }
986
- );
987
- };
988
- return {
989
- onLoadAction
990
- };
991
- };
992
-
993
- // src/hooks/core/use-get-specification.ts
994
- var import_react10 = require("react");
995
- var useGetSpecification = ({
996
- model,
997
- viewData,
998
- fields
999
- }) => {
1000
- const baseModel = (0, import_react10.useMemo)(
1001
- () => ({
1002
- name: String(model),
1003
- view: viewData,
1004
- fields
1005
- }),
1006
- [model, viewData, fields]
1007
- );
1008
- const initModel = (0, import_hooks2.useModel)();
1009
- const modelInstance = (0, import_react10.useMemo)(() => {
1010
- if (viewData) {
1011
- return initModel.initModel(baseModel);
1012
- }
1013
- return null;
1014
- }, [baseModel, viewData, model]);
1015
- const specification = (0, import_react10.useMemo)(() => {
1016
- if (modelInstance) {
1017
- return modelInstance.getSpecification();
1018
- }
1019
- return null;
1020
- }, [modelInstance, model]);
1021
- return { specification };
1022
- };
1023
-
1024
- // src/hooks/core/use-list-data.ts
1025
- var import_react13 = require("react");
1026
- var import_utils5 = require("@fctc/interface-logic/utils");
1027
-
1028
- // src/hooks/utils/use-debounce.ts
1029
- var import_react11 = require("react");
1030
- function useDebounce(value, delay) {
1031
- const [debouncedValue, setDebouncedValue] = (0, import_react11.useState)(value);
1032
- (0, import_react11.useEffect)(() => {
1033
- const handler = setTimeout(() => {
1034
- setDebouncedValue(value);
1035
- }, delay);
1036
- return () => {
1037
- clearTimeout(handler);
1038
- };
1039
- }, [value, delay]);
1040
- return [debouncedValue];
1041
- }
1042
-
1043
- // src/hooks/utils/use-get-rowids.ts
1044
- var import_react12 = require("react");
1045
- var useGetRowIds = (tableRef) => {
1046
- function isElementVisible(el) {
1047
- const style = window.getComputedStyle(el);
1048
- return style.display !== "none" && style.visibility !== "hidden" && style.opacity !== "0";
1049
- }
1050
- function arraysAreEqual(a, b) {
1051
- if (a.length !== b.length) return false;
1052
- if (a.length === 0 && b.length === 0) return true;
1053
- const setA = new Set(a);
1054
- const setB = new Set(b);
1055
- if (setA.size !== setB.size) return false;
1056
- for (const val of setA) {
1057
- if (!setB.has(val)) return false;
1058
- }
1059
- return true;
1060
- }
1061
- const [rowIds, setRowIds] = (0, import_react12.useState)([]);
1062
- const lastRowIdsRef = (0, import_react12.useRef)([]);
1063
- const updateVisibleRowIds = (0, import_react12.useCallback)(() => {
1064
- const table = tableRef.current;
1065
- if (!table) return;
1066
- const rows = table.querySelectorAll("tr[data-row-id]");
1067
- const ids = [];
1068
- rows.forEach((row) => {
1069
- const el = row;
1070
- if (isElementVisible(el)) {
1071
- const id = el.getAttribute("data-row-id");
1072
- if (id) ids.push(id);
1073
- }
1074
- });
1075
- const uniqueIds = Array.from(new Set(ids));
1076
- if (!arraysAreEqual(lastRowIdsRef.current, uniqueIds)) {
1077
- lastRowIdsRef.current = uniqueIds;
1078
- setRowIds(uniqueIds);
1079
- }
1080
- }, [tableRef]);
1081
- (0, import_react12.useEffect)(() => {
1082
- const table = tableRef.current;
1083
- if (!table) return;
1084
- const mutationObserver = new MutationObserver(() => {
1085
- updateVisibleRowIds();
1086
- });
1087
- mutationObserver.observe(table, {
1088
- childList: true,
1089
- subtree: true,
1090
- attributes: true,
1091
- attributeFilter: ["style", "class"]
1092
- });
1093
- const resizeObserver = new ResizeObserver(() => {
1094
- updateVisibleRowIds();
1095
- });
1096
- resizeObserver.observe(table);
1097
- const handleScroll = () => updateVisibleRowIds();
1098
- table.addEventListener("scroll", handleScroll, true);
1099
- updateVisibleRowIds();
1100
- return () => {
1101
- mutationObserver.disconnect();
1102
- resizeObserver.disconnect();
1103
- table.removeEventListener("scroll", handleScroll, true);
1104
- };
1105
- }, [updateVisibleRowIds, tableRef?.current]);
1106
- return { rowIds, refresh: updateVisibleRowIds };
1107
- };
1108
-
1109
- // src/hooks/core/use-list-data.ts
1110
- var useListData = ({
1111
- action,
1112
- context,
1113
- viewData,
1114
- model,
1115
- service,
1116
- xNode,
1117
- mode,
1118
- limit = 10
1119
- }) => {
1120
- const { useGetListData: useGetListData2 } = (0, provider_exports.useService)();
1121
- const [page, setPage] = (0, import_react13.useState)(0);
1122
- const [pageLimit, setPageLimit] = (0, import_react13.useState)(limit);
1123
- const [groupByList, setGroupByList] = (0, import_react13.useState)(null);
1124
- const [domain, setDomain] = (0, import_react13.useState)(null);
1125
- const [order, setOrder] = (0, import_react13.useState)("");
1126
- const [selectedRowKeys, setSelectedRowKeys] = (0, import_react13.useState)([]);
1127
- const [debouncedPage] = useDebounce(page, 500);
1128
- const [debouncedDomain] = useDebounce(domain, 500);
1129
- const { specification } = useGetSpecification({
1130
- model,
1131
- viewData,
1132
- fields: mode === "kanban" ? viewData?.views?.kanban?.fields : viewData?.views?.list?.fields
1133
- });
1134
- const listDataProps = (0, import_react13.useMemo)(() => {
1135
- if (!viewData || !action || !context) {
1136
- return null;
1137
- }
1138
- const domainParse = domain ? [...domain] : action?.domain ? Array.isArray(action?.domain) ? [...action?.domain] : (0, import_utils5.evalJSONDomain)(action?.domain, context) : [];
1139
- const limit2 = pageLimit;
1140
- const offset = debouncedPage * pageLimit;
1141
- const fields = typeof groupByList === "object" ? groupByList?.fields : void 0;
1142
- const groupby = typeof groupByList === "object" ? [groupByList?.contexts?.[0]?.group_by] : [];
1143
- const sort = order ?? (0, import_utils5.formatSortingString)(
1144
- (mode === "kanban" ? viewData?.views?.kanban : viewData?.views?.list)?.default_order
1145
- ) ?? "";
1146
- return {
1147
- model: action?.res_model,
1148
- specification,
1149
- domain: domainParse,
1150
- limit: limit2,
1151
- offset,
1152
- fields,
1153
- groupby,
1154
- context,
1155
- sort,
1156
- mode
1157
- };
1158
- }, [
1159
- action,
1160
- groupByList,
1161
- order,
1162
- debouncedPage,
1163
- pageLimit,
1164
- debouncedDomain,
1165
- context,
1166
- model
1167
- ]);
1168
- const list = useGetListData2(
1169
- { ...listDataProps },
1170
- [
1171
- listDataProps?.domain,
1172
- listDataProps?.groupby,
1173
- listDataProps?.limit,
1174
- listDataProps?.offset,
1175
- listDataProps?.sort,
1176
- listDataProps?.context,
1177
- listDataProps?.specification,
1178
- listDataProps?.mode
1179
- ],
1180
- !!listDataProps && !!specification && !isObjectEmpty(specification) && !!domain,
1181
- service,
1182
- xNode
1183
- );
1184
- return {
1185
- ...list,
1186
- state: {
1187
- specification,
1188
- page,
1189
- order,
1190
- domain: listDataProps?.domain,
1191
- pageLimit,
1192
- groupByList,
1193
- selectedRowKeys,
1194
- setPage,
1195
- setOrder,
1196
- setDomain,
1197
- setPageLimit,
1198
- setGroupByList,
1199
- setSelectedRowKeys
1200
- }
1201
- };
1202
- };
1203
-
1204
- // src/config.ts
1205
- var config_exports = {};
1206
- __reExport(config_exports, require("@fctc/interface-logic/configs"));
1207
-
1208
- // src/index.ts
1209
- __reExport(index_exports, config_exports, module.exports);
1210
-
1211
- // src/widget/basic/status-dropdown-field/controller.ts
1212
- var import_react14 = require("react");
1213
- var import_environment = require("@fctc/interface-logic/environment");
1214
- var import_hooks4 = require("@fctc/interface-logic/hooks");
1215
- var statusDropdownController = (props) => {
1216
- const { selection, isForm, id, model, name, state, onRefetch } = props;
1217
- const env = (0, import_environment.getEnv)();
1218
- const colors = {
1219
- normal: "bg-[#e9ecef]",
1220
- done: "bg-primary",
1221
- blocked: "bg-red-500"
1222
- };
1223
- const [isOpen, setIsOpen] = (0, import_react14.useState)(false);
1224
- const buttonRef = (0, import_react14.useRef)(null);
1225
- (0, import_react14.useEffect)(() => {
1226
- const handleClickOutside = (event) => {
1227
- if (buttonRef.current && !buttonRef.current.contains(event.target)) {
1228
- setIsOpen(false);
1229
- }
1230
- };
1231
- document.addEventListener("mousedown", handleClickOutside);
1232
- return () => {
1233
- document.removeEventListener("mousedown", handleClickOutside);
1234
- };
1235
- }, []);
1236
- const { mutate: onSave } = (0, import_hooks4.useSave)();
1237
- const handleClick = async (status) => {
1238
- setIsOpen(!isOpen);
1239
- onSave(
1240
- {
1241
- ids: id ? [id] : [],
1242
- model: model ?? "",
1243
- data: { [name ?? ""]: status },
1244
- context: env.context
1245
- },
1246
- {
1247
- onSuccess: () => {
1248
- onRefetch && onRefetch();
1249
- }
1250
- }
1251
- );
1252
- };
1253
- return {
1254
- handleClick,
1255
- buttonRef,
1256
- isForm,
1257
- setIsOpen,
1258
- isOpen,
1259
- selection,
1260
- state,
1261
- colors
1262
- };
1263
- };
1264
-
1265
- // src/widget/basic/many2one-field/controller.ts
1266
- var import_react15 = require("react");
1267
- var MANY2ONE_EXTERNAL = "many2one_external";
1268
- var many2oneFieldController = (props) => {
1269
- const {
1270
- methods,
1271
- relation,
1272
- domain,
1273
- formValues,
1274
- value: propValue,
1275
- onChange,
1276
- name,
1277
- context: fieldContext,
1278
- options: fieldOptions,
1279
- showDetail,
1280
- service,
1281
- xNode,
1282
- isForm,
1283
- widget,
1284
- in_list_view,
1285
- isEditTable
1286
- } = props;
1287
- const { env } = (0, provider_exports.useEnv)();
1288
- const { action } = useAppProvider();
1289
- const { useGetSelection: useGetSelection3, useGetDetail: useGetDetail2 } = (0, provider_exports.useService)();
1290
- const [listOptions, setListOptions] = (0, import_react15.useState)([]);
1291
- const [inputValue, setInputValue] = (0, import_react15.useState)("");
1292
- const [debouncedInputValue] = useDebounce(inputValue, 1e3);
1293
- const [isShowModalMany2Many, setIsShowModalMany2Many] = (0, import_react15.useState)(false);
1294
- const [tempSelectedOption, setTempSelectedOption] = (0, import_react15.useState)(null);
1295
- const [domainModal, setDomainModal] = (0, import_react15.useState)(null);
1296
- const [domainObject, setDomainObject] = (0, import_react15.useState)(null);
1297
- const initValue = methods?.getValues(name);
1298
- const contextObject = {
1299
- ...(typeof action?.context === "string" ? (0, utils_exports.evalJSONContext)(action?.context) : action?.context) || {},
1300
- ...fieldContext,
1301
- ...env?.context
1302
- };
1303
- const optionsObject = typeof fieldOptions === "string" ? (0, utils_exports.evalJSONContext)(fieldOptions, {
1304
- ...formValues,
1305
- ...contextObject,
1306
- context: contextObject,
1307
- parent: { ...formValues }
1308
- }) : fieldOptions;
1309
- const fetchGetDetail = useGetDetail2();
1310
- const data = {
1311
- model: widget === MANY2ONE_EXTERNAL ? optionsObject?.model : relation,
1312
- domain: widget === MANY2ONE_EXTERNAL ? optionsObject?.domain : domainObject,
1313
- context: {
1314
- ...contextObject,
1315
- ...optionsObject?.context
1316
- },
1317
- specification: widget === MANY2ONE_EXTERNAL ? optionsObject?.specification : {
1318
- id: {},
1319
- name: {},
1320
- display_name: {}
1321
- }
1322
- };
1323
- const {
1324
- data: dataOfSelection,
1325
- refetch,
1326
- isFetching
1327
- } = useGetSelection3({
1328
- data,
1329
- queryKey: [`data_${relation}`, domainObject],
1330
- enabled: false,
1331
- service: widget === MANY2ONE_EXTERNAL ? optionsObject?.service : service,
1332
- xNode
1333
- });
1334
- const selectOptions = (0, import_react15.useMemo)(() => {
1335
- return dataOfSelection?.records?.map((val) => ({
1336
- value: val?.id,
1337
- label: val?.display_name || val?.name,
1338
- ...widget === MANY2ONE_EXTERNAL ? val : {}
1339
- })) || [];
1340
- }, [dataOfSelection]);
1341
- (0, import_react15.useEffect)(() => {
1342
- setListOptions(selectOptions);
1343
- setDomainModal(domainObject);
1344
- }, [selectOptions]);
1345
- const parsedFormValues = (0, import_react15.useMemo)(
1346
- () => JSON.parse(
1347
- JSON.stringify({
1348
- ...formValues,
1349
- ...contextObject,
1350
- context: contextObject
1351
- })
1352
- ) ?? {},
1353
- [formValues, contextObject]
1354
- );
1355
- (0, import_react15.useEffect)(() => {
1356
- const newDomain = (0, utils_exports.evalJSONDomain)(domain, parsedFormValues);
1357
- const parsedDomain = typeof newDomain === "string" ? JSON.parse(
1358
- newDomain.replace(/\(/g, "[").replace(/\)/g, "]").replace(/'/g, '"')
1359
- ) : newDomain;
1360
- setDomainObject((prev) => {
1361
- const prevStr = JSON.stringify(prev);
1362
- const nextStr = JSON.stringify(parsedDomain);
1363
- return prevStr === nextStr ? prev : parsedDomain;
1364
- });
1365
- }, [domain, parsedFormValues]);
1366
- (0, import_react15.useEffect)(() => {
1367
- if (!propValue && tempSelectedOption) {
1368
- methods?.setValue(name, null, { shouldDirty: true });
1369
- setTempSelectedOption(null);
1370
- } else if (propValue) {
1371
- if (isForm && !isEditTable && optionsObject?.service && optionsObject?.model && !propValue?.display_name && !in_list_view) {
1372
- fetchGetDetail.mutate(
1373
- {
1374
- model: optionsObject?.model,
1375
- ids: propValue?.id ?? propValue,
1376
- specification: widget === MANY2ONE_EXTERNAL ? optionsObject?.specification : {
1377
- id: {},
1378
- display_name: {}
1379
- },
1380
- context: { ...env.context },
1381
- service: optionsObject ? optionsObject?.service : service,
1382
- xNode
1383
- },
1384
- {
1385
- onSuccess: (dataResponse) => {
1386
- const detailData = dataResponse?.[0];
1387
- setTempSelectedOption({
1388
- value: detailData?.id,
1389
- label: detailData?.display_name
1390
- });
1391
- if (widget === MANY2ONE_EXTERNAL && optionsObject?.values_included) {
1392
- Object.keys(optionsObject?.values_included)?.forEach(
1393
- (field) => {
1394
- methods?.setValue(
1395
- optionsObject?.values_included[field]?.name,
1396
- detailData?.[field]
1397
- );
1398
- }
1399
- );
1400
- methods?.setValue(name, detailData);
1401
- }
1402
- },
1403
- onError: (error) => {
1404
- console.log("error", error);
1405
- }
1406
- }
1407
- );
1408
- return;
1409
- }
1410
- setTempSelectedOption({
1411
- value: propValue?.id,
1412
- label: propValue?.display_name
1413
- });
1414
- }
1415
- }, [propValue]);
1416
- const fetchMoreOptions = (0, import_react15.useCallback)(() => {
1417
- refetch();
1418
- }, [refetch]);
1419
- (0, import_react15.useEffect)(() => {
1420
- if (debouncedInputValue) {
1421
- const filteredDomain = [...domainObject ?? []]?.filter(
1422
- (d) => !(Array.isArray(d) && d[0] === "name" && d[1] === "ilike")
1423
- ) || [];
1424
- const newDomain = [
1425
- ...filteredDomain,
1426
- ...debouncedInputValue ? [["name", "ilike", debouncedInputValue]] : []
1427
- ];
1428
- setDomainObject(newDomain);
1429
- setTimeout(() => {
1430
- fetchMoreOptions();
1431
- }, 50);
1432
- }
1433
- }, [debouncedInputValue]);
1434
- const handleChooseRecord = (0, import_react15.useCallback)(
1435
- (idRecord) => {
1436
- const newOption = listOptions?.find(
1437
- (option) => option.value === idRecord
1438
- );
1439
- const newValue = widget === MANY2ONE_EXTERNAL && optionsObject?.field_name ? newOption?.[optionsObject?.field_name] : newOption.value;
1440
- if (widget === MANY2ONE_EXTERNAL && optionsObject?.values_included) {
1441
- Object.keys(optionsObject?.values_included)?.forEach((field) => {
1442
- methods?.setValue(
1443
- optionsObject?.values_included[field]?.name,
1444
- newOption?.[field],
1445
- { shouldDirty: true }
1446
- );
1447
- });
1448
- }
1449
- if (newOption) {
1450
- methods?.setValue(
1451
- name,
1452
- {
1453
- ...newOption,
1454
- id: newValue,
1455
- display_name: newOption?.label
1456
- },
1457
- { shouldDirty: true }
1458
- );
1459
- setTempSelectedOption(newOption);
1460
- onChange && onChange(String(name), {
1461
- ...newOption,
1462
- id: newValue,
1463
- display_name: newOption?.label
1464
- });
1465
- methods.trigger(name);
1466
- }
1467
- setIsShowModalMany2Many(false);
1468
- },
1469
- [listOptions, methods, name, onChange]
1470
- );
1471
- const handleClose = (0, import_react15.useCallback)(() => setIsShowModalMany2Many(false), []);
1472
- const handleSelectChange = (0, import_react15.useCallback)(
1473
- (selectedOption) => {
1474
- if (!selectedOption) {
1475
- if (widget === MANY2ONE_EXTERNAL && optionsObject?.values_included) {
1476
- Object.keys(optionsObject?.values_included)?.forEach((field) => {
1477
- methods?.setValue(
1478
- optionsObject?.values_included[field]?.name,
1479
- null,
1480
- { shouldDirty: true }
1481
- );
1482
- });
1483
- }
1484
- methods.setValue(name, null, { shouldDirty: true });
1485
- setTempSelectedOption(null);
1486
- onChange && onChange(String(name), null);
1487
- methods.trigger(name);
1488
- return;
1489
- }
1490
- const newValue = widget === MANY2ONE_EXTERNAL && optionsObject?.field_name ? selectedOption?.[optionsObject?.field_name] : selectedOption.value;
1491
- if (widget === MANY2ONE_EXTERNAL && optionsObject?.values_included) {
1492
- Object.keys(optionsObject?.values_included)?.forEach((field) => {
1493
- methods?.setValue(
1494
- optionsObject?.values_included[field]?.name,
1495
- selectedOption?.[field],
1496
- { shouldDirty: true }
1497
- );
1498
- });
1499
- }
1500
- methods?.setValue(
1501
- name,
1502
- {
1503
- id: newValue,
1504
- display_name: selectedOption?.label
1505
- },
1506
- { shouldDirty: true }
1507
- );
1508
- setTempSelectedOption(selectedOption);
1509
- onChange && onChange(String(name), {
1510
- id: newValue,
1511
- display_name: selectedOption.label
1512
- });
1513
- methods.trigger(name);
1514
- },
1515
- [methods, name, onChange]
1516
- );
1517
- const allowShowDetail = showDetail && contextObject?.form_view_ref && (!optionsObject || !("no_open" in optionsObject) || optionsObject.no_open === false);
1518
- return {
1519
- isShowModalMany2Many,
1520
- isFetching,
1521
- initValue,
1522
- handleChooseRecord,
1523
- handleClose,
1524
- handleSelectChange,
1525
- domainModal,
1526
- setInputValue,
1527
- allowShowDetail,
1528
- contextObject: {
1529
- ...contextObject,
1530
- ...optionsObject?.context
1531
- },
1532
- tempSelectedOption,
1533
- listOptions,
1534
- fetchMoreOptions,
1535
- domainObject: widget === MANY2ONE_EXTERNAL ? optionsObject?.domain : domainObject,
1536
- setIsShowModalMany2Many,
1537
- setDomainObject,
1538
- options: optionsObject,
1539
- relation: widget === MANY2ONE_EXTERNAL ? optionsObject?.model : relation,
1540
- service: widget === MANY2ONE_EXTERNAL ? optionsObject?.service : service
1541
- };
1542
- };
1543
-
1544
- // src/widget/basic/many2one-button-field/controller.ts
1545
- var import_environment2 = require("@fctc/interface-logic/environment");
1546
- var import_hooks6 = require("@fctc/interface-logic/hooks");
1547
- var import_utils9 = require("@fctc/interface-logic/utils");
1548
- var many2oneButtonController = (props) => {
1549
- const { domain, methods, relation, service, xNode } = props;
1550
- const actionDataString = sessionStorage.getItem("actionData");
1551
- const env = (0, import_environment2.getEnv)();
1552
- const domainObject = (0, import_utils9.evalJSONDomain)(domain, methods?.getValues() || {});
1553
- const actionData = actionDataString && actionDataString !== "undefined" ? JSON.parse(actionDataString) : {};
1554
- const { data: dataOfSelection } = (0, import_hooks6.useGetSelection)({
1555
- data: {
1556
- model: relation ?? "",
1557
- domain: domainObject,
1558
- context: { ...env.context, ...(0, import_utils9.evalJSONContext)(actionData?.context) }
1559
- },
1560
- queryKey: [`data_${relation}`, domainObject],
1561
- service,
1562
- xNode
1563
- });
1564
- const options = dataOfSelection?.records?.map((val) => ({
1565
- value: val.id,
1566
- label: val.name
1567
- })) || [];
1568
- return {
1569
- options
1570
- };
1571
- };
1572
-
1573
- // src/widget/basic/many2many-field/controller.ts
1574
- var import_react16 = require("react");
1575
- var import_utils10 = require("@fctc/interface-logic/utils");
1576
- var many2manyFieldController = (props) => {
1577
- const {
1578
- relation,
1579
- domain,
1580
- context,
1581
- options,
1582
- enabled: enabledCallAPI,
1583
- service
1584
- } = props;
1585
- const { env } = (0, provider_exports.useEnv)();
1586
- const { user } = useAppProvider();
1587
- const { useGetView: useGetView2 } = (0, provider_exports.useService)();
1588
- const dataUser = user?.userProfile?.data;
1589
- const contextObject = (0, import_react16.useMemo)(
1590
- () => ({
1591
- ...env.context,
1592
- ...context || {}
1593
- }),
1594
- [env?.context, context]
1595
- );
1596
- const viewParams = (0, import_react16.useMemo)(
1597
- () => ({
1598
- model: relation,
1599
- views: [
1600
- [false, "list"],
1601
- [false, "search"]
1602
- ],
1603
- context: contextObject,
1604
- service,
1605
- xNode: service == "wesap" && dataUser?.x_node
1606
- }),
1607
- [relation, contextObject, service, dataUser?.x_node]
1608
- );
1609
- const { data: viewResponse } = useGetView2({
1610
- viewParams,
1611
- enabled: enabledCallAPI
1612
- });
1613
- const default_order = viewResponse && viewResponse?.views?.list?.default_order;
1614
- const optionsObject = (0, import_react16.useMemo)(
1615
- () => (options && typeof options === "string" ? (0, import_utils10.evalJSONContext)(options) : options) || {},
1616
- [options]
1617
- );
1618
- const {
1619
- data: dataResponse,
1620
- isFetched,
1621
- isLoading,
1622
- state,
1623
- isPlaceholderData
1624
- } = useListData({
1625
- action: {
1626
- domain,
1627
- res_model: relation
1628
- },
1629
- context: contextObject,
1630
- model: relation ?? "",
1631
- viewData: viewResponse,
1632
- service,
1633
- xNode: service == "wesap" && dataUser?.x_node
1634
- });
1635
- const {
1636
- selectedRowKeys,
1637
- groupByList,
1638
- domain: domainList,
1639
- page,
1640
- pageLimit,
1641
- setDomain,
1642
- setOrder,
1643
- setPage,
1644
- setSelectedRowKeys,
1645
- setGroupByList,
1646
- setPageLimit,
1647
- specification
1648
- } = state;
1649
- (0, import_react16.useEffect)(() => {
1650
- return () => {
1651
- setDomain(null);
1652
- setOrder("");
1653
- setGroupByList(null);
1654
- setPageLimit(10);
1655
- };
1656
- }, []);
1657
- const { rows, columns, typeTable, onToggleColumnOptional } = tableController({
1658
- data: {
1659
- fields: viewResponse?.views?.list?.fields,
1660
- records: dataResponse?.records ?? dataResponse?.groups,
1661
- dataModel: viewResponse?.models?.[String(relation)],
1662
- context: contextObject,
1663
- typeTable: dataResponse?.groups ? "group" : "list"
1664
- }
1665
- });
1666
- const searchControllers = searchController({
1667
- viewData: viewResponse,
1668
- model: relation ?? "",
1669
- context: contextObject,
1670
- domain,
1671
- fieldsList: [
1672
- ...columns?.filter(
1673
- (col) => col?.field?.type_co === "field" && col?.optional !== "hide"
1674
- )?.map((col) => ({ ...col.field })) ?? []
1675
- ]
1676
- });
1677
- const handleCreateNewOnPage = async () => {
1678
- };
1679
- return {
1680
- rows,
1681
- columns,
1682
- optionsObject,
1683
- viewData: viewResponse,
1684
- totalRows: dataResponse?.length ?? 0,
1685
- onToggleColumnOptional,
1686
- typeTable,
1687
- isLoading,
1688
- isFetched,
1689
- isPlaceholderData,
1690
- page,
1691
- pageLimit,
1692
- groupByList,
1693
- selectedRowKeys,
1694
- domain: domainList,
1695
- setPage,
1696
- setDomain,
1697
- setPageLimit,
1698
- setGroupByList,
1699
- setSelectedRowKeys,
1700
- searchController: searchControllers,
1701
- handleCreateNewOnPage,
1702
- specification
1703
- };
1704
- };
1705
-
1706
- // src/widget/basic/many2many-tags-field/controller.ts
1707
- var import_react17 = require("react");
1708
- var import_constants2 = require("@fctc/interface-logic/constants");
1709
- var import_utils11 = require("@fctc/interface-logic/utils");
1710
- var many2manyTagsController = (props) => {
1711
- const {
1712
- relation,
1713
- domain,
1714
- options: optionsFields,
1715
- widget,
1716
- formValues,
1717
- service,
1718
- xNode,
1719
- context: fieldContext,
1720
- onChange,
1721
- methods,
1722
- name
1723
- } = props;
1724
- const isUser = relation === "res.users" || relation === "res.partner";
1725
- const { env } = (0, provider_exports.useEnv)();
1726
- const { action } = useAppProvider();
1727
- const { useGetSelection: useGetSelection3 } = (0, provider_exports.useService)();
1728
- const [options, setOptions] = (0, import_react17.useState)([]);
1729
- const [domainObject, setDomainObject] = (0, import_react17.useState)(null);
1730
- const [isShowModalMany2Many, setIsShowModalMany2Many] = (0, import_react17.useState)(false);
1731
- const addtionalFields = optionsFields ? (0, import_utils11.evalJSONContext)(optionsFields) : null;
1732
- const contextObject = {
1733
- ...(0, import_utils11.evalJSONContext)(action?.context) || {},
1734
- ...fieldContext ?? {},
1735
- ...env?.context
1736
- };
1737
- const parsedFormValues = (0, import_react17.useMemo)(
1738
- () => JSON.parse(
1739
- JSON.stringify({
1740
- ...formValues,
1741
- ...contextObject,
1742
- context: contextObject,
1743
- parent: { ...formValues }
1744
- })
1745
- ) ?? {},
1746
- [formValues, contextObject]
1747
- );
1748
- (0, import_react17.useEffect)(() => {
1749
- const newDomain = (0, import_utils11.evalJSONDomain)(domain, parsedFormValues);
1750
- setDomainObject(
1751
- (prev) => JSON.stringify(prev) === JSON.stringify(newDomain) ? prev : newDomain
1752
- );
1753
- }, [domain, parsedFormValues]);
1754
- const data = {
1755
- model: relation ?? "",
1756
- domain: domainObject,
1757
- specification: {
1758
- id: {},
1759
- name: {},
1760
- display_name: {},
1761
- ...widget && import_constants2.WIDGETAVATAR[widget] ? { image_256: {} } : {},
1762
- ...widget && import_constants2.WIDGETCOLOR[widget] && addtionalFields?.color_field ? { color: {} } : {}
1763
- },
1764
- context: env.context
1765
- };
1766
- const queryKey = [`data_${relation}`, domainObject];
1767
- const {
1768
- data: dataOfSelection,
1769
- refetch,
1770
- isFetching
1771
- } = useGetSelection3({
1772
- data,
1773
- queryKey,
1774
- service,
1775
- xNode,
1776
- enabled: false
1777
- });
1778
- const selectOptions = (0, import_react17.useMemo)(() => {
1779
- return dataOfSelection?.records?.map((val) => ({
1780
- value: val.id,
1781
- label: val.name ?? val.display_name,
1782
- ...val
1783
- })) || [];
1784
- }, [dataOfSelection]);
1785
- (0, import_react17.useEffect)(() => {
1786
- setOptions(selectOptions);
1787
- }, [selectOptions]);
1788
- const fetchMoreOptions = (0, import_react17.useCallback)(() => {
1789
- refetch();
1790
- }, [refetch]);
1791
- const transfer = (data2) => {
1792
- return data2?.map((val) => ({
1793
- id: val.value,
1794
- display_name: val.label
1795
- })) || [];
1796
- };
1797
- const handleChooseRecord = (0, import_react17.useCallback)(
1798
- (idRecord) => {
1799
- const newOption = options.find(
1800
- (option) => option.value === idRecord
1801
- );
1802
- setIsShowModalMany2Many(false);
1803
- },
1804
- [options, methods, name, onChange]
1805
- );
1806
- const handleClose = (0, import_react17.useCallback)(() => setIsShowModalMany2Many(false), []);
1807
- return {
1808
- options,
1809
- transfer,
1810
- isUser,
1811
- isFetching,
1812
- fetchMoreOptions,
1813
- domainObject,
1814
- setDomainObject,
1815
- handleChooseRecord,
1816
- handleClose,
1817
- isShowModalMany2Many,
1818
- setIsShowModalMany2Many
1819
- };
1820
- };
1821
-
1822
- // src/widget/basic/status-bar-field/controller.ts
1823
- var import_react18 = require("react");
1824
- var import_utils12 = require("@fctc/interface-logic/utils");
1825
- var durationController = (props) => {
1826
- const { relation, domain, formValues, name, id, model, onRefetch, enabled } = props;
1827
- const specification = {
1828
- id: 0,
1829
- name: "",
1830
- fold: ""
1831
- };
1832
- const { useGetListData: useGetListData2, useChangeStatus: useChangeStatus2 } = (0, provider_exports.useService)();
1833
- const { env } = (0, provider_exports.useEnv)();
1834
- const [disabled, setDisabled] = (0, import_react18.useState)(false);
1835
- const [modelStatus, setModalStatus] = (0, import_react18.useState)(false);
1836
- const queryKey = [`data-status-duration`, specification];
1837
- const listDataProps = {
1838
- model: relation,
1839
- specification,
1840
- domain: (0, import_utils12.evalJSONDomain)(domain, JSON.parse(JSON.stringify(formValues))),
1841
- limit: 10,
1842
- offset: 0,
1843
- fields: "",
1844
- groupby: [],
1845
- context: {
1846
- lang: env.context.lang
1847
- },
1848
- sort: ""
1849
- };
1850
- const { data: dataResponse } = useGetListData2(
1851
- listDataProps,
1852
- queryKey,
1853
- enabled
1854
- );
1855
- const { mutate: fetchChangeStatus } = useChangeStatus2();
1856
- const handleClick = async (stage_id) => {
1857
- setDisabled(true);
1858
- if (stage_id) {
1859
- fetchChangeStatus(
1860
- {
1861
- data: {
1862
- stage_id,
1863
- name,
1864
- id,
1865
- model,
1866
- lang: env.context.lang
1867
- }
1868
- },
1869
- {
1870
- onSuccess: (res) => {
1871
- if (res) {
1872
- setDisabled(false);
1873
- onRefetch && onRefetch();
1874
- }
1875
- }
1876
- }
1877
- );
1878
- }
1879
- };
1880
- return {
1881
- dataResponse,
1882
- handleClick,
1883
- disabled,
1884
- modelStatus,
1885
- setModalStatus
1886
- };
1887
- };
1888
-
1889
- // src/widget/basic/priority-field/controller.ts
1890
- var import_utils13 = require("@fctc/interface-logic/utils");
1891
- var priorityFieldController = (props) => {
1892
- const { name, model, index, actionData, context, onChange, specification } = props;
1893
- const _context = { ...(0, import_utils13.evalJSONContext)(actionData?.context) };
1894
- const contextObject = { ...context, ..._context };
1895
- const { useSave: useSave3 } = (0, provider_exports.useService)();
1896
- const { mutateAsync: fetchSave } = useSave3();
1897
- const savePriorities = async ({
1898
- value,
1899
- resetPriority
1900
- }) => {
1901
- const priorityValue = value <= 0 ? 0 : value - 1;
1902
- try {
1903
- fetchSave({
1904
- ids: index ? [index] : [],
1905
- data: { [String(name)]: String(priorityValue) },
1906
- model: String(model),
1907
- context: contextObject,
1908
- specification
1909
- });
1910
- if (typeof onChange === "function") {
1911
- onChange(String(name), String(priorityValue));
1912
- }
1913
- } catch (error) {
1914
- if (resetPriority) {
1915
- resetPriority();
1916
- }
1917
- }
1918
- };
1919
- return {
1920
- savePriorities
1921
- };
1922
- };
1923
-
1924
- // src/widget/basic/download-file-field/controller.ts
1925
- var import_react19 = require("react");
1926
- var downloadFileController = () => {
1927
- const inputId = (0, import_react19.useId)();
1928
- const [file, setFile] = (0, import_react19.useState)(null);
1929
- const handleFileChange = (e) => {
1930
- setFile(e.target.files[0]);
1931
- };
1932
- const handleFileDownload = () => {
1933
- const url = URL.createObjectURL(file);
1934
- const link = document.createElement("a");
1935
- link.href = url;
1936
- link.download = file.name;
1937
- document.body.appendChild(link);
1938
- link.click();
1939
- document.body.removeChild(link);
1940
- };
1941
- return {
1942
- inputId,
1943
- file,
1944
- handleFileChange,
1945
- handleFileDownload
1946
- };
1947
- };
1948
-
1949
- // src/widget/basic/download-binary-field/controller.ts
1950
- var downLoadBinaryController = (props) => {
1951
- const { value, defaultValue, formValues } = props;
1952
- const downloadFile = async (url, filename) => {
1953
- try {
1954
- const response = await fetch(url);
1955
- if (!response.ok) throw new Error(`Failed to fetch ${url}`);
1956
- const contentType = response.headers.get("Content-Type") || "";
1957
- let ext = "";
1958
- if (contentType.includes("pdf")) ext = ".pdf";
1959
- else if (contentType.includes("png")) ext = ".png";
1960
- else if (contentType.includes("jpeg") || contentType.includes("jpg"))
1961
- ext = ".jpg";
1962
- else if (contentType.includes("zip")) ext = ".zip";
1963
- else if (contentType.includes("msword")) ext = ".doc";
1964
- else if (contentType.includes("spreadsheet")) ext = ".xls";
1965
- else if (contentType.includes("json")) ext = ".json";
1966
- else if (contentType.includes("text")) ext = ".txt";
1967
- else {
1968
- ext = "";
1969
- }
1970
- const blob = await response.blob();
1971
- const urlBlob = window.URL.createObjectURL(blob);
1972
- const link = document.createElement("a");
1973
- link.href = urlBlob;
1974
- link.download = (filename || "file") + ext;
1975
- document.body.appendChild(link);
1976
- link.click();
1977
- document.body.removeChild(link);
1978
- window.URL.revokeObjectURL(urlBlob);
1979
- } catch (error) {
1980
- console.error("File download failed:", error);
1981
- }
1982
- };
1983
- const handleFileDownload = async (e) => {
1984
- e.stopPropagation();
1985
- await downloadFile(value || defaultValue, formValues?.name);
1986
- };
1987
- return {
1988
- handleFileDownload
1989
- };
1990
- };
1991
-
1992
- // src/widget/basic/copy-link-button/controller.ts
1993
- var import_react20 = require("react");
1994
- var copyTextToClipboard = async (text) => {
1995
- if ("clipboard" in navigator) {
1996
- return await navigator.clipboard.writeText(text);
1997
- } else {
1998
- const textArea = document.createElement("textarea");
1999
- textArea.value = text;
2000
- textArea.style.position = "fixed";
2001
- document.body.appendChild(textArea);
2002
- textArea.focus();
2003
- textArea.select();
2004
- try {
2005
- document.execCommand("copy");
2006
- } finally {
2007
- document.body.removeChild(textArea);
2008
- }
2009
- }
2010
- };
2011
- var copyLinkButtonController = (props) => {
2012
- const { value, defaultValue } = props;
2013
- const [isCopied, setIsCopied] = (0, import_react20.useState)(false);
2014
- const handleCopyToClipboard = async (value2) => {
2015
- await copyTextToClipboard(value2);
2016
- setIsCopied(true);
2017
- setTimeout(() => setIsCopied(false), 2e3);
2018
- };
2019
- const propValue = value || defaultValue;
2020
- return {
2021
- isCopied,
2022
- handleCopyToClipboard,
2023
- propValue
2024
- };
2025
- };
2026
-
2027
- // src/widget/basic/color-field/color-controller.ts
2028
- var import_utils14 = require("@fctc/interface-logic/utils");
2029
- var colorFieldController = (props) => {
2030
- const { value, isForm, name, formValues, idForm, model, actionData } = props;
2031
- const { env } = (0, provider_exports.useEnv)();
2032
- const { useSave: useSave3 } = (0, provider_exports.useService)();
2033
- const _context = { ...(0, import_utils14.evalJSONContext)(actionData?.context) || {} };
2034
- const contextObject = { ...env.context, ..._context };
2035
- const idDefault = isForm ? idForm : formValues?.id;
2036
- const { mutate: onSave } = useSave3();
2037
- const savePickColor = async (colorObject) => {
2038
- const { id } = colorObject;
2039
- if (value === id) return;
2040
- try {
2041
- onSave({
2042
- ids: idDefault !== null ? [idDefault] : [],
2043
- model: String(model),
2044
- data: { [String(name)]: id },
2045
- specification: {
2046
- name: {},
2047
- color: {}
2048
- },
2049
- context: contextObject
2050
- });
2051
- } catch (error) {
2052
- console.log(error);
2053
- }
2054
- };
2055
- return {
2056
- savePickColor
2057
- };
2058
- };
2059
-
2060
- // src/widget/basic/binary-field/controller.ts
2061
- var import_react21 = require("react");
2062
- var binaryFieldController = (props) => {
2063
- const {
2064
- name,
2065
- methods,
2066
- readonly = false,
2067
- filename,
2068
- onChange: handleOnchange,
2069
- service,
2070
- xNode,
2071
- path,
2072
- rootField,
2073
- index,
2074
- value
2075
- } = props;
2076
- const { useUploadFile: useUploadFile2 } = (0, provider_exports.useService)();
2077
- const { mutateAsync } = useUploadFile2();
2078
- const [url, setUrl] = (0, import_react21.useState)(value || null);
2079
- const [fileInfo, setFileInfo] = (0, import_react21.useState)(null);
2080
- (0, import_react21.useEffect)(() => {
2081
- if (!value) {
2082
- setUrl(null);
2083
- setFileInfo(null);
2084
- return;
2085
- }
2086
- fetchFileMeta(value);
2087
- }, [value]);
2088
- const formatSize = (bytes) => {
2089
- if (bytes < 1024) return bytes + " B";
2090
- let kb = bytes / 1024;
2091
- if (kb < 1024) return kb.toFixed(2) + " KB";
2092
- let mb = kb / 1024;
2093
- if (mb < 1024) return mb.toFixed(2) + " MB";
2094
- return (mb / 1024).toFixed(2) + " GB";
2095
- };
2096
- const fetchFileMeta = async (url2) => {
2097
- try {
2098
- const res = await fetch(url2, { method: "HEAD" });
2099
- const size = res.headers.get("content-length") || "";
2100
- let type = res.headers.get("content-type") || "";
2101
- const date = res.headers.get("last-modified") || "";
2102
- const guessed = guessTypeFromUrl(url2);
2103
- if (guessed) type = guessed;
2104
- setFileInfo({
2105
- size: size ? formatSize(Number(size)) : "--",
2106
- type,
2107
- date: date ? new Date(date).toLocaleString() : "--"
2108
- });
2109
- setUrl(url2);
2110
- } catch (e) {
2111
- console.error(e);
2112
- }
2113
- };
2114
- const onUploadFile = async (formData) => {
2115
- const res = await mutateAsync({
2116
- formData,
2117
- service,
2118
- xNode,
2119
- path
2120
- });
2121
- const url2 = res?.url;
2122
- methods?.setValue(name, url2, { shouldDirty: true });
2123
- handleOnchange && handleOnchange(name ?? "", url2);
2124
- if (filename) {
2125
- methods?.setValue(
2126
- rootField ? `${rootField?.name}.${index}.${filename}` : filename,
2127
- url2?.split("/").pop(),
2128
- { shouldDirty: true }
2129
- );
2130
- handleOnchange && handleOnchange(
2131
- rootField ? `${rootField?.name}.${index}.${filename}` : filename,
2132
- url2?.split("/").pop()
2133
- );
2134
- }
2135
- setUrl(url2);
2136
- fetchFileMeta(url2);
2137
- return url2;
2138
- };
2139
- const onDeleteFile = () => {
2140
- if (filename) {
2141
- methods?.setValue(
2142
- rootField ? `${rootField?.name}.${index}.${filename}` : filename,
2143
- null,
2144
- { shouldDirty: true }
2145
- );
2146
- handleOnchange && handleOnchange(
2147
- rootField ? `${rootField?.name}.${index}.${filename}` : filename,
2148
- null
2149
- );
2150
- }
2151
- setUrl(null);
2152
- setFileInfo(null);
2153
- methods?.setValue(name, null, { shouldDirty: true });
2154
- handleOnchange && handleOnchange(name ?? "", null);
2155
- };
2156
- return {
2157
- onUploadFile,
2158
- onDeleteFile,
2159
- fileInfo,
2160
- url
2161
- };
2162
- };
2163
-
2164
- // src/widget/basic/many2many-binary-field/controller.tsx
2165
- var import_react22 = require("react");
2166
- var many2manyBinaryController = (props) => {
2167
- const {
2168
- name,
2169
- methods,
2170
- value,
2171
- onChange: handleOnchange,
2172
- service,
2173
- xNode,
2174
- path
2175
- } = props;
2176
- const inputId = (0, import_react22.useId)();
2177
- const { useUploadFile: useUploadFile2 } = (0, provider_exports.useService)();
2178
- const { mutateAsync } = useUploadFile2();
2179
- const binaryRef = (0, import_react22.useRef)(null);
2180
- const [initialFiles, setInitialFiles] = (0, import_react22.useState)(
2181
- Array.isArray(value) ? value : value ? [value] : []
2182
- );
2183
- const checkIsImageLink = (url) => {
2184
- const imageExtensions = /\.(jpg|jpeg|png|gif|bmp|webp|svg|tiff|ico)$/i;
2185
- return imageExtensions.test(url) || isBase64Image(url) || isBlobUrl(url);
2186
- };
2187
- const sanitizeForBE = (list) => list.filter((x) => x?.datas && !isBlobUrl(x.datas)).map((x) => ({ name: x.name, datas: x.datas, mimetype: x.mimetype }));
2188
- const isBase64Image = (str) => {
2189
- const base64Regex = /^data:image\/(png|jpeg|jpg|gif|webp);base64,/;
2190
- if (!base64Regex.test(str)) {
2191
- return false;
2192
- }
2193
- try {
2194
- const base64Data = str.split(",")[1];
2195
- return !!base64Data && atob(base64Data).length > 0;
2196
- } catch (error) {
2197
- return false;
2198
- }
2199
- };
2200
- const handleFileChange = async (files, e, oldValues) => {
2201
- try {
2202
- const uploadedUrls = await Promise.all(
2203
- files.map(async (f) => {
2204
- const formData = new FormData();
2205
- formData.append("file", f);
2206
- const res = await mutateAsync({ formData, service, xNode, path });
2207
- return res?.url;
2208
- })
2209
- );
2210
- const uploadedItems = files.map((f, i) => ({
2211
- name: f.name,
2212
- datas: uploadedUrls[i] ?? "",
2213
- mimetype: f.type
2214
- }));
2215
- const finalList = [...oldValues, ...uploadedItems];
2216
- methods?.setValue(name, finalList, { shouldDirty: true });
2217
- const payloadForBE = sanitizeForBE(finalList);
2218
- handleOnchange && handleOnchange(name ?? "", payloadForBE);
2219
- } catch (err) {
2220
- console.error(err);
2221
- } finally {
2222
- e.target.value = "";
2223
- }
2224
- };
2225
- const handleRemoveAt = (idx) => {
2226
- const current = methods?.getValues(name) || [];
2227
- const next = current.filter((_, i) => i !== idx);
2228
- setInitialFiles((p) => p.filter((_, i) => i !== idx));
2229
- methods?.setValue(name, next.length ? next : null, { shouldDirty: true });
2230
- const payloadForBE = next.length ? sanitizeForBE(next) : null;
2231
- handleOnchange && handleOnchange(name ?? "", payloadForBE);
2232
- };
2233
- const handleRemoveAll = () => {
2234
- setInitialFiles([]);
2235
- methods?.setValue(name, null, { shouldDirty: true });
2236
- handleOnchange && handleOnchange(name ?? "", null);
2237
- };
2238
- return {
2239
- inputId,
2240
- initialFiles,
2241
- binaryRef,
2242
- handleFileChange,
2243
- handleRemoveAt,
2244
- handleRemoveAll,
2245
- checkIsImageLink,
2246
- setInitialFiles
2247
- };
2248
- };
2249
-
2250
- // src/widget/basic/provider-einvoice-field/controller.ts
2251
- var providerEinvoiceFieldController = (props) => {
2252
- const { relation, formValues, options: fieldOptions, xNode } = props;
2253
- const { env } = (0, provider_exports.useEnv)();
2254
- const { action } = useAppProvider();
2255
- const { useGetSelection: useGetSelection3 } = (0, provider_exports.useService)();
2256
- const contextObject = {
2257
- ...(typeof action?.context === "string" ? (0, utils_exports.evalJSONContext)(action?.context) : action?.context) || {},
2258
- ...env?.context
2259
- };
2260
- const optionsObject = typeof fieldOptions === "string" ? (0, utils_exports.evalJSONContext)(fieldOptions, {
2261
- ...formValues,
2262
- ...contextObject,
2263
- context: contextObject,
2264
- parent: { ...formValues }
2265
- }) : fieldOptions;
2266
- const data = {
2267
- model: optionsObject?.model,
2268
- domain: optionsObject?.domain,
2269
- context: {
2270
- ...contextObject,
2271
- ...optionsObject?.context
2272
- },
2273
- specification: optionsObject?.specification
2274
- };
2275
- const { data: listDataCard } = useGetSelection3({
2276
- data,
2277
- queryKey: [`data_${relation}`],
2278
- enabled: true,
2279
- service: optionsObject?.service,
2280
- xNode
2281
- });
2282
- return {
2283
- listDataCard
2284
- };
2285
- };
2286
-
2287
- // src/widget/advance/table/table-head/controller.ts
2288
- var import_react23 = require("react");
2289
- var tableHeadController = (props) => {
2290
- const {
2291
- typeTable,
2292
- rows,
2293
- tableRef,
2294
- groupByList,
2295
- selectedRowKeys,
2296
- setSelectedRowKeys
2297
- } = props;
2298
- const { rowIds: recordIds } = useGetRowIds(tableRef);
2299
- const selectedRowKeysRef = (0, import_react23.useRef)(recordIds);
2300
- const isGroupTable = typeTable === "group";
2301
- const recordsCheckedGroup = (0, import_react23.useMemo)(() => {
2302
- if (!rows || !groupByList) return 0;
2303
- const groupBy = typeof groupByList === "object" ? groupByList?.contexts?.[0]?.group_by : void 0;
2304
- return countSum(rows, groupBy);
2305
- }, [rows, groupByList]);
2306
- const isAllGroupChecked = (0, import_react23.useMemo)(() => {
2307
- if (!isGroupTable || !selectedRowKeys?.length) return false;
2308
- const selectedLength = selectedRowKeys.filter((id) => id !== -1).length;
2309
- const allRecordsSelected = recordIds.length === selectedRowKeys.length ? recordIds.length === selectedLength : false;
2310
- const allGroupsSelected = recordsCheckedGroup === selectedRowKeys.length;
2311
- return allGroupsSelected || allRecordsSelected;
2312
- }, [isGroupTable, selectedRowKeys, recordIds, recordsCheckedGroup]);
2313
- const isAllNormalChecked = (0, import_react23.useMemo)(() => {
2314
- if (isGroupTable || !selectedRowKeys?.length || !rows?.length) return false;
2315
- return selectedRowKeys.length === rows.length && selectedRowKeys.every(
2316
- (id) => rows.some((record) => record.id === id)
2317
- );
2318
- }, [isGroupTable, selectedRowKeys, rows]);
2319
- const checkedAll = isAllGroupChecked || isAllNormalChecked;
2320
- const handleCheckBoxAll = (event) => {
2321
- if (event?.target?.checked && typeTable === "list") {
2322
- const allRowKeys = Array.isArray(rows) ? rows.map((record) => record?.id) : [];
2323
- setSelectedRowKeys(allRowKeys);
2324
- } else if (event?.target?.checked && typeTable === "group") {
2325
- const rowsIDs = document.querySelectorAll("tr[data-row-id]");
2326
- const ids = Array.from(rowsIDs)?.map(
2327
- (row) => Number(row?.getAttribute("data-row-id"))
2328
- );
2329
- if (ids?.length > 0) {
2330
- setSelectedRowKeys(ids);
2331
- } else {
2332
- const sum = countSum(
2333
- rows,
2334
- typeof groupByList === "object" ? groupByList?.contexts?.[0]?.group_by : void 0
2335
- );
2336
- const keys = Array.from({ length: sum }, (_) => void 0);
2337
- setSelectedRowKeys(keys);
2338
- }
2339
- if (selectedRowKeysRef) {
2340
- selectedRowKeysRef.current = [];
2341
- }
2342
- } else {
2343
- setSelectedRowKeys([]);
2344
- }
2345
- };
2346
- return {
2347
- handleCheckBoxAll,
2348
- checkedAll,
2349
- selectedRowKeysRef
2350
- };
2351
- };
2352
-
2353
- // src/widget/advance/table/table-view/controller.ts
2354
- var import_react24 = require("react");
2355
- var import_utils18 = require("@fctc/interface-logic/utils");
2356
- var tableController = ({ data }) => {
2357
- const [rows, setRows] = (0, import_react24.useState)([]);
2358
- const [columnVisibility, setColumnVisibility] = (0, import_react24.useState)({});
2359
- const dataModelFields = (0, import_react24.useMemo)(() => {
2360
- return data?.fields?.map((field) => ({
2361
- ...data.dataModel?.[field?.name],
2362
- ...field,
2363
- string: field?.string || data.dataModel?.[field?.name]?.string
2364
- })) ?? [];
2365
- }, [data?.fields, data?.dataModel]);
2366
- const mergeFields = (0, import_react24.useMemo)(
2367
- () => mergeButtons(dataModelFields),
2368
- [dataModelFields]
2369
- );
2370
- const transformData = (0, import_react24.useCallback)(
2371
- (dataList) => {
2372
- if (!dataList) return [];
2373
- return dataList.map((item) => {
2374
- const transformedItem = { ...item };
2375
- Object.keys(item).forEach((field) => {
2376
- if (field !== "__domain") {
2377
- if (item[field] && typeof item[field] === "object" && item[field].display_name) {
2378
- transformedItem[field] = item[field];
2379
- } else if (Array.isArray(item[field]) && item[field].length > 0) {
2380
- if (data.typeTable === "group" && item[field]?.length === 2 && typeof item[field]?.[1] === "string") {
2381
- transformedItem["string"] = item[field]?.[1];
2382
- }
2383
- transformedItem[field] = item[field];
2384
- }
2385
- }
2386
- });
2387
- return item.display_name ? { ...transformedItem, item: item.display_name } : transformedItem;
2388
- });
2389
- },
2390
- [data?.typeTable]
2391
- );
2392
- (0, import_react24.useEffect)(() => {
2393
- setRows(transformData(data?.records));
2394
- }, [data?.records, transformData]);
2395
- const columns = (0, import_react24.useMemo)(() => {
2396
- try {
2397
- return mergeFields?.filter((item) => {
2398
- return item?.widget !== "details_Receive_money" && !(item?.column_invisible ? import_utils18.domainHelper.matchDomains(
2399
- data.context,
2400
- item?.column_invisible
2401
- ) : item?.invisible ? import_utils18.domainHelper.matchDomains(data.context, item?.invisible) : false);
2402
- })?.map((field) => {
2403
- const overridden = columnVisibility[field?.name];
2404
- return {
2405
- name: field?.name,
2406
- optional: overridden ?? field?.optional,
2407
- title: field?.type_co === "button" ? "" : field?.string,
2408
- field: { ...field }
2409
- };
2410
- }) ?? [];
2411
- } catch (error) {
2412
- console.error("Error in useTable:", error);
2413
- return [];
2414
- }
2415
- }, [mergeFields, data?.context, columnVisibility]);
2416
- const onToggleColumnOptional = (0, import_react24.useCallback)((item) => {
2417
- setColumnVisibility((prev) => ({
2418
- ...prev,
2419
- [item?.name]: item?.optional === "show" ? "hide" : "show"
2420
- }));
2421
- }, []);
2422
- return {
2423
- rows,
2424
- columns,
2425
- onToggleColumnOptional,
2426
- typeTable: data?.typeTable
2427
- };
2428
- };
2429
-
2430
- // src/widget/advance/table/table-group/controller.ts
2431
- var import_react25 = require("react");
2432
- var tableGroupController = (props) => {
2433
- const { env } = (0, provider_exports.useEnv)();
2434
- const { useGetListData: useGetListData2 } = (0, provider_exports.useService)();
2435
- const {
2436
- columns,
2437
- row,
2438
- model,
2439
- viewData,
2440
- level,
2441
- specification,
2442
- context,
2443
- checkedAll,
2444
- groupByList,
2445
- setSelectedRowKeys
2446
- } = props;
2447
- const [pageGroup, setPageGroup] = (0, import_react25.useState)(0);
2448
- const [isShowGroup, setIsShowGroup] = (0, import_react25.useState)(false);
2449
- const [colEmptyGroup, setColEmptyGroup] = (0, import_react25.useState)({
2450
- fromStart: 1,
2451
- fromEnd: 1
2452
- });
2453
- const domain = row?.__domain;
2454
- const processedData = (0, import_react25.useMemo)(() => {
2455
- const calculateColSpanEmpty = () => {
2456
- const startIndex = columns.findIndex(
2457
- (col) => col.field.type === "monetary" && typeof row[col.key] === "number" || col.field.aggregator === "sum"
2458
- );
2459
- const endIndex = columns.findLastIndex(
2460
- (col) => col.field.type === "monetary" && typeof row[col.key] === "number" || col.field.aggregator !== "sum"
2461
- );
2462
- const fromStart = startIndex === -1 ? columns.length : startIndex;
2463
- const fromEnd = endIndex === -1 ? columns.length : columns.length - 1 - endIndex;
2464
- setColEmptyGroup({ fromStart: fromStart + 1, fromEnd: fromEnd + 1 });
2465
- return { fromStart: fromStart + 1, fromEnd: fromEnd + 1 };
2466
- };
2467
- return calculateColSpanEmpty();
2468
- }, [columns, row]);
2469
- const shouldFetchData = (0, import_react25.useMemo)(() => {
2470
- return !!isShowGroup;
2471
- }, [isShowGroup]);
2472
- const enabled = shouldFetchData && !!processedData;
2473
- const listDataProps = {
2474
- model,
2475
- specification,
2476
- domain,
2477
- context,
2478
- offset: pageGroup * 10,
2479
- fields: groupByList?.fields,
2480
- groupby: [groupByList?.contexts[level]?.group_by],
2481
- limit: 10
2482
- };
2483
- const queryKey = [
2484
- `data-${model}-level_${level}-row-${row?.id}`,
2485
- specification,
2486
- domain,
2487
- pageGroup
2488
- ];
2489
- const {
2490
- data: dataGroup,
2491
- isFetched: isDataGroupFetched,
2492
- isLoading,
2493
- isFetching,
2494
- isPlaceholderData: isDataPlaceHolder
2495
- } = useGetListData2(listDataProps, queryKey, enabled);
2496
- const {
2497
- columns: columnsGroup,
2498
- rows: rowsGroup,
2499
- typeTable: typeTableGroup
2500
- } = tableController({
2501
- data: {
2502
- fields: viewData?.views?.list?.fields,
2503
- records: dataGroup?.records ?? dataGroup?.groups,
2504
- dataModel: viewData?.models?.[model],
2505
- context: env.context,
2506
- typeTable: dataGroup?.groups ? "group" : "list"
2507
- }
2508
- });
2509
- const group_by_field_name = groupByList?.contexts[level - 1]?.group_by;
2510
- const nameGroup = Array.isArray(row[group_by_field_name]) ? row?.string ?? row[`${group_by_field_name}`][1] : viewData?.models?.[model]?.[group_by_field_name]?.selection ? viewData.models[model][group_by_field_name].selection.find(
2511
- (selectItem) => selectItem?.[0] === row[group_by_field_name]
2512
- )?.[1] : row[group_by_field_name];
2513
- const toggleShowGroup = () => setIsShowGroup((prev) => !prev);
2514
- return {
2515
- // onExpandChildGroup,
2516
- colEmptyGroup,
2517
- isShowGroup,
2518
- isDataGroupFetched,
2519
- isDataPlaceHolder,
2520
- // nameGroupWithCount,
2521
- columnsGroup,
2522
- rowsGroup,
2523
- dataGroup,
2524
- pageGroup,
2525
- setPageGroup,
2526
- typeTableGroup
2527
- };
2528
- };
2529
-
2530
- // src/widget/advance/search/controller.ts
2531
- var import_moment2 = __toESM(require("moment"));
2532
- var import_react26 = require("react");
2533
-
2534
- // src/constants.ts
2535
- var constants_exports = {};
2536
- __reExport(constants_exports, require("@fctc/interface-logic/constants"));
2537
-
2538
- // src/widget/advance/search/controller.ts
2539
- var searchController = ({
2540
- viewData,
2541
- model,
2542
- domain,
2543
- context,
2544
- fieldsList
2545
- }) => {
2546
- const { env } = (0, provider_exports.useEnv)();
2547
- const [filterBy, setFilterBy] = (0, import_react26.useState)(null);
2548
- const [searchBy, setSearchBy] = (0, import_react26.useState)(null);
2549
- const [groupBy, setGroupBy] = (0, import_react26.useState)(null);
2550
- const [selectedTags, setSelectedTags] = (0, import_react26.useState)(null);
2551
- const [searchString, setSearchString] = (0, import_react26.useState)("");
2552
- const [searchMap, setSearchMap] = (0, import_react26.useState)({});
2553
- const [hoveredIndex, setHoveredIndex] = (0, import_react26.useState)(0);
2554
- const [hoveredIndexSearchList, setHoveredIndexSearchList] = (0, import_react26.useState)(0);
2555
- const actionContext = typeof context === "string" ? (0, utils_exports.evalJSONContext)(context) : context;
2556
- const contextSearch = { ...env.context, ...actionContext };
2557
- const domainAction = domain ? Array.isArray(domain) ? [...domain] : (0, utils_exports.evalJSONDomain)(domain, contextSearch) : [];
2558
- const clearSearch = () => {
2559
- setFilterBy([]);
2560
- setGroupBy([]);
2561
- setSearchBy([]);
2562
- setSelectedTags(null);
2563
- setSearchString("");
2564
- setSearchMap({});
2565
- };
2566
- const fetchData = async () => {
2567
- if (viewData) {
2568
- try {
2569
- const dataModel = viewData?.models?.[model];
2570
- const searchViews = viewData?.views?.search;
2571
- const searchByItems = searchViews?.search_by?.filter(
2572
- (item) => !utils_exports.domainHelper.matchDomains(contextSearch, item.invisible)
2573
- )?.map(
2574
- ({ string, name, filter_domain, operator, widget }, index) => ({
2575
- dataIndex: index,
2576
- title: string ?? dataModel?.[name]?.string,
2577
- name: name ?? dataModel?.[name]?.name,
2578
- filter_domain,
2579
- operator,
2580
- widget,
2581
- type: dataModel?.[name]?.type
2582
- })
2583
- );
2584
- const filterByItems = searchViews?.filter_by.filter((item) => {
2585
- return !utils_exports.domainHelper.matchDomains(contextSearch, item?.invisible);
2586
- })?.map((item) => ({ ...item, active: false }));
2587
- const groupByItems = searchViews?.group_by.filter(
2588
- (item) => !utils_exports.domainHelper.matchDomains(contextSearch, item?.invisible)
2589
- ).map((item) => ({
2590
- ...item,
2591
- string: item.string ?? viewData?.models?.[model]?.[item?.name?.split("group_by_")?.[1]]?.string
2592
- }));
2593
- setSearchBy(searchByItems);
2594
- setFilterBy(filterByItems);
2595
- setGroupBy(groupByItems);
2596
- } catch (error) {
2597
- console.error("Error fetching data:", error);
2598
- }
2599
- }
2600
- };
2601
- (0, import_react26.useEffect)(() => {
2602
- fetchData();
2603
- }, [model, viewData]);
2604
- const onChangeSearchInput = (search_string) => {
2605
- setSearchString(search_string);
2606
- };
2607
- const removeKeyFromSearchMap = ({
2608
- key,
2609
- item
2610
- }) => {
2611
- const values = searchMap[key];
2612
- if (!values) return searchMap;
2613
- const newSearchMap = { ...searchMap };
2614
- if (item) {
2615
- const filtered = values.filter((value) => value.name !== item.name);
2616
- if (filtered.length > 0) {
2617
- newSearchMap[key] = filtered;
2618
- } else {
2619
- delete newSearchMap[key];
2620
- }
2621
- } else {
2622
- delete newSearchMap[key];
2623
- }
2624
- setSearchMap(newSearchMap);
2625
- };
2626
- const updateSearchMap = ({ key, item }) => {
2627
- const newSearchMap = { ...searchMap };
2628
- const currentValues = searchMap[key] ?? [];
2629
- newSearchMap[key] = [...currentValues, item];
2630
- setSearchMap(newSearchMap);
2631
- };
2632
- const removeSearchItems = (key, item) => {
2633
- removeKeyFromSearchMap({ key: String(key), item });
2634
- };
2635
- const addSearchItems = (key, newItem) => {
2636
- updateSearchMap({ key, item: newItem });
2637
- };
2638
- const formatDomain = () => {
2639
- if (domainAction) {
2640
- const domain2 = [];
2641
- if (Array.isArray(domainAction) && domainAction.length > 0) {
2642
- if (Object.keys(searchMap).some((key) => !key.includes(constants_exports.SearchType.GROUP))) {
2643
- domain2.push("&");
2644
- }
2645
- domainAction.forEach((domainItem) => {
2646
- domain2.push(domainItem);
2647
- });
2648
- }
2649
- Object.keys(searchMap).forEach((key, keyIndex, keys) => {
2650
- if (!key?.includes(constants_exports.SearchType.GROUP)) {
2651
- if (keys.length > 1 && keyIndex < keys.length - 1) {
2652
- domain2.push("&");
2653
- }
2654
- const valuesOfKey = searchMap[key];
2655
- valuesOfKey.forEach((value, index) => {
2656
- if (index < valuesOfKey.length - 1) {
2657
- domain2.push("|");
2658
- }
2659
- if (value.domain) {
2660
- domain2.push(...value.domain);
2661
- return;
2662
- }
2663
- let valueDomainItem = value?.value;
2664
- if (value?.modelType === "date") {
2665
- valueDomainItem = validateAndParseDate(value?.value);
2666
- } else if (value?.modelType === "datetime") {
2667
- if (value?.operator === "<=" || value?.operator === "<") {
2668
- const parsedDate = validateAndParseDate(value?.value, true);
2669
- const hasTime = (0, import_moment2.default)(value?.value).format("HH:mm:ss") !== "00:00:00";
2670
- valueDomainItem = hasTime ? (0, import_moment2.default)(parsedDate).format("YYYY-MM-DD HH:mm:ss") : (0, import_moment2.default)(parsedDate).add(1, "day").subtract(1, "second").format("YYYY-MM-DD HH:mm:ss");
2671
- } else {
2672
- valueDomainItem = validateAndParseDate(value?.value, true);
2673
- }
2674
- }
2675
- const operator = value?.modelType === "date" || value?.modelType === "datetime" || value?.modelType === "boolean" || value?.modelType === "integer" ? value?.operator ?? "=" : value.operator ?? "ilike";
2676
- domain2.push([value.name, operator, valueDomainItem]);
2677
- });
2678
- }
2679
- });
2680
- return [...domain2];
2681
- }
2682
- };
2683
- const setTagSearch = (0, import_react26.useCallback)(
2684
- (updatedMap) => {
2685
- if (!updatedMap) return;
2686
- const tagsSearch = Object.entries(updatedMap).map(
2687
- ([key, objValues]) => {
2688
- const {
2689
- title,
2690
- name,
2691
- groupIndex,
2692
- type,
2693
- widget,
2694
- modelType,
2695
- dataIndex
2696
- } = objValues[0];
2697
- if (!key?.includes(constants_exports.SearchType.GROUP)) {
2698
- const values = objValues?.map((objValue) => objValue.value);
2699
- return {
2700
- title,
2701
- name: type === constants_exports.SearchType.SEARCH ? `${constants_exports.SearchType.SEARCH}_${String(dataIndex)}` : groupIndex ?? name,
2702
- values,
2703
- type,
2704
- widget,
2705
- modelType
2706
- };
2707
- } else {
2708
- const contexts = [];
2709
- let groupValues = [];
2710
- objValues?.forEach((objValue) => {
2711
- const { context: context2, value, active, groupIndex: groupIndex2, isDefault } = objValue;
2712
- const indexAppend = groupIndex2 != null ? groupIndex2 : viewData?.views?.search?.filters_by?.length ?? 0;
2713
- contexts.push(
2714
- ...Array.isArray(context2?.group_by) ? context2.group_by.map((item) => ({ group_by: item })) : [context2]
2715
- );
2716
- groupValues[indexAppend] = {
2717
- contexts: [
2718
- ...Array.isArray(context2?.group_by) ? context2.group_by.map((item) => ({
2719
- group_by: item
2720
- })) : [context2]
2721
- ],
2722
- strings: isDefault ? [value] : [...groupValues[indexAppend]?.strings ?? [], value]
2723
- };
2724
- });
2725
- const fields = [
2726
- ...new Set(fieldsList?.map((item) => item?.name))
2727
- ];
2728
- const groupByTag = {
2729
- title,
2730
- values: groupValues?.filter(
2731
- (item) => item !== void 0
2732
- ),
2733
- type,
2734
- contexts,
2735
- fields
2736
- };
2737
- return groupByTag;
2738
- }
2739
- }
2740
- );
2741
- setSelectedTags(tagsSearch);
2742
- setSearchString("");
2743
- },
2744
- [searchMap]
2745
- );
2746
- (0, import_react26.useEffect)(() => {
2747
- setTagSearch(searchMap);
2748
- }, [searchMap]);
2749
- const handleAddTagSearch = (tag) => {
2750
- const { domain: domain2, groupIndex, value, type, context: context2, dataIndex } = tag;
2751
- const domainFormat = new utils_exports.domainHelper.Domain(domain2);
2752
- if (type === constants_exports.SearchType.FILTER) {
2753
- addSearchItems(`${constants_exports.SearchType.FILTER}_${groupIndex}`, {
2754
- ...tag,
2755
- domain: domain2 ? domainFormat.toList(context2) : null
2756
- });
2757
- } else if (type === constants_exports.SearchType.SEARCH) {
2758
- addSearchItems(`${constants_exports.SearchType.SEARCH}_${String(dataIndex)}`, {
2759
- ...tag,
2760
- domain: domain2 ? domainFormat.toList({
2761
- ...context2,
2762
- self: value
2763
- }) : null
2764
- });
2765
- } else if (type === constants_exports.SearchType.GROUP) {
2766
- addSearchItems(`${constants_exports.SearchType.GROUP}`, {
2767
- ...tag,
2768
- domain: domain2 ? domainFormat.toList({
2769
- context: context2,
2770
- self: value
2771
- }) : null
2772
- });
2773
- }
2774
- };
2775
- const onKeyDown = (e) => {
2776
- if (!searchBy || searchBy.length === 0) return;
2777
- switch (e.key) {
2778
- case "Backspace": {
2779
- if (!searchString && selectedTags && selectedTags.length > 0) {
2780
- const lastTag = selectedTags[selectedTags.length - 1];
2781
- if (!lastTag) return;
2782
- const key = lastTag.type === constants_exports.SearchType.GROUP ? constants_exports.SearchType.GROUP : lastTag.name;
2783
- removeKeyFromSearchMap({ key: String(key) });
2784
- }
2785
- break;
2786
- }
2787
- case "ArrowDown": {
2788
- e.preventDefault();
2789
- setHoveredIndex((prev) => {
2790
- const maxIndex = searchBy.length - 1;
2791
- const next = prev < maxIndex ? prev + 1 : prev;
2792
- setHoveredIndexSearchList(next);
2793
- return next;
2794
- });
2795
- break;
2796
- }
2797
- case "ArrowUp": {
2798
- e.preventDefault();
2799
- setHoveredIndex((prev) => {
2800
- const next = prev > 0 ? prev - 1 : prev;
2801
- setHoveredIndexSearchList(next);
2802
- return next;
2803
- });
2804
- break;
2805
- }
2806
- case "Enter": {
2807
- e.preventDefault();
2808
- if (!searchString.trim()) return;
2809
- const head = searchBy[hoveredIndex];
2810
- if (!head) return;
2811
- handleAddTagSearch({
2812
- title: head.title,
2813
- name: head.name,
2814
- value: searchString,
2815
- type: constants_exports.SearchType.SEARCH,
2816
- domain: head.filter_domain,
2817
- operator: head.operator,
2818
- dataIndex: head.dataIndex,
2819
- widget: head.widget,
2820
- modelType: head.type
2821
- });
2822
- break;
2823
- }
2824
- default:
2825
- break;
2826
- }
2827
- };
2828
- const handleMouseEnter = (index) => {
2829
- setHoveredIndexSearchList(index);
2830
- };
2831
- const handleMouseLeave = () => {
2832
- setHoveredIndexSearchList(null);
2833
- };
2834
- return {
2835
- groupBy,
2836
- searchBy,
2837
- filterBy,
2838
- selectedTags,
2839
- searchString,
2840
- setFilterBy,
2841
- setGroupBy,
2842
- setSearchBy,
2843
- clearSearch,
2844
- setSelectedTags,
2845
- removeSearchItems,
2846
- onSearchString: onChangeSearchInput,
2847
- handleAddTagSearch,
2848
- domain: formatDomain(),
2849
- context: contextSearch,
2850
- onKeyDown,
2851
- handleMouseEnter,
2852
- handleMouseLeave,
2853
- hoveredIndexSearchList
2854
- };
2855
- };
2856
-
2857
- // src/index.ts
2858
- __reExport(index_exports, utils_exports, module.exports);
2859
- __reExport(index_exports, constants_exports, module.exports);
2860
-
2861
- // src/environment.ts
2862
- var environment_exports = {};
2863
- __reExport(environment_exports, require("@fctc/interface-logic/environment"));
2864
-
2865
- // src/index.ts
2866
- __reExport(index_exports, environment_exports, module.exports);
2867
- __reExport(index_exports, provider_exports, module.exports);
2868
-
2869
- // src/services.ts
2870
- var services_exports = {};
2871
- __reExport(services_exports, require("@fctc/interface-logic/services"));
2872
-
2873
- // src/index.ts
2874
- __reExport(index_exports, services_exports, module.exports);
2875
-
2876
- // src/types.ts
2877
- var types_exports = {};
2878
- __reExport(types_exports, require("@fctc/interface-logic/types"));
2879
-
2880
- // src/index.ts
2881
- __reExport(index_exports, types_exports, module.exports);
2882
- // Annotate the CommonJS export names for ESM import in node:
2883
- 0 && (module.exports = {
2884
- AppProvider,
2885
- STORAGES,
2886
- binaryFieldController,
2887
- colorFieldController,
2888
- copyLinkButtonController,
2889
- countSum,
2890
- downLoadBinaryController,
2891
- downloadFileController,
2892
- durationController,
2893
- guessTypeFromUrl,
2894
- isObjectEmpty,
2895
- languages,
2896
- many2manyBinaryController,
2897
- many2manyFieldController,
2898
- many2manyTagsController,
2899
- many2oneButtonController,
2900
- many2oneFieldController,
2901
- mergeButtons,
2902
- priorityFieldController,
2903
- providerEinvoiceFieldController,
2904
- searchController,
2905
- setStorageItemAsync,
2906
- statusDropdownController,
2907
- tableController,
2908
- tableGroupController,
2909
- tableHeadController,
2910
- useAddEntity,
2911
- useAppProvider,
2912
- useButton,
2913
- useCallAction,
2914
- useChangeOrderPreparationState,
2915
- useChangeStatus,
2916
- useCheckPayment,
2917
- useCompany,
2918
- useConfig,
2919
- useCreateEntity,
2920
- useCreatePosConfig,
2921
- useCreateSession,
2922
- useDebounce,
2923
- useDelete,
2924
- useDeleteComment,
2925
- useDeleteEntity,
2926
- useDetail,
2927
- useDuplicateRecord,
2928
- useExecuteImport,
2929
- useExportExcel,
2930
- useForgotPassword,
2931
- useForgotPasswordSSO,
2932
- useGenSerialNumber,
2933
- useGeneratePaymentQrInfo,
2934
- useGet2FAMethods,
2935
- useGetASession,
2936
- useGetAccessByCode,
2937
- useGetAction,
2938
- useGetActionDetail,
2939
- useGetAll,
2940
- useGetCalendar,
2941
- useGetComment,
2942
- useGetCompanyInfo,
2943
- useGetConversionRate,
2944
- useGetCurrency,
2945
- useGetCurrentCompany,
2946
- useGetDetail,
2947
- useGetExternalTabs,
2948
- useGetFieldExport,
2949
- useGetFieldOnChange,
2950
- useGetFileExcel,
2951
- useGetFormView,
2952
- useGetGroups,
2953
- useGetList,
2954
- useGetListCompany,
2955
- useGetListData,
2956
- useGetListMyBankAccount,
2957
- useGetMenu,
2958
- useGetOrderLine,
2959
- useGetPinCode,
2960
- useGetPrintReport,
2961
- useGetProGressBar,
2962
- useGetProfile,
2963
- useGetProvider,
2964
- useGetResequence,
2965
- useGetRowIds,
2966
- useGetSelection,
2967
- useGetSpecification,
2968
- useGetUser,
2969
- useGetView,
2970
- useGrantAccess,
2971
- useIsValidToken,
2972
- useListData,
2973
- useLoadAction,
2974
- useLoadMessage,
2975
- useLoginCredential,
2976
- useLoginSocial,
2977
- useLogout,
2978
- useMenu,
2979
- useModel,
2980
- useOdooDataTransform,
2981
- useOnChangeForm,
2982
- useParsePreview,
2983
- usePrint,
2984
- useProfile,
2985
- useReadGroup,
2986
- useRemoveRow,
2987
- useRemoveTotpSetup,
2988
- useRequestSetupTotp,
2989
- useResetPassword,
2990
- useResetPasswordSSO,
2991
- useRunAction,
2992
- useSave,
2993
- useSendComment,
2994
- useSettingsWebRead2fa,
2995
- useSignInSSO,
2996
- useStorageState,
2997
- useSwitchLocale,
2998
- useUpdatePassword,
2999
- useUploadFile,
3000
- useUploadFileExcel,
3001
- useUploadIdFile,
3002
- useUploadImage,
3003
- useUser,
3004
- useValidateActionToken,
3005
- useVerify2FA,
3006
- useVerifyTotp,
3007
- useViewV2,
3008
- validateAndParseDate
3009
- });