@michalrakus/x-react-web-lib 1.38.2 → 1.38.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/lib/components/XFormComponentDT.js +3 -1
- package/lib/components/XInputDate.d.ts +1 -1
- package/lib/components/XLazyDataTable/XLazyDataTable.d.ts +10 -2
- package/lib/components/XLazyDataTable/XLazyDataTable.js +86 -40
- package/lib/components/XUtils.js +3 -1
- package/lib/modules/docTemplates/xt-doc-template.d.ts +1 -0
- package/package.json +1 -1
|
@@ -55,7 +55,9 @@ var XFormComponentDT = /** @class */ (function (_super) {
|
|
|
55
55
|
// if the length of field is 2 or more, then readOnly
|
|
56
56
|
readOnly = true;
|
|
57
57
|
}
|
|
58
|
-
// formReadOnlyBase is called on the level XFormDataTable2
|
|
58
|
+
// formReadOnlyBase is called on the level XFormDataTable2 and XFormPanelList
|
|
59
|
+
// the reason is (probably) that in XFormDataTable2 and XFormPanelList we know the assoc name whereas here in component we know only field name
|
|
60
|
+
// (assoc name is param of formReadOnlyBase)
|
|
59
61
|
// else if (this.props.form.formReadOnlyBase("xxx")) {
|
|
60
62
|
// readOnly = true;
|
|
61
63
|
// }
|
|
@@ -2,7 +2,7 @@ import React from "react";
|
|
|
2
2
|
import { XFormComponentProps } from "./XFormComponent";
|
|
3
3
|
import { XInput } from "./XInput";
|
|
4
4
|
import { XDateScale } from "../serverApi/XUtilsConversions";
|
|
5
|
-
export interface XInputDateProps extends XFormComponentProps<
|
|
5
|
+
export interface XInputDateProps extends XFormComponentProps<Date> {
|
|
6
6
|
field: string;
|
|
7
7
|
scale?: XDateScale;
|
|
8
8
|
}
|
|
@@ -3,7 +3,7 @@ import { DataTableFilterMeta, DataTableFilterMetaData, DataTableOperatorFilterMe
|
|
|
3
3
|
import { ColumnBodyOptions, ColumnFilterElementTemplateOptions } from 'primereact/column';
|
|
4
4
|
import { XStorageType, XViewStatusOrBoolean } from "../XUtils";
|
|
5
5
|
import { XSearchBrowseParams } from "../XSearchBrowseParams";
|
|
6
|
-
import { XAggregateFunction, XCustomFilter } from "../../serverApi/FindParam";
|
|
6
|
+
import { FindParam, XAggregateFunction, XCustomFilter } from "../../serverApi/FindParam";
|
|
7
7
|
import { XOnSaveOrCancelProp } from "../XFormBase";
|
|
8
8
|
import { IconType } from "primereact/utils";
|
|
9
9
|
import { ButtonProps } from "primereact/button";
|
|
@@ -12,17 +12,22 @@ export type XBetweenFilterProp = "row" | "column" | undefined;
|
|
|
12
12
|
export type XMultilineRenderType = "singleLine" | "fewLines" | "allLines";
|
|
13
13
|
export type XOpenFormForInsert = (initValues?: object, onSaveOrCancel?: XOnSaveOrCancelProp, form?: JSX.Element) => void;
|
|
14
14
|
export type XOpenFormForUpdate = (id: number, onSaveOrCancel?: XOnSaveOrCancelProp, form?: JSX.Element) => void;
|
|
15
|
+
export type XAppButtonForRowOnClick = (selectedRow: any, findParam: FindParam) => void;
|
|
15
16
|
export interface XAppButtonForRow {
|
|
16
17
|
key?: string;
|
|
17
18
|
icon?: IconType<ButtonProps>;
|
|
18
19
|
label: string;
|
|
19
|
-
onClick:
|
|
20
|
+
onClick: XAppButtonForRowOnClick;
|
|
20
21
|
style?: React.CSSProperties;
|
|
21
22
|
}
|
|
22
23
|
export interface XOptionalCustomFilter {
|
|
23
24
|
label: string;
|
|
24
25
|
filter: XCustomFilter;
|
|
25
26
|
}
|
|
27
|
+
export interface XAssocToSort {
|
|
28
|
+
assoc: string;
|
|
29
|
+
sortField: string;
|
|
30
|
+
}
|
|
26
31
|
export interface XEditModeHandlers {
|
|
27
32
|
onStart: () => void;
|
|
28
33
|
onSave: () => void;
|
|
@@ -92,6 +97,7 @@ export interface XLazyDataTableProps {
|
|
|
92
97
|
sortField?: string | DataTableSortMeta[];
|
|
93
98
|
fullTextSearch?: boolean | string[];
|
|
94
99
|
fields?: string[];
|
|
100
|
+
assocsToSort?: XAssocToSort[];
|
|
95
101
|
multilineSwitch?: boolean;
|
|
96
102
|
multilineSwitchInitValue?: XMultilineRenderType;
|
|
97
103
|
multilineSwitchFewLinesCount?: number;
|
|
@@ -157,6 +163,8 @@ export interface XLazyColumnProps {
|
|
|
157
163
|
aggregateType?: XAggregateFunction;
|
|
158
164
|
columnViewStatus: XViewStatusOrBoolean;
|
|
159
165
|
filterElement?: XFilterElementProp;
|
|
166
|
+
className?: string;
|
|
167
|
+
style?: React.CSSProperties;
|
|
160
168
|
body?: React.ReactNode | ((data: any, options: ColumnBodyOptions) => React.ReactNode);
|
|
161
169
|
}
|
|
162
170
|
export type XLazyColumnType = {
|
|
@@ -209,11 +209,15 @@ exports.XLazyDataTable = (0, react_1.forwardRef)(function (_a, ref) {
|
|
|
209
209
|
for (var columns_2 = __values(columns), columns_2_1 = columns_2.next(); !columns_2_1.done; columns_2_1 = columns_2.next()) {
|
|
210
210
|
var column = columns_2_1.value;
|
|
211
211
|
var xLazyColumn = column; // nevedel som to krajsie...
|
|
212
|
+
// in some situations, this would be suitable, but for dynamic hide/show columns it can cause crash
|
|
213
|
+
// better place for initializing filters is probably creating columns - function(child)
|
|
214
|
+
//if (XUtils.xViewStatus(xLazyColumn.props.columnViewStatus) !== XViewStatus.Hidden) {
|
|
212
215
|
var field = xLazyColumn.props.field;
|
|
213
216
|
var xField = XUtilsMetadataCommon_1.XUtilsMetadataCommon.getXFieldByPath(xEntity, field);
|
|
214
217
|
// TODO column.props.dropdownInFilter - pre "menu" by bolo fajn mat zoznam "enumov"
|
|
215
218
|
var filterMatchMode = getInitFilterMatchMode(xLazyColumn.props, xField);
|
|
216
219
|
filtersInit[field] = createFilterItem(props.filterDisplay, { value: null, matchMode: filterMatchMode });
|
|
220
|
+
//}
|
|
217
221
|
}
|
|
218
222
|
}
|
|
219
223
|
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
|
@@ -619,15 +623,16 @@ exports.XLazyDataTable = (0, react_1.forwardRef)(function (_a, ref) {
|
|
|
619
623
|
return [4 /*yield*/, findByFilter(findParam)];
|
|
620
624
|
case 1:
|
|
621
625
|
findResult = _a.sent();
|
|
626
|
+
sortAssocsToSort(findResult);
|
|
622
627
|
setValue(findResult);
|
|
623
628
|
setupExpandedRows(findResult, multilineSwitchValue);
|
|
624
629
|
setLoading(false);
|
|
625
630
|
// save table state into session/local
|
|
626
|
-
//saveTableState(findParam); <- old solution, state is saved
|
|
627
|
-
// odlozime si filter hodnoty pre pripadny export
|
|
628
|
-
setFiltersAfterFiltering(filters);
|
|
631
|
+
//saveTableState(findParam); <- old solution, state is saved immediately after change of some filter field, sorting, etc.
|
|
632
|
+
// odlozime si filter hodnoty pre pripadny export (maybe simple cloning is enough, but to be sure we use deep)
|
|
633
|
+
setFiltersAfterFiltering(_.cloneDeep(filters));
|
|
629
634
|
setFtsInputValueAfterFiltering(ftsInputValue ? __assign({}, ftsInputValue) : undefined);
|
|
630
|
-
setOptionalCustomFilterAfterFiltering(optionalCustomFilter);
|
|
635
|
+
setOptionalCustomFilterAfterFiltering(optionalCustomFilter ? _.cloneDeep(optionalCustomFilter) : undefined);
|
|
631
636
|
// async check for new version - the purpose is to get new version of app to the browser (if available) in short time (10 minutes)
|
|
632
637
|
// (if there is no new version, the check will run async (as the last operation) and nothing will happen)
|
|
633
638
|
XUtils_1.XUtils.reloadIfNewVersion();
|
|
@@ -635,8 +640,44 @@ exports.XLazyDataTable = (0, react_1.forwardRef)(function (_a, ref) {
|
|
|
635
640
|
}
|
|
636
641
|
});
|
|
637
642
|
}); };
|
|
643
|
+
var sortAssocsToSort = function (findResult) {
|
|
644
|
+
var e_4, _a, e_5, _b;
|
|
645
|
+
if (props.assocsToSort) {
|
|
646
|
+
if (findResult.rowList) {
|
|
647
|
+
try {
|
|
648
|
+
for (var _c = __values(findResult.rowList), _d = _c.next(); !_d.done; _d = _c.next()) {
|
|
649
|
+
var row = _d.value;
|
|
650
|
+
try {
|
|
651
|
+
// sorting in javascript (avoid of sorting in DB)
|
|
652
|
+
for (var _e = (e_5 = void 0, __values(props.assocsToSort)), _f = _e.next(); !_f.done; _f = _e.next()) {
|
|
653
|
+
var assocToSort = _f.value;
|
|
654
|
+
var assocRowList = row[assocToSort.assoc];
|
|
655
|
+
if (assocRowList) {
|
|
656
|
+
row[assocToSort.assoc] = XUtilsCommon_1.XUtilsCommon.arraySort(assocRowList, assocToSort.sortField);
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
catch (e_5_1) { e_5 = { error: e_5_1 }; }
|
|
661
|
+
finally {
|
|
662
|
+
try {
|
|
663
|
+
if (_f && !_f.done && (_b = _e.return)) _b.call(_e);
|
|
664
|
+
}
|
|
665
|
+
finally { if (e_5) throw e_5.error; }
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
catch (e_4_1) { e_4 = { error: e_4_1 }; }
|
|
670
|
+
finally {
|
|
671
|
+
try {
|
|
672
|
+
if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
|
|
673
|
+
}
|
|
674
|
+
finally { if (e_4) throw e_4.error; }
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
};
|
|
638
679
|
var setupExpandedRows = function (findResult, multilineSwitchValue) {
|
|
639
|
-
var
|
|
680
|
+
var e_6, _a;
|
|
640
681
|
if (props.rowExpansionTemplate) {
|
|
641
682
|
var expandedRowsLocal = {};
|
|
642
683
|
if (findResult.rowList) {
|
|
@@ -652,12 +693,12 @@ exports.XLazyDataTable = (0, react_1.forwardRef)(function (_a, ref) {
|
|
|
652
693
|
}
|
|
653
694
|
}
|
|
654
695
|
}
|
|
655
|
-
catch (
|
|
696
|
+
catch (e_6_1) { e_6 = { error: e_6_1 }; }
|
|
656
697
|
finally {
|
|
657
698
|
try {
|
|
658
699
|
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
|
|
659
700
|
}
|
|
660
|
-
finally { if (
|
|
701
|
+
finally { if (e_6) throw e_6.error; }
|
|
661
702
|
}
|
|
662
703
|
}
|
|
663
704
|
setExpandedRows(expandedRowsLocal);
|
|
@@ -700,7 +741,7 @@ exports.XLazyDataTable = (0, react_1.forwardRef)(function (_a, ref) {
|
|
|
700
741
|
var getFields = function (addPropsFields) {
|
|
701
742
|
// krasne zobrazi cely objekt!
|
|
702
743
|
//console.log(dataTableEl.current);
|
|
703
|
-
var
|
|
744
|
+
var e_7, _a;
|
|
704
745
|
var fields = [];
|
|
705
746
|
var columns = dataTableEl.current.props.children;
|
|
706
747
|
try {
|
|
@@ -709,12 +750,12 @@ exports.XLazyDataTable = (0, react_1.forwardRef)(function (_a, ref) {
|
|
|
709
750
|
fields.push(column.props.field);
|
|
710
751
|
}
|
|
711
752
|
}
|
|
712
|
-
catch (
|
|
753
|
+
catch (e_7_1) { e_7 = { error: e_7_1 }; }
|
|
713
754
|
finally {
|
|
714
755
|
try {
|
|
715
756
|
if (columns_3_1 && !columns_3_1.done && (_a = columns_3.return)) _a.call(columns_3);
|
|
716
757
|
}
|
|
717
|
-
finally { if (
|
|
758
|
+
finally { if (e_7) throw e_7.error; }
|
|
718
759
|
}
|
|
719
760
|
if (addPropsFields) {
|
|
720
761
|
if (props.fields) {
|
|
@@ -726,7 +767,7 @@ exports.XLazyDataTable = (0, react_1.forwardRef)(function (_a, ref) {
|
|
|
726
767
|
var getHeaders = function () {
|
|
727
768
|
// krasne zobrazi cely objekt!
|
|
728
769
|
//console.log(dataTableEl.current);
|
|
729
|
-
var
|
|
770
|
+
var e_8, _a;
|
|
730
771
|
var headers = [];
|
|
731
772
|
var columns = dataTableEl.current.props.children;
|
|
732
773
|
try {
|
|
@@ -736,17 +777,17 @@ exports.XLazyDataTable = (0, react_1.forwardRef)(function (_a, ref) {
|
|
|
736
777
|
headers.push(column.props.header);
|
|
737
778
|
}
|
|
738
779
|
}
|
|
739
|
-
catch (
|
|
780
|
+
catch (e_8_1) { e_8 = { error: e_8_1 }; }
|
|
740
781
|
finally {
|
|
741
782
|
try {
|
|
742
783
|
if (columns_4_1 && !columns_4_1.done && (_a = columns_4.return)) _a.call(columns_4);
|
|
743
784
|
}
|
|
744
|
-
finally { if (
|
|
785
|
+
finally { if (e_8) throw e_8.error; }
|
|
745
786
|
}
|
|
746
787
|
return headers;
|
|
747
788
|
};
|
|
748
789
|
var getWidths = function () {
|
|
749
|
-
var
|
|
790
|
+
var e_9, _a;
|
|
750
791
|
var _b;
|
|
751
792
|
// vrati sirky stlpcov napr. ['7.75rem', '20rem', '8.5rem', '8.5rem', '6rem']
|
|
752
793
|
// nevracia aktualne sirky stlpcov (po manualnom rozsireni) ale tie ktore boli nastavene/vypocitane v kode
|
|
@@ -758,17 +799,17 @@ exports.XLazyDataTable = (0, react_1.forwardRef)(function (_a, ref) {
|
|
|
758
799
|
widths.push((_b = column.props.headerStyle) === null || _b === void 0 ? void 0 : _b.width);
|
|
759
800
|
}
|
|
760
801
|
}
|
|
761
|
-
catch (
|
|
802
|
+
catch (e_9_1) { e_9 = { error: e_9_1 }; }
|
|
762
803
|
finally {
|
|
763
804
|
try {
|
|
764
805
|
if (columns_5_1 && !columns_5_1.done && (_a = columns_5.return)) _a.call(columns_5);
|
|
765
806
|
}
|
|
766
|
-
finally { if (
|
|
807
|
+
finally { if (e_9) throw e_9.error; }
|
|
767
808
|
}
|
|
768
809
|
return widths;
|
|
769
810
|
};
|
|
770
811
|
var getFieldSetIds = function () {
|
|
771
|
-
var
|
|
812
|
+
var e_10, _a;
|
|
772
813
|
var fieldSetIds = [];
|
|
773
814
|
// warning note: props.children are used to get props of XLazyColumn whereas dataTableEl.current.props.children are used to get props of Primereact DataTable
|
|
774
815
|
var columns = props.children;
|
|
@@ -780,12 +821,12 @@ exports.XLazyDataTable = (0, react_1.forwardRef)(function (_a, ref) {
|
|
|
780
821
|
}
|
|
781
822
|
}
|
|
782
823
|
}
|
|
783
|
-
catch (
|
|
824
|
+
catch (e_10_1) { e_10 = { error: e_10_1 }; }
|
|
784
825
|
finally {
|
|
785
826
|
try {
|
|
786
827
|
if (columns_6_1 && !columns_6_1.done && (_a = columns_6.return)) _a.call(columns_6);
|
|
787
828
|
}
|
|
788
|
-
finally { if (
|
|
829
|
+
finally { if (e_10) throw e_10.error; }
|
|
789
830
|
}
|
|
790
831
|
return fieldSetIds;
|
|
791
832
|
};
|
|
@@ -870,7 +911,7 @@ exports.XLazyDataTable = (0, react_1.forwardRef)(function (_a, ref) {
|
|
|
870
911
|
setFormDialogState({ opened: false });
|
|
871
912
|
};
|
|
872
913
|
var onClickRemoveRow = function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
873
|
-
var reread_1,
|
|
914
|
+
var reread_1, e_11, e_12;
|
|
874
915
|
return __generator(this, function (_a) {
|
|
875
916
|
switch (_a.label) {
|
|
876
917
|
case 0:
|
|
@@ -885,8 +926,8 @@ exports.XLazyDataTable = (0, react_1.forwardRef)(function (_a, ref) {
|
|
|
885
926
|
reread_1 = _a.sent();
|
|
886
927
|
return [3 /*break*/, 4];
|
|
887
928
|
case 3:
|
|
888
|
-
|
|
889
|
-
XUtils_1.XUtils.showErrorMessage((0, XLocale_1.xLocaleOption)('removeRowFailed'),
|
|
929
|
+
e_11 = _a.sent();
|
|
930
|
+
XUtils_1.XUtils.showErrorMessage((0, XLocale_1.xLocaleOption)('removeRowFailed'), e_11);
|
|
890
931
|
return [3 /*break*/, 4];
|
|
891
932
|
case 4:
|
|
892
933
|
if (reread_1) {
|
|
@@ -908,8 +949,8 @@ exports.XLazyDataTable = (0, react_1.forwardRef)(function (_a, ref) {
|
|
|
908
949
|
_a.sent();
|
|
909
950
|
return [3 /*break*/, 9];
|
|
910
951
|
case 8:
|
|
911
|
-
|
|
912
|
-
XUtils_1.XUtils.showErrorMessage((0, XLocale_1.xLocaleOption)('removeRowFailed'),
|
|
952
|
+
e_12 = _a.sent();
|
|
953
|
+
XUtils_1.XUtils.showErrorMessage((0, XLocale_1.xLocaleOption)('removeRowFailed'), e_12);
|
|
913
954
|
return [3 /*break*/, 9];
|
|
914
955
|
case 9:
|
|
915
956
|
loadData();
|
|
@@ -927,39 +968,41 @@ exports.XLazyDataTable = (0, react_1.forwardRef)(function (_a, ref) {
|
|
|
927
968
|
}); };
|
|
928
969
|
var onClickAppButtonForRow = function (onClick) {
|
|
929
970
|
if (selectedRow !== null) {
|
|
930
|
-
onClick(selectedRow);
|
|
971
|
+
onClick(selectedRow, createFindParamUsingAfterFiltering());
|
|
931
972
|
}
|
|
932
973
|
else {
|
|
933
974
|
alert((0, XLocale_1.xLocaleOption)('pleaseSelectRow'));
|
|
934
975
|
}
|
|
935
976
|
};
|
|
936
977
|
var onClickExport = function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
937
|
-
var
|
|
978
|
+
var findParam, findResult, exportParams;
|
|
938
979
|
return __generator(this, function (_a) {
|
|
939
980
|
switch (_a.label) {
|
|
940
981
|
case 0:
|
|
941
|
-
|
|
942
|
-
findParam = {
|
|
943
|
-
resultType: FindParam_1.ResultType.OnlyRowCount,
|
|
944
|
-
first: first,
|
|
945
|
-
rows: rowsLocal,
|
|
946
|
-
filters: filtersAfterFiltering,
|
|
947
|
-
fullTextSearch: createXFullTextSearch(ftsInputValueAfterFiltering),
|
|
948
|
-
customFilterItems: createXCustomFilterItems(customFilterItems, optionalCustomFilterAfterFiltering),
|
|
949
|
-
multiSortMeta: multiSortMeta,
|
|
950
|
-
entity: props.entity,
|
|
951
|
-
fields: fields,
|
|
952
|
-
aggregateItems: aggregateItems
|
|
953
|
-
};
|
|
982
|
+
findParam = createFindParamUsingAfterFiltering();
|
|
954
983
|
return [4 /*yield*/, findByFilter(findParam)];
|
|
955
984
|
case 1:
|
|
956
985
|
findResult = _a.sent();
|
|
957
|
-
exportParams = createExportParams(
|
|
986
|
+
exportParams = createExportParams(getFields(false), findResult.totalRecords);
|
|
958
987
|
setExportRowsDialogState({ dialogOpened: true, exportParams: exportParams });
|
|
959
988
|
return [2 /*return*/];
|
|
960
989
|
}
|
|
961
990
|
});
|
|
962
991
|
}); };
|
|
992
|
+
var createFindParamUsingAfterFiltering = function () {
|
|
993
|
+
return {
|
|
994
|
+
resultType: FindParam_1.ResultType.OnlyRowCount,
|
|
995
|
+
first: first,
|
|
996
|
+
rows: rowsLocal,
|
|
997
|
+
filters: filtersAfterFiltering,
|
|
998
|
+
fullTextSearch: createXFullTextSearch(ftsInputValueAfterFiltering),
|
|
999
|
+
customFilterItems: createXCustomFilterItems(customFilterItems, optionalCustomFilterAfterFiltering),
|
|
1000
|
+
multiSortMeta: multiSortMeta,
|
|
1001
|
+
entity: props.entity,
|
|
1002
|
+
fields: getFields(false),
|
|
1003
|
+
aggregateItems: aggregateItems
|
|
1004
|
+
};
|
|
1005
|
+
};
|
|
963
1006
|
var createExportParams = function (fields, rowCount) {
|
|
964
1007
|
var queryParam = {
|
|
965
1008
|
filters: filtersAfterFiltering,
|
|
@@ -1146,6 +1189,9 @@ exports.XLazyDataTable = (0, react_1.forwardRef)(function (_a, ref) {
|
|
|
1146
1189
|
else {
|
|
1147
1190
|
bodyValue = valueAsUI(rowDataValue, xField, columnProps.contentType, columnProps.fieldSetId);
|
|
1148
1191
|
}
|
|
1192
|
+
if (columnProps.className || columnProps.style) {
|
|
1193
|
+
bodyValue = react_1.default.createElement("div", { className: columnProps.className, style: columnProps.style }, bodyValue);
|
|
1194
|
+
}
|
|
1149
1195
|
return bodyValue;
|
|
1150
1196
|
};
|
|
1151
1197
|
// in order that row expansion works like standard row, we wrap row expansion into div
|
package/lib/components/XUtils.js
CHANGED
|
@@ -582,7 +582,9 @@ var XUtils = exports.XUtils = /** @class */ (function () {
|
|
|
582
582
|
// if the length of field is 2 or more, then readOnly
|
|
583
583
|
isReadOnly = true;
|
|
584
584
|
}
|
|
585
|
-
// formReadOnlyBase is called on the level XFormDataTable2
|
|
585
|
+
// formReadOnlyBase is called on the level XFormDataTable2 and XFormPanelList
|
|
586
|
+
// the reason is (probably) that in XFormDataTable2 and XFormPanelList we know the assoc name whereas here in component we know only field name
|
|
587
|
+
// (assoc name is param of formReadOnlyBase)
|
|
586
588
|
// else if (this.props.form.formReadOnlyBase("xxx")) {
|
|
587
589
|
// isReadOnly = true;
|
|
588
590
|
// }
|