@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.
Files changed (45) hide show
  1. package/babel.config.alias.js +2 -2
  2. package/babel.config.js +1 -7
  3. package/bin/create-app/App.js +1 -0
  4. package/bin/create-app/app.json +1 -1
  5. package/bin/create-app/dependencies.js +31 -28
  6. package/bin/create-app/devDependencies.js +0 -1
  7. package/bin/create-app.js +2 -3
  8. package/docs/expo-upgrades.txt +1 -0
  9. package/expo-ui-path.js +18 -23
  10. package/metro.config.js +5 -0
  11. package/package.json +5 -15
  12. package/readMe.md +9 -9
  13. package/src/auth/Login.js +16 -7
  14. package/src/auth/utils.js +10 -0
  15. package/src/components/AppBar/utils.js +3 -5
  16. package/src/components/Avatar/AutoHeightImage/cache.js +2 -1
  17. package/src/components/BottomSheet/Sheet.js +5 -5
  18. package/src/components/Chart/appexChart/appexChart.html +23 -23
  19. package/src/components/Datagrid/Accordion/Filters.js +2 -2
  20. package/src/components/Datagrid/Common/Common.js +7 -10
  21. package/src/components/Drawer/DrawerItems/index.js +5 -5
  22. package/src/components/Fab/Group.js +2 -3
  23. package/src/components/Filter/index.js +2 -1
  24. package/src/components/Form/Form.js +2 -1
  25. package/src/components/Form/FormData/DialogProvider.js +2 -2
  26. package/src/components/Form/FormData/FieldContent.js +2 -1
  27. package/src/components/Form/FormData/FormData.js +2 -1
  28. package/src/components/Grid/Cell.js +1 -1
  29. package/src/components/Icon/Checkbox.js +3 -3
  30. package/src/components/Image/index.js +5 -2
  31. package/src/components/Table/Header/index.js +2 -2
  32. package/src/components/Table/index.js +4 -4
  33. package/src/components/TableLink/index.js +4 -7
  34. package/src/context/Provider.js +1 -0
  35. package/src/layouts/DatabaseStatistics/index.js +3 -3
  36. package/src/layouts/Screen/TableData.js +1 -1
  37. package/src/navigation/Drawer/index.js +2 -2
  38. package/src/navigation/Drawer/items/index.js +2 -1
  39. package/src/navigation/utils.js +3 -2
  40. package/src/pdf/index.js +3 -8
  41. package/src/screens/Auth/PermLines.js +0 -8
  42. package/src/screens/Auth/Profile.js +3 -6
  43. package/bin/create-app/webpack.config.js +0 -1
  44. package/compiler.config.js +0 -33
  45. 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
- const testID = defaultStr(testID,"RN_AccordionFilters");
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 {isWeb,isMobileNative} from "$cplatform";
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 = checkPerm(renderChartIsAllowed,pArgs)
210
- const ePDFIsAllowed = !isMobileNative() && checkPerm(exportToPDFIsAllowed,pArgs);
211
- const eExcelISAllowed = checkPerm(exportToExcelIsAllowed,pArgs);
212
- const renderSectionListIsAllowedP = checkPerm(renderSectionListIsAllowed,pArgs);
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 = dS === false ? null : typeof this.props.dataSourceSelector ==='function'? this.props.dataSourceSelector({
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 Auth from "$cauth";
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(isNonNullString(item.perm) && !Auth.isAllowedFromStr(item.perm)) return null;
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 = ({item,minimized,renderExpandableOrSection,index,key})=>{
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(isNonNullString(item.perm) && !Auth.isAllowedFromStr(item.perm)) return null;
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 {isAllowedFromStr} from "$cauth/perms";
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(typeof isAllowed =='function' && isAllowed() === false) return null;
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
- const responsiveProps = Object.assign({},responsiveProps);
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(isNonNullString(this.props.perm) && !Auth.isAllowedFromStr(this.props.perm)){
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
- const {closeAction} = props;
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
- const closeAction = defaultObj(closeAction);
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 || (isNonNullString(perm) && !Auth.isAllowedFromStr(perm))){
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 : isNonNullString(this.props.perm) ? Auth.isAllowedFromStr(this.props.perm) : true
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 elevation == "number"? elevation : withSurface ? 5 : undefined;
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 = defaultStr(checkedIcon,CHECKED_ICON);
12
- const uncheckedIcon = defaultStr(uncheckedIcon,UNCHECKED_ICON);
13
- const [checked,setIsChecked] = React.useState(!!checked);
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(r," triing to resolve image asset from source ",source)
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 emptyContent = <View onRender={onComponentRender} testID={testID+"_EmptyData"} style={styles.hasNotData}>
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((isNonNullString(perm))){
54
- if(!Auth.isAllowedFromString(perm))return false;
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)=>{
@@ -1,3 +1,4 @@
1
+ import "@expo/metro-runtime";
1
2
  import "$session";
2
3
  import React from "$react";
3
4
  import appConfig from "$capp/config";
@@ -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(!Auth.isAllowedFromStr(chartAllowedPerm)) return null;
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(isNonNullString(table.perm) && !Auth.isAllowedFromStr(table.perm)) return;
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);
@@ -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(isNonNullString(perm)){
39
- isAllowed = Auth.isAllowedFromStr(perm)
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(typeof options.perm =="function"){
270
- if(!options.perm({table,tableObj})) {
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 {isWeb} from "$cplatform";
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(typeof changeElectronAppUrlPerm ==='string'){
53
- return Auth.isAllowedFromStr(changeElectronAppUrlPerm);
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");
@@ -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
- };;