@fto-consult/expo-ui 8.83.3 → 9.0.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 +2 -2
- package/babel.config.js +1 -7
- package/bin/create-app/App.js +1 -0
- package/bin/create-app/app.json +1 -1
- package/bin/create-app/dependencies.js +31 -28
- package/bin/create-app/devDependencies.js +0 -1
- package/bin/create-app.js +2 -3
- package/docs/expo-upgrades.txt +1 -0
- package/expo-ui-path.js +18 -23
- package/metro.config.js +5 -0
- package/package.json +5 -15
- package/readMe.md +9 -9
- package/src/auth/Login.js +16 -7
- package/src/auth/utils.js +10 -0
- package/src/components/AppBar/utils.js +3 -5
- package/src/components/Avatar/AutoHeightImage/cache.js +2 -1
- package/src/components/BottomSheet/Sheet.js +5 -5
- package/src/components/Chart/appexChart/appexChart.html +23 -23
- package/src/components/Datagrid/Accordion/Filters.js +2 -2
- package/src/components/Datagrid/Common/Common.js +7 -10
- package/src/components/Drawer/DrawerItems/index.js +5 -5
- package/src/components/Fab/Group.js +2 -3
- package/src/components/Filter/index.js +2 -1
- package/src/components/Form/Form.js +2 -1
- package/src/components/Form/FormData/DialogProvider.js +2 -2
- package/src/components/Form/FormData/FieldContent.js +2 -1
- package/src/components/Form/FormData/FormData.js +2 -1
- package/src/components/Grid/Cell.js +1 -1
- package/src/components/Icon/Checkbox.js +3 -3
- package/src/components/Image/index.js +5 -2
- package/src/components/Table/Header/index.js +2 -2
- package/src/components/Table/index.js +4 -4
- package/src/components/TableLink/index.js +4 -7
- package/src/context/Provider.js +1 -0
- package/src/layouts/DatabaseStatistics/index.js +3 -3
- package/src/layouts/Screen/TableData.js +1 -1
- package/src/navigation/Drawer/index.js +2 -2
- package/src/navigation/Drawer/items/index.js +2 -1
- package/src/navigation/utils.js +3 -2
- package/src/pdf/index.js +3 -8
- package/src/screens/Auth/PermLines.js +0 -8
- package/src/screens/Auth/Profile.js +3 -6
- package/bin/create-app/webpack.config.js +0 -1
- package/compiler.config.js +0 -33
- package/webpack.config.js +0 -82
@@ -18,8 +18,8 @@ import { useDatagrid } from "../hooks";
|
|
18
18
|
const MIN_WIDTH = 250;
|
19
19
|
let windowWidth = Dimensions.get("window").width;
|
20
20
|
|
21
|
-
const FiltersAccordionComponent = React.forwardRef(({children,filters,filteredColumns,context,label,testID:cTestID,filterTitle:customFilterTitle,visible:customVisible,orOperator,andOperator,onToggleFilters,...rest},ref)=>{
|
22
|
-
|
21
|
+
const FiltersAccordionComponent = React.forwardRef(({children,testID,filters,filteredColumns,context,label,testID:cTestID,filterTitle:customFilterTitle,visible:customVisible,orOperator,andOperator,onToggleFilters,...rest},ref)=>{
|
22
|
+
testID = defaultStr(testID,"RN_AccordionFilters");
|
23
23
|
const [visibleColumns,setVisibleColumns] = React.useState(filteredColumns);
|
24
24
|
const [visible,setVisible] = React.useState(defaultBool(customVisible,false));
|
25
25
|
const valuesRefs = React.useRef({});
|
@@ -44,10 +44,11 @@ import events from "../events";
|
|
44
44
|
import {MORE_ICON} from "$ecomponents/Icon"
|
45
45
|
import ActivityIndicator from "$ecomponents/ActivityIndicator";
|
46
46
|
import {createTableHeader,fields as pdfFields,pageHeaderMargin,sprintf as pdfSprintf} from "$cpdf";
|
47
|
-
import {
|
47
|
+
import {isMobileNative} from "$cplatform";
|
48
48
|
import { createPDF,getFields as getPdfFields } from '$expo-ui/pdf';
|
49
49
|
import actions from '$cactions';
|
50
50
|
import {printTableData} from "$epdf";
|
51
|
+
import {isPermAllowed} from "$eauth/utils";
|
51
52
|
|
52
53
|
export const TIMEOUT = 100;
|
53
54
|
|
@@ -160,10 +161,6 @@ Object.map(displayTypes,(c,k)=>{
|
|
160
161
|
const dataSourceArgs = {};
|
161
162
|
export const footerFieldName = "dgrid-fters-fields";
|
162
163
|
|
163
|
-
const checkPerm = (perm,args)=>{
|
164
|
-
return typeof perm ==='function'? perm(args) : isNonNullString(perm) ? Auth.isAllowedFromStr(perm) : typeof perm =='boolean'? perm : true;
|
165
|
-
}
|
166
|
-
|
167
164
|
/*****
|
168
165
|
* Pour spécifier qu'un champ du datagrid n'existe pas en bd il s'ufit de suffixer le nom du champ par le suffix : "FoundInDB" et de renseigner false comme valeur
|
169
166
|
de l'objet rowData de cette propriété
|
@@ -206,10 +203,10 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
206
203
|
const disTypes = {};
|
207
204
|
let hasFoundDisplayTypes = false;
|
208
205
|
const pArgs = {context:this,data,props:this.props}
|
209
|
-
const perm =
|
210
|
-
const ePDFIsAllowed = !isMobileNative() &&
|
211
|
-
const eExcelISAllowed =
|
212
|
-
const renderSectionListIsAllowedP =
|
206
|
+
const perm = isPermAllowed(renderChartIsAllowed,pArgs)
|
207
|
+
const ePDFIsAllowed = !isMobileNative() && isPermAllowed(exportToPDFIsAllowed,pArgs);
|
208
|
+
const eExcelISAllowed = isPermAllowed(exportToExcelIsAllowed,pArgs);
|
209
|
+
const renderSectionListIsAllowedP = isPermAllowed(renderSectionListIsAllowed,pArgs);
|
213
210
|
if(typeof customCheckPerms =='function'){
|
214
211
|
customCheckPerms({context:this});
|
215
212
|
}
|
@@ -1054,7 +1051,7 @@ export default class CommonDatagridComponent extends AppComponent {
|
|
1054
1051
|
renderDataSourceSelector(){
|
1055
1052
|
const t = !this.props.handleTitle ? null : isNonNullString(this.props.title) || typeof this.props.title ==='number' ? <Label textBold primary style={[theme.styles.fs14]} testID={"RN_DatagridTitleProp"}>{this.props.title}</Label> : React.isValidElement(this.props.title)? this.props.title : null;
|
1056
1053
|
const table = defaultStr(this.props.table,this.props.tableName);
|
1057
|
-
const dS =
|
1054
|
+
const dS = this.props.dataSourceSelector === false ? null : typeof this.props.dataSourceSelector ==='function'? this.props.dataSourceSelector({
|
1058
1055
|
defaultValue : this.currentDataSources,
|
1059
1056
|
onChange : this.onChangeDataSources.bind(this),
|
1060
1057
|
tableName:table,
|
@@ -6,8 +6,7 @@ import DrawerSection from "./DrawerSection"
|
|
6
6
|
import PropTypes from "prop-types";
|
7
7
|
import Divider from "$ecomponents/Divider";
|
8
8
|
import View from "$ecomponents/View";
|
9
|
-
import
|
10
|
-
import { useDrawer } from '../context';
|
9
|
+
import {isPermAllowed} from "$eauth/utils";
|
11
10
|
|
12
11
|
export * from "./utils";
|
13
12
|
|
@@ -23,7 +22,7 @@ const DrawerItemsComponent = React.forwardRef((props,ref)=> {
|
|
23
22
|
const r = React.useMemo(()=>{
|
24
23
|
let items = []
|
25
24
|
const renderExpandableOrSection = ({item,key,items})=>{
|
26
|
-
if(
|
25
|
+
if(!isPermAllowed(item.perm,props)) return null;
|
27
26
|
const {section,items:itx2,...rest} = item;
|
28
27
|
if(section){
|
29
28
|
const sDivider = rest.divider !== false && !hasDivider && items.length ? true : false;
|
@@ -128,7 +127,8 @@ const getDefaultProps = function(item){
|
|
128
127
|
return item;
|
129
128
|
}
|
130
129
|
|
131
|
-
const renderItem = (
|
130
|
+
const renderItem = (args1)=>{
|
131
|
+
let {item,minimized,renderExpandableOrSection,index,key} = args1;
|
132
132
|
key = key||index;
|
133
133
|
if(React.isValidElement(item)){
|
134
134
|
hasDivider = false;
|
@@ -136,7 +136,7 @@ const renderItem = ({item,minimized,renderExpandableOrSection,index,key})=>{
|
|
136
136
|
{item}
|
137
137
|
</React.Fragment>
|
138
138
|
} else {
|
139
|
-
if(
|
139
|
+
if(!isPermAllowed(item.perm,args1)) return null;
|
140
140
|
if(!item.label && !item.text && !item.icon) {
|
141
141
|
if(item.divider === true && !hasDivider){
|
142
142
|
const {divider,...rest} = item;
|
@@ -7,7 +7,7 @@ import {MENU_ICON} from "$ecomponents/Icon";
|
|
7
7
|
import theme,{Colors} from "$theme";
|
8
8
|
import Group from "./GroupComponent";
|
9
9
|
import {Portal} from "react-native-paper";
|
10
|
-
import {
|
10
|
+
import { isPermAllowed } from "$eauth/utils";
|
11
11
|
import { useIsScreenFocused } from '$enavigation/hooks';
|
12
12
|
import { useScreen } from '$econtext/hooks';
|
13
13
|
|
@@ -129,8 +129,7 @@ const FabGroupComponent = React.forwardRef((props,innerRef)=>{
|
|
129
129
|
const a = actionMutator ? actionMutator ({action:act,key:i,isFab:true,fab:true}) : act;
|
130
130
|
if(!isObj(a) || !isNonNullString(a.label)) return null;
|
131
131
|
const {perm,isAllowed,primary,secondary,...restItem} = a;
|
132
|
-
if(
|
133
|
-
if(isNonNullString(perm) && !isAllowedFromStr(perm)) return false;
|
132
|
+
if(!isPermAllowed(perm,{...props,permAction:"fab",action:a}) || !isPermAllowed(isAllowed,{...props,permAction:"fab",action:a})) return false;
|
134
133
|
if(primary){
|
135
134
|
restItem.style = StyleSheet.flatten([restItem.style,{color:theme.colors.onPrimary,backgroundColor:theme.colors.primary}])
|
136
135
|
} else if(secondary){
|
@@ -481,6 +481,7 @@ export default class Filter extends AppComponent {
|
|
481
481
|
data,
|
482
482
|
testID,
|
483
483
|
filterContainerProps,
|
484
|
+
responsiveProps,
|
484
485
|
...rest
|
485
486
|
} = {...this.props,...this.filterProps};
|
486
487
|
const type = this.type;
|
@@ -646,7 +647,7 @@ export default class Filter extends AppComponent {
|
|
646
647
|
const containerProps = defaultObj(this.props.containerProps,rest.containerProps);
|
647
648
|
delete rest.containerProps;
|
648
649
|
const Component = isBetweenAction ? FilterBetweenComponent : this.Component;
|
649
|
-
|
650
|
+
responsiveProps = Object.assign({},responsiveProps);
|
650
651
|
responsiveProps.style = [theme.styles.w100,responsiveProps.style]
|
651
652
|
if(ignoreDefaultValue && isPeriodAction) {
|
652
653
|
rest.isPeriodAction = true;
|
@@ -7,6 +7,7 @@ import { StyleSheet } from "react-native";
|
|
7
7
|
import APP from "$capp/instance";
|
8
8
|
import PropTypes from "prop-types";
|
9
9
|
import View from "$ecomponents/View";
|
10
|
+
import { isPermAllowed } from "$eauth/utils";
|
10
11
|
|
11
12
|
/**** règles d'utilisation :
|
12
13
|
1. les forms doivent toujours avoir un nom : chaine de caractère unique pour l'application et non null
|
@@ -101,7 +102,7 @@ export default class FormComponent extends React.AppComponent {
|
|
101
102
|
Forms.trigger("novalidate",this.props.name,...rest);
|
102
103
|
}
|
103
104
|
render (){
|
104
|
-
if(
|
105
|
+
if(!isPermAllowed(this.props.perm,this.props)){
|
105
106
|
return null;
|
106
107
|
}
|
107
108
|
let {
|
@@ -22,7 +22,7 @@ const FormDataDialogProvider = React.forwardRef((props,innerRef)=>{
|
|
22
22
|
const [state,setState] = React.useState({});
|
23
23
|
const isMobile = isMobileOrTabletMedia();
|
24
24
|
const formRef = React.useRef(null);
|
25
|
-
|
25
|
+
let {closeAction} = props;
|
26
26
|
const context = {
|
27
27
|
open : (props)=>{
|
28
28
|
let sData = {};
|
@@ -68,7 +68,7 @@ const FormDataDialogProvider = React.forwardRef((props,innerRef)=>{
|
|
68
68
|
rest.windowWidth = !isMob ? MAX_WIDTH : undefined;
|
69
69
|
const no = extendObj({},props.no,state.no);
|
70
70
|
rest.actions = Array.isArray(rest.actions)? Object.clone(rest.actions) : isObj(rest.actions)? Object.clone(rest.actions) : null;
|
71
|
-
|
71
|
+
closeAction = defaultObj(closeAction);
|
72
72
|
rest.cancelButton = false;
|
73
73
|
if(cancelButton !== false && rest.actions && (!isMob || rest.fullScreen === false) && state.no !== false){
|
74
74
|
if(isDesktopMedia() && typeof rest.maxActions !=='number'){
|
@@ -4,6 +4,7 @@ import {defaultStr,isNonNullString,defaultObj,defaultBool} from "$cutils";
|
|
4
4
|
import getComponentFromType from "./componentsTypes";
|
5
5
|
import appConfig from "$capp/config";
|
6
6
|
import Colors from "$theme/colors";
|
7
|
+
import { isPermAllowed } from "$eauth/utils";
|
7
8
|
|
8
9
|
const FieldContentComponent = React.forwardRef(({field,data,index,fields,formName,onLoopField,fieldProps,backgroundColor,primaryKey:customPrimaryKey,increment,fieldProp,archivable,disabled,windowWidth,responsive,responsiveProps,archived,...props},ref)=>{
|
9
10
|
if(field?.form === false) return null;
|
@@ -19,7 +20,7 @@ const FieldContentComponent = React.forwardRef(({field,data,index,fields,formNam
|
|
19
20
|
if(customPrimaryKey === true){
|
20
21
|
primaryKey = true;
|
21
22
|
}
|
22
|
-
if(form === false || ignore || (
|
23
|
+
if(form === false || ignore || (!isPermAllowed(perm,{...props,field,isFormData:true,index,data,formName}))){
|
23
24
|
return null;
|
24
25
|
}
|
25
26
|
if(rest.nullable === false){
|
@@ -11,6 +11,7 @@ import {handleBeforeSaveCallback} from "./utils";
|
|
11
11
|
import isDbDocEditing,{checkPrimaryKey} from "../utils/isDocEditing";
|
12
12
|
import keyboardShortcuts from "../utils/keyboardShortcuts";
|
13
13
|
import FieldsContent from "./FieldsContent";
|
14
|
+
import { isPermAllowed } from "$eauth/utils";
|
14
15
|
|
15
16
|
export default class FormDataComponent extends AppComponent{
|
16
17
|
constructor(props){
|
@@ -24,7 +25,7 @@ export default class FormDataComponent extends AppComponent{
|
|
24
25
|
value : x=> formName,
|
25
26
|
},
|
26
27
|
isAllowed : {
|
27
|
-
value :
|
28
|
+
value : isPermAllowed(this.props.perm,props),
|
28
29
|
},
|
29
30
|
});
|
30
31
|
}
|
@@ -74,7 +74,7 @@ const GridCellComponent = React.forwardRef((p,ref)=>{
|
|
74
74
|
const testID = defaultStr(props.testID,"RN_Grid.CellComponent");
|
75
75
|
const contentProps = defaultObj(cProps);
|
76
76
|
const C = onPress || onLongPress || onPressIn || onPressOut ? Pressable : View;
|
77
|
-
const elevation = typeof
|
77
|
+
const elevation = typeof cElev == "number"? cElev : withSurface ? 5 : undefined;
|
78
78
|
const elevStyle = typeof elevation =="number" ? Elevations[elevation] || null : null;
|
79
79
|
return <View
|
80
80
|
{...props}
|
@@ -8,9 +8,9 @@ import {CHECKED_ICON,UNCHECKED_ICON} from "$ecomponents/Icon/utils";
|
|
8
8
|
/****** icon de type checkbox variant en fonction de l'environnement ou la plateforme */
|
9
9
|
const Checkbox = React.forwardRef((props,ref)=>{
|
10
10
|
const {checked:customChecked,color:customColor,primary,secondary,primaryOnCheck,secondaryOnCheck,onChange,checkedIcon:customCheckedIcon,uncheckedIcon:customUncheckedIcon,onPress,...rest} = props;
|
11
|
-
const checkedIcon =
|
12
|
-
const uncheckedIcon =
|
13
|
-
const [checked,setIsChecked] = React.useState(!!
|
11
|
+
const checkedIcon = customCheckedIcon || CHECKED_ICON;
|
12
|
+
const uncheckedIcon = customUncheckedIcon || UNCHECKED_ICON;
|
13
|
+
const [checked,setIsChecked] = React.useState(!!customChecked);
|
14
14
|
const isMounted = React.useIsMounted();
|
15
15
|
const prevChecked = React.usePrevious(checked);
|
16
16
|
const callOnChangeRef = React.useRef(true);
|
@@ -7,7 +7,7 @@ let maxWidthDiff = 100, maxHeightDiff = 100;
|
|
7
7
|
import {StyleSheet} from "react-native";
|
8
8
|
import React from "$react";
|
9
9
|
import PropTypes from "prop-types";
|
10
|
-
import {isMobileNative} from "$cplatform";
|
10
|
+
import {isMobileNative,isWeb} from "$cplatform";
|
11
11
|
import {uniqid} from "$cutils";
|
12
12
|
//import Signature from "$ecomponents/Signature";
|
13
13
|
import Label from "$ecomponents/Label";
|
@@ -26,9 +26,12 @@ export const isValidImageSrc = (src)=>{
|
|
26
26
|
export const resolveAssetSource = (source)=>{
|
27
27
|
if(!source && !isDecimal(source)) return undefined;
|
28
28
|
try {
|
29
|
+
if(isWeb()){
|
30
|
+
return {uri:source};
|
31
|
+
}
|
29
32
|
return Image.resolveAssetSource(source);
|
30
33
|
} catch(e){
|
31
|
-
console.log(
|
34
|
+
console.log(e," triing to resolve image asset from source ",source)
|
32
35
|
return undefined;
|
33
36
|
}
|
34
37
|
}
|
@@ -17,8 +17,6 @@ import Filters from "./Filters";
|
|
17
17
|
|
18
18
|
export default function RowHeaderComponent({isFilter,isFooter,isHeader,className,children:cChildren,...rest}){
|
19
19
|
const {showHeaders,visibleColsNames,colsWidths,filterable,visibleColsNamesStr,headerContainerProps,footerContainerProps,filtersContainerProps,showFilters,filters,showFooters} = useTable();
|
20
|
-
const canV = showHeaders === false ? false : Array.isArray(children)? !!children.length : true;
|
21
|
-
const visible = canV && (isHeader ? true : isFilter ? !!showFilters && filterable !== false : isFooter ? !!showFooters: true);
|
22
20
|
const containerProps = defaultObj( isHeader ? headerContainerProps : isFooter ? footerContainerProps : filtersContainerProps);
|
23
21
|
const style = filters ? styles.filters : isFooter ? styles.footer : null;
|
24
22
|
const children = React.useMemo(()=>{
|
@@ -26,6 +24,8 @@ export default function RowHeaderComponent({isFilter,isFooter,isHeader,className
|
|
26
24
|
return <CellWrapper width={colsWidths[columnField]} isFilter={isFilter} isFooter={isFooter} key={columnField} columnField={columnField} columIndex={index}/>
|
27
25
|
});
|
28
26
|
},[visibleColsNamesStr]);
|
27
|
+
const canV = showHeaders === false ? false : Array.isArray(children)? !!children.length : true;
|
28
|
+
const visible = canV && (isHeader ? true : isFilter ? !!showFilters && filterable !== false : isFooter ? !!showFooters: true);
|
29
29
|
if(!visible && !isFilter) return null;
|
30
30
|
const rP = isNative ? rest : {className:classNames(className,"table-footer-or-header-row")}
|
31
31
|
return <Component {...rP} {...containerProps} style={StyleSheet.flatten([styles.header,style,rest.style,containerProps.style,!visible && hStyle.hidden])}>
|
@@ -65,9 +65,7 @@ const TableComponent = React.forwardRef(({containerProps,tableHeadId,fixedHeader
|
|
65
65
|
const hasData = !!Object.size(items,true);
|
66
66
|
const emptyData = !hasData && (renderListContent === false ?null : typeof renderEmpty =='function' ? renderEmpty() : null) || null;
|
67
67
|
const hasEmptyData = emptyData && React.isValidElement(emptyData);
|
68
|
-
const
|
69
|
-
{emptyData}
|
70
|
-
</View>
|
68
|
+
const listWidth = '100%';
|
71
69
|
const scrollContentContainerStyle = {flex:1,width:listWidth,minWidth:totalWidths,height:'100%'};
|
72
70
|
const scrollEventThrottle = isMobileNative()?200:50;
|
73
71
|
const scrollViewFlexGrow = {flexGrow:0};
|
@@ -80,7 +78,6 @@ const TableComponent = React.forwardRef(({containerProps,tableHeadId,fixedHeader
|
|
80
78
|
scrollViewProps.style],
|
81
79
|
contentContainerStyle : [styles.scrollView,scrollViewProps.contentContainerStyle,scrollViewFlexGrow,scrollContentContainerStyle]
|
82
80
|
}
|
83
|
-
const listWidth = '100%';
|
84
81
|
const footerScrollViewRef = React.useRef(null);
|
85
82
|
const context = {
|
86
83
|
listRef,
|
@@ -143,6 +140,9 @@ const TableComponent = React.forwardRef(({containerProps,tableHeadId,fixedHeader
|
|
143
140
|
}
|
144
141
|
}
|
145
142
|
};
|
143
|
+
const emptyContent = <View onRender={onComponentRender} testID={testID+"_EmptyData"} style={styles.hasNotData}>
|
144
|
+
{emptyData}
|
145
|
+
</View>
|
146
146
|
return <View testID= {testID+"_Container"} {...containerProps} onLayout={(e)=>{
|
147
147
|
layoutRef.current = e.nativeEvent.layout;
|
148
148
|
if(containerProps.onLayout){
|
@@ -16,6 +16,8 @@ import Auth from "$cauth";
|
|
16
16
|
import fetch from "$capi/fetch";
|
17
17
|
import useContext from "$econtext/hooks";
|
18
18
|
import TouchableRipple from "$ecomponents/TouchableRipple";
|
19
|
+
import { isPermAllowed } from "$eauth/utils";
|
20
|
+
|
19
21
|
/***** la fonction fetchForeignData permet de spécifier s'il s'agit d'une données de structure où non
|
20
22
|
dans le champ isStructData
|
21
23
|
*/
|
@@ -50,13 +52,8 @@ export const usePrepareProps = (props)=>{
|
|
50
52
|
}
|
51
53
|
const fetchArgs = {type,columnType:type,isStructData,fetch,foreignKeyTable,foreignKeyColumn,data,id};
|
52
54
|
const checkIfAllowed = ()=>{
|
53
|
-
if((
|
54
|
-
|
55
|
-
} else {
|
56
|
-
if(typeof isAllowed ==="function"){
|
57
|
-
if(!isAllowed(args)) return false;
|
58
|
-
} else if(!Auth[isStructData?"isStructDataAllowed":"isTableDataAllowed"]({table:foreignKeyTable,action:'read'})) return false;
|
59
|
-
}
|
55
|
+
if(!isPermAllowed(perm,props) || !isPermAllowed(isAllowed,props)) return false;
|
56
|
+
if((!perm && !isAllowed && perm !== undefined && isAllowed !== undefined) && !Auth[isStructData?"isStructDataAllowed":"isTableDataAllowed"]({table:foreignKeyTable,action:'read'})) return false;
|
60
57
|
return true;
|
61
58
|
}
|
62
59
|
const navigate = (data)=>{
|
package/src/context/Provider.js
CHANGED
@@ -8,6 +8,7 @@ import PropTypes from "prop-types";
|
|
8
8
|
import Auth from "$cauth";
|
9
9
|
import Surface from "$ecomponents/Surface";
|
10
10
|
import { StyleSheet } from "react-native";
|
11
|
+
import {isPermAllowed} from "$eauth/utils";
|
11
12
|
|
12
13
|
export const title = 'Statistiques en BD';
|
13
14
|
export default function DatabaseStatisticScreen ({withScreen,fetchDataProps,itemProps,itemContainerProps,tableFilter,fetchCount,fetchData,title:customTitle,contentProps,containerProps,tables,Component,...props}){
|
@@ -38,10 +39,9 @@ export default function DatabaseStatisticScreen ({withScreen,fetchDataProps,item
|
|
38
39
|
let {containerProps,cellProps,...rDBProps} = dbStatisticsProps;
|
39
40
|
cellProps = Object.assign({},cellProps);
|
40
41
|
containerProps = Object.assign({},containerProps);
|
41
|
-
const chartAllowedPerm = defaultStr(table.chartAllowedPerm);
|
42
42
|
const testID = "RN_DatabaseStatisticsCell_"+index;
|
43
|
-
if(chartAllowedPerm){
|
44
|
-
if(!
|
43
|
+
if(table.chartAllowedPerm !== undefined){
|
44
|
+
if(!isPermAllowed(table.chartAllowedPerm,{table,tables,databaseStatistic:true})) return null;
|
45
45
|
} else if((!Auth.isTableDataAllowed({table:tableName}))) return null;
|
46
46
|
content.push(<Cell elevation = {5} withSurface mobileSize={12} desktopSize={3} tabletSize={6} {...contentProps} testID={testID} {...cellProps} style={[contentProps.style,cellProps.style]} key = {index} >
|
47
47
|
<Surface testID = {testID+"_Surface"} elevation = {5} {...itemContainerProps} {...containerProps} style={[theme.styles.w100,styles.itemContainer,itemContainerProps.style,containerProps.style]}>
|
@@ -289,6 +289,7 @@ export default class TableDataScreenComponent extends FormDataScreen{
|
|
289
289
|
currentField.readOnly = true;
|
290
290
|
}
|
291
291
|
});
|
292
|
+
const isPrimary = this.primaryKeyFields[columnField] && true || false;
|
292
293
|
const cArgs = {...rest,field:currentField,columnField,columnDef:currentField,isUpdate:isUpdated,name:columnField,index:i,counterIndex,isPrimary,fields:preparedFields,contex:this,data:this.getCurrentData(),datas,currentIndex,isUpdated,tableName,table};
|
293
294
|
if(isUpdated){
|
294
295
|
//la props readOnlyOnEditing permet de rendre le champ readOnly en cas de mise à jour de la tableData
|
@@ -311,7 +312,6 @@ export default class TableDataScreenComponent extends FormDataScreen{
|
|
311
312
|
if(field.primaryKey ===true){
|
312
313
|
this.primaryKeyFields[columnField] = true;
|
313
314
|
}
|
314
|
-
const isPrimary = this.primaryKeyFields[columnField] && true || false;
|
315
315
|
if(!canRenderActions){
|
316
316
|
currentField.disabled = true;
|
317
317
|
}
|
@@ -14,6 +14,8 @@ const DrawerNavigator = React.forwardRef(({content,children:customChildren,state
|
|
14
14
|
const mergedRefs = React.useMergeRefs(drawerRef,ref);
|
15
15
|
const forceRender = React.useForceRender();
|
16
16
|
const refreshItemsRef = React.useRef(false);
|
17
|
+
const isAuthLoggedIn = Auth.isLoggedIn();
|
18
|
+
const [isLoggedIn,setIsLoggedIn] = React.useState(isAuthLoggedIn);
|
17
19
|
const items = useGetItems({refresh:()=>{
|
18
20
|
if(drawerRef.current && drawerRef.current && drawerRef.current.forceRenderNavigationView){
|
19
21
|
return drawerRef.current.forceRenderNavigationView();
|
@@ -45,8 +47,6 @@ const DrawerNavigator = React.forwardRef(({content,children:customChildren,state
|
|
45
47
|
}
|
46
48
|
return <ProfilAvatar ref={uProfileRef} drawerRef={drawerRef}/>;
|
47
49
|
};
|
48
|
-
const isAuthLoggedIn = Auth.isLoggedIn();
|
49
|
-
const [isLoggedIn,setIsLoggedIn] = React.useState(isAuthLoggedIn);
|
50
50
|
const prevIsLoggedIn = React.usePrevious(isLoggedIn);
|
51
51
|
const navigationViewRef = React.useRef(null);
|
52
52
|
state = defaultObj(state);
|
@@ -16,6 +16,7 @@ import useExpoUI from "$econtext/hooks";
|
|
16
16
|
import Auth,{useIsSignedIn,tableDataPerms} from "$cauth";
|
17
17
|
import {getTableDataListRouteName} from "$enavigation/utils";
|
18
18
|
import {isValidElement,usePrevious} from "$react";
|
19
|
+
import { isPermAllowed } from "$eauth/utils";
|
19
20
|
|
20
21
|
/***** les props supplémentaires à passer aux drawers items d'une table de données sont dans le champ drawerItemProps */
|
21
22
|
const useGetItems = (options)=>{
|
@@ -73,7 +74,7 @@ const useGetItems = (options)=>{
|
|
73
74
|
if(!tableName || table.showInDrawer === false || !Auth.isTableDataAllowed({table:tableName})){
|
74
75
|
return;
|
75
76
|
}
|
76
|
-
if(
|
77
|
+
if(!isPermAllowed(table.perm,{...options,tableName:table,permAction:"drawerItem",tables,table,index})) return;
|
77
78
|
const section = (table.drawerSection).trim();
|
78
79
|
if(!items[section]){
|
79
80
|
if(!sections) sections = Object.keys(items);
|
package/src/navigation/utils.js
CHANGED
@@ -4,6 +4,7 @@
|
|
4
4
|
import {navigate,sanitizeName} from "$cnavigation";
|
5
5
|
import {isNonNullString,defaultStr,defaultObj,isObj} from "$cutils";
|
6
6
|
import appConfig from "$capp/config";
|
7
|
+
import { isPermAllowed } from "$eauth/utils";
|
7
8
|
|
8
9
|
export const tableDataRouteName = 'table-data';
|
9
10
|
|
@@ -35,8 +36,8 @@ const navigateToTableOrStructData = function(tableName,params,actionType){
|
|
35
36
|
let isAllowed = true;
|
36
37
|
actionType = defaultStr(actionType,"tabledata").replaceAll("_","").replaceAll("-","").replaceAll(" ","").toLowerCase();
|
37
38
|
const isTableData = actionType =='tabledata';
|
38
|
-
if(
|
39
|
-
isAllowed =
|
39
|
+
if(perm !== undefined){
|
40
|
+
isAllowed = isPermAllowed(perm,{permAction:"navigate",...params,tableName,table:tableName})
|
40
41
|
} else if(canCheckNavPerms() !== false){
|
41
42
|
if(actionType =='structdata') {
|
42
43
|
isAllowed = Auth.isStructDataAllowed({table:tableName})
|
package/src/pdf/index.js
CHANGED
@@ -10,6 +10,7 @@ import appConfig from "$capp/config";
|
|
10
10
|
import Auth from "$cauth";
|
11
11
|
import DateLib from "$clib/date";
|
12
12
|
import crypToJS from "$clib/crypto-js";
|
13
|
+
import { isPermAllowed } from "$eauth/utils";
|
13
14
|
|
14
15
|
export const QR_CODE_HASH_KEY_PREFIX = defaultStr(appConfig.name).replace(/\s/g, "");
|
15
16
|
export const QR_CODE_HASH_KEY = `${QR_CODE_HASH_KEY_PREFIX}-QR_CODE_HASH_KEY`;//la clé de décryptage du QRCODE
|
@@ -266,14 +267,8 @@ export function printTableData(data,options){
|
|
266
267
|
if(!tablePrint){
|
267
268
|
return Promise.reject({message : `La fonction d'impression n'est pas supportée par la table [${tableText}]`})
|
268
269
|
}
|
269
|
-
if(
|
270
|
-
|
271
|
-
return Promise.reject({message:'Vous n\'etes pas autorisé à imprimer ce type de document'});
|
272
|
-
}
|
273
|
-
} else if(isNonNullString(options.perm)){
|
274
|
-
if(!Auth.isAllowedFromString(options.perm)){
|
275
|
-
return Promise.reject({message:'Vous n\'etes pas autorisé à imprimer ce type de document'});
|
276
|
-
}
|
270
|
+
if((options.perm !== undefined && !isPermAllowed(options.perm,{...options,table,tableObj,permAction:'print',tableName:table,data}))){
|
271
|
+
return Promise.reject({message:'Vous n\'etes pas autorisé à imprimer ce type de document'});
|
277
272
|
} else if(!Auth.isTableDataAllowed({table,action:'print'})){
|
278
273
|
return Promise.reject({message:'Vous n\'etes pas autorisé à imprimer ce type de document'});
|
279
274
|
}
|
@@ -111,14 +111,6 @@ const PermLines = React.forwardRef(({user,gridProps,defaultActions:cDefaultActio
|
|
111
111
|
});
|
112
112
|
|
113
113
|
PermLines.displayName = "AuthPermsLinesComponent";
|
114
|
-
const PermTextType = PropTypes.shape({
|
115
|
-
text : PropTypes.string,//le texte de la permission
|
116
|
-
label : PropTypes.string,
|
117
|
-
title : PropTypes.string, //le tooltip associé à la permission
|
118
|
-
tooltip : PropTypes.string, //alias à title,
|
119
|
-
actions : PropTypes.objectOf(PermTextType),//les actions supportées par la permission
|
120
|
-
defaultAction : PropTypes.bool,//si les actions par défaut seront associés à la permission en cours
|
121
|
-
});
|
122
114
|
|
123
115
|
const permsType = PropTypes.oneOfType([
|
124
116
|
PropTypes.func,PropTypes.object,
|
@@ -15,7 +15,7 @@ import {isValidUrl} from "$cutils";
|
|
15
15
|
import {screenName} from "./utils";
|
16
16
|
import notify from "$notify";
|
17
17
|
import {getAnimationType,setAnimationType,animationTypes} from "$enavigation/animationTypes"
|
18
|
-
import {
|
18
|
+
import { isPermAllowed } from "$eauth/utils";
|
19
19
|
|
20
20
|
export default function UserProfileScreen({fields,...p}){
|
21
21
|
const {auth:{profilePropsMutator}} = useContext();
|
@@ -49,11 +49,8 @@ export default function UserProfileScreen({fields,...p}){
|
|
49
49
|
const {changeElectronAppUrlPerm} = props;
|
50
50
|
const changeElectronUrl = React.useMemo(()=>{
|
51
51
|
if(!isElectron() || !window?.ELECTRON || typeof ELECTRON?.setAppUrl !=='function' || typeof ELECTRON?.getAppUrl !=='function') return false;
|
52
|
-
if(
|
53
|
-
|
54
|
-
} else if(typeof changeElectronAppUrlPerm =='function'){
|
55
|
-
return !!changeElectronAppUrlPerm(props);
|
56
|
-
}
|
52
|
+
if(!isPermAllowed(changeElectronAppUrlPerm,props)) return false;
|
53
|
+
if(changeElectronAppUrlPerm) return true;
|
57
54
|
return Auth.isMasterAdmin();
|
58
55
|
},[changeElectronAppUrlPerm]);
|
59
56
|
const user = defaultObj(props.user,Auth.getLoggedUser());
|
@@ -1 +0,0 @@
|
|
1
|
-
module.exports = require("@fto-consult/expo-ui/webpack.config.js");
|
package/compiler.config.js
DELETED
@@ -1,33 +0,0 @@
|
|
1
|
-
const path = require("path");
|
2
|
-
module.exports = function({config,nodeModulesPath}){
|
3
|
-
const base = process.cwd();
|
4
|
-
const expoUi = path.resolve(require("./expo-ui-path")());
|
5
|
-
nodeModulesPath = Array.isArray(nodeModulesPath)? nodeModulesPath : [];
|
6
|
-
config.resolve.modules = Array.isArray(config.resolve.modules)? config.resolve.modules:[]
|
7
|
-
config.resolve.modules = [path.resolve(base, 'node_modules'),path.resolve(expoUi,"node_modules"),...nodeModulesPath,...config.resolve.modules];
|
8
|
-
config.module.rules.push({
|
9
|
-
test: /\.(js|jsx|ts|tsx)$/,
|
10
|
-
type: "javascript/auto",
|
11
|
-
include: [
|
12
|
-
base,
|
13
|
-
/node_modules\/@fto-consult/,
|
14
|
-
expoUi,
|
15
|
-
],
|
16
|
-
exclude:[
|
17
|
-
/node_modules[/\\](?!react-native-paper|react-native|react-native-vector-icons|react-native-safe-area-view)/,
|
18
|
-
],
|
19
|
-
use: {
|
20
|
-
loader: 'babel-loader',
|
21
|
-
},
|
22
|
-
});
|
23
|
-
config.module.rules.push({
|
24
|
-
test: /\.mjs$/,
|
25
|
-
include: /node_modules/,
|
26
|
-
type: 'javascript/auto',
|
27
|
-
resolve: {
|
28
|
-
fullySpecified: false
|
29
|
-
}
|
30
|
-
});
|
31
|
-
config.plugins.push(require("@fto-consult/common/circular-dependencies"));
|
32
|
-
return config;
|
33
|
-
}
|
package/webpack.config.js
DELETED
@@ -1,82 +0,0 @@
|
|
1
|
-
/**@see : https://www.npmjs.com/package/@expo/webpack-config */
|
2
|
-
const isObj = x => x && typeof x =='object' && !Array.isArray(x);
|
3
|
-
//const webpack = require("webpack");
|
4
|
-
const fs = require("fs");
|
5
|
-
const supportedPlatforms = ["web","electron"];
|
6
|
-
const mainExtensions = [".js", ".jsx",".ts",".tsx",".mjs"];
|
7
|
-
const path = require("path");
|
8
|
-
|
9
|
-
// Expo CLI will await this method so you can optionally return a promise.
|
10
|
-
module.exports = async function(env, argv,opts) {
|
11
|
-
const isLocalDev = require("./is-local-dev")();//si l'application est en developpement local
|
12
|
-
const nodeModulePath = path.resolve(`${process.cwd()}`,"node_modules");
|
13
|
-
const localNodeEuiP = path.resolve(nodeModulePath,"@expo/webpack-config");
|
14
|
-
const wConfigPath = fs.existsSync(localNodeEuiP) && localNodeEuiP || "@expo/webpack-config";
|
15
|
-
const createExpoWebpackConfigAsync = require(wConfigPath);
|
16
|
-
env = env || {};
|
17
|
-
opts = typeof opts =="object" && opts ? opts : {};
|
18
|
-
const babel = isObj(opts.babel)? opts.babel : {};
|
19
|
-
const isElectron = process.env.isElectron || process.env.platform =="electron" || typeof env.platform =="string" && env.platform.toLowerCase().trim() ==='electron';
|
20
|
-
const isNeutralino = process.env.isNeutralino || process.env.platform =="neutralino";
|
21
|
-
if(isElectron || isNeutralino){
|
22
|
-
env.platform = isElectron ? "electron":"neutralino";
|
23
|
-
env.mode = env.mode =="production" && "production" || "development";
|
24
|
-
env.pwa = false;
|
25
|
-
}
|
26
|
-
const platform = isElectron && "electron" || isNeutralino && "neutralino" || process.env.platform && supportedPlatforms.includes(process.platform) && process.platform || typeof opts.platform =="string" && supportedPlatforms.includes(opts.platform)? opts.platform : "web";
|
27
|
-
const transpileModules = Array.isArray(opts.transpileModules)? opts.transpileModules : [];
|
28
|
-
const projectRoot = opts.projectRoot && typeof opts.projectRoot =="string" && fs.existsSync(opts.projectRoot) && opts.projectRoot || process.cwd();
|
29
|
-
const config = await createExpoWebpackConfigAsync(
|
30
|
-
{
|
31
|
-
...env,
|
32
|
-
platform,
|
33
|
-
projectRoot,
|
34
|
-
babel: {
|
35
|
-
...babel,
|
36
|
-
dangerouslyAddModulePathsToTranspile: [
|
37
|
-
// Ensure that all packages starting with @fto-consult are transpiled.
|
38
|
-
'@fto-consult',
|
39
|
-
...transpileModules,
|
40
|
-
],
|
41
|
-
},
|
42
|
-
},
|
43
|
-
argv
|
44
|
-
);
|
45
|
-
config.module.rules.push(
|
46
|
-
{
|
47
|
-
test: /.mjs$/,
|
48
|
-
include: /node_modules/,
|
49
|
-
type: "javascript/auto",
|
50
|
-
use: {loader: 'babel-loader'}
|
51
|
-
});
|
52
|
-
config.mode = (config.mode =="development" || config.mode =='production') ? config.mode : "development";
|
53
|
-
// Maybe you want to turn off compression in dev mode.
|
54
|
-
if (config.mode === 'development') {
|
55
|
-
config.devServer.compress = false;
|
56
|
-
}
|
57
|
-
// Or prevent minimizing the bundle when you build.
|
58
|
-
if (config.mode === 'production') {
|
59
|
-
config.optimization.minimize = true;
|
60
|
-
}
|
61
|
-
config.performance = typeof config.performance =="object" && config.performance ? config.performance : {};
|
62
|
-
config.performance.hints = "hints" in config.performance ? config.performance.hints : false;
|
63
|
-
config.performance.maxEntrypointSize = typeof config.performance.maxEntrypointSize =='number'? config.performance.maxEntrypointSize : 512000;
|
64
|
-
config.performance.maxAssetSize = typeof config.performance.maxAssetSize =='number'? config.performance.maxAssetSize : 512000;
|
65
|
-
config.devtool = (config.mode === 'development') ? 'inline-source-map' : false;
|
66
|
-
require("./compiler.config.js")({config,...opts});
|
67
|
-
const extensions = config.resolve.extensions;
|
68
|
-
if(isElectron || isNeutralino){
|
69
|
-
mainExtensions.map((ex)=>{
|
70
|
-
const nExt = `.${isElectron?"electron":"neu"}${ex}`;
|
71
|
-
if(!extensions.includes(nExt)){
|
72
|
-
extensions.unshift(nExt);
|
73
|
-
}
|
74
|
-
});
|
75
|
-
}
|
76
|
-
config.resolve.fallback = {
|
77
|
-
...Object.assign({},config.resolve.fallback),
|
78
|
-
crypto: require.resolve("crypto-browserify"),
|
79
|
-
stream: require.resolve("stream-browserify"),
|
80
|
-
}
|
81
|
-
return config;
|
82
|
-
};;
|