@fto-consult/expo-ui 5.2.0 → 5.4.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/appConfig.txt +1 -0
- package/index.js +13 -0
- package/package.json +2 -2
- package/src/App.js +3 -1
- package/src/components/AppBar/index.js +1 -1
- package/src/components/Datagrid/SWRDatagrid.js +3 -0
- package/src/index.js +14 -7
- package/src/navigation/index.js +13 -5
- package/src/screens/Auth/Profile.js +1 -1
- package/src/screens/Help/PrivacyPolicy/content.js +1 -1
- package/src/screens/ScreenWrapper.js +1 -1
- package/src/screens/index.js +13 -12
package/appConfig.txt
CHANGED
|
@@ -20,4 +20,5 @@
|
|
|
20
20
|
}
|
|
21
21
|
getTableData : {function(tableName)=>table} retourne l'ojet table data,
|
|
22
22
|
swrRefreshTimeout : {number} le délai d'inactivité auquel, une fois l'application active, les données de type listData sont rafraichies
|
|
23
|
+
handleHelpScreen : {boolean}, //if Help screen will be added on navigation's main drawer
|
|
23
24
|
}
|
package/index.js
CHANGED
|
@@ -2,6 +2,19 @@ import { registerRootComponent } from "expo";
|
|
|
2
2
|
import {Platform } from 'react-native';
|
|
3
3
|
import App from "./src/App";
|
|
4
4
|
const isWeb = Platform.OS === "web";
|
|
5
|
+
|
|
6
|
+
/****
|
|
7
|
+
* les options sont de la forme :
|
|
8
|
+
* {
|
|
9
|
+
* @param init {function} ()=>Promise<{}>, initialise l'application, lorsque la promèsse n'est pas résolue, alors l'application considère qu'il s'agit d'une étape pour l'écran de GetStarted dans ce cas,
|
|
10
|
+
* l'option la route getStartedRouteName est utilisée comme route par défaut de l'application
|
|
11
|
+
* @param initialRouteName {string} la route initiale, par d'afaut Home, valide lorsque la promèsse résultat de la fonction init est résolue
|
|
12
|
+
* @param getStartedRouteName {string} la route de l'écran de GetStarted, valide lorsque la promèsse résultat de la fonction init n'est pas résolue
|
|
13
|
+
* L'écran de route getStartedRouteName prend en paramètre onGetStarted {function}, qui est appelée lorsque le contenu de l'écran GetStarted est affiché à l'utilisateur
|
|
14
|
+
* @maram {swrConfig}, les options supplémentaires à passer au gestinnaire swr
|
|
15
|
+
* les écrans d'initialisation doivent garder la propriété Start à true ou doivent avoir le groupe INTALL, pour spécifier que ce sont es écrans qui apparaissent lorsque l'application n'est pas initialisée
|
|
16
|
+
* }
|
|
17
|
+
*/
|
|
5
18
|
export default function registerApp (options){
|
|
6
19
|
options = options && typeof options =='object' && !Array.isArray(options)? options : {};
|
|
7
20
|
registerRootComponent(function(props){
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fto-consult/expo-ui",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.4.0",
|
|
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": "^
|
|
64
|
+
"@fto-consult/common": "^3.3.5",
|
|
65
65
|
"@gorhom/portal": "^1.0.14",
|
|
66
66
|
"@react-native-async-storage/async-storage": "^1.17.11",
|
|
67
67
|
"@react-native-community/datetimepicker": "^6.7.3",
|
package/src/App.js
CHANGED
|
@@ -40,7 +40,7 @@ Object.map(Utils,(v,i)=>{
|
|
|
40
40
|
window[i] = v;
|
|
41
41
|
}
|
|
42
42
|
});
|
|
43
|
-
export default function getIndex({onMount,onUnmount,onRender,preferences:appPreferences,...rest}){
|
|
43
|
+
export default function getIndex({onMount,onUnmount,swrConfig,onRender,preferences:appPreferences,...rest}){
|
|
44
44
|
const isScreenFocusedRef = React.useRef(true);
|
|
45
45
|
///garde pour chaque écran sa date de dernière activité
|
|
46
46
|
const screensRef = React.useRef({});//la liste des écrans actifs
|
|
@@ -49,6 +49,7 @@ export default function getIndex({onMount,onUnmount,onRender,preferences:appPref
|
|
|
49
49
|
const appStateRef = React.useRef({});
|
|
50
50
|
const isKeyboardOpenRef = React.useRef(false);
|
|
51
51
|
React.useOnRender(onRender);
|
|
52
|
+
swrConfig = defaultObj(swrConfig);
|
|
52
53
|
React.useEffect(()=>{
|
|
53
54
|
///la fonction de rappel lorsque le composant est monté
|
|
54
55
|
let cb = typeof onMount =='function'? onMount() : null;
|
|
@@ -120,6 +121,7 @@ export default function getIndex({onMount,onUnmount,onRender,preferences:appPref
|
|
|
120
121
|
return (
|
|
121
122
|
<SWRConfig
|
|
122
123
|
value={{
|
|
124
|
+
...swrConfig,
|
|
123
125
|
provider: () => new Map(),
|
|
124
126
|
isOnline() {
|
|
125
127
|
/* Customize the network state detector */
|
|
@@ -27,7 +27,6 @@ export const GO_BACK_EVENT = "STACK_NAVIGATOR_GO_BACK";
|
|
|
27
27
|
* @param menuProps : les props à passer au menu au cas où les actions de l'appBar son segmentés avec certaines qui sont découpées dans un menu more
|
|
28
28
|
|
|
29
29
|
*/
|
|
30
|
-
const isNullOrE = x => x === null || x === false;
|
|
31
30
|
|
|
32
31
|
const AppBarComponent = React.forwardRef((props,ref)=> {
|
|
33
32
|
let { bindResizeEvent,elevation,isMainDrawer,
|
|
@@ -66,6 +65,7 @@ const AppBarComponent = React.forwardRef((props,ref)=> {
|
|
|
66
65
|
}
|
|
67
66
|
title = defaultVal(title,params.title,APP.getName());
|
|
68
67
|
backActionProps = Object.assign({},backActionProps);
|
|
68
|
+
backActionProps.testID = defaultStr(backActionProps.testID,testID+"_BackAction");
|
|
69
69
|
|
|
70
70
|
let BackActionComponent = backAction === false ? null : React.isComponent(backAction)? backAction : back ? Appbar.BackAction : Icon ;
|
|
71
71
|
backActionProps.color = backActionProps.color && Colors.isValid(backActionProps.color)? backActionProps.color : anchorStyle.color;
|
|
@@ -177,6 +177,9 @@ const SWRDatagridComponent = React.forwardRef((props,ref)=>{
|
|
|
177
177
|
opts = defaultObj(opts);
|
|
178
178
|
opts.fetchOptions = isObj(opts.fetchOptions)? Object.clone(opts.fetchOptions) : {};
|
|
179
179
|
extendObj(true,opts.fetchOptions,fetchOptionsRef.current?.fetchOptions);
|
|
180
|
+
if(props.convertFiltersToSQL === false){
|
|
181
|
+
opts.fetchOptions.selector = extendObj(true,{},opts.fetchOptions.selector,fetchOptionsRef.current?.selector);
|
|
182
|
+
}
|
|
180
183
|
opts.fetchOptions.sort = sortRef.current;
|
|
181
184
|
if(canHandleLimit){
|
|
182
185
|
opts.fetchOptions.limit = limitRef.current;
|
package/src/index.js
CHANGED
|
@@ -33,7 +33,12 @@ const resetExitCounter = ()=>{
|
|
|
33
33
|
|
|
34
34
|
const NAVIGATION_PERSISTENCE_KEY = 'NAVIGATION_STATE';
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+
/****
|
|
37
|
+
* init {function}: ()=>Promise<{}> est la fonction d'initialisation de l'application
|
|
38
|
+
* initialRouteName : la route initiale par défaut
|
|
39
|
+
* getStartedRouteName : la route par défaut de getStarted lorsque l'application est en mode getStarted, c'est à dire lorsque la fonction init renvoie une erreur (reject)
|
|
40
|
+
*/
|
|
41
|
+
function App({init:initApp,initialRouteName:appInitialRouteName,getStartedRouteName}) {
|
|
37
42
|
AppStateService.init();
|
|
38
43
|
const [initialState, setInitialState] = React.useState(undefined);
|
|
39
44
|
const appReadyRef = React.useRef(true);
|
|
@@ -156,16 +161,16 @@ function App({init:initApp}) {
|
|
|
156
161
|
console.log(e," is net info heinn")
|
|
157
162
|
});
|
|
158
163
|
loadResources().finally(()=>{
|
|
159
|
-
(typeof initApp =='function'?initApp : init)().then(()=>{
|
|
164
|
+
(typeof initApp =='function'?initApp : init)().then((args)=>{
|
|
160
165
|
if(Auth.isLoggedIn()){
|
|
161
166
|
Auth.loginUser(false);
|
|
162
167
|
}
|
|
163
168
|
setState({
|
|
164
|
-
...state,isInitialized:true,isLoading : false,
|
|
169
|
+
...state,hasGetStarted:true,...defaultObj(args && args?.state),isInitialized:true,isLoading : false,
|
|
165
170
|
});
|
|
166
171
|
}).catch((e)=>{
|
|
167
172
|
console.error(e," initializing app")
|
|
168
|
-
setState({...state,isInitialized:true,isLoading : false});
|
|
173
|
+
setState({...state,isInitialized:true,isLoading : false,hasGetStarted:false});
|
|
169
174
|
})
|
|
170
175
|
});
|
|
171
176
|
|
|
@@ -197,7 +202,6 @@ function App({init:initApp}) {
|
|
|
197
202
|
}
|
|
198
203
|
}, []);
|
|
199
204
|
const {isInitialized} = state;
|
|
200
|
-
const hasGetStarted = true;
|
|
201
205
|
const isLoading = state.isLoading || !isInitialized || !appReadyRef.current? true : false;
|
|
202
206
|
React.useEffect(()=>{
|
|
203
207
|
if(isInitialized){
|
|
@@ -205,7 +209,7 @@ function App({init:initApp}) {
|
|
|
205
209
|
trackIDLE(true);
|
|
206
210
|
}
|
|
207
211
|
},[isInitialized]);
|
|
208
|
-
const
|
|
212
|
+
const hasGetStarted = state.hasGetStarted !== false? true : false;
|
|
209
213
|
return (<SplashScreen isLoaded={!isLoading}>
|
|
210
214
|
<NavigationContainer
|
|
211
215
|
ref={navigationRef}
|
|
@@ -216,9 +220,12 @@ function App({init:initApp}) {
|
|
|
216
220
|
}
|
|
217
221
|
>
|
|
218
222
|
<Navigation
|
|
219
|
-
initialRouteName = {
|
|
223
|
+
initialRouteName = {defaultStr(hasGetStarted ? appInitialRouteName : getStartedRouteName,"Home")}
|
|
220
224
|
state = {state}
|
|
221
225
|
hasGetStarted = {hasGetStarted}
|
|
226
|
+
onGetStart = {(e)=>{
|
|
227
|
+
setState({...state,hasGetStarted:true})
|
|
228
|
+
}}
|
|
222
229
|
/>
|
|
223
230
|
</NavigationContainer>
|
|
224
231
|
</SplashScreen>);
|
package/src/navigation/index.js
CHANGED
|
@@ -6,15 +6,23 @@ import DrawerNavigator from "./Drawer";
|
|
|
6
6
|
|
|
7
7
|
export * from "./utils";
|
|
8
8
|
|
|
9
|
+
/**** la fonction onGetStart doit normalement être appélée lorsque l'application
|
|
10
|
+
* lorsque hasGetStarted est à false, celle-ci rend l'écran Start permettant de rendre le contenu GetStarted
|
|
11
|
+
*/
|
|
9
12
|
export default function NavigationComponent (props){
|
|
10
|
-
let {state,hasGetStarted,initialRouteName,extra} = props;
|
|
13
|
+
let {state,hasGetStarted,onGetStart,initialRouteName,extra} = props;
|
|
11
14
|
const allScreens = initScreens({Factory:Stack,ModalFactory:Stack,filter:({name,Screen})=>{
|
|
12
|
-
|
|
15
|
+
if(name === initialRouteName){
|
|
16
|
+
extra = defaultObj(extra);
|
|
17
|
+
extra.onGetStart = onGetStart;
|
|
18
|
+
extra.state = state;
|
|
19
|
+
return extra;
|
|
20
|
+
}
|
|
21
|
+
return true;
|
|
13
22
|
}});
|
|
14
|
-
|
|
15
23
|
initialRouteName = sanitizeName(initialRouteName);
|
|
16
|
-
const drawerScreens = handleContent({screens:allScreens,hasGetStarted,initialRouteName,state,Factory:Stack});
|
|
17
|
-
const stackScreens = handleContent({screens:allScreens.modals,hasGetStarted,initialRouteName,state,Factory:Stack});
|
|
24
|
+
const drawerScreens = handleContent({screens:allScreens,onGetStart,hasGetStarted,initialRouteName,state,Factory:Stack});
|
|
25
|
+
const stackScreens = handleContent({screens:allScreens.modals,onGetStart,hasGetStarted,initialRouteName,state,Factory:Stack});
|
|
18
26
|
if(!drawerScreens.length && !stackScreens.length){
|
|
19
27
|
console.error("apps will stuck on splash screen because any valid screen has been found on screens ",allScreens);
|
|
20
28
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import FormDataScreen from "$elayouts/Screen/FormData";
|
|
2
2
|
import {defaultStr,defaultObj,isObjOrArray,isObj} from "$utils";
|
|
3
|
-
import Auth from "$
|
|
3
|
+
import Auth from "$cauth";
|
|
4
4
|
import {navigate} from "$cnavigation";
|
|
5
5
|
import SelectTheme from "$themeSelectorComponent";
|
|
6
6
|
import Preloader from "$epreloader";
|
|
@@ -6,7 +6,7 @@ import Label from "$components/Label";
|
|
|
6
6
|
|
|
7
7
|
export default function ContentPrivacy (){
|
|
8
8
|
return <Label primary style={{fontSize:15,fontWeight:'bold',padding:10}}>
|
|
9
|
-
Pour modifier le contenu de la
|
|
9
|
+
Pour modifier le contenu de la politique de confidentialité, il suffit de déclarer dans les alias, l'alias
|
|
10
10
|
$PrivacyPolicy prointant vers un fichier javascript dans lequel on exporte par défaut, soit un composant React
|
|
11
11
|
où encore un élément react valide dont le rendu remplacera ledit contenu.
|
|
12
12
|
</Label>
|
|
@@ -62,7 +62,7 @@ export default function ScreenWrapperNavComponent(_props){
|
|
|
62
62
|
}
|
|
63
63
|
},[]);
|
|
64
64
|
setScreenOptions(options);
|
|
65
|
-
const allowDrawer = typeof options.allowDrawer ==='boolean'? options.allowDrawer : typeof Screen.allowDrawer =='boolean'? Screen.allowDrawer : Screen.isModalScreen == true ? false : true;
|
|
65
|
+
const allowDrawer = typeof options.allowDrawer ==='boolean'? options.allowDrawer : typeof options.withDrawer =='boolean'? options.withDrawer : typeof Screen.allowDrawer =='boolean'? Screen.allowDrawer : Screen.isModalScreen == true ? false : true;
|
|
66
66
|
return <Screen
|
|
67
67
|
{...rest}
|
|
68
68
|
key = {sanitizedName}
|
package/src/screens/index.js
CHANGED
|
@@ -7,8 +7,7 @@ import { SCREEN_OPTIONS } from "./utils";
|
|
|
7
7
|
|
|
8
8
|
export * from "./utils";
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
export const handleScreen = ({Screen,Factory,ModalFactory,result,useTheme,filter,index})=>{
|
|
10
|
+
export const handleScreen = ({Screen,Factory,ModalFactory,result,filter,index})=>{
|
|
12
11
|
result = defaultObj(result);
|
|
13
12
|
result.screens = defaultObj(result.screens);
|
|
14
13
|
result.groups = defaultObj(result.groups);
|
|
@@ -18,7 +17,7 @@ export const handleScreen = ({Screen,Factory,ModalFactory,result,useTheme,filter
|
|
|
18
17
|
let screenOptions = undefined;
|
|
19
18
|
if(Array.isArray(Screen)){
|
|
20
19
|
Screen.map((S,i)=>{
|
|
21
|
-
return handleScreen({Screen:S,Factory,ModalFactory,result,groups,
|
|
20
|
+
return handleScreen({Screen:S,Factory,ModalFactory,result,groups,filter,index:i});
|
|
22
21
|
})
|
|
23
22
|
} else if(typeof Screen ==='object' && React.isComponent(Screen.Component) && isNonNullString(Screen.screenName)){
|
|
24
23
|
screenName = Screen.screenName;
|
|
@@ -40,11 +39,15 @@ export const handleScreen = ({Screen,Factory,ModalFactory,result,useTheme,filter
|
|
|
40
39
|
if(!GROUP_NAMES[groupName]){
|
|
41
40
|
groupName = GROUP_NAMES.PRIVATE;
|
|
42
41
|
}
|
|
43
|
-
if(
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
42
|
+
if( groupName !== GROUP_NAMES.INSTALL){
|
|
43
|
+
if(!authRequired){
|
|
44
|
+
groupName = groupName || GROUP_NAMES.PUBLIC;
|
|
45
|
+
} else{
|
|
46
|
+
groupName = GROUP_NAMES.PRIVATE;
|
|
47
|
+
authRequired = true;
|
|
48
|
+
}
|
|
49
|
+
} else {
|
|
50
|
+
authRequired = false;
|
|
48
51
|
}
|
|
49
52
|
groups[groupName] = defaultObj(groups[groupName]);
|
|
50
53
|
groups[groupName][sanitizeName] = name;
|
|
@@ -84,7 +87,6 @@ export const handleScreen = ({Screen,Factory,ModalFactory,result,useTheme,filter
|
|
|
84
87
|
* @param Factory {typeof Factory : voir @https://reactnavigation.org/}
|
|
85
88
|
* @param screens {Object {screns:{screens:{},groups:{}}}} l'objet dans lequel le screensat sera retourné
|
|
86
89
|
* @param screens {array} la liste des écrans à rendre dynamiquement dans le FactoryContainer
|
|
87
|
-
* @param useTheme {boolean} si le composant sera wrapper par le hook withTheme de react-native-paper
|
|
88
90
|
* @return {object} : objet comportant deux propriétés :
|
|
89
91
|
* screens : {} : liste des écrans de l'application initialisés. il est à noter que, tous les écrans sont dans les sous répertoire du dossier courant
|
|
90
92
|
screens screens est de la forme : {group1:[],group2:[], ...groupN:[]}:
|
|
@@ -92,7 +94,7 @@ export const handleScreen = ({Screen,Factory,ModalFactory,result,useTheme,filter
|
|
|
92
94
|
|
|
93
95
|
groups : {} : la liste des différents groupes d'écrans rendus par la méthode
|
|
94
96
|
*/
|
|
95
|
-
export default function initScreens ({Factory,ModalFactory,
|
|
97
|
+
export default function initScreens ({Factory,ModalFactory,screens,result,filter}){
|
|
96
98
|
if(!isArray(screens) || !screens.length){
|
|
97
99
|
screens = mainScreens;
|
|
98
100
|
}
|
|
@@ -100,7 +102,6 @@ export default function initScreens ({Factory,ModalFactory,useTheme,screens,resu
|
|
|
100
102
|
result.screens = defaultObj(result.screens);
|
|
101
103
|
result.groups = defaultObj(result.groups);
|
|
102
104
|
///lorsque les écrans sont passés enparamètres, par défaut, le wrapper withTheme n'est pas utilisé
|
|
103
|
-
useTheme = defaultBool(useTheme,false);
|
|
104
105
|
filter = typeof filter =="function" ? filter : x=> true;
|
|
105
106
|
defaultArray(screens).map((Screen,index)=>{
|
|
106
107
|
handleScreen({Screen,result,Factory,ModalFactory,filter,index})
|
|
@@ -108,7 +109,7 @@ export default function initScreens ({Factory,ModalFactory,useTheme,screens,resu
|
|
|
108
109
|
return result;
|
|
109
110
|
}
|
|
110
111
|
|
|
111
|
-
export const handleContent = ({screens,hasGetStarted,state,Factory})=>{
|
|
112
|
+
export const handleContent = ({screens,hasGetStarted,onGetStart,state,Factory})=>{
|
|
112
113
|
const content = [];
|
|
113
114
|
state = defaultObj(state);
|
|
114
115
|
screens = defaultObj(screens);
|