@fto-consult/expo-ui 2.12.7 → 2.13.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 +4 -3
- package/readMe.md +4 -1
- package/src/components/CountUp/index.js +1 -1
- package/src/components/Datagrid/SWRDatagrid.js +31 -18
- package/src/components/Drawer/index.js +3 -3
- package/src/components/Drawer/utils.js +12 -2
- package/src/layouts/DatabaseStatistics/DatabaseStatistic.js +96 -0
- package/src/layouts/DatabaseStatistics/index.js +54 -0
- package/src/media/file-system/exports.js +16 -0
- package/src/media/file-system/index.js +6 -17
- package/src/media/file-system/utils/index.js +3 -1
- package/src/media/file-system/utils/write.js +30 -4
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fto-consult/expo-ui",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.13.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": "^1.
|
|
64
|
+
"@fto-consult/common": "^1.21.1",
|
|
65
65
|
"@gorhom/portal": "^1.0.14",
|
|
66
66
|
"@react-native-async-storage/async-storage": "~1.17.3",
|
|
67
67
|
"@react-native-community/datetimepicker": "6.5.2",
|
|
@@ -102,7 +102,8 @@
|
|
|
102
102
|
"react-native-web": "~0.18.7",
|
|
103
103
|
"react-native-webview": "11.23.1",
|
|
104
104
|
"sharp-cli": "^2.1.0",
|
|
105
|
-
"tippy.js": "^6.3.7"
|
|
105
|
+
"tippy.js": "^6.3.7",
|
|
106
|
+
"xlsx": "^0.18.5"
|
|
106
107
|
},
|
|
107
108
|
"devDependencies": {
|
|
108
109
|
"@babel/plugin-proposal-export-namespace-from": "^7.18.9",
|
package/readMe.md
CHANGED
|
@@ -5,4 +5,7 @@
|
|
|
5
5
|
-->
|
|
6
6
|
|
|
7
7
|
## Installation des dépendences, packages de dévéloppement
|
|
8
|
-
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
npm i --D @babel/plugin-proposal-export-namespace-from @babel/preset-react babel-plugin-inline-dotenv babel-plugin-module-resolver babel-plugin-transform-inline-environment-variables @expo/metro-config @expo/webpack-config
|
|
11
|
+
```
|
|
@@ -5,7 +5,7 @@ import {defaultNumber,defaultStr} from "$utils";
|
|
|
5
5
|
|
|
6
6
|
export const getDefaultStep = (count)=>{
|
|
7
7
|
count = Math.abs(parseInt(count)||0);
|
|
8
|
-
return count <= 20 ?
|
|
8
|
+
return count <= 20 ? 5 : count <= 50 ? 5 : count <= 100 ? 10 : Math.floor(count/10);
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
const CountUpComponent = ({from,to,format,type,duration,step,formatter,interval,...props})=>{
|
|
@@ -12,6 +12,7 @@ import Auth from "$cauth";
|
|
|
12
12
|
import DateLib from "$lib/date";
|
|
13
13
|
import {getFetchOptions} from "$cutils/filters";
|
|
14
14
|
import {setQueryParams} from "$cutils/uri";
|
|
15
|
+
import { getFetcherOptions } from "$capi/fetch";
|
|
15
16
|
import Icon from "$ecomponents/Icon";
|
|
16
17
|
import Label from "$ecomponents/Label";
|
|
17
18
|
import { StyleSheet,View } from "react-native";
|
|
@@ -93,28 +94,40 @@ const SWRDatagridComponent = React.forwardRef((props,ref)=>{
|
|
|
93
94
|
fetchPath = defaultStr(fetchPath,table.queryPath,tableName.toLowerCase()).trim();
|
|
94
95
|
const innerRef = React.useRef(null);
|
|
95
96
|
const showProgressRef = React.useRef(true);
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
97
|
+
const dataRef = React.useRef(null);
|
|
98
|
+
const hasResultRef = React.useRef(false);
|
|
99
|
+
const totalRef = React.useRef(0);
|
|
100
|
+
const isFetchingRef = React.useRef(false);
|
|
101
|
+
const {error, isValidating,isLoading,refresh} = useSWR(fetchPath,{
|
|
102
|
+
fetcher : (url,opts)=>{
|
|
103
|
+
opts = extendObj({},opts,fetchOptionsRef.current);
|
|
104
|
+
opts.queryParams = defaultObj(opts.queryParams);
|
|
105
|
+
opts.queryParams.withTotal = true;
|
|
106
|
+
const fetchCB = ({data,total})=>{
|
|
107
|
+
totalRef.current = total;
|
|
108
|
+
dataRef.current = data;
|
|
109
|
+
hasResultRef.current = true;
|
|
110
|
+
return data;
|
|
111
|
+
};
|
|
112
|
+
hasResultRef.current = false;
|
|
113
|
+
isFetchingRef.current = true;
|
|
114
|
+
if(typeof fetcher =='function'){
|
|
115
|
+
url = setQueryParams(url,opts.queryParams);
|
|
116
|
+
return fetcher(url,opts).then(fetchCB).finally(()=>{
|
|
117
|
+
isFetchingRef.current = false;
|
|
118
|
+
});
|
|
102
119
|
}
|
|
120
|
+
const {url:fUrl,fetcher:cFetcher,...rest} = getFetcherOptions(url,opts);
|
|
121
|
+
return cFetcher(fUrl,rest).then(fetchCB).finally(()=>{
|
|
122
|
+
isFetchingRef.current = false;
|
|
123
|
+
});
|
|
103
124
|
},
|
|
104
|
-
fetcher,
|
|
105
125
|
showError : false,
|
|
106
126
|
swrOptions : {
|
|
107
127
|
...swrOptions,
|
|
108
128
|
...defaultObj(appConfig.swr),
|
|
109
129
|
},
|
|
110
130
|
});
|
|
111
|
-
const fetchedRef = React.useRef(fetchedData);
|
|
112
|
-
const hasResult = !isLoading && !isValidating && isObj(fetchedData) && 'data' in fetchedData;
|
|
113
|
-
if(hasResult){
|
|
114
|
-
fetchedRef.current = fetchedData;
|
|
115
|
-
}
|
|
116
|
-
const data = fetchedRef.current?.data;
|
|
117
|
-
const total = fetchedRef.current?.total;
|
|
118
131
|
React.useEffect(()=>{
|
|
119
132
|
innerRef.current && innerRef.current.setIsLoading && innerRef.current.setIsLoading(isLoading);
|
|
120
133
|
},[isLoading])
|
|
@@ -126,7 +139,8 @@ const SWRDatagridComponent = React.forwardRef((props,ref)=>{
|
|
|
126
139
|
}
|
|
127
140
|
},[isValidating,isLoading])
|
|
128
141
|
const doRefresh = (showProgress)=>{
|
|
129
|
-
|
|
142
|
+
if(isFetchingRef.current) return;
|
|
143
|
+
showProgressRef.current = showProgress ? typeof showProgress ==='boolean' : true;
|
|
130
144
|
refreshCBRef.current = ()=>{
|
|
131
145
|
showProgressRef.current = true;
|
|
132
146
|
};
|
|
@@ -152,15 +166,14 @@ const SWRDatagridComponent = React.forwardRef((props,ref)=>{
|
|
|
152
166
|
isLoading = {isLoading|| isValidating && !error && showProgressRef.current && true || false}
|
|
153
167
|
beforeFetchData = {({fetchOptions:opts})=>{
|
|
154
168
|
opts.fields = fetchFields;
|
|
155
|
-
opts = getFetchOptions({
|
|
156
|
-
opts.queryParams.withTotal = true;
|
|
169
|
+
opts = getFetchOptions({showError:showProgressRef.current,...opts});
|
|
157
170
|
fetchOptionsRef.current = opts;
|
|
158
171
|
doRefresh(true);
|
|
159
172
|
return false;
|
|
160
173
|
}}
|
|
161
174
|
isTableData
|
|
162
175
|
fetchData = {undefined}
|
|
163
|
-
data = {
|
|
176
|
+
data = {dataRef.current}
|
|
164
177
|
canMakePhoneCall={canMakePhoneCall}
|
|
165
178
|
key={tableName}
|
|
166
179
|
sessionName={defaultStr(sessionName,'list-data')}
|
|
@@ -10,7 +10,7 @@ import DrawerItems from './DrawerItems';
|
|
|
10
10
|
import {isDesktopMedia} from "$cplatform/dimensions";
|
|
11
11
|
import {isMobileNative} from "$cplatform";
|
|
12
12
|
import {open,close} from "$epreloader";
|
|
13
|
-
import {DRAWER_POSITIONS,DRAWER_TYPES,MINIMIZED_WIDTH,
|
|
13
|
+
import {DRAWER_POSITIONS,DRAWER_TYPES,MINIMIZED_WIDTH,getDrawerWidth,MINIMIZED_ICON_SIZE,ICON_SIZE} from './utils';
|
|
14
14
|
import Icon,{MENU_ICON} from "$ecomponents/Icon";
|
|
15
15
|
import apiSession from "./session";
|
|
16
16
|
import View from "$ecomponents/View";
|
|
@@ -82,7 +82,7 @@ const DrawerComponent = React.forwardRef((props,ref)=>{
|
|
|
82
82
|
if(!overlayColor){
|
|
83
83
|
overlayColor = theme.colors.backdrop;// drawerType === DRAWER_TYPES.front ? 'black' : '#00000000';
|
|
84
84
|
}
|
|
85
|
-
let drawerWidth =
|
|
85
|
+
let drawerWidth = getDrawerWidth();
|
|
86
86
|
const restP = {};
|
|
87
87
|
const isDesktop = isDesktopMedia();
|
|
88
88
|
const _canBeMinimizedOrPermanent = canBeMinimizedOrPermanent();
|
|
@@ -155,7 +155,7 @@ const DrawerComponent = React.forwardRef((props,ref)=>{
|
|
|
155
155
|
isPermanent = false;
|
|
156
156
|
isMinimized = false;
|
|
157
157
|
restP.drawerLockMode = "unlocked";
|
|
158
|
-
drawerWidth =
|
|
158
|
+
drawerWidth = drawerWidth;
|
|
159
159
|
}
|
|
160
160
|
context.isMinimizable = ()=>{
|
|
161
161
|
return minimizable !== false && canBeMinimizedOrPermanent() ? true : false;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {isDesktopMedia} from "$cdimensions";
|
|
1
|
+
import Dimensions,{isDesktopMedia} from "$cdimensions";
|
|
2
2
|
|
|
3
3
|
export * from "./DrawerItems/utils";
|
|
4
4
|
|
|
@@ -6,7 +6,17 @@ let activeItem = null;
|
|
|
6
6
|
export const getActiveItem = x=> activeItem;
|
|
7
7
|
export {default as session} from "./session";
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
const DRAWER_WIDTH = 320;
|
|
10
|
+
const DESKTOP_DRAWER_WIDTH = 280;
|
|
11
|
+
|
|
12
|
+
export const getDrawerWidth = ()=>{
|
|
13
|
+
if(isDesktopMedia()) return DESKTOP_DRAWER_WIDTH;
|
|
14
|
+
const {width} = Dimensions.get("window");
|
|
15
|
+
if(width > DRAWER_WIDTH + 100) return DRAWER_WIDTH;
|
|
16
|
+
const percent = Math.floor((width <= DRAWER_WIDTH?90:80)*width/100);
|
|
17
|
+
if(width <= DESKTOP_DRAWER_WIDTH) return percent;
|
|
18
|
+
return Math.max(percent,DESKTOP_DRAWER_WIDTH);
|
|
19
|
+
}
|
|
10
20
|
|
|
11
21
|
export const MINIMIZED_WIDTH = 85;
|
|
12
22
|
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import {defaultStr,isNonNullString} from "$utils";
|
|
2
|
+
import React from "$react";
|
|
3
|
+
import CountUp from "$ecomponents/CountUp";
|
|
4
|
+
import Avatar from "$ecomponents/Avatar";
|
|
5
|
+
import { ActivityIndicator } from "react-native-paper";
|
|
6
|
+
import Item from "$ecomponents/Expandable/Item";
|
|
7
|
+
import {navigateToTableDataList} from "$enavigation/utils";
|
|
8
|
+
import theme from "$theme";
|
|
9
|
+
import Label from "$ecomponents/Label";
|
|
10
|
+
import PropTypes from "prop-types";
|
|
11
|
+
import APP from "$capp/instance"
|
|
12
|
+
import cActions from "$cactions";
|
|
13
|
+
import {View} from "react-native";
|
|
14
|
+
|
|
15
|
+
export default function DatabaseStatisticContainer (props){
|
|
16
|
+
const [state,setState] = React.useState({
|
|
17
|
+
isLoading : true,
|
|
18
|
+
count : 0,
|
|
19
|
+
});
|
|
20
|
+
let {table,fetchCount,index,testID,title,icon,onPress} = props;
|
|
21
|
+
title = defaultStr(title)
|
|
22
|
+
table = defaultObj(table);
|
|
23
|
+
const tableName = defaultStr(table.tableName,table.table).toUpperCase();
|
|
24
|
+
fetchCount = typeof table.fetchCount =='function'? table.fetchCount : typeof fetchCount =='function'? fetchCount : undefined;
|
|
25
|
+
if(!fetchCount || !tableName) return null;
|
|
26
|
+
const refreshingRef = React.useRef(null);
|
|
27
|
+
const isMounted = React.useIsMounted();
|
|
28
|
+
const refresh = ()=>{
|
|
29
|
+
if(refreshingRef.current || !isMounted()) return;
|
|
30
|
+
refreshingRef.current = true;
|
|
31
|
+
setTimeout(()=>{
|
|
32
|
+
fetchCount().then((count)=>{
|
|
33
|
+
setState({...state,isLoading:false,count});
|
|
34
|
+
refreshingRef.current = false;
|
|
35
|
+
}).catch((e)=>{
|
|
36
|
+
setState({
|
|
37
|
+
isLoading : false, count : 0,
|
|
38
|
+
});
|
|
39
|
+
refreshingRef.current = false;
|
|
40
|
+
});
|
|
41
|
+
},100);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
React.useEffect(()=>{
|
|
45
|
+
APP.on(cActions.upsert(tableName),refresh);
|
|
46
|
+
APP.on(cActions.remove(tableName),refresh);
|
|
47
|
+
refresh();
|
|
48
|
+
return ()=>{
|
|
49
|
+
APP.off(cActions.upsert(tableName),refresh);
|
|
50
|
+
APP.off(cActions.remove(tableName),refresh);
|
|
51
|
+
}
|
|
52
|
+
},[]);
|
|
53
|
+
React.useEffect(()=>{
|
|
54
|
+
refresh();
|
|
55
|
+
},[props])
|
|
56
|
+
const {isLoading,count} = state;
|
|
57
|
+
return <Item
|
|
58
|
+
testID = {defaultStr(testID,"RN_DatabaseStatistic_"+table)}
|
|
59
|
+
onPress = {(args)=>{
|
|
60
|
+
if(onPress && onPress(args) === false) return;
|
|
61
|
+
navigateToTableDataList(tableName,{
|
|
62
|
+
tableName
|
|
63
|
+
})
|
|
64
|
+
}}
|
|
65
|
+
left = {(aProps)=>{
|
|
66
|
+
return <Avatar suffix={index} {...aProps} icon= {icon} size={40} label={title}/>
|
|
67
|
+
}}
|
|
68
|
+
//right = {(rP)=><Icon {...rP} name='refresh' onPress={refresh}/>}
|
|
69
|
+
title = {<Label splitText numberOfLines={1} primary style={[{fontSize:15}]}>{title}</Label>}
|
|
70
|
+
titleProps = {{primary : true}}
|
|
71
|
+
description = {isLoading?<View style={[theme.styles.justifyContentFlexStart,theme.styles.alignItemsFlexStart]}>
|
|
72
|
+
<ActivityIndicator color={theme.colors.primary}/>
|
|
73
|
+
</View>:<CountUp
|
|
74
|
+
from={0}
|
|
75
|
+
to={count}
|
|
76
|
+
style = {{fontSize:20,color:theme.colors.secondaryOnSurface}}
|
|
77
|
+
/>}
|
|
78
|
+
>
|
|
79
|
+
|
|
80
|
+
</Item>
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/*** DBSTAT, prend en paramètre le nom de la bd ainsi que celui de la table et affiche en statistic,:
|
|
84
|
+
* Le nombre d'éléments crées en bases ainsi que ceux actifs
|
|
85
|
+
*/
|
|
86
|
+
DatabaseStatisticContainer.propTypes = {
|
|
87
|
+
...Item.propTypes,
|
|
88
|
+
/*** La méthode fetchCount doit retourner une promèsse qui lorsqu'elle est résolue, résoue le nombre d'éléments de la table de données en bd */
|
|
89
|
+
fetchCount : PropTypes.func,//la fonction permettant de counter les éléments de la table data
|
|
90
|
+
table : PropTypes.shape({
|
|
91
|
+
table : PropTypes.string,
|
|
92
|
+
tableName : PropTypes.string,
|
|
93
|
+
fetchCount : PropTypes.func,//la fonction permettant de counter les éléments de la table data
|
|
94
|
+
}).isRequired,
|
|
95
|
+
title : PropTypes.string, //le titre à afficher
|
|
96
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import Screen from "$screen";
|
|
2
|
+
import Grid,{Cell} from "$components/Grid";
|
|
3
|
+
import {defaultStr,defaultNumber,defaultVal} from "$utils";
|
|
4
|
+
import React from "$react";
|
|
5
|
+
import DatabaseStatistic from "./DatabaseStatistic";
|
|
6
|
+
import theme from "$theme";
|
|
7
|
+
import PropTypes from "prop-types";
|
|
8
|
+
|
|
9
|
+
export const title = 'Statistiques en BD';
|
|
10
|
+
export default function DatabaseStatisticScreen ({withScreen,title:customTitle,contentProps,containerProps,tables,Component,...props}){
|
|
11
|
+
Component = React.isComponent(Component)? Component : Grid;
|
|
12
|
+
containerProps = defaultObj(containerProps);
|
|
13
|
+
const title = containerProps.title = defaultStr(containerProps.title,DatabaseStatisticScreen.title);
|
|
14
|
+
contentProps = defaultObj(contentProps);
|
|
15
|
+
if(Component == Cell){
|
|
16
|
+
containerProps.desktopSize = defaultNumber(containerProps.desktopSize,12);
|
|
17
|
+
containerProps.tabletSize = defaultNumber(containerProps.tabletSize,8);
|
|
18
|
+
containerProps.phoneSize = defaultNumber(containerProps.phoneSize,4);
|
|
19
|
+
}
|
|
20
|
+
let content = [];
|
|
21
|
+
Object.map(tables,(table,index,suffix)=>{
|
|
22
|
+
if(isObj(table)){
|
|
23
|
+
content.push(
|
|
24
|
+
<Cell elevation = {5} withSurface mobileSize={12} desktopSize={3} tabletSize={4} {...contentProps} key = {index} >
|
|
25
|
+
<DatabaseStatistic
|
|
26
|
+
icon = {table.icon}
|
|
27
|
+
key = {index}
|
|
28
|
+
table = {table}
|
|
29
|
+
index = {suffix}
|
|
30
|
+
title = {table.text|| table.title}
|
|
31
|
+
></DatabaseStatistic>
|
|
32
|
+
</Cell>
|
|
33
|
+
)
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
if(!content.length) {
|
|
37
|
+
Auth.showError();
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
content = <Component {...containerProps} style={[containerProps.style,theme.styles.mr1,theme.styles.ml1]}>
|
|
41
|
+
{content}
|
|
42
|
+
</Component>;
|
|
43
|
+
return withScreen !== false ? <Screen withScrollView title={defaultVal(customTitle,title)} {...props}>{content}</Screen> : content;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export const screenName = DatabaseStatisticScreen.screenName = "DatabaseStatistics";
|
|
47
|
+
DatabaseStatisticScreen.title = title;
|
|
48
|
+
|
|
49
|
+
DatabaseStatisticScreen.propTypes = {
|
|
50
|
+
tables : PropTypes.oneOfType([
|
|
51
|
+
PropTypes.arrayOf(PropTypes.object),
|
|
52
|
+
PropTypes.objectOf(PropTypes.object)
|
|
53
|
+
]).isRequired
|
|
54
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { readAsStringAsync } from "./utils";
|
|
2
|
+
import { loadAsset } from "../Assets/utils";
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
export * from "./utils";
|
|
6
|
+
|
|
7
|
+
export const readFileAsText = async (asset)=>{
|
|
8
|
+
return await new Promise((resolve,reject)=>{
|
|
9
|
+
loadAsset(asset).then((a)=>{
|
|
10
|
+
readAsStringAsync(a.localUri).then((data) => {
|
|
11
|
+
resolve(data);
|
|
12
|
+
}).catch(reject);
|
|
13
|
+
}).catch(reject);
|
|
14
|
+
})
|
|
15
|
+
}
|
|
16
|
+
export const readFile = readFileAsText;
|
|
@@ -1,20 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
// Copyright 2022 @fto-consult/Boris Fouomene. All rights reserved.
|
|
2
|
+
// Use of this source code is governed by a BSD-style
|
|
3
|
+
// license that can be found in the LICENSE file.
|
|
3
4
|
|
|
4
|
-
|
|
5
|
+
import * as FileSystem from "./exports";
|
|
5
6
|
|
|
6
|
-
export
|
|
7
|
-
return await new Promise((resolve,reject)=>{
|
|
8
|
-
loadAsset(asset).then((a)=>{
|
|
9
|
-
readAsStringAsync(a.localUri).then((data) => {
|
|
10
|
-
resolve(data);
|
|
11
|
-
}).catch(reject);
|
|
12
|
-
}).catch(reject);
|
|
13
|
-
})
|
|
14
|
-
}
|
|
15
|
-
export const readFile = readFileAsText;
|
|
7
|
+
export default FileSystem;
|
|
16
8
|
|
|
17
|
-
export
|
|
18
|
-
readFileAsText,
|
|
19
|
-
readFile,
|
|
20
|
-
}
|
|
9
|
+
export * from "./exports";
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
// Copyright 2022 @fto-consult/Boris Fouomene. All rights reserved.
|
|
2
2
|
// Use of this source code is governed by a BSD-style
|
|
3
3
|
// license that can be found in the LICENSE file.
|
|
4
|
-
import {defaultStr,isNonNullString,defaultNumber,defaultBool,dataURLToBase64,isBlob,isBase64,isDataURL} from "$utils";
|
|
4
|
+
import {defaultStr,isNonNullString,getFileName,getFileExtension,defaultNumber,defaultBool,dataURLToBase64,isBlob,isBase64,isDataURL} from "$utils";
|
|
5
5
|
const FileSaver = require('file-saver');
|
|
6
6
|
const mime = require('mime-types')
|
|
7
|
+
const XLSX = require("xlsx");
|
|
8
|
+
import Preloader from "$preloader";
|
|
9
|
+
|
|
7
10
|
/**** sauvegarde un fichier sur le disque
|
|
8
11
|
* @param {object} {
|
|
9
12
|
* content {mix}: le contenu du fichier à enregistrer
|
|
@@ -16,9 +19,9 @@ const mime = require('mime-types')
|
|
|
16
19
|
* isBinary : si c'est un fichier binaire
|
|
17
20
|
* }
|
|
18
21
|
*/
|
|
19
|
-
export const write = ({content,type,isBinary,timeout,delay,share,contentType,
|
|
22
|
+
export const write = ({content,type,isBinary,timeout,delay,share,contentType,path,directory,fileName})=>{
|
|
20
23
|
share = defaultBool(share,true);
|
|
21
|
-
fileName = sanitizeFileName(
|
|
24
|
+
fileName = sanitizeFileName(fileName);
|
|
22
25
|
contentType = defaultStr(contentType) || mime.contentType(fileName) || mime.contentType(".txt");
|
|
23
26
|
return new Promise((resolve,reject)=>{
|
|
24
27
|
if(!isNonNullString(fileName)){
|
|
@@ -27,7 +30,7 @@ const mime = require('mime-types')
|
|
|
27
30
|
}
|
|
28
31
|
content = isBlob(content)? content : new Blob(content,contentType);
|
|
29
32
|
try {
|
|
30
|
-
FileSaver.saveAs(
|
|
33
|
+
FileSaver.saveAs(content, fileName);
|
|
31
34
|
setTimeout(() => {
|
|
32
35
|
resolve({path:fileName,isWeb : true});
|
|
33
36
|
}, defaultNumber(timeout,delay,3000));
|
|
@@ -39,4 +42,27 @@ const mime = require('mime-types')
|
|
|
39
42
|
|
|
40
43
|
export const writeText = (args)=>{
|
|
41
44
|
return write({...args,contentType:mime.contentType(".txt")});
|
|
45
|
+
}
|
|
46
|
+
/***
|
|
47
|
+
* @see https://ourtechroom.com/tech/mime-type-for-excel/ for excel mimesTypes
|
|
48
|
+
* .xls : application/vnd.ms-excel
|
|
49
|
+
*/
|
|
50
|
+
export const writeExcel = ({workbook,content,contentType,fileName,...rest})=>{
|
|
51
|
+
if(!isNonNullString(contentType) || !contentType.contains("application/vnd.")){
|
|
52
|
+
//contentType = "application/vnd.ms-excel";
|
|
53
|
+
contentType : "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
|
|
54
|
+
}
|
|
55
|
+
let ext = defaultStr(getFileExtension(fileName,true),"xlsx");
|
|
56
|
+
fileName = sanitizeFileName(getFileName(fileName,true))+"."+ext;
|
|
57
|
+
if(!isNonNullString(fileName)){
|
|
58
|
+
return Promise.reject({status:false,message:'Nom de fichier invalide pour le contenu excel à créer'});
|
|
59
|
+
}
|
|
60
|
+
if(isBlob(content)){
|
|
61
|
+
return write({...rest,content,fileName,contentType})
|
|
62
|
+
}
|
|
63
|
+
Preloader.open("génération du fichier excel "+fileName);
|
|
64
|
+
XLSX.writeFile(workbook, fileName);
|
|
65
|
+
setTimeout(()=>{
|
|
66
|
+
Preloader.close();
|
|
67
|
+
},1000);
|
|
42
68
|
}
|