@fto-consult/expo-ui 5.7.0 → 5.7.2

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.
@@ -1,4 +1,4 @@
1
- import ApexChart from 'apexcharts/dist/apexcharts.common';
1
+ import ApexChart from 'apexcharts/dist/apexcharts.min';
2
2
  import React from "$react";
3
3
  import View from "$components/View";
4
4
  import { destroyChart } from './utils';
@@ -1,6 +1,6 @@
1
1
  import React, { Component } from "$react";
2
2
  import {normalize,RGB_MAX,HUE_MAX,SV_MAX,hexToRgb} from "$theme/colors";
3
- import {extendObj} from "$cutils";
3
+ import {extendObj,defaultStr,isNonNullString,defaultObj,isObj} from "$cutils";
4
4
  import View from "$ecomponents/View";
5
5
  import {
6
6
  Animated,
@@ -15,7 +15,7 @@ import srcWheel from './assets/color-wheel.png';
15
15
  import srcSlider from './assets/black-gradient.png';
16
16
  import srcSliderRotated from './assets/black-gradient-rotated.png';
17
17
 
18
- import {Colors} from "$theme";
18
+ import theme,{Colors} from "$theme";
19
19
  import TextField from "$ecomponents/TextField";
20
20
 
21
21
 
@@ -398,7 +398,7 @@ export default class ColorPickerComponent extends Component {
398
398
  }
399
399
  renderSwatches () {
400
400
  this.swatches = this.props.palette.map((c,i) => (
401
- <View style={[styles.swatch,{backgroundColor:c}]} key={'S'+i} hitSlop={this.props.swatchesHitSlop}>
401
+ <View testID={"RN_ColorPicker_SWATCHES"} style={[styles.swatch,theme.styles.cursorPointer,{backgroundColor:c}]} key={'S'+i} hitSlop={this.props.swatchesHitSlop}>
402
402
  <TouchableWithoutFeedback onPress={x=>this.onSwatchPress(c,i)} hitSlop={this.props.swatchesHitSlop}>
403
403
  <Animated.View style={[styles.swatchTouch,{backgroundColor:c,transform:[{scale:this.swatchAnim[i].interpolate({inputRange:[0,0.5,1],outputRange:[0.666,1,0.666]})}]}]} />
404
404
  </TouchableWithoutFeedback>
@@ -407,8 +407,8 @@ export default class ColorPickerComponent extends Component {
407
407
  }
408
408
  renderDiscs () {
409
409
  this.disc = (`1`).repeat(this.props.discreteLength).split('').map((c,i) => (
410
- <View style={[styles.swatch,{backgroundColor:this.state.hueSaturation}]} key={'D'+i} hitSlop={this.props.swatchesHitSlop}>
411
- <TouchableWithoutFeedback onPress={x=>this.onDiscPress(c,i)} hitSlop={this.props.swatchesHitSlop}>
410
+ <View testID={"RN_ColorPicker_DISC"} style={[styles.swatch,{backgroundColor:this.state.hueSaturation}]} key={'D'+i} hitSlop={this.props.swatchesHitSlop}>
411
+ <TouchableWithoutFeedback style={[theme.styles.cursorPointer]} onPress={x=>this.onDiscPress(c,i)} hitSlop={this.props.swatchesHitSlop}>
412
412
  <Animated.View style={[styles.swatchTouch,{backgroundColor:this.state.hueSaturation,transform:[{scale:this.discAnim[i].interpolate({inputRange:[0,0.5,1],outputRange:[0.666,1,0.666]})}]}]}>
413
413
  <View style={[styles.wheelImg,{backgroundColor:'#000',opacity:1-(i>=9?1:(i*11/100))}]}></View>
414
414
  </Animated.View>
@@ -430,6 +430,7 @@ export default class ColorPickerComponent extends Component {
430
430
  disabled,
431
431
  editable,
432
432
  row,
433
+ testID : customTestId,
433
434
  } = this.props
434
435
  const swatches = !!(this.props.swatches || swatchesOnly)
435
436
  const hsv = hsvToHex(this.color), hex = hsvToHex(this.color.h,this.color.s,100)
@@ -483,34 +484,47 @@ export default class ColorPickerComponent extends Component {
483
484
  marginBottom:row?0:margin,
484
485
  }
485
486
  // console.log('RENDER >>',row,thumbSize,sliderSize)
487
+ const testID = defaultStr(customTestId,"RN_ColorPickerContainer");
488
+ const hasHex = Colors.isValid(hex);
489
+ const contrastColor = hasHex ? Colors.getContrast(hex) : undefined;
490
+ const restProps = hasHex ? {
491
+ color : contrastColor,
492
+ backgroundColor : hex,
493
+ style : [{
494
+ color : contrastColor,
495
+ backgroundColor : hex,
496
+ }]
497
+ } : {};
486
498
  return (
487
- <View testID="RN_ColorPickerContainer">
488
- <View style={[styles.root,row?{flexDirection:'row'}:{},style]}>
489
- { swatches && !swatchesLast && <View style={[styles.swatches,swatchStyle,swatchFirstStyle]} key={'SW'}>{ this.swatches }</View> }
490
- { !swatchesOnly && <View style={[styles.wheel]} key={'$1'} onLayout={this.onSquareLayout}>
499
+ <View testID={testID}>
500
+ <View testID={`${testID}_RowContainer`} style={[styles.root,row?{flexDirection:'row'}:{},style]}>
501
+ { swatches && !swatchesLast && <View testID={`${testID}_SwatchestLast`} style={[styles.swatches,swatchStyle,swatchFirstStyle]} key={'SW'}>{ this.swatches }</View> }
502
+ { !swatchesOnly && <View testID={`${testID}_SwatchesOnly`} style={[styles.wheel]} key={'$1'} onLayout={this.onSquareLayout}>
491
503
  { this.wheelWidth>0 && <View style={[{padding:thumbSize/2,width:this.wheelWidth,height:this.wheelWidth}]}>
492
- <View style={[styles.wheelWrap]}>
493
- <Image style={styles.wheelImg} source={srcWheel} />
494
- <Animated.View style={[styles.wheelThumb,wheelThumbStyle,Elevations[4],{pointerEvents:'none'}]} />
495
- <View style={[styles.cover]} onLayout={this.onWheelLayout} {...wheelPanHandlers} ref={r => { this.wheel = r }}></View>
504
+ <View style={[styles.wheelWrap,theme.styles.cursorPointer]} testID={`${testID}_WheelWrap`}>
505
+ <Image testID={testID+"_WheelImg"} style={styles.wheelImg} source={srcWheel} />
506
+ <Animated.View testID={testID+"WheelThumb"} style={[styles.wheelThumb,wheelThumbStyle,Elevations[4],{pointerEvents:'none'}]} />
507
+ <View testID={testID+"_WheelWrapLayout"} style={[styles.cover]} onLayout={this.onWheelLayout} {...wheelPanHandlers} ref={r => { this.wheel = r }}></View>
496
508
  </View>
497
509
  </View> }
498
510
  </View> }
499
- { !swatchesOnly && !sliderHidden && (discrete ? <View style={[styles.swatches,swatchStyle]} key={'$2'}>{ this.disc }</View> : <View style={[styles.slider,sliderStyle]} key={'$2'}>
500
- <View style={[styles.grad,{backgroundColor:hex}]}>
511
+ { !swatchesOnly && !sliderHidden && (discrete ? <View testID={`${testID}_SwatchesDiscrete`} style={[styles.swatches,swatchStyle]} key={'$2'}>{ this.disc }</View> : <View style={[styles.slider,sliderStyle]} key={'$2'}>
512
+ <View testID={testID+"_WheelGrad"} sstyle={[styles.grad,{backgroundColor:hex}]}>
501
513
  <Image style={styles.sliderImg} source={row?srcSliderRotated:srcSlider} resizeMode="stretch" />
502
514
  </View>
503
515
  <Animated.View style={[styles.sliderThumb,sliderThumbStyle,Elevations[4],{pointerEvents:'none'}]} />
504
516
  <View style={[styles.cover]} onLayout={this.onSliderLayout} {...sliderPanHandlers} ref={r => { this.slider = r }}></View>
505
517
  </View>) }
506
- { swatches && swatchesLast && <View style={[styles.swatches,swatchStyle]} key={'SW'}>{ this.swatches }</View> }
518
+ { swatches && swatchesLast && <View testID={`${testID}_SwatchesList`} style={[styles.swatches,swatchStyle]} key={'SW'}>{ this.swatches }</View> }
507
519
  <TextField
520
+ testID={`${testID}_ColorPickerInput`}
508
521
  enableCopy
509
522
  label = ''
510
523
  editable = {editable}
511
524
  disabled = {disabled}
512
525
  defaultValue = {hex}
513
- style = {styles.textInput}
526
+ {...restProps}
527
+ style = {[styles.textInput,restProps.style]}
514
528
  onChangeText = {(value)=>{
515
529
  if(Colors.isHex(value)){
516
530
  this.update(value);
@@ -9,6 +9,7 @@ import theme from "$theme"
9
9
  import {styles as rStyles} from "../utils";
10
10
  import {getSelectedBackgroundColor} from "../Actions/Header";
11
11
  import Swipeable from 'react-native-gesture-handler/Swipeable';
12
+ import {isMobileNative} from "$platform";
12
13
 
13
14
  const DatagridAccordionRow = React.forwardRef((props,ref)=>{
14
15
  const {selectable,rowKey,
@@ -166,7 +167,7 @@ const DatagridAccordionRow = React.forwardRef((props,ref)=>{
166
167
  _rP.style,rowProps.style,
167
168
  styles.container,
168
169
  numColumns > 1 && {width:'99%'},
169
- selected && styles.containerSelected,
170
+ //selected && !hasAvatar && styles.containerSelected,
170
171
  styles.bordered,
171
172
  wrapperStyle,
172
173
  style,
@@ -273,7 +274,7 @@ const styles = StyleSheet.create({
273
274
  container : {
274
275
  marginVertical : 10,
275
276
  paddingVertical : 5,
276
- paddingHorizontal : 15,
277
+ paddingHorizontal : 10,// isMobileNative()? 15:10,
277
278
  marginHorizontal : 5,
278
279
  flexWrap : 'nowrap',
279
280
  justifyContent : 'center',
@@ -2686,11 +2686,12 @@ export default class CommonDatagridComponent extends AppComponent {
2686
2686
  return defaultNumber(this.sectionListDataSize.current)
2687
2687
  }
2688
2688
  prepareData(args,cb){
2689
- let {pagination,config,aggregatorFunction:customAggregatorFunction,displayOnlySectionListHeaders:cdisplayOnlySectionListHeaders,data,force,sectionListColumns,updateFooters} = defaultObj(args);
2689
+ let {pagination,config,aggregatorFunction:customAggregatorFunction,displayOnlySectionListHeaders:cdisplayOnlySectionListHeaders,data,force,sectionListColumns,sectionListCollapsedStates,updateFooters} = defaultObj(args);
2690
2690
  cb = typeof cb ==='function'? cb : typeof args.cb == 'function'? args.cb : undefined;
2691
2691
  config = isObj(config) && Object.size(config,true)? config : this.getConfig();
2692
2692
  const aggregatorFunction = isNonNullString(customAggregatorFunction) && customAggregatorFunction in this.aggregatorFunctions ? this.aggregatorFunctions[customAggregatorFunction] : this.getActiveAggregatorFunction();
2693
2693
  sectionListColumns = isObj(sectionListColumns) ? sectionListColumns : this.state.sectionListColumns;
2694
+ sectionListCollapsedStates = isObj(sectionListCollapsedStates)? sectionListCollapsedStates: defaultObj(this.state.sectionListCollapsedStates);
2694
2695
  const displayOnlySectionListHeaders = typeof cdisplayOnlySectionListHeaders == 'boolean'?cdisplayOnlySectionListHeaders : this.state.displayOnlySectionListHeaders;
2695
2696
  let isArr = Array.isArray(data);
2696
2697
  //let push = (d,index) => isArr ? newData.push(d) : newData[index] = d;
@@ -2808,7 +2809,7 @@ export default class CommonDatagridComponent extends AppComponent {
2808
2809
  } else if(force){
2809
2810
  this.setSelectedRows();
2810
2811
  }
2811
- const state = {data,displayOnlySectionListHeaders,aggregatorFunction:aggregatorFunction.code};
2812
+ const state = {data,displayOnlySectionListHeaders,sectionListCollapsedStates,aggregatorFunction:aggregatorFunction.code};
2812
2813
  if((cb)){
2813
2814
  cb(state);
2814
2815
  }
@@ -2821,7 +2822,7 @@ export default class CommonDatagridComponent extends AppComponent {
2821
2822
  const config = isObj(args.config) && Object.size(args.config,true)? args.config : this.getConfig();
2822
2823
  const displayGroupLabels = "displayGroupLabels" in config? config.displayGroupLabels : true;
2823
2824
  const displayGroupLabelsSeparator = typeof config.displayGroupLabelsSeparator =='string'? config.displayGroupLabelsSeparator : arrayValueSeparator;
2824
- const {fields,sectionListColumnsSize} = args;
2825
+ const {fields} = args;
2825
2826
  const d = [];
2826
2827
  Object.map(fields,(field,i)=>{
2827
2828
  const txt = this.renderRowCell({
@@ -2832,10 +2833,11 @@ export default class CommonDatagridComponent extends AppComponent {
2832
2833
  columnField : defaultStr(field.field,i),
2833
2834
  });
2834
2835
  if(!isNonNullString(txt) && typeof txt !=='number') return;
2835
- if(!displayGroupLabels){
2836
+ const labelText = defaultStr(field.label,field.text);
2837
+ if(!displayGroupLabels || !labelText){
2836
2838
  d.push(txt);
2837
2839
  } else {
2838
- d.push("{0} : {1}".sprintf(defaultStr(field.label,field.txt),txt))
2840
+ d.push("{0} : {1}".sprintf(labelText,txt))
2839
2841
  }
2840
2842
  });
2841
2843
  return d.length ? d.join(displayGroupLabelsSeparator) : undefined;
@@ -2846,6 +2848,22 @@ export default class CommonDatagridComponent extends AppComponent {
2846
2848
  getFlashListItemType(item){
2847
2849
  return typeof item === "string" || isObj(item) && item.isSectionListHeader === true ? "sectionHeader" : "row";;
2848
2850
  }
2851
+ getSectionListCollapsedStates(){
2852
+ return defaultObj(this.state.sectionListCollapsedStates)
2853
+ }
2854
+ isSectionListCollapsed(sectionListKey){
2855
+ return isNonNullString(sectionListKey)? !!this.getSectionListCollapsedStates()[sectionListKey] : false;
2856
+ }
2857
+ toggleSectionListCollapsedState(sectionKey){
2858
+ const s = getSectionListCollapsedStates;
2859
+ if(!isNonNullString(sectionKey)) return;
2860
+ s[sectionKey] = !!!s[sectionKey];
2861
+ setTimeout(()=>{
2862
+ this.setIsLoading(true,()=>{
2863
+ this.setState({sectionListCollapsedStates:{...s}});
2864
+ },true);
2865
+ },TIMEOUT)
2866
+ }
2849
2867
  /****permet de faire le rendu flashlist */
2850
2868
  renderFlashListItem(args){
2851
2869
  if(!this.hasSectionListData()) return null;
@@ -2904,7 +2922,19 @@ export default class CommonDatagridComponent extends AppComponent {
2904
2922
  });
2905
2923
  }
2906
2924
  }
2925
+ const isCollapsed = this.isSectionListCollapsed(key);
2907
2926
  return <View testID={testID+"_ContentContainer"} style={[theme.styles.w100,isA && this.state.displayOnlySectionListHeaders && {borderTopColor:theme.colors.divider,borderTopWidth:1},isA ? [theme.styles.ph2,theme.styles.pt1] : [theme.styles.pt1,theme.styles.noPadding,theme.styles.noMargin],theme.styles.justifyContentCenter,theme.styles.alignItemsCenter,theme.styles.pb1,!cells && theme.styles.ml1,theme.styles.mr1,cStyle]}>
2927
+ {false && <View testID={testID+"_LabelAndCollapsedContainer"} style={[theme.styles.w100,theme.styles.row,theme.styles.alignItemsCenter,theme.styles.justifyContentStart]}>
2928
+ <Icon
2929
+ name = {isCollapsed?"chevron-up":"chevron-right"}
2930
+ color = {theme.colors.primaryOnSurface}
2931
+ style = {[theme.styles.noMargin,theme.styles.noPadding]}
2932
+ size = {25}
2933
+ onPress = {(e)=>{
2934
+ this.toggleSectionListCollapsedState(key);
2935
+ }}
2936
+ />
2937
+ </View>}
2908
2938
  <Label testID={testID+"_Label"} splitText numberOfLines={3} textBold style={[theme.styles.w100,{color:theme.colors.primaryOnSurface,fontSize:isA?15 :16},lStyle,theme.styles.ph1]}>{label}</Label>
2909
2939
  {cells ? <View testID={testID+"_TableRow"} style = {[theme.styles.w100,theme.styles.row,isA && theme.styles.pt1,theme.styles.alignItemsFlexStart,this.isAccordion() && theme.styles.rowWrap]}
2910
2940
  >{cells}</View> : null}
@@ -93,6 +93,7 @@ const SWRDatagridComponent = React.forwardRef((props,ref)=>{
93
93
  autoSort,
94
94
  fetchOptions:customFetchOptions,
95
95
  handleQueryLimit,
96
+ handlePagination,
96
97
  onFetchData,
97
98
  beforeFetchData,
98
99
  sort,
@@ -162,7 +163,8 @@ const SWRDatagridComponent = React.forwardRef((props,ref)=>{
162
163
  const totalRef = React.useRef(0);
163
164
  const isFetchingRef = React.useRef(false);
164
165
  const pageRef = React.useRef(1);
165
- const canHandleLimit = handleQueryLimit !== false ? true : false;
166
+ const canHandlePagination = handlePagination !== false ? true : false;
167
+ const canHandleLimit = handleQueryLimit !== false && canHandlePagination ? true : false;
166
168
  const limitRef = React.useRef(!canHandleLimit ?0 : defaultNumber(getSessionData("limit"),500));
167
169
  const isInitializedRef = React.useRef(false);
168
170
  testID = defaultStr(testID,"RNSWRDatagridComponent");
@@ -191,7 +193,8 @@ const SWRDatagridComponent = React.forwardRef((props,ref)=>{
191
193
  delete opts.page;
192
194
  delete opts.offset;
193
195
  }
194
- const fetchCB = ({data,total})=>{
196
+ const fetchCB = (fArgs)=>{
197
+ let {data,total} = (Array.isArray(fArgs) ? {data:fArgs,total:fArgs.length} : isObj(fArgs)? fArgs : {data:[],total:0});
195
198
  totalRef.current = total;
196
199
  dataRef.current = data;
197
200
  const dd = Object.size(data);
@@ -254,6 +257,7 @@ const SWRDatagridComponent = React.forwardRef((props,ref)=>{
254
257
  refresh();
255
258
  }
256
259
  const canPaginate = ()=>{
260
+ if(!canHandlePagination) return false;
257
261
  if(canHandleLimit && typeof totalRef.current !=='number' || typeof pageRef.current !='number' || typeof limitRef.current !='number') return false;
258
262
  if(limitRef.current <= 0) return false;
259
263
  return true;
@@ -455,6 +459,7 @@ SWRDatagridComponent.displayName = "SWRDatagridComponent";
455
459
 
456
460
  SWRDatagridComponent.propTypes = {
457
461
  ...Datagrid.propTypes,
462
+ handlePagination : PropTypes.bool, //spécifie si le datagrid prendra en compte la pagination
458
463
  /*** le nom de la colonne de trie par défaut */
459
464
  defaultSortColumn : PropTypes.string,
460
465
  fetchPath : PropTypes.string,
@@ -623,10 +623,8 @@ export default class Field extends AppComponent {
623
623
  if(!this.canValidate) return;
624
624
  let {keyboardEvents,onKeyEvent} = this.props;
625
625
  const formInstance = this.getForm();
626
- const arg = {key,event,formInstance,field:this.name,formName:this.getFormName(),value:this.getValidRule(),validValue:this.getValidValue(),context:this,isFormField:true,data:{},formInstance};
627
- if(formInstance ){
628
- arg.data = formInstance.getData();
629
- }
626
+ const data = formInstance ? formInstance.getData() : {};
627
+ const arg = {key,event,formInstance,field:this.name,formName:this.getFormName(),value:this.getValidRule(),validValue:this.getValidValue(data),data,context:this,isFormField:true,formInstance};
630
628
  let handler = undefined;
631
629
  if(isObj(keyboardEvents)){
632
630
  handler = keyboardEvents[key];
@@ -0,0 +1,115 @@
1
+ import TextField from "./TextField";
2
+ import PropTypes from "prop-types";
3
+ import { UPPER_CASE } from "$clib/validator";
4
+ import {isNonNullString,defaultStr,isPromise} from "$cutils";
5
+ import React from "$react";
6
+ import { ActivityIndicator } from "react-native-paper";
7
+
8
+ export default class FormIDField extends TextField {
9
+ constructor(props){
10
+ super(props)
11
+ this.autobind();
12
+ }
13
+ UNSAFE_componentWillReceiveProps(nextProps){
14
+ this.newFieldIdValue = undefined;
15
+ return super.UNSAFE_componentWillReceiveProps(nextProps);
16
+ }
17
+ componentDidMount(){
18
+ super.componentDidMount();
19
+ this.fetchNewId(false);
20
+ }
21
+ handleCheckIdError(msg,errorCb){
22
+ this.canCheckAgain = false;
23
+ this.hasError = true;
24
+ if(isNonNullString(msg)) this.onNoValidate(msg,undefined,this,null,null);
25
+ if(isFunction(errorCb)){
26
+ errorCb(e);
27
+ }
28
+ }
29
+
30
+ /*** met à jour la données du numéro de piece */
31
+ fetchNewId(focus){
32
+ const data = defaultObj(this.props.data);
33
+ if(!isNonNullString(this.name)) return undefined;
34
+ const cb = (value)=>{
35
+ if(isNonNullString(value)){
36
+ this.newFieldIdValue = value;
37
+ this.validate({value});
38
+ if(focus) this.focus();
39
+ }
40
+ }
41
+ if(isNonNullString(data[this.name])){
42
+ cb(data[this.name]);
43
+ return data[this.name]
44
+ }
45
+ setTimeout(()=>{
46
+ const fId = typeof this.props.fetchNewId =='function'? this.props.fetchNewId({...this.props,data,columnField:this.name}) : null;
47
+ if(isPromise(fId)){
48
+ return fId.then(cb).catch(e=>{
49
+ console.log(e," fetching new piece id ",this.name);
50
+ });
51
+ }
52
+ return cb(fId);
53
+ },10);
54
+ }
55
+ /*** retourne la valeur validée */
56
+ getValidValue(data){
57
+ const validValue = super.getValidValue(data);
58
+ console.log(data, " is valid value ",data);
59
+ if(!isNonNullString(this.name)) return validValue;
60
+ data[this.name] = defaultStr(data[this.name],validValue,this.newFieldIdValue);
61
+ return validValue;
62
+ }
63
+ isValidRuleDynamic(){
64
+ return true;
65
+ }
66
+ isTextField(){
67
+ return false;
68
+ }
69
+ componentDidUpdate(){
70
+ if(!isNonNullString(this.newFieldIdValue)){
71
+ this.fetchNewId();
72
+ }
73
+ }
74
+ _render(props,setRef){
75
+ delete props.validType;
76
+ if(isNonNullString(this.name) && isObj(props.data) && isNonNullString(props.data[this.name])){
77
+ props.disabled = true;
78
+ props.validType = UPPER_CASE;
79
+ props.defaultValue = props.data[this.name];
80
+ } else {
81
+ props.validType = 'required|'+UPPER_CASE;
82
+ }
83
+ if(typeof props.minLength !=='number'){
84
+ props.minLength = 2;
85
+ }
86
+ const defValue = props.defaultValue = isNonNullString(props.defaultValue)? props.defaultValue : isNonNullString(this.newFieldIdValue)? this.newFieldIdValue : undefined;
87
+ props.validRule = props.validType;
88
+ props.contentContainerProps = Object.assign({},props.contentContainerProps)
89
+ props.contentContainerProps.pointerEvents = defaultStr(props.contentContainerProps.pointerEvents,"auto");
90
+ props.enableCopy = typeof props.enableCopy ==='boolean'? props.enableCopy : (props.defaultValue || this.newFieldIdValue ? true : false);
91
+ const {right} = props;
92
+ props.editable = typeof props.editable =='boolean'? props.editable : typeof props.disabled ==='boolean' ? !!!props.disabled : typeof props.readOnly =="boolean"? !!!props.disabled : false;
93
+ props.right = (props)=>{
94
+ const r = typeof right =='function'? right (props) : React.isValidElement(right)? right : null;
95
+ if(!defValue){
96
+ return <>{r}<ActivityIndicator
97
+ {...props}
98
+ style = {[props.style,{marginRight:10}]}
99
+ /></>
100
+ }
101
+ return r;
102
+ }
103
+ this.setValidRule(props.validType);
104
+ return super._render(props,setRef);
105
+ }
106
+ }
107
+
108
+ /*** le principe est de générer une id et vérifier l'existance deans la bd, jusqu'à retourner un
109
+ * qui n'existe pas en bd
110
+ */
111
+ FormIDField.propTypes = {
112
+ ...TextField.propTypes,
113
+ fetchNewId : PropTypes.func, ///({data,...props}), la fonction permettant de fetch un newId pour la données
114
+ }
115
+ FormIDField.filter = false;//disabled on filter component
@@ -6,7 +6,7 @@ import Checkbox from "./Checkbox";
6
6
  import SelectTableData from "./SelectTableData";
7
7
  import SelectCurrency from "./SelectCurrency";
8
8
  //import IdField from "./IdField";
9
- //import PieceField from "./PieceField";
9
+ import IDField from "./IDField";
10
10
  import Slider from "./Slider";
11
11
  import ColorPicker from "./Color";
12
12
  import Date from "./Date";
@@ -34,7 +34,7 @@ const defFormFields = {
34
34
  ,Switch
35
35
  ,Checkbox
36
36
  //,IdField
37
- //,PieceField
37
+ ,IDField
38
38
  ,Slider
39
39
  ,ColorPicker
40
40
  ,Date
@@ -66,7 +66,7 @@ export {
66
66
  ,Switch
67
67
  ,Checkbox
68
68
  //,IdField
69
- //,PieceField
69
+ ,IDField
70
70
  ,Slider
71
71
  ,ColorPicker
72
72
  ,ColorPicker as Color
@@ -76,4 +76,14 @@ export {
76
76
  ,Tel
77
77
  ,SelectDateFormat
78
78
  ,Html
79
- }
79
+ }
80
+
81
+ export const extendFields = (fields)=>{
82
+ Object.map(fields,(f,i)=>{
83
+ if(React.isComponent(f)){
84
+ defFormFields[i] = f;
85
+ }
86
+ })
87
+ }
88
+
89
+ export const extendFormFields = extendFields;
@@ -10,7 +10,7 @@ import PropTypes from "prop-types";
10
10
  import {renderActions} from "$ecomponents/Dialog/utils";
11
11
  //import {isDocUpdate} from "$database/utils";
12
12
  import {handleBeforeSaveCallback} from "./utils";
13
- import componentsTypes from "./componentsTypes";
13
+ import getComponentFromType from "./componentsTypes";
14
14
  import { keyboardShortcuts } from "../utils";
15
15
  import appConfig from "$capp/config";
16
16
 
@@ -191,9 +191,9 @@ export default class FormDataComponent extends AppComponent{
191
191
  content.push(<Divider key = {index} style={theme.styles.w100}/>)
192
192
  } else if(isObj(field) && field.form !== false) {
193
193
  const name = defaultStr(field.name,field.field,index);
194
- const type = defaultStr(field.jsType,field.type,"text").trim().toLowerCase().replaceAll("_","");
194
+ const type = defaultStr(field.jsType,field.type,"text").trim().toLowerCase().replaceAll(" ","").replaceAll("-","").replaceAll("_","");
195
195
  const isDate = (type.contains('date') || type.contains('time'));
196
- const Component = componentsTypes[type] || componentsTypes.default;
196
+ const Component = getComponentFromType(defaultStr(field.jsType,field.type,"text"));
197
197
  let {defaultValue,useDefaultValueFromData,primaryKey,hidden,renderFormDataField,getMediaQueryStyle,printLabels,queryLimit,selected,value,dataFilesInterest,perm,ignore,form,responsiveProps:customResponsiveProps,...rest} = field;
198
198
  rest = Object.assign({},rest);
199
199
  delete rest.import;
@@ -4,38 +4,49 @@ import Fields from "../Fields";
4
4
  import i18n from "$i18n";
5
5
  import React from "$react";
6
6
 
7
- const componentTypes = {
8
- ...Fields,
9
- id : Fields.IdField,
10
- selecttabledata : Fields.SelectTableData,
11
- idfield : Fields.IdField,
12
- piecefield : Fields.PieceField,
13
- piece : Fields.PieceField,
14
- select : Fields.SelectField,
15
- switch : Fields.Switch,
16
- selectcountry : Fields.SelectCountry,
17
- selectdateformat : Fields.SelectDateFormat,
18
- selectcurrency : Fields.SelectCurrency,
19
- currencyformat : Fields.CurrencyFormat,
20
- dateformat : Fields.SelectDateFormat,
21
- date : Fields.Date,
22
- time : Fields.Time,
23
- datetime : Fields.DateTime,
24
- date2time : Fields.DateTime,
25
- checkbox : Fields.Checkbox,
26
- slider : Fields.Slider,
27
- color : Fields.ColorPicker,
28
- tel : Fields.Tel,
29
- html : Fields.Html,
30
- datafile : Fields.DataFile,
31
- image : Fields.Image,
32
- schedule : Fields.Scheduler,
33
- scheduler : Fields.Scheduler,
34
- default : Fields.TextField,
7
+
8
+ export const getComponentTypes = ()=>{
9
+ return {
10
+ id : Fields.IDField,
11
+ ...Fields,
12
+ selecttabledata : Fields.SelectTableData,
13
+ idfield : Fields.IdField,
14
+ select : Fields.SelectField,
15
+ switch : Fields.Switch,
16
+ selectcountry : Fields.SelectCountry,
17
+ selectdateformat : Fields.SelectDateFormat,
18
+ selectcurrency : Fields.SelectCurrency,
19
+ currencyformat : Fields.CurrencyFormat,
20
+ dateformat : Fields.SelectDateFormat,
21
+ date : Fields.Date,
22
+ time : Fields.Time,
23
+ datetime : Fields.DateTime,
24
+ date2time : Fields.DateTime,
25
+ checkbox : Fields.Checkbox,
26
+ slider : Fields.Slider,
27
+ color : Fields.ColorPicker,
28
+ tel : Fields.Tel,
29
+ html : Fields.Html,
30
+ datafile : Fields.DataFile,
31
+ image : Fields.Image,
32
+ schedule : Fields.Scheduler,
33
+ scheduler : Fields.Scheduler,
34
+ default : Fields.TextField,
35
+ };
36
+ }
37
+ export function getComponentFromType(type){
38
+ const types = getComponentTypes();
39
+ if(!isNonNullString(type)){
40
+ return types.default;
41
+ }
42
+ type = type.trim().toLowerCase().replaceAll(" ","").replaceAll("-","").replaceAll("_","");
43
+ return React.isComponent(types[type]) && types[type] || types.default;
35
44
  };
36
45
 
37
- export default componentTypes;
46
+ export default getComponentFromType;
47
+
38
48
 
49
+ /**** pour interdire qu'on composant FormField soit utilisé en cas de filtre, il suffit de passer au composant FormField, la props filter à false */
39
50
 
40
51
  export const getFilterComponentProps = (_props)=>{
41
52
  let {
@@ -67,6 +78,7 @@ export const getFilterComponentProps = (_props)=>{
67
78
  ...props
68
79
  } = _props;
69
80
  props = defaultObj(props);
81
+ const componentTypes = getComponentTypes();
70
82
  let component = Fields.TextField;
71
83
  type = defaultStr(jsType,type,'text').toLowerCase().replaceAll("_","").replaceAll("-","").trim();
72
84
  const sanitizedType = type.replaceAll("_","").toLowerCase().trim();
@@ -101,7 +113,7 @@ export const getFilterComponentProps = (_props)=>{
101
113
  component = Fields.ColorPicker;
102
114
  } else if(type == 'dateformat' || type =='select_dateformat' || type =='select_date_format') {
103
115
  component = Fields.SelectDateFormat;
104
- } else if(React.isComponent(componentTypes[type])) {
116
+ } else if(React.isComponent(componentTypes[type]) && componentTypes[type] !== false) {
105
117
  component = componentTypes[type];
106
118
  } else if(isNonNullString(props.foreignKeyColumn) && isNonNullString(props.foreignKeyTable)) {
107
119
  component = Fields.SelectTableData;
@@ -112,7 +124,7 @@ export const getFilterComponentProps = (_props)=>{
112
124
  }
113
125
  delete props.dbName;
114
126
  delete props.tableName;
115
- delete props.fieldName;
127
+ delete props.fieldName;
116
128
  }
117
129
  type = type || "text"
118
130
  if(type =='select'){
@@ -91,14 +91,7 @@ export const handleBeforeSaveCallback = (beforeSaveCallback,successCb,arg)=>{
91
91
  }
92
92
  successCb(arg);
93
93
  }).catch((e)=>{
94
- if(isNonNullString(e)){
95
- notify.error(e);
96
- } else if(e){
97
- let ms = defaultStr(e.msg,e.message);
98
- if(isNonNullString(ms)){
99
- notify.error(ms);
100
- }
101
- }
94
+ notify.error(e);
102
95
  })
103
96
  return arg;
104
97
  } else if(isNonNullString(bF)){
@@ -1,5 +1,5 @@
1
1
  export * from "./FormData";
2
-
2
+ export * from "./Fields";
3
3
  export * from "./Form";
4
4
 
5
5
  export {default as List} from "./List";
@@ -36,7 +36,6 @@ const IconButtonComponent = ({
36
36
  const borderColor = theme.colors.outline || theme.colors.divider;
37
37
  const rippleColor = Colors.setAlpha(iconColor,0.32);
38
38
  const buttonSize = size * 1.5;
39
- console.log(iconColor, " is conndddd ",color,rest);
40
39
  const borderStyles = {
41
40
  borderWidth: 0,
42
41
  borderRadius: buttonSize / 2,
@@ -41,7 +41,7 @@ const TableLinKComponent = React.forwardRef((props,ref)=>{
41
41
  const r2 = typeof fetchForeignData === 'function'? fetchForeignData({...args,...defaultObj(a)}) : undefined;
42
42
  if(isPromise(r2)){
43
43
  return r2.then((data)=>{
44
- if(isObj(data) && data[foreignKeyColumn] !== undefined){
44
+ if(isObj(data) && (isNonNullString(foreignKeyColumn) ? data[foreignKeyColumn] !== undefined:true)){
45
45
  navigateToTableData({tableName:foreignKeyTable,data});
46
46
  }
47
47
  });
@@ -81,7 +81,7 @@ export default class TableDataScreenComponent extends FormDataScreen{
81
81
  const f = fields[i];
82
82
  f.type = defaultStr(f.jsType,f.type).toLowerCase();
83
83
  const name = f.field = defaultStr(f.field,i);
84
- if((f.type =='id' || f.type =='piece' || f.unique === true) && f.unique !== false && f.disabled !== true && f.editable !== false && f.readOnly !== true){
84
+ if((f.type =='id' || f.type =='piece' || f.primaryKey || f.unique === true) && f.unique !== false && f.disabled !== true && f.editable !== false && f.readOnly !== true){
85
85
  const {onBlur} = f;
86
86
  f.onBlur = (args)=>{
87
87
  args = {...f,...args,fetch,columnField:name,fieldName:name,id:args.value};
@@ -104,6 +104,7 @@ export default class TableDataScreenComponent extends FormDataScreen{
104
104
  }
105
105
  }).catch((e)=>{
106
106
  if(e && e.status?.toString() == '404') return;
107
+ console.log(e," fetching unique id on table data element id : ",args)
107
108
  const message = defaultStr(e?.message,e?.msg);
108
109
  if(message){
109
110
  context.onNoValidate({...args,msg:message,message,error:e,context,validRule:context.getValidRule()});