@gisce/react-ooui 2.0.0-alpha.54 → 2.0.0-alpha.55
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/helpers/treeHelper.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/react-ooui.es.js +3193 -3086
- package/dist/react-ooui.es.js.map +1 -1
- package/dist/ui/TitleHeader.d.ts.map +1 -1
- package/dist/widgets/views/{Tree.d.ts → Tree/Tree.d.ts} +4 -4
- package/dist/widgets/views/Tree/Tree.d.ts.map +1 -0
- package/dist/widgets/views/Tree/index.d.ts +2 -0
- package/dist/widgets/views/Tree/index.d.ts.map +1 -0
- package/dist/widgets/views/Tree/treeComponents.d.ts +131 -0
- package/dist/widgets/views/Tree/treeComponents.d.ts.map +1 -0
- package/package.json +2 -2
- package/src/helpers/{treeHelper.ts → treeHelper.tsx} +25 -4
- package/src/index.ts +1 -1
- package/src/ui/TitleHeader.tsx +10 -1
- package/src/widgets/views/Dashboard/DashboardTree.tsx +1 -1
- package/src/widgets/views/Graph/GraphDefaults.ts +1 -1
- package/src/widgets/views/SearchTree.tsx +2 -2
- package/src/widgets/views/Tree/Tree.tsx +298 -0
- package/src/widgets/views/Tree/index.ts +1 -0
- package/src/widgets/views/Tree/treeComponents.tsx +276 -0
- package/dist/widgets/views/Tree.d.ts.map +0 -1
- package/src/widgets/views/Tree.tsx +0 -450
|
@@ -1,450 +0,0 @@
|
|
|
1
|
-
import React, { useContext, useEffect, useRef, useState } from "react";
|
|
2
|
-
import { Pagination, Checkbox, Space, Row, Col, Spin, Tag, Badge } from "antd";
|
|
3
|
-
import {
|
|
4
|
-
getTree,
|
|
5
|
-
getTableColumns,
|
|
6
|
-
getTableItems,
|
|
7
|
-
hasActualValues,
|
|
8
|
-
} from "@/helpers/treeHelper";
|
|
9
|
-
import { Tree as TreeOoui } from "@gisce/ooui";
|
|
10
|
-
|
|
11
|
-
import { TreeView, Column } from "@/types";
|
|
12
|
-
import { LocaleContext, LocaleContextType } from "@/context/LocaleContext";
|
|
13
|
-
import { calculateColumnsWidth } from "@/helpers/dynamicColumnsHelper";
|
|
14
|
-
import { parseFloatToString } from "@/helpers/timeHelper";
|
|
15
|
-
import { ProgressBarInput } from "../base/ProgressBar";
|
|
16
|
-
import { Table as GisceTable } from "@gisce/react-formiga-table";
|
|
17
|
-
import {
|
|
18
|
-
PlusSquareOutlined,
|
|
19
|
-
MinusSquareOutlined,
|
|
20
|
-
LoadingOutlined,
|
|
21
|
-
} from "@ant-design/icons";
|
|
22
|
-
import { One2manyValue } from "../base/one2many/One2manyInput";
|
|
23
|
-
import { Interweave } from "interweave";
|
|
24
|
-
import {
|
|
25
|
-
ActionViewContext,
|
|
26
|
-
ActionViewContextType,
|
|
27
|
-
} from "@/context/ActionViewContext";
|
|
28
|
-
import { Many2oneTree } from "../base/many2one/Many2oneTree";
|
|
29
|
-
import { ReferenceTree } from "../base/ReferenceTree";
|
|
30
|
-
import dayjs from "dayjs";
|
|
31
|
-
import Avatar from "../custom/Avatar";
|
|
32
|
-
import { CustomTag, TagInput } from "../custom/Tag";
|
|
33
|
-
import { DatePickerConfig } from "@/common/DatePicker";
|
|
34
|
-
import { SelectAllRecordsRow } from "@/common/SelectAllRecordsRow";
|
|
35
|
-
import ConnectionProvider from "@/ConnectionProvider";
|
|
36
|
-
import { colorFromString } from "@/helpers/formHelper";
|
|
37
|
-
|
|
38
|
-
type Props = {
|
|
39
|
-
total?: number;
|
|
40
|
-
limit: number;
|
|
41
|
-
page?: number;
|
|
42
|
-
loading: boolean;
|
|
43
|
-
treeView: TreeView;
|
|
44
|
-
results: any[];
|
|
45
|
-
showPagination?: boolean;
|
|
46
|
-
onRequestPageChange?: (page: number, pageSize?: number) => void;
|
|
47
|
-
onRowClicked?: (record: any) => void;
|
|
48
|
-
rowSelection?: any;
|
|
49
|
-
scrollY?: number;
|
|
50
|
-
colorsForResults?: { [key: number]: string };
|
|
51
|
-
statusForResults?: { [key: number]: string };
|
|
52
|
-
onChangeSort?: (results: any) => void;
|
|
53
|
-
sorter?: any;
|
|
54
|
-
onFetchChildrenForRecord?: (item: any) => Promise<any[]>;
|
|
55
|
-
childField?: string;
|
|
56
|
-
rootTree?: boolean;
|
|
57
|
-
context?: any;
|
|
58
|
-
readonly?: boolean;
|
|
59
|
-
onSelectAllRecords?: () => Promise<void>;
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
const booleanComponentFn = (value: boolean): React.ReactElement => {
|
|
63
|
-
return (
|
|
64
|
-
<div
|
|
65
|
-
style={{
|
|
66
|
-
display: "flex",
|
|
67
|
-
justifyContent: "center",
|
|
68
|
-
alignContent: "center",
|
|
69
|
-
}}
|
|
70
|
-
>
|
|
71
|
-
<Checkbox checked={value} disabled />
|
|
72
|
-
</div>
|
|
73
|
-
);
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
const many2OneComponentFn = (m2oField: any): React.ReactElement => {
|
|
77
|
-
return <Many2oneTree m2oField={m2oField} />;
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
const textComponentFn = (value: any): React.ReactElement => {
|
|
81
|
-
return (
|
|
82
|
-
<Interweave
|
|
83
|
-
content={value?.toString().replace(/(?:\r\n|\r|\n)/g, "<br>")}
|
|
84
|
-
/>
|
|
85
|
-
);
|
|
86
|
-
};
|
|
87
|
-
|
|
88
|
-
const dateComponentFn = (value: any): React.ReactElement => {
|
|
89
|
-
if (!value || (value && value.length === 0)) return <></>;
|
|
90
|
-
|
|
91
|
-
const formattedValue = dayjs(
|
|
92
|
-
value,
|
|
93
|
-
DatePickerConfig.date.dateInternalFormat,
|
|
94
|
-
).format(DatePickerConfig.date.dateDisplayFormat);
|
|
95
|
-
return <>{formattedValue}</>;
|
|
96
|
-
};
|
|
97
|
-
|
|
98
|
-
const dateTimeComponentFn = (value: any): React.ReactElement => {
|
|
99
|
-
if (!value || (value && value.length === 0)) return <></>;
|
|
100
|
-
const formattedValue = dayjs(
|
|
101
|
-
value,
|
|
102
|
-
DatePickerConfig.time.dateInternalFormat,
|
|
103
|
-
).format(DatePickerConfig.time.dateDisplayFormat);
|
|
104
|
-
return <>{formattedValue}</>;
|
|
105
|
-
};
|
|
106
|
-
|
|
107
|
-
const one2ManyComponentFn = (value: One2manyValue): React.ReactElement => {
|
|
108
|
-
const length = Array.isArray(value?.items) ? value?.items.length : 0;
|
|
109
|
-
return <>{`( ${length} )`}</>;
|
|
110
|
-
};
|
|
111
|
-
|
|
112
|
-
const progressBarComponentFn = (value: any): React.ReactElement => {
|
|
113
|
-
return <ProgressBarInput value={value} />;
|
|
114
|
-
};
|
|
115
|
-
|
|
116
|
-
const floatTimeComponent = (value: number): React.ReactElement => {
|
|
117
|
-
return <>{parseFloatToString(value)}</>;
|
|
118
|
-
};
|
|
119
|
-
|
|
120
|
-
const numberComponent = (value: number): React.ReactElement => {
|
|
121
|
-
return <div style={{ textAlign: "right" }}>{value}</div>;
|
|
122
|
-
};
|
|
123
|
-
|
|
124
|
-
const imageComponent = (value: string): React.ReactElement => {
|
|
125
|
-
return (
|
|
126
|
-
<img
|
|
127
|
-
src={`data:image/*;base64,${value}`}
|
|
128
|
-
style={{ maxWidth: "50px", padding: "5px" }}
|
|
129
|
-
/>
|
|
130
|
-
);
|
|
131
|
-
};
|
|
132
|
-
|
|
133
|
-
const TagComponent = (
|
|
134
|
-
value: any,
|
|
135
|
-
key: string,
|
|
136
|
-
ooui: any,
|
|
137
|
-
context: any,
|
|
138
|
-
): React.ReactElement => {
|
|
139
|
-
return <TagInput ooui={ooui} value={value} />;
|
|
140
|
-
};
|
|
141
|
-
|
|
142
|
-
const TagsComponent = (
|
|
143
|
-
value: any,
|
|
144
|
-
key: string,
|
|
145
|
-
ooui: any,
|
|
146
|
-
context: any,
|
|
147
|
-
): React.ReactElement => {
|
|
148
|
-
const [values, setValues] = useState<string[]>([]);
|
|
149
|
-
const { relation, field } = ooui;
|
|
150
|
-
useEffect(() => {
|
|
151
|
-
const loadValues = async () => {
|
|
152
|
-
try {
|
|
153
|
-
const optionsRead = await ConnectionProvider.getHandler().search({
|
|
154
|
-
model: relation,
|
|
155
|
-
params: [["id", "in", value.items.map((v: any) => v.id)]],
|
|
156
|
-
fields: [field],
|
|
157
|
-
context,
|
|
158
|
-
});
|
|
159
|
-
setValues(optionsRead.map((i: any) => i.name));
|
|
160
|
-
} catch (error) {
|
|
161
|
-
console.log("Error loading data", error);
|
|
162
|
-
}
|
|
163
|
-
};
|
|
164
|
-
if (value) {
|
|
165
|
-
loadValues();
|
|
166
|
-
}
|
|
167
|
-
}, []);
|
|
168
|
-
const tags = values.map((v) => {
|
|
169
|
-
const color = colorFromString(v);
|
|
170
|
-
return <CustomTag color={color}>{v}</CustomTag>;
|
|
171
|
-
});
|
|
172
|
-
return (
|
|
173
|
-
<div style={{ maxWidth: "300px", whiteSpace: "break-spaces" }}>{tags}</div>
|
|
174
|
-
);
|
|
175
|
-
};
|
|
176
|
-
|
|
177
|
-
const SelectionComponent = (
|
|
178
|
-
value: any,
|
|
179
|
-
key: string,
|
|
180
|
-
ooui: any,
|
|
181
|
-
context: any,
|
|
182
|
-
): React.ReactElement => {
|
|
183
|
-
return <>{ooui.selectionValues.get(value)}</>;
|
|
184
|
-
};
|
|
185
|
-
|
|
186
|
-
const referenceComponent = (
|
|
187
|
-
value: any,
|
|
188
|
-
key: string,
|
|
189
|
-
ooui: any,
|
|
190
|
-
context: any,
|
|
191
|
-
): React.ReactElement => {
|
|
192
|
-
return (
|
|
193
|
-
<>
|
|
194
|
-
<ReferenceTree
|
|
195
|
-
value={value}
|
|
196
|
-
selectionValues={ooui.selectionValues}
|
|
197
|
-
context={context}
|
|
198
|
-
/>
|
|
199
|
-
</>
|
|
200
|
-
);
|
|
201
|
-
};
|
|
202
|
-
|
|
203
|
-
const AvatarFn = (
|
|
204
|
-
value: any,
|
|
205
|
-
key: string,
|
|
206
|
-
ooui: any,
|
|
207
|
-
context: any,
|
|
208
|
-
): React.ReactElement => <Avatar ooui={ooui} value={value} />;
|
|
209
|
-
|
|
210
|
-
function Tree(props: Props): React.ReactElement {
|
|
211
|
-
const {
|
|
212
|
-
page = 1,
|
|
213
|
-
limit,
|
|
214
|
-
total,
|
|
215
|
-
treeView,
|
|
216
|
-
results,
|
|
217
|
-
onRequestPageChange,
|
|
218
|
-
loading,
|
|
219
|
-
onRowClicked,
|
|
220
|
-
showPagination = true,
|
|
221
|
-
rowSelection,
|
|
222
|
-
scrollY,
|
|
223
|
-
colorsForResults = {},
|
|
224
|
-
statusForResults = {},
|
|
225
|
-
onChangeSort,
|
|
226
|
-
sorter,
|
|
227
|
-
onFetchChildrenForRecord,
|
|
228
|
-
childField,
|
|
229
|
-
rootTree = false,
|
|
230
|
-
context,
|
|
231
|
-
readonly,
|
|
232
|
-
onSelectAllRecords,
|
|
233
|
-
} = props;
|
|
234
|
-
|
|
235
|
-
const [items, setItems] = useState<any[]>([]);
|
|
236
|
-
const [columns, setColumns] = useState<Column[]>([]);
|
|
237
|
-
|
|
238
|
-
const errorInParseColors = useRef<boolean>(false);
|
|
239
|
-
|
|
240
|
-
const treeOoui = useRef<any>(null);
|
|
241
|
-
|
|
242
|
-
const { t } = useContext(LocaleContext) as LocaleContextType;
|
|
243
|
-
const internalLimit = useRef(limit);
|
|
244
|
-
|
|
245
|
-
const actionViewContext = useContext(
|
|
246
|
-
ActionViewContext,
|
|
247
|
-
) as ActionViewContextType;
|
|
248
|
-
const { title = undefined, setTitle = undefined } =
|
|
249
|
-
(rootTree ? actionViewContext : {}) || {};
|
|
250
|
-
|
|
251
|
-
useEffect(() => {
|
|
252
|
-
treeOoui.current = getTree(treeView);
|
|
253
|
-
|
|
254
|
-
const columns = getTableColumns(
|
|
255
|
-
treeOoui.current,
|
|
256
|
-
{
|
|
257
|
-
boolean: booleanComponentFn,
|
|
258
|
-
many2one: many2OneComponentFn,
|
|
259
|
-
text: textComponentFn,
|
|
260
|
-
one2many: one2ManyComponentFn,
|
|
261
|
-
many2many: one2ManyComponentFn,
|
|
262
|
-
progressbar: progressBarComponentFn,
|
|
263
|
-
float_time: floatTimeComponent,
|
|
264
|
-
image: imageComponent,
|
|
265
|
-
integer: numberComponent,
|
|
266
|
-
float: numberComponent,
|
|
267
|
-
reference: referenceComponent,
|
|
268
|
-
tag: TagComponent,
|
|
269
|
-
selection: SelectionComponent,
|
|
270
|
-
date: dateComponentFn,
|
|
271
|
-
datetime: dateTimeComponentFn,
|
|
272
|
-
avatar: AvatarFn,
|
|
273
|
-
tags: TagsComponent,
|
|
274
|
-
},
|
|
275
|
-
context,
|
|
276
|
-
);
|
|
277
|
-
|
|
278
|
-
setColumns(columns);
|
|
279
|
-
|
|
280
|
-
if (treeOoui.current.string && title !== treeOoui.current.string) {
|
|
281
|
-
setTitle?.(treeOoui.current.string);
|
|
282
|
-
}
|
|
283
|
-
}, [treeView]);
|
|
284
|
-
|
|
285
|
-
useEffect(() => {
|
|
286
|
-
errorInParseColors.current = false;
|
|
287
|
-
const items = getTableItems(treeOoui.current, results);
|
|
288
|
-
setItems(items);
|
|
289
|
-
internalLimit.current = limit;
|
|
290
|
-
}, [results]);
|
|
291
|
-
|
|
292
|
-
const from = (page - 1) * internalLimit.current + 1;
|
|
293
|
-
const to = from - 1 + items.length;
|
|
294
|
-
const summary =
|
|
295
|
-
total === undefined
|
|
296
|
-
? null
|
|
297
|
-
: total === 0
|
|
298
|
-
? t("no_results")
|
|
299
|
-
: t("summary")
|
|
300
|
-
.replace("{from}", from?.toString())
|
|
301
|
-
.replace("{to}", to?.toString())
|
|
302
|
-
.replace("{total}", total?.toString());
|
|
303
|
-
|
|
304
|
-
const pagination = () => {
|
|
305
|
-
if (!showPagination || treeView.isExpandable) {
|
|
306
|
-
return null;
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
const numberOfVisibleSelectedRows = items?.filter(
|
|
310
|
-
(entry) =>
|
|
311
|
-
rowSelection?.selectedRowKeys &&
|
|
312
|
-
rowSelection?.selectedRowKeys.includes(entry.id),
|
|
313
|
-
).length;
|
|
314
|
-
|
|
315
|
-
return loading ? null : total === undefined ? (
|
|
316
|
-
<Spin className="pb-4" />
|
|
317
|
-
) : (
|
|
318
|
-
<Row align="bottom" className="pb-4">
|
|
319
|
-
<Col span={onSelectAllRecords ? 8 : 12}>
|
|
320
|
-
<Pagination
|
|
321
|
-
total={total}
|
|
322
|
-
pageSize={
|
|
323
|
-
internalLimit.current === 0 ? total : internalLimit.current
|
|
324
|
-
}
|
|
325
|
-
current={page}
|
|
326
|
-
showSizeChanger={false}
|
|
327
|
-
onChange={onRequestPageChange}
|
|
328
|
-
/>
|
|
329
|
-
</Col>
|
|
330
|
-
{onSelectAllRecords && (
|
|
331
|
-
<Col span={8} className="text-center">
|
|
332
|
-
<SelectAllRecordsRow
|
|
333
|
-
numberOfVisibleSelectedRows={numberOfVisibleSelectedRows}
|
|
334
|
-
numberOfRealSelectedRows={
|
|
335
|
-
rowSelection?.selectedRowKeys?.length || 0
|
|
336
|
-
}
|
|
337
|
-
numberOfTotalRows={items.length}
|
|
338
|
-
totalRecords={total || 0}
|
|
339
|
-
onSelectAllRecords={onSelectAllRecords}
|
|
340
|
-
/>
|
|
341
|
-
</Col>
|
|
342
|
-
)}
|
|
343
|
-
<Col span={onSelectAllRecords ? 8 : 12} className="text-right">
|
|
344
|
-
{summary}
|
|
345
|
-
</Col>
|
|
346
|
-
</Row>
|
|
347
|
-
);
|
|
348
|
-
};
|
|
349
|
-
|
|
350
|
-
function getSums() {
|
|
351
|
-
const tree = treeOoui.current as TreeOoui;
|
|
352
|
-
|
|
353
|
-
const sumFields = tree.columns
|
|
354
|
-
.filter((it) => it.sum !== undefined)
|
|
355
|
-
.map((it) => {
|
|
356
|
-
return { label: it.sum, field: it.id };
|
|
357
|
-
});
|
|
358
|
-
|
|
359
|
-
if (!sumFields || sumFields.length === 0) {
|
|
360
|
-
return null;
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
const summary: string[] = [];
|
|
364
|
-
const sumItems =
|
|
365
|
-
rowSelection?.selectedRowKeys?.length > 0
|
|
366
|
-
? items.filter((result: any) => {
|
|
367
|
-
return rowSelection?.selectedRowKeys.includes(result.id);
|
|
368
|
-
})
|
|
369
|
-
: items;
|
|
370
|
-
|
|
371
|
-
sumFields.forEach((sumField) => {
|
|
372
|
-
const total = sumItems.reduce((prev, current) => {
|
|
373
|
-
if (current[sumField.field] && !isNaN(current[sumField.field]))
|
|
374
|
-
return prev + current[sumField.field];
|
|
375
|
-
else return prev;
|
|
376
|
-
}, 0);
|
|
377
|
-
|
|
378
|
-
summary.push(`${sumField.label}: ${Math.round(total * 100) / 100}`);
|
|
379
|
-
});
|
|
380
|
-
|
|
381
|
-
return <div className="p-1 pb-0 pl-2 mt-2 ">{summary.join(", ")}</div>;
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
let dataTable;
|
|
385
|
-
let adjustedHeight = scrollY;
|
|
386
|
-
|
|
387
|
-
// This helper function helps to calculate the width for each column
|
|
388
|
-
// based on all table cells - column cell and source cell
|
|
389
|
-
if (treeOoui.current !== null) {
|
|
390
|
-
const maxWidthPerCell = 600;
|
|
391
|
-
dataTable = calculateColumnsWidth(columns, items, maxWidthPerCell);
|
|
392
|
-
const tree = treeOoui.current as TreeOoui;
|
|
393
|
-
|
|
394
|
-
if (scrollY && tree.columns.some((it) => it.sum !== undefined)) {
|
|
395
|
-
adjustedHeight = scrollY - 30;
|
|
396
|
-
}
|
|
397
|
-
}
|
|
398
|
-
return treeOoui.current === null ||
|
|
399
|
-
!dataTable ||
|
|
400
|
-
dataTable.columns?.length === 0 ? (
|
|
401
|
-
<Spin style={{ padding: "2rem" }} />
|
|
402
|
-
) : (
|
|
403
|
-
<div>
|
|
404
|
-
{pagination()}
|
|
405
|
-
<GisceTable
|
|
406
|
-
height={adjustedHeight!}
|
|
407
|
-
columns={dataTable.columns}
|
|
408
|
-
dataSource={items}
|
|
409
|
-
loading={loading}
|
|
410
|
-
loadingComponent={<Spin />}
|
|
411
|
-
onRowStyle={(record: any) => {
|
|
412
|
-
if (colorsForResults![record.id]) {
|
|
413
|
-
return { color: colorsForResults![record.id] };
|
|
414
|
-
}
|
|
415
|
-
return undefined;
|
|
416
|
-
}}
|
|
417
|
-
onRowStatus={
|
|
418
|
-
hasActualValues(statusForResults)
|
|
419
|
-
? (record: any) => {
|
|
420
|
-
if (statusForResults![record.id]) {
|
|
421
|
-
return <Badge color={statusForResults[record.id]} />;
|
|
422
|
-
}
|
|
423
|
-
return undefined;
|
|
424
|
-
}
|
|
425
|
-
: undefined
|
|
426
|
-
}
|
|
427
|
-
onRowDoubleClick={onRowClicked}
|
|
428
|
-
selectionRowKeys={rowSelection?.selectedRowKeys}
|
|
429
|
-
onRowSelectionChange={rowSelection?.onChange}
|
|
430
|
-
onChangeSort={onChangeSort}
|
|
431
|
-
sorter={sorter}
|
|
432
|
-
readonly={readonly}
|
|
433
|
-
expandableOpts={
|
|
434
|
-
onFetchChildrenForRecord
|
|
435
|
-
? {
|
|
436
|
-
expandIcon: PlusSquareOutlined,
|
|
437
|
-
collapseIcon: MinusSquareOutlined,
|
|
438
|
-
loadingIcon: LoadingOutlined,
|
|
439
|
-
onFetchChildrenForRecord,
|
|
440
|
-
childField: childField!,
|
|
441
|
-
}
|
|
442
|
-
: undefined
|
|
443
|
-
}
|
|
444
|
-
/>
|
|
445
|
-
{getSums()}
|
|
446
|
-
</div>
|
|
447
|
-
);
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
export default Tree;
|