@fto-consult/expo-ui 2.46.4 → 2.47.1
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/package.json +2 -2
- package/src/components/Datagrid/Common/Common.js +252 -78
- package/src/components/Datagrid/Common/TableData.js +1 -122
- package/src/components/Datagrid/Common/utils.js +5 -0
- package/src/components/Datagrid/SWRDatagrid.js +9 -15
- package/src/components/Datagrid/Table/index.js +7 -7
- package/src/components/Dropdown/index.js +1 -1
- package/src/components/Icon/Checkbox.js +3 -3
- package/src/components/Icon/Icon.js +0 -1
- package/src/components/Icon/utils.js +4 -0
- package/src/components/ScrollView/index.js +30 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fto-consult/expo-ui",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.47.1",
|
|
4
4
|
"description": "Bibliothèque de composants UI Expo,react-native",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
"@emotion/native": "^11.10.0",
|
|
62
62
|
"@expo/html-elements": "^0.2.0",
|
|
63
63
|
"@expo/vector-icons": "^13.0.0",
|
|
64
|
-
"@fto-consult/common": "^2.
|
|
64
|
+
"@fto-consult/common": "^2.9.4",
|
|
65
65
|
"@gorhom/portal": "^1.0.14",
|
|
66
66
|
"@react-native-async-storage/async-storage": "~1.17.3",
|
|
67
67
|
"@react-native-community/datetimepicker": "6.5.2",
|
|
@@ -9,7 +9,7 @@ import Tooltip from "$ecomponents/Tooltip";
|
|
|
9
9
|
import setQueryLimit from "./setQueryLimit";
|
|
10
10
|
import {showConfirm} from "$ecomponents/Dialog";
|
|
11
11
|
import Label from "$ecomponents/Label";
|
|
12
|
-
import Icon,{COPY_ICON} from "$ecomponents/Icon";
|
|
12
|
+
import Icon,{COPY_ICON,CHECKED_ICON,UNCHECKED_ICON} from "$ecomponents/Icon";
|
|
13
13
|
import filterUtils from "$cfilters";
|
|
14
14
|
import {sortBy,isDecimal,defaultVal,sanitizeSheetName,extendObj,isObjOrArray,isObj,defaultNumber,defaultStr,isFunction,defaultBool,defaultArray,defaultObj,isNonNullString,defaultDecimal} from "$utils";
|
|
15
15
|
import {Datagrid as DatagridContentLoader} from "$ecomponents/ContentLoader";
|
|
@@ -36,10 +36,10 @@ import notify from "$cnotify";
|
|
|
36
36
|
import FileSystem from "$file-system";
|
|
37
37
|
import sprintf from "$cutils/sprintf";
|
|
38
38
|
import { renderRowCell,formatValue,arrayValueSeparator } from "./utils";
|
|
39
|
-
import {ScrollView} from "react-native";
|
|
40
39
|
import Button from "$ecomponents/Button";
|
|
41
40
|
import stableHash from "stable-hash";
|
|
42
41
|
import * as XLSX from "xlsx";
|
|
42
|
+
import {convertToSQL} from "$ecomponents/Filter";
|
|
43
43
|
|
|
44
44
|
export const TIMEOUT = 100;
|
|
45
45
|
|
|
@@ -264,21 +264,20 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
264
264
|
sectionListColumnsSize : {value : {current:0}}, //la taille du nombre d'éléments de section dans les colonnes
|
|
265
265
|
chartRef : {value : {current:null}},
|
|
266
266
|
layoutRef : {value : {}},
|
|
267
|
+
hidePreloaderOnRenderKey : {value : uniqid("hide-preloader-on-render")},
|
|
267
268
|
isRenderingRef : {value : {current:false}},
|
|
268
269
|
chartSeriesNamesColumnsMapping : {value : {}},//le mappage entre les index des series et les colonnes coorespondantes
|
|
269
270
|
})
|
|
271
|
+
const config = extendObj(true,{},this.getSessionData("config"),this.props.chartConfig);
|
|
272
|
+
Object.map(config,(v,k)=>{
|
|
273
|
+
if(typeof v =='function'){
|
|
274
|
+
delete config[k];
|
|
275
|
+
}
|
|
276
|
+
});
|
|
277
|
+
this.state.fetchOnlyVisibleColumns = !!defaultVal(this.props.fetchOnlyVisibleColumns,config.fetchOnlyVisibleColumns,this.getSessionData("fetchOnlyVisibleColumns"));
|
|
270
278
|
this.state.abreviateValues = "abreviateValues" in this.props? !!this.props.abreviateValues : !!this.getSessionData("abreviateValues");
|
|
271
|
-
const sessionAggregator =
|
|
272
|
-
|
|
273
|
-
let aggregatorFunction = null;
|
|
274
|
-
if(aggregatorProps && isValidAggregator(this.aggregatorFunctions[aggregatorProps])){
|
|
275
|
-
aggregatorFunction = aggregatorProps;
|
|
276
|
-
} else if(isNonNullString(sessionAggregator) && isValidAggregator(this.aggregatorFunctions[sessionAggregator])){
|
|
277
|
-
aggregatorFunction = sessionAggregator;
|
|
278
|
-
} else {
|
|
279
|
-
aggregatorFunction = Object.keys(this.aggregatorFunctions)[0];
|
|
280
|
-
}
|
|
281
|
-
this.state.aggregatorFunction= aggregatorFunction;
|
|
279
|
+
const sessionAggregator = this.getSessionData("aggregatorFunction");
|
|
280
|
+
this.state.aggregatorFunction= this.isValidAggregator(config.aggregatorFunction) && config.aggregatorFunction || this.isValidAggregator(this.props.aggregatorFunction) && this.props.aggregatorFunction || this.isValidAggregator(sessionAggregator) && sessionAggregator || Object.keys(this.aggregatorFunctions)[0];;
|
|
282
281
|
this.isLoading = this.isLoading.bind(this);
|
|
283
282
|
this.getProgressBar = this.getProgressBar.bind(this);
|
|
284
283
|
this.sortRef.current.dir = defaultStr(this.sortRef.current.dir,this.sortRef.current.column == "date"?"desc":'asc')
|
|
@@ -290,6 +289,7 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
290
289
|
this.INITIAL_STATE = {
|
|
291
290
|
data,
|
|
292
291
|
}
|
|
292
|
+
this.prepareFetchData();
|
|
293
293
|
this._datagridId = isNonNullString(this.props.id)? this.props.id : uniqid("datagrid-id")
|
|
294
294
|
this.canDoFilter = true;
|
|
295
295
|
this.filters = {}
|
|
@@ -306,15 +306,14 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
306
306
|
}
|
|
307
307
|
});
|
|
308
308
|
this.state.filteredColumns = defaultObj(this.getSessionData("filteredColumns"+this.getSessionNameKey()),this.props.filters);
|
|
309
|
-
this.filtersSelectors = {selector:this.getFilters()};
|
|
310
309
|
const {sectionListColumns} = this.prepareColumns();
|
|
311
310
|
this.state.sectionListColumns = sectionListColumns;
|
|
312
311
|
if(this.canHandleColumnResize()){
|
|
313
312
|
this.state.columnsWidths = this.preparedColumns.widths;
|
|
314
313
|
}
|
|
315
|
-
this.state.
|
|
316
|
-
if(!("sparkline" in this.state.
|
|
317
|
-
this.state.
|
|
314
|
+
this.state.config = config;
|
|
315
|
+
if(!("sparkline" in this.state.config) && this.isDashboard()){
|
|
316
|
+
this.state.config.sparkline = true;
|
|
318
317
|
}
|
|
319
318
|
const dType = defaultStr(this.props.displayType,this.getSessionData("displayType"),"table");
|
|
320
319
|
this.state.displayType = this.displayTypes[dType] ? this.displayTypes[dType].code : "table" in this.displayTypes ? "table" : Object.keys(this.displayTypes)[0]?.code;
|
|
@@ -368,7 +367,34 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
368
367
|
}
|
|
369
368
|
this.persistDisplayType(this.state.displayType);
|
|
370
369
|
}
|
|
371
|
-
|
|
370
|
+
/*** si l'on peut récuperer à distance, les colonnes seulement visibles */
|
|
371
|
+
canFetchOnlyVisibleColumns(){
|
|
372
|
+
return this.isTableData() && this.props.canFetchOnlyVisibleColumns !== false && true || false;
|
|
373
|
+
}
|
|
374
|
+
isFetchOnlyVisibleColumnsEnabled(){
|
|
375
|
+
return this.canFetchOnlyVisibleColumns() && !!this.state.fetchOnlyVisibleColumns;
|
|
376
|
+
}
|
|
377
|
+
fetchDataIfCanFetchColumnsIfVisible(){
|
|
378
|
+
if(!this.canFetchOnlyVisibleColumns()) return;
|
|
379
|
+
this.toggleHidePreloaderOnRender(false);
|
|
380
|
+
return this.fetchData({force:true});
|
|
381
|
+
}
|
|
382
|
+
toggleFetchOnlyVisibleColumns(){
|
|
383
|
+
if(!this.canFetchOnlyVisibleColumns()){
|
|
384
|
+
return Promise.reject({});
|
|
385
|
+
}
|
|
386
|
+
const fetchOnlyVisibleColumns = !this.isFetchOnlyVisibleColumnsEnabled();
|
|
387
|
+
setTimeout(()=>{
|
|
388
|
+
this.setIsLoading(true,()=>{
|
|
389
|
+
this.toggleHidePreloaderOnRender(true);
|
|
390
|
+
this.setSessionData("fetchOnlyVisibleColumns",fetchOnlyVisibleColumns);
|
|
391
|
+
this.setState({fetchOnlyVisibleColumns},this.fetchDataIfCanFetchColumnsIfVisible.bind(this))
|
|
392
|
+
},true)
|
|
393
|
+
},TIMEOUT)
|
|
394
|
+
}
|
|
395
|
+
isValidAggregator(aggregatorFunction){
|
|
396
|
+
return isNonNullString(aggregatorFunction) && isValidAggregator(this.aggregatorFunctions[aggregatorFunction])
|
|
397
|
+
}
|
|
372
398
|
/*** si une ligne peut être selectionable */
|
|
373
399
|
canSelectRow(row){
|
|
374
400
|
return isObj(row) && row.isSectionListHeader !== true ? true : false;
|
|
@@ -957,7 +983,7 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
957
983
|
this._previousSortObj = Object.clone(this.sortRef.current);
|
|
958
984
|
this.sortRef.current = sort;
|
|
959
985
|
this.prepareColumns({sortedColumn : this.sortRef.current});
|
|
960
|
-
if(typeof this.props.onSort =='function' && this.props.onSort({
|
|
986
|
+
if(typeof this.props.onSort =='function' && this.props.onSort({context:this,sort,data:this.INITIAL_STATE.data,fields:this.state.columns,columns:this.state.columns}) === false){
|
|
961
987
|
return;
|
|
962
988
|
}
|
|
963
989
|
this.prepareData({data:this.INITIAL_STATE.data,updateFooters:false},(state)=>{
|
|
@@ -1005,6 +1031,17 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
1005
1031
|
*/
|
|
1006
1032
|
renderCustomMenu(){
|
|
1007
1033
|
const customMenu = []
|
|
1034
|
+
if(this.canFetchOnlyVisibleColumns()){
|
|
1035
|
+
const isFE = this.isFetchOnlyVisibleColumnsEnabled();
|
|
1036
|
+
customMenu.push({
|
|
1037
|
+
text : "Valeurs Cols visibles",
|
|
1038
|
+
tooltip : "Récupérer uniquement les valeurs des colonnes visibles",
|
|
1039
|
+
icon : "material-radio-button-{0}".sprintf(isFE?"on":"off"),
|
|
1040
|
+
onPress : (e)=>{
|
|
1041
|
+
this.toggleFetchOnlyVisibleColumns();
|
|
1042
|
+
}
|
|
1043
|
+
})
|
|
1044
|
+
}
|
|
1008
1045
|
Object.map(this.props.customMenu,(menu,i)=>{
|
|
1009
1046
|
if(isObj(menu)){
|
|
1010
1047
|
const {onPress,label,text,children,...rest} = menu;
|
|
@@ -1177,7 +1214,8 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
1177
1214
|
}
|
|
1178
1215
|
this.setIsLoading(true,()=>{
|
|
1179
1216
|
this.prepareColumns({columns});
|
|
1180
|
-
this.
|
|
1217
|
+
this.toggleHidePreloaderOnRender(this.canFetchOnlyVisibleColumns());
|
|
1218
|
+
this.setState({columns},this.fetchDataIfCanFetchColumnsIfVisible.bind(this));
|
|
1181
1219
|
})
|
|
1182
1220
|
},TIMEOUT)
|
|
1183
1221
|
}
|
|
@@ -1301,7 +1339,7 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
1301
1339
|
return !this.isPivotDatagrid() && this.hasFootersFields();
|
|
1302
1340
|
}
|
|
1303
1341
|
isValidChartConfig(){
|
|
1304
|
-
const config = this.state.
|
|
1342
|
+
const config = this.state.config;
|
|
1305
1343
|
return isNonNullString(config.x) && isNonNullString(config.y);
|
|
1306
1344
|
}
|
|
1307
1345
|
canRenderChart(){
|
|
@@ -1323,21 +1361,21 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
1323
1361
|
});
|
|
1324
1362
|
},true)
|
|
1325
1363
|
} else {
|
|
1326
|
-
const cb = (
|
|
1364
|
+
const cb = (config)=>{
|
|
1327
1365
|
setTimeout(()=>{
|
|
1328
1366
|
this.setIsLoading(true,()=>{
|
|
1329
|
-
this.setState({
|
|
1367
|
+
this.setState({config,displayType},()=>{
|
|
1330
1368
|
this.persistDisplayType(displayType);
|
|
1331
1369
|
})
|
|
1332
1370
|
},true);
|
|
1333
1371
|
},200);
|
|
1334
1372
|
}
|
|
1335
1373
|
if(!this.isValidChartConfig()){
|
|
1336
|
-
return this.configureChart(false).then((
|
|
1337
|
-
cb(
|
|
1374
|
+
return this.configureChart(false).then((config)=>{
|
|
1375
|
+
cb(config);
|
|
1338
1376
|
});
|
|
1339
1377
|
}
|
|
1340
|
-
cb({...this.state.
|
|
1378
|
+
cb({...this.state.config});
|
|
1341
1379
|
}
|
|
1342
1380
|
}
|
|
1343
1381
|
getActiveAggregatorFunction(){
|
|
@@ -1421,7 +1459,7 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
1421
1459
|
/>
|
|
1422
1460
|
}
|
|
1423
1461
|
configureSectionLists(){
|
|
1424
|
-
const config = this.
|
|
1462
|
+
const config = this.getConfig();
|
|
1425
1463
|
return new Promise((resolve)=>{
|
|
1426
1464
|
DialogProvider.open({
|
|
1427
1465
|
title : "Paramètres de groupe",
|
|
@@ -1445,13 +1483,13 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
1445
1483
|
text : "Configurer",
|
|
1446
1484
|
icon : "check",
|
|
1447
1485
|
onPress : ({data})=>{
|
|
1448
|
-
const
|
|
1449
|
-
this.setSessionData("
|
|
1486
|
+
const nConfig = {...config,...data};
|
|
1487
|
+
this.setSessionData("config",nConfig);
|
|
1450
1488
|
DialogProvider.close();
|
|
1451
1489
|
this.setIsLoading(true,true);
|
|
1452
|
-
this.prepareData({data:this.INITIAL_STATE.data,config:
|
|
1453
|
-
this.setState({...state,
|
|
1454
|
-
resolve(
|
|
1490
|
+
this.prepareData({data:this.INITIAL_STATE.data,config:nConfig},(state)=>{
|
|
1491
|
+
this.setState({...state,config:nConfig},()=>{
|
|
1492
|
+
resolve(nConfig)
|
|
1455
1493
|
})
|
|
1456
1494
|
})
|
|
1457
1495
|
}
|
|
@@ -1464,7 +1502,7 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
1464
1502
|
if(!this.isChartRendable()){
|
|
1465
1503
|
return Promise.reject({message:'Impossible de configurer le graphe car le type de données ne permet pas de rendu de type graphe'});
|
|
1466
1504
|
}
|
|
1467
|
-
const xItems = {},yItems = {},config = defaultObj(this.state.
|
|
1505
|
+
const xItems = {},yItems = {},config = defaultObj(this.state.config);
|
|
1468
1506
|
const series = {},seriesGroups = {};
|
|
1469
1507
|
const footers = this.getFootersFields();
|
|
1470
1508
|
const isValidConfig = this.isValidChartConfig();
|
|
@@ -1496,7 +1534,7 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
1496
1534
|
}
|
|
1497
1535
|
}
|
|
1498
1536
|
return new Promise((resolve,reject)=>{
|
|
1499
|
-
const data = this.
|
|
1537
|
+
const data = this.getConfig();
|
|
1500
1538
|
DialogProvider.open({
|
|
1501
1539
|
title : 'Configuration des graphes',
|
|
1502
1540
|
subtitle : false,
|
|
@@ -1608,23 +1646,23 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
1608
1646
|
text : "Configurer",
|
|
1609
1647
|
icon : "check",
|
|
1610
1648
|
onPress : ({data})=>{
|
|
1611
|
-
const
|
|
1612
|
-
this.setSessionData("
|
|
1649
|
+
const nConfig = {...config,...data};
|
|
1650
|
+
this.setSessionData("config",nConfig);
|
|
1613
1651
|
DialogProvider.close();
|
|
1614
1652
|
if(!isValidConfig && refreshChart !== false){
|
|
1615
|
-
return this.setState({
|
|
1616
|
-
resolve(
|
|
1653
|
+
return this.setState({config:nConfig},()=>{
|
|
1654
|
+
resolve(nConfig)
|
|
1617
1655
|
})
|
|
1618
1656
|
}
|
|
1619
|
-
resolve(
|
|
1657
|
+
resolve(nConfig);
|
|
1620
1658
|
}
|
|
1621
1659
|
}
|
|
1622
1660
|
]
|
|
1623
1661
|
})
|
|
1624
1662
|
})
|
|
1625
1663
|
}
|
|
1626
|
-
|
|
1627
|
-
return defaultObj(this.state.
|
|
1664
|
+
getConfig(){
|
|
1665
|
+
return defaultObj(this.state.config);
|
|
1628
1666
|
}
|
|
1629
1667
|
getChartIsRendableArgs(){
|
|
1630
1668
|
return {
|
|
@@ -1640,7 +1678,7 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
1640
1678
|
downloadChart(){
|
|
1641
1679
|
if(!this.chartRef.current || !this.chartRef.current.dataURI) return Promise.reject({message:'Référence du graphique non valide'});
|
|
1642
1680
|
return this.chartRef.current.dataURI().then(({ imgURI, blob })=>{
|
|
1643
|
-
const config = this.
|
|
1681
|
+
const config = this.getConfig();
|
|
1644
1682
|
const fileName = sprintf(defaultStr(config.fileName,config.title,"graphe"));
|
|
1645
1683
|
FileSystem.write({content:imgURI,fileName})
|
|
1646
1684
|
});
|
|
@@ -1890,9 +1928,9 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
1890
1928
|
text : "Configurer les graphes",
|
|
1891
1929
|
icon :"material-settings",
|
|
1892
1930
|
onPress : ()=>{
|
|
1893
|
-
this.configureChart(false).then((
|
|
1931
|
+
this.configureChart(false).then((config)=>{
|
|
1894
1932
|
this.setIsLoading(true,()=>{
|
|
1895
|
-
this.setState({
|
|
1933
|
+
this.setState({config});
|
|
1896
1934
|
},true)
|
|
1897
1935
|
})
|
|
1898
1936
|
}
|
|
@@ -1968,7 +2006,7 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
1968
2006
|
* @param {object} de la forme suivante :
|
|
1969
2007
|
* @param {object} chartType le type de chart, l'un des types du tableau displayTypes en haut du présent fichier
|
|
1970
2008
|
* @param {object} yAxisColumn la colonne de l'axe vertical y
|
|
1971
|
-
* @param {object} xAxisColumn la colonne de l'axe des x de la courbe, pris dans les configurations du chart,
|
|
2009
|
+
* @param {object} xAxisColumn la colonne de l'axe des x de la courbe, pris dans les configurations du chart, config
|
|
1972
2010
|
* @param {object} la fonction d'aggrégation, l'une des fonctions issues des fonctions d'aggrégations aggregatorsFuncions, @see : dans $components/Datagrid/Footer
|
|
1973
2011
|
* en affichage des tableaux de type sectionList, seul les colonnes de totalisation sont utilisées pour l'affichage du graphe
|
|
1974
2012
|
* Le nombre de graphes (series) à afficher est valable pour tous les graphes sauf les graphes de type pie/donut.
|
|
@@ -1977,12 +2015,12 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
1977
2015
|
getSectionListHeadersChartOptions({chartType,yAxisColumn,xAxisColumn,aggregatorFunction}){
|
|
1978
2016
|
if(!this.isSectionList()) return null;
|
|
1979
2017
|
if(!isObj(chartType) || !isObj(yAxisColumn) || !yAxisColumn.field) return null;
|
|
1980
|
-
if(!isValidAggregator(aggregatorFunction)){
|
|
2018
|
+
if(!this.isValidAggregator(aggregatorFunction)){
|
|
1981
2019
|
aggregatorFunction = this.getActiveAggregatorFunction();
|
|
1982
2020
|
}
|
|
1983
2021
|
const code = aggregatorFunction.code;
|
|
1984
2022
|
const isDonut = chartType.isDonut || chartType.isRadial;
|
|
1985
|
-
const config = this.
|
|
2023
|
+
const config = this.getConfig();
|
|
1986
2024
|
//@see : https://apexcharts.com/docs/series/
|
|
1987
2025
|
///lorsqu'on affiche uniquement les totaux des sections, alors la visualition se fait sur uniquement sur la base des valeurs
|
|
1988
2026
|
///on parcoure uniquement les entêtes des sectionLis
|
|
@@ -2076,7 +2114,7 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
2076
2114
|
return null;
|
|
2077
2115
|
}
|
|
2078
2116
|
const isDonut = chartType.isDonut || chartType.isRadial;
|
|
2079
|
-
const config = this.
|
|
2117
|
+
const config = this.getConfig();
|
|
2080
2118
|
if(!this.state.columns[config.y]) return null;
|
|
2081
2119
|
const yAxisColumn = this.state.columns[config.y];
|
|
2082
2120
|
const type = defaultStr(yAxisColumn.jsType,yAxisColumn.type).toLowerCase();
|
|
@@ -2453,6 +2491,9 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
2453
2491
|
},
|
|
2454
2492
|
title : title,
|
|
2455
2493
|
icon : visible?CHECKED_ICON_NAME : null,
|
|
2494
|
+
right : false ? (p)=><Icon {...p} icon="material-gear"
|
|
2495
|
+
onPress = {(e)=>{console.log(e," is pressed toddd config")}}
|
|
2496
|
+
/> : undefined
|
|
2456
2497
|
});
|
|
2457
2498
|
restCol.field = header.field;
|
|
2458
2499
|
|
|
@@ -2636,7 +2677,7 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
2636
2677
|
prepareData(args,cb){
|
|
2637
2678
|
let {pagination,config,aggregatorFunction:customAggregatorFunction,displayOnlySectionListHeaders:cdisplayOnlySectionListHeaders,data,force,sectionListColumns,updateFooters} = defaultObj(args);
|
|
2638
2679
|
cb = typeof cb ==='function'? cb : typeof args.cb == 'function'? args.cb : undefined;
|
|
2639
|
-
config = isObj(config) && Object.size(config,true)? config : this.
|
|
2680
|
+
config = isObj(config) && Object.size(config,true)? config : this.getConfig();
|
|
2640
2681
|
const aggregatorFunction = isNonNullString(customAggregatorFunction) && customAggregatorFunction in this.aggregatorFunctions ? this.aggregatorFunctions[customAggregatorFunction] : this.getActiveAggregatorFunction();
|
|
2641
2682
|
sectionListColumns = isObj(sectionListColumns) ? sectionListColumns : this.state.sectionListColumns;
|
|
2642
2683
|
const displayOnlySectionListHeaders = typeof cdisplayOnlySectionListHeaders == 'boolean'?cdisplayOnlySectionListHeaders : this.state.displayOnlySectionListHeaders;
|
|
@@ -2766,9 +2807,9 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
2766
2807
|
if(this.getSectionListHeaderProp){
|
|
2767
2808
|
return this.getSectionListHeaderProp(args);
|
|
2768
2809
|
}
|
|
2769
|
-
const
|
|
2770
|
-
const displayGroupLabels = "displayGroupLabels" in
|
|
2771
|
-
const displayGroupLabelsSeparator = typeof
|
|
2810
|
+
const config = isObj(args.config) && Object.size(args.config,true)? args.config : this.getConfig();
|
|
2811
|
+
const displayGroupLabels = "displayGroupLabels" in config? config.displayGroupLabels : true;
|
|
2812
|
+
const displayGroupLabelsSeparator = typeof config.displayGroupLabelsSeparator =='string'? config.displayGroupLabelsSeparator : arrayValueSeparator;
|
|
2772
2813
|
const {fields,sectionListColumnsSize} = args;
|
|
2773
2814
|
const d = [];
|
|
2774
2815
|
Object.map(fields,(field,i)=>{
|
|
@@ -2780,7 +2821,7 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
2780
2821
|
columnField : defaultStr(field.field,i),
|
|
2781
2822
|
});
|
|
2782
2823
|
if(!isNonNullString(txt) && typeof txt !=='number') return;
|
|
2783
|
-
if(
|
|
2824
|
+
if(!displayGroupLabels){
|
|
2784
2825
|
d.push(txt);
|
|
2785
2826
|
} else {
|
|
2786
2827
|
d.push("{0} : {1}".sprintf(defaultStr(field.label,field.txt),txt))
|
|
@@ -3069,23 +3110,117 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
3069
3110
|
this.previousDataSources = dataSources;
|
|
3070
3111
|
this.previousServer = server;
|
|
3071
3112
|
}
|
|
3113
|
+
prepareFetchData(fetchData){
|
|
3114
|
+
this.INITIAL_STATE.fetchData = defaultVal(fetchData,this.props.fetchData);
|
|
3115
|
+
}
|
|
3072
3116
|
beforeFetchData(){}
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
|
|
3082
|
-
|
|
3083
|
-
|
|
3084
|
-
|
|
3085
|
-
|
|
3117
|
+
/**** retourne la liste des items, utile lorsqu'une s'agit d'une fonction
|
|
3118
|
+
Lorsque data est une chaine de caractère, alors elle doit être sous la forme recommandée par la function
|
|
3119
|
+
getDataFunc de l'object dataSource
|
|
3120
|
+
la props data, peut être une chaine de caractère contenant le nom de la base et de la bd de travail de l'application
|
|
3121
|
+
example common[articles], dans ce cas, la fonction fetchData, aura pour rôle de chercher toutes les données qui match
|
|
3122
|
+
la table dans la base common.
|
|
3123
|
+
Elle pourra éventuellement passer directement la limite et les filtres à la fonction fetchdata
|
|
3124
|
+
*/
|
|
3125
|
+
fetchData ({cb,callback,force,fetchOptions,...rest}){
|
|
3126
|
+
if(!this._isMounted()) return Promise.resolve(this.state.data);
|
|
3127
|
+
if(this.isFetchingData) {
|
|
3128
|
+
if(!isPromise(this.fetchingPromiseData)){
|
|
3129
|
+
this.fetchingPromiseData = Promise.resolve(this.state.data)
|
|
3086
3130
|
}
|
|
3087
|
-
|
|
3088
|
-
|
|
3131
|
+
return this.fetchingPromiseData;
|
|
3132
|
+
};
|
|
3133
|
+
this.isFetchingData = true;
|
|
3134
|
+
cb = typeof cb =='function'? cb : typeof callback =='function'? callback : undefined;
|
|
3135
|
+
this.fetchingPromiseData = new Promise((resolve,reject)=>{
|
|
3136
|
+
setTimeout(()=>{
|
|
3137
|
+
if(typeof cb === 'boolean'){
|
|
3138
|
+
force = cb;
|
|
3139
|
+
cb = undefined;
|
|
3140
|
+
}
|
|
3141
|
+
fetchOptions = this.getFetchOptions({fetchOptions,convertToSQL:false});
|
|
3142
|
+
if(typeof this.props.fetchOptionsMutator =='function' && this.props.fetchOptionsMutator(fetchOptions) === false){
|
|
3143
|
+
this.isFetchingData = false;
|
|
3144
|
+
return resolve(this.state.data);
|
|
3145
|
+
}
|
|
3146
|
+
if(this.beforeFetchData(fetchOptions) === false) return resolve(this.state.data);
|
|
3147
|
+
if(this.willConvertFiltersToSQL()){
|
|
3148
|
+
fetchOptions.selector = convertToSQL(fetchOptions.selector);
|
|
3149
|
+
}
|
|
3150
|
+
if(typeof this.props.beforeFetchData =='function' && this.props.beforeFetchData({...rest,context:this,force,fetchOptions,options:fetchOptions}) === false){
|
|
3151
|
+
this.isFetchingData = false;
|
|
3152
|
+
return resolve(this.state.data);
|
|
3153
|
+
}
|
|
3154
|
+
if(force !== true && isArray(this.INITIAL_STATE.data)) {
|
|
3155
|
+
return this.resolveFetchedDataPromise({cb,data:this.INITIAL_STATE.data}).then(resolve).catch(reject)
|
|
3156
|
+
}
|
|
3157
|
+
let fetchData = this.INITIAL_STATE.fetchData;
|
|
3158
|
+
if(isFunction(this.props.fetchData)){
|
|
3159
|
+
/**** l'on peut définir la props fetchData, qui est la fonction appelée pour la recherche des données */
|
|
3160
|
+
fetchData = this.props.fetchData.call(this,fetchOptions);
|
|
3161
|
+
}
|
|
3162
|
+
fetchData = isFunction(fetchData)? fetchData.call(this,fetchOptions) : fetchData;
|
|
3163
|
+
this.setIsLoading(true,()=>{
|
|
3164
|
+
if(isPromise(fetchData)){
|
|
3165
|
+
return fetchData.then(data=>{
|
|
3166
|
+
return this.resolveFetchedDataPromise({cb,data,force}).then((data)=>{
|
|
3167
|
+
resolve(data);
|
|
3168
|
+
}).catch((e)=>{
|
|
3169
|
+
console.log(e,' fetching datagrid data')
|
|
3170
|
+
reject(e);
|
|
3171
|
+
});
|
|
3172
|
+
}).catch((e)=>{
|
|
3173
|
+
console.log(e," resolve fetching data for datagrid");
|
|
3174
|
+
return this.resolveFetchedDataPromise({cb,data:[],force}).then((data)=>{
|
|
3175
|
+
resolve(data);
|
|
3176
|
+
}).catch((e)=>{
|
|
3177
|
+
console.log(e,' fetching datagrid data')
|
|
3178
|
+
reject(e);
|
|
3179
|
+
});;
|
|
3180
|
+
})
|
|
3181
|
+
} else {
|
|
3182
|
+
let data = !isPromise(fetchData)? Object.toArray(fetchData) : [];
|
|
3183
|
+
///if(data.length <=0) data = this.state.data;
|
|
3184
|
+
return this.resolveFetchedDataPromise({cb,data,force}).then((data)=>{
|
|
3185
|
+
resolve(data);
|
|
3186
|
+
}).catch((e)=>{
|
|
3187
|
+
console.log(e,' fetching datagrid data')
|
|
3188
|
+
reject(e);
|
|
3189
|
+
});
|
|
3190
|
+
}
|
|
3191
|
+
},true);
|
|
3192
|
+
},1);
|
|
3193
|
+
})
|
|
3194
|
+
return this.fetchingPromiseData;
|
|
3195
|
+
}
|
|
3196
|
+
resolveFetchedDataPromise(arg){
|
|
3197
|
+
arg = defaultObj(arg);
|
|
3198
|
+
const d = arg.data;
|
|
3199
|
+
if(isObj(d) && d.data && typeof d.data ==='object'){
|
|
3200
|
+
arg.data = d.data;
|
|
3201
|
+
arg.total = defaultNumber(arg.total,arg.data.total);
|
|
3202
|
+
}
|
|
3203
|
+
/*if(typeof arg.total != 'number'){
|
|
3204
|
+
arg.total = Object.size(arg.data);
|
|
3205
|
+
}*/
|
|
3206
|
+
const {cb,total,data} = arg;
|
|
3207
|
+
return new Promise((resolve)=>{
|
|
3208
|
+
this.prepareData(arg,(state)=>{
|
|
3209
|
+
state.data = Array.isArray(state.data)? state.data : [];
|
|
3210
|
+
if(typeof this.props.onFetchData =='function'){
|
|
3211
|
+
this.props.onFetchData({...arg,allData:data,context:this,props:this.props,data:state.data})
|
|
3212
|
+
}
|
|
3213
|
+
this.setState(state,()=>{
|
|
3214
|
+
if(isFunction(cb)) {
|
|
3215
|
+
cb(data)
|
|
3216
|
+
}
|
|
3217
|
+
resolve(data);
|
|
3218
|
+
this.isRenderingRef.current = false;
|
|
3219
|
+
this.isFetchingData = undefined;
|
|
3220
|
+
this.setIsLoading(false,false);
|
|
3221
|
+
})
|
|
3222
|
+
});
|
|
3223
|
+
})
|
|
3089
3224
|
}
|
|
3090
3225
|
/**** Filtre le tableau */
|
|
3091
3226
|
doFilter ({value,field,selector,event,force}){
|
|
@@ -3115,8 +3250,7 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
3115
3250
|
this._pagination.page = 1;
|
|
3116
3251
|
this._pagination.start = 0;
|
|
3117
3252
|
}
|
|
3118
|
-
this.
|
|
3119
|
-
return this.fetchData({force:true,isFiltering : true,fetchOptions:this.filtersSelectors});
|
|
3253
|
+
return this.fetchData({force:true});
|
|
3120
3254
|
}
|
|
3121
3255
|
onSetQueryLimit(){
|
|
3122
3256
|
if(!this.canSetQueryLimit()) return;
|
|
@@ -3169,6 +3303,35 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
3169
3303
|
</Pressable>
|
|
3170
3304
|
</Tooltip>
|
|
3171
3305
|
}
|
|
3306
|
+
/*** récupère les fetchOptions du datagrid */
|
|
3307
|
+
getFetchOptions({fetchOptions,convertToSQL}){
|
|
3308
|
+
const fetchFilters = this.getFilters({convertToSQL:typeof convertToSQL =='boolean'? convertToSQL : false});
|
|
3309
|
+
fetchOptions = Object.clone(isObj(fetchOptions)? fetchOptions : {});
|
|
3310
|
+
fetchOptions.selector = defaultObj(fetchOptions.selector);
|
|
3311
|
+
fetchOptions.dataSources = this.currentDataSources;
|
|
3312
|
+
fetchOptions.selector = fetchFilters;
|
|
3313
|
+
fetchOptions.sort = this.getSort();
|
|
3314
|
+
const ff = this.getFilterableColumnsNames();
|
|
3315
|
+
let fields = ff;
|
|
3316
|
+
if(this.isFetchOnlyVisibleColumnsEnabled()){
|
|
3317
|
+
fields = [];
|
|
3318
|
+
Object.map(ff,(field)=>{
|
|
3319
|
+
if(isNonNullString(field) && isObj(this.state.columns[field]) && this.state.columns[field].visible !== false){
|
|
3320
|
+
fields.push(field);
|
|
3321
|
+
}
|
|
3322
|
+
});
|
|
3323
|
+
}
|
|
3324
|
+
fetchOptions.fields = fields;
|
|
3325
|
+
let limit = this.getQueryLimit();
|
|
3326
|
+
if(limit > 0 && !this.isPivotDatagrid()){
|
|
3327
|
+
fetchOptions.limit = limit;
|
|
3328
|
+
} else {
|
|
3329
|
+
if(!isDecimal(fetchOptions.limit) || fetchOptions.limit <=0){
|
|
3330
|
+
delete fetchOptions.limit
|
|
3331
|
+
}
|
|
3332
|
+
}
|
|
3333
|
+
return fetchOptions;
|
|
3334
|
+
}
|
|
3172
3335
|
getFetchDataOpts(){
|
|
3173
3336
|
return this.props.fetchDataOpts;
|
|
3174
3337
|
}
|
|
@@ -3272,16 +3435,20 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
3272
3435
|
canSetIsLoading(){
|
|
3273
3436
|
return isObj(this.progressBarRef.current) && typeof this.progressBarRef.current.setIsLoading =='function' ? true : false;
|
|
3274
3437
|
}
|
|
3438
|
+
canHidePreloaderOnRender(){
|
|
3439
|
+
const cH = this[this.hidePreloaderOnRenderKey];
|
|
3440
|
+
return typeof cH =='boolean'? cH : true;
|
|
3441
|
+
}
|
|
3442
|
+
toggleHidePreloaderOnRender(toggle){
|
|
3443
|
+
this[this.hidePreloaderOnRenderKey] = !!toggle;
|
|
3444
|
+
}
|
|
3275
3445
|
onRender(){
|
|
3276
|
-
if(
|
|
3277
|
-
|
|
3278
|
-
|
|
3279
|
-
if(this.isRenderingRef.current === true){
|
|
3280
|
-
//setTimeout(()=>{
|
|
3281
|
-
this.isRenderingRef.current = false;
|
|
3282
|
-
return this.setIsLoading(false,undefined,undefined,"yes mannnnaaaaaa");
|
|
3283
|
-
//},500);
|
|
3446
|
+
if(!this.canHidePreloaderOnRender()) return ;
|
|
3447
|
+
if(typeof this.props.onRender ==='function' && this.props.onRender({context:this}) === false){
|
|
3448
|
+
return ;
|
|
3284
3449
|
}
|
|
3450
|
+
this.isRenderingRef.current = false;
|
|
3451
|
+
return this.setIsLoading(false,undefined,undefined);
|
|
3285
3452
|
}
|
|
3286
3453
|
/***
|
|
3287
3454
|
* @param {boolean} loading
|
|
@@ -3749,6 +3916,10 @@ CommonDatagridComponent.propTypes = {
|
|
|
3749
3916
|
renderCustomPagination : PropTypes.func,
|
|
3750
3917
|
getActionsArgs : PropTypes.func,//fonction permettant de récupérer les props supplémentaires à passer aux actions du datagrid
|
|
3751
3918
|
displayOnlySectionListHeaders : PropTypes.bool,// si uniquement les entêtes des sections seront affichés, valides uniquement en affichage des sectionHeader
|
|
3919
|
+
/***les props de configuration du chart, */
|
|
3920
|
+
config : PropTypes.shape({
|
|
3921
|
+
aggregatorFunction : PropTypes.string, //la fonction d'aggrégation à utiliser
|
|
3922
|
+
}),
|
|
3752
3923
|
/*** les options de configuration du graphe */
|
|
3753
3924
|
chartConfig : PropTypes.shape({
|
|
3754
3925
|
//type : PropTypes.oneOfType(chartDisplayType).isRequired,//le type de graphe : l'une des valeurs parmis les éléments cités plus haut
|
|
@@ -3771,6 +3942,9 @@ CommonDatagridComponent.propTypes = {
|
|
|
3771
3942
|
aggregatorFunction : PropTypes.string,
|
|
3772
3943
|
/*** permet de faire une mutation sur les options de la recherche, immédiatement avant le lancement de la recherche */
|
|
3773
3944
|
fetchOptionsMutator : PropTypes.func,
|
|
3945
|
+
/*** si les données à récupérer à distance seront */
|
|
3946
|
+
fetchOnlyVisibleColumns : PropTypes.bool,
|
|
3947
|
+
canFetchOnlyVisibleColumns : PropTypes.bool,//si l'on peut modifier le type d'affichage lié à la possibilité de récupérer uniquement les données reletives aux colonnes visibles
|
|
3774
3948
|
useLinesProgressBar : PropTypes.bool,//si le progress bar lignes horizontale seront utilisés
|
|
3775
3949
|
abreviateValues : PropTypes.bool, //si les valeurs numériques seront abregées
|
|
3776
3950
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import CommonDatagrid from "./Common";
|
|
2
2
|
import {defaultObj,extendObj,defaultStr,isNonNullString,isFunction,isPromise} from "$utils";
|
|
3
3
|
import PropTypes from "prop-types";
|
|
4
|
-
import {convertToSQL} from "$ecomponents/Filter";
|
|
5
4
|
import actions from "$actions";
|
|
6
5
|
/****
|
|
7
6
|
* la fonction fetchOptionsMutator permet éventuellemnt de faire une mutations sur les options fetchOptions avant qu'elle ne soit appliquée pour la recherche. elle
|
|
@@ -18,16 +17,13 @@ export default class CommonTableDatagrid extends CommonDatagrid{
|
|
|
18
17
|
} = props;
|
|
19
18
|
dataSource = CommonDatagrid.getDataSource({...props,dataSource,context:this});
|
|
20
19
|
tableName = defaultStr(tableName,table).toUpperCase();
|
|
21
|
-
this.prepareFetchData();
|
|
22
20
|
if(tableName){
|
|
23
21
|
Object.defineProperties(this,{
|
|
24
22
|
tableName : {value:tableName,override:false,writable:false}
|
|
25
23
|
})
|
|
26
24
|
}
|
|
27
25
|
}
|
|
28
|
-
|
|
29
|
-
this.INITIAL_STATE.fetchData = defaultVal(fetchData,this.props.fetchData);
|
|
30
|
-
}
|
|
26
|
+
|
|
31
27
|
/*** lorsque la données est modifiée */
|
|
32
28
|
onUpsertData =(arg) =>{
|
|
33
29
|
if(!this._isMounted()) return;
|
|
@@ -61,127 +57,10 @@ export default class CommonTableDatagrid extends CommonDatagrid{
|
|
|
61
57
|
isTableData(){
|
|
62
58
|
return true;
|
|
63
59
|
}
|
|
64
|
-
|
|
65
60
|
getProgressBar(props){
|
|
66
61
|
if(this.isDataJustComeToUpsert) return null;
|
|
67
62
|
return super.getProgressBar(props);
|
|
68
63
|
}
|
|
69
|
-
/**** retourne la liste des items, utile lorsqu'une s'agit d'une fonction
|
|
70
|
-
Lorsque data est une chaine de caractère, alors elle doit être sous la forme recommandée par la function
|
|
71
|
-
getDataFunc de l'object dataSource
|
|
72
|
-
la props data, peut être une chaine de caractère contenant le nom de la base et de la bd de travail de l'application
|
|
73
|
-
example common[articles], dans ce cas, la fonction fetchData, aura pour rôle de chercher toutes les données qui match
|
|
74
|
-
la table dans la base common.
|
|
75
|
-
Elle pourra éventuellement passer directement la limite et les filtres à la fonction fetchdata
|
|
76
|
-
*/
|
|
77
|
-
fetchData ({cb,callback,force,fetchOptions,...rest}){
|
|
78
|
-
if(!this._isMounted()) return Promise.resolve(this.state.data);
|
|
79
|
-
if(this.isFetchingData) {
|
|
80
|
-
if(!isPromise(this.fetchingPromiseData)){
|
|
81
|
-
this.fetchingPromiseData = Promise.resolve(this.state.data)
|
|
82
|
-
}
|
|
83
|
-
return this.fetchingPromiseData;
|
|
84
|
-
};
|
|
85
|
-
this.isFetchingData = true;
|
|
86
|
-
cb = typeof cb =='function'? cb : typeof callback =='function'? callback : undefined;
|
|
87
|
-
this.fetchingPromiseData = new Promise((resolve,reject)=>{
|
|
88
|
-
setTimeout(()=>{
|
|
89
|
-
if(typeof cb === 'boolean'){
|
|
90
|
-
force = cb;
|
|
91
|
-
cb = undefined;
|
|
92
|
-
}
|
|
93
|
-
const fetchFilters = this.getFilters({convertToSQL:false});
|
|
94
|
-
fetchOptions = defaultObj(fetchOptions);
|
|
95
|
-
fetchOptions = Object.clone(fetchOptions);
|
|
96
|
-
fetchOptions.selector = defaultObj(fetchOptions.selector);
|
|
97
|
-
fetchOptions.dataSources = this.currentDataSources;
|
|
98
|
-
fetchOptions = extendObj(true,true,{},fetchOptions,{selector : fetchFilters});
|
|
99
|
-
fetchOptions.dataSources = this.currentDataSources;
|
|
100
|
-
fetchOptions.sort = this.getSort();
|
|
101
|
-
fetchOptions.fields = this.getFilterableColumnsNames();
|
|
102
|
-
let limit = this.getQueryLimit();
|
|
103
|
-
if(limit > 0 && !this.isPivotDatagrid()){
|
|
104
|
-
fetchOptions.limit = limit;
|
|
105
|
-
} else {
|
|
106
|
-
if(!isDecimal(fetchOptions.limit) || fetchOptions.limit <=0){
|
|
107
|
-
delete fetchOptions.limit
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
if(typeof this.props.fetchOptionsMutator =='function' && this.props.fetchOptionsMutator(fetchOptions) === false){
|
|
111
|
-
this.isFetchingData = false;
|
|
112
|
-
return resolve(this.state.data);
|
|
113
|
-
}
|
|
114
|
-
this.beforeFetchData(fetchOptions);
|
|
115
|
-
if(this.willConvertFiltersToSQL()){
|
|
116
|
-
fetchOptions.selector = convertToSQL(fetchOptions.selector);
|
|
117
|
-
}
|
|
118
|
-
if(typeof this.props.beforeFetchData =='function' && this.props.beforeFetchData({...rest,context:this,force,fetchOptions,options:fetchOptions}) === false){
|
|
119
|
-
this.isFetchingData = false;
|
|
120
|
-
return resolve(this.state.data);
|
|
121
|
-
}
|
|
122
|
-
if(force !== true && isArray(this.INITIAL_STATE.data)) {
|
|
123
|
-
return this.resolveFetchedDataPromise({cb,data:this.INITIAL_STATE.data}).then(resolve).catch(reject)
|
|
124
|
-
}
|
|
125
|
-
let fetchData = this.INITIAL_STATE.fetchData;
|
|
126
|
-
if(isFunction(this.props.fetchData)){
|
|
127
|
-
/**** l'on peut définir la props fetchData, qui est la fonction appelée pour la recherche des données */
|
|
128
|
-
fetchData = this.props.fetchData.call(this,fetchOptions);
|
|
129
|
-
}
|
|
130
|
-
fetchData = isFunction(fetchData)? fetchData.call(this,fetchOptions) : fetchData;
|
|
131
|
-
this.setIsLoading(true,()=>{
|
|
132
|
-
if(isPromise(fetchData)){
|
|
133
|
-
return fetchData.then(data=>{
|
|
134
|
-
return this.resolveFetchedDataPromise({cb,data,force}).then((data)=>{
|
|
135
|
-
resolve(data);
|
|
136
|
-
}).catch((e)=>{
|
|
137
|
-
console.log(e,' fetching datagrid data')
|
|
138
|
-
reject(e);
|
|
139
|
-
});
|
|
140
|
-
}).catch((e)=>{
|
|
141
|
-
console.log(e," resolve fetching data for datagrid");
|
|
142
|
-
return this.resolveFetchedDataPromise({cb,data:[],force}).then((data)=>{
|
|
143
|
-
resolve(data);
|
|
144
|
-
}).catch((e)=>{
|
|
145
|
-
console.log(e,' fetching datagrid data')
|
|
146
|
-
reject(e);
|
|
147
|
-
});;
|
|
148
|
-
})
|
|
149
|
-
} else {
|
|
150
|
-
let data = !isPromise(fetchData)? Object.toArray(fetchData) : [];
|
|
151
|
-
///if(data.length <=0) data = this.state.data;
|
|
152
|
-
return this.resolveFetchedDataPromise({cb,data,force}).then((data)=>{
|
|
153
|
-
resolve(data);
|
|
154
|
-
}).catch((e)=>{
|
|
155
|
-
console.log(e,' fetching datagrid data')
|
|
156
|
-
reject(e);
|
|
157
|
-
});
|
|
158
|
-
}
|
|
159
|
-
},true);
|
|
160
|
-
},1);
|
|
161
|
-
})
|
|
162
|
-
return this.fetchingPromiseData;
|
|
163
|
-
}
|
|
164
|
-
resolveFetchedDataPromise(arg){
|
|
165
|
-
arg = defaultObj(arg);
|
|
166
|
-
const {cb,data} = arg;
|
|
167
|
-
return new Promise((resolve)=>{
|
|
168
|
-
this.prepareData(arg,(state)=>{
|
|
169
|
-
state.data = Array.isArray(state.data)? state.data : [];
|
|
170
|
-
if(typeof this.props.onFetchData =='function'){
|
|
171
|
-
this.props.onFetchData({...arg,allData:data,context:this,props:this.props,data:state.data})
|
|
172
|
-
}
|
|
173
|
-
this.setState(state,()=>{
|
|
174
|
-
if(isFunction(cb)) {
|
|
175
|
-
cb(data)
|
|
176
|
-
}
|
|
177
|
-
resolve(data);
|
|
178
|
-
this.isRenderingRef.current = false;
|
|
179
|
-
this.isFetchingData = undefined;
|
|
180
|
-
this.setIsLoading(false,false);
|
|
181
|
-
})
|
|
182
|
-
});
|
|
183
|
-
})
|
|
184
|
-
}
|
|
185
64
|
}
|
|
186
65
|
|
|
187
66
|
CommonTableDatagrid.propTypes = {
|
|
@@ -10,6 +10,7 @@ import Label from "$ecomponents/Label";
|
|
|
10
10
|
import TableLink from "$TableLink";
|
|
11
11
|
import {Flag} from "$ecomponents/Countries";
|
|
12
12
|
import { StyleSheet } from "react-native";
|
|
13
|
+
import {isDesktopMedia} from "$dimensions";
|
|
13
14
|
|
|
14
15
|
export const renderRowCell = (arg)=>{
|
|
15
16
|
let {rowData,getRowKey,context,formatValue:customFormatValue,renderRowCell:customRenderRowCell,abreviateValues,isSectionListHeader,rowIndex,index,rowCounterIndex,columnDef,columnField} = arg;
|
|
@@ -198,5 +199,9 @@ export const formatValue = (value,format,abreviateValues,formatter)=>{
|
|
|
198
199
|
return abreviateValues ? value.abreviate() : value.formatNumber();
|
|
199
200
|
}
|
|
200
201
|
|
|
202
|
+
export const getRowsPerPagesLimits = ()=>{
|
|
203
|
+
return [5,10,15,20,25,30,40,50,60,80,100,500,1000,1500,2000,2500,3000,3500,4000,4500,5000,...(isDesktopMedia() ? [6000,7000,8000,9000,10000]:[])];
|
|
204
|
+
}
|
|
205
|
+
|
|
201
206
|
|
|
202
207
|
export const arrayValueSeparator = ", ";
|
|
@@ -8,7 +8,6 @@
|
|
|
8
8
|
import Datagrid from "./IndexComponent";
|
|
9
9
|
import {defaultStr,defaultObj,defaultVal,isNonNullString,defaultNumber,isObjOrArray,isObj,extendObj} from "$utils";
|
|
10
10
|
import {Pressable} from "react-native";
|
|
11
|
-
import SimpleSelect from "$ecomponents/SimpleSelect";
|
|
12
11
|
import React from "$react";
|
|
13
12
|
import Auth from "$cauth";
|
|
14
13
|
import DateLib from "$lib/date";
|
|
@@ -20,13 +19,10 @@ import Icon from "$ecomponents/Icon";
|
|
|
20
19
|
import Label from "$ecomponents/Label";
|
|
21
20
|
import { StyleSheet,View } from "react-native";
|
|
22
21
|
import theme from "$theme";
|
|
23
|
-
import useSWR
|
|
22
|
+
import useSWR from "$swr";
|
|
24
23
|
import appConfig from "$capp/config";
|
|
25
|
-
import
|
|
26
|
-
|
|
24
|
+
import {getRowsPerPagesLimits} from "./Common/utils";
|
|
27
25
|
import PropTypes from "prop-types";
|
|
28
|
-
import {isDesktopMedia} from "$dimensions";
|
|
29
|
-
import ActivityIndicator from "$ecomponents/ActivityIndicator";
|
|
30
26
|
import {Menu} from "$ecomponents/BottomSheet";
|
|
31
27
|
import session from "$session";
|
|
32
28
|
|
|
@@ -69,9 +65,7 @@ export const getSWROptions = ()=>{
|
|
|
69
65
|
}
|
|
70
66
|
}
|
|
71
67
|
|
|
72
|
-
|
|
73
|
-
return [5,10,15,20,25,30,40,50,60,80,100,500,1000,...(isDesktopMedia() ? [1500,2000,2500,3000,3500,4000,4500,5000,10000]:[])];
|
|
74
|
-
}
|
|
68
|
+
|
|
75
69
|
/****la fonction fetcher doit toujours retourner :
|
|
76
70
|
* 1. la liste des éléments fetchés dans la props data
|
|
77
71
|
* 2. le nombre total d'éléments de la liste obtenue en escluant les clause limit et offset correspondant à la même requête
|
|
@@ -160,6 +154,7 @@ const SWRDatagridComponent = React.forwardRef((props,ref)=>{
|
|
|
160
154
|
if(fetchPath){
|
|
161
155
|
fetchPath = setQueryParams(fetchPath,"SWRFetchPathKey",fPathRef.current)
|
|
162
156
|
}
|
|
157
|
+
const sortRef = React.useRef({});
|
|
163
158
|
const innerRef = React.useRef(null);
|
|
164
159
|
const showProgressRef = React.useRef(true);
|
|
165
160
|
const dataRef = React.useRef([]);
|
|
@@ -181,9 +176,8 @@ const SWRDatagridComponent = React.forwardRef((props,ref)=>{
|
|
|
181
176
|
}
|
|
182
177
|
opts = defaultObj(opts);
|
|
183
178
|
opts.fetchOptions = isObj(opts.fetchOptions)? Object.clone(opts.fetchOptions) : {};
|
|
184
|
-
opts.fetchOptions.withTotal = true;
|
|
185
|
-
opts.fetchOptions.fields = fetchFields;
|
|
186
179
|
extendObj(true,opts.fetchOptions,fetchOptionsRef.current?.fetchOptions);
|
|
180
|
+
opts.fetchOptions.sort = sortRef.current;
|
|
187
181
|
if(canHandleLimit){
|
|
188
182
|
opts.fetchOptions.limit = limitRef.current;
|
|
189
183
|
opts.fetchOptions.page = pageRef.current -1;
|
|
@@ -194,7 +188,6 @@ const SWRDatagridComponent = React.forwardRef((props,ref)=>{
|
|
|
194
188
|
delete opts.page;
|
|
195
189
|
delete opts.offset;
|
|
196
190
|
}
|
|
197
|
-
|
|
198
191
|
const fetchCB = ({data,total})=>{
|
|
199
192
|
totalRef.current = total;
|
|
200
193
|
dataRef.current = data;
|
|
@@ -291,7 +284,7 @@ const SWRDatagridComponent = React.forwardRef((props,ref)=>{
|
|
|
291
284
|
text : "Limite nbre elts par page",
|
|
292
285
|
divider : true,
|
|
293
286
|
}]
|
|
294
|
-
|
|
287
|
+
getRowsPerPagesLimits().map((item)=>{
|
|
295
288
|
itLimits.push({
|
|
296
289
|
text : item.formatNumber(),
|
|
297
290
|
icon : limitRef.current == item ? 'check' : null,
|
|
@@ -314,8 +307,8 @@ const SWRDatagridComponent = React.forwardRef((props,ref)=>{
|
|
|
314
307
|
{...rest}
|
|
315
308
|
sort = {sort}
|
|
316
309
|
onSort = {({sort})=>{
|
|
310
|
+
sortRef.current = sort;
|
|
317
311
|
if(!canSortRemotely()) return;
|
|
318
|
-
fetchOptionsRef.current.sort = sort;
|
|
319
312
|
pageRef.current = firstPage;
|
|
320
313
|
doRefresh(true);
|
|
321
314
|
return false;
|
|
@@ -380,7 +373,7 @@ const SWRDatagridComponent = React.forwardRef((props,ref)=>{
|
|
|
380
373
|
{...iconProp}
|
|
381
374
|
title = {"Aller à la page suivante {0}".sprintf(nextPage && nextPage.formatNumber()||undefined)}
|
|
382
375
|
name="material-keyboard-arrow-right"
|
|
383
|
-
disabled = {nextPage
|
|
376
|
+
disabled = {nextPage > totalPages || getNextPage() === false ? true : false}
|
|
384
377
|
onPress = {()=>{
|
|
385
378
|
const page = getNextPage();
|
|
386
379
|
if(page === false) return;
|
|
@@ -416,6 +409,7 @@ const SWRDatagridComponent = React.forwardRef((props,ref)=>{
|
|
|
416
409
|
opts = getFetchOptions({showError:showProgressRef.current,...opts});
|
|
417
410
|
isInitializedRef.current = true;
|
|
418
411
|
fetchOptionsRef.current = opts;
|
|
412
|
+
sortRef.current = opts.fetchOptions.sort;
|
|
419
413
|
if(force){
|
|
420
414
|
pageRef.current = firstPage;
|
|
421
415
|
}
|
|
@@ -167,26 +167,26 @@ const DatagridFactory = (Factory)=>{
|
|
|
167
167
|
const progressBar = this.getProgressBar();
|
|
168
168
|
const pointerEvents = this.getPointerEvents();
|
|
169
169
|
|
|
170
|
-
|
|
170
|
+
const restItems = [...this.renderCustomMenu()];
|
|
171
171
|
let max = this.getMaxSelectableRows();
|
|
172
172
|
if(selectableMultiple && max){
|
|
173
173
|
max = max.formatNumber();
|
|
174
|
-
|
|
175
|
-
|
|
174
|
+
if(selectableMultiple && !canRenderChart){
|
|
175
|
+
restItems.push({
|
|
176
176
|
label : "Sélectionner "+max.formatNumber(),
|
|
177
177
|
icon : "select-all",
|
|
178
178
|
onPress : (x,event)=>{
|
|
179
179
|
this.handleAllRowsToggle(true);
|
|
180
180
|
}
|
|
181
|
-
}
|
|
182
|
-
{
|
|
181
|
+
});
|
|
182
|
+
restItems.push({
|
|
183
183
|
label : "Tout désélectionner",
|
|
184
184
|
onPress : (x,event)=>{
|
|
185
185
|
this.handleAllRowsToggle(false);
|
|
186
186
|
},
|
|
187
187
|
icon : "select"
|
|
188
|
-
}
|
|
189
|
-
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
190
|
}
|
|
191
191
|
const maxHeight = this.getMaxListHeight();
|
|
192
192
|
const rPagination = showPagination ? <View style={[styles.paginationContainer]}>
|
|
@@ -923,7 +923,7 @@ class DropdownComponent extends AppComponent {
|
|
|
923
923
|
}}
|
|
924
924
|
containerProps = {{...containerProps,style:[containerProps.style,styles.mbO]}}
|
|
925
925
|
error = {!!error}
|
|
926
|
-
right = {loadingElement ?
|
|
926
|
+
right = {loadingElement ? loadingElement : disabled? null : (props)=>{
|
|
927
927
|
let r = React.isValidElement(defRight)?<>{defRight}</> : <></>;
|
|
928
928
|
if(typeof defRight =='function'){
|
|
929
929
|
const t = defRight(props);
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import {defaultObj,defaultStr} from "$utils";
|
|
2
2
|
import PropTypes from "prop-types";
|
|
3
3
|
import theme,{Colors} from "$theme";
|
|
4
|
-
import {isIos} from "$cplatform";
|
|
5
4
|
import React from "$react";
|
|
6
5
|
import Icon from "./Icon";
|
|
6
|
+
import {CHECKED_ICON,UNCHECKED_ICON} from "$ecomponents/Icon/utils";
|
|
7
7
|
|
|
8
8
|
/****** icon de type checkbox variant en fonction de l'environnement ou la plateforme */
|
|
9
9
|
const Checkbox = React.forwardRef((props,ref)=>{
|
|
10
10
|
const {checked:customChecked,color:customColor,primary,secondary,primaryOnCheck,secondaryOnCheck,onChange,checkedIcon:customCheckedIcon,uncheckedIcon:customUncheckedIcon,onPress,...rest} = props;
|
|
11
|
-
const checkedIcon = defaultStr(checkedIcon,
|
|
12
|
-
const uncheckedIcon = defaultStr(uncheckedIcon,
|
|
11
|
+
const checkedIcon = defaultStr(checkedIcon,CHECKED_ICON);
|
|
12
|
+
const uncheckedIcon = defaultStr(uncheckedIcon,UNCHECKED_ICON);
|
|
13
13
|
const [checked,setIsChecked] = React.useStateIfMounted(!!checked);
|
|
14
14
|
const isMounted = React.useIsMounted();
|
|
15
15
|
const prevChecked = React.usePrevious(checked);
|
|
@@ -9,9 +9,23 @@ const ScrollViewComponent = React.forwardRef(({virtualized,contentProps,containe
|
|
|
9
9
|
const isKeyboardOpenRef = React.useRef(false);
|
|
10
10
|
const testID = defaultStr(customTestID,'RN_ScrollViewComponent');
|
|
11
11
|
containerProps = defaultObj(containerProps)
|
|
12
|
+
const layoutRef = React.useRef(null);
|
|
12
13
|
const [layout,setLayout] = React.useState(Dimensions.get("window"));
|
|
13
14
|
const {height} = layout;
|
|
15
|
+
const hasInitializedRef = React.useRef(false);
|
|
14
16
|
const children = React.useStableMemo(()=>cChildren,[cChildren]);
|
|
17
|
+
const updateLayout = ()=>{
|
|
18
|
+
return new Promise((resolve)=>{
|
|
19
|
+
if(layoutRef.current && layoutRef.current.measureInWindow){
|
|
20
|
+
layoutRef.current.measureInWindow((x, y, width, height) => {
|
|
21
|
+
const r = { x, y, width, height };
|
|
22
|
+
setLayout({...Dimensions.get("window"),layout:r});
|
|
23
|
+
hasInitializedRef.current = true;
|
|
24
|
+
resolve(r);
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
})
|
|
28
|
+
}
|
|
15
29
|
React.useEffect(()=>{
|
|
16
30
|
const onKeyboardToggle = ({visible})=>{
|
|
17
31
|
isKeyboardOpenRef.current = visible;
|
|
@@ -19,7 +33,7 @@ const ScrollViewComponent = React.forwardRef(({virtualized,contentProps,containe
|
|
|
19
33
|
const onResizePage = ()=>{
|
|
20
34
|
setTimeout(()=>{
|
|
21
35
|
if(isKeyboardOpenRef.current) return;
|
|
22
|
-
|
|
36
|
+
updateLayout();
|
|
23
37
|
},300);
|
|
24
38
|
}
|
|
25
39
|
APP.on(APP.EVENTS.RESIZE_PAGE,onResizePage);
|
|
@@ -29,8 +43,21 @@ const ScrollViewComponent = React.forwardRef(({virtualized,contentProps,containe
|
|
|
29
43
|
APP.off(APP.EVENTS.KEYBOARD_DID_TOGGLE,onKeyboardToggle);
|
|
30
44
|
}
|
|
31
45
|
},[]);
|
|
32
|
-
|
|
33
|
-
|
|
46
|
+
|
|
47
|
+
const cStyle = {maxHeight:Math.max(height-100,250),width:'100%'};
|
|
48
|
+
if(isObj(layout.layout) && typeof layout.layout.y =='number'){
|
|
49
|
+
const {layout : {x,y}} = layout;
|
|
50
|
+
const minHeight = height - y;
|
|
51
|
+
if(minHeight> 0){
|
|
52
|
+
cStyle.minHeight = minHeight;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
const contentContainerStyle = [cStyle,rest.contentContainerStyle];
|
|
56
|
+
return <View ref={layoutRef} onLayout={()=>{
|
|
57
|
+
if(!hasInitializedRef.current){
|
|
58
|
+
updateLayout();
|
|
59
|
+
}
|
|
60
|
+
}} {...containerProps} style={[theme.styles.w100,containerProps.style]} testID={testID+"_ScrollViewContainer"}>
|
|
34
61
|
<ScrollView
|
|
35
62
|
ref={ref} {...rest}
|
|
36
63
|
testID={testID}
|