@fto-consult/expo-ui 6.15.1 → 6.15.3
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.js +1 -1
- package/package.json +2 -2
- package/src/components/Form/List/List.js +2 -2
- package/src/components/List/Common.js +8 -20
- package/src/components/{Table/List/List.js → List/Virtuoso/index.js} +79 -13
- package/src/components/List/hooks.js +26 -0
- package/src/components/List/index.js +3 -1
- package/src/components/Table/List/index.js +1 -1
- package/src/components/TableLink/index.js +7 -3
- package/src/layouts/Screen/FormData/FormData.js +0 -1
- package/src/layouts/Screen/FormData/List.js +6 -4
- /package/src/components/{Table/List/List.native.js → List/Virtuoso/index.native.js} +0 -0
package/babel.config.js
CHANGED
|
@@ -122,7 +122,7 @@ const generateTableOrStructDataStr = (tableDataPath)=>{
|
|
|
122
122
|
//on génère le fichier getTable des tables data de l'application
|
|
123
123
|
if(getTableJSContent){
|
|
124
124
|
return (`
|
|
125
|
-
|
|
125
|
+
export default function(tableName){
|
|
126
126
|
\tif(!tableName || typeof tableName !=="string") return null;
|
|
127
127
|
\ttableName = tableName.toUpperCase().trim();
|
|
128
128
|
${getTableJSContent}\treturn null;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fto-consult/expo-ui",
|
|
3
|
-
"version": "6.15.
|
|
3
|
+
"version": "6.15.3",
|
|
4
4
|
"description": "Bibliothèque de composants UI Expo,react-native",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
"@emotion/native": "^11.11.0",
|
|
63
63
|
"@expo/html-elements": "^0.5.1",
|
|
64
64
|
"@expo/vector-icons": "^13.0.0",
|
|
65
|
-
"@fto-consult/common": "^3.
|
|
65
|
+
"@fto-consult/common": "^3.23.1",
|
|
66
66
|
"@gorhom/portal": "^1.0.14",
|
|
67
67
|
"@pchmn/expo-material3-theme": "^1.3.1",
|
|
68
68
|
"@react-native-async-storage/async-storage": "1.18.2",
|
|
@@ -10,7 +10,7 @@ import {isPhoneMedia} from "$cplatform/dimensions";
|
|
|
10
10
|
import View from "$ecomponents/View";
|
|
11
11
|
import {StyleSheet} from "react-native";
|
|
12
12
|
import {List} from "react-native-paper";
|
|
13
|
-
import FlashList from "$ecomponents/List";
|
|
13
|
+
import FlashList from "$ecomponents/Table/List";
|
|
14
14
|
import Surface from "$ecomponents/Surface";
|
|
15
15
|
import {navigate} from "$cnavigation";
|
|
16
16
|
import { handleBeforeSaveCallback } from "$ecomponents/Form/FormData/utils";
|
|
@@ -476,7 +476,7 @@ export default class FormListComponent extends AppComponent {
|
|
|
476
476
|
addIconLabel = defaultVal(addIconLabel,"Ajouter un élément");
|
|
477
477
|
addIcon = defaultVal(addIcon,"plus")
|
|
478
478
|
addIconObj = {...onCHandle,icon:addIcon,text:addIconLabel};
|
|
479
|
-
if(isNonNullString(addIcon)) _addIcon = <Icon name={addIcon} size={
|
|
479
|
+
if(isNonNullString(addIcon)) _addIcon = <Icon name={addIcon} size={30} title={'ajouter un élément'}></Icon>;
|
|
480
480
|
if(!React.isValidElement(addIcon)){
|
|
481
481
|
addIcon = _addIcon;
|
|
482
482
|
}
|
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
|
|
2
2
|
import React from "$react";
|
|
3
3
|
import { prepareItems as customPrepareItems,getBToTopRef } from "./utils";
|
|
4
|
-
import
|
|
4
|
+
import {grid,StylePropTypes} from "$theme";
|
|
5
5
|
import PropTypes from "prop-types";
|
|
6
|
-
import {defaultObj,isObj,defaultDecimal,defaultArray,defaultFunc} from "$cutils";
|
|
6
|
+
import {defaultObj,extendObj,isObj,defaultDecimal,defaultArray,defaultFunc} from "$cutils";
|
|
7
7
|
import {isMobileMedia} from "$cplatform/dimensions";
|
|
8
8
|
import BackToTop from "$ecomponents/BackToTop";
|
|
9
9
|
import {FlatList,StyleSheet,View} from "react-native";
|
|
10
10
|
import Label from "$ecomponents/Label";
|
|
11
11
|
import { useWindowDimensions,Dimensions } from "react-native";
|
|
12
|
+
import { useList } from "./hooks";
|
|
12
13
|
|
|
13
14
|
const CommonListComponent = React.forwardRef((props,ref)=>{
|
|
15
|
+
const context = useList(props);
|
|
14
16
|
let {responsive,defaultItemHeight,itemHeight,windowWidth,onRender,componentProps,columnWrapperStyle,onViewableItemsChanged,withFlatListItem,Component,withBackToTop,backToTopRef:customBackToTopRef,withBackToTopButton,onScroll,onScrollEnd,onMount,onUnmount,renderScrollViewWrapper,prepareItems,getItemKey,getKey,keyExtractor,items,filter,renderItem,numColumns,containerProps,bindResizeEvents,...rest} = props;
|
|
15
17
|
withBackToTopButton = withBackToTop === true || withBackToTopButton == true || isMobileMedia()? true : false;
|
|
16
18
|
rest = defaultObj(rest);
|
|
@@ -28,10 +30,7 @@ const CommonListComponent = React.forwardRef((props,ref)=>{
|
|
|
28
30
|
const hasCustomBackToTop = typeof customBackToTopRef == 'function'? true : false;
|
|
29
31
|
const backToTopRef = React.useRef(null);
|
|
30
32
|
const isFlatList = Component === FlatList;
|
|
31
|
-
|
|
32
|
-
const context = {
|
|
33
|
-
itemsRefs : [],
|
|
34
|
-
prepareItems : defaultFunc((prepareItems === false ? (items)=> items:null),prepareItems,customPrepareItems),
|
|
33
|
+
extendObj(context,{
|
|
35
34
|
getKey : typeof keyExtractor =='function'? keyExtractor : typeof getItemKey =='function'? getItemKey : typeof getKey =='function'? getKey : undefined,
|
|
36
35
|
addItemsRefs : function(ref, itemRef){
|
|
37
36
|
context.itemsRefs[itemRef.index] = {
|
|
@@ -130,21 +129,10 @@ const CommonListComponent = React.forwardRef((props,ref)=>{
|
|
|
130
129
|
onBackActionPress : !hasCustomBackToTop ? function(){
|
|
131
130
|
return context?.scrollToTop()
|
|
132
131
|
}: undefined,
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
contextRef.prevItems = React.usePrevious(items);
|
|
136
|
-
const getItems = React.useCallback(()=>{
|
|
137
|
-
if(items === contextRef.prevItems && contextRef.items) {
|
|
138
|
-
return contextRef.items;
|
|
139
|
-
}
|
|
140
|
-
return context.prepareItems(items,filter);
|
|
141
|
-
},[items]);
|
|
132
|
+
})
|
|
133
|
+
|
|
142
134
|
context.listRef = listRef.current;
|
|
143
|
-
|
|
144
|
-
if(!Array.isArray(context.items)){
|
|
145
|
-
console.error(context.items," is not valid list data array",props);
|
|
146
|
-
context.items = [];
|
|
147
|
-
}
|
|
135
|
+
|
|
148
136
|
React.useOnRender(onRender,Math.max(items.length/10 || 0,500));
|
|
149
137
|
React.setRef(ref,context);
|
|
150
138
|
React.useEffect(()=>{
|
|
@@ -2,11 +2,14 @@
|
|
|
2
2
|
// Use of this source code is governed by a BSD-style
|
|
3
3
|
// license that can be found in the LICENSE file.
|
|
4
4
|
|
|
5
|
-
import {Virtuoso} from "react-virtuoso/dist/index.mjs";
|
|
5
|
+
import {Virtuoso,VirtuosoGrid} from "react-virtuoso/dist/index.mjs";
|
|
6
6
|
import React from "$react";
|
|
7
7
|
import PropTypes from "prop-types";
|
|
8
|
-
import {defaultObj,defaultNumber,isDOMElement,isNumber,uniqid,isNonNullString,defaultStr} from "$cutils";
|
|
8
|
+
import {defaultObj,classNames,defaultNumber,isObj,isDOMElement,isNumber,uniqid,isNonNullString,defaultStr} from "$cutils";
|
|
9
9
|
import { View } from "react-native";
|
|
10
|
+
import {useList} from "../hooks";
|
|
11
|
+
import theme,{grid} from "$theme";
|
|
12
|
+
import Dimensions from "$cdimensions";
|
|
10
13
|
|
|
11
14
|
const propTypes = {
|
|
12
15
|
...defaultObj(Virtuoso.propTypes),
|
|
@@ -26,13 +29,17 @@ const propTypes = {
|
|
|
26
29
|
isScrolling : PropTypes.func,
|
|
27
30
|
};
|
|
28
31
|
/***@see : https://virtuoso.dev/virtuoso-api-reference/ */
|
|
29
|
-
const VirtuosoListComponent = React.forwardRef(({
|
|
32
|
+
const VirtuosoListComponent = React.forwardRef(({onRender,listClassName,components,itemProps,windowWidth,numColumns,responsive,testID,renderItem,onEndReached,onLayout,onContentSizeChange,onScroll,isScrolling,estimatedItemSize,onEndReachedThreshold,containerProps,style,autoSizedStyle,...props},ref)=>{
|
|
33
|
+
const Component = React.useMemo(()=>responsive?VirtuosoGrid:Virtuoso,[responsive])
|
|
34
|
+
const context = useList(props);
|
|
35
|
+
itemProps = defaultObj(itemProps);
|
|
36
|
+
const items = context.items;
|
|
30
37
|
const r2 = {};
|
|
31
|
-
|
|
38
|
+
Object.map(Component.propTypes,(_,i)=>{
|
|
32
39
|
if(i in props){
|
|
33
40
|
r2[i] = props[i];
|
|
34
41
|
}
|
|
35
|
-
}
|
|
42
|
+
});
|
|
36
43
|
containerProps = defaultObj(containerProps);
|
|
37
44
|
testID = defaultStr(testID,containerProps.testID,"RN_VirtuosoListComponent");
|
|
38
45
|
const listIdRef = React.useRef(uniqid("virtuoso-list-id"));
|
|
@@ -95,10 +102,20 @@ const VirtuosoListComponent = React.forwardRef(({items,onRender,testID,renderIte
|
|
|
95
102
|
},[]);
|
|
96
103
|
React.useOnRender((a,b,c)=>{
|
|
97
104
|
if(onRender && onRender(a,b,c));
|
|
98
|
-
},Math.max(Array.isArray(items) && items.length/10 || 0,500))
|
|
105
|
+
},Math.max(Array.isArray(items) && items.length/10 || 0,500));
|
|
106
|
+
const listP = responsive ? {
|
|
107
|
+
listClassName : classNames(listClassName,"rn-virtuoso-list",responsive && gridClassName)
|
|
108
|
+
} : {
|
|
109
|
+
atBottomThreshold : typeof onEndReachedThreshold =='number'? onEndReachedThreshold : undefined,
|
|
110
|
+
totalListHeightChanged : (height)=>{
|
|
111
|
+
checkSize();
|
|
112
|
+
},
|
|
113
|
+
defaultItemHeight : typeof estimatedItemSize=='number' && estimatedItemSize || undefined,
|
|
114
|
+
};
|
|
99
115
|
return <View {...containerProps} {...props} style={[{flex:1},containerProps.style,style,autoSizedStyle,{minWidth:'100%',height:'100%',maxWidth:'100%'}]} onLayout={onLayout} testID={testID}>
|
|
100
|
-
<
|
|
116
|
+
<Component
|
|
101
117
|
{...r2}
|
|
118
|
+
{...listP}
|
|
102
119
|
style = {listStyle}
|
|
103
120
|
ref = {listRef}
|
|
104
121
|
data = {items}
|
|
@@ -108,7 +125,6 @@ const VirtuosoListComponent = React.forwardRef(({items,onRender,testID,renderIte
|
|
|
108
125
|
itemContent = {(index)=>{
|
|
109
126
|
return renderItem({index,item:items[index],items})
|
|
110
127
|
}}
|
|
111
|
-
atBottomThreshold = {typeof onEndReachedThreshold =='number'? onEndReachedThreshold : undefined}
|
|
112
128
|
atBottomStateChange = {()=>{
|
|
113
129
|
if(typeof onEndReached =='function'){
|
|
114
130
|
onEndReached();
|
|
@@ -120,16 +136,23 @@ const VirtuosoListComponent = React.forwardRef(({items,onRender,testID,renderIte
|
|
|
120
136
|
return isScrolling(isC);
|
|
121
137
|
}
|
|
122
138
|
}}
|
|
123
|
-
|
|
124
|
-
|
|
139
|
+
components = {{
|
|
140
|
+
Item : responsive ? function(props){return <ItemContainer {...props} style={[itemProps.style,props.style]} numColumns={numColumns}/>} : undefined,
|
|
141
|
+
//List : responsive ? ResponsiveVirtuosoListItemContainer: undefined,
|
|
142
|
+
...defaultObj(components),
|
|
125
143
|
}}
|
|
126
|
-
defaultItemHeight = {typeof estimatedItemSize=='number' && estimatedItemSize || undefined}
|
|
127
144
|
/>
|
|
128
145
|
</View>
|
|
129
146
|
});
|
|
130
147
|
|
|
131
148
|
VirtuosoListComponent.propTypes = {
|
|
132
|
-
...propTypes
|
|
149
|
+
...propTypes,
|
|
150
|
+
numColumns : PropTypes.number,
|
|
151
|
+
items : PropTypes.oneOfType([
|
|
152
|
+
PropTypes.object,
|
|
153
|
+
PropTypes.array,
|
|
154
|
+
PropTypes.func,
|
|
155
|
+
])
|
|
133
156
|
};
|
|
134
157
|
|
|
135
158
|
VirtuosoListComponent.displayName = "VirtuosoListComponent";
|
|
@@ -166,4 +189,47 @@ const normalizeEvent = (e)=>{
|
|
|
166
189
|
},
|
|
167
190
|
timeStamp: Date.now()
|
|
168
191
|
};
|
|
169
|
-
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
function ItemContainer({numColumns,responsive,windowWidth,...props}){
|
|
195
|
+
const width = React.useMemo(()=>{
|
|
196
|
+
if(!numColumns || numColumns <= 1) return undefined;
|
|
197
|
+
if(typeof windowWidth =='number' && windowWidth <=600) return "100%";
|
|
198
|
+
if(Dimensions.isMobileMedia()){
|
|
199
|
+
return "100%";
|
|
200
|
+
}
|
|
201
|
+
return (100/numColumns)+"%";
|
|
202
|
+
},[windowWidth,numColumns]);
|
|
203
|
+
const style = width && {width} || grid.col(windowWidth);
|
|
204
|
+
const dataIntex = "index" in props ? props.index : "data-index" in props ? props["data-index"] : ""
|
|
205
|
+
const dataItemIndex = props["data-item-index"];
|
|
206
|
+
if(isObj(style)){
|
|
207
|
+
style.paddingRight = style.paddingLeft = style.paddingHorizontal = undefined;
|
|
208
|
+
}
|
|
209
|
+
return <View
|
|
210
|
+
testID={`RN_VirtosoGridItem_${dataIntex}-${dataItemIndex}`}
|
|
211
|
+
{...props}
|
|
212
|
+
style = {[style,props.style]}
|
|
213
|
+
/>
|
|
214
|
+
}
|
|
215
|
+
const ResponsiveVirtuosoListItemContainer = React.forwardRef((props,ref)=>{
|
|
216
|
+
return <View ref={ref} testID={"RN_ResponsiveVirtuosoListItemContainer"} {...props} style={[responsiveListStyle,props.style,]}/>
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
export const gridClassName = "rn-virtuoso-responsive-list";
|
|
220
|
+
|
|
221
|
+
const responsiveListStyle = [theme.styles.row,theme.styles.row,theme.styles.flexWrap,theme.styles.justifyContentStart,theme.styles.alignItemsStart]
|
|
222
|
+
ResponsiveVirtuosoListItemContainer.displayName = "ResponsiveVirtuosoListItemContainer";
|
|
223
|
+
|
|
224
|
+
if(typeof document !=='undefined' && document && document?.createElement){
|
|
225
|
+
const gridDomId = "dynamic-virtuoso-grid-styles";
|
|
226
|
+
let style = document.getElementById(gridDomId);
|
|
227
|
+
if(!style){
|
|
228
|
+
style = document.createElement("style");
|
|
229
|
+
}
|
|
230
|
+
style.id = gridDomId;
|
|
231
|
+
style.textContent = `
|
|
232
|
+
.${gridClassName}{display:flex;flex-direction:row;align-items:flex-start;flex-wrap:wrap;justify-content:flex-start;};
|
|
233
|
+
`;
|
|
234
|
+
document.body.appendChild(style);
|
|
235
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import React from "$react";
|
|
2
|
+
import { prepareItems as customPrepareItems} from "./utils";
|
|
3
|
+
import {defaultFunc} from "$cutils";
|
|
4
|
+
|
|
5
|
+
/**** retourne le contexte associé au composant List
|
|
6
|
+
|
|
7
|
+
*/
|
|
8
|
+
export const useList = ({items,filter,prepareItems,...props})=>{
|
|
9
|
+
const contextRef = React.useRef({itemsRefs:[]});
|
|
10
|
+
const context = contextRef.current;
|
|
11
|
+
context.itemsRefs = Array.isArray(context.itemsRefs) && context.itemsRefs || [];
|
|
12
|
+
context.prepareItems = defaultFunc((prepareItems === false ? (items)=> items:null),prepareItems,customPrepareItems);
|
|
13
|
+
contextRef.prevItems = React.usePrevious(items);
|
|
14
|
+
const getItems = React.useCallback(()=>{
|
|
15
|
+
if(items === context.prevItems && context.items) {
|
|
16
|
+
return context.items;
|
|
17
|
+
}
|
|
18
|
+
return context.prepareItems(items,filter);
|
|
19
|
+
},[items]);
|
|
20
|
+
context.items = contextRef.items = prepareItems === false ? items : getItems();
|
|
21
|
+
if(!Array.isArray(context.items)){
|
|
22
|
+
console.error(context.items," is not valid list data array",items,props);
|
|
23
|
+
context.items = [];
|
|
24
|
+
}
|
|
25
|
+
return context;
|
|
26
|
+
}
|
|
@@ -2,7 +2,7 @@ import FlashList from "./FlashList";
|
|
|
2
2
|
|
|
3
3
|
export * from "./utils";
|
|
4
4
|
|
|
5
|
-
export default
|
|
5
|
+
export {default} from "./Virtuoso";
|
|
6
6
|
|
|
7
7
|
export {default as FlatList} from "./FlatList";
|
|
8
8
|
|
|
@@ -10,3 +10,5 @@ export {default as FlashList} from "./FlashList";
|
|
|
10
10
|
|
|
11
11
|
export {default as BigList} from "./BigList";
|
|
12
12
|
|
|
13
|
+
export {default as Virtuoso} from "./Virtuoso";
|
|
14
|
+
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from "$react";
|
|
2
2
|
import {Vertical as AutoSizeVertical} from "$ecomponents/AutoSizer";
|
|
3
|
-
import List from "
|
|
3
|
+
import List from "$ecomponents/List/Virtuoso";
|
|
4
4
|
import {defaultStr,isObj,defaultObj} from "$cutils";
|
|
5
5
|
const normalize = (size)=>{
|
|
6
6
|
if(isObj(size)){
|
|
@@ -15,12 +15,16 @@ import {navigateToTableData} from "$enavigation/utils";
|
|
|
15
15
|
import Auth from "$cauth";
|
|
16
16
|
import fetch from "$capi/fetch";
|
|
17
17
|
import useContext from "$econtext/hooks";
|
|
18
|
+
/***** la fonction fetchForeignData permet de spécifier s'il s'agit d'une données de structure où non
|
|
19
|
+
dans le champ isStructData
|
|
20
|
+
*/
|
|
18
21
|
const TableLinKComponent = React.forwardRef((props,ref)=>{
|
|
19
22
|
const {components:{tableLinkPropsMutator}} = useContext();
|
|
20
|
-
let {disabled,readOnly,labelProps,server,containerProps,perm,id,fetchForeignData,foreignKeyTable,foreignKeyColumn,data,testID,Component,routeName,routeParams,component,primary,triggerProps,onPress,children, ...rest} = tableLinkPropsMutator(props);
|
|
23
|
+
let {disabled,readOnly,labelProps,server,containerProps,isStructData,type,perm,id,fetchForeignData,foreignKeyTable,foreignKeyColumn,data,testID,Component,routeName,routeParams,component,primary,triggerProps,onPress,children, ...rest} = tableLinkPropsMutator(props);
|
|
21
24
|
testID = defaultStr(testID,"RN_TableDataLinkContainer")
|
|
22
25
|
foreignKeyTable = defaultStr(foreignKeyTable).trim();
|
|
23
26
|
foreignKeyColumn = defaultStr(foreignKeyColumn).trim();
|
|
27
|
+
isStructData = isStructData || defaultStr(type).toLowerCase().replaceAll("_","").replaceAll("-","").includes("structdata");
|
|
24
28
|
rest = defaultObj(rest);
|
|
25
29
|
containerProps = defaultObj(containerProps)
|
|
26
30
|
labelProps = defaultObj(labelProps);
|
|
@@ -32,10 +36,10 @@ const TableLinKComponent = React.forwardRef((props,ref)=>{
|
|
|
32
36
|
const pointerEvents = disabled || readOnly ? 'none' : 'auto';
|
|
33
37
|
const onPressLink = (event)=>{
|
|
34
38
|
React.stopEventPropagation(event);
|
|
35
|
-
if((isNonNullString(perm) && !Auth.isAllowedFromString(perm)) || !Auth
|
|
39
|
+
if((isNonNullString(perm) && !Auth.isAllowedFromString(perm)) || !Auth[isStructData?"isStructDataAllowed":"isTableDataAllowed"]({table:foreignKeyTable,action:'read'})){
|
|
36
40
|
return;
|
|
37
41
|
}
|
|
38
|
-
const args = {...React.getOnPressArgs(event),...rest,fetch,foreignKeyTable,foreignKeyColumn,data,id,value:id};
|
|
42
|
+
const args = {...React.getOnPressArgs(event),...rest,type,columnType:type,isStructData,fetch,foreignKeyTable,foreignKeyColumn,data,id,value:id};
|
|
39
43
|
let r = typeof onPress =='function'? onPress(args) : undefined;
|
|
40
44
|
if(r === false) return;
|
|
41
45
|
const cb = (a)=>{
|
|
@@ -28,17 +28,19 @@ export default class FormDataListScreen extends FormData{
|
|
|
28
28
|
,saveAction : typeof saveAction !=='undefined'? saveAction:true,
|
|
29
29
|
});
|
|
30
30
|
}
|
|
31
|
-
createNew (){
|
|
31
|
+
createNew (...p){
|
|
32
32
|
const {show} = this.props;
|
|
33
33
|
if(typeof show =='function'){
|
|
34
|
-
show({...this.props,index:undefined,data:{}});
|
|
34
|
+
return show({...this.props,index:undefined,data:{}});
|
|
35
35
|
}
|
|
36
|
+
return super.createNew(...p)
|
|
36
37
|
}
|
|
37
|
-
doSave2New(args){
|
|
38
|
+
doSave2New(args,...rest){
|
|
38
39
|
const {show} = this.props;
|
|
39
40
|
if(typeof show =='function'){
|
|
40
|
-
show({...args,index:undefined,data:{}});
|
|
41
|
+
return show({...args,index:undefined,data:{}});
|
|
41
42
|
}
|
|
43
|
+
return super.doSave2Close(args,...rest);
|
|
42
44
|
}
|
|
43
45
|
doSave2Close(args){
|
|
44
46
|
return this.close();
|
|
File without changes
|