@fto-consult/expo-ui 6.52.6 → 6.53.1

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.
Files changed (27) hide show
  1. package/package.json +3 -3
  2. package/src/components/Chart/appexChart/appexChart.html +4 -4
  3. package/src/components/Datagrid/Accordion/Filters.js +2 -7
  4. package/src/components/Datagrid/Common/Common.js +46 -27
  5. package/src/components/Datagrid/{Table → Filters}/Filter.js +18 -14
  6. package/src/components/Datagrid/{Table → Filters}/FiltersMenu.js +1 -1
  7. package/src/components/Datagrid/{Table/Filters.js → Filters/index.js} +19 -24
  8. package/src/components/Datagrid/{Table → Filters}/styles.js +6 -2
  9. package/src/components/Datagrid/SWRDatagrid.js +0 -1
  10. package/src/components/Datagrid/Table/index.js +3 -8
  11. package/src/components/Datagrid/hooks/index.js +7 -1
  12. package/src/components/Dropdown/index.js +2 -3
  13. package/src/components/Filter/index.js +37 -13
  14. package/src/components/Form/Fields/Field.js +11 -6
  15. package/src/components/Form/Fields/SelectField.js +0 -1
  16. package/src/components/Form/Fields/SelectTableData/Component.js +6 -4
  17. package/src/components/Form/FormData/componentsTypes.js +3 -2
  18. package/src/components/List/Virtuoso/index.js +7 -4
  19. package/src/components/Table/Header/Filters.js +37 -0
  20. package/src/components/Table/Header/index.js +3 -2
  21. package/src/components/Table/Headers/index.js +24 -0
  22. package/src/components/Table/VirtuosoTable/index.js +7 -2
  23. package/src/components/Table/index.js +16 -15
  24. package/src/context/Provider.js +5 -2
  25. package/src/screens/Help/openLibraries.js +1 -1
  26. package/src/components/Datagrid/Table/hooks.js +0 -9
  27. /package/src/components/Datagrid/{Table → Filters}/FilterMenu.js +0 -0
@@ -13,20 +13,18 @@ import { Dimensions } from "react-native";
13
13
  import Grid from "$ecomponents/Grid";
14
14
  import { Pressable } from "react-native";
15
15
  import Tooltip from "$ecomponents/Tooltip";
16
+ import { useDatagrid } from "../hooks";
16
17
 
17
18
  const MIN_WIDTH = 250;
18
19
  let windowWidth = Dimensions.get("window").width;
19
20
 
20
- const FiltersAccordionComponent = React.forwardRef((props,ref)=>{
21
- const {filters,isLoading,filteredColumns,children,label,testID:cTestID,filterTitle:customFilterTitle,visible:customVisible,orOperator,andOperator,onToggleFilters,context:customContext,...restProps} = props;
22
- const context = defaultObj(customContext);
21
+ const FiltersAccordionComponent = React.forwardRef(({children,filters,filteredColumns,context,label,testID:cTestID,filterTitle:customFilterTitle,visible:customVisible,orOperator,andOperator,onToggleFilters,...rest},ref)=>{
23
22
  const testID = defaultStr(testID,"RN_AccordionFilters");
24
23
  const [visibleColumns,setVisibleColumns] = React.useState(filteredColumns);
25
24
  const [visible,setVisible] = React.useState(defaultBool(customVisible,false));
26
25
  const valuesRefs = React.useRef({});
27
26
  windowWidth = Dimensions.get("window").width;
28
27
  const innerRef = React.useRef(null);
29
- const rest = defaultObj(restProps);
30
28
  const filterTitle = defaultStr(customFilterTitle,'Filtres');
31
29
  const canHandlerFilterRef = React.useRef(0);
32
30
  const filteredRef = React.useRef({});
@@ -74,9 +72,6 @@ const FiltersAccordionComponent = React.forwardRef((props,ref)=>{
74
72
  {...rest}
75
73
  {...(isObj(valuesRefs.current[key]) ? valuesRefs.current[key] : {})}
76
74
  dynamicRendered
77
- //isLoading = {isLoading && filteredRef.current[key] ? true : false}
78
- orOperator = {defaultBool(orOperator,filter.orOperator,true)}
79
- andOperator = {defaultBool(andOperator,filter.andOperator,true)}
80
75
  onChange = {(arg)=>{
81
76
  if(!arg.action && !arg.operator || !arg.field) return;
82
77
  const canHandle = canHandleFilter(arg);
@@ -15,7 +15,7 @@ import {sortBy,isDecimal,defaultVal,sanitizeSheetName,extendObj,isObjOrArray,isO
15
15
  import {Datagrid as DatagridContentLoader} from "$ecomponents/ContentLoader";
16
16
  import React from "$react";
17
17
  import DateLib from "$lib/date";
18
- import Filter,{canHandleFilter,prepareFilters} from "$ecomponents/Filter";
18
+ import Filter,{canHandleFilter,prepareFilters,compareValues} from "$ecomponents/Filter";
19
19
  import {CHECKED_ICON_NAME} from "$ecomponents/Checkbox";
20
20
  import { COLUMN_WIDTH,DATE_COLUMN_WIDTH,willConvertFiltersToSQL } from "../utils";
21
21
  import { StyleSheet,Dimensions,useWindowDimensions} from "react-native";
@@ -2505,9 +2505,10 @@ export default class CommonDatagridComponent extends AppComponent {
2505
2505
  datagridMenuItems,
2506
2506
  ...restCol
2507
2507
  } = header;
2508
+ this.filteredValues = defaultObj(this.filteredValues);
2508
2509
  restCol = Object.clone(defaultObj(restCol));
2509
2510
  let colFilter = defaultVal(restCol.filter,true);
2510
- field = header.field = restCol.field = defaultStr(header.field,field,headerIndex);
2511
+ const columnField = field = restCol.field = header.field = restCol.field = defaultStr(field,headerIndex);
2511
2512
  delete restCol.filter;
2512
2513
 
2513
2514
  const type = defaultStr(header.jsType,header.type,"text").toLowerCase();
@@ -2533,20 +2534,21 @@ export default class CommonDatagridComponent extends AppComponent {
2533
2534
  width = Math.max(width,minWidth);
2534
2535
  }
2535
2536
  totalWidths +=width;
2536
- widths[header.field] = width;
2537
+ widths[columnField] = width;
2537
2538
  const colProps = {id,key}
2538
- colProps.key = isNonNullString(key)?key : (header.field||("datagrid-column-header-"+headerIndex))
2539
+ colProps.key = isNonNullString(key)?key : (columnField||("datagrid-column-header-"+headerIndex))
2539
2540
  colProps.style = Object.assign({},StyleSheet.flatten(restCol.style));
2540
2541
  if(!visible){
2541
2542
  colProps.style.display = 'none';
2542
2543
  }
2543
- const title = header.text = header.text || header.label || header.title||header.field
2544
- visibleColumnsNames[header.field] = visible ? true : false;
2545
-
2544
+ visibleColumnsNames[columnField] = visible ? true : false;
2545
+ const label = header.label = header.text = restCol.label = header.text && React.isValidElement(header.text,true) ? header.text : header.label && React.isValidElement(header.label,true)? header.label : columnField;
2546
+ const title = label || header.title && React.isValidElement(header.title,true)? header.title : columnField
2547
+
2546
2548
  visibleColumns.push({
2547
2549
  onPress : ()=>{
2548
2550
  setTimeout(() => {
2549
- this.toggleColumnVisibility(header.field);
2551
+ this.toggleColumnVisibility(columnField);
2550
2552
  },100);
2551
2553
  return false;
2552
2554
  },
@@ -2556,9 +2558,6 @@ export default class CommonDatagridComponent extends AppComponent {
2556
2558
  onPress = {(e)=>{console.log(e," is pressed toddd config")}}
2557
2559
  /> : undefined
2558
2560
  });
2559
- restCol.field = header.field;
2560
-
2561
- restCol.label = defaultStr(header.text,header.label) ;
2562
2561
  restCol.type = type;
2563
2562
  if(!restCol.label){
2564
2563
  console.error(header," has not label or text in datagrid",columns,this.props)
@@ -2588,12 +2587,31 @@ export default class CommonDatagridComponent extends AppComponent {
2588
2587
  const sortedProps = isColumnSorted ? {...sortedColumn} : {};
2589
2588
  let filterProps = {};
2590
2589
  if(colFilter){
2591
- const fCol = defaultObj(this.filters[header.field]);
2592
- this.filters[header.field] = fCol;
2593
- filterableColumnsNames.push(header.field);
2590
+ const fCol = defaultObj(this.filters[columnField]);
2591
+ this.filters[columnField] = fCol;
2592
+ filterableColumnsNames.push(columnField);
2594
2593
  delete restCol.sortable;
2594
+ const defaultFilterProps = {
2595
+ operator : fCol.operator,
2596
+ action : defaultStr(fCol.originAction,fCol.action),
2597
+ defaultValue : defaultVal(fCol.defaultValue,restCol.defaultValue),
2598
+ }
2599
+ const filteringVal = this.filteredValues[columnField];
2600
+ if(!isObj(filteringVal)){
2601
+ this.filteredValues[columnField] = defaultFilterProps;
2602
+ } else {
2603
+ if("value" in filteringVal){
2604
+ defaultFilterProps.defaultValue = filteringVal.value;
2605
+ }
2606
+ if("operator" in filteringVal){
2607
+ defaultFilterProps.operator = filteringVal.operator;
2608
+ }
2609
+ if("action" in filteringVal){
2610
+ defaultFilterProps.action = filteringVal.action;
2611
+ }
2612
+ }
2595
2613
  filterProps = {
2596
- ...restCol,
2614
+ ...Object.clone(restCol),
2597
2615
  type,
2598
2616
  columnIndex,
2599
2617
  visibleColumnIndex,
@@ -2602,23 +2620,22 @@ export default class CommonDatagridComponent extends AppComponent {
2602
2620
  sortedColumn :sortedProps,///les props de la columns triée
2603
2621
  sortedProps,
2604
2622
  width,
2605
- columnField : field,
2623
+ columnField,
2624
+ field,
2606
2625
  index : headerIndex,
2607
2626
  visible,
2608
- key : header.field,
2609
- label : defaultStr(header.label,header.text),
2610
- orOperator : filterOrOperator,
2611
- andOperator : filterAndOperator,
2627
+ key : columnField,
2628
+ label,
2629
+ orOperator : defaultBool(filterOrOperator,header.orOperator,true),
2630
+ andOperator : defaultBool(this.props.filterAndOperator,header.andOperator,true),
2612
2631
  searchIconTooltip : 'Filtre',
2613
2632
  searchIcon : 'filter_list',
2614
- defaultValue : defaultVal(fCol.defaultValue,restCol.defaultValue),
2615
- name : header.field,
2633
+ name : columnField,
2616
2634
  onClearFilter : this.onClearFilter.bind(this),
2617
2635
  onChange : this.onFilterChange.bind(this),
2618
- operator : fCol.operator,
2619
- action : defaultStr(fCol.originAction,fCol.action),
2636
+ ...defaultFilterProps,
2620
2637
  };
2621
- this.currentFilteringColumns[header.field] = filterProps;
2638
+ this.currentFilteringColumns[columnField] = filterProps;
2622
2639
  this.prepareFilter(filterProps,headerFilters);
2623
2640
  }
2624
2641
  this.prepareColumn({
@@ -2637,11 +2654,11 @@ export default class CommonDatagridComponent extends AppComponent {
2637
2654
  //columnDef : header,
2638
2655
  index : headerIndex,
2639
2656
  filterProps,
2640
- key : header.field,
2657
+ key : columnField,
2641
2658
  filter :colFilter,
2642
2659
  },headerFilters)
2643
2660
 
2644
- if(this.props.groupable !== false && header.groupable !== false && !this.isSelectableColumn(header,header.field) && !this.isIndexColumn(header,header.field)){
2661
+ if(this.props.groupable !== false && header.groupable !== false && !this.isSelectableColumn(header,columnField) && !this.isIndexColumn(header,columnField)){
2645
2662
  const isInSectionListHeader = isObj(sListColumns[field]);
2646
2663
  if(isInSectionListHeader){
2647
2664
  nSectionList[field] = {
@@ -2696,6 +2713,8 @@ export default class CommonDatagridComponent extends AppComponent {
2696
2713
  this.preparedColumns.sectionListColumns = sectionListColumns;
2697
2714
  this.preparedColumns.sectionListColumnsMenuItems = sectionListColumnsMenuItems;
2698
2715
  this.preparedColumns.filterableColumnsNames = filterableColumnsNames;
2716
+ this.preparedColumns.filteredValues = this.filteredValues;
2717
+ this.preparedColumns.filtersByColumnsNames = this.currentFilteringColumns; //l'objet contenant pour chaqun des field name, le filterProp correspondant
2699
2718
  return this.preparedColumns;
2700
2719
  }
2701
2720
  getFooterValues(){
@@ -1,22 +1,21 @@
1
1
  import React from "$react";
2
2
  import View from "$ecomponents/View";
3
3
  import Label from "$ecomponents/Label";
4
- import { useDatagrid } from "./hooks";
4
+ import { useDatagrid } from "../hooks";
5
5
  import styles from "./styles";
6
6
  import {defaultStr} from "$cutils";
7
7
  import theme from "$theme";
8
- import Filter, {canHandleFilter} from "$ecomponents/Filter";
8
+ import Filter from "$ecomponents/Filter";
9
9
  import { getMenuStyle } from "./styles";
10
10
 
11
- export default function DatagridTableFilterComponent({columnField,label,onChange,text,testID,...rest}){
12
- const {context,filteredColumns} = useDatagrid();
11
+ export default function DatagridTableFilterComponent({columnField,visible:cVisible,label,text,testID,...rest}){
12
+ const {context,filteredValues,filteredColumns} = useDatagrid();
13
13
  const [visible,setVisible] = React.useState(!!filteredColumns[columnField]);
14
14
  testID = defaultStr(testID,"RN_DatagridTableFilterComponent");
15
15
  React.useEffect(()=>{
16
16
  if(typeof context?.on ==='function'){
17
17
  const onToggleVisibility = ({columnField:cField,visible:nVisible})=>{
18
18
  if(columnField === cField && visible !== nVisible){
19
- console.log("toggle ",columnField,nVisible);
20
19
  setVisible(nVisible);
21
20
  }
22
21
  }
@@ -26,25 +25,30 @@ export default function DatagridTableFilterComponent({columnField,label,onChange
26
25
  }
27
26
  }
28
27
  },[context]);
28
+ React.useEffect(()=>{
29
+ return ()=>{
30
+ }
31
+ },[])
32
+ const filteredProps = Object.assign({},filteredValues[columnField]);
33
+ if("value" in filteredProps){
34
+ filteredProps.defaultValue = filteredProps.value;
35
+ delete filteredProps.value;
36
+ }
29
37
  label = label || text;
30
38
  return <View testID={testID+"_DatagridFilterTableContainer"} style={[styles.filter,getMenuStyle(),!visible && styles.hidden]}>
31
39
  <View testID={testID+"_DatagridTableFilterContent"} style={[theme.styles.row,theme.styles.alignItemsCenter,theme.styles.justifyContentStart,!visible && styles.hidden]}>
32
- {React.isValidElement(label,true) ? <Label numberOfLines={1} style={[styles.filterLabel]}>
40
+ {React.isValidElement(label,true) ? <Label style={[styles.filterLabel]}>
33
41
  {label}
34
- Un label
35
42
  </Label>:null}
36
43
  <Filter
37
44
  {...rest}
45
+ {...filteredProps}
38
46
  withLabel={false}
47
+ containerProps = {{
48
+ style : [styles.filterContainer]
49
+ }}
39
50
  testID={testID+"_DatagridFilterComponent_"+columnField}
40
51
  anchorProps = {{size:20,style:[theme.styles.noMargin,theme.styles.noPadding]}}
41
- onChange = {(...args)=>{
42
- if(!visible){
43
- return;
44
- }
45
- console.log("calling on change ",args);
46
- onChange && onChange(...args);
47
- }}
48
52
  />
49
53
  </View>
50
54
  </View>;
@@ -1,6 +1,6 @@
1
1
  import Menu from "$ecomponents/Menu";
2
2
  import Icon from "$ecomponents/Icon";
3
- import { useDatagrid } from "./hooks";
3
+ import { useDatagrid } from "../hooks";
4
4
  import {Pressable} from "react-native";
5
5
  import {defaultStr} from "$cutils";
6
6
  import theme from "$theme";
@@ -6,18 +6,20 @@ import { StyleSheet,ScrollView } from "react-native";
6
6
  import Label from "$ecomponents/Label";
7
7
  import Filter from "./Filter";
8
8
  import FiltersMenu from "./FiltersMenu";
9
- import {useDatagrid} from "./hooks";
9
+ import {useDatagrid} from "../hooks";
10
10
 
11
11
  export default function DatagridTableFiltersComponent({orOperator,andOperator,testID}){
12
12
  testID = defaultStr(testID,"RN_DatagridTableFiltersComponent")
13
- const {filters,filteredColumns,filterableColumnsNames} = useDatagrid();
14
- const [visibleColumns,context,setVisibleColumns] = React.useState(filteredColumns);
15
- const valuesRefs = React.useRef({});
13
+ const {context,filteredColumns,filtersByColumnsNames} = useDatagrid();
14
+ const fArray = React.useMemo(()=>Object.keys(filteredColumns).filter(v=>!!filteredColumns[v]),[]);
15
+ const [visibleColumns,setVisibleColumns] = React.useState(fArray);
16
16
  React.useEffect(()=>{
17
17
  if(typeof context?.on ==='function'){
18
18
  const onToggleVisibility = ({columnField,visible})=>{
19
- if(visibleColumns[columnField] !== visible){
20
- setVisibleColumns({...visibleColumns,[columnField]:visible});
19
+ const nVisible = visibleColumns.includes(columnField);
20
+ if(nVisible !== visible){
21
+ const nVisibleColumns = nVisible ? [...visibleColumns].filter((v)=>v !== columnField) : [...visibleColumns,columnField];
22
+ setVisibleColumns(nVisibleColumns)
21
23
  }
22
24
  }
23
25
  context.on("toggleFilterColumnVisibility",onToggleVisibility);
@@ -26,25 +28,18 @@ export default function DatagridTableFiltersComponent({orOperator,andOperator,te
26
28
  }
27
29
  }
28
30
  },[context]);
29
- const {content} = React.useStableMemo(()=>{
31
+ const content = React.useStableMemo(()=>{
30
32
  const content = [];
31
- Object.map(filters,(filter,index)=>{
32
- if(isObj(filter)){
33
- const {filter:isFiltered,...rest} = filter;
34
- if(isFiltered === false) return null;
35
- const columnField = defaultStr(filter.field,filter.columnField,String(index));
36
- if(!columnField || !visibleColumns[columnField]) return null;
37
- content.push(<Filter
38
- {...rest}
39
- //{...(isObj(valuesRefs.current[columnField]) ? valuesRefs.current[columnField] : {})}
40
- columnField={columnField}
41
- dynamicRendered={false}
42
- orOperator = {defaultBool(orOperator,filter.orOperator,true)}
43
- andOperator = {defaultBool(andOperator,filter.andOperator,true)}
44
- />)
45
- }
46
- })
47
- return {content};
33
+ visibleColumns.map((columnField)=>{
34
+ if(!columnField || !isObj(filtersByColumnsNames[columnField])) return;
35
+ const filter = filtersByColumnsNames[columnField];
36
+ content.push(<Filter
37
+ {...filter}
38
+ columnField={columnField}
39
+ dynamicRendered={true}
40
+ />)
41
+ });
42
+ return content;
48
43
  },[visibleColumns])
49
44
  return <ScrollView horizontal testID={testID+"_FiltersScrollView"}>
50
45
  <View testID={testID} style = {[theme.styles.row,styles.container,theme.styles.rowWrap,theme.styles.justifyStart,theme.styles.alignItemsCenter]}>
@@ -13,8 +13,12 @@ const styles = StyleSheet.create({
13
13
  opacity : 0,
14
14
  },
15
15
  filterLabel : {
16
- fontSize:11,
17
- }
16
+ fontSize:13,
17
+ marginRight : 7,
18
+ },
19
+ filterContainer : {
20
+ width : undefined,
21
+ },
18
22
  });
19
23
 
20
24
  export const getMenuStyle = (style)=>([styles.menuItem,{backgroundColor:theme.colors.surface},style]);
@@ -193,7 +193,6 @@ const SWRDatagridComponent = React.forwardRef((props,ref)=>{
193
193
  if(showProgressRef.current ===false){
194
194
  opts.showError = false;
195
195
  }
196
- console.log("will fetch ",url,opts);
197
196
  if(typeof fetcher =='function'){
198
197
  return fetcher(url,opts);
199
198
  }
@@ -15,7 +15,7 @@ import Footer from "../Footer/Footer";
15
15
  import theme from "$theme";
16
16
  import Table,{styles as tableStyles} from "$ecomponents/Table";
17
17
  import DatagridProvider from "../hooks/Provider";
18
- import Filters from "./Filters";
18
+ import Filters from "../Filters";
19
19
 
20
20
 
21
21
  const DatagridFactory = (Factory)=>{
@@ -298,11 +298,6 @@ const DatagridFactory = (Factory)=>{
298
298
  /> : null}
299
299
  {rPagination}
300
300
  {progressBar}
301
- <Filters
302
- testID={testID+"_DatagridTableHeaderFilters"}
303
- orOperator = {this.props.filterOrOperator}
304
- andOperator = {this.props.filterAndOperator}
305
- />
306
301
  </View>
307
302
  {canRenderChart ?
308
303
  <View testID={testID+"_ChartContainer"} {...chartContainerProps} style={[theme.styles.w100,chartContainerProps.style]}>
@@ -320,7 +315,7 @@ const DatagridFactory = (Factory)=>{
320
315
  renderItem = {this.renderFlashListItem.bind(this)}
321
316
  renderSectionHeader = {this.renderFlashListItem.bind(this)}
322
317
  hasFooters = {hasFootersFields && !canRenderChart ? true : false}
323
- showFilters = {false}
318
+ showFilters = {showFilters}
324
319
  showFooters = {showFooters && !canRenderChart ? true : false}
325
320
  showHeaders = { canRenderChart ? !!showFilters : true}
326
321
  headerCellContainerProps = {{
@@ -340,7 +335,7 @@ const DatagridFactory = (Factory)=>{
340
335
  data = {this.state.data}
341
336
  footers = {this.getFooterValues()}
342
337
  renderHeaderCell={this.renderHeaderCell.bind(this)}
343
- //renderFilterCell={this.renderFilterCell.bind(this)}
338
+ renderFilterCell={this.renderFilterCell.bind(this)}
344
339
  renderFooterCell={this.renderFooterCell.bind(this)}
345
340
  renderEmpty = {this.renderEmpty.bind(this)}
346
341
  />}
@@ -7,7 +7,13 @@ export const useDatagrid = x=> {
7
7
  if(!t || !t?.context || !t?.context?.state || !t?.context?.state?.data){
8
8
  throw "Le composant Datagrid actions doit être enfant d'un contexe de datagrid valide";
9
9
  }
10
- return t;
10
+ const {context} = t;
11
+ const isLoading = context && context.isLoading() || false;
12
+ const r = typeof context?.getPreparedColumns =='function'? context?.getPreparedColumns() : {};
13
+ const columns = typeof context?.getColumns =='function' && context.getColumns() || {}
14
+ r.filtersByColumnsNames = isObj(r.filtersByColumnsNames) ? r.filtersByColumnsNames : {};
15
+ r.filteredValues = isObj(r.filteredValues) ? r.filteredValues : {};
16
+ return {...t,...r,isLoading,context,columns}
11
17
  };
12
18
  export const useDatagridContext = ()=>{
13
19
  return useDatagrid()?.context;
@@ -111,7 +111,6 @@ class DropdownComponent extends AppComponent {
111
111
  const previousSelected = this.state.selected;
112
112
  const prevValueKey = this.getValueKey(previousSelected);
113
113
  const prevItem = prevValueKey ? this.state.valuesKeys[prevValueKey] : null;
114
- //if(this.countEee ===5) return
115
114
  return this.setState(nState,()=>{
116
115
  ///vérifie s'il y a eu changement call on change par exemple
117
116
  let selectedItem = null;
@@ -151,7 +150,7 @@ class DropdownComponent extends AppComponent {
151
150
  if(this.props.onChange){
152
151
  this.props.onChange({value:this.state.selected,selectedKey:valueKey,selectedItems : this.getSelectedItems(),selectedItem,item:selectedItem,items:this.state.data});
153
152
  }
154
- });
153
+ },force);
155
154
  }
156
155
  selectItem ({value,select,valueKey}){
157
156
  let selected = this.canHandleMultiple ? [...this.state.selected] : undefined;
@@ -604,7 +603,7 @@ class DropdownComponent extends AppComponent {
604
603
  const {items,defaultValue,selected} = nextProps;
605
604
  if(!React.areEquals(items,this.props.items)){
606
605
  const nState = this.prepareItems({items,defaultValue,selected});
607
- return this.updateSelected(nState);
606
+ return this.updateSelected(nState,true);
608
607
  }
609
608
  let value = this.prepareSelected({defaultValue});
610
609
  let areEquals = !this.canHandleMultiple ? this.compare(value,this.state.selected) : false;
@@ -22,7 +22,6 @@ const manualRunKey = "manual-run";
22
22
 
23
23
  export * from "$cfilters";
24
24
 
25
-
26
25
  /***** Coposant Filter, pour les filtres de données */
27
26
  export default class Filter extends AppComponent {
28
27
  constructor(props) {
@@ -117,9 +116,12 @@ export default class Filter extends AppComponent {
117
116
  const t = defaultStr(this.type,this.props.type).toLowerCase();
118
117
  return t =="number" || t =='decimal' ? true : false;
119
118
  }
119
+ compareValues(v1,v2,...args){
120
+ return compareValues(this.prepareValue(v1),this.prepareValue(v2),...args);
121
+ }
120
122
  onFilterValidate(arg){
121
123
  arg = defaultObj(arg);
122
- if(JSON.stringify(this.state.defaultValue) === JSON.stringify(arg.value)){
124
+ if(this.compareValues(this.state.defaultValue, arg.value)){
123
125
  return;
124
126
  }
125
127
  this.setState({defaultValue:arg.value},()=>{
@@ -168,25 +170,34 @@ export default class Filter extends AppComponent {
168
170
  if(!action){
169
171
  action = this.getDefaultAction(type);
170
172
  }
173
+ let defaultValue = defaultVal(this.props.defaultValue);
171
174
  operator = defaultVal(operator,"$and");
172
- return {actions,action,ignoreCase,operator,operators,manualRun:defaultBool(this.props.manualRun,false),defaultValue:defaultVal(this.props.defaultValue),isTextFilter};
175
+ if(actions == _inActions || type.contains("select") || this.props.multiple){
176
+ defaultValue = isNonNullString(defaultValue)? defaultValue.split(",") : Array.isArray(defaultValue)? defaultValue : !isNullOrEmpty(defaultValue)? [defaultValue] : {};
177
+ }
178
+ return {actions,action,ignoreCase,operator,operators,manualRun:defaultBool(this.props.manualRun,false),defaultValue,isTextFilter};
179
+ }
180
+ /**** prepare la valeur afin qu'elle soit soumise au composant qui implémente le filtre en question */
181
+ prepareValue(value){
182
+ if(!isObjOrArray(value) && (isNullOrEmpty(value,true) || String(value).trim() ==='undefined') ){
183
+ value = undefined;
184
+ }
185
+ if(this.isDecimal()){
186
+ value = parseDecimal(value)
187
+ if(value == 0){
188
+ value = undefined;
189
+ }
190
+ }
191
+ return value;
173
192
  }
174
193
  fireValueChanged (forceRun){
175
194
  if(this.willRunManually() && !forceRun) return;
176
195
  let {defaultValue:value,action,ignoreCase,operator} = this.state;
177
196
  let force = forceRun ===true ? true : false;
178
- if(!isObjOrArray(value) && (isNullOrEmpty(value,true) || value ==='undefined') ){
179
- value = undefined;
180
- }
197
+ value = this.prepareValue(value);
181
198
  if(action =="$today" || action =='$yesterday'){
182
199
  force = true;
183
200
  }
184
- if(this.isDecimal()){
185
- value = parseDecimal(value)
186
- if(value == 0){
187
- value = undefined;
188
- }
189
- }
190
201
  const prev = JSON.stringify(this.previousRef.current), current = {value,operator,action,ignoreCase};
191
202
  if(prev == JSON.stringify(current) && (force !== true)){
192
203
  return this;
@@ -229,6 +240,9 @@ export default class Filter extends AppComponent {
229
240
  super.componentDidUpdate();
230
241
  this.canBindEvent = true;
231
242
  }
243
+ componentDidMount(){
244
+ super.componentDidMount();
245
+ }
232
246
  setIgnoreCase(ignoreCase){
233
247
  if(!(this.searchFilter.current) ) return;
234
248
  if(ignoreCase === this.state.ignoreCase) return;
@@ -689,4 +703,14 @@ Filter.propTypes = {
689
703
  /**** lorsque le contenu du filtre est réinitialisé */
690
704
  onClearFilter : PropTypes.func,
691
705
  onResetFilter : PropTypes.func, //idem à onClearFilter
692
- }
706
+ }
707
+ /****
708
+ compare
709
+ */
710
+ export const compareValues = (v1,v2)=>{
711
+ if(v1 === v2) return true;
712
+ if(Array.isArray(v1) && v1.length ==0 || v1 === null || v1 =="" || String(v1).trim() =="") v1 = undefined;
713
+ if(Array.isArray(v2) && v2.length ==0 || v2 === null || v2 == "" || String(v2).trim() =="") v2 = undefined;
714
+ return v1 === v2 || JSON.stringify(v1) === JSON.stringify(v2);
715
+ }
716
+ Filter.compareValues = compareValues;
@@ -203,9 +203,8 @@ export default class Field extends AppComponent {
203
203
  Object.defineProperties(this,{
204
204
  name : {value:name,override:false,writable:false},
205
205
  formName : {value:formName,override:false,writable : false},
206
- canValidate : {value : defaultVal(props.validate,true),override:false,writable:false},
207
206
  })
208
- if(this.canValidate !== false){
207
+ if(this.canRegisterField()){
209
208
  Forms.trigger("registerField",name,formName,this);
210
209
  this.initObservers();
211
210
  }
@@ -227,6 +226,12 @@ export default class Field extends AppComponent {
227
226
  this.state.wrapperStyle = this.getMediaQueryUpdateStyle();
228
227
  this.state.currentMedia = Dimensions.getDimensionsProps().currentMedia;
229
228
  }
229
+ canRegisterField(){
230
+ return !this.isFilter() && this.canValidate();
231
+ }
232
+ canValidate(){
233
+ return this.props.validate !== false;
234
+ }
230
235
  validatorBeforeValidate({value,validRule,validParams,event,...rest}){
231
236
  let _result = undefined;
232
237
  this.trigger.call(this,"beforeValidate",{...defaultObj(rest),value,name:this.name,field:this.name,formName:this.formName,context:this,event,validRule,validParams},(result)=>{
@@ -541,7 +546,7 @@ export default class Field extends AppComponent {
541
546
  validate ({value,event,...rest}){
542
547
  value = this.parseDecimal(value);
543
548
  this.validatingValue = value;
544
- if((!this.canValidate) && !this.isSelectField()){
549
+ if((!this.canValidate()) && !this.isSelectField()){
545
550
  if(this._isInitialized && !this.hasValueChanged(value)) {
546
551
  return;
547
552
  }
@@ -618,7 +623,7 @@ export default class Field extends AppComponent {
618
623
  componentDidMount (validate){
619
624
  super.componentDidMount();
620
625
  this.mediaQueryUpdateStyleSubscription = addMediaQueryUpdateStyeSubscription(this.doUpdateMediaQueryStyle.bind(this));
621
- if(this.canValidate !== false){
626
+ if(this.canRegisterField()){
622
627
  Forms.trigger("registerField",this.getName(),this.getFormName(),this);
623
628
  }
624
629
  if(defaultVal(validate,true) && !this.isFilter()) this.validate({context:this,value:defaultVal(this.props.defaultValue)});
@@ -631,7 +636,7 @@ export default class Field extends AppComponent {
631
636
  if(this.mediaQueryUpdateStyleSubscription && this.mediaQueryUpdateStyleSubscription?.remove){
632
637
  this.mediaQueryUpdateStyleSubscription.remove();
633
638
  }
634
- if(this.canValidate !== false){
639
+ if(this.canRegisterField()){
635
640
  Forms.trigger("unregisterField",this.getName(),this.getFormName());
636
641
  }
637
642
  }
@@ -656,7 +661,7 @@ export default class Field extends AppComponent {
656
661
  }
657
662
  onKeyEvent(key,event){
658
663
  let form = this.getForm();
659
- if(!this.canValidate) return;
664
+ if(!this.canValidate()) return;
660
665
  let {keyboardEvents,onKeyEvent} = this.props;
661
666
  const formInstance = this.getForm();
662
667
  const data = formInstance ? formInstance.getData() : {};
@@ -25,7 +25,6 @@ export default class FormSelectField extends Field{
25
25
  this.validate({context:this,value});
26
26
  }
27
27
  return;
28
-
29
28
  }
30
29
  getDefaultValue(){
31
30
  if(this._field){
@@ -215,14 +215,16 @@ const TableDataSelectField = React.forwardRef(({foreignKeyColumn,isStructData,ge
215
215
  if(Array.isArray(foreignKeyLabel)){
216
216
  let itl = "";
217
217
  foreignKeyLabel.map(fk=>{
218
- if(!fk) return;
219
- const itv = p.item[fk];
220
- itl+= (itl?" ":"")+ (typeof itv =='number' && itv || defaultStr(itv))
218
+ if(!isNonNullString(fk)) return;
219
+ let itv = p.item[fk];
220
+ if(typeof itv =='number'){
221
+ itv = String(itv);
222
+ }
223
+ itl+= (itl?" ":"")+ (itv || defaultStr(itv))
221
224
  })
222
225
  if(itl){
223
226
  itemLabel = itl;
224
227
  }
225
-
226
228
  }
227
229
  if(!itemLabel && isNonNullString(foreignKeyLabel)){
228
230
  itemLabel = defaultStr(p.item[foreignKeyLabel] !== undefined && p.item[foreignKeyLabel] !== null && p.item[foreignKeyLabel].toString(), p.item[foreignKeyColumn] !== undefined && p.item[foreignKeyColumn] !== null && p.item[foreignKeyColumn].toString());
@@ -92,6 +92,7 @@ export const getFilterComponentProps = (_props)=>{
92
92
  const sanitizedType = type.replaceAll("_","").toLowerCase().trim();
93
93
  props = defaultObj(props);
94
94
  props.label = defaultStr(label,text);
95
+ const SelectTableData = React.isComponent(componentTypes['selecttabledata']) ? componentTypes['selecttabledata'] : componentTypes.SelectTableData
95
96
  if(sanitizedType.startsWith("select")){
96
97
  props.inputProps = Object.assign({},props.inputProps);
97
98
  props.inputProps.placeholder = defaultStr(props.inputProps.placeholder,i18n.lang("search.."))
@@ -99,7 +100,7 @@ export const getFilterComponentProps = (_props)=>{
99
100
  if(sanitizedType ==='selectcountry'){
100
101
  component = componentTypes.SelectCountry;
101
102
  } else if(sanitizedType ==='selecttabledata'){
102
- component = componentTypes.SelectTableData;
103
+ component = SelectTableData;
103
104
  } else if(React.isComponent(componentTypes[type])){
104
105
  component = componentTypes[type];
105
106
  } else if(React.isComponent(componentTypes[sanitizedType])){
@@ -122,7 +123,7 @@ export const getFilterComponentProps = (_props)=>{
122
123
  } else if(type == 'dateformat' || type =='select_dateformat' || type =='select_date_format') {
123
124
  component = componentTypes.SelectDateFormat;
124
125
  } else if(isNonNullString(props.foreignKeyColumn) && isNonNullString(props.foreignKeyTable)) {
125
- component = componentTypes.SelectTableData;
126
+ component = SelectTableData;
126
127
  type = "select";
127
128
  } else if(React.isComponent(componentTypes[type]) && componentTypes[type] !== false) {
128
129
  component = componentTypes[type];