@fto-consult/expo-ui 2.22.0 → 2.23.0
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 +86 -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,64 @@ 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
|
+
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"
|
|
1280
|
+
anchor = {(p)=><Icon name="material-functions" {...p}/>}
|
|
1281
|
+
/>
|
|
1282
|
+
}
|
|
1221
1283
|
configureChart(refreshChart){
|
|
1222
1284
|
if(!this.isChartRendable()){
|
|
1223
1285
|
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 +1345,6 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
1283
1345
|
items : yItems,
|
|
1284
1346
|
multiple : true,
|
|
1285
1347
|
},
|
|
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
1348
|
stacked : {
|
|
1295
1349
|
type : 'switch',
|
|
1296
1350
|
text : "Graphe empilé?",
|
|
@@ -1438,8 +1492,8 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
1438
1492
|
getSectionListHeadersChartOptions({chartType,yAxisColumn,xAxisColumn,aggregatorFunction}){
|
|
1439
1493
|
if(!this.isSectionList()) return null;
|
|
1440
1494
|
if(!isObj(chartType) || !isObj(yAxisColumn) || !yAxisColumn.field) return null;
|
|
1441
|
-
if(!
|
|
1442
|
-
aggregatorFunction =
|
|
1495
|
+
if(!isValidAggregator(aggregatorFunction)){
|
|
1496
|
+
aggregatorFunction = this.getActiveAggregatorFunction();
|
|
1443
1497
|
}
|
|
1444
1498
|
const code = aggregatorFunction.code;
|
|
1445
1499
|
const isDonut = chartType.isDonut || chartType.isRadial;
|
|
@@ -1544,17 +1598,12 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
1544
1598
|
}
|
|
1545
1599
|
xAxisColumn = this.state.columns[config.x];
|
|
1546
1600
|
}
|
|
1547
|
-
|
|
1601
|
+
const aggregatorFunction = this.getActiveAggregatorFunction().eval;
|
|
1548
1602
|
const emptyValue = this.getEmptyDataValue();
|
|
1549
1603
|
const indexes = {};
|
|
1550
1604
|
let series = [],xaxis = {},customConfig = {};
|
|
1551
1605
|
let count = 0;
|
|
1552
1606
|
if(!this.isSectionList()){
|
|
1553
|
-
if(isObj(aggregatorFunction) && typeof aggregatorFunction.eval =='function'){
|
|
1554
|
-
aggregatorFunction = aggregatorFunction.eval;
|
|
1555
|
-
} else {
|
|
1556
|
-
aggregatorFunction = aggregatorFunctions.sum.eval;
|
|
1557
|
-
}
|
|
1558
1607
|
this.state.data.map((data,index)=>{
|
|
1559
1608
|
if(!isObj(data))return null;
|
|
1560
1609
|
const txt = this.renderRowCell({
|
|
@@ -1575,8 +1624,9 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
1575
1624
|
const current = indexes[s];
|
|
1576
1625
|
current[text] = typeof current[text] =="number"? current[text] : 0;
|
|
1577
1626
|
const value = getFooterColumnValue({data,columnDef,columnField:columnDef.field});
|
|
1578
|
-
|
|
1579
|
-
|
|
1627
|
+
const rArgs = aggregatorFunction =='average'?{sum:current[text]+value,count:count+1} : {};
|
|
1628
|
+
current[text] = aggregatorFunction({value,total:current[text],data,columnDef,columnField:columnDef.field,count,...rArgs});
|
|
1629
|
+
});
|
|
1580
1630
|
});
|
|
1581
1631
|
Object.map(indexes,(values,serieName)=>{
|
|
1582
1632
|
const col = this.state.columns[serieName];
|
|
@@ -2041,7 +2091,7 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
2041
2091
|
result.push(currentSectionListFooter);
|
|
2042
2092
|
}
|
|
2043
2093
|
Object.map(footersColumns,(columnDef,field)=>{
|
|
2044
|
-
evalSingleValue({data:d,columnDef,field,result,displayLabel:false})
|
|
2094
|
+
evalSingleValue({data:d,aggregatorFunction:this.getActiveAggregatorFunction(),aggregatorFunctions:this.aggregatorFunctions,columnDef,field,result,displayLabel:false})
|
|
2045
2095
|
});
|
|
2046
2096
|
}
|
|
2047
2097
|
newData.push(d);
|
|
@@ -2152,6 +2202,8 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
2152
2202
|
key = {key}
|
|
2153
2203
|
testID={testID+"_FooterItem_"+key}
|
|
2154
2204
|
{...footer}
|
|
2205
|
+
aggregatorFunction = {this.getActiveAggregatorFunction().code}
|
|
2206
|
+
aggregatorFunctions = {this.aggregatorFunctions}
|
|
2155
2207
|
displayLabel = {false}
|
|
2156
2208
|
//anchorProps = {{style:[theme.styles.ph1,theme.styles.mh05]}}
|
|
2157
2209
|
/>
|
|
@@ -2483,10 +2535,18 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
2483
2535
|
getMaxSelectedRows(){
|
|
2484
2536
|
return 0;
|
|
2485
2537
|
}
|
|
2538
|
+
///retourne la longueur réelle du nombre d'éléments du tableau en excluant les valerus d'entêtes de section
|
|
2539
|
+
getStateDataSize(includeSectionListDataSize){
|
|
2540
|
+
const dSize = defaultNumber(this.state.data.length);
|
|
2541
|
+
if(!dSize) return 0;
|
|
2542
|
+
if(includeSectionListDataSize === false) return dSize;
|
|
2543
|
+
return Math.max(dSize - this.getSectionListDataSize(),0);
|
|
2544
|
+
}
|
|
2486
2545
|
getMaxSelectableRows(){
|
|
2487
2546
|
let max = this.getMaxSelectedRows();
|
|
2488
|
-
|
|
2489
|
-
|
|
2547
|
+
const dataSize = this.getStateDataSize();
|
|
2548
|
+
if(dataSize){
|
|
2549
|
+
max = max ? Math.min(max,dataSize,max) : dataSize;
|
|
2490
2550
|
}
|
|
2491
2551
|
return Math.max(max-this.getSectionListDataSize(),0);
|
|
2492
2552
|
}
|
|
@@ -3095,7 +3155,9 @@ CommonDatagridComponent.propTypes = {
|
|
|
3095
3155
|
}),
|
|
3096
3156
|
displayType : chartDisplayType,
|
|
3097
3157
|
/*** les types d'afichates supportés par l'application */
|
|
3098
|
-
displayTypes : PropTypes.arrayOf(chartDisplayType)
|
|
3158
|
+
displayTypes : PropTypes.arrayOf(chartDisplayType),
|
|
3159
|
+
/***le code de la fonction d'aggregation à utilier par défaut, dans la liste des fonctions d'aggrégations du composant */
|
|
3160
|
+
aggregatorFunction : PropTypes.string,
|
|
3099
3161
|
}
|
|
3100
3162
|
|
|
3101
3163
|
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"}
|