@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 +5 -0
- package/package.json +2 -2
- package/src/components/Chart/index.js +5 -1
- package/src/components/Datagrid/Common/Common.js +156 -32
- package/src/components/Datagrid/Common/TableData.js +1 -0
- package/src/components/Form/Fields/CurrencyFormat.js +18 -0
- package/src/components/Form/Fields/Field.js +5 -3
- package/src/components/Form/Fields/SelectCurrency.js +2 -26
- package/src/components/Form/Fields/SelectTableData/Component.js +4 -2
- package/src/components/Form/Fields/index.js +3 -1
- package/src/components/Form/Fields/sprintf.js +51 -19
- package/src/components/Form/Fields/sprintfSelectors.js +8 -105
- package/src/components/Form/FormData/componentsTypes.js +2 -0
- package/src/components/SelectCurrency/Format.js +27 -0
- package/src/components/SelectCurrency/index.js +5 -69
- package/src/layouts/DatabaseStatistics/DatabaseStatistic.js +10 -7
- package/src/layouts/DatabaseStatistics/index.js +21 -21
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.
|
|
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.
|
|
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
|
-
|
|
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(
|
|
1269
|
-
config =
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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
|
-
|
|
1816
|
-
{
|
|
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
|
|
1835
|
-
|
|
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
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
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
|
-
|
|
1853
|
-
chartOptions.
|
|
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 ?
|
|
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(
|
|
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(
|
|
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(),
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
19
|
+
const results = {};
|
|
20
20
|
let length = keys.length;
|
|
21
21
|
let index = length;
|
|
22
22
|
let key = undefined
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
let
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
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
|
|
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
|
-
|
|
72
|
+
next();
|
|
73
|
+
})
|
|
42
74
|
}
|
|
@@ -1,116 +1,19 @@
|
|
|
1
1
|
import Date from "$lib/date";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
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
|
-
|
|
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
|
-
"®lement&" : {
|
|
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
|
-
|
|
109
|
-
|
|
110
|
-
|
|
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 {
|
|
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
|
|
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
|
|
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
|
|
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)
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
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]}>
|