@fto-consult/expo-ui 2.21.0 → 2.21.2
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 +2 -1
- package/src/components/Chart/index.js +16 -18
- package/src/components/Datagrid/Accordion/index.js +13 -8
- package/src/components/Datagrid/Common/Common.js +333 -72
- package/src/components/Datagrid/Footer/Footer.js +44 -0
- package/src/components/Datagrid/Table/index.js +17 -9
- package/src/components/Form/Fields/Field.js +3 -0
- package/src/components/Form/FormData/DialogProvider.js +1 -0
- package/src/components/Menu/Item.js +15 -6
- 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.21.
|
|
3
|
+
"version": "2.21.2",
|
|
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(({
|
|
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}
|
|
@@ -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
|
-
|
|
51
|
-
code :
|
|
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
|
-
|
|
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
|
-
|
|
204
|
-
|
|
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
|
-
|
|
1050
|
-
configureSectionListColumn(column){
|
|
1057
|
+
isSectionListColumnConfigurable(column){
|
|
1051
1058
|
if(!isObj(column) || !isNonNullString(column.field) || !isObj(this.state.columns[column.field])){
|
|
1052
|
-
return
|
|
1053
|
-
}
|
|
1054
|
-
const
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
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
|
-
|
|
1091
|
+
setTimeout(()=>{
|
|
1092
|
+
resolve(column);
|
|
1093
|
+
if(toggleSectionList !== false){
|
|
1094
|
+
this.toggleColumnInSectionList(column.field,true);
|
|
1095
|
+
}
|
|
1096
|
+
},100)
|
|
1071
1097
|
},
|
|
1072
|
-
|
|
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
|
-
|
|
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()
|
|
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
|
|
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
|
-
|
|
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({
|
|
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
|
|
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
|
-
|
|
1161
|
-
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
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(
|
|
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),
|
|
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)} }
|
|
@@ -326,7 +329,8 @@ 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)=>{
|
|
@@ -335,11 +339,15 @@ const DatagridFactory = (Factory)=>{
|
|
|
335
339
|
}
|
|
336
340
|
this.updateLayout(args);
|
|
337
341
|
}}
|
|
342
|
+
children = {canRenderChart ? <View testID={testID+"_ChartContainer"} {...chartContainerProps} style={[theme.styles.w100,chartContainerProps.style]}>
|
|
343
|
+
{this.renderChart()}
|
|
344
|
+
</View> : null}
|
|
338
345
|
getItemType = {this.getFlashListItemType.bind(this)}
|
|
339
346
|
renderItem = {this.renderFlashListItem.bind(this)}
|
|
340
|
-
hasFooters = {hasFooterFields}
|
|
347
|
+
hasFooters = {hasFooterFields && !canRenderChart ? true : false}
|
|
341
348
|
showFilters = {showFilters}
|
|
342
|
-
showFooters = {showFooters}
|
|
349
|
+
showFooters = {showFooters && !canRenderChart ? true : false}
|
|
350
|
+
showHeaders = { canRenderChart ? !!showFilters : true}
|
|
343
351
|
headerContainerProps = {{}}
|
|
344
352
|
headerCellContainerProps = {{
|
|
345
353
|
style : showFilters?{justifyContent:'flex-start'}:null
|
|
@@ -360,7 +368,7 @@ const DatagridFactory = (Factory)=>{
|
|
|
360
368
|
renderFilterCell={this.renderFilterCell.bind(this)}
|
|
361
369
|
renderFooterCell={this.renderFooterCell.bind(this)}
|
|
362
370
|
renderEmpty = {this.renderEmpty.bind(this)}
|
|
363
|
-
/>
|
|
371
|
+
/>}
|
|
364
372
|
</View>
|
|
365
373
|
}
|
|
366
374
|
}
|
|
@@ -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
|
}
|
|
@@ -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+"
|
|
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
|
-
|
|
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
|
|
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
|
|
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,
|