@fto-consult/expo-ui 8.16.1 → 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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fto-consult/expo-ui",
3
- "version": "8.16.1",
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,7 @@
70
70
  "dependencies": {
71
71
  "@emotion/react": "^11.11.1",
72
72
  "@faker-js/faker": "^8.0.2",
73
- "@fto-consult/common": "^4.15.57",
73
+ "@fto-consult/common": "^4.18.3",
74
74
  "@fto-consult/expo-ui": "^8.16.0",
75
75
  "@fto-consult/node-utils": "^1.4.7",
76
76
  "apexcharts": "^3.45.2",
@@ -93,7 +93,7 @@
93
93
  "react-native-paper": "^5.12.3",
94
94
  "react-native-paper-dates": "^0.21.7",
95
95
  "react-native-web": "^0.19.10",
96
- "react-virtuoso": "^4.6.2",
96
+ "react-virtuoso": "^4.6.3",
97
97
  "readable-stream": "^4.5.2",
98
98
  "sanitize-filename": "^1.6.3",
99
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 header = Object.clone(headerCol1);
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],{...config,filter:(a)=>{
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 $ecomponents/Datagrid/Footer
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,rowIndex,rowKey);
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
- const defaultValue = renderArgs.defaultValue = renderArgs.value = rowData[columnField];
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
- } else {
42
- _render = defaultValue;
41
+ }
42
+ const cellValue = defaultVal(_render,rowData[columnField]);
43
+ {
44
+ _render = cellValue;
43
45
  if(!renderText && defaultStr(columnDef.format).toLowerCase() === 'hashtag'){
44
- _render = <Hashtag>{_render}</Hashtag>
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(rowData[columnField]){
48
+ if(cellValue){
49
49
  const sqlFormat =_type === 'time'? undefined : _type ==="datetime" ? DateLib.SQLDateTimeFormat : DateLib.SQLDateFormat;
50
- let _dd =DateLib.parse(rowData[columnField],sqlFormat);
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 = rowData[columnField]
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(rowData[columnField],columnDef.defaultValue,columnDef.value)
63
- if(val === checkedValue){
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={defaultValue}/>
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 = rowData[columnField]?.toString();
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
- </> : <TableLink
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 = rowData[columnField];
140
+ columnDef.src = cellValue;
141
141
  _render = <Image {...columnDef}/>
142
142
  }
143
143
  if(_render === undefined || _render ===null){
144
- _render = rowData[columnField];
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 = rowData[columnField];
158
+ _render = cellValue;
159
159
  }
160
160
  if(isArray(_render)){
161
161
  _render = _render.join(arrayValueSeparator);
@@ -235,10 +235,10 @@ export const renderSelectFieldCell= ({rowData,rowCellValue,columnDef,columnFiel
235
235
  }
236
236
 
237
237
  export const formatValue = (value,format,abreviateValues,formatter)=>{
238
+ if(typeof value !='number') return value;
238
239
  if(typeof value =='boolean'){
239
240
  return value ? "Oui" : "Non";
240
241
  }
241
- if(typeof value !='number') return value;
242
242
  format = typeof format =='string'? format.toLowerCase().trim() : "";
243
243
  if(typeof formatter =='function'){
244
244
  return formatter({value,format,abreviateValues,abreviate:abreviateValues});
@@ -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 = {({context})=>{
313
+ renderCustomPagination = {(...args)=>{
314
+ const cPagination = typeof renderCustomPagination =="function"? renderCustomPagination(...args) : null;
312
315
  if(!canPaginate()) {
313
- return <View testID={testID+"_PaginationLabel"}>
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
- </View>
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);
@@ -3,7 +3,7 @@ import {isNativeMobile,isTouchDevice} from "$cplatform";
3
3
 
4
4
  export const matchOperators = /[|\\{}()[\]^$+*?.]/g;
5
5
 
6
- export const SEARCH_TIMEOUT = 1500;
6
+ export const SEARCH_TIMEOUT = 1000;
7
7
 
8
8
  export const MAX_AUTO_FOCUS_ITEMS = 10;
9
9
 
@@ -1,6 +1,6 @@
1
1
  import PropTypes from "prop-types";
2
2
  import KeyboardEventHandler from "../KeyboardEventHandler";
3
- import { addMediaQueryUpdateStyeSubscription } from "$econtext/hooks";
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
- let fields = getFormFields(this.formName);
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
- let actions = getActions(this.formName);
271
- let action = canEnable?"enable":"disable";
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
- let form = Forms.getForm(this.formName);
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 (JSON.stringify(this.state.previousValue) === JSON.stringify(value))? false : true;
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.validValue},()=>{
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({...defaultObj(rest),onValidatorValid:this.onValidatorValid.bind(this),context:this,value,validRule,validType:validRule,validParams:this.INITIAL_STATE.validParams,event})
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) && !this.isFilter()) this.validate({context:this,value:defaultVal(this.props.defaultValue)});
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 = {(args)=>{
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 = {(args)=>{
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 = {(args)=>{
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
  }}
@@ -16,13 +16,15 @@ import {useSWR} from "$econtext/hooks";
16
16
  import stableHash from "stable-hash";
17
17
  import {formatValue} from "$ecomponents/Datagrid/Common/utils";
18
18
 
19
+
19
20
  /*** la tabledataSelectField permet de faire des requêtes distantes pour rechercher les données
20
21
  * Elle doit prendre en paramètre et de manière requis : les props suivante :
21
22
  * foreignKeyColumn : La colonne dont le champ fait référence à la clé étrangère, ie fKeyTable dans laquelle faire les requêtes fetch
22
23
  * foreignKeyTable : la tableData dans laquelle effectuer les donées de la requêtes
23
24
  * foreignKeyLabel : Le libélé dans la table étrangère
24
25
  */
25
- const TableDataSelectField = React.forwardRef(({foreignKeyColumn,swrOptions,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;
26
28
  props.data = defaultObj(props.data);
27
29
  const type = defaultStr(props.type)?.toLowerCase();
28
30
  isStructData = isStructData || type?.replaceAll("-","").replaceAll("_","").trim().contains("structdata");
@@ -97,7 +99,6 @@ const TableDataSelectField = React.forwardRef(({foreignKeyColumn,swrOptions,onCh
97
99
  const hashKey = React.useMemo(()=>{
98
100
  return stableHash(fetchOptions);
99
101
  },[fetchOptions]);
100
- const hasRefreshedRef = React.useRef(false);
101
102
  const showAdd = React.useMemo(()=>{
102
103
  if(isFilter || !foreignKeyTable) return false;
103
104
  if(typeof canShowAdd ==='function'){
@@ -112,10 +113,12 @@ const TableDataSelectField = React.forwardRef(({foreignKeyColumn,swrOptions,onCh
112
113
  fetchItemsRef.current = customFetchItem;
113
114
  swrOptions = Object.assign({},swrOptions);
114
115
  ///@see : https://swr.vercel.app/docs/revalidation#disable-automatic-revalidations
115
- if(isFilter || isDisabled){
116
- swrOptions.refreshInterval = 0;
117
- swrOptions.revalidateOnFocus = false;
118
- swrOptions.revalidateIfStale = false;
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;
119
122
  swrOptions.revalidateOnReconnect = false;
120
123
  }
121
124
  const restOptionsRef = React.useRef({});
@@ -157,7 +160,6 @@ const TableDataSelectField = React.forwardRef(({foreignKeyColumn,swrOptions,onCh
157
160
  if(typeof onFetchItemsRef.current ==='function'){
158
161
  onFetchItemsRef.current({...args,context:{refresh},props});
159
162
  }
160
- hasRefreshedRef.current = true;
161
163
  fetchedResultRef.current = args;
162
164
  return fetchedResultRef.current;
163
165
  }).catch((e)=>{
@@ -203,6 +205,7 @@ const TableDataSelectField = React.forwardRef(({foreignKeyColumn,swrOptions,onCh
203
205
  } else {
204
206
  dropdownActions.trefreshItem = refreshItem;
205
207
  }
208
+ foreignKeyLabelRenderers = defaultObj(foreignKeyLabelRenderers);
206
209
  const rItem = (p)=>{
207
210
  if(!isObj(p) || !isObj(p.item)) return null;
208
211
  let itemLabel = typeof foreignKeyLabel =='function'? foreignKeyLabel(p) : undefined;
@@ -258,14 +261,7 @@ const TableDataSelectField = React.forwardRef(({foreignKeyColumn,swrOptions,onCh
258
261
  showAdd = {showAdd}
259
262
  isLoading = {isLoading}
260
263
  dialogProps = {dialogProps}
261
- onChange = {(...args)=>{
262
- if(isFilter){
263
- if(!hasRefreshedRef.current) return;
264
- if(JSON.stringify(defaultValueRef.current) === JSON.stringify(args[0]?.value)) return;
265
- defaultValueRef.current = args[0]?.value;
266
- }
267
- if(onChange) return onChange(...args);
268
- }}
264
+ onChange = {onChange}
269
265
  ref = {ref}
270
266
  defaultValue = {foreignKeyColumnValue}
271
267
  dropdownActions = {dropdownActions}
@@ -307,6 +303,11 @@ const TableDataSelectField = React.forwardRef(({foreignKeyColumn,swrOptions,onCh
307
303
  TableDataSelectField.propTypes = {
308
304
  ...Dropdown.propTypes,
309
305
  swrOptions : PropTypes.object,//les options supplémentaires à passer à la fonction swr
306
+ /*** permet de faire le mappage entre les foreignKeyLabel et les type correspondants */
307
+ foreignKeyLabelRenderers : PropTypes.objectOf(PropTypes.oneOfType([
308
+ PropTypes.string, //représente le type de données associée à la colone dont le nom la clé
309
+ PropTypes.func, //la fonction utilisée pour le rendu des colonnes de ce type
310
+ ])),
310
311
  prepareFilters : PropTypes.bool,//si les filtres seront customisé
311
312
  bindUpsert2RemoveEvents : PropTypes.bool,//si le composant écoutera l'évènement de rafraichissement des données
312
313
  onAdd : PropTypes.func, //({})=>, la fonction appelée lorsque l'on clique sur le bouton add
@@ -5,12 +5,7 @@ export default class FormSelectTableDataField extends SelectField{
5
5
  _render(props){
6
6
  return <SelectTableData
7
7
  {...props}
8
- onChange = {(args)=>{
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 : {
@@ -34,6 +34,7 @@ export const useSWR = (path,options)=>{
34
34
  ...Object.assign({},options),
35
35
  swrOptions : {
36
36
  provider: () => new Map(),
37
+ keepPreviousData : true,
37
38
  ...swrConfig,
38
39
  isOnline(...rest) {
39
40
  if(isLocalHost) return true;
@@ -1,12 +1,8 @@
1
1
  module.exports = {
2
2
  "@fto-consult/expo-ui": {
3
- "name": "@fto-consult/expo-ui",
4
- "version": "8.14.5",
5
- "repository": {
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.15.56",
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.2",
148
+ "version": "4.6.3",
153
149
  "url": "https://virtuoso.dev/",
154
150
  "license": "MIT"
155
151
  },