@fto-consult/expo-ui 8.16.0 → 8.17.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/package.json +4 -3
- package/src/components/Datagrid/Common/Common.js +7 -5
- package/src/components/Datagrid/Common/utils.js +18 -18
- package/src/components/Datagrid/SWRDatagrid.js +8 -3
- package/src/components/Dropdown/index.js +2 -1
- package/src/components/Dropdown/utils.js +1 -1
- package/src/components/Form/Fields/Field.js +21 -16
- package/src/components/Form/Fields/SelectField.js +1 -7
- package/src/components/Form/Fields/SelectFontIcon.js +1 -6
- package/src/components/Form/Fields/SelectStructData.js +1 -6
- package/src/components/Form/Fields/SelectTableData/Component.js +32 -39
- package/src/components/Form/Fields/SelectTableData/index.js +1 -6
- package/src/components/Preloader/index.js +4 -1
- package/src/context/hooks.js +1 -0
- package/src/screens/Help/openLibraries.js +5 -9
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@fto-consult/expo-ui",
|
3
|
-
"version": "8.
|
3
|
+
"version": "8.17.0",
|
4
4
|
"description": "Bibliothèque de composants UI Expo,react-native",
|
5
5
|
"scripts": {
|
6
6
|
"clear-npx-cache": "npx clear-npx-cache",
|
@@ -70,7 +70,8 @@
|
|
70
70
|
"dependencies": {
|
71
71
|
"@emotion/react": "^11.11.1",
|
72
72
|
"@faker-js/faker": "^8.0.2",
|
73
|
-
"@fto-consult/common": "^4.
|
73
|
+
"@fto-consult/common": "^4.18.3",
|
74
|
+
"@fto-consult/expo-ui": "^8.16.0",
|
74
75
|
"@fto-consult/node-utils": "^1.4.7",
|
75
76
|
"apexcharts": "^3.45.2",
|
76
77
|
"commander": "^11.1.0",
|
@@ -92,7 +93,7 @@
|
|
92
93
|
"react-native-paper": "^5.12.3",
|
93
94
|
"react-native-paper-dates": "^0.21.7",
|
94
95
|
"react-native-web": "^0.19.10",
|
95
|
-
"react-virtuoso": "^4.6.
|
96
|
+
"react-virtuoso": "^4.6.3",
|
96
97
|
"readable-stream": "^4.5.2",
|
97
98
|
"sanitize-filename": "^1.6.3",
|
98
99
|
"sharp-cli": "^2.1.0",
|
@@ -731,7 +731,9 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
731
731
|
const rowKeysColumns = {};
|
732
732
|
Object.mapToArray(columns,(headerCol1,headerIndex)=>{
|
733
733
|
if(!isObj(headerCol1)) return;
|
734
|
-
const
|
734
|
+
const hClone = Object.clone(headerCol1);
|
735
|
+
const header = isObj(hClone.datagrid) ? extendObj(true,{},hClone,hClone.datagrid) : hClone;
|
736
|
+
//delete header.render;
|
735
737
|
header.field = defaultStr(header.field, headerIndex)
|
736
738
|
if(header.primaryKey){
|
737
739
|
rowKeysColumns[header.field] = true;
|
@@ -1825,7 +1827,7 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
1825
1827
|
return this.SetExportOptions({excel:false,pdf:true}).then((opts)=>{
|
1826
1828
|
const {data,config:cConfig,pdfConfig} = opts;
|
1827
1829
|
const config = extendObj({},pdfConfig,cConfig);
|
1828
|
-
data[0] = createTableHeader(data[0],{
|
1830
|
+
data[0] = createTableHeader(data[0],{filter:(a)=>{
|
1829
1831
|
return true;
|
1830
1832
|
}});
|
1831
1833
|
const pT = defaultStr(config.pdfDocumentTitle).trim();
|
@@ -2124,7 +2126,7 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
2124
2126
|
* @param {object} chartType le type de chart, l'un des types du tableau displayTypes en haut du présent fichier
|
2125
2127
|
* @param {object} yAxisColumn la colonne de l'axe vertical y
|
2126
2128
|
* @param {object} xAxisColumn la colonne de l'axe des x de la courbe, pris dans les configurations du chart, config
|
2127
|
-
* @param {object} la fonction d'aggrégation, l'une des fonctions issues des fonctions d'aggrégations aggregatorsFuncions, @see : dans $
|
2129
|
+
* @param {object} la fonction d'aggrégation, l'une des fonctions issues des fonctions d'aggrégations aggregatorsFuncions, @see : dans $components/Datagrid/Footer
|
2128
2130
|
* en affichage des tableaux de type sectionList, seul les colonnes de totalisation sont utilisées pour l'affichage du graphe
|
2129
2131
|
* Le nombre de graphes (series) à afficher est valable pour tous les graphes sauf les graphes de type pie/donut.
|
2130
2132
|
* il est récupéré dans la variable chartConfig des configuration du chart, où par défaut le nombre de colonnes de totalisation des tableau (inférieur au nombre maximum de courbes surpportées par appexchart)
|
@@ -3572,8 +3574,8 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
3572
3574
|
return rr;
|
3573
3575
|
}
|
3574
3576
|
}
|
3575
|
-
const rkey = React.getKeyFromObj(row,
|
3576
|
-
if(rkey){
|
3577
|
+
const rkey = React.getKeyFromObj(row,rowKey);
|
3578
|
+
if(rkey && (typeof rkey =="number" || typeof rkey =="string")){
|
3577
3579
|
return rkey;
|
3578
3580
|
}
|
3579
3581
|
if(isNonNullString(rowKey) && isObj(row) && (isNonNullString(row[rowKey]) || isDecimal(row[rowKey]))){
|
@@ -32,44 +32,44 @@ export const renderRowCell = (arg)=>{
|
|
32
32
|
const extra = {style},renderArgs = arg;
|
33
33
|
renderArgs.extra = extra;
|
34
34
|
renderArgs.item = rowData;
|
35
|
-
|
35
|
+
renderArgs.defaultValue = renderArgs.value = rowData[columnField];
|
36
36
|
let key = getRowKey.call(context,rowData,rowIndex)+"-"+columnField;
|
37
37
|
if(isObj(columnDef.datagrid) && isFunction(columnDef.datagrid.render)){
|
38
38
|
_render = columnDef.datagrid.render.call(context,renderArgs);
|
39
39
|
} else if(isFunction(columnDef.multiplicater)){
|
40
40
|
_render = defaultDecimal(columnDef.multiplicater({...renderArgs,value:rowData[columnField]}),rowData[columnField]);
|
41
|
-
}
|
42
|
-
|
41
|
+
}
|
42
|
+
const cellValue = defaultVal(_render,rowData[columnField]);
|
43
|
+
{
|
44
|
+
_render = cellValue;
|
43
45
|
if(!renderText && defaultStr(columnDef.format).toLowerCase() === 'hashtag'){
|
44
|
-
|
45
|
-
} else if(typeof columnDef.render === "function"){
|
46
|
-
_render = columnDef.render.call(context,renderArgs);
|
46
|
+
_render = <Hashtag>{_render}</Hashtag>
|
47
47
|
} else if(arrayValueExists( _type,["date","datetime","time"])){
|
48
|
-
if(
|
48
|
+
if(cellValue){
|
49
49
|
const sqlFormat =_type === 'time'? undefined : _type ==="datetime" ? DateLib.SQLDateTimeFormat : DateLib.SQLDateFormat;
|
50
|
-
let _dd =DateLib.parse(
|
50
|
+
let _dd =DateLib.parse(cellValue,sqlFormat);
|
51
51
|
if(DateLib.isDateObj(_dd)){
|
52
52
|
const eFormat = defaultStr(columnDef.format,(_type === 'time'?DateLib.defaultTimeFormat:_type=="datetime"? DateLib.defaultDateTimeFormat:DateLib.masks.defaultDate));
|
53
53
|
_render = DateLib.format(_dd,eFormat);
|
54
54
|
}
|
55
55
|
}
|
56
|
-
if(!_render) _render =
|
56
|
+
if(!_render) _render = cellValue
|
57
57
|
} else if(arrayValueExists(_type,['switch','checkbox'])){
|
58
58
|
let {checkedLabel,checkedValue,uncheckedLabel,uncheckedValue} = columnDef;
|
59
59
|
checkedLabel = defaultStr(checkedLabel,'Oui')
|
60
60
|
uncheckedLabel = defaultStr(uncheckedLabel,'Non')
|
61
61
|
checkedValue = defaultVal(checkedValue,1); uncheckedValue = defaultVal(uncheckedValue,0)
|
62
|
-
let val = defaultVal(
|
63
|
-
if(val
|
62
|
+
let val = defaultVal(cellValue,columnDef.defaultValue,columnDef.value)
|
63
|
+
if(val == checkedValue){
|
64
64
|
_render = checkedLabel;
|
65
65
|
} else _render = uncheckedLabel;
|
66
66
|
}
|
67
67
|
else if(!renderText && (_type =='selectcountry')){
|
68
|
-
_render = <Flag withCode {...columnDef} length={undefined} width={undefined} height={undefined} code={
|
68
|
+
_render = <Flag withCode {...columnDef} length={undefined} width={undefined} height={undefined} code={cellValue}/>
|
69
69
|
}
|
70
70
|
///le lien vers le table data se fait via la colonne ayant la propriété foreignKeyTable de type chaine de caractère non nulle
|
71
71
|
else if(!renderText && (isNonNullString(columnDef.foreignKeyTable) || columnDef.primaryKey === true || arrayValueExists(['id','piece'],_type))){
|
72
|
-
const id =
|
72
|
+
const id = defaultStr(cellValue,typeof cellValue ==="number" ? String(cellValue) : undefined)?.toString();
|
73
73
|
if(isNonNullString(id) || typeof id ==='number'){
|
74
74
|
const foreignKeyTable = defaultStr(columnDef.foreignKeyTable,columnDef.table,columnDef.tableName);
|
75
75
|
const foreignKeyColumn = defaultStr(columnDef.foreignKeyColumn,columnDef.field);
|
@@ -100,7 +100,7 @@ export const renderRowCell = (arg)=>{
|
|
100
100
|
hasC = true;
|
101
101
|
renderedItems++;
|
102
102
|
const suffix = renderedItems === maxItemsToRender && idSplit.length > maxItemsToRender ? <Label>...et {" "+idSplit.length.formatNumber()+" de plus"}</Label> : null;
|
103
|
-
return suffix ?
|
103
|
+
return suffix ? <React.Fragment key={index}>
|
104
104
|
<TableLink
|
105
105
|
key = {index}
|
106
106
|
{...rProps}
|
@@ -109,7 +109,7 @@ export const renderRowCell = (arg)=>{
|
|
109
109
|
{sep2+idd}
|
110
110
|
</TableLink>
|
111
111
|
{suffix}
|
112
|
-
|
112
|
+
</React.Fragment> : <TableLink
|
113
113
|
key = {index}
|
114
114
|
{...rProps}
|
115
115
|
id = {idd}
|
@@ -137,11 +137,11 @@ export const renderRowCell = (arg)=>{
|
|
137
137
|
columnDef.size = defaultDecimal(columnDef.size,50);
|
138
138
|
columnDef.readOnly = defaultBool(columnDef.readOnly,true)
|
139
139
|
columnDef.rounded = defaultBool(columnDef.rounded,columnDef.round,true);
|
140
|
-
columnDef.src =
|
140
|
+
columnDef.src = cellValue;
|
141
141
|
_render = <Image {...columnDef}/>
|
142
142
|
}
|
143
143
|
if(_render === undefined || _render ===null){
|
144
|
-
_render =
|
144
|
+
_render = cellValue;
|
145
145
|
}
|
146
146
|
if(columnDef.type =="password" && isNonNullString(_render)){
|
147
147
|
let l = Math.max(_render.length,20);
|
@@ -155,7 +155,7 @@ export const renderRowCell = (arg)=>{
|
|
155
155
|
}
|
156
156
|
}
|
157
157
|
if(_render ===undefined){
|
158
|
-
_render =
|
158
|
+
_render = cellValue;
|
159
159
|
}
|
160
160
|
if(isArray(_render)){
|
161
161
|
_render = _render.join(arrayValueSeparator);
|
@@ -25,6 +25,7 @@ import PropTypes from "prop-types";
|
|
25
25
|
import {Menu} from "$ecomponents/BottomSheet";
|
26
26
|
import session from "$session";
|
27
27
|
import {useScreen,useSWR} from "$econtext/hooks";
|
28
|
+
import {HStack} from "$ecomponents/Stack";
|
28
29
|
|
29
30
|
export const getSessionKey = ()=>{
|
30
31
|
return Auth.getSessionKey("swrDatagrid");
|
@@ -82,6 +83,7 @@ const SWRDatagridComponent = React.forwardRef((props,ref)=>{
|
|
82
83
|
icon : cIcon,
|
83
84
|
swrOptions,
|
84
85
|
pagination,
|
86
|
+
renderCustomPagination,
|
85
87
|
...rest
|
86
88
|
} = props;
|
87
89
|
const screenContext = useScreen();
|
@@ -308,13 +310,15 @@ const SWRDatagridComponent = React.forwardRef((props,ref)=>{
|
|
308
310
|
doRefresh(true);
|
309
311
|
return false;
|
310
312
|
}}
|
311
|
-
renderCustomPagination = {(
|
313
|
+
renderCustomPagination = {(...args)=>{
|
314
|
+
const cPagination = typeof renderCustomPagination =="function"? renderCustomPagination(...args) : null;
|
312
315
|
if(!canPaginate()) {
|
313
|
-
return <
|
316
|
+
return <HStack testID={testID+"_PaginationLabel"}>
|
317
|
+
{React.isValidElement(cPagination)? cPagination : null}
|
314
318
|
<Label textBold primary style={{fontSize:15}}>
|
315
319
|
{total.formatNumber()}
|
316
320
|
</Label>
|
317
|
-
</
|
321
|
+
</HStack>
|
318
322
|
}
|
319
323
|
const page = pageRef.current, totalPages = getTotalPages(), prevPage = getPrevPage(),nextPage = getNextPage();
|
320
324
|
const iconProp = {
|
@@ -324,6 +328,7 @@ const SWRDatagridComponent = React.forwardRef((props,ref)=>{
|
|
324
328
|
const sStyle = [styles.limitStyle1,theme.styles.noPadding,theme.styles.noMargin];
|
325
329
|
return <View testID={testID+"_PaginationContainer"} pointerEvents={pointerEvents}>
|
326
330
|
<View style={[theme.styles.row,theme.styles.w100]} pointerEvents={pointerEvents} testID={testID+"_PaginationContentContainer"}>
|
331
|
+
{React.isValidElement(cPagination)? cPagination : null}
|
327
332
|
<Menu
|
328
333
|
testID={testID+"_SimpleSelect"}
|
329
334
|
style = {sStyle}
|
@@ -27,6 +27,7 @@ import {Content as BottomSheet,Menu as BottomSheetMenu,getContentHeight} from "$
|
|
27
27
|
import {isWeb} from "$cplatform";
|
28
28
|
import Tooltip from "$ecomponents/Tooltip";
|
29
29
|
import TouchableRipple from "$ecomponents/TouchableRipple";
|
30
|
+
import stableHash from "stable-hash";
|
30
31
|
|
31
32
|
const _isIos = isIos();
|
32
33
|
|
@@ -168,7 +169,7 @@ class DropdownComponent extends AppComponent {
|
|
168
169
|
}
|
169
170
|
}
|
170
171
|
}
|
171
|
-
if(this.props.onChange){
|
172
|
+
if(typeof this.props.onChange =="function" && stableHash(previousSelected) != stableHash(this.state.selected)){
|
172
173
|
this.props.onChange({value:this.state.selected,selectedKey:valueKey,selectedItems : this.getSelectedItems(),selectedItem,item:selectedItem,items:this.state.data});
|
173
174
|
}
|
174
175
|
},force);
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import PropTypes from "prop-types";
|
2
2
|
import KeyboardEventHandler from "../KeyboardEventHandler";
|
3
|
-
import { addMediaQueryUpdateStyeSubscription } from "$
|
3
|
+
import { addMediaQueryUpdateStyeSubscription } from "$context/hooks";
|
4
4
|
import Dimensions from "$cdimensions";
|
5
5
|
const {getActions,getFormFields,Forms} = require("../utils")
|
6
6
|
import TextField,{parseDecimal} from "$ecomponents/TextField";
|
@@ -23,7 +23,7 @@ import sprintf from "./sprintf";
|
|
23
23
|
import ErrorMessage from "$ecomponents/ErrorBoundary/ErrorMessage";
|
24
24
|
import { UPPER_CASE, LOWER_CASE} from "$common/lib/validator";
|
25
25
|
import Label from "$ecomponents/Label";
|
26
|
-
|
26
|
+
import stableHash from "stable-hash";
|
27
27
|
|
28
28
|
export default class Field extends AppComponent {
|
29
29
|
constructor(props) {
|
@@ -65,7 +65,7 @@ export default class Field extends AppComponent {
|
|
65
65
|
},override : false, writable : false
|
66
66
|
},
|
67
67
|
isFilter : {
|
68
|
-
value : ()=>defaultVal(renderfilter,render_filter) ? true : false,override : false,writable : false,
|
68
|
+
value : ()=>defaultVal(renderfilter,render_filter,this.props.renderfilter,this.props._render_filter) ? true : false,override : false,writable : false,
|
69
69
|
},
|
70
70
|
isEditableBySymbol : {
|
71
71
|
value : ()=>{
|
@@ -253,7 +253,7 @@ export default class Field extends AppComponent {
|
|
253
253
|
this.INITIAL_STATE._lastValidatingValue = value;
|
254
254
|
this.setState ({validValue:value,validatingValue:value,previousValue:this.state.validValue,errorText:"",error:false},()=>{
|
255
255
|
this._previousValue = this.state.validValue;
|
256
|
-
|
256
|
+
const fields = getFormFields(this.formName);
|
257
257
|
let canEnable = true;
|
258
258
|
for(var k in fields){
|
259
259
|
if(k === this.getName()) continue;
|
@@ -267,12 +267,12 @@ export default class Field extends AppComponent {
|
|
267
267
|
break;
|
268
268
|
}
|
269
269
|
}
|
270
|
-
|
271
|
-
|
270
|
+
const actions = getActions(this.formName);
|
271
|
+
const action = canEnable?"enable":"disable";
|
272
272
|
for(var k in actions){
|
273
273
|
actions[k][action]();
|
274
274
|
}
|
275
|
-
|
275
|
+
const form = Forms.getForm(this.formName);
|
276
276
|
typeof this.props.onValidate=="function" && this.props.onValidate.call(this,{...defaultObj(rest),isFilter:this.isFilter(),props:this.props,formName:this.formName,form,name:this.name,field:this.name,value,event,context:this});
|
277
277
|
this.callOnChange({value,event,isValid:true,...rest});
|
278
278
|
if(form && form.props){
|
@@ -520,7 +520,7 @@ export default class Field extends AppComponent {
|
|
520
520
|
return this._previousValue;
|
521
521
|
}
|
522
522
|
hasValueChanged(value){
|
523
|
-
return (
|
523
|
+
return (stableHash(this.state.validatingValue) === stableHash(value))? false : true;
|
524
524
|
}
|
525
525
|
isValidRuleDynamic(){
|
526
526
|
return false;
|
@@ -535,15 +535,15 @@ export default class Field extends AppComponent {
|
|
535
535
|
}
|
536
536
|
validate ({value,event,...rest}){
|
537
537
|
value = this.parseDecimal(value);
|
538
|
+
if(!this.hasValueChanged(value) && (this.isFilter()? true : this.__hasAlreadyValidated)){
|
539
|
+
return;
|
540
|
+
}
|
541
|
+
this.__hasAlreadyValidated = true;
|
538
542
|
this.validatingValue = value;
|
539
|
-
if((!this.canValidate()) && !this.isSelectField()){
|
540
|
-
if(this._isInitialized && !this.hasValueChanged(value)) {
|
541
|
-
return;
|
542
|
-
}
|
543
|
-
this._isInitialized = true;
|
543
|
+
if(((!this.canValidate()) && !this.isSelectField()) || this.isFilter()){
|
544
544
|
this._previousValue = this.state.validValue;
|
545
545
|
this.trigger("validate",{...defaultObj(rest),context:this,value,event,oldValue:this.INITIAL_STATE._lastValidatingValue},(results)=>{
|
546
|
-
this.setState({validValue:value,validatingValue:value,sk:!this.state.sk,previousValue:this.state.
|
546
|
+
this.setState({validValue:value,validatingValue:value,sk:!this.state.sk,previousValue:this.state.validatingValue},()=>{
|
547
547
|
if(isFunction(this.props.onValidate)){
|
548
548
|
this.props.onValidate({...defaultObj(rest),props:this.props,name:this.name,field:this.name,value,event,context:this,oldValue:this.INITIAL_STATE._lastValidatingValue});
|
549
549
|
}
|
@@ -559,7 +559,7 @@ export default class Field extends AppComponent {
|
|
559
559
|
if(this.isValidRuleDynamic()){
|
560
560
|
this.INITIAL_STATE.validRule = this.INITIAL_STATE.validType = validRule;
|
561
561
|
}
|
562
|
-
Validator.validate({...
|
562
|
+
Validator.validate({...rest,onValidatorValid:this.onValidatorValid.bind(this),context:this,value,validRule,validType:validRule,validParams:this.INITIAL_STATE.validParams,event})
|
563
563
|
}
|
564
564
|
|
565
565
|
/**** met le focus sur l'élément précédent */
|
@@ -616,7 +616,9 @@ export default class Field extends AppComponent {
|
|
616
616
|
if(this.canRegisterField()){
|
617
617
|
Forms.trigger("registerField",this.getName(),this.getFormName(),this);
|
618
618
|
}
|
619
|
-
if(defaultVal(validate,true) &&
|
619
|
+
if(!this.isFilter() && defaultVal(validate,true) && this.props.validateOnMount !== false) {
|
620
|
+
this.validate({context:this,value:defaultVal(this.props.defaultValue)})
|
621
|
+
}
|
620
622
|
}
|
621
623
|
componentWillUnmount() {
|
622
624
|
super.componentWillUnmount();
|
@@ -1043,6 +1045,9 @@ export default class Field extends AppComponent {
|
|
1043
1045
|
}
|
1044
1046
|
|
1045
1047
|
Field.propTypes = {
|
1048
|
+
validateOnMount : PropTypes.oneOfType([
|
1049
|
+
PropTypes.bool,//si la formField sera validée immédiatement au montage du composant
|
1050
|
+
]),
|
1046
1051
|
left : PropTypes.oneOfType([
|
1047
1052
|
PropTypes.node,
|
1048
1053
|
PropTypes.func,
|
@@ -2,7 +2,6 @@ import Field from "./Field";
|
|
2
2
|
import Dropdown from "$ecomponents/Dropdown";
|
3
3
|
import PropTypes from "prop-types";
|
4
4
|
import {isObj} from "$cutils";
|
5
|
-
|
6
5
|
export default class FormSelectField extends Field{
|
7
6
|
constructor(props) {
|
8
7
|
super(props);
|
@@ -127,12 +126,7 @@ export default class FormSelectField extends Field{
|
|
127
126
|
props.onMount({context,...rest});
|
128
127
|
}
|
129
128
|
}}
|
130
|
-
onChange = {(
|
131
|
-
this.validateWithCallOnChange(args);
|
132
|
-
if(typeof props.onChange =='function'){
|
133
|
-
props.onChange(args);
|
134
|
-
}
|
135
|
-
}}
|
129
|
+
onChange = {this.validateWithCallOnChange.bind(this)}
|
136
130
|
/>
|
137
131
|
}
|
138
132
|
}
|
@@ -14,12 +14,7 @@ export default class FormFieldSelectFontIcon extends SelectField{
|
|
14
14
|
props.onMount({context,...rest});
|
15
15
|
}
|
16
16
|
}}
|
17
|
-
onChange = {(
|
18
|
-
this.validateWithCallOnChange(args);
|
19
|
-
if(typeof props.onChange =='function'){
|
20
|
-
props.onChange(args);
|
21
|
-
}
|
22
|
-
}}
|
17
|
+
onChange = {this.validateWithCallOnChange.bind(this)}
|
23
18
|
/>
|
24
19
|
}
|
25
20
|
}
|
@@ -5,12 +5,7 @@ export default class FormSelectStructDataField extends SelectField{
|
|
5
5
|
_render(props){
|
6
6
|
return <SelectStructData
|
7
7
|
{...props}
|
8
|
-
onChange = {(
|
9
|
-
this.validateWithCallOnChange(args);
|
10
|
-
if(typeof this.props.onChange =='function'){
|
11
|
-
this.props.onChange(args);
|
12
|
-
}
|
13
|
-
}}
|
8
|
+
onChange = {this.validateWithCallOnChange.bind(this)}
|
14
9
|
ref = {(el)=>{
|
15
10
|
this._field = el;
|
16
11
|
}}
|
@@ -14,6 +14,8 @@ import useApp from "$econtext/hooks";
|
|
14
14
|
import DateLib from "$lib/date";
|
15
15
|
import {useSWR} from "$econtext/hooks";
|
16
16
|
import stableHash from "stable-hash";
|
17
|
+
import {formatValue} from "$ecomponents/Datagrid/Common/utils";
|
18
|
+
|
17
19
|
|
18
20
|
/*** la tabledataSelectField permet de faire des requêtes distantes pour rechercher les données
|
19
21
|
* Elle doit prendre en paramètre et de manière requis : les props suivante :
|
@@ -21,7 +23,8 @@ import stableHash from "stable-hash";
|
|
21
23
|
* foreignKeyTable : la tableData dans laquelle effectuer les donées de la requêtes
|
22
24
|
* foreignKeyLabel : Le libélé dans la table étrangère
|
23
25
|
*/
|
24
|
-
const TableDataSelectField = React.forwardRef(({foreignKeyColumn,swrOptions,foreignKeyLabelRenderers,onChange,isStructData,getForeignKeyTable:cGetForeignKeyTable,prepareFilters:cPrepareFilters,bindUpsert2RemoveEvents,onAdd,showAdd:customShowAdd,canShowAdd,foreignKeyTable,fetchItemsPath,foreignKeyLabel,foreignKeyLabelIndex,dropdownActions,fields,fetchItems:customFetchItem,parseMangoQueries,mutateFetchedItems,onFetchItems,isFilter,isUpdate,isDocEditing,items:customItems,onAddProps,fetchOptions,...props},ref)=>{
|
26
|
+
const TableDataSelectField = React.forwardRef(({foreignKeyColumn,swrOptions,foreignKeyLabelRenderers,onChange,isStructData,getForeignKeyTable:cGetForeignKeyTable,prepareFilters:cPrepareFilters,bindUpsert2RemoveEvents,onAdd,showAdd:customShowAdd,canShowAdd,foreignKeyTable,fetchItemsPath,foreignKeyLabel,foreignKeyLabelIndex,dropdownActions,fields,fetchItems:customFetchItem,parseMangoQueries,mutateFetchedItems,onFetchItems,isFilter,renderFilter,render_filter,isUpdate,isDocEditing,items:customItems,onAddProps,fetchOptions,...props},ref)=>{
|
27
|
+
isFilter = isFilter || !!renderFilter || !!render_filter;
|
25
28
|
props.data = defaultObj(props.data);
|
26
29
|
const type = defaultStr(props.type)?.toLowerCase();
|
27
30
|
isStructData = isStructData || type?.replaceAll("-","").replaceAll("_","").trim().contains("structdata");
|
@@ -96,7 +99,6 @@ const TableDataSelectField = React.forwardRef(({foreignKeyColumn,swrOptions,fore
|
|
96
99
|
const hashKey = React.useMemo(()=>{
|
97
100
|
return stableHash(fetchOptions);
|
98
101
|
},[fetchOptions]);
|
99
|
-
const hasRefreshedRef = React.useRef(false);
|
100
102
|
const showAdd = React.useMemo(()=>{
|
101
103
|
if(isFilter || !foreignKeyTable) return false;
|
102
104
|
if(typeof canShowAdd ==='function'){
|
@@ -111,10 +113,12 @@ const TableDataSelectField = React.forwardRef(({foreignKeyColumn,swrOptions,fore
|
|
111
113
|
fetchItemsRef.current = customFetchItem;
|
112
114
|
swrOptions = Object.assign({},swrOptions);
|
113
115
|
///@see : https://swr.vercel.app/docs/revalidation#disable-automatic-revalidations
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
116
|
+
const canDisable = isFilter || isDisabled;
|
117
|
+
swrOptions.revalidateOnFocus = canDisable? false : typeof swrOptions.revalidateOnFocus === "boolean" ? swrOptions.revalidateOnFocus : false;
|
118
|
+
swrOptions.revalidateIfStale = canDisable? false : typeof swrOptions.revalidateIfStale ==="boolean"? swrOptions.revalidateIfStale : false;
|
119
|
+
if(canDisable){
|
120
|
+
swrOptions.refreshInterval = 2500*1000*60;
|
121
|
+
swrOptions.refreshWhenHidden = false;
|
118
122
|
swrOptions.revalidateOnReconnect = false;
|
119
123
|
}
|
120
124
|
const restOptionsRef = React.useRef({});
|
@@ -124,6 +128,7 @@ const TableDataSelectField = React.forwardRef(({foreignKeyColumn,swrOptions,fore
|
|
124
128
|
const onFetchItemsRef = React.useRef();
|
125
129
|
onFetchItemsRef.current = onFetchItems;
|
126
130
|
const mutateFetchedItemsRef = React.useRef();
|
131
|
+
const fkeyFields = defaultObj(fKeyTable.fields);
|
127
132
|
mutateFetchedItemsRef.current = mutateFetchedItems;
|
128
133
|
const {isLoading:cIsLoading,data:fetchedItems,isValidating,refresh} = useSWR(hasErrors?null:queryPathKey,{
|
129
134
|
fetcher : (url,opts1)=>{
|
@@ -155,7 +160,6 @@ const TableDataSelectField = React.forwardRef(({foreignKeyColumn,swrOptions,fore
|
|
155
160
|
if(typeof onFetchItemsRef.current ==='function'){
|
156
161
|
onFetchItemsRef.current({...args,context:{refresh},props});
|
157
162
|
}
|
158
|
-
hasRefreshedRef.current = true;
|
159
163
|
fetchedResultRef.current = args;
|
160
164
|
return fetchedResultRef.current;
|
161
165
|
}).catch((e)=>{
|
@@ -206,34 +210,30 @@ const TableDataSelectField = React.forwardRef(({foreignKeyColumn,swrOptions,fore
|
|
206
210
|
if(!isObj(p) || !isObj(p.item)) return null;
|
207
211
|
let itemLabel = typeof foreignKeyLabel =='function'? foreignKeyLabel(p) : undefined;
|
208
212
|
if(Array.isArray(foreignKeyLabel)){
|
209
|
-
let
|
213
|
+
let labels = "";
|
210
214
|
foreignKeyLabel.map(fk=>{
|
211
215
|
if(!isNonNullString(fk)) return;
|
212
|
-
const
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
itv = t =='money'? itv.formatMoney() : itv.formatNumber();
|
224
|
-
}
|
225
|
-
} else {
|
226
|
-
/***
|
227
|
-
if(typeof itv =='string' && itv && DateLib.isIsoDateStr(itv)){
|
228
|
-
itv = DateLib.format(itv,DateLib.defaultDateFormat);
|
229
|
-
}
|
230
|
-
*/
|
216
|
+
const field = defaultObj(fkeyFields[fk]);
|
217
|
+
const type = defaultStr(field.type,"text").toLowerCase();
|
218
|
+
const format = defaultStr(field.format).toLowerCase();
|
219
|
+
const formatter = typeof field.formatValue =='function' && field.formatValue|| undefined;
|
220
|
+
let value = p.item[fk];
|
221
|
+
if(["date","datetime"].includes(type)){
|
222
|
+
value = DateLib.format(value,type=='date'?DateLib.defaultDateFormat:DateLib.defaultDateTimeFormat);
|
223
|
+
} else if(format && formatter) {
|
224
|
+
const v = formatValue(value,format,false,formatter);
|
225
|
+
if(isNonNullString(v)){
|
226
|
+
value = v;
|
231
227
|
}
|
232
|
-
}
|
233
|
-
|
228
|
+
} else if(typeof value =="number"){
|
229
|
+
if(format =="money"){
|
230
|
+
value = value.formatMoney();
|
231
|
+
} else value = value.formatNumber();
|
232
|
+
}
|
233
|
+
labels+= (labels?" ":"")+ (defaultStr(value))
|
234
234
|
});
|
235
|
-
if(
|
236
|
-
itemLabel =
|
235
|
+
if(labels){
|
236
|
+
itemLabel = labels;
|
237
237
|
}
|
238
238
|
}
|
239
239
|
if(!itemLabel && isNonNullString(foreignKeyLabel)){
|
@@ -261,14 +261,7 @@ const TableDataSelectField = React.forwardRef(({foreignKeyColumn,swrOptions,fore
|
|
261
261
|
showAdd = {showAdd}
|
262
262
|
isLoading = {isLoading}
|
263
263
|
dialogProps = {dialogProps}
|
264
|
-
onChange = {
|
265
|
-
if(isFilter){
|
266
|
-
if(!hasRefreshedRef.current) return;
|
267
|
-
if(JSON.stringify(defaultValueRef.current) === JSON.stringify(args[0]?.value)) return;
|
268
|
-
defaultValueRef.current = args[0]?.value;
|
269
|
-
}
|
270
|
-
if(onChange) return onChange(...args);
|
271
|
-
}}
|
264
|
+
onChange = {onChange}
|
272
265
|
ref = {ref}
|
273
266
|
defaultValue = {foreignKeyColumnValue}
|
274
267
|
dropdownActions = {dropdownActions}
|
@@ -5,12 +5,7 @@ export default class FormSelectTableDataField extends SelectField{
|
|
5
5
|
_render(props){
|
6
6
|
return <SelectTableData
|
7
7
|
{...props}
|
8
|
-
onChange = {(
|
9
|
-
this.validateWithCallOnChange(args);
|
10
|
-
if(typeof this.props.onChange =='function'){
|
11
|
-
this.props.onChange(args);
|
12
|
-
}
|
13
|
-
}}
|
8
|
+
onChange = {this.validateWithCallOnChange.bind(this)}
|
14
9
|
beforeFetchItems = {(opts)=>{
|
15
10
|
if(typeof props.beforeFetchItems =='function'){
|
16
11
|
return props.beforeFetchItems({...opts,context:this,dropdownContext : this._field})
|
@@ -115,9 +115,12 @@ const styles = StyleSheet.create({
|
|
115
115
|
justifyContent : 'center',
|
116
116
|
paddingVertical : 15,
|
117
117
|
paddingHorizontal : 20,
|
118
|
+
flexWrap : "wrap",
|
118
119
|
},
|
119
120
|
text : {
|
120
|
-
marginLeft:20
|
121
|
+
marginLeft:20,
|
122
|
+
paddingHorizontal : 5,
|
123
|
+
maxWidth : "98%",
|
121
124
|
},
|
122
125
|
content : {},
|
123
126
|
indicatorLeft : {
|
package/src/context/hooks.js
CHANGED
@@ -1,12 +1,8 @@
|
|
1
1
|
module.exports = {
|
2
2
|
"@fto-consult/expo-ui": {
|
3
|
-
"
|
4
|
-
"
|
5
|
-
"
|
6
|
-
"type": "git",
|
7
|
-
"url": "git+https://github.com/borispipo/expo-ui.git"
|
8
|
-
},
|
9
|
-
"homepage": "https://github.com/borispipo/expo-ui#readme"
|
3
|
+
"version": "8.16.0",
|
4
|
+
"url": "https://github.com/borispipo/expo-ui#readme",
|
5
|
+
"license": "ISC"
|
10
6
|
},
|
11
7
|
"@babel/plugin-proposal-export-namespace-from": {
|
12
8
|
"version": "7.18.9",
|
@@ -34,7 +30,7 @@ module.exports = {
|
|
34
30
|
"license": "MIT"
|
35
31
|
},
|
36
32
|
"@fto-consult/common": {
|
37
|
-
"version": "4.
|
33
|
+
"version": "4.18.3",
|
38
34
|
"url": "https://github.com/borispipo/common#readme",
|
39
35
|
"license": "ISC"
|
40
36
|
},
|
@@ -149,7 +145,7 @@ module.exports = {
|
|
149
145
|
"license": "MIT"
|
150
146
|
},
|
151
147
|
"react-virtuoso": {
|
152
|
-
"version": "4.6.
|
148
|
+
"version": "4.6.3",
|
153
149
|
"url": "https://virtuoso.dev/",
|
154
150
|
"license": "MIT"
|
155
151
|
},
|