@fto-consult/expo-ui 8.73.0 → 8.74.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/App.js +29 -0
- package/package.json +3 -2
- package/src/components/BottomSheet/Sheet.js +0 -6
- package/src/components/Datagrid/Accordion/index.js +2 -2
- package/src/components/Icon/Font.js +1 -0
- package/src/context/Provider.js +1 -0
- package/src/layouts/ProfilAvatar/index.js +87 -35
- package/src/layouts/Screen/Screen.js +16 -6
- package/src/layouts/Screen/ScreenWithoutAuthContainer.js +4 -2
- package/src/pdf/Reader/index.js +6 -0
- package/src/pdf/Reader/index.web.js +16 -173
- package/src/pdf/Reader/index.web.old.js +178 -0
- package/src/pdf/Reader/web/Viewer.js +20 -0
- package/src/pdf/Reader/web/script.js +334 -0
- package/src/screens/Help/openLibraries.js +125 -82
package/bin/create-app/App.js
CHANGED
@@ -127,6 +127,27 @@ export default function AppMainEntry(){
|
|
127
127
|
({object})=><{object}>, la fonction permettant de muter les props du composant Fab, affiché dans les écrans par défaut
|
128
128
|
*/
|
129
129
|
fabPropsMutator : (props)=>props,
|
130
|
+
/****
|
131
|
+
les props personnalisés à passer au composant ProfilAvatar
|
132
|
+
@param {
|
133
|
+
user <Object>, l'objet en rapport à l'utilisateur connecté
|
134
|
+
canSignOut <boolean>, renseigne si l'utilisateur peut se déconnecté. est à false lorsque la gestion de l'authentification est désactivé,
|
135
|
+
renderedOnAppBar <boolean>, renseigne si l'avatar est rendu sur l'AppBar où sur le drawer
|
136
|
+
closeDrawer : (callback<function>)=><any>, la fonction permettant de fermer le drawer, lorsque celui-ci est en mode temporaire
|
137
|
+
navigateToPreferences : <func>, la fonction permettant de naviguer vers les préférences utilisateurs,
|
138
|
+
signOut <func>, la fonction permetant de déconnecter l'utilisateur
|
139
|
+
...rest,
|
140
|
+
},
|
141
|
+
@return <object> {
|
142
|
+
pseudo <string>, le pseudo à utiliser pour l'affichage du profil avatar
|
143
|
+
label <string>, le label, le sous nom à afficher juste en bas du pseudo
|
144
|
+
...imageProps <object>, les props à utilser pour le rendu de l'avatar, idem au props du composant image,
|
145
|
+
menuItems : <array | object>, les items supplémentaires à afficher pour le rendu du menu,
|
146
|
+
preferencesMenuItem : <boolean>, si l'items préférence sera rendu dans les items du menu
|
147
|
+
signOutMenuItem : <boolean>, si l'item Déconnection sera rendu des les items de menu
|
148
|
+
}
|
149
|
+
*/
|
150
|
+
profilAvatarProps : ({user,renderedOnAppBar,closeDrawer,canSignOut})=>({}),
|
130
151
|
}}
|
131
152
|
/*** //for application initialization
|
132
153
|
@param {
|
@@ -145,6 +166,14 @@ export default function AppMainEntry(){
|
|
145
166
|
beforeExit = {()=>Promise.resolve(true)}
|
146
167
|
|
147
168
|
handleHelpScreen ={true} //si l'écran d'aide sera pris en compte, l'écran d'aide ainsi que les écrans des termes d'utilisations et autres
|
169
|
+
/***
|
170
|
+
Les filtres vers les icons Set
|
171
|
+
@param {object} font, l'objet font parmis la liste des fonts icons supportés : voir : https://icons.expo.fyi/Index
|
172
|
+
@param {string} fontName, le nom de la font
|
173
|
+
@param {string} fontNameLower, le nom de la font en lowerCase
|
174
|
+
@return {boolean}, si true, l'icon set sera pris en compte
|
175
|
+
*/
|
176
|
+
FontsIconsFilter ={(font,fontName,fontNameLower)=>false}
|
148
177
|
/>
|
149
178
|
}
|
150
179
|
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@fto-consult/expo-ui",
|
3
|
-
"version": "8.
|
3
|
+
"version": "8.74.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": {
|
@@ -70,7 +70,8 @@
|
|
70
70
|
"dependencies": {
|
71
71
|
"@emotion/react": "^11.11.1",
|
72
72
|
"@faker-js/faker": "^8.0.2",
|
73
|
-
"@fto-consult/common": "^4.
|
73
|
+
"@fto-consult/common": "^4.45.0",
|
74
|
+
"@fto-consult/expo-ui": "^8.73.1",
|
74
75
|
"apexcharts": "^3.48.0",
|
75
76
|
"file-saver": "^2.0.5",
|
76
77
|
"google-libphonenumber": "^3.2.34",
|
@@ -59,7 +59,6 @@ const BottomSheetComponent = React.forwardRef((props,ref)=> {
|
|
59
59
|
modalProps,
|
60
60
|
titleProps : _titleProps,
|
61
61
|
withScrollView,
|
62
|
-
bindResizeEvent,
|
63
62
|
scrollViewProps : _scrollViewProps,
|
64
63
|
actionTitle,
|
65
64
|
elevation:customElevation,
|
@@ -228,12 +227,8 @@ const BottomSheetComponent = React.forwardRef((props,ref)=> {
|
|
228
227
|
|
229
228
|
React.setRef(ref,{close:closeModal,open})
|
230
229
|
React.useEffect(()=>{
|
231
|
-
if(bindResizeEvent && false){
|
232
|
-
APP.on(APP.EVENTS.RESIZE_PAGE,closeModal);
|
233
|
-
}
|
234
230
|
return ()=>{
|
235
231
|
removeListeners();
|
236
|
-
APP.off(APP.EVENTS.RESIZE_PAGE,closeModal);
|
237
232
|
React.setRef(ref,null);
|
238
233
|
}
|
239
234
|
},[]);
|
@@ -326,7 +321,6 @@ BottomSheetComponent.propTypes = {
|
|
326
321
|
|
327
322
|
BottomSheetComponent.defaultProps = {
|
328
323
|
withScrollView : PropTypes.bool,
|
329
|
-
bindResizeEvent : PropTypes.bool,
|
330
324
|
animationType: isNativeMobile ? "slide" : "fade",//Background animation ("none", "fade", "slide")
|
331
325
|
height:undefined,//Height of Bottom Sheet
|
332
326
|
minClosingHeight: 0,//Minimum height of Bottom Sheet before close
|
@@ -21,8 +21,8 @@ import BackToTop from "$ecomponents/BackToTop";
|
|
21
21
|
import FiltersAccordionComponent from "./Filters";
|
22
22
|
import RenderType from "../RenderType";
|
23
23
|
import { flatMode} from "$ecomponents/TextField";
|
24
|
-
|
25
|
-
import List from "$ecomponents/List/FlashList";
|
24
|
+
import List from "$ecomponents/Table/List";
|
25
|
+
//import List from "$ecomponents/List/FlashList";
|
26
26
|
import theme,{Colors} from "$theme";
|
27
27
|
import {styles as rStyles} from "../utils";
|
28
28
|
import Avatar from "$ecomponents/Avatar";
|
@@ -19,6 +19,7 @@ import MaterialIcons from "@expo/vector-icons/MaterialIcons";
|
|
19
19
|
import Octicons from "@expo/vector-icons/Octicons";
|
20
20
|
import SimpleLineIcons from "@expo/vector-icons/SimpleLineIcons";
|
21
21
|
import Zocial from "@expo/vector-icons/Zocial";
|
22
|
+
import Colors from "$theme/colors";
|
22
23
|
|
23
24
|
/*** @see : https://icons.expo.fyi/ popur tous les icons supportés*/
|
24
25
|
/*** L'iconSet par défaut est le MaterialCommunityIcon qui ne nécessite pas de préfixer les noms des icones
|
package/src/context/Provider.js
CHANGED
@@ -67,6 +67,7 @@ Object.map(Utils,(v,i)=>{
|
|
67
67
|
fabPropsMutator : ({object})=><{object}>, la fonction permettant de muter les props du composant Fab, affiché dans les écrans par défaut,
|
68
68
|
TableDataScreen | TableDataScreenItem : {ReactComponent}, le composant TableDataScreenItem, à utiliser pour le rendu des écrans
|
69
69
|
TableDataScreenList | TableDataListScreen {ReactComponent}, le composant TableDataList à utiliser pour le rendu des écrans listants les éléments du table data
|
70
|
+
profilAvatarProps : {function | object}, si fonction, ({user,size,renderedOnAppBar,})=>{pseudo,label,size,menuItems,...rest}
|
70
71
|
},
|
71
72
|
|
72
73
|
navigation : {
|
@@ -16,13 +16,31 @@ import appConfig from "$capp/config";
|
|
16
16
|
import Preloader from "$preloader";
|
17
17
|
import {defaultNumber} from "$cutils";
|
18
18
|
import Tooltip from "$ecomponents/Tooltip";
|
19
|
+
import PropTypes from "prop-types";
|
20
|
+
import { useContext } from "$econtext/hooks";
|
19
21
|
|
20
|
-
const UserProfileAvatarComponent = React.forwardRef(({drawerRef,chevronIconProps:customChevronIconProps,size,withLabel,...props},ref)=>{
|
22
|
+
const UserProfileAvatarComponent = React.forwardRef(({drawerRef,renderedOnAppBar,chevronIconProps:customChevronIconProps,size,withLabel,menuItems,...props},ref)=>{
|
21
23
|
let u = defaultObj(Auth.getLoggedUser());
|
22
24
|
const deviceNameRef = React.useRef(null);
|
23
25
|
const deviceName = appConfig.deviceName;
|
24
26
|
customChevronIconProps = defaultObj(customChevronIconProps);
|
25
27
|
props = defaultObj(props);
|
28
|
+
const navigateToPreferences = (a)=>{
|
29
|
+
closeDrawer(()=>{
|
30
|
+
return navigate({
|
31
|
+
routeName : screenName,
|
32
|
+
params : {
|
33
|
+
user : u,
|
34
|
+
}
|
35
|
+
})
|
36
|
+
});
|
37
|
+
};
|
38
|
+
const signOut = (a)=>{
|
39
|
+
closeDrawer(()=>{
|
40
|
+
Preloader.open("Déconnexion en cours...");
|
41
|
+
Auth.signOut().finally(Preloader.close)
|
42
|
+
});
|
43
|
+
};
|
26
44
|
const closeDrawer = cb => {
|
27
45
|
if(drawerRef && drawerRef.current && drawerRef.current.close){
|
28
46
|
return drawerRef && drawerRef.current && drawerRef.current.close(cb);
|
@@ -37,8 +55,15 @@ const UserProfileAvatarComponent = React.forwardRef(({drawerRef,chevronIconProps
|
|
37
55
|
size = defaultNumber(size,!withLabel?40:40);
|
38
56
|
const userPseudo = Auth.getUserPseudo();
|
39
57
|
const defaultPseudo = "Default User";
|
40
|
-
const
|
41
|
-
const
|
58
|
+
const canSignOut = Auth.canSignOut();
|
59
|
+
const {components:{profilAvatarProps}} = useContext();
|
60
|
+
const customProps = Object.assign({},typeof profilAvatarProps =='function'? profilAvatarProps({...props,signOut,navigateToPreferences,canSignOut,closeDrawer,user:u,size,close:closeDrawer,setDeviceId:onLongPress,renderedOnAppBar,}) : profilAvatarProps);
|
61
|
+
if(typeof customProps.size =="number"){
|
62
|
+
size = customProps.size;
|
63
|
+
}
|
64
|
+
const pseudo = defaultStr(customProps.pseudo,userPseudo,Auth.getUserCode(),Auth.getUserEmail(),appConfig.authDefaultUsername,defaultPseudo);
|
65
|
+
const label = defaultStr(customProps.label,Auth.getUserFullName(),userPseudo);
|
66
|
+
delete customProps.label;
|
42
67
|
const onLongPress = ()=>{
|
43
68
|
appConfig.setDeviceId().then((r)=>{
|
44
69
|
if(deviceNameRef.current && deviceNameRef.current.update){
|
@@ -48,15 +73,16 @@ const UserProfileAvatarComponent = React.forwardRef(({drawerRef,chevronIconProps
|
|
48
73
|
};
|
49
74
|
const pseudoTooltip = (pseudo == defaultPseudo ? `Pour modifier la valeur du pseudo actuel, définissez dans le fichier package.json, la propriété : authDefaultUsername de type chaine de caractère`:"");
|
50
75
|
const tooltip = "Pressez longtemps pour définir un identifiant unique pour l'appareil";
|
51
|
-
const
|
52
|
-
const
|
76
|
+
const testID = defaultStr(customProps.testID,props.testID,"RN_ProfilAvatar")
|
77
|
+
const pseudoContent = <Label testID={testID+"_PseudoContent"} splitText numberOfLines={1} style={{color:theme.colors.primaryOnSurface,fontSize:15}}>{pseudo}</Label>;
|
78
|
+
const children = <View testID={testID+"_AnchorContainer"} style={[styles.labelContainer,!withLabel && theme.styles.justifyContentCenter]}>
|
53
79
|
{pseudoTooltip?<Tooltip title={pseudoTooltip}>
|
54
80
|
{pseudoContent}
|
55
81
|
</Tooltip>:pseudoContent}
|
56
|
-
<Label splitText numberOfLines={1} style={[{fontSize:12,color:theme.colors.secondaryOnSurface,marginTop:6},!withLabel &&
|
82
|
+
{label != pseudo ? <Label testID={testID+"_ProfilAvatarLabel"} splitText numberOfLines={1} style={[{fontSize:12,color:theme.colors.secondaryOnSurface,marginTop:6},!withLabel && styles.withNotLabel]}>
|
57
83
|
{label}
|
58
|
-
</Label
|
59
|
-
{deviceName && <Label.withRef textBold splitText title={"Identifiant unique de l'application, installé sur cet appareil"} ref={deviceNameRef} secondary style={{fontSize:10}}>
|
84
|
+
</Label>:null}
|
85
|
+
{deviceName && <Label.withRef testID={testID+"_ProfilAvatarDeviceName"} textBold splitText title={"Identifiant unique de l'application, installé sur cet appareil"} ref={deviceNameRef} secondary style={{fontSize:10}}>
|
60
86
|
[{deviceName}]
|
61
87
|
</Label.withRef> || null}
|
62
88
|
</View>
|
@@ -68,30 +94,22 @@ const UserProfileAvatarComponent = React.forwardRef(({drawerRef,chevronIconProps
|
|
68
94
|
closeOnPress : false,
|
69
95
|
divider : true,
|
70
96
|
},
|
71
|
-
{
|
97
|
+
...(Array.isArray(menuItems)? menuItems : isObj(menuItems)? Object.keys(menuItems).map(k=>{
|
98
|
+
return menuItems[k];
|
99
|
+
}) : []),
|
100
|
+
...(Array.isArray(customProps.menuItems)? customProps.menuItems : isObj(customProps.menuItems)? Object.keys(customProps.menuItems).map(k=>{
|
101
|
+
return customProps.menuItems[k];
|
102
|
+
}) : []),
|
103
|
+
customProps.preferencesMenuItem != false && {
|
72
104
|
label : i18n.lang("preferences",'Préférences'),
|
73
105
|
icon : "account-cog",
|
74
|
-
onPress :
|
75
|
-
closeDrawer(()=>{
|
76
|
-
return navigate({
|
77
|
-
routeName : screenName,
|
78
|
-
params : {
|
79
|
-
user : u,
|
80
|
-
}
|
81
|
-
})
|
82
|
-
});
|
83
|
-
}
|
106
|
+
onPress : navigateToPreferences,
|
84
107
|
},
|
85
|
-
|
108
|
+
canSignOut && customProps.signOutMenuItem !== false && {
|
86
109
|
label : i18n.lang("logout",'Déconnexion'),
|
87
110
|
icon : "logout",
|
88
|
-
onPress :
|
89
|
-
|
90
|
-
Preloader.open("Déconnexion en cours...");
|
91
|
-
Auth.signOut().finally(Preloader.close)
|
92
|
-
});
|
93
|
-
}
|
94
|
-
}
|
111
|
+
onPress : signOut,
|
112
|
+
},
|
95
113
|
];
|
96
114
|
|
97
115
|
const onChangeAvatar = ({dataURL})=>{
|
@@ -105,7 +123,7 @@ const UserProfileAvatarComponent = React.forwardRef(({drawerRef,chevronIconProps
|
|
105
123
|
}
|
106
124
|
Auth.upsertUser({...u,avatar:u.avatar},false);
|
107
125
|
}
|
108
|
-
return <View ref ={ref}>
|
126
|
+
return <View ref ={ref} testID={testID+"_ProfilAvatarWrapper"}>
|
109
127
|
<Menu
|
110
128
|
anchor = { (aProps)=>{
|
111
129
|
const chevronIconProps = {
|
@@ -117,19 +135,21 @@ const UserProfileAvatarComponent = React.forwardRef(({drawerRef,chevronIconProps
|
|
117
135
|
style : [styles.icon,withLabel=== false && {color:theme.colors.onPrimary},customChevronIconProps.style],
|
118
136
|
}
|
119
137
|
if(!withLabel){
|
120
|
-
return <View testID={"
|
138
|
+
return <View testID={testID+"_AvatarContainer"} style={[theme.styles.row,theme.styles.alignItemsCenter,theme.styles.pr1]}>
|
121
139
|
<Image
|
122
140
|
pickImageProps = {{quality:0.4}}
|
123
141
|
{...props}
|
124
142
|
{...aProps}
|
143
|
+
{...customProps}
|
125
144
|
size={size}
|
126
145
|
style = {styles.itemLeft}
|
127
|
-
testID = {"
|
146
|
+
testID = {testID+"_Avatar"}
|
128
147
|
readOnly = {false}
|
129
148
|
defaultSource ={avatarProps.defaultSrc}
|
130
149
|
onChange = {onChangeAvatar}
|
131
150
|
/>
|
132
|
-
<Icon
|
151
|
+
<Icon.Font
|
152
|
+
testID={testID+"_ChevronIcon"}
|
133
153
|
{...chevronIconProps}
|
134
154
|
{...aProps}
|
135
155
|
style = {[chevronIconProps.style,{marginLeft:-5}]}
|
@@ -137,6 +157,7 @@ const UserProfileAvatarComponent = React.forwardRef(({drawerRef,chevronIconProps
|
|
137
157
|
</View>
|
138
158
|
}
|
139
159
|
return <Pressable
|
160
|
+
testID={testID+"_ProfilAvatarContainer"}
|
140
161
|
normal
|
141
162
|
upperCase = {false}
|
142
163
|
disableRipple
|
@@ -148,15 +169,17 @@ const UserProfileAvatarComponent = React.forwardRef(({drawerRef,chevronIconProps
|
|
148
169
|
>
|
149
170
|
<Image
|
150
171
|
{...props}
|
172
|
+
{...customProps}
|
151
173
|
size={size}
|
152
174
|
style = {styles.itemLeft}
|
153
|
-
testID = {"
|
175
|
+
testID = {testID+"_Avatar"}
|
154
176
|
readOnly = {false}
|
155
177
|
defaultSource ={avatarProps.defaultSrc}
|
156
178
|
onChange = {onChangeAvatar}
|
157
179
|
/>
|
158
180
|
{children}
|
159
181
|
<Icon
|
182
|
+
testID={testID+"_ChevronIcon"}
|
160
183
|
{...chevronIconProps}
|
161
184
|
/>
|
162
185
|
</Pressable>
|
@@ -185,6 +208,9 @@ const styles = StyleSheet.create({
|
|
185
208
|
maxWidth : 140,
|
186
209
|
minWidth : 100,
|
187
210
|
},
|
211
|
+
withNotLabel : {
|
212
|
+
textAlign : "center",
|
213
|
+
},
|
188
214
|
pseudo : {
|
189
215
|
flexDirection : "row",
|
190
216
|
justifyContent : "center",
|
@@ -197,9 +223,35 @@ const styles = StyleSheet.create({
|
|
197
223
|
icon : {
|
198
224
|
marginHorizontal:0,
|
199
225
|
paddingHorizontal : 0,
|
200
|
-
}
|
201
|
-
|
226
|
+
},
|
227
|
+
notLabelHeader : {
|
228
|
+
textAlign : "left",
|
229
|
+
alignSelf :"flex-start"
|
230
|
+
},
|
231
|
+
});
|
202
232
|
|
203
233
|
export default UserProfileAvatarComponent;
|
204
234
|
|
205
|
-
UserProfileAvatarComponent.displayName = "UserProfileAvatarComponent";
|
235
|
+
UserProfileAvatarComponent.displayName = "UserProfileAvatarComponent";
|
236
|
+
|
237
|
+
UserProfileAvatarComponent.propTypes = {
|
238
|
+
renderedOnAppBar : PropTypes.bool,//spécifie si le profil avatar est rendu si true sur l'appBar, si false sur le drawer
|
239
|
+
...Object.assign({},Image.propTypes), //par défaut les props de l'image qui est utilisée pour le rendu de l'avatar
|
240
|
+
withLabel : PropTypes.bool, //si le label sera affiché, ie, le nom où pseudo de l'utilisateur
|
241
|
+
menuItems : PropTypes.oneOfType([
|
242
|
+
PropTypes.array,
|
243
|
+
PropTypes.object,
|
244
|
+
]),
|
245
|
+
/****
|
246
|
+
La props customProps issue de la propriété {component:profilAvatarProps} de useContext, prend les propriétés suivatnes :
|
247
|
+
il peut s'agir d'une fonction où d'un objet. s'il s'agit d'une fonction alors la dite fonction est de la forme :
|
248
|
+
({canSignOut<boolean>,renderedOnAppBar<boolean>,user<object>,....rest})=> <CustomAvatarProps>
|
249
|
+
<CustomAvatarProps> : {
|
250
|
+
...Image.propTypes,
|
251
|
+
size <number>,
|
252
|
+
pseudo <string>, le pseudo à afficher
|
253
|
+
label <string>, la chaine de caractère à afficher pour le rendu du label/FullName,
|
254
|
+
menuItems : <Array<object> | object<object>>, les menu items personnalisés à utiliser pour l'affichage
|
255
|
+
}
|
256
|
+
*/
|
257
|
+
}
|
@@ -6,10 +6,10 @@ import Container from "$cauth/Container";
|
|
6
6
|
import ScreenWithoutAuthContainer from "./ScreenWithoutAuthContainer";
|
7
7
|
import ProfilAvatar from "$elayouts/ProfilAvatar";
|
8
8
|
import {defaultObj,defaultBool} from "$cutils";
|
9
|
-
import View from "$ecomponents/View";
|
10
9
|
import theme from "$theme";
|
10
|
+
import React from "$react";
|
11
11
|
|
12
|
-
export default function MainScreenComponent({profilAvatarProps,withDrawer,allowDrawer,profilAvatarContainerProps,withProfilAvatarOnAppBar:cWithPorilAvatarOnAppbar,authProps,authRequired,...props}){
|
12
|
+
export default function MainScreenComponent({profilAvatarProps,appBarProps,testID,withDrawer,allowDrawer,profilAvatarContainerProps,withProfilAvatarOnAppBar:cWithPorilAvatarOnAppbar,authProps,authRequired,...props}){
|
13
13
|
authProps = Object.assign({},authProps),
|
14
14
|
profilAvatarContainerProps = defaultObj(profilAvatarContainerProps);
|
15
15
|
profilAvatarProps = defaultObj(profilAvatarProps);
|
@@ -18,16 +18,26 @@ export default function MainScreenComponent({profilAvatarProps,withDrawer,allowD
|
|
18
18
|
if(allowDrawer === false){
|
19
19
|
withDrawer = false;
|
20
20
|
}
|
21
|
+
testID = defaultStr(testID,"RN_MainScreenComponent");
|
21
22
|
const withProfilAvatarOnAppBar = cWithPorilAvatarOnAppbar !== false && withDrawer && !theme.showProfilAvatarOnDrawer ? true : false;
|
22
|
-
|
23
|
+
appBarProps = defaultObj(appBarProps);
|
24
|
+
const {right} = appBarProps;
|
25
|
+
if(withProfilAvatarOnAppBar){
|
26
|
+
appBarProps.right = (...p)=>{
|
27
|
+
const r = typeof right =='function'? right(p) : right;
|
28
|
+
return <>
|
29
|
+
<ProfilAvatar renderedOnAppBar withLabel={false} size={40} {...profilAvatarProps}/>
|
30
|
+
{React.isValidElement(r)? r : null}
|
31
|
+
</>
|
32
|
+
}
|
33
|
+
}
|
34
|
+
return <Container authProps={authProps} required={authRequired} testID={testID}>
|
23
35
|
<ScreenWithoutAuthContainer
|
24
36
|
{...props}
|
25
37
|
withDrawer={withDrawer}
|
26
38
|
allowDrawer={allowDrawer}
|
27
39
|
authRequired = {authRequired}
|
28
|
-
|
29
|
-
{<ProfilAvatar withLabel={false} {...profilAvatarProps}/>}
|
30
|
-
</View> || null}
|
40
|
+
appBarProps={appBarProps}
|
31
41
|
/>
|
32
42
|
</Container>
|
33
43
|
}
|
@@ -37,7 +37,7 @@ export default function MainScreenScreenWithoutAuthContainer(props) {
|
|
37
37
|
contentContainerStyle,
|
38
38
|
options,
|
39
39
|
backAction,
|
40
|
-
appBarProps,
|
40
|
+
appBarProps:cAppbarProps,
|
41
41
|
elevation,
|
42
42
|
withFab,
|
43
43
|
withNotifications,
|
@@ -63,7 +63,7 @@ export default function MainScreenScreenWithoutAuthContainer(props) {
|
|
63
63
|
containerProps = defaultObj(containerProps);
|
64
64
|
backgroundColor = theme.Colors.isValid(backgroundColor)? backgroundColor : theme.colors.background;
|
65
65
|
options = defaultObj(options);
|
66
|
-
appBarProps = defaultObj(
|
66
|
+
const {right,left,...appBarProps} = defaultObj(cAppbarProps);
|
67
67
|
title = defaultVal(title,appBarProps.title);
|
68
68
|
subtitle = defaultVal(subtitle,appBarProps.subtitle);
|
69
69
|
notificationsProps = {...Object.assign({},notificationsProps),...Object.assign({},appBarProps.notificationsProps)};
|
@@ -117,6 +117,7 @@ export default function MainScreenScreenWithoutAuthContainer(props) {
|
|
117
117
|
{appBar === false ? null : React.isValidElement(appBar)? AppBar : <AppBar
|
118
118
|
testID={testID+'_AppBar'}
|
119
119
|
{...appBarProps}
|
120
|
+
left = {left}
|
120
121
|
backAction = {defaultVal(appBarProps.backAction,backAction)}
|
121
122
|
elevation={defaultNumber(appBarProps.elevation,elevation)}
|
122
123
|
notificationsProps = {notificationsProps}
|
@@ -124,6 +125,7 @@ export default function MainScreenScreenWithoutAuthContainer(props) {
|
|
124
125
|
ref={appBarRef} title={title}
|
125
126
|
subtitle={subtitle}
|
126
127
|
withNotifications = {withNotifications}
|
128
|
+
right = {right}
|
127
129
|
/>}
|
128
130
|
{withScrollView !== false ? (
|
129
131
|
<ScrollView
|
@@ -1,178 +1,21 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
let Icon = require("$ecomponents/Icon")
|
4
|
-
require("./styles.css")
|
5
|
-
let PDFObject = require("pdfobject")
|
6
|
-
let {MenuButton} = require("$ui")
|
7
|
-
let isMSE = //checkEdge ? false :
|
8
|
-
window.navigator && typeof window.navigator.msSaveOrOpenBlob == "function" ? true : false;
|
9
|
-
class PDFViewer extends APP.Component {
|
10
|
-
constructor(props){
|
11
|
-
super(props);
|
12
|
-
APP.extend(this._events,{
|
13
|
-
resize : this.resetPos.bind(this)
|
14
|
-
})
|
15
|
-
this.autobind();
|
16
|
-
}
|
1
|
+
import React from "$react";
|
2
|
+
import DialogProvider from "$ecomponents/Dialog/Provider";
|
17
3
|
|
18
|
-
|
19
|
-
super.componentDidMount();
|
20
|
-
this.updatePdfContent();
|
21
|
-
window.addEventListener('resize',this._events.resize, true)
|
22
|
-
this.resetPos();
|
23
|
-
}
|
24
|
-
resetPos (){
|
25
|
-
if(!this._isMounted()) return;
|
26
|
-
let pdfWrap = document.getElementById(this.pdfViewerWrapperDomId);
|
27
|
-
if(isDOMElement(pdfWrap)){
|
28
|
-
let parent = pdfWrap.parentNode;
|
29
|
-
let mP = pdfWrap.closest(".dialog.md-dialog-container");
|
30
|
-
if(isDOMElement(parent) && isDOMElement(mP)){
|
31
|
-
let maxHeight = mezr.height(parent);
|
32
|
-
let maxH2 = mezr.height(mP);
|
33
|
-
let min = Math.min(maxHeight,maxH2);
|
34
|
-
if(min == 0){
|
35
|
-
min = "100%";
|
36
|
-
} else min = min+"px";
|
37
|
-
pdfWrap.style.height = min;
|
38
|
-
}
|
39
|
-
}
|
40
|
-
}
|
4
|
+
let dialogRef = null;
|
41
5
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
componentWillUnmount(){
|
51
|
-
super.componentWillUnmount();
|
52
|
-
this.dialogRef = undefined;
|
53
|
-
window.removeEventListener('resize',this._events.resize, true)
|
54
|
-
this.clearEvents();
|
55
|
-
}
|
56
|
-
viewCapacitor (){
|
57
|
-
let f = window.PreviewAnyFile || (cordova && cordova.plugins.PreviewAnyFile);
|
58
|
-
if(f && f.preview){
|
59
|
-
f = f.preview;
|
60
|
-
let {file} = this.props;
|
61
|
-
APP.FILE.getCapacitorPDFromDataURL({content:file,fileName:this.props.fileName,success:({path})=>{
|
62
|
-
if(isFunction(f)){
|
63
|
-
f(
|
64
|
-
path,
|
65
|
-
function(win){},
|
66
|
-
function(err){
|
67
|
-
console.log(err," pdf viewer in cap android ios")
|
68
|
-
}
|
69
|
-
)
|
70
|
-
}
|
71
|
-
}})
|
72
|
-
}
|
73
|
-
}
|
74
|
-
updatePdfContent(){
|
75
|
-
let file = this.props.file;
|
76
|
-
if (isMSE) {
|
77
|
-
let b64 = dataURLToBase64(file);
|
78
|
-
if(b64){
|
79
|
-
var byteCharacters = atob(b64);
|
80
|
-
var byteNumbers = new Array(byteCharacters.length);
|
81
|
-
for (var i = 0; i < byteCharacters.length; i++) {
|
82
|
-
byteNumbers[i] = byteCharacters.charCodeAt(i);
|
83
|
-
}
|
84
|
-
var byteArray = new Uint8Array(byteNumbers);
|
85
|
-
var blob = new Blob([byteArray], {
|
86
|
-
type: 'application/pdf'
|
87
|
-
});
|
88
|
-
return window.navigator.msSaveOrOpenBlob(blob, defaultStr(this.props.title,'données-impr')+".pdf");
|
89
|
-
}
|
90
|
-
return null;
|
91
|
-
}
|
92
|
-
if(isElectron()){
|
93
|
-
return ELECTRON.PRINTER.preview({
|
94
|
-
content:this.props.file,
|
95
|
-
fileName : this.props.fileName,
|
96
|
-
fileExtension : 'pdf',
|
97
|
-
});
|
98
|
-
}
|
99
|
-
if(isCapacitor(true)){
|
100
|
-
return this.viewCapacitor();
|
101
|
-
}
|
102
|
-
let dom = document.getElementById(this.pdfViewerWrapperDomId);
|
103
|
-
if(isDOMElement(dom)){
|
104
|
-
try {
|
105
|
-
this.pdfInstance = PDFObject.embed(file,dom);
|
106
|
-
} catch (e){
|
107
|
-
console.log(e,' error on loading pdf file')
|
108
|
-
}
|
109
|
-
}
|
110
|
-
}
|
111
|
-
UNSAFE_componentWillReceiveProps(nexProps,prevProps){
|
112
|
-
if(nexProps.file && nexProps.file != this.state.file){
|
113
|
-
this._pageNumber = 1;
|
114
|
-
}
|
115
|
-
}
|
116
|
-
onPrint (args){
|
117
|
-
console.log(args,' was printed');
|
118
|
-
}
|
119
|
-
getPrintSettings(){
|
120
|
-
return defaultObj(this.props.printProps,this.props.printOptions);
|
121
|
-
}
|
122
|
-
render (){
|
123
|
-
if(isMSE || isElectron() || isCapacitor(true)) return null;
|
124
|
-
let {file,dialogProps,title,onPrint,printProps,printOptions,fileName,...rest} = this.props;
|
125
|
-
dialogProps = defaultObj(dialogProps);
|
126
|
-
dialogProps.contentProps = defaultObj(dialogProps.contentProps)
|
127
|
-
dialogProps.contentProps.id = defaultStr(dialogProps.contentProps.id,this.dialogWrapperParentId,uniqid('dialog-content-wrp-par'))
|
128
|
-
this.dialogWrapperParentId = dialogProps.contentProps.id;
|
129
|
-
dialogProps.contentProps.className = classNames(dialogProps.contentProps.className,'no-padding pdf-viewer-dialog-content')
|
130
|
-
dialogProps.className = classNames(dialogProps.className,'pdf-viewer-dialog')
|
131
|
-
dialogProps.title = defaultStr(dialogProps.title,title)
|
132
|
-
rest = defaultObj(rest)
|
133
|
-
let {actions} = dialogProps;
|
134
|
-
let acts = []
|
135
|
-
let mIts = []
|
136
|
-
if(mIts.length > 0){
|
137
|
-
acts.push(
|
138
|
-
<MenuButton
|
139
|
-
menuItems = {mIts}
|
140
|
-
flat
|
141
|
-
id = {uniqid("view-page-id-butt")}
|
142
|
-
>
|
143
|
-
{<Icon name="material-more_vert" title={"pages"}/>}
|
144
|
-
</MenuButton>
|
145
|
-
)
|
146
|
-
}
|
147
|
-
Object.map(actions,(a,i)=>{
|
148
|
-
if(!a) return;
|
149
|
-
acts.push(a);
|
150
|
-
})
|
151
|
-
this.pdfViewerWrapperDomId = defaultStr(this.pdfViewerWrapperDomId,uniqid("pdf-viewer-wrapper-id"))
|
152
|
-
return (
|
153
|
-
<Dialog
|
154
|
-
key = {_uniqid("dialog-pdf-viewer-key-id")}
|
155
|
-
{...dialogProps}
|
156
|
-
ref = {(el)=>{
|
157
|
-
if(el){
|
158
|
-
this.dialogRef = el;
|
159
|
-
}
|
160
|
-
}}
|
161
|
-
fullPage
|
162
|
-
visible
|
163
|
-
actions = {acts}
|
164
|
-
>
|
165
|
-
<div className="pdf-viewer-wrapper w100 h100" id={this.pdfViewerWrapperDomId}></div>
|
166
|
-
</Dialog>
|
167
|
-
);
|
168
|
-
}
|
6
|
+
export default function WebPDFReader(){
|
7
|
+
dialogRef = React.useRef(null);
|
8
|
+
return <>
|
9
|
+
<DialogProvider
|
10
|
+
ref = {dialogRef}
|
11
|
+
responsive = {false}
|
12
|
+
/>
|
13
|
+
</>
|
169
14
|
}
|
170
15
|
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
/*** méthode appelée lorsque le document est imprimé */
|
177
|
-
onPrint : PropTypes.func,
|
16
|
+
export const open = (props)=>{
|
17
|
+
if(!dialogRef || !dialogRef?.current) return;
|
18
|
+
DialogProvider.open({
|
19
|
+
...props,
|
20
|
+
},dialogRef.current);
|
178
21
|
}
|