@fto-consult/expo-ui 2.23.11 → 2.24.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.
@@ -40,17 +40,25 @@ import {styles as tableStyles} from "$ecomponents/Table";
40
40
  import {DialogProvider} from "$ecomponents/Form/FormData";
41
41
  import Chart,{getMaxSupportedSeriesSize} from "$ecomponents/Chart";
42
42
 
43
- const chart = "chart";
44
43
  export const donutChart = {
45
44
  isChart : true,
46
45
  code : 'donutChart',
47
- label : 'Graphique|Circulaire',
46
+ label : 'Donut',
48
47
  icon : "chart-donut",
49
48
  type: 'donut',
49
+ key : "donut",
50
50
  isDonut : true,
51
- isRendable : ({displayOnlySectionListHeaders,isSectionList})=>isSectionList && displayOnlySectionListHeaders,
51
+ isRendable : ({displayOnlySectionListHeaders,isSectionList})=> false && isSectionList && displayOnlySectionListHeaders,
52
52
  tooltip : "Pour pouvoir visulaiser ce type de graphe, vous devez : grouper les données du tableau selon le criètre de votre choix, puis afficher uniquement les totaux des données groupées"
53
53
  }
54
+ const stackSettings = {
55
+ type : 'switch',
56
+ text : "Graphe empilé?",
57
+ checkedValue : true,
58
+ uncheckedValue : false,
59
+ //le nom de la propriétés dans les propriétés du tableau
60
+ settingKey : "chart",
61
+ }
54
62
  export const displayTypes = {
55
63
  table : {
56
64
  code : "table",
@@ -62,26 +70,49 @@ export const displayTypes = {
62
70
  lineChart : {
63
71
  code : "lineChart",
64
72
  isChart : true,
65
- label : 'Graphique|Linéaire',
73
+ label : 'Linéaire',
66
74
  icon : "chart-areaspline",
67
75
  type : 'line',
76
+ key : "line",
68
77
  },
69
78
  areaChart : {
70
79
  isChart : true,
71
80
  code : 'areaChart',
72
- label : 'Graphique|Surface',
81
+ label : 'Surface',
73
82
  icon : "chart-areaspline-variant",
74
83
  type: 'area',
84
+ key : "line",
75
85
  },
76
86
  barChart : {
77
87
  isChart : true,
78
88
  code : 'barChart',
79
- label : 'Graphique|Barres',
89
+ label : 'Histogramme',
80
90
  icon : "chart-bar",
81
91
  type: 'bar',
82
- isBar : true,
92
+ key : "line",
93
+ settings : {
94
+ stacked : stackSettings,
95
+ }
96
+ },
97
+ pieChart : {
98
+ ...donutChart,
99
+ code : 'pieChart',
100
+ label : 'Pie',
101
+ icon : "chart-pie",
102
+ type: 'pie',
83
103
  },
84
104
  donutChart,
105
+ radarChart : {
106
+ isChart : true,
107
+ code : 'radarChart',
108
+ label : 'Radar',
109
+ icon : "radar",
110
+ type: 'radar',
111
+ key : "line",
112
+ settings : {
113
+ stacked : stackSettings,
114
+ }
115
+ }
85
116
  /*rangeChart : {
86
117
  code : "rangeChart",
87
118
  isChart : true,
@@ -197,6 +228,7 @@ export default class CommonDatagridComponent extends AppComponent {
197
228
  sectionListDataSize : {value : {current : 0}},
198
229
  enablePointerEventsRef : {value : {current:false}},
199
230
  configureSectionListSelectedValues : {value : {}},
231
+ chartIdPrefix : {value : uniqid("datagrid-chart-id-prefix")},
200
232
  ///la liste des fonctions d'aggregations supportées
201
233
  aggregatorFunctions : {value : extendAggreagatorFunctions(this.props.aggregatorFunctions)},
202
234
  ///les types d'affichage
@@ -1261,8 +1293,8 @@ export default class CommonDatagridComponent extends AppComponent {
1261
1293
  if(!isValidAggregator(ag) || ag.code == this.state.aggregatorFunction) return null;
1262
1294
  setTimeout(()=>{
1263
1295
  this.setIsLoading(true,()=>{
1264
- this.prepareData({data:this.INITIAL_STATE.data},(state)=>{
1265
- this.setState({...state,aggregatorFunction:ag.code},()=>{
1296
+ this.prepareData({data:this.INITIAL_STATE.data,aggregatorFunction:ag.code},(state)=>{
1297
+ this.setState(state,()=>{
1266
1298
  this.setSessionData("aggregatorFunction",ag.code);
1267
1299
  this.setIsLoading(false,false);
1268
1300
  })
@@ -1345,13 +1377,7 @@ export default class CommonDatagridComponent extends AppComponent {
1345
1377
  items : yItems,
1346
1378
  multiple : true,
1347
1379
  },
1348
- stacked : {
1349
- type : 'switch',
1350
- text : "Graphe empilé?",
1351
- disabled : this.state.displayType !== "barChart",
1352
- checkedValue : true,
1353
- uncheckedValue : false,
1354
- },
1380
+ stacked : stackSettings,
1355
1381
  title : {
1356
1382
  text : "Titre du graphe",
1357
1383
  format :'hashtag',
@@ -1494,6 +1520,7 @@ export default class CommonDatagridComponent extends AppComponent {
1494
1520
  if(!isValidAggregator(aggregatorFunction)){
1495
1521
  aggregatorFunction = this.getActiveAggregatorFunction();
1496
1522
  }
1523
+
1497
1524
  const code = aggregatorFunction.code;
1498
1525
  const isDonut = chartType.isDonut || chartType.isRadial;
1499
1526
  const config = this.getCharConfig();
@@ -1523,12 +1550,10 @@ export default class CommonDatagridComponent extends AppComponent {
1523
1550
  const loopForFooter = ({column,serieName,footers,header})=>{
1524
1551
  if(!isObj(column) || !isObj(footers)) return null;
1525
1552
  if(!isObj(footers[column.field])) return null;
1526
- const footer = footers[column.field]
1553
+ const footer = footers[column.field];
1527
1554
  if(typeof footer[code] !== 'number') return null;
1528
- const label = defaultStr(footer.label,footer.text,footer.field);
1529
1555
  if(typeof footer[code] !== 'number') return null;
1530
1556
  if(isDonut){
1531
- serieName = label;
1532
1557
  dataIndexes[header] = footer[code];
1533
1558
  } else {
1534
1559
  dataIndexes[serieName] = defaultArray(dataIndexes[serieName]);
@@ -1555,6 +1580,7 @@ export default class CommonDatagridComponent extends AppComponent {
1555
1580
  labels.push(index);
1556
1581
  });
1557
1582
  return {
1583
+ name : defaultStr(yAxisColumn.label,yAxisColumn.text,yAxisColumn.field),
1558
1584
  series,
1559
1585
  labels,
1560
1586
  }
@@ -1567,6 +1593,10 @@ export default class CommonDatagridComponent extends AppComponent {
1567
1593
  series
1568
1594
  }
1569
1595
  }
1596
+ }
1597
+ /*** permet de formatter les valeurs de la courbe en fonction du type passé en paramètre */
1598
+ chartValueFormattter(value,columnType){
1599
+
1570
1600
  }
1571
1601
  renderChart(){
1572
1602
  if(!this.canRenderChart()) return null;
@@ -1577,6 +1607,7 @@ export default class CommonDatagridComponent extends AppComponent {
1577
1607
  console.warn("impossible d'afficher le graphe de type ",chartType.label," car le type de données requis pour le rendu de ce graphe est invalide")
1578
1608
  return null;
1579
1609
  }
1610
+ const isDonut = chartType.isDonut || chartType.isRadial;
1580
1611
  const config = this.getCharConfig();
1581
1612
  if(!this.state.columns[config.y]) return null;
1582
1613
  const yAxisColumn = this.state.columns[config.y];
@@ -1656,38 +1687,54 @@ export default class CommonDatagridComponent extends AppComponent {
1656
1687
  customConfig = defaultObj(customConfig);
1657
1688
  customConfig.chart = defaultObj(customConfig.chart);
1658
1689
  const chartProps = extendObj(true,{},this.props.chartProps,customConfig);
1659
- if(chartType.isBar){
1660
- chartProps.chart.stacked = !!config.stacked;
1661
- } else chartProps.chart.stacked = undefined;
1662
- return <Chart
1663
- options = {{
1664
- ...chartProps,
1665
- title : {
1666
- text: defaultStr(config.title,chartProps.title),
1667
- align: 'left',
1668
- //margin: 10,
1669
- //offsetX: 0,
1670
- //offsetY: 0,
1671
- //floating: false,
1672
- style: {
1673
- //fontSize: '14px',
1674
- //fontWeight: 'bold',
1675
- //fontFamily: undefined,
1676
- color: theme.Colors.isValid(config.titleColor)?config.titleColor : undefined,
1677
- },
1678
- },
1679
- series,
1680
- chart : {
1681
- height :350,
1682
- ...defaultObj(chartProps.chart),
1683
- type : chartType.type,
1690
+ const settings = defaultObj(chartType.settings);
1691
+ Object.map(settings,(s,key)=>{
1692
+ if(!isObj(s) || !(key in config)) return null;
1693
+ const settingKey = defaultStr(s.settingKey,"chart");
1694
+ chartProps[settingKey] = defaultObj(chartProps[settingKey]);
1695
+ chartProps[settingKey][key] = config[key];
1696
+ });
1697
+ const chartOptions = {
1698
+ ...chartProps,
1699
+ title :extendObj(true,{}, {
1700
+ text: defaultStr(config.title,chartProps.title),
1701
+ align: 'left',
1702
+ //margin: 10,
1703
+ //offsetX: 0,
1704
+ //offsetY: 0,
1705
+ //floating: false,
1706
+ style: {
1707
+ //fontSize: '14px',
1708
+ //fontWeight: 'bold',
1709
+ //fontFamily: undefined,
1710
+ color: theme.Colors.isValid(config.titleColor)?config.titleColor : undefined,
1684
1711
  },
1685
- xaxis: {
1686
- ...defaultObj(chartProps.xaxis),
1687
- type: 'category',
1688
- ...defaultObj(xaxis)
1689
- }
1690
- }}
1712
+ },chartProps.title),
1713
+ series,
1714
+ chart : extendObj(true,{},{height :350},chartProps.chart,{
1715
+ type : chartType.type,
1716
+ })
1717
+ }
1718
+ //console.log(chartOptions," is chart options");
1719
+ const labelColor = theme.Colors.isValid(config.labelColor)? config.labelColor : theme.colors.text;
1720
+ if(!isDonut){
1721
+ chartOptions.xaxis = extendObj(true,{},{type: 'category'},chartProps.xaxis,{xaxis});
1722
+ const xLabels = chartOptions.xaxis.labels = defaultObj(chartOptions.xaxis.labels);
1723
+ xLabels.style = defaultObj(xLabels.style)
1724
+ xLabels.style.colors = (Array.isArray(xLabels.style.colors) && xLabels.style.colors.length || theme.Colors.isValid(xLabels.style.colors)) ? xLabels.style.colors : labelColor;
1725
+ chartOptions.yaxis = extendObj(true,{},{type: 'category'},chartProps.yaxis);
1726
+ const yLabels = chartOptions.yaxis.labels = defaultObj(chartOptions.yaxis.labels);
1727
+ yLabels.style = defaultObj(yLabels.style)
1728
+ yLabels.style.colors = (Array.isArray(yLabels.style.colors) && yLabels.style.colors.length || theme.Colors.isValid(yLabels.style.colors)) ? yLabels.style.colors : labelColor;
1729
+
1730
+ } else {
1731
+ delete chartOptions.xaxis;
1732
+ delete chartOptions.yaxis;
1733
+ }
1734
+ chartOptions.chart.id = this.chartIdPrefix+defaultStr(chartType.key,"no-key")
1735
+ return <Chart
1736
+ options = {chartOptions}
1737
+ key = {chartOptions.chart.id}
1691
1738
  />
1692
1739
  }
1693
1740
  canShowFooters(){
@@ -2018,8 +2065,9 @@ export default class CommonDatagridComponent extends AppComponent {
2018
2065
  return defaultNumber(this.sectionListDataSize.current)
2019
2066
  }
2020
2067
  prepareData(args,cb){
2021
- let {pagination,displayOnlySectionListHeaders:cdisplayOnlySectionListHeaders,data,force,sectionListColumns,updateFooters} = defaultObj(args);
2068
+ let {pagination,aggregatorFunction:customAggregatorFunction,displayOnlySectionListHeaders:cdisplayOnlySectionListHeaders,data,force,sectionListColumns,updateFooters} = defaultObj(args);
2022
2069
  cb = typeof cb ==='function'? cb : typeof args.cb == 'function'? args.cb : undefined;
2070
+ const aggregatorFunction = isNonNullString(customAggregatorFunction) && customAggregatorFunction in this.aggregatorFunctions ? this.aggregatorFunctions[customAggregatorFunction] : this.getActiveAggregatorFunction();
2023
2071
  sectionListColumns = isObj(sectionListColumns) ? sectionListColumns : this.state.sectionListColumns;
2024
2072
  const displayOnlySectionListHeaders = typeof cdisplayOnlySectionListHeaders == 'boolean'?cdisplayOnlySectionListHeaders : this.state.displayOnlySectionListHeaders;
2025
2073
  let isArr = Array.isArray(data);
@@ -2096,7 +2144,7 @@ export default class CommonDatagridComponent extends AppComponent {
2096
2144
  result.push(currentSectionListFooter);
2097
2145
  }
2098
2146
  Object.map(footersColumns,(columnDef,field)=>{
2099
- evalSingleValue({data:d,aggregatorFunction:this.getActiveAggregatorFunction(),aggregatorFunctions:this.aggregatorFunctions,columnDef,field,result,displayLabel:false})
2147
+ evalSingleValue({data:d,aggregatorFunction,aggregatorFunctions:this.aggregatorFunctions,columnDef,field,result,displayLabel:false})
2100
2148
  });
2101
2149
  }
2102
2150
  newData.push(d);
@@ -2127,7 +2175,7 @@ export default class CommonDatagridComponent extends AppComponent {
2127
2175
  } else if(force){
2128
2176
  this.setSelectedRows();
2129
2177
  }
2130
- const state = {data,displayOnlySectionListHeaders};
2178
+ const state = {data,displayOnlySectionListHeaders,aggregatorFunction:aggregatorFunction.code};
2131
2179
  if((cb)){
2132
2180
  cb(state);
2133
2181
  }
@@ -2263,9 +2311,10 @@ export default class CommonDatagridComponent extends AppComponent {
2263
2311
  if(typeof props !=='object' || !props){
2264
2312
  props = {};
2265
2313
  }
2266
- const children = React.isValidElement(this.props.progressBar) ? this.props.progressBar :
2314
+ const ProgressBar = this.props.progressBar;
2315
+ const children = React.isValidElement(ProgressBar) ? ProgressBar :
2267
2316
  this.props.useLinesProgressBar === true || this.props.useLineProgressBar === true ? CommonDatagridComponent.LineProgressBar(props)
2268
- : this.getDefaultPreloader(props);
2317
+ : React.isComponent(ProgressBar) ?<ProgressBar/> : this.getDefaultPreloader(props);
2269
2318
  return <DatagridProgressBar
2270
2319
  {...props}
2271
2320
  onChange = {(context)=>{
@@ -3172,6 +3221,7 @@ CommonDatagridComponent.propTypes = {
3172
3221
  aggregatorFunction : PropTypes.string,
3173
3222
  /*** permet de faire une mutation sur les options de la recherche, immédiatement avant le lancement de la recherche */
3174
3223
  fetchOptionsMutator : PropTypes.func,
3224
+ useLinesProgressBar : PropTypes.bool,//si le progress bar lignes horizontale seront utilisés
3175
3225
  }
3176
3226
 
3177
3227
  const styles = StyleSheet.create({
@@ -6,13 +6,12 @@ import React from "$react";
6
6
  import {defaultObj,isNonNullString} from "$utils";
7
7
  import SimpleSelect from "$ecomponents/SimpleSelect";
8
8
  import Provider from "$ecomponents/Dialog/Provider";
9
- import TextField from "$components/TextField";
10
- import Label from "$components/Label";
9
+ import TextField from "$ecomponents/TextField";
10
+ import Label from "$ecomponents/Label";
11
11
  import theme from "$theme";
12
12
  import notify from "$notify";
13
13
  import { View } from "react-native";
14
- import Icon from "$components/Icon";
15
- import PropTypes from "prop-types";
14
+ import Icon from "$ecomponents/Icon";
16
15
 
17
16
  const DateFormatSelector = React.forwardRef((props,ref)=>{
18
17
  return <SimpleSelect ref={ref} {...selectDateFormatFieldProps(props)}/>
@@ -797,7 +797,7 @@ export default class Field extends AppComponent {
797
797
  jsType,
798
798
  fieldToPopulateOnBlur,
799
799
  ...rest
800
- } = this.props;
800
+ } = this.getComponentProps(this.props);
801
801
  if(this.state.caughtAnError){
802
802
  return <ErrorMessage
803
803
  error={this.state.caughtError}
@@ -0,0 +1,39 @@
1
+ import SelectField from "./SelectField";
2
+ import {selectCurrencyFieldProps} from "$ecomponents/SelectCurrency";
3
+ import appConfig from "$app/config";
4
+ import {defaultStr} from "$utils";
5
+
6
+ export default class FormFieldSelectCurrency extends SelectField{
7
+ constructor(props){
8
+ super(props);
9
+ Object.defineProperties(this,{
10
+ currencyFormatRef : {value : {current:defaultStr(appConfig.currencyFormat)}}
11
+ });
12
+ }
13
+ onValidate(args){
14
+ const {context} = args;
15
+ if(context && context.getField){
16
+ const field = context.getField("currencyFormat");
17
+ if(field && field.setValue){
18
+ field.setValue(defaultStr(this.currencyFormatRef.current));
19
+ }
20
+ }
21
+ super.onValidate(args);
22
+ }
23
+ getComponentProps(props){
24
+ this.currencyFormatRef.current = defaultStr(props.currencyFormat,this.currencyFormatRef.current,appConfig.currencyFormat)
25
+ return {...selectCurrencyFieldProps({...props,onChange:(args)=>{
26
+ this.currencyFormatRef.current = defaultStr(args.currencyFormat);
27
+ if(this.props.onChange){
28
+ this.props.onChange(args);
29
+ }
30
+ }})}
31
+ }
32
+ getValidValue(data){
33
+ data.currencyFormat = this.currencyFormatRef.current;
34
+ return super.getValidValue(data);
35
+ }
36
+ }
37
+ FormFieldSelectCurrency.propTypes = {
38
+ ...SelectField.propTypes,
39
+ }
@@ -130,7 +130,9 @@ export default class FormSelectField extends Field{
130
130
  }}
131
131
  onChange = {(args)=>{
132
132
  this.validateWithCallOnChange(args);
133
- if(typeof this.props.onChange =='function'){
133
+ if(typeof props.onChange =='function'){
134
+ props.onChange(args);
135
+ } else if(this.props.onChange =='function'){
134
136
  this.props.onChange(args);
135
137
  }
136
138
  }}
@@ -4,6 +4,7 @@ import SelectField from "./SelectField";
4
4
  import Switch from "./Switch";
5
5
  import Checkbox from "./Checkbox";
6
6
  import SelectTableData from "./SelectTableData";
7
+ import SelectCurrency from "./SelectCurrency";
7
8
  //import IdField from "./IdField";
8
9
  //import PieceField from "./PieceField";
9
10
  import Slider from "./Slider";
@@ -27,7 +28,8 @@ const defFormFields = {
27
28
  TextField,
28
29
  SelectField,
29
30
  SelectTableData,
30
- SelectCountry
31
+ SelectCountry,
32
+ SelectCurrency
31
33
  ,Switch
32
34
  ,Checkbox
33
35
  //,IdField
@@ -58,6 +60,7 @@ export {
58
60
  SelectField,
59
61
  SelectTableData,
60
62
  SelectCountry
63
+ ,SelectCurrency
61
64
  ,Switch
62
65
  ,Checkbox
63
66
  //,IdField
@@ -8,7 +8,6 @@ const componentTypes = {
8
8
  ...Fields,
9
9
  id : Fields.IdField,
10
10
  selecttabledata : Fields.SelectTableData,
11
- select_tabledata : Fields.SelectTableData,
12
11
  idfield : Fields.IdField,
13
12
  piecefield : Fields.PieceField,
14
13
  piece : Fields.PieceField,
@@ -16,6 +15,7 @@ const componentTypes = {
16
15
  switch : Fields.Switch,
17
16
  selectcountry : Fields.SelectCountry,
18
17
  selectdateformat : Fields.SelectDateFormat,
18
+ selectcurrency : Fields.SelectCurrency,
19
19
  dateformat : Fields.SelectDateFormat,
20
20
  date : Fields.Date,
21
21
  time : Fields.Time,
@@ -100,9 +100,11 @@ export const getFilterComponentProps = (_props)=>{
100
100
  component = Fields.ColorPicker;
101
101
  } else if(type == 'dateformat' || type =='select_dateformat' || type =='select_date_format') {
102
102
  component = Fields.SelectDateFormat;
103
- } else if(React.isComponent()) {
103
+ } else if(React.isComponent(componentTypes[type])) {
104
104
  component = componentTypes[type];
105
- }else {
105
+ } else if(React.isComponent(componentTypes[type.replaceAll("_","")])){
106
+ component = componentTypes[type.replaceAll("_","")];
107
+ } else {
106
108
  const tt = type.replaceAll("_","").toLowerCase();
107
109
  if(React.isComponent(componentTypes[tt])){
108
110
  component = componentTypes[tt];
@@ -14,6 +14,7 @@ const OptimizedHeavyScreen = React.forwardRef(({
14
14
  ),
15
15
  style,
16
16
  children,
17
+ isLoading,
17
18
  timeout,
18
19
  testID,
19
20
  transitionTimeout,
@@ -30,7 +31,7 @@ const OptimizedHeavyScreen = React.forwardRef(({
30
31
  style={[{flex:1},style]}
31
32
  ref={React.useMergeRefs(transitionRef,ref)}
32
33
  >
33
- {areInteractionsComplete ? (children) : placeholder}
34
+ {areInteractionsComplete && isLoading !==true ? (children) : placeholder}
34
35
  </Transitioning.View>
35
36
  )
36
37
  });
@@ -46,7 +47,8 @@ OptimizedHeavyScreen.propTypes = {
46
47
  placeholder : PropTypes.oneOfType([
47
48
  PropTypes.node,
48
49
  PropTypes.element,
49
- ])
50
+ ]),
51
+ isLoading : PropTypes.bool,//si l'écan où les données sont en train d'être chargé
50
52
  }
51
53
 
52
54
  OptimizedHeavyScreen.displayName = "OptimizedHeavyScreenComponent";
@@ -0,0 +1,100 @@
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
+ import React from "$react";
5
+ import {defaultObj,defaultStr,isNonNullString} from "$utils";
6
+ import SimpleSelect from "$ecomponents/SimpleSelect";
7
+ import TextField from "$ecomponents/TextField";
8
+ import Icon from "$ecomponents/Icon";
9
+ import {currencies} from "$ccurrency";
10
+ import { Pressable } from "react-native";
11
+ import {styles} from "$theme";
12
+ import appConfig from "$app/config";
13
+
14
+ const CurrencySelector = React.forwardRef((props,ref)=>{
15
+ return <SimpleSelect ref={ref} {...selectCurrencyFieldProps(props)}/>
16
+ });
17
+
18
+ CurrencySelector.displayName = "CurrencySelector";
19
+
20
+ export default CurrencySelector;
21
+
22
+ export const currencyFormatRef = React.createRef(null);
23
+
24
+ /*** onAdd est appelé lorsqu'on ajoute un format personalisé */
25
+ export const selectCurrencyFieldProps = ({right,disabled,readOnly,isFilter,onChange,onBlur,editable,...props})=>{
26
+ const isEditable = disabled !== true && readOnly !== true && editable !== false;
27
+ const currency = appConfig.currency;
28
+ currencyFormatRef.current = defaultStr(currencyFormatRef.current,appConfig.currencyFormat,"%v%s");
29
+ const iconSize = 25;
30
+ return {
31
+ items : currencies,
32
+ getItemValue : ({item})=>item.code,
33
+ renderItem : ({item}) => "["+item.code+"] " +item.name,
34
+ showAdd : false,
35
+ defaultValue : defaultStr(currency.code),
36
+ enableCopy : false,
37
+ ...props,
38
+ isFilter,
39
+ onChange : (args)=>{
40
+ args.currencyFormat = args.format = defaultStr(currencyFormatRef.current)
41
+ if(onChange){
42
+ onChange(args);
43
+ }
44
+ },
45
+ onBlur : (args)=>{
46
+ args.currencyFormat = args.format = defaultStr(currencyFormatRef.current);
47
+ if(onBlur){
48
+ onBlur(args);
49
+ }
50
+ },
51
+ disabled : !isEditable,
52
+ editable : isEditable,
53
+ right : !isEditable || isFilter ? right : (rP)=>{
54
+ const r = typeof right =='function'? right(rP) : right;
55
+ return <>
56
+ <Pressable style={{width:80}}
57
+ onPress = {(e)=>{
58
+ React.stopEventPropagation(e);
59
+ }}
60
+ >
61
+ <TextField
62
+ {...rP}
63
+ affix = {false}
64
+ editable = {isEditable}
65
+ disabled = {disabled}
66
+ readOnly = {readOnly}
67
+ enableCopy = {false}
68
+ contentContainerProps = {{
69
+ style:{height:37,paddingVertical:0,paddingHorizontal:0},
70
+ }}
71
+ mode = {'flat'}
72
+ left = {(p)=>{
73
+ return <Icon
74
+ {...rP}
75
+ {...p}
76
+ size = {iconSize}
77
+ style = {[styles.ml0,styles.mr0,{width:iconSize,height:iconSize}]}
78
+ icon = "alpha-f-box"
79
+ title="Format d'affichage des valeurs numériques : de la forme %v%s ou %v représente la valeur du montant et %s représente la devise : exemple %s%v => $10 et %s %v => 10 $"
80
+ />
81
+ }}
82
+ defaultValue = {currencyFormatRef.current}
83
+ containerProps = {{
84
+ width:70,
85
+ }}
86
+ onChange = {({value})=>{
87
+ currencyFormatRef.current = value;
88
+ }}
89
+ />
90
+ </Pressable>
91
+ {React.isValidElement(r) && r || null}
92
+ </>
93
+ },
94
+ type : 'select',
95
+ }
96
+ }
97
+
98
+ CurrencySelector.propTypes = {
99
+ ...SimpleSelect.propTypes,
100
+ }
@@ -19,7 +19,7 @@ export default function DatabaseStatisticScreen ({withScreen,title:customTitle,c
19
19
  }
20
20
  let content = [];
21
21
  Object.map(tables,(table,index,suffix)=>{
22
- if(isObj(table) && table.databaseStatistic !== false){
22
+ if(isObj(table) && table.databaseStatistic !== false && table.databaseStatistics !== false){
23
23
  content.push(
24
24
  <Cell elevation = {5} withSurface mobileSize={12} desktopSize={3} tabletSize={4} {...contentProps} key = {index} >
25
25
  <DatabaseStatistic
@@ -68,13 +68,14 @@ export default class FormDataLayout extends FormDataActions {
68
68
  preloader,
69
69
  preloaderProps,
70
70
  testID,
71
+ isLoading,
71
72
  } = this.props;
72
73
  wProps = defaultObj(wProps);
73
- const useHeavyScreen = withHeavyScreen !== false ? true : false;
74
+ const useHeavyScreen = withHeavyScreen !== false || isLoading == true? true : false;
74
75
  const Wrapper = useHeavyScreen ? HeavyScreen : React.Fragment;
75
76
  testID = defaultStr(wProps.testID,testID,"RN_FormDataScren");
76
77
  const placeholder = React.isValidElement(preloader)? preloader : <FormLoader {...defaultObj(preloaderProps)}/>;
77
- const wrapperProps = useHeavyScreen ? {...wProps,placeholder,testID:testID+"_HeavyScreen"} : {}
78
+ const wrapperProps = useHeavyScreen ? {...wProps,isLoading,placeholder,testID:testID+"_HeavyScreen"} : {}
78
79
  return <Wrapper {...wrapperProps}>
79
80
  {content}
80
81
  </Wrapper>
@@ -94,6 +95,7 @@ FormDataLayout.propTypes = {
94
95
  withHeavyScreen : PropTypes.bool,
95
96
  withAppBar : PropTypes.bool, ///si l'appBar sera affiché
96
97
  preloader : PropTypes.node,
98
+ isLoading : PropTypes.bool,//Si l'écran est en mode chargement des données
97
99
  preloaderProps : PropTypes.object,
98
100
  header : PropTypes.oneOfType([
99
101
  PropTypes.element,
@@ -1,4 +1,5 @@
1
1
  import {defaultStr,isNumber,isPromise,defaultVal,extendObj,defaultObj,uniqid,isObj,isObjOrArray} from "$utils";
2
+ import stableHash from "stable-hash";
2
3
  import {FormData} from "$ecomponents/Form";
3
4
  import FormDataScreen from "./FormData";
4
5
  import ScreenContainer from "./Screen";
@@ -71,18 +72,8 @@ export const isDocEditing = (data,fields,checkPrimaryKey)=>{
71
72
  export default class TableDataScreenComponent extends FormDataScreen{
72
73
  constructor(props){
73
74
  super(props);
74
- let cDatas = [];
75
75
  const mainProps = getScreenProps(props);
76
- const hasManyData = isObjOrArray(mainProps.datas) && Object.size(mainProps.datas,true) > 0 ? true : false;
77
- if(hasManyData){
78
- cDatas = Object.toArray(mainProps.datas);
79
- }
80
- extendObj(this.state,{
81
- hasManyData,
82
- datas : cDatas,
83
- currentIndex : 0,
84
- data : hasManyData ? defaultObj(cDatas[0]) : isObj(mainProps.data)? mainProps.data : {}
85
- });
76
+ extendObj(this.state,this.prepareStateData(mainProps));
86
77
  const table = defaultObj(mainProps.table);
87
78
  const fields = {},primaryKeyFields = {};
88
79
  Object.map(table.fields,(field,i)=>{
@@ -157,6 +148,20 @@ export default class TableDataScreenComponent extends FormDataScreen{
157
148
  this.hidePreloader = this.hidePreloader.bind(this);
158
149
  this.showPreloader = this.showPreloader.bind(this);
159
150
  };
151
+ prepareStateData(props){
152
+ const mainProps = defaultObj(props,this.props);
153
+ const hasManyData = isObjOrArray(mainProps.datas) && Object.size(mainProps.datas,true) > 0 ? true : false;
154
+ let cDatas = [];
155
+ if(hasManyData){
156
+ cDatas = Object.toArray(mainProps.datas);
157
+ }
158
+ return {
159
+ hasManyData,
160
+ datas : cDatas,
161
+ currentIndex : 0,
162
+ data : hasManyData ? defaultObj(cDatas[0]) : isObj(mainProps.data)? mainProps.data : {}
163
+ };
164
+ }
160
165
  isCurrentDocEditingUpdate(){
161
166
  return this.isDocEditingRef.current === true ? true : false;
162
167
  }
@@ -561,6 +566,14 @@ export default class TableDataScreenComponent extends FormDataScreen{
561
566
  },typeof timeoutCallback =='number'? timeoutCallback : HIDE_PRELOADER_TIMEOUT);
562
567
  return this.hidePreloaderTimeout;
563
568
  }
569
+ UNSAFE_componentWillReceiveProps(nextProps){
570
+ const props = getScreenProps(nextProps);
571
+ const {data,datas}= props;
572
+ if(stableHash({data,datas}) != stableHash({data:this.state.data,datas:this.state.datas})){
573
+ this.setState(this.prepareStateData(props));
574
+ }
575
+ return;
576
+ }
564
577
  reset (args,cb){
565
578
  if(!this._isMounted()) return;
566
579
  clearTimeout(this.timeoutCallback);