@fto-consult/expo-ui 2.15.1 → 2.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/components/Datagrid/utils.js +1 -1
- package/src/components/Form/Fields/Field.js +17 -4
- package/src/components/Form/Fields/SelectTableData/Component.js +17 -6
- package/src/layouts/DatabaseStatistics/index.js +1 -1
- package/src/layouts/Fab/index.js +71 -36
- package/src/layouts/Screen/TableData.js +28 -11
- package/src/layouts/Fab/actions.js +0 -5
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@ import KeyboardEventHandler from "../KeyboardEventHandler";
|
|
|
3
3
|
const {getActions,getFormFields,Forms} = require("../utils")
|
|
4
4
|
import TextField,{parseDecimal} from "$ecomponents/TextField";
|
|
5
5
|
import Icon from "$ecomponents/Icon";
|
|
6
|
-
import {extendObj,isBool,isUndefined,uniqid,defaultObj,isObj,defaultFunc,isFunction,isNumber,arrayValueExists,defaultVal,defaultStr,isNonNullString,defaultBool,defaultDecimal} from "$utils";
|
|
6
|
+
import {extendObj,isBool,isUndefined,uniqid,isValidDataFileName,defaultObj,isObj,defaultFunc,isFunction,isNumber,arrayValueExists,defaultVal,defaultStr,isNonNullString,defaultBool,defaultDecimal} from "$utils";
|
|
7
7
|
import {Component as AppComponent} from "$react";
|
|
8
8
|
import {observable,addObserver} from "$observable";
|
|
9
9
|
import {Validator} from "$validator";
|
|
@@ -47,8 +47,11 @@ export default class Field extends AppComponent {
|
|
|
47
47
|
render_filter,
|
|
48
48
|
maxLength,
|
|
49
49
|
validParams,
|
|
50
|
+
jsType,
|
|
51
|
+
type,
|
|
50
52
|
} = props;
|
|
51
53
|
Object.defineProperties(this,{
|
|
54
|
+
type : {value : defaultStr(jsType,type,"text").trim().toLowerCase()},
|
|
52
55
|
__disabledSymbol : {value : Symbol('_disabled'),override:false,writable:false},
|
|
53
56
|
__isDisabledSymbol : { value : Symbol('_isDisabled'),override:false,writable:false},
|
|
54
57
|
__isReadOnlySymbol : { value : Symbol('_isReadOnly'),override:false,writable:false},
|
|
@@ -89,7 +92,7 @@ export default class Field extends AppComponent {
|
|
|
89
92
|
},
|
|
90
93
|
/** si la valeur valide à retourner par le field est de type decimal */
|
|
91
94
|
canValueBeDecimal : {
|
|
92
|
-
value : this.isTextField() && arrayValueExists(['number','decimal'],this.
|
|
95
|
+
value : this.isTextField() && arrayValueExists(['number','decimal'],this.type)
|
|
93
96
|
,override : false, writable : false
|
|
94
97
|
},
|
|
95
98
|
wrapperRef : {
|
|
@@ -240,6 +243,12 @@ export default class Field extends AppComponent {
|
|
|
240
243
|
});
|
|
241
244
|
}
|
|
242
245
|
onValidatorValid(args){
|
|
246
|
+
if(!this.isFilter() && ((this.props.allowWhiteSpaces === false) || ((this.type ==='id' || this.type =='piece') && this.props.allowWhiteSpaces !== true))){
|
|
247
|
+
const value = isNonNullString(args.value) && args.value.replaceAll("/","").replaceAll("\\",'') || undefined;
|
|
248
|
+
if(value && (value.contains(" ") || !isValidDataFileName(value))){
|
|
249
|
+
return "Veuillez renseigner une valeur ne contenant pas d'espace ou de caractère accentués";
|
|
250
|
+
}
|
|
251
|
+
}
|
|
243
252
|
if(isFunction(this.props.onValidatorValid)){
|
|
244
253
|
return this.props.onValidatorValid(args);
|
|
245
254
|
}
|
|
@@ -321,7 +330,7 @@ export default class Field extends AppComponent {
|
|
|
321
330
|
* sont pas par défaut définies comme champ de formulaire
|
|
322
331
|
*/
|
|
323
332
|
parseDecimal(v){
|
|
324
|
-
return parseDecimal(v,
|
|
333
|
+
return parseDecimal(v,this.type);
|
|
325
334
|
}
|
|
326
335
|
getInvalidValue(){
|
|
327
336
|
return this.state.invalidValue;
|
|
@@ -876,7 +885,7 @@ export default class Field extends AppComponent {
|
|
|
876
885
|
delete rest.archivable;
|
|
877
886
|
|
|
878
887
|
this.___formattedField = undefined;
|
|
879
|
-
let _type = this.type
|
|
888
|
+
let _type = this.type;
|
|
880
889
|
format = defaultStr(format).toLowerCase().trim();
|
|
881
890
|
tooltip = defaultVal(tooltip,title);
|
|
882
891
|
|
|
@@ -1063,6 +1072,10 @@ Field.propTypes = {
|
|
|
1063
1072
|
elle doit toujours être définie dans la classe qui hérite directement au composant Field
|
|
1064
1073
|
*/
|
|
1065
1074
|
/////getFieldInstance : PropTypes.func.IsRequired,
|
|
1075
|
+
/***allowWhiteSpace, si le champ aceeptera les espaces où les caractères accentuées
|
|
1076
|
+
* lorsque allowWhiteSpace === false alors on vérifiera si le champ n'admet pas des caractères accentuées
|
|
1077
|
+
*/
|
|
1078
|
+
allowWhiteSpaces : PropTypes.bool,
|
|
1066
1079
|
}
|
|
1067
1080
|
|
|
1068
1081
|
const styles = StyleSheet.create({
|
|
@@ -23,7 +23,6 @@ const TableDataSelectField = React.forwardRef((_props,ref)=>{
|
|
|
23
23
|
props = defaultObj(props);
|
|
24
24
|
props.data = defaultObj(props.data);
|
|
25
25
|
foreignKeyColumn = foreignKeyColumn.trim();
|
|
26
|
-
foreignKeyLabel = defaultStr(foreignKeyLabel).trim();
|
|
27
26
|
convertFiltersToSQL = defaultVal(convertFiltersToSQL,willConvertFiltersToSQL());
|
|
28
27
|
const fKeyTable = getForeignKeyTable(foreignKeyTable,props)
|
|
29
28
|
if(!isObj(fKeyTable) || !(defaultStr(fKeyTable.tableName,fKeyTable.table))){
|
|
@@ -45,9 +44,10 @@ const TableDataSelectField = React.forwardRef((_props,ref)=>{
|
|
|
45
44
|
isUpdate = false;
|
|
46
45
|
}
|
|
47
46
|
const defaultFields = [foreignKeyColumn];
|
|
48
|
-
if(foreignKeyLabel){
|
|
47
|
+
if(isNonNullString(foreignKeyLabel)){
|
|
48
|
+
foreignKeyLabel = foreignKeyLabel.trim();
|
|
49
49
|
defaultFields.push(foreignKeyLabel);
|
|
50
|
-
}
|
|
50
|
+
}
|
|
51
51
|
if(fetchDataOpts.fields !== 'all' && (!Array.isArray(fetchDataOpts.fields) || !fetchDataOpts.fields.length)){
|
|
52
52
|
fetchDataOpts.fields = defaultFields;
|
|
53
53
|
}
|
|
@@ -86,7 +86,7 @@ const TableDataSelectField = React.forwardRef((_props,ref)=>{
|
|
|
86
86
|
|
|
87
87
|
let dat = isNonNullString(foreignKeyColumnValue)? {
|
|
88
88
|
[foreignKeyColumn]:foreignKeyColumnValue,
|
|
89
|
-
...(foreignKeyLabel ? {[foreignKeyLabel]:foreignKeyColumnValue+", introuvable dans le système"}:{})
|
|
89
|
+
...(isNonNullString(foreignKeyLabel) ? {[foreignKeyLabel]:foreignKeyColumnValue+", introuvable dans le système"}:{})
|
|
90
90
|
} : null;
|
|
91
91
|
|
|
92
92
|
const context = {
|
|
@@ -158,7 +158,15 @@ const TableDataSelectField = React.forwardRef((_props,ref)=>{
|
|
|
158
158
|
}
|
|
159
159
|
const rItem = (p)=>{
|
|
160
160
|
if(!isObj(p) || !isObj(p.item)) return null;
|
|
161
|
-
|
|
161
|
+
let itemLabel = typeof foreignKeyLabel =='function'? foreignKeyLabel(p) : undefined;
|
|
162
|
+
if(isNonNullString(foreignKeyLabel)){
|
|
163
|
+
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());
|
|
164
|
+
}
|
|
165
|
+
const itemCode = p.item[foreignKeyColumn] !== undefined && p.item[foreignKeyColumn] !== null && p.item[foreignKeyColumn].toString() || undefined;
|
|
166
|
+
if(!isNonNullString(itemLabel)){
|
|
167
|
+
itemLabel = "";
|
|
168
|
+
}
|
|
169
|
+
if(!itemLabel) return itemCode;
|
|
162
170
|
return (itemLabel !== itemCode ? ((isNonNullString(itemCode)?("["+itemCode+"] "):"")+itemLabel):itemLabel);
|
|
163
171
|
}
|
|
164
172
|
const dialogProps = defaultObj(props.dialogProps);
|
|
@@ -212,7 +220,10 @@ TableDataSelectField.propTypes = {
|
|
|
212
220
|
fetchItems : PropTypes.func,//la fonction de rappel à utiliser pour faire une requête fetch permettant de selectionner les données à distance
|
|
213
221
|
beforeFetchItems : PropTypes.func, //appelée immédiatement avant l'exécution de la requête fetch
|
|
214
222
|
foreignKeyColumn : PropTypes.string.isRequired,//le nom de la clé étrangère à laquelle fait référence la colone dans la fKeyTable
|
|
215
|
-
foreignKeyLabel : PropTypes.
|
|
223
|
+
foreignKeyLabel : PropTypes.oneOfType([
|
|
224
|
+
PropTypes.string,
|
|
225
|
+
PropTypes.func, //s'il s'agit d'une fonciton qui sera appelée
|
|
226
|
+
]),
|
|
216
227
|
getForeignKeyTable : PropTypes.func.isRequired, //la fonction permettant de récupérer la fKeyTable data dont fait référence le champ
|
|
217
228
|
foreignKeyTable : PropTypes.string, //le nom de la fKeyTable data à laquelle se reporte le champ
|
|
218
229
|
onFetchItems : PropTypes.func,
|
|
@@ -19,7 +19,7 @@ export default function DatabaseStatisticScreen ({withScreen,title:customTitle,c
|
|
|
19
19
|
}
|
|
20
20
|
let content = [];
|
|
21
21
|
Object.map(tables,(table,index,suffix)=>{
|
|
22
|
-
if(isObj(table)){
|
|
22
|
+
if(isObj(table) && table.databaseStatistic !== false){
|
|
23
23
|
content.push(
|
|
24
24
|
<Cell elevation = {5} withSurface mobileSize={12} desktopSize={3} tabletSize={4} {...contentProps} key = {index} >
|
|
25
25
|
<DatabaseStatistic
|
package/src/layouts/Fab/index.js
CHANGED
|
@@ -1,46 +1,76 @@
|
|
|
1
1
|
import Fab from "$ecomponents/Fab";
|
|
2
2
|
import { StyleSheet } from "react-native";
|
|
3
|
-
import
|
|
4
|
-
import {isObjOrArray} from "$utils";
|
|
5
|
-
import {removeFabRef,createFabRef} from "./utils";
|
|
6
|
-
import PropTypes from "prop-types";
|
|
3
|
+
import {isObjOrArray,isObj,defaultStr,defaultObj} from "$utils";
|
|
7
4
|
import APP from "$capp";
|
|
8
5
|
import React from "$react";
|
|
9
|
-
import {
|
|
6
|
+
import {navigateToTableData} from "$enavigation/utils";
|
|
7
|
+
import PropTypes from "prop-types";
|
|
8
|
+
import theme from "$theme";
|
|
9
|
+
import {isLoggedIn as isAuthLoggedIn} from "$cauth/utils/session";
|
|
10
10
|
|
|
11
11
|
export * from "./utils";
|
|
12
12
|
|
|
13
|
-
const
|
|
14
|
-
const
|
|
15
|
-
const
|
|
16
|
-
|
|
13
|
+
const FabLayoutComponent = React.forwardRef(({style,screenName,tables,...props},ref)=>{
|
|
14
|
+
const [isLoggedIn,setIsLoggedIn] = React.useState(isAuthLoggedIn());
|
|
15
|
+
const isMounted = React.useIsMounted();
|
|
16
|
+
const actions = React.useCallback(()=>{
|
|
17
|
+
if(!isLoggedIn) return null;
|
|
18
|
+
const a = [];
|
|
19
|
+
Object.map(tables,(table,i,index)=>{
|
|
20
|
+
if(!isObj(table) || table.showInFab === false) return;
|
|
21
|
+
const icon = defaultStr(table.addIcon,"material-add");
|
|
22
|
+
const text = defaultStr(table.text,table.label);
|
|
23
|
+
const addText = defaultStr(table.newElementLabel,"Nouveau");
|
|
24
|
+
const tableName = defaultStr(table.table,table.tableName);
|
|
25
|
+
let auth = true;
|
|
26
|
+
if(typeof Auth !=='undefined' && Auth && Auth.isTableDataAllowed){
|
|
27
|
+
auth = Auth.isTableDataAllowed({table:tableName,action:'create'});
|
|
28
|
+
}
|
|
29
|
+
if(!table || !icon || !text || !auth) return;
|
|
30
|
+
let fabProps = typeof table.getFabProps ==='function'? table.getFabProps({tableName}) : defaultObj(table.fabProps);;
|
|
31
|
+
if(fabProps === false) return;
|
|
32
|
+
fabProps = defaultObj(fabProps);
|
|
33
|
+
const cSuffix = theme.Colors.getSuffix(index);
|
|
34
|
+
const color = theme.Colors.isValid(fabProps.color)? fabProps.color : theme.Colors.getContrast(cSuffix);
|
|
35
|
+
const backgroundColor = theme.Colors.isValid(fabProps.backgroundColor)?fabProps.backgroundColor : cSuffix;
|
|
36
|
+
const label = defaultStr(fabProps.label,fabProps.text,"{0} | {1}".sprintf(addText,text));
|
|
37
|
+
a.push({
|
|
38
|
+
icon,
|
|
39
|
+
label,
|
|
40
|
+
tooltip:label,
|
|
41
|
+
...fabProps,
|
|
42
|
+
color,
|
|
43
|
+
backgroundColor,
|
|
44
|
+
onPress : (e)=>{
|
|
45
|
+
if(fabProps.onPress && fabProps.onPress({...React.getOnPressArgs(e),table,tableName,navigateToTableData,navigate:navigateToTableData}) === false) return;
|
|
46
|
+
navigateToTableData({tableName});
|
|
47
|
+
}
|
|
48
|
+
})
|
|
49
|
+
})
|
|
50
|
+
return a.length ? a : null;
|
|
51
|
+
},[isLoggedIn])();
|
|
17
52
|
React.useEffect(()=>{
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
53
|
+
const onLogin = ()=>{
|
|
54
|
+
if(!isMounted())return;
|
|
55
|
+
setIsLoggedIn(true);
|
|
56
|
+
},onLogout = ()=>{
|
|
57
|
+
if(!isMounted()) return;
|
|
58
|
+
setIsLoggedIn(false);
|
|
59
|
+
}
|
|
60
|
+
APP.on(APP.EVENTS.AUTH_LOGIN_USER,onLogin);
|
|
61
|
+
APP.on(APP.EVENTS.AUTH_LOGOUT_USER,onLogout);
|
|
62
|
+
return ()=>{
|
|
63
|
+
APP.off(APP.EVENTS.AUTH_LOGIN_USER,onLogin);
|
|
64
|
+
APP.off(APP.EVENTS.AUTH_LOGOUT_USER,onLogout);
|
|
27
65
|
}
|
|
28
|
-
}
|
|
29
|
-
APP.on(APP.EVENTS.SCREEN_FOCUS,onFocusFab);
|
|
30
|
-
APP.on(APP.EVENTS.SCREEN_BLUR,onBlurFab);
|
|
31
|
-
return ()=>{
|
|
32
|
-
APP.off(APP.EVENTS.SCREEN_FOCUS,onFocusFab);
|
|
33
|
-
APP.off(APP.EVENTS.SCREEN_BLUR,onBlurFab);
|
|
34
|
-
removeFabRef(screenName);
|
|
35
|
-
}
|
|
36
66
|
},[])
|
|
37
|
-
return <Fab.Group
|
|
38
|
-
{...
|
|
67
|
+
return actions ? <Fab.Group
|
|
68
|
+
{...props}
|
|
39
69
|
screenName = {screenName}
|
|
40
70
|
ref = {ref}
|
|
41
|
-
style={styles.fab}
|
|
42
|
-
actions = {
|
|
43
|
-
/>
|
|
71
|
+
style={[styles.fab,style]}
|
|
72
|
+
actions = {actions}
|
|
73
|
+
/> : null;
|
|
44
74
|
});
|
|
45
75
|
const styles = StyleSheet.create({
|
|
46
76
|
fab: {
|
|
@@ -51,9 +81,14 @@ const styles = StyleSheet.create({
|
|
|
51
81
|
},
|
|
52
82
|
})
|
|
53
83
|
|
|
54
|
-
export default
|
|
84
|
+
export default FabLayoutComponent;
|
|
85
|
+
|
|
86
|
+
FabLayoutComponent.displayName = "FabLayoutComponent";
|
|
55
87
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
88
|
+
FabLayoutComponent.propTypes = {
|
|
89
|
+
tables : PropTypes.oneOfType([
|
|
90
|
+
PropTypes.objectOf(PropTypes.object),
|
|
91
|
+
PropTypes.arrayOf(PropTypes.object)
|
|
92
|
+
]).isRequired,
|
|
93
|
+
screenName : PropTypes.string,
|
|
94
|
+
}
|
|
@@ -228,6 +228,7 @@ export default class TableDataScreenComponent extends FormDataScreen{
|
|
|
228
228
|
containerProps : customContainerProps,
|
|
229
229
|
formProps : customFormProps,
|
|
230
230
|
newElementLabel,
|
|
231
|
+
prepareField,
|
|
231
232
|
...rest
|
|
232
233
|
} = getScreenProps(props);
|
|
233
234
|
const table = this.table;
|
|
@@ -241,29 +242,44 @@ export default class TableDataScreenComponent extends FormDataScreen{
|
|
|
241
242
|
this.INITIAL_STATE.archived = archived;
|
|
242
243
|
this.INITIAL_STATE.tableName = tableName;
|
|
243
244
|
const fields = {};
|
|
244
|
-
Object.map(this.fields,(field,i)=>{
|
|
245
|
+
Object.map(this.fields,(field,i,counterIndex)=>{
|
|
246
|
+
let currentField = isObj(field)?Object.clone(field):field;
|
|
245
247
|
if(isObj(field)){
|
|
246
|
-
|
|
248
|
+
const type = currentField.type = defaultStr(currentField.jsType,currentField.type,"text").toLowerCase();
|
|
249
|
+
/**** lorsqu'un champ porte la propriété visibleOnlyOnEditing à true alors ce champ sera disponible uniquement en cas de modification */
|
|
250
|
+
if(currentField.visibleOnlyOnEditing === true && !isUpdated){
|
|
251
|
+
currentField.form = false;
|
|
252
|
+
}
|
|
253
|
+
// les champs de type date par défaut qui sont requis, auront comme valeur par défaut la date actuelle s'il ne sont pas définies
|
|
254
|
+
if((type.contains('date') || type.contains('time')) && currentField.required === true && !currentField.defaultValue){
|
|
255
|
+
currentField.defaultValue = new Date();
|
|
256
|
+
}
|
|
247
257
|
generatedColumnsProperties.map((f)=>{
|
|
248
258
|
//on affiche les champs générés uniquement en cas de mise à jour
|
|
249
|
-
if(
|
|
250
|
-
|
|
251
|
-
|
|
259
|
+
if(currentField[f] === true){
|
|
260
|
+
currentField.visible = isUpdated ? true : false;
|
|
261
|
+
currentField.readOnly = true;
|
|
252
262
|
}
|
|
253
263
|
});
|
|
254
264
|
if(isUpdated){
|
|
255
265
|
//la props readOnlyOnEditing permet de rendre le champ readOnly en cas de mise à jour de la tableData
|
|
256
|
-
if((
|
|
257
|
-
|
|
266
|
+
if((currentField.readOnlyOnEditing === true)){
|
|
267
|
+
currentField.readOnly = true;
|
|
258
268
|
}
|
|
259
|
-
if((
|
|
260
|
-
|
|
269
|
+
if((currentField.disabledOnEditing === true)){
|
|
270
|
+
currentField.disabled = true;
|
|
261
271
|
}
|
|
262
272
|
}
|
|
263
273
|
|
|
264
|
-
} else {
|
|
265
|
-
fields[i] = field;
|
|
266
274
|
}
|
|
275
|
+
///on effectue une mutator sur le champ en cours de modification
|
|
276
|
+
if(typeof prepareField =='function'){
|
|
277
|
+
const name = isObj(currentField) && defaultStr(currentField.field,i) || "";
|
|
278
|
+
const isPrimary = name && this.primaryKeyFields[name] && true || false;
|
|
279
|
+
const f = prepareField({field:defaultObj(currentField),isUpdate:isUpdated,name,index:i,counterIndex,isPrimary,fields,contex:this,data,datas,currentIndex,isUpdated,tableName,table});
|
|
280
|
+
if(f === false) return;
|
|
281
|
+
}
|
|
282
|
+
fields[i] = currentField;
|
|
267
283
|
})
|
|
268
284
|
if(isObj(customFields)){
|
|
269
285
|
extendObj(true,fields,customFields);
|
|
@@ -791,6 +807,7 @@ export default class TableDataScreenComponent extends FormDataScreen{
|
|
|
791
807
|
|
|
792
808
|
TableDataScreenComponent.propTypes = {
|
|
793
809
|
...defaultObj(FormData.propTypes),
|
|
810
|
+
prepareField : PropTypes.func,//La fonction permettant de faire des mutations sur le champ field à passer au formulaire form. si elle retourne false alors la field ne sera pas pris een compte
|
|
794
811
|
table : PropTypes.shape({
|
|
795
812
|
tableName : PropTypes.string,
|
|
796
813
|
table : PropTypes.string,
|