@onehat/ui 0.4.69 → 0.4.70
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -1358,7 +1358,7 @@ function Form(props) {
|
|
|
1358
1358
|
icon={getEditorMode() === EDITOR_MODE__ADD ? Plus : FloppyDiskRegular}
|
|
1359
1359
|
isDisabled={isSaveDisabled}
|
|
1360
1360
|
className="text-white"
|
|
1361
|
-
text={getEditorMode() === EDITOR_MODE__ADD ? 'Add' : 'Save'}
|
|
1361
|
+
text={(getEditorMode() === EDITOR_MODE__ADD ? 'Add' : 'Save') + (props.record?.length > 1 ? ` (${props.record.length})` : '')}
|
|
1362
1362
|
/>}
|
|
1363
1363
|
|
|
1364
1364
|
{showSubmitBtn &&
|
|
@@ -194,6 +194,7 @@ function GridComponent(props) {
|
|
|
194
194
|
onView,
|
|
195
195
|
onContextMenu,
|
|
196
196
|
isAdding,
|
|
197
|
+
isEditorViewOnly,
|
|
197
198
|
|
|
198
199
|
// withData
|
|
199
200
|
Repository,
|
|
@@ -432,7 +433,7 @@ function GridComponent(props) {
|
|
|
432
433
|
} else {
|
|
433
434
|
let canDoEdit = false,
|
|
434
435
|
canDoView = false;
|
|
435
|
-
if (onEdit && canUser && canUser(EDIT) && (!canRecordBeEdited || canRecordBeEdited(selection)) && !props.disableEdit) {
|
|
436
|
+
if (onEdit && canUser && canUser(EDIT) && (!canRecordBeEdited || canRecordBeEdited(selection)) && !props.disableEdit && !isEditorViewOnly) {
|
|
436
437
|
canDoEdit = true;
|
|
437
438
|
} else
|
|
438
439
|
if (onView && canUser && canUser(VIEW) && !props.disableView) {
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { useMemo, useEffect, } from 'react';
|
|
1
|
+
import { useMemo, useState, useEffect, } from 'react';
|
|
2
2
|
import {
|
|
3
3
|
Box,
|
|
4
4
|
HStack,
|
|
5
5
|
HStackNative,
|
|
6
6
|
Icon,
|
|
7
|
+
Text,
|
|
7
8
|
TextNative,
|
|
8
9
|
} from '@project-components/Gluestack';
|
|
9
10
|
import {
|
|
@@ -16,9 +17,11 @@ import getComponentFromType from '../../Functions/getComponentFromType.js';
|
|
|
16
17
|
import UiGlobals from '../../UiGlobals.js';
|
|
17
18
|
import { withDragSource, withDropTarget } from '../Hoc/withDnd.js';
|
|
18
19
|
import testProps from '../../Functions/testProps.js';
|
|
20
|
+
import Loading from '../Messages/Loading.js';
|
|
19
21
|
import AngleRight from '../Icons/AngleRight.js';
|
|
20
22
|
import RowDragHandle from './RowDragHandle.js';
|
|
21
23
|
import RowSelectHandle from './RowSelectHandle.js';
|
|
24
|
+
import useAsyncRenderers from '../../Hooks/useAsyncRenderers.js';
|
|
22
25
|
import _ from 'lodash';
|
|
23
26
|
|
|
24
27
|
// Conditional import for web only
|
|
@@ -64,7 +67,11 @@ function GridRow(props) {
|
|
|
64
67
|
dropTargetRef,
|
|
65
68
|
...propsToPass
|
|
66
69
|
} = props,
|
|
67
|
-
styles = UiGlobals.styles
|
|
70
|
+
styles = UiGlobals.styles,
|
|
71
|
+
{
|
|
72
|
+
results: asyncResults,
|
|
73
|
+
loading: asyncLoading,
|
|
74
|
+
} = useAsyncRenderers(columnsConfig, item);
|
|
68
75
|
|
|
69
76
|
if (item.isDestroyed) {
|
|
70
77
|
return null;
|
|
@@ -159,21 +166,25 @@ function GridRow(props) {
|
|
|
159
166
|
}
|
|
160
167
|
if (_.isPlainObject(config)) {
|
|
161
168
|
if (config.renderer) {
|
|
162
|
-
const
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
169
|
+
const
|
|
170
|
+
asyncResult = asyncResults.get(key),
|
|
171
|
+
isLoading = asyncLoading.has(key),
|
|
172
|
+
extraProps = _.omit(config, [
|
|
173
|
+
'header',
|
|
174
|
+
'fieldName',
|
|
175
|
+
'type',
|
|
176
|
+
'isEditable',
|
|
177
|
+
'editor',
|
|
178
|
+
'format',
|
|
179
|
+
'renderer',
|
|
180
|
+
'isAsync',
|
|
181
|
+
'isReorderable',
|
|
182
|
+
'isResizable',
|
|
183
|
+
'isSortable',
|
|
184
|
+
'w',
|
|
185
|
+
'flex',
|
|
186
|
+
'isOver',
|
|
187
|
+
]);
|
|
177
188
|
|
|
178
189
|
if (!extraProps._web) {
|
|
179
190
|
extraProps._web = {};
|
|
@@ -185,6 +196,31 @@ function GridRow(props) {
|
|
|
185
196
|
// userSelect: 'none',
|
|
186
197
|
};
|
|
187
198
|
|
|
199
|
+
let content = null;
|
|
200
|
+
if (config.isAsync) {
|
|
201
|
+
// Async renderer
|
|
202
|
+
if (isLoading) {
|
|
203
|
+
content = <Loading />;
|
|
204
|
+
} else if (asyncResult) {
|
|
205
|
+
if (asyncResult.error) {
|
|
206
|
+
content = <Text>Render Error: {asyncResult.error.message || String(asyncResult.error)}</Text>;
|
|
207
|
+
} else {
|
|
208
|
+
content = asyncResult.result;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
} else {
|
|
212
|
+
// Synchronous renderer
|
|
213
|
+
try {
|
|
214
|
+
const result = config.renderer(item);
|
|
215
|
+
if (result && typeof result.then === 'function') {
|
|
216
|
+
content = <Text>Error: Async renderer not properly configured</Text>;
|
|
217
|
+
} else {
|
|
218
|
+
content = result;
|
|
219
|
+
}
|
|
220
|
+
} catch (error) {
|
|
221
|
+
content = <Text>Render Error: {error}</Text>;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
188
224
|
return <HStackNative
|
|
189
225
|
key={key}
|
|
190
226
|
{...testProps('rendererCol-' + key)}
|
|
@@ -192,7 +228,7 @@ function GridRow(props) {
|
|
|
192
228
|
{...propsToPass}
|
|
193
229
|
{...extraProps}
|
|
194
230
|
style={colStyle}
|
|
195
|
-
>{
|
|
231
|
+
>{content}</HStackNative>;
|
|
196
232
|
}
|
|
197
233
|
if (config.fieldName) {
|
|
198
234
|
|
|
@@ -390,6 +426,8 @@ function GridRow(props) {
|
|
|
390
426
|
>{rowContents}</HStackNative>;
|
|
391
427
|
}, [
|
|
392
428
|
columnsConfig,
|
|
429
|
+
asyncResults,
|
|
430
|
+
asyncLoading,
|
|
393
431
|
columnProps,
|
|
394
432
|
fields,
|
|
395
433
|
rowProps,
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { useState, useEffect, } from 'react';
|
|
2
|
+
|
|
3
|
+
export default function useAsyncRenderers(columnsConfig, item) {
|
|
4
|
+
const
|
|
5
|
+
[results, setResults] = useState(new Map()),
|
|
6
|
+
[loading, setLoading] = useState(new Set());
|
|
7
|
+
|
|
8
|
+
useEffect(() => {
|
|
9
|
+
const asyncConfigs = columnsConfig.filter(config =>
|
|
10
|
+
config.renderer && typeof config.renderer === 'function'
|
|
11
|
+
);
|
|
12
|
+
|
|
13
|
+
if (asyncConfigs.length === 0) {
|
|
14
|
+
setResults(new Map());
|
|
15
|
+
setLoading(new Set());
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const newLoading = new Set();
|
|
20
|
+
asyncConfigs.forEach((config, index) => {
|
|
21
|
+
newLoading.add(index);
|
|
22
|
+
});
|
|
23
|
+
setLoading(newLoading);
|
|
24
|
+
|
|
25
|
+
const promises = asyncConfigs.map(async (config, configIndex) => {
|
|
26
|
+
try {
|
|
27
|
+
const result = await config.renderer(item);
|
|
28
|
+
return { configIndex, result, error: null };
|
|
29
|
+
} catch (error) {
|
|
30
|
+
return { configIndex, result: null, error };
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
Promise.allSettled(promises).then(settled => {
|
|
35
|
+
const
|
|
36
|
+
newResults = new Map(),
|
|
37
|
+
newLoading = new Set();
|
|
38
|
+
|
|
39
|
+
settled.forEach((outcome, index) => {
|
|
40
|
+
if (outcome.status === 'fulfilled') {
|
|
41
|
+
const { configIndex, result, error } = outcome.value;
|
|
42
|
+
newResults.set(configIndex, { result, error });
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
setResults(newResults);
|
|
47
|
+
setLoading(newLoading);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
}, [columnsConfig, item]);
|
|
51
|
+
|
|
52
|
+
return { results, loading };
|
|
53
|
+
}
|