@fto-consult/expo-ui 2.21.0 → 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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fto-consult/expo-ui",
3
- "version": "2.21.0",
3
+ "version": "2.21.1",
4
4
  "description": "Bibliothèque de composants UI Expo,react-native",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -62,6 +62,7 @@
62
62
  "@expo/html-elements": "^0.2.0",
63
63
  "@expo/vector-icons": "^13.0.0",
64
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(({type, height,chartId, width, series, options,testID,webViewProps, ...props },ref)=>{
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 chartIdRef = React.useRef(defaultStr(chartId,options.chart?.id,uniqid("chart-id")));
23
- const config = extend(options,{
24
- chart: {
25
- type,
26
- height,
27
- width,
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(config);
42
+ chartContext.current.updateOptions(options);
47
43
  } else if(prevOptions != options){
48
44
  chartContext.current.updateSeries(series);
49
45
  }
50
46
  }
51
- },[stableHash({type,options,series,width,height})])
52
- return <Chart {...props} options={config} chartId={chartIdRef.current} chartContext={chartContext} testID={testID} ref={ref}/>
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
- /> : <View style={styles.hasNotData}>
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}
@@ -39,33 +39,40 @@ import {Menu} from "$ecomponents/BottomSheet";
39
39
  import {styles as tableStyles} from "$ecomponents/Table";
40
40
  import {DialogProvider} from "$ecomponents/Form/FormData";
41
41
  import Chart from "$ecomponents/Chart";
42
+ import { aggregatorFunctions} from "../Footer/Footer";
42
43
 
44
+ const chart = "chart";
43
45
  export const displayTypes = {
44
46
  table : {
45
47
  code : "table",
48
+ isChart : false,
46
49
  label : 'Tableau',
47
50
  icon : "table",
48
51
  type : 'table',
49
52
  },
50
- /*lineChart : {
51
- code : 'lineChart',
53
+ lineChart : {
54
+ code : "lineChart",
55
+ isChart : true,
52
56
  label : 'Graphique|Linéaire',
53
57
  icon : "chart-areaspline",
54
58
  type : 'line',
55
59
  },
56
60
  areaChart : {
61
+ isChart : true,
57
62
  code : 'areaChart',
58
63
  label : 'Graphique|Surface',
59
64
  icon : "chart-areaspline-variant",
60
65
  type: 'area',
61
66
  },
62
67
  barChart : {
68
+ isChart : true,
63
69
  code : 'barChart',
64
70
  label : 'Graphique|Barres',
65
71
  icon : "chart-bar",
66
72
  type: 'bar'
67
73
  },
68
- donutChar : {
74
+ /*donutChart : {
75
+ isChart : true,
69
76
  code : 'donutChart',
70
77
  label : 'Graphique|Circulaire',
71
78
  icon : "chart-donut",
@@ -200,8 +207,9 @@ export default class CommonDatagridComponent extends AppComponent {
200
207
  if(this.canHandleColumnResize()){
201
208
  this.state.columnsWidths = this.preparedColumns.widths;
202
209
  }
203
- const dType = defaultStr(this.props.displayType,this.getSessionData("diplayType"),"table");
204
- this.state.displayType = this.displayTypes[dType] ? this.displayTypes[dType].code : "table" in this.displayTypes ? "table" : Object.keys(this.displayTypes)[0];
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;
205
213
  extendObj(this.state,this.prepareData({data}));
206
214
  const {width:windowWidth,height:windowHeight} = Dimensions.get("window");
207
215
  this.state.layout = {
@@ -281,7 +289,7 @@ export default class CommonDatagridComponent extends AppComponent {
281
289
  let sessionName = this.props.sessionName;
282
290
  let isDatagrid = this.isDatagrid()
283
291
  if(!isNonNullString(sessionName)){
284
- sessionName = 'datagrid';
292
+ //sessionName = 'datagrid';
285
293
  }
286
294
  let userCode = Auth.getLoggedUserCode();
287
295
  Object.defineProperties(this,{
@@ -1046,58 +1054,63 @@ export default class CommonDatagridComponent extends AppComponent {
1046
1054
  }
1047
1055
  return null;
1048
1056
  }
1049
- /*** configure la */
1050
- configureSectionListColumn(column){
1057
+ isSectionListColumnConfigurable(column){
1051
1058
  if(!isObj(column) || !isNonNullString(column.field) || !isObj(this.state.columns[column.field])){
1052
- 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'})
1053
- }
1054
- const col = this.state.columns[column.field];
1055
- const type = defaultStr(col.jsType,col.type).toLowerCase();
1056
- if(type.contains("date") || type =='time'){
1057
- return new Promise((resolve,reject)=>{
1058
- DialogProvider.open({
1059
- title : 'Format de date',
1060
- fields : {
1061
- dateFormat : {
1062
- type : 'select_dateformat',
1063
- required : true,
1064
- text : 'Sélectionnez un format de date',
1065
- defaultValue : defaultStr(this.configureSectionListSelectedValues[column.field],"dd/mm/yyyy"),
1066
- }
1067
- },
1068
- onCancelButtonPress : ()=>{
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}
1069
1090
  DialogProvider.close();
1070
- reject({msg:'aucun format sélectionné'})
1091
+ setTimeout(()=>{
1092
+ resolve(column);
1093
+ if(toggleSectionList !== false){
1094
+ this.toggleColumnInSectionList(column.field,true);
1095
+ }
1096
+ },100)
1071
1097
  },
1072
- actions : [{
1073
- text : "Sélectionnez",
1074
- icon : "check",
1075
- onPress : ({data})=>{
1076
- column.format = data.dateFormat;
1077
- this.configureSectionListSelectedValues[column.field] = data.dateFormat;
1078
- DialogProvider.close();
1079
- setTimeout(()=>{
1080
- resolve(column);
1081
- },100)
1082
- },
1083
- }]
1084
- })
1098
+ }]
1085
1099
  })
1086
- }
1087
- return Promise.resolve(column);
1100
+ })
1088
1101
  }
1089
- toggleColumnInSectionList(columnName){
1102
+ toggleColumnInSectionList(columnName,enable){
1090
1103
  if(!isNonNullString(columnName) || !isObj(this.state.columns[columnName])) return;
1091
1104
  if(!isObj(this.state.sectionListColumns) || !Array.isArray(this.preparedColumns?.sectionListColumnsMenuItems))return;
1092
1105
  const menuItems = this.preparedColumns?.sectionListColumnsMenuItems;
1093
1106
  if(!menuItems.length) return;
1094
1107
  const sectionListColumns = {...this.state.sectionListColumns};
1095
- if(isObj(sectionListColumns[columnName])){
1108
+ if(enable !== true && isObj(sectionListColumns[columnName])){
1096
1109
  delete sectionListColumns[columnName];
1097
1110
  } else {
1098
1111
  sectionListColumns[columnName] = {field:columnName};
1099
1112
  }
1100
- const cb =()=>{
1113
+ setTimeout(() => {
1101
1114
  const {sectionListColumns:pSListColumns} = this.prepareColumns({sectionListColumns});
1102
1115
  this.setIsLoading(true,()=>{
1103
1116
  this.prepareData({data:this.INITIAL_STATE.data,sectionListColumns:pSListColumns},(state)=>{
@@ -1107,12 +1120,6 @@ export default class CommonDatagridComponent extends AppComponent {
1107
1120
  });
1108
1121
  });
1109
1122
  },true);
1110
- }
1111
- setTimeout(() => {
1112
- if(!isObj(sectionListColumns[columnName])){
1113
- return cb();
1114
- }
1115
- return this.configureSectionListColumn(sectionListColumns[columnName]).then(cb).catch(notify.error)
1116
1123
  }, 100);
1117
1124
  }
1118
1125
  removeAllColumnsInSectionList(){
@@ -1131,34 +1138,162 @@ export default class CommonDatagridComponent extends AppComponent {
1131
1138
  }
1132
1139
  /*** si l'on peut rendre le contenu de type graphique */
1133
1140
  isChartRendable(){
1134
- return !this.isPivotDatagrid() && this.hasFooterFields() && this.isSectionList();
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);
1135
1146
  }
1136
1147
  canRenderChart(){
1137
- return this.isChartRendable() && this.state.displayType.toLowerCase().contains("chart");
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);
1138
1152
  }
1139
1153
  /***modifie le type de données d'affichage du tableau */
1140
- setDisplay(type){
1154
+ setDisplayType(type){
1141
1155
  if(!isObj(type) || !isNonNullString(type.code) || !displayTypes[type.code]) return;
1142
1156
  const tt = displayTypes[type.code];
1157
+ if(this.state.displayType == tt.code) return;
1158
+ const displayType = tt.code;
1143
1159
  if(tt.code == 'table'){
1144
- if(this.state.displayType == 'table') return;
1145
1160
  return this.setIsLoading(true,()=>{
1146
- this.setState({displayTypes:'table'},()=>{
1161
+ this.setState({displayType},()=>{
1147
1162
  this.setIsLoading(false,false);
1163
+ this.persistDisplayType(displayType);
1148
1164
  });
1149
1165
  },true)
1150
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)=>{
1151
1215
  DialogProvider.open({
1152
- title : 'Configuration de la courbe'
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
+ ]
1153
1267
  })
1154
- }
1268
+ })
1269
+ }
1270
+ getCharConfig(){
1271
+ return defaultObj(this.state.chartConfig);
1155
1272
  }
1156
1273
  renderDisplayTypes(){
1157
1274
  const m = [];
1158
- let activeType = null;
1275
+ let activeType = null,hasFoundChart = false,hasFoundTable = false;
1276
+ const hasConfig = this.isValidChartConfig();
1159
1277
  Object.map(this.displayTypes,(type,k)=>{
1160
- let c = k.toLowerCase();
1161
- if(c.contains('chart') && !this.isChartRendable()) return null;
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
+ }
1162
1297
  const active = this.state.displayType === k;
1163
1298
  if(active){
1164
1299
  activeType = type;
@@ -1166,10 +1301,14 @@ export default class CommonDatagridComponent extends AppComponent {
1166
1301
  m.push({
1167
1302
  ...type,
1168
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,
1169
1308
  onPress:()=>{
1170
- this.setDisplay(type);
1309
+ this.setDisplayType(type);
1171
1310
  }
1172
- })
1311
+ });
1173
1312
  });
1174
1313
  if(m.length <= 1 || !activeType) return null;
1175
1314
  if(!isMobileOrTabletMedia()){
@@ -1187,17 +1326,117 @@ export default class CommonDatagridComponent extends AppComponent {
1187
1326
  }}
1188
1327
  />
1189
1328
  }
1329
+ getEmptyDataValue(){
1330
+ return "N/A";
1331
+ }
1190
1332
  renderChart(){
1191
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
+ />
1192
1430
  }
1193
1431
  toggleDisplayOnlySectionListHeaders(){
1194
1432
  if(!this.canDisplayOnlySectionListHeaders()) return
1195
1433
  setTimeout(()=>{
1434
+ const showFooters = true;
1196
1435
  const displayOnlySectionListHeaders = !!!this.state.displayOnlySectionListHeaders;
1197
1436
  this.setSessionData("displayOnlySectionListHeaders",displayOnlySectionListHeaders);
1198
1437
  if(!displayOnlySectionListHeaders){
1199
1438
  return this.prepareData({data:this.INITIAL_STATE.data,displayOnlySectionListHeaders},(state)=>{
1200
- this.setState(state)
1439
+ this.setState({...state,showFooters})
1201
1440
  })
1202
1441
  } else {
1203
1442
  this.setIsLoading(true,()=>{
@@ -1207,7 +1446,7 @@ export default class CommonDatagridComponent extends AppComponent {
1207
1446
  data.push(d);
1208
1447
  }
1209
1448
  });
1210
- this.setState({data,displayOnlySectionListHeaders},()=>{
1449
+ this.setState({data,displayOnlySectionListHeaders,showFooters},()=>{
1211
1450
  this.setIsLoading(false),false;
1212
1451
  });
1213
1452
  },true)
@@ -1293,6 +1532,7 @@ export default class CommonDatagridComponent extends AppComponent {
1293
1532
  } = header;
1294
1533
  restCol = Object.clone(defaultObj(restCol));
1295
1534
  let colFilter = defaultVal(restCol.filter,true);
1535
+ const format = defaultStr(restCol.format).toLowerCase();
1296
1536
  field = header.field = defaultStr(header.field,field,headerIndex);
1297
1537
  delete restCol.filter;
1298
1538
 
@@ -1420,19 +1660,32 @@ export default class CommonDatagridComponent extends AppComponent {
1420
1660
  ...header,
1421
1661
  width,
1422
1662
  type,
1663
+ ...defaultObj(this.configureSectionListSelectedValues[field]),
1423
1664
  ...sListColumns[field],
1424
1665
  };///les colonnes de sections
1425
1666
  this.sectionListColumnsSize.current++;
1426
1667
  }
1427
- sectionListColumnsMenuItems.push({
1668
+ const mItem = {
1428
1669
  field,
1670
+ type,
1671
+ format,
1429
1672
  onPress : ()=>{
1430
1673
  this.toggleColumnInSectionList(field);
1431
1674
  return false;
1432
1675
  },
1433
1676
  title : title,
1434
1677
  icon : isInSectionListHeader?CHECKED_ICON_NAME : null,
1435
- });
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);
1436
1689
  }
1437
1690
  columnIndex++;
1438
1691
  visibleColumnIndex++;
@@ -2424,7 +2677,11 @@ export const ProgressBar = CommonDatagridComponent.LinesProgressBar;
2424
2677
  CommonDatagridComponent.getDefaultPreloader = (props)=>{
2425
2678
  return <Preloader {...defaultObj(props)}/>
2426
2679
  }
2427
- const allDTypes = Object.keys(displayTypes);
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
+ }));
2428
2685
  CommonDatagridComponent.propTypes = {
2429
2686
  canMakePhoneCall : PropTypes.bool,//si l'on peut faire un appel sur la données sélectionnées
2430
2687
  makePhoneCallProps : PropTypes.oneOfType([
@@ -2602,12 +2859,16 @@ CommonDatagridComponent.propTypes = {
2602
2859
  renderCustomPagination : PropTypes.func,
2603
2860
  getActionsArgs : PropTypes.func,//fonction permettant de récupérer les props supplémentaires à passer aux actions du datagrid
2604
2861
  displayOnlySectionListHeaders : PropTypes.bool,// si uniquement les entêtes des sections seront affichés, valides uniquement en affichage des sectionHeader
2605
-
2606
- /*** types d'affichage displayTypes */
2607
- /** les types d'affichage supportés */
2608
- displayType : PropTypes.oneOf(allDTypes),
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,
2609
2870
  /*** les types d'afichates supportés par l'application */
2610
- displayTypes : PropTypes.arrayOf(PropTypes.oneOf(allDTypes))
2871
+ displayTypes : PropTypes.arrayOf(chartDisplayType)
2611
2872
  }
2612
2873
 
2613
2874
  const styles = StyleSheet.create({
@@ -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),150);
192
- if(winheight<=300){
193
- maxHeight = 300;
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)} }
@@ -326,20 +329,28 @@ const DatagridFactory = (Factory)=>{
326
329
  {rPagination}
327
330
  {_progressBar}
328
331
  </View>
329
- <Table
332
+ {<Table
333
+ renderListContent = {canRenderChart? false:true}
330
334
  ref = {this.listRef}
331
335
  {...rest}
332
336
  onLayout = {(args)=>{
333
337
  if(rest.onLayout){
334
338
  rest.onLayout(args);
335
339
  }
340
+ if(canRenderChart){
341
+ return;
342
+ }
336
343
  this.updateLayout(args);
337
344
  }}
345
+ children = {canRenderChart ? <View testID={testID+"_ChartContainer"} {...chartContainerProps} style={[theme.styles.w100,chartContainerProps.style]}>
346
+ {this.renderChart()}
347
+ </View> : null}
338
348
  getItemType = {this.getFlashListItemType.bind(this)}
339
349
  renderItem = {this.renderFlashListItem.bind(this)}
340
- hasFooters = {hasFooterFields}
350
+ hasFooters = {hasFooterFields && !canRenderChart ? true : false}
341
351
  showFilters = {showFilters}
342
- showFooters = {showFooters}
352
+ showFooters = {showFooters && !canRenderChart ? true : false}
353
+ showHeaders = { canRenderChart ? !!showFilters : true}
343
354
  headerContainerProps = {{}}
344
355
  headerCellContainerProps = {{
345
356
  style : showFilters?{justifyContent:'flex-start'}:null
@@ -360,7 +371,7 @@ const DatagridFactory = (Factory)=>{
360
371
  renderFilterCell={this.renderFilterCell.bind(this)}
361
372
  renderFooterCell={this.renderFooterCell.bind(this)}
362
373
  renderEmpty = {this.renderEmpty.bind(this)}
363
- />
374
+ />}
364
375
  </View>
365
376
  }
366
377
  }
@@ -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
  }
@@ -48,6 +48,7 @@ const FormDataDialogProvider = React.forwardRef((props,innerRef)=>{
48
48
  return <Dialog
49
49
  responsive
50
50
  withScrollView
51
+ subtitle ={false}
51
52
  {...props}
52
53
  {...state}
53
54
  formProps = {formProps}
@@ -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
 
@@ -34,8 +34,10 @@ const MenuItemComponent = React.forwardRef(({
34
34
  isBottomSheetItem,
35
35
  accessibilityLabel,
36
36
  right,
37
+ contentContainerProps,
37
38
  ...rest
38
39
  },ref) => {
40
+ contentContainerProps = defaultObj(contentContainerProps);
39
41
  title = defaultVal(label,text,title);
40
42
  const disabledColor = color(theme.dark ? white : black)
41
43
  .alpha(0.32)
@@ -64,6 +66,7 @@ const MenuItemComponent = React.forwardRef(({
64
66
  const maxWidthStyle = isBottomSheetItem ? {width:winW,maxWidth:null} : undefined;
65
67
  const maxWidthTextStyle = isBottomSheetItem ? {width:winW-50} : null;
66
68
  right = typeof right =='function'? right ({color:titleColor}) : right;
69
+ if(!React.isValidElement(right)) right = null;
67
70
  return (
68
71
  <Tooltip
69
72
  {...defaultObj(rest)}
@@ -85,28 +88,31 @@ const MenuItemComponent = React.forwardRef(({
85
88
  </View>
86
89
  ) : null}
87
90
  <View
88
- testID={testID+"_LabelContainer"}
91
+ testID={testID+"_Right2LabelContainer"}
92
+ pointerEvents={!right?"none":"auto"}
93
+ {...contentContainerProps}
89
94
  style={[
90
95
  styles.item,
91
96
  styles.content,
92
97
  !maxWidthStyle && icon ? styles.widthWithIcon : null,
93
98
  contentStyle,
94
99
  !icon?styles.titleNoIcon:null,
95
- maxWidthStyle
100
+ right && theme.styles.row,
101
+ maxWidthStyle,
102
+ contentContainerProps.style
96
103
  ]}
97
- pointerEvents="none"
98
104
  >
99
105
  <Label
100
106
  testID={testID+"_Label"}
101
107
  selectable={false}
102
108
  numberOfLines={1}
103
109
  ellipsizeMode = {"tail"}
104
- style={[styles.title, { color: titleColor }, labelStyle,styles.noMargin,maxWidthTextStyle]}
110
+ style={[styles.title, { color: titleColor }, labelStyle,styles.noMargin,!right ? maxWidthTextStyle : null]}
105
111
  >
106
112
  {title}
107
113
  </Label>
114
+ {right}
108
115
  </View>
109
- {React.isValidElement(right) && right || null}
110
116
  </View>
111
117
  </Tooltip>
112
118
  );
@@ -157,6 +163,9 @@ const styles = StyleSheet.create({
157
163
  widthWithIcon: {
158
164
  maxWidth: maxWidth - iconWidth /*+ 48*/,
159
165
  },
166
+ widthWithRight: {
167
+ maxWidth: maxWidth - iconWidth /*+ 48*/,
168
+ },
160
169
  titleNoIcon : {
161
170
  marginHorizontal : 8
162
171
  }
@@ -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 hContent = h.length ? <View testID={testID+"_Header"}{...hProps} {...headerContainerProps} style={[styles.header,headerContainerProps.style,hProps.style,f.length]}>
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
- {hasEmptyData ? <View testID={testID+"_Empty"} style={styles.hasNotData}>
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 : 50,
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,