data-primals-engine 1.3.1 → 1.3.2
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/Dockerfile +19 -9
- package/DockerfileTest +19 -9
- package/README.md +782 -782
- package/client/package-lock.json +172 -1
- package/client/package.json +1 -0
- package/client/src/CalendarConfigModal.jsx +60 -21
- package/client/src/CalendarView.jsx +107 -0
- package/client/src/CalendarView.scss +9 -0
- package/client/src/DataLayout.jsx +52 -25
- package/client/src/Dialog.scss +4 -3
- package/client/src/HistoryDialog.jsx +252 -95
- package/client/src/HistoryDialog.scss +319 -72
- package/client/src/ViewSwitcher.jsx +6 -6
- package/client/src/translations.js +192 -49
- package/package.json +1 -1
- package/src/modules/data/data.history.js +489 -303
- package/src/modules/data/data.js +4632 -4620
- package/src/HistoryDialog.jsx +0 -86
- package/src/HistoryDialog.scss +0 -77
package/client/package-lock.json
CHANGED
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
"express-rate-limit": "^7.5.1",
|
|
31
31
|
"lowlight": "^3.3.0",
|
|
32
32
|
"react": ">=18.0.0",
|
|
33
|
+
"react-big-calendar": "^1.19.4",
|
|
33
34
|
"react-dom": "^18.3.1",
|
|
34
35
|
"react-router": "^7.2.0",
|
|
35
36
|
"react-switch": "^7.1.0",
|
|
@@ -1370,7 +1371,6 @@
|
|
|
1370
1371
|
"version": "2.11.8",
|
|
1371
1372
|
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz",
|
|
1372
1373
|
"integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==",
|
|
1373
|
-
"peer": true,
|
|
1374
1374
|
"funding": {
|
|
1375
1375
|
"type": "opencollective",
|
|
1376
1376
|
"url": "https://opencollective.com/popperjs"
|
|
@@ -1381,6 +1381,17 @@
|
|
|
1381
1381
|
"resolved": "https://registry.npmjs.org/@remirror/core-constants/-/core-constants-3.0.0.tgz",
|
|
1382
1382
|
"integrity": "sha512-42aWfPrimMfDKDi4YegyS7x+/0tlzaqwPQCULLanv3DMIlu96KTJR0fM5isWX2UViOqlGnX6YFgqWepcX+XMNg=="
|
|
1383
1383
|
},
|
|
1384
|
+
"node_modules/@restart/hooks": {
|
|
1385
|
+
"version": "0.4.16",
|
|
1386
|
+
"resolved": "https://registry.npmjs.org/@restart/hooks/-/hooks-0.4.16.tgz",
|
|
1387
|
+
"integrity": "sha512-f7aCv7c+nU/3mF7NWLtVVr0Ra80RqsO89hO72r+Y/nvQr5+q0UFGkocElTH6MJApvReVh6JHUFYn2cw1WdHF3w==",
|
|
1388
|
+
"dependencies": {
|
|
1389
|
+
"dequal": "^2.0.3"
|
|
1390
|
+
},
|
|
1391
|
+
"peerDependencies": {
|
|
1392
|
+
"react": ">=16.8.0"
|
|
1393
|
+
}
|
|
1394
|
+
},
|
|
1384
1395
|
"node_modules/@rolldown/pluginutils": {
|
|
1385
1396
|
"version": "1.0.0-beta.27",
|
|
1386
1397
|
"resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.27.tgz",
|
|
@@ -2199,6 +2210,11 @@
|
|
|
2199
2210
|
"integrity": "sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==",
|
|
2200
2211
|
"peer": true
|
|
2201
2212
|
},
|
|
2213
|
+
"node_modules/@types/warning": {
|
|
2214
|
+
"version": "3.0.3",
|
|
2215
|
+
"resolved": "https://registry.npmjs.org/@types/warning/-/warning-3.0.3.tgz",
|
|
2216
|
+
"integrity": "sha512-D1XC7WK8K+zZEveUPY+cf4+kgauk8N4eHr/XIHXGlGYkHLud6hK9lYfZk1ry1TNh798cZUCgb6MqGEG8DkJt6Q=="
|
|
2217
|
+
},
|
|
2202
2218
|
"node_modules/@uiw/codemirror-extensions-basic-setup": {
|
|
2203
2219
|
"version": "4.24.2",
|
|
2204
2220
|
"resolved": "https://registry.npmjs.org/@uiw/codemirror-extensions-basic-setup/-/codemirror-extensions-basic-setup-4.24.2.tgz",
|
|
@@ -2703,6 +2719,14 @@
|
|
|
2703
2719
|
"resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz",
|
|
2704
2720
|
"integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow=="
|
|
2705
2721
|
},
|
|
2722
|
+
"node_modules/clsx": {
|
|
2723
|
+
"version": "1.2.1",
|
|
2724
|
+
"resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz",
|
|
2725
|
+
"integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==",
|
|
2726
|
+
"engines": {
|
|
2727
|
+
"node": ">=6"
|
|
2728
|
+
}
|
|
2729
|
+
},
|
|
2706
2730
|
"node_modules/codemirror": {
|
|
2707
2731
|
"version": "6.0.2",
|
|
2708
2732
|
"resolved": "https://registry.npmjs.org/codemirror/-/codemirror-6.0.2.tgz",
|
|
@@ -2877,6 +2901,11 @@
|
|
|
2877
2901
|
"url": "https://github.com/sponsors/ljharb"
|
|
2878
2902
|
}
|
|
2879
2903
|
},
|
|
2904
|
+
"node_modules/date-arithmetic": {
|
|
2905
|
+
"version": "4.1.0",
|
|
2906
|
+
"resolved": "https://registry.npmjs.org/date-arithmetic/-/date-arithmetic-4.1.0.tgz",
|
|
2907
|
+
"integrity": "sha512-QWxYLR5P/6GStZcdem+V1xoto6DMadYWpMXU82ES3/RfR3Wdwr3D0+be7mgOJ+Ov0G9D5Dmb9T17sNLQYj9XOg=="
|
|
2908
|
+
},
|
|
2880
2909
|
"node_modules/date-fns": {
|
|
2881
2910
|
"version": "4.1.0",
|
|
2882
2911
|
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz",
|
|
@@ -2886,6 +2915,11 @@
|
|
|
2886
2915
|
"url": "https://github.com/sponsors/kossnocorp"
|
|
2887
2916
|
}
|
|
2888
2917
|
},
|
|
2918
|
+
"node_modules/dayjs": {
|
|
2919
|
+
"version": "1.11.13",
|
|
2920
|
+
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz",
|
|
2921
|
+
"integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg=="
|
|
2922
|
+
},
|
|
2889
2923
|
"node_modules/debug": {
|
|
2890
2924
|
"version": "4.4.1",
|
|
2891
2925
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
|
|
@@ -2989,6 +3023,15 @@
|
|
|
2989
3023
|
"node": ">=0.10.0"
|
|
2990
3024
|
}
|
|
2991
3025
|
},
|
|
3026
|
+
"node_modules/dom-helpers": {
|
|
3027
|
+
"version": "5.2.1",
|
|
3028
|
+
"resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz",
|
|
3029
|
+
"integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==",
|
|
3030
|
+
"dependencies": {
|
|
3031
|
+
"@babel/runtime": "^7.8.7",
|
|
3032
|
+
"csstype": "^3.0.2"
|
|
3033
|
+
}
|
|
3034
|
+
},
|
|
2992
3035
|
"node_modules/dotenv": {
|
|
2993
3036
|
"version": "16.6.1",
|
|
2994
3037
|
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz",
|
|
@@ -3875,6 +3918,11 @@
|
|
|
3875
3918
|
"node": ">=10.13.0"
|
|
3876
3919
|
}
|
|
3877
3920
|
},
|
|
3921
|
+
"node_modules/globalize": {
|
|
3922
|
+
"version": "0.1.1",
|
|
3923
|
+
"resolved": "https://registry.npmjs.org/globalize/-/globalize-0.1.1.tgz",
|
|
3924
|
+
"integrity": "sha512-5e01v8eLGfuQSOvx2MsDMOWS0GFtCx1wPzQSmcHw4hkxFzrQDBO3Xwg/m8Hr/7qXMrHeOIE29qWVzyv06u1TZA=="
|
|
3925
|
+
},
|
|
3878
3926
|
"node_modules/globals": {
|
|
3879
3927
|
"version": "15.15.0",
|
|
3880
3928
|
"resolved": "https://registry.npmjs.org/globals/-/globals-15.15.0.tgz",
|
|
@@ -4196,6 +4244,14 @@
|
|
|
4196
4244
|
"node": ">= 0.4"
|
|
4197
4245
|
}
|
|
4198
4246
|
},
|
|
4247
|
+
"node_modules/invariant": {
|
|
4248
|
+
"version": "2.2.4",
|
|
4249
|
+
"resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
|
|
4250
|
+
"integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
|
|
4251
|
+
"dependencies": {
|
|
4252
|
+
"loose-envify": "^1.0.0"
|
|
4253
|
+
}
|
|
4254
|
+
},
|
|
4199
4255
|
"node_modules/ipaddr.js": {
|
|
4200
4256
|
"version": "1.9.1",
|
|
4201
4257
|
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
|
|
@@ -4721,6 +4777,16 @@
|
|
|
4721
4777
|
"url": "https://github.com/sponsors/sindresorhus"
|
|
4722
4778
|
}
|
|
4723
4779
|
},
|
|
4780
|
+
"node_modules/lodash": {
|
|
4781
|
+
"version": "4.17.21",
|
|
4782
|
+
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
|
4783
|
+
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
|
|
4784
|
+
},
|
|
4785
|
+
"node_modules/lodash-es": {
|
|
4786
|
+
"version": "4.17.21",
|
|
4787
|
+
"resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz",
|
|
4788
|
+
"integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="
|
|
4789
|
+
},
|
|
4724
4790
|
"node_modules/lodash.merge": {
|
|
4725
4791
|
"version": "4.6.2",
|
|
4726
4792
|
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
|
|
@@ -4761,6 +4827,14 @@
|
|
|
4761
4827
|
"yallist": "^3.0.2"
|
|
4762
4828
|
}
|
|
4763
4829
|
},
|
|
4830
|
+
"node_modules/luxon": {
|
|
4831
|
+
"version": "3.7.1",
|
|
4832
|
+
"resolved": "https://registry.npmjs.org/luxon/-/luxon-3.7.1.tgz",
|
|
4833
|
+
"integrity": "sha512-RkRWjA926cTvz5rAb1BqyWkKbbjzCGchDUIKMCUvNi17j6f6j8uHGDV82Aqcqtzd+icoYpELmG3ksgGiFNNcNg==",
|
|
4834
|
+
"engines": {
|
|
4835
|
+
"node": ">=12"
|
|
4836
|
+
}
|
|
4837
|
+
},
|
|
4764
4838
|
"node_modules/markdown-it": {
|
|
4765
4839
|
"version": "14.1.0",
|
|
4766
4840
|
"resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz",
|
|
@@ -4809,6 +4883,11 @@
|
|
|
4809
4883
|
"node": ">= 0.8"
|
|
4810
4884
|
}
|
|
4811
4885
|
},
|
|
4886
|
+
"node_modules/memoize-one": {
|
|
4887
|
+
"version": "6.0.0",
|
|
4888
|
+
"resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz",
|
|
4889
|
+
"integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw=="
|
|
4890
|
+
},
|
|
4812
4891
|
"node_modules/merge-descriptors": {
|
|
4813
4892
|
"version": "2.0.0",
|
|
4814
4893
|
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz",
|
|
@@ -4859,6 +4938,25 @@
|
|
|
4859
4938
|
"node": "*"
|
|
4860
4939
|
}
|
|
4861
4940
|
},
|
|
4941
|
+
"node_modules/moment": {
|
|
4942
|
+
"version": "2.30.1",
|
|
4943
|
+
"resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz",
|
|
4944
|
+
"integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==",
|
|
4945
|
+
"engines": {
|
|
4946
|
+
"node": "*"
|
|
4947
|
+
}
|
|
4948
|
+
},
|
|
4949
|
+
"node_modules/moment-timezone": {
|
|
4950
|
+
"version": "0.5.48",
|
|
4951
|
+
"resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.48.tgz",
|
|
4952
|
+
"integrity": "sha512-f22b8LV1gbTO2ms2j2z13MuPogNoh5UzxL3nzNAYKGraILnbGc9NEE6dyiiiLv46DGRb8A4kg8UKWLjPthxBHw==",
|
|
4953
|
+
"dependencies": {
|
|
4954
|
+
"moment": "^2.29.4"
|
|
4955
|
+
},
|
|
4956
|
+
"engines": {
|
|
4957
|
+
"node": "*"
|
|
4958
|
+
}
|
|
4959
|
+
},
|
|
4862
4960
|
"node_modules/monaco-editor": {
|
|
4863
4961
|
"version": "0.45.0",
|
|
4864
4962
|
"resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.45.0.tgz",
|
|
@@ -5520,6 +5618,33 @@
|
|
|
5520
5618
|
"node": ">=0.10.0"
|
|
5521
5619
|
}
|
|
5522
5620
|
},
|
|
5621
|
+
"node_modules/react-big-calendar": {
|
|
5622
|
+
"version": "1.19.4",
|
|
5623
|
+
"resolved": "https://registry.npmjs.org/react-big-calendar/-/react-big-calendar-1.19.4.tgz",
|
|
5624
|
+
"integrity": "sha512-FrvbDx2LF6JAWFD96LU1jjloppC5OgIvMYUYIPzAw5Aq+ArYFPxAjLqXc4DyxfsQDN0TJTMuS/BIbcSB7Pg0YA==",
|
|
5625
|
+
"dependencies": {
|
|
5626
|
+
"@babel/runtime": "^7.20.7",
|
|
5627
|
+
"clsx": "^1.2.1",
|
|
5628
|
+
"date-arithmetic": "^4.1.0",
|
|
5629
|
+
"dayjs": "^1.11.7",
|
|
5630
|
+
"dom-helpers": "^5.2.1",
|
|
5631
|
+
"globalize": "^0.1.1",
|
|
5632
|
+
"invariant": "^2.2.4",
|
|
5633
|
+
"lodash": "^4.17.21",
|
|
5634
|
+
"lodash-es": "^4.17.21",
|
|
5635
|
+
"luxon": "^3.2.1",
|
|
5636
|
+
"memoize-one": "^6.0.0",
|
|
5637
|
+
"moment": "^2.29.4",
|
|
5638
|
+
"moment-timezone": "^0.5.40",
|
|
5639
|
+
"prop-types": "^15.8.1",
|
|
5640
|
+
"react-overlays": "^5.2.1",
|
|
5641
|
+
"uncontrollable": "^7.2.1"
|
|
5642
|
+
},
|
|
5643
|
+
"peerDependencies": {
|
|
5644
|
+
"react": "^16.14.0 || ^17 || ^18 || ^19",
|
|
5645
|
+
"react-dom": "^16.14.0 || ^17 || ^18 || ^19"
|
|
5646
|
+
}
|
|
5647
|
+
},
|
|
5523
5648
|
"node_modules/react-chartjs-2": {
|
|
5524
5649
|
"version": "5.3.0",
|
|
5525
5650
|
"resolved": "https://registry.npmjs.org/react-chartjs-2/-/react-chartjs-2-5.3.0.tgz",
|
|
@@ -5690,6 +5815,30 @@
|
|
|
5690
5815
|
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
|
5691
5816
|
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
|
|
5692
5817
|
},
|
|
5818
|
+
"node_modules/react-lifecycles-compat": {
|
|
5819
|
+
"version": "3.0.4",
|
|
5820
|
+
"resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
|
|
5821
|
+
"integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
|
|
5822
|
+
},
|
|
5823
|
+
"node_modules/react-overlays": {
|
|
5824
|
+
"version": "5.2.1",
|
|
5825
|
+
"resolved": "https://registry.npmjs.org/react-overlays/-/react-overlays-5.2.1.tgz",
|
|
5826
|
+
"integrity": "sha512-GLLSOLWr21CqtJn8geSwQfoJufdt3mfdsnIiQswouuQ2MMPns+ihZklxvsTDKD3cR2tF8ELbi5xUsvqVhR6WvA==",
|
|
5827
|
+
"dependencies": {
|
|
5828
|
+
"@babel/runtime": "^7.13.8",
|
|
5829
|
+
"@popperjs/core": "^2.11.6",
|
|
5830
|
+
"@restart/hooks": "^0.4.7",
|
|
5831
|
+
"@types/warning": "^3.0.0",
|
|
5832
|
+
"dom-helpers": "^5.2.0",
|
|
5833
|
+
"prop-types": "^15.7.2",
|
|
5834
|
+
"uncontrollable": "^7.2.1",
|
|
5835
|
+
"warning": "^4.0.3"
|
|
5836
|
+
},
|
|
5837
|
+
"peerDependencies": {
|
|
5838
|
+
"react": ">=16.3.0",
|
|
5839
|
+
"react-dom": ">=16.3.0"
|
|
5840
|
+
}
|
|
5841
|
+
},
|
|
5693
5842
|
"node_modules/react-query": {
|
|
5694
5843
|
"version": "3.39.3",
|
|
5695
5844
|
"resolved": "https://registry.npmjs.org/react-query/-/react-query-3.39.3.tgz",
|
|
@@ -7101,6 +7250,20 @@
|
|
|
7101
7250
|
"url": "https://github.com/sponsors/ljharb"
|
|
7102
7251
|
}
|
|
7103
7252
|
},
|
|
7253
|
+
"node_modules/uncontrollable": {
|
|
7254
|
+
"version": "7.2.1",
|
|
7255
|
+
"resolved": "https://registry.npmjs.org/uncontrollable/-/uncontrollable-7.2.1.tgz",
|
|
7256
|
+
"integrity": "sha512-svtcfoTADIB0nT9nltgjujTi7BzVmwjZClOmskKu/E8FW9BXzg9os8OLr4f8Dlnk0rYWJIWr4wv9eKUXiQvQwQ==",
|
|
7257
|
+
"dependencies": {
|
|
7258
|
+
"@babel/runtime": "^7.6.3",
|
|
7259
|
+
"@types/react": ">=16.9.11",
|
|
7260
|
+
"invariant": "^2.2.4",
|
|
7261
|
+
"react-lifecycles-compat": "^3.0.4"
|
|
7262
|
+
},
|
|
7263
|
+
"peerDependencies": {
|
|
7264
|
+
"react": ">=15.0.0"
|
|
7265
|
+
}
|
|
7266
|
+
},
|
|
7104
7267
|
"node_modules/uniqid": {
|
|
7105
7268
|
"version": "5.4.0",
|
|
7106
7269
|
"resolved": "https://registry.npmjs.org/uniqid/-/uniqid-5.4.0.tgz",
|
|
@@ -7285,6 +7448,14 @@
|
|
|
7285
7448
|
"resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz",
|
|
7286
7449
|
"integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ=="
|
|
7287
7450
|
},
|
|
7451
|
+
"node_modules/warning": {
|
|
7452
|
+
"version": "4.0.3",
|
|
7453
|
+
"resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz",
|
|
7454
|
+
"integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==",
|
|
7455
|
+
"dependencies": {
|
|
7456
|
+
"loose-envify": "^1.0.0"
|
|
7457
|
+
}
|
|
7458
|
+
},
|
|
7288
7459
|
"node_modules/which": {
|
|
7289
7460
|
"version": "2.0.2",
|
|
7290
7461
|
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
package/client/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/components/dataview/CalendarConfigModal.jsx
|
|
2
|
-
import React, {
|
|
2
|
+
import React, {useState, useMemo, useEffect} from 'react';
|
|
3
3
|
import { useTranslation } from 'react-i18next';
|
|
4
4
|
import {Dialog} from "./Dialog.jsx";
|
|
5
5
|
|
|
@@ -8,42 +8,81 @@ const Modal = ({ isOpen, onClose, title, children }) => isOpen ? <div style={{..
|
|
|
8
8
|
const Select = ({ children, ...props }) => <select {...props}>{children}</select>;
|
|
9
9
|
const Button = (props) => <button {...props} />;
|
|
10
10
|
|
|
11
|
-
export default function CalendarConfigModal({ isOpen, onClose, onSave, modelFields }) {
|
|
11
|
+
export default function CalendarConfigModal({ isOpen, onClose, onSave, modelFields, initialSettings }) {
|
|
12
12
|
const { t } = useTranslation();
|
|
13
13
|
const [selectedField, setSelectedField] = useState('');
|
|
14
|
+
// État pour contenir la configuration complète
|
|
15
|
+
const [config, setConfig] = useState({
|
|
16
|
+
titleField: '',
|
|
17
|
+
startField: '',
|
|
18
|
+
endField: '',
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
// Remplir l'état à partir des `initialSettings` lorsque la modale s'ouvre
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
if (isOpen) {
|
|
24
|
+
setConfig({
|
|
25
|
+
titleField: initialSettings?.titleField || '',
|
|
26
|
+
startField: initialSettings?.startField || '',
|
|
27
|
+
endField: initialSettings?.endField || '',
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
}, [initialSettings, isOpen]);
|
|
31
|
+
|
|
32
|
+
const handleConfigChange = (e) => {
|
|
33
|
+
const { name, value } = e.target;
|
|
34
|
+
setConfig(prev => ({ ...prev, [name]: value }));
|
|
35
|
+
};
|
|
14
36
|
|
|
15
37
|
const dateFields = useMemo(() =>
|
|
16
|
-
modelFields.filter(f =>
|
|
38
|
+
modelFields.filter(f => ['date', 'datetime'].includes(f.type)),
|
|
17
39
|
[modelFields]
|
|
18
40
|
);
|
|
19
41
|
|
|
42
|
+
const titleFields = useMemo(() => modelFields.filter(f =>
|
|
43
|
+
['string', 'string_t', 'enum', 'number'].includes(f.type)
|
|
44
|
+
), [modelFields]);
|
|
45
|
+
|
|
46
|
+
|
|
20
47
|
const handleSave = () => {
|
|
21
|
-
|
|
22
|
-
onSave({ dateField: selectedField });
|
|
23
|
-
}
|
|
48
|
+
onSave(config);
|
|
24
49
|
};
|
|
25
50
|
|
|
51
|
+
const isSaveDisabled = !config.titleField || !config.startField || !config.endField;
|
|
52
|
+
|
|
26
53
|
if (!isOpen) return null;
|
|
27
54
|
|
|
28
55
|
return (
|
|
29
|
-
// Utilisez votre propre composant Modal ici
|
|
30
56
|
<Dialog isOpen={isOpen} onClose={onClose}>
|
|
31
|
-
<h2>{t('dataview.calendar.configureTitle')}</h2>
|
|
32
|
-
<p>{t('dataview.calendar.
|
|
33
|
-
|
|
34
|
-
<div style={{ margin: '20px 0' }}>
|
|
35
|
-
<
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
57
|
+
<h2>{t('dataview.calendar.configureTitle', 'Configurer la vue Calendrier')}</h2>
|
|
58
|
+
<p>{t('dataview.calendar.configureText', 'Sélectionnez les champs à utiliser pour afficher les données dans le calendrier.')}</p>
|
|
59
|
+
|
|
60
|
+
<div style={{ margin: '20px 0', display: 'flex', flexDirection: 'column', gap: '15px' }}>
|
|
61
|
+
<div>
|
|
62
|
+
<label htmlFor="titleField">{t('dataview.calendar.titleFieldLabel', "Champ pour le titre de l'événement")}</label>
|
|
63
|
+
<Select id="titleField" name="titleField" value={config.titleField} onChange={handleConfigChange}>
|
|
64
|
+
<option value="">{t('dataview.calendar.selectPlaceholder', 'Sélectionner un champ...')}</option>
|
|
65
|
+
{titleFields.map(field => (<option key={field.name} value={field.name}>{field.name}</option>))}
|
|
66
|
+
</Select>
|
|
67
|
+
</div>
|
|
68
|
+
<div>
|
|
69
|
+
<label htmlFor="startField">{t('dataview.calendar.startFieldLabel', 'Champ pour la date de début')}</label>
|
|
70
|
+
<Select id="startField" name="startField" value={config.startField} onChange={handleConfigChange}>
|
|
71
|
+
<option value="">{t('dataview.calendar.selectPlaceholder', 'Sélectionner un champ...')}</option>
|
|
72
|
+
{dateFields.map(field => (<option key={field.name} value={field.name}>{field.name}</option>))}
|
|
73
|
+
</Select>
|
|
74
|
+
</div>
|
|
75
|
+
<div>
|
|
76
|
+
<label htmlFor="endField">{t('dataview.calendar.endFieldLabel', 'Champ pour la date de fin')}</label>
|
|
77
|
+
<Select id="endField" name="endField" value={config.endField} onChange={handleConfigChange}>
|
|
78
|
+
<option value="">{t('dataview.calendar.selectPlaceholder', 'Sélectionner un champ...')}</option>
|
|
79
|
+
{dateFields.map(field => (<option key={field.name} value={field.name}>{field.name}</option>))}
|
|
80
|
+
</Select>
|
|
81
|
+
</div>
|
|
43
82
|
</div>
|
|
44
83
|
|
|
45
|
-
<Button onClick={handleSave} disabled={
|
|
46
|
-
<Button onClick={onClose} style={{ marginLeft: '10px' }}>{t('btns.cancel')}</Button>
|
|
84
|
+
<Button onClick={handleSave} disabled={isSaveDisabled}>{t('btns.saveConfig', 'Enregistrer')}</Button>
|
|
85
|
+
<Button onClick={onClose} style={{ marginLeft: '10px' }}>{t('btns.cancel', 'Annuler')}</Button>
|
|
47
86
|
</Dialog>
|
|
48
87
|
);
|
|
49
88
|
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import React, { useMemo } from 'react';
|
|
2
|
+
import { useQuery } from 'react-query';
|
|
3
|
+
import { Calendar, dateFnsLocalizer } from 'react-big-calendar';
|
|
4
|
+
import { useTranslation } from 'react-i18next';
|
|
5
|
+
import { format, parse, startOfWeek, getDay } from 'date-fns';
|
|
6
|
+
// Importer les locales dont vous avez besoin
|
|
7
|
+
|
|
8
|
+
import 'react-big-calendar/lib/css/react-big-calendar.css';
|
|
9
|
+
import { useAuthContext } from "./contexts/AuthContext.jsx";
|
|
10
|
+
import './CalendarView.scss';
|
|
11
|
+
|
|
12
|
+
import { enUS, fr } from 'date-fns/locale';
|
|
13
|
+
// Configurer le localizer en fournissant les fonctions de date-fns
|
|
14
|
+
const locales = {
|
|
15
|
+
'en-US': enUS,
|
|
16
|
+
'en': enUS,
|
|
17
|
+
'fr': fr,
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const localizer = dateFnsLocalizer({
|
|
21
|
+
format,
|
|
22
|
+
parse,
|
|
23
|
+
startOfWeek,
|
|
24
|
+
getDay,
|
|
25
|
+
locales,
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Traite les données brutes pour les structurer pour le calendrier.
|
|
30
|
+
* @param {Array<Object>} data - La liste des éléments du modèle.
|
|
31
|
+
* @param {Object} settings - Les paramètres de la vue, contenant titleField, startField, endField.
|
|
32
|
+
* @returns {Array<Object>} Un tableau d'objets événement pour react-big-calendar.
|
|
33
|
+
*/
|
|
34
|
+
const processDataForCalendar = (data, settings) => {
|
|
35
|
+
if (!data || !settings.titleField || !settings.startField || !settings.endField) {
|
|
36
|
+
return [];
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return data.map(item => {
|
|
40
|
+
const title = item[settings.titleField]?.value || item[settings.titleField] || 'Sans titre';
|
|
41
|
+
const start = item[settings.startField] ? new Date(item[settings.startField]) : null;
|
|
42
|
+
const end = item[settings.endField] ? new Date(item[settings.endField]) : null;
|
|
43
|
+
|
|
44
|
+
// S'assurer que les dates sont valides
|
|
45
|
+
if (!start || !end || isNaN(start.getTime()) || isNaN(end.getTime())) {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return {
|
|
50
|
+
title,
|
|
51
|
+
start,
|
|
52
|
+
end,
|
|
53
|
+
resource: item, // Garder l'objet original pour plus de détails au clic
|
|
54
|
+
};
|
|
55
|
+
}).filter(Boolean); // Filtrer les éléments qui n'ont pas pu être convertis
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const CalendarView = ({ settings, model, onEditData }) => {
|
|
59
|
+
const { me } = useAuthContext();
|
|
60
|
+
const { i18n } = useTranslation();
|
|
61
|
+
|
|
62
|
+
// Récupérer toutes les données du modèle nécessaires pour le calendrier
|
|
63
|
+
const { data: calendarData, isLoading, isError } = useQuery(
|
|
64
|
+
['calendarData', model.name],
|
|
65
|
+
() => fetch(`/api/data/search?_user=${me.username}&depth=1`, {
|
|
66
|
+
method: 'POST',
|
|
67
|
+
headers: { 'Content-Type': 'application/json' },
|
|
68
|
+
// Note : Pour de très grands ensembles de données, vous pourriez vouloir implémenter une récupération par plage de dates.
|
|
69
|
+
body: JSON.stringify({ model: model.name, page: 1 })
|
|
70
|
+
}).then(res => res.json()),
|
|
71
|
+
{
|
|
72
|
+
enabled: !!model?.name && !!settings.titleField && !!settings.startField && !!settings.endField,
|
|
73
|
+
select: (data) => data.data || [],
|
|
74
|
+
}
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
const { events, culture } = useMemo(() => {
|
|
78
|
+
const processedEvents = calendarData ? processDataForCalendar(calendarData, settings) : [];
|
|
79
|
+
const lang = i18n.language.split(/[-_]/)[0];
|
|
80
|
+
const culture = Object.keys(locales).includes(lang) ? lang : 'en';
|
|
81
|
+
return { events: processedEvents, culture };
|
|
82
|
+
}, [calendarData, settings, i18n.language]);
|
|
83
|
+
|
|
84
|
+
if (isLoading) return <div>Chargement du calendrier...</div>;
|
|
85
|
+
if (isError) return <div>Erreur lors du chargement des données.</div>;
|
|
86
|
+
if (!settings.titleField || !settings.startField || !settings.endField) {
|
|
87
|
+
return <div>La vue calendrier n'est pas configurée. Veuillez définir les champs pour le titre, la date de début et la date de fin dans les paramètres de la vue.</div>
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return (
|
|
91
|
+
<div className="calendar-view-container">
|
|
92
|
+
<Calendar
|
|
93
|
+
localizer={localizer}
|
|
94
|
+
events={events}
|
|
95
|
+
culture={culture}
|
|
96
|
+
startAccessor="start"
|
|
97
|
+
endAccessor="end"
|
|
98
|
+
// Vous pouvez ajouter un gestionnaire onSelectEvent pour afficher une modale avec les détails de l'événement
|
|
99
|
+
onSelectEvent={event => {
|
|
100
|
+
onEditData(model, event.resource);
|
|
101
|
+
}}
|
|
102
|
+
/>
|
|
103
|
+
</div>
|
|
104
|
+
);
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
export default CalendarView;
|