@fto-consult/expo-ui 2.20.1 → 2.21.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +3 -2
- package/src/components/Chart/index.js +16 -18
- package/src/components/Datagrid/Accordion/index.js +13 -8
- package/src/components/Datagrid/Common/Common.js +476 -58
- package/src/components/Datagrid/Common/readMe.txt +12 -0
- package/src/components/Datagrid/Footer/Footer.js +44 -0
- package/src/components/Datagrid/Table/index.js +21 -9
- package/src/components/Date/FormatSelector.js +1 -1
- package/src/components/Form/Fields/Field.js +3 -0
- package/src/components/Form/Fields/SelectField.js +4 -2
- package/src/components/Form/Fields/Tel.js +2 -0
- package/src/components/Form/FormData/DialogProvider.js +1 -0
- package/src/components/Menu/Item.js +25 -12
- package/src/components/Snackbar/index.js +1 -1
- package/src/components/Table/index.js +9 -6
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fto-consult/expo-ui",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.21.1",
|
|
4
4
|
"description": "Bibliothèque de composants UI Expo,react-native",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -61,7 +61,8 @@
|
|
|
61
61
|
"@emotion/native": "^11.10.0",
|
|
62
62
|
"@expo/html-elements": "^0.2.0",
|
|
63
63
|
"@expo/vector-icons": "^13.0.0",
|
|
64
|
-
"@fto-consult/common": "^1.23.
|
|
64
|
+
"@fto-consult/common": "^1.23.9",
|
|
65
|
+
"@fto-consult/expo-ui": "^2.21.0",
|
|
65
66
|
"@gorhom/portal": "^1.0.14",
|
|
66
67
|
"@react-native-async-storage/async-storage": "~1.17.3",
|
|
67
68
|
"@react-native-community/datetimepicker": "6.5.2",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from '$react'
|
|
2
2
|
import PropTypes from 'prop-types'
|
|
3
|
-
import {defaultStr,defaultObj,uniqid,defaultNumber} from "$utils";
|
|
3
|
+
import {defaultStr,defaultVal,extendObj,defaultObj,uniqid,defaultNumber} from "$utils";
|
|
4
4
|
import {extend} from "./utils"
|
|
5
5
|
import stableHash from 'stable-hash';
|
|
6
6
|
import Chart from "./appexChart";
|
|
@@ -16,20 +16,15 @@ import Chart from "./appexChart";
|
|
|
16
16
|
* options {number} - les options supplémentaires au chart
|
|
17
17
|
*
|
|
18
18
|
*/
|
|
19
|
-
const ChartComponent = React.forwardRef(({
|
|
19
|
+
const ChartComponent = React.forwardRef(({options,height,width,chartId,testID,webViewProps, ...props },ref)=>{
|
|
20
20
|
const chartContext = React.useRef(null);
|
|
21
21
|
options = defaultObj(options);
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
id : chartIdRef.current
|
|
29
|
-
},
|
|
30
|
-
series,
|
|
31
|
-
});
|
|
32
|
-
config.chart.id = chartIdRef.current;
|
|
22
|
+
const series = options.series;
|
|
23
|
+
options.chart = defaultObj(options.chart);
|
|
24
|
+
const chartIdRef = React.useRef(defaultStr(chartId,options.chart.id,uniqid("chart-id")));
|
|
25
|
+
width = options.chart.width = defaultVal(options.chart.width,width);
|
|
26
|
+
height = options.chart.height = defaultVal(options.chart.height,height)
|
|
27
|
+
options.chart.id = chartIdRef.current;
|
|
33
28
|
testID = defaultStr(testID,"RN_ChartComponent");
|
|
34
29
|
const prevWidth = React.usePrevious(width), prevHeight = React.usePrevious(height);
|
|
35
30
|
const prevOptions = React.usePrevious(options,JSON.stringify);
|
|
@@ -40,21 +35,21 @@ const ChartComponent = React.forwardRef(({type, height,chartId, width, series, o
|
|
|
40
35
|
options.xaxis.stroke.width = defaultNumber(options.xaxis.stroke.width,2);
|
|
41
36
|
options.xaxis.stroke.height = defaultNumber(options.xaxis.height,1);
|
|
42
37
|
|
|
38
|
+
console.log(options,' is optssss');
|
|
43
39
|
React.useEffect(()=>{
|
|
44
40
|
if(chartContext.current && chartContext.current.updateOptions){
|
|
45
41
|
if((prevSeries == series) || width != prevWidth || height != prevHeight){
|
|
46
|
-
chartContext.current.updateOptions(
|
|
42
|
+
chartContext.current.updateOptions(options);
|
|
47
43
|
} else if(prevOptions != options){
|
|
48
44
|
chartContext.current.updateSeries(series);
|
|
49
45
|
}
|
|
50
46
|
}
|
|
51
|
-
},[stableHash({
|
|
52
|
-
return <Chart {...props} options={
|
|
47
|
+
},[stableHash({options,series,width,height})])
|
|
48
|
+
return <Chart {...props} options={options} chartId={chartIdRef.current} chartContext={chartContext} testID={testID} ref={ref}/>
|
|
53
49
|
});
|
|
54
50
|
|
|
55
51
|
|
|
56
52
|
ChartComponent.propTypes = {
|
|
57
|
-
type: PropTypes.string.isRequired,
|
|
58
53
|
width: PropTypes.oneOfType([
|
|
59
54
|
PropTypes.string,
|
|
60
55
|
PropTypes.number,
|
|
@@ -63,9 +58,12 @@ ChartComponent.propTypes = {
|
|
|
63
58
|
PropTypes.string,
|
|
64
59
|
PropTypes.number,
|
|
65
60
|
]),
|
|
66
|
-
series: PropTypes.array.isRequired,
|
|
67
61
|
options: PropTypes.shape({
|
|
62
|
+
chart : PropTypes.shape({
|
|
63
|
+
type: PropTypes.string,
|
|
64
|
+
}),
|
|
68
65
|
xaxis : PropTypes.object,
|
|
66
|
+
series: PropTypes.array.isRequired,
|
|
69
67
|
}).isRequired,
|
|
70
68
|
///lorsque le chart est rendu en environnement native, les props du webView
|
|
71
69
|
webViewProps : PropTypes.object,
|
|
@@ -339,8 +339,11 @@ const DatagridFactory = (Factory)=>{
|
|
|
339
339
|
backToTopProps,
|
|
340
340
|
testID,
|
|
341
341
|
renderEmpty,
|
|
342
|
+
chartContainerProps,
|
|
342
343
|
...rest
|
|
343
344
|
} = this.props
|
|
345
|
+
chartContainerProps = defaultObj(chartContainerProps);
|
|
346
|
+
const canRenderChart = this.canRenderChart();
|
|
344
347
|
const hasData = this.state.data.length ? true : false;
|
|
345
348
|
testID = defaultStr(testID,"RN_DatagridAccordion");
|
|
346
349
|
backToTopProps = defaultObj(backToTopProps);
|
|
@@ -504,25 +507,25 @@ const DatagridFactory = (Factory)=>{
|
|
|
504
507
|
icon : "refresh",
|
|
505
508
|
onPress : this.refresh.bind(this)
|
|
506
509
|
},
|
|
507
|
-
visibleColumns.length ? {
|
|
510
|
+
!canRenderChart && visibleColumns.length ? {
|
|
508
511
|
text : 'colonnes',
|
|
509
512
|
icon : "view-column",
|
|
510
513
|
items : visibleColumns,
|
|
511
514
|
closeOnPress : false,
|
|
512
515
|
} : null,
|
|
513
|
-
hasFooterFields ? {
|
|
516
|
+
!canRenderChart && hasFooterFields ? {
|
|
514
517
|
onPress : ()=>{this.toggleFooters(!showFooters)}
|
|
515
518
|
,icon : showFooters?'view-column':'view-module'
|
|
516
519
|
,text : (showFooters?'Masquer/Ligne des totaux':'Afficher/Ligne des totaux')
|
|
517
520
|
}:null,
|
|
518
521
|
...this.renderCustomMenu(),
|
|
519
522
|
...restItems,
|
|
520
|
-
this.canScrollTo() && {
|
|
523
|
+
!canRenderChart && this.canScrollTo() && {
|
|
521
524
|
text : 'Retour en haut',
|
|
522
525
|
icon : "arrow-up-bold",
|
|
523
526
|
onPress : this.scrollToTop.bind(this)
|
|
524
527
|
},
|
|
525
|
-
this.canScrollTo() && {
|
|
528
|
+
!canRenderChart && this.canScrollTo() && {
|
|
526
529
|
text : 'Aller à la dernière ligne',
|
|
527
530
|
icon : "arrow-down-bold",
|
|
528
531
|
onPress : this.scrollToEnd.bind(this)
|
|
@@ -570,7 +573,7 @@ const DatagridFactory = (Factory)=>{
|
|
|
570
573
|
/> : null}
|
|
571
574
|
{datagridHeader}
|
|
572
575
|
{_progressBar}
|
|
573
|
-
{showFooters ? (
|
|
576
|
+
{!canRenderChart && showFooters ? (
|
|
574
577
|
<View testID={testID+"_FooterContainer"} pointerEvents={pointerEvents} style={[{justifyContent:'center'}]}>
|
|
575
578
|
<View testID={testID+"_FooterContentContainer"} style={[styles.footersContainer]}>
|
|
576
579
|
<ScrollView testID={testID+"_FooterScrollView"} horizontal contentContainerStyle={[styles.contentContainerStyle]}>
|
|
@@ -589,7 +592,7 @@ const DatagridFactory = (Factory)=>{
|
|
|
589
592
|
</View>
|
|
590
593
|
) : null}
|
|
591
594
|
</View>
|
|
592
|
-
{hasData ? <FlashList
|
|
595
|
+
{hasData && !canRenderChart ? <FlashList
|
|
593
596
|
estimatedItemSize = {150}
|
|
594
597
|
prepareItems = {false}
|
|
595
598
|
{...rest}
|
|
@@ -609,11 +612,13 @@ const DatagridFactory = (Factory)=>{
|
|
|
609
612
|
return this.backToTopRef.current;
|
|
610
613
|
}:false}
|
|
611
614
|
keyExtractor = {this.getRowKey.bind(this)}
|
|
612
|
-
/> :
|
|
615
|
+
/> : canRenderChart ?<View testID={testID+"_ChartContainer"} {...chartContainerProps} style={[theme.styles.w100,chartContainerProps.style]}>
|
|
616
|
+
{this.renderChart()}
|
|
617
|
+
</View> : <View style={styles.hasNotData}>
|
|
613
618
|
{this.renderEmpty()}
|
|
614
619
|
</View>}
|
|
615
620
|
</View>}
|
|
616
|
-
{backToTopRef ? <BackToTop testID={testID+"_BackToTop"} {...backToTopProps} ref={this.backToTopRef} style={[styles.backToTop,backToTopProps.style]} onPress={this.scrollToTop.bind(this)}/>:null}
|
|
621
|
+
{!canRenderChart && backToTopRef ? <BackToTop testID={testID+"_BackToTop"} {...backToTopProps} ref={this.backToTopRef} style={[styles.backToTop,backToTopProps.style]} onPress={this.scrollToTop.bind(this)}/>:null}
|
|
617
622
|
<BottomSheet
|
|
618
623
|
testID = {testID+"_BottomSheet"}
|
|
619
624
|
renderMenuContent = {false}
|
|
@@ -38,6 +38,47 @@ 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";
|
|
43
|
+
|
|
44
|
+
const chart = "chart";
|
|
45
|
+
export const displayTypes = {
|
|
46
|
+
table : {
|
|
47
|
+
code : "table",
|
|
48
|
+
isChart : false,
|
|
49
|
+
label : 'Tableau',
|
|
50
|
+
icon : "table",
|
|
51
|
+
type : 'table',
|
|
52
|
+
},
|
|
53
|
+
lineChart : {
|
|
54
|
+
code : "lineChart",
|
|
55
|
+
isChart : true,
|
|
56
|
+
label : 'Graphique|Linéaire',
|
|
57
|
+
icon : "chart-areaspline",
|
|
58
|
+
type : 'line',
|
|
59
|
+
},
|
|
60
|
+
areaChart : {
|
|
61
|
+
isChart : true,
|
|
62
|
+
code : 'areaChart',
|
|
63
|
+
label : 'Graphique|Surface',
|
|
64
|
+
icon : "chart-areaspline-variant",
|
|
65
|
+
type: 'area',
|
|
66
|
+
},
|
|
67
|
+
barChart : {
|
|
68
|
+
isChart : true,
|
|
69
|
+
code : 'barChart',
|
|
70
|
+
label : 'Graphique|Barres',
|
|
71
|
+
icon : "chart-bar",
|
|
72
|
+
type: 'bar'
|
|
73
|
+
},
|
|
74
|
+
/*donutChart : {
|
|
75
|
+
isChart : true,
|
|
76
|
+
code : 'donutChart',
|
|
77
|
+
label : 'Graphique|Circulaire',
|
|
78
|
+
icon : "chart-donut",
|
|
79
|
+
type: 'donut'
|
|
80
|
+
},*/
|
|
81
|
+
}
|
|
41
82
|
|
|
42
83
|
export const arrayValueSeparator = ", ";
|
|
43
84
|
|
|
@@ -85,6 +126,17 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
85
126
|
showFooters : defaultBool(props.showFooters,(sData.showFooters? true : false)),
|
|
86
127
|
fixedTable : sData.fixedTable
|
|
87
128
|
});
|
|
129
|
+
const disTypes = {};
|
|
130
|
+
let hasFoundDisplayTypes = false;
|
|
131
|
+
Object.map(this.props.displayTypes,(dType,v)=>{
|
|
132
|
+
if(isNonNullString(dType)){
|
|
133
|
+
dType = dType.toLowerCase().trim();
|
|
134
|
+
if(displayTypes[dType]){
|
|
135
|
+
disTypes[dType] = Object.clone(displayTypes[dType]);
|
|
136
|
+
}
|
|
137
|
+
hasFoundDisplayTypes = true;
|
|
138
|
+
}
|
|
139
|
+
});
|
|
88
140
|
Object.defineProperties(this,{
|
|
89
141
|
layoutRef : {
|
|
90
142
|
value : React.createRef(null),
|
|
@@ -119,6 +171,8 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
119
171
|
sectionListDataSize : {value : {current : 0}},
|
|
120
172
|
enablePointerEventsRef : {value : {current:false}},
|
|
121
173
|
configureSectionListSelectedValues : {value : {}},
|
|
174
|
+
///les types d'affichage
|
|
175
|
+
displayTypes : {value : hasFoundDisplayTypes ? disTypes : Object.clone(displayTypes)},
|
|
122
176
|
sectionListColumnsSize : {value : {current:0}}, //la taille du nombre d'éléments de section dans les colonnes
|
|
123
177
|
})
|
|
124
178
|
this.isLoading = this.isLoading.bind(this);
|
|
@@ -150,10 +204,12 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
150
204
|
this.state.filteredColumns = defaultObj(this.getSessionData("filteredColumns"+this.getSessionNameKey()),this.props.filters);
|
|
151
205
|
this.filtersSelectors = {selector:this.getFilters()};
|
|
152
206
|
const {sectionListColumns} = this.prepareColumns();
|
|
153
|
-
this.state.sectionListColumns = sectionListColumns;
|
|
154
207
|
if(this.canHandleColumnResize()){
|
|
155
208
|
this.state.columnsWidths = this.preparedColumns.widths;
|
|
156
209
|
}
|
|
210
|
+
this.state.chartConfig = defaultObj(this.props.chartConfig,this.getSessionData("chartConfig"));
|
|
211
|
+
const dType = defaultStr(this.props.displayType,this.getSessionData("displayType"),"table");
|
|
212
|
+
this.state.displayType = this.displayTypes[dType] ? this.displayTypes[dType].code : "table" in this.displayTypes ? "table" : Object.keys(this.displayTypes)[0]?.code;
|
|
157
213
|
extendObj(this.state,this.prepareData({data}));
|
|
158
214
|
const {width:windowWidth,height:windowHeight} = Dimensions.get("window");
|
|
159
215
|
this.state.layout = {
|
|
@@ -198,7 +254,10 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
198
254
|
} else {
|
|
199
255
|
this.currentDataSources = Object.toArray(this.currentDataSources);
|
|
200
256
|
}
|
|
257
|
+
this.state.sectionListColumns = sectionListColumns;
|
|
258
|
+
this.state.displayOnlySectionListHeaders = defaultBool(this.getSessionData("displayOnlySectionListHeaders"),this.props.displayOnlySectionListHeaders,false)
|
|
201
259
|
}
|
|
260
|
+
|
|
202
261
|
/*** si une ligne peut être selectionable */
|
|
203
262
|
canSelectRow(row){
|
|
204
263
|
return isObj(row) && row.isSectionListHeader !== true ? true : false;
|
|
@@ -206,7 +265,7 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
206
265
|
prepareSectionListColumns(props){
|
|
207
266
|
props = defaultObj(props,this.props);
|
|
208
267
|
const l = {};
|
|
209
|
-
(Array.isArray(props.sectionListColumns) ? props.sectionListColumns :
|
|
268
|
+
(Array.isArray(props.sectionListColumns) ? props.sectionListColumns : defaultArray(this.getSessionData("sectionListColumns"))).map((col)=>{
|
|
210
269
|
if(isNonNullString(col)){
|
|
211
270
|
l[col.trim()] = {};
|
|
212
271
|
}
|
|
@@ -230,7 +289,7 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
230
289
|
let sessionName = this.props.sessionName;
|
|
231
290
|
let isDatagrid = this.isDatagrid()
|
|
232
291
|
if(!isNonNullString(sessionName)){
|
|
233
|
-
sessionName = 'datagrid';
|
|
292
|
+
//sessionName = 'datagrid';
|
|
234
293
|
}
|
|
235
294
|
let userCode = Auth.getLoggedUserCode();
|
|
236
295
|
Object.defineProperties(this,{
|
|
@@ -995,72 +1054,72 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
995
1054
|
}
|
|
996
1055
|
return null;
|
|
997
1056
|
}
|
|
998
|
-
|
|
999
|
-
configureSectionListColumn(column){
|
|
1057
|
+
isSectionListColumnConfigurable(column){
|
|
1000
1058
|
if(!isObj(column) || !isNonNullString(column.field) || !isObj(this.state.columns[column.field])){
|
|
1001
|
-
return
|
|
1002
|
-
}
|
|
1003
|
-
const
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1059
|
+
return false;
|
|
1060
|
+
}
|
|
1061
|
+
const type = defaultStr(column.jsType,column.type).toLowerCase();
|
|
1062
|
+
return type.contains("date") || type =='time' ? true : false;
|
|
1063
|
+
}
|
|
1064
|
+
/*** configure la */
|
|
1065
|
+
configureSectionListColumn(column,toggleSectionList){
|
|
1066
|
+
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")
|
|
1068
|
+
return new Promise((resolve,reject)=>{
|
|
1069
|
+
DialogProvider.open({
|
|
1070
|
+
title : 'Format de date',
|
|
1071
|
+
subtitle : false,
|
|
1072
|
+
fields : {
|
|
1073
|
+
dateFormat : {
|
|
1074
|
+
type : 'select_dateformat',
|
|
1075
|
+
required : true,
|
|
1076
|
+
text : 'Sélectionnez un format de date',
|
|
1077
|
+
defaultValue : format,
|
|
1078
|
+
}
|
|
1079
|
+
},
|
|
1080
|
+
onCancelButtonPress : ()=>{
|
|
1081
|
+
DialogProvider.close();
|
|
1082
|
+
reject({msg:'aucun format sélectionné'})
|
|
1083
|
+
},
|
|
1084
|
+
actions : [{
|
|
1085
|
+
text : "Sélectionnez",
|
|
1086
|
+
icon : "check",
|
|
1087
|
+
onPress : ({data})=>{
|
|
1088
|
+
column.format = data.dateFormat;
|
|
1089
|
+
this.configureSectionListSelectedValues[column.field] = {format:column.format}
|
|
1018
1090
|
DialogProvider.close();
|
|
1019
|
-
|
|
1091
|
+
setTimeout(()=>{
|
|
1092
|
+
resolve(column);
|
|
1093
|
+
if(toggleSectionList !== false){
|
|
1094
|
+
this.toggleColumnInSectionList(column.field,true);
|
|
1095
|
+
}
|
|
1096
|
+
},100)
|
|
1020
1097
|
},
|
|
1021
|
-
|
|
1022
|
-
text : "Sélectionnez",
|
|
1023
|
-
icon : "check",
|
|
1024
|
-
onPress : ({data})=>{
|
|
1025
|
-
column.format = data.dateFormat;
|
|
1026
|
-
this.configureSectionListSelectedValues[column.field] = data.dateFormat;
|
|
1027
|
-
DialogProvider.close();
|
|
1028
|
-
setTimeout(()=>{
|
|
1029
|
-
resolve(column);
|
|
1030
|
-
},100)
|
|
1031
|
-
},
|
|
1032
|
-
}]
|
|
1033
|
-
})
|
|
1098
|
+
}]
|
|
1034
1099
|
})
|
|
1035
|
-
}
|
|
1036
|
-
return Promise.resolve(column);
|
|
1100
|
+
})
|
|
1037
1101
|
}
|
|
1038
|
-
toggleColumnInSectionList(columnName){
|
|
1102
|
+
toggleColumnInSectionList(columnName,enable){
|
|
1039
1103
|
if(!isNonNullString(columnName) || !isObj(this.state.columns[columnName])) return;
|
|
1040
1104
|
if(!isObj(this.state.sectionListColumns) || !Array.isArray(this.preparedColumns?.sectionListColumnsMenuItems))return;
|
|
1041
1105
|
const menuItems = this.preparedColumns?.sectionListColumnsMenuItems;
|
|
1042
1106
|
if(!menuItems.length) return;
|
|
1043
1107
|
const sectionListColumns = {...this.state.sectionListColumns};
|
|
1044
|
-
if(isObj(sectionListColumns[columnName])){
|
|
1108
|
+
if(enable !== true && isObj(sectionListColumns[columnName])){
|
|
1045
1109
|
delete sectionListColumns[columnName];
|
|
1046
1110
|
} else {
|
|
1047
1111
|
sectionListColumns[columnName] = {field:columnName};
|
|
1048
1112
|
}
|
|
1049
|
-
|
|
1113
|
+
setTimeout(() => {
|
|
1050
1114
|
const {sectionListColumns:pSListColumns} = this.prepareColumns({sectionListColumns});
|
|
1051
1115
|
this.setIsLoading(true,()=>{
|
|
1052
1116
|
this.prepareData({data:this.INITIAL_STATE.data,sectionListColumns:pSListColumns},(state)=>{
|
|
1053
1117
|
this.setState({...state,sectionListColumns:pSListColumns},()=>{
|
|
1054
1118
|
this.setIsLoading(false,false);
|
|
1119
|
+
this.setSessionData("sectionListColumns",Object.keys(pSListColumns));
|
|
1055
1120
|
});
|
|
1056
1121
|
});
|
|
1057
1122
|
},true);
|
|
1058
|
-
}
|
|
1059
|
-
setTimeout(() => {
|
|
1060
|
-
if(!isObj(sectionListColumns[columnName])){
|
|
1061
|
-
return cb();
|
|
1062
|
-
}
|
|
1063
|
-
return this.configureSectionListColumn(sectionListColumns[columnName]).then(cb).catch(notify.error)
|
|
1064
1123
|
}, 100);
|
|
1065
1124
|
}
|
|
1066
1125
|
removeAllColumnsInSectionList(){
|
|
@@ -1069,16 +1128,338 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
1069
1128
|
this.prepareData({data:this.INITIAL_STATE.data,sectionListColumns},(state)=>{
|
|
1070
1129
|
this.setState({...state,sectionListColumns},()=>{
|
|
1071
1130
|
this.setIsLoading(false,false);
|
|
1131
|
+
this.setSessionData("sectionListColumns",null);
|
|
1072
1132
|
});
|
|
1073
1133
|
});
|
|
1074
1134
|
},true);
|
|
1075
1135
|
}
|
|
1136
|
+
canDisplayOnlySectionListHeaders(){
|
|
1137
|
+
return this.hasFooterFields() && this.isSectionList() && this.hasSectionListData();
|
|
1138
|
+
}
|
|
1139
|
+
/*** si l'on peut rendre le contenu de type graphique */
|
|
1140
|
+
isChartRendable(){
|
|
1141
|
+
return !this.isPivotDatagrid() && this.hasFooterFields();
|
|
1142
|
+
}
|
|
1143
|
+
isValidChartConfig(config){
|
|
1144
|
+
config = defaultObj(config,this.state.chartConfig);
|
|
1145
|
+
return isNonNullString(config.x) && isNonNullString(config.y);
|
|
1146
|
+
}
|
|
1147
|
+
canRenderChart(){
|
|
1148
|
+
return this.isChartRendable() && isNonNullString(this.state.displayType) && displayTypes[this.state.displayType]?.isChart === true ? true : false;
|
|
1149
|
+
}
|
|
1150
|
+
persistDisplayType(displayType){
|
|
1151
|
+
this.setSessionData("displayType",displayType);
|
|
1152
|
+
}
|
|
1153
|
+
/***modifie le type de données d'affichage du tableau */
|
|
1154
|
+
setDisplayType(type){
|
|
1155
|
+
if(!isObj(type) || !isNonNullString(type.code) || !displayTypes[type.code]) return;
|
|
1156
|
+
const tt = displayTypes[type.code];
|
|
1157
|
+
if(this.state.displayType == tt.code) return;
|
|
1158
|
+
const displayType = tt.code;
|
|
1159
|
+
if(tt.code == 'table'){
|
|
1160
|
+
return this.setIsLoading(true,()=>{
|
|
1161
|
+
this.setState({displayType},()=>{
|
|
1162
|
+
this.setIsLoading(false,false);
|
|
1163
|
+
this.persistDisplayType(displayType);
|
|
1164
|
+
});
|
|
1165
|
+
},true)
|
|
1166
|
+
} else {
|
|
1167
|
+
const cb = (chartConfig)=>{
|
|
1168
|
+
this.setIsLoading(true,()=>{
|
|
1169
|
+
this.setState({chartConfig,displayType},()=>{
|
|
1170
|
+
this.setIsLoading(false,false);
|
|
1171
|
+
this.persistDisplayType(displayType);
|
|
1172
|
+
})
|
|
1173
|
+
},true);
|
|
1174
|
+
}
|
|
1175
|
+
if(!this.isValidChartConfig()){
|
|
1176
|
+
return this.configureChart(false).then((chartConfig)=>{
|
|
1177
|
+
cb(chartConfig);
|
|
1178
|
+
});
|
|
1179
|
+
}
|
|
1180
|
+
cb({...this.state.chartConfig});
|
|
1181
|
+
}
|
|
1182
|
+
}
|
|
1183
|
+
configureChart(refreshChart){
|
|
1184
|
+
if(!this.isChartRendable()){
|
|
1185
|
+
return Promise.reject({message:'Impossible de configurer le graphe car le type de données ne permet pas de rendu de type graphe'});
|
|
1186
|
+
}
|
|
1187
|
+
const xItems = {},yItems = {},config = defaultObj(this.state.chartConfig);
|
|
1188
|
+
const series = {};
|
|
1189
|
+
let hasSeries = false;
|
|
1190
|
+
const isValidConfig = this.isValidChartConfig();
|
|
1191
|
+
Object.map(this.state.columns,(field,f)=>{
|
|
1192
|
+
if(isObj(field) && !this.isSelectableColumn(field) && !this.isIndexColumn(field)){
|
|
1193
|
+
xItems[f] = field;
|
|
1194
|
+
const type = defaultStr(field.jsType,field.type).toLowerCase();
|
|
1195
|
+
if(type === 'number' || type=='decimal'){
|
|
1196
|
+
yItems[f] = field;
|
|
1197
|
+
series[f] = field;
|
|
1198
|
+
}
|
|
1199
|
+
}
|
|
1200
|
+
});
|
|
1201
|
+
const onValidatorValid = ({context,value})=>{
|
|
1202
|
+
if(context && value){
|
|
1203
|
+
const name = context.getName();
|
|
1204
|
+
const isHorizontal = name =="x";
|
|
1205
|
+
const oContext = context.getField(isHorizontal ? "y" : "x");
|
|
1206
|
+
if(!oContext) return;
|
|
1207
|
+
const v2 = oContext.getValue()
|
|
1208
|
+
if(v2 === value){
|
|
1209
|
+
return "la valeur du champ [{0}] doit être différent de celle du champ [{1}]".sprintf(context.getLabel(),oContext.getLabel())
|
|
1210
|
+
}
|
|
1211
|
+
oContext.validate({value:v2,context:oContext});
|
|
1212
|
+
}
|
|
1213
|
+
}
|
|
1214
|
+
return new Promise((resolve,reject)=>{
|
|
1215
|
+
DialogProvider.open({
|
|
1216
|
+
title : 'Configuration des graphes',
|
|
1217
|
+
subtitle : false,
|
|
1218
|
+
fields : {
|
|
1219
|
+
x : {
|
|
1220
|
+
text : 'Axe des x[horizontal]',
|
|
1221
|
+
type : "select",
|
|
1222
|
+
required : true,
|
|
1223
|
+
items : xItems,
|
|
1224
|
+
defaultValue : config.x,
|
|
1225
|
+
onValidatorValid,
|
|
1226
|
+
},
|
|
1227
|
+
y : {
|
|
1228
|
+
text : 'Axe des y[Vertical]',
|
|
1229
|
+
type : "select",
|
|
1230
|
+
required : true,
|
|
1231
|
+
items : yItems,
|
|
1232
|
+
defaultValue : config.y,
|
|
1233
|
+
onValidatorValid,
|
|
1234
|
+
},
|
|
1235
|
+
series : hasSeries && {
|
|
1236
|
+
text : 'Series',
|
|
1237
|
+
type : "select",
|
|
1238
|
+
items : series,
|
|
1239
|
+
multiple : true,
|
|
1240
|
+
},
|
|
1241
|
+
aggregatorFunction : {
|
|
1242
|
+
type : 'select',
|
|
1243
|
+
text : "Foncton d'aggrégation",
|
|
1244
|
+
required : true,
|
|
1245
|
+
multiple : false,
|
|
1246
|
+
defaultValue : "sum",
|
|
1247
|
+
items : aggregatorFunctions,
|
|
1248
|
+
}
|
|
1249
|
+
},
|
|
1250
|
+
actions : [
|
|
1251
|
+
{
|
|
1252
|
+
text : "Configurer",
|
|
1253
|
+
icon : "check",
|
|
1254
|
+
onPress : ({data})=>{
|
|
1255
|
+
const chartConfig = {...config,...data};
|
|
1256
|
+
this.setSessionData("chartConfig",chartConfig);
|
|
1257
|
+
DialogProvider.close();
|
|
1258
|
+
if(false && !isValidConfig && refreshChart !== false){
|
|
1259
|
+
return this.setState({chartConfig},()=>{
|
|
1260
|
+
resolve(chartConfig)
|
|
1261
|
+
})
|
|
1262
|
+
}
|
|
1263
|
+
resolve(chartConfig);
|
|
1264
|
+
}
|
|
1265
|
+
}
|
|
1266
|
+
]
|
|
1267
|
+
})
|
|
1268
|
+
})
|
|
1269
|
+
}
|
|
1270
|
+
getCharConfig(){
|
|
1271
|
+
return defaultObj(this.state.chartConfig);
|
|
1272
|
+
}
|
|
1273
|
+
renderDisplayTypes(){
|
|
1274
|
+
const m = [];
|
|
1275
|
+
let activeType = null,hasFoundChart = false,hasFoundTable = false;
|
|
1276
|
+
const hasConfig = this.isValidChartConfig();
|
|
1277
|
+
Object.map(this.displayTypes,(type,k)=>{
|
|
1278
|
+
if(type.isChart === true ) {
|
|
1279
|
+
if(!this.isChartRendable()){
|
|
1280
|
+
return null;
|
|
1281
|
+
}
|
|
1282
|
+
if(!hasFoundChart){
|
|
1283
|
+
if(hasFoundTable){
|
|
1284
|
+
m.push({divider:true});
|
|
1285
|
+
}
|
|
1286
|
+
hasFoundChart = true;
|
|
1287
|
+
m.push({
|
|
1288
|
+
divider : true,
|
|
1289
|
+
text : "Configurer les graphes",
|
|
1290
|
+
icon :"material-settings",
|
|
1291
|
+
onPress : this.configureChart.bind(this)
|
|
1292
|
+
});
|
|
1293
|
+
}
|
|
1294
|
+
} else if(k === 'table'){
|
|
1295
|
+
hasFoundTable = true;
|
|
1296
|
+
}
|
|
1297
|
+
const active = this.state.displayType === k;
|
|
1298
|
+
if(active){
|
|
1299
|
+
activeType = type;
|
|
1300
|
+
}
|
|
1301
|
+
m.push({
|
|
1302
|
+
...type,
|
|
1303
|
+
labelStyle : active && {fontWeight:'bold',color:theme.colors.primaryOnSurface} || null,
|
|
1304
|
+
right : <>
|
|
1305
|
+
{active ? <Icon color={theme.colors.primaryOnSurface} name="check"/>: null}
|
|
1306
|
+
</>,
|
|
1307
|
+
disabled : type.isChart && !hasConfig ? true : undefined,
|
|
1308
|
+
onPress:()=>{
|
|
1309
|
+
this.setDisplayType(type);
|
|
1310
|
+
}
|
|
1311
|
+
});
|
|
1312
|
+
});
|
|
1313
|
+
if(m.length <= 1 || !activeType) return null;
|
|
1314
|
+
if(!isMobileOrTabletMedia()){
|
|
1315
|
+
m.unshift({text:"Type d'affichage des données",divider:true});
|
|
1316
|
+
}
|
|
1317
|
+
return <Menu
|
|
1318
|
+
title = "Type d'affichage"
|
|
1319
|
+
items = {m}
|
|
1320
|
+
anchor = {(p)=>{
|
|
1321
|
+
return <Icon
|
|
1322
|
+
{...p}
|
|
1323
|
+
name = {activeType.icon}
|
|
1324
|
+
title = {"Les données s'affichent actuellement en {0}. Cliquez pour modifier le type d'affichage".sprintf(activeType.label)}
|
|
1325
|
+
/>
|
|
1326
|
+
}}
|
|
1327
|
+
/>
|
|
1328
|
+
}
|
|
1329
|
+
getEmptyDataValue(){
|
|
1330
|
+
return "N/A";
|
|
1331
|
+
}
|
|
1332
|
+
renderChart(){
|
|
1333
|
+
if(!this.canRenderChart()) return null;
|
|
1334
|
+
if(!this.isValidChartConfig()) return null;
|
|
1335
|
+
const chartType = displayTypes[this.state.displayType];
|
|
1336
|
+
if(!isObj(chartType) || !isNonNullString(chartType.type)) return null;
|
|
1337
|
+
const config = this.getCharConfig();
|
|
1338
|
+
if(!this.state.columns[config.y]) return null;
|
|
1339
|
+
const yaxis = this.state.columns[config.y];
|
|
1340
|
+
const type = defaultStr(yaxis.jsType,yaxis.type).toLowerCase();
|
|
1341
|
+
if(type !== 'number'&& type !== 'decimal') return null;
|
|
1342
|
+
const isEmptyY = config.x === this.emptySectionListHeaderValue;
|
|
1343
|
+
const seriesConfig = Array.isArray(config.series) && config.series.length ? config.series : [yaxis.field];
|
|
1344
|
+
let xaxis = null;
|
|
1345
|
+
if(!isEmptyY){
|
|
1346
|
+
if(!this.state.columns[config.x]){
|
|
1347
|
+
return null;
|
|
1348
|
+
}
|
|
1349
|
+
xaxis = this.state.columns[config.x];
|
|
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;
|
|
1359
|
+
}
|
|
1360
|
+
const emptyValue = this.getEmptyDataValue();
|
|
1361
|
+
const indexes = {}
|
|
1362
|
+
let count = 0;
|
|
1363
|
+
this.state.data.map((data,index)=>{
|
|
1364
|
+
if(!isObj(data))return null;
|
|
1365
|
+
const txt = this.renderRowCell({
|
|
1366
|
+
data,
|
|
1367
|
+
rowData : data,
|
|
1368
|
+
rowCounterIndex : index,
|
|
1369
|
+
rowIndex : index,
|
|
1370
|
+
columnDef : xaxis,
|
|
1371
|
+
renderRowCell : false,
|
|
1372
|
+
columnField : xaxis.field,
|
|
1373
|
+
});
|
|
1374
|
+
const text = isNonNullString(txt)? txt : emptyValue;
|
|
1375
|
+
Object.map(seriesConfig,(s,v)=>{
|
|
1376
|
+
if(!isNonNullString(s) || !this.state.columns[s]) return null;
|
|
1377
|
+
const col = this.state.columns[s];
|
|
1378
|
+
if(!isObj(col)) return null;
|
|
1379
|
+
const value = defaultNumber(data[col.field]);
|
|
1380
|
+
indexes[s] = defaultObj(indexes[s]);
|
|
1381
|
+
const current = indexes[s];
|
|
1382
|
+
current[text] = typeof current[text] =="number"? current[text] : 0;
|
|
1383
|
+
current[text] = aggregatorFunction(value,current[text],count);
|
|
1384
|
+
})
|
|
1385
|
+
});
|
|
1386
|
+
const series = [];
|
|
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,
|
|
1394
|
+
})
|
|
1395
|
+
})
|
|
1396
|
+
series.push({
|
|
1397
|
+
name,
|
|
1398
|
+
type : chartType.type,
|
|
1399
|
+
data,
|
|
1400
|
+
})
|
|
1401
|
+
})
|
|
1402
|
+
const {width,height:winheight} = Dimensions.get("window");
|
|
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;
|
|
1409
|
+
} else {
|
|
1410
|
+
maxHeight = diff;
|
|
1411
|
+
}
|
|
1412
|
+
}
|
|
1413
|
+
const chartProps = defaultObj(chartProps);
|
|
1414
|
+
return <Chart
|
|
1415
|
+
options = {{
|
|
1416
|
+
...defaultObj(chartProps.options),
|
|
1417
|
+
series,
|
|
1418
|
+
chart : {
|
|
1419
|
+
height :350,
|
|
1420
|
+
maxHeight,
|
|
1421
|
+
...defaultObj(chartProps.chart),
|
|
1422
|
+
type : chartType.type,
|
|
1423
|
+
},
|
|
1424
|
+
xaxis: {
|
|
1425
|
+
...defaultObj(chartProps.xaxis),
|
|
1426
|
+
type: 'category'
|
|
1427
|
+
}
|
|
1428
|
+
}}
|
|
1429
|
+
/>
|
|
1430
|
+
}
|
|
1431
|
+
toggleDisplayOnlySectionListHeaders(){
|
|
1432
|
+
if(!this.canDisplayOnlySectionListHeaders()) return
|
|
1433
|
+
setTimeout(()=>{
|
|
1434
|
+
const showFooters = true;
|
|
1435
|
+
const displayOnlySectionListHeaders = !!!this.state.displayOnlySectionListHeaders;
|
|
1436
|
+
this.setSessionData("displayOnlySectionListHeaders",displayOnlySectionListHeaders);
|
|
1437
|
+
if(!displayOnlySectionListHeaders){
|
|
1438
|
+
return this.prepareData({data:this.INITIAL_STATE.data,displayOnlySectionListHeaders},(state)=>{
|
|
1439
|
+
this.setState({...state,showFooters})
|
|
1440
|
+
})
|
|
1441
|
+
} else {
|
|
1442
|
+
this.setIsLoading(true,()=>{
|
|
1443
|
+
const data = [];
|
|
1444
|
+
this.state.data.map((d)=>{
|
|
1445
|
+
if(isObj(d) && d.isSectionListHeader === true){
|
|
1446
|
+
data.push(d);
|
|
1447
|
+
}
|
|
1448
|
+
});
|
|
1449
|
+
this.setState({data,displayOnlySectionListHeaders,showFooters},()=>{
|
|
1450
|
+
this.setIsLoading(false),false;
|
|
1451
|
+
});
|
|
1452
|
+
},true)
|
|
1453
|
+
}
|
|
1454
|
+
},100);
|
|
1455
|
+
}
|
|
1076
1456
|
/*** permet d'effectuer le rendu des colonnes groupable dans le menu item */
|
|
1077
1457
|
renderSectionListMenu(){
|
|
1078
1458
|
const m = Array.isArray(this.preparedColumns?.sectionListColumnsMenuItems)? this.preparedColumns?.sectionListColumnsMenuItems : [];
|
|
1079
1459
|
if(!m.length){
|
|
1080
1460
|
return null;
|
|
1081
1461
|
}
|
|
1462
|
+
const hasList = this.sectionListColumnsSize.current;
|
|
1082
1463
|
const isMobile = isMobileOrTabletMedia();
|
|
1083
1464
|
return <Menu
|
|
1084
1465
|
title = {"Grouper les données du tableau"}
|
|
@@ -1093,7 +1474,12 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
1093
1474
|
closeOnPress : false,
|
|
1094
1475
|
divider : true,
|
|
1095
1476
|
},
|
|
1096
|
-
this.
|
|
1477
|
+
this.canDisplayOnlySectionListHeaders() && {
|
|
1478
|
+
text : "Afficher uniquement totaux",
|
|
1479
|
+
icon : this.state.displayOnlySectionListHeaders?"check":null,
|
|
1480
|
+
onPress : this.toggleDisplayOnlySectionListHeaders.bind(this)
|
|
1481
|
+
},
|
|
1482
|
+
hasList && {
|
|
1097
1483
|
text : "Supprimer les groupes",
|
|
1098
1484
|
icon: "ungroup",
|
|
1099
1485
|
divider : true,
|
|
@@ -1146,6 +1532,7 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
1146
1532
|
} = header;
|
|
1147
1533
|
restCol = Object.clone(defaultObj(restCol));
|
|
1148
1534
|
let colFilter = defaultVal(restCol.filter,true);
|
|
1535
|
+
const format = defaultStr(restCol.format).toLowerCase();
|
|
1149
1536
|
field = header.field = defaultStr(header.field,field,headerIndex);
|
|
1150
1537
|
delete restCol.filter;
|
|
1151
1538
|
|
|
@@ -1273,19 +1660,32 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
1273
1660
|
...header,
|
|
1274
1661
|
width,
|
|
1275
1662
|
type,
|
|
1663
|
+
...defaultObj(this.configureSectionListSelectedValues[field]),
|
|
1276
1664
|
...sListColumns[field],
|
|
1277
1665
|
};///les colonnes de sections
|
|
1278
1666
|
this.sectionListColumnsSize.current++;
|
|
1279
1667
|
}
|
|
1280
|
-
|
|
1668
|
+
const mItem = {
|
|
1281
1669
|
field,
|
|
1670
|
+
type,
|
|
1671
|
+
format,
|
|
1282
1672
|
onPress : ()=>{
|
|
1283
1673
|
this.toggleColumnInSectionList(field);
|
|
1284
1674
|
return false;
|
|
1285
1675
|
},
|
|
1286
1676
|
title : title,
|
|
1287
1677
|
icon : isInSectionListHeader?CHECKED_ICON_NAME : null,
|
|
1288
|
-
}
|
|
1678
|
+
};
|
|
1679
|
+
if(this.isSectionListColumnConfigurable(mItem)){
|
|
1680
|
+
mItem.right = (p)=>{
|
|
1681
|
+
return <Icon name="material-settings" {...p} onPress={(e)=>{
|
|
1682
|
+
React.stopEventPropagation(e);
|
|
1683
|
+
this.configureSectionListColumn(mItem);
|
|
1684
|
+
return false;
|
|
1685
|
+
}}/>
|
|
1686
|
+
}
|
|
1687
|
+
}
|
|
1688
|
+
sectionListColumnsMenuItems.push(mItem);
|
|
1289
1689
|
}
|
|
1290
1690
|
columnIndex++;
|
|
1291
1691
|
visibleColumnIndex++;
|
|
@@ -1314,9 +1714,9 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
1314
1714
|
getFooterValues(){
|
|
1315
1715
|
return defaultObj(this.___evaluatedFootersValues);
|
|
1316
1716
|
}
|
|
1317
|
-
|
|
1717
|
+
|
|
1318
1718
|
/**** s'il s'agit d'une section list */
|
|
1319
|
-
isSectionList(sectionListColumns){
|
|
1719
|
+
isSectionList (sectionListColumns){
|
|
1320
1720
|
sectionListColumns = isObj(sectionListColumns) ? sectionListColumns : this.state.sectionListColumns;
|
|
1321
1721
|
return !this.isPivotDatagrid() && isObj(sectionListColumns) && Object.size(sectionListColumns,true) ? true : false;
|
|
1322
1722
|
}
|
|
@@ -1341,13 +1741,14 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
1341
1741
|
return defaultNumber(this.sectionListDataSize.current)
|
|
1342
1742
|
}
|
|
1343
1743
|
prepareData(args,cb){
|
|
1344
|
-
let {pagination,data,force,sectionListColumns,updateFooters} = defaultObj(args);
|
|
1744
|
+
let {pagination,displayOnlySectionListHeaders:cdisplayOnlySectionListHeaders,data,force,sectionListColumns,updateFooters} = defaultObj(args);
|
|
1345
1745
|
cb = typeof cb ==='function'? cb : typeof args.cb == 'function'? args.cb : undefined;
|
|
1346
1746
|
sectionListColumns = isObj(sectionListColumns) ? sectionListColumns : this.state.sectionListColumns;
|
|
1747
|
+
const displayOnlySectionListHeaders = typeof cdisplayOnlySectionListHeaders == 'boolean'?cdisplayOnlySectionListHeaders : this.state.displayOnlySectionListHeaders;
|
|
1347
1748
|
let isArr = Array.isArray(data);
|
|
1348
1749
|
//let push = (d,index) => isArr ? newData.push(d) : newData[index] = d;
|
|
1349
1750
|
const hasLocalFilter = this.props.filters !== false && this.hasLocalFilters;
|
|
1350
|
-
let footersColumns = this.getFooterFields(),hasFooterFields =
|
|
1751
|
+
let footersColumns = this.getFooterFields(),hasFooterFields = this.hasFooterFields();
|
|
1351
1752
|
const canUpdateFooters = !!(updateFooters !== false && hasFooterFields);
|
|
1352
1753
|
this.hasFoundSectionData.current = false;
|
|
1353
1754
|
this.sectionListDataSize.current = 0;
|
|
@@ -1430,9 +1831,11 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
1430
1831
|
//this.sectionListData[i] = sortConfig ? sortBy(this.sectionListData[i],sortConfig):this.sectionListData[i];
|
|
1431
1832
|
//const v = i;// === this.emptySectionListHeaderValue ? "" : i;
|
|
1432
1833
|
data.push({isSectionListHeader:true,sectionListHeaderKey:i});
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1834
|
+
if(!displayOnlySectionListHeaders){
|
|
1835
|
+
this.sectionListData[i].map((d)=>{
|
|
1836
|
+
data.push(d);
|
|
1837
|
+
})
|
|
1838
|
+
}
|
|
1436
1839
|
}
|
|
1437
1840
|
}
|
|
1438
1841
|
if(!this.hasSectionListData() && this.canPaginateData()){
|
|
@@ -1444,7 +1847,7 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
1444
1847
|
} else if(force){
|
|
1445
1848
|
this.setSelectedRows();
|
|
1446
1849
|
}
|
|
1447
|
-
const state = {data};
|
|
1850
|
+
const state = {data,displayOnlySectionListHeaders};
|
|
1448
1851
|
if((cb)){
|
|
1449
1852
|
cb(state);
|
|
1450
1853
|
}
|
|
@@ -2275,6 +2678,10 @@ CommonDatagridComponent.getDefaultPreloader = (props)=>{
|
|
|
2275
2678
|
return <Preloader {...defaultObj(props)}/>
|
|
2276
2679
|
}
|
|
2277
2680
|
|
|
2681
|
+
const chartDisplayType = PropTypes.oneOf(Object.keys(displayTypes).filter(type=>{
|
|
2682
|
+
const x = displayTypes[type];
|
|
2683
|
+
return typeof x =='object' && x && typeof x.disabled !== true && x.isChart === true && true || false;
|
|
2684
|
+
}));
|
|
2278
2685
|
CommonDatagridComponent.propTypes = {
|
|
2279
2686
|
canMakePhoneCall : PropTypes.bool,//si l'on peut faire un appel sur la données sélectionnées
|
|
2280
2687
|
makePhoneCallProps : PropTypes.oneOfType([
|
|
@@ -2451,6 +2858,17 @@ CommonDatagridComponent.propTypes = {
|
|
|
2451
2858
|
/**** la fonction permettant de faire le rendu dun contenu paginé, personalisé */
|
|
2452
2859
|
renderCustomPagination : PropTypes.func,
|
|
2453
2860
|
getActionsArgs : PropTypes.func,//fonction permettant de récupérer les props supplémentaires à passer aux actions du datagrid
|
|
2861
|
+
displayOnlySectionListHeaders : PropTypes.bool,// si uniquement les entêtes des sections seront affichés, valides uniquement en affichage des sectionHeader
|
|
2862
|
+
/*** les options de configuration du graphe */
|
|
2863
|
+
chartConfig : PropTypes.shape({
|
|
2864
|
+
//type : PropTypes.oneOfType(chartDisplayType).isRequired,//le type de graphe : l'une des valeurs parmis les éléments cités plus haut
|
|
2865
|
+
x : PropTypes.string.isRequired, //l'axe horizontal
|
|
2866
|
+
y : PropTypes.string.isRequired, //l'axe des y, les colonnes de type nombre
|
|
2867
|
+
series : PropTypes.arrayOf([PropTypes.string]), //les séries, le nombre de courbe a afficher sur le graphe, en fonction du type
|
|
2868
|
+
}),
|
|
2869
|
+
displayType : chartDisplayType,
|
|
2870
|
+
/*** les types d'afichates supportés par l'application */
|
|
2871
|
+
displayTypes : PropTypes.arrayOf(chartDisplayType)
|
|
2454
2872
|
}
|
|
2455
2873
|
|
|
2456
2874
|
const styles = StyleSheet.create({
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// Copyright 2022 @fto-consult/Boris Fouomene. All rights reserved.
|
|
2
|
+
// Use of this source code is governed by a BSD-style
|
|
3
|
+
// license that can be found in the LICENSE file.
|
|
4
|
+
|
|
5
|
+
Les propriétés d'états :
|
|
6
|
+
displayType, displayOnlySectionListHeaders, sectionListHeaderColumns sont persistées
|
|
7
|
+
ça sous entend que lorsqu'on charge la table data, ces valeurs sont restaurées
|
|
8
|
+
|
|
9
|
+
- Pour faire un affichage en graphique, il faut :
|
|
10
|
+
1. grouper les éléments du tableau avec au moins une colonne
|
|
11
|
+
2. disposer dans le tableau, des colonnes de totalisation (de type montant et somme)
|
|
12
|
+
3.
|
|
@@ -14,6 +14,50 @@ let methods = {
|
|
|
14
14
|
max : 'Maximum',
|
|
15
15
|
count : "Nombre",
|
|
16
16
|
}
|
|
17
|
+
/*** les fonction d'aggreations */
|
|
18
|
+
export const aggregatorFunctions = {
|
|
19
|
+
sum : {
|
|
20
|
+
code : "sum",
|
|
21
|
+
label : "Somme",
|
|
22
|
+
eval : (current,prev,count)=>{
|
|
23
|
+
current = typeof current =='number'?current : 0;
|
|
24
|
+
prev = typeof prev =='number'? prev : 0;
|
|
25
|
+
return current+prev;
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
/*average : {
|
|
29
|
+
code : "average",
|
|
30
|
+
label : "Moyenne",
|
|
31
|
+
eval : ()=>{
|
|
32
|
+
|
|
33
|
+
}
|
|
34
|
+
},*/
|
|
35
|
+
min : {
|
|
36
|
+
code : "min",
|
|
37
|
+
label : "Minimum",
|
|
38
|
+
eval : (current,prev,count)=>{
|
|
39
|
+
current = typeof current =='number'?current : 0;
|
|
40
|
+
prev = typeof prev =='number'? prev : 0;
|
|
41
|
+
return Math.min(current,prev);
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
max : {
|
|
45
|
+
code : "max",
|
|
46
|
+
label: 'Maximum',
|
|
47
|
+
eval : (current,prev,count)=>{
|
|
48
|
+
current = typeof current =='number'?current : 0;
|
|
49
|
+
prev = typeof prev =='number'? prev : 0;
|
|
50
|
+
return Math.max(current,prev);
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
count : {
|
|
54
|
+
code : "count",
|
|
55
|
+
label : "Nombre",
|
|
56
|
+
eval : (current,prev,count)=>{
|
|
57
|
+
return (typeof count =='number'? count : 0)+1;
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
}
|
|
17
61
|
const formatValue = ({value,format,method})=>{
|
|
18
62
|
return (format === 'money' && method != 'count')? value.formatMoney():value.formatNumber();
|
|
19
63
|
}
|
|
@@ -116,9 +116,12 @@ const DatagridFactory = (Factory)=>{
|
|
|
116
116
|
selectable,pagin,showPagination,
|
|
117
117
|
sessionName,onMount,onUnmount,onFetchData,dataSourceSelector,dataSourceSelectorProps,queryLimit,
|
|
118
118
|
filters,
|
|
119
|
+
chartContainerProps,
|
|
119
120
|
accordion, //pour le rendu du header en accordion
|
|
120
121
|
...rest
|
|
121
122
|
} = this.props;
|
|
123
|
+
const canRenderChart = this.canRenderChart();
|
|
124
|
+
chartContainerProps = defaultObj(chartContainerProps);
|
|
122
125
|
testID = defaultStr(testID,'RN_DatagridTableComponent');
|
|
123
126
|
rest = defaultObj(rest);
|
|
124
127
|
let showDataSourceSelector = false;
|
|
@@ -168,7 +171,7 @@ const DatagridFactory = (Factory)=>{
|
|
|
168
171
|
if(selectableMultiple && max){
|
|
169
172
|
max = max.formatNumber();
|
|
170
173
|
restItems = [
|
|
171
|
-
...(selectableMultiple ? [{
|
|
174
|
+
...(selectableMultiple && !canRenderChart ? [{
|
|
172
175
|
label : "Sélectionner "+max.formatNumber(),
|
|
173
176
|
icon : "select-all",
|
|
174
177
|
onPress : (x,event)=>{
|
|
@@ -188,9 +191,9 @@ const DatagridFactory = (Factory)=>{
|
|
|
188
191
|
const {layout} = this.state;
|
|
189
192
|
let maxHeight = winheight-100;
|
|
190
193
|
if(layout && typeof layout.windowHeight =='number' && layout.windowHeight){
|
|
191
|
-
const diff = winheight - Math.max(defaultNumber(layout.y,layout.top),
|
|
192
|
-
if(winheight<=
|
|
193
|
-
maxHeight =
|
|
194
|
+
const diff = winheight - Math.max(defaultNumber(layout.y,layout.top),100);
|
|
195
|
+
if(winheight<=350){
|
|
196
|
+
maxHeight = 350;
|
|
194
197
|
} else {
|
|
195
198
|
maxHeight = diff;
|
|
196
199
|
}
|
|
@@ -216,7 +219,7 @@ const DatagridFactory = (Factory)=>{
|
|
|
216
219
|
{showFilters?'Masquer/Filtres':'Afficher/Filtres'}
|
|
217
220
|
</Button>
|
|
218
221
|
)}
|
|
219
|
-
{hasFooterFields ? <Button
|
|
222
|
+
{hasFooterFields && !canRenderChart ? <Button
|
|
220
223
|
normal
|
|
221
224
|
style={styles.paginationItem}
|
|
222
225
|
onPress = {()=>{this.toggleFooters(!showFooters)} }
|
|
@@ -284,6 +287,7 @@ const DatagridFactory = (Factory)=>{
|
|
|
284
287
|
|
|
285
288
|
/>
|
|
286
289
|
{this.renderSectionListMenu()}
|
|
290
|
+
{this.renderDisplayTypes()}
|
|
287
291
|
<View testID={testID+"_HeaderPagination"} style = {styles.paginationItem}>
|
|
288
292
|
<BottomSheetMenu
|
|
289
293
|
testID={testID+"_HeaderMenus"}
|
|
@@ -325,20 +329,28 @@ const DatagridFactory = (Factory)=>{
|
|
|
325
329
|
{rPagination}
|
|
326
330
|
{_progressBar}
|
|
327
331
|
</View>
|
|
328
|
-
<Table
|
|
332
|
+
{<Table
|
|
333
|
+
renderListContent = {canRenderChart? false:true}
|
|
329
334
|
ref = {this.listRef}
|
|
330
335
|
{...rest}
|
|
331
336
|
onLayout = {(args)=>{
|
|
332
337
|
if(rest.onLayout){
|
|
333
338
|
rest.onLayout(args);
|
|
334
339
|
}
|
|
340
|
+
if(canRenderChart){
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
335
343
|
this.updateLayout(args);
|
|
336
344
|
}}
|
|
345
|
+
children = {canRenderChart ? <View testID={testID+"_ChartContainer"} {...chartContainerProps} style={[theme.styles.w100,chartContainerProps.style]}>
|
|
346
|
+
{this.renderChart()}
|
|
347
|
+
</View> : null}
|
|
337
348
|
getItemType = {this.getFlashListItemType.bind(this)}
|
|
338
349
|
renderItem = {this.renderFlashListItem.bind(this)}
|
|
339
|
-
hasFooters = {hasFooterFields}
|
|
350
|
+
hasFooters = {hasFooterFields && !canRenderChart ? true : false}
|
|
340
351
|
showFilters = {showFilters}
|
|
341
|
-
showFooters = {showFooters}
|
|
352
|
+
showFooters = {showFooters && !canRenderChart ? true : false}
|
|
353
|
+
showHeaders = { canRenderChart ? !!showFilters : true}
|
|
342
354
|
headerContainerProps = {{}}
|
|
343
355
|
headerCellContainerProps = {{
|
|
344
356
|
style : showFilters?{justifyContent:'flex-start'}:null
|
|
@@ -359,7 +371,7 @@ const DatagridFactory = (Factory)=>{
|
|
|
359
371
|
renderFilterCell={this.renderFilterCell.bind(this)}
|
|
360
372
|
renderFooterCell={this.renderFooterCell.bind(this)}
|
|
361
373
|
renderEmpty = {this.renderEmpty.bind(this)}
|
|
362
|
-
/>
|
|
374
|
+
/>}
|
|
363
375
|
</View>
|
|
364
376
|
}
|
|
365
377
|
}
|
|
@@ -85,7 +85,7 @@ export const selectDateFormatFieldProps = ({onAdd:customOnAdd,onAddCustomFormat,
|
|
|
85
85
|
showAdd : false,
|
|
86
86
|
}
|
|
87
87
|
}
|
|
88
|
-
export const getDateFormatSelectorItems = x=> Object.map(DateLib.
|
|
88
|
+
export const getDateFormatSelectorItems = x=> Object.map(DateLib.sortedFormats,(format)=>{
|
|
89
89
|
return {code : format,label:new Date().toFormat(format)}
|
|
90
90
|
});
|
|
91
91
|
|
|
@@ -318,6 +318,9 @@ export default class Field extends AppComponent {
|
|
|
318
318
|
getName (){
|
|
319
319
|
return this.name;
|
|
320
320
|
}
|
|
321
|
+
getLabel (){
|
|
322
|
+
return defaultStr(this.label,this.props.label,this.props.text,this.props.title,this.name);
|
|
323
|
+
}
|
|
321
324
|
getFormName(){
|
|
322
325
|
return this.formName;
|
|
323
326
|
}
|
|
@@ -2,6 +2,7 @@ import Field from "./Field";
|
|
|
2
2
|
import Dropdown from "$ecomponents/Dropdown";
|
|
3
3
|
import PropTypes from "prop-types";
|
|
4
4
|
import {isObj} from "$utils";
|
|
5
|
+
import appConfig from "$capp/config";
|
|
5
6
|
|
|
6
7
|
export default class FormSelectField extends Field{
|
|
7
8
|
constructor(props) {
|
|
@@ -115,8 +116,9 @@ export default class FormSelectField extends Field{
|
|
|
115
116
|
delete props.format;
|
|
116
117
|
delete props.import;
|
|
117
118
|
delete props.exports;
|
|
118
|
-
|
|
119
|
-
|
|
119
|
+
const isCountry = this.type.contains('country');
|
|
120
|
+
if( isCountry && props.multiple !== true){
|
|
121
|
+
props.defaultValue = defaultStr(props.defaultValue,appConfig.countryCode,appConfig.get("countryCode","country"));
|
|
120
122
|
}
|
|
121
123
|
return <Dropdown
|
|
122
124
|
{...props}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import PhoneInput from "$ecomponents/PhoneInput";
|
|
2
2
|
import Field from "./Field";
|
|
3
|
+
import appConfig from "$capp/config";
|
|
3
4
|
|
|
4
5
|
export default class FormPhoneInputField extends Field {
|
|
5
6
|
canFocus(){
|
|
@@ -9,6 +10,7 @@ export default class FormPhoneInputField extends Field {
|
|
|
9
10
|
props.onChange = (args)=>{
|
|
10
11
|
this.validate(args);
|
|
11
12
|
}
|
|
13
|
+
props.country = defaultStr(props.country,appConfig.countryCode,appConfig.get("countryCode","country"))
|
|
12
14
|
return <PhoneInput
|
|
13
15
|
{...props}
|
|
14
16
|
setRef = {setRef}
|
|
@@ -9,7 +9,7 @@ import theme,{black,white,Colors,StylePropTypes,DISABLED_OPACITY} from "$theme";
|
|
|
9
9
|
import PropTypes from "prop-types";
|
|
10
10
|
import { Dimensions } from 'react-native';
|
|
11
11
|
import View from "$ecomponents/View";
|
|
12
|
-
import {defaultVal} from "$utils";
|
|
12
|
+
import {defaultVal,isNonNullString,defaultStr,defaultObj} from "$utils";
|
|
13
13
|
import Tooltip from "$ecomponents/Tooltip";
|
|
14
14
|
import Label from "$ecomponents/Label";
|
|
15
15
|
|
|
@@ -27,14 +27,17 @@ const MenuItemComponent = React.forwardRef(({
|
|
|
27
27
|
style,
|
|
28
28
|
contentStyle,
|
|
29
29
|
testID,
|
|
30
|
-
|
|
30
|
+
labelStyle,
|
|
31
31
|
primary,
|
|
32
32
|
secondary,
|
|
33
33
|
iconProps,
|
|
34
34
|
isBottomSheetItem,
|
|
35
35
|
accessibilityLabel,
|
|
36
|
+
right,
|
|
37
|
+
contentContainerProps,
|
|
36
38
|
...rest
|
|
37
39
|
},ref) => {
|
|
40
|
+
contentContainerProps = defaultObj(contentContainerProps);
|
|
38
41
|
title = defaultVal(label,text,title);
|
|
39
42
|
const disabledColor = color(theme.dark ? white : black)
|
|
40
43
|
.alpha(0.32)
|
|
@@ -49,20 +52,21 @@ const MenuItemComponent = React.forwardRef(({
|
|
|
49
52
|
? disabledColor
|
|
50
53
|
: color(theme.colors.text).alpha(theme.ALPHA).rgb().string();
|
|
51
54
|
iconProps = defaultObj(iconProps);
|
|
52
|
-
|
|
55
|
+
labelStyle = Object.assign({},StyleSheet.flatten(labelStyle));
|
|
53
56
|
style = Object.assign({},StyleSheet.flatten(style));
|
|
54
57
|
|
|
55
|
-
if(Colors.isValid(
|
|
56
|
-
iconColor =
|
|
58
|
+
if(Colors.isValid(labelStyle.color)){
|
|
59
|
+
iconColor = labelStyle.color;
|
|
57
60
|
} else if(Colors.isValid(style.color)){
|
|
58
61
|
titleColor = iconColor = style.color;
|
|
59
62
|
}
|
|
60
|
-
|
|
61
63
|
const pointerEvents = disabled ? 'none' : 'auto';
|
|
62
64
|
const disabledStyle = disabled ? {opacity:DISABLED_OPACITY} : null;
|
|
63
65
|
const winW = Dimensions.get("window").width-30;
|
|
64
66
|
const maxWidthStyle = isBottomSheetItem ? {width:winW,maxWidth:null} : undefined;
|
|
65
67
|
const maxWidthTextStyle = isBottomSheetItem ? {width:winW-50} : null;
|
|
68
|
+
right = typeof right =='function'? right ({color:titleColor}) : right;
|
|
69
|
+
if(!React.isValidElement(right)) right = null;
|
|
66
70
|
return (
|
|
67
71
|
<Tooltip
|
|
68
72
|
{...defaultObj(rest)}
|
|
@@ -77,31 +81,37 @@ const MenuItemComponent = React.forwardRef(({
|
|
|
77
81
|
accessibilityState={{ disabled }}
|
|
78
82
|
pointerEvents = {pointerEvents}
|
|
79
83
|
>
|
|
80
|
-
<View style={[styles.row]} ref={ref}>
|
|
84
|
+
<View style={[styles.row]} ref={ref} testID={testID+"_ContentContainer"}>
|
|
81
85
|
{icon ? (
|
|
82
|
-
<View style={[styles.item, styles.icon]} pointerEvents="box-none">
|
|
86
|
+
<View testID={testID+"_IconContainer"} style={[styles.item, styles.icon]} pointerEvents="box-none">
|
|
83
87
|
<Icon source={icon} size={24} {...iconProps} style={[iconProps.style,styles.iconT]} color={iconColor} />
|
|
84
88
|
</View>
|
|
85
89
|
) : null}
|
|
86
90
|
<View
|
|
91
|
+
testID={testID+"_Right2LabelContainer"}
|
|
92
|
+
pointerEvents={!right?"none":"auto"}
|
|
93
|
+
{...contentContainerProps}
|
|
87
94
|
style={[
|
|
88
95
|
styles.item,
|
|
89
96
|
styles.content,
|
|
90
97
|
!maxWidthStyle && icon ? styles.widthWithIcon : null,
|
|
91
98
|
contentStyle,
|
|
92
99
|
!icon?styles.titleNoIcon:null,
|
|
93
|
-
|
|
100
|
+
right && theme.styles.row,
|
|
101
|
+
maxWidthStyle,
|
|
102
|
+
contentContainerProps.style
|
|
94
103
|
]}
|
|
95
|
-
pointerEvents="none"
|
|
96
104
|
>
|
|
97
105
|
<Label
|
|
106
|
+
testID={testID+"_Label"}
|
|
98
107
|
selectable={false}
|
|
99
108
|
numberOfLines={1}
|
|
100
109
|
ellipsizeMode = {"tail"}
|
|
101
|
-
style={[styles.title, { color: titleColor },
|
|
110
|
+
style={[styles.title, { color: titleColor }, labelStyle,styles.noMargin,!right ? maxWidthTextStyle : null]}
|
|
102
111
|
>
|
|
103
112
|
{title}
|
|
104
113
|
</Label>
|
|
114
|
+
{right}
|
|
105
115
|
</View>
|
|
106
116
|
</View>
|
|
107
117
|
</Tooltip>
|
|
@@ -153,6 +163,9 @@ const styles = StyleSheet.create({
|
|
|
153
163
|
widthWithIcon: {
|
|
154
164
|
maxWidth: maxWidth - iconWidth /*+ 48*/,
|
|
155
165
|
},
|
|
166
|
+
widthWithRight: {
|
|
167
|
+
maxWidth: maxWidth - iconWidth /*+ 48*/,
|
|
168
|
+
},
|
|
156
169
|
titleNoIcon : {
|
|
157
170
|
marginHorizontal : 8
|
|
158
171
|
}
|
|
@@ -185,7 +198,7 @@ MenuItemComponent.propTypes = {
|
|
|
185
198
|
*/
|
|
186
199
|
style: StylePropTypes,
|
|
187
200
|
contentStyle: StylePropTypes,
|
|
188
|
-
|
|
201
|
+
labelStyle : StylePropTypes,
|
|
189
202
|
/**
|
|
190
203
|
* @optional
|
|
191
204
|
*/
|
|
@@ -124,7 +124,7 @@ const Snackbar = ({
|
|
|
124
124
|
testID={testID+"_Container"}
|
|
125
125
|
{...containerProps}
|
|
126
126
|
pointerEvents="box-none"
|
|
127
|
-
style={[styles.wrapper, containerPaddings,containerProps.style]}
|
|
127
|
+
style={[styles.wrapper, containerPaddings,action && theme.styles.pr1,containerProps.style]}
|
|
128
128
|
>
|
|
129
129
|
<Surface
|
|
130
130
|
pointerEvents="box-none"
|
|
@@ -43,7 +43,7 @@ const getOnScrollCb = (refs,pos,cb2)=>{
|
|
|
43
43
|
return isMobileNative()? cb : debounce(cb,200);
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
const TableComponent = React.forwardRef(({containerProps,renderEmpty,renderItem,isRowSelected,headerScrollViewProps,footerScrollViewProps,scrollViewProps,showFooters,renderFooterCell,footerCellContainerProps,filterCellContainerProps,headerContainerProps,headerCellContainerProps,headerProps,rowProps:customRowProps,renderCell,cellContainerProps,hasFooters,renderHeaderCell,renderFilterCell,columnProps,getRowKey,columnsWidths,colsWidths,footerContainerProps,showFilters,columns,data,testID,...props},tableRef)=>{
|
|
46
|
+
const TableComponent = React.forwardRef(({containerProps,renderListContent,children,renderEmpty,renderItem,isRowSelected,headerScrollViewProps,footerScrollViewProps,scrollViewProps,showFooters,renderFooterCell,footerCellContainerProps,filterCellContainerProps,headerContainerProps,headerCellContainerProps,headerProps,rowProps:customRowProps,renderCell,cellContainerProps,hasFooters,renderHeaderCell,renderFilterCell,columnProps,getRowKey,columnsWidths,colsWidths,footerContainerProps,showHeaders,showFilters,columns,data,testID,...props},tableRef)=>{
|
|
47
47
|
containerProps = defaultObj(containerProps);
|
|
48
48
|
testID = defaultStr(testID,"RN_TableComponent");
|
|
49
49
|
cellContainerProps = defaultObj(cellContainerProps);
|
|
@@ -138,7 +138,7 @@ const TableComponent = React.forwardRef(({containerProps,renderEmpty,renderItem,
|
|
|
138
138
|
React.useEffect(()=>{
|
|
139
139
|
setState({...state,...prepareState()});
|
|
140
140
|
},[data,columns]);
|
|
141
|
-
const emptyData = typeof renderEmpty =='function' && !Object.size(data,true)? renderEmpty() : null;
|
|
141
|
+
const emptyData = renderListContent === false ?null : typeof renderEmpty =='function' && !Object.size(data,true)? renderEmpty() : null;
|
|
142
142
|
const hasEmptyData = emptyData && React.isValidElement(emptyData);
|
|
143
143
|
const {visibleColumns,columns:cols,headers,footers,filters} = state;
|
|
144
144
|
headerContainerProps = defaultObj(headerContainerProps);
|
|
@@ -199,10 +199,11 @@ const TableComponent = React.forwardRef(({containerProps,renderEmpty,renderItem,
|
|
|
199
199
|
get scrollViewContext(){ return scrollViewRef.current},
|
|
200
200
|
get headerScrollViewContext(){return headerScrollViewRef.current},
|
|
201
201
|
}
|
|
202
|
-
const
|
|
202
|
+
const showTableHeaders = showHeaders !== false || showFilters ;
|
|
203
|
+
const hContent = showTableHeaders && h.length ? <View testID={testID+"_Header"}{...hProps} {...headerContainerProps} style={[styles.header,headerContainerProps.style,hProps.style,f.length]}>
|
|
203
204
|
{h}
|
|
204
205
|
</View> : null,
|
|
205
|
-
fContent = f.length ? <View testID={testID+"_Footer"} {...footerContainerProps} style={[styles.header,styles.footers,footerContainerProps.style,theme.styles.pt0,theme.styles.pb0,theme.styles.ml0,theme.styles.mr0]}>
|
|
206
|
+
fContent = showTableHeaders && f.length ? <View testID={testID+"_Footer"} {...footerContainerProps} style={[styles.header,styles.footers,footerContainerProps.style,theme.styles.pt0,theme.styles.pb0,theme.styles.ml0,theme.styles.mr0]}>
|
|
206
207
|
{f}
|
|
207
208
|
</View> : null,
|
|
208
209
|
filtersContent = fFilters.length ? <View testID={testID+"_Filters"} style={[styles.header,styles.footers,theme.styles.pt0,theme.styles.pb0,theme.styles.ml0,theme.styles.mr0]}>
|
|
@@ -241,7 +242,8 @@ const TableComponent = React.forwardRef(({containerProps,renderEmpty,renderItem,
|
|
|
241
242
|
</View>
|
|
242
243
|
</ScrollView>
|
|
243
244
|
</RNView>
|
|
244
|
-
{
|
|
245
|
+
{renderListContent === false ? (React.isValidElement(children)? children : null) :
|
|
246
|
+
hasEmptyData ? <View testID={testID+"_Empty"} style={styles.hasNotData}>
|
|
245
247
|
{emptyData}
|
|
246
248
|
</View> : <ScrollView {...scrollViewProps} scrollEventThrottle = {scrollEventThrottle} horizontal contentContainerStyle={[scrollContentContainerStyle,scrollViewProps.contentContainerStyle]} showsVerticalScrollIndicator={false}
|
|
247
249
|
onScroll = {getOnScrollCb([headerScrollViewRef,footerScrollViewRef],null,(args)=>{
|
|
@@ -379,7 +381,7 @@ export const styles = StyleSheet.create({
|
|
|
379
381
|
container : {
|
|
380
382
|
width : '100%',
|
|
381
383
|
minHeight : 300,
|
|
382
|
-
paddingBottom :
|
|
384
|
+
paddingBottom : 10,
|
|
383
385
|
paddingLeft : 10,
|
|
384
386
|
paddingRight : 0,
|
|
385
387
|
flex : 1,
|
|
@@ -497,6 +499,7 @@ TableComponent.popTypes = {
|
|
|
497
499
|
PropTypes.func,
|
|
498
500
|
PropTypes.object
|
|
499
501
|
]),
|
|
502
|
+
renderListContent : PropTypes.bool,//si l'on devra rendre le contenu de la FlashList
|
|
500
503
|
renderItem : PropTypes.func,//la fonction permettant de gérer le rendu des item
|
|
501
504
|
headerScrollViewProps : PropTypes.object,
|
|
502
505
|
footerScrollViewProps : PropTypes.object,
|