@fctc/widget-logic 1.8.6 → 1.8.7

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 CHANGED
@@ -5209,48 +5209,63 @@ var statusDropdownController = (props) => {
5209
5209
 
5210
5210
  // src/widget/basic/many2one-field/controller.ts
5211
5211
  var import_react14 = require("react");
5212
- var import_hooks11 = require("@fctc/interface-logic/hooks");
5213
- var import_store7 = require("@fctc/interface-logic/store");
5214
- var import_utils3 = require("@fctc/interface-logic/utils");
5212
+
5213
+ // src/utils.ts
5214
+ var utils_exports = {};
5215
+ __export(utils_exports, {
5216
+ API_APP_URL: () => API_APP_URL,
5217
+ API_PRESCHOOL_URL: () => API_PRESCHOOL_URL,
5218
+ STORAGES: () => STORAGES,
5219
+ combineContexts: () => combineContexts,
5220
+ convertFieldsToArray: () => convertFieldsToArray,
5221
+ countSum: () => countSum,
5222
+ getDateRange: () => getDateRange,
5223
+ languages: () => languages,
5224
+ mergeButtons: () => mergeButtons,
5225
+ setStorageItemAsync: () => setStorageItemAsync,
5226
+ useGetRowIds: () => useGetRowIds,
5227
+ useSelectionState: () => useSelectionState,
5228
+ useStorageState: () => useStorageState
5229
+ });
5230
+ __reExport(utils_exports, require("@fctc/interface-logic/utils"));
5231
+
5232
+ // src/provider.ts
5233
+ var provider_exports = {};
5234
+ __reExport(provider_exports, require("@fctc/interface-logic/provider"));
5235
+
5236
+ // src/widget/basic/many2one-field/controller.ts
5215
5237
  var many2oneFieldController = (props) => {
5216
5238
  const {
5217
- name,
5239
+ sessionStorageUtils,
5218
5240
  methods,
5219
- formValues,
5220
- domain,
5221
5241
  relation,
5222
- onChange,
5242
+ domain,
5243
+ formValues,
5223
5244
  value: propValue,
5245
+ onChange,
5246
+ name,
5224
5247
  context: fieldContext,
5225
5248
  options: fieldOptions,
5226
- showDetail = true,
5227
- actionData
5249
+ showDetail
5228
5250
  } = props;
5229
5251
  const [options, setOptions] = (0, import_react14.useState)([]);
5252
+ const [inputValue, setInputValue] = (0, import_react14.useState)("");
5253
+ const [debouncedInputValue] = useDebounce(inputValue, 1e3);
5230
5254
  const [isShowModalMany2Many, setIsShowModalMany2Many] = (0, import_react14.useState)(false);
5231
5255
  const [tempSelectedOption, setTempSelectedOption] = (0, import_react14.useState)(null);
5232
- const { menuList } = (0, import_store7.useAppSelector)(import_store7.selectNavbar);
5233
- const { context } = (0, import_store7.useAppSelector)(import_store7.selectEnv);
5234
5256
  const [domainModal, setDomainModal] = (0, import_react14.useState)(null);
5257
+ const [domainObject, setDomainObject] = (0, import_react14.useState)(null);
5258
+ const actionData = sessionStorageUtils.getActionData();
5259
+ const { menuList } = (0, store_exports.useAppSelector)(store_exports.selectNavbar);
5260
+ const { context } = (0, store_exports.useAppSelector)(store_exports.selectEnv);
5235
5261
  const initValue = methods?.getValues(name);
5236
- const domainObject = (0, import_react14.useMemo)(
5237
- () => (0, import_utils3.evalJSONDomain)(domain, JSON.parse(JSON.stringify(formValues)) ?? {}),
5238
- [domain, formValues]
5239
- );
5240
- const optionsObject = (0, import_utils3.evalJSONContext)(fieldOptions) || {};
5262
+ const optionsObject = (0, utils_exports.evalJSONContext)(fieldOptions) || {};
5241
5263
  const contextObject = {
5242
- ...(0, import_utils3.evalJSONContext)(actionData?.context) || {},
5264
+ ...(0, utils_exports.evalJSONContext)(actionData?.context) || {},
5243
5265
  ...fieldContext,
5244
5266
  ...context
5245
5267
  };
5246
- const actionId = (0, import_react14.useMemo)(
5247
- () => menuList?.flatMap(
5248
- (item) => item?.child_id.filter(
5249
- (childItem) => childItem?.is_display && childItem?.action?.res_model === relation
5250
- )
5251
- )?.[0]?.action?.id,
5252
- [menuList, relation]
5253
- );
5268
+ const { useGetSelection: useGetSelection3 } = (0, provider_exports.useService)();
5254
5269
  const data = {
5255
5270
  model: relation,
5256
5271
  domain: domainObject,
@@ -5264,9 +5279,9 @@ var many2oneFieldController = (props) => {
5264
5279
  const queryKey = [`data_${relation}`, domainObject];
5265
5280
  const {
5266
5281
  data: dataOfSelection,
5267
- // refetch,
5282
+ refetch,
5268
5283
  isFetching
5269
- } = (0, import_hooks11.useGetSelection)({
5284
+ } = useGetSelection3({
5270
5285
  data,
5271
5286
  queryKey,
5272
5287
  enabled: false
@@ -5280,8 +5295,16 @@ var many2oneFieldController = (props) => {
5280
5295
  (0, import_react14.useEffect)(() => {
5281
5296
  setOptions(selectOptions);
5282
5297
  setDomainModal(domainObject);
5283
- if (relation === "student.subject") (0, import_store7.setListSubject)(selectOptions);
5298
+ if (relation === "student.subject") (0, store_exports.setListSubject)(selectOptions);
5284
5299
  }, [selectOptions]);
5300
+ (0, import_react14.useEffect)(() => {
5301
+ setDomainObject(
5302
+ (0, utils_exports.evalJSONDomain)(
5303
+ domain,
5304
+ JSON.parse(JSON.stringify({ ...formValues, context: contextObject })) ?? {}
5305
+ )
5306
+ );
5307
+ }, [domain, formValues]);
5285
5308
  (0, import_react14.useEffect)(() => {
5286
5309
  if (!propValue && tempSelectedOption) {
5287
5310
  methods.setValue(name, null);
@@ -5293,11 +5316,24 @@ var many2oneFieldController = (props) => {
5293
5316
  });
5294
5317
  }
5295
5318
  }, [propValue]);
5319
+ const fetchMoreOptions = (0, import_react14.useCallback)(() => {
5320
+ refetch();
5321
+ }, [refetch]);
5296
5322
  (0, import_react14.useEffect)(() => {
5297
- if (actionId) {
5298
- localStorage.setItem("aid", actionId);
5323
+ if (debouncedInputValue) {
5324
+ const filteredDomain = [...domainObject ?? []]?.filter(
5325
+ (d) => !(Array.isArray(d) && d[0] === "name" && d[1] === "ilike")
5326
+ ) || [];
5327
+ const newDomain = [
5328
+ ...filteredDomain,
5329
+ ...debouncedInputValue ? [["name", "ilike", debouncedInputValue]] : []
5330
+ ];
5331
+ setDomainObject(newDomain);
5332
+ setTimeout(() => {
5333
+ fetchMoreOptions();
5334
+ }, 50);
5299
5335
  }
5300
- }, [actionId]);
5336
+ }, [debouncedInputValue]);
5301
5337
  const handleChooseRecord = (0, import_react14.useCallback)(
5302
5338
  (idRecord) => {
5303
5339
  const newOption = options.find(
@@ -5349,52 +5385,42 @@ var many2oneFieldController = (props) => {
5349
5385
  [methods, name, onChange]
5350
5386
  );
5351
5387
  const allowShowDetail = showDetail && contextObject?.form_view_ref && (!("no_open" in optionsObject) || optionsObject?.no_open === false);
5352
- const fetchMoreOptions = (0, import_react14.useCallback)(() => {
5353
- if (typeof dataOfSelection?.refetch === "function") {
5354
- ;
5355
- dataOfSelection.refetch();
5356
- }
5357
- }, [dataOfSelection]);
5358
5388
  return {
5359
- allowShowDetail,
5360
- handleClose,
5389
+ isShowModalMany2Many,
5390
+ isFetching,
5391
+ initValue,
5392
+ menuList,
5361
5393
  handleChooseRecord,
5394
+ handleClose,
5362
5395
  handleSelectChange,
5363
- initValue,
5364
- isFetching,
5365
- isShowModalMany2Many,
5366
- options,
5367
- fetchMoreOptions,
5368
5396
  domainModal,
5369
- tempSelectedOption,
5370
- setTempSelectedOption,
5371
- setDomainModal,
5372
- dataOfSelection,
5373
- refetch: dataOfSelection?.refetch ?? (() => {
5374
- }),
5375
- selectOptions,
5376
- optionsObject,
5397
+ setInputValue,
5398
+ allowShowDetail,
5377
5399
  contextObject,
5378
- actionId,
5379
- setIsShowModalMany2Many
5400
+ tempSelectedOption,
5401
+ options,
5402
+ fetchMoreOptions,
5403
+ domainObject,
5404
+ setIsShowModalMany2Many,
5405
+ setDomainObject
5380
5406
  };
5381
5407
  };
5382
5408
 
5383
5409
  // src/widget/basic/many2one-button-field/controller.ts
5384
5410
  var import_environment6 = require("@fctc/interface-logic/environment");
5385
5411
  var import_hooks12 = require("@fctc/interface-logic/hooks");
5386
- var import_utils4 = require("@fctc/interface-logic/utils");
5412
+ var import_utils5 = require("@fctc/interface-logic/utils");
5387
5413
  var many2oneButtonController = (props) => {
5388
5414
  const { domain, methods, relation } = props;
5389
5415
  const actionDataString = sessionStorage.getItem("actionData");
5390
5416
  const env = (0, import_environment6.getEnv)();
5391
- const domainObject = (0, import_utils4.evalJSONDomain)(domain, methods?.getValues() || {});
5417
+ const domainObject = (0, import_utils5.evalJSONDomain)(domain, methods?.getValues() || {});
5392
5418
  const actionData = actionDataString && actionDataString !== "undefined" ? JSON.parse(actionDataString) : {};
5393
5419
  const { data: dataOfSelection } = (0, import_hooks12.useGetSelection)({
5394
5420
  data: {
5395
5421
  model: relation ?? "",
5396
5422
  domain: domainObject,
5397
- context: { ...env.context, ...(0, import_utils4.evalJSONContext)(actionData?.context) }
5423
+ context: { ...env.context, ...(0, import_utils5.evalJSONContext)(actionData?.context) }
5398
5424
  },
5399
5425
  queryKey: [`data_${relation}`, domainObject]
5400
5426
  });
@@ -5408,204 +5434,473 @@ var many2oneButtonController = (props) => {
5408
5434
  };
5409
5435
 
5410
5436
  // src/widget/basic/many2many-field/controller.ts
5411
- var import_react19 = require("react");
5412
-
5413
- // src/widget/advance/table/table-body/controller.ts
5414
- var import_store8 = require("@fctc/interface-logic/store");
5415
5437
  var import_react15 = require("react");
5416
- var tableBodyController = (props) => {
5438
+ var import_store8 = require("@fctc/interface-logic/store");
5439
+ var import_utils6 = require("@fctc/interface-logic/utils");
5440
+ var many2manyFieldController = (props) => {
5417
5441
  const {
5418
- checkedAll,
5419
- checkboxRef,
5420
- setIsAutoSelect,
5421
- selectedRowKeys,
5422
- row,
5423
- isAutoSelect,
5424
- selectedRowKeysRef,
5425
- onClickRow
5442
+ relation,
5443
+ domain,
5444
+ context,
5445
+ tab,
5446
+ model,
5447
+ aid,
5448
+ setSelectedRowKeys: setSelectedRowKeys4,
5449
+ fields,
5450
+ setFields,
5451
+ groupByDomain,
5452
+ page,
5453
+ options,
5454
+ sessionStorageUtils
5426
5455
  } = props;
5427
5456
  const appDispatch = (0, import_store8.useAppDispatch)();
5428
- const checked = (0, import_react15.useMemo)(() => {
5429
- if (!row?.id) return false;
5430
- if (selectedRowKeys?.includes(row.id)) {
5431
- return true;
5457
+ const actionData = sessionStorageUtils.getActionData();
5458
+ const [debouncedPage] = useDebounce(page, 500);
5459
+ const [order, setOrder] = (0, import_react15.useState)();
5460
+ const [isLoadedData, setIsLoadedData] = (0, import_react15.useState)(false);
5461
+ const [domainMany2Many, setDomainMany2Many] = (0, import_react15.useState)(domain);
5462
+ const { env } = (0, provider_exports.useEnv)();
5463
+ const { useGetView: useGetView2, useGetListData: useGetListData4, useGetFormView } = (0, provider_exports.useService)();
5464
+ const viewParams = {
5465
+ model: relation,
5466
+ views: [
5467
+ [false, "list"],
5468
+ [false, "search"]
5469
+ ],
5470
+ context
5471
+ };
5472
+ const { data: viewResponse } = useGetView2(viewParams, actionData);
5473
+ const baseModel = (0, import_react15.useMemo)(
5474
+ () => ({
5475
+ name: String(relation),
5476
+ view: viewResponse || {},
5477
+ actContext: context,
5478
+ fields: [
5479
+ ...Object.values(viewResponse?.views?.list?.fields ?? {}),
5480
+ ...tab?.fields ? tab.fields : []
5481
+ ]
5482
+ }),
5483
+ [model, viewResponse]
5484
+ );
5485
+ const initModel = (0, hooks_exports.useModel)();
5486
+ const modelInstance = (0, import_react15.useMemo)(() => {
5487
+ if (viewResponse) {
5488
+ return initModel.initModel(baseModel);
5432
5489
  }
5433
- return checkedAll;
5434
- }, [row?.id, selectedRowKeys, checkedAll]);
5435
- const handleCheckBoxSingle = (event) => {
5436
- event.stopPropagation();
5437
- if (checkedAll) {
5438
- checkboxRef.current = "uncheck";
5439
- setIsAutoSelect(true);
5440
- return;
5490
+ return null;
5491
+ }, [baseModel, viewResponse]);
5492
+ const specification = (0, import_react15.useMemo)(() => {
5493
+ if (modelInstance) {
5494
+ return modelInstance.getSpecification();
5495
+ }
5496
+ return null;
5497
+ }, [modelInstance]);
5498
+ const default_order = viewResponse && viewResponse?.views?.list?.default_order;
5499
+ const optionsObject = tab?.options ? (0, import_utils6.evalJSONContext)(tab?.options) : (options ? (0, import_utils6.evalJSONContext)(options) : {}) || {};
5500
+ const fetchData = async () => {
5501
+ try {
5502
+ setDomainMany2Many(domain);
5503
+ appDispatch((0, import_store8.setFirstDomain)(domain));
5504
+ appDispatch((0, import_store8.setViewDataStore)(viewResponse));
5505
+ const modalData = viewResponse?.views?.list?.fields.map((field) => ({
5506
+ ...viewResponse?.models?.[String(model)]?.[field?.name],
5507
+ ...field
5508
+ }));
5509
+ if (!fields?.[`${aid}_${relation}_popupmany2many`] && modalData) {
5510
+ setFields({
5511
+ ...fields,
5512
+ [`${aid}_${relation}_popupmany2many`]: modalData
5513
+ });
5514
+ }
5515
+ appDispatch((0, import_store8.setPage)(0));
5516
+ } catch (err) {
5517
+ console.log(err);
5441
5518
  }
5442
- const newSelectedRowKeys = selectedRowKeys?.includes(row.id) ? selectedRowKeys?.filter((key) => key !== row.id) : [...selectedRowKeys, row.id];
5443
- console.log("newSelectedRowKeys", newSelectedRowKeys);
5444
- appDispatch((0, import_store8.setSelectedRowKeys)(newSelectedRowKeys));
5445
5519
  };
5446
- const handleClickRow = (col, row2) => {
5447
- onClickRow(col, row2);
5520
+ const queryKey = [
5521
+ `view-${relation}-${aid}`,
5522
+ specification,
5523
+ domainMany2Many,
5524
+ debouncedPage,
5525
+ groupByDomain,
5526
+ order
5527
+ ];
5528
+ const data = {
5529
+ model: relation,
5530
+ specification,
5531
+ domain: domainMany2Many,
5532
+ offset: debouncedPage * 10,
5533
+ limit: 10,
5534
+ context,
5535
+ fields: groupByDomain?.fields,
5536
+ groupby: [groupByDomain?.contexts[0]?.group_by],
5537
+ sort: order ? order : default_order ? (0, import_utils6.formatSortingString)(default_order) : ""
5448
5538
  };
5539
+ const enabled = isLoadedData && !!specification && !!relation && !!domainMany2Many && !!viewResponse;
5540
+ const {
5541
+ data: dataResponse,
5542
+ isLoading: isDataLoading,
5543
+ isFetched: isDataResponseFetched,
5544
+ isPlaceholderData
5545
+ } = useGetListData4(data, queryKey, enabled);
5449
5546
  (0, import_react15.useEffect)(() => {
5450
- if (!row?.id) return;
5451
- if (isAutoSelect) {
5452
- if (checkboxRef?.current === "uncheck") {
5453
- const filtered = selectedRowKeysRef.current.filter(
5454
- (id) => id !== row.id
5455
- );
5456
- selectedRowKeysRef.current = filtered;
5457
- appDispatch((0, import_store8.setSelectedRowKeys)(filtered));
5458
- } else {
5459
- const unique = Array.from(
5460
- /* @__PURE__ */ new Set([...selectedRowKeysRef?.current, row?.id])
5461
- );
5462
- selectedRowKeysRef.current = unique;
5463
- appDispatch((0, import_store8.setSelectedRowKeys)(unique));
5464
- }
5547
+ if (viewResponse) {
5548
+ fetchData();
5465
5549
  }
5466
- }, [isAutoSelect]);
5550
+ return () => {
5551
+ appDispatch((0, import_store8.setGroupByDomain)(null));
5552
+ setFields((prevFields) => ({
5553
+ ...prevFields,
5554
+ [`${aid}_${relation}_popupmany2many`]: null
5555
+ }));
5556
+ appDispatch((0, import_store8.setPage)(0));
5557
+ setSelectedRowKeys4([]);
5558
+ setDomainMany2Many(null);
5559
+ setIsLoadedData(false);
5560
+ };
5561
+ }, [viewResponse]);
5562
+ const { rows, columns, typeTable } = tableController({
5563
+ data: {
5564
+ fields: fields?.[`${aid}_${relation}_popupmany2many`] || viewResponse?.views?.list?.fields,
5565
+ records: dataResponse?.records ?? dataResponse?.groups,
5566
+ dataModel: viewResponse?.models?.[String(relation)],
5567
+ context: { ...env.context, ...context },
5568
+ typeTable: dataResponse?.groups ? "group" : "list"
5569
+ }
5570
+ });
5571
+ const dataFormView = {
5572
+ id: null,
5573
+ model: relation,
5574
+ context
5575
+ };
5576
+ const {
5577
+ refetch,
5578
+ data: dataFormViewResponse,
5579
+ isSuccess
5580
+ } = useGetFormView({
5581
+ data: dataFormView,
5582
+ queryKey: [`form-view-action-${relation}`],
5583
+ enabled: false
5584
+ });
5467
5585
  (0, import_react15.useEffect)(() => {
5468
- if (!checkedAll) {
5469
- checkboxRef.current = "enabled";
5470
- false;
5586
+ if (isSuccess && dataFormViewResponse) {
5587
+ sessionStorage.setItem("actionData", JSON.stringify(dataFormViewResponse));
5588
+ window.location.href = `/form/menu?model=${relation}`;
5471
5589
  }
5472
- }, [checkedAll]);
5590
+ }, [isSuccess]);
5591
+ (0, import_react15.useEffect)(() => {
5592
+ if (domainMany2Many && !isLoadedData) {
5593
+ setIsLoadedData(true);
5594
+ }
5595
+ }, [domainMany2Many]);
5596
+ const handleCreateNewOnPage = async () => {
5597
+ try {
5598
+ refetch();
5599
+ } catch (error) {
5600
+ console.log(error);
5601
+ }
5602
+ };
5473
5603
  return {
5474
- handleCheckBoxSingle,
5475
- checked,
5476
- handleClickRow
5604
+ handleCreateNewOnPage,
5605
+ optionsObject,
5606
+ rows,
5607
+ columns,
5608
+ typeTable,
5609
+ isDataLoading,
5610
+ isDataResponseFetched,
5611
+ isPlaceholderData
5477
5612
  };
5478
5613
  };
5479
5614
 
5480
- // src/widget/advance/table/table-head/controller.ts
5481
- var import_store9 = require("@fctc/interface-logic/store");
5482
- var tableHeadController = (props) => {
5483
- const { typeTable, rows, selectedRowKeysRef } = props;
5484
- const appDispatch = (0, import_store9.useAppDispatch)();
5485
- const { groupByDomain } = (0, import_store9.useAppSelector)(import_store9.selectSearch);
5486
- const handleCheckBoxAll = (event) => {
5487
- if (event?.target?.checked && typeTable === "list") {
5488
- const allRowKeys = Array.isArray(rows) ? rows.map((record) => record?.id) : [];
5489
- appDispatch((0, import_store9.setSelectedRowKeys)(allRowKeys));
5490
- } else if (event?.target?.checked && typeTable === "group") {
5491
- const rowsIDs = document.querySelectorAll("tr[data-row-id]");
5492
- const ids = Array.from(rowsIDs)?.map(
5493
- (row) => Number(row?.getAttribute("data-row-id"))
5494
- );
5495
- if (ids?.length > 0) {
5496
- appDispatch((0, import_store9.setSelectedRowKeys)(ids));
5497
- } else {
5498
- const sum = countSum(
5499
- rows,
5500
- typeof groupByDomain === "object" ? groupByDomain?.contexts?.[0]?.group_by : void 0
5501
- );
5502
- const keys = Array.from({ length: sum }, (_) => void 0);
5503
- appDispatch((0, import_store9.setSelectedRowKeys)(keys));
5504
- }
5505
- if (selectedRowKeysRef) {
5506
- selectedRowKeysRef.current = [];
5507
- }
5508
- } else {
5509
- appDispatch((0, import_store9.setSelectedRowKeys)([]));
5510
- }
5615
+ // src/widget/basic/many2many-tags-field/controller.ts
5616
+ var import_react16 = require("react");
5617
+ var import_constants4 = require("@fctc/interface-logic/constants");
5618
+ var import_environment7 = require("@fctc/interface-logic/environment");
5619
+ var import_hooks14 = require("@fctc/interface-logic/hooks");
5620
+ var import_utils7 = require("@fctc/interface-logic/utils");
5621
+ var many2manyTagsController = (props) => {
5622
+ const {
5623
+ relation,
5624
+ domain,
5625
+ options: optionsFields,
5626
+ widget,
5627
+ formValues,
5628
+ placeholderNoOption
5629
+ } = props;
5630
+ const isUser = relation === "res.users" || relation === "res.partner";
5631
+ const env = (0, import_environment7.getEnv)();
5632
+ const addtionalFields = optionsFields ? (0, import_utils7.evalJSONContext)(optionsFields) : null;
5633
+ const domainObject = (0, import_react16.useMemo)(
5634
+ () => (0, import_utils7.evalJSONDomain)(domain, JSON.parse(JSON.stringify(formValues || {}))),
5635
+ [domain, formValues]
5636
+ );
5637
+ const data = {
5638
+ model: relation ?? "",
5639
+ domain: domainObject,
5640
+ specification: {
5641
+ id: {},
5642
+ name: {},
5643
+ display_name: {},
5644
+ ...widget && import_constants4.WIDGETAVATAR[widget] ? { image_256: {} } : {},
5645
+ ...widget && import_constants4.WIDGETCOLOR[widget] && addtionalFields?.color_field ? { color: {} } : {}
5646
+ },
5647
+ enabled: true,
5648
+ context: env.context
5649
+ };
5650
+ const { data: dataOfSelection } = (0, import_hooks14.useGetSelection)({
5651
+ data,
5652
+ queryKey: [`data_${relation}`, domainObject]
5653
+ });
5654
+ const customNoOptionsMessage = () => placeholderNoOption;
5655
+ const tranfer = (data2) => {
5656
+ return data2?.map((val) => ({
5657
+ id: val.value,
5658
+ display_name: val.label
5659
+ })) || [];
5511
5660
  };
5661
+ const options = dataOfSelection?.records?.map((val) => ({
5662
+ value: val.id,
5663
+ label: val.name ?? val.display_name,
5664
+ ...val
5665
+ })) || [];
5512
5666
  return {
5513
- handleCheckBoxAll
5667
+ options,
5668
+ customNoOptionsMessage,
5669
+ tranfer,
5670
+ dataOfSelection,
5671
+ isUser
5514
5672
  };
5515
5673
  };
5516
5674
 
5517
- // src/widget/advance/table/table-view/controller.ts
5518
- var import_react16 = require("react");
5519
- var import_store10 = require("@fctc/interface-logic/store");
5520
- var import_utils5 = require("@fctc/interface-logic/utils");
5521
- var tableController = ({ data }) => {
5522
- const [rows, setRows] = (0, import_react16.useState)(data.records || []);
5523
- const [columns, setColumns] = (0, import_react16.useState)([]);
5524
- const dataModelFields = data.fields?.map((field) => {
5525
- return {
5526
- ...data.dataModel?.[field?.name],
5527
- ...field,
5528
- string: field?.string || data.dataModel?.[field?.name]?.string
5529
- };
5530
- });
5531
- const mergeFields = mergeButtons(dataModelFields);
5532
- const transformData = (dataList) => {
5533
- if (!dataList) return;
5534
- return dataList?.map((item) => {
5535
- const transformedItem = { ...item };
5536
- Object.keys(item).forEach((field) => {
5537
- if (field !== "__domain") {
5538
- if (item[field] && typeof item[field] === "object" && item[field].display_name) {
5539
- transformedItem[field] = item[field];
5540
- } else if (Array.isArray(item[field]) && item[field].length > 0) {
5541
- if (data.typeTable === "group" && item[field]?.length === 2 && typeof item[field]?.[1] === "string") {
5542
- transformedItem["string"] = item[field]?.[1];
5675
+ // src/widget/basic/status-bar-field/controller.ts
5676
+ var import_react17 = require("react");
5677
+ var import_hooks15 = require("@fctc/interface-logic/hooks");
5678
+ var import_store9 = require("@fctc/interface-logic/store");
5679
+ var import_utils8 = require("@fctc/interface-logic/utils");
5680
+ var durationController = (props) => {
5681
+ const {
5682
+ relation,
5683
+ defaultValue,
5684
+ domain,
5685
+ formValues,
5686
+ name,
5687
+ id,
5688
+ model,
5689
+ onRefetch
5690
+ } = props;
5691
+ const specification = {
5692
+ id: 0,
5693
+ name: "",
5694
+ fold: ""
5695
+ };
5696
+ const [disabled, setDisabled] = (0, import_react17.useState)(false);
5697
+ const [modelStatus, setModalStatus] = (0, import_react17.useState)(false);
5698
+ const { context } = (0, import_store9.useAppSelector)(import_store9.selectEnv);
5699
+ const queryKey = [`data-status-duration`, specification];
5700
+ const listDataProps = {
5701
+ model: relation,
5702
+ specification,
5703
+ domain: (0, import_utils8.evalJSONDomain)(domain, JSON.parse(JSON.stringify(formValues))),
5704
+ limit: 10,
5705
+ offset: 0,
5706
+ fields: "",
5707
+ groupby: [],
5708
+ context: {
5709
+ lang: context.lang
5710
+ },
5711
+ sort: ""
5712
+ };
5713
+ const { data: dataResponse } = (0, import_hooks15.useGetListData)(listDataProps, queryKey);
5714
+ const { mutate: fetchChangeStatus } = (0, import_hooks15.useChangeStatus)();
5715
+ const handleClick = async (stage_id) => {
5716
+ setDisabled(true);
5717
+ if (stage_id) {
5718
+ fetchChangeStatus(
5719
+ {
5720
+ data: {
5721
+ stage_id,
5722
+ name,
5723
+ id,
5724
+ model,
5725
+ lang: context.lang
5726
+ }
5727
+ },
5728
+ {
5729
+ onSuccess: (res) => {
5730
+ if (res) {
5731
+ setDisabled(false);
5732
+ onRefetch && onRefetch();
5543
5733
  }
5544
- transformedItem[field] = item[field];
5545
5734
  }
5546
5735
  }
5547
- });
5548
- return item.display_name ? { ...transformedItem, item: item.display_name } : transformedItem;
5549
- });
5736
+ );
5737
+ }
5550
5738
  };
5551
- (0, import_react16.useEffect)(() => {
5552
- setRows(transformData(data.records || null));
5553
- }, [data.records]);
5554
- const handleGetColumns = () => {
5555
- let cols = [];
5739
+ return {
5740
+ defaultValue,
5741
+ dataResponse,
5742
+ handleClick,
5743
+ disabled,
5744
+ modelStatus,
5745
+ setModalStatus
5746
+ };
5747
+ };
5748
+
5749
+ // src/widget/basic/priority-field/controller.ts
5750
+ var import_hooks16 = require("@fctc/interface-logic/hooks");
5751
+ var import_utils9 = require("@fctc/interface-logic/utils");
5752
+ var priorityFieldController = (props) => {
5753
+ const {
5754
+ value,
5755
+ isForm,
5756
+ name,
5757
+ methods,
5758
+ onChange,
5759
+ model,
5760
+ selection,
5761
+ id,
5762
+ actionData,
5763
+ viewData,
5764
+ context
5765
+ } = props;
5766
+ const _context = { ...(0, import_utils9.evalJSONContext)(actionData?.context) };
5767
+ const contextObject = { ...context, ..._context };
5768
+ const defaultPriority = parseInt(value) + 1;
5769
+ const label = viewData?.models?.[model]?.[name ?? ""]?.string ?? name;
5770
+ const { mutateAsync: fetchSave } = (0, import_hooks16.useSave)();
5771
+ const savePriorities = async ({
5772
+ value: value2,
5773
+ resetPriority
5774
+ }) => {
5775
+ const priorityValue = value2 <= 0 ? 0 : value2 - 1;
5556
5776
  try {
5557
- cols = mergeFields?.filter((item) => {
5558
- return item?.widget !== "details_Receive_money" && !(item?.column_invisible ? import_utils5.domainHelper.matchDomains(data.context, item?.column_invisible) : item?.invisible ? import_utils5.domainHelper.matchDomains(data.context, item?.invisible) : false);
5559
- })?.map((field) => {
5560
- return {
5561
- name: field?.name,
5562
- optional: field?.optional,
5563
- title: field?.type_co === "button" ? "" : field?.string,
5564
- field: { ...field }
5565
- };
5777
+ fetchSave({
5778
+ ids: id ? [id] : [],
5779
+ data: { [name ?? ""]: String(priorityValue) },
5780
+ model: model ?? "",
5781
+ context: contextObject
5566
5782
  });
5783
+ if (typeof onChange === "function") {
5784
+ onChange(name ?? "", String(priorityValue));
5785
+ }
5567
5786
  } catch (error) {
5568
- console.error("Error in useTable:", error);
5569
- }
5570
- return cols;
5571
- };
5572
- (0, import_react16.useEffect)(() => {
5573
- const columns2 = handleGetColumns();
5574
- setColumns(columns2);
5575
- }, [data.records]);
5576
- const onToggleColumnOptional = (item) => {
5577
- const tempColumn = [...columns]?.map((val) => {
5578
- if (item?.name === val?.name) {
5579
- return {
5580
- ...val,
5581
- optional: item?.optional === "show" ? "hide" : "show"
5582
- };
5787
+ if (resetPriority) {
5788
+ resetPriority();
5583
5789
  }
5584
- return val;
5585
- });
5586
- setColumns(tempColumn);
5790
+ }
5587
5791
  };
5588
5792
  return {
5589
- rows,
5590
- columns,
5591
- onToggleColumnOptional,
5592
- typeTable: data.typeTable
5793
+ selection,
5794
+ isForm,
5795
+ methods,
5796
+ defaultPriority,
5797
+ savePriorities,
5798
+ label,
5799
+ id,
5800
+ onChange
5593
5801
  };
5594
5802
  };
5595
5803
 
5596
- // src/widget/advance/table/table-group/controller.ts
5597
- var import_react17 = require("react");
5598
-
5599
- // src/utils/i18n.ts
5600
- var import_react_i18next2 = require("react-i18next");
5601
- var import_i18next = __toESM(require("i18next"));
5602
- var import_i18next_browser_languagedetector = __toESM(require("i18next-browser-languagedetector"));
5603
-
5604
- // src/locales/vi.json
5605
- var vi_default = {
5606
- login: "\u0110\u0103ng Nh\u1EADp",
5607
- english: "Ti\u1EBFng Anh",
5608
- vietnamese: "Ti\u1EBFng Vi\u1EC7t",
5804
+ // src/widget/basic/float-time-field/controller.ts
5805
+ var import_react18 = require("react");
5806
+ var import_utils10 = require("@fctc/interface-logic/utils");
5807
+ var floatTimeFiledController = ({
5808
+ onChange: fieldOnChange,
5809
+ onBlur,
5810
+ value,
5811
+ isDirty,
5812
+ props
5813
+ }) => {
5814
+ const { name, defaultValue = 0, onChange } = props;
5815
+ const [input, setInput] = (0, import_react18.useState)(
5816
+ (0, import_utils10.convertFloatToTime)(value ?? defaultValue)
5817
+ );
5818
+ const [formattedTime, setFormattedTime] = (0, import_react18.useState)("");
5819
+ const [errors, setErrors] = (0, import_react18.useState)("");
5820
+ const handleInputChange = (e) => {
5821
+ const raw = e.target.value.replace(/[^\d:]/g, "");
5822
+ setInput(raw);
5823
+ const timeRegex = /^(\d{1,2}):?(\d{0,2})$/;
5824
+ const match = raw.match(timeRegex);
5825
+ if (!match) {
5826
+ setErrors("\u0110\u1ECBnh d\u1EA1ng kh\xF4ng h\u1EE3p l\u1EC7");
5827
+ setFormattedTime("");
5828
+ return;
5829
+ }
5830
+ let hours = parseInt(match[1] ?? "0", 10);
5831
+ let minutes = parseInt(match[2] ?? "0", 10);
5832
+ if (isNaN(hours)) hours = 0;
5833
+ if (isNaN(minutes)) minutes = 0;
5834
+ if (hours >= 24) {
5835
+ hours = 0;
5836
+ }
5837
+ if (minutes >= 60) {
5838
+ minutes = 0;
5839
+ }
5840
+ const formatted = `${hours.toString().padStart(2, "0")}:${minutes.toString().padStart(2, "0")}`;
5841
+ setErrors("");
5842
+ setFormattedTime(formatted);
5843
+ fieldOnChange(formatted);
5844
+ };
5845
+ const handleBlur = () => {
5846
+ if (!isDirty) return;
5847
+ if (formattedTime) {
5848
+ setInput(formattedTime);
5849
+ const floatVal = (0, import_utils10.convertTimeToFloat)(formattedTime);
5850
+ fieldOnChange(floatVal);
5851
+ if (onChange) {
5852
+ onChange(name ?? "", floatVal);
5853
+ }
5854
+ } else {
5855
+ setInput("00:00");
5856
+ fieldOnChange(0);
5857
+ if (onChange) {
5858
+ onChange(name ?? "", 0);
5859
+ }
5860
+ setErrors("");
5861
+ }
5862
+ onBlur();
5863
+ };
5864
+ const handleKeyDown = (e) => {
5865
+ {
5866
+ const allowed = [
5867
+ "Backspace",
5868
+ "Tab",
5869
+ "ArrowLeft",
5870
+ "ArrowRight",
5871
+ "Delete",
5872
+ "Home",
5873
+ "End",
5874
+ ":"
5875
+ ];
5876
+ const isNumber = /^[0-9]$/.test(e.key);
5877
+ if (!isNumber && !allowed.includes(e.key)) {
5878
+ e.preventDefault();
5879
+ }
5880
+ }
5881
+ };
5882
+ return {
5883
+ handleInputChange,
5884
+ handleBlur,
5885
+ handleKeyDown,
5886
+ input,
5887
+ errors
5888
+ };
5889
+ };
5890
+
5891
+ // src/widget/basic/float-field/controller.ts
5892
+ var import_react19 = require("react");
5893
+
5894
+ // src/utils/i18n.ts
5895
+ var import_react_i18next2 = require("react-i18next");
5896
+ var import_i18next = __toESM(require("i18next"));
5897
+ var import_i18next_browser_languagedetector = __toESM(require("i18next-browser-languagedetector"));
5898
+
5899
+ // src/locales/vi.json
5900
+ var vi_default = {
5901
+ login: "\u0110\u0103ng Nh\u1EADp",
5902
+ english: "Ti\u1EBFng Anh",
5903
+ vietnamese: "Ti\u1EBFng Vi\u1EC7t",
5609
5904
  note_login: "Xin h\xE3y \u0111\u0103ng nh\u1EADp v\xE0o t\xE0i kho\u1EA3n c\u1EE7a b\u1EA1n",
5610
5905
  "note-forgotpassword": "Vui l\xF2ng nh\u1EADp \u0111\u1ECBa ch\u1EC9 email b\u1EA1n mu\u1ED1n th\xF4ng tin \u0111\u1EB7t l\u1EA1i m\u1EADt kh\u1EA9u c\u1EE7a b\u1EA1n \u0111\u01B0\u1EE3c g\u1EEDi t\u1EDBi ",
5611
5906
  placeholder_email: "Nh\u1EADp \u0111\u1ECBa ch\u1EC9 email c\u1EE7a b\u1EA1n",
@@ -6362,947 +6657,62 @@ import_i18next.default.use(import_i18next_browser_languagedetector.default).use(
6362
6657
  });
6363
6658
  var i18n_default = import_i18next.default;
6364
6659
 
6365
- // src/widget/advance/table/table-group/controller.ts
6366
- var import_hooks13 = require("@fctc/interface-logic/hooks");
6367
- var import_store11 = require("@fctc/interface-logic/store");
6368
-
6369
- // src/environment.ts
6370
- var environment_exports = {};
6371
- __reExport(environment_exports, require("@fctc/interface-logic/environment"));
6372
-
6373
- // src/widget/advance/table/table-group/controller.ts
6374
- var tableGroupController = (props) => {
6375
- const env = (0, environment_exports.getEnv)();
6376
- const {
6377
- rows,
6378
- columns,
6379
- indexRow,
6380
- row,
6381
- model,
6382
- viewData,
6383
- renderField,
6384
- level,
6385
- specification,
6386
- domain,
6387
- context,
6388
- checkedAll,
6389
- isDisplayCheckbox,
6390
- isAutoSelect,
6391
- setIsAutoSelect,
6392
- selectedRowKeysRef
6393
- } = props;
6394
- const [pageGroup, setPageGroup] = (0, import_react17.useState)(0);
6395
- const { groupByDomain, selectedTags } = (0, import_store11.useAppSelector)(import_store11.selectSearch);
6396
- const { selectedRowKeys } = (0, import_store11.useAppSelector)(import_store11.selectList);
6397
- const appDispatch = (0, import_store11.useAppDispatch)();
6398
- const { toDataJS } = (0, import_hooks13.useOdooDataTransform)();
6399
- const initVal = toDataJS(row, viewData, model);
6400
- const [isShowGroup, setIsShowGroup] = (0, import_react17.useState)(false);
6401
- const [colEmptyGroup, setColEmptyGroup] = (0, import_react17.useState)({
6402
- fromStart: 1,
6403
- fromEnd: 1
6404
- });
6405
- const processedData = (0, import_react17.useMemo)(() => {
6406
- const calculateColSpanEmpty = () => {
6407
- const startIndex = columns.findIndex(
6408
- (col) => col.field.type === "monetary" && typeof row[col.key] === "number" || col.field.aggregator === "sum"
6409
- );
6410
- const endIndex = columns.findLastIndex(
6411
- (col) => col.field.type === "monetary" && typeof row[col.key] === "number" || col.field.aggregator !== "sum"
6412
- );
6413
- const fromStart = startIndex === -1 ? columns.length : startIndex;
6414
- const fromEnd = endIndex === -1 ? columns.length : columns.length - 1 - endIndex;
6415
- setColEmptyGroup({ fromStart: fromStart + 1, fromEnd: fromEnd + 1 });
6416
- return { fromStart: fromStart + 1, fromEnd: fromEnd + 1 };
6417
- };
6418
- return calculateColSpanEmpty();
6419
- }, [columns, row]);
6420
- const shouldFetchData = (0, import_react17.useMemo)(() => {
6421
- return !!isShowGroup;
6422
- }, [isShowGroup]);
6423
- const enabled = shouldFetchData && !!processedData;
6424
- const listDataProps = {
6425
- model,
6426
- specification,
6427
- domain,
6428
- context,
6429
- offset: pageGroup * 10,
6430
- fields: groupByDomain?.fields,
6431
- groupby: [groupByDomain?.contexts[level]?.group_by]
6432
- };
6433
- const queryKey = [
6434
- `data-${model}--${level}-row${indexRow}`,
6435
- specification,
6436
- domain,
6437
- pageGroup
6438
- ];
6439
- const {
6440
- data: dataResponse,
6441
- isFetched: isQueryFetched,
6442
- isPlaceholderData,
6443
- isLoading,
6444
- isFetching
6445
- } = (0, import_hooks13.useGetListData)(listDataProps, queryKey, enabled);
6446
- const {
6447
- columns: columnsGroup,
6448
- rows: rowsGroup,
6449
- typeTable: typeTableGroup
6450
- } = tableController({
6451
- data: {
6452
- fields: viewData?.views?.list?.fields,
6453
- records: dataResponse?.records ?? dataResponse?.groups,
6454
- dataModel: viewData?.models?.[model],
6455
- context: env.context,
6456
- typeTable: dataResponse?.groups ? "group" : "list"
6457
- }
6458
- });
6459
- const leftPadding = level > 1 ? level * 8 + "px" : "0px";
6460
- (0, import_react17.useEffect)(() => {
6461
- if (isShowGroup && selectedTags?.length > 0) {
6462
- setIsShowGroup(false);
6463
- }
6464
- }, [selectedTags]);
6465
- const group_by_field_name = groupByDomain?.contexts[level - 1]?.group_by;
6466
- 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(
6467
- (selectItem) => selectItem?.[0] === row[group_by_field_name]
6468
- )?.[1] : row[group_by_field_name];
6469
- const nameGroupWithCount = `${typeof nameGroup === "string" ? nameGroup : typeof nameGroup === "boolean" && nameGroup ? i18n_default.t("yes") : i18n_default.t("no")} (${row[`${group_by_field_name?.split(":")?.[0]}_count`]})`;
6470
- const allIdsNull = selectedRowKeys?.every((item) => item === void 0);
6471
- const handleExpandChildGroup = () => {
6472
- if (isLoading || isFetching) return;
6473
- const toggleShowGroup = () => setIsShowGroup((prev) => !prev);
6474
- if (allIdsNull || typeTableGroup === "group") {
6475
- toggleShowGroup();
6476
- return;
6660
+ // src/widget/basic/float-field/controller.ts
6661
+ var floatController = ({
6662
+ onChange,
6663
+ value,
6664
+ props
6665
+ }) => {
6666
+ const { name, required, methods, onChange: handleOnchange, string } = props;
6667
+ const { setError, clearErrors } = methods;
6668
+ const [inputValue, setInputValue] = (0, import_react19.useState)(
6669
+ value !== void 0 && value !== null ? useFormatFloatNumber(value) : ""
6670
+ );
6671
+ (0, import_react19.useEffect)(() => {
6672
+ if (value !== void 0 && value !== null && value !== parseFloat(inputValue?.replace(/,/g, ""))) {
6673
+ setInputValue(useFormatFloatNumber(value));
6674
+ clearErrors(name);
6675
+ } else if (value === null || value === void 0) {
6676
+ setInputValue("");
6477
6677
  }
6478
- if (isShowGroup && checkedAll) {
6479
- const ids = rowsGroup?.map((item) => item?.id) || [];
6480
- const filteredIds = selectedRowKeys.filter(
6481
- (id) => !ids.includes(id)
6482
- );
6483
- appDispatch((0, import_store11.setSelectedRowKeys)(filteredIds));
6484
- } else if (!isShowGroup && selectedRowKeys?.length > 0 && typeTableGroup === "list" && checkedAll && !allIdsNull && isQueryFetched) {
6485
- const clonedKeys = [...selectedRowKeys];
6486
- appDispatch((0, import_store11.setSelectedRowKeys)([...clonedKeys, -1]));
6487
- setTimeout(() => appDispatch((0, import_store11.setSelectedRowKeys)(clonedKeys)), 500);
6488
- } else if (isShowGroup && selectedRowKeys?.length > 0 && typeTableGroup === "list" && !checkedAll && !allIdsNull) {
6489
- const filteredKeys = selectedRowKeys.filter((id) => id > -1);
6490
- appDispatch((0, import_store11.setSelectedRowKeys)(filteredKeys));
6678
+ }, [value, name, clearErrors]);
6679
+ const isDirtyRef = (0, import_react19.useRef)(false);
6680
+ const inputRef = (0, import_react19.useRef)(null);
6681
+ const lastCommittedValueRef = (0, import_react19.useRef)(null);
6682
+ const handleInputChange = (e) => {
6683
+ const newValue = e.target.value;
6684
+ const valueWithoutCommas = newValue.replace(/,/g, "");
6685
+ if (/^[0-9]*[.,]?[0-9]*$/.test(valueWithoutCommas) || newValue === "") {
6686
+ const parts = valueWithoutCommas.split(".");
6687
+ let integerPart = parts[0] || "";
6688
+ const decimalPart = parts[1] || "";
6689
+ if (decimalPart.length > 100) return;
6690
+ if (integerPart) {
6691
+ integerPart = Number(integerPart).toLocaleString("en-US");
6692
+ }
6693
+ const formattedValue = decimalPart ? `${integerPart}.${decimalPart}` : integerPart;
6694
+ setInputValue(formattedValue);
6695
+ const parsedValue = parseFloat(valueWithoutCommas.replace(",", "."));
6696
+ if (!isNaN(parsedValue)) {
6697
+ if (parsedValue < 0) {
6698
+ setError(name, {
6699
+ type: "validate",
6700
+ message: i18n_default.t("invalid_number")
6701
+ });
6702
+ } else {
6703
+ onChange(parsedValue);
6704
+ clearErrors(name);
6705
+ isDirtyRef.current = true;
6706
+ }
6707
+ } else {
6708
+ onChange(null);
6709
+ clearErrors(name);
6710
+ }
6491
6711
  }
6492
- toggleShowGroup();
6493
6712
  };
6494
- (0, import_react17.useEffect)(() => {
6495
- if (!isQueryFetched || !rowsGroup || !checkedAll || allIdsNull || typeTableGroup === "group") {
6496
- return;
6497
- }
6498
- const clonedKeys = [...selectedRowKeys];
6499
- (0, import_store11.setSelectedRowKeys)([...clonedKeys, -1]);
6500
- setTimeout(() => (0, import_store11.setSelectedRowKeys)(clonedKeys), 500);
6501
- }, [isQueryFetched]);
6502
- return {
6503
- handleExpandChildGroup,
6504
- colEmptyGroup,
6505
- leftPadding,
6506
- isShowGroup,
6507
- isQueryFetched,
6508
- nameGroupWithCount,
6509
- columns,
6510
- row,
6511
- isPlaceholderData,
6512
- columnsGroup,
6513
- indexRow,
6514
- rowsGroup,
6515
- model,
6516
- viewData,
6517
- renderField,
6518
- level,
6519
- specification,
6520
- context,
6521
- checkedAll,
6522
- isDisplayCheckbox,
6523
- isAutoSelect,
6524
- setIsAutoSelect,
6525
- selectedRowKeysRef,
6526
- initVal,
6527
- dataResponse,
6528
- pageGroup,
6529
- setPageGroup
6530
- };
6531
- };
6532
-
6533
- // src/widget/advance/search/controller.ts
6534
- var import_constants3 = require("@fctc/interface-logic/constants");
6535
- var import_utils6 = require("@fctc/interface-logic/utils");
6536
- var import_moment = __toESM(require_moment());
6537
- var import_react18 = require("react");
6538
- var searchController = ({
6539
- viewData,
6540
- actionData,
6541
- fieldsList,
6542
- contextSearch,
6543
- setSearchMap,
6544
- searchMap
6545
- }) => {
6546
- const [filterBy, setFilterBy] = (0, import_react18.useState)(null);
6547
- const [searchBy, setSearchBy] = (0, import_react18.useState)(null);
6548
- const [groupBy, setGroupBy] = (0, import_react18.useState)(null);
6549
- const [selectedTags, setSelectedTags] = (0, import_react18.useState)(null);
6550
- const [searchString, setSearchString] = (0, import_react18.useState)("");
6551
- const aid = actionData?.id;
6552
- const model = actionData?.res_model;
6553
- const clearSearch = () => {
6554
- setFilterBy([]);
6555
- setGroupBy([]);
6556
- setSearchBy([]);
6557
- setSelectedTags(null);
6558
- setSearchString("");
6559
- setSearchMap({});
6560
- };
6561
- const fetchData = async () => {
6562
- if (viewData) {
6563
- try {
6564
- const dataModel = viewData?.models?.[model];
6565
- const searchViews = viewData?.views?.search;
6566
- const searchByItems = searchViews?.search_by?.filter(
6567
- (item) => !import_utils6.domainHelper.matchDomains(contextSearch, item.invisible)
6568
- )?.map(
6569
- ({ string, name, filter_domain, operator, widget }, index) => ({
6570
- dataIndex: index,
6571
- title: string ?? dataModel[name]?.string,
6572
- name: name ?? dataModel[name]?.name,
6573
- filter_domain,
6574
- operator,
6575
- widget,
6576
- type: dataModel[name]?.type
6577
- })
6578
- );
6579
- const filterByItems = searchViews?.filter_by.filter((item) => {
6580
- return !import_utils6.domainHelper.matchDomains(contextSearch, item?.invisible);
6581
- })?.map((item) => ({ ...item, active: false }));
6582
- const groupByItems = searchViews?.group_by.filter(
6583
- (item) => !import_utils6.domainHelper.matchDomains(contextSearch, item?.invisible)
6584
- ).map((item) => ({
6585
- ...item,
6586
- string: item.string ?? viewData?.models?.[model]?.[item?.name?.split("group_by_")?.[1]]?.string
6587
- }));
6588
- setSearchBy(searchByItems);
6589
- setFilterBy(filterByItems);
6590
- setGroupBy(groupByItems);
6591
- } catch (error) {
6592
- console.error("Error fetching data:", error);
6593
- }
6594
- }
6595
- };
6596
- (0, import_react18.useEffect)(() => {
6597
- clearSearch();
6598
- fetchData();
6599
- }, [aid, model, viewData]);
6600
- const onChangeSearchInput = (search_string) => {
6601
- setSearchString(search_string);
6602
- };
6603
- const removeKeyFromSearchMap = ({
6604
- key,
6605
- item
6606
- }) => {
6607
- const values = searchMap[key];
6608
- if (!values) return searchMap;
6609
- const newSearchMap = { ...searchMap };
6610
- if (item) {
6611
- const filtered = values.filter((value) => value.name !== item.name);
6612
- if (filtered.length > 0) {
6613
- newSearchMap[key] = filtered;
6614
- } else {
6615
- delete newSearchMap[key];
6616
- }
6617
- } else {
6618
- delete newSearchMap[key];
6619
- }
6620
- setSearchMap(newSearchMap);
6621
- };
6622
- const updateSearchMap = ({ key, item }) => {
6623
- const newSearchMap = { ...searchMap };
6624
- const currentValues = searchMap[key] ?? [];
6625
- newSearchMap[key] = [...currentValues, item];
6626
- setSearchMap(newSearchMap);
6627
- };
6628
- const removeSearchItems = (key, item) => {
6629
- removeKeyFromSearchMap({ key: String(key), item });
6630
- };
6631
- const addSearchItems = (key, newItem) => {
6632
- updateSearchMap({ key, item: newItem });
6633
- };
6634
- const domainAction = actionData?.domain ? Array.isArray(actionData?.domain) ? [...actionData?.domain] : (0, import_utils6.evalJSONDomain)(actionData?.domain, contextSearch) : [];
6635
- const formatDomain = () => {
6636
- if (domainAction) {
6637
- const domain = [];
6638
- if (domainAction?.length > 0) {
6639
- if (Object.keys(searchMap).length > 0) {
6640
- domain.push("&");
6641
- }
6642
- domainAction.forEach((domainItem) => {
6643
- domain.push(domainItem);
6644
- });
6645
- }
6646
- Object.keys(searchMap).forEach((key, keyIndex, keys) => {
6647
- if (!key?.includes(import_constants3.SearchType.GROUP)) {
6648
- if (keys.length > 1 && keyIndex < keys.length - 1) {
6649
- domain.push("&");
6650
- }
6651
- const valuesOfKey = searchMap[key];
6652
- valuesOfKey.forEach((value, index) => {
6653
- if (index < valuesOfKey.length - 1) {
6654
- domain.push("|");
6655
- }
6656
- if (value.domain) {
6657
- domain.push(...value.domain);
6658
- return;
6659
- }
6660
- let valueDomainItem = value?.value;
6661
- if (value?.modelType === "date") {
6662
- valueDomainItem = (0, import_utils6.validateAndParseDate)(value?.value);
6663
- } else if (value?.modelType === "datetime") {
6664
- if (value?.operator === "<=" || value?.operator === "<") {
6665
- const parsedDate = (0, import_utils6.validateAndParseDate)(value?.value, true);
6666
- const hasTime = (0, import_moment.default)(value?.value).format("HH:mm:ss") !== "00:00:00";
6667
- valueDomainItem = hasTime ? (0, import_moment.default)(parsedDate).format("YYYY-MM-DD HH:mm:ss") : (0, import_moment.default)(parsedDate).add(1, "day").subtract(1, "second").format("YYYY-MM-DD HH:mm:ss");
6668
- } else {
6669
- valueDomainItem = (0, import_utils6.validateAndParseDate)(value?.value, true);
6670
- }
6671
- }
6672
- const operator = value?.modelType === "date" || value?.modelType === "datetime" || value?.modelType === "boolean" || value?.modelType === "integer" ? value?.operator ?? "=" : value.operator ?? "ilike";
6673
- domain.push([value.name, operator, valueDomainItem]);
6674
- });
6675
- }
6676
- });
6677
- return [...domain];
6678
- }
6679
- };
6680
- const setTagSearch = (0, import_react18.useCallback)(
6681
- (updatedMap) => {
6682
- if (!updatedMap) return;
6683
- const tagsSearch = Object.entries(updatedMap).map(
6684
- ([key, objValues]) => {
6685
- const {
6686
- title,
6687
- name,
6688
- groupIndex,
6689
- type,
6690
- widget,
6691
- modelType,
6692
- dataIndex
6693
- } = objValues[0];
6694
- if (!key?.includes(import_constants3.SearchType.GROUP)) {
6695
- const values = objValues?.map((objValue) => objValue.value);
6696
- return {
6697
- title,
6698
- name: type === import_constants3.SearchType.SEARCH ? `${import_constants3.SearchType.SEARCH}_${String(dataIndex)}` : groupIndex ?? name,
6699
- values,
6700
- type,
6701
- widget,
6702
- modelType
6703
- };
6704
- } else {
6705
- const contexts = [];
6706
- let groupValues = [];
6707
- objValues?.forEach((objValue) => {
6708
- const { context, value, active, groupIndex: groupIndex2, isDefault } = objValue;
6709
- const indexAppend = groupIndex2 != null ? groupIndex2 : viewData?.views?.search?.filters_by?.length ?? 0;
6710
- contexts.push(
6711
- ...Array.isArray(context?.group_by) ? context.group_by.map((item) => ({ group_by: item })) : [context]
6712
- );
6713
- groupValues[indexAppend] = {
6714
- contexts: [
6715
- ...Array.isArray(context?.group_by) ? context.group_by.map((item) => ({
6716
- group_by: item
6717
- })) : [context]
6718
- ],
6719
- strings: isDefault ? [value] : [...groupValues[indexAppend]?.strings ?? [], value]
6720
- };
6721
- });
6722
- const fields = [
6723
- ...new Set(fieldsList?.map((item) => item?.name))
6724
- ];
6725
- const groupByTag = {
6726
- title,
6727
- values: groupValues?.filter(
6728
- (item) => item !== void 0
6729
- ),
6730
- type,
6731
- contexts,
6732
- fields
6733
- };
6734
- return groupByTag;
6735
- }
6736
- }
6737
- );
6738
- setSelectedTags(tagsSearch);
6739
- setSearchString("");
6740
- },
6741
- [searchMap]
6742
- );
6743
- (0, import_react18.useEffect)(() => {
6744
- setSelectedTags(null);
6745
- setTagSearch(searchMap);
6746
- }, [searchMap]);
6747
- const handleAddTagSearch = (tag) => {
6748
- const {
6749
- domain,
6750
- groupIndex,
6751
- value,
6752
- type,
6753
- title,
6754
- context,
6755
- active,
6756
- dataIndex
6757
- } = tag;
6758
- const domainFormat = new import_utils6.domainHelper.Domain(domain);
6759
- if (type === import_constants3.SearchType.FILTER) {
6760
- addSearchItems(`${import_constants3.SearchType.FILTER}_${groupIndex}`, {
6761
- ...tag,
6762
- domain: domain ? domainFormat.toList(context) : null
6763
- });
6764
- } else if (type === import_constants3.SearchType.SEARCH) {
6765
- addSearchItems(`${import_constants3.SearchType.SEARCH}_${String(dataIndex)}`, {
6766
- ...tag,
6767
- domain: domain ? domainFormat.toList({
6768
- ...context,
6769
- self: value
6770
- }) : null
6771
- });
6772
- } else if (type === import_constants3.SearchType.GROUP) {
6773
- addSearchItems(`${import_constants3.SearchType.GROUP}`, {
6774
- ...tag,
6775
- domain: domain ? domainFormat.toList({
6776
- context,
6777
- self: value
6778
- }) : null
6779
- });
6780
- }
6781
- };
6782
- return {
6783
- groupBy,
6784
- searchBy,
6785
- filterBy,
6786
- selectedTags,
6787
- searchString,
6788
- setFilterBy,
6789
- setGroupBy,
6790
- setSearchBy,
6791
- clearSearch,
6792
- setSelectedTags,
6793
- removeSearchItems,
6794
- onSearchString: onChangeSearchInput,
6795
- handleAddTagSearch,
6796
- domain: formatDomain()
6797
- };
6798
- };
6799
-
6800
- // src/widget/basic/many2many-field/controller.ts
6801
- var import_environment8 = require("@fctc/interface-logic/environment");
6802
- var import_store12 = require("@fctc/interface-logic/store");
6803
- var import_utils7 = require("@fctc/interface-logic/utils");
6804
- var many2manyFieldController = (props) => {
6805
- const {
6806
- relation,
6807
- domain,
6808
- context,
6809
- tab,
6810
- model,
6811
- aid,
6812
- setSelectedRowKeys: setSelectedRowKeys4,
6813
- fields,
6814
- setFields,
6815
- groupByDomain,
6816
- page,
6817
- options,
6818
- sessionStorageUtils
6819
- } = props;
6820
- const appDispatch = (0, import_store12.useAppDispatch)();
6821
- const actionData = sessionStorageUtils.getActionData();
6822
- const [debouncedPage] = useDebounce(page, 500);
6823
- const [order, setOrder] = (0, import_react19.useState)();
6824
- const [isLoadedData, setIsLoadedData] = (0, import_react19.useState)(false);
6825
- const [domainMany2Many, setDomainMany2Many] = (0, import_react19.useState)(domain);
6826
- const env = (0, import_environment8.getEnv)();
6827
- const { selectedTags } = (0, import_store12.useAppSelector)(import_store12.selectSearch);
6828
- const viewParams = {
6829
- model: relation,
6830
- views: [
6831
- [false, "list"],
6832
- [false, "search"]
6833
- ],
6834
- context
6835
- };
6836
- const { data: viewResponse, isFetched: isViewReponseFetched } = (0, hooks_exports.useGetView)(
6837
- viewParams,
6838
- actionData
6839
- );
6840
- const baseModel = (0, import_react19.useMemo)(
6841
- () => ({
6842
- name: String(relation),
6843
- view: viewResponse || {},
6844
- actContext: context,
6845
- fields: [
6846
- ...Object.values(viewResponse?.views?.list?.fields ?? {}),
6847
- ...tab?.fields ? tab.fields : []
6848
- ]
6849
- }),
6850
- [model, viewResponse]
6851
- );
6852
- const initModel = (0, hooks_exports.useModel)();
6853
- const modelInstance = (0, import_react19.useMemo)(() => {
6854
- if (viewResponse) {
6855
- return initModel.initModel(baseModel);
6856
- }
6857
- return null;
6858
- }, [baseModel, viewResponse]);
6859
- const specification = (0, import_react19.useMemo)(() => {
6860
- if (modelInstance) {
6861
- return modelInstance.getSpecification();
6862
- }
6863
- return null;
6864
- }, [modelInstance]);
6865
- const default_order = viewResponse && viewResponse?.views?.list?.default_order;
6866
- const optionsObject = tab?.options ? (0, import_utils7.evalJSONContext)(tab?.options) : (options ? (0, import_utils7.evalJSONContext)(options) : {}) || {};
6867
- const fetchData = async () => {
6868
- try {
6869
- setDomainMany2Many(domain);
6870
- appDispatch((0, import_store12.setFirstDomain)(domain));
6871
- appDispatch((0, import_store12.setViewDataStore)(viewResponse));
6872
- const modalData = viewResponse?.views?.list?.fields.map((field) => ({
6873
- ...viewResponse?.models?.[String(model)]?.[field?.name],
6874
- ...field
6875
- }));
6876
- if (!fields?.[`${aid}_${relation}_popupmany2many`] && modalData) {
6877
- setFields({
6878
- ...fields,
6879
- [`${aid}_${relation}_popupmany2many`]: modalData
6880
- });
6881
- }
6882
- appDispatch((0, import_store12.setPage)(0));
6883
- } catch (err) {
6884
- console.log(err);
6885
- }
6886
- };
6887
- const queryKey = [
6888
- `view-${relation}-${aid}`,
6889
- specification,
6890
- domainMany2Many,
6891
- debouncedPage,
6892
- groupByDomain,
6893
- order
6894
- ];
6895
- const data = {
6896
- model: relation,
6897
- specification,
6898
- domain: domainMany2Many,
6899
- offset: debouncedPage * 10,
6900
- limit: 10,
6901
- context,
6902
- fields: groupByDomain?.fields,
6903
- groupby: [groupByDomain?.contexts[0]?.group_by],
6904
- sort: order ? order : default_order ? (0, import_utils7.formatSortingString)(default_order) : ""
6905
- };
6906
- const enabled = isLoadedData && !!specification && !!relation && !!domainMany2Many && !!viewResponse;
6907
- const {
6908
- data: dataResponse,
6909
- isLoading: isDataLoading,
6910
- isFetched: isDataResponseFetched,
6911
- isPlaceholderData
6912
- } = (0, hooks_exports.useGetListData)(data, queryKey, enabled);
6913
- (0, import_react19.useEffect)(() => {
6914
- if (viewResponse) {
6915
- fetchData();
6916
- }
6917
- return () => {
6918
- appDispatch((0, import_store12.setGroupByDomain)(null));
6919
- setFields((prevFields) => ({
6920
- ...prevFields,
6921
- [`${aid}_${relation}_popupmany2many`]: null
6922
- }));
6923
- appDispatch((0, import_store12.setPage)(0));
6924
- setSelectedRowKeys4([]);
6925
- setDomainMany2Many(null);
6926
- setIsLoadedData(false);
6927
- };
6928
- }, [viewResponse]);
6929
- const { rows, columns, typeTable } = tableController({
6930
- data: {
6931
- fields: fields?.[`${aid}_${relation}_popupmany2many`] || viewResponse?.views?.list?.fields,
6932
- records: dataResponse?.records ?? dataResponse?.groups,
6933
- dataModel: viewResponse?.models?.[String(relation)],
6934
- context: { ...env.context, ...context },
6935
- typeTable: dataResponse?.groups ? "group" : "list"
6936
- }
6937
- });
6938
- const dataFormView = {
6939
- id: null,
6940
- model: relation,
6941
- context
6942
- };
6943
- const {
6944
- refetch,
6945
- data: dataFormViewResponse,
6946
- isSuccess
6947
- } = (0, hooks_exports.useGetFormView)({
6948
- data: dataFormView,
6949
- queryKey: [`form-view-action-${relation}`],
6950
- enabled: false
6951
- });
6952
- (0, import_react19.useEffect)(() => {
6953
- if (isSuccess && dataFormViewResponse) {
6954
- sessionStorage.setItem("actionData", JSON.stringify(dataFormViewResponse));
6955
- window.location.href = `/form/menu?model=${relation}`;
6956
- }
6957
- }, [isSuccess]);
6958
- (0, import_react19.useEffect)(() => {
6959
- if (domainMany2Many && !isLoadedData) {
6960
- setIsLoadedData(true);
6961
- }
6962
- }, [domainMany2Many]);
6963
- const handleCreateNewOnPage = async () => {
6964
- try {
6965
- refetch();
6966
- } catch (error) {
6967
- console.log(error);
6968
- }
6969
- };
6970
- return {};
6971
- };
6972
-
6973
- // src/widget/basic/many2many-tags-field/controller.ts
6974
- var import_react20 = require("react");
6975
- var import_constants4 = require("@fctc/interface-logic/constants");
6976
- var import_environment9 = require("@fctc/interface-logic/environment");
6977
- var import_hooks15 = require("@fctc/interface-logic/hooks");
6978
- var import_utils8 = require("@fctc/interface-logic/utils");
6979
- var many2manyTagsController = (props) => {
6980
- const {
6981
- relation,
6982
- domain,
6983
- options: optionsFields,
6984
- widget,
6985
- formValues,
6986
- placeholderNoOption
6987
- } = props;
6988
- const isUser = relation === "res.users" || relation === "res.partner";
6989
- const env = (0, import_environment9.getEnv)();
6990
- const addtionalFields = optionsFields ? (0, import_utils8.evalJSONContext)(optionsFields) : null;
6991
- const domainObject = (0, import_react20.useMemo)(
6992
- () => (0, import_utils8.evalJSONDomain)(domain, JSON.parse(JSON.stringify(formValues || {}))),
6993
- [domain, formValues]
6994
- );
6995
- const data = {
6996
- model: relation ?? "",
6997
- domain: domainObject,
6998
- specification: {
6999
- id: {},
7000
- name: {},
7001
- display_name: {},
7002
- ...widget && import_constants4.WIDGETAVATAR[widget] ? { image_256: {} } : {},
7003
- ...widget && import_constants4.WIDGETCOLOR[widget] && addtionalFields?.color_field ? { color: {} } : {}
7004
- },
7005
- enabled: true,
7006
- context: env.context
7007
- };
7008
- const { data: dataOfSelection } = (0, import_hooks15.useGetSelection)({
7009
- data,
7010
- queryKey: [`data_${relation}`, domainObject]
7011
- });
7012
- const customNoOptionsMessage = () => placeholderNoOption;
7013
- const tranfer = (data2) => {
7014
- return data2?.map((val) => ({
7015
- id: val.value,
7016
- display_name: val.label
7017
- })) || [];
7018
- };
7019
- const options = dataOfSelection?.records?.map((val) => ({
7020
- value: val.id,
7021
- label: val.name ?? val.display_name,
7022
- ...val
7023
- })) || [];
7024
- return {
7025
- options,
7026
- customNoOptionsMessage,
7027
- tranfer,
7028
- dataOfSelection,
7029
- isUser
7030
- };
7031
- };
7032
-
7033
- // src/widget/basic/status-bar-field/controller.ts
7034
- var import_react21 = require("react");
7035
- var import_hooks16 = require("@fctc/interface-logic/hooks");
7036
- var import_store13 = require("@fctc/interface-logic/store");
7037
- var import_utils9 = require("@fctc/interface-logic/utils");
7038
- var durationController = (props) => {
7039
- const {
7040
- relation,
7041
- defaultValue,
7042
- domain,
7043
- formValues,
7044
- name,
7045
- id,
7046
- model,
7047
- onRefetch
7048
- } = props;
7049
- const specification = {
7050
- id: 0,
7051
- name: "",
7052
- fold: ""
7053
- };
7054
- const [disabled, setDisabled] = (0, import_react21.useState)(false);
7055
- const [modelStatus, setModalStatus] = (0, import_react21.useState)(false);
7056
- const { context } = (0, import_store13.useAppSelector)(import_store13.selectEnv);
7057
- const queryKey = [`data-status-duration`, specification];
7058
- const listDataProps = {
7059
- model: relation,
7060
- specification,
7061
- domain: (0, import_utils9.evalJSONDomain)(domain, JSON.parse(JSON.stringify(formValues))),
7062
- limit: 10,
7063
- offset: 0,
7064
- fields: "",
7065
- groupby: [],
7066
- context: {
7067
- lang: context.lang
7068
- },
7069
- sort: ""
7070
- };
7071
- const { data: dataResponse } = (0, import_hooks16.useGetListData)(listDataProps, queryKey);
7072
- const { mutate: fetchChangeStatus } = (0, import_hooks16.useChangeStatus)();
7073
- const handleClick = async (stage_id) => {
7074
- setDisabled(true);
7075
- if (stage_id) {
7076
- fetchChangeStatus(
7077
- {
7078
- data: {
7079
- stage_id,
7080
- name,
7081
- id,
7082
- model,
7083
- lang: context.lang
7084
- }
7085
- },
7086
- {
7087
- onSuccess: (res) => {
7088
- if (res) {
7089
- setDisabled(false);
7090
- onRefetch && onRefetch();
7091
- }
7092
- }
7093
- }
7094
- );
7095
- }
7096
- };
7097
- return {
7098
- defaultValue,
7099
- dataResponse,
7100
- handleClick,
7101
- disabled,
7102
- modelStatus,
7103
- setModalStatus
7104
- };
7105
- };
7106
-
7107
- // src/widget/basic/priority-field/controller.ts
7108
- var import_hooks17 = require("@fctc/interface-logic/hooks");
7109
- var import_utils10 = require("@fctc/interface-logic/utils");
7110
- var priorityFieldController = (props) => {
7111
- const {
7112
- value,
7113
- isForm,
7114
- name,
7115
- methods,
7116
- onChange,
7117
- model,
7118
- selection,
7119
- id,
7120
- actionData,
7121
- viewData,
7122
- context
7123
- } = props;
7124
- const _context = { ...(0, import_utils10.evalJSONContext)(actionData?.context) };
7125
- const contextObject = { ...context, ..._context };
7126
- const defaultPriority = parseInt(value) + 1;
7127
- const label = viewData?.models?.[model]?.[name ?? ""]?.string ?? name;
7128
- const { mutateAsync: fetchSave } = (0, import_hooks17.useSave)();
7129
- const savePriorities = async ({
7130
- value: value2,
7131
- resetPriority
7132
- }) => {
7133
- const priorityValue = value2 <= 0 ? 0 : value2 - 1;
7134
- try {
7135
- fetchSave({
7136
- ids: id ? [id] : [],
7137
- data: { [name ?? ""]: String(priorityValue) },
7138
- model: model ?? "",
7139
- context: contextObject
7140
- });
7141
- if (typeof onChange === "function") {
7142
- onChange(name ?? "", String(priorityValue));
7143
- }
7144
- } catch (error) {
7145
- if (resetPriority) {
7146
- resetPriority();
7147
- }
7148
- }
7149
- };
7150
- return {
7151
- selection,
7152
- isForm,
7153
- methods,
7154
- defaultPriority,
7155
- savePriorities,
7156
- label,
7157
- id,
7158
- onChange
7159
- };
7160
- };
7161
-
7162
- // src/widget/basic/float-time-field/controller.ts
7163
- var import_react22 = require("react");
7164
- var import_utils11 = require("@fctc/interface-logic/utils");
7165
- var floatTimeFiledController = ({
7166
- onChange: fieldOnChange,
7167
- onBlur,
7168
- value,
7169
- isDirty,
7170
- props
7171
- }) => {
7172
- const { name, defaultValue = 0, onChange } = props;
7173
- const [input, setInput] = (0, import_react22.useState)(
7174
- (0, import_utils11.convertFloatToTime)(value ?? defaultValue)
7175
- );
7176
- const [formattedTime, setFormattedTime] = (0, import_react22.useState)("");
7177
- const [errors, setErrors] = (0, import_react22.useState)("");
7178
- const handleInputChange = (e) => {
7179
- const raw = e.target.value.replace(/[^\d:]/g, "");
7180
- setInput(raw);
7181
- const timeRegex = /^(\d{1,2}):?(\d{0,2})$/;
7182
- const match = raw.match(timeRegex);
7183
- if (!match) {
7184
- setErrors("\u0110\u1ECBnh d\u1EA1ng kh\xF4ng h\u1EE3p l\u1EC7");
7185
- setFormattedTime("");
7186
- return;
7187
- }
7188
- let hours = parseInt(match[1] ?? "0", 10);
7189
- let minutes = parseInt(match[2] ?? "0", 10);
7190
- if (isNaN(hours)) hours = 0;
7191
- if (isNaN(minutes)) minutes = 0;
7192
- if (hours >= 24) {
7193
- hours = 0;
7194
- }
7195
- if (minutes >= 60) {
7196
- minutes = 0;
7197
- }
7198
- const formatted = `${hours.toString().padStart(2, "0")}:${minutes.toString().padStart(2, "0")}`;
7199
- setErrors("");
7200
- setFormattedTime(formatted);
7201
- fieldOnChange(formatted);
7202
- };
7203
- const handleBlur = () => {
7204
- if (!isDirty) return;
7205
- if (formattedTime) {
7206
- setInput(formattedTime);
7207
- const floatVal = (0, import_utils11.convertTimeToFloat)(formattedTime);
7208
- fieldOnChange(floatVal);
7209
- if (onChange) {
7210
- onChange(name ?? "", floatVal);
7211
- }
7212
- } else {
7213
- setInput("00:00");
7214
- fieldOnChange(0);
7215
- if (onChange) {
7216
- onChange(name ?? "", 0);
7217
- }
7218
- setErrors("");
7219
- }
7220
- onBlur();
7221
- };
7222
- const handleKeyDown = (e) => {
7223
- {
7224
- const allowed = [
7225
- "Backspace",
7226
- "Tab",
7227
- "ArrowLeft",
7228
- "ArrowRight",
7229
- "Delete",
7230
- "Home",
7231
- "End",
7232
- ":"
7233
- ];
7234
- const isNumber = /^[0-9]$/.test(e.key);
7235
- if (!isNumber && !allowed.includes(e.key)) {
7236
- e.preventDefault();
7237
- }
7238
- }
7239
- };
7240
- return {
7241
- handleInputChange,
7242
- handleBlur,
7243
- handleKeyDown,
7244
- input,
7245
- errors
7246
- };
7247
- };
7248
-
7249
- // src/widget/basic/float-field/controller.ts
7250
- var import_react23 = require("react");
7251
- var floatController = ({
7252
- onChange,
7253
- value,
7254
- props
7255
- }) => {
7256
- const { name, required, methods, onChange: handleOnchange, string } = props;
7257
- const { setError, clearErrors } = methods;
7258
- const [inputValue, setInputValue] = (0, import_react23.useState)(
7259
- value !== void 0 && value !== null ? useFormatFloatNumber(value) : ""
7260
- );
7261
- (0, import_react23.useEffect)(() => {
7262
- if (value !== void 0 && value !== null && value !== parseFloat(inputValue?.replace(/,/g, ""))) {
7263
- setInputValue(useFormatFloatNumber(value));
7264
- clearErrors(name);
7265
- } else if (value === null || value === void 0) {
7266
- setInputValue("");
7267
- }
7268
- }, [value, name, clearErrors]);
7269
- const isDirtyRef = (0, import_react23.useRef)(false);
7270
- const inputRef = (0, import_react23.useRef)(null);
7271
- const lastCommittedValueRef = (0, import_react23.useRef)(null);
7272
- const handleInputChange = (e) => {
7273
- const newValue = e.target.value;
7274
- const valueWithoutCommas = newValue.replace(/,/g, "");
7275
- if (/^[0-9]*[.,]?[0-9]*$/.test(valueWithoutCommas) || newValue === "") {
7276
- const parts = valueWithoutCommas.split(".");
7277
- let integerPart = parts[0] || "";
7278
- const decimalPart = parts[1] || "";
7279
- if (decimalPart.length > 100) return;
7280
- if (integerPart) {
7281
- integerPart = Number(integerPart).toLocaleString("en-US");
7282
- }
7283
- const formattedValue = decimalPart ? `${integerPart}.${decimalPart}` : integerPart;
7284
- setInputValue(formattedValue);
7285
- const parsedValue = parseFloat(valueWithoutCommas.replace(",", "."));
7286
- if (!isNaN(parsedValue)) {
7287
- if (parsedValue < 0) {
7288
- setError(name, {
7289
- type: "validate",
7290
- message: i18n_default.t("invalid_number")
7291
- });
7292
- } else {
7293
- onChange(parsedValue);
7294
- clearErrors(name);
7295
- isDirtyRef.current = true;
7296
- }
7297
- } else {
7298
- onChange(null);
7299
- clearErrors(name);
7300
- }
7301
- }
7302
- };
7303
- const handleInputMouseLeave = () => {
7304
- if (!isDirtyRef.current) {
7305
- inputRef.current?.blur();
6713
+ const handleInputMouseLeave = () => {
6714
+ if (!isDirtyRef.current) {
6715
+ inputRef.current?.blur();
7306
6716
  return;
7307
6717
  }
7308
6718
  const rawValue = inputValue.replace(/,/g, "");
@@ -7369,10 +6779,10 @@ var useFormatFloatNumber = (value) => {
7369
6779
  };
7370
6780
 
7371
6781
  // src/widget/basic/download-file-field/controller.ts
7372
- var import_react24 = require("react");
6782
+ var import_react20 = require("react");
7373
6783
  var downloadFileController = () => {
7374
- const inputId = (0, import_react24.useId)();
7375
- const [file, setFile] = (0, import_react24.useState)(null);
6784
+ const inputId = (0, import_react20.useId)();
6785
+ const [file, setFile] = (0, import_react20.useState)(null);
7376
6786
  const handleFileChange = (e) => {
7377
6787
  setFile(e.target.files[0]);
7378
6788
  };
@@ -7414,297 +6824,897 @@ var downLoadBinaryController = (props) => {
7414
6824
  document.body.removeChild(link);
7415
6825
  window.URL.revokeObjectURL(urlBlob);
7416
6826
  }
7417
- } catch (error) {
7418
- console.error("File download failed:", error);
6827
+ } catch (error) {
6828
+ console.error("File download failed:", error);
6829
+ }
6830
+ };
6831
+ return {
6832
+ handleFileDownload
6833
+ };
6834
+ };
6835
+
6836
+ // src/widget/basic/date-field/controller.ts
6837
+ var import_moment = __toESM(require_moment());
6838
+ var DURATIONS = {
6839
+ PAST: "past",
6840
+ NOW: "now",
6841
+ FUTURE: "future"
6842
+ };
6843
+ var dateFieldController = (props) => {
6844
+ const {
6845
+ string,
6846
+ showTime = false,
6847
+ widget,
6848
+ min,
6849
+ max,
6850
+ viewData,
6851
+ formValues,
6852
+ model
6853
+ } = props;
6854
+ const range = (start, end, step = 1) => {
6855
+ const arr = [];
6856
+ for (let i = start; i < end; i += step) {
6857
+ arr.push(i);
6858
+ }
6859
+ return arr;
6860
+ };
6861
+ const formatDate = showTime ? "DD/MM/YYYY HH:mm:ss" : "DD/MM/YYYY";
6862
+ const formatDateParse = showTime ? "YYYY-MM-DD HH:mm:ss" : "YYYY-MM-DD";
6863
+ const fieldForCustom = widget === "datetime_custom" || widget === "date_custom";
6864
+ const minNowValue = fieldForCustom && (min === DURATIONS.NOW ? true : typeof min === "string" && Object.keys(formValues)?.includes(min) && formValues?.[min] ? (0, import_moment.default)(formValues?.[min], formatDateParse).add(7, "hours") : null);
6865
+ const maxNowValue = fieldForCustom && (max === DURATIONS.NOW ? true : typeof max === "string" && Object.keys(formValues)?.includes(max) && formValues?.[max] ? (0, import_moment.default)(formValues?.[max], formatDateParse).add(7, "hours") : null);
6866
+ const years = range(
6867
+ minNowValue ? (/* @__PURE__ */ new Date()).getFullYear() : 1990,
6868
+ (/* @__PURE__ */ new Date()).getFullYear() + 4,
6869
+ 1
6870
+ );
6871
+ const months_vi = [
6872
+ "Th\xE1ng 1",
6873
+ "Th\xE1ng 2",
6874
+ "Th\xE1ng 3",
6875
+ "Th\xE1ng 4",
6876
+ "Th\xE1ng 5",
6877
+ "Th\xE1ng 6",
6878
+ "Th\xE1ng 7",
6879
+ "Th\xE1ng 8",
6880
+ "Th\xE1ng 9",
6881
+ "Th\xE1ng 10",
6882
+ "Th\xE1ng 11",
6883
+ "Th\xE1ng 12"
6884
+ ];
6885
+ const months_en = [
6886
+ "January",
6887
+ "February",
6888
+ "March",
6889
+ "April",
6890
+ "May",
6891
+ "June",
6892
+ "July",
6893
+ "August",
6894
+ "September",
6895
+ "October",
6896
+ "November",
6897
+ "December"
6898
+ ];
6899
+ const customValidateMinMax = (date) => {
6900
+ const selected = (0, import_moment.default)(date, formatDateParse);
6901
+ const now = (0, import_moment.default)();
6902
+ const compareSelected = showTime ? selected : selected.clone().startOf("day");
6903
+ const compareNow = showTime ? now : now.clone().startOf("day");
6904
+ if (minNowValue) {
6905
+ if (compareSelected.isBefore(compareNow) && typeof minNowValue === "boolean" && minNowValue === true) {
6906
+ return `${i18n_default.t("please_enter")} ${string} ${i18n_default.t(
6907
+ "greater_or_equal_now"
6908
+ )}`;
6909
+ } else if (import_moment.default.isMoment(minNowValue)) {
6910
+ const compareMin = showTime ? minNowValue : minNowValue.clone().startOf("day");
6911
+ if (compareSelected.isBefore(compareMin)) {
6912
+ const fieldRelationDate = viewData?.models?.[model]?.[min ?? ""];
6913
+ return `${i18n_default.t("please_enter")} ${string} ${i18n_default.t(
6914
+ "greater_or_equal"
6915
+ )} ${fieldRelationDate?.string}`;
6916
+ }
6917
+ }
6918
+ } else if (maxNowValue) {
6919
+ if (compareSelected.isAfter(compareNow) && typeof maxNowValue === "boolean" && maxNowValue === true) {
6920
+ return `${i18n_default.t("please_enter")} ${string} ${i18n_default.t(
6921
+ "less_or_equal_now"
6922
+ )}`;
6923
+ } else if (import_moment.default.isMoment(maxNowValue)) {
6924
+ const compareMax = showTime ? maxNowValue : maxNowValue.clone().startOf("day");
6925
+ if (compareSelected.isAfter(compareMax)) {
6926
+ const fieldRelationDate = viewData?.models?.[model]?.[max ?? ""];
6927
+ return `${i18n_default.t("please_enter")} ${string} ${i18n_default.t(
6928
+ "less_or_equal"
6929
+ )} ${fieldRelationDate?.string}`;
6930
+ }
6931
+ }
6932
+ }
6933
+ return false;
6934
+ };
6935
+ return {
6936
+ formatDate,
6937
+ formatDateParse,
6938
+ range,
6939
+ years,
6940
+ months_vi,
6941
+ months_en,
6942
+ customValidateMinMax,
6943
+ minNowValue,
6944
+ maxNowValue
6945
+ };
6946
+ };
6947
+
6948
+ // src/widget/basic/copy-link-button/controller.ts
6949
+ var import_react21 = require("react");
6950
+ var import_utils11 = require("@fctc/interface-logic/utils");
6951
+ var copyLinkButtonController = (props) => {
6952
+ const { value, defaultValue } = props;
6953
+ const [isCopied, setIsCopied] = (0, import_react21.useState)(false);
6954
+ const handleCopyToClipboard = async (value2) => {
6955
+ await (0, import_utils11.copyTextToClipboard)(value2);
6956
+ setIsCopied(true);
6957
+ setTimeout(() => setIsCopied(false), 2e3);
6958
+ };
6959
+ const propValue = value || defaultValue;
6960
+ return {
6961
+ isCopied,
6962
+ handleCopyToClipboard,
6963
+ propValue
6964
+ };
6965
+ };
6966
+
6967
+ // src/widget/basic/color-field/color-controller.ts
6968
+ var import_environment8 = require("@fctc/interface-logic/environment");
6969
+ var import_hooks17 = require("@fctc/interface-logic/hooks");
6970
+ var import_utils12 = require("@fctc/interface-logic/utils");
6971
+ var colorFieldController = (props) => {
6972
+ const { value, isForm, name, formValues, idForm, model, actionData } = props;
6973
+ const env = (0, import_environment8.getEnv)();
6974
+ const _context = { ...(0, import_utils12.evalJSONContext)(actionData?.context) || {} };
6975
+ const contextObject = { ...env.context, ..._context };
6976
+ const idDefault = isForm ? idForm : formValues?.id;
6977
+ const { mutate: onSave } = (0, import_hooks17.useSave)();
6978
+ const savePickColor = async (colorObject) => {
6979
+ const { id } = colorObject;
6980
+ if (value === id) return;
6981
+ try {
6982
+ onSave({
6983
+ ids: idDefault !== null ? [idDefault] : [],
6984
+ model: model ?? "",
6985
+ data: { [name ?? ""]: id },
6986
+ specification: {
6987
+ name: {},
6988
+ color: {}
6989
+ },
6990
+ context: contextObject
6991
+ });
6992
+ } catch (error) {
6993
+ console.log(error);
6994
+ }
6995
+ };
6996
+ return {
6997
+ savePickColor
6998
+ };
6999
+ };
7000
+
7001
+ // src/widget/basic/binary-field/controller.ts
7002
+ var import_react22 = require("react");
7003
+ var import_utils13 = require("@fctc/interface-logic/utils");
7004
+ var binaryFieldController = (props) => {
7005
+ const { name, methods, readonly = false, value } = props;
7006
+ const inputId = (0, import_react22.useId)();
7007
+ const [selectedImage, setSelectedImage] = (0, import_react22.useState)(null);
7008
+ const [initialImage, setInitialImage] = (0, import_react22.useState)(value || null);
7009
+ const [isInsideTable, setIsInsideTable] = (0, import_react22.useState)(false);
7010
+ const { setValue } = methods;
7011
+ const binaryRef = (0, import_react22.useRef)(null);
7012
+ const convertUrlToBase64 = async (url) => {
7013
+ try {
7014
+ const response = await fetch(url);
7015
+ const blob = await response.blob();
7016
+ return new Promise((resolve, reject) => {
7017
+ const reader = new FileReader();
7018
+ reader.onloadend = () => {
7019
+ resolve(reader.result);
7020
+ };
7021
+ reader.onerror = reject;
7022
+ reader.readAsDataURL(blob);
7023
+ });
7024
+ } catch (error) {
7025
+ console.error("Error converting URL to Base64:", error);
7026
+ throw error;
7027
+ }
7028
+ };
7029
+ const extractBase64Data = (base64Url) => {
7030
+ if (base64Url.includes("base64,")) {
7031
+ return base64Url.split("base64,")[1];
7032
+ }
7033
+ return base64Url;
7034
+ };
7035
+ const handleImageChange = async (e, onChange) => {
7036
+ if (readonly) return;
7037
+ const file = e?.target?.files?.[0];
7038
+ if (file) {
7039
+ const imageUrl = URL.createObjectURL(file);
7040
+ setSelectedImage(imageUrl);
7041
+ setInitialImage(null);
7042
+ onChange(file);
7043
+ const compressedBase64 = await convertUrlToBase64(imageUrl);
7044
+ const base64Data = extractBase64Data(compressedBase64);
7045
+ setValue(name, base64Data, {
7046
+ shouldDirty: true
7047
+ });
7048
+ }
7049
+ };
7050
+ const handleRemoveImage = (onChange) => {
7051
+ setSelectedImage(null);
7052
+ setInitialImage(null);
7053
+ onChange(null);
7054
+ };
7055
+ const isBlobUrl = (url) => {
7056
+ return /^blob:/.test(url);
7057
+ };
7058
+ const checkIsImageLink = (url) => {
7059
+ const imageExtensions = /\.(jpg|jpeg|png|gif|bmp|webp|svg|tiff|ico)$/i;
7060
+ return imageExtensions.test(url) || (0, import_utils13.isBase64Image)(url) || isBlobUrl(url);
7061
+ };
7062
+ const getImageBase64WithMimeType = (base64) => {
7063
+ if (typeof base64 !== "string" || base64.length < 10) return null;
7064
+ if ((0, import_utils13.isBase64Image)(base64)) return base64;
7065
+ let mimeType = null;
7066
+ if (base64.startsWith("iVBORw0KGgo")) mimeType = "image/png";
7067
+ else if (base64.startsWith("/9j/")) mimeType = "image/jpeg";
7068
+ else if (base64.startsWith("R0lGOD")) mimeType = "image/gif";
7069
+ else if (base64.startsWith("Qk")) mimeType = "image/bmp";
7070
+ else if (base64.startsWith("UklGR")) mimeType = "image/webp";
7071
+ return mimeType ? `data:${mimeType};base64,${base64}` : null;
7072
+ };
7073
+ (0, import_react22.useEffect)(() => {
7074
+ return () => {
7075
+ if (selectedImage) {
7076
+ URL.revokeObjectURL(selectedImage);
7077
+ }
7078
+ };
7079
+ }, [selectedImage]);
7080
+ (0, import_react22.useEffect)(() => {
7081
+ if (binaryRef.current) {
7082
+ const isInsideTable2 = !!binaryRef.current.closest("table");
7083
+ setIsInsideTable(isInsideTable2);
7419
7084
  }
7420
- };
7085
+ }, []);
7421
7086
  return {
7422
- handleFileDownload
7087
+ inputId,
7088
+ selectedImage,
7089
+ initialImage,
7090
+ isInsideTable,
7091
+ binaryRef,
7092
+ handleImageChange,
7093
+ handleRemoveImage,
7094
+ checkIsImageLink,
7095
+ getImageBase64WithMimeType
7423
7096
  };
7424
7097
  };
7425
7098
 
7426
- // src/widget/basic/date-field/controller.ts
7427
- var import_moment2 = __toESM(require_moment());
7428
- var DURATIONS = {
7429
- PAST: "past",
7430
- NOW: "now",
7431
- FUTURE: "future"
7432
- };
7433
- var dateFieldController = (props) => {
7099
+ // src/widget/advance/table/table-body/controller.ts
7100
+ var import_store10 = require("@fctc/interface-logic/store");
7101
+ var import_react23 = require("react");
7102
+ var tableBodyController = (props) => {
7434
7103
  const {
7435
- string,
7436
- showTime = false,
7437
- widget,
7438
- min,
7439
- max,
7440
- viewData,
7441
- formValues,
7442
- model
7104
+ checkedAll,
7105
+ checkboxRef,
7106
+ setIsAutoSelect,
7107
+ selectedRowKeys,
7108
+ row,
7109
+ isAutoSelect,
7110
+ selectedRowKeysRef,
7111
+ onClickRow
7443
7112
  } = props;
7444
- const range = (start, end, step = 1) => {
7445
- const arr = [];
7446
- for (let i = start; i < end; i += step) {
7447
- arr.push(i);
7113
+ const appDispatch = (0, import_store10.useAppDispatch)();
7114
+ const checked = (0, import_react23.useMemo)(() => {
7115
+ if (!row?.id) return false;
7116
+ if (selectedRowKeys?.includes(row.id)) {
7117
+ return true;
7448
7118
  }
7449
- return arr;
7119
+ return checkedAll;
7120
+ }, [row?.id, selectedRowKeys, checkedAll]);
7121
+ const handleCheckBoxSingle = (event) => {
7122
+ event.stopPropagation();
7123
+ if (checkedAll) {
7124
+ checkboxRef.current = "uncheck";
7125
+ setIsAutoSelect(true);
7126
+ return;
7127
+ }
7128
+ const newSelectedRowKeys = selectedRowKeys?.includes(row.id) ? selectedRowKeys?.filter((key) => key !== row.id) : [...selectedRowKeys, row.id];
7129
+ console.log("newSelectedRowKeys", newSelectedRowKeys);
7130
+ appDispatch((0, import_store10.setSelectedRowKeys)(newSelectedRowKeys));
7450
7131
  };
7451
- const formatDate = showTime ? "DD/MM/YYYY HH:mm:ss" : "DD/MM/YYYY";
7452
- const formatDateParse = showTime ? "YYYY-MM-DD HH:mm:ss" : "YYYY-MM-DD";
7453
- const fieldForCustom = widget === "datetime_custom" || widget === "date_custom";
7454
- const minNowValue = fieldForCustom && (min === DURATIONS.NOW ? true : typeof min === "string" && Object.keys(formValues)?.includes(min) && formValues?.[min] ? (0, import_moment2.default)(formValues?.[min], formatDateParse).add(7, "hours") : null);
7455
- const maxNowValue = fieldForCustom && (max === DURATIONS.NOW ? true : typeof max === "string" && Object.keys(formValues)?.includes(max) && formValues?.[max] ? (0, import_moment2.default)(formValues?.[max], formatDateParse).add(7, "hours") : null);
7456
- const years = range(
7457
- minNowValue ? (/* @__PURE__ */ new Date()).getFullYear() : 1990,
7458
- (/* @__PURE__ */ new Date()).getFullYear() + 4,
7459
- 1
7460
- );
7461
- const months_vi = [
7462
- "Th\xE1ng 1",
7463
- "Th\xE1ng 2",
7464
- "Th\xE1ng 3",
7465
- "Th\xE1ng 4",
7466
- "Th\xE1ng 5",
7467
- "Th\xE1ng 6",
7468
- "Th\xE1ng 7",
7469
- "Th\xE1ng 8",
7470
- "Th\xE1ng 9",
7471
- "Th\xE1ng 10",
7472
- "Th\xE1ng 11",
7473
- "Th\xE1ng 12"
7474
- ];
7475
- const months_en = [
7476
- "January",
7477
- "February",
7478
- "March",
7479
- "April",
7480
- "May",
7481
- "June",
7482
- "July",
7483
- "August",
7484
- "September",
7485
- "October",
7486
- "November",
7487
- "December"
7488
- ];
7489
- const customValidateMinMax = (date) => {
7490
- const selected = (0, import_moment2.default)(date, formatDateParse);
7491
- const now = (0, import_moment2.default)();
7492
- const compareSelected = showTime ? selected : selected.clone().startOf("day");
7493
- const compareNow = showTime ? now : now.clone().startOf("day");
7494
- if (minNowValue) {
7495
- if (compareSelected.isBefore(compareNow) && typeof minNowValue === "boolean" && minNowValue === true) {
7496
- return `${i18n_default.t("please_enter")} ${string} ${i18n_default.t(
7497
- "greater_or_equal_now"
7498
- )}`;
7499
- } else if (import_moment2.default.isMoment(minNowValue)) {
7500
- const compareMin = showTime ? minNowValue : minNowValue.clone().startOf("day");
7501
- if (compareSelected.isBefore(compareMin)) {
7502
- const fieldRelationDate = viewData?.models?.[model]?.[min ?? ""];
7503
- return `${i18n_default.t("please_enter")} ${string} ${i18n_default.t(
7504
- "greater_or_equal"
7505
- )} ${fieldRelationDate?.string}`;
7506
- }
7132
+ const handleClickRow = (col, row2) => {
7133
+ onClickRow(col, row2);
7134
+ };
7135
+ (0, import_react23.useEffect)(() => {
7136
+ if (!row?.id) return;
7137
+ if (isAutoSelect) {
7138
+ if (checkboxRef?.current === "uncheck") {
7139
+ const filtered = selectedRowKeysRef.current.filter(
7140
+ (id) => id !== row.id
7141
+ );
7142
+ selectedRowKeysRef.current = filtered;
7143
+ appDispatch((0, import_store10.setSelectedRowKeys)(filtered));
7144
+ } else {
7145
+ const unique = Array.from(
7146
+ /* @__PURE__ */ new Set([...selectedRowKeysRef?.current, row?.id])
7147
+ );
7148
+ selectedRowKeysRef.current = unique;
7149
+ appDispatch((0, import_store10.setSelectedRowKeys)(unique));
7507
7150
  }
7508
- } else if (maxNowValue) {
7509
- if (compareSelected.isAfter(compareNow) && typeof maxNowValue === "boolean" && maxNowValue === true) {
7510
- return `${i18n_default.t("please_enter")} ${string} ${i18n_default.t(
7511
- "less_or_equal_now"
7512
- )}`;
7513
- } else if (import_moment2.default.isMoment(maxNowValue)) {
7514
- const compareMax = showTime ? maxNowValue : maxNowValue.clone().startOf("day");
7515
- if (compareSelected.isAfter(compareMax)) {
7516
- const fieldRelationDate = viewData?.models?.[model]?.[max ?? ""];
7517
- return `${i18n_default.t("please_enter")} ${string} ${i18n_default.t(
7518
- "less_or_equal"
7519
- )} ${fieldRelationDate?.string}`;
7520
- }
7151
+ }
7152
+ }, [isAutoSelect]);
7153
+ (0, import_react23.useEffect)(() => {
7154
+ if (!checkedAll) {
7155
+ checkboxRef.current = "enabled";
7156
+ false;
7157
+ }
7158
+ }, [checkedAll]);
7159
+ return {
7160
+ handleCheckBoxSingle,
7161
+ checked,
7162
+ handleClickRow
7163
+ };
7164
+ };
7165
+
7166
+ // src/widget/advance/table/table-head/controller.ts
7167
+ var import_store11 = require("@fctc/interface-logic/store");
7168
+ var tableHeadController = (props) => {
7169
+ const { typeTable, rows, selectedRowKeysRef } = props;
7170
+ const appDispatch = (0, import_store11.useAppDispatch)();
7171
+ const { groupByDomain } = (0, import_store11.useAppSelector)(import_store11.selectSearch);
7172
+ const handleCheckBoxAll = (event) => {
7173
+ if (event?.target?.checked && typeTable === "list") {
7174
+ const allRowKeys = Array.isArray(rows) ? rows.map((record) => record?.id) : [];
7175
+ appDispatch((0, import_store11.setSelectedRowKeys)(allRowKeys));
7176
+ } else if (event?.target?.checked && typeTable === "group") {
7177
+ const rowsIDs = document.querySelectorAll("tr[data-row-id]");
7178
+ const ids = Array.from(rowsIDs)?.map(
7179
+ (row) => Number(row?.getAttribute("data-row-id"))
7180
+ );
7181
+ if (ids?.length > 0) {
7182
+ appDispatch((0, import_store11.setSelectedRowKeys)(ids));
7183
+ } else {
7184
+ const sum = countSum(
7185
+ rows,
7186
+ typeof groupByDomain === "object" ? groupByDomain?.contexts?.[0]?.group_by : void 0
7187
+ );
7188
+ const keys = Array.from({ length: sum }, (_) => void 0);
7189
+ appDispatch((0, import_store11.setSelectedRowKeys)(keys));
7190
+ }
7191
+ if (selectedRowKeysRef) {
7192
+ selectedRowKeysRef.current = [];
7521
7193
  }
7194
+ } else {
7195
+ appDispatch((0, import_store11.setSelectedRowKeys)([]));
7522
7196
  }
7523
- return false;
7524
7197
  };
7525
7198
  return {
7526
- formatDate,
7527
- formatDateParse,
7528
- range,
7529
- years,
7530
- months_vi,
7531
- months_en,
7532
- customValidateMinMax,
7533
- minNowValue,
7534
- maxNowValue
7199
+ handleCheckBoxAll
7535
7200
  };
7536
7201
  };
7537
7202
 
7538
- // src/widget/basic/copy-link-button/controller.ts
7539
- var import_react25 = require("react");
7540
- var import_utils12 = require("@fctc/interface-logic/utils");
7541
- var copyLinkButtonController = (props) => {
7542
- const { value, defaultValue } = props;
7543
- const [isCopied, setIsCopied] = (0, import_react25.useState)(false);
7544
- const handleCopyToClipboard = async (value2) => {
7545
- await (0, import_utils12.copyTextToClipboard)(value2);
7546
- setIsCopied(true);
7547
- setTimeout(() => setIsCopied(false), 2e3);
7203
+ // src/widget/advance/table/table-view/controller.ts
7204
+ var import_react24 = require("react");
7205
+ var import_store12 = require("@fctc/interface-logic/store");
7206
+ var import_utils14 = require("@fctc/interface-logic/utils");
7207
+ var tableController = ({ data }) => {
7208
+ const [rows, setRows] = (0, import_react24.useState)(data.records || []);
7209
+ const [columns, setColumns] = (0, import_react24.useState)([]);
7210
+ const dataModelFields = data.fields?.map((field) => {
7211
+ return {
7212
+ ...data.dataModel?.[field?.name],
7213
+ ...field,
7214
+ string: field?.string || data.dataModel?.[field?.name]?.string
7215
+ };
7216
+ });
7217
+ const mergeFields = mergeButtons(dataModelFields);
7218
+ const transformData = (dataList) => {
7219
+ if (!dataList) return;
7220
+ return dataList?.map((item) => {
7221
+ const transformedItem = { ...item };
7222
+ Object.keys(item).forEach((field) => {
7223
+ if (field !== "__domain") {
7224
+ if (item[field] && typeof item[field] === "object" && item[field].display_name) {
7225
+ transformedItem[field] = item[field];
7226
+ } else if (Array.isArray(item[field]) && item[field].length > 0) {
7227
+ if (data.typeTable === "group" && item[field]?.length === 2 && typeof item[field]?.[1] === "string") {
7228
+ transformedItem["string"] = item[field]?.[1];
7229
+ }
7230
+ transformedItem[field] = item[field];
7231
+ }
7232
+ }
7233
+ });
7234
+ return item.display_name ? { ...transformedItem, item: item.display_name } : transformedItem;
7235
+ });
7236
+ };
7237
+ (0, import_react24.useEffect)(() => {
7238
+ setRows(transformData(data.records || null));
7239
+ }, [data.records]);
7240
+ const handleGetColumns = () => {
7241
+ let cols = [];
7242
+ try {
7243
+ cols = mergeFields?.filter((item) => {
7244
+ return item?.widget !== "details_Receive_money" && !(item?.column_invisible ? import_utils14.domainHelper.matchDomains(data.context, item?.column_invisible) : item?.invisible ? import_utils14.domainHelper.matchDomains(data.context, item?.invisible) : false);
7245
+ })?.map((field) => {
7246
+ return {
7247
+ name: field?.name,
7248
+ optional: field?.optional,
7249
+ title: field?.type_co === "button" ? "" : field?.string,
7250
+ field: { ...field }
7251
+ };
7252
+ });
7253
+ } catch (error) {
7254
+ console.error("Error in useTable:", error);
7255
+ }
7256
+ return cols;
7257
+ };
7258
+ (0, import_react24.useEffect)(() => {
7259
+ const columns2 = handleGetColumns();
7260
+ setColumns(columns2);
7261
+ }, [data.records]);
7262
+ const onToggleColumnOptional = (item) => {
7263
+ const tempColumn = [...columns]?.map((val) => {
7264
+ if (item?.name === val?.name) {
7265
+ return {
7266
+ ...val,
7267
+ optional: item?.optional === "show" ? "hide" : "show"
7268
+ };
7269
+ }
7270
+ return val;
7271
+ });
7272
+ setColumns(tempColumn);
7548
7273
  };
7549
- const propValue = value || defaultValue;
7550
7274
  return {
7551
- isCopied,
7552
- handleCopyToClipboard,
7553
- propValue
7275
+ rows,
7276
+ columns,
7277
+ onToggleColumnOptional,
7278
+ typeTable: data.typeTable
7554
7279
  };
7555
7280
  };
7556
7281
 
7557
- // src/widget/basic/color-field/color-controller.ts
7558
- var import_environment10 = require("@fctc/interface-logic/environment");
7282
+ // src/widget/advance/table/table-group/controller.ts
7283
+ var import_react25 = require("react");
7559
7284
  var import_hooks18 = require("@fctc/interface-logic/hooks");
7560
- var import_utils13 = require("@fctc/interface-logic/utils");
7561
- var colorFieldController = (props) => {
7562
- const { value, isForm, name, formValues, idForm, model, actionData } = props;
7563
- const env = (0, import_environment10.getEnv)();
7564
- const _context = { ...(0, import_utils13.evalJSONContext)(actionData?.context) || {} };
7565
- const contextObject = { ...env.context, ..._context };
7566
- const idDefault = isForm ? idForm : formValues?.id;
7567
- const { mutate: onSave } = (0, import_hooks18.useSave)();
7568
- const savePickColor = async (colorObject) => {
7569
- const { id } = colorObject;
7570
- if (value === id) return;
7571
- try {
7572
- onSave({
7573
- ids: idDefault !== null ? [idDefault] : [],
7574
- model: model ?? "",
7575
- data: { [name ?? ""]: id },
7576
- specification: {
7577
- name: {},
7578
- color: {}
7579
- },
7580
- context: contextObject
7581
- });
7582
- } catch (error) {
7583
- console.log(error);
7285
+ var import_store13 = require("@fctc/interface-logic/store");
7286
+
7287
+ // src/environment.ts
7288
+ var environment_exports = {};
7289
+ __reExport(environment_exports, require("@fctc/interface-logic/environment"));
7290
+
7291
+ // src/widget/advance/table/table-group/controller.ts
7292
+ var tableGroupController = (props) => {
7293
+ const env = (0, environment_exports.getEnv)();
7294
+ const {
7295
+ rows,
7296
+ columns,
7297
+ indexRow,
7298
+ row,
7299
+ model,
7300
+ viewData,
7301
+ renderField,
7302
+ level,
7303
+ specification,
7304
+ domain,
7305
+ context,
7306
+ checkedAll,
7307
+ isDisplayCheckbox,
7308
+ isAutoSelect,
7309
+ setIsAutoSelect,
7310
+ selectedRowKeysRef
7311
+ } = props;
7312
+ const [pageGroup, setPageGroup] = (0, import_react25.useState)(0);
7313
+ const { groupByDomain, selectedTags } = (0, import_store13.useAppSelector)(import_store13.selectSearch);
7314
+ const { selectedRowKeys } = (0, import_store13.useAppSelector)(import_store13.selectList);
7315
+ const appDispatch = (0, import_store13.useAppDispatch)();
7316
+ const { toDataJS } = (0, import_hooks18.useOdooDataTransform)();
7317
+ const initVal = toDataJS(row, viewData, model);
7318
+ const [isShowGroup, setIsShowGroup] = (0, import_react25.useState)(false);
7319
+ const [colEmptyGroup, setColEmptyGroup] = (0, import_react25.useState)({
7320
+ fromStart: 1,
7321
+ fromEnd: 1
7322
+ });
7323
+ const processedData = (0, import_react25.useMemo)(() => {
7324
+ const calculateColSpanEmpty = () => {
7325
+ const startIndex = columns.findIndex(
7326
+ (col) => col.field.type === "monetary" && typeof row[col.key] === "number" || col.field.aggregator === "sum"
7327
+ );
7328
+ const endIndex = columns.findLastIndex(
7329
+ (col) => col.field.type === "monetary" && typeof row[col.key] === "number" || col.field.aggregator !== "sum"
7330
+ );
7331
+ const fromStart = startIndex === -1 ? columns.length : startIndex;
7332
+ const fromEnd = endIndex === -1 ? columns.length : columns.length - 1 - endIndex;
7333
+ setColEmptyGroup({ fromStart: fromStart + 1, fromEnd: fromEnd + 1 });
7334
+ return { fromStart: fromStart + 1, fromEnd: fromEnd + 1 };
7335
+ };
7336
+ return calculateColSpanEmpty();
7337
+ }, [columns, row]);
7338
+ const shouldFetchData = (0, import_react25.useMemo)(() => {
7339
+ return !!isShowGroup;
7340
+ }, [isShowGroup]);
7341
+ const enabled = shouldFetchData && !!processedData;
7342
+ const listDataProps = {
7343
+ model,
7344
+ specification,
7345
+ domain,
7346
+ context,
7347
+ offset: pageGroup * 10,
7348
+ fields: groupByDomain?.fields,
7349
+ groupby: [groupByDomain?.contexts[level]?.group_by]
7350
+ };
7351
+ const queryKey = [
7352
+ `data-${model}--${level}-row${indexRow}`,
7353
+ specification,
7354
+ domain,
7355
+ pageGroup
7356
+ ];
7357
+ const {
7358
+ data: dataResponse,
7359
+ isFetched: isQueryFetched,
7360
+ isPlaceholderData,
7361
+ isLoading,
7362
+ isFetching
7363
+ } = (0, import_hooks18.useGetListData)(listDataProps, queryKey, enabled);
7364
+ const {
7365
+ columns: columnsGroup,
7366
+ rows: rowsGroup,
7367
+ typeTable: typeTableGroup
7368
+ } = tableController({
7369
+ data: {
7370
+ fields: viewData?.views?.list?.fields,
7371
+ records: dataResponse?.records ?? dataResponse?.groups,
7372
+ dataModel: viewData?.models?.[model],
7373
+ context: env.context,
7374
+ typeTable: dataResponse?.groups ? "group" : "list"
7375
+ }
7376
+ });
7377
+ const leftPadding = level > 1 ? level * 8 + "px" : "0px";
7378
+ (0, import_react25.useEffect)(() => {
7379
+ if (isShowGroup && selectedTags?.length > 0) {
7380
+ setIsShowGroup(false);
7381
+ }
7382
+ }, [selectedTags]);
7383
+ const group_by_field_name = groupByDomain?.contexts[level - 1]?.group_by;
7384
+ 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(
7385
+ (selectItem) => selectItem?.[0] === row[group_by_field_name]
7386
+ )?.[1] : row[group_by_field_name];
7387
+ const nameGroupWithCount = `${typeof nameGroup === "string" ? nameGroup : typeof nameGroup === "boolean" && nameGroup ? i18n_default.t("yes") : i18n_default.t("no")} (${row[`${group_by_field_name?.split(":")?.[0]}_count`]})`;
7388
+ const allIdsNull = selectedRowKeys?.every((item) => item === void 0);
7389
+ const handleExpandChildGroup = () => {
7390
+ if (isLoading || isFetching) return;
7391
+ const toggleShowGroup = () => setIsShowGroup((prev) => !prev);
7392
+ if (allIdsNull || typeTableGroup === "group") {
7393
+ toggleShowGroup();
7394
+ return;
7584
7395
  }
7396
+ if (isShowGroup && checkedAll) {
7397
+ const ids = rowsGroup?.map((item) => item?.id) || [];
7398
+ const filteredIds = selectedRowKeys.filter(
7399
+ (id) => !ids.includes(id)
7400
+ );
7401
+ appDispatch((0, import_store13.setSelectedRowKeys)(filteredIds));
7402
+ } else if (!isShowGroup && selectedRowKeys?.length > 0 && typeTableGroup === "list" && checkedAll && !allIdsNull && isQueryFetched) {
7403
+ const clonedKeys = [...selectedRowKeys];
7404
+ appDispatch((0, import_store13.setSelectedRowKeys)([...clonedKeys, -1]));
7405
+ setTimeout(() => appDispatch((0, import_store13.setSelectedRowKeys)(clonedKeys)), 500);
7406
+ } else if (isShowGroup && selectedRowKeys?.length > 0 && typeTableGroup === "list" && !checkedAll && !allIdsNull) {
7407
+ const filteredKeys = selectedRowKeys.filter((id) => id > -1);
7408
+ appDispatch((0, import_store13.setSelectedRowKeys)(filteredKeys));
7409
+ }
7410
+ toggleShowGroup();
7585
7411
  };
7412
+ (0, import_react25.useEffect)(() => {
7413
+ if (!isQueryFetched || !rowsGroup || !checkedAll || allIdsNull || typeTableGroup === "group") {
7414
+ return;
7415
+ }
7416
+ const clonedKeys = [...selectedRowKeys];
7417
+ (0, import_store13.setSelectedRowKeys)([...clonedKeys, -1]);
7418
+ setTimeout(() => (0, import_store13.setSelectedRowKeys)(clonedKeys), 500);
7419
+ }, [isQueryFetched]);
7586
7420
  return {
7587
- savePickColor
7421
+ handleExpandChildGroup,
7422
+ colEmptyGroup,
7423
+ leftPadding,
7424
+ isShowGroup,
7425
+ isQueryFetched,
7426
+ nameGroupWithCount,
7427
+ columns,
7428
+ row,
7429
+ isPlaceholderData,
7430
+ columnsGroup,
7431
+ indexRow,
7432
+ rowsGroup,
7433
+ model,
7434
+ viewData,
7435
+ renderField,
7436
+ level,
7437
+ specification,
7438
+ context,
7439
+ checkedAll,
7440
+ isDisplayCheckbox,
7441
+ isAutoSelect,
7442
+ setIsAutoSelect,
7443
+ selectedRowKeysRef,
7444
+ initVal,
7445
+ dataResponse,
7446
+ pageGroup,
7447
+ setPageGroup
7588
7448
  };
7589
7449
  };
7590
7450
 
7591
- // src/widget/basic/binary-field/controller.ts
7451
+ // src/widget/advance/search/controller.ts
7452
+ var import_constants5 = require("@fctc/interface-logic/constants");
7453
+ var import_utils15 = require("@fctc/interface-logic/utils");
7454
+ var import_moment2 = __toESM(require_moment());
7592
7455
  var import_react26 = require("react");
7593
- var import_utils14 = require("@fctc/interface-logic/utils");
7594
- var binaryFieldController = (props) => {
7595
- const { name, methods, readonly = false, value } = props;
7596
- const inputId = (0, import_react26.useId)();
7597
- const [selectedImage, setSelectedImage] = (0, import_react26.useState)(null);
7598
- const [initialImage, setInitialImage] = (0, import_react26.useState)(value || null);
7599
- const [isInsideTable, setIsInsideTable] = (0, import_react26.useState)(false);
7600
- const { setValue } = methods;
7601
- const binaryRef = (0, import_react26.useRef)(null);
7602
- const convertUrlToBase64 = async (url) => {
7603
- try {
7604
- const response = await fetch(url);
7605
- const blob = await response.blob();
7606
- return new Promise((resolve, reject) => {
7607
- const reader = new FileReader();
7608
- reader.onloadend = () => {
7609
- resolve(reader.result);
7610
- };
7611
- reader.onerror = reject;
7612
- reader.readAsDataURL(blob);
7613
- });
7614
- } catch (error) {
7615
- console.error("Error converting URL to Base64:", error);
7616
- throw error;
7456
+ var searchController = ({
7457
+ viewData,
7458
+ actionData,
7459
+ fieldsList,
7460
+ contextSearch,
7461
+ setSearchMap,
7462
+ searchMap
7463
+ }) => {
7464
+ const [filterBy, setFilterBy] = (0, import_react26.useState)(null);
7465
+ const [searchBy, setSearchBy] = (0, import_react26.useState)(null);
7466
+ const [groupBy, setGroupBy] = (0, import_react26.useState)(null);
7467
+ const [selectedTags, setSelectedTags] = (0, import_react26.useState)(null);
7468
+ const [searchString, setSearchString] = (0, import_react26.useState)("");
7469
+ const domainAction = actionData?.domain ? Array.isArray(actionData?.domain) ? [...actionData?.domain] : (0, import_utils15.evalJSONDomain)(actionData?.domain, contextSearch) : [];
7470
+ const aid = actionData?.id;
7471
+ const model = actionData?.res_model;
7472
+ const clearSearch = () => {
7473
+ setFilterBy([]);
7474
+ setGroupBy([]);
7475
+ setSearchBy([]);
7476
+ setSelectedTags(null);
7477
+ setSearchString("");
7478
+ setSearchMap({});
7479
+ };
7480
+ const fetchData = async () => {
7481
+ if (viewData) {
7482
+ try {
7483
+ const dataModel = viewData?.models?.[model];
7484
+ const searchViews = viewData?.views?.search;
7485
+ const searchByItems = searchViews?.search_by?.filter(
7486
+ (item) => !import_utils15.domainHelper.matchDomains(contextSearch, item.invisible)
7487
+ )?.map(
7488
+ ({ string, name, filter_domain, operator, widget }, index) => ({
7489
+ dataIndex: index,
7490
+ title: string ?? dataModel[name]?.string,
7491
+ name: name ?? dataModel[name]?.name,
7492
+ filter_domain,
7493
+ operator,
7494
+ widget,
7495
+ type: dataModel[name]?.type
7496
+ })
7497
+ );
7498
+ const filterByItems = searchViews?.filter_by.filter((item) => {
7499
+ return !import_utils15.domainHelper.matchDomains(contextSearch, item?.invisible);
7500
+ })?.map((item) => ({ ...item, active: false }));
7501
+ const groupByItems = searchViews?.group_by.filter(
7502
+ (item) => !import_utils15.domainHelper.matchDomains(contextSearch, item?.invisible)
7503
+ ).map((item) => ({
7504
+ ...item,
7505
+ string: item.string ?? viewData?.models?.[model]?.[item?.name?.split("group_by_")?.[1]]?.string
7506
+ }));
7507
+ setSearchBy(searchByItems);
7508
+ setFilterBy(filterByItems);
7509
+ setGroupBy(groupByItems);
7510
+ } catch (error) {
7511
+ console.error("Error fetching data:", error);
7512
+ }
7617
7513
  }
7618
7514
  };
7619
- const extractBase64Data = (base64Url) => {
7620
- if (base64Url.includes("base64,")) {
7621
- return base64Url.split("base64,")[1];
7622
- }
7623
- return base64Url;
7515
+ (0, import_react26.useEffect)(() => {
7516
+ clearSearch();
7517
+ fetchData();
7518
+ }, [aid, model, viewData]);
7519
+ const onChangeSearchInput = (search_string) => {
7520
+ setSearchString(search_string);
7624
7521
  };
7625
- const handleImageChange = async (e, onChange) => {
7626
- if (readonly) return;
7627
- const file = e?.target?.files?.[0];
7628
- if (file) {
7629
- const imageUrl = URL.createObjectURL(file);
7630
- setSelectedImage(imageUrl);
7631
- setInitialImage(null);
7632
- onChange(file);
7633
- const compressedBase64 = await convertUrlToBase64(imageUrl);
7634
- const base64Data = extractBase64Data(compressedBase64);
7635
- setValue(name, base64Data, {
7636
- shouldDirty: true
7637
- });
7522
+ const removeKeyFromSearchMap = ({
7523
+ key,
7524
+ item
7525
+ }) => {
7526
+ const values = searchMap[key];
7527
+ if (!values) return searchMap;
7528
+ const newSearchMap = { ...searchMap };
7529
+ if (item) {
7530
+ const filtered = values.filter((value) => value.name !== item.name);
7531
+ if (filtered.length > 0) {
7532
+ newSearchMap[key] = filtered;
7533
+ } else {
7534
+ delete newSearchMap[key];
7535
+ }
7536
+ } else {
7537
+ delete newSearchMap[key];
7638
7538
  }
7539
+ setSearchMap(newSearchMap);
7639
7540
  };
7640
- const handleRemoveImage = (onChange) => {
7641
- setSelectedImage(null);
7642
- setInitialImage(null);
7643
- onChange(null);
7644
- };
7645
- const isBlobUrl = (url) => {
7646
- return /^blob:/.test(url);
7541
+ const updateSearchMap = ({ key, item }) => {
7542
+ const newSearchMap = { ...searchMap };
7543
+ const currentValues = searchMap[key] ?? [];
7544
+ newSearchMap[key] = [...currentValues, item];
7545
+ setSearchMap(newSearchMap);
7647
7546
  };
7648
- const checkIsImageLink = (url) => {
7649
- const imageExtensions = /\.(jpg|jpeg|png|gif|bmp|webp|svg|tiff|ico)$/i;
7650
- return imageExtensions.test(url) || (0, import_utils14.isBase64Image)(url) || isBlobUrl(url);
7547
+ const removeSearchItems = (key, item) => {
7548
+ removeKeyFromSearchMap({ key: String(key), item });
7651
7549
  };
7652
- const getImageBase64WithMimeType = (base64) => {
7653
- if (typeof base64 !== "string" || base64.length < 10) return null;
7654
- if ((0, import_utils14.isBase64Image)(base64)) return base64;
7655
- let mimeType = null;
7656
- if (base64.startsWith("iVBORw0KGgo")) mimeType = "image/png";
7657
- else if (base64.startsWith("/9j/")) mimeType = "image/jpeg";
7658
- else if (base64.startsWith("R0lGOD")) mimeType = "image/gif";
7659
- else if (base64.startsWith("Qk")) mimeType = "image/bmp";
7660
- else if (base64.startsWith("UklGR")) mimeType = "image/webp";
7661
- return mimeType ? `data:${mimeType};base64,${base64}` : null;
7550
+ const addSearchItems = (key, newItem) => {
7551
+ updateSearchMap({ key, item: newItem });
7662
7552
  };
7663
- (0, import_react26.useEffect)(() => {
7664
- return () => {
7665
- if (selectedImage) {
7666
- URL.revokeObjectURL(selectedImage);
7553
+ const formatDomain = () => {
7554
+ if (domainAction) {
7555
+ const domain = [];
7556
+ if (domainAction?.length > 0) {
7557
+ if (Object.keys(searchMap).length > 0) {
7558
+ domain.push("&");
7559
+ }
7560
+ domainAction.forEach((domainItem) => {
7561
+ domain.push(domainItem);
7562
+ });
7667
7563
  }
7668
- };
7669
- }, [selectedImage]);
7564
+ Object.keys(searchMap).forEach((key, keyIndex, keys) => {
7565
+ if (!key?.includes(import_constants5.SearchType.GROUP)) {
7566
+ if (keys.length > 1 && keyIndex < keys.length - 1) {
7567
+ domain.push("&");
7568
+ }
7569
+ const valuesOfKey = searchMap[key];
7570
+ valuesOfKey.forEach((value, index) => {
7571
+ if (index < valuesOfKey.length - 1) {
7572
+ domain.push("|");
7573
+ }
7574
+ if (value.domain) {
7575
+ domain.push(...value.domain);
7576
+ return;
7577
+ }
7578
+ let valueDomainItem = value?.value;
7579
+ if (value?.modelType === "date") {
7580
+ valueDomainItem = (0, import_utils15.validateAndParseDate)(value?.value);
7581
+ } else if (value?.modelType === "datetime") {
7582
+ if (value?.operator === "<=" || value?.operator === "<") {
7583
+ const parsedDate = (0, import_utils15.validateAndParseDate)(value?.value, true);
7584
+ const hasTime = (0, import_moment2.default)(value?.value).format("HH:mm:ss") !== "00:00:00";
7585
+ 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");
7586
+ } else {
7587
+ valueDomainItem = (0, import_utils15.validateAndParseDate)(value?.value, true);
7588
+ }
7589
+ }
7590
+ const operator = value?.modelType === "date" || value?.modelType === "datetime" || value?.modelType === "boolean" || value?.modelType === "integer" ? value?.operator ?? "=" : value.operator ?? "ilike";
7591
+ domain.push([value.name, operator, valueDomainItem]);
7592
+ });
7593
+ }
7594
+ });
7595
+ return [...domain];
7596
+ }
7597
+ };
7598
+ const setTagSearch = (0, import_react26.useCallback)(
7599
+ (updatedMap) => {
7600
+ if (!updatedMap) return;
7601
+ const tagsSearch = Object.entries(updatedMap).map(
7602
+ ([key, objValues]) => {
7603
+ const {
7604
+ title,
7605
+ name,
7606
+ groupIndex,
7607
+ type,
7608
+ widget,
7609
+ modelType,
7610
+ dataIndex
7611
+ } = objValues[0];
7612
+ if (!key?.includes(import_constants5.SearchType.GROUP)) {
7613
+ const values = objValues?.map((objValue) => objValue.value);
7614
+ return {
7615
+ title,
7616
+ name: type === import_constants5.SearchType.SEARCH ? `${import_constants5.SearchType.SEARCH}_${String(dataIndex)}` : groupIndex ?? name,
7617
+ values,
7618
+ type,
7619
+ widget,
7620
+ modelType
7621
+ };
7622
+ } else {
7623
+ const contexts = [];
7624
+ let groupValues = [];
7625
+ objValues?.forEach((objValue) => {
7626
+ const { context, value, active, groupIndex: groupIndex2, isDefault } = objValue;
7627
+ const indexAppend = groupIndex2 != null ? groupIndex2 : viewData?.views?.search?.filters_by?.length ?? 0;
7628
+ contexts.push(
7629
+ ...Array.isArray(context?.group_by) ? context.group_by.map((item) => ({ group_by: item })) : [context]
7630
+ );
7631
+ groupValues[indexAppend] = {
7632
+ contexts: [
7633
+ ...Array.isArray(context?.group_by) ? context.group_by.map((item) => ({
7634
+ group_by: item
7635
+ })) : [context]
7636
+ ],
7637
+ strings: isDefault ? [value] : [...groupValues[indexAppend]?.strings ?? [], value]
7638
+ };
7639
+ });
7640
+ const fields = [
7641
+ ...new Set(fieldsList?.map((item) => item?.name))
7642
+ ];
7643
+ const groupByTag = {
7644
+ title,
7645
+ values: groupValues?.filter(
7646
+ (item) => item !== void 0
7647
+ ),
7648
+ type,
7649
+ contexts,
7650
+ fields
7651
+ };
7652
+ return groupByTag;
7653
+ }
7654
+ }
7655
+ );
7656
+ setSelectedTags(tagsSearch);
7657
+ setSearchString("");
7658
+ },
7659
+ [searchMap]
7660
+ );
7670
7661
  (0, import_react26.useEffect)(() => {
7671
- if (binaryRef.current) {
7672
- const isInsideTable2 = !!binaryRef.current.closest("table");
7673
- setIsInsideTable(isInsideTable2);
7662
+ setSelectedTags(null);
7663
+ setTagSearch(searchMap);
7664
+ }, [searchMap]);
7665
+ const handleAddTagSearch = (tag) => {
7666
+ const {
7667
+ domain,
7668
+ groupIndex,
7669
+ value,
7670
+ type,
7671
+ title,
7672
+ context,
7673
+ active,
7674
+ dataIndex
7675
+ } = tag;
7676
+ const domainFormat = new import_utils15.domainHelper.Domain(domain);
7677
+ if (type === import_constants5.SearchType.FILTER) {
7678
+ addSearchItems(`${import_constants5.SearchType.FILTER}_${groupIndex}`, {
7679
+ ...tag,
7680
+ domain: domain ? domainFormat.toList(context) : null
7681
+ });
7682
+ } else if (type === import_constants5.SearchType.SEARCH) {
7683
+ addSearchItems(`${import_constants5.SearchType.SEARCH}_${String(dataIndex)}`, {
7684
+ ...tag,
7685
+ domain: domain ? domainFormat.toList({
7686
+ ...context,
7687
+ self: value
7688
+ }) : null
7689
+ });
7690
+ } else if (type === import_constants5.SearchType.GROUP) {
7691
+ addSearchItems(`${import_constants5.SearchType.GROUP}`, {
7692
+ ...tag,
7693
+ domain: domain ? domainFormat.toList({
7694
+ context,
7695
+ self: value
7696
+ }) : null
7697
+ });
7674
7698
  }
7675
- }, []);
7699
+ };
7676
7700
  return {
7677
- inputId,
7678
- selectedImage,
7679
- initialImage,
7680
- isInsideTable,
7681
- binaryRef,
7682
- handleImageChange,
7683
- handleRemoveImage,
7684
- checkIsImageLink,
7685
- getImageBase64WithMimeType
7701
+ groupBy,
7702
+ searchBy,
7703
+ filterBy,
7704
+ selectedTags,
7705
+ searchString,
7706
+ setFilterBy,
7707
+ setGroupBy,
7708
+ setSearchBy,
7709
+ clearSearch,
7710
+ setSelectedTags,
7711
+ removeSearchItems,
7712
+ onSearchString: onChangeSearchInput,
7713
+ handleAddTagSearch,
7714
+ domain: formatDomain()
7686
7715
  };
7687
7716
  };
7688
7717
 
7689
- // src/utils.ts
7690
- var utils_exports = {};
7691
- __export(utils_exports, {
7692
- API_APP_URL: () => API_APP_URL,
7693
- API_PRESCHOOL_URL: () => API_PRESCHOOL_URL,
7694
- STORAGES: () => STORAGES,
7695
- combineContexts: () => combineContexts,
7696
- convertFieldsToArray: () => convertFieldsToArray,
7697
- countSum: () => countSum,
7698
- getDateRange: () => getDateRange,
7699
- languages: () => languages,
7700
- mergeButtons: () => mergeButtons,
7701
- setStorageItemAsync: () => setStorageItemAsync,
7702
- useGetRowIds: () => useGetRowIds,
7703
- useSelectionState: () => useSelectionState,
7704
- useStorageState: () => useStorageState
7705
- });
7706
- __reExport(utils_exports, require("@fctc/interface-logic/utils"));
7707
-
7708
7718
  // src/index.ts
7709
7719
  __reExport(index_exports, utils_exports, module.exports);
7710
7720
  __reExport(index_exports, store_exports, module.exports);
@@ -7716,12 +7726,6 @@ __reExport(constants_exports, require("@fctc/interface-logic/constants"));
7716
7726
  // src/index.ts
7717
7727
  __reExport(index_exports, constants_exports, module.exports);
7718
7728
  __reExport(index_exports, environment_exports, module.exports);
7719
-
7720
- // src/provider.ts
7721
- var provider_exports = {};
7722
- __reExport(provider_exports, require("@fctc/interface-logic/provider"));
7723
-
7724
- // src/index.ts
7725
7729
  __reExport(index_exports, provider_exports, module.exports);
7726
7730
 
7727
7731
  // src/services.ts