@fto-consult/expo-ui 5.8.11 → 5.10.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/babel.config.alias.js +27 -1
- package/babel.config.js +0 -1
- package/package.json +11 -11
- package/src/App.js +5 -40
- package/src/app.config.json +31 -0
- package/src/components/Datagrid/Common/Common.js +31 -23
- package/src/components/Datagrid/SWRDatagrid.js +2 -2
- package/src/components/Form/Fields/Field.js +1 -1
- package/src/components/Form/Fields/IDField.js +0 -1
- package/src/components/Form/Fields/SelectTableData/Component.js +9 -4
- package/src/components/InlineIndicator/Select.js +1 -0
- package/src/components/InlineIndicator/index.js +1 -1
- package/src/components/SimpleSelect/index.js +2 -2
- package/src/components/SplashScreen/index.js +122 -152
- package/src/index.js +69 -30
- package/src/layouts/DatabaseStatistics/index.js +1 -1
- package/src/layouts/Screen/FormData/FormData.js +4 -1
- package/src/layouts/Screen/TableData.js +72 -52
- package/src/layouts/Screen/utils.js +15 -9
- package/src/navigation/Drawer/index.js +2 -1
- package/src/navigation/Drawer/items/utils.js +0 -0
- package/src/screens/Auth/PermProfile.js +2 -2
package/babel.config.alias.js
CHANGED
|
@@ -16,8 +16,34 @@ module.exports = (opts)=>{
|
|
|
16
16
|
const cpath = fs.existsSync(euCommon)? path.resolve(euCommon,"babel.config.alias") : "@fto-consult/common/babel.config.alias";
|
|
17
17
|
const r = require(`${cpath}`)(opts);
|
|
18
18
|
const expo = path.resolve(expoUI,"src");
|
|
19
|
-
|
|
19
|
+
|
|
20
|
+
/**** package json */
|
|
21
|
+
const packagePath = path.resolve(base,"package.json");
|
|
22
|
+
const configPath = path.resolve(expo,"app.config.json");
|
|
23
|
+
if(fs.existsSync(packagePath)){
|
|
24
|
+
try {
|
|
25
|
+
const packageObj = require(`${packagePath}`);
|
|
26
|
+
if(typeof packageObj.name =="string"){
|
|
27
|
+
packageObj.name = packageObj.name.toUpperCase();
|
|
28
|
+
}
|
|
29
|
+
if(packageObj){
|
|
30
|
+
["scripts","private","main","repository","keywords","bugs","dependencies","devDependencies"].map(v=>{
|
|
31
|
+
delete packageObj[v];
|
|
32
|
+
})
|
|
33
|
+
fs.writeFileSync(configPath,JSON.stringify(packageObj,null,"\t"));
|
|
34
|
+
}
|
|
35
|
+
} catch (e){
|
|
36
|
+
console.log(e," writing file sync on package JSON, file : $common/babel.config.alias")
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
if(fs.existsSync(configPath)){
|
|
40
|
+
r["$package.json"] = r["$packageJSON"] = configPath;
|
|
41
|
+
}
|
|
42
|
+
|
|
20
43
|
r["$ecomponents"] = r["$expo-components"] = path.resolve(expo,"components");
|
|
44
|
+
r["$econfirm"] = path.resolve(r["$expo-components"],"Dialog","confirm");
|
|
45
|
+
r["$confirm"] = r["$confirm"] || r["$econfirm"];
|
|
46
|
+
r["$eauth"] = path.resolve(expo,"auth");
|
|
21
47
|
r["$etableLink"] = r["$eTableLink"] = path.resolve(r["$ecomponents"],"TableLink");
|
|
22
48
|
r.$tableLink = r.$TableLink = r.$tableLink || r.$TableLink || path.resolve(r.$etableLink,"default");
|
|
23
49
|
r["$components"] = r["$components"] || r["$ecomponents"];
|
package/babel.config.js
CHANGED
|
@@ -14,7 +14,6 @@ module.exports = function(api,opts) {
|
|
|
14
14
|
inlineDovOptions.path ='./.env';
|
|
15
15
|
}
|
|
16
16
|
/*** par défaut, les variables d'environnements sont stockés dans le fichier .env situé à la racine du projet, référencée par la prop base */
|
|
17
|
-
|
|
18
17
|
const alias = require("./babel.config.alias")(options);
|
|
19
18
|
return {
|
|
20
19
|
presets: [
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fto-consult/expo-ui",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.10.0",
|
|
4
4
|
"description": "Bibliothèque de composants UI Expo,react-native",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -58,10 +58,10 @@
|
|
|
58
58
|
},
|
|
59
59
|
"homepage": "https://github.com/borispipo/expo-ui#readme",
|
|
60
60
|
"dependencies": {
|
|
61
|
-
"@emotion/native": "^11.
|
|
61
|
+
"@emotion/native": "^11.11.0",
|
|
62
62
|
"@expo/html-elements": "^0.2.0",
|
|
63
63
|
"@expo/vector-icons": "^13.0.0",
|
|
64
|
-
"@fto-consult/common": "^3.
|
|
64
|
+
"@fto-consult/common": "^3.14.1",
|
|
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",
|
|
@@ -70,8 +70,8 @@
|
|
|
70
70
|
"@react-navigation/native": "^6.1.6",
|
|
71
71
|
"@react-navigation/native-stack": "^6.9.12",
|
|
72
72
|
"@shopify/flash-list": "^1.4.0",
|
|
73
|
-
"apexcharts": "^3.
|
|
74
|
-
"expo": "^48.0.
|
|
73
|
+
"apexcharts": "^3.40.0",
|
|
74
|
+
"expo": "^48.0.17",
|
|
75
75
|
"expo-camera": "~13.2.1",
|
|
76
76
|
"expo-clipboard": "~4.1.1",
|
|
77
77
|
"expo-font": "~11.1.1",
|
|
@@ -91,20 +91,20 @@
|
|
|
91
91
|
"react-content-loader": "^6.2.1",
|
|
92
92
|
"react-dom": "^18.2.0",
|
|
93
93
|
"react-native": "^0.71.3",
|
|
94
|
-
"react-native-big-list": "^1.6.
|
|
94
|
+
"react-native-big-list": "^1.6.1",
|
|
95
95
|
"react-native-blob-util": "^0.17.0",
|
|
96
96
|
"react-native-gesture-handler": "~2.9.0",
|
|
97
97
|
"react-native-iphone-x-helper": "^1.3.1",
|
|
98
98
|
"react-native-mime-types": "^2.3.0",
|
|
99
|
-
"react-native-paper": "^5.
|
|
100
|
-
"react-native-paper-dates": "^0.
|
|
99
|
+
"react-native-paper": "^5.8.0",
|
|
100
|
+
"react-native-paper-dates": "^0.16.2",
|
|
101
101
|
"react-native-reanimated": "~2.14.4",
|
|
102
|
-
"react-native-safe-area-context": "^4.5.
|
|
103
|
-
"react-native-screens": "
|
|
102
|
+
"react-native-safe-area-context": "^4.5.3",
|
|
103
|
+
"react-native-screens": "^3.20.0",
|
|
104
104
|
"react-native-svg": "13.4.0",
|
|
105
105
|
"react-native-web": "~0.18.7",
|
|
106
106
|
"react-native-webview": "^11.26.0",
|
|
107
|
-
"react-virtuoso": "^4.
|
|
107
|
+
"react-virtuoso": "^4.3.7",
|
|
108
108
|
"sharp-cli": "^2.1.0",
|
|
109
109
|
"tippy.js": "^6.3.7",
|
|
110
110
|
"websql": "^2.0.3",
|
package/src/App.js
CHANGED
|
@@ -2,18 +2,11 @@ import '$session';
|
|
|
2
2
|
import React from 'react';
|
|
3
3
|
import {SWRConfig} from "$swr";
|
|
4
4
|
import {defaultObj} from "$cutils";
|
|
5
|
-
import {updateTheme,defaultTheme} from "$theme";
|
|
6
|
-
import {Provider as PaperProvider } from 'react-native-paper';
|
|
7
5
|
import Index from './index';
|
|
8
6
|
import notify from "$notify";
|
|
9
7
|
import { SafeAreaProvider } from 'react-native-safe-area-context';
|
|
10
|
-
import { PreferencesContext } from './Preferences';
|
|
11
|
-
import {AuthProvider} from '$cauth';
|
|
12
|
-
import ErrorBoundary from "$ecomponents/ErrorBoundary";
|
|
13
8
|
import {GestureHandlerRootView} from "react-native-gesture-handler";
|
|
14
|
-
import StatusBar from "$ecomponents/StatusBar";
|
|
15
9
|
import APP from "$app";
|
|
16
|
-
import FontIcon from "$ecomponents/Icon/Font"
|
|
17
10
|
import {isMobileNative} from "$cplatform";
|
|
18
11
|
import {setDeviceIdRef} from "$capp";
|
|
19
12
|
import appConfig from "$capp/config";
|
|
@@ -30,7 +23,7 @@ Object.map(Utils,(v,i)=>{
|
|
|
30
23
|
window[i] = v;
|
|
31
24
|
}
|
|
32
25
|
});
|
|
33
|
-
export default function getIndex({onMount,onUnmount,swrConfig,
|
|
26
|
+
export default function getIndex({onMount,onUnmount,swrConfig,onRender,...rest}){
|
|
34
27
|
const isScreenFocusedRef = React.useRef(true);
|
|
35
28
|
///garde pour chaque écran sa date de dernière activité
|
|
36
29
|
const screensRef = React.useRef({});//la liste des écrans actifs
|
|
@@ -97,19 +90,7 @@ export default function getIndex({onMount,onUnmount,swrConfig,render,onRender,pr
|
|
|
97
90
|
}
|
|
98
91
|
}
|
|
99
92
|
},[])
|
|
100
|
-
|
|
101
|
-
const updatePreferenceTheme = (customTheme,persist)=>{
|
|
102
|
-
setTheme(updateTheme(customTheme));
|
|
103
|
-
};
|
|
104
|
-
const forceRender = React.useForceRender();
|
|
105
|
-
const pref = typeof appPreferences =='function'? appPreferences({setTheme,forceRender,updateTheme:updatePreferenceTheme}) : appPreferences;
|
|
106
|
-
const preferences = React.useMemo(()=>({
|
|
107
|
-
updateTheme:updatePreferenceTheme,
|
|
108
|
-
theme,
|
|
109
|
-
...defaultObj(pref),
|
|
110
|
-
}),[theme,pref]);
|
|
111
|
-
const child = <Index {...rest} theme={theme}/>;
|
|
112
|
-
const content = typeof render == 'function'? render({children:child,appConfig,config:appConfig}) : child;
|
|
93
|
+
|
|
113
94
|
return (
|
|
114
95
|
<SWRConfig
|
|
115
96
|
value={{
|
|
@@ -160,25 +141,9 @@ export default function getIndex({onMount,onUnmount,swrConfig,render,onRender,pr
|
|
|
160
141
|
}}
|
|
161
142
|
>
|
|
162
143
|
<GestureHandlerRootView style={{ flex: 1 }}>
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
icon: (props) => {
|
|
167
|
-
return <FontIcon {...props}/>
|
|
168
|
-
},
|
|
169
|
-
}}
|
|
170
|
-
>
|
|
171
|
-
<SafeAreaProvider>
|
|
172
|
-
<AuthProvider>
|
|
173
|
-
<ErrorBoundary>
|
|
174
|
-
<StatusBar/>
|
|
175
|
-
<PreferencesContext.Provider value={preferences}>
|
|
176
|
-
{React.isValidElement(content) && content || child}
|
|
177
|
-
</PreferencesContext.Provider>
|
|
178
|
-
</ErrorBoundary>
|
|
179
|
-
</AuthProvider>
|
|
180
|
-
</SafeAreaProvider>
|
|
181
|
-
</PaperProvider>
|
|
144
|
+
<SafeAreaProvider>
|
|
145
|
+
<Index {...rest}/>
|
|
146
|
+
</SafeAreaProvider>
|
|
182
147
|
</GestureHandlerRootView>
|
|
183
148
|
</SWRConfig>
|
|
184
149
|
);
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "SALITE",
|
|
3
|
+
"version": "7.0.0",
|
|
4
|
+
"description": "Logiciel de gestion commerciale pour PME",
|
|
5
|
+
"realeaseDateStr": "1er Juin 2021",
|
|
6
|
+
"releaseDate": "2020-05-23",
|
|
7
|
+
"devMail": "saliteapp@gmail.com",
|
|
8
|
+
"devWebsite": "http://fto-consulting.com/salite/",
|
|
9
|
+
"copyRight": "firsto consulting@Jan 2020",
|
|
10
|
+
"id": "com.ftc.apps.salite7",
|
|
11
|
+
"pouchdbNamePrefix": "com.ftc.apps.slite-",
|
|
12
|
+
"includeFieldsInDatagridFetchOptions": false,
|
|
13
|
+
"feeds": {
|
|
14
|
+
"VIDEOS": {
|
|
15
|
+
"link": "http://fto-consulting.com/salite/feeds",
|
|
16
|
+
"label": "Bibliothèque vidéo",
|
|
17
|
+
"provider": "",
|
|
18
|
+
"icon": "file-video"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"theme": {
|
|
22
|
+
"light": {
|
|
23
|
+
"primary": "#0073B1",
|
|
24
|
+
"secondary": "#EC008C",
|
|
25
|
+
"primaryOnSurface": "#0073B1",
|
|
26
|
+
"secondaryOnSurface": "#EC008C"
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
"author": "@fto-consulting",
|
|
30
|
+
"license": "ISC"
|
|
31
|
+
}
|
|
@@ -40,6 +40,7 @@ import Button from "$ecomponents/Button";
|
|
|
40
40
|
import stableHash from "stable-hash";
|
|
41
41
|
import * as XLSX from "xlsx";
|
|
42
42
|
import {convertToSQL} from "$ecomponents/Filter";
|
|
43
|
+
import appConfig from "$capp/config";
|
|
43
44
|
|
|
44
45
|
export const TIMEOUT = 100;
|
|
45
46
|
|
|
@@ -934,19 +935,22 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
934
935
|
})
|
|
935
936
|
if(size === 1 && canMakePhoneCall === true && canMakeCall()){
|
|
936
937
|
const rowKey = Object.keys(this.selectedRows)[0], rowData = defaultObj(this.selectedRows[rowKey]);
|
|
937
|
-
|
|
938
|
-
callProps =
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
938
|
+
const table = defaultStr(this.props.table,this.props.tableName).trim();
|
|
939
|
+
let callProps = typeof makePhoneCallProps == 'function'? makePhoneCallProps({rowData,rowKey,table,tableName:table,data:rowData,key:rowKey,context:this,props:this.props}) : makePhoneCallProps;
|
|
940
|
+
if(callProps !== false){
|
|
941
|
+
callProps = defaultObj(callProps);
|
|
942
|
+
r.push({
|
|
943
|
+
text : defaultStr(callProps.text,callProps.label,'Appeler'),
|
|
944
|
+
icon : defaultStr(callProps.icon,'phone'),
|
|
945
|
+
flat : true,
|
|
946
|
+
onPress : ()=>{
|
|
947
|
+
return makePhoneCall(
|
|
948
|
+
rowData,
|
|
949
|
+
callProps
|
|
950
|
+
);
|
|
951
|
+
}
|
|
952
|
+
})
|
|
953
|
+
}
|
|
950
954
|
}
|
|
951
955
|
if(isObj(this.props.columns) && size ===1){
|
|
952
956
|
r.push({
|
|
@@ -3365,17 +3369,20 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
|
3365
3369
|
fetchOptions.dataSources = this.currentDataSources;
|
|
3366
3370
|
fetchOptions.selector = fetchFilters;
|
|
3367
3371
|
fetchOptions.sort = this.getSort();
|
|
3368
|
-
const
|
|
3369
|
-
|
|
3370
|
-
|
|
3371
|
-
fields =
|
|
3372
|
-
|
|
3373
|
-
|
|
3374
|
-
|
|
3375
|
-
|
|
3376
|
-
|
|
3372
|
+
const canIncludeField = typeof this.props.includeFieldsInFetchOptions =='boolean'? this.props.includeFieldsInFetchOptions : defaultBool(appConfig.get("includeFieldsInDatagridFetchOptions"),appConfig.includeFieldsInDatagridFetchOptions) !== false;
|
|
3373
|
+
if(canIncludeField){
|
|
3374
|
+
const ff = this.getFilterableColumnsNames();
|
|
3375
|
+
let fields = ff;
|
|
3376
|
+
if(this.isFetchOnlyVisibleColumnsEnabled()){
|
|
3377
|
+
fields = [];
|
|
3378
|
+
Object.map(ff,(field)=>{
|
|
3379
|
+
if(isNonNullString(field) && isObj(this.state.columns[field]) && this.state.columns[field].visible !== false){
|
|
3380
|
+
fields.push(field);
|
|
3381
|
+
}
|
|
3382
|
+
});
|
|
3383
|
+
}
|
|
3384
|
+
fetchOptions.fields = fields;
|
|
3377
3385
|
}
|
|
3378
|
-
fetchOptions.fields = fields;
|
|
3379
3386
|
let limit = this.getQueryLimit();
|
|
3380
3387
|
if(limit > 0 && !this.isPivotDatagrid()){
|
|
3381
3388
|
fetchOptions.limit = limit;
|
|
@@ -3809,6 +3816,7 @@ CommonDatagridComponent.propTypes = {
|
|
|
3809
3816
|
PropTypes.node,
|
|
3810
3817
|
PropTypes.element,
|
|
3811
3818
|
]),
|
|
3819
|
+
includeFieldsInFetchOptions : PropTypes.bool,//si les champs de colonnes seront inclus dans les fetchOptions du datagrid
|
|
3812
3820
|
canMakePhoneCall : PropTypes.bool,//si l'on peut faire un appel sur la données sélectionnées
|
|
3813
3821
|
makePhoneCallProps : PropTypes.oneOfType([
|
|
3814
3822
|
PropTypes.object,
|
|
@@ -65,7 +65,7 @@ export const getSWROptions = ()=>{
|
|
|
65
65
|
}
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
-
|
|
68
|
+
const isValidMakePhoneCallProps = p=> isObj(p) && Object.size(p,true) || typeof p ==='function';
|
|
69
69
|
/****la fonction fetcher doit toujours retourner :
|
|
70
70
|
* 1. la liste des éléments fetchés dans la props data
|
|
71
71
|
* 2. le nombre total d'éléments de la liste obtenue en escluant les clause limit et offset correspondant à la même requête
|
|
@@ -118,7 +118,7 @@ const SWRDatagridComponent = React.forwardRef((props,ref)=>{
|
|
|
118
118
|
delete sort.column;
|
|
119
119
|
}
|
|
120
120
|
canMakePhoneCall = defaultBool(canMakePhoneCall,table.canMakePhoneCall);
|
|
121
|
-
makePhoneCallProps =
|
|
121
|
+
makePhoneCallProps = isValidMakePhoneCallProps(makePhoneCallProps) && makePhoneCallProps || isValidMakePhoneCallProps(rest.makePhoneCallProps) && rest.makePhoneCallProps || isValidMakePhoneCallProps(table.makePhoneCallProps) && table.makePhoneCallProps || {};
|
|
122
122
|
const isExportable = !!Auth.isTableDataAllowed({table:tableName,action:'export'});
|
|
123
123
|
rest.exportable = isExportable;
|
|
124
124
|
rowKey = defaultStr(rowKey,table.rowKey,table.primaryKeyColumnName);
|
|
@@ -397,7 +397,7 @@ export default class Field extends AppComponent {
|
|
|
397
397
|
getValidValue (data){
|
|
398
398
|
let v = this.state.validValue;
|
|
399
399
|
if(isFunction(this.props.getValidValue)){
|
|
400
|
-
let v1 = this.props.getValidValue.call(this,{data,context:this,props:this.props});
|
|
400
|
+
let v1 = this.props.getValidValue.call(this,{data,context:this,value:v,validValue:v,state:this.state,props:this.props});
|
|
401
401
|
if(v1 !== undefined){
|
|
402
402
|
v = v1;
|
|
403
403
|
}
|
|
@@ -55,7 +55,6 @@ export default class FormIDField extends TextField {
|
|
|
55
55
|
/*** retourne la valeur validée */
|
|
56
56
|
getValidValue(data){
|
|
57
57
|
const validValue = super.getValidValue(data);
|
|
58
|
-
console.log(data, " is valid value ",data);
|
|
59
58
|
if(!isNonNullString(this.name)) return validValue;
|
|
60
59
|
data[this.name] = defaultStr(data[this.name],validValue,this.newFieldIdValue);
|
|
61
60
|
return validValue;
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// license that can be found in the LICENSE file.
|
|
4
4
|
|
|
5
5
|
import Dropdown from "$ecomponents/Dropdown";
|
|
6
|
-
import {defaultStr,isFunction,defaultVal,isObjOrArray,defaultObj} from "$cutils";
|
|
6
|
+
import {defaultStr,extendObj,isFunction,defaultVal,isObjOrArray,defaultObj} from "$cutils";
|
|
7
7
|
import PropTypes from "prop-types";
|
|
8
8
|
import actions from "$cactions";
|
|
9
9
|
import {navigateToTableData} from "$enavigation/utils";
|
|
@@ -19,7 +19,7 @@ import appConfig from "$appConfig";
|
|
|
19
19
|
* foreignKeyTable : la tableData dans laquelle effectuer les donées de la requêtes
|
|
20
20
|
* foreignKeyLabel : Le libélé dans la table étrangère
|
|
21
21
|
*/
|
|
22
|
-
const TableDataSelectField = React.forwardRef(({foreignKeyColumn,bindUpsert2RemoveEvents,onAdd,showAdd:customShowAdd,canShowAdd,foreignKeyTable,fetchItemsPath,foreignKeyLabel,foreignKeyLabelIndex,dropdownActions,fields,fetchItems:customFetchItem,convertFiltersToSQL,mutateFetchedItems,getForeignKeyTable,onFetchItems,isFilter,isUpdate,isDocEditing,items,onAddProps,fetchOptions,...props},ref)=>{
|
|
22
|
+
const TableDataSelectField = React.forwardRef(({foreignKeyColumn,prepareFilters:cPrepareFilters,bindUpsert2RemoveEvents,onAdd,showAdd:customShowAdd,canShowAdd,foreignKeyTable,fetchItemsPath,foreignKeyLabel,foreignKeyLabelIndex,dropdownActions,fields,fetchItems:customFetchItem,convertFiltersToSQL,mutateFetchedItems,getForeignKeyTable,onFetchItems,isFilter,isUpdate,isDocEditing,items,onAddProps,fetchOptions,...props},ref)=>{
|
|
23
23
|
props.data = defaultObj(props.data);
|
|
24
24
|
if(!foreignKeyColumn && isNonNullString(props.field)){
|
|
25
25
|
foreignKeyColumn = props.field;
|
|
@@ -138,8 +138,12 @@ const TableDataSelectField = React.forwardRef(({foreignKeyColumn,bindUpsert2Remo
|
|
|
138
138
|
if(!isMounted()) return;
|
|
139
139
|
if(typeof beforeFetchItems ==='function' && beforeFetchItems(fetchOptions) === false) return;
|
|
140
140
|
let opts = Object.clone(fetchOptions);
|
|
141
|
-
|
|
142
|
-
|
|
141
|
+
if(cPrepareFilters !== false){
|
|
142
|
+
opts.selector = prepareFilters(fetchOptions.selector,{convertToSQL:convertFiltersToSQL});
|
|
143
|
+
opts = getFetchOptions(opts);
|
|
144
|
+
} else {
|
|
145
|
+
opts = {fetchOptions};
|
|
146
|
+
}
|
|
143
147
|
const r = fetchItems(opts);
|
|
144
148
|
if(r === false) return;
|
|
145
149
|
setIsLoading(true);
|
|
@@ -296,6 +300,7 @@ const TableDataSelectField = React.forwardRef(({foreignKeyColumn,bindUpsert2Remo
|
|
|
296
300
|
|
|
297
301
|
TableDataSelectField.propTypes = {
|
|
298
302
|
...Dropdown.propTypes,
|
|
303
|
+
prepareFilters : PropTypes.bool,//si les filtres seront customisé
|
|
299
304
|
bindUpsert2RemoveEvents : PropTypes.bool,//si le composant écoutera l'évènement de rafraichissement des données
|
|
300
305
|
onAdd : PropTypes.func, //({})=>, la fonction appelée lorsque l'on clique sur le bouton add
|
|
301
306
|
canShowAdd : PropTypes.func, //({foreignKeyTable,foreignKeyColumn})=><boolean> la fonction permettant de spécifier si l'on peut afficher le bouton showAdd
|
|
@@ -312,7 +312,7 @@ const SimpleSelect = React.forwardRef((props,ref)=>{
|
|
|
312
312
|
style = {[{marginTop}]}
|
|
313
313
|
anchor = {anchor}
|
|
314
314
|
contentProps = {{style:{flex:1}}}
|
|
315
|
-
minWidth = {
|
|
315
|
+
minWidth = {180}
|
|
316
316
|
contentStyle = {[{paddingVertical:0},rProps.contentStyle]}
|
|
317
317
|
>
|
|
318
318
|
<View
|
|
@@ -322,7 +322,7 @@ const SimpleSelect = React.forwardRef((props,ref)=>{
|
|
|
322
322
|
paddingHorizontal : 10,
|
|
323
323
|
paddingVertical:0,
|
|
324
324
|
height : !isMob?contentContainerHeight:'90%',
|
|
325
|
-
width : !isMob ? Math.max(layout.width,
|
|
325
|
+
width : !isMob ? Math.max(layout.width,180) : undefined,
|
|
326
326
|
},
|
|
327
327
|
isMob && {flex:1},
|
|
328
328
|
!isMob && {paddingRight : 0},
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/* @flow */
|
|
2
2
|
/*** fork of https://www.npmjs.com/package/react-native-animated-splash-screen */
|
|
3
3
|
import PropTypes from "prop-types"
|
|
4
|
-
import
|
|
4
|
+
import React from "$react"
|
|
5
5
|
import {Animated, StyleSheet } from "react-native";
|
|
6
6
|
import View from "$ecomponents/View";
|
|
7
7
|
import {isNativeMobile} from "$cplatform";
|
|
@@ -19,167 +19,136 @@ import styles, {
|
|
|
19
19
|
const isNative = isNativeMobile();
|
|
20
20
|
const Component = isNative? Animated.View : View;
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
state = {
|
|
22
|
+
const SplashScreenComponent = ({isLoaded,children , duration, delay,logoWidth,logoHeight,backgroundColor,imageBackgroundSource,imageBackgroundResizeMode,
|
|
23
|
+
testID,
|
|
24
|
+
disableAppScale,
|
|
25
|
+
disableImageBackgroundAnimation,preload})=>{
|
|
26
|
+
const [state,setState] = React.useState({
|
|
28
27
|
animationDone: false,
|
|
29
28
|
loadingProgress: new Animated.Value(0)
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
if(!isNativeMobile()){
|
|
38
|
-
this.setState({animationDone:true});
|
|
39
|
-
} else {
|
|
40
|
-
Animated.timing(loadingProgress, {
|
|
41
|
-
toValue: 100,
|
|
42
|
-
duration: duration || 1000,
|
|
43
|
-
delay: delay || 0,
|
|
44
|
-
useNativeDriver: true,
|
|
45
|
-
}).start(() => {
|
|
46
|
-
this.setState({
|
|
47
|
-
animationDone: true,
|
|
48
|
-
})
|
|
49
|
-
})
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
renderChildren() {
|
|
55
|
-
const { children, preload, isLoaded } = this.props
|
|
56
|
-
if (preload || preload == null) {
|
|
57
|
-
return children
|
|
29
|
+
});
|
|
30
|
+
const { loadingProgress, animationDone } = state;
|
|
31
|
+
const prevIsLoaded = React.usePrevious(isLoaded);
|
|
32
|
+
React.useEffect(()=>{
|
|
33
|
+
if(prevIsLoaded == isLoaded || !isLoaded) return;
|
|
34
|
+
if(!isNativeMobile()){
|
|
35
|
+
setState({...state,animationDone:true});
|
|
58
36
|
} else {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
37
|
+
Animated.timing(loadingProgress, {
|
|
38
|
+
toValue: 100,
|
|
39
|
+
duration: duration || 1000,
|
|
40
|
+
delay: delay || 0,
|
|
41
|
+
useNativeDriver: true,
|
|
42
|
+
}).start(() => {
|
|
43
|
+
setState({
|
|
44
|
+
...state,
|
|
45
|
+
animationDone: true,
|
|
46
|
+
})
|
|
47
|
+
})
|
|
62
48
|
}
|
|
63
|
-
|
|
64
|
-
|
|
49
|
+
},[isLoaded]);
|
|
50
|
+
testID = defaultStr(testID,"RN_SplashscreenComponent")
|
|
51
|
+
logoWidth = defaultDecimal(logoWidth,150);
|
|
52
|
+
logoHeight = defaultDecimal(logoHeight,250);
|
|
53
|
+
const opacityClearToVisible = {
|
|
54
|
+
opacity: loadingProgress.interpolate({
|
|
55
|
+
inputRange: [0, 15, 30],
|
|
56
|
+
outputRange: [0, 0, 1],
|
|
57
|
+
extrapolate: "clamp",
|
|
58
|
+
}),
|
|
59
|
+
}
|
|
60
|
+
const imageScale = {
|
|
61
|
+
transform: [
|
|
62
|
+
{
|
|
63
|
+
scale: loadingProgress.interpolate({
|
|
64
|
+
inputRange: [0, 10, 100],
|
|
65
|
+
outputRange: [1, 1, 65],
|
|
66
|
+
}),
|
|
67
|
+
},
|
|
68
|
+
],
|
|
65
69
|
}
|
|
66
70
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
disableAppScale,
|
|
78
|
-
disableImageBackgroundAnimation,
|
|
79
|
-
} = this.props
|
|
80
|
-
testID = defaultStr(testID,"RN_SplashscreenComponent")
|
|
81
|
-
logoWidth = defaultDecimal(logoWidth,150);
|
|
82
|
-
logoHeight = defaultDecimal(logoHeight,250);
|
|
83
|
-
const opacityClearToVisible = {
|
|
84
|
-
opacity: loadingProgress.interpolate({
|
|
85
|
-
inputRange: [0, 15, 30],
|
|
86
|
-
outputRange: [0, 0, 1],
|
|
87
|
-
extrapolate: "clamp",
|
|
88
|
-
}),
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
const imageScale = {
|
|
92
|
-
transform: [
|
|
93
|
-
{
|
|
94
|
-
scale: loadingProgress.interpolate({
|
|
95
|
-
inputRange: [0, 10, 100],
|
|
96
|
-
outputRange: [1, 1, 65],
|
|
97
|
-
}),
|
|
98
|
-
},
|
|
99
|
-
],
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
const logoScale = {
|
|
103
|
-
transform: [
|
|
104
|
-
{
|
|
105
|
-
scale: loadingProgress.interpolate({
|
|
106
|
-
inputRange: [0, 10, 100],
|
|
107
|
-
outputRange: [1, 0.8, 10],
|
|
108
|
-
}),
|
|
109
|
-
},
|
|
110
|
-
],
|
|
111
|
-
}
|
|
71
|
+
const logoScale = {
|
|
72
|
+
transform: [
|
|
73
|
+
{
|
|
74
|
+
scale: loadingProgress.interpolate({
|
|
75
|
+
inputRange: [0, 10, 100],
|
|
76
|
+
outputRange: [1, 0.8, 10],
|
|
77
|
+
}),
|
|
78
|
+
},
|
|
79
|
+
],
|
|
80
|
+
}
|
|
112
81
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
82
|
+
const logoOpacity = {
|
|
83
|
+
opacity: loadingProgress.interpolate({
|
|
84
|
+
inputRange: [0, 20, 100],
|
|
85
|
+
outputRange: [1, 0, 0],
|
|
86
|
+
extrapolate: "clamp",
|
|
87
|
+
}),
|
|
88
|
+
}
|
|
120
89
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
return (
|
|
133
|
-
<View style={[styles.container]} testID={testID} nativeID={testID}>
|
|
134
|
-
{!animationDone && <View style={StyleSheet.absoluteFill} testID={testID+"_Animation"}/>}
|
|
135
|
-
<View style={styles.containerGlue}>
|
|
136
|
-
{!animationDone && (
|
|
137
|
-
<Animated.View
|
|
138
|
-
style={_staticBackground(logoOpacity, backgroundColor)}
|
|
139
|
-
testID={testID+"_AnimationDone"}
|
|
140
|
-
/>
|
|
141
|
-
)}
|
|
142
|
-
{(animationDone || isNative) && <Component style={[!disableAppScale && appScale, opacityClearToVisible, styles.flex]}>
|
|
143
|
-
{this.renderChildren()}
|
|
144
|
-
</Component>}
|
|
145
|
-
{!animationDone && (
|
|
146
|
-
<Animated.Image
|
|
147
|
-
testID={testID+"AnimateImage"}
|
|
148
|
-
resizeMode={imageBackgroundResizeMode || "cover"}
|
|
149
|
-
source={imageBackgroundSource}
|
|
150
|
-
style={[disableImageBackgroundAnimation && _staticBackground(
|
|
151
|
-
logoOpacity,
|
|
152
|
-
backgroundColor
|
|
153
|
-
), disableImageBackgroundAnimation && _dynamicImageBackground(
|
|
154
|
-
imageScale,
|
|
155
|
-
logoOpacity,
|
|
156
|
-
backgroundColor
|
|
157
|
-
)]}
|
|
158
|
-
/>
|
|
159
|
-
)}
|
|
160
|
-
{!animationDone && (
|
|
161
|
-
<View testID={testID+"_LogoContainer"} style={[StyleSheet.absoluteFill, styles.logoStyle]}>
|
|
162
|
-
{(
|
|
163
|
-
<Animated.View
|
|
164
|
-
testID={testID+"_Logo"}
|
|
165
|
-
style={_dynamicCustomComponentStyle(
|
|
166
|
-
logoScale,
|
|
167
|
-
logoOpacity,
|
|
168
|
-
logoWidth,
|
|
169
|
-
logoHeight
|
|
170
|
-
)}>
|
|
171
|
-
{<LogoProgress/>}
|
|
172
|
-
</Animated.View>
|
|
173
|
-
)}
|
|
174
|
-
</View>
|
|
175
|
-
)}
|
|
176
|
-
</View>
|
|
177
|
-
</View>
|
|
178
|
-
)
|
|
90
|
+
const appScale = {
|
|
91
|
+
transform: [
|
|
92
|
+
{
|
|
93
|
+
scale: loadingProgress.interpolate({
|
|
94
|
+
inputRange: [0, 7, 100],
|
|
95
|
+
outputRange: [1.1, 1.05, 1],
|
|
96
|
+
}),
|
|
97
|
+
},
|
|
98
|
+
],
|
|
179
99
|
}
|
|
100
|
+
const child = (animationDone && isLoaded)? React.isValidElement(children) && children : null;
|
|
101
|
+
return (
|
|
102
|
+
<View style={[styles.container]} testID={testID} nativeID={testID}>
|
|
103
|
+
{!animationDone && <View style={StyleSheet.absoluteFill} testID={testID+"_Animation"}/>}
|
|
104
|
+
<View style={styles.containerGlue}>
|
|
105
|
+
{!animationDone && (
|
|
106
|
+
<Animated.View
|
|
107
|
+
style={_staticBackground(logoOpacity, backgroundColor)}
|
|
108
|
+
testID={testID+"_AnimationDone"}
|
|
109
|
+
/>
|
|
110
|
+
)}
|
|
111
|
+
{(animationDone || isNative) && <Component style={[!disableAppScale && appScale, opacityClearToVisible, styles.flex]}>
|
|
112
|
+
{child}
|
|
113
|
+
</Component>}
|
|
114
|
+
{!animationDone && (
|
|
115
|
+
<Animated.Image
|
|
116
|
+
testID={testID+"AnimateImage"}
|
|
117
|
+
resizeMode={imageBackgroundResizeMode || "cover"}
|
|
118
|
+
source={imageBackgroundSource}
|
|
119
|
+
style={[disableImageBackgroundAnimation && _staticBackground(
|
|
120
|
+
logoOpacity,
|
|
121
|
+
backgroundColor
|
|
122
|
+
), disableImageBackgroundAnimation && _dynamicImageBackground(
|
|
123
|
+
imageScale,
|
|
124
|
+
logoOpacity,
|
|
125
|
+
backgroundColor
|
|
126
|
+
)]}
|
|
127
|
+
/>
|
|
128
|
+
)}
|
|
129
|
+
{!animationDone && (
|
|
130
|
+
<View testID={testID+"_LogoContainer"} style={[StyleSheet.absoluteFill, styles.logoStyle]}>
|
|
131
|
+
{(
|
|
132
|
+
<Animated.View
|
|
133
|
+
testID={testID+"_Logo"}
|
|
134
|
+
style={_dynamicCustomComponentStyle(
|
|
135
|
+
logoScale,
|
|
136
|
+
logoOpacity,
|
|
137
|
+
logoWidth,
|
|
138
|
+
logoHeight
|
|
139
|
+
)}>
|
|
140
|
+
{<LogoProgress/>}
|
|
141
|
+
</Animated.View>
|
|
142
|
+
)}
|
|
143
|
+
</View>
|
|
144
|
+
)}
|
|
145
|
+
</View>
|
|
146
|
+
</View>
|
|
147
|
+
)
|
|
180
148
|
}
|
|
181
149
|
|
|
182
|
-
|
|
150
|
+
|
|
151
|
+
SplashScreenComponent.propTypes = {
|
|
183
152
|
preload: PropTypes.bool,
|
|
184
153
|
logoWidth: PropTypes.number,
|
|
185
154
|
children: PropTypes.element,
|
|
@@ -197,4 +166,5 @@ AnimatedSplash.propTypes = {
|
|
|
197
166
|
delay: PropTypes.number,
|
|
198
167
|
}
|
|
199
168
|
|
|
200
|
-
|
|
169
|
+
SplashScreenComponent.displayName = "SplashScreenComponent";
|
|
170
|
+
export default SplashScreenComponent;
|
package/src/index.js
CHANGED
|
@@ -31,6 +31,13 @@ import {PortalProvider,PortalHost } from '$ecomponents/Portal';
|
|
|
31
31
|
import ErrorBoundaryProvider from "$ecomponents/ErrorBoundary/Provider";
|
|
32
32
|
import notify, {notificationRef} from "$notify";
|
|
33
33
|
import DropdownAlert from '$ecomponents/Dialog/DropdownAlert';
|
|
34
|
+
import {AuthProvider} from '$cauth';
|
|
35
|
+
import { PreferencesContext } from './Preferences';
|
|
36
|
+
import ErrorBoundary from "$ecomponents/ErrorBoundary";
|
|
37
|
+
import {updateTheme,defaultTheme} from "$theme";
|
|
38
|
+
import StatusBar from "$ecomponents/StatusBar";
|
|
39
|
+
import {Provider as PaperProvider } from 'react-native-paper';
|
|
40
|
+
import FontIcon from "$ecomponents/Icon/Font";
|
|
34
41
|
|
|
35
42
|
let MAX_BACK_COUNT = 1;
|
|
36
43
|
let countBack = 0;
|
|
@@ -48,13 +55,13 @@ const NAVIGATION_PERSISTENCE_KEY = 'NAVIGATION_STATE';
|
|
|
48
55
|
* initialRouteName : la route initiale par défaut
|
|
49
56
|
* 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)
|
|
50
57
|
*/
|
|
51
|
-
function App({init:initApp,initialRouteName:appInitialRouteName,getStartedRouteName}) {
|
|
58
|
+
function App({init:initApp,initialRouteName:appInitialRouteName,render,preferences:appPreferences,getStartedRouteName}) {
|
|
52
59
|
AppStateService.init();
|
|
53
60
|
const [initialState, setInitialState] = React.useState(undefined);
|
|
54
61
|
const appReadyRef = React.useRef(true);
|
|
55
62
|
const [state,setState] = React.useState({
|
|
56
63
|
isLoading : true,
|
|
57
|
-
isInitialized:
|
|
64
|
+
isInitialized:false,
|
|
58
65
|
});
|
|
59
66
|
React.useEffect(() => {
|
|
60
67
|
const loadResources = ()=>{
|
|
@@ -220,35 +227,67 @@ function App({init:initApp,initialRouteName:appInitialRouteName,getStartedRouteN
|
|
|
220
227
|
}
|
|
221
228
|
},[isInitialized]);
|
|
222
229
|
const hasGetStarted = state.hasGetStarted !== false? true : false;
|
|
230
|
+
|
|
231
|
+
const [theme,setTheme] = React.useState(updateTheme(defaultTheme));
|
|
232
|
+
const updatePreferenceTheme = (customTheme,persist)=>{
|
|
233
|
+
setTheme(updateTheme(customTheme));
|
|
234
|
+
};
|
|
235
|
+
const forceRender = React.useForceRender();
|
|
236
|
+
const pref = typeof appPreferences =='function'? appPreferences({setTheme,forceRender,updateTheme:updatePreferenceTheme}) : appPreferences;
|
|
237
|
+
const preferences = React.useMemo(()=>({
|
|
238
|
+
updateTheme:updatePreferenceTheme,
|
|
239
|
+
theme,
|
|
240
|
+
...defaultObj(pref),
|
|
241
|
+
}),[theme,pref]);
|
|
242
|
+
const isLoaded = !isLoading;
|
|
243
|
+
const child = isLoaded ? <NavigationContainer
|
|
244
|
+
ref={navigationRef}
|
|
245
|
+
initialState={initialState}
|
|
246
|
+
onStateChange={(state) =>{
|
|
247
|
+
setSession(NAVIGATION_PERSISTENCE_KEY,decycle(state),false);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
>
|
|
251
|
+
<PortalProvider>
|
|
252
|
+
<Portal.Host>
|
|
253
|
+
<PreloaderProvider/>
|
|
254
|
+
<DialogProvider responsive/>
|
|
255
|
+
<AlertProvider SimpleSelect={SimpleSelect}/>
|
|
256
|
+
<FormDataDialogProvider/>
|
|
257
|
+
<BottomSheetProvider/>
|
|
258
|
+
<DropdownAlert ref={notificationRef}/>
|
|
259
|
+
<ErrorBoundaryProvider/>
|
|
260
|
+
<Navigation
|
|
261
|
+
initialRouteName = {defaultStr(hasGetStarted ? appInitialRouteName : getStartedRouteName,"Home")}
|
|
262
|
+
state = {state}
|
|
263
|
+
hasGetStarted = {hasGetStarted}
|
|
264
|
+
isInitialized = {!isLoading}
|
|
265
|
+
onGetStart = {(e)=>{
|
|
266
|
+
setState({...state,hasGetStarted:true})
|
|
267
|
+
}}
|
|
268
|
+
/>
|
|
269
|
+
</Portal.Host>
|
|
270
|
+
</PortalProvider>
|
|
271
|
+
</NavigationContainer> : null;
|
|
272
|
+
const content = isLoaded ? typeof render == 'function'? render({children:child,appConfig,config:appConfig}) : child : null;
|
|
223
273
|
return (<SplashScreen isLoaded={!isLoading}>
|
|
224
|
-
<
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
<Navigation
|
|
242
|
-
initialRouteName = {defaultStr(hasGetStarted ? appInitialRouteName : getStartedRouteName,"Home")}
|
|
243
|
-
state = {state}
|
|
244
|
-
hasGetStarted = {hasGetStarted}
|
|
245
|
-
onGetStart = {(e)=>{
|
|
246
|
-
setState({...state,hasGetStarted:true})
|
|
247
|
-
}}
|
|
248
|
-
/>
|
|
249
|
-
</Portal.Host>
|
|
250
|
-
</PortalProvider>
|
|
251
|
-
</NavigationContainer>
|
|
274
|
+
<AuthProvider>
|
|
275
|
+
<PaperProvider
|
|
276
|
+
theme={theme}
|
|
277
|
+
settings={{
|
|
278
|
+
icon: (props) => {
|
|
279
|
+
return <FontIcon {...props}/>
|
|
280
|
+
},
|
|
281
|
+
}}
|
|
282
|
+
>
|
|
283
|
+
<ErrorBoundary>
|
|
284
|
+
<StatusBar/>
|
|
285
|
+
<PreferencesContext.Provider value={preferences}>
|
|
286
|
+
{React.isValidElement(content) && content || child}
|
|
287
|
+
</PreferencesContext.Provider>
|
|
288
|
+
</ErrorBoundary>
|
|
289
|
+
</PaperProvider>
|
|
290
|
+
</AuthProvider>
|
|
252
291
|
</SplashScreen>);
|
|
253
292
|
}
|
|
254
293
|
|
|
@@ -54,7 +54,7 @@ export default function DatabaseStatisticScreen ({withScreen,fetchDataProps,tabl
|
|
|
54
54
|
if(!content.length) {
|
|
55
55
|
return null;
|
|
56
56
|
}
|
|
57
|
-
content = <Component {...containerProps} style={[containerProps.style,theme.styles.mr1,theme.styles.ml1]}>
|
|
57
|
+
content = <Component {...containerProps} style={[containerProps.style,theme.styles.mr1,theme.styles.pv1,theme.styles.ml1]}>
|
|
58
58
|
{content}
|
|
59
59
|
</Component>;
|
|
60
60
|
return withScreen !== false ? <Screen containerProps={{style:[{flexGrow:0,flex:0}]}} withScrollView title={defaultVal(customTitle,title)} {...props}>{content}</Screen> : content;
|
|
@@ -53,14 +53,17 @@ export default class FormDataLayout extends FormDataActions {
|
|
|
53
53
|
close(){
|
|
54
54
|
return goBack(true);
|
|
55
55
|
}
|
|
56
|
+
isLoading(){
|
|
57
|
+
return !!(this.props.isLoading)
|
|
58
|
+
}
|
|
56
59
|
wrapRenderingContent(content,wProps){
|
|
57
60
|
let {
|
|
58
61
|
withHeavyScreen,
|
|
59
62
|
preloader,
|
|
60
63
|
preloaderProps,
|
|
61
64
|
testID,
|
|
62
|
-
isLoading,
|
|
63
65
|
} = this.props;
|
|
66
|
+
const isLoading = this.isLoading();
|
|
64
67
|
wProps = defaultObj(wProps);
|
|
65
68
|
const useHeavyScreen = withHeavyScreen !== false || isLoading == true? true : false;
|
|
66
69
|
const Wrapper = useHeavyScreen ? HeavyScreen : React.Fragment;
|
|
@@ -20,7 +20,7 @@ import {renderTabsContent,renderActions} from "./utils";
|
|
|
20
20
|
import theme from "$theme";
|
|
21
21
|
import cActions from "$cactions";
|
|
22
22
|
import APP from "$capp/instance";
|
|
23
|
-
import { generatedColumnsProperties } from "./utils";
|
|
23
|
+
import { generatedColumnsProperties,defaultArchivedPermsFilter } from "./utils";
|
|
24
24
|
import {isDocEditing,checkPrimaryKey} from "$ecomponents/Form";
|
|
25
25
|
import i18n from "$i18n";
|
|
26
26
|
import fetch from "$capi/fetch";
|
|
@@ -55,7 +55,7 @@ export default class TableDataScreenComponent extends FormDataScreen{
|
|
|
55
55
|
if(r === false || (!args.value && typeof args.value != 'number')) return r;
|
|
56
56
|
//on applique la validation seulement en cas de non mise à jour
|
|
57
57
|
if(!this.isCurrentDocEditingUpdate() && context && typeof context.onNoValidate =='function'){
|
|
58
|
-
const cb = typeof field.fetchUniqueId =='function'? field.fetchUniqueId : typeof this.fetchUniqueId =='function'? this.fetchUniqueId : undefined;
|
|
58
|
+
const cb = typeof field.fetchUniqueId =='function'? field.fetchUniqueId : typeof this.props.fetchUniqueId =='function'? this.props.fetchUniqueId : undefined;
|
|
59
59
|
if(cb){
|
|
60
60
|
const r2 = cb(args);
|
|
61
61
|
if(isPromise(r2)){
|
|
@@ -93,21 +93,11 @@ export default class TableDataScreenComponent extends FormDataScreen{
|
|
|
93
93
|
tableName : { value : defaultStr(table.table,table.tableName)},
|
|
94
94
|
fields : {value : fields},
|
|
95
95
|
table : {value : table},
|
|
96
|
+
archivedPermsFilterFunc : {value : typeof mainProps.archivedPermsFilter =='function'? mainProps.archivedPermsFilter:defaultArchivedPermsFilter},
|
|
96
97
|
isDocEditingRef : {value : {current:false}},
|
|
97
|
-
validateDataBeforeSave : {value : mainProps.validateData},
|
|
98
|
-
upsertDataToDB : {value : mainProps.upsertToDB},
|
|
99
|
-
makePhoneCallProps : {value : mainProps.makePhoneCallProps},
|
|
100
|
-
onSaveProp : {value : mainProps.onSave},
|
|
101
|
-
titleProp : {value : mainProps.title},
|
|
102
98
|
closeOnSaveProp : {value : mainProps.closeOnSave || mainProps.closeAfterSave },
|
|
103
|
-
newActionProp : {value : mainProps.newAction},
|
|
104
|
-
fetchUniqueId : {value : mainProps.fetchUniqueId},
|
|
105
99
|
//la liste des champ de type clé primaire associés à la table
|
|
106
100
|
primaryKeyFields : {value : primaryKeyFields},
|
|
107
|
-
cloneProp : {value : typeof mainProps.clone =='function' && mainProps.clone || undefined},
|
|
108
|
-
printProp : {value : typeof mainProps.print =='function' && mainProps.print || undefined},
|
|
109
|
-
archiveProp : {value : typeof mainProps.archive =='function' && mainProps.archive || undefined },
|
|
110
|
-
testIDProp : {value : defaultStr(mainProps.testID)},
|
|
111
101
|
showPreloaderOnUpsert : {value : mainProps.showPreloaderOnUpsert},
|
|
112
102
|
});
|
|
113
103
|
this.hidePreloader = this.hidePreloader.bind(this);
|
|
@@ -145,7 +135,7 @@ export default class TableDataScreenComponent extends FormDataScreen{
|
|
|
145
135
|
return defaultObj(this.state.data);
|
|
146
136
|
}
|
|
147
137
|
/**** retourne les props en cours d'édition */
|
|
148
|
-
|
|
138
|
+
getCurrentRenderingProps (){
|
|
149
139
|
return defaultObj(this.currentRenderingProps);
|
|
150
140
|
}
|
|
151
141
|
/* Attention, cette méthode est appélée dans la méthode getComponentProps de la classe parente.
|
|
@@ -165,15 +155,44 @@ export default class TableDataScreenComponent extends FormDataScreen{
|
|
|
165
155
|
* datas: la liste des données passées à la TableData
|
|
166
156
|
* }
|
|
167
157
|
*/
|
|
168
|
-
getActionsPerms(
|
|
169
|
-
|
|
158
|
+
getActionsPerms(args){
|
|
159
|
+
const eProps = this.getCurrentRenderingProps();
|
|
160
|
+
const gPA = typeof eProps.getActionsPerms =='function'? eProps.getActionsPerms : typeof this.props.getActionsPerms =='function'? this.props.getActionsPerms : undefined;
|
|
161
|
+
const permsR = gPA ? gPA.call(this,args) : null;
|
|
162
|
+
const {perm,action,tableName} = args;
|
|
163
|
+
const ePerms = (isNonNullString(perm)? Auth.isAllowed({resource:perm.split(':')[0],action}):Auth.isTableDataAllowed({table:tableName,action}));
|
|
164
|
+
return isObj(permsR) ? extendObj({},ePerms,permsR) : ePerms;
|
|
170
165
|
}
|
|
171
166
|
getRenderedActionPrefix (){}
|
|
172
167
|
renderActions(){
|
|
173
168
|
return null;
|
|
174
169
|
}
|
|
170
|
+
isLoading(){
|
|
171
|
+
return !!(this.getCurrentRenderingProps().isLoading) || !!this.props.isLoading;
|
|
172
|
+
}
|
|
173
|
+
/**** permet de preparer les composant props
|
|
174
|
+
si la fonction retourne un élément react, alors l'élément react est rendu comme résultat du composant
|
|
175
|
+
*/
|
|
176
|
+
prepareComponentProps(props){
|
|
177
|
+
const obj = typeof this.props.prepareComponentProps =='function'? this.props.prepareComponentProps(props) : null;
|
|
178
|
+
if(isObj(obj)){
|
|
179
|
+
return extendObj({},props,obj);
|
|
180
|
+
}
|
|
181
|
+
return props;
|
|
182
|
+
}
|
|
175
183
|
getComponentProps(props){
|
|
176
184
|
this.resetState();
|
|
185
|
+
const table = this.table;
|
|
186
|
+
const {datas,currentIndex,data} = this.state;
|
|
187
|
+
const tableName = this.tableName;
|
|
188
|
+
const isUpdated = this.isDocEditing(data);
|
|
189
|
+
this.isDocEditingRef.current = !!isUpdated;
|
|
190
|
+
const isMobOrTab = isMobileOrTabletMedia();
|
|
191
|
+
let archived = this.isArchived();
|
|
192
|
+
this.INITIAL_STATE.archived = archived;
|
|
193
|
+
this.INITIAL_STATE.tableName = tableName;
|
|
194
|
+
const fields = {};
|
|
195
|
+
const fieldsToPrepare = extendObj({},true,this.fields,customFields);
|
|
177
196
|
const {
|
|
178
197
|
actions,
|
|
179
198
|
fields:customFields,
|
|
@@ -202,20 +221,10 @@ export default class TableDataScreenComponent extends FormDataScreen{
|
|
|
202
221
|
formProps : customFormProps,
|
|
203
222
|
newElementLabel,
|
|
204
223
|
prepareField,
|
|
224
|
+
prepareComponentProps,
|
|
205
225
|
...rest
|
|
206
|
-
} = props;
|
|
207
|
-
const table = this.table;
|
|
208
|
-
const {datas,currentIndex,data} = this.state;
|
|
209
|
-
const tableName = this.tableName;
|
|
226
|
+
} = this.prepareComponentProps({...props,tableName,fields:fieldsToPrepare,isUpdated,isUpdate:isUpdated,data,datas,currentIndex});
|
|
210
227
|
const sessionName = this.INITIAL_STATE.sessionName = defaultStr(customSessionName,"table-form-data"+tableName);
|
|
211
|
-
const isUpdated = this.isDocEditing(data);
|
|
212
|
-
this.isDocEditingRef.current = !!isUpdated;
|
|
213
|
-
const isMobOrTab = isMobileOrTabletMedia();
|
|
214
|
-
let archived = this.isArchived();
|
|
215
|
-
this.INITIAL_STATE.archived = archived;
|
|
216
|
-
this.INITIAL_STATE.tableName = tableName;
|
|
217
|
-
const fields = {};
|
|
218
|
-
const fieldsToPrepare = extendObj({},true,this.fields,customFields);
|
|
219
228
|
const prepareCb = typeof prepareField =='function'? prepareField : x=> x;
|
|
220
229
|
///on effectue une mutator sur le champ en cours de modification
|
|
221
230
|
Object.map(fieldsToPrepare,(field,i,counterIndex)=>{
|
|
@@ -287,11 +296,11 @@ export default class TableDataScreenComponent extends FormDataScreen{
|
|
|
287
296
|
sessionName,
|
|
288
297
|
table,
|
|
289
298
|
newElementLabel : this.getNewElementLabel(),
|
|
290
|
-
printable : this.isPrintable(),///si la table data est imprimable,
|
|
299
|
+
printable : (typeof rest.printable ==='boolean' ? rest.printable : true) && this.isPrintable(),///si la table data est imprimable,
|
|
291
300
|
canMakePhoneCall : this.canMakePhoneCall(),
|
|
292
301
|
makePhoneCallProps:this.getMakePhoneCallProps(),
|
|
293
302
|
onPressToMakePhoneCall : this.makePhoneCall.bind(this),
|
|
294
|
-
archivable : this.isArchivable(),
|
|
303
|
+
archivable : (typeof rest.archivable ==='boolean' ? rest.archivable : true) && this.isArchivable(),
|
|
295
304
|
saveButton : isUpdated?'Modifier':'Enregistrer',
|
|
296
305
|
currentData:data,
|
|
297
306
|
hasManyData : this.hasManyData(),
|
|
@@ -355,10 +364,10 @@ export default class TableDataScreenComponent extends FormDataScreen{
|
|
|
355
364
|
return rActionsArg;
|
|
356
365
|
}
|
|
357
366
|
_render ({header,content,context}){
|
|
358
|
-
const restProps = this.
|
|
367
|
+
const restProps = this.getCurrentRenderingProps();
|
|
359
368
|
delete restProps.tabs;
|
|
360
369
|
let {tabProps,firstTabProps,tabsProps,withScrollView} = restProps;
|
|
361
|
-
let testID = this.
|
|
370
|
+
let testID = this.props.testID;
|
|
362
371
|
tabsProps = defaultObj(tabsProps);
|
|
363
372
|
tabsProps.tabContentProps = defaultObj(tabsProps.tabContentProps);
|
|
364
373
|
tabsProps.tabContentProps.stopChildrenEventPropagation = typeof tabsProps.tabContentProps.stopChildrenEventPropagation =="function" ? tabsProps.tabContentProps.stopChildrenEventPropagation : false;
|
|
@@ -438,7 +447,9 @@ export default class TableDataScreenComponent extends FormDataScreen{
|
|
|
438
447
|
return this.state.currentIndex;
|
|
439
448
|
}
|
|
440
449
|
isArchivable(){
|
|
441
|
-
|
|
450
|
+
const editingProps = this.getCurrentRenderingProps();
|
|
451
|
+
if(typeof editingProps.archivable =='boolean') return editingProps.archivable;
|
|
452
|
+
return !!this.props.archivable;
|
|
442
453
|
}
|
|
443
454
|
isArchived(data){
|
|
444
455
|
data = defaultObj(data,this.state.data);
|
|
@@ -491,7 +502,7 @@ export default class TableDataScreenComponent extends FormDataScreen{
|
|
|
491
502
|
return true;
|
|
492
503
|
}
|
|
493
504
|
isPrintable(){
|
|
494
|
-
return
|
|
505
|
+
return !!(this.props.printable);
|
|
495
506
|
}
|
|
496
507
|
/*** retourne la liste des valeurs de clé primarire associés à la table data pour la données en cours de modification
|
|
497
508
|
* Elle permet d'afficher dans la barre de titre, les identifiants de la table de données en cours de modification
|
|
@@ -519,17 +530,17 @@ export default class TableDataScreenComponent extends FormDataScreen{
|
|
|
519
530
|
return super.isDocEditing(data);
|
|
520
531
|
}
|
|
521
532
|
print(data){
|
|
522
|
-
if(!this.isPrintable() && typeof this.
|
|
533
|
+
if(!this.isPrintable() && typeof this.props.print !=='function') return;
|
|
523
534
|
data = this.isDocEditing(data)? data : isObj(data) && this.isDocEditing(data.data)? data.data : {};
|
|
524
|
-
return this.
|
|
535
|
+
return this.props.print(data,this);
|
|
525
536
|
}
|
|
526
537
|
isClonable(){
|
|
527
|
-
return
|
|
538
|
+
return !!(this.props.clonable !==false);
|
|
528
539
|
}
|
|
529
540
|
clone (data){
|
|
530
541
|
if(!this._isMounted() || !this.isClonable())return data;
|
|
531
542
|
data = {...this.getCurrentEditingData(data)};
|
|
532
|
-
if(this.
|
|
543
|
+
if(typeof this.props.clone ==='function' && this.props.clone(data,this) === false) return data;
|
|
533
544
|
this.showPreloader();
|
|
534
545
|
delete data.approved;
|
|
535
546
|
Object.map(['_rev',...generatedColumnsProperties,...Object.keys(this.primaryKeyFields),'_id','code','updateBy','updatedDate','createBy','updatedHour','createdHour','createdDate'],(idx)=>{
|
|
@@ -580,8 +591,8 @@ export default class TableDataScreenComponent extends FormDataScreen{
|
|
|
580
591
|
return true;
|
|
581
592
|
}
|
|
582
593
|
upsertToDB(args){
|
|
583
|
-
if(typeof this.
|
|
584
|
-
return this.
|
|
594
|
+
if(typeof this.props.upsertToDB ==='function'){
|
|
595
|
+
return this.props.upsertToDB(args);
|
|
585
596
|
}
|
|
586
597
|
return Promise.resolve({});
|
|
587
598
|
}
|
|
@@ -596,15 +607,19 @@ export default class TableDataScreenComponent extends FormDataScreen{
|
|
|
596
607
|
return this.doSave(args);
|
|
597
608
|
}
|
|
598
609
|
canCreateNew(){
|
|
599
|
-
|
|
610
|
+
const editingProps = this.getCurrentRenderingProps();
|
|
611
|
+
if("newAction" in editingProps){
|
|
612
|
+
return !!editingProps.newAction;
|
|
613
|
+
}
|
|
614
|
+
return this.props.newAction !== false ? true : false;
|
|
600
615
|
}
|
|
601
616
|
createNew(){
|
|
602
617
|
return this.reset();
|
|
603
618
|
}
|
|
604
619
|
archive(){}
|
|
605
620
|
validateData(args){
|
|
606
|
-
if(typeof this.
|
|
607
|
-
return this.
|
|
621
|
+
if(typeof this.props.validateData =='function'){
|
|
622
|
+
return this.props.validateData(args);
|
|
608
623
|
}
|
|
609
624
|
return true;
|
|
610
625
|
}
|
|
@@ -659,7 +674,7 @@ export default class TableDataScreenComponent extends FormDataScreen{
|
|
|
659
674
|
let savedData = this.isDocEditing(upserted)? upserted : data;
|
|
660
675
|
const newArgs = {tableName,actionName:action,action,table:this.table,data:savedData,result:upserted,context};
|
|
661
676
|
APP.trigger(cActions.upsert(tableName),newArgs);
|
|
662
|
-
if(this.onSaveTableData(newArgs) === false || (isFunction(this.
|
|
677
|
+
if(this.onSaveTableData(newArgs) === false || (isFunction(this.props.onSave)&& this.props.onSave(newArgs) === false)){
|
|
663
678
|
closePreloader();
|
|
664
679
|
return;
|
|
665
680
|
}
|
|
@@ -754,20 +769,23 @@ export default class TableDataScreenComponent extends FormDataScreen{
|
|
|
754
769
|
}
|
|
755
770
|
getMakePhoneCallProps (){
|
|
756
771
|
const table = this.table;
|
|
757
|
-
const makePhoneCallProps = defaultVal(this.makePhoneCallProps,table.makePhoneCallProps);
|
|
758
|
-
|
|
772
|
+
const makePhoneCallProps = defaultVal(this.props.makePhoneCallProps,table.makePhoneCallProps);
|
|
773
|
+
const rowData = this.getCurrentData();
|
|
774
|
+
const mP = typeof makePhoneCallProps === 'function' ? makePhoneCallProps({rowData,data:rowData,isTableData:true,props:this.props,context:this,table,tableName:this.table}) : makePhoneCallProps;
|
|
775
|
+
return mP !== false ? defaultObj(mP) : null;
|
|
759
776
|
}
|
|
760
777
|
makePhoneCall(data){
|
|
761
|
-
|
|
762
|
-
|
|
778
|
+
const mP = this.getMakePhoneCallProps();
|
|
779
|
+
if(!this.canMakePhoneCall() || !canMakePhoneCall() || !isObj(mP)) return false;
|
|
780
|
+
makePCall(defaultObj(data || this.getCurrentData()),mP);
|
|
763
781
|
return false;
|
|
764
782
|
}
|
|
765
783
|
|
|
766
784
|
/*** archivedPermsFilter est la fonction permettant de filtres les permissions qui par défaut ne figurent pas parmis les permissions en readOnly
|
|
767
785
|
* si archivedPermFilter retourne true pour une permission données alors cette permission sera ignorée
|
|
768
786
|
*/
|
|
769
|
-
archivedPermsFilter (
|
|
770
|
-
return
|
|
787
|
+
archivedPermsFilter (...args){
|
|
788
|
+
return !!this.archivedPermsFilterFunc(...args);
|
|
771
789
|
};
|
|
772
790
|
copyToClipboard(){
|
|
773
791
|
return copyToClipboard({
|
|
@@ -791,7 +809,8 @@ export default class TableDataScreenComponent extends FormDataScreen{
|
|
|
791
809
|
return ret;
|
|
792
810
|
}
|
|
793
811
|
getAppBarTitle (){
|
|
794
|
-
|
|
812
|
+
const editingProps = this.getCurrentRenderingProps();
|
|
813
|
+
return React.isValidElement(editingProps.title,true) && editingProps.title || React.isValidElement(this.props.title,true) && this.props.title || this.table.text || this.table.label || null;
|
|
795
814
|
}
|
|
796
815
|
getAppBarProps(a){
|
|
797
816
|
const r = super.getAppBarProps(a);
|
|
@@ -808,6 +827,7 @@ export default class TableDataScreenComponent extends FormDataScreen{
|
|
|
808
827
|
|
|
809
828
|
TableDataScreenComponent.propTypes = {
|
|
810
829
|
...defaultObj(FormData.propTypes),
|
|
830
|
+
prepareComponentProps : PropTypes.func, //permet d'appreter les components props à utiliser pour le rendu des données
|
|
811
831
|
prepareField : PropTypes.func,//La fonction permettant de faire des mutations sur le champ field à passer au formulaire form. si elle retourne false alors la field ne sera pas pris een compte
|
|
812
832
|
table : PropTypes.shape({
|
|
813
833
|
tableName : PropTypes.string,
|
|
@@ -817,7 +837,7 @@ TableDataScreenComponent.propTypes = {
|
|
|
817
837
|
unique : PropTypes.bool,//si la validation de type unique sur le champ sera effective
|
|
818
838
|
fetchUniqueId : PropTypes.func,//la fonction permettant de fetch un élément unique pour la validation de type uniqueID, liée aux champs de type piece et id
|
|
819
839
|
validateData : PropTypes.func,// la fonction permettant de valider les données à enregistrer
|
|
820
|
-
archivedPermsFilter : PropTypes.func,///le filtre des permissions archivées
|
|
840
|
+
archivedPermsFilter : PropTypes.func,///le filtre des permissions archivées, elle permet de laisser uniquement les permissions de faire un filtre sur les permission et ne laisser que celle qui sont considérées comme disposible en cas de document archivé
|
|
821
841
|
newElementLabel : PropTypes.string,//le titre du bouton nouveau pour l'ajout d'un nouvel élément
|
|
822
842
|
customActionKeyPrefix : PropTypes.oneOfType([
|
|
823
843
|
PropTypes.string,
|
|
@@ -71,11 +71,10 @@ export const renderTabsContent = ({tabs,context,data,sessionName,tabsPropsMutato
|
|
|
71
71
|
}
|
|
72
72
|
return null;
|
|
73
73
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
export function renderActions({context,isUpdate,newElementLabel,makePhoneCallProps,hasManyData,onPressCopyToClipboard,archived,archivedPermsFilter,canMakePhoneCall,onPressToMakePhoneCall,saveAction,save2newAction,save2closeAction,cloneAction,readOnly,printable,archivable,data,table,perm,tableName,saveButton,datas,rows,currentData,currentDataIndex,onPressToSave,onPressToCreateNew,onPressToPrint,onPressToPrevious,onPressToNext,onPressToArchive,...rest}){
|
|
74
|
+
export const readablePerms = ["read","print"];
|
|
75
|
+
export const defaultArchivedPermsFilter = ({perm})=>!readablePerms.includes(perm) && !readablePerms.includes(perm.toLowerCase());
|
|
76
|
+
export function renderActions({context,isUpdate,newElementLabel,readablePerms:cReadablePerms,makePhoneCallProps,hasManyData,onPressCopyToClipboard,archived,archivedPermsFilter,canMakePhoneCall,onPressToMakePhoneCall,saveAction,save2newAction,save2closeAction,cloneAction,readOnly,printable,archivable,data,table,perm,tableName,saveButton,datas,rows,currentData,currentDataIndex,onPressToSave,onPressToCreateNew,onPressToPrint,onPressToPrevious,onPressToNext,onPressToArchive,...rest}){
|
|
77
77
|
let textSave = defaultStr(saveButton)
|
|
78
|
-
archivedPermsFilter = defaultFunc(archivedPermsFilter,x=>true);
|
|
79
78
|
table = defaultStr(tableName,table);
|
|
80
79
|
datas = defaultArray(datas,rows);
|
|
81
80
|
const self = context || {}
|
|
@@ -83,9 +82,10 @@ export function renderActions({context,isUpdate,newElementLabel,makePhoneCallPr
|
|
|
83
82
|
const getActionsPerms = isFunction(self.getActionsPerms) ? self.getActionsPerms.bind(self) : undefined;
|
|
84
83
|
let perms = {};
|
|
85
84
|
readOnly = defaultBool(readOnly,false);
|
|
85
|
+
const callArgs = {readOnly,perm,archived,isUpdate,currentData,action,data,tableName:table,table,context,datas};
|
|
86
86
|
if(getActionsPerms){
|
|
87
87
|
/**** getAction perms est la fonction appelée parl'objet TableData, pour retourner les permission des actions de la tableData */
|
|
88
|
-
perms = getActionsPerms.call(self,
|
|
88
|
+
perms = getActionsPerms.call(self,callArgs)
|
|
89
89
|
} else {
|
|
90
90
|
perms = (isNonNullString(perm)? Auth.isAllowed({resource:perm.split(':')[0],action}):Auth.isTableDataAllowed({table,action}));
|
|
91
91
|
}
|
|
@@ -97,14 +97,20 @@ export function renderActions({context,isUpdate,newElementLabel,makePhoneCallPr
|
|
|
97
97
|
delete perms.archive;
|
|
98
98
|
delete perms.archivable;
|
|
99
99
|
}
|
|
100
|
-
if(
|
|
101
|
-
|
|
100
|
+
if(archived){
|
|
101
|
+
archivedPermsFilter = defaultFunc(archivedPermsFilter,defaultArchivedPermsFilter);
|
|
102
|
+
Object.map(perms,(p,perm)=>{
|
|
103
|
+
if(archivedPermsFilter({perm,perms,data,tableName,readOnly,currentData,context,tableName,isUpdate})) delete perms[i];
|
|
104
|
+
});
|
|
102
105
|
}
|
|
103
106
|
rest = defaultObj(rest);
|
|
104
107
|
newElementLabel = defaultStr(newElementLabel,"Nouveau");
|
|
105
108
|
let permsObj = checkPermsActions.call(self,{...defaultObj(perms),isUpdate})
|
|
106
|
-
makePhoneCallProps =
|
|
109
|
+
makePhoneCallProps = typeof makePhoneCallProps ==='function'? makePhoneCallProps({data,rowData:data,context:{},isTableDataActions:true,table,tableName:table}): makePhoneCallProps;
|
|
107
110
|
self.permsObj = permsObj;
|
|
111
|
+
if(makePhoneCallProps !== false){
|
|
112
|
+
makePhoneCallProps = defaultObj(makePhoneCallProps);
|
|
113
|
+
}
|
|
108
114
|
let save = (!readOnly && !permsObj.canSave || (saveAction === false))? null: {
|
|
109
115
|
text :hasManyData? 'Modifier': textSave,
|
|
110
116
|
title :hasManyData? 'Modifier': textSave,
|
|
@@ -197,7 +203,7 @@ export function renderActions({context,isUpdate,newElementLabel,makePhoneCallPr
|
|
|
197
203
|
flat : true,
|
|
198
204
|
onPress : createCallback({context:self,action:'new',callback:onPressToCreateNew})
|
|
199
205
|
} : null,
|
|
200
|
-
makePhoneCall : (canMakePhoneCall && isUpdate)?{
|
|
206
|
+
makePhoneCall : (canMakePhoneCall && isUpdate && isObj(makePhoneCallProps))?{
|
|
201
207
|
text : defaultStr(makePhoneCallProps.text,makePhoneCallProps.label,'Appeler'),
|
|
202
208
|
isAction : true,
|
|
203
209
|
icon : defaultStr(makePhoneCallProps.icon,'phone'),
|
|
File without changes
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import showConfirm from "$components/Dialog/confirm";
|
|
2
|
-
import notify from "$
|
|
2
|
+
import notify from "$notify";
|
|
3
3
|
import {defaultArray,arrayValueExists,defaultStr,uniqid} from "$cutils";
|
|
4
|
-
import userDbName from "$database/
|
|
4
|
+
import userDbName from "$database/tables/users/dbName";
|
|
5
5
|
import Auth from "$auth";
|
|
6
6
|
import getData from "$database/getData";
|
|
7
7
|
import getDB from "$database/getDB";
|