@gisce/react-ooui 2.0.0-alpha.54 → 2.0.0-alpha.56

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.
Files changed (30) hide show
  1. package/dist/helpers/treeHelper.d.ts.map +1 -1
  2. package/dist/index.d.ts +1 -1
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/react-ooui.es.js +3248 -3144
  5. package/dist/react-ooui.es.js.map +1 -1
  6. package/dist/ui/TitleHeader.d.ts.map +1 -1
  7. package/dist/widgets/base/one2many/One2manyInput.d.ts.map +1 -1
  8. package/dist/widgets/modals/SearchModal.d.ts.map +1 -1
  9. package/dist/widgets/views/Dashboard/DashboardTree.d.ts.map +1 -1
  10. package/dist/widgets/views/SearchTree.d.ts.map +1 -1
  11. package/dist/widgets/views/{Tree.d.ts → Tree/Tree.d.ts} +6 -5
  12. package/dist/widgets/views/Tree/Tree.d.ts.map +1 -0
  13. package/dist/widgets/views/Tree/index.d.ts +2 -0
  14. package/dist/widgets/views/Tree/index.d.ts.map +1 -0
  15. package/dist/widgets/views/Tree/treeComponents.d.ts +131 -0
  16. package/dist/widgets/views/Tree/treeComponents.d.ts.map +1 -0
  17. package/package.json +2 -2
  18. package/src/helpers/{treeHelper.ts → treeHelper.tsx} +25 -4
  19. package/src/index.ts +1 -1
  20. package/src/ui/TitleHeader.tsx +10 -1
  21. package/src/widgets/base/one2many/One2manyInput.tsx +5 -4
  22. package/src/widgets/modals/SearchModal.tsx +2 -4
  23. package/src/widgets/views/Dashboard/DashboardTree.tsx +3 -1
  24. package/src/widgets/views/Graph/GraphDefaults.ts +1 -1
  25. package/src/widgets/views/SearchTree.tsx +21 -11
  26. package/src/widgets/views/Tree/Tree.tsx +295 -0
  27. package/src/widgets/views/Tree/index.ts +1 -0
  28. package/src/widgets/views/Tree/treeComponents.tsx +276 -0
  29. package/dist/widgets/views/Tree.d.ts.map +0 -1
  30. 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;