@fto-consult/expo-ui 2.14.3 → 2.15.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/Checkbox.js +3 -1
- package/src/components/Datagrid/SWRDatagrid.js +1 -1
- package/src/components/Datagrid/Table/index.js +2 -1
- package/src/components/Form/Fields/Field.js +1 -1
- package/src/components/Label/index.js +6 -1
- package/src/layouts/Screen/TableData.js +44 -1
- package/src/navigation/utils.js +3 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fto-consult/expo-ui",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.15.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.21.
|
|
64
|
+
"@fto-consult/common": "^1.21.2",
|
|
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",
|
|
@@ -2,12 +2,14 @@ import {Checkbox} from "$ecomponents/Icon";
|
|
|
2
2
|
import React from "$react";
|
|
3
3
|
import {defaultObj,isObj} from "$utils";
|
|
4
4
|
import PropTypes from "prop-types";
|
|
5
|
+
import theme from "$theme";
|
|
5
6
|
|
|
6
7
|
const DatagridCheckboxComponent = React.forwardRef((props,ref)=>{
|
|
7
8
|
const {onChange,rowKey,rowData,row,rowIndex,index,rowsRefs,...rest} = props;
|
|
8
9
|
return <Checkbox
|
|
9
10
|
secondaryOnCheck
|
|
10
|
-
{...
|
|
11
|
+
{...rest}
|
|
12
|
+
style = {[rest.style,theme.styles.alignItemsCenter]}
|
|
11
13
|
ref = {(el)=>{
|
|
12
14
|
React.setRef(ref,el);
|
|
13
15
|
if(isObj(rowsRefs) && rowKey){
|
|
@@ -274,7 +274,7 @@ const SWRDatagridComponent = React.forwardRef((props,ref)=>{
|
|
|
274
274
|
style = {sStyle}
|
|
275
275
|
anchor = {(p)=>{
|
|
276
276
|
return <Pressable style={[theme.styles.noMargin,theme.styles.noPadding]} {...p} testID={testID+"MenuSelectLimit"}>
|
|
277
|
-
<Label primary
|
|
277
|
+
<Label primary testID={testID+"_Label"} fontSize={16}>
|
|
278
278
|
{limitRef.current.formatNumber()}
|
|
279
279
|
</Label>
|
|
280
280
|
</Pressable>
|
|
@@ -677,7 +677,7 @@ export default class Field extends AppComponent {
|
|
|
677
677
|
return true;
|
|
678
678
|
}
|
|
679
679
|
onBlurField(event){
|
|
680
|
-
if(isFunction(this.props.onBlur) && this.props.onBlur({event,context:this}) === false){
|
|
680
|
+
if(isFunction(this.props.onBlur) && this.props.onBlur({event,value:this.getValue(),context:this}) === false){
|
|
681
681
|
return;
|
|
682
682
|
}
|
|
683
683
|
if(this.isFilter()) return
|
|
@@ -10,7 +10,7 @@ const defaultSelectable = canTextBeSelectable();
|
|
|
10
10
|
|
|
11
11
|
export const EllipsizeMode = {'head':'head','middle':'middle', 'tail':'tail' , 'clip':'clip'}
|
|
12
12
|
|
|
13
|
-
const LabelComponent = React.forwardRef(({ children,upperCase,testID,wrap,nativeID,wrapText,error,underlined,splitText,secondary,primary,bold,textBold,disabled,text,style,...rest},ref)=> {
|
|
13
|
+
const LabelComponent = React.forwardRef(({ children,upperCase,fontSize,testID,wrap,nativeID,wrapText,error,underlined,splitText,secondary,primary,bold,textBold,disabled,text,style,...rest},ref)=> {
|
|
14
14
|
children = defaultVal(children,text);
|
|
15
15
|
let isText = false;
|
|
16
16
|
if(!React.isValidElement(children) && Array.isArray(children) && children.length){
|
|
@@ -37,6 +37,7 @@ const LabelComponent = React.forwardRef(({ children,upperCase,testID,wrap,native
|
|
|
37
37
|
if(underlined){
|
|
38
38
|
r1.textDecorationLine = 'underline';
|
|
39
39
|
}
|
|
40
|
+
|
|
40
41
|
style = Object.assign({},StyleSheet.flatten(style));
|
|
41
42
|
testID = defaultStr(testID,"RN_LabelComponent");
|
|
42
43
|
const restProps = {nativeID};
|
|
@@ -57,6 +58,9 @@ const LabelComponent = React.forwardRef(({ children,upperCase,testID,wrap,native
|
|
|
57
58
|
children = children.toUpperCase();
|
|
58
59
|
}
|
|
59
60
|
}
|
|
61
|
+
if(fontSize){
|
|
62
|
+
r1.fontSize = fontSize;
|
|
63
|
+
}
|
|
60
64
|
return (<Text allowFontScaling = {true} ref = {ref} selectable={defaultSelectable} {...rest} {...restProps} testID={testID} disabled={disabled} style={[styles.label,splitText?styles.wrap:null,splitText?styles.w100:null,bold?styles.bold:null,r2,style,r1,styles.webFontFamilly]}>{children}</Text>)
|
|
61
65
|
}
|
|
62
66
|
let hasP = false;
|
|
@@ -91,6 +95,7 @@ LabelComponentExported.propTypes = {
|
|
|
91
95
|
children : PropTypes.any,
|
|
92
96
|
upperCase: PropTypes.bool,///si la transformation sera en majuscule
|
|
93
97
|
text : PropTypes.any,
|
|
98
|
+
fontSize : PropTypes.number,
|
|
94
99
|
wrap : PropTypes.bool, //si le texte sera splité vers la ligne suivantes
|
|
95
100
|
wrapText : PropTypes.bool,///alias à wrap
|
|
96
101
|
primary : PropTypes.bool,
|
|
@@ -21,6 +21,8 @@ import theme from "$theme";
|
|
|
21
21
|
import cActions from "$cactions";
|
|
22
22
|
import APP from "$capp/instance";
|
|
23
23
|
import { generatedColumnsProperties } from "./utils";
|
|
24
|
+
import i18n from "$i18n";
|
|
25
|
+
import fetch from "$capi/fetch";
|
|
24
26
|
|
|
25
27
|
|
|
26
28
|
const HIDE_PRELOADER_TIMEOUT = 300;
|
|
@@ -86,6 +88,39 @@ export default class TableDataScreenComponent extends FormDataScreen{
|
|
|
86
88
|
Object.map(table.fields,(field,i)=>{
|
|
87
89
|
if(isObj(field) && field.form !== false){
|
|
88
90
|
fields[i] = Object.clone(field);
|
|
91
|
+
const f = fields[i];
|
|
92
|
+
f.type = defaultStr(f.jsType,f.type).toLowerCase();
|
|
93
|
+
const name = f.field = defaultStr(f.field,i);
|
|
94
|
+
if((f.type =='id' || f.type =='piece' || f.unique === true) && f.unique !== false && f.disabled !== true && f.editable !== false && f.readOnly !== true){
|
|
95
|
+
const {onBlur} = f;
|
|
96
|
+
f.onBlur = (args)=>{
|
|
97
|
+
args = {...f,...args,fetch,columnField:name,fieldName:name,id:args.value};
|
|
98
|
+
const {context} = args;
|
|
99
|
+
const r = typeof onBlur =='function'? onBlur (args) : undefined;
|
|
100
|
+
if(r === false) return r;
|
|
101
|
+
//on applique la validation seulement en cas de non mise à jour
|
|
102
|
+
if(!this.isCurrentDocEditingUpdate() && context && typeof context.onNoValidate =='function'){
|
|
103
|
+
const cb = typeof field.fetchUniqueId =='function'? field.fetchUniqueId : typeof this.fetchUniqueId =='function'? this.fetchUniqueId : undefined;
|
|
104
|
+
if(cb){
|
|
105
|
+
const r2 = cb(args);
|
|
106
|
+
if(isPromise(r2)){
|
|
107
|
+
r2.then((data)=>{
|
|
108
|
+
let message = data;
|
|
109
|
+
if(isObj(data) && Object.size(data,true)){
|
|
110
|
+
message = i18n.lang('validate_rule_field_must_be_unique')+ defaultStr(f.label,f.text);
|
|
111
|
+
}
|
|
112
|
+
if(isNonNullString(message)){
|
|
113
|
+
context.onNoValidate({...args,msg:message,message,context,validRule:context.getValidRule()});
|
|
114
|
+
}
|
|
115
|
+
}).catch((e)=>{
|
|
116
|
+
|
|
117
|
+
})
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return r;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
89
124
|
if(field.primaryKey === true){
|
|
90
125
|
primaryKeyFields[field.field || i] = true;
|
|
91
126
|
}
|
|
@@ -98,6 +133,7 @@ export default class TableDataScreenComponent extends FormDataScreen{
|
|
|
98
133
|
tableName : { value : defaultStr(table.table,table.tableName)},
|
|
99
134
|
fields : {value : fields},
|
|
100
135
|
table : {value : table},
|
|
136
|
+
isDocEditingRef : {value : {current:false}},
|
|
101
137
|
validateDataBeforeSave : {value : mainProps.validateData},
|
|
102
138
|
upsertDataToDB : {value : mainProps.upsertToDB},
|
|
103
139
|
makePhoneCallProps : {value : mainProps.makePhoneCallProps},
|
|
@@ -105,6 +141,7 @@ export default class TableDataScreenComponent extends FormDataScreen{
|
|
|
105
141
|
titleProp : {value : mainProps.title},
|
|
106
142
|
closeOnSaveProp : {value : mainProps.closeOnSave || mainProps.closeAfterSave },
|
|
107
143
|
newActionProp : {value : mainProps.newAction},
|
|
144
|
+
fetchUniqueId : {value : mainProps.fetchUniqueId},
|
|
108
145
|
//la liste des champ de type clé primaire associés à la table
|
|
109
146
|
primaryKeyFields : {value : primaryKeyFields},
|
|
110
147
|
cloneProp : {value : typeof mainProps.clone =='function' && mainProps.clone || undefined},
|
|
@@ -116,6 +153,9 @@ export default class TableDataScreenComponent extends FormDataScreen{
|
|
|
116
153
|
this.hidePreloader = this.hidePreloader.bind(this);
|
|
117
154
|
this.showPreloader = this.showPreloader.bind(this);
|
|
118
155
|
};
|
|
156
|
+
isCurrentDocEditingUpdate(){
|
|
157
|
+
return this.isDocEditingRef.current === true ? true : false;
|
|
158
|
+
}
|
|
119
159
|
resetState(){
|
|
120
160
|
Object.map(this.INITIAL_STATE,(s,k)=>{
|
|
121
161
|
delete this.INITIAL_STATE[k];
|
|
@@ -195,6 +235,7 @@ export default class TableDataScreenComponent extends FormDataScreen{
|
|
|
195
235
|
const tableName = this.tableName;
|
|
196
236
|
const sessionName = this.INITIAL_STATE.sessionName = defaultStr(customSessionName,"table-form-data"+tableName);
|
|
197
237
|
const isUpdated = this.isDocEditing(data);
|
|
238
|
+
this.isDocEditingRef.current = !!isUpdated;
|
|
198
239
|
const isMobOrTab = isMobileOrTabletMedia();
|
|
199
240
|
let archived = this.isArchived();
|
|
200
241
|
this.INITIAL_STATE.archived = archived;
|
|
@@ -361,7 +402,7 @@ export default class TableDataScreenComponent extends FormDataScreen{
|
|
|
361
402
|
}
|
|
362
403
|
} else {
|
|
363
404
|
mainContent = <Surface {...contentProps} testID={testID+"_MainContentContainer"} elevation={elevation} style={[styles.container,styles.noPadding,{paddingTop:0,marginTop:0}]}>
|
|
364
|
-
<ScrollView virtualized testID={testID+"
|
|
405
|
+
<ScrollView virtualized testID={testID+"_MainContentScrollViewWithoutTab"}>
|
|
365
406
|
<View testID={testID+"_MainContent"} style={[styles.screenContent,!isMobOrTab && theme.styles.p1,header?styles.screenContentWithHeader:null]}>
|
|
366
407
|
{header}
|
|
367
408
|
{content}
|
|
@@ -755,6 +796,8 @@ TableDataScreenComponent.propTypes = {
|
|
|
755
796
|
table : PropTypes.string,
|
|
756
797
|
fields : PropTypes.object,
|
|
757
798
|
}),
|
|
799
|
+
unique : PropTypes.bool,//si la validation de type unique sur le champ sera effective
|
|
800
|
+
fetchUniqueId : PropTypes.func,//la fonction permettant de fetch un élément unique pour la validation de type uniqueID, liée aux champs de type piece et id
|
|
758
801
|
validateData : PropTypes.func,// la fonction permettant de valider les données à enregistrer
|
|
759
802
|
archivedPermsFilter : PropTypes.func,///le filtre des permissions archivées
|
|
760
803
|
newElementLabel : PropTypes.string,//le titre du bouton nouveau pour l'ajout d'un nouvel élément
|
package/src/navigation/utils.js
CHANGED
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
// license that can be found in the LICENSE file.
|
|
4
4
|
import {navigate,sanitizeName} from "$cnavigation";
|
|
5
5
|
import {isNonNullString,defaultObj,isObj} from "$utils";
|
|
6
|
-
|
|
7
6
|
export const tableDataRouteName = 'TableData';
|
|
8
7
|
|
|
9
8
|
export const navigateToTableData = function(tableName,params,actionType){
|
|
@@ -54,6 +53,9 @@ export const getTableDataListRouteName = function(tableName){
|
|
|
54
53
|
export const navigateToTableDataList = function (tableName,params){
|
|
55
54
|
const route = getTableDataListRouteName(tableName);
|
|
56
55
|
if(isNonNullString(route)){
|
|
56
|
+
if(!Auth.isTableDataAllowed({table:tableName,action:'read'})){
|
|
57
|
+
return Auth.showError()
|
|
58
|
+
}
|
|
57
59
|
return navigate({routeName:route,params});
|
|
58
60
|
}
|
|
59
61
|
return false;
|