@fto-consult/expo-ui 8.53.1 → 8.54.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.
@@ -12,6 +12,8 @@ import Notifications from "$components/Notifications";
12
12
  import auth from "$src/auth";
13
13
  import tablesData, { getTable as getTableData } from "$database/tables";
14
14
  import {defaultStr} from "$cutils";
15
+ import customFormFields from "$components/Form/customFields";
16
+
15
17
 
16
18
  export default function AppMainEntry(){
17
19
  return <ExpoUIProvider
@@ -88,7 +90,7 @@ export default function AppMainEntry(){
88
90
  test : Test, //ou test est le fom field associé au type test, ie le composant qui sera rendu pour ce type de Champ,
89
91
  }
90
92
  */
91
- customFormFields : {},
93
+ customFormFields,
92
94
  /***
93
95
  la fonction permettant de muter les props du composant TableLink, permetant de lier les tables entre elles
94
96
  Le composant TableLink permet de lier les données d'une tableData, L'usage dudit composant est définit dans la documentation de l'application
@@ -0,0 +1,28 @@
1
+ import IdField from "$ecomponents/Form/Fields/IdField";
2
+
3
+ export default class IdFieldComponent extends IdField {
4
+ constructor(props) {
5
+ super(props);
6
+ }
7
+ isValidRuleDynamic() {
8
+ return true;
9
+ }
10
+
11
+ /*****
12
+ Le composant de type id, permet de générer un id pour chaque champ de ce type qui est en mode disabled en cas de modification de la donnée.
13
+ L'id générée peut être le résultat d'un appel d'api distante et doit être soit un nombre soit une chaine de caractère non null.
14
+ normalement les champs de type id sont unique dans une table data, la fonction suivante a pour but une fois, en cas d'ajout d'un novuel élémnent de la table data
15
+ et lorsque l'évènement onBlur est appelé sur le champ de type id, d'appeler une fonction distante afin de générer une valeur de l'id pour la valeur à enregistrer en bd;
16
+ @param {function} callback, la fonction de rappel à appeler une fois l'id récupérer. doit passer en paramètre de la dite fonction, l'id récupérée en bd. L'id récupérée en bd doit être unique et ne dois jamais été assigné à un autre élément de la table data
17
+ */
18
+ fetchNewIdRemotely(callback){
19
+ return super.fetchNewIdRemotely(callback);
20
+ }
21
+ isTextField() {
22
+ return true;
23
+ }
24
+ }
25
+
26
+ IdFieldComponent.propTypes = {
27
+ ...Object.assign({},IdField.propTypes)
28
+ };
@@ -0,0 +1,27 @@
1
+ import SelectTableData from "$ecomponents/Form/Fields/SelectTableData";
2
+ import React from "$react";
3
+ import fetch from "$capi/fetch";
4
+
5
+ const SelectTableDataComponentLayout = React.forwardRef(({fetchItems,...props},ref)=>{
6
+ return <SelectTableData
7
+ {...props}
8
+ ref = {ref}
9
+ parseMangoQueries = {true}
10
+ prepareFilters = {false}
11
+ /****
12
+ implémenter votre logique de récupération des données des en base de donées, des champs de type SelectTableData, permettant la sélection d'une table de donénes de la bd
13
+ */
14
+ fetchItems={(path,opts)=>{
15
+ if(typeof fetchItems =='function'){
16
+ return fetchItems(path,opts);
17
+ }
18
+ return fetch(path,opts);
19
+ }}
20
+ />
21
+ });
22
+
23
+ SelectTableDataComponentLayout.propTypes = SelectTableData.propTypes;
24
+
25
+ SelectTableDataComponentLayout.displayName = "SelectTableDataComponentLayout";
26
+
27
+ export default SelectTableDataComponentLayout;
@@ -0,0 +1,9 @@
1
+ import IdField from "./IdField";
2
+ import SelectTableData from "./SelectTableData";
3
+
4
+ export default {
5
+ id : IdField,
6
+ idfield : IdField,
7
+ SelectTableData,
8
+ selecttabledata : SelectTableData,
9
+ };
@@ -8,16 +8,42 @@
8
8
 
9
9
  import TableData from "$eScreen/TableData";
10
10
  import notify from "$cnotify";
11
+ import {defaultStr} from "$cutils";
12
+ import getTable from "$database/tables/getTable"
11
13
 
12
14
 
13
15
  export default class TableDataScreenItem extends TableData{
14
16
  /**** cette méthode est très utile pour la vérification des id de type unique en base de données
17
+ Elle est valable pour les champs de type id, de type piece, ou dont la propriété primaryKey est à true ou la proprité unique est à true,
18
+ Elle est appelée pour les champs de type id en cas d'ajout d'un élément de la table data; Lorsque l'évènement onBlur est appelé sur le champ de type id,
19
+ La fonction suivante est appelée dans le but de vérifier s'il existe déjà en base de données une valeur idenetique à celle renseignée par l'utilisateur.
15
20
  par exemple, vous avez une table en base de données dont l'id est le code et en création de la nouvelle données, vous vérifiez si celle entrée par l'utilisateur existe déjà en base ou non
16
21
  Cette fonction doit retourner une promise, qui lorsque la donnée existe, elle doit retourner l'objet correspondant à l'id recherché en bd ou généer une exception si elle n'existe pas
17
-
22
+ @return {Promise<object>}
18
23
  */
19
- fetchUniqueId ({value,field,fieldName,foreignKeyColumn,table:customT,foreignKeyTable}){
20
- return Promise.resolve({});
24
+ fetchUniqueId ({value,field,fieldName,foreignKeyColumn,table:customTable,tableName:customTableName,foreignKeyTable}){
25
+ const tableObj = this.getTableObj(); //tableObj représente la table data, enreigstré dans $src/database/tables dont le nom est passé à l'item en cours
26
+ let tableName = defaultStr(foreignKeyTable,this.tableName,customTable,customTableName).trim().toUpperCase();
27
+ const foreignTableObj = tableName !== this.tableName ? getTable(tableName) : tableObj
28
+ foreignKeyColumn = defaultStr(foreignKeyColumn,field,fieldName);
29
+ if(!foreignKeyColumn){
30
+ return Promise.reject({message:"Impossible de faire un fetch de l'id unique pour la table"+foreignKeyTable+", de valuer : "+value})
31
+ }
32
+ if(!foreignTableObj){
33
+ return Promise.reject({message:`Impossible de récupérer la données d'id unique lié à la table ${foreignKeyTable}, colonne ${foreignKeyColumn} car la table data est invalide`})
34
+ }
35
+ tableName = defaultStr(foreignTableObj.tableName,this.tableName,foreignTableObj.table,tableName).toUpperCase();
36
+ //il s'agit là de récupérer une données en base de données, ayant dont la colonne [foreignKeyColumn.trim()] = value;
37
+ const where = {
38
+ [foreignKeyColumn.trim()] : value //la condition d'appel de la données à récupérer en base de données
39
+ };
40
+ /***
41
+ implémenter votre propre logique afin de récupérer la données, au backend; il est à noter que l'objet à retourner, si existant en bd doit être avoir au moins un champ définit de la forme : {[foreignKeyColmn]:[valuerEnBD]}
42
+ Si une exception est généré, alors cette exception doit avoir un champ status = 404, pour signifier que l'objet n'existe pas en bd
43
+ */
44
+ return Promise.reject({
45
+ message : `Veuillez implémenter votre logique de récupération en bd du champ ${foreignKeyColumn} pour la valeur ${value} de la table data ${tableName}. Consultez le fichier $src/screens/TableDataScreen afin d'implémenetr la fonction fetchUniqueId`
46
+ });
21
47
  }
22
48
  /*** implémenter la routine beforeSave, avant l'enregistrement de la données liée à la table encours
23
49
  -si cette fonction retourne une chaine de caractère, alors cette chaine est considérée comme une erreur et elle est affichée via une notification à l'utilisateur
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fto-consult/expo-ui",
3
- "version": "8.53.1",
3
+ "version": "8.54.0",
4
4
  "description": "Bibliothèque de composants UI Expo,react-native",
5
5
  "react-native-paper-doc": "https://github.com/callstack/react-native-paper/tree/main/docs/docs/guides",
6
6
  "scripts": {
@@ -45,6 +45,11 @@ export default function TestDatagridComponent({count,...props}){
45
45
  avatar : {
46
46
  type : "image",
47
47
  label: 'Avatar',
48
+ withLabel : false,
49
+ size : 120,
50
+ datagrid : {
51
+ size : 50,
52
+ }
48
53
  },
49
54
  birthdate : {
50
55
  type : "date",
@@ -14,6 +14,12 @@ export default class FormIDField extends TextField {
14
14
  this.newFieldIdValue = undefined;
15
15
  return super.UNSAFE_componentWillReceiveProps(nextProps);
16
16
  }
17
+ /***
18
+ détermnine si la valeur est valide
19
+ */
20
+ isValidIdValue(value){
21
+ return isNonNullString(value) || typeof value =="number";
22
+ }
17
23
  componentDidMount(){
18
24
  super.componentDidMount();
19
25
  this.fetchNewId(false);
@@ -26,40 +32,51 @@ export default class FormIDField extends TextField {
26
32
  errorCb(e);
27
33
  }
28
34
  }
29
-
35
+
36
+ /****
37
+ récupère la valeur de l'id distante
38
+ @param {function} cb, la fonction de rappel à appeler pour le rendu du résultata
39
+ */
40
+ fetchNewIdRemotely(cb){
41
+ const data = defaultObj(this.props.data);
42
+ const fId = typeof this.props.fetchNewId =='function'? this.props.fetchNewId({...this.props,data,columnField:this.name}) : null;
43
+ if(isPromise(fId)){
44
+ return fId.then(cb).catch(e=>{
45
+ console.log(e," fetching new piece id ",this.name);
46
+ });
47
+ }
48
+ return cb(fId);
49
+ }
50
+
51
+
30
52
  /*** met à jour la données du numéro de piece */
31
53
  fetchNewId(focus){
32
54
  if(this.isFilter()){
33
55
  return Promise.resolve("");
34
56
  }
35
57
  const data = defaultObj(this.props.data);
36
- if(!isNonNullString(this.name)) return undefined;
58
+ const name = defaultStr(this.name, this.props.name);
59
+ if(!name) return Promise.resolve("");
37
60
  const cb = (value)=>{
38
- if(isNonNullString(value)){
61
+ if(this.isValidIdValue(value)){
39
62
  this.newFieldIdValue = value;
40
63
  this.validate({value});
41
64
  if(focus) this.focus();
42
65
  }
43
66
  }
44
- if(isNonNullString(data[this.name])){
45
- cb(data[this.name]);
46
- return data[this.name]
67
+ if(this.isValidIdValue(data[name])){
68
+ cb(data[name]);
69
+ return data[name]
47
70
  }
48
71
  setTimeout(()=>{
49
- const fId = typeof this.props.fetchNewId =='function'? this.props.fetchNewId({...this.props,data,columnField:this.name}) : null;
50
- if(isPromise(fId)){
51
- return fId.then(cb).catch(e=>{
52
- console.log(e," fetching new piece id ",this.name);
53
- });
54
- }
55
- return cb(fId);
72
+ this.fetchNewIdRemotely(cb);
56
73
  },10);
57
74
  }
58
75
  /*** retourne la valeur validée */
59
76
  getValidValue(data){
60
77
  const validValue = super.getValidValue(data);
61
78
  if(!isNonNullString(this.name)) return validValue;
62
- data[this.name] = defaultStr(data[this.name],validValue,this.newFieldIdValue);
79
+ data[this.name] = this.isValidIdValue(data[this.name])? data[this.name] : this.isValidIdValue(validValue)? validValue : this.newFieldIdValue;
63
80
  return validValue;
64
81
  }
65
82
  isValidRuleDynamic(){
@@ -69,30 +86,34 @@ export default class FormIDField extends TextField {
69
86
  return false;
70
87
  }
71
88
  componentDidUpdate(){
72
- if(!this.isFilter() && !isNonNullString(this.newFieldIdValue)){
89
+ if(!this.isFilter() && !this.isValidIdValue(this.newFieldIdValue)){
73
90
  this.fetchNewId();
74
91
  }
75
92
  }
76
93
  _render(props,setRef){
77
94
  delete props.validType;
95
+ const data = defaultObj(props.data);
96
+ const name = defaultStr(this.name, this.props.name);
97
+ const hasV = this.isValidIdValue(data[name]);
98
+ props.upper = typeof props.upper =="boolean"? props.upper : true;
78
99
  if(!this.isFilter()){
79
- const upper = props.upper !== false ? UPPER_CASE : "";
80
- if(isNonNullString(this.name) && isObj(props.data) && isNonNullString(props.data[this.name])){
100
+ const upper = props.upper ? UPPER_CASE : "";
101
+ if(name && hasV){
81
102
  props.disabled = true;
82
103
  props.validType = upper;
83
- props.defaultValue = props.data[this.name];
104
+ props.defaultValue = data[name];
84
105
  } else {
85
106
  props.validType = 'required|'+upper;
86
107
  }
87
108
  if(typeof props.minLength !=='number'){
88
- props.minLength = 2;
109
+ props.minLength = 2; //la longueur minimale d'un champ de type id est de 2
89
110
  }
90
- const defValue = props.defaultValue = isNonNullString(props.defaultValue)? props.defaultValue : isNonNullString(this.newFieldIdValue)? this.newFieldIdValue : undefined;
111
+ const defValue = props.defaultValue = this.isValidIdValue(props.defaultValue)? props.defaultValue : this.isValidIdValue(this.newFieldIdValue)? this.newFieldIdValue : undefined;
91
112
  props.validRule = props.validType;
92
113
  props.contentContainerProps = Object.assign({},props.contentContainerProps)
93
114
  props.contentContainerProps.pointerEvents = defaultStr(props.contentContainerProps.pointerEvents,"auto");
94
115
  props.enableCopy = typeof props.enableCopy ==='boolean'? props.enableCopy : (props.defaultValue || this.newFieldIdValue ? true : false);
95
- props.readOnly = typeof props.disabled ==='boolean' ? !!!props.disabled : typeof props.readOnly =="boolean"? !!!props.disabled : false;
116
+ props.readOnly = typeof props.readOnly =="boolean"? props.readOnly : typeof props.disabled ==='boolean' ? props.disabled : false;
96
117
 
97
118
  const {right} = props;
98
119
  props.right = (props)=>{
@@ -105,7 +126,6 @@ export default class FormIDField extends TextField {
105
126
  }
106
127
  return r;
107
128
  }
108
-
109
129
  this.setValidRule(props.validType);
110
130
  } else {
111
131
  props.enableCopy = false;
@@ -463,8 +463,9 @@ export default class FormListComponent extends AppComponent {
463
463
  primaryText = defaultFunc(primaryText,x=>null);
464
464
  renderAvatar = defaultFunc(renderAvatar,x=>null);
465
465
  /*** les props de chaque items de la liste */
466
- itemProps= {...defaultObj(itemProps)}
466
+ itemProps= Object.clone(defaultObj(itemProps))
467
467
  const descriptionNumberOfLines = typeof itemProps.rows ==='number' && itemProps.rows ? itemProps.rows : 3;
468
+ const {left:itemLeft,right:itemRight} = itemProps;
468
469
  let counter = -1;
469
470
  let is_o = this.isHandlingObject;
470
471
  let addIconObj = null;
@@ -563,8 +564,9 @@ export default class FormListComponent extends AppComponent {
563
564
  </View>
564
565
  <View testID={testID+"_FormListWrapper"} style={[theme.styles.ph1]}>
565
566
  <FlashList
566
- items = {allData}
567
567
  responsive
568
+ {...defaultObj(this.props.listProps)}
569
+ items = {allData}
568
570
  prepareItems = {(items)=>{
569
571
  const itx = [];
570
572
  Object.map(items,(data,index,ct)=>{
@@ -572,7 +574,7 @@ export default class FormListComponent extends AppComponent {
572
574
  const _index = this.getIndex({data,index,allData:items});
573
575
  if(is_o && (!isNumber(_index) && !isNonNullString(_index))) return null;
574
576
  counter++;
575
- const pArgs = {avatarProps,context,itemProps,data:data,index,allData:allData};
577
+ const pArgs = {avatarProps,context,itemProps,data,item:data,index,allData:allData};
576
578
  const deletable = deletableFunc(pArgs),
577
579
  readOnly = readOnlyFunc(pArgs);
578
580
  let avatar = renderAvatar.call(context,pArgs);
@@ -590,6 +592,12 @@ export default class FormListComponent extends AppComponent {
590
592
  avatar = undefined;
591
593
  }
592
594
  itemProps.left = (lProps)=>{
595
+ const l = typeof itemLeft =="function"? itemLeft({...lProps,...pArgs}) : itemLeft;
596
+ if(l && React.isValidElement(l)){
597
+ return <>
598
+ {l}<Avatar suffix={ct} {...avatarProps} src={src}>{avatar}</Avatar>
599
+ </>
600
+ }
593
601
  return <Avatar suffix={ct} {...avatarProps} src={src}>{avatar}</Avatar>
594
602
  };
595
603
  }
@@ -616,6 +624,7 @@ export default class FormListComponent extends AppComponent {
616
624
  renderItem = {({item})=>{
617
625
  const {data,title,description,key,_index,props,index,readOnly,deletable} = item;
618
626
  const titleText = React.getTextContent(title);
627
+ const r = typeof itemRight =="function"? itemRight(item) : itemRight;
619
628
  return <View key={key} testID={testID+".Cell"+key} style={[theme.styles.w100]}>
620
629
  <Surface key={key} elevation={5} {...itemContainerProps} style={[styles.itemContainer,itemContainerProps.style]}>
621
630
  <List.Item
@@ -637,6 +646,7 @@ export default class FormListComponent extends AppComponent {
637
646
  React.stopEventPropagation(e);
638
647
  this.delete({...data},index,title);
639
648
  }}></Icon>}
649
+ {React.isValidElement(r)? r : null}
640
650
  </View>
641
651
  }}
642
652
  />
@@ -767,6 +777,7 @@ FormListComponent.propTypes = {
767
777
  //sa peut être un contenu noeu où alors un élément où une chaine de caractère
768
778
  onRemove : PropTypes.func,
769
779
  onDelete : PropTypes.func,
780
+ listProps : PropTypes.object, //les props à passer au composant FlashList
770
781
  }
771
782
 
772
783
  const styles = StyleSheet.create({
@@ -1,6 +1,6 @@
1
1
  module.exports = {
2
2
  "@fto-consult/expo-ui": {
3
- "version": "8.52.6",
3
+ "version": "8.53.1",
4
4
  "url": "https://github.com/borispipo/expo-ui#readme",
5
5
  "license": "ISC"
6
6
  },
@@ -44,6 +44,11 @@ module.exports = {
44
44
  "url": "https://github.com/react-native-async-storage/async-storage#readme",
45
45
  "license": "MIT"
46
46
  },
47
+ "@react-native-community/datetimepicker": {
48
+ "version": "7.6.1",
49
+ "url": "https://github.com/react-native-community/datetimepicker#readme",
50
+ "license": "MIT"
51
+ },
47
52
  "@react-native-community/netinfo": {
48
53
  "version": "11.1.0",
49
54
  "url": "https://github.com/react-native-netinfo/react-native-netinfo#readme",
@@ -149,25 +154,26 @@ module.exports = {
149
154
  "url": "https://docs.expo.dev/versions/latest/sdk/webbrowser/",
150
155
  "license": "MIT"
151
156
  },
152
- "react": {
153
- "version": "18.2.0",
154
- "url": "https://reactjs.org/",
155
- "license": "MIT"
156
- },
157
157
  "react-native": {
158
158
  "version": "0.73.5",
159
159
  "url": "https://reactnative.dev/",
160
160
  "license": "MIT"
161
161
  },
162
+ "react-native-big-list": {
163
+ "version": "1.6.1",
164
+ "url": "https://marcocesarato.github.io/react-native-big-list-docs/",
165
+ "license": "GPL-3.0-or-later"
166
+ },
167
+ "react-native-blob-util": {
168
+ "version": "0.18.6",
169
+ "url": "https://github.com/RonRadtke/react-native-blob-util",
170
+ "license": "MIT"
171
+ },
162
172
  "react-native-gesture-handler": {
163
173
  "version": "2.14.1",
164
174
  "url": "https://github.com/software-mansion/react-native-gesture-handler#readme",
165
175
  "license": "MIT"
166
176
  },
167
- "react-native-get-random-values": {
168
- "version": "1.8.0",
169
- "license": "MIT"
170
- },
171
177
  "react-native-reanimated": {
172
178
  "version": "3.6.2",
173
179
  "url": "https://github.com/software-mansion/react-native-reanimated#readme",
@@ -188,21 +194,11 @@ module.exports = {
188
194
  "url": "https://github.com/react-native-community/react-native-svg",
189
195
  "license": "MIT"
190
196
  },
191
- "react-native-view-shot": {
192
- "version": "3.8.0",
193
- "url": "https://github.com/gre/react-native-view-shot",
194
- "license": "MIT"
195
- },
196
197
  "react-native-webview": {
197
198
  "version": "13.6.4",
198
199
  "url": "https://github.com/react-native-webview/react-native-webview#readme",
199
200
  "license": "MIT"
200
201
  },
201
- "socket.io-client": {
202
- "version": "4.7.4",
203
- "url": "https://github.com/socketio/socket.io-client.git",
204
- "license": "MIT"
205
- },
206
202
  "stream-browserify": {
207
203
  "version": "3.0.0",
208
204
  "url": "https://github.com/browserify/stream-browserify",
@@ -1,5 +0,0 @@
1
- export default function BarCodeScanner(){
2
- return null;
3
- }
4
-
5
- BarCodeScanner.propTypes = {}