@fto-consult/expo-ui 2.22.0 → 2.23.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/appConfig.txt +3 -0
- package/package.json +1 -1
- package/src/components/Datagrid/Accordion/index.js +5 -2
- package/src/components/Datagrid/Common/Common.js +87 -24
- package/src/components/Datagrid/Footer/Footer.js +68 -44
- package/src/components/Datagrid/Footer/index.js +19 -12
- package/src/components/Datagrid/IndexComponent.js +1 -1
- package/src/components/Datagrid/RenderType.js +3 -3
- package/src/components/Datagrid/Table/index.js +5 -2
- package/src/components/Snackbar/index.js +3 -1
package/appConfig.txt
CHANGED
|
@@ -8,4 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
/*** le nombre maximal de courbes qu'on peut afficher sur le même graphe***/
|
|
10
10
|
maxSupportedChartSeries {number}
|
|
11
|
+
|
|
12
|
+
/***les fonctions d'aggregations du datagrid**/
|
|
13
|
+
datagridAggregatorFunctions : {objectOf({code:{string},label:{string},eval:{function}})|| arrayOf({code:{string},label:{string},eval:{function}})}
|
|
11
14
|
}
|
package/package.json
CHANGED
|
@@ -344,7 +344,7 @@ const DatagridFactory = (Factory)=>{
|
|
|
344
344
|
} = this.props
|
|
345
345
|
chartContainerProps = defaultObj(chartContainerProps);
|
|
346
346
|
const canRenderChart = this.canRenderChart();
|
|
347
|
-
const hasData = this.
|
|
347
|
+
const hasData = this.getStateDataSize(false) ? true : false;
|
|
348
348
|
testID = defaultStr(testID,"RN_DatagridAccordion");
|
|
349
349
|
backToTopProps = defaultObj(backToTopProps);
|
|
350
350
|
accordionProps = defaultObj(accordionProps);
|
|
@@ -445,7 +445,7 @@ const DatagridFactory = (Factory)=>{
|
|
|
445
445
|
<View testID={testID+"_HeaderContentCntainer"} style={[styles.table,styles.pullRight]}>
|
|
446
446
|
{dbSelector}
|
|
447
447
|
<View testID={testID+"_HeaderQueryLimit"} style={[styles.paginationItem]}>
|
|
448
|
-
{this.renderQueryLimit(this.
|
|
448
|
+
{this.renderQueryLimit(this.getStateDataSize().formatNumber())}
|
|
449
449
|
</View>
|
|
450
450
|
{this.renderCustomPagination()}
|
|
451
451
|
{sortedColumnsLength ? <View testID={testID+"_HeaderSortedColumns"} style={[styles.sortableItems,styles.paginationItem,{paddingRight:10}]}>
|
|
@@ -519,6 +519,7 @@ const DatagridFactory = (Factory)=>{
|
|
|
519
519
|
,icon : showFooters?'view-column':'view-module'
|
|
520
520
|
,text : (showFooters?'Masquer les totaux':'Afficher les totaux')
|
|
521
521
|
}:null,
|
|
522
|
+
...this.getAggregatorFunctionsMenuItems(),
|
|
522
523
|
...this.renderCustomMenu(),
|
|
523
524
|
...restItems,
|
|
524
525
|
!canRenderChart && this.canScrollTo() && {
|
|
@@ -584,6 +585,8 @@ const DatagridFactory = (Factory)=>{
|
|
|
584
585
|
key = {field}
|
|
585
586
|
testID={testID+"_FooterItem_"+field}
|
|
586
587
|
{...footer}
|
|
588
|
+
aggregatorFunction = {this.getActiveAggregatorFunction().code}
|
|
589
|
+
aggregatorFunctions = {this.aggregatorFunctions}
|
|
587
590
|
anchorProps = {{style:[theme.styles.ph1,theme.styles.mh05]}}
|
|
588
591
|
/>
|
|
589
592
|
})}
|
|
@@ -24,7 +24,7 @@ import { StyleSheet,Dimensions,useWindowDimensions} from "react-native";
|
|
|
24
24
|
import Preloader from "$ecomponents/Preloader";
|
|
25
25
|
import Checkbox from "../Checkbox";
|
|
26
26
|
import { TouchableRipple } from "react-native-paper";
|
|
27
|
-
import { evalSingleValue,Footer,getFooterColumnValue
|
|
27
|
+
import { evalSingleValue,Footer,getFooterColumnValue,isValidAggregator,extendAggreagatorFunctions} from "../Footer";
|
|
28
28
|
import i18n from "$i18n";
|
|
29
29
|
import { makePhoneCall,canMakePhoneCall as canMakeCall} from "$makePhoneCall";
|
|
30
30
|
import copyToClipboard from "$capp/clipboard";
|
|
@@ -39,7 +39,6 @@ import {Menu} from "$ecomponents/BottomSheet";
|
|
|
39
39
|
import {styles as tableStyles} from "$ecomponents/Table";
|
|
40
40
|
import {DialogProvider} from "$ecomponents/Form/FormData";
|
|
41
41
|
import Chart,{getMaxSupportedSeriesSize} from "$ecomponents/Chart";
|
|
42
|
-
import { aggregatorFunctions} from "../Footer/Footer";
|
|
43
42
|
|
|
44
43
|
const chart = "chart";
|
|
45
44
|
export const donutChart = {
|
|
@@ -198,10 +197,15 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
198
197
|
sectionListDataSize : {value : {current : 0}},
|
|
199
198
|
enablePointerEventsRef : {value : {current:false}},
|
|
200
199
|
configureSectionListSelectedValues : {value : {}},
|
|
200
|
+
///la liste des fonctions d'aggregations supportées
|
|
201
|
+
aggregatorFunctions : {value : extendAggreagatorFunctions(this.props.aggregatorFunctions)},
|
|
201
202
|
///les types d'affichage
|
|
202
203
|
displayTypes : {value : hasFoundDisplayTypes ? disTypes : Object.clone(displayTypes)},
|
|
203
204
|
sectionListColumnsSize : {value : {current:0}}, //la taille du nombre d'éléments de section dans les colonnes
|
|
204
205
|
})
|
|
206
|
+
const sessionAggregator = defaultStr(this.getSessionData("aggregatorFunction")).trim();
|
|
207
|
+
const aggregatorProps = defaultStr(this.props.aggregatorFunction).trim();
|
|
208
|
+
this.state.aggregatorFunction= aggregatorProps && isValidAggregator(this.aggregatorFunctions[aggregatorProps]) ? aggregatorProps ? isNonNullString(sessionAggregator) && isValidAggregator(this.aggregatorFunctions[sessionAggregator]) : sessionAggregator : Object.keys(this.aggregatorFunctions)[0];
|
|
205
209
|
this.isLoading = this.isLoading.bind(this);
|
|
206
210
|
this.getProgressBar = this.getProgressBar.bind(this);
|
|
207
211
|
this.sortRef.current.dir = defaultStr(this.sortRef.current.dir,this.sortRef.current.column == "date"?"desc":'asc')
|
|
@@ -1218,6 +1222,65 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
1218
1222
|
cb({...this.state.chartConfig});
|
|
1219
1223
|
}
|
|
1220
1224
|
}
|
|
1225
|
+
getActiveAggregatorFunction(){
|
|
1226
|
+
if(isNonNullString(this.state.aggregatorFunction) && this.aggregatorFunctions[this.state.aggregatorFunction]){
|
|
1227
|
+
return this.aggregatorFunctions[this.state.aggregatorFunction]
|
|
1228
|
+
}
|
|
1229
|
+
return this.aggregatorFunctions[Object.keys(this.aggregatorFunctions)[0]];
|
|
1230
|
+
}
|
|
1231
|
+
/**** récupère l'item de menu permettant lié à la sélection de la fonction d'aggggrégation */
|
|
1232
|
+
getAggregatorFunctionsMenuItems(withDivider){
|
|
1233
|
+
if(!this.hasFootersFields()) return [];
|
|
1234
|
+
const m = [];
|
|
1235
|
+
const aggregatorFunction = this.getActiveAggregatorFunction().code;
|
|
1236
|
+
Object.map(this.aggregatorFunctions,(ag)=>{
|
|
1237
|
+
const active = ag.code == aggregatorFunction;
|
|
1238
|
+
m.push({
|
|
1239
|
+
...ag,
|
|
1240
|
+
icon : active?"check":null,
|
|
1241
|
+
onPress : active ? undefined : ()=>{
|
|
1242
|
+
this.toggleActiveAggregatorFunction(ag);
|
|
1243
|
+
}
|
|
1244
|
+
})
|
|
1245
|
+
});
|
|
1246
|
+
if(m.length){
|
|
1247
|
+
m.unshift({
|
|
1248
|
+
text : "Fonctions d'aggrégation",
|
|
1249
|
+
icon : "material-functions",
|
|
1250
|
+
divider : true,
|
|
1251
|
+
});
|
|
1252
|
+
if(withDivider !== false){
|
|
1253
|
+
m.unshift({divider:true});
|
|
1254
|
+
}
|
|
1255
|
+
if(withDivider !== false){
|
|
1256
|
+
m[m.length-1].divider = true;
|
|
1257
|
+
}
|
|
1258
|
+
}
|
|
1259
|
+
return m;
|
|
1260
|
+
}
|
|
1261
|
+
toggleActiveAggregatorFunction(ag){
|
|
1262
|
+
if(!isValidAggregator(ag) || ag.code == this.state.aggregatorFunction) return null;
|
|
1263
|
+
setTimeout(()=>{
|
|
1264
|
+
this.setIsLoading(true,()=>{
|
|
1265
|
+
this.prepareData({data:this.INITIAL_STATE.data},(state)=>{
|
|
1266
|
+
this.setState({...state,aggregatorFunction:ag.code},()=>{
|
|
1267
|
+
this.setSessionData("aggregatorFunction",ag.code);
|
|
1268
|
+
this.setIsLoading(false,false);
|
|
1269
|
+
})
|
|
1270
|
+
})
|
|
1271
|
+
},true);
|
|
1272
|
+
},200);
|
|
1273
|
+
}
|
|
1274
|
+
renderAggregatorFunctionsMenu(){
|
|
1275
|
+
const m = this.getAggregatorFunctionsMenuItems(false,false);
|
|
1276
|
+
if(!m.length) return null;
|
|
1277
|
+
return <Menu
|
|
1278
|
+
items = {m}
|
|
1279
|
+
anchor = {(p)=><Icon name="material-functions" {...p}
|
|
1280
|
+
title = "Fonctions d'aggrégations. Veuillez sélectionner la fonction à utiliser par défaut pour la totalisation des données des colonnes de type nombre"
|
|
1281
|
+
/>}
|
|
1282
|
+
/>
|
|
1283
|
+
}
|
|
1221
1284
|
configureChart(refreshChart){
|
|
1222
1285
|
if(!this.isChartRendable()){
|
|
1223
1286
|
return Promise.reject({message:'Impossible de configurer le graphe car le type de données ne permet pas de rendu de type graphe'});
|
|
@@ -1283,14 +1346,6 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
1283
1346
|
items : yItems,
|
|
1284
1347
|
multiple : true,
|
|
1285
1348
|
},
|
|
1286
|
-
aggregatorFunction : {
|
|
1287
|
-
type : 'select',
|
|
1288
|
-
text : "Foncton d'aggrégation",
|
|
1289
|
-
required : true,
|
|
1290
|
-
multiple : false,
|
|
1291
|
-
defaultValue : "sum",
|
|
1292
|
-
items : aggregatorFunctions,
|
|
1293
|
-
},
|
|
1294
1349
|
stacked : {
|
|
1295
1350
|
type : 'switch',
|
|
1296
1351
|
text : "Graphe empilé?",
|
|
@@ -1438,8 +1493,8 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
1438
1493
|
getSectionListHeadersChartOptions({chartType,yAxisColumn,xAxisColumn,aggregatorFunction}){
|
|
1439
1494
|
if(!this.isSectionList()) return null;
|
|
1440
1495
|
if(!isObj(chartType) || !isObj(yAxisColumn) || !yAxisColumn.field) return null;
|
|
1441
|
-
if(!
|
|
1442
|
-
aggregatorFunction =
|
|
1496
|
+
if(!isValidAggregator(aggregatorFunction)){
|
|
1497
|
+
aggregatorFunction = this.getActiveAggregatorFunction();
|
|
1443
1498
|
}
|
|
1444
1499
|
const code = aggregatorFunction.code;
|
|
1445
1500
|
const isDonut = chartType.isDonut || chartType.isRadial;
|
|
@@ -1544,17 +1599,12 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
1544
1599
|
}
|
|
1545
1600
|
xAxisColumn = this.state.columns[config.x];
|
|
1546
1601
|
}
|
|
1547
|
-
|
|
1602
|
+
const aggregatorFunction = this.getActiveAggregatorFunction().eval;
|
|
1548
1603
|
const emptyValue = this.getEmptyDataValue();
|
|
1549
1604
|
const indexes = {};
|
|
1550
1605
|
let series = [],xaxis = {},customConfig = {};
|
|
1551
1606
|
let count = 0;
|
|
1552
1607
|
if(!this.isSectionList()){
|
|
1553
|
-
if(isObj(aggregatorFunction) && typeof aggregatorFunction.eval =='function'){
|
|
1554
|
-
aggregatorFunction = aggregatorFunction.eval;
|
|
1555
|
-
} else {
|
|
1556
|
-
aggregatorFunction = aggregatorFunctions.sum.eval;
|
|
1557
|
-
}
|
|
1558
1608
|
this.state.data.map((data,index)=>{
|
|
1559
1609
|
if(!isObj(data))return null;
|
|
1560
1610
|
const txt = this.renderRowCell({
|
|
@@ -1575,8 +1625,9 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
1575
1625
|
const current = indexes[s];
|
|
1576
1626
|
current[text] = typeof current[text] =="number"? current[text] : 0;
|
|
1577
1627
|
const value = getFooterColumnValue({data,columnDef,columnField:columnDef.field});
|
|
1578
|
-
|
|
1579
|
-
|
|
1628
|
+
const rArgs = aggregatorFunction =='average'?{sum:current[text]+value,count:count+1} : {};
|
|
1629
|
+
current[text] = aggregatorFunction({value,total:current[text],data,columnDef,columnField:columnDef.field,count,...rArgs});
|
|
1630
|
+
});
|
|
1580
1631
|
});
|
|
1581
1632
|
Object.map(indexes,(values,serieName)=>{
|
|
1582
1633
|
const col = this.state.columns[serieName];
|
|
@@ -2041,7 +2092,7 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
2041
2092
|
result.push(currentSectionListFooter);
|
|
2042
2093
|
}
|
|
2043
2094
|
Object.map(footersColumns,(columnDef,field)=>{
|
|
2044
|
-
evalSingleValue({data:d,columnDef,field,result,displayLabel:false})
|
|
2095
|
+
evalSingleValue({data:d,aggregatorFunction:this.getActiveAggregatorFunction(),aggregatorFunctions:this.aggregatorFunctions,columnDef,field,result,displayLabel:false})
|
|
2045
2096
|
});
|
|
2046
2097
|
}
|
|
2047
2098
|
newData.push(d);
|
|
@@ -2152,6 +2203,8 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
2152
2203
|
key = {key}
|
|
2153
2204
|
testID={testID+"_FooterItem_"+key}
|
|
2154
2205
|
{...footer}
|
|
2206
|
+
aggregatorFunction = {this.getActiveAggregatorFunction().code}
|
|
2207
|
+
aggregatorFunctions = {this.aggregatorFunctions}
|
|
2155
2208
|
displayLabel = {false}
|
|
2156
2209
|
//anchorProps = {{style:[theme.styles.ph1,theme.styles.mh05]}}
|
|
2157
2210
|
/>
|
|
@@ -2483,10 +2536,18 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
2483
2536
|
getMaxSelectedRows(){
|
|
2484
2537
|
return 0;
|
|
2485
2538
|
}
|
|
2539
|
+
///retourne la longueur réelle du nombre d'éléments du tableau en excluant les valerus d'entêtes de section
|
|
2540
|
+
getStateDataSize(includeSectionListDataSize){
|
|
2541
|
+
const dSize = defaultNumber(this.state.data.length);
|
|
2542
|
+
if(!dSize) return 0;
|
|
2543
|
+
if(includeSectionListDataSize === false) return dSize;
|
|
2544
|
+
return Math.max(dSize - this.getSectionListDataSize(),0);
|
|
2545
|
+
}
|
|
2486
2546
|
getMaxSelectableRows(){
|
|
2487
2547
|
let max = this.getMaxSelectedRows();
|
|
2488
|
-
|
|
2489
|
-
|
|
2548
|
+
const dataSize = this.getStateDataSize();
|
|
2549
|
+
if(dataSize){
|
|
2550
|
+
max = max ? Math.min(max,dataSize,max) : dataSize;
|
|
2490
2551
|
}
|
|
2491
2552
|
return Math.max(max-this.getSectionListDataSize(),0);
|
|
2492
2553
|
}
|
|
@@ -3095,7 +3156,9 @@ CommonDatagridComponent.propTypes = {
|
|
|
3095
3156
|
}),
|
|
3096
3157
|
displayType : chartDisplayType,
|
|
3097
3158
|
/*** les types d'afichates supportés par l'application */
|
|
3098
|
-
displayTypes : PropTypes.arrayOf(chartDisplayType)
|
|
3159
|
+
displayTypes : PropTypes.arrayOf(chartDisplayType),
|
|
3160
|
+
/***le code de la fonction d'aggregation à utilier par défaut, dans la liste des fonctions d'aggrégations du composant */
|
|
3161
|
+
aggregatorFunction : PropTypes.string,
|
|
3099
3162
|
}
|
|
3100
3163
|
|
|
3101
3164
|
const styles = StyleSheet.create({
|
|
@@ -2,66 +2,89 @@ import Menu from "$ecomponents/BottomSheet/Menu";
|
|
|
2
2
|
import View from "$ecomponents/View";
|
|
3
3
|
import {Pressable,StyleSheet} from "react-native";
|
|
4
4
|
import Label from "$ecomponents/Label";
|
|
5
|
-
import {defaultVal,defaultObj} from "$utils";
|
|
5
|
+
import {defaultVal,defaultObj,isNonNullString,isObj} from "$utils";
|
|
6
6
|
import React from "$react";
|
|
7
7
|
import theme from "$theme"
|
|
8
|
+
import appConfig from "$capp/config";
|
|
8
9
|
|
|
9
|
-
let methods = {
|
|
10
|
-
sum : "Somme",
|
|
11
|
-
average : "Moyenne",
|
|
12
|
-
min : "Minimum",
|
|
13
|
-
max : 'Maximum',
|
|
14
|
-
count : "Nombre",
|
|
15
|
-
}
|
|
16
10
|
/*** les fonction d'aggreations */
|
|
17
11
|
export const aggregatorFunctions = {
|
|
18
12
|
sum : {
|
|
19
13
|
code : "sum",
|
|
20
14
|
label : "Somme",
|
|
21
|
-
eval : (
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
return
|
|
15
|
+
eval : ({value,total,count})=>{
|
|
16
|
+
value = typeof value =='number'?value : 0;
|
|
17
|
+
total = typeof total =='number'? total : 0;
|
|
18
|
+
return value+total;
|
|
25
19
|
}
|
|
26
20
|
},
|
|
27
|
-
/*average : {
|
|
28
|
-
code : "average",
|
|
29
|
-
label : "Moyenne",
|
|
30
|
-
eval : ()=>{
|
|
31
|
-
|
|
32
|
-
}
|
|
33
|
-
},*/
|
|
34
21
|
min : {
|
|
35
22
|
code : "min",
|
|
36
23
|
label : "Minimum",
|
|
37
|
-
eval : (
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
return Math.min(
|
|
24
|
+
eval : ({value,total,count})=>{
|
|
25
|
+
value = typeof value =='number'?value : 0;
|
|
26
|
+
total = typeof total =='number'? total : 0;
|
|
27
|
+
return Math.min(value,total);
|
|
41
28
|
},
|
|
42
29
|
},
|
|
43
30
|
max : {
|
|
44
31
|
code : "max",
|
|
45
32
|
label: 'Maximum',
|
|
46
|
-
eval : (
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
return Math.max(
|
|
33
|
+
eval : ({value,total,count})=>{
|
|
34
|
+
value = typeof value =='number'?value : 0;
|
|
35
|
+
total = typeof total =='number'? total : 0;
|
|
36
|
+
return Math.max(value,total);
|
|
50
37
|
},
|
|
51
38
|
},
|
|
52
39
|
count : {
|
|
53
40
|
code : "count",
|
|
54
41
|
label : "Nombre",
|
|
55
|
-
eval : (
|
|
42
|
+
eval : ({value,total,count})=>{
|
|
56
43
|
return (typeof count =='number'? count : 0)+1;
|
|
57
44
|
}
|
|
58
45
|
},
|
|
46
|
+
average : {
|
|
47
|
+
code : "average",
|
|
48
|
+
label : "Moyenne",
|
|
49
|
+
eval : ({count,sum})=>{
|
|
50
|
+
return typeof count =='number' && count > 0 && typeof sum =='number'? sum/count : 0;
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
}
|
|
54
|
+
/****
|
|
55
|
+
* Vérifie si la fonction d'aggregation est valide
|
|
56
|
+
*/
|
|
57
|
+
export const isValidAggregator = (aggregatorFunctionObject)=>{
|
|
58
|
+
return isObj(aggregatorFunctionObject) && isNonNullString(aggregatorFunctionObject.code) && typeof aggregatorFunctionObject.eval =='function' && true || false;
|
|
59
|
+
}
|
|
60
|
+
/*** permet d'étendre les fonction d'aggregations
|
|
61
|
+
* @param {object|Array} liste des functions d'aggregation supplémentaires, de la forme
|
|
62
|
+
* {
|
|
63
|
+
* code {string} le code de la fonction d'aggrégation
|
|
64
|
+
* label {string} le libele
|
|
65
|
+
* eval {function} la function a utiiser pour évaluer la données via l'aggregator
|
|
66
|
+
|
|
67
|
+
* }
|
|
68
|
+
*/
|
|
69
|
+
export function extendAggreagatorFunctions(aFunctions){
|
|
70
|
+
const r = {...aggregatorFunctions};
|
|
71
|
+
loopForAggregator(appConfig.get("datagridAggregatorFunctions"),r);
|
|
72
|
+
loopForAggregator(aFunctions,r);
|
|
73
|
+
return r;
|
|
74
|
+
}
|
|
75
|
+
const loopForAggregator = (aggregatorFunctions,result)=>{
|
|
76
|
+
result = defaultObj(result);
|
|
77
|
+
Object.map(aggregatorFunctions,(aggregatorObj,key)=>{
|
|
78
|
+
if(!isValidAggregator(aggregatorObj)) return null;
|
|
79
|
+
result[aggregatorObj.code] = aggregatorObj;
|
|
80
|
+
});
|
|
59
81
|
}
|
|
60
|
-
const formatValue = ({value,format,
|
|
61
|
-
return (format === 'money' &&
|
|
82
|
+
const formatValue = ({value,format,aggregatorFunction})=>{
|
|
83
|
+
return (format === 'money' && aggregatorFunction != 'count')? value.formatMoney():value.formatNumber();
|
|
62
84
|
}
|
|
63
85
|
export default function DGGridFooterValue (props){
|
|
64
|
-
let {label,text,displayLabel,style,format,testID,anchorProps} = props;
|
|
86
|
+
let {label,text,displayLabel,style,aggregatorFunctions,aggregatorFunction,format,testID,anchorProps} = props;
|
|
87
|
+
aggregatorFunctions = defaultObj(aggregatorFunctions);
|
|
65
88
|
anchorProps = defaultObj(anchorProps);
|
|
66
89
|
testID = defaultStr(testID,"RN_DatagridFooterComponent");
|
|
67
90
|
label = defaultVal(label,text);
|
|
@@ -69,27 +92,28 @@ export default function DGGridFooterValue (props){
|
|
|
69
92
|
if(displayLabel !== false){
|
|
70
93
|
if(!label || !React.isValidElement(label,true)) return null;
|
|
71
94
|
} else label = undefined;
|
|
72
|
-
const [active,setActive] = React.useState(isNonNullString(
|
|
95
|
+
const [active,setActive] = React.useState(isNonNullString(aggregatorFunction) && aggregatorFunction in aggregatorFunctions ? aggregatorFunction : aggregatorFunctions[Object.keys(aggregatorFunctions)[0]]?.code)
|
|
73
96
|
React.useEffect(()=>{
|
|
74
|
-
if(isNonNullString(
|
|
75
|
-
setActive(
|
|
97
|
+
if(aggregatorFunction !== active && isNonNullString(aggregatorFunction) && aggregatorFunction in aggregatorFunctions){
|
|
98
|
+
setActive(aggregatorFunction)
|
|
76
99
|
}
|
|
77
|
-
},[
|
|
100
|
+
},[aggregatorFunction])
|
|
78
101
|
let title = "";
|
|
79
102
|
let menuItems = []
|
|
80
103
|
const activeStyle = {color:theme.colors.primaryOnSurface};
|
|
81
|
-
for(let
|
|
82
|
-
let val = defaultDecimal(props[
|
|
104
|
+
for(let aggregatorFunction in aggregatorFunctions){
|
|
105
|
+
let val = defaultDecimal(props[aggregatorFunction]);
|
|
83
106
|
if(isDecimal(val)){
|
|
84
|
-
let fText = formatValue({value:val,format,
|
|
85
|
-
|
|
107
|
+
let fText = formatValue({value:val,format,aggregatorFunction});
|
|
108
|
+
const mText = defaultStr(aggregatorFunctions[aggregatorFunction].label,aggregatorFunctions[aggregatorFunction].code,aggregatorFunction);
|
|
109
|
+
title +=(title? ", ":"")+mText +" : "+fText
|
|
86
110
|
menuItems.push({
|
|
87
|
-
text :
|
|
88
|
-
icon : active ==
|
|
89
|
-
style : [{paddingHorizontal:0},active ===
|
|
111
|
+
text : mText + " : "+fText,
|
|
112
|
+
icon : active == aggregatorFunction ? "check" : null,
|
|
113
|
+
style : [{paddingHorizontal:0},active ===aggregatorFunction ?activeStyle:null],
|
|
90
114
|
onPress : (e)=>{
|
|
91
115
|
React.stopEventPropagation(e);
|
|
92
|
-
setActive(
|
|
116
|
+
setActive(aggregatorFunction)
|
|
93
117
|
}
|
|
94
118
|
})
|
|
95
119
|
}
|
|
@@ -108,7 +132,7 @@ export default function DGGridFooterValue (props){
|
|
|
108
132
|
</>
|
|
109
133
|
: null}
|
|
110
134
|
<Label testID={testID+"_LabelContent"} primary style={[styles.value]}>
|
|
111
|
-
{formatValue({value:defaultDecimal(props[active]),
|
|
135
|
+
{formatValue({value:defaultDecimal(props[active]),aggregatorFunction:active,format})}
|
|
112
136
|
</Label>
|
|
113
137
|
</Pressable>
|
|
114
138
|
}}
|
|
@@ -4,7 +4,7 @@ import React from "$react";
|
|
|
4
4
|
import memoize from "$react/memoize";
|
|
5
5
|
export {default as FooterItem} from "./Footer";
|
|
6
6
|
import {parseDecimal,defaultObj,defaultStr,isNonNullString} from "$utils";
|
|
7
|
-
|
|
7
|
+
import { aggregatorFunctions as mAggregatorFunctions } from "./Footer";
|
|
8
8
|
export * from "./Footer";
|
|
9
9
|
|
|
10
10
|
/***évalue la valeur décimale selon les paramètres */
|
|
@@ -19,8 +19,9 @@ export const getFooterColumnValue = ({data,columnDef,field,result,columnField})
|
|
|
19
19
|
return typeof val =='number'? parseDecimal(val.toFixed(12)) : 0;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
export const evalSingleValue = ({data,columnDef,field,columnField,withLabel,result,displayLabel,onlyVisible})=>{
|
|
23
|
-
if(!isNonNullString(field) || !isObj(columnDef)) return result;
|
|
22
|
+
export const evalSingleValue = ({data,columnDef,field,count,columnField,aggregatorFunctions,withLabel,result,displayLabel,onlyVisible})=>{
|
|
23
|
+
if(!isNonNullString(field) || !isObj(columnDef) || !isObj(data)) return result;
|
|
24
|
+
aggregatorFunctions = defaultObj(aggregatorFunctions,mAggregatorFunctions);
|
|
24
25
|
onlyVisible = defaultBool(onlyVisible,true);
|
|
25
26
|
if(onlyVisible === true && !(columnDef.visible !== false)) result;
|
|
26
27
|
let val = getFooterColumnValue({data,columnDef,columnField,result,field});
|
|
@@ -36,21 +37,27 @@ export const evalSingleValue = ({data,columnDef,field,columnField,withLabel,resu
|
|
|
36
37
|
}
|
|
37
38
|
}
|
|
38
39
|
const obj = currentResult[field];
|
|
39
|
-
obj.max = isDecimal(obj.max) ? Math.max(obj.max,val) : val;
|
|
40
|
-
obj.min = isDecimal(obj.min) ? Math.min(obj.min,val) : val;
|
|
41
|
-
obj.count = isDecimal(obj.count) ?
|
|
42
|
-
obj.sum = isDecimal(obj.sum) ? (parseDecimal((obj.sum+val).toFixed(10))) : val;
|
|
43
|
-
|
|
40
|
+
//obj.max = isDecimal(obj.max) ? Math.max(obj.max,val) : val;
|
|
41
|
+
//obj.min = isDecimal(obj.min) ? Math.min(obj.min,val) : val;
|
|
42
|
+
//obj.count = isDecimal(obj.count) ? obj.count : 0;
|
|
43
|
+
//obj.sum = isDecimal(obj.sum) ? (parseDecimal((obj.sum+val).toFixed(10))) : val;
|
|
44
|
+
Object.map(aggregatorFunctions,(aggegatorFunction,key)=>{
|
|
45
|
+
const code = aggegatorFunction.code;
|
|
46
|
+
obj[code] = aggegatorFunction.eval({columnDef,columnField,data,value : val,count,...obj,total:defaultNumber(obj[code])});
|
|
47
|
+
});
|
|
48
|
+
if(typeof obj.count =='number' && obj.count >0 && typeof obj.sum =='number'){
|
|
49
|
+
obj.average = obj.sum / obj.count;
|
|
50
|
+
}
|
|
44
51
|
return currentResult;
|
|
45
52
|
})
|
|
46
53
|
return result;
|
|
47
54
|
}
|
|
48
|
-
export const evalValues = memoize(({data,columns,onlyVisible,withLabel,displayLabel})=>{
|
|
55
|
+
export const evalValues = memoize(({data,columns,aggregatorFunctions,onlyVisible,withLabel,displayLabel})=>{
|
|
49
56
|
let result = {};
|
|
50
57
|
Object.map(data,(rowData,i)=>{
|
|
51
58
|
if(!isObj(rowData)) return result;
|
|
52
59
|
Object.map(columns,(columnDef,field)=>{
|
|
53
|
-
result = evalSingleValue({data:rowData,columnDef,field,result,withLabel,displayLabel,onlyVisible})
|
|
60
|
+
result = evalSingleValue({data:rowData,aggregatorFunctions,columnDef,field,result,withLabel,displayLabel,onlyVisible})
|
|
54
61
|
})
|
|
55
62
|
})
|
|
56
63
|
return result;
|
|
@@ -65,7 +72,7 @@ export const evalValues = memoize(({data,columns,onlyVisible,withLabel,displayLa
|
|
|
65
72
|
* @param : children {func}, fonction permettant de générer le contenu du footer
|
|
66
73
|
*/
|
|
67
74
|
export default function DGGridFooters (props){
|
|
68
|
-
let {columns,children,displayLabel,Component,data,onlyVisible,...rest} = props;
|
|
75
|
+
let {columns,children,displayLabel,aggregatorFunctions,Component,data,onlyVisible,...rest} = props;
|
|
69
76
|
rest = defaultObj(rest)
|
|
70
77
|
if(Component === false){
|
|
71
78
|
Component = React.Fragment;
|
|
@@ -83,7 +90,7 @@ export default function DGGridFooters (props){
|
|
|
83
90
|
React.useEffect(()=>{
|
|
84
91
|
setState({...state,data:props.data})
|
|
85
92
|
},[props.data]);
|
|
86
|
-
let footers = evalValues({data:state.data,columns:state.columns,onlyVisible,displayLabel});
|
|
93
|
+
let footers = evalValues({data:state.data,aggregatorFunctions,columns:state.columns,onlyVisible,displayLabel});
|
|
87
94
|
return <Component {...rest}>
|
|
88
95
|
{children({
|
|
89
96
|
footers,
|
|
@@ -18,7 +18,7 @@ const DatagridMainComponent = React.forwardRef((props,ref)=>{
|
|
|
18
18
|
const AccordionComponent = isTableDataRef.current ? TableDataAccordion : Accordion;
|
|
19
19
|
let Component = TableComponent;
|
|
20
20
|
const canRenderAccordion = (isFunction(props.accordion) || (isObj(props.accordionProps) && isFunction(props.accordionProps.accordion)) || props.accordion === true);
|
|
21
|
-
let renderType = defaultStr(getRenderType(),isDesk? "
|
|
21
|
+
let renderType = defaultStr(getRenderType(),isDesk? "table":'accordion').trim().toLowerCase()
|
|
22
22
|
if(renderType == 'accordion' && canRenderAccordion){
|
|
23
23
|
Component = AccordionComponent;
|
|
24
24
|
} else if(renderType =='table'){
|
|
@@ -18,9 +18,9 @@ const DatagridRenderTypeComponent = (props)=>{
|
|
|
18
18
|
let type = defaultStr(get(typeKey),isDesk? "fixed":'accordion').toLowerCase().trim();
|
|
19
19
|
const rTypes = [
|
|
20
20
|
{...getActiveProps(type,'accordion'),tooltip:"Les éléments de liste s'affichent de manière optimisé pour téléphone mobile",code:'accordion',icon:accordionIcon,label:'Mobile',labelText:'environnement optimisé pour téléphone mobile'},
|
|
21
|
-
|
|
21
|
+
{...getActiveProps(type,'table'),tooltip:"Les éléments de listes s'affichent dans un tableau",code:'table',icon:tableIcon,label:'Tableau'}
|
|
22
22
|
]
|
|
23
|
-
Object.map(rendersTypes,(t,i)=>{
|
|
23
|
+
/*Object.map(rendersTypes,(t,i)=>{
|
|
24
24
|
if(isObj(t)){
|
|
25
25
|
if((isDesk && t.desktop) || (!isDesk && t.mobile)){
|
|
26
26
|
rTypes.push({
|
|
@@ -29,7 +29,7 @@ const DatagridRenderTypeComponent = (props)=>{
|
|
|
29
29
|
})
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
|
-
})
|
|
32
|
+
});*/
|
|
33
33
|
let typeObj = {};
|
|
34
34
|
Object.map(rTypes,(t)=>{
|
|
35
35
|
if(isObj(t) && t.code == type){
|
|
@@ -56,10 +56,11 @@ const DatagridFactory = (Factory)=>{
|
|
|
56
56
|
const footerFields = this.getFootersFields();
|
|
57
57
|
if(isObj(footerFields[columnField])){
|
|
58
58
|
return <Footer
|
|
59
|
-
//{...footerFields[columnField]}
|
|
60
59
|
{...defaultObj(footersValues[columnField])}
|
|
61
60
|
displayLabel = {false}
|
|
62
61
|
style = {[style]}
|
|
62
|
+
aggregatorFunction = {this.getActiveAggregatorFunction().code}
|
|
63
|
+
aggregatorFunctions = {this.aggregatorFunctions}
|
|
63
64
|
/>
|
|
64
65
|
}
|
|
65
66
|
return null;
|
|
@@ -203,7 +204,7 @@ const DatagridFactory = (Factory)=>{
|
|
|
203
204
|
<ScrollView horizontal showsHorizontalScrollIndicator={!isLoading} style={styles.paginationContainerStyle} contentContainerStyle={styles.minW100}>
|
|
204
205
|
<View style={[styles.paginationContent]}>
|
|
205
206
|
<View testID={testID+"_HeaderQueryLimit"}>
|
|
206
|
-
{this.renderQueryLimit(this.
|
|
207
|
+
{this.renderQueryLimit(this.getStateDataSize().formatNumber())}
|
|
207
208
|
</View>
|
|
208
209
|
{this.renderCustomPagination()}
|
|
209
210
|
{!isMobile && <>
|
|
@@ -283,12 +284,14 @@ const DatagridFactory = (Factory)=>{
|
|
|
283
284
|
,icon : showFooters?'view-column':'view-module'
|
|
284
285
|
,text : (showFooters?'Masquer/Ligne des totaux':'Afficher/Ligne des totaux')
|
|
285
286
|
} : null,
|
|
287
|
+
...this.getAggregatorFunctionsMenuItems(),
|
|
286
288
|
...(selectableMultiple ? restItems : [])
|
|
287
289
|
] : visibleColumns}
|
|
288
290
|
|
|
289
291
|
/>
|
|
290
292
|
{this.renderSectionListMenu()}
|
|
291
293
|
{this.renderDisplayTypes()}
|
|
294
|
+
{!isMobile && this.renderAggregatorFunctionsMenu() || null}
|
|
292
295
|
<View testID={testID+"_HeaderPagination"} style = {styles.paginationItem}>
|
|
293
296
|
<BottomSheetMenu
|
|
294
297
|
testID={testID+"_HeaderMenus"}
|