@fto-consult/expo-ui 2.21.3 → 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 +14 -0
- package/package.json +1 -1
- package/src/components/Chart/appexChart/index.js +3 -1
- package/src/components/Chart/index.js +9 -20
- package/src/components/Chart/utils.js +10 -21
- package/src/components/Datagrid/Accordion/index.js +12 -8
- package/src/components/Datagrid/Common/Common.js +428 -139
- package/src/components/Datagrid/Footer/Footer.js +68 -45
- package/src/components/Datagrid/Footer/index.js +34 -21
- package/src/components/Datagrid/IndexComponent.js +1 -1
- package/src/components/Datagrid/RenderType.js +3 -3
- package/src/components/Datagrid/Table/index.js +13 -9
- package/src/components/Date/FormatSelector.js +2 -1
- package/src/components/Form/Fields/Field.js +1 -1
- package/src/components/Snackbar/index.js +3 -1
|
@@ -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
|
|
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";
|
|
@@ -38,10 +38,19 @@ import View from "$ecomponents/View";
|
|
|
38
38
|
import {Menu} from "$ecomponents/BottomSheet";
|
|
39
39
|
import {styles as tableStyles} from "$ecomponents/Table";
|
|
40
40
|
import {DialogProvider} from "$ecomponents/Form/FormData";
|
|
41
|
-
import Chart from "$ecomponents/Chart";
|
|
42
|
-
import { aggregatorFunctions} from "../Footer/Footer";
|
|
41
|
+
import Chart,{getMaxSupportedSeriesSize} from "$ecomponents/Chart";
|
|
43
42
|
|
|
44
43
|
const chart = "chart";
|
|
44
|
+
export const donutChart = {
|
|
45
|
+
isChart : true,
|
|
46
|
+
code : 'donutChart',
|
|
47
|
+
label : 'Graphique|Circulaire',
|
|
48
|
+
icon : "chart-donut",
|
|
49
|
+
type: 'donut',
|
|
50
|
+
isDonut : true,
|
|
51
|
+
isRendable : ({displayOnlySectionListHeaders,isSectionList})=>false,//isSectionList && displayOnlySectionListHeaders,
|
|
52
|
+
tooltip : "Pour pouvoir visulaiser ce type de graphe, vous devez : grouper les données du tableau selon le criètre de votre choix, puis afficher uniquement les totaux des données groupées"
|
|
53
|
+
}
|
|
45
54
|
export const displayTypes = {
|
|
46
55
|
table : {
|
|
47
56
|
code : "table",
|
|
@@ -69,14 +78,31 @@ export const displayTypes = {
|
|
|
69
78
|
code : 'barChart',
|
|
70
79
|
label : 'Graphique|Barres',
|
|
71
80
|
icon : "chart-bar",
|
|
72
|
-
type: 'bar'
|
|
81
|
+
type: 'bar',
|
|
82
|
+
isBar : true,
|
|
73
83
|
},
|
|
74
|
-
|
|
84
|
+
donutChart,
|
|
85
|
+
/*rangeChart : {
|
|
86
|
+
code : "rangeChart",
|
|
87
|
+
isChart : true,
|
|
88
|
+
label : 'Graphique|Bar Interval',
|
|
89
|
+
icon : "chart-timeline",
|
|
90
|
+
type: 'boxPlot'
|
|
91
|
+
},*/
|
|
92
|
+
/*chartBoxPlot : {
|
|
93
|
+
code : "chartBoxPlot",
|
|
94
|
+
isChart : true,
|
|
95
|
+
label : 'Graphique|Box plot',
|
|
96
|
+
icon : "chart-waterfall",
|
|
97
|
+
type: 'boxPlot'
|
|
98
|
+
},*/
|
|
99
|
+
//@see : https://apexcharts.com/docs/chart-types/treemap-chart/
|
|
100
|
+
/*treeMap : {
|
|
101
|
+
code : "treeMap",
|
|
75
102
|
isChart : true,
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
type: 'donut'
|
|
103
|
+
label : 'Graphique|Aborescente',
|
|
104
|
+
icon : "chart-tree",
|
|
105
|
+
type: 'treemap'
|
|
80
106
|
},*/
|
|
81
107
|
}
|
|
82
108
|
|
|
@@ -122,7 +148,7 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
122
148
|
sData.fixedTable = defaultBool(sData.fixedTable,false);
|
|
123
149
|
extendObj(this.state, {
|
|
124
150
|
data,
|
|
125
|
-
showFilters : this.isFilterable() && defaultBool(props.showFilters,(sData.
|
|
151
|
+
showFilters : this.isFilterable() && defaultBool(props.showFilters,(sData.showFilters? true : this.isPivotDatagrid())) || false,
|
|
126
152
|
showFooters : defaultBool(props.showFooters,(sData.showFooters? true : false)),
|
|
127
153
|
fixedTable : sData.fixedTable
|
|
128
154
|
});
|
|
@@ -171,10 +197,15 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
171
197
|
sectionListDataSize : {value : {current : 0}},
|
|
172
198
|
enablePointerEventsRef : {value : {current:false}},
|
|
173
199
|
configureSectionListSelectedValues : {value : {}},
|
|
200
|
+
///la liste des fonctions d'aggregations supportées
|
|
201
|
+
aggregatorFunctions : {value : extendAggreagatorFunctions(this.props.aggregatorFunctions)},
|
|
174
202
|
///les types d'affichage
|
|
175
203
|
displayTypes : {value : hasFoundDisplayTypes ? disTypes : Object.clone(displayTypes)},
|
|
176
204
|
sectionListColumnsSize : {value : {current:0}}, //la taille du nombre d'éléments de section dans les colonnes
|
|
177
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];
|
|
178
209
|
this.isLoading = this.isLoading.bind(this);
|
|
179
210
|
this.getProgressBar = this.getProgressBar.bind(this);
|
|
180
211
|
this.sortRef.current.dir = defaultStr(this.sortRef.current.dir,this.sortRef.current.column == "date"?"desc":'asc')
|
|
@@ -204,12 +235,17 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
204
235
|
this.state.filteredColumns = defaultObj(this.getSessionData("filteredColumns"+this.getSessionNameKey()),this.props.filters);
|
|
205
236
|
this.filtersSelectors = {selector:this.getFilters()};
|
|
206
237
|
const {sectionListColumns} = this.prepareColumns();
|
|
238
|
+
this.state.sectionListColumns = sectionListColumns;
|
|
207
239
|
if(this.canHandleColumnResize()){
|
|
208
240
|
this.state.columnsWidths = this.preparedColumns.widths;
|
|
209
241
|
}
|
|
210
|
-
this.state.chartConfig =
|
|
242
|
+
this.state.chartConfig = extendObj({},this.getSessionData("chartConfig"),this.props.chartConfig);
|
|
211
243
|
const dType = defaultStr(this.props.displayType,this.getSessionData("displayType"),"table");
|
|
212
244
|
this.state.displayType = this.displayTypes[dType] ? this.displayTypes[dType].code : "table" in this.displayTypes ? "table" : Object.keys(this.displayTypes)[0]?.code;
|
|
245
|
+
this.state.displayOnlySectionListHeaders = defaultBool(this.getSessionData("displayOnlySectionListHeaders"),this.props.displayOnlySectionListHeaders,false)
|
|
246
|
+
if(this.state.displayOnlySectionListHeaders){
|
|
247
|
+
this.state.showFooters = true;
|
|
248
|
+
}
|
|
213
249
|
extendObj(this.state,this.prepareData({data}));
|
|
214
250
|
const {width:windowWidth,height:windowHeight} = Dimensions.get("window");
|
|
215
251
|
this.state.layout = {
|
|
@@ -254,8 +290,6 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
254
290
|
} else {
|
|
255
291
|
this.currentDataSources = Object.toArray(this.currentDataSources);
|
|
256
292
|
}
|
|
257
|
-
this.state.sectionListColumns = sectionListColumns;
|
|
258
|
-
this.state.displayOnlySectionListHeaders = defaultBool(this.getSessionData("displayOnlySectionListHeaders"),this.props.displayOnlySectionListHeaders,false)
|
|
259
293
|
}
|
|
260
294
|
|
|
261
295
|
/*** si une ligne peut être selectionable */
|
|
@@ -606,7 +640,7 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
606
640
|
}
|
|
607
641
|
}
|
|
608
642
|
}
|
|
609
|
-
|
|
643
|
+
const footers = this.getFootersFields(true);
|
|
610
644
|
let isAccordion = this.isAccordion();
|
|
611
645
|
Object.mapToArray(columns,(headerCol1,headerIndex)=>{
|
|
612
646
|
if(!isObj(headerCol1)) return;
|
|
@@ -614,6 +648,7 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
614
648
|
if(isAccordion && headerCol.accordion === false) return null;
|
|
615
649
|
let header = {...headerCol};
|
|
616
650
|
header.field = defaultStr(header.field, headerIndex)
|
|
651
|
+
header.type = defaultStr(header.jsType,header.type,"text").toLowerCase();
|
|
617
652
|
/**** pour ignorer une colonne du datagrid, il suffit de passer le paramètre datagrid à false */
|
|
618
653
|
if(!isNonNullString(header.field) || header.datagrid === false) {
|
|
619
654
|
return;
|
|
@@ -624,7 +659,7 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
624
659
|
this.state.columns[header.field] = header;
|
|
625
660
|
/*** les pieds de pages sont les données de type decimal, où qu'on peut compter */
|
|
626
661
|
if(header.footer !== false && ((arrayValueExists(['decimal','number','money'],header.type) && header.format) || header.format == 'money' || header.format =='number')){
|
|
627
|
-
footers[header.field] = header;
|
|
662
|
+
footers[header.field] = Object.clone(header);
|
|
628
663
|
}
|
|
629
664
|
if(!this.hasColumnsHalreadyInitialized){
|
|
630
665
|
this.initColumnsCallback({...header,colIndex,columnField:header.field});
|
|
@@ -632,12 +667,12 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
632
667
|
})
|
|
633
668
|
return footers;
|
|
634
669
|
}
|
|
635
|
-
|
|
670
|
+
getFootersFields(init){
|
|
636
671
|
this[this.footerFieldName] = init === true ? {} : defaultObj(this[this.footerFieldName]);
|
|
637
672
|
return this[this.footerFieldName];
|
|
638
673
|
}
|
|
639
|
-
|
|
640
|
-
return Object.size(this.
|
|
674
|
+
hasFootersFields(){
|
|
675
|
+
return Object.size(this.getFootersFields(),true) ? true : false;
|
|
641
676
|
}
|
|
642
677
|
getActionsArgs(selected){
|
|
643
678
|
const r = isObj(selected)? selected : {};
|
|
@@ -948,7 +983,7 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
948
983
|
this.isUpdating = true;
|
|
949
984
|
this.setState( {showFilters:true},()=>{
|
|
950
985
|
this.isUpdating = false;
|
|
951
|
-
this.setSessionData({
|
|
986
|
+
this.setSessionData({showFilters:true});
|
|
952
987
|
})
|
|
953
988
|
}
|
|
954
989
|
hideFilters (){
|
|
@@ -959,12 +994,12 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
959
994
|
if(this.isUpdating) return false;
|
|
960
995
|
this.setState({showFilters:false},()=>{
|
|
961
996
|
this.isUpdating = false;
|
|
962
|
-
this.setSessionData({
|
|
997
|
+
this.setSessionData({showFilters:false})
|
|
963
998
|
})
|
|
964
999
|
}
|
|
965
1000
|
|
|
966
1001
|
toggleFooters(showOrHide){
|
|
967
|
-
if(typeof showOrHide !=='boolean' || this.
|
|
1002
|
+
if(typeof showOrHide !=='boolean' || this.canShowFooters() === showOrHide) return;
|
|
968
1003
|
if(!this._isMounted()) {
|
|
969
1004
|
this.isUpdating = false;
|
|
970
1005
|
return;
|
|
@@ -1030,7 +1065,7 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
1030
1065
|
if(!isNonNullString(field)) return;
|
|
1031
1066
|
let columns = {...this.state.columns};
|
|
1032
1067
|
columns[field].visible = !columns[field].visible;
|
|
1033
|
-
let footers = this.
|
|
1068
|
+
let footers = this.getFootersFields();
|
|
1034
1069
|
if(isObj(footers[field])){
|
|
1035
1070
|
footers[field].visible = columns[field].visible;
|
|
1036
1071
|
}
|
|
@@ -1039,6 +1074,10 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
1039
1074
|
if(removeFocus) document.body.click();
|
|
1040
1075
|
});
|
|
1041
1076
|
}
|
|
1077
|
+
/****le nombre maximum de courbes supportées */
|
|
1078
|
+
getMaxSeriesSize(){
|
|
1079
|
+
return getMaxSupportedSeriesSize();
|
|
1080
|
+
}
|
|
1042
1081
|
prepareFilter(props,filteredColumns){
|
|
1043
1082
|
filteredColumns.push(props);
|
|
1044
1083
|
}
|
|
@@ -1064,7 +1103,7 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
1064
1103
|
/*** configure la */
|
|
1065
1104
|
configureSectionListColumn(column,toggleSectionList){
|
|
1066
1105
|
if(!this.isSectionListColumnConfigurable(column)) return Promise.reject({message : 'type de colonne invalide, impossible de configurer la colonne, pour permettre qu\elle soit ajoutée dans les colonnes de groupe du tableau'});
|
|
1067
|
-
const format = defaultStr(defaultObj(this.configureSectionListSelectedValues[column.field]).format,"dd/mm/yyyy")
|
|
1106
|
+
const format = defaultStr(defaultObj(this.configureSectionListSelectedValues[column.field]).format,column.format,"dd/mm/yyyy")
|
|
1068
1107
|
return new Promise((resolve,reject)=>{
|
|
1069
1108
|
DialogProvider.open({
|
|
1070
1109
|
title : 'Format de date',
|
|
@@ -1126,19 +1165,20 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
1126
1165
|
const {sectionListColumns} = this.prepareColumns({sectionListColumns:{}});
|
|
1127
1166
|
this.setIsLoading(true,()=>{
|
|
1128
1167
|
this.prepareData({data:this.INITIAL_STATE.data,sectionListColumns},(state)=>{
|
|
1129
|
-
this.setState({...state,sectionListColumns},()=>{
|
|
1168
|
+
this.setState({...state,sectionListColumns,displayOnlySectionListHeaders:false},()=>{
|
|
1130
1169
|
this.setIsLoading(false,false);
|
|
1131
1170
|
this.setSessionData("sectionListColumns",null);
|
|
1171
|
+
this.setSessionData("displayOnlySectionListHeaders",false);
|
|
1132
1172
|
});
|
|
1133
1173
|
});
|
|
1134
1174
|
},true);
|
|
1135
1175
|
}
|
|
1136
1176
|
canDisplayOnlySectionListHeaders(){
|
|
1137
|
-
return this.
|
|
1177
|
+
return this.hasFootersFields() && this.isSectionList() && this.hasSectionListData();
|
|
1138
1178
|
}
|
|
1139
1179
|
/*** si l'on peut rendre le contenu de type graphique */
|
|
1140
1180
|
isChartRendable(){
|
|
1141
|
-
return !this.isPivotDatagrid() && this.
|
|
1181
|
+
return !this.isPivotDatagrid() && this.hasFootersFields();
|
|
1142
1182
|
}
|
|
1143
1183
|
isValidChartConfig(config){
|
|
1144
1184
|
config = defaultObj(config,this.state.chartConfig);
|
|
@@ -1165,12 +1205,14 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
1165
1205
|
},true)
|
|
1166
1206
|
} else {
|
|
1167
1207
|
const cb = (chartConfig)=>{
|
|
1168
|
-
|
|
1169
|
-
this.
|
|
1170
|
-
this.
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1208
|
+
setTimeout(()=>{
|
|
1209
|
+
this.setIsLoading(true,()=>{
|
|
1210
|
+
this.setState({chartConfig,displayType},()=>{
|
|
1211
|
+
this.setIsLoading(false,false);
|
|
1212
|
+
this.persistDisplayType(displayType);
|
|
1213
|
+
})
|
|
1214
|
+
},true);
|
|
1215
|
+
},200);
|
|
1174
1216
|
}
|
|
1175
1217
|
if(!this.isValidChartConfig()){
|
|
1176
1218
|
return this.configureChart(false).then((chartConfig)=>{
|
|
@@ -1180,21 +1222,79 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
1180
1222
|
cb({...this.state.chartConfig});
|
|
1181
1223
|
}
|
|
1182
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
|
+
}
|
|
1183
1283
|
configureChart(refreshChart){
|
|
1184
1284
|
if(!this.isChartRendable()){
|
|
1185
1285
|
return Promise.reject({message:'Impossible de configurer le graphe car le type de données ne permet pas de rendu de type graphe'});
|
|
1186
1286
|
}
|
|
1187
1287
|
const xItems = {},yItems = {},config = defaultObj(this.state.chartConfig);
|
|
1188
1288
|
const series = {};
|
|
1189
|
-
let hasSeries = false;
|
|
1190
1289
|
const isValidConfig = this.isValidChartConfig();
|
|
1191
1290
|
Object.map(this.state.columns,(field,f)=>{
|
|
1192
1291
|
if(isObj(field) && !this.isSelectableColumn(field) && !this.isIndexColumn(field)){
|
|
1193
|
-
xItems[f] = field;
|
|
1194
1292
|
const type = defaultStr(field.jsType,field.type).toLowerCase();
|
|
1195
1293
|
if(type === 'number' || type=='decimal'){
|
|
1196
1294
|
yItems[f] = field;
|
|
1197
1295
|
series[f] = field;
|
|
1296
|
+
} else {
|
|
1297
|
+
xItems[f] = field;
|
|
1198
1298
|
}
|
|
1199
1299
|
}
|
|
1200
1300
|
});
|
|
@@ -1215,6 +1315,7 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
1215
1315
|
DialogProvider.open({
|
|
1216
1316
|
title : 'Configuration des graphes',
|
|
1217
1317
|
subtitle : false,
|
|
1318
|
+
data : this.getCharConfig(),
|
|
1218
1319
|
fields : {
|
|
1219
1320
|
x : {
|
|
1220
1321
|
text : 'Axe des x[horizontal]',
|
|
@@ -1232,20 +1333,33 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
1232
1333
|
defaultValue : config.y,
|
|
1233
1334
|
onValidatorValid,
|
|
1234
1335
|
},
|
|
1235
|
-
series :
|
|
1336
|
+
series : {
|
|
1236
1337
|
text : 'Series',
|
|
1237
1338
|
type : "select",
|
|
1238
1339
|
items : series,
|
|
1239
1340
|
multiple : true,
|
|
1240
1341
|
},
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
multiple :
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1342
|
+
sectionListHeadersSeries : {
|
|
1343
|
+
text : "Series des données groupées",
|
|
1344
|
+
type : "select",
|
|
1345
|
+
items : yItems,
|
|
1346
|
+
multiple : true,
|
|
1347
|
+
},
|
|
1348
|
+
stacked : {
|
|
1349
|
+
type : 'switch',
|
|
1350
|
+
text : "Graphe empilé?",
|
|
1351
|
+
disabled : this.state.displayType !== "barChart",
|
|
1352
|
+
checkedValue : true,
|
|
1353
|
+
uncheckedValue : false,
|
|
1354
|
+
},
|
|
1355
|
+
title : {
|
|
1356
|
+
text : "Titre du graphe",
|
|
1357
|
+
format :'hashtag',
|
|
1358
|
+
},
|
|
1359
|
+
titleColor: {
|
|
1360
|
+
text : "Couleur de titre",
|
|
1361
|
+
type :"color",
|
|
1362
|
+
},
|
|
1249
1363
|
},
|
|
1250
1364
|
actions : [
|
|
1251
1365
|
{
|
|
@@ -1270,15 +1384,24 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
1270
1384
|
getCharConfig(){
|
|
1271
1385
|
return defaultObj(this.state.chartConfig);
|
|
1272
1386
|
}
|
|
1387
|
+
getChartIsRendableArgs(){
|
|
1388
|
+
return {
|
|
1389
|
+
context:this,isSectionList:this.isSectionList(),hasSectionListData:this.hasSectionListData(),
|
|
1390
|
+
data : this.state.data,
|
|
1391
|
+
displayOnlySectionListHeaders : this.canDisplayOnlySectionListHeaders(),
|
|
1392
|
+
};
|
|
1393
|
+
}
|
|
1273
1394
|
renderDisplayTypes(){
|
|
1274
1395
|
const m = [];
|
|
1275
1396
|
let activeType = null,hasFoundChart = false,hasFoundTable = false;
|
|
1276
1397
|
const hasConfig = this.isValidChartConfig();
|
|
1277
1398
|
Object.map(this.displayTypes,(type,k)=>{
|
|
1399
|
+
let isChartDisabled = false;
|
|
1278
1400
|
if(type.isChart === true ) {
|
|
1279
1401
|
if(!this.isChartRendable()){
|
|
1280
1402
|
return null;
|
|
1281
1403
|
}
|
|
1404
|
+
isChartDisabled = typeof type.isRendable =='function' && type.isRendable(this.getChartIsRendableArgs()) === false ? true : false;
|
|
1282
1405
|
if(!hasFoundChart){
|
|
1283
1406
|
if(hasFoundTable){
|
|
1284
1407
|
m.push({divider:true});
|
|
@@ -1288,7 +1411,16 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
1288
1411
|
divider : true,
|
|
1289
1412
|
text : "Configurer les graphes",
|
|
1290
1413
|
icon :"material-settings",
|
|
1291
|
-
onPress :
|
|
1414
|
+
onPress : ()=>{
|
|
1415
|
+
this.configureChart(false).then((chartConfig)=>{
|
|
1416
|
+
this.setIsLoading(true,()=>{
|
|
1417
|
+
this.setState({chartConfig},()=>{
|
|
1418
|
+
this.setSessionData("chartConfig",chartConfig);
|
|
1419
|
+
this.setIsLoading(false,false);
|
|
1420
|
+
});
|
|
1421
|
+
},true)
|
|
1422
|
+
})
|
|
1423
|
+
}
|
|
1292
1424
|
});
|
|
1293
1425
|
}
|
|
1294
1426
|
} else if(k === 'table'){
|
|
@@ -1304,7 +1436,7 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
1304
1436
|
right : <>
|
|
1305
1437
|
{active ? <Icon color={theme.colors.primaryOnSurface} name="check"/>: null}
|
|
1306
1438
|
</>,
|
|
1307
|
-
disabled : type.isChart && !hasConfig ? true : undefined,
|
|
1439
|
+
disabled : isChartDisabled || type.isChart && !hasConfig ? true : undefined,
|
|
1308
1440
|
onPress:()=>{
|
|
1309
1441
|
this.setDisplayType(type);
|
|
1310
1442
|
}
|
|
@@ -1329,105 +1461,242 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
1329
1461
|
getEmptyDataValue(){
|
|
1330
1462
|
return "N/A";
|
|
1331
1463
|
}
|
|
1464
|
+
/*** retourne les sectionHeaderSeries par défautt */
|
|
1465
|
+
getDefaultSectionHeadersSeries(){
|
|
1466
|
+
if(!this.isSectionList() || !this.hasFootersFields()) return [];
|
|
1467
|
+
const footersFields = this.getFootersFields();
|
|
1468
|
+
const r = [],max = this.getMaxSeriesSize();
|
|
1469
|
+
let counter = 0;
|
|
1470
|
+
for(let i in footersFields){
|
|
1471
|
+
const footer = footersFields[i];
|
|
1472
|
+
if(!isObj(footer)) continue;
|
|
1473
|
+
if(counter >= max) break;
|
|
1474
|
+
r.push(i);
|
|
1475
|
+
}
|
|
1476
|
+
return r;
|
|
1477
|
+
}
|
|
1478
|
+
formatChartDataValue({value,column,options}){
|
|
1479
|
+
return value;
|
|
1480
|
+
}
|
|
1481
|
+
/*****
|
|
1482
|
+
* retourne les paramètres à passer au chart, lorsque les données sont groupées, ie les sectionsListColumns est non nulle
|
|
1483
|
+
* @param {object} de la forme suivante :
|
|
1484
|
+
* @param {object} chartType le type de chart, l'un des types du tableau displayTypes en haut du présent fichier
|
|
1485
|
+
* @param {object} yAxisColumn la colonne de l'axe vertical y
|
|
1486
|
+
* @param {object} xAxisColumn la colonne de l'axe des x de la courbe, pris dans les configurations du chart, chartConfig
|
|
1487
|
+
* @param {object} la fonction d'aggrégation, l'une des fonctions issues des fonctions d'aggrégations aggregatorsFuncions, @see : dans $components/Datagrid/Footer
|
|
1488
|
+
* en affichage des tableaux de type sectionList, seul les colonnes de totalisation sont utilisées pour l'affichage du graphe
|
|
1489
|
+
* Le nombre de graphes (series) à afficher est valable pour tous les graphes sauf les graphes de type pie/donut.
|
|
1490
|
+
* il est récupéré dans la variable chartConfig des configuration du chart, où par défaut le nombre de colonnes de totalisation des tableau (inférieur au nombre maximum de courbes surpportées par appexchart)
|
|
1491
|
+
*/
|
|
1492
|
+
getSectionListHeadersChartOptions({chartType,yAxisColumn,xAxisColumn,aggregatorFunction}){
|
|
1493
|
+
if(!this.isSectionList()) return null;
|
|
1494
|
+
if(!isObj(chartType) || !isObj(yAxisColumn) || !yAxisColumn.field) return null;
|
|
1495
|
+
if(!isValidAggregator(aggregatorFunction)){
|
|
1496
|
+
aggregatorFunction = this.getActiveAggregatorFunction();
|
|
1497
|
+
}
|
|
1498
|
+
const code = aggregatorFunction.code;
|
|
1499
|
+
const isDonut = chartType.isDonut || chartType.isRadial;
|
|
1500
|
+
const config = this.getCharConfig();
|
|
1501
|
+
//@see : https://apexcharts.com/docs/series/
|
|
1502
|
+
///lorsqu'on affiche uniquement les totaux des sections, alors la visualition se fait sur uniquement sur la base des valeurs
|
|
1503
|
+
///on parcoure uniquement les entêtes des sectionLis
|
|
1504
|
+
const dataIndexes={},dataInexesNames = {};
|
|
1505
|
+
//la variable sectionListHeaderSeries, permet de récupérer les colonnes de type montant à utiliser pour le rendu du chart
|
|
1506
|
+
let serieName = "";
|
|
1507
|
+
const tableFooters = this.getFootersFields();
|
|
1508
|
+
const defaultSectionListHeadersSeries = this.getDefaultSectionHeadersSeries();
|
|
1509
|
+
let seriesConfig = isDonut ? [] : Array.isArray(config.sectionListHeadersSeries) && config.sectionListHeadersSeries.length ? config.sectionListHeadersSeries : [];
|
|
1510
|
+
if(!isDonut){
|
|
1511
|
+
if(seriesConfig.length){
|
|
1512
|
+
const ss = [];
|
|
1513
|
+
seriesConfig.map((s)=>{
|
|
1514
|
+
if(!isNonNullString(s) || !tableFooters[s]) return null;
|
|
1515
|
+
ss.push(s);
|
|
1516
|
+
});
|
|
1517
|
+
seriesConfig = ss;
|
|
1518
|
+
}
|
|
1519
|
+
if(!seriesConfig.length){
|
|
1520
|
+
seriesConfig = defaultSectionListHeadersSeries;
|
|
1521
|
+
}
|
|
1522
|
+
}
|
|
1523
|
+
/**** boucle sur chaque éléments trouvée dans le tableau des données sectionListData */
|
|
1524
|
+
const loopForFooter = ({column,serieName,footers,header})=>{
|
|
1525
|
+
if(!isObj(column) || !isObj(footers)) return null;
|
|
1526
|
+
if(!isObj(footers[column.field])) return null;
|
|
1527
|
+
const footer = footers[column.field]
|
|
1528
|
+
if(typeof footer[code] !== 'number') return null;
|
|
1529
|
+
const label = defaultStr(footer.label,footer.text,footer.field);
|
|
1530
|
+
if(typeof footer[code] !== 'number') return null;
|
|
1531
|
+
if(isDonut){
|
|
1532
|
+
serieName = label;
|
|
1533
|
+
dataIndexes[header] = footer[code];
|
|
1534
|
+
} else {
|
|
1535
|
+
dataIndexes[serieName] = defaultArray(dataIndexes[serieName]);
|
|
1536
|
+
dataIndexes[serieName].push({x:header,y:footer[code]});
|
|
1537
|
+
}
|
|
1538
|
+
}
|
|
1539
|
+
Object.map(this.sectionListData,(data,header)=>{
|
|
1540
|
+
if(!isObj(this.sectionListHeaderFooters[header])) return null;
|
|
1541
|
+
const footers = this.sectionListHeaderFooters[header];
|
|
1542
|
+
if(isDonut){
|
|
1543
|
+
loopForFooter({footers,header,column:yAxisColumn})
|
|
1544
|
+
} else {
|
|
1545
|
+
seriesConfig.map((s)=>{
|
|
1546
|
+
const serie = this.state.columns[s];
|
|
1547
|
+
const serieName = defaultStr(s.label,s.text,s);
|
|
1548
|
+
loopForFooter({footers,serie,serieName,header,column:tableFooters[s]})
|
|
1549
|
+
})
|
|
1550
|
+
}
|
|
1551
|
+
});
|
|
1552
|
+
if(isDonut){
|
|
1553
|
+
const series = [],labels = [];
|
|
1554
|
+
Object.map(dataIndexes,(serie,index)=>{
|
|
1555
|
+
series.push(serie);
|
|
1556
|
+
labels.push(index);
|
|
1557
|
+
});
|
|
1558
|
+
return {
|
|
1559
|
+
series,
|
|
1560
|
+
labels,
|
|
1561
|
+
}
|
|
1562
|
+
} else {
|
|
1563
|
+
const series = [];
|
|
1564
|
+
Object.map(dataIndexes,(data,name)=>{
|
|
1565
|
+
series.push({name,data});
|
|
1566
|
+
});
|
|
1567
|
+
return {
|
|
1568
|
+
series
|
|
1569
|
+
}
|
|
1570
|
+
}
|
|
1571
|
+
}
|
|
1332
1572
|
renderChart(){
|
|
1333
1573
|
if(!this.canRenderChart()) return null;
|
|
1334
1574
|
if(!this.isValidChartConfig()) return null;
|
|
1335
1575
|
const chartType = displayTypes[this.state.displayType];
|
|
1336
1576
|
if(!isObj(chartType) || !isNonNullString(chartType.type)) return null;
|
|
1577
|
+
if(typeof chartType.isRendable =='function' && chartType.isRendable(this.getChartIsRendableArgs()) === false) {
|
|
1578
|
+
console.warn("impossible d'afficher le graphe de type ",chartType.label," car le type de données requis pour le rendu de ce graphe est invalide")
|
|
1579
|
+
return null;
|
|
1580
|
+
}
|
|
1337
1581
|
const config = this.getCharConfig();
|
|
1338
1582
|
if(!this.state.columns[config.y]) return null;
|
|
1339
|
-
const
|
|
1340
|
-
const type = defaultStr(
|
|
1583
|
+
const yAxisColumn = this.state.columns[config.y];
|
|
1584
|
+
const type = defaultStr(yAxisColumn.jsType,yAxisColumn.type).toLowerCase();
|
|
1341
1585
|
if(type !== 'number'&& type !== 'decimal') return null;
|
|
1342
1586
|
const isEmptyY = config.x === this.emptySectionListHeaderValue;
|
|
1343
|
-
|
|
1344
|
-
|
|
1587
|
+
let seriesConfig = Array.isArray(config.series) && config.series.length ? config.series : [yAxisColumn.field];
|
|
1588
|
+
const snConfig = [];
|
|
1589
|
+
Object.map(seriesConfig,(s,v)=>{
|
|
1590
|
+
if(!isNonNullString(s) || !this.state.columns[s]) return null;
|
|
1591
|
+
snConfig.push(s);
|
|
1592
|
+
});
|
|
1593
|
+
seriesConfig = snConfig.length> 0 ? snConfig : [yAxisColumn.field];
|
|
1594
|
+
let xAxisColumn = null;
|
|
1345
1595
|
if(!isEmptyY){
|
|
1346
1596
|
if(!this.state.columns[config.x]){
|
|
1347
1597
|
return null;
|
|
1348
1598
|
}
|
|
1349
|
-
|
|
1350
|
-
}
|
|
1351
|
-
let aggregatorFunction = typeof config.aggregatorFunction =='string' && aggregatorFunctions[config.aggregatorFunction]?aggregatorFunctions[config.aggregatorFunction] :aggregatorFunctions.sum;
|
|
1352
|
-
if(isObj(aggregatorFunction) && typeof aggregatorFunction.eval =='function'){
|
|
1353
|
-
aggregatorFunction = aggregatorFunction.eval;
|
|
1354
|
-
} else {
|
|
1355
|
-
aggregatorFunction = aggregatorFunctions.sum.eval;
|
|
1356
|
-
}
|
|
1357
|
-
if(this.isSectionList()){
|
|
1358
|
-
return null;
|
|
1599
|
+
xAxisColumn = this.state.columns[config.x];
|
|
1359
1600
|
}
|
|
1601
|
+
const aggregatorFunction = this.getActiveAggregatorFunction().eval;
|
|
1360
1602
|
const emptyValue = this.getEmptyDataValue();
|
|
1361
|
-
const indexes = {}
|
|
1603
|
+
const indexes = {};
|
|
1604
|
+
let series = [],xaxis = {},customConfig = {};
|
|
1362
1605
|
let count = 0;
|
|
1363
|
-
this.
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1606
|
+
if(!this.isSectionList()){
|
|
1607
|
+
this.state.data.map((data,index)=>{
|
|
1608
|
+
if(!isObj(data))return null;
|
|
1609
|
+
const txt = this.renderRowCell({
|
|
1610
|
+
data,
|
|
1611
|
+
rowData : data,
|
|
1612
|
+
rowCounterIndex : index,
|
|
1613
|
+
rowIndex : index,
|
|
1614
|
+
columnDef : xAxisColumn,
|
|
1615
|
+
renderRowCell : false,
|
|
1616
|
+
columnField : xAxisColumn.field,
|
|
1617
|
+
});
|
|
1618
|
+
const text = isNonNullString(txt)? txt : emptyValue;
|
|
1619
|
+
Object.map(seriesConfig,(s,v)=>{
|
|
1620
|
+
if(!isNonNullString(s) || !this.state.columns[s]) return null;
|
|
1621
|
+
const columnDef = this.state.columns[s];
|
|
1622
|
+
if(!isObj(columnDef)) return null;
|
|
1623
|
+
indexes[s] = defaultObj(indexes[s]);
|
|
1624
|
+
const current = indexes[s];
|
|
1625
|
+
current[text] = typeof current[text] =="number"? current[text] : 0;
|
|
1626
|
+
const value = getFooterColumnValue({data,columnDef,columnField:columnDef.field});
|
|
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
|
+
});
|
|
1373
1630
|
});
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
Object.map(indexes,(values,serieName)=>{
|
|
1388
|
-
const col = this.state.columns[serieName];
|
|
1389
|
-
const name = defaultStr(col?.label,col?.text,serieName),data = [];
|
|
1390
|
-
Object.map(values,(v,i)=>{
|
|
1391
|
-
data.push({
|
|
1392
|
-
x : i,
|
|
1393
|
-
y : v,
|
|
1631
|
+
Object.map(indexes,(values,serieName)=>{
|
|
1632
|
+
const col = this.state.columns[serieName];
|
|
1633
|
+
const name = defaultStr(col?.label,col?.text,serieName),data = [];
|
|
1634
|
+
Object.map(values,(v,i)=>{
|
|
1635
|
+
data.push({
|
|
1636
|
+
x : i,
|
|
1637
|
+
y : v,
|
|
1638
|
+
})
|
|
1639
|
+
})
|
|
1640
|
+
series.push({
|
|
1641
|
+
name,
|
|
1642
|
+
type : chartType.type,
|
|
1643
|
+
data,
|
|
1394
1644
|
})
|
|
1395
1645
|
})
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
const {layout} = this.state;
|
|
1404
|
-
let maxHeight = winheight-100;
|
|
1405
|
-
if(layout && typeof layout.windowHeight =='number' && layout.windowHeight){
|
|
1406
|
-
const diff = winheight - Math.max(defaultNumber(layout.y,layout.top),100);
|
|
1407
|
-
if(winheight<=350){
|
|
1408
|
-
maxHeight = 350;
|
|
1646
|
+
} else {
|
|
1647
|
+
const configs = this.getSectionListHeadersChartOptions({chartType,aggregatorFunction,xAxisColumn,yAxisColumn});
|
|
1648
|
+
if(isObj(configs)){
|
|
1649
|
+
const {series :customSeries,xaxis:customXaxis,...rest} = configs;
|
|
1650
|
+
series = Array.isArray(customSeries) ? customSeries : series;
|
|
1651
|
+
xaxis = isObj(customXaxis)? customXaxis : xaxis;
|
|
1652
|
+
customConfig = rest;
|
|
1409
1653
|
} else {
|
|
1410
|
-
|
|
1654
|
+
return null;
|
|
1411
1655
|
}
|
|
1412
1656
|
}
|
|
1413
|
-
|
|
1657
|
+
customConfig = defaultObj(customConfig);
|
|
1658
|
+
customConfig.chart = defaultObj(customConfig.chart);
|
|
1659
|
+
const chartProps = extendObj(true,{},this.props.chartProps,customConfig);
|
|
1660
|
+
if(chartType.isBar){
|
|
1661
|
+
chartProps.chart.stacked = !!config.stacked;
|
|
1662
|
+
} else chartProps.chart.stacked = undefined;
|
|
1414
1663
|
return <Chart
|
|
1415
1664
|
options = {{
|
|
1416
|
-
...
|
|
1665
|
+
...chartProps,
|
|
1666
|
+
title : {
|
|
1667
|
+
text: defaultStr(config.title,chartProps.title),
|
|
1668
|
+
align: 'left',
|
|
1669
|
+
//margin: 10,
|
|
1670
|
+
//offsetX: 0,
|
|
1671
|
+
//offsetY: 0,
|
|
1672
|
+
//floating: false,
|
|
1673
|
+
style: {
|
|
1674
|
+
//fontSize: '14px',
|
|
1675
|
+
//fontWeight: 'bold',
|
|
1676
|
+
//fontFamily: undefined,
|
|
1677
|
+
color: theme.Colors.isValid(config.titleColor)?config.titleColor : undefined,
|
|
1678
|
+
},
|
|
1679
|
+
},
|
|
1417
1680
|
series,
|
|
1418
1681
|
chart : {
|
|
1419
1682
|
height :350,
|
|
1420
|
-
maxHeight,
|
|
1421
1683
|
...defaultObj(chartProps.chart),
|
|
1422
1684
|
type : chartType.type,
|
|
1423
1685
|
},
|
|
1424
1686
|
xaxis: {
|
|
1425
1687
|
...defaultObj(chartProps.xaxis),
|
|
1426
|
-
type: 'category'
|
|
1688
|
+
type: 'category',
|
|
1689
|
+
...defaultObj(xaxis)
|
|
1427
1690
|
}
|
|
1428
1691
|
}}
|
|
1429
1692
|
/>
|
|
1430
1693
|
}
|
|
1694
|
+
canShowFooters(){
|
|
1695
|
+
return this.state.showFooters || this.hasSectionListData() && this.state.displayOnlySectionListHeaders;
|
|
1696
|
+
}
|
|
1697
|
+
canShowFilters(){
|
|
1698
|
+
return this.state.showFilters
|
|
1699
|
+
}
|
|
1431
1700
|
toggleDisplayOnlySectionListHeaders(){
|
|
1432
1701
|
if(!this.canDisplayOnlySectionListHeaders()) return
|
|
1433
1702
|
setTimeout(()=>{
|
|
@@ -1532,7 +1801,6 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
1532
1801
|
} = header;
|
|
1533
1802
|
restCol = Object.clone(defaultObj(restCol));
|
|
1534
1803
|
let colFilter = defaultVal(restCol.filter,true);
|
|
1535
|
-
const format = defaultStr(restCol.format).toLowerCase();
|
|
1536
1804
|
field = header.field = defaultStr(header.field,field,headerIndex);
|
|
1537
1805
|
delete restCol.filter;
|
|
1538
1806
|
|
|
@@ -1588,9 +1856,13 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
1588
1856
|
sortedColumn.header = header;
|
|
1589
1857
|
sortedColumn.label = restCol.label;
|
|
1590
1858
|
const isDesc = currentSortedColumn.dir === "desc";
|
|
1859
|
+
const sortDir = isDesc ? "descending" : "ascending";
|
|
1591
1860
|
const prefix = (sortType =='number' || sortType == 'decimal') ? "numeric" : sortType =='boolean'?'bool' : sortType.contains('date') ? 'calendar': sortType =='time'? 'clock' : 'alphabetical';
|
|
1592
|
-
sortedColumn.icon = 'sort-'+prefix+'-'+
|
|
1861
|
+
sortedColumn.icon = 'sort-'+prefix+'-'+sortDir;
|
|
1593
1862
|
sortedColumn.title = (isDesc ? "Trié par ordre décroissant":"Trié par ordre croissant ")+ " du champ ["+restCol.label+"]";
|
|
1863
|
+
if(sortType.contains('date') || sortType.contains("time")){
|
|
1864
|
+
sortedColumn.title = "le champ {0} est actuellement trié du plus {1} au plus {2}".sprintf(restCol.label,isDesc?"récent":"ancien",isDesc?"ancien":"récent")
|
|
1865
|
+
}
|
|
1594
1866
|
}
|
|
1595
1867
|
sortedColumns[field] = restCol.label;
|
|
1596
1868
|
sortedColumnsLength++;
|
|
@@ -1660,15 +1932,15 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
1660
1932
|
...header,
|
|
1661
1933
|
width,
|
|
1662
1934
|
type,
|
|
1935
|
+
...sListColumns[field],
|
|
1663
1936
|
...defaultObj(this.configureSectionListSelectedValues[field]),
|
|
1664
|
-
...sListColumns[field],
|
|
1665
1937
|
};///les colonnes de sections
|
|
1666
1938
|
this.sectionListColumnsSize.current++;
|
|
1667
1939
|
}
|
|
1668
1940
|
const mItem = {
|
|
1941
|
+
...header,
|
|
1669
1942
|
field,
|
|
1670
1943
|
type,
|
|
1671
|
-
format,
|
|
1672
1944
|
onPress : ()=>{
|
|
1673
1945
|
this.toggleColumnInSectionList(field);
|
|
1674
1946
|
return false;
|
|
@@ -1679,9 +1951,9 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
1679
1951
|
if(this.isSectionListColumnConfigurable(mItem)){
|
|
1680
1952
|
mItem.right = (p)=>{
|
|
1681
1953
|
return <Icon name="material-settings" {...p} onPress={(e)=>{
|
|
1682
|
-
React.stopEventPropagation(e);
|
|
1954
|
+
//React.stopEventPropagation(e);
|
|
1683
1955
|
this.configureSectionListColumn(mItem);
|
|
1684
|
-
return false;
|
|
1956
|
+
//return false;
|
|
1685
1957
|
}}/>
|
|
1686
1958
|
}
|
|
1687
1959
|
}
|
|
@@ -1748,11 +2020,25 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
1748
2020
|
let isArr = Array.isArray(data);
|
|
1749
2021
|
//let push = (d,index) => isArr ? newData.push(d) : newData[index] = d;
|
|
1750
2022
|
const hasLocalFilter = this.props.filters !== false && this.hasLocalFilters;
|
|
1751
|
-
|
|
1752
|
-
const canUpdateFooters = !!(updateFooters !== false &&
|
|
2023
|
+
const footersColumns = this.getFootersFields(),hasFootersFields = this.hasFootersFields();
|
|
2024
|
+
const canUpdateFooters = !!(updateFooters !== false && hasFootersFields);
|
|
1753
2025
|
this.hasFoundSectionData.current = false;
|
|
1754
2026
|
this.sectionListDataSize.current = 0;
|
|
1755
2027
|
const isSList = this.isSectionList(sectionListColumns);
|
|
2028
|
+
if(this.canAutoSort() && isNonNullString(this.sortRef.current.column)){
|
|
2029
|
+
if(isObj(this.state.columns) && this.state.columns[this.sortRef.current.column]){
|
|
2030
|
+
let field = this.state.columns[this.sortRef.current.column];
|
|
2031
|
+
const sortConfig = Object.assign({},this.sortRef.current);
|
|
2032
|
+
sortConfig.getItem = (item,columnName,{getItem})=>{
|
|
2033
|
+
if(isObj(item) && (field.type =='decimal' || field.type =="number")){
|
|
2034
|
+
const v = item[columnName];
|
|
2035
|
+
return isDecimal(v)? v : isNonNullString(v)? parseDecimal(v) : 0;
|
|
2036
|
+
}
|
|
2037
|
+
return getItem(item,columnName);
|
|
2038
|
+
}
|
|
2039
|
+
data = sortBy(data,sortConfig);//on trie tout d'abord les données
|
|
2040
|
+
}
|
|
2041
|
+
}
|
|
1756
2042
|
if(hasLocalFilter || !isArr || canUpdateFooters || isSList) {
|
|
1757
2043
|
if(canUpdateFooters){
|
|
1758
2044
|
this.___evaluatedFootersValues = {}
|
|
@@ -1765,10 +2051,12 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
1765
2051
|
Object.map(this.sectionListData,(v,i)=>{
|
|
1766
2052
|
delete this.sectionListData[i];
|
|
1767
2053
|
});
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
2054
|
+
if(canUpdateFooters){
|
|
2055
|
+
//on réinnitialise tous les footes
|
|
2056
|
+
Object.map(this.sectionListHeaderFooters,(v,i)=>{
|
|
2057
|
+
delete this.sectionListHeaderFooters[i];
|
|
2058
|
+
})
|
|
2059
|
+
}
|
|
1772
2060
|
}
|
|
1773
2061
|
let currentSectionListFooter = null;
|
|
1774
2062
|
const sectionListData = this.sectionListData;//l'ensemble des données de sectionList
|
|
@@ -1791,6 +2079,7 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
1791
2079
|
}
|
|
1792
2080
|
sectionListData[r].push(d);
|
|
1793
2081
|
if(canUpdateFooters){
|
|
2082
|
+
///garde pour chaque éléments de groue, la valeur des champs de son footer
|
|
1794
2083
|
this.sectionListHeaderFooters[r] = defaultObj(this.sectionListHeaderFooters[r]);
|
|
1795
2084
|
currentSectionListFooter = this.sectionListHeaderFooters[r];
|
|
1796
2085
|
}
|
|
@@ -1802,7 +2091,7 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
1802
2091
|
result.push(currentSectionListFooter);
|
|
1803
2092
|
}
|
|
1804
2093
|
Object.map(footersColumns,(columnDef,field)=>{
|
|
1805
|
-
evalSingleValue({data:d,columnDef,field,result,displayLabel:false})
|
|
2094
|
+
evalSingleValue({data:d,aggregatorFunction:this.getActiveAggregatorFunction(),aggregatorFunctions:this.aggregatorFunctions,columnDef,field,result,displayLabel:false})
|
|
1806
2095
|
});
|
|
1807
2096
|
}
|
|
1808
2097
|
newData.push(d);
|
|
@@ -1810,20 +2099,6 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
1810
2099
|
});
|
|
1811
2100
|
data = newData;
|
|
1812
2101
|
}
|
|
1813
|
-
if(this.canAutoSort() && isNonNullString(this.sortRef.current.column)){
|
|
1814
|
-
if(isObj(this.state.columns) && this.state.columns[this.sortRef.current.column]){
|
|
1815
|
-
let field = this.state.columns[this.sortRef.current.column];
|
|
1816
|
-
const sortConfig = Object.assign({},this.sortRef.current);
|
|
1817
|
-
sortConfig.getItem = (item,columnName,{getItem})=>{
|
|
1818
|
-
if(isObj(item) && (field.type =='decimal' || field.type =="number")){
|
|
1819
|
-
const v = item[columnName];
|
|
1820
|
-
return isDecimal(v)? v : isNonNullString(v)? parseDecimal(v) : 0;
|
|
1821
|
-
}
|
|
1822
|
-
return getItem(item,columnName);
|
|
1823
|
-
}
|
|
1824
|
-
data = sortBy(data,sortConfig);//on trie tout d'abord les données
|
|
1825
|
-
}
|
|
1826
|
-
}
|
|
1827
2102
|
this.INITIAL_STATE.data = data;
|
|
1828
2103
|
if(this.hasFoundSectionData.current){
|
|
1829
2104
|
data = [];
|
|
@@ -1905,7 +2180,7 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
1905
2180
|
}
|
|
1906
2181
|
}
|
|
1907
2182
|
let cells = null;
|
|
1908
|
-
if(this.
|
|
2183
|
+
if(this.canShowFooters() && isObj(this.sectionListHeaderFooters[key])){
|
|
1909
2184
|
const {visibleColumnsNames,widths} = defaultObj(this.preparedColumns);
|
|
1910
2185
|
if(isObj(visibleColumnsNames) &&isObj(widths)){
|
|
1911
2186
|
cells = [];
|
|
@@ -1927,6 +2202,8 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
1927
2202
|
key = {key}
|
|
1928
2203
|
testID={testID+"_FooterItem_"+key}
|
|
1929
2204
|
{...footer}
|
|
2205
|
+
aggregatorFunction = {this.getActiveAggregatorFunction().code}
|
|
2206
|
+
aggregatorFunctions = {this.aggregatorFunctions}
|
|
1930
2207
|
displayLabel = {false}
|
|
1931
2208
|
//anchorProps = {{style:[theme.styles.ph1,theme.styles.mh05]}}
|
|
1932
2209
|
/>
|
|
@@ -2258,10 +2535,18 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
2258
2535
|
getMaxSelectedRows(){
|
|
2259
2536
|
return 0;
|
|
2260
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
|
+
}
|
|
2261
2545
|
getMaxSelectableRows(){
|
|
2262
2546
|
let max = this.getMaxSelectedRows();
|
|
2263
|
-
|
|
2264
|
-
|
|
2547
|
+
const dataSize = this.getStateDataSize();
|
|
2548
|
+
if(dataSize){
|
|
2549
|
+
max = max ? Math.min(max,dataSize,max) : dataSize;
|
|
2265
2550
|
}
|
|
2266
2551
|
return Math.max(max-this.getSectionListDataSize(),0);
|
|
2267
2552
|
}
|
|
@@ -2865,10 +3150,14 @@ CommonDatagridComponent.propTypes = {
|
|
|
2865
3150
|
x : PropTypes.string.isRequired, //l'axe horizontal
|
|
2866
3151
|
y : PropTypes.string.isRequired, //l'axe des y, les colonnes de type nombre
|
|
2867
3152
|
series : PropTypes.arrayOf([PropTypes.string]), //les séries, le nombre de courbe a afficher sur le graphe, en fonction du type
|
|
3153
|
+
/**** les series à utiliser pour l'affichage des données lorsque les colonnes sont groupées, ie les montant de totalisation sont utilisés */
|
|
3154
|
+
sectionListHeadersSeries : PropTypes.arrayOf([PropTypes.string]),
|
|
2868
3155
|
}),
|
|
2869
3156
|
displayType : chartDisplayType,
|
|
2870
3157
|
/*** les types d'afichates supportés par l'application */
|
|
2871
|
-
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,
|
|
2872
3161
|
}
|
|
2873
3162
|
|
|
2874
3163
|
const styles = StyleSheet.create({
|