@fto-consult/expo-ui 2.19.8 → 2.20.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.
- package/package.json +2 -2
- package/src/components/Datagrid/Common/Common.js +63 -15
- package/src/components/Date/FormatSelector.js +99 -0
- package/src/components/Date/index.js +3 -0
- package/src/components/Form/Fields/SelectCountry.js +3 -1
- package/src/components/Form/Fields/SelectDateFormat.js +46 -0
- package/src/components/Form/Fields/index.js +3 -0
- package/src/components/Form/FormData/FormData.js +2 -2
- package/src/components/Form/FormData/componentsTypes.js +9 -2
- package/src/components/Snackbar/index.js +3 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fto-consult/expo-ui",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.20.1",
|
|
4
4
|
"description": "Bibliothèque de composants UI Expo,react-native",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
"@emotion/native": "^11.10.0",
|
|
62
62
|
"@expo/html-elements": "^0.2.0",
|
|
63
63
|
"@expo/vector-icons": "^13.0.0",
|
|
64
|
-
"@fto-consult/common": "^1.
|
|
64
|
+
"@fto-consult/common": "^1.23.4",
|
|
65
65
|
"@gorhom/portal": "^1.0.14",
|
|
66
66
|
"@react-native-async-storage/async-storage": "~1.17.3",
|
|
67
67
|
"@react-native-community/datetimepicker": "6.5.2",
|
|
@@ -37,6 +37,7 @@ import {Flag} from "$ecomponents/Countries"
|
|
|
37
37
|
import View from "$ecomponents/View";
|
|
38
38
|
import {Menu} from "$ecomponents/BottomSheet";
|
|
39
39
|
import {styles as tableStyles} from "$ecomponents/Table";
|
|
40
|
+
import {DialogProvider} from "$ecomponents/Form/FormData";
|
|
40
41
|
|
|
41
42
|
export const arrayValueSeparator = ", ";
|
|
42
43
|
|
|
@@ -117,6 +118,7 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
117
118
|
sectionListHeaderFooters : {value : {}},
|
|
118
119
|
sectionListDataSize : {value : {current : 0}},
|
|
119
120
|
enablePointerEventsRef : {value : {current:false}},
|
|
121
|
+
configureSectionListSelectedValues : {value : {}},
|
|
120
122
|
sectionListColumnsSize : {value : {current:0}}, //la taille du nombre d'éléments de section dans les colonnes
|
|
121
123
|
})
|
|
122
124
|
this.isLoading = this.isLoading.bind(this);
|
|
@@ -993,6 +995,46 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
993
995
|
}
|
|
994
996
|
return null;
|
|
995
997
|
}
|
|
998
|
+
/*** configure la */
|
|
999
|
+
configureSectionListColumn(column){
|
|
1000
|
+
if(!isObj(column) || !isNonNullString(column.field) || !isObj(this.state.columns[column.field])){
|
|
1001
|
+
return Promise.reject({message : 'type de colonne invalide, impossible de configurer la colonne, pour permettre qu\elle soit ajoutée dans les colonnes de groupe du tableau'})
|
|
1002
|
+
}
|
|
1003
|
+
const col = this.state.columns[column.field];
|
|
1004
|
+
const type = defaultStr(col.jsType,col.type).toLowerCase();
|
|
1005
|
+
if(type.contains("date") || type =='time'){
|
|
1006
|
+
return new Promise((resolve,reject)=>{
|
|
1007
|
+
DialogProvider.open({
|
|
1008
|
+
title : 'Format de date',
|
|
1009
|
+
fields : {
|
|
1010
|
+
dateFormat : {
|
|
1011
|
+
type : 'select_dateformat',
|
|
1012
|
+
required : true,
|
|
1013
|
+
text : 'Sélectionnez un format de date',
|
|
1014
|
+
defaultValue : defaultStr(this.configureSectionListSelectedValues[column.field],"dd/mm/yyyy"),
|
|
1015
|
+
}
|
|
1016
|
+
},
|
|
1017
|
+
onCancelButtonPress : ()=>{
|
|
1018
|
+
DialogProvider.close();
|
|
1019
|
+
reject({msg:'aucun format sélectionné'})
|
|
1020
|
+
},
|
|
1021
|
+
actions : [{
|
|
1022
|
+
text : "Sélectionnez",
|
|
1023
|
+
icon : "check",
|
|
1024
|
+
onPress : ({data})=>{
|
|
1025
|
+
column.format = data.dateFormat;
|
|
1026
|
+
this.configureSectionListSelectedValues[column.field] = data.dateFormat;
|
|
1027
|
+
DialogProvider.close();
|
|
1028
|
+
setTimeout(()=>{
|
|
1029
|
+
resolve(column);
|
|
1030
|
+
},100)
|
|
1031
|
+
},
|
|
1032
|
+
}]
|
|
1033
|
+
})
|
|
1034
|
+
})
|
|
1035
|
+
}
|
|
1036
|
+
return Promise.resolve(column);
|
|
1037
|
+
}
|
|
996
1038
|
toggleColumnInSectionList(columnName){
|
|
997
1039
|
if(!isNonNullString(columnName) || !isObj(this.state.columns[columnName])) return;
|
|
998
1040
|
if(!isObj(this.state.sectionListColumns) || !Array.isArray(this.preparedColumns?.sectionListColumnsMenuItems))return;
|
|
@@ -1002,16 +1044,24 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
1002
1044
|
if(isObj(sectionListColumns[columnName])){
|
|
1003
1045
|
delete sectionListColumns[columnName];
|
|
1004
1046
|
} else {
|
|
1005
|
-
sectionListColumns[columnName] = {};
|
|
1006
|
-
}
|
|
1007
|
-
const
|
|
1008
|
-
|
|
1009
|
-
this.
|
|
1010
|
-
this.
|
|
1011
|
-
this.
|
|
1047
|
+
sectionListColumns[columnName] = {field:columnName};
|
|
1048
|
+
}
|
|
1049
|
+
const cb =()=>{
|
|
1050
|
+
const {sectionListColumns:pSListColumns} = this.prepareColumns({sectionListColumns});
|
|
1051
|
+
this.setIsLoading(true,()=>{
|
|
1052
|
+
this.prepareData({data:this.INITIAL_STATE.data,sectionListColumns:pSListColumns},(state)=>{
|
|
1053
|
+
this.setState({...state,sectionListColumns:pSListColumns},()=>{
|
|
1054
|
+
this.setIsLoading(false,false);
|
|
1055
|
+
});
|
|
1012
1056
|
});
|
|
1013
|
-
});
|
|
1014
|
-
}
|
|
1057
|
+
},true);
|
|
1058
|
+
}
|
|
1059
|
+
setTimeout(() => {
|
|
1060
|
+
if(!isObj(sectionListColumns[columnName])){
|
|
1061
|
+
return cb();
|
|
1062
|
+
}
|
|
1063
|
+
return this.configureSectionListColumn(sectionListColumns[columnName]).then(cb).catch(notify.error)
|
|
1064
|
+
}, 100);
|
|
1015
1065
|
}
|
|
1016
1066
|
removeAllColumnsInSectionList(){
|
|
1017
1067
|
const {sectionListColumns} = this.prepareColumns({sectionListColumns:{}});
|
|
@@ -1050,7 +1100,7 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
1050
1100
|
onPress : ()=>{
|
|
1051
1101
|
setTimeout(()=>{
|
|
1052
1102
|
this.removeAllColumnsInSectionList();
|
|
1053
|
-
},
|
|
1103
|
+
},100)
|
|
1054
1104
|
}
|
|
1055
1105
|
},
|
|
1056
1106
|
...m,
|
|
@@ -1129,7 +1179,7 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
1129
1179
|
onPress : ()=>{
|
|
1130
1180
|
setTimeout(() => {
|
|
1131
1181
|
this.toggleColumnVisibility(header.field);
|
|
1132
|
-
},
|
|
1182
|
+
},100);
|
|
1133
1183
|
return false;
|
|
1134
1184
|
},
|
|
1135
1185
|
title : title,
|
|
@@ -1230,9 +1280,7 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
1230
1280
|
sectionListColumnsMenuItems.push({
|
|
1231
1281
|
field,
|
|
1232
1282
|
onPress : ()=>{
|
|
1233
|
-
|
|
1234
|
-
this.toggleColumnInSectionList(field);
|
|
1235
|
-
},300)
|
|
1283
|
+
this.toggleColumnInSectionList(field);
|
|
1236
1284
|
return false;
|
|
1237
1285
|
},
|
|
1238
1286
|
title : title,
|
|
@@ -1851,7 +1899,7 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
1851
1899
|
}
|
|
1852
1900
|
cb && setTimeout(() => {
|
|
1853
1901
|
cb();
|
|
1854
|
-
},
|
|
1902
|
+
}, 200);
|
|
1855
1903
|
}
|
|
1856
1904
|
isAllRowsSelected(update){
|
|
1857
1905
|
return this.selectedRowsCount && this.selectedRowsCount === this.getMaxSelectableRows()? true : false;
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
// Copyright 2022 @fto-consult/Boris Fouomene. All rights reserved.
|
|
2
|
+
// Use of this source code is governed by a BSD-style
|
|
3
|
+
// license that can be found in the LICENSE file.
|
|
4
|
+
import DateLib from "$date";
|
|
5
|
+
import React from "$react";
|
|
6
|
+
import {defaultObj,isNonNullString} from "$utils";
|
|
7
|
+
import SimpleSelect from "$ecomponents/SimpleSelect";
|
|
8
|
+
import Provider from "$ecomponents/Dialog/Provider";
|
|
9
|
+
import TextField from "$components/TextField";
|
|
10
|
+
import Label from "$components/Label";
|
|
11
|
+
import theme from "$theme";
|
|
12
|
+
import notify from "$notify";
|
|
13
|
+
import { View } from "react-native";
|
|
14
|
+
import Icon from "$components/Icon";
|
|
15
|
+
import PropTypes from "prop-types";
|
|
16
|
+
|
|
17
|
+
const DateFormatSelector = React.forwardRef((props,ref)=>{
|
|
18
|
+
return <SimpleSelect ref={ref} {...selectDateFormatFieldProps(props)}/>
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
DateFormatSelector.displayName = "DateFormatSelector";
|
|
22
|
+
|
|
23
|
+
export default DateFormatSelector;
|
|
24
|
+
|
|
25
|
+
/*** onAdd est appelé lorsqu'on ajoute un format personalisé */
|
|
26
|
+
export const selectDateFormatFieldProps = ({onAdd:customOnAdd,onAddCustomFormat,...props})=>{
|
|
27
|
+
const onAdd = ()=>{
|
|
28
|
+
const labelRef = React.createRef(null);
|
|
29
|
+
const valueRef = React.createRef(null);
|
|
30
|
+
Provider.open(({
|
|
31
|
+
title : "Ajouter un format de date personalisé",
|
|
32
|
+
children : <View style={[theme.styles.w100,theme.styles.ph1]}>
|
|
33
|
+
<TextField
|
|
34
|
+
type = "text"
|
|
35
|
+
label = "Format personalisé"
|
|
36
|
+
right ={(p)=><Icon {...p} name ="material-help" title="Utilisez les champ d : pour date, m pour mois, y pour année, H pour heure, M pour minute, s pour seconde. les jour sur 3 lettres (Lun) sont : ddd, les jours écris complètement sont ddddd (Lundi); les mois en court sont définis par mmm (Juil), les mois en complet : mmmm (Juillet)."/>}
|
|
37
|
+
onChange = {(args)=>{
|
|
38
|
+
const {value} = args;
|
|
39
|
+
if(!labelRef.current || !labelRef.current.update) return;
|
|
40
|
+
if((value)){
|
|
41
|
+
try {
|
|
42
|
+
var d = new Date().toFormat(value);
|
|
43
|
+
if(d){
|
|
44
|
+
labelRef.current.update(d);
|
|
45
|
+
valueRef.current = {...args,code:value,label:d};
|
|
46
|
+
} else {
|
|
47
|
+
labelRef.current.update("");
|
|
48
|
+
valueRef.current = null;
|
|
49
|
+
}
|
|
50
|
+
} catch{
|
|
51
|
+
labelRef.current.update("");
|
|
52
|
+
valueRef.current = null;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}}
|
|
56
|
+
/>
|
|
57
|
+
<View style={[theme.styles.w100,theme.styles.row,theme.styles.flexWrap]}>
|
|
58
|
+
<Label>EX : </Label>
|
|
59
|
+
<Label.withRef primary textBold ref={labelRef}></Label.withRef>
|
|
60
|
+
</View>
|
|
61
|
+
</View>,
|
|
62
|
+
actions : [{
|
|
63
|
+
text : "Valider",
|
|
64
|
+
icon : "check",
|
|
65
|
+
onPress : ()=>{
|
|
66
|
+
if(!isObj(valueRef.current) || !isNonNullString(valueRef.current.value)){
|
|
67
|
+
return notify.error("Vous devez spécifier un format valide");
|
|
68
|
+
}
|
|
69
|
+
if(typeof customOnAdd =='function'){
|
|
70
|
+
customOnAdd(valueRef.current);
|
|
71
|
+
}
|
|
72
|
+
Provider.close();
|
|
73
|
+
}
|
|
74
|
+
}],
|
|
75
|
+
}))
|
|
76
|
+
};
|
|
77
|
+
return {
|
|
78
|
+
items : getDateFormatSelectorItems(),
|
|
79
|
+
getItemValue : ({item})=>item.code,
|
|
80
|
+
renderItem : dateFormatSelectorRenderItem,
|
|
81
|
+
showAdd : true,
|
|
82
|
+
...defaultObj(props),
|
|
83
|
+
onAdd,
|
|
84
|
+
onAdd : undefined,
|
|
85
|
+
showAdd : false,
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
export const getDateFormatSelectorItems = x=> Object.map(DateLib.formats,(format)=>{
|
|
89
|
+
return {code : format,label:new Date().toFormat(format)}
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
export const dateFormatSelectorRenderItem = ({item})=>{
|
|
93
|
+
return "{0} [{1}]".sprintf(item.label,item.code);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
DateFormatSelector.propTypes = {
|
|
97
|
+
...SimpleSelect.propTypes,
|
|
98
|
+
//appelée lorsqu'on ajoute un format personalisé
|
|
99
|
+
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import SelectField from "./SelectField";
|
|
2
2
|
import {getCountryFieldProps} from "$ecomponents/Countries";
|
|
3
|
-
import {defaultVal} from "$utils";
|
|
4
3
|
|
|
5
4
|
export default class FormFieldSelectCountry extends SelectField{
|
|
6
5
|
getComponentProps(props){
|
|
@@ -9,4 +8,7 @@ export default class FormFieldSelectCountry extends SelectField{
|
|
|
9
8
|
_render(props){
|
|
10
9
|
return super._render(this.getComponentProps(props))
|
|
11
10
|
}
|
|
11
|
+
}
|
|
12
|
+
FormFieldSelectCountry.propTypes = {
|
|
13
|
+
...SelectField.propTypes,
|
|
12
14
|
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import SelectField from "./SelectField";
|
|
2
|
+
import {selectDateFormatFieldProps,getDateFormatSelectorItems} from "$ecomponents/Date/FormatSelector";
|
|
3
|
+
import DateLib from "$date";
|
|
4
|
+
|
|
5
|
+
export default class FormFieldSelectDateFormat extends SelectField{
|
|
6
|
+
constructor(props){
|
|
7
|
+
super(props);
|
|
8
|
+
Object.defineProperties(this,{
|
|
9
|
+
itemsRef : {value : {current : getDateFormatSelectorItems()}},
|
|
10
|
+
valueRef : {value : {current : undefined}},
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
getComponentProps(props){
|
|
14
|
+
const {onAdd} = props;
|
|
15
|
+
const rest = selectDateFormatFieldProps({
|
|
16
|
+
...props,onAdd : (args)=>{
|
|
17
|
+
if(onAdd && onAdd(args) === false){
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
const {value,label} = args;
|
|
21
|
+
const code = value+"-"+value;
|
|
22
|
+
const it = {[code]:{code : value, label : label || new Date().toFormat(value)}}
|
|
23
|
+
Object.map(this.itemsRef.current,(v,k)=>{
|
|
24
|
+
it[k] = v;
|
|
25
|
+
});
|
|
26
|
+
this.valueRef.current = value;
|
|
27
|
+
if(this._field && this._field.refresh && this._field.prepareItems){
|
|
28
|
+
this._field.setState(this._field.prepareItems({items:it,defaultValue:value}))
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
rest.items = this.itemsRef.current;
|
|
33
|
+
if(this.valueRef.current){
|
|
34
|
+
rest.defaultValue = this.valueRef.current;
|
|
35
|
+
}
|
|
36
|
+
this.valueRef.current = undefined;
|
|
37
|
+
return rest;
|
|
38
|
+
}
|
|
39
|
+
_render(props){
|
|
40
|
+
return super._render(this.getComponentProps(props))
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
FormFieldSelectDateFormat.propTypes = {
|
|
45
|
+
...SelectField.propTypes,
|
|
46
|
+
}
|
|
@@ -18,6 +18,7 @@ import Html from "./Html";
|
|
|
18
18
|
import * as eFormFields from "$extendFormFields";
|
|
19
19
|
import "$utils";
|
|
20
20
|
import React from "$react";
|
|
21
|
+
import SelectDateFormat from "./SelectDateFormat";
|
|
21
22
|
|
|
22
23
|
export * from "$extendFormFields";
|
|
23
24
|
|
|
@@ -38,6 +39,7 @@ const defFormFields = {
|
|
|
38
39
|
,Time
|
|
39
40
|
,Image
|
|
40
41
|
,Tel
|
|
42
|
+
,SelectDateFormat
|
|
41
43
|
,Html
|
|
42
44
|
}
|
|
43
45
|
|
|
@@ -67,5 +69,6 @@ export {
|
|
|
67
69
|
,Time
|
|
68
70
|
,Image
|
|
69
71
|
,Tel
|
|
72
|
+
,SelectDateFormat
|
|
70
73
|
,Html
|
|
71
74
|
}
|
|
@@ -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
|
|
13
|
+
import componentsTypes from "./componentsTypes";
|
|
14
14
|
import { keyboardShortcuts } from "../utils";
|
|
15
15
|
|
|
16
16
|
export default class FormDataComponent extends AppComponent{
|
|
@@ -191,7 +191,7 @@ export default class FormDataComponent extends AppComponent{
|
|
|
191
191
|
} else if(isObj(field) && field.form !== false) {
|
|
192
192
|
const name = defaultStr(field.name,field.field,index);
|
|
193
193
|
const type = defaultStr(field.jsType,field.type,"text").trim().toLowerCase().replaceAll("_","");
|
|
194
|
-
const Component =
|
|
194
|
+
const Component = componentsTypes[type] || componentsTypes.default;
|
|
195
195
|
let {defaultValue,useDefaultValueFromData,hidden,renderFormDataField,getMediaQueryStyle,printLabels,queryLimit,selected,value,visible,dataFilesInterest,perm,ignore,form,responsiveProps:customResponsiveProps,...rest} = field;
|
|
196
196
|
rest = Object.assign({},rest);
|
|
197
197
|
delete rest.import;
|
|
@@ -14,8 +14,9 @@ const componentTypes = {
|
|
|
14
14
|
piece : Fields.PieceField,
|
|
15
15
|
select : Fields.SelectField,
|
|
16
16
|
switch : Fields.Switch,
|
|
17
|
-
select_country : Fields.SelectCountry,
|
|
18
17
|
selectcountry : Fields.SelectCountry,
|
|
18
|
+
selectdateformat : Fields.SelectDateFormat,
|
|
19
|
+
dateformat : Fields.SelectDateFormat,
|
|
19
20
|
date : Fields.Date,
|
|
20
21
|
time : Fields.Time,
|
|
21
22
|
datetime : Fields.DateTime,
|
|
@@ -97,9 +98,15 @@ export const getFilterComponentProps = (_props)=>{
|
|
|
97
98
|
component = type == 'datetime' ? Fields.DateTime : type === 'date'? Fields.Date : Fields.Time;
|
|
98
99
|
} else if(type == 'color' || type =='colorpicker') {
|
|
99
100
|
component = Fields.ColorPicker;
|
|
100
|
-
} else if(
|
|
101
|
+
} else if(type == 'dateformat' || type =='select_dateformat' || type =='select_date_format') {
|
|
102
|
+
component = Fields.SelectDateFormat;
|
|
103
|
+
} else if(React.isComponent()) {
|
|
101
104
|
component = componentTypes[type];
|
|
102
105
|
}else {
|
|
106
|
+
const tt = type.replaceAll("_","").toLowerCase();
|
|
107
|
+
if(React.isComponent(componentTypes[tt])){
|
|
108
|
+
component = componentTypes[tt];
|
|
109
|
+
}
|
|
103
110
|
delete props.dbName;
|
|
104
111
|
delete props.tableName;
|
|
105
112
|
props.label = label;
|
|
@@ -118,6 +118,7 @@ const Snackbar = ({
|
|
|
118
118
|
paddingBottom: bottom,
|
|
119
119
|
paddingHorizontal: Math.max(left, right),
|
|
120
120
|
};
|
|
121
|
+
action = React.isValidElement(action)? action : null;
|
|
121
122
|
return (
|
|
122
123
|
<View
|
|
123
124
|
testID={testID+"_Container"}
|
|
@@ -150,13 +151,13 @@ const Snackbar = ({
|
|
|
150
151
|
style
|
|
151
152
|
]}
|
|
152
153
|
>
|
|
153
|
-
{<View testID={testID+"_Content"} {...contentProps} style={[styles.content,contentProps.style]}>
|
|
154
|
+
{<View testID={testID+"_Content"} {...contentProps} style={[styles.content,contentProps.style,action && theme.styles.pr1]}>
|
|
154
155
|
{typeof children =='string' || typeof children ==='string' ?
|
|
155
156
|
<Label {...labelProps} style={[{color:flattenStyle.color,backgroundColor:flattenStyle.backgroundColor},labelProps.style]}>
|
|
156
157
|
{children}
|
|
157
158
|
</Label> : React.isValidElement(children)? children : null}
|
|
158
159
|
</View>}
|
|
159
|
-
{
|
|
160
|
+
{action}
|
|
160
161
|
</Surface>
|
|
161
162
|
</View>
|
|
162
163
|
);
|