@fto-consult/expo-ui 8.58.6 → 8.60.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/bin/create-app/dependencies.js +2 -1
- package/bin/create-app.js +2 -1
- package/package.json +2 -2
- package/src/components/DocumentPicker/index.js +41 -0
- package/src/components/Fab/FabItem/old/FabItem.js +0 -1
- package/src/importer/getSelectFieldValue.js +23 -0
- package/src/importer/index.js +4 -0
- package/src/importer/parseCSV.js +81 -0
- package/src/importer/run.js +400 -0
- package/src/importer/validate.js +137 -0
- package/src/media/document.js +55 -0
- package/src/media/exports.js +131 -0
- package/src/media/index.js +1 -131
- package/src/screens/Help/openLibraries.js +122 -83
@@ -0,0 +1,137 @@
|
|
1
|
+
import getSelectFieldValue from "./getSelectFieldValue";
|
2
|
+
import appConfig from "$capp/config";
|
3
|
+
|
4
|
+
export default function validate(args){
|
5
|
+
let {data,requiredFields,index,fields,table,tableText}= defaultObj(args)
|
6
|
+
data = defaultObj(data);
|
7
|
+
requiredFields = defaultArray(requiredFields);
|
8
|
+
if(!isObj(fields)) return "champs de validation incorects";
|
9
|
+
for(let i in fields){
|
10
|
+
let field = fields[i];
|
11
|
+
if(!isObj(field)) continue;
|
12
|
+
let code = defaultStr(i,field.code);
|
13
|
+
let label = defaultStr(field.label,field.text,i);
|
14
|
+
let v = data[code];
|
15
|
+
let isFieldSelected = arrayValueExists(requiredFields,code);
|
16
|
+
let type = defaultStr(field.type,'text').toLowerCase().trim();
|
17
|
+
let validType = defaultStr(field.validType).toLowerCase();
|
18
|
+
let lSuffix = isNonNullString(tableText)? ("["+tableText+"]"):"";
|
19
|
+
let labelStr = (isNonNullString(v) || isNumber(v) ? (" la valeur <"+v+"> du champ ") : "le champ ")+label+lSuffix+"";
|
20
|
+
labelStr += (index)? (", ligne "+index):""
|
21
|
+
let isIdField = type == 'id' || type =="piece";
|
22
|
+
|
23
|
+
/**** les donées passés en paramètre de type tableau */
|
24
|
+
if(type.contains("select")){
|
25
|
+
if(field.multiple){
|
26
|
+
v = isArray(v)? v : (v?(v+""):"").split(",");
|
27
|
+
} else v = defaultStr(v);
|
28
|
+
let itemCodes = "";
|
29
|
+
let itemsL = Object.size((isObjOrArray(field.items)? field.items : [])) > 0 ? true : false;
|
30
|
+
let hasF = true;
|
31
|
+
let isSelectTableData = type == "selecttabledata";
|
32
|
+
if(isArray(v)){
|
33
|
+
let arr = [];
|
34
|
+
v.map((value)=>{
|
35
|
+
if(itemsL){
|
36
|
+
let _v = getSelectFieldValue({field,value});
|
37
|
+
itemCodes = defaultStr(itemCodes,_v.itemCodes);
|
38
|
+
if(_v.value !== false){
|
39
|
+
arr.push(_v.value);
|
40
|
+
}
|
41
|
+
} else if(isNonNullString(value)) {
|
42
|
+
arr.push(isSelectTableData? value.toUpperCase():value)
|
43
|
+
}
|
44
|
+
});
|
45
|
+
hasF = arr.length > 0 ? true : false;
|
46
|
+
v = arr;
|
47
|
+
} else {
|
48
|
+
if(itemsL){
|
49
|
+
let _v = getSelectFieldValue({field,value:v});
|
50
|
+
itemCodes = _v.itemCodes;
|
51
|
+
hasF = _v.value !== false? true : false;
|
52
|
+
if(hasF){
|
53
|
+
v = _v.value;
|
54
|
+
}
|
55
|
+
}
|
56
|
+
if(isSelectTableData && hasF){
|
57
|
+
v = v.toUpperCase();
|
58
|
+
}
|
59
|
+
//eif(isFieldSelected) console.log(hasF, code,_v,' is value');
|
60
|
+
}
|
61
|
+
if(isFieldSelected && !hasF && itemCodes){
|
62
|
+
return labelStr+" doit figurer parmi la liste : ["+itemCodes+"]";
|
63
|
+
}
|
64
|
+
}
|
65
|
+
|
66
|
+
if((isIdField || validType.contains("required") || field.required)){
|
67
|
+
if(isIdField && isNonNullString(data.table)){
|
68
|
+
} else if(v == undefined || v == null || v =='' || (isArray(v) && v.length <= 0)) {
|
69
|
+
return labelStr+" est requis";
|
70
|
+
}
|
71
|
+
}
|
72
|
+
if(isIdField && isNonNullString(v)){
|
73
|
+
v = v.trim();
|
74
|
+
if(!isValidDataFileName(v.replaceAll("/",""))) return labelStr+" a une valeur invalide";
|
75
|
+
}
|
76
|
+
if(type =="datafile" && v && !APP.DATA_FILE_MANAGER.get(v)){
|
77
|
+
return labelStr+ ", le "+APP.DATA_FILE_MANAGER.dataFileText+" "+defaultStr(v) +" est innexistant"
|
78
|
+
}
|
79
|
+
if((type =="number" || type=="decimal" || validType.contains("number") || validType.contains("decimal"))){
|
80
|
+
if(!isNumber(v)){
|
81
|
+
v = parseDecimal(v);
|
82
|
+
if(!isNumber(v) && isFieldSelected){
|
83
|
+
return labelStr+" doit être un nombre";
|
84
|
+
} else {
|
85
|
+
v = defaultDecimal(v);
|
86
|
+
}
|
87
|
+
}
|
88
|
+
}
|
89
|
+
|
90
|
+
if(type =='email' && v && !isValidEmail(v,false)){
|
91
|
+
return labelStr+" doit être un email valide";
|
92
|
+
}
|
93
|
+
if(type == 'date' && v){
|
94
|
+
let date = APP.date.toDateObj(v,true);
|
95
|
+
if(!date || !date.date){
|
96
|
+
return labelStr+" doit être une date valide au format yyyy-mm-dd";
|
97
|
+
}
|
98
|
+
}
|
99
|
+
if(type == 'time' && v && !APP.date.isValidSQLTime(v)){
|
100
|
+
return labelStr+" doit être une heure valide au format hh:mm:ss";
|
101
|
+
}
|
102
|
+
|
103
|
+
let strValid = labelStr+" doit être une chaine de caractère non nulle ";
|
104
|
+
if(isNumber(field.length) && isNonNullString(v) && v.length != field.length){
|
105
|
+
return strValid+" de "+field.length + " caractères";
|
106
|
+
}
|
107
|
+
if(isNumber(field.minLength) && isNonNullString(v) && v.length < field.minLength){
|
108
|
+
return strValid+" de "+field.minLength+" caractères minimum";
|
109
|
+
}
|
110
|
+
if(isNumber(field.maxLength) && isNonNullString(v) && v.length > field.maxLength){
|
111
|
+
return strValid+" de "+field.maxLength+" caractères maximum";
|
112
|
+
}
|
113
|
+
if(type =='switch'){
|
114
|
+
let checkedLabel = defaultStr(field.checkedLabel,code =='archived'?'Archivé':'Désactivé').toLowerCase().trim(),
|
115
|
+
uncheckedLabel = defaultStr(field.uncheckedLabel,code =='archived'?'Non archivé':'Activé').toLowerCase().trim(),
|
116
|
+
checkedValue = defaultVal(field.checkedValue,1),uncheckedValue = defaultVal(field.uncheckedValue,0)
|
117
|
+
v = (defaultVal(v,field.defaultValue,"")+"").toLowerCase().trim();
|
118
|
+
if(v == checkedValue+""){
|
119
|
+
v = checkedValue;
|
120
|
+
} else if(v == uncheckedValue+""){
|
121
|
+
v = uncheckedValue;
|
122
|
+
} else if(v == checkedLabel){
|
123
|
+
v = checkedValue;
|
124
|
+
} else if(v == uncheckedLabel){
|
125
|
+
v = uncheckedValue;
|
126
|
+
}
|
127
|
+
if(!arrayValueExists([checkedValue,uncheckedValue],v)){
|
128
|
+
return labelStr+" doit l'une des valeur : "+checkedLabel+"/"+uncheckedLabel+"/"+checkedValue+"/"+uncheckedValue;
|
129
|
+
}
|
130
|
+
}
|
131
|
+
if(isFieldSelected && v !== undefined){
|
132
|
+
data[code] = v;
|
133
|
+
}
|
134
|
+
}
|
135
|
+
data["has-validate-content-imp"] = true;
|
136
|
+
return true;
|
137
|
+
}
|
@@ -0,0 +1,55 @@
|
|
1
|
+
import * as DocumentPicker from 'expo-document-picker';
|
2
|
+
import {extendObj} from "$cutils";
|
3
|
+
import notify from "$cnotify";
|
4
|
+
|
5
|
+
export const mimeTypes = {
|
6
|
+
sql : "application/sql",
|
7
|
+
json : "application/json",
|
8
|
+
pdf : "application/pdf",
|
9
|
+
xlsx : "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
10
|
+
image : "image/*",
|
11
|
+
xml : "application/xml",
|
12
|
+
csv : "text/csv",
|
13
|
+
}
|
14
|
+
/****
|
15
|
+
@param {object}, @see : https://docs.expo.dev/versions/latest/sdk/document-picker/#documentpickeroptions
|
16
|
+
for mimeTypes, @see : https://en.wikipedia.org/wiki/Media_type
|
17
|
+
*/
|
18
|
+
export const pickDocument = (options)=>{
|
19
|
+
options = extendObj({},{
|
20
|
+
copyToCacheDirectory : true,
|
21
|
+
multiple : false,
|
22
|
+
type : undefined,
|
23
|
+
},options);
|
24
|
+
return new Promise((resolve,reject)=>{
|
25
|
+
return DocumentPicker.getDocumentAsync(options).then(({canceled,...rest})=>{
|
26
|
+
if(canceled){
|
27
|
+
notify.error("Opération annulée par l'utilisateur");
|
28
|
+
return reject({canceled});
|
29
|
+
}
|
30
|
+
return resolve({canceled,...rest});
|
31
|
+
})
|
32
|
+
})
|
33
|
+
}
|
34
|
+
|
35
|
+
export const pickJSON = (options)=>{
|
36
|
+
return pickDocument(extendObj({},options,{
|
37
|
+
type : mimeTypes.json,
|
38
|
+
}));
|
39
|
+
}
|
40
|
+
export const pickCSV = (options)=>{
|
41
|
+
return pickDocument(extendObj({},options,{
|
42
|
+
type : mimeTypes.csv,
|
43
|
+
}));
|
44
|
+
}
|
45
|
+
export const pickPDF = (options)=>{
|
46
|
+
return pickDocument(extendObj({},options,{
|
47
|
+
type : mimeTypes.pdf
|
48
|
+
}));
|
49
|
+
}
|
50
|
+
|
51
|
+
export const pickSQL = (options)=>{
|
52
|
+
return pickDocument(extendObj({},options,{
|
53
|
+
type : mimeTypes.sql,
|
54
|
+
}));
|
55
|
+
}
|
@@ -0,0 +1,131 @@
|
|
1
|
+
import {isObj,isBase64} from "$cutils";
|
2
|
+
import notify from "$enotify";
|
3
|
+
import Camera from "./camera";
|
4
|
+
import {isMobileNative} from "$platform";
|
5
|
+
import {getFilePickerOptions} from "./utils";
|
6
|
+
import React from "react";
|
7
|
+
|
8
|
+
let cameraRef = null;
|
9
|
+
|
10
|
+
export {cameraRef}
|
11
|
+
|
12
|
+
export const createCameraRef = ()=>{
|
13
|
+
const ref = React.useRef(null);
|
14
|
+
React.useEffect(()=>{
|
15
|
+
cameraRef = ref.current;
|
16
|
+
},[ref.current])
|
17
|
+
return ref;
|
18
|
+
}
|
19
|
+
|
20
|
+
import * as ImagePicker from 'expo-image-picker';
|
21
|
+
|
22
|
+
export const MEDIA_TYPES = {
|
23
|
+
ALL : ImagePicker.MediaTypeOptions.All,
|
24
|
+
IMAGES : ImagePicker.MediaTypeOptions.Images,
|
25
|
+
VIDEOS : ImagePicker.MediaTypeOptions.Videos,
|
26
|
+
}
|
27
|
+
|
28
|
+
export {ImagePicker};
|
29
|
+
|
30
|
+
export function checkPermission (method){
|
31
|
+
return new Promise((resolve,reject)=>{
|
32
|
+
(typeof method =="function" && method || ImagePicker.requestMediaLibraryPermissionsAsync)().then((r)=>{
|
33
|
+
if(isObj(r) && (r.granted || r.status =='granted')){
|
34
|
+
resolve(r);
|
35
|
+
return true;
|
36
|
+
} else {
|
37
|
+
reject(r);
|
38
|
+
}
|
39
|
+
}).catch((e)=>{
|
40
|
+
console.log(e," unable to grand media permission");
|
41
|
+
notify.error("Permission à l'accès aux médias refusée par l'utilisateur");
|
42
|
+
reject(e);
|
43
|
+
});
|
44
|
+
})
|
45
|
+
}
|
46
|
+
|
47
|
+
export * from "./utils";
|
48
|
+
|
49
|
+
const prepareImageResult = (result)=>{
|
50
|
+
if(!isObj(result)) return result;
|
51
|
+
if(Array.isArray(result.assets) && isObj(result.assets[0])){
|
52
|
+
result = {
|
53
|
+
...result,
|
54
|
+
...result.assets[0],
|
55
|
+
}
|
56
|
+
}
|
57
|
+
result.dataURL = result.dataUrl = isBase64(result.base64) ? ('data:image/jpeg;base64,'+result.base64) : null;
|
58
|
+
return result;
|
59
|
+
}
|
60
|
+
|
61
|
+
/**** @see : https://docs.expo.dev/versions/latest/sdk/imagepicker/#imagepickeroptions
|
62
|
+
* form more options.
|
63
|
+
*/
|
64
|
+
export const pickImageOrVideo = (options)=>{
|
65
|
+
return checkPermission().then(()=>{
|
66
|
+
return new Promise((resolve,reject)=>{
|
67
|
+
ImagePicker.launchImageLibraryAsync(getFilePickerOptions(options)).then((result)=>{
|
68
|
+
if(!result.cancelled && !result.canceled) {
|
69
|
+
resolve(prepareImageResult(result));
|
70
|
+
} else {
|
71
|
+
notify.warning("Opération annulée par l'utilisateur");
|
72
|
+
reject(result);
|
73
|
+
}
|
74
|
+
return null;
|
75
|
+
}).catch(reject);
|
76
|
+
})
|
77
|
+
})
|
78
|
+
}
|
79
|
+
|
80
|
+
export const pickImage = (options)=>{
|
81
|
+
options = defaultObj(options);
|
82
|
+
options.mediaTypes = ImagePicker.MediaTypeOptions.Images;
|
83
|
+
return pickImageOrVideo(options)
|
84
|
+
}
|
85
|
+
|
86
|
+
export const pickVideo = (options)=>{
|
87
|
+
options = defaultObj(options);
|
88
|
+
options.mediaTypes = ImagePicker.MediaTypeOptions.Videos;
|
89
|
+
return pickImageOrVideo(options)
|
90
|
+
}
|
91
|
+
|
92
|
+
export const nonZeroMin = function(args){
|
93
|
+
let arra = Array.prototype.slice.call(arguments,0).sort();
|
94
|
+
let min = 0;
|
95
|
+
for(let i in arra){
|
96
|
+
if(isNumber(arra[i]) && arra[i] > 0) {
|
97
|
+
if(min <= 0){
|
98
|
+
min = arra[i]
|
99
|
+
} else if(arra[i]< min ){
|
100
|
+
min = arra[i]
|
101
|
+
}
|
102
|
+
}
|
103
|
+
}
|
104
|
+
return min;
|
105
|
+
};
|
106
|
+
|
107
|
+
export {Camera};
|
108
|
+
|
109
|
+
export async function canTakePhoto(){
|
110
|
+
if(!isMobileNative()) return false;
|
111
|
+
return true;
|
112
|
+
}
|
113
|
+
|
114
|
+
export const takePhoto = (options)=>{
|
115
|
+
return new Promise((resolve,reject)=>{
|
116
|
+
return checkPermission(ImagePicker.requestCameraPermissionsAsync).then((perm)=>{
|
117
|
+
options = {base64:true,...Object.assign({},options)}
|
118
|
+
return ImagePicker.launchCameraAsync({...getFilePickerOptions(options)}).then((result)=>{
|
119
|
+
if(!result.cancelled && !result.canceled) {
|
120
|
+
resolve(prepareImageResult(result));
|
121
|
+
} else {
|
122
|
+
notify.warning("Opération annulée par l'utilisateur");
|
123
|
+
reject(result);
|
124
|
+
}
|
125
|
+
return null;
|
126
|
+
})
|
127
|
+
}).catch(reject);
|
128
|
+
})
|
129
|
+
}
|
130
|
+
|
131
|
+
export const takePicture = takePhoto;
|
package/src/media/index.js
CHANGED
@@ -1,131 +1 @@
|
|
1
|
-
|
2
|
-
import notify from "$enotify";
|
3
|
-
import Camera from "./camera";
|
4
|
-
import {isMobileNative} from "$platform";
|
5
|
-
import {getFilePickerOptions} from "./utils";
|
6
|
-
import React from "react";
|
7
|
-
|
8
|
-
let cameraRef = null;
|
9
|
-
|
10
|
-
export {cameraRef}
|
11
|
-
|
12
|
-
export const createCameraRef = ()=>{
|
13
|
-
const ref = React.useRef(null);
|
14
|
-
React.useEffect(()=>{
|
15
|
-
cameraRef = ref.current;
|
16
|
-
},[ref.current])
|
17
|
-
return ref;
|
18
|
-
}
|
19
|
-
|
20
|
-
import * as ImagePicker from 'expo-image-picker';
|
21
|
-
|
22
|
-
export const MEDIA_TYPES = {
|
23
|
-
ALL : ImagePicker.MediaTypeOptions.All,
|
24
|
-
IMAGES : ImagePicker.MediaTypeOptions.Images,
|
25
|
-
VIDEOS : ImagePicker.MediaTypeOptions.Videos,
|
26
|
-
}
|
27
|
-
|
28
|
-
export {ImagePicker};
|
29
|
-
|
30
|
-
export function checkPermission (method){
|
31
|
-
return new Promise((resolve,reject)=>{
|
32
|
-
(typeof method =="function" && method || ImagePicker.requestMediaLibraryPermissionsAsync)().then((r)=>{
|
33
|
-
if(isObj(r) && (r.granted || r.status =='granted')){
|
34
|
-
resolve(r);
|
35
|
-
return true;
|
36
|
-
} else {
|
37
|
-
reject(r);
|
38
|
-
}
|
39
|
-
}).catch((e)=>{
|
40
|
-
console.log(e," unable to grand media permission");
|
41
|
-
notify.error("Permission à l'accès aux médias refusée par l'utilisateur");
|
42
|
-
reject(e);
|
43
|
-
});
|
44
|
-
})
|
45
|
-
}
|
46
|
-
|
47
|
-
export * from "./utils";
|
48
|
-
|
49
|
-
const prepareImageResult = (result)=>{
|
50
|
-
if(!isObj(result)) return result;
|
51
|
-
if(Array.isArray(result.assets) && isObj(result.assets[0])){
|
52
|
-
result = {
|
53
|
-
...result,
|
54
|
-
...result.assets[0],
|
55
|
-
}
|
56
|
-
}
|
57
|
-
result.dataURL = result.dataUrl = isBase64(result.base64) ? ('data:image/jpeg;base64,'+result.base64) : null;
|
58
|
-
return result;
|
59
|
-
}
|
60
|
-
|
61
|
-
/**** @see : https://docs.expo.dev/versions/latest/sdk/imagepicker/#imagepickeroptions
|
62
|
-
* form more options.
|
63
|
-
*/
|
64
|
-
export const pickImageOrVideo = (options)=>{
|
65
|
-
return checkPermission().then(()=>{
|
66
|
-
return new Promise((resolve,reject)=>{
|
67
|
-
ImagePicker.launchImageLibraryAsync(getFilePickerOptions(options)).then((result)=>{
|
68
|
-
if(!result.cancelled && !result.canceled) {
|
69
|
-
resolve(prepareImageResult(result));
|
70
|
-
} else {
|
71
|
-
notify.warning("Opération annulée par l'utilisateur");
|
72
|
-
reject(result);
|
73
|
-
}
|
74
|
-
return null;
|
75
|
-
}).catch(reject);
|
76
|
-
})
|
77
|
-
})
|
78
|
-
}
|
79
|
-
|
80
|
-
export const pickImage = (options)=>{
|
81
|
-
options = defaultObj(options);
|
82
|
-
options.mediaTypes = ImagePicker.MediaTypeOptions.Images;
|
83
|
-
return pickImageOrVideo(options)
|
84
|
-
}
|
85
|
-
|
86
|
-
export const pickVideo = (options)=>{
|
87
|
-
options = defaultObj(options);
|
88
|
-
options.mediaTypes = ImagePicker.MediaTypeOptions.Videos;
|
89
|
-
return pickImageOrVideo(options)
|
90
|
-
}
|
91
|
-
|
92
|
-
export const nonZeroMin = function(args){
|
93
|
-
let arra = Array.prototype.slice.call(arguments,0).sort();
|
94
|
-
let min = 0;
|
95
|
-
for(let i in arra){
|
96
|
-
if(isNumber(arra[i]) && arra[i] > 0) {
|
97
|
-
if(min <= 0){
|
98
|
-
min = arra[i]
|
99
|
-
} else if(arra[i]< min ){
|
100
|
-
min = arra[i]
|
101
|
-
}
|
102
|
-
}
|
103
|
-
}
|
104
|
-
return min;
|
105
|
-
};
|
106
|
-
|
107
|
-
export {Camera};
|
108
|
-
|
109
|
-
export async function canTakePhoto(){
|
110
|
-
if(!isMobileNative()) return false;
|
111
|
-
return true;
|
112
|
-
}
|
113
|
-
|
114
|
-
export const takePhoto = (options)=>{
|
115
|
-
return new Promise((resolve,reject)=>{
|
116
|
-
return checkPermission(ImagePicker.requestCameraPermissionsAsync).then((perm)=>{
|
117
|
-
options = {base64:true,...Object.assign({},options)}
|
118
|
-
return ImagePicker.launchCameraAsync({...getFilePickerOptions(options)}).then((result)=>{
|
119
|
-
if(!result.cancelled && !result.canceled) {
|
120
|
-
resolve(prepareImageResult(result));
|
121
|
-
} else {
|
122
|
-
notify.warning("Opération annulée par l'utilisateur");
|
123
|
-
reject(result);
|
124
|
-
}
|
125
|
-
return null;
|
126
|
-
})
|
127
|
-
}).catch(reject);
|
128
|
-
})
|
129
|
-
}
|
130
|
-
|
131
|
-
export const takePicture = takePhoto;
|
1
|
+
export * from "./exports";
|