@fto-consult/expo-ui 2.31.5 → 2.33.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/appConfig.txt CHANGED
@@ -11,4 +11,9 @@
11
11
 
12
12
  /***les fonctions d'aggregations du datagrid**/
13
13
  datagridAggregatorFunctions : {objectOf({code:{string},label:{string},eval:{function}})|| arrayOf({code:{string},label:{string},eval:{function}})}
14
+ /**l'ensemble des selectors à appliquer au champs de type hashtag, permettant de faire des liens vers d'autres tables**/
15
+ sprintfSelectors : {
16
+ "&libele&" : selectLabel,
17
+ }
18
+ getTableData : {function(tableName)=>table} retourne l'ojet table data
14
19
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fto-consult/expo-ui",
3
- "version": "2.31.5",
3
+ "version": "2.33.0",
4
4
  "description": "Bibliothèque de composants UI Expo,react-native",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -61,7 +61,7 @@
61
61
  "@emotion/native": "^11.10.0",
62
62
  "@expo/html-elements": "^0.2.0",
63
63
  "@expo/vector-icons": "^13.0.0",
64
- "@fto-consult/common": "^1.25.24",
64
+ "@fto-consult/common": "^1.26.0",
65
65
  "@gorhom/portal": "^1.0.14",
66
66
  "@react-native-async-storage/async-storage": "~1.17.3",
67
67
  "@react-native-community/datetimepicker": "6.5.2",
@@ -41,7 +41,11 @@ const ChartComponent = React.forwardRef(({options,style,height,width,chartId:cus
41
41
  destroyChart(chartContext.current);
42
42
  }
43
43
  },[])
44
- return <Chart {...props} ref={ref} chartId={chartId} style={[theme.styles.pb1,style]} options={options} chartContext={chartContext} testID={testID}/>
44
+ if(theme.isDark()){
45
+ options.tooltip = defaultObj(options.tooltip);
46
+ options.tooltip.theme = 'dark';
47
+ }
48
+ return <Chart {...props} ref={ref} chartId={chartId} style={[options.chart.height && {minHeight:options.chart.height},options.chart.width && {minWidth:options.chart.width},theme.styles.p1,style]} options={options} chartContext={chartContext} testID={testID}/>
45
49
  });
46
50
 
47
51
 
@@ -41,6 +41,7 @@ import {DialogProvider} from "$ecomponents/Form/FormData";
41
41
  import Chart,{getMaxSupportedSeriesSize} from "$ecomponents/Chart";
42
42
  import notify from "$cnotify";
43
43
  import FileSystem from "$file-system";
44
+ import sprintf from "$cutils/sprintf";
44
45
 
45
46
  export const donutChart = {
46
47
  isChart : true,
@@ -245,6 +246,7 @@ export default class CommonDatagridComponent extends AppComponent {
245
246
  dateFields : {value : {}},
246
247
  sectionListColumnsSize : {value : {current:0}}, //la taille du nombre d'éléments de section dans les colonnes
247
248
  chartRef : {value : {current:null}},
249
+ chartSeriesNamesColumnsMapping : {value : {}},//le mappage entre les index des series et les colonnes coorespondantes
248
250
  })
249
251
  const sessionAggregator = defaultStr(this.getSessionData("aggregatorFunction")).trim();
250
252
  const aggregatorProps = defaultStr(this.props.aggregatorFunction).trim();
@@ -290,7 +292,7 @@ export default class CommonDatagridComponent extends AppComponent {
290
292
  if(this.canHandleColumnResize()){
291
293
  this.state.columnsWidths = this.preparedColumns.widths;
292
294
  }
293
- this.state.chartConfig = extendObj({},this.getSessionData("chartConfig"),this.props.chartConfig);
295
+ this.state.chartConfig = extendObj(true,{},this.getSessionData("chartConfig"),this.props.chartConfig);
294
296
  if(!("sparkline" in this.state.chartConfig) && this.isDashboard()){
295
297
  this.state.chartConfig.sparkline = true;
296
298
  }
@@ -1265,8 +1267,8 @@ export default class CommonDatagridComponent extends AppComponent {
1265
1267
  isChartRendable(){
1266
1268
  return !this.isPivotDatagrid() && this.hasFootersFields();
1267
1269
  }
1268
- isValidChartConfig(config){
1269
- config = defaultObj(config,this.state.chartConfig);
1270
+ isValidChartConfig(){
1271
+ const config = this.state.chartConfig;
1270
1272
  return isNonNullString(config.x) && isNonNullString(config.y);
1271
1273
  }
1272
1274
  canRenderChart(){
@@ -1402,10 +1404,11 @@ export default class CommonDatagridComponent extends AppComponent {
1402
1404
  }
1403
1405
  }
1404
1406
  return new Promise((resolve,reject)=>{
1407
+ const data = this.getChartConfig();
1405
1408
  DialogProvider.open({
1406
1409
  title : 'Configuration des graphes',
1407
1410
  subtitle : false,
1408
- data : this.getCharConfig(),
1411
+ data,
1409
1412
  fields : {
1410
1413
  x : {
1411
1414
  text : 'Axe des x[horizontal]',
@@ -1435,6 +1438,50 @@ export default class CommonDatagridComponent extends AppComponent {
1435
1438
  items : yItems,
1436
1439
  multiple : true,
1437
1440
  },
1441
+ dataLabels : {
1442
+ type : 'switch',
1443
+ label : "Affich les valeurs",
1444
+ checkedTooltip : "Les étiquettes de valeurs seront affichées sur le graphe",
1445
+ checkedValue : true,
1446
+ uncheckedValue : false,
1447
+ defaultValue : this.isDashboard()? true : false,
1448
+ },
1449
+ showXaxis : {
1450
+ type : "switch",
1451
+ text : "Afficher l'axe des X",
1452
+ type : "switch",
1453
+ checkedValue : true,
1454
+ uncheckedValue : false,
1455
+ defaultValue : !this.isDashboard(),
1456
+ },
1457
+ showYaxis : {
1458
+ type : "switch",
1459
+ text : "Afficher l'axe des Y",
1460
+ type : "switch",
1461
+ checkedValue : true,
1462
+ uncheckedValue : false,
1463
+ defaultValue : !this.isDashboard(),
1464
+ },
1465
+ showLegend : {
1466
+ type : "switch",
1467
+ text : "Afficher la legende",
1468
+ type : "switch",
1469
+ checkedValue : true,
1470
+ uncheckedValue : false,
1471
+ defaultValue : !this.isDashboard(),
1472
+ },
1473
+ width : {
1474
+ type : "number",
1475
+ text : "Largeur du graphe",
1476
+ tooltip : "Définissez la valeur 0 si vous voulez que le graphe occupe toute la largeur de con contenueur",
1477
+ defaultValue : this.getDefaultChartWidth(),
1478
+ },
1479
+ height : {
1480
+ type : "number",
1481
+ text : "Hauteur du graphe",
1482
+ validType : "numberGreaterThan[0]",
1483
+ defaultValue : this.getDefaultChartHeight(),
1484
+ },
1438
1485
  stacked : stackSettings,
1439
1486
  sparkline : {
1440
1487
  type : 'switch',
@@ -1451,6 +1498,12 @@ export default class CommonDatagridComponent extends AppComponent {
1451
1498
  titleColor: {
1452
1499
  text : "Couleur de titre",
1453
1500
  type :"color",
1501
+ format : "hashtag"
1502
+ },
1503
+ fileName : {
1504
+ text : "Nom fichier en téléchargement",
1505
+ format : "hashtag",
1506
+ tooltip : "Veuillez spécifier le nom du fichier du graphe qui sera utilisée lors du téléchargement"
1454
1507
  },
1455
1508
  },
1456
1509
  actions : [
@@ -1473,7 +1526,7 @@ export default class CommonDatagridComponent extends AppComponent {
1473
1526
  })
1474
1527
  })
1475
1528
  }
1476
- getCharConfig(){
1529
+ getChartConfig(){
1477
1530
  return defaultObj(this.state.chartConfig);
1478
1531
  }
1479
1532
  getChartIsRendableArgs(){
@@ -1490,7 +1543,9 @@ export default class CommonDatagridComponent extends AppComponent {
1490
1543
  downloadChart(){
1491
1544
  if(!this.chartRef.current || !this.chartRef.current.dataURI) return Promise.reject({message:'Référence du graphique non valide'});
1492
1545
  return this.chartRef.current.dataURI().then(({ imgURI, blob })=>{
1493
- FileSystem.write({content:imgURI,fileName:"graphe.png",contentType:"image/png"})
1546
+ const config = this.getChartConfig();
1547
+ const fileName = sprintf(defaultStr(config.fileName,config.title,"graphe"));
1548
+ FileSystem.write({content:imgURI,fileName})
1494
1549
  });
1495
1550
  }
1496
1551
  ///reoturne les options de menus à appliquer sur le char
@@ -1582,8 +1637,8 @@ export default class CommonDatagridComponent extends AppComponent {
1582
1637
  }}
1583
1638
  />
1584
1639
  }
1585
- getEmptyDataValue(){
1586
- return "N/A";
1640
+ getEmptySectionListHeaderValue(){
1641
+ return defaultStr(this.props.sectionListHeaderEmptyValue,"N/A");
1587
1642
  }
1588
1643
  /*** retourne les sectionHeaderSeries par défautt */
1589
1644
  getDefaultSectionHeadersSeries(){
@@ -1596,6 +1651,7 @@ export default class CommonDatagridComponent extends AppComponent {
1596
1651
  if(!isObj(footer)) continue;
1597
1652
  if(counter >= max) break;
1598
1653
  r.push(i);
1654
+ counter ++;
1599
1655
  }
1600
1656
  return r;
1601
1657
  }
@@ -1622,13 +1678,12 @@ export default class CommonDatagridComponent extends AppComponent {
1622
1678
 
1623
1679
  const code = aggregatorFunction.code;
1624
1680
  const isDonut = chartType.isDonut || chartType.isRadial;
1625
- const config = this.getCharConfig();
1681
+ const config = this.getChartConfig();
1626
1682
  //@see : https://apexcharts.com/docs/series/
1627
1683
  ///lorsqu'on affiche uniquement les totaux des sections, alors la visualition se fait sur uniquement sur la base des valeurs
1628
1684
  ///on parcoure uniquement les entêtes des sectionLis
1629
1685
  const dataIndexes={},dataInexesNames = {};
1630
1686
  //la variable sectionListHeaderSeries, permet de récupérer les colonnes de type montant à utiliser pour le rendu du chart
1631
- let serieName = "";
1632
1687
  const tableFooters = this.getFootersFields();
1633
1688
  const defaultSectionListHeadersSeries = this.getDefaultSectionHeadersSeries();
1634
1689
  let seriesConfig = isDonut ? [] : Array.isArray(config.sectionListHeadersSeries) && config.sectionListHeadersSeries.length ? config.sectionListHeadersSeries : [];
@@ -1645,6 +1700,7 @@ export default class CommonDatagridComponent extends AppComponent {
1645
1700
  seriesConfig = defaultSectionListHeadersSeries;
1646
1701
  }
1647
1702
  }
1703
+ const seriesNamesMapping = {};
1648
1704
  /**** boucle sur chaque éléments trouvée dans le tableau des données sectionListData */
1649
1705
  const loopForFooter = ({column,serieName,footers,header})=>{
1650
1706
  if(!isObj(column) || !isObj(footers)) return null;
@@ -1652,6 +1708,9 @@ export default class CommonDatagridComponent extends AppComponent {
1652
1708
  const footer = footers[column.field];
1653
1709
  if(typeof footer[code] !== 'number') return null;
1654
1710
  if(typeof footer[code] !== 'number') return null;
1711
+ if(header === this.emptySectionListHeaderValue){
1712
+ header = this.getEmptySectionListHeaderValue();
1713
+ }
1655
1714
  if(isDonut){
1656
1715
  dataIndexes[header] = footer[code];
1657
1716
  } else {
@@ -1663,12 +1722,13 @@ export default class CommonDatagridComponent extends AppComponent {
1663
1722
  if(!isObj(this.sectionListHeaderFooters[header])) return null;
1664
1723
  const footers = this.sectionListHeaderFooters[header];
1665
1724
  if(isDonut){
1666
- loopForFooter({footers,header,column:yAxisColumn})
1725
+ loopForFooter({footers,header,column:yAxisColumn,columnField:yAxisColumn.field})
1667
1726
  } else {
1668
1727
  seriesConfig.map((s)=>{
1669
1728
  const serie = this.state.columns[s];
1670
1729
  const serieName = defaultStr(serie.label,serie.text,s);
1671
- loopForFooter({footers,serie,serieName,header,column:tableFooters[s]})
1730
+ this.chartSeriesNamesColumnsMapping[serieName] = serie;
1731
+ loopForFooter({footers,serie,columnField:s,serieName,header,column:tableFooters[s]})
1672
1732
  })
1673
1733
  }
1674
1734
  });
@@ -1693,6 +1753,12 @@ export default class CommonDatagridComponent extends AppComponent {
1693
1753
  }
1694
1754
  }
1695
1755
  }
1756
+ getDefaultChartHeight(){
1757
+ return defaultNumber(this.props.chartProps?.height,this.isDashboard()?80:350);
1758
+ }
1759
+ getDefaultChartWidth(){
1760
+ return defaultNumber(this.props.chartProps?.width);
1761
+ }
1696
1762
  /*** permet de formatter les valeurs de la courbe en fonction du type passé en paramètre */
1697
1763
  chartValueFormattter(value,columnType){
1698
1764
 
@@ -1707,7 +1773,7 @@ export default class CommonDatagridComponent extends AppComponent {
1707
1773
  return null;
1708
1774
  }
1709
1775
  const isDonut = chartType.isDonut || chartType.isRadial;
1710
- const config = this.getCharConfig();
1776
+ const config = this.getChartConfig();
1711
1777
  if(!this.state.columns[config.y]) return null;
1712
1778
  const yAxisColumn = this.state.columns[config.y];
1713
1779
  const type = defaultStr(yAxisColumn.jsType,yAxisColumn.type).toLowerCase();
@@ -1728,10 +1794,14 @@ export default class CommonDatagridComponent extends AppComponent {
1728
1794
  xAxisColumn = this.state.columns[config.x];
1729
1795
  }
1730
1796
  const aggregatorFunction = this.getActiveAggregatorFunction().eval;
1731
- const emptyValue = this.getEmptyDataValue();
1797
+ const emptyValue = this.getEmptySectionListHeaderValue();
1732
1798
  const indexes = {};
1733
1799
  let series = [],xaxis = {},customConfig = {},seriesNamesToColumns={};
1734
1800
  let count = 0;
1801
+ //on réinitialise le mappage entre les index
1802
+ Object.map(this.chartSeriesNamesColumnsMapping,(_,k)=>{
1803
+ delete this.chartSeriesNamesColumnsMapping[k];
1804
+ });
1735
1805
  if(!this.isSectionList()){
1736
1806
  this.state.data.map((data,index)=>{
1737
1807
  if(!isObj(data))return null;
@@ -1771,6 +1841,7 @@ export default class CommonDatagridComponent extends AppComponent {
1771
1841
  type : chartType.type,
1772
1842
  data,
1773
1843
  })
1844
+ this.chartSeriesNamesColumnsMapping[name] = col;
1774
1845
  })
1775
1846
  } else {
1776
1847
  const configs = this.getSectionListHeadersChartOptions({chartType,aggregatorFunction,xAxisColumn,yAxisColumn});
@@ -1793,8 +1864,25 @@ export default class CommonDatagridComponent extends AppComponent {
1793
1864
  chartProps[settingKey] = defaultObj(chartProps[settingKey]);
1794
1865
  chartProps[settingKey][key] = config[key];
1795
1866
  });
1867
+ const dataLabelFormatter = typeof chartProps.dataLabels?.formatter =="function"? chartProps.dataLabels.formatter : undefined;
1796
1868
  const chartOptions = {
1797
1869
  ...chartProps,
1870
+ dataLabels : extendObj(true,{enabled:!this.isDashboard()},chartProps.dataLabels,{
1871
+ formatter : (value, { seriesIndex, dataPointIndex, w })=> {
1872
+ const serie = w.config.series[seriesIndex];
1873
+ const serieName = serie.name;
1874
+ const column = isDonut ? defaultObj((this.state.columns[yAxisColumn.field],yAxisColumn)): defaultObj(this.chartSeriesNamesColumnsMapping[serieName]);
1875
+ const columnField = defaultStr(column.field, isDonut? config.y : undefined);
1876
+ if(dataLabelFormatter){
1877
+ return dataLabelFormatter({value,column,columnDef:column,columnField,serie,serieName,seriesIndex})
1878
+ }
1879
+ if(typeof value !=='number') return value;
1880
+ if(defaultStr(column.format).toLowerCase() ==='money'){
1881
+ return value.formatMoney();
1882
+ }
1883
+ return value.formatNumber();
1884
+ }
1885
+ }),
1798
1886
  title :extendObj(true,{}, {
1799
1887
  text: defaultStr(config.title,chartProps.title),
1800
1888
  align: 'left',
@@ -1812,8 +1900,12 @@ export default class CommonDatagridComponent extends AppComponent {
1812
1900
  series,
1813
1901
  chart : extendObj(true,{},
1814
1902
  {toolbar : {show : false}},
1815
- {height :this.isDashboard()?80:350},chartProps.chart,
1816
- {type : chartType.type}
1903
+ chartProps.chart,
1904
+ {
1905
+ height : defaultNumber(config.height,this.getDefaultChartHeight()),
1906
+ width : defaultNumber(config.width) || this.getDefaultChartWidth() || undefined,
1907
+ type : chartType.type
1908
+ },
1817
1909
  )
1818
1910
  }
1819
1911
  const labelColor = theme.Colors.isValid(config.labelColor)? config.labelColor : theme.colors.text;
@@ -1826,13 +1918,35 @@ export default class CommonDatagridComponent extends AppComponent {
1826
1918
  delete chartOptions.xaxis;
1827
1919
  //delete chartOptions.yaxis;
1828
1920
  }
1829
- chartOptions.yaxis = extendObj(true,{},{type: 'category'},chartProps.yaxis);
1921
+ chartOptions.yaxis = extendObj(true,{},{type: 'category'},defaultObj(chartProps.yaxis));
1830
1922
  const yLabels = chartOptions.yaxis.labels = defaultObj(chartOptions.yaxis.labels);
1831
1923
  yLabels.style = defaultObj(yLabels.style)
1832
1924
  yLabels.style.colors = (Array.isArray(yLabels.style.colors) && yLabels.style.colors.length || theme.Colors.isValid(yLabels.style.colors)) ? yLabels.style.colors : labelColor;
1925
+ const yLabelsSerieName = series?.length == 1 && series[0] && series[0].name ? series[0].name : undefined;
1926
+ const yLabelsColumn = yLabelsSerieName ? this.chartSeriesNamesColumnsMapping[yLabelsSerieName] : undefined;
1927
+ let yLabelFormat = null;
1928
+ if(!isDonut && !yLabelFormat){
1929
+ for(let i in series){
1930
+ const v = series[i];
1931
+ if(!isObj(v) || !isNonNullString(v.name) || !this.chartSeriesNamesColumnsMapping[v.name]) break;
1932
+ if(yLabelFormat && this.chartSeriesNamesColumnsMapping[v.name]?.format !=yLabelFormat) {
1933
+ yLabelFormat = null;
1934
+ break;
1935
+ }
1936
+ if(!yLabelFormat){
1937
+ yLabelFormat = this.chartSeriesNamesColumnsMapping[v.name]?.format;
1938
+ }
1939
+ }
1940
+ }
1833
1941
  yLabels.formatter = (value)=>{
1834
- if(typeof value =="number") return value.formatNumber();
1835
- return value;
1942
+ if(typeof value !='number') return value;
1943
+ if(yLabelFormat =='money' || (isDonut && yAxisColumn.format =="money")){
1944
+ return value.formatMoney();
1945
+ }
1946
+ if(yLabelsColumn && yLabelsColumn.format =='money'){
1947
+ return value.formatMoney();
1948
+ }
1949
+ return value.formatNumber();
1836
1950
  }
1837
1951
  chartOptions.chart.id = this.chartIdPrefix+"-"+defaultStr(chartType.key,"no-key");
1838
1952
  if(!chartType.isDonut){
@@ -1844,16 +1958,19 @@ export default class CommonDatagridComponent extends AppComponent {
1844
1958
  if(chartOptions.chart.sparkline){
1845
1959
  chartOptions.chart.sparkline = {enabled: true}
1846
1960
  } else delete chartOptions.chart.sparkline;
1847
- if(chartOptions.chart.sparkline && chartOptions.chart.sparkline.enabled){
1848
- chartOptions.xaxis = defaultObj(chartOptions.xaxis);
1849
- chartOptions.xaxis.labels = defaultObj(chartOptions.xaxis.labels);
1850
- chartOptions.xaxis.labels.show = false;
1961
+ //const spackLine = chartOptions.chart.sparkline;
1962
+ chartOptions.xaxis = defaultObj(chartOptions.xaxis);
1963
+ chartOptions.xaxis.labels = defaultObj(chartOptions.xaxis.labels);
1964
+ chartOptions.xaxis.labels.show = ("showXaxis" in config) ? !!config.showXaxis : !this.isDashboard();
1965
+
1966
+ chartOptions.yaxis.labels = defaultObj(chartOptions.yaxis.labels);
1967
+ chartOptions.yaxis.labels.show = ("showYaxis" in config) ? !!config.showYaxis : !this.isDashboard();
1968
+
1969
+ chartOptions.legend = defaultObj(chartOptions.legend);
1970
+ chartOptions.legend.show = ("showLegend" in config) ? !!config.showLegend : !this.isDashboard();
1851
1971
 
1852
- chartOptions.yaxis = defaultObj(chartOptions.yaxis);
1853
- chartOptions.yaxis.labels = defaultObj(chartOptions.yaxis.labels);
1854
- chartOptions.yaxis.labels.show = false;
1855
- chartOptions.legend = defaultObj(chartOptions.legend);
1856
- chartOptions.legend.show = false;
1972
+ if("dataLabels" in config){
1973
+ chartOptions.dataLabels.enabled = !!config.dataLabels;
1857
1974
  }
1858
1975
  return <Chart
1859
1976
  options = {chartOptions}
@@ -1951,7 +2068,7 @@ export default class CommonDatagridComponent extends AppComponent {
1951
2068
  const columns = args.columns || this.state.columns;
1952
2069
  const currentSortedColumn = isObj(args.sortedColumn) && args.sortedColumn.column? args.sortedColumn : defaultObj(this.sortRef.current);
1953
2070
  const visibleColumns = [],headerFilters = [],visibleColumnsNames={};
1954
- const sectionListColumnsMenuItems = [];
2071
+ const sectionListColumnsMenuItems = [],filterableColumnsNames = [];
1955
2072
  const sortable = defaultBool(this.props.sortable,true);
1956
2073
  const sortedColumns = {};
1957
2074
  let sortedColumnsLength = 0;
@@ -2054,6 +2171,7 @@ export default class CommonDatagridComponent extends AppComponent {
2054
2171
  if(colFilter){
2055
2172
  const fCol = defaultObj(this.filters[header.field]);
2056
2173
  this.filters[header.field] = fCol;
2174
+ filterableColumnsNames.push(header.field);
2057
2175
  delete restCol.sortable;
2058
2176
  filterProps = {
2059
2177
  ...restCol,
@@ -2154,6 +2272,7 @@ export default class CommonDatagridComponent extends AppComponent {
2154
2272
  this.preparedColumns.totalWidths = totalWidths;
2155
2273
  this.preparedColumns.sectionListColumns = sectionListColumns;
2156
2274
  this.preparedColumns.sectionListColumnsMenuItems = sectionListColumnsMenuItems;
2275
+ this.preparedColumns.filterableColumnsNames = filterableColumnsNames;
2157
2276
  return this.preparedColumns;
2158
2277
  }
2159
2278
  getPaginatedSelectedRows(data){
@@ -2359,7 +2478,7 @@ export default class CommonDatagridComponent extends AppComponent {
2359
2478
  args.columns = this.preparedColumns.visibleColumns;
2360
2479
  args.columnsNames = this.preparedColumns.visibleColumnsNames;
2361
2480
  const key = item.sectionListHeaderKey;
2362
- const label = key === this.emptySectionListHeaderValue ? defaultStr(this.props.sectionListHeaderEmptyValue,"N/A") : key;
2481
+ const label = key === this.emptySectionListHeaderValue ? this.getEmptySectionListHeaderValue() : key;
2363
2482
  const style = typeof this.props.getSectionListHeaderStyle =='function' ? this.props.getSectionListHeaderStyle(args) : null;
2364
2483
  const cStyle = typeof this.props.getSectionListHeaderContentContainerStyle =="function" ?this.props.getSectionListHeaderContentContainerStyle(args) : undefined;
2365
2484
  const lStyle = typeof this.props.getSectionListHeaderLabelStyle =='function' ? this.props.getSectionListHeaderLabelStyle(args) : null;
@@ -2543,6 +2662,11 @@ export default class CommonDatagridComponent extends AppComponent {
2543
2662
  willConvertFiltersToSQL(){
2544
2663
  return !!defaultVal(this.props.convertFiltersToSQL,willConvertFiltersToSQL());;
2545
2664
  }
2665
+ /*** retourne la liste des colonnes sur lesquelles on peut effectuer un filtre*/
2666
+ getFilterableColumnsNames(){
2667
+ const {filterableColumnsNames} = defaultObj(this.preparedColumns);
2668
+ return Array.isArray(filterableColumnsNames)? filterableColumnsNames : [];
2669
+ }
2546
2670
  /*** récupère les filtres en cours du datagrid
2547
2671
  * @param {boolean} prepare si les filtres seront apprêtés grace à la méthode prepareFilters de $cFilters
2548
2672
  * @param {boolean} convertFiltersToSQL si les filtres seront convertis au formatSQL
@@ -3380,9 +3504,9 @@ CommonDatagridComponent.propTypes = {
3380
3504
  //type : PropTypes.oneOfType(chartDisplayType).isRequired,//le type de graphe : l'une des valeurs parmis les éléments cités plus haut
3381
3505
  x : PropTypes.string.isRequired, //l'axe horizontal
3382
3506
  y : PropTypes.string.isRequired, //l'axe des y, les colonnes de type nombre
3383
- series : PropTypes.arrayOf([PropTypes.string]), //les séries, le nombre de courbe a afficher sur le graphe, en fonction du type
3507
+ series : PropTypes.arrayOf(PropTypes.string), //les séries, le nombre de courbe a afficher sur le graphe, en fonction du type
3384
3508
  /**** les series à utiliser pour l'affichage des données lorsque les colonnes sont groupées, ie les montant de totalisation sont utilisés */
3385
- sectionListHeadersSeries : PropTypes.arrayOf([PropTypes.string]),
3509
+ sectionListHeadersSeries : PropTypes.arrayOf(PropTypes.string),
3386
3510
  }),
3387
3511
  displayType : chartDisplayType,
3388
3512
  /*** les types d'afichates supportés par l'application */
@@ -98,6 +98,7 @@ export default class CommonTableDatagrid extends CommonDatagrid{
98
98
  fetchOptions = extendObj(true,true,{},fetchOptions,{selector : fetchFilters});
99
99
  fetchOptions.dataSources = this.currentDataSources;
100
100
  fetchOptions.sort = this.getSort();
101
+ fetchOptions.fields = this.getFilterableColumnsNames();
101
102
  let limit = this.getQueryLimit();
102
103
  if(limit > 0 && !this.isPivotDatagrid()){
103
104
  fetchOptions.limit = limit;
@@ -0,0 +1,18 @@
1
+ import Format from "$ecomponents/SelectCurrency/Format";
2
+ import TextField from"./TextField";
3
+ export default class CurrencyFormatField extends TextField{
4
+ _render(props,setRef){
5
+ props.onChange = (args)=>{
6
+ this.validate(args);
7
+ }
8
+ return <Format
9
+ {...props}
10
+ setRef = {setRef}
11
+ />
12
+ }
13
+ }
14
+
15
+
16
+ CurrencyFormatField.propTypes = {
17
+ ...TextField.propTypes,
18
+ }
@@ -505,9 +505,9 @@ export default class Field extends AppComponent {
505
505
  }
506
506
  sprintf(){
507
507
  if(this.isDisabled() || this.isReadOnly()) return this;
508
- sprintf({value:this.getValue(),cb:(val)=>{
508
+ sprintf({context:this,value:this.getValue(),formatter:this.props.sprintfResultFormatter}).then((val)=>{
509
509
  this.setValue(APP.sprintf(val),true);
510
- }});
510
+ });
511
511
  }
512
512
  /**** met le focus sur le prochain cham */
513
513
  focusNextField (){
@@ -915,7 +915,7 @@ export default class Field extends AppComponent {
915
915
  right = <Icon color={theme.colors.primary} {...props} tooltip = {tooltip} style={[styles.icon,props.style]} icon="information"/>;
916
916
  }
917
917
  if(canRenderHashtag && !rest.disabled && !rest.readOnly){
918
- const nRight = <Icon {...props} icon={"format-header-pound"} style={[right||cRight?{marginLeft:-5}:null,props.style]} title={"Cliquer insérer un hashtag, ie faire référence à une données de ventes, d'achas, de stocks, de règlement..."} onPress={this.sprintf.bind(this)}/>;
918
+ const nRight = <Icon {...props} icon={"format-header-pound"} style={[right||cRight?{marginLeft:-5}:null,props.style]} title={"Cliquer insérer un hashtag, ie faire référence à une données externe"} onPress={this.sprintf.bind(this)}/>;
919
919
  right = right ? <>{right}{nRight}</> : nRight;
920
920
  }
921
921
  return (cRight)? <>{cRight}{right}</> : right;
@@ -988,6 +988,8 @@ Field.propTypes = {
988
988
  PropTypes.node,
989
989
  PropTypes.func,
990
990
  ]),
991
+ /**** la fonction utilisée pour le formattage des valeurs de type sprintf */
992
+ sprintfResultFormatter : PropTypes.func,
991
993
  jsType : PropTypes.string,
992
994
  usePlaceholderWhenEmpty : PropTypes.bool,//si la valeur du placeholder sera utilée, lorsque la valeur du champ de type formatable est nulle ou égale à la valeur vide
993
995
  responsive : PropTypes.bool,
@@ -1,39 +1,15 @@
1
1
  import SelectField from "./SelectField";
2
2
  import {selectCurrencyFieldProps} from "$ecomponents/SelectCurrency";
3
- import appConfig from "$app/config";
4
- import {defaultStr} from "$utils";
5
3
 
6
4
  export default class FormFieldSelectCurrency extends SelectField{
7
5
  constructor(props){
8
6
  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
7
  }
23
8
  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);
9
+ return {...selectCurrencyFieldProps(props)}
35
10
  }
36
11
  }
12
+
37
13
  FormFieldSelectCurrency.propTypes = {
38
14
  ...SelectField.propTypes,
39
15
  }
@@ -11,6 +11,7 @@ import {getFetchOptions,prepareFilters} from "$cutils/filters";
11
11
  import fetch from "$capi"
12
12
  import {willConvertFiltersToSQL} from "$ecomponents/Datagrid/utils";
13
13
  import React from "$react";
14
+ import appConfig from "$appConfig";
14
15
 
15
16
  /*** la tabledataSelectField permet de faire des requêtes distantes pour rechercher les données
16
17
  * Elle doit prendre en paramètre et de manière requis : les props suivante :
@@ -24,7 +25,8 @@ const TableDataSelectField = React.forwardRef((_props,ref)=>{
24
25
  props.data = defaultObj(props.data);
25
26
  foreignKeyColumn = foreignKeyColumn.trim();
26
27
  convertFiltersToSQL = defaultVal(convertFiltersToSQL,willConvertFiltersToSQL());
27
- const fKeyTable = getForeignKeyTable(foreignKeyTable,props)
28
+ getForeignKeyTable = getForeignKeyTable || appConfig.get("getTableData");
29
+ const fKeyTable = typeof getForeignKeyTable =='function' ? getForeignKeyTable(foreignKeyTable,props) : undefined
28
30
  if(!isObj(fKeyTable) || !(defaultStr(fKeyTable.tableName,fKeyTable.table))){
29
31
  console.error("type de données invalide pour la fKeyTable ",fKeyTable," composant SelectTableData",_props);
30
32
  return null;
@@ -224,7 +226,7 @@ TableDataSelectField.propTypes = {
224
226
  PropTypes.string,
225
227
  PropTypes.func, //s'il s'agit d'une fonciton qui sera appelée
226
228
  ]),
227
- getForeignKeyTable : PropTypes.func.isRequired, //la fonction permettant de récupérer la fKeyTable data dont fait référence le champ
229
+ getForeignKeyTable : PropTypes.func, //la fonction permettant de récupérer la fKeyTable data dont fait référence le champ
228
230
  foreignKeyTable : PropTypes.string, //le nom de la fKeyTable data à laquelle se reporte le champ
229
231
  onFetchItems : PropTypes.func,
230
232
  fetchDataOpts : PropTypes.shape({
@@ -20,7 +20,7 @@ import * as eFormFields from "$extendFormFields";
20
20
  import "$utils";
21
21
  import React from "$react";
22
22
  import SelectDateFormat from "./SelectDateFormat";
23
-
23
+ import CurrencyFormat from "./CurrencyFormat";
24
24
  export * from "$extendFormFields";
25
25
 
26
26
  const defFormFields = {
@@ -30,6 +30,7 @@ const defFormFields = {
30
30
  SelectTableData,
31
31
  SelectCountry,
32
32
  SelectCurrency
33
+ ,CurrencyFormat
33
34
  ,Switch
34
35
  ,Checkbox
35
36
  //,IdField
@@ -61,6 +62,7 @@ export {
61
62
  SelectTableData,
62
63
  SelectCountry
63
64
  ,SelectCurrency
65
+ ,CurrencyFormat
64
66
  ,Switch
65
67
  ,Checkbox
66
68
  //,IdField
@@ -1,7 +1,7 @@
1
1
  import selectors from "./sprintfSelectors";
2
- import {isNonNullString,defaultFunc} from "$utils";
2
+ import {isNonNullString,defaultFunc,isObj,isPromise} from "$utils";
3
3
 
4
- export default ({value,val,cb,success})=>{
4
+ export default ({value,val,formatter,cb,success})=>{
5
5
  val = defaultStr(value,val)
6
6
  if(!isNonNullString(val)){
7
7
  return null;
@@ -16,27 +16,59 @@ export default ({value,val,cb,success})=>{
16
16
  keys.push(i.toUpperCase())
17
17
  }
18
18
  }
19
- let results = {};
19
+ const results = {};
20
20
  let length = keys.length;
21
21
  let index = length;
22
22
  let key = undefined
23
- const next = ()=>{
24
- index -=1;
25
- if(index < 0){
26
- for(let i in results){
27
- let t = selectors[i.toLowerCase()];
28
- let replace = results[i];
29
- let dbName = defaultStr(t.dbName).toLowerCase(), type = defaultStr(t.type).toLowerCase();
30
- if( dbName !== 'struct_data' && type !== 'field' && type !== 'form'){
31
- replace = " #"+defaultStr(t.dbName)+"["+i.ltrim("&").rtrim("&")+"-"+replace+"]".toUpperCase();
23
+ const sKeys = {};
24
+ return new Promise((resolve)=>{
25
+ const next = ()=>{
26
+ index -=1;
27
+ if(index < 0){
28
+ for(let i in results){
29
+ let indexName = i.toLowerCase();
30
+ let selector = selectors[indexName];
31
+ if(!selector){
32
+ indexName = i.toUpperCase();
33
+ selector = selectors[indexName];
34
+ }
35
+ const replace = results[i];
36
+ if(typeof formatter =='function'){
37
+ val = formatter({selectors,selector,value:val,replace,result:results[i],results,indexName,selectorIndex:indexName,selectorName:indexName})
38
+ }
39
+ if(typeof val =='string' && typeof replace =='string'){
40
+ val = val.replaceAll(i,replace);
41
+ }
32
42
  }
33
- val = val.replaceAll(i,replace.toUpperCase());
43
+ val = defaultStr(val);
44
+ cb(val);
45
+ resolve(val);
46
+ } else {
47
+ key = keys[index];
48
+ if(!isNonNullString(key)) {return next();}
49
+ let indexName = i.toLowerCase();
50
+ let selector = selectors[indexName];
51
+ if(!selector){
52
+ indexName = i.toUpperCase();
53
+ selector = selectors[indexName];
54
+ }
55
+ sKeys[i] = indexName;
56
+ const select = isObj(selector)? selector.select : selector;
57
+ if(typeof cb =='function'){
58
+ const v = select({...rest,selector,selectors,indexName,selectorIndex:indexName,selectorName:indexName,results,index:key,keys,key,value:val});
59
+ if(isPromise(v)){
60
+ return v.then((r)=>{
61
+ if(typeof r ==='string'){
62
+ results[key] = r;
63
+ }
64
+ }).finally(next);
65
+ } else if(typeof v =='string' || typeof v =='number'){
66
+ results[key] = v.toString();
67
+ }
68
+ }
69
+ next();
34
70
  }
35
- cb(val);
36
- } else {
37
- key = keys[index];
38
- if(!isNonNullString(key)) {return next();}
39
71
  }
40
- }
41
- next();
72
+ next();
73
+ })
42
74
  }
@@ -1,116 +1,19 @@
1
1
  import Date from "$lib/date";
2
- const selectLabel = {
3
- title : 'Sélectionner un libelé',
4
- table : 'labels',
5
- dbName : 'struct_data',
6
- itemValue : ({item})=>defaultStr(item.label,item.code)
7
- }
2
+ import {defaultObj} from "$utils";
3
+ import appConfig from "$capp/config";
4
+ const sprintfSelectors = defaultObj(appConfig.get("sprintfSelectors"));
8
5
  export default {
9
- "&libele&" : selectLabel,
10
- "&vente&" : {
11
- title : 'Sélectionner une vente',
12
- table : 'sales',
13
- },
14
- "&achat&" : {
15
- title : 'Sélectionner un achat',
16
- table : 'purchases',
17
- },
18
- "&stock&" : {
19
- title : 'Sélectionner stock',
20
- table : 'stocks',
21
- },
22
- "&transfert&" : {
23
- title : 'Sélectionner mouvement de transfert',
24
- table : 'stocks_transfers',
25
- },
26
- "&reglement&" : {
27
- title : 'Sélectionner un règlement',
28
- table : 'payments',
29
- },
30
- "&tiers&" : {
31
- title : 'Sélectionner un tier',
32
- table : 'third_parties',
33
- dbName : 'third_parties',
34
- },
35
- "&projet&" : {
36
- title : 'Sélectionner un projet',
37
- table : 'projects',
38
- dbName : 'projects',
39
- },
40
- "&tache&" : {
41
- title : 'Sélectionner une tâche',
42
- table : 'tasks',
43
- dbName : 'projects',
44
- },
45
- "&commercial&" : {
46
- title : 'Sélectionner commercial',
47
- table : 'users',
48
- dbName : 'users',
49
- fetchDataOpts:{
50
- selector : {$and:[{isSeller:1}]}
51
- }
52
- },
53
- "&client&" : {
54
- title : 'Sélectionner client',
55
- table : 'third_parties',
56
- dbName : 'third_parties',
57
- fetchDataOpts:{
58
- selector : {$and:[{type:{$in:["customer"]}}]}
59
- }
60
- },
61
- "&fournisseur&" : {
62
- title : 'Sélectionner Fournisseur',
63
- table : 'third_parties',
64
- dbName : 'third_parties',
65
- fetchDataOpts:{
66
- selector : {$and:[{type:{$in:["provider"]}}]}
67
- }
68
- },
69
- "&utilisateur&" : {
70
- title : 'Sélectionner un utilisateur',
71
- table : 'users',
72
- dbName : 'users',
73
- },
74
- "&caisse&" : {
75
- title : 'Sélectionner une caisse',
76
- table : 'checkouts',
77
- dbName : 'common',
78
- },
79
- "&produit&" : {
80
- title : 'Sélectionner un produit/article',
81
- table : 'products',
82
- dbName : 'products',
83
- },
84
- "&categorie&" : {
85
- title : 'Sélectionner une catégorie de produit',
86
- table : 'products_categories',
87
- dbName : 'products',
88
- },
89
- "&taxe&" : {
90
- title : 'Sélectionner une taxe',
91
- table : 'taxes',
92
- dbName : 'common',
93
- },
94
- "&depot&" : {
95
- title : 'Sélectionner un dépôt',
96
- table : 'warehouses',
97
- dbName : 'common',
98
- },
99
- "&contact&" : {
100
- title : 'Sélectionner un contact',
101
- table : 'contacts',
102
- dbName : 'common',
103
- },
6
+ ...sprintfSelectors,
104
7
  "&sdate&" : {
105
8
  title : 'Sélectionner une date',
106
9
  type : 'field',
107
10
  field : {
108
- type : 'date',
109
- text : 'Sélectionner une date',
110
- format : Date.defaultDateFormat
11
+ type : 'date',
12
+ text : 'Sélectionner une date',
13
+ format : Date.defaultDateFormat
111
14
  },
112
15
  desc : "remplace le motif par la date qui sera sélectionnée par l'utilisateur au format jj/mm/aaaa",
113
- },
16
+ },
114
17
  "&date&" : "remplace le motif par la date actuelle au format : jj/mm/aaaa",
115
18
  "&heure&" : "remplace le motif par l'heure actuelle au format hh:mm:ss",
116
19
  "&dateheure&" : "remplace le motif par la date et l'heure actuelle au format : jj/mm/aaaa hh:mm:ss",
@@ -16,6 +16,8 @@ const componentTypes = {
16
16
  selectcountry : Fields.SelectCountry,
17
17
  selectdateformat : Fields.SelectDateFormat,
18
18
  selectcurrency : Fields.SelectCurrency,
19
+ currencyformat : Fields.CurrencyFormat,
20
+ currencyFormat : Fields.CurrencyFormat,
19
21
  dateformat : Fields.SelectDateFormat,
20
22
  date : Fields.Date,
21
23
  time : Fields.Time,
@@ -0,0 +1,27 @@
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 TextField from "$components/TextField";
6
+ import appConfig from "$capp/config";
7
+ import {isNonNullString,defaultStr} from "$cutils";
8
+
9
+ const CurrencyFormat = React.forwardRef((props,ref)=>{
10
+ const defaultValue = isNonNullString(props.defaultValue) && props.defaultValue.contains("v" && props.defaultValue || defaultStr(appConfig.currencyFormat,"%v %s"))
11
+ return <TextField
12
+ affix = {false}
13
+ enableCopy = {false}
14
+ {...props}
15
+ defaultValue = {defaultValue}
16
+ ref = {ref}
17
+ 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 $"
18
+ />
19
+ });
20
+
21
+ CurrencyFormat.displayName = "CurrencyFormatComponent";
22
+
23
+ export default CurrencyFormat;
24
+
25
+ CurrencyFormat.propTypes = {
26
+ ...TextField.propTypes
27
+ }
@@ -2,32 +2,25 @@
2
2
  // Use of this source code is governed by a BSD-style
3
3
  // license that can be found in the LICENSE file.
4
4
  import React from "$react";
5
- import {defaultObj,defaultStr,isNonNullString} from "$utils";
5
+ import {defaultStr} from "$utils";
6
6
  import SimpleSelect from "$ecomponents/SimpleSelect";
7
- import TextField from "$ecomponents/TextField";
8
- import Icon from "$ecomponents/Icon";
9
7
  import {currencies} from "$ccurrency";
10
- import { Pressable } from "react-native";
11
- import {styles} from "$theme";
12
8
  import appConfig from "$app/config";
13
- import PropTypes from "prop-types";
9
+ import Format from "./Format";
14
10
 
15
11
  const CurrencySelector = React.forwardRef((props,ref)=>{
16
12
  return <SimpleSelect ref={ref} {...selectCurrencyFieldProps(props)}/>
17
13
  });
18
14
 
15
+ export {Format};
19
16
  CurrencySelector.displayName = "CurrencySelector";
17
+ CurrencySelector.Format = Format;
20
18
 
21
19
  export default CurrencySelector;
22
20
 
23
- export const currencyFormatRef = React.createRef(null);
24
-
25
- /*** onAdd est appelé lorsqu'on ajoute un format personalisé */
26
- export const selectCurrencyFieldProps = ({right,disabled,readOnly,onFormatChange,isFilter,onChange,onBlur,editable,...props})=>{
21
+ export const selectCurrencyFieldProps = ({disabled,readOnly,isFilter,editable,...props})=>{
27
22
  const isEditable = disabled !== true && readOnly !== true && editable !== false;
28
23
  const currency = appConfig.currency;
29
- currencyFormatRef.current = defaultStr(currencyFormatRef.current,appConfig.currencyFormat,"%v %s");
30
- const iconSize = 25;
31
24
  return {
32
25
  items : currencies,
33
26
  getItemValue : ({item})=>item.code,
@@ -37,69 +30,12 @@ export const selectCurrencyFieldProps = ({right,disabled,readOnly,onFormatChange
37
30
  enableCopy : false,
38
31
  ...props,
39
32
  isFilter,
40
- onChange : (args)=>{
41
- args.currencyFormat = args.format = defaultStr(currencyFormatRef.current)
42
- if(onChange){
43
- onChange(args);
44
- }
45
- },
46
- onBlur : (args)=>{
47
- args.currencyFormat = args.format = defaultStr(currencyFormatRef.current);
48
- if(onBlur){
49
- onBlur(args);
50
- }
51
- },
52
33
  disabled : !isEditable,
53
34
  editable : isEditable,
54
- right : !isEditable || isFilter ? right : (rP)=>{
55
- const r = typeof right =='function'? right(rP) : right;
56
- return <>
57
- <Pressable style={{width:80}}
58
- onPress = {(e)=>{
59
- React.stopEventPropagation(e);
60
- }}
61
- >
62
- <TextField
63
- {...rP}
64
- affix = {false}
65
- editable = {isEditable}
66
- disabled = {disabled}
67
- readOnly = {readOnly}
68
- enableCopy = {false}
69
- contentContainerProps = {{
70
- style:{height:37,paddingVertical:0,paddingHorizontal:0},
71
- }}
72
- mode = {'flat'}
73
- left = {(p)=>{
74
- return <Icon
75
- {...rP}
76
- {...p}
77
- size = {iconSize}
78
- style = {[styles.ml0,styles.mr0,{width:iconSize,height:iconSize}]}
79
- icon = "alpha-f-box"
80
- 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 $"
81
- />
82
- }}
83
- defaultValue = {currencyFormatRef.current}
84
- containerProps = {{
85
- width:70,
86
- }}
87
- onChange = {(args)=>{
88
- currencyFormatRef.current = args.value;
89
- if(typeof onFormatChange =="function"){
90
- onFormatChange(args)
91
- }
92
- }}
93
- />
94
- </Pressable>
95
- {React.isValidElement(r) && r || null}
96
- </>
97
- },
98
35
  type : 'select',
99
36
  }
100
37
  }
101
38
 
102
39
  CurrencySelector.propTypes = {
103
40
  ...SimpleSelect.propTypes,
104
- onFormatChange : PropTypes.func,//lorsque le format de la currency change
105
41
  }
@@ -16,7 +16,7 @@ import {Menu} from "$ecomponents/BottomSheet";
16
16
  import Dashboard from "$ecomponents/Datagrid/Dashboard";
17
17
  import fetch from "$capi/fetch";
18
18
  import Auth from "$auth";
19
- import Footer from "$ecomponents/Datagrid/Footer/Footer";
19
+ import Icon from "$ecomponents/Icon";
20
20
 
21
21
  export default function DatabaseStatisticContainer ({dashboardProps,fetchDataProps,table,fetchCount,index,testID,title,icon,onPress:customOnPress,columns,fetchData,withDashboard,...props}){
22
22
  dashboardProps = defaultObj(dashboardProps);
@@ -27,7 +27,7 @@ export default function DatabaseStatisticContainer ({dashboardProps,fetchDataPro
27
27
  table = defaultObj(table);
28
28
  const dbStatistics = defaultObj(table.databaseStatistics,table.databaseStatisticsProps);
29
29
  const databaseStatisticsFields = defaultObj(table.databaseStatisticsFields);
30
- const hasDFields = Object.size(databaseStatisticsFields,true);
30
+ const hasDFields = table.databaseStatistics !== false && Object.size(databaseStatisticsFields,true);
31
31
  if(!withDashboard && hasDFields){
32
32
  withDashboard = true;
33
33
  }
@@ -39,7 +39,9 @@ export default function DatabaseStatisticContainer ({dashboardProps,fetchDataPro
39
39
  columns = Object.size(columns,true)? columns : Object.size(dFields,true)? dFields : table.fields;
40
40
  const tableName = defaultStr(table.tableName,table.table).toUpperCase();
41
41
  fetchCount = typeof table.fetchCount =='function'? table.fetchCount : typeof fetchCount =='function'? fetchCount : undefined;
42
- if((!fetchCount && !withDashboard) || !tableName) return null;
42
+ if((!fetchCount && !withDashboard) || !tableName) {
43
+ return null
44
+ }
43
45
  const refreshingRef = React.useRef(null);
44
46
  const isMounted = React.useIsMounted();
45
47
 
@@ -76,7 +78,7 @@ export default function DatabaseStatisticContainer ({dashboardProps,fetchDataPro
76
78
  }
77
79
  }
78
80
  },[]);
79
- const progressBar = <View style={[theme.styles.justifyContentFlexStart,theme.styles.alignItemsFlexStart]}>
81
+ const progressBar = <View style={[theme.styles.justifyContentFlexStart,theme.styles.p1,theme.styles.alignItemsFlexStart]}>
80
82
  <ActivityIndicator color={theme.colors.primary}/>
81
83
  </View>;
82
84
  const isDatagridLoading = datagridRef.current && datagridRef.current.isLoading && datagridRef.current.isLoading();
@@ -90,7 +92,7 @@ export default function DatabaseStatisticContainer ({dashboardProps,fetchDataPro
90
92
  const fetchFields = React.useCallback(()=>{
91
93
  const fetchFields = [];
92
94
  Object.map(columns,(field,f)=>{
93
- const ff = defaultStr(isObj(field)? field.field: undefined,f);
95
+ const ff = defaultStr(isObj(field) && field.filter !== false? field.field: undefined,f);
94
96
  if(ff){
95
97
  fetchFields.push(ff);
96
98
  }
@@ -112,7 +114,7 @@ export default function DatabaseStatisticContainer ({dashboardProps,fetchDataPro
112
114
  sessionName = {tableName+"-database-statistics"}
113
115
  {...props}
114
116
  {...dbStatistics}
115
- style = {[theme.styles.ph1,props.style]}
117
+ style = {[theme.styles.pr1,props.style]}
116
118
  columns = {columns}
117
119
  ref = {datagridRef}
118
120
  progressBar = {isLoading?<View/>:<View style={[theme.styles.w100,theme.styles.alignItemsCenter,theme.styles.justifyContentCenter]}>{progressBar}</View>}
@@ -138,6 +140,7 @@ export default function DatabaseStatisticContainer ({dashboardProps,fetchDataPro
138
140
  return <Pressable onPress={onPress} testID={testID+"_TitleContainer"} style={[theme.styles.w100]}>
139
141
  <View testID={testID+"_TitleCountUp"} style={[theme.styles.w100]}>
140
142
  <View style={[theme.styles.w100,theme.styles.row,theme.styles.alignItemsCenter]}>
143
+ <Icon style={[theme.styles.noPadding,theme.styles.noMargin]} suffix={index} icon= {icon} size={20} label={title}/>
141
144
  {title}
142
145
  {typeof dataSize =='number' && dataSize && <Label>
143
146
  {dataSize.formatNumber()}
@@ -146,7 +149,7 @@ export default function DatabaseStatisticContainer ({dashboardProps,fetchDataPro
146
149
  <Menu
147
150
  testID={testID+"_Menu"}
148
151
  items = {context.renderMenu()}
149
- anchor = {(p)=><Pressable {...p} testID={testID+"_MenuAnchor"}>
152
+ anchor = {(p)=><Pressable {...p} style={[theme.styles.pl1]} testID={testID+"_MenuAnchor"}>
150
153
  <Label
151
154
  textCenter
152
155
  style = {counUpStyle}
@@ -20,31 +20,31 @@ export default function DatabaseStatisticScreen ({withScreen,fetchDataProps,tabl
20
20
  let content = [];
21
21
  tableFilter = typeof tableFilter ==="function"? tableFilter : x=>true;
22
22
  Object.map(tables,(table,index,suffix)=>{
23
- const t = typeof getTable =='function'?getTable(defaultStr(table?.tableName,table?.table,index)) : null;
23
+ if(!isObj(table)) return null;
24
+ let tableName = defaultStr(table.tableName,table.table);
25
+ if(!tableName || tableFilter({table,tableName}) === false) return null;
26
+ const t = typeof getTable =='function'?getTable(defaultStr(table?.tableName,table?.table,index),table) :null;
24
27
  if(isObj(t) && defaultStr(t.table,t.tableName)){
25
- table = t;
26
- }
27
- if(isObj(table) && table.databaseStatistic !== false && table.databaseStatistics !== false && tableFilter(table) !== false){
28
- content.push(
29
- <Cell elevation = {5} withSurface mobileSize={12} desktopSize={3} tabletSize={4} {...contentProps} key = {index} >
30
- <DatabaseStatistic
31
- icon = {table.icon}
32
- key = {index}
33
- table = {table}
34
- fetchData = {fetchData}
35
- fetchDataProps = {fetchDataProps}
36
- index = {suffix}
37
- title = {defaultStr(table.text,table.label,table.title)}
38
- fetchCount = {table.fetchCount|| typeof fetchCount =='function'? (a,b)=>{
39
- return fetchCount({table,tableName:defaultStr(table.tableName,table.table)})
40
- }:undefined}
41
- ></DatabaseStatistic>
42
- </Cell>
43
- )
28
+ table = t;
44
29
  }
30
+ if(table.databaseStatistic === false || table.databaseStatistics === false) return null;
31
+ content.push(<Cell elevation = {5} withSurface mobileSize={12} desktopSize={3} tabletSize={4} {...contentProps} key = {index} >
32
+ <DatabaseStatistic
33
+ icon = {table.icon}
34
+ key = {index}
35
+ table = {table}
36
+ fetchData = {fetchData}
37
+ fetchDataProps = {fetchDataProps}
38
+ index = {suffix}
39
+ title = {defaultStr(table.text,table.label,table.title)}
40
+ fetchCount = {table.fetchCount|| typeof fetchCount =='function'? (a,b)=>{
41
+ return fetchCount({table,tableName})
42
+ }:undefined}
43
+ ></DatabaseStatistic>
44
+ </Cell>
45
+ )
45
46
  });
46
47
  if(!content.length) {
47
- Auth.showError();
48
48
  return null;
49
49
  }
50
50
  content = <Component {...containerProps} style={[containerProps.style,theme.styles.mr1,theme.styles.ml1]}>