react-graph-grid 0.0.2 → 0.0.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/README.md CHANGED
@@ -1,3 +1,132 @@
1
1
  # react-graph-grid
2
2
 
3
- A React package containing a grid that can communicate with other grids through a connection graph
3
+ A React package containing a grid that can communicate with other grids through a connection graph
4
+
5
+ For all questions, please contact rmb@mail.ru
6
+
7
+ Installation
8
+
9
+ npm install react-grpah-grid
10
+
11
+
12
+ Example
13
+
14
+ import { GridFE } from '../../node_modules/react-graph-grid/src/GridFE';
15
+ import TestData from '../../node_modules/react-graph-grid/src/Tests/TestData';
16
+
17
+ ...
18
+
19
+ /*
20
+ * assuming the API returns something like this:
21
+ * const rows = [
22
+ * {
23
+ * Id: 1,
24
+ * Name: 'Mikle',
25
+ * SecondName: 'Razumtsev',
26
+ * Date: '26/01/1979'
27
+ * Comment: 'Me',
28
+ * Hometown: 'Voronezh',
29
+ * HometownId: 1,
30
+ * },
31
+ * {
32
+ * Id: 2,
33
+ * Name: 'Boris',
34
+ * SecondName: 'Razumtsev',
35
+ * Date: '14/06/1953'
36
+ * Comment: 'Father',
37
+ * Hometown: 'Grafskaya',
38
+ * HometownId: 2,
39
+ * },
40
+ * {
41
+ * Id: 3,
42
+ * Name: 'Ilia',
43
+ * SecondName: 'Razumtsev',
44
+ * Date: '16/09/1980'
45
+ * Comment: 'Brother',
46
+ * Hometown: 'Pskov',
47
+ * HometownId: 4,
48
+ * },
49
+ * ]
50
+ *
51
+ *
52
+ * e.params = [
53
+ * { key: 'pageSize', value: 10 },
54
+ * { key: 'pageNumber', value: 1 }
55
+ * ]
56
+ *
57
+ */
58
+
59
+ function loadRows(e) {
60
+ return new Promise(function (resolve, reject) {
61
+ const fetchParams = {
62
+ mode: 'cors',
63
+ method: 'post',
64
+ headers: {
65
+ 'Content-Type': 'application/json'
66
+ },
67
+ body: JSON.stringify(e.params)
68
+ };
69
+
70
+ fetch(`/awesome-api-url/`, fetchParams).then(
71
+ (response) => {
72
+ resolve(response.json());
73
+ }
74
+ )
75
+ .catch(error => {
76
+ reject(error);
77
+ });
78
+ });
79
+ };
80
+
81
+ function loadColumns() {
82
+ return [
83
+ { name: 'Id', sortable: true, filtrable: true },
84
+ { name: 'Name', sortable: true, filtrable: true },
85
+ { name: 'SecondName', sortable: true, filtrable: true },
86
+ { name: 'Date', sortable: true },
87
+ { name: 'Comment', sortable: true, filtrable: true },
88
+ { name: 'HometownId', visible: false },
89
+ {
90
+ name: 'Hometown',
91
+ sortable: true,
92
+ filtrable: true,
93
+ type: 'lookup',
94
+ keyField: 'HometownId',
95
+ refKeyField: 'Id',
96
+ refNameField: 'City',
97
+ getRows: (e) => {
98
+ return new Promise(function (resolve, reject) {
99
+
100
+ const rows = new TestData().getCity(e);
101
+
102
+ if (rows != null) {
103
+ resolve(rows);
104
+ } else {
105
+ reject(Error("Error getting rows"));
106
+ }
107
+ });
108
+ }
109
+ },
110
+ ]
111
+ };
112
+
113
+
114
+ <GridFE
115
+ getRows={loadRows}
116
+ getColumns={loadColumns}
117
+ allowEditGrid={true}
118
+ />
119
+
120
+
121
+ Some grid properties
122
+
123
+ uid - grid uid
124
+ parentGrids - parent grids uids
125
+ buttons - buttons array [{ id: 1, name: 'commit', title: 'Commit changes', label: 'Commit', img: Images.commit, click: (e) => grid.commitChanges(e), getDisabled: (e) => grid.commitChangesDisabled(e) }, ... ]
126
+ multi - rows multiselect through a pocket
127
+ renderCell - custom render grid cell
128
+ getDefaultLinkContent - returns an object containing a data using when child grid responds to the parent grid active record
129
+ pageSize - grid page size
130
+
131
+
132
+ For more examples see DebugApp.jsx
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "author": "Mikhail Razumtsev",
4
4
  "description": "A React package containing a grid that can communicate with other grids through a connection graph",
5
5
  "private": false,
6
- "version": "0.0.2",
6
+ "version": "0.0.4",
7
7
  "type": "module",
8
8
  "scripts": {
9
9
  "dev": "vite --port 4000",
package/src/Grid.jsx CHANGED
@@ -90,7 +90,7 @@ export class GridClass extends BaseComponent {
90
90
  grid.renderCell = props.renderCell;
91
91
  }
92
92
 
93
- grid.dateFormat = props.dateFormat || 'dd.MM.yyyy';//'DD.MM.YYYY';
93
+ grid.dateFormat = props.dateFormat || 'dd.MM.yyyy';
94
94
  grid.dateTimeFormat = props.dateTimeFormat || 'dd.MM.yyyy HH:mm:ss';
95
95
 
96
96
  grid.rows = [];
@@ -289,6 +289,7 @@ export class GridClass extends BaseComponent {
289
289
  gridTemplateRows: '1.5em auto',
290
290
  gridAutoFlow: 'row',
291
291
  width: 'calc(100% + 8px)',
292
+ justifyContent: 'space-between',
292
293
  }}
293
294
  >
294
295
  {grid.renderHeaderCell(col, context)}
@@ -498,7 +499,8 @@ export class GridClass extends BaseComponent {
498
499
  for (let col of grid.columns) {
499
500
  col.id = id++;
500
501
  col.title = col.title || col.name;
501
- col.w = col.initW = col.w || 100;
502
+ col.w = col.w || 100;
503
+ col.initW = col.initW || 100;
502
504
  col.minW = col.minW || 50;
503
505
  col.grid = grid;
504
506
  grid.colDict[col.id] = grid.colDict[col.name] = grid.colDict[col.name.toLowerCase()] = col;
package/src/GridDB.jsx CHANGED
@@ -151,7 +151,12 @@ export class GridDBClass extends GridPKClass {
151
151
  {grid.renderPager()}
152
152
  {super.render()}
153
153
  {grid.renderPager(true)}
154
- <Dropdown init={(dd) => { grid.menuDropdown = dd; }} getItems={(e) => { return grid.getGridSettings(e); }} onItemClick={(e) => { grid.onSettingsItemClick(e.itemId); }}></Dropdown>
154
+ <Dropdown
155
+ init={(dd) => { grid.menuDropdown = dd; }}
156
+ closeWhenMiss={true}
157
+ getItems={(e) => { return grid.getGridSettings(e); }}
158
+ onItemClick={(e) => { grid.onSettingsItemClick(e.itemId); }}>
159
+ </Dropdown>
155
160
  </>
156
161
  )
157
162
  }
@@ -607,7 +612,7 @@ export class GridDBClass extends GridPKClass {
607
612
  }
608
613
  // -------------------------------------------------------------------------------------------------------------------------------------------------------------
609
614
  getHeaderGridTemplateColumns(col) {
610
- return col.sortInd == null ? 'auto 8px' : 'auto 22px';
615
+ return col.sortInd == null ? 'auto 12px' : 'auto 22px';
611
616
  }
612
617
  // -------------------------------------------------------------------------------------------------------------------------------------------------------------
613
618
  renderHeaderCell(col, context) {
@@ -774,12 +779,20 @@ export class GridDBClass extends GridPKClass {
774
779
  resetColumnsSort() {
775
780
  const grid = this;
776
781
  grid._sortString = '';
782
+ let needRefresh = false;
777
783
  for (let col of grid.columns) {
784
+ needRefresh = needRefresh || col.asc != false || col.desc != false;
785
+
778
786
  delete col.asc;
779
787
  delete col.desc;
780
788
  delete col.sortInd;
781
789
  }
782
- grid.refresh();
790
+ if (needRefresh) {
791
+ grid.refresh();
792
+ }
793
+ else {
794
+ grid.refreshState();
795
+ }
783
796
  }
784
797
  // -------------------------------------------------------------------------------------------------------------------------------------------------------------
785
798
  changeColumnSortOrder(column, e) {
package/src/GridFE.jsx CHANGED
@@ -506,4 +506,78 @@ export class GridFEClass extends GridFLClass {
506
506
  });
507
507
  }
508
508
  // -------------------------------------------------------------------------------------------------------------------------------------------------------------
509
+ getGridSettingsList() {
510
+ const res = super.getGridSettingsList();
511
+
512
+ const grid = this;
513
+ if (!grid.exportDisabled) {
514
+ res.push({ id: 4, text: grid.translate('Export to CSV', 'grid-menu') });
515
+ }
516
+
517
+ return res;
518
+ }
519
+ // -------------------------------------------------------------------------------------------------------------------------------------------------------------
520
+ onSettingsItemClick(itemId) {
521
+ super.onSettingsItemClick(itemId);
522
+ const grid = this;
523
+
524
+ switch (String(itemId)) {
525
+ case '4':
526
+ grid.exportToCSV();
527
+
528
+ grid.refreshState();
529
+ break;
530
+ default:
531
+ }
532
+ }
533
+ // -------------------------------------------------------------------------------------------------------------------------------------------------------------
534
+ exportToCSV(filename, delimeter) {
535
+ const grid = this;
536
+
537
+ if (filename == null || filename == '') {
538
+ const date = new Date();
539
+ filename = `exportCSV_${date.getDate()}_${date.getMonth()}_${date.getFullYear()}_${date.getTime()}_`;
540
+ };
541
+
542
+ delimeter = delimeter || ';';
543
+
544
+ let titles = [];
545
+ for (let col of grid.columns) {
546
+ if (col.visible == false) continue;
547
+ titles.push(col.title || col.name);
548
+ }
549
+
550
+ // 1. Преобразование данных в CSV строку
551
+ const csvContent = "\uFEFF" + // Добавляем BOM для корректного отображения кириллицы в Excel
552
+ [
553
+ titles.join(delimeter), // Заголовки
554
+ ...grid.rows.map(item => {
555
+
556
+ let values = [];
557
+ for (let col of grid.columns) {
558
+ if (col.visible == false) continue;
559
+ values.push(item[col.name]);
560
+ }
561
+ return values.join(delimeter);
562
+
563
+ //return Object.values(item).join(delimeter);
564
+ }) // Строки данных
565
+ ].join("\n");
566
+
567
+ // 2. Создание Blob
568
+ const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
569
+
570
+ // 3. Создание ссылки и скачивание
571
+ const link = document.createElement("a");
572
+ if (link.download !== undefined) {
573
+ const url = URL.createObjectURL(blob);
574
+ link.setAttribute("href", url);
575
+ link.setAttribute("download", filename);
576
+ link.style.visibility = 'hidden';
577
+ document.body.appendChild(link);
578
+ link.click();
579
+ document.body.removeChild(link);
580
+ }
581
+ }
582
+ // -------------------------------------------------------------------------------------------------------------------------------------------------------------
509
583
  }
package/src/GridFL.jsx CHANGED
@@ -79,6 +79,7 @@ export class GridFLClass extends GridDBClass {
79
79
  <Dropdown
80
80
  getItems={(e) => { return grid.getAutocomleteItems(e); }}
81
81
  onItemClick={(e) => { grid.onAutocomleteItemClick(e); }}
82
+ closeWhenMiss={true}
82
83
  init={(dd) => {
83
84
  if (grid._autocompleteDropdown) {
84
85
  dd.visible = grid._autocompleteDropdown.visible;
@@ -411,7 +412,7 @@ export class GridFLClass extends GridDBClass {
411
412
  }
412
413
  // -------------------------------------------------------------------------------------------------------------------------------------------------------------
413
414
  getHeaderGridTemplateColumns(col) {
414
- return col.sortInd == null /*&& (col.filter == null || col.filter === '')*/ ? 'auto 18px' : 'auto 22px';
415
+ return col.sortInd == null ? 'auto 12px' : 'auto 22px';
415
416
  }
416
417
  // -------------------------------------------------------------------------------------------------------------------------------------------------------------
417
418
  getGridSettingsList() {
package/src/Modal.jsx CHANGED
@@ -54,7 +54,8 @@ export class ModalClass extends BaseComponent {
54
54
 
55
55
  wnd.opt.closeWhenClick = props.closeWhenClick;
56
56
  wnd.opt.closeWhenEscape = props.closeWhenEscape;
57
- wnd.opt.closeWhenMiss = (props.closeWhenMiss || !props.closeWhenMouseLeave) && wnd.opt.isModal;
57
+ wnd.opt.closeWhenMiss = props.closeWhenMiss && wnd.opt.isModal;
58
+ //wnd.opt.closeWhenMiss = (props.closeWhenMiss || props.closeWhenMouseLeave == false) && wnd.opt.isModal;
58
59
  wnd.opt.closeWhenMouseLeave = props.closeWhenMouseLeave;
59
60
 
60
61
  wnd.opt.onMouseEnter = props.onMouseEnter;
@@ -306,12 +307,14 @@ export class ModalClass extends BaseComponent {
306
307
  // -------------------------------------------------------------------------------------------------------------------------------------------------------------
307
308
  close() {
308
309
  const wnd = this;
309
- wnd.visible = false;
310
310
 
311
311
  if (wnd.onClose) {
312
- wnd.onClose();
312
+ const ev = {};
313
+ wnd.onClose(ev);
314
+ if (ev.cancel) return;
313
315
  }
314
316
 
317
+ wnd.visible = false;
315
318
  wnd.refreshState();
316
319
  }
317
320
  // -------------------------------------------------------------------------------------------------------------------------------------------------------------
@@ -10,7 +10,7 @@ export default class TestData {
10
10
 
11
11
  const family = [
12
12
  { Id: 1, ParentId: [3, 4], Name: 'Mikle', SecondName: 'Razumtsev', Date: '26/01/1979', Comment: 'Good boy', Hometown: 'Voronezh', HometownId: 1 },
13
- { Id: 2, ParentId: [0], Name: 'Nataly', SecondName: 'Sche..', Date: '15/01/1999', Comment: 'Good girl', Hometown: 'Hanty-Mansiysk', HometownId: 12 },
13
+ { Id: 2, ParentId: [0], Name: 'Nataly', SecondName: 'Sche..', Date: '14/01/1999', Comment: 'Good girl', Hometown: 'Hanty-Mansiysk', HometownId: 12 },
14
14
  { Id: 3, ParentId: [11, 23], Name: 'Lyuda', SecondName: 'Razumtseva', Date: '03/07/1953', Comment: 'Mommy', Hometown: 'Novosibirsk', HometownId: 8 },
15
15
  { Id: 4, ParentId: [5, 22], Name: 'Borya', SecondName: 'Razumtsev', Date: '14/06/1953', Comment: 'Papa', Hometown: 'Grafskaya', HometownId: 2 },
16
16
  { Id: 5, ParentId: [0], Name: 'Nina', SecondName: 'Razumtseva', Date: '17/06/1917', Comment: 'Babushka', Hometown: 'Ustyuzhna', HometownId: 9 },
@@ -30,8 +30,8 @@ export default class TestData {
30
30
  { Id: 19, ParentId: [11, 23], Name: 'Nadya', SecondName: 'Shaula', Date: '11/11/196?', Comment: 'Tetya', Hometown: 'Novosibirsk', HometownId: 8 },
31
31
  { Id: 20, ParentId: [11, 23], Name: 'Vitia', SecondName: 'Dolginov', Date: '11/11/196?', Comment: 'Dadya', Hometown: 'Novosibirsk', HometownId: 8 },
32
32
  { Id: 21, ParentId: [11, 23], Name: 'Tanya', SecondName: 'Dolginova', Date: '07/01/1963', Comment: 'Tetya', Hometown: 'Elista', HometownId: 5 },
33
- { Id: 22, ParentId: [0], Name: 'Misha', SecondName: 'Razumtsev', Date: '??/??/19??', Comment: 'Ded', Hometown: 'Grafskaya', HometownId: 2 },
34
- { Id: 23, ParentId: [0], Name: 'Zambo', SecondName: 'Dolginov', Date: '??/??/19??', Comment: 'Ded 2', Hometown: 'Elista', HometownId: 5 },
33
+ { Id: 22, ParentId: [0], Name: 'Misha', SecondName: 'Razumtsev', Date: '05/11/1918', Comment: 'Ded', Hometown: 'Grafskaya', HometownId: 2 },
34
+ { Id: 23, ParentId: [0], Name: 'Zambo', SecondName: 'Dolginov', Date: '24/04/1926', Comment: 'Ded 2', Hometown: 'Elista', HometownId: 5 },
35
35
 
36
36
  { Id: 24, ParentId: [18, 34], Name: 'Alina', SecondName: 'Ushakova', Date: '??/??/????', Comment: 'Dv. Sister', Hometown: 'Elista', HometownId: 5 },
37
37
  { Id: 25, ParentId: [19, 33], Name: 'Igor', SecondName: 'Shaula', Date: '??/??/????', Comment: 'Dv. Brother', Hometown: 'Energodar', HometownId: 14 },
@@ -40,7 +40,7 @@ export default class TestData {
40
40
  { Id: 28, ParentId: [20, 35], Name: 'Venia', SecondName: 'Dolginov', Date: '??/??/????', Comment: 'Dv. Brother', Hometown: 'Elista', HometownId: 5 },
41
41
  { Id: 29, ParentId: [20, 36], Name: 'Oleg', SecondName: 'Dolginov', Date: '??/??/????', Comment: 'Dv. Brother', Hometown: 'Elista', HometownId: 5 },
42
42
 
43
- { Id: 30, ParentId: [0], Name: 'Yura', SecondName: 'Pelushskiy', Date: '??/??/????', Comment: 'Dv. Ded', Hometown: 'Ustyuzhna', HometownId: 9 },
43
+ { Id: 30, ParentId: [0], Name: 'Yura', SecondName: 'Pelushskiy', Date: '??/??/1921', Comment: 'Dv. Ded', Hometown: 'Ustyuzhna', HometownId: 9 },
44
44
  { Id: 31, ParentId: [0], Name: 'Sanal', SecondName: 'Batyrev', Date: '11/06/????', Comment: 'Muzh Sestry 3', Hometown: 'Elista', HometownId: 5 },
45
45
  { Id: 32, ParentId: [0], Name: 'Dima', SecondName: 'Markelov', Date: '??/??/????', Comment: 'Muzh Sestry 2', Hometown: 'Elista', HometownId: 5 },
46
46
  { Id: 33, ParentId: [0], Name: 'Slava', SecondName: 'Shaula', Date: '??/??/????', Comment: 'Muzh Teti', Hometown: 'Energodar', HometownId: 14 },