@fctc/widget-logic 1.2.2 → 1.2.4
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/hooks.js +3 -7
- package/dist/hooks.mjs +3 -7
- package/dist/index.js +758 -760
- package/dist/index.mjs +895 -897
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -4724,9 +4724,7 @@ var AppProvider = ({ children }) => {
|
|
|
4724
4724
|
return combineContexts([user.context, company.context]);
|
|
4725
4725
|
}, [user.context, company.context]);
|
|
4726
4726
|
const menu = useMenu({ context: menuContext });
|
|
4727
|
-
const action = useMemo7(() =>
|
|
4728
|
-
return menu.state.action;
|
|
4729
|
-
}, [menu.state.action]);
|
|
4727
|
+
const action = useMemo7(() => menu.state.action, [menu.state.action]);
|
|
4730
4728
|
const viewContext = useMemo7(() => {
|
|
4731
4729
|
return combineContexts([
|
|
4732
4730
|
menuContext,
|
|
@@ -4755,15 +4753,13 @@ var AppProvider = ({ children }) => {
|
|
|
4755
4753
|
action,
|
|
4756
4754
|
view
|
|
4757
4755
|
},
|
|
4758
|
-
children
|
|
4756
|
+
children
|
|
4759
4757
|
}
|
|
4760
4758
|
);
|
|
4761
4759
|
};
|
|
4762
4760
|
var useAppProvider = () => {
|
|
4763
4761
|
const context = useContext(ReactContext);
|
|
4764
|
-
if (!context)
|
|
4765
|
-
return AppProviderInitialValue;
|
|
4766
|
-
}
|
|
4762
|
+
if (!context) return AppProviderInitialValue;
|
|
4767
4763
|
return context;
|
|
4768
4764
|
};
|
|
4769
4765
|
|
|
@@ -5163,7 +5159,7 @@ var many2oneFieldController = (props) => {
|
|
|
5163
5159
|
const queryKey = [`data_${relation}`, domainObject];
|
|
5164
5160
|
const {
|
|
5165
5161
|
data: dataOfSelection,
|
|
5166
|
-
refetch,
|
|
5162
|
+
// refetch,
|
|
5167
5163
|
isFetching
|
|
5168
5164
|
} = useGetSelection({
|
|
5169
5165
|
data,
|
|
@@ -5192,9 +5188,6 @@ var many2oneFieldController = (props) => {
|
|
|
5192
5188
|
});
|
|
5193
5189
|
}
|
|
5194
5190
|
}, [propValue]);
|
|
5195
|
-
const fetchMoreOptions = useCallback6(() => {
|
|
5196
|
-
refetch();
|
|
5197
|
-
}, [refetch]);
|
|
5198
5191
|
useEffect10(() => {
|
|
5199
5192
|
if (actionId) {
|
|
5200
5193
|
localStorage.setItem("aid", actionId);
|
|
@@ -5251,6 +5244,12 @@ var many2oneFieldController = (props) => {
|
|
|
5251
5244
|
[methods, name, onChange]
|
|
5252
5245
|
);
|
|
5253
5246
|
const allowShowDetail = showDetail && contextObject?.form_view_ref && (!("no_open" in optionsObject) || optionsObject?.no_open === false);
|
|
5247
|
+
const fetchMoreOptions = useCallback6(() => {
|
|
5248
|
+
if (typeof dataOfSelection?.refetch === "function") {
|
|
5249
|
+
;
|
|
5250
|
+
dataOfSelection.refetch();
|
|
5251
|
+
}
|
|
5252
|
+
}, [dataOfSelection]);
|
|
5254
5253
|
return {
|
|
5255
5254
|
allowShowDetail,
|
|
5256
5255
|
handleClose,
|
|
@@ -5266,7 +5265,8 @@ var many2oneFieldController = (props) => {
|
|
|
5266
5265
|
setTempSelectedOption,
|
|
5267
5266
|
setDomainModal,
|
|
5268
5267
|
dataOfSelection,
|
|
5269
|
-
refetch
|
|
5268
|
+
refetch: dataOfSelection?.refetch ?? (() => {
|
|
5269
|
+
}),
|
|
5270
5270
|
selectOptions,
|
|
5271
5271
|
optionsObject,
|
|
5272
5272
|
contextObject,
|
|
@@ -5306,32 +5306,141 @@ var many2oneButtonController = (props) => {
|
|
|
5306
5306
|
};
|
|
5307
5307
|
|
|
5308
5308
|
// src/widget/basic/many2many-field/controller.ts
|
|
5309
|
-
import { useEffect as
|
|
5309
|
+
import { useEffect as useEffect14, useMemo as useMemo12, useState as useState10 } from "react";
|
|
5310
5310
|
import {
|
|
5311
5311
|
evalJSONContext as evalJSONContext4,
|
|
5312
5312
|
formatSortingString as formatSortingString2,
|
|
5313
|
-
getEnv as
|
|
5314
|
-
selectSearch as
|
|
5313
|
+
getEnv as getEnv9,
|
|
5314
|
+
selectSearch as selectSearch5,
|
|
5315
5315
|
setFirstDomain,
|
|
5316
5316
|
setGroupByDomain,
|
|
5317
5317
|
setPage,
|
|
5318
5318
|
setViewDataStore,
|
|
5319
|
-
useAppDispatch as
|
|
5320
|
-
useAppSelector as
|
|
5319
|
+
useAppDispatch as useAppDispatch8,
|
|
5320
|
+
useAppSelector as useAppSelector7,
|
|
5321
5321
|
useGetFormView,
|
|
5322
|
-
useGetListData as
|
|
5322
|
+
useGetListData as useGetListData3,
|
|
5323
5323
|
useGetView as useGetView2,
|
|
5324
5324
|
useModel as useModel2
|
|
5325
5325
|
} from "@fctc/interface-logic";
|
|
5326
5326
|
|
|
5327
|
+
// src/widget/advance/table/table-body/controller.ts
|
|
5328
|
+
import { setSelectedRowKeys, useAppDispatch as useAppDispatch5 } from "@fctc/interface-logic";
|
|
5329
|
+
import { useEffect as useEffect11, useMemo as useMemo9 } from "react";
|
|
5330
|
+
var tableBodyController = (props) => {
|
|
5331
|
+
const {
|
|
5332
|
+
checkedAll,
|
|
5333
|
+
checkboxRef,
|
|
5334
|
+
setIsAutoSelect,
|
|
5335
|
+
selectedRowKeys,
|
|
5336
|
+
row,
|
|
5337
|
+
isAutoSelect,
|
|
5338
|
+
selectedRowKeysRef,
|
|
5339
|
+
onClickRow
|
|
5340
|
+
} = props;
|
|
5341
|
+
const appDispatch = useAppDispatch5();
|
|
5342
|
+
const checked = useMemo9(() => {
|
|
5343
|
+
if (!row?.id) return false;
|
|
5344
|
+
if (selectedRowKeys?.includes(row.id)) {
|
|
5345
|
+
return true;
|
|
5346
|
+
}
|
|
5347
|
+
return checkedAll;
|
|
5348
|
+
}, [row?.id, selectedRowKeys, checkedAll]);
|
|
5349
|
+
const handleCheckBoxSingle = (event) => {
|
|
5350
|
+
event.stopPropagation();
|
|
5351
|
+
if (checkedAll) {
|
|
5352
|
+
checkboxRef.current = "uncheck";
|
|
5353
|
+
setIsAutoSelect(true);
|
|
5354
|
+
return;
|
|
5355
|
+
}
|
|
5356
|
+
const newSelectedRowKeys = selectedRowKeys?.includes(row.id) ? selectedRowKeys?.filter((key) => key !== row.id) : [...selectedRowKeys, row.id];
|
|
5357
|
+
console.log("newSelectedRowKeys", newSelectedRowKeys);
|
|
5358
|
+
appDispatch(setSelectedRowKeys(newSelectedRowKeys));
|
|
5359
|
+
};
|
|
5360
|
+
const handleClickRow = (col, row2) => {
|
|
5361
|
+
onClickRow(col, row2);
|
|
5362
|
+
};
|
|
5363
|
+
useEffect11(() => {
|
|
5364
|
+
if (!row?.id) return;
|
|
5365
|
+
if (isAutoSelect) {
|
|
5366
|
+
if (checkboxRef?.current === "uncheck") {
|
|
5367
|
+
const filtered = selectedRowKeysRef.current.filter(
|
|
5368
|
+
(id) => id !== row.id
|
|
5369
|
+
);
|
|
5370
|
+
selectedRowKeysRef.current = filtered;
|
|
5371
|
+
appDispatch(setSelectedRowKeys(filtered));
|
|
5372
|
+
} else {
|
|
5373
|
+
const unique = Array.from(
|
|
5374
|
+
/* @__PURE__ */ new Set([...selectedRowKeysRef?.current, row?.id])
|
|
5375
|
+
);
|
|
5376
|
+
selectedRowKeysRef.current = unique;
|
|
5377
|
+
appDispatch(setSelectedRowKeys(unique));
|
|
5378
|
+
}
|
|
5379
|
+
}
|
|
5380
|
+
}, [isAutoSelect]);
|
|
5381
|
+
useEffect11(() => {
|
|
5382
|
+
if (!checkedAll) {
|
|
5383
|
+
checkboxRef.current = "enabled";
|
|
5384
|
+
false;
|
|
5385
|
+
}
|
|
5386
|
+
}, [checkedAll]);
|
|
5387
|
+
return {
|
|
5388
|
+
handleCheckBoxSingle,
|
|
5389
|
+
checked,
|
|
5390
|
+
handleClickRow
|
|
5391
|
+
};
|
|
5392
|
+
};
|
|
5393
|
+
|
|
5394
|
+
// src/widget/advance/table/table-head/controller.ts
|
|
5395
|
+
import {
|
|
5396
|
+
selectSearch as selectSearch2,
|
|
5397
|
+
setSelectedRowKeys as setSelectedRowKeys2,
|
|
5398
|
+
useAppDispatch as useAppDispatch6,
|
|
5399
|
+
useAppSelector as useAppSelector4
|
|
5400
|
+
} from "@fctc/interface-logic";
|
|
5401
|
+
var tableHeadController = (props) => {
|
|
5402
|
+
const { typeTable, rows, selectedRowKeysRef } = props;
|
|
5403
|
+
const appDispatch = useAppDispatch6();
|
|
5404
|
+
const { groupByDomain } = useAppSelector4(selectSearch2);
|
|
5405
|
+
const handleCheckBoxAll = (event) => {
|
|
5406
|
+
if (event?.target?.checked && typeTable === "list") {
|
|
5407
|
+
const allRowKeys = Array.isArray(rows) ? rows.map((record) => record?.id) : [];
|
|
5408
|
+
appDispatch(setSelectedRowKeys2(allRowKeys));
|
|
5409
|
+
} else if (event?.target?.checked && typeTable === "group") {
|
|
5410
|
+
const rowsIDs = document.querySelectorAll("tr[data-row-id]");
|
|
5411
|
+
const ids = Array.from(rowsIDs)?.map(
|
|
5412
|
+
(row) => Number(row?.getAttribute("data-row-id"))
|
|
5413
|
+
);
|
|
5414
|
+
if (ids?.length > 0) {
|
|
5415
|
+
appDispatch(setSelectedRowKeys2(ids));
|
|
5416
|
+
} else {
|
|
5417
|
+
const sum = countSum(
|
|
5418
|
+
rows,
|
|
5419
|
+
typeof groupByDomain === "object" ? groupByDomain?.contexts?.[0]?.group_by : void 0
|
|
5420
|
+
);
|
|
5421
|
+
const keys = Array.from({ length: sum }, (_) => void 0);
|
|
5422
|
+
appDispatch(setSelectedRowKeys2(keys));
|
|
5423
|
+
}
|
|
5424
|
+
if (selectedRowKeysRef) {
|
|
5425
|
+
selectedRowKeysRef.current = [];
|
|
5426
|
+
}
|
|
5427
|
+
} else {
|
|
5428
|
+
appDispatch(setSelectedRowKeys2([]));
|
|
5429
|
+
}
|
|
5430
|
+
};
|
|
5431
|
+
return {
|
|
5432
|
+
handleCheckBoxAll
|
|
5433
|
+
};
|
|
5434
|
+
};
|
|
5435
|
+
|
|
5327
5436
|
// src/widget/advance/table/table-view/controller.ts
|
|
5328
5437
|
import {
|
|
5329
5438
|
domainHelper,
|
|
5330
5439
|
selectList as selectList2,
|
|
5331
|
-
selectSearch as
|
|
5332
|
-
useAppSelector as
|
|
5440
|
+
selectSearch as selectSearch3,
|
|
5441
|
+
useAppSelector as useAppSelector5
|
|
5333
5442
|
} from "@fctc/interface-logic";
|
|
5334
|
-
import { useEffect as
|
|
5443
|
+
import { useEffect as useEffect12, useMemo as useMemo10, useRef as useRef4, useState as useState8 } from "react";
|
|
5335
5444
|
var tableController = ({ data }) => {
|
|
5336
5445
|
const [rows, setRows] = useState8(data.records || []);
|
|
5337
5446
|
const [columns, setColumns] = useState8([]);
|
|
@@ -5362,7 +5471,7 @@ var tableController = ({ data }) => {
|
|
|
5362
5471
|
return item.display_name ? { ...transformedItem, item: item.display_name } : transformedItem;
|
|
5363
5472
|
});
|
|
5364
5473
|
};
|
|
5365
|
-
|
|
5474
|
+
useEffect12(() => {
|
|
5366
5475
|
setRows(transformData(data.records || null));
|
|
5367
5476
|
}, [data.records]);
|
|
5368
5477
|
const handleGetColumns = () => {
|
|
@@ -5383,7 +5492,7 @@ var tableController = ({ data }) => {
|
|
|
5383
5492
|
}
|
|
5384
5493
|
return cols;
|
|
5385
5494
|
};
|
|
5386
|
-
|
|
5495
|
+
useEffect12(() => {
|
|
5387
5496
|
const columns2 = handleGetColumns();
|
|
5388
5497
|
setColumns(columns2);
|
|
5389
5498
|
}, [data.records]);
|
|
@@ -5407,466 +5516,23 @@ var tableController = ({ data }) => {
|
|
|
5407
5516
|
};
|
|
5408
5517
|
};
|
|
5409
5518
|
|
|
5410
|
-
// src/widget/
|
|
5411
|
-
var many2manyFieldController = (props) => {
|
|
5412
|
-
const {
|
|
5413
|
-
relation,
|
|
5414
|
-
domain,
|
|
5415
|
-
context,
|
|
5416
|
-
tab,
|
|
5417
|
-
model,
|
|
5418
|
-
aid,
|
|
5419
|
-
setSelectedRowKeys: setSelectedRowKeys4,
|
|
5420
|
-
fields,
|
|
5421
|
-
setFields,
|
|
5422
|
-
groupByDomain,
|
|
5423
|
-
page,
|
|
5424
|
-
options,
|
|
5425
|
-
sessionStorageUtils
|
|
5426
|
-
} = props;
|
|
5427
|
-
const appDispatch = useAppDispatch5();
|
|
5428
|
-
const actionData = sessionStorageUtils.getActionData();
|
|
5429
|
-
const [debouncedPage] = useDebounce(page, 500);
|
|
5430
|
-
const [order, setOrder] = useState9();
|
|
5431
|
-
const [isLoadedData, setIsLoadedData] = useState9(false);
|
|
5432
|
-
const [domainMany2Many, setDomainMany2Many] = useState9(domain);
|
|
5433
|
-
const env = getEnv8();
|
|
5434
|
-
const { selectedTags } = useAppSelector5(selectSearch3);
|
|
5435
|
-
const viewParams = {
|
|
5436
|
-
model: relation,
|
|
5437
|
-
views: [
|
|
5438
|
-
[false, "list"],
|
|
5439
|
-
[false, "search"]
|
|
5440
|
-
],
|
|
5441
|
-
context
|
|
5442
|
-
};
|
|
5443
|
-
const { data: viewResponse, isFetched: isViewReponseFetched } = useGetView2(
|
|
5444
|
-
viewParams,
|
|
5445
|
-
actionData
|
|
5446
|
-
);
|
|
5447
|
-
const baseModel = useMemo10(
|
|
5448
|
-
() => ({
|
|
5449
|
-
name: String(relation),
|
|
5450
|
-
view: viewResponse || {},
|
|
5451
|
-
actContext: context,
|
|
5452
|
-
fields: [
|
|
5453
|
-
...Object.values(viewResponse?.views?.list?.fields ?? {}),
|
|
5454
|
-
...tab?.fields ? tab.fields : []
|
|
5455
|
-
]
|
|
5456
|
-
}),
|
|
5457
|
-
[model, viewResponse]
|
|
5458
|
-
);
|
|
5459
|
-
const initModel = useModel2();
|
|
5460
|
-
const modelInstance = useMemo10(() => {
|
|
5461
|
-
if (viewResponse) {
|
|
5462
|
-
return initModel.initModel(baseModel);
|
|
5463
|
-
}
|
|
5464
|
-
return null;
|
|
5465
|
-
}, [baseModel, viewResponse]);
|
|
5466
|
-
const specification = useMemo10(() => {
|
|
5467
|
-
if (modelInstance) {
|
|
5468
|
-
return modelInstance.getSpecification();
|
|
5469
|
-
}
|
|
5470
|
-
return null;
|
|
5471
|
-
}, [modelInstance]);
|
|
5472
|
-
const default_order = viewResponse && viewResponse?.views?.list?.default_order;
|
|
5473
|
-
const optionsObject = tab?.options ? evalJSONContext4(tab?.options) : (options ? evalJSONContext4(options) : {}) || {};
|
|
5474
|
-
const fetchData = async () => {
|
|
5475
|
-
try {
|
|
5476
|
-
setDomainMany2Many(domain);
|
|
5477
|
-
appDispatch(setFirstDomain(domain));
|
|
5478
|
-
appDispatch(setViewDataStore(viewResponse));
|
|
5479
|
-
const modalData = viewResponse?.views?.list?.fields.map((field) => ({
|
|
5480
|
-
...viewResponse?.models?.[String(model)]?.[field?.name],
|
|
5481
|
-
...field
|
|
5482
|
-
}));
|
|
5483
|
-
if (!fields?.[`${aid}_${relation}_popupmany2many`] && modalData) {
|
|
5484
|
-
setFields({
|
|
5485
|
-
...fields,
|
|
5486
|
-
[`${aid}_${relation}_popupmany2many`]: modalData
|
|
5487
|
-
});
|
|
5488
|
-
}
|
|
5489
|
-
appDispatch(setPage(0));
|
|
5490
|
-
} catch (err) {
|
|
5491
|
-
console.log(err);
|
|
5492
|
-
}
|
|
5493
|
-
};
|
|
5494
|
-
const queryKey = [
|
|
5495
|
-
`view-${relation}-${aid}`,
|
|
5496
|
-
specification,
|
|
5497
|
-
domainMany2Many,
|
|
5498
|
-
debouncedPage,
|
|
5499
|
-
groupByDomain,
|
|
5500
|
-
order
|
|
5501
|
-
];
|
|
5502
|
-
const data = {
|
|
5503
|
-
model: relation,
|
|
5504
|
-
specification,
|
|
5505
|
-
domain: domainMany2Many,
|
|
5506
|
-
offset: debouncedPage * 10,
|
|
5507
|
-
limit: 10,
|
|
5508
|
-
context,
|
|
5509
|
-
fields: groupByDomain?.fields,
|
|
5510
|
-
groupby: [groupByDomain?.contexts[0]?.group_by],
|
|
5511
|
-
sort: order ? order : default_order ? formatSortingString2(default_order) : ""
|
|
5512
|
-
};
|
|
5513
|
-
const enabled = isLoadedData && !!specification && !!relation && !!domainMany2Many && !!viewResponse;
|
|
5514
|
-
const {
|
|
5515
|
-
data: dataResponse,
|
|
5516
|
-
isLoading: isDataLoading,
|
|
5517
|
-
isFetched: isDataResponseFetched,
|
|
5518
|
-
isPlaceholderData
|
|
5519
|
-
} = useGetListData2(data, queryKey, enabled);
|
|
5520
|
-
useEffect12(() => {
|
|
5521
|
-
if (viewResponse) {
|
|
5522
|
-
fetchData();
|
|
5523
|
-
}
|
|
5524
|
-
return () => {
|
|
5525
|
-
appDispatch(setGroupByDomain(null));
|
|
5526
|
-
setFields((prevFields) => ({
|
|
5527
|
-
...prevFields,
|
|
5528
|
-
[`${aid}_${relation}_popupmany2many`]: null
|
|
5529
|
-
}));
|
|
5530
|
-
appDispatch(setPage(0));
|
|
5531
|
-
setSelectedRowKeys4([]);
|
|
5532
|
-
setDomainMany2Many(null);
|
|
5533
|
-
setIsLoadedData(false);
|
|
5534
|
-
};
|
|
5535
|
-
}, [viewResponse]);
|
|
5536
|
-
const { rows, columns, typeTable } = tableController({
|
|
5537
|
-
data: {
|
|
5538
|
-
fields: fields?.[`${aid}_${relation}_popupmany2many`] || viewResponse?.views?.list?.fields,
|
|
5539
|
-
records: dataResponse?.records ?? dataResponse?.groups,
|
|
5540
|
-
dataModel: viewResponse?.models?.[String(relation)],
|
|
5541
|
-
context: { ...env.context, ...context },
|
|
5542
|
-
typeTable: dataResponse?.groups ? "group" : "list"
|
|
5543
|
-
}
|
|
5544
|
-
});
|
|
5545
|
-
const dataFormView = {
|
|
5546
|
-
id: null,
|
|
5547
|
-
model: relation,
|
|
5548
|
-
context
|
|
5549
|
-
};
|
|
5550
|
-
const {
|
|
5551
|
-
refetch,
|
|
5552
|
-
data: dataFormViewResponse,
|
|
5553
|
-
isSuccess
|
|
5554
|
-
} = useGetFormView({
|
|
5555
|
-
data: dataFormView,
|
|
5556
|
-
queryKey: [`form-view-action-${relation}`],
|
|
5557
|
-
enabled: false
|
|
5558
|
-
});
|
|
5559
|
-
useEffect12(() => {
|
|
5560
|
-
if (isSuccess && dataFormViewResponse) {
|
|
5561
|
-
sessionStorage.setItem("actionData", JSON.stringify(dataFormViewResponse));
|
|
5562
|
-
window.location.href = `/form/menu?model=${relation}`;
|
|
5563
|
-
}
|
|
5564
|
-
}, [isSuccess]);
|
|
5565
|
-
useEffect12(() => {
|
|
5566
|
-
if (domainMany2Many && !isLoadedData) {
|
|
5567
|
-
setIsLoadedData(true);
|
|
5568
|
-
}
|
|
5569
|
-
}, [domainMany2Many]);
|
|
5570
|
-
const handleCreateNewOnPage = async () => {
|
|
5571
|
-
try {
|
|
5572
|
-
refetch();
|
|
5573
|
-
} catch (error) {
|
|
5574
|
-
console.log(error);
|
|
5575
|
-
}
|
|
5576
|
-
};
|
|
5577
|
-
return {};
|
|
5578
|
-
};
|
|
5579
|
-
|
|
5580
|
-
// src/widget/basic/many2many-tags-field/controller.ts
|
|
5581
|
-
import { useMemo as useMemo11 } from "react";
|
|
5582
|
-
import {
|
|
5583
|
-
evalJSONContext as evalJSONContext5,
|
|
5584
|
-
evalJSONDomain as evalJSONDomain4,
|
|
5585
|
-
getEnv as getEnv9,
|
|
5586
|
-
useGetSelection as useGetSelection3,
|
|
5587
|
-
WIDGETAVATAR,
|
|
5588
|
-
WIDGETCOLOR
|
|
5589
|
-
} from "@fctc/interface-logic";
|
|
5590
|
-
var many2manyTagsController = (props) => {
|
|
5591
|
-
const {
|
|
5592
|
-
relation,
|
|
5593
|
-
domain,
|
|
5594
|
-
options: optionsFields,
|
|
5595
|
-
widget,
|
|
5596
|
-
formValues,
|
|
5597
|
-
placeholderNoOption
|
|
5598
|
-
} = props;
|
|
5599
|
-
const isUser = relation === "res.users" || relation === "res.partner";
|
|
5600
|
-
const env = getEnv9();
|
|
5601
|
-
const addtionalFields = optionsFields ? evalJSONContext5(optionsFields) : null;
|
|
5602
|
-
const domainObject = useMemo11(
|
|
5603
|
-
() => evalJSONDomain4(domain, JSON.parse(JSON.stringify(formValues || {}))),
|
|
5604
|
-
[domain, formValues]
|
|
5605
|
-
);
|
|
5606
|
-
const data = {
|
|
5607
|
-
model: relation ?? "",
|
|
5608
|
-
domain: domainObject,
|
|
5609
|
-
specification: {
|
|
5610
|
-
id: {},
|
|
5611
|
-
name: {},
|
|
5612
|
-
display_name: {},
|
|
5613
|
-
...widget && WIDGETAVATAR[widget] ? { image_256: {} } : {},
|
|
5614
|
-
...widget && WIDGETCOLOR[widget] && addtionalFields?.color_field ? { color: {} } : {}
|
|
5615
|
-
},
|
|
5616
|
-
enabled: true,
|
|
5617
|
-
context: env.context
|
|
5618
|
-
};
|
|
5619
|
-
const { data: dataOfSelection } = useGetSelection3({
|
|
5620
|
-
data,
|
|
5621
|
-
queryKey: [`data_${relation}`, domainObject]
|
|
5622
|
-
});
|
|
5623
|
-
const customNoOptionsMessage = () => placeholderNoOption;
|
|
5624
|
-
const tranfer = (data2) => {
|
|
5625
|
-
return data2?.map((val) => ({
|
|
5626
|
-
id: val.value,
|
|
5627
|
-
display_name: val.label
|
|
5628
|
-
})) || [];
|
|
5629
|
-
};
|
|
5630
|
-
const options = dataOfSelection?.records?.map((val) => ({
|
|
5631
|
-
value: val.id,
|
|
5632
|
-
label: val.name ?? val.display_name,
|
|
5633
|
-
...val
|
|
5634
|
-
})) || [];
|
|
5635
|
-
return {
|
|
5636
|
-
options,
|
|
5637
|
-
customNoOptionsMessage,
|
|
5638
|
-
tranfer,
|
|
5639
|
-
dataOfSelection,
|
|
5640
|
-
isUser
|
|
5641
|
-
};
|
|
5642
|
-
};
|
|
5643
|
-
|
|
5644
|
-
// src/widget/basic/status-bar-field/controller.ts
|
|
5645
|
-
import { useState as useState10 } from "react";
|
|
5519
|
+
// src/widget/advance/table/table-group/controller.ts
|
|
5646
5520
|
import {
|
|
5647
|
-
|
|
5648
|
-
|
|
5521
|
+
getEnv as getEnv8,
|
|
5522
|
+
selectList as selectList3,
|
|
5523
|
+
selectSearch as selectSearch4,
|
|
5524
|
+
setSelectedRowKeys as setSelectedRowKeys3,
|
|
5525
|
+
useAppDispatch as useAppDispatch7,
|
|
5649
5526
|
useAppSelector as useAppSelector6,
|
|
5650
|
-
|
|
5651
|
-
|
|
5527
|
+
useGetListData as useGetListData2,
|
|
5528
|
+
useOdooDataTransform
|
|
5652
5529
|
} from "@fctc/interface-logic";
|
|
5653
|
-
|
|
5654
|
-
const {
|
|
5655
|
-
relation,
|
|
5656
|
-
defaultValue,
|
|
5657
|
-
domain,
|
|
5658
|
-
formValues,
|
|
5659
|
-
name,
|
|
5660
|
-
id,
|
|
5661
|
-
model,
|
|
5662
|
-
onRefetch
|
|
5663
|
-
} = props;
|
|
5664
|
-
const specification = {
|
|
5665
|
-
id: 0,
|
|
5666
|
-
name: "",
|
|
5667
|
-
fold: ""
|
|
5668
|
-
};
|
|
5669
|
-
const [disabled, setDisabled] = useState10(false);
|
|
5670
|
-
const [modelStatus, setModalStatus] = useState10(false);
|
|
5671
|
-
const { context } = useAppSelector6(selectEnv3);
|
|
5672
|
-
const queryKey = [`data-status-duration`, specification];
|
|
5673
|
-
const listDataProps = {
|
|
5674
|
-
model: relation,
|
|
5675
|
-
specification,
|
|
5676
|
-
domain: evalJSONDomain5(domain, JSON.parse(JSON.stringify(formValues))),
|
|
5677
|
-
limit: 10,
|
|
5678
|
-
offset: 0,
|
|
5679
|
-
fields: "",
|
|
5680
|
-
groupby: [],
|
|
5681
|
-
context: {
|
|
5682
|
-
lang: context.lang
|
|
5683
|
-
},
|
|
5684
|
-
sort: ""
|
|
5685
|
-
};
|
|
5686
|
-
const { data: dataResponse } = useGetListData3(listDataProps, queryKey);
|
|
5687
|
-
const { mutate: fetchChangeStatus } = useChangeStatus();
|
|
5688
|
-
const handleClick = async (stage_id) => {
|
|
5689
|
-
setDisabled(true);
|
|
5690
|
-
if (stage_id) {
|
|
5691
|
-
fetchChangeStatus(
|
|
5692
|
-
{
|
|
5693
|
-
data: {
|
|
5694
|
-
stage_id,
|
|
5695
|
-
name,
|
|
5696
|
-
id,
|
|
5697
|
-
model,
|
|
5698
|
-
lang: context.lang
|
|
5699
|
-
}
|
|
5700
|
-
},
|
|
5701
|
-
{
|
|
5702
|
-
onSuccess: (res) => {
|
|
5703
|
-
if (res) {
|
|
5704
|
-
setDisabled(false);
|
|
5705
|
-
onRefetch && onRefetch();
|
|
5706
|
-
}
|
|
5707
|
-
}
|
|
5708
|
-
}
|
|
5709
|
-
);
|
|
5710
|
-
}
|
|
5711
|
-
};
|
|
5712
|
-
return {
|
|
5713
|
-
defaultValue,
|
|
5714
|
-
dataResponse,
|
|
5715
|
-
handleClick,
|
|
5716
|
-
disabled,
|
|
5717
|
-
modelStatus,
|
|
5718
|
-
setModalStatus
|
|
5719
|
-
};
|
|
5720
|
-
};
|
|
5530
|
+
import { useEffect as useEffect13, useMemo as useMemo11, useState as useState9 } from "react";
|
|
5721
5531
|
|
|
5722
|
-
// src/
|
|
5723
|
-
import {
|
|
5724
|
-
|
|
5725
|
-
|
|
5726
|
-
value,
|
|
5727
|
-
isForm,
|
|
5728
|
-
name,
|
|
5729
|
-
methods,
|
|
5730
|
-
onChange,
|
|
5731
|
-
model,
|
|
5732
|
-
selection,
|
|
5733
|
-
id,
|
|
5734
|
-
actionData,
|
|
5735
|
-
viewData,
|
|
5736
|
-
context
|
|
5737
|
-
} = props;
|
|
5738
|
-
const _context = { ...evalJSONContext6(actionData?.context) };
|
|
5739
|
-
const contextObject = { ...context, ..._context };
|
|
5740
|
-
const defaultPriority = parseInt(value) + 1;
|
|
5741
|
-
const label = viewData?.models?.[model]?.[name ?? ""]?.string ?? name;
|
|
5742
|
-
const { mutateAsync: fetchSave } = useSave2();
|
|
5743
|
-
const savePriorities = async ({
|
|
5744
|
-
value: value2,
|
|
5745
|
-
resetPriority
|
|
5746
|
-
}) => {
|
|
5747
|
-
const priorityValue = value2 <= 0 ? 0 : value2 - 1;
|
|
5748
|
-
try {
|
|
5749
|
-
fetchSave({
|
|
5750
|
-
ids: id ? [id] : [],
|
|
5751
|
-
data: { [name ?? ""]: String(priorityValue) },
|
|
5752
|
-
model: model ?? "",
|
|
5753
|
-
context: contextObject
|
|
5754
|
-
});
|
|
5755
|
-
if (typeof onChange === "function") {
|
|
5756
|
-
onChange(name ?? "", String(priorityValue));
|
|
5757
|
-
}
|
|
5758
|
-
} catch (error) {
|
|
5759
|
-
if (resetPriority) {
|
|
5760
|
-
resetPriority();
|
|
5761
|
-
}
|
|
5762
|
-
}
|
|
5763
|
-
};
|
|
5764
|
-
return {
|
|
5765
|
-
selection,
|
|
5766
|
-
isForm,
|
|
5767
|
-
methods,
|
|
5768
|
-
defaultPriority,
|
|
5769
|
-
savePriorities,
|
|
5770
|
-
label,
|
|
5771
|
-
id,
|
|
5772
|
-
onChange
|
|
5773
|
-
};
|
|
5774
|
-
};
|
|
5775
|
-
|
|
5776
|
-
// src/widget/basic/float-time-field/controller.ts
|
|
5777
|
-
import { useState as useState11 } from "react";
|
|
5778
|
-
import { convertFloatToTime, convertTimeToFloat } from "@fctc/interface-logic";
|
|
5779
|
-
var floatTimeFiledController = ({
|
|
5780
|
-
onChange: fieldOnChange,
|
|
5781
|
-
onBlur,
|
|
5782
|
-
value,
|
|
5783
|
-
isDirty,
|
|
5784
|
-
props
|
|
5785
|
-
}) => {
|
|
5786
|
-
const { name, defaultValue = 0, onChange } = props;
|
|
5787
|
-
const [input, setInput] = useState11(
|
|
5788
|
-
convertFloatToTime(value ?? defaultValue)
|
|
5789
|
-
);
|
|
5790
|
-
const [formattedTime, setFormattedTime] = useState11("");
|
|
5791
|
-
const [errors, setErrors] = useState11("");
|
|
5792
|
-
const handleInputChange = (e) => {
|
|
5793
|
-
const raw = e.target.value.replace(/[^\d:]/g, "");
|
|
5794
|
-
setInput(raw);
|
|
5795
|
-
const timeRegex = /^(\d{1,2}):?(\d{0,2})$/;
|
|
5796
|
-
const match = raw.match(timeRegex);
|
|
5797
|
-
if (!match) {
|
|
5798
|
-
setErrors("\u0110\u1ECBnh d\u1EA1ng kh\xF4ng h\u1EE3p l\u1EC7");
|
|
5799
|
-
setFormattedTime("");
|
|
5800
|
-
return;
|
|
5801
|
-
}
|
|
5802
|
-
let hours = parseInt(match[1] ?? "0", 10);
|
|
5803
|
-
let minutes = parseInt(match[2] ?? "0", 10);
|
|
5804
|
-
if (isNaN(hours)) hours = 0;
|
|
5805
|
-
if (isNaN(minutes)) minutes = 0;
|
|
5806
|
-
if (hours >= 24) {
|
|
5807
|
-
hours = 0;
|
|
5808
|
-
}
|
|
5809
|
-
if (minutes >= 60) {
|
|
5810
|
-
minutes = 0;
|
|
5811
|
-
}
|
|
5812
|
-
const formatted = `${hours.toString().padStart(2, "0")}:${minutes.toString().padStart(2, "0")}`;
|
|
5813
|
-
setErrors("");
|
|
5814
|
-
setFormattedTime(formatted);
|
|
5815
|
-
fieldOnChange(formatted);
|
|
5816
|
-
};
|
|
5817
|
-
const handleBlur = () => {
|
|
5818
|
-
if (!isDirty) return;
|
|
5819
|
-
if (formattedTime) {
|
|
5820
|
-
setInput(formattedTime);
|
|
5821
|
-
const floatVal = convertTimeToFloat(formattedTime);
|
|
5822
|
-
fieldOnChange(floatVal);
|
|
5823
|
-
if (onChange) {
|
|
5824
|
-
onChange(name ?? "", floatVal);
|
|
5825
|
-
}
|
|
5826
|
-
} else {
|
|
5827
|
-
setInput("00:00");
|
|
5828
|
-
fieldOnChange(0);
|
|
5829
|
-
if (onChange) {
|
|
5830
|
-
onChange(name ?? "", 0);
|
|
5831
|
-
}
|
|
5832
|
-
setErrors("");
|
|
5833
|
-
}
|
|
5834
|
-
onBlur();
|
|
5835
|
-
};
|
|
5836
|
-
const handleKeyDown = (e) => {
|
|
5837
|
-
{
|
|
5838
|
-
const allowed = [
|
|
5839
|
-
"Backspace",
|
|
5840
|
-
"Tab",
|
|
5841
|
-
"ArrowLeft",
|
|
5842
|
-
"ArrowRight",
|
|
5843
|
-
"Delete",
|
|
5844
|
-
"Home",
|
|
5845
|
-
"End",
|
|
5846
|
-
":"
|
|
5847
|
-
];
|
|
5848
|
-
const isNumber = /^[0-9]$/.test(e.key);
|
|
5849
|
-
if (!isNumber && !allowed.includes(e.key)) {
|
|
5850
|
-
e.preventDefault();
|
|
5851
|
-
}
|
|
5852
|
-
}
|
|
5853
|
-
};
|
|
5854
|
-
return {
|
|
5855
|
-
handleInputChange,
|
|
5856
|
-
handleBlur,
|
|
5857
|
-
handleKeyDown,
|
|
5858
|
-
input,
|
|
5859
|
-
errors
|
|
5860
|
-
};
|
|
5861
|
-
};
|
|
5862
|
-
|
|
5863
|
-
// src/widget/basic/float-field/controller.ts
|
|
5864
|
-
import { useEffect as useEffect13, useRef as useRef5, useState as useState12 } from "react";
|
|
5865
|
-
|
|
5866
|
-
// src/utils/i18n.ts
|
|
5867
|
-
import { initReactI18next } from "react-i18next";
|
|
5868
|
-
import i18n from "i18next";
|
|
5869
|
-
import LanguageDetector from "i18next-browser-languagedetector";
|
|
5532
|
+
// src/utils/i18n.ts
|
|
5533
|
+
import { initReactI18next } from "react-i18next";
|
|
5534
|
+
import i18n from "i18next";
|
|
5535
|
+
import LanguageDetector from "i18next-browser-languagedetector";
|
|
5870
5536
|
|
|
5871
5537
|
// src/locales/vi.json
|
|
5872
5538
|
var vi_default = {
|
|
@@ -6053,8 +5719,6 @@ var vi_default = {
|
|
|
6053
5719
|
add_new_attribute: "Th\xEAm thu\u1ED9c t\xEDnh",
|
|
6054
5720
|
add_attribute_name: "T\xEAn thu\u1ED9c t\xEDnh",
|
|
6055
5721
|
images_product: "H\xECnh \u1EA3nh",
|
|
6056
|
-
selected: "\u0111\u01B0\u1EE3c ch\u1ECDn",
|
|
6057
|
-
print: "In",
|
|
6058
5722
|
generate_code_product: "T\u1EA1o m\xE3 s\u1EA3n ph\u1EA9m",
|
|
6059
5723
|
order_today: "\u0110\u01A1n h\xE0ng",
|
|
6060
5724
|
list_best_selling_product: "S\u1EA3n ph\u1EA9m b\xE1n ch\u1EA1y",
|
|
@@ -6612,26 +6276,640 @@ var vi_default = {
|
|
|
6612
6276
|
"export-all-data-error": "Xu\u1EA5t d\u1EEF li\u1EC7u kh\xF4ng th\xE0nh c\xF4ng, vui l\xF2ng th\u1EED l\u1EA1i sau"
|
|
6613
6277
|
};
|
|
6614
6278
|
|
|
6615
|
-
// src/utils/i18n.ts
|
|
6616
|
-
i18n.use(LanguageDetector).use(initReactI18next).init({
|
|
6617
|
-
resources: {
|
|
6618
|
-
vi: { translation: vi_default },
|
|
6619
|
-
en: { translation: vi_default }
|
|
6620
|
-
},
|
|
6621
|
-
fallbackLng: "vi",
|
|
6622
|
-
lng: "vi_VN",
|
|
6623
|
-
debug: false,
|
|
6624
|
-
nonExplicitSupportedLngs: true,
|
|
6625
|
-
interpolation: {
|
|
6626
|
-
escapeValue: false
|
|
6627
|
-
},
|
|
6628
|
-
detection: {
|
|
6629
|
-
caches: ["cookie"]
|
|
6630
|
-
}
|
|
6631
|
-
});
|
|
6632
|
-
var i18n_default = i18n;
|
|
6633
|
-
|
|
6279
|
+
// src/utils/i18n.ts
|
|
6280
|
+
i18n.use(LanguageDetector).use(initReactI18next).init({
|
|
6281
|
+
resources: {
|
|
6282
|
+
vi: { translation: vi_default },
|
|
6283
|
+
en: { translation: vi_default }
|
|
6284
|
+
},
|
|
6285
|
+
fallbackLng: "vi",
|
|
6286
|
+
lng: "vi_VN",
|
|
6287
|
+
debug: false,
|
|
6288
|
+
nonExplicitSupportedLngs: true,
|
|
6289
|
+
interpolation: {
|
|
6290
|
+
escapeValue: false
|
|
6291
|
+
},
|
|
6292
|
+
detection: {
|
|
6293
|
+
caches: ["cookie"]
|
|
6294
|
+
}
|
|
6295
|
+
});
|
|
6296
|
+
var i18n_default = i18n;
|
|
6297
|
+
|
|
6298
|
+
// src/widget/advance/table/table-group/controller.ts
|
|
6299
|
+
var tableGroupController = (props) => {
|
|
6300
|
+
const env = getEnv8();
|
|
6301
|
+
const {
|
|
6302
|
+
rows,
|
|
6303
|
+
columns,
|
|
6304
|
+
indexRow,
|
|
6305
|
+
row,
|
|
6306
|
+
model,
|
|
6307
|
+
viewData,
|
|
6308
|
+
renderField,
|
|
6309
|
+
level,
|
|
6310
|
+
specification,
|
|
6311
|
+
domain,
|
|
6312
|
+
context,
|
|
6313
|
+
checkedAll,
|
|
6314
|
+
isDisplayCheckbox,
|
|
6315
|
+
isAutoSelect,
|
|
6316
|
+
setIsAutoSelect,
|
|
6317
|
+
selectedRowKeysRef
|
|
6318
|
+
} = props;
|
|
6319
|
+
const [pageGroup, setPageGroup] = useState9(0);
|
|
6320
|
+
const { groupByDomain, selectedTags } = useAppSelector6(selectSearch4);
|
|
6321
|
+
const { selectedRowKeys } = useAppSelector6(selectList3);
|
|
6322
|
+
const appDispatch = useAppDispatch7();
|
|
6323
|
+
const { toDataJS } = useOdooDataTransform();
|
|
6324
|
+
const initVal = toDataJS(row, viewData, model);
|
|
6325
|
+
const [isShowGroup, setIsShowGroup] = useState9(false);
|
|
6326
|
+
const [colEmptyGroup, setColEmptyGroup] = useState9({
|
|
6327
|
+
fromStart: 1,
|
|
6328
|
+
fromEnd: 1
|
|
6329
|
+
});
|
|
6330
|
+
const processedData = useMemo11(() => {
|
|
6331
|
+
const calculateColSpanEmpty = () => {
|
|
6332
|
+
const startIndex = columns.findIndex(
|
|
6333
|
+
(col) => col.field.type === "monetary" && typeof row[col.key] === "number" || col.field.aggregator === "sum"
|
|
6334
|
+
);
|
|
6335
|
+
const endIndex = columns.findLastIndex(
|
|
6336
|
+
(col) => col.field.type === "monetary" && typeof row[col.key] === "number" || col.field.aggregator !== "sum"
|
|
6337
|
+
);
|
|
6338
|
+
const fromStart = startIndex === -1 ? columns.length : startIndex;
|
|
6339
|
+
const fromEnd = endIndex === -1 ? columns.length : columns.length - 1 - endIndex;
|
|
6340
|
+
setColEmptyGroup({ fromStart: fromStart + 1, fromEnd: fromEnd + 1 });
|
|
6341
|
+
return { fromStart: fromStart + 1, fromEnd: fromEnd + 1 };
|
|
6342
|
+
};
|
|
6343
|
+
return calculateColSpanEmpty();
|
|
6344
|
+
}, [columns, row]);
|
|
6345
|
+
const shouldFetchData = useMemo11(() => {
|
|
6346
|
+
return !!isShowGroup;
|
|
6347
|
+
}, [isShowGroup]);
|
|
6348
|
+
const enabled = shouldFetchData && !!processedData;
|
|
6349
|
+
const listDataProps = {
|
|
6350
|
+
model,
|
|
6351
|
+
specification,
|
|
6352
|
+
domain,
|
|
6353
|
+
context,
|
|
6354
|
+
offset: pageGroup * 10,
|
|
6355
|
+
fields: groupByDomain?.fields,
|
|
6356
|
+
groupby: [groupByDomain?.contexts[level]?.group_by]
|
|
6357
|
+
};
|
|
6358
|
+
const queryKey = [
|
|
6359
|
+
`data-${model}--${level}-row${indexRow}`,
|
|
6360
|
+
specification,
|
|
6361
|
+
domain,
|
|
6362
|
+
pageGroup
|
|
6363
|
+
];
|
|
6364
|
+
const {
|
|
6365
|
+
data: dataResponse,
|
|
6366
|
+
isFetched: isQueryFetched,
|
|
6367
|
+
isPlaceholderData,
|
|
6368
|
+
isLoading,
|
|
6369
|
+
isFetching
|
|
6370
|
+
} = useGetListData2(listDataProps, queryKey, enabled);
|
|
6371
|
+
const {
|
|
6372
|
+
columns: columnsGroup,
|
|
6373
|
+
rows: rowsGroup,
|
|
6374
|
+
typeTable: typeTableGroup
|
|
6375
|
+
} = tableController({
|
|
6376
|
+
data: {
|
|
6377
|
+
fields: viewData?.views?.list?.fields,
|
|
6378
|
+
records: dataResponse?.records ?? dataResponse?.groups,
|
|
6379
|
+
dataModel: viewData?.models?.[model],
|
|
6380
|
+
context: env.context,
|
|
6381
|
+
typeTable: dataResponse?.groups ? "group" : "list"
|
|
6382
|
+
}
|
|
6383
|
+
});
|
|
6384
|
+
const leftPadding = level > 1 ? level * 8 + "px" : "0px";
|
|
6385
|
+
useEffect13(() => {
|
|
6386
|
+
if (isShowGroup && selectedTags?.length > 0) {
|
|
6387
|
+
setIsShowGroup(false);
|
|
6388
|
+
}
|
|
6389
|
+
}, [selectedTags]);
|
|
6390
|
+
const group_by_field_name = groupByDomain?.contexts[level - 1]?.group_by;
|
|
6391
|
+
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(
|
|
6392
|
+
(selectItem) => selectItem?.[0] === row[group_by_field_name]
|
|
6393
|
+
)?.[1] : row[group_by_field_name];
|
|
6394
|
+
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`]})`;
|
|
6395
|
+
const allIdsNull = selectedRowKeys?.every((item) => item === void 0);
|
|
6396
|
+
const handleExpandChildGroup = () => {
|
|
6397
|
+
if (isLoading || isFetching) return;
|
|
6398
|
+
const toggleShowGroup = () => setIsShowGroup((prev) => !prev);
|
|
6399
|
+
if (allIdsNull || typeTableGroup === "group") {
|
|
6400
|
+
toggleShowGroup();
|
|
6401
|
+
return;
|
|
6402
|
+
}
|
|
6403
|
+
if (isShowGroup && checkedAll) {
|
|
6404
|
+
const ids = rowsGroup?.map((item) => item?.id) || [];
|
|
6405
|
+
const filteredIds = selectedRowKeys.filter(
|
|
6406
|
+
(id) => !ids.includes(id)
|
|
6407
|
+
);
|
|
6408
|
+
appDispatch(setSelectedRowKeys3(filteredIds));
|
|
6409
|
+
} else if (!isShowGroup && selectedRowKeys?.length > 0 && typeTableGroup === "list" && checkedAll && !allIdsNull && isQueryFetched) {
|
|
6410
|
+
const clonedKeys = [...selectedRowKeys];
|
|
6411
|
+
appDispatch(setSelectedRowKeys3([...clonedKeys, -1]));
|
|
6412
|
+
setTimeout(() => appDispatch(setSelectedRowKeys3(clonedKeys)), 500);
|
|
6413
|
+
} else if (isShowGroup && selectedRowKeys?.length > 0 && typeTableGroup === "list" && !checkedAll && !allIdsNull) {
|
|
6414
|
+
const filteredKeys = selectedRowKeys.filter((id) => id > -1);
|
|
6415
|
+
appDispatch(setSelectedRowKeys3(filteredKeys));
|
|
6416
|
+
}
|
|
6417
|
+
toggleShowGroup();
|
|
6418
|
+
};
|
|
6419
|
+
useEffect13(() => {
|
|
6420
|
+
if (!isQueryFetched || !rowsGroup || !checkedAll || allIdsNull || typeTableGroup === "group") {
|
|
6421
|
+
return;
|
|
6422
|
+
}
|
|
6423
|
+
const clonedKeys = [...selectedRowKeys];
|
|
6424
|
+
setSelectedRowKeys3([...clonedKeys, -1]);
|
|
6425
|
+
setTimeout(() => setSelectedRowKeys3(clonedKeys), 500);
|
|
6426
|
+
}, [isQueryFetched]);
|
|
6427
|
+
return {
|
|
6428
|
+
handleExpandChildGroup,
|
|
6429
|
+
colEmptyGroup,
|
|
6430
|
+
leftPadding,
|
|
6431
|
+
isShowGroup,
|
|
6432
|
+
isQueryFetched,
|
|
6433
|
+
nameGroupWithCount,
|
|
6434
|
+
columns,
|
|
6435
|
+
row,
|
|
6436
|
+
isPlaceholderData,
|
|
6437
|
+
columnsGroup,
|
|
6438
|
+
indexRow,
|
|
6439
|
+
rowsGroup,
|
|
6440
|
+
model,
|
|
6441
|
+
viewData,
|
|
6442
|
+
renderField,
|
|
6443
|
+
level,
|
|
6444
|
+
specification,
|
|
6445
|
+
context,
|
|
6446
|
+
checkedAll,
|
|
6447
|
+
isDisplayCheckbox,
|
|
6448
|
+
isAutoSelect,
|
|
6449
|
+
setIsAutoSelect,
|
|
6450
|
+
selectedRowKeysRef,
|
|
6451
|
+
initVal,
|
|
6452
|
+
dataResponse,
|
|
6453
|
+
pageGroup,
|
|
6454
|
+
setPageGroup
|
|
6455
|
+
};
|
|
6456
|
+
};
|
|
6457
|
+
|
|
6458
|
+
// src/widget/basic/many2many-field/controller.ts
|
|
6459
|
+
var many2manyFieldController = (props) => {
|
|
6460
|
+
const {
|
|
6461
|
+
relation,
|
|
6462
|
+
domain,
|
|
6463
|
+
context,
|
|
6464
|
+
tab,
|
|
6465
|
+
model,
|
|
6466
|
+
aid,
|
|
6467
|
+
setSelectedRowKeys: setSelectedRowKeys4,
|
|
6468
|
+
fields,
|
|
6469
|
+
setFields,
|
|
6470
|
+
groupByDomain,
|
|
6471
|
+
page,
|
|
6472
|
+
options,
|
|
6473
|
+
sessionStorageUtils
|
|
6474
|
+
} = props;
|
|
6475
|
+
const appDispatch = useAppDispatch8();
|
|
6476
|
+
const actionData = sessionStorageUtils.getActionData();
|
|
6477
|
+
const [debouncedPage] = useDebounce(page, 500);
|
|
6478
|
+
const [order, setOrder] = useState10();
|
|
6479
|
+
const [isLoadedData, setIsLoadedData] = useState10(false);
|
|
6480
|
+
const [domainMany2Many, setDomainMany2Many] = useState10(domain);
|
|
6481
|
+
const env = getEnv9();
|
|
6482
|
+
const { selectedTags } = useAppSelector7(selectSearch5);
|
|
6483
|
+
const viewParams = {
|
|
6484
|
+
model: relation,
|
|
6485
|
+
views: [
|
|
6486
|
+
[false, "list"],
|
|
6487
|
+
[false, "search"]
|
|
6488
|
+
],
|
|
6489
|
+
context
|
|
6490
|
+
};
|
|
6491
|
+
const { data: viewResponse, isFetched: isViewReponseFetched } = useGetView2(
|
|
6492
|
+
viewParams,
|
|
6493
|
+
actionData
|
|
6494
|
+
);
|
|
6495
|
+
const baseModel = useMemo12(
|
|
6496
|
+
() => ({
|
|
6497
|
+
name: String(relation),
|
|
6498
|
+
view: viewResponse || {},
|
|
6499
|
+
actContext: context,
|
|
6500
|
+
fields: [
|
|
6501
|
+
...Object.values(viewResponse?.views?.list?.fields ?? {}),
|
|
6502
|
+
...tab?.fields ? tab.fields : []
|
|
6503
|
+
]
|
|
6504
|
+
}),
|
|
6505
|
+
[model, viewResponse]
|
|
6506
|
+
);
|
|
6507
|
+
const initModel = useModel2();
|
|
6508
|
+
const modelInstance = useMemo12(() => {
|
|
6509
|
+
if (viewResponse) {
|
|
6510
|
+
return initModel.initModel(baseModel);
|
|
6511
|
+
}
|
|
6512
|
+
return null;
|
|
6513
|
+
}, [baseModel, viewResponse]);
|
|
6514
|
+
const specification = useMemo12(() => {
|
|
6515
|
+
if (modelInstance) {
|
|
6516
|
+
return modelInstance.getSpecification();
|
|
6517
|
+
}
|
|
6518
|
+
return null;
|
|
6519
|
+
}, [modelInstance]);
|
|
6520
|
+
const default_order = viewResponse && viewResponse?.views?.list?.default_order;
|
|
6521
|
+
const optionsObject = tab?.options ? evalJSONContext4(tab?.options) : (options ? evalJSONContext4(options) : {}) || {};
|
|
6522
|
+
const fetchData = async () => {
|
|
6523
|
+
try {
|
|
6524
|
+
setDomainMany2Many(domain);
|
|
6525
|
+
appDispatch(setFirstDomain(domain));
|
|
6526
|
+
appDispatch(setViewDataStore(viewResponse));
|
|
6527
|
+
const modalData = viewResponse?.views?.list?.fields.map((field) => ({
|
|
6528
|
+
...viewResponse?.models?.[String(model)]?.[field?.name],
|
|
6529
|
+
...field
|
|
6530
|
+
}));
|
|
6531
|
+
if (!fields?.[`${aid}_${relation}_popupmany2many`] && modalData) {
|
|
6532
|
+
setFields({
|
|
6533
|
+
...fields,
|
|
6534
|
+
[`${aid}_${relation}_popupmany2many`]: modalData
|
|
6535
|
+
});
|
|
6536
|
+
}
|
|
6537
|
+
appDispatch(setPage(0));
|
|
6538
|
+
} catch (err) {
|
|
6539
|
+
console.log(err);
|
|
6540
|
+
}
|
|
6541
|
+
};
|
|
6542
|
+
const queryKey = [
|
|
6543
|
+
`view-${relation}-${aid}`,
|
|
6544
|
+
specification,
|
|
6545
|
+
domainMany2Many,
|
|
6546
|
+
debouncedPage,
|
|
6547
|
+
groupByDomain,
|
|
6548
|
+
order
|
|
6549
|
+
];
|
|
6550
|
+
const data = {
|
|
6551
|
+
model: relation,
|
|
6552
|
+
specification,
|
|
6553
|
+
domain: domainMany2Many,
|
|
6554
|
+
offset: debouncedPage * 10,
|
|
6555
|
+
limit: 10,
|
|
6556
|
+
context,
|
|
6557
|
+
fields: groupByDomain?.fields,
|
|
6558
|
+
groupby: [groupByDomain?.contexts[0]?.group_by],
|
|
6559
|
+
sort: order ? order : default_order ? formatSortingString2(default_order) : ""
|
|
6560
|
+
};
|
|
6561
|
+
const enabled = isLoadedData && !!specification && !!relation && !!domainMany2Many && !!viewResponse;
|
|
6562
|
+
const {
|
|
6563
|
+
data: dataResponse,
|
|
6564
|
+
isLoading: isDataLoading,
|
|
6565
|
+
isFetched: isDataResponseFetched,
|
|
6566
|
+
isPlaceholderData
|
|
6567
|
+
} = useGetListData3(data, queryKey, enabled);
|
|
6568
|
+
useEffect14(() => {
|
|
6569
|
+
if (viewResponse) {
|
|
6570
|
+
fetchData();
|
|
6571
|
+
}
|
|
6572
|
+
return () => {
|
|
6573
|
+
appDispatch(setGroupByDomain(null));
|
|
6574
|
+
setFields((prevFields) => ({
|
|
6575
|
+
...prevFields,
|
|
6576
|
+
[`${aid}_${relation}_popupmany2many`]: null
|
|
6577
|
+
}));
|
|
6578
|
+
appDispatch(setPage(0));
|
|
6579
|
+
setSelectedRowKeys4([]);
|
|
6580
|
+
setDomainMany2Many(null);
|
|
6581
|
+
setIsLoadedData(false);
|
|
6582
|
+
};
|
|
6583
|
+
}, [viewResponse]);
|
|
6584
|
+
const { rows, columns, typeTable } = tableController({
|
|
6585
|
+
data: {
|
|
6586
|
+
fields: fields?.[`${aid}_${relation}_popupmany2many`] || viewResponse?.views?.list?.fields,
|
|
6587
|
+
records: dataResponse?.records ?? dataResponse?.groups,
|
|
6588
|
+
dataModel: viewResponse?.models?.[String(relation)],
|
|
6589
|
+
context: { ...env.context, ...context },
|
|
6590
|
+
typeTable: dataResponse?.groups ? "group" : "list"
|
|
6591
|
+
}
|
|
6592
|
+
});
|
|
6593
|
+
const dataFormView = {
|
|
6594
|
+
id: null,
|
|
6595
|
+
model: relation,
|
|
6596
|
+
context
|
|
6597
|
+
};
|
|
6598
|
+
const {
|
|
6599
|
+
refetch,
|
|
6600
|
+
data: dataFormViewResponse,
|
|
6601
|
+
isSuccess
|
|
6602
|
+
} = useGetFormView({
|
|
6603
|
+
data: dataFormView,
|
|
6604
|
+
queryKey: [`form-view-action-${relation}`],
|
|
6605
|
+
enabled: false
|
|
6606
|
+
});
|
|
6607
|
+
useEffect14(() => {
|
|
6608
|
+
if (isSuccess && dataFormViewResponse) {
|
|
6609
|
+
sessionStorage.setItem("actionData", JSON.stringify(dataFormViewResponse));
|
|
6610
|
+
window.location.href = `/form/menu?model=${relation}`;
|
|
6611
|
+
}
|
|
6612
|
+
}, [isSuccess]);
|
|
6613
|
+
useEffect14(() => {
|
|
6614
|
+
if (domainMany2Many && !isLoadedData) {
|
|
6615
|
+
setIsLoadedData(true);
|
|
6616
|
+
}
|
|
6617
|
+
}, [domainMany2Many]);
|
|
6618
|
+
const handleCreateNewOnPage = async () => {
|
|
6619
|
+
try {
|
|
6620
|
+
refetch();
|
|
6621
|
+
} catch (error) {
|
|
6622
|
+
console.log(error);
|
|
6623
|
+
}
|
|
6624
|
+
};
|
|
6625
|
+
return {};
|
|
6626
|
+
};
|
|
6627
|
+
|
|
6628
|
+
// src/widget/basic/many2many-tags-field/controller.ts
|
|
6629
|
+
import { useMemo as useMemo13 } from "react";
|
|
6630
|
+
import {
|
|
6631
|
+
evalJSONContext as evalJSONContext5,
|
|
6632
|
+
evalJSONDomain as evalJSONDomain4,
|
|
6633
|
+
getEnv as getEnv10,
|
|
6634
|
+
useGetSelection as useGetSelection3,
|
|
6635
|
+
WIDGETAVATAR,
|
|
6636
|
+
WIDGETCOLOR
|
|
6637
|
+
} from "@fctc/interface-logic";
|
|
6638
|
+
var many2manyTagsController = (props) => {
|
|
6639
|
+
const {
|
|
6640
|
+
relation,
|
|
6641
|
+
domain,
|
|
6642
|
+
options: optionsFields,
|
|
6643
|
+
widget,
|
|
6644
|
+
formValues,
|
|
6645
|
+
placeholderNoOption
|
|
6646
|
+
} = props;
|
|
6647
|
+
const isUser = relation === "res.users" || relation === "res.partner";
|
|
6648
|
+
const env = getEnv10();
|
|
6649
|
+
const addtionalFields = optionsFields ? evalJSONContext5(optionsFields) : null;
|
|
6650
|
+
const domainObject = useMemo13(
|
|
6651
|
+
() => evalJSONDomain4(domain, JSON.parse(JSON.stringify(formValues || {}))),
|
|
6652
|
+
[domain, formValues]
|
|
6653
|
+
);
|
|
6654
|
+
const data = {
|
|
6655
|
+
model: relation ?? "",
|
|
6656
|
+
domain: domainObject,
|
|
6657
|
+
specification: {
|
|
6658
|
+
id: {},
|
|
6659
|
+
name: {},
|
|
6660
|
+
display_name: {},
|
|
6661
|
+
...widget && WIDGETAVATAR[widget] ? { image_256: {} } : {},
|
|
6662
|
+
...widget && WIDGETCOLOR[widget] && addtionalFields?.color_field ? { color: {} } : {}
|
|
6663
|
+
},
|
|
6664
|
+
enabled: true,
|
|
6665
|
+
context: env.context
|
|
6666
|
+
};
|
|
6667
|
+
const { data: dataOfSelection } = useGetSelection3({
|
|
6668
|
+
data,
|
|
6669
|
+
queryKey: [`data_${relation}`, domainObject]
|
|
6670
|
+
});
|
|
6671
|
+
const customNoOptionsMessage = () => placeholderNoOption;
|
|
6672
|
+
const tranfer = (data2) => {
|
|
6673
|
+
return data2?.map((val) => ({
|
|
6674
|
+
id: val.value,
|
|
6675
|
+
display_name: val.label
|
|
6676
|
+
})) || [];
|
|
6677
|
+
};
|
|
6678
|
+
const options = dataOfSelection?.records?.map((val) => ({
|
|
6679
|
+
value: val.id,
|
|
6680
|
+
label: val.name ?? val.display_name,
|
|
6681
|
+
...val
|
|
6682
|
+
})) || [];
|
|
6683
|
+
return {
|
|
6684
|
+
options,
|
|
6685
|
+
customNoOptionsMessage,
|
|
6686
|
+
tranfer,
|
|
6687
|
+
dataOfSelection,
|
|
6688
|
+
isUser
|
|
6689
|
+
};
|
|
6690
|
+
};
|
|
6691
|
+
|
|
6692
|
+
// src/widget/basic/status-bar-field/controller.ts
|
|
6693
|
+
import { useState as useState11 } from "react";
|
|
6694
|
+
import {
|
|
6695
|
+
evalJSONDomain as evalJSONDomain5,
|
|
6696
|
+
selectEnv as selectEnv3,
|
|
6697
|
+
useAppSelector as useAppSelector8,
|
|
6698
|
+
useChangeStatus,
|
|
6699
|
+
useGetListData as useGetListData4
|
|
6700
|
+
} from "@fctc/interface-logic";
|
|
6701
|
+
var durationController = (props) => {
|
|
6702
|
+
const {
|
|
6703
|
+
relation,
|
|
6704
|
+
defaultValue,
|
|
6705
|
+
domain,
|
|
6706
|
+
formValues,
|
|
6707
|
+
name,
|
|
6708
|
+
id,
|
|
6709
|
+
model,
|
|
6710
|
+
onRefetch
|
|
6711
|
+
} = props;
|
|
6712
|
+
const specification = {
|
|
6713
|
+
id: 0,
|
|
6714
|
+
name: "",
|
|
6715
|
+
fold: ""
|
|
6716
|
+
};
|
|
6717
|
+
const [disabled, setDisabled] = useState11(false);
|
|
6718
|
+
const [modelStatus, setModalStatus] = useState11(false);
|
|
6719
|
+
const { context } = useAppSelector8(selectEnv3);
|
|
6720
|
+
const queryKey = [`data-status-duration`, specification];
|
|
6721
|
+
const listDataProps = {
|
|
6722
|
+
model: relation,
|
|
6723
|
+
specification,
|
|
6724
|
+
domain: evalJSONDomain5(domain, JSON.parse(JSON.stringify(formValues))),
|
|
6725
|
+
limit: 10,
|
|
6726
|
+
offset: 0,
|
|
6727
|
+
fields: "",
|
|
6728
|
+
groupby: [],
|
|
6729
|
+
context: {
|
|
6730
|
+
lang: context.lang
|
|
6731
|
+
},
|
|
6732
|
+
sort: ""
|
|
6733
|
+
};
|
|
6734
|
+
const { data: dataResponse } = useGetListData4(listDataProps, queryKey);
|
|
6735
|
+
const { mutate: fetchChangeStatus } = useChangeStatus();
|
|
6736
|
+
const handleClick = async (stage_id) => {
|
|
6737
|
+
setDisabled(true);
|
|
6738
|
+
if (stage_id) {
|
|
6739
|
+
fetchChangeStatus(
|
|
6740
|
+
{
|
|
6741
|
+
data: {
|
|
6742
|
+
stage_id,
|
|
6743
|
+
name,
|
|
6744
|
+
id,
|
|
6745
|
+
model,
|
|
6746
|
+
lang: context.lang
|
|
6747
|
+
}
|
|
6748
|
+
},
|
|
6749
|
+
{
|
|
6750
|
+
onSuccess: (res) => {
|
|
6751
|
+
if (res) {
|
|
6752
|
+
setDisabled(false);
|
|
6753
|
+
onRefetch && onRefetch();
|
|
6754
|
+
}
|
|
6755
|
+
}
|
|
6756
|
+
}
|
|
6757
|
+
);
|
|
6758
|
+
}
|
|
6759
|
+
};
|
|
6760
|
+
return {
|
|
6761
|
+
defaultValue,
|
|
6762
|
+
dataResponse,
|
|
6763
|
+
handleClick,
|
|
6764
|
+
disabled,
|
|
6765
|
+
modelStatus,
|
|
6766
|
+
setModalStatus
|
|
6767
|
+
};
|
|
6768
|
+
};
|
|
6769
|
+
|
|
6770
|
+
// src/widget/basic/priority-field/controller.ts
|
|
6771
|
+
import { evalJSONContext as evalJSONContext6, useSave as useSave2 } from "@fctc/interface-logic";
|
|
6772
|
+
var priorityFieldController = (props) => {
|
|
6773
|
+
const {
|
|
6774
|
+
value,
|
|
6775
|
+
isForm,
|
|
6776
|
+
name,
|
|
6777
|
+
methods,
|
|
6778
|
+
onChange,
|
|
6779
|
+
model,
|
|
6780
|
+
selection,
|
|
6781
|
+
id,
|
|
6782
|
+
actionData,
|
|
6783
|
+
viewData,
|
|
6784
|
+
context
|
|
6785
|
+
} = props;
|
|
6786
|
+
const _context = { ...evalJSONContext6(actionData?.context) };
|
|
6787
|
+
const contextObject = { ...context, ..._context };
|
|
6788
|
+
const defaultPriority = parseInt(value) + 1;
|
|
6789
|
+
const label = viewData?.models?.[model]?.[name ?? ""]?.string ?? name;
|
|
6790
|
+
const { mutateAsync: fetchSave } = useSave2();
|
|
6791
|
+
const savePriorities = async ({
|
|
6792
|
+
value: value2,
|
|
6793
|
+
resetPriority
|
|
6794
|
+
}) => {
|
|
6795
|
+
const priorityValue = value2 <= 0 ? 0 : value2 - 1;
|
|
6796
|
+
try {
|
|
6797
|
+
fetchSave({
|
|
6798
|
+
ids: id ? [id] : [],
|
|
6799
|
+
data: { [name ?? ""]: String(priorityValue) },
|
|
6800
|
+
model: model ?? "",
|
|
6801
|
+
context: contextObject
|
|
6802
|
+
});
|
|
6803
|
+
if (typeof onChange === "function") {
|
|
6804
|
+
onChange(name ?? "", String(priorityValue));
|
|
6805
|
+
}
|
|
6806
|
+
} catch (error) {
|
|
6807
|
+
if (resetPriority) {
|
|
6808
|
+
resetPriority();
|
|
6809
|
+
}
|
|
6810
|
+
}
|
|
6811
|
+
};
|
|
6812
|
+
return {
|
|
6813
|
+
selection,
|
|
6814
|
+
isForm,
|
|
6815
|
+
methods,
|
|
6816
|
+
defaultPriority,
|
|
6817
|
+
savePriorities,
|
|
6818
|
+
label,
|
|
6819
|
+
id,
|
|
6820
|
+
onChange
|
|
6821
|
+
};
|
|
6822
|
+
};
|
|
6823
|
+
|
|
6824
|
+
// src/widget/basic/float-time-field/controller.ts
|
|
6825
|
+
import { useState as useState12 } from "react";
|
|
6826
|
+
import { convertFloatToTime, convertTimeToFloat } from "@fctc/interface-logic";
|
|
6827
|
+
var floatTimeFiledController = ({
|
|
6828
|
+
onChange: fieldOnChange,
|
|
6829
|
+
onBlur,
|
|
6830
|
+
value,
|
|
6831
|
+
isDirty,
|
|
6832
|
+
props
|
|
6833
|
+
}) => {
|
|
6834
|
+
const { name, defaultValue = 0, onChange } = props;
|
|
6835
|
+
const [input, setInput] = useState12(
|
|
6836
|
+
convertFloatToTime(value ?? defaultValue)
|
|
6837
|
+
);
|
|
6838
|
+
const [formattedTime, setFormattedTime] = useState12("");
|
|
6839
|
+
const [errors, setErrors] = useState12("");
|
|
6840
|
+
const handleInputChange = (e) => {
|
|
6841
|
+
const raw = e.target.value.replace(/[^\d:]/g, "");
|
|
6842
|
+
setInput(raw);
|
|
6843
|
+
const timeRegex = /^(\d{1,2}):?(\d{0,2})$/;
|
|
6844
|
+
const match = raw.match(timeRegex);
|
|
6845
|
+
if (!match) {
|
|
6846
|
+
setErrors("\u0110\u1ECBnh d\u1EA1ng kh\xF4ng h\u1EE3p l\u1EC7");
|
|
6847
|
+
setFormattedTime("");
|
|
6848
|
+
return;
|
|
6849
|
+
}
|
|
6850
|
+
let hours = parseInt(match[1] ?? "0", 10);
|
|
6851
|
+
let minutes = parseInt(match[2] ?? "0", 10);
|
|
6852
|
+
if (isNaN(hours)) hours = 0;
|
|
6853
|
+
if (isNaN(minutes)) minutes = 0;
|
|
6854
|
+
if (hours >= 24) {
|
|
6855
|
+
hours = 0;
|
|
6856
|
+
}
|
|
6857
|
+
if (minutes >= 60) {
|
|
6858
|
+
minutes = 0;
|
|
6859
|
+
}
|
|
6860
|
+
const formatted = `${hours.toString().padStart(2, "0")}:${minutes.toString().padStart(2, "0")}`;
|
|
6861
|
+
setErrors("");
|
|
6862
|
+
setFormattedTime(formatted);
|
|
6863
|
+
fieldOnChange(formatted);
|
|
6864
|
+
};
|
|
6865
|
+
const handleBlur = () => {
|
|
6866
|
+
if (!isDirty) return;
|
|
6867
|
+
if (formattedTime) {
|
|
6868
|
+
setInput(formattedTime);
|
|
6869
|
+
const floatVal = convertTimeToFloat(formattedTime);
|
|
6870
|
+
fieldOnChange(floatVal);
|
|
6871
|
+
if (onChange) {
|
|
6872
|
+
onChange(name ?? "", floatVal);
|
|
6873
|
+
}
|
|
6874
|
+
} else {
|
|
6875
|
+
setInput("00:00");
|
|
6876
|
+
fieldOnChange(0);
|
|
6877
|
+
if (onChange) {
|
|
6878
|
+
onChange(name ?? "", 0);
|
|
6879
|
+
}
|
|
6880
|
+
setErrors("");
|
|
6881
|
+
}
|
|
6882
|
+
onBlur();
|
|
6883
|
+
};
|
|
6884
|
+
const handleKeyDown = (e) => {
|
|
6885
|
+
{
|
|
6886
|
+
const allowed = [
|
|
6887
|
+
"Backspace",
|
|
6888
|
+
"Tab",
|
|
6889
|
+
"ArrowLeft",
|
|
6890
|
+
"ArrowRight",
|
|
6891
|
+
"Delete",
|
|
6892
|
+
"Home",
|
|
6893
|
+
"End",
|
|
6894
|
+
":"
|
|
6895
|
+
];
|
|
6896
|
+
const isNumber = /^[0-9]$/.test(e.key);
|
|
6897
|
+
if (!isNumber && !allowed.includes(e.key)) {
|
|
6898
|
+
e.preventDefault();
|
|
6899
|
+
}
|
|
6900
|
+
}
|
|
6901
|
+
};
|
|
6902
|
+
return {
|
|
6903
|
+
handleInputChange,
|
|
6904
|
+
handleBlur,
|
|
6905
|
+
handleKeyDown,
|
|
6906
|
+
input,
|
|
6907
|
+
errors
|
|
6908
|
+
};
|
|
6909
|
+
};
|
|
6910
|
+
|
|
6634
6911
|
// src/widget/basic/float-field/controller.ts
|
|
6912
|
+
import { useEffect as useEffect15, useRef as useRef5, useState as useState13 } from "react";
|
|
6635
6913
|
var floatController = ({
|
|
6636
6914
|
onChange,
|
|
6637
6915
|
value,
|
|
@@ -6639,10 +6917,10 @@ var floatController = ({
|
|
|
6639
6917
|
}) => {
|
|
6640
6918
|
const { name, required, methods, onChange: handleOnchange, string } = props;
|
|
6641
6919
|
const { setError, clearErrors } = methods;
|
|
6642
|
-
const [inputValue, setInputValue] =
|
|
6920
|
+
const [inputValue, setInputValue] = useState13(
|
|
6643
6921
|
value !== void 0 && value !== null ? useFormatFloatNumber(value) : ""
|
|
6644
6922
|
);
|
|
6645
|
-
|
|
6923
|
+
useEffect15(() => {
|
|
6646
6924
|
if (value !== void 0 && value !== null && value !== parseFloat(inputValue?.replace(/,/g, ""))) {
|
|
6647
6925
|
setInputValue(useFormatFloatNumber(value));
|
|
6648
6926
|
clearErrors(name);
|
|
@@ -6753,10 +7031,10 @@ var useFormatFloatNumber = (value) => {
|
|
|
6753
7031
|
};
|
|
6754
7032
|
|
|
6755
7033
|
// src/widget/basic/download-file-field/controller.ts
|
|
6756
|
-
import { useId, useState as
|
|
7034
|
+
import { useId, useState as useState14 } from "react";
|
|
6757
7035
|
var downloadFileController = () => {
|
|
6758
7036
|
const inputId = useId();
|
|
6759
|
-
const [file, setFile] =
|
|
7037
|
+
const [file, setFile] = useState14(null);
|
|
6760
7038
|
const handleFileChange = (e) => {
|
|
6761
7039
|
setFile(e.target.files[0]);
|
|
6762
7040
|
};
|
|
@@ -6920,11 +7198,11 @@ var dateFieldController = (props) => {
|
|
|
6920
7198
|
};
|
|
6921
7199
|
|
|
6922
7200
|
// src/widget/basic/copy-link-button/controller.ts
|
|
6923
|
-
import { useState as
|
|
7201
|
+
import { useState as useState15 } from "react";
|
|
6924
7202
|
import { copyTextToClipboard } from "@fctc/interface-logic";
|
|
6925
7203
|
var copyLinkButtonController = (props) => {
|
|
6926
7204
|
const { value, defaultValue } = props;
|
|
6927
|
-
const [isCopied, setIsCopied] =
|
|
7205
|
+
const [isCopied, setIsCopied] = useState15(false);
|
|
6928
7206
|
const handleCopyToClipboard = async (value2) => {
|
|
6929
7207
|
await copyTextToClipboard(value2);
|
|
6930
7208
|
setIsCopied(true);
|
|
@@ -6939,412 +7217,132 @@ var copyLinkButtonController = (props) => {
|
|
|
6939
7217
|
};
|
|
6940
7218
|
|
|
6941
7219
|
// src/widget/basic/color-field/color-controller.ts
|
|
6942
|
-
import { evalJSONContext as evalJSONContext7, getEnv as
|
|
7220
|
+
import { evalJSONContext as evalJSONContext7, getEnv as getEnv11, useSave as useSave3 } from "@fctc/interface-logic";
|
|
6943
7221
|
var colorFieldController = (props) => {
|
|
6944
7222
|
const { value, isForm, name, formValues, idForm, model, actionData } = props;
|
|
6945
|
-
const env =
|
|
6946
|
-
const _context = { ...evalJSONContext7(actionData?.context) || {} };
|
|
6947
|
-
const contextObject = { ...env.context, ..._context };
|
|
6948
|
-
const idDefault = isForm ? idForm : formValues?.id;
|
|
6949
|
-
const { mutate: onSave } = useSave3();
|
|
6950
|
-
const savePickColor = async (colorObject) => {
|
|
6951
|
-
const { id } = colorObject;
|
|
6952
|
-
if (value === id) return;
|
|
6953
|
-
try {
|
|
6954
|
-
onSave({
|
|
6955
|
-
ids: idDefault !== null ? [idDefault] : [],
|
|
6956
|
-
model: model ?? "",
|
|
6957
|
-
data: { [name ?? ""]: id },
|
|
6958
|
-
specification: {
|
|
6959
|
-
name: {},
|
|
6960
|
-
color: {}
|
|
6961
|
-
},
|
|
6962
|
-
context: contextObject
|
|
6963
|
-
});
|
|
6964
|
-
} catch (error) {
|
|
6965
|
-
console.log(error);
|
|
6966
|
-
}
|
|
6967
|
-
};
|
|
6968
|
-
return {
|
|
6969
|
-
savePickColor
|
|
6970
|
-
};
|
|
6971
|
-
};
|
|
6972
|
-
|
|
6973
|
-
// src/widget/basic/binary-field/controller.ts
|
|
6974
|
-
import { useEffect as useEffect14, useId as useId2, useRef as useRef6, useState as useState15 } from "react";
|
|
6975
|
-
import { isBase64Image } from "@fctc/interface-logic";
|
|
6976
|
-
var binaryFieldController = (props) => {
|
|
6977
|
-
const { name, methods, readonly = false, value } = props;
|
|
6978
|
-
const inputId = useId2();
|
|
6979
|
-
const [selectedImage, setSelectedImage] = useState15(null);
|
|
6980
|
-
const [initialImage, setInitialImage] = useState15(value || null);
|
|
6981
|
-
const [isInsideTable, setIsInsideTable] = useState15(false);
|
|
6982
|
-
const { setValue } = methods;
|
|
6983
|
-
const binaryRef = useRef6(null);
|
|
6984
|
-
const convertUrlToBase64 = async (url) => {
|
|
6985
|
-
try {
|
|
6986
|
-
const response = await fetch(url);
|
|
6987
|
-
const blob = await response.blob();
|
|
6988
|
-
return new Promise((resolve, reject) => {
|
|
6989
|
-
const reader = new FileReader();
|
|
6990
|
-
reader.onloadend = () => {
|
|
6991
|
-
resolve(reader.result);
|
|
6992
|
-
};
|
|
6993
|
-
reader.onerror = reject;
|
|
6994
|
-
reader.readAsDataURL(blob);
|
|
6995
|
-
});
|
|
6996
|
-
} catch (error) {
|
|
6997
|
-
console.error("Error converting URL to Base64:", error);
|
|
6998
|
-
throw error;
|
|
6999
|
-
}
|
|
7000
|
-
};
|
|
7001
|
-
const extractBase64Data = (base64Url) => {
|
|
7002
|
-
if (base64Url.includes("base64,")) {
|
|
7003
|
-
return base64Url.split("base64,")[1];
|
|
7004
|
-
}
|
|
7005
|
-
return base64Url;
|
|
7006
|
-
};
|
|
7007
|
-
const handleImageChange = async (e, onChange) => {
|
|
7008
|
-
if (readonly) return;
|
|
7009
|
-
const file = e?.target?.files?.[0];
|
|
7010
|
-
if (file) {
|
|
7011
|
-
const imageUrl = URL.createObjectURL(file);
|
|
7012
|
-
setSelectedImage(imageUrl);
|
|
7013
|
-
setInitialImage(null);
|
|
7014
|
-
onChange(file);
|
|
7015
|
-
const compressedBase64 = await convertUrlToBase64(imageUrl);
|
|
7016
|
-
const base64Data = extractBase64Data(compressedBase64);
|
|
7017
|
-
setValue(name, base64Data, {
|
|
7018
|
-
shouldDirty: true
|
|
7019
|
-
});
|
|
7020
|
-
}
|
|
7021
|
-
};
|
|
7022
|
-
const handleRemoveImage = (onChange) => {
|
|
7023
|
-
setSelectedImage(null);
|
|
7024
|
-
setInitialImage(null);
|
|
7025
|
-
onChange(null);
|
|
7026
|
-
};
|
|
7027
|
-
const isBlobUrl = (url) => {
|
|
7028
|
-
return /^blob:/.test(url);
|
|
7029
|
-
};
|
|
7030
|
-
const checkIsImageLink = (url) => {
|
|
7031
|
-
const imageExtensions = /\.(jpg|jpeg|png|gif|bmp|webp|svg|tiff|ico)$/i;
|
|
7032
|
-
return imageExtensions.test(url) || isBase64Image(url) || isBlobUrl(url);
|
|
7033
|
-
};
|
|
7034
|
-
const getImageBase64WithMimeType = (base64) => {
|
|
7035
|
-
if (typeof base64 !== "string" || base64.length < 10) return null;
|
|
7036
|
-
if (isBase64Image(base64)) return base64;
|
|
7037
|
-
let mimeType = null;
|
|
7038
|
-
if (base64.startsWith("iVBORw0KGgo")) mimeType = "image/png";
|
|
7039
|
-
else if (base64.startsWith("/9j/")) mimeType = "image/jpeg";
|
|
7040
|
-
else if (base64.startsWith("R0lGOD")) mimeType = "image/gif";
|
|
7041
|
-
else if (base64.startsWith("Qk")) mimeType = "image/bmp";
|
|
7042
|
-
else if (base64.startsWith("UklGR")) mimeType = "image/webp";
|
|
7043
|
-
return mimeType ? `data:${mimeType};base64,${base64}` : null;
|
|
7044
|
-
};
|
|
7045
|
-
useEffect14(() => {
|
|
7046
|
-
return () => {
|
|
7047
|
-
if (selectedImage) {
|
|
7048
|
-
URL.revokeObjectURL(selectedImage);
|
|
7049
|
-
}
|
|
7050
|
-
};
|
|
7051
|
-
}, [selectedImage]);
|
|
7052
|
-
useEffect14(() => {
|
|
7053
|
-
if (binaryRef.current) {
|
|
7054
|
-
const isInsideTable2 = !!binaryRef.current.closest("table");
|
|
7055
|
-
setIsInsideTable(isInsideTable2);
|
|
7056
|
-
}
|
|
7057
|
-
}, []);
|
|
7058
|
-
return {
|
|
7059
|
-
inputId,
|
|
7060
|
-
selectedImage,
|
|
7061
|
-
initialImage,
|
|
7062
|
-
isInsideTable,
|
|
7063
|
-
binaryRef,
|
|
7064
|
-
handleImageChange,
|
|
7065
|
-
handleRemoveImage,
|
|
7066
|
-
checkIsImageLink,
|
|
7067
|
-
getImageBase64WithMimeType
|
|
7068
|
-
};
|
|
7069
|
-
};
|
|
7070
|
-
|
|
7071
|
-
// src/widget/advance/table/table-body/controller.ts
|
|
7072
|
-
import { setSelectedRowKeys, useAppDispatch as useAppDispatch6 } from "@fctc/interface-logic";
|
|
7073
|
-
import { useEffect as useEffect15, useMemo as useMemo12 } from "react";
|
|
7074
|
-
var tableBodyController = (props) => {
|
|
7075
|
-
const {
|
|
7076
|
-
checkedAll,
|
|
7077
|
-
checkboxRef,
|
|
7078
|
-
setIsAutoSelect,
|
|
7079
|
-
selectedRowKeys,
|
|
7080
|
-
row,
|
|
7081
|
-
isAutoSelect,
|
|
7082
|
-
selectedRowKeysRef,
|
|
7083
|
-
onClickRow
|
|
7084
|
-
} = props;
|
|
7085
|
-
const appDispatch = useAppDispatch6();
|
|
7086
|
-
const checked = useMemo12(() => {
|
|
7087
|
-
if (!row?.id) return false;
|
|
7088
|
-
if (selectedRowKeys?.includes(row.id)) {
|
|
7089
|
-
return true;
|
|
7090
|
-
}
|
|
7091
|
-
return checkedAll;
|
|
7092
|
-
}, [row?.id, selectedRowKeys, checkedAll]);
|
|
7093
|
-
const handleCheckBoxSingle = (event) => {
|
|
7094
|
-
event.stopPropagation();
|
|
7095
|
-
if (checkedAll) {
|
|
7096
|
-
checkboxRef.current = "uncheck";
|
|
7097
|
-
setIsAutoSelect(true);
|
|
7098
|
-
return;
|
|
7099
|
-
}
|
|
7100
|
-
const newSelectedRowKeys = selectedRowKeys?.includes(row.id) ? selectedRowKeys?.filter((key) => key !== row.id) : [...selectedRowKeys, row.id];
|
|
7101
|
-
console.log("newSelectedRowKeys", newSelectedRowKeys);
|
|
7102
|
-
appDispatch(setSelectedRowKeys(newSelectedRowKeys));
|
|
7103
|
-
};
|
|
7104
|
-
const handleClickRow = (col, row2) => {
|
|
7105
|
-
onClickRow(col, row2);
|
|
7106
|
-
};
|
|
7107
|
-
useEffect15(() => {
|
|
7108
|
-
if (!row?.id) return;
|
|
7109
|
-
if (isAutoSelect) {
|
|
7110
|
-
if (checkboxRef?.current === "uncheck") {
|
|
7111
|
-
const filtered = selectedRowKeysRef.current.filter(
|
|
7112
|
-
(id) => id !== row.id
|
|
7113
|
-
);
|
|
7114
|
-
selectedRowKeysRef.current = filtered;
|
|
7115
|
-
appDispatch(setSelectedRowKeys(filtered));
|
|
7116
|
-
} else {
|
|
7117
|
-
const unique = Array.from(
|
|
7118
|
-
/* @__PURE__ */ new Set([...selectedRowKeysRef?.current, row?.id])
|
|
7119
|
-
);
|
|
7120
|
-
selectedRowKeysRef.current = unique;
|
|
7121
|
-
appDispatch(setSelectedRowKeys(unique));
|
|
7122
|
-
}
|
|
7123
|
-
}
|
|
7124
|
-
}, [isAutoSelect]);
|
|
7125
|
-
useEffect15(() => {
|
|
7126
|
-
if (!checkedAll) {
|
|
7127
|
-
checkboxRef.current = "enabled";
|
|
7128
|
-
false;
|
|
7129
|
-
}
|
|
7130
|
-
}, [checkedAll]);
|
|
7131
|
-
return {
|
|
7132
|
-
handleCheckBoxSingle,
|
|
7133
|
-
checked,
|
|
7134
|
-
handleClickRow
|
|
7135
|
-
};
|
|
7136
|
-
};
|
|
7137
|
-
|
|
7138
|
-
// src/widget/advance/table/table-head/controller.ts
|
|
7139
|
-
import {
|
|
7140
|
-
selectSearch as selectSearch4,
|
|
7141
|
-
setSelectedRowKeys as setSelectedRowKeys2,
|
|
7142
|
-
useAppDispatch as useAppDispatch7,
|
|
7143
|
-
useAppSelector as useAppSelector7
|
|
7144
|
-
} from "@fctc/interface-logic";
|
|
7145
|
-
var tableHeadController = (props) => {
|
|
7146
|
-
const { typeTable, rows, selectedRowKeysRef } = props;
|
|
7147
|
-
const appDispatch = useAppDispatch7();
|
|
7148
|
-
const { groupByDomain } = useAppSelector7(selectSearch4);
|
|
7149
|
-
const handleCheckBoxAll = (event) => {
|
|
7150
|
-
if (event?.target?.checked && typeTable === "list") {
|
|
7151
|
-
const allRowKeys = Array.isArray(rows) ? rows.map((record) => record?.id) : [];
|
|
7152
|
-
appDispatch(setSelectedRowKeys2(allRowKeys));
|
|
7153
|
-
} else if (event?.target?.checked && typeTable === "group") {
|
|
7154
|
-
const rowsIDs = document.querySelectorAll("tr[data-row-id]");
|
|
7155
|
-
const ids = Array.from(rowsIDs)?.map(
|
|
7156
|
-
(row) => Number(row?.getAttribute("data-row-id"))
|
|
7157
|
-
);
|
|
7158
|
-
if (ids?.length > 0) {
|
|
7159
|
-
appDispatch(setSelectedRowKeys2(ids));
|
|
7160
|
-
} else {
|
|
7161
|
-
const sum = countSum(
|
|
7162
|
-
rows,
|
|
7163
|
-
typeof groupByDomain === "object" ? groupByDomain?.contexts?.[0]?.group_by : void 0
|
|
7164
|
-
);
|
|
7165
|
-
const keys = Array.from({ length: sum }, (_) => void 0);
|
|
7166
|
-
appDispatch(setSelectedRowKeys2(keys));
|
|
7167
|
-
}
|
|
7168
|
-
if (selectedRowKeysRef) {
|
|
7169
|
-
selectedRowKeysRef.current = [];
|
|
7170
|
-
}
|
|
7171
|
-
} else {
|
|
7172
|
-
appDispatch(setSelectedRowKeys2([]));
|
|
7223
|
+
const env = getEnv11();
|
|
7224
|
+
const _context = { ...evalJSONContext7(actionData?.context) || {} };
|
|
7225
|
+
const contextObject = { ...env.context, ..._context };
|
|
7226
|
+
const idDefault = isForm ? idForm : formValues?.id;
|
|
7227
|
+
const { mutate: onSave } = useSave3();
|
|
7228
|
+
const savePickColor = async (colorObject) => {
|
|
7229
|
+
const { id } = colorObject;
|
|
7230
|
+
if (value === id) return;
|
|
7231
|
+
try {
|
|
7232
|
+
onSave({
|
|
7233
|
+
ids: idDefault !== null ? [idDefault] : [],
|
|
7234
|
+
model: model ?? "",
|
|
7235
|
+
data: { [name ?? ""]: id },
|
|
7236
|
+
specification: {
|
|
7237
|
+
name: {},
|
|
7238
|
+
color: {}
|
|
7239
|
+
},
|
|
7240
|
+
context: contextObject
|
|
7241
|
+
});
|
|
7242
|
+
} catch (error) {
|
|
7243
|
+
console.log(error);
|
|
7173
7244
|
}
|
|
7174
7245
|
};
|
|
7175
7246
|
return {
|
|
7176
|
-
|
|
7247
|
+
savePickColor
|
|
7177
7248
|
};
|
|
7178
7249
|
};
|
|
7179
7250
|
|
|
7180
|
-
// src/widget/
|
|
7181
|
-
import {
|
|
7182
|
-
|
|
7183
|
-
|
|
7184
|
-
|
|
7185
|
-
|
|
7186
|
-
|
|
7187
|
-
|
|
7188
|
-
|
|
7189
|
-
|
|
7190
|
-
|
|
7191
|
-
|
|
7192
|
-
|
|
7193
|
-
|
|
7194
|
-
|
|
7195
|
-
|
|
7196
|
-
|
|
7197
|
-
|
|
7198
|
-
|
|
7199
|
-
|
|
7200
|
-
|
|
7201
|
-
|
|
7202
|
-
|
|
7203
|
-
|
|
7204
|
-
|
|
7205
|
-
|
|
7206
|
-
checkedAll,
|
|
7207
|
-
isDisplayCheckbox,
|
|
7208
|
-
isAutoSelect,
|
|
7209
|
-
setIsAutoSelect,
|
|
7210
|
-
selectedRowKeysRef
|
|
7211
|
-
} = props;
|
|
7212
|
-
const [pageGroup, setPageGroup] = useState16(0);
|
|
7213
|
-
const { groupByDomain, selectedTags } = useAppSelector8(selectSearch5);
|
|
7214
|
-
const { selectedRowKeys } = useAppSelector8(selectList3);
|
|
7215
|
-
const appDispatch = useAppDispatch8();
|
|
7216
|
-
const { toDataJS } = useOdooDataTransform();
|
|
7217
|
-
const initVal = toDataJS(row, viewData, model);
|
|
7218
|
-
const [isShowGroup, setIsShowGroup] = useState16(false);
|
|
7219
|
-
const [colEmptyGroup, setColEmptyGroup] = useState16({
|
|
7220
|
-
fromStart: 1,
|
|
7221
|
-
fromEnd: 1
|
|
7222
|
-
});
|
|
7223
|
-
const processedData = useMemo13(() => {
|
|
7224
|
-
const calculateColSpanEmpty = () => {
|
|
7225
|
-
const startIndex = columns.findIndex(
|
|
7226
|
-
(col) => col.field.type === "monetary" && typeof row[col.key] === "number" || col.field.aggregator === "sum"
|
|
7227
|
-
);
|
|
7228
|
-
const endIndex = columns.findLastIndex(
|
|
7229
|
-
(col) => col.field.type === "monetary" && typeof row[col.key] === "number" || col.field.aggregator !== "sum"
|
|
7230
|
-
);
|
|
7231
|
-
const fromStart = startIndex === -1 ? columns.length : startIndex;
|
|
7232
|
-
const fromEnd = endIndex === -1 ? columns.length : columns.length - 1 - endIndex;
|
|
7233
|
-
setColEmptyGroup({ fromStart: fromStart + 1, fromEnd: fromEnd + 1 });
|
|
7234
|
-
return { fromStart: fromStart + 1, fromEnd: fromEnd + 1 };
|
|
7235
|
-
};
|
|
7236
|
-
return calculateColSpanEmpty();
|
|
7237
|
-
}, [columns, row]);
|
|
7238
|
-
const shouldFetchData = useMemo13(() => {
|
|
7239
|
-
return !!isShowGroup;
|
|
7240
|
-
}, [isShowGroup]);
|
|
7241
|
-
const enabled = shouldFetchData && !!processedData;
|
|
7242
|
-
const listDataProps = {
|
|
7243
|
-
model,
|
|
7244
|
-
specification,
|
|
7245
|
-
domain,
|
|
7246
|
-
context,
|
|
7247
|
-
offset: pageGroup * 10,
|
|
7248
|
-
fields: groupByDomain?.fields,
|
|
7249
|
-
groupby: [groupByDomain?.contexts[level]?.group_by]
|
|
7250
|
-
};
|
|
7251
|
-
const queryKey = [
|
|
7252
|
-
`data-${model}--${level}-row${indexRow}`,
|
|
7253
|
-
specification,
|
|
7254
|
-
domain,
|
|
7255
|
-
pageGroup
|
|
7256
|
-
];
|
|
7257
|
-
const {
|
|
7258
|
-
data: dataResponse,
|
|
7259
|
-
isFetched: isQueryFetched,
|
|
7260
|
-
isPlaceholderData,
|
|
7261
|
-
isLoading,
|
|
7262
|
-
isFetching
|
|
7263
|
-
} = useGetListData4(listDataProps, queryKey, enabled);
|
|
7264
|
-
const {
|
|
7265
|
-
columns: columnsGroup,
|
|
7266
|
-
rows: rowsGroup,
|
|
7267
|
-
typeTable: typeTableGroup
|
|
7268
|
-
} = tableController({
|
|
7269
|
-
data: {
|
|
7270
|
-
fields: viewData?.views?.list?.fields,
|
|
7271
|
-
records: dataResponse?.records ?? dataResponse?.groups,
|
|
7272
|
-
dataModel: viewData?.models?.[model],
|
|
7273
|
-
context: env.context,
|
|
7274
|
-
typeTable: dataResponse?.groups ? "group" : "list"
|
|
7275
|
-
}
|
|
7276
|
-
});
|
|
7277
|
-
const leftPadding = level > 1 ? level * 8 + "px" : "0px";
|
|
7278
|
-
useEffect16(() => {
|
|
7279
|
-
if (isShowGroup && selectedTags?.length > 0) {
|
|
7280
|
-
setIsShowGroup(false);
|
|
7251
|
+
// src/widget/basic/binary-field/controller.ts
|
|
7252
|
+
import { useEffect as useEffect16, useId as useId2, useRef as useRef6, useState as useState16 } from "react";
|
|
7253
|
+
import { isBase64Image } from "@fctc/interface-logic";
|
|
7254
|
+
var binaryFieldController = (props) => {
|
|
7255
|
+
const { name, methods, readonly = false, value } = props;
|
|
7256
|
+
const inputId = useId2();
|
|
7257
|
+
const [selectedImage, setSelectedImage] = useState16(null);
|
|
7258
|
+
const [initialImage, setInitialImage] = useState16(value || null);
|
|
7259
|
+
const [isInsideTable, setIsInsideTable] = useState16(false);
|
|
7260
|
+
const { setValue } = methods;
|
|
7261
|
+
const binaryRef = useRef6(null);
|
|
7262
|
+
const convertUrlToBase64 = async (url) => {
|
|
7263
|
+
try {
|
|
7264
|
+
const response = await fetch(url);
|
|
7265
|
+
const blob = await response.blob();
|
|
7266
|
+
return new Promise((resolve, reject) => {
|
|
7267
|
+
const reader = new FileReader();
|
|
7268
|
+
reader.onloadend = () => {
|
|
7269
|
+
resolve(reader.result);
|
|
7270
|
+
};
|
|
7271
|
+
reader.onerror = reject;
|
|
7272
|
+
reader.readAsDataURL(blob);
|
|
7273
|
+
});
|
|
7274
|
+
} catch (error) {
|
|
7275
|
+
console.error("Error converting URL to Base64:", error);
|
|
7276
|
+
throw error;
|
|
7281
7277
|
}
|
|
7282
|
-
}
|
|
7283
|
-
const
|
|
7284
|
-
|
|
7285
|
-
|
|
7286
|
-
)?.[1] : row[group_by_field_name];
|
|
7287
|
-
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`]})`;
|
|
7288
|
-
const allIdsNull = selectedRowKeys?.every((item) => item === void 0);
|
|
7289
|
-
const handleExpandChildGroup = () => {
|
|
7290
|
-
if (isLoading || isFetching) return;
|
|
7291
|
-
const toggleShowGroup = () => setIsShowGroup((prev) => !prev);
|
|
7292
|
-
if (allIdsNull || typeTableGroup === "group") {
|
|
7293
|
-
toggleShowGroup();
|
|
7294
|
-
return;
|
|
7278
|
+
};
|
|
7279
|
+
const extractBase64Data = (base64Url) => {
|
|
7280
|
+
if (base64Url.includes("base64,")) {
|
|
7281
|
+
return base64Url.split("base64,")[1];
|
|
7295
7282
|
}
|
|
7296
|
-
|
|
7297
|
-
|
|
7298
|
-
|
|
7299
|
-
|
|
7300
|
-
|
|
7301
|
-
|
|
7302
|
-
|
|
7303
|
-
|
|
7304
|
-
|
|
7305
|
-
|
|
7306
|
-
|
|
7307
|
-
const
|
|
7308
|
-
|
|
7283
|
+
return base64Url;
|
|
7284
|
+
};
|
|
7285
|
+
const handleImageChange = async (e, onChange) => {
|
|
7286
|
+
if (readonly) return;
|
|
7287
|
+
const file = e?.target?.files?.[0];
|
|
7288
|
+
if (file) {
|
|
7289
|
+
const imageUrl = URL.createObjectURL(file);
|
|
7290
|
+
setSelectedImage(imageUrl);
|
|
7291
|
+
setInitialImage(null);
|
|
7292
|
+
onChange(file);
|
|
7293
|
+
const compressedBase64 = await convertUrlToBase64(imageUrl);
|
|
7294
|
+
const base64Data = extractBase64Data(compressedBase64);
|
|
7295
|
+
setValue(name, base64Data, {
|
|
7296
|
+
shouldDirty: true
|
|
7297
|
+
});
|
|
7309
7298
|
}
|
|
7310
|
-
|
|
7299
|
+
};
|
|
7300
|
+
const handleRemoveImage = (onChange) => {
|
|
7301
|
+
setSelectedImage(null);
|
|
7302
|
+
setInitialImage(null);
|
|
7303
|
+
onChange(null);
|
|
7304
|
+
};
|
|
7305
|
+
const isBlobUrl = (url) => {
|
|
7306
|
+
return /^blob:/.test(url);
|
|
7307
|
+
};
|
|
7308
|
+
const checkIsImageLink = (url) => {
|
|
7309
|
+
const imageExtensions = /\.(jpg|jpeg|png|gif|bmp|webp|svg|tiff|ico)$/i;
|
|
7310
|
+
return imageExtensions.test(url) || isBase64Image(url) || isBlobUrl(url);
|
|
7311
|
+
};
|
|
7312
|
+
const getImageBase64WithMimeType = (base64) => {
|
|
7313
|
+
if (typeof base64 !== "string" || base64.length < 10) return null;
|
|
7314
|
+
if (isBase64Image(base64)) return base64;
|
|
7315
|
+
let mimeType = null;
|
|
7316
|
+
if (base64.startsWith("iVBORw0KGgo")) mimeType = "image/png";
|
|
7317
|
+
else if (base64.startsWith("/9j/")) mimeType = "image/jpeg";
|
|
7318
|
+
else if (base64.startsWith("R0lGOD")) mimeType = "image/gif";
|
|
7319
|
+
else if (base64.startsWith("Qk")) mimeType = "image/bmp";
|
|
7320
|
+
else if (base64.startsWith("UklGR")) mimeType = "image/webp";
|
|
7321
|
+
return mimeType ? `data:${mimeType};base64,${base64}` : null;
|
|
7311
7322
|
};
|
|
7312
7323
|
useEffect16(() => {
|
|
7313
|
-
|
|
7314
|
-
|
|
7324
|
+
return () => {
|
|
7325
|
+
if (selectedImage) {
|
|
7326
|
+
URL.revokeObjectURL(selectedImage);
|
|
7327
|
+
}
|
|
7328
|
+
};
|
|
7329
|
+
}, [selectedImage]);
|
|
7330
|
+
useEffect16(() => {
|
|
7331
|
+
if (binaryRef.current) {
|
|
7332
|
+
const isInsideTable2 = !!binaryRef.current.closest("table");
|
|
7333
|
+
setIsInsideTable(isInsideTable2);
|
|
7315
7334
|
}
|
|
7316
|
-
|
|
7317
|
-
setSelectedRowKeys3([...clonedKeys, -1]);
|
|
7318
|
-
setTimeout(() => setSelectedRowKeys3(clonedKeys), 500);
|
|
7319
|
-
}, [isQueryFetched]);
|
|
7335
|
+
}, []);
|
|
7320
7336
|
return {
|
|
7321
|
-
|
|
7322
|
-
|
|
7323
|
-
|
|
7324
|
-
|
|
7325
|
-
|
|
7326
|
-
|
|
7327
|
-
|
|
7328
|
-
|
|
7329
|
-
|
|
7330
|
-
columnsGroup,
|
|
7331
|
-
indexRow,
|
|
7332
|
-
rowsGroup,
|
|
7333
|
-
model,
|
|
7334
|
-
viewData,
|
|
7335
|
-
renderField,
|
|
7336
|
-
level,
|
|
7337
|
-
specification,
|
|
7338
|
-
context,
|
|
7339
|
-
checkedAll,
|
|
7340
|
-
isDisplayCheckbox,
|
|
7341
|
-
isAutoSelect,
|
|
7342
|
-
setIsAutoSelect,
|
|
7343
|
-
selectedRowKeysRef,
|
|
7344
|
-
initVal,
|
|
7345
|
-
dataResponse,
|
|
7346
|
-
pageGroup,
|
|
7347
|
-
setPageGroup
|
|
7337
|
+
inputId,
|
|
7338
|
+
selectedImage,
|
|
7339
|
+
initialImage,
|
|
7340
|
+
isInsideTable,
|
|
7341
|
+
binaryRef,
|
|
7342
|
+
handleImageChange,
|
|
7343
|
+
handleRemoveImage,
|
|
7344
|
+
checkIsImageLink,
|
|
7345
|
+
getImageBase64WithMimeType
|
|
7348
7346
|
};
|
|
7349
7347
|
};
|
|
7350
7348
|
export {
|