@abtnode/ux 1.16.17-beta-4f13d99d → 1.16.17-beta-5d4664f8
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/es/blocklet/component/add.js +5 -1
- package/es/blocklet/publish/create-release.js +19 -30
- package/es/blocklet/publish/resource.js +129 -22
- package/es/blocklet/publish/tree.js +235 -0
- package/lib/blocklet/component/add.js +5 -1
- package/lib/blocklet/publish/create-release.js +20 -27
- package/lib/blocklet/publish/resource.js +115 -20
- package/lib/blocklet/publish/tree.js +199 -0
- package/package.json +15 -15
|
@@ -1070,13 +1070,17 @@ export default function AddComponent({
|
|
|
1070
1070
|
overflow: 'hidden',
|
|
1071
1071
|
textOverflow: 'ellipsis',
|
|
1072
1072
|
whiteSpace: 'nowrap',
|
|
1073
|
+
minWidth: '140px',
|
|
1073
1074
|
maxWidth: '280px',
|
|
1074
|
-
|
|
1075
|
+
textAlign: 'center'
|
|
1075
1076
|
},
|
|
1076
1077
|
children: /*#__PURE__*/_jsxs(Box, {
|
|
1077
1078
|
display: "flex",
|
|
1078
1079
|
alignItems: "center",
|
|
1079
1080
|
children: [(typeof step.loading === 'boolean' ? step.loading : loading) && /*#__PURE__*/_jsx(Spinner, {
|
|
1081
|
+
style: {
|
|
1082
|
+
marginRight: 8
|
|
1083
|
+
},
|
|
1080
1084
|
size: 16
|
|
1081
1085
|
}), step.confirm]
|
|
1082
1086
|
})
|
|
@@ -16,8 +16,8 @@ import InputAdornment from '@mui/material/InputAdornment';
|
|
|
16
16
|
import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
|
|
17
17
|
import Button from '@arcblock/ux/lib/Button';
|
|
18
18
|
import Toast from '@arcblock/ux/lib/Toast';
|
|
19
|
-
import Tabs from '@arcblock/ux/lib/Tabs';
|
|
20
19
|
import Empty from '@arcblock/ux/lib/Empty';
|
|
20
|
+
import Tabs from '@arcblock/ux/lib/Tabs';
|
|
21
21
|
import { PROJECT } from '@blocklet/constant';
|
|
22
22
|
import { WELLKNOWN_SERVICE_PATH_PREFIX } from '@abtnode/constant';
|
|
23
23
|
import BlockletBundleAvatar from '../bundle-avatar';
|
|
@@ -79,7 +79,6 @@ const addComponentTabs = ({
|
|
|
79
79
|
const key = blocklet.meta.did;
|
|
80
80
|
tabs.push({
|
|
81
81
|
label: /*#__PURE__*/_jsxs(Box, {
|
|
82
|
-
ml: -4,
|
|
83
82
|
display: "flex",
|
|
84
83
|
alignItems: "center",
|
|
85
84
|
justifyContent: "flex-start",
|
|
@@ -88,7 +87,7 @@ const addComponentTabs = ({
|
|
|
88
87
|
blocklet: blocklet,
|
|
89
88
|
ancestors: ancestors
|
|
90
89
|
}), /*#__PURE__*/_jsx(Box, {
|
|
91
|
-
ml: "
|
|
90
|
+
ml: "4px",
|
|
92
91
|
className: "text",
|
|
93
92
|
children: /*#__PURE__*/_jsx(Box, {
|
|
94
93
|
children: blocklet.meta.title
|
|
@@ -129,7 +128,7 @@ export default function CreateRelease({
|
|
|
129
128
|
const releaseId = inputReleaseId === 'create' ? '' : inputReleaseId;
|
|
130
129
|
const mode = inputReleaseId === 'create' ? 'create' : 'edit';
|
|
131
130
|
const tabs = [];
|
|
132
|
-
const resourceComponents = (blocklet?.children || []).filter(x => x.meta.capabilities.
|
|
131
|
+
const resourceComponents = (blocklet?.children || []).filter(x => x.meta.capabilities.resourceExportApi);
|
|
133
132
|
resourceComponents.forEach(item => {
|
|
134
133
|
addComponentTabs({
|
|
135
134
|
tabs,
|
|
@@ -340,6 +339,7 @@ export default function CreateRelease({
|
|
|
340
339
|
autoComplete: "off",
|
|
341
340
|
variant: "outlined",
|
|
342
341
|
fullWidth: true,
|
|
342
|
+
required: true,
|
|
343
343
|
value: params.blockletTitle || '',
|
|
344
344
|
onChange: e => {
|
|
345
345
|
setParamsErrTip({
|
|
@@ -358,6 +358,7 @@ export default function CreateRelease({
|
|
|
358
358
|
'data-cy': 'blocklet-description',
|
|
359
359
|
readOnly
|
|
360
360
|
},
|
|
361
|
+
required: true,
|
|
361
362
|
autoComplete: "off",
|
|
362
363
|
variant: "outlined",
|
|
363
364
|
fullWidth: true,
|
|
@@ -420,6 +421,7 @@ export default function CreateRelease({
|
|
|
420
421
|
flex: 1
|
|
421
422
|
},
|
|
422
423
|
children: [/*#__PURE__*/_jsx(TextField, {
|
|
424
|
+
required: true,
|
|
423
425
|
label: `Blocklet ${t('common.version')}`,
|
|
424
426
|
placeholder: `Blocklet ${t('common.version')}`,
|
|
425
427
|
InputProps: {
|
|
@@ -455,6 +457,7 @@ export default function CreateRelease({
|
|
|
455
457
|
fullWidth: true,
|
|
456
458
|
multiline: true,
|
|
457
459
|
minRows: 4,
|
|
460
|
+
required: true,
|
|
458
461
|
value: params.note,
|
|
459
462
|
onChange: e => {
|
|
460
463
|
setParamsErrTip({
|
|
@@ -608,27 +611,27 @@ export default function CreateRelease({
|
|
|
608
611
|
display: "flex",
|
|
609
612
|
mt: 3,
|
|
610
613
|
className: "section full-width",
|
|
611
|
-
children: [/*#__PURE__*/
|
|
614
|
+
children: [/*#__PURE__*/_jsx(Box, {
|
|
612
615
|
className: "left",
|
|
613
|
-
children:
|
|
616
|
+
children: /*#__PURE__*/_jsx(Typography, {
|
|
614
617
|
variant: "h3",
|
|
615
618
|
children: t('blocklet.publish.resourceTitle')
|
|
616
|
-
})
|
|
619
|
+
})
|
|
620
|
+
}), /*#__PURE__*/_jsxs(Box, {
|
|
621
|
+
sx: {
|
|
622
|
+
flex: 1
|
|
623
|
+
},
|
|
624
|
+
children: [/*#__PURE__*/_jsx(Tabs, {
|
|
617
625
|
tabs: tabs,
|
|
618
626
|
current: tab,
|
|
619
|
-
orientation: "vertical",
|
|
620
627
|
onChange: onTabChange,
|
|
621
628
|
sx: {
|
|
622
|
-
|
|
629
|
+
ml: -2,
|
|
630
|
+
mt: -1.5
|
|
623
631
|
}
|
|
624
|
-
})
|
|
625
|
-
}), /*#__PURE__*/_jsx(Box, {
|
|
626
|
-
sx: {
|
|
627
|
-
flex: 1
|
|
628
|
-
},
|
|
629
|
-
children: /*#__PURE__*/_jsx(Box, {
|
|
632
|
+
}), /*#__PURE__*/_jsx(Box, {
|
|
630
633
|
children: resourceContent
|
|
631
|
-
})
|
|
634
|
+
})]
|
|
632
635
|
})]
|
|
633
636
|
})]
|
|
634
637
|
})]
|
|
@@ -694,20 +697,6 @@ const Main = styled.div`
|
|
|
694
697
|
flex-shrink: 0;
|
|
695
698
|
width: 140px;
|
|
696
699
|
}
|
|
697
|
-
.MuiTabs-root {
|
|
698
|
-
margin-top: 8px;
|
|
699
|
-
transform: translateX(-16px);
|
|
700
|
-
.MuiButtonBase-root .text {
|
|
701
|
-
color: ${({
|
|
702
|
-
theme
|
|
703
|
-
}) => theme.palette.text.primary};
|
|
704
|
-
}
|
|
705
|
-
.MuiButtonBase-root.Mui-selected .text {
|
|
706
|
-
color: ${({
|
|
707
|
-
theme
|
|
708
|
-
}) => theme.palette.primary.main};
|
|
709
|
-
}
|
|
710
|
-
}
|
|
711
700
|
.MuiTabs-indicator {
|
|
712
701
|
display: none;
|
|
713
702
|
}
|
|
@@ -1,12 +1,35 @@
|
|
|
1
|
-
|
|
2
|
-
/* eslint-disable react/no-unstable-nested-components */
|
|
3
|
-
import { useState, useRef, useEffect } from 'react';
|
|
1
|
+
import { useState, useEffect, useMemo } from 'react';
|
|
4
2
|
import PropTypes from 'prop-types';
|
|
5
3
|
import styled from '@emotion/styled';
|
|
6
|
-
import
|
|
4
|
+
import difference from 'lodash/difference';
|
|
7
5
|
import joinUrl from 'url-join';
|
|
6
|
+
import Box from '@mui/material/Box';
|
|
8
7
|
import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
|
|
8
|
+
import Button from '@arcblock/ux/lib/Button';
|
|
9
|
+
import Toast from '@arcblock/ux/lib/Toast';
|
|
10
|
+
import Tree from './tree';
|
|
11
|
+
import { useNodeContext } from '../../contexts/node';
|
|
12
|
+
import { axios } from '../../util/api';
|
|
9
13
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
14
|
+
import { jsxs as _jsxs } from "react/jsx-runtime";
|
|
15
|
+
const fillParent = (nodes, parentId) => {
|
|
16
|
+
nodes.forEach(node => {
|
|
17
|
+
if (parentId) {
|
|
18
|
+
node.parent = parentId;
|
|
19
|
+
}
|
|
20
|
+
(node.children || []).forEach(child => {
|
|
21
|
+
child.parent = node.id;
|
|
22
|
+
fillParent(child.children || [], child.id);
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
return nodes;
|
|
26
|
+
};
|
|
27
|
+
const checkDiff = (a, b) => {
|
|
28
|
+
if (a.length !== b.length) {
|
|
29
|
+
return true;
|
|
30
|
+
}
|
|
31
|
+
return !!difference(a, b || []).length;
|
|
32
|
+
};
|
|
10
33
|
export default function Resource({
|
|
11
34
|
app,
|
|
12
35
|
component,
|
|
@@ -17,20 +40,81 @@ export default function Resource({
|
|
|
17
40
|
t,
|
|
18
41
|
locale
|
|
19
42
|
} = useLocaleContext();
|
|
20
|
-
const
|
|
43
|
+
const {
|
|
44
|
+
api
|
|
45
|
+
} = useNodeContext();
|
|
46
|
+
const [resources, setResources] = useState([]);
|
|
47
|
+
const [selectedResourceIds, setSelectedResourceIds] = useState([]);
|
|
48
|
+
const [savedResourceIds, setSavedResourceIds] = useState([]);
|
|
49
|
+
const [loading, setLoading] = useState(false);
|
|
21
50
|
const releaseId = release.id;
|
|
22
51
|
const readonly = release.status === 'published';
|
|
23
52
|
const {
|
|
24
|
-
|
|
53
|
+
resourceExportApi = '/'
|
|
25
54
|
} = component?.meta.capabilities || {};
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
55
|
+
const hasDiff = useMemo(() => checkDiff(savedResourceIds, selectedResourceIds), [savedResourceIds, selectedResourceIds]);
|
|
56
|
+
const urlObj = new URL(joinUrl('http://127.0.0.1', component.mountPoint, resourceExportApi || '/').replace(/\/+/g, '/'));
|
|
57
|
+
urlObj.searchParams.set('projectId', projectId);
|
|
58
|
+
urlObj.searchParams.set('releaseId', releaseId);
|
|
59
|
+
urlObj.searchParams.set('local', locale);
|
|
60
|
+
const url = `${urlObj.pathname}${urlObj.search}`;
|
|
61
|
+
const saveSelected = async data => {
|
|
62
|
+
try {
|
|
63
|
+
await api.updateSelectedResources({
|
|
64
|
+
input: {
|
|
65
|
+
did: app.meta.did,
|
|
66
|
+
projectId,
|
|
67
|
+
releaseId,
|
|
68
|
+
componentDid: component.meta.did,
|
|
69
|
+
resources: data
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
setSavedResourceIds(data);
|
|
73
|
+
} catch (err) {
|
|
74
|
+
Toast.error(err.message);
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
const onSave = async () => {
|
|
78
|
+
const params = selectedResourceIds;
|
|
79
|
+
try {
|
|
80
|
+
setLoading(true);
|
|
81
|
+
await axios.post(url, {
|
|
82
|
+
resources: params,
|
|
83
|
+
projectId,
|
|
84
|
+
releaseId,
|
|
85
|
+
locale
|
|
86
|
+
});
|
|
87
|
+
Toast.success(t('common.saveSuccess'));
|
|
88
|
+
setLoading(false);
|
|
89
|
+
saveSelected(selectedResourceIds);
|
|
90
|
+
} catch (err) {
|
|
91
|
+
setLoading(false);
|
|
92
|
+
Toast.error(err.message);
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
useEffect(() => {
|
|
96
|
+
axios.get(url).then(res => {
|
|
97
|
+
const tree = fillParent(res.data?.resources || []);
|
|
98
|
+
setResources(tree);
|
|
99
|
+
}).catch(err => {
|
|
100
|
+
Toast.error(err.message);
|
|
101
|
+
});
|
|
102
|
+
api.getSelectedResources({
|
|
103
|
+
input: {
|
|
104
|
+
did: app.meta.did,
|
|
105
|
+
projectId,
|
|
106
|
+
releaseId,
|
|
107
|
+
componentDid: component.meta.did
|
|
108
|
+
}
|
|
109
|
+
}).then(res => {
|
|
110
|
+
const list = res?.resources || [];
|
|
111
|
+
setSelectedResourceIds(list);
|
|
112
|
+
setSavedResourceIds(list);
|
|
113
|
+
}).catch(err => {
|
|
114
|
+
Toast.error(err.message);
|
|
115
|
+
});
|
|
116
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
117
|
+
}, [url]);
|
|
34
118
|
if (component.status !== 'running') {
|
|
35
119
|
return /*#__PURE__*/_jsx(Container, {
|
|
36
120
|
children: /*#__PURE__*/_jsx(Box, {
|
|
@@ -42,12 +126,23 @@ export default function Resource({
|
|
|
42
126
|
});
|
|
43
127
|
}
|
|
44
128
|
return /*#__PURE__*/_jsx(Container, {
|
|
45
|
-
children: /*#__PURE__*/
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
129
|
+
children: /*#__PURE__*/_jsxs(Box, {
|
|
130
|
+
children: [/*#__PURE__*/_jsx(Tree, {
|
|
131
|
+
data: resources,
|
|
132
|
+
value: selectedResourceIds,
|
|
133
|
+
onChange: data => {
|
|
134
|
+
setSelectedResourceIds(data);
|
|
135
|
+
},
|
|
136
|
+
disabled: loading || readonly
|
|
137
|
+
}), !readonly && /*#__PURE__*/_jsx(Box, {
|
|
138
|
+
className: "footer",
|
|
139
|
+
children: /*#__PURE__*/_jsx(Button, {
|
|
140
|
+
variant: "contained",
|
|
141
|
+
disabled: loading || !hasDiff,
|
|
142
|
+
onClick: () => onSave(),
|
|
143
|
+
children: t('common.save')
|
|
144
|
+
})
|
|
145
|
+
})]
|
|
51
146
|
})
|
|
52
147
|
});
|
|
53
148
|
}
|
|
@@ -66,7 +161,19 @@ Resource.defaultProps = {
|
|
|
66
161
|
}
|
|
67
162
|
};
|
|
68
163
|
const Container = styled(Box)`
|
|
69
|
-
|
|
70
|
-
|
|
164
|
+
border: 1px solid #ccc;
|
|
165
|
+
border-radius: 4px;
|
|
166
|
+
padding: 16px;
|
|
167
|
+
padding-bottom: 0px;
|
|
168
|
+
max-height: 600px;
|
|
169
|
+
overflow-y: auto;
|
|
170
|
+
.footer {
|
|
171
|
+
border-top: 1px solid #ddd;
|
|
172
|
+
display: flex;
|
|
173
|
+
padding: 12px 0;
|
|
174
|
+
margin-top: 12px;
|
|
175
|
+
position: sticky;
|
|
176
|
+
bottom: 0;
|
|
177
|
+
background: #fff;
|
|
71
178
|
}
|
|
72
179
|
`;
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
import PropTypes from 'prop-types';
|
|
2
|
+
import styled from '@emotion/styled';
|
|
3
|
+
import classnames from 'classnames';
|
|
4
|
+
import isUrl from 'is-url';
|
|
5
|
+
import Box from '@mui/material/Box';
|
|
6
|
+
import FormControlLabel from '@mui/material/FormControlLabel';
|
|
7
|
+
import TreeView from '@mui/lab/TreeView';
|
|
8
|
+
import TreeItem from '@mui/lab/TreeItem';
|
|
9
|
+
import Checkbox from '@mui/material/Checkbox';
|
|
10
|
+
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
|
|
11
|
+
import ChevronRightIcon from '@mui/icons-material/ChevronRight';
|
|
12
|
+
import OpenInNewIcon from '@mui/icons-material/OpenInNew';
|
|
13
|
+
import { Icon } from '@iconify/react';
|
|
14
|
+
|
|
15
|
+
// BFS algorithm to find node by his ID
|
|
16
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
17
|
+
import { jsxs as _jsxs } from "react/jsx-runtime";
|
|
18
|
+
const bfsSearch = (graph, targetId) => {
|
|
19
|
+
const queue = [...graph];
|
|
20
|
+
while (queue.length > 0) {
|
|
21
|
+
const currNode = queue.shift();
|
|
22
|
+
if (currNode.id === targetId) {
|
|
23
|
+
return currNode;
|
|
24
|
+
}
|
|
25
|
+
if (currNode.children) {
|
|
26
|
+
queue.push(...currNode.children);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return []; // Target node not found
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
function ResourceIcon({
|
|
33
|
+
icon
|
|
34
|
+
}) {
|
|
35
|
+
if (!icon) {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
if (isUrl(icon)) {
|
|
39
|
+
return /*#__PURE__*/_jsx("img", {
|
|
40
|
+
className: "resource-icon",
|
|
41
|
+
src: icon,
|
|
42
|
+
alt: "icon"
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
return /*#__PURE__*/_jsx(Icon, {
|
|
46
|
+
className: "resource-icon",
|
|
47
|
+
icon: icon
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
ResourceIcon.propTypes = {
|
|
51
|
+
icon: PropTypes.string
|
|
52
|
+
};
|
|
53
|
+
ResourceIcon.defaultProps = {
|
|
54
|
+
icon: ''
|
|
55
|
+
};
|
|
56
|
+
export default function Tree({
|
|
57
|
+
disabled,
|
|
58
|
+
data,
|
|
59
|
+
onChange,
|
|
60
|
+
value
|
|
61
|
+
}) {
|
|
62
|
+
const selectedNodes = value;
|
|
63
|
+
|
|
64
|
+
// Retrieve all ids from node to his children's
|
|
65
|
+
function getAllIds(node, idList = []) {
|
|
66
|
+
idList.push(node.id);
|
|
67
|
+
if (node.children) {
|
|
68
|
+
node.children.forEach(child => getAllIds(child, idList));
|
|
69
|
+
}
|
|
70
|
+
return idList;
|
|
71
|
+
}
|
|
72
|
+
// Get IDs of all children from specific node
|
|
73
|
+
const getAllChild = id => {
|
|
74
|
+
return getAllIds(bfsSearch(data, id));
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
// Get all father IDs from specific node
|
|
78
|
+
const getAllFathers = (id, list = []) => {
|
|
79
|
+
const node = bfsSearch(data, id);
|
|
80
|
+
if (node.parent) {
|
|
81
|
+
list.push(node.parent);
|
|
82
|
+
return getAllFathers(node.parent, list);
|
|
83
|
+
}
|
|
84
|
+
return list;
|
|
85
|
+
};
|
|
86
|
+
function isAllChildrenChecked(node, list) {
|
|
87
|
+
const allChild = getAllChild(node.id);
|
|
88
|
+
const nodeIdIndex = allChild.indexOf(node.id);
|
|
89
|
+
allChild.splice(nodeIdIndex, 1);
|
|
90
|
+
return allChild.every(nodeId => selectedNodes.concat(list).includes(nodeId));
|
|
91
|
+
}
|
|
92
|
+
const handleNodeSelect = (event, nodeId) => {
|
|
93
|
+
event.stopPropagation();
|
|
94
|
+
const allChild = getAllChild(nodeId);
|
|
95
|
+
const fathers = getAllFathers(nodeId);
|
|
96
|
+
if (selectedNodes.includes(nodeId)) {
|
|
97
|
+
// Need to de-check
|
|
98
|
+
const newValue = selectedNodes.filter(id => !allChild.concat(fathers).includes(id));
|
|
99
|
+
onChange(newValue);
|
|
100
|
+
} else {
|
|
101
|
+
// Need to check
|
|
102
|
+
const ToBeChecked = allChild;
|
|
103
|
+
for (let i = 0; i < fathers.length; ++i) {
|
|
104
|
+
if (isAllChildrenChecked(bfsSearch(data, fathers[i]), ToBeChecked)) {
|
|
105
|
+
ToBeChecked.push(fathers[i]);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
onChange([...selectedNodes].concat(ToBeChecked));
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
const stopExpand = event => {
|
|
112
|
+
// prevent the click event from propagating to the checkbox
|
|
113
|
+
event.stopPropagation();
|
|
114
|
+
};
|
|
115
|
+
const hadChildren = data.some(node => node.children?.length > 0);
|
|
116
|
+
const renderTree = node => /*#__PURE__*/_jsx(TreeItem, {
|
|
117
|
+
nodeId: node.id,
|
|
118
|
+
label: /*#__PURE__*/_jsx(FormControlLabel, {
|
|
119
|
+
onClick: stopExpand,
|
|
120
|
+
control: /*#__PURE__*/_jsx(Checkbox, {
|
|
121
|
+
size: "small",
|
|
122
|
+
checked: selectedNodes.indexOf(node.id) !== -1,
|
|
123
|
+
tabIndex: -1,
|
|
124
|
+
disableRipple: true,
|
|
125
|
+
onClick: event => handleNodeSelect(event, node.id),
|
|
126
|
+
disabled: disabled
|
|
127
|
+
}),
|
|
128
|
+
label: /*#__PURE__*/_jsxs(Box, {
|
|
129
|
+
className: "content",
|
|
130
|
+
children: [/*#__PURE__*/_jsxs(Box, {
|
|
131
|
+
display: "flex",
|
|
132
|
+
alignItems: "center",
|
|
133
|
+
children: [node.icon && /*#__PURE__*/_jsx(ResourceIcon, {
|
|
134
|
+
icon: node.icon
|
|
135
|
+
}), /*#__PURE__*/_jsx(Box, {
|
|
136
|
+
className: "name",
|
|
137
|
+
children: node.name
|
|
138
|
+
}), node.url && /*#__PURE__*/_jsx("a", {
|
|
139
|
+
href: node.url,
|
|
140
|
+
target: "_blank",
|
|
141
|
+
rel: "noreferrer",
|
|
142
|
+
className: "link",
|
|
143
|
+
children: /*#__PURE__*/_jsx(OpenInNewIcon, {
|
|
144
|
+
className: "link-icon"
|
|
145
|
+
})
|
|
146
|
+
})]
|
|
147
|
+
}), !!node.description && /*#__PURE__*/_jsx(Box, {
|
|
148
|
+
className: "description",
|
|
149
|
+
children: node.description
|
|
150
|
+
})]
|
|
151
|
+
})
|
|
152
|
+
}),
|
|
153
|
+
children: Array.isArray(node.children) ? node.children.map(renderTree) : null
|
|
154
|
+
}, node.id);
|
|
155
|
+
return /*#__PURE__*/_jsx(StyledTreeView, {
|
|
156
|
+
className: classnames(!hadChildren && 'no-children'),
|
|
157
|
+
multiSelect: true,
|
|
158
|
+
defaultCollapseIcon: /*#__PURE__*/_jsx(ExpandMoreIcon, {}),
|
|
159
|
+
defaultExpandIcon: /*#__PURE__*/_jsx(ChevronRightIcon, {}),
|
|
160
|
+
selected: selectedNodes,
|
|
161
|
+
children: data.map(node => renderTree(node))
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
Tree.propTypes = {
|
|
165
|
+
data: PropTypes.array,
|
|
166
|
+
value: PropTypes.array,
|
|
167
|
+
onChange: PropTypes.func,
|
|
168
|
+
disabled: PropTypes.bool
|
|
169
|
+
};
|
|
170
|
+
Tree.defaultProps = {
|
|
171
|
+
data: [],
|
|
172
|
+
value: [],
|
|
173
|
+
onChange: () => {},
|
|
174
|
+
disabled: false
|
|
175
|
+
};
|
|
176
|
+
const StyledTreeView = styled(TreeView)`
|
|
177
|
+
&.no-children {
|
|
178
|
+
.MuiTreeItem-content {
|
|
179
|
+
padding: 0;
|
|
180
|
+
.MuiTreeItem-iconContainer {
|
|
181
|
+
display: none;
|
|
182
|
+
}
|
|
183
|
+
.MuiTreeItem-label {
|
|
184
|
+
padding-left: 0;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
.MuiTreeItem-content {
|
|
189
|
+
align-items: flex-start;
|
|
190
|
+
.MuiTreeItem-iconContainer {
|
|
191
|
+
transform: translateY(10px);
|
|
192
|
+
}
|
|
193
|
+
&.Mui-selected {
|
|
194
|
+
background-color: transparent;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
.MuiTreeItem-label {
|
|
198
|
+
cursor: default;
|
|
199
|
+
}
|
|
200
|
+
.MuiFormControlLabel-root {
|
|
201
|
+
align-items: flex-start;
|
|
202
|
+
}
|
|
203
|
+
.content {
|
|
204
|
+
padding-top: 6px;
|
|
205
|
+
}
|
|
206
|
+
.name {
|
|
207
|
+
font-size: 16px;
|
|
208
|
+
font-weight: 700;
|
|
209
|
+
}
|
|
210
|
+
.resource-icon {
|
|
211
|
+
margin-right: 2px;
|
|
212
|
+
font-size: 16px;
|
|
213
|
+
}
|
|
214
|
+
img.resource-icon {
|
|
215
|
+
width: 1rem;
|
|
216
|
+
height: 1rem;
|
|
217
|
+
}
|
|
218
|
+
.link {
|
|
219
|
+
margin-left: 8px;
|
|
220
|
+
font-size: 16px;
|
|
221
|
+
color: ${({
|
|
222
|
+
theme
|
|
223
|
+
}) => theme.palette.primary.main};
|
|
224
|
+
display: flex;
|
|
225
|
+
}
|
|
226
|
+
.link-icon {
|
|
227
|
+
font-size: inherit;
|
|
228
|
+
}
|
|
229
|
+
.description {
|
|
230
|
+
font-size: 14px;
|
|
231
|
+
color: ${({
|
|
232
|
+
theme
|
|
233
|
+
}) => theme.palette.text.secondary};
|
|
234
|
+
}
|
|
235
|
+
`;
|
|
@@ -1078,13 +1078,17 @@ function AddComponent(_ref2) {
|
|
|
1078
1078
|
overflow: 'hidden',
|
|
1079
1079
|
textOverflow: 'ellipsis',
|
|
1080
1080
|
whiteSpace: 'nowrap',
|
|
1081
|
+
minWidth: '140px',
|
|
1081
1082
|
maxWidth: '280px',
|
|
1082
|
-
|
|
1083
|
+
textAlign: 'center'
|
|
1083
1084
|
},
|
|
1084
1085
|
children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_Box.default, {
|
|
1085
1086
|
display: "flex",
|
|
1086
1087
|
alignItems: "center",
|
|
1087
1088
|
children: [(typeof step.loading === 'boolean' ? step.loading : loading) && /*#__PURE__*/(0, _jsxRuntime.jsx)(_CircularProgress.default, {
|
|
1089
|
+
style: {
|
|
1090
|
+
marginRight: 8
|
|
1091
|
+
},
|
|
1088
1092
|
size: 16
|
|
1089
1093
|
}), step.confirm]
|
|
1090
1094
|
})
|
|
@@ -22,8 +22,8 @@ var _InputAdornment = _interopRequireDefault(require("@mui/material/InputAdornme
|
|
|
22
22
|
var _context = require("@arcblock/ux/lib/Locale/context");
|
|
23
23
|
var _Button = _interopRequireDefault(require("@arcblock/ux/lib/Button"));
|
|
24
24
|
var _Toast = _interopRequireDefault(require("@arcblock/ux/lib/Toast"));
|
|
25
|
-
var _Tabs = _interopRequireDefault(require("@arcblock/ux/lib/Tabs"));
|
|
26
25
|
var _Empty = _interopRequireDefault(require("@arcblock/ux/lib/Empty"));
|
|
26
|
+
var _Tabs = _interopRequireDefault(require("@arcblock/ux/lib/Tabs"));
|
|
27
27
|
var _constant = require("@blocklet/constant");
|
|
28
28
|
var _constant2 = require("@abtnode/constant");
|
|
29
29
|
var _bundleAvatar = _interopRequireDefault(require("../bundle-avatar"));
|
|
@@ -95,7 +95,6 @@ const addComponentTabs = _ref => {
|
|
|
95
95
|
const key = blocklet.meta.did;
|
|
96
96
|
tabs.push({
|
|
97
97
|
label: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_Box.default, {
|
|
98
|
-
ml: -4,
|
|
99
98
|
display: "flex",
|
|
100
99
|
alignItems: "center",
|
|
101
100
|
justifyContent: "flex-start",
|
|
@@ -104,7 +103,7 @@ const addComponentTabs = _ref => {
|
|
|
104
103
|
blocklet: blocklet,
|
|
105
104
|
ancestors: ancestors
|
|
106
105
|
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_Box.default, {
|
|
107
|
-
ml: "
|
|
106
|
+
ml: "4px",
|
|
108
107
|
className: "text",
|
|
109
108
|
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Box.default, {
|
|
110
109
|
children: blocklet.meta.title
|
|
@@ -145,7 +144,7 @@ function CreateRelease(_ref2) {
|
|
|
145
144
|
const releaseId = inputReleaseId === 'create' ? '' : inputReleaseId;
|
|
146
145
|
const mode = inputReleaseId === 'create' ? 'create' : 'edit';
|
|
147
146
|
const tabs = [];
|
|
148
|
-
const resourceComponents = ((blocklet === null || blocklet === void 0 ? void 0 : blocklet.children) || []).filter(x => x.meta.capabilities.
|
|
147
|
+
const resourceComponents = ((blocklet === null || blocklet === void 0 ? void 0 : blocklet.children) || []).filter(x => x.meta.capabilities.resourceExportApi);
|
|
149
148
|
resourceComponents.forEach(item => {
|
|
150
149
|
addComponentTabs({
|
|
151
150
|
tabs,
|
|
@@ -350,6 +349,7 @@ function CreateRelease(_ref2) {
|
|
|
350
349
|
autoComplete: "off",
|
|
351
350
|
variant: "outlined",
|
|
352
351
|
fullWidth: true,
|
|
352
|
+
required: true,
|
|
353
353
|
value: params.blockletTitle || '',
|
|
354
354
|
onChange: e => {
|
|
355
355
|
setParamsErrTip({
|
|
@@ -368,6 +368,7 @@ function CreateRelease(_ref2) {
|
|
|
368
368
|
'data-cy': 'blocklet-description',
|
|
369
369
|
readOnly
|
|
370
370
|
},
|
|
371
|
+
required: true,
|
|
371
372
|
autoComplete: "off",
|
|
372
373
|
variant: "outlined",
|
|
373
374
|
fullWidth: true,
|
|
@@ -430,6 +431,7 @@ function CreateRelease(_ref2) {
|
|
|
430
431
|
flex: 1
|
|
431
432
|
},
|
|
432
433
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_TextField.default, {
|
|
434
|
+
required: true,
|
|
433
435
|
label: "Blocklet ".concat(t('common.version')),
|
|
434
436
|
placeholder: "Blocklet ".concat(t('common.version')),
|
|
435
437
|
InputProps: {
|
|
@@ -465,6 +467,7 @@ function CreateRelease(_ref2) {
|
|
|
465
467
|
fullWidth: true,
|
|
466
468
|
multiline: true,
|
|
467
469
|
minRows: 4,
|
|
470
|
+
required: true,
|
|
468
471
|
value: params.note,
|
|
469
472
|
onChange: e => {
|
|
470
473
|
setParamsErrTip({
|
|
@@ -619,27 +622,27 @@ function CreateRelease(_ref2) {
|
|
|
619
622
|
display: "flex",
|
|
620
623
|
mt: 3,
|
|
621
624
|
className: "section full-width",
|
|
622
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.
|
|
625
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_Box.default, {
|
|
623
626
|
className: "left",
|
|
624
|
-
children:
|
|
627
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Typography.default, {
|
|
625
628
|
variant: "h3",
|
|
626
629
|
children: t('blocklet.publish.resourceTitle')
|
|
627
|
-
})
|
|
630
|
+
})
|
|
631
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_Box.default, {
|
|
632
|
+
sx: {
|
|
633
|
+
flex: 1
|
|
634
|
+
},
|
|
635
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_Tabs.default, {
|
|
628
636
|
tabs: tabs,
|
|
629
637
|
current: tab,
|
|
630
|
-
orientation: "vertical",
|
|
631
638
|
onChange: onTabChange,
|
|
632
639
|
sx: {
|
|
633
|
-
|
|
640
|
+
ml: -2,
|
|
641
|
+
mt: -1.5
|
|
634
642
|
}
|
|
635
|
-
})
|
|
636
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_Box.default, {
|
|
637
|
-
sx: {
|
|
638
|
-
flex: 1
|
|
639
|
-
},
|
|
640
|
-
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Box.default, {
|
|
643
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_Box.default, {
|
|
641
644
|
children: resourceContent
|
|
642
|
-
})
|
|
645
|
+
})]
|
|
643
646
|
})]
|
|
644
647
|
})]
|
|
645
648
|
})]
|
|
@@ -647,7 +650,7 @@ function CreateRelease(_ref2) {
|
|
|
647
650
|
}
|
|
648
651
|
CreateRelease.propTypes = {};
|
|
649
652
|
CreateRelease.defaultProps = {};
|
|
650
|
-
const Main = _styled.default.div(_templateObject || (_templateObject = _taggedTemplateLiteral(["\n .sticky-header {\n margin-top: -12px;\n padding: 12px 0;\n position: sticky;\n top: 0;\n z-index: 99;\n display: flex;\n align-items: center;\n justify-content: space-between;\n background-color: #fff;\n padding-bottom: 12px;\n border-bottom: ", ";\n }\n .screenshot {\n margin-bottom: 16px;\n max-width: 200px;\n max-height: 140px;\n width: 200px;\n height: 140px;\n overflow: hidden;\n display: flex;\n align-items: center;\n justify-content: center;\n background-color: #eee;\n margin-right: 16px;\n position: relative;\n .action {\n visibility: hidden;\n position: absolute;\n top: 0px;\n right: 0px;\n background-color: rgba(0, 0, 0, 0.2);\n color: rgba(255, 255, 255, 0.8);\n }\n &:hover .action {\n visibility: visible;\n }\n }\n .screenshot img {\n width: 100%; /* \u56FE\u50CF\u5BBD\u5EA6\u586B\u5145\u5BB9\u5668 */\n height: auto; /* \u56FE\u50CF\u9AD8\u5EA6\u81EA\u9002\u5E94 */\n }\n .section {\n max-width: 800px;\n &.full-width {\n max-width: 100%;\n }\n .MuiTypography-h3 {\n font-size: 1.1rem;\n font-weight: 700;\n }\n .left {\n flex-shrink: 0;\n width: 140px;\n }\n .MuiTabs-
|
|
653
|
+
const Main = _styled.default.div(_templateObject || (_templateObject = _taggedTemplateLiteral(["\n .sticky-header {\n margin-top: -12px;\n padding: 12px 0;\n position: sticky;\n top: 0;\n z-index: 99;\n display: flex;\n align-items: center;\n justify-content: space-between;\n background-color: #fff;\n padding-bottom: 12px;\n border-bottom: ", ";\n }\n .screenshot {\n margin-bottom: 16px;\n max-width: 200px;\n max-height: 140px;\n width: 200px;\n height: 140px;\n overflow: hidden;\n display: flex;\n align-items: center;\n justify-content: center;\n background-color: #eee;\n margin-right: 16px;\n position: relative;\n .action {\n visibility: hidden;\n position: absolute;\n top: 0px;\n right: 0px;\n background-color: rgba(0, 0, 0, 0.2);\n color: rgba(255, 255, 255, 0.8);\n }\n &:hover .action {\n visibility: visible;\n }\n }\n .screenshot img {\n width: 100%; /* \u56FE\u50CF\u5BBD\u5EA6\u586B\u5145\u5BB9\u5668 */\n height: auto; /* \u56FE\u50CF\u9AD8\u5EA6\u81EA\u9002\u5E94 */\n }\n .section {\n max-width: 800px;\n &.full-width {\n max-width: 100%;\n }\n .MuiTypography-h3 {\n font-size: 1.1rem;\n font-weight: 700;\n }\n .left {\n flex-shrink: 0;\n width: 140px;\n }\n .MuiTabs-indicator {\n display: none;\n }\n .MuiTypography-subtitle1 {\n width: 120px;\n font-weight: 700;\n font-size: 1rem;\n ", " {\n width: 80px;\n }\n }\n }\n .MuiButtonBase-root {\n a {\n color: inherit;\n }\n }\n .MuiInputBase-multiline .MuiInputAdornment-positionEnd {\n align-self: flex-end;\n .MuiTypography-root {\n font-size: 0.8rem;\n }\n font-size: 0.8rem;\n }\n"])), _ref3 => {
|
|
651
654
|
let {
|
|
652
655
|
theme
|
|
653
656
|
} = _ref3;
|
|
@@ -656,15 +659,5 @@ const Main = _styled.default.div(_templateObject || (_templateObject = _taggedTe
|
|
|
656
659
|
let {
|
|
657
660
|
theme
|
|
658
661
|
} = _ref4;
|
|
659
|
-
return theme.palette.text.primary;
|
|
660
|
-
}, _ref5 => {
|
|
661
|
-
let {
|
|
662
|
-
theme
|
|
663
|
-
} = _ref5;
|
|
664
|
-
return theme.palette.primary.main;
|
|
665
|
-
}, _ref6 => {
|
|
666
|
-
let {
|
|
667
|
-
theme
|
|
668
|
-
} = _ref6;
|
|
669
662
|
return theme.breakpoints.down('sm');
|
|
670
663
|
});
|
|
@@ -7,15 +7,37 @@ exports.default = Resource;
|
|
|
7
7
|
var _react = require("react");
|
|
8
8
|
var _propTypes = _interopRequireDefault(require("prop-types"));
|
|
9
9
|
var _styled = _interopRequireDefault(require("@emotion/styled"));
|
|
10
|
-
var
|
|
10
|
+
var _difference = _interopRequireDefault(require("lodash/difference"));
|
|
11
11
|
var _urlJoin = _interopRequireDefault(require("url-join"));
|
|
12
|
+
var _Box = _interopRequireDefault(require("@mui/material/Box"));
|
|
12
13
|
var _context = require("@arcblock/ux/lib/Locale/context");
|
|
14
|
+
var _Button = _interopRequireDefault(require("@arcblock/ux/lib/Button"));
|
|
15
|
+
var _Toast = _interopRequireDefault(require("@arcblock/ux/lib/Toast"));
|
|
16
|
+
var _tree = _interopRequireDefault(require("./tree"));
|
|
17
|
+
var _node = require("../../contexts/node");
|
|
18
|
+
var _api = require("../../util/api");
|
|
13
19
|
var _jsxRuntime = require("react/jsx-runtime");
|
|
14
20
|
var _templateObject;
|
|
15
|
-
/* eslint-disable no-unused-vars */
|
|
16
|
-
/* eslint-disable react/no-unstable-nested-components */
|
|
17
21
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
18
22
|
function _taggedTemplateLiteral(strings, raw) { if (!raw) { raw = strings.slice(0); } return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })); }
|
|
23
|
+
const fillParent = (nodes, parentId) => {
|
|
24
|
+
nodes.forEach(node => {
|
|
25
|
+
if (parentId) {
|
|
26
|
+
node.parent = parentId;
|
|
27
|
+
}
|
|
28
|
+
(node.children || []).forEach(child => {
|
|
29
|
+
child.parent = node.id;
|
|
30
|
+
fillParent(child.children || [], child.id);
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
return nodes;
|
|
34
|
+
};
|
|
35
|
+
const checkDiff = (a, b) => {
|
|
36
|
+
if (a.length !== b.length) {
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
return !!(0, _difference.default)(a, b || []).length;
|
|
40
|
+
};
|
|
19
41
|
function Resource(_ref) {
|
|
20
42
|
let {
|
|
21
43
|
app,
|
|
@@ -27,20 +49,82 @@ function Resource(_ref) {
|
|
|
27
49
|
t,
|
|
28
50
|
locale
|
|
29
51
|
} = (0, _context.useLocaleContext)();
|
|
30
|
-
const
|
|
52
|
+
const {
|
|
53
|
+
api
|
|
54
|
+
} = (0, _node.useNodeContext)();
|
|
55
|
+
const [resources, setResources] = (0, _react.useState)([]);
|
|
56
|
+
const [selectedResourceIds, setSelectedResourceIds] = (0, _react.useState)([]);
|
|
57
|
+
const [savedResourceIds, setSavedResourceIds] = (0, _react.useState)([]);
|
|
58
|
+
const [loading, setLoading] = (0, _react.useState)(false);
|
|
31
59
|
const releaseId = release.id;
|
|
32
60
|
const readonly = release.status === 'published';
|
|
33
61
|
const {
|
|
34
|
-
|
|
62
|
+
resourceExportApi = '/'
|
|
35
63
|
} = (component === null || component === void 0 ? void 0 : component.meta.capabilities) || {};
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
64
|
+
const hasDiff = (0, _react.useMemo)(() => checkDiff(savedResourceIds, selectedResourceIds), [savedResourceIds, selectedResourceIds]);
|
|
65
|
+
const urlObj = new URL((0, _urlJoin.default)('http://127.0.0.1', component.mountPoint, resourceExportApi || '/').replace(/\/+/g, '/'));
|
|
66
|
+
urlObj.searchParams.set('projectId', projectId);
|
|
67
|
+
urlObj.searchParams.set('releaseId', releaseId);
|
|
68
|
+
urlObj.searchParams.set('local', locale);
|
|
69
|
+
const url = "".concat(urlObj.pathname).concat(urlObj.search);
|
|
70
|
+
const saveSelected = async data => {
|
|
71
|
+
try {
|
|
72
|
+
await api.updateSelectedResources({
|
|
73
|
+
input: {
|
|
74
|
+
did: app.meta.did,
|
|
75
|
+
projectId,
|
|
76
|
+
releaseId,
|
|
77
|
+
componentDid: component.meta.did,
|
|
78
|
+
resources: data
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
setSavedResourceIds(data);
|
|
82
|
+
} catch (err) {
|
|
83
|
+
_Toast.default.error(err.message);
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
const onSave = async () => {
|
|
87
|
+
const params = selectedResourceIds;
|
|
88
|
+
try {
|
|
89
|
+
setLoading(true);
|
|
90
|
+
await _api.axios.post(url, {
|
|
91
|
+
resources: params,
|
|
92
|
+
projectId,
|
|
93
|
+
releaseId,
|
|
94
|
+
locale
|
|
95
|
+
});
|
|
96
|
+
_Toast.default.success(t('common.saveSuccess'));
|
|
97
|
+
setLoading(false);
|
|
98
|
+
saveSelected(selectedResourceIds);
|
|
99
|
+
} catch (err) {
|
|
100
|
+
setLoading(false);
|
|
101
|
+
_Toast.default.error(err.message);
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
(0, _react.useEffect)(() => {
|
|
105
|
+
_api.axios.get(url).then(res => {
|
|
106
|
+
var _res$data;
|
|
107
|
+
const tree = fillParent(((_res$data = res.data) === null || _res$data === void 0 ? void 0 : _res$data.resources) || []);
|
|
108
|
+
setResources(tree);
|
|
109
|
+
}).catch(err => {
|
|
110
|
+
_Toast.default.error(err.message);
|
|
111
|
+
});
|
|
112
|
+
api.getSelectedResources({
|
|
113
|
+
input: {
|
|
114
|
+
did: app.meta.did,
|
|
115
|
+
projectId,
|
|
116
|
+
releaseId,
|
|
117
|
+
componentDid: component.meta.did
|
|
118
|
+
}
|
|
119
|
+
}).then(res => {
|
|
120
|
+
const list = (res === null || res === void 0 ? void 0 : res.resources) || [];
|
|
121
|
+
setSelectedResourceIds(list);
|
|
122
|
+
setSavedResourceIds(list);
|
|
123
|
+
}).catch(err => {
|
|
124
|
+
_Toast.default.error(err.message);
|
|
125
|
+
});
|
|
126
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
127
|
+
}, [url]);
|
|
44
128
|
if (component.status !== 'running') {
|
|
45
129
|
return /*#__PURE__*/(0, _jsxRuntime.jsx)(Container, {
|
|
46
130
|
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Box.default, {
|
|
@@ -52,12 +136,23 @@ function Resource(_ref) {
|
|
|
52
136
|
});
|
|
53
137
|
}
|
|
54
138
|
return /*#__PURE__*/(0, _jsxRuntime.jsx)(Container, {
|
|
55
|
-
children: /*#__PURE__*/(0, _jsxRuntime.
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
139
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_Box.default, {
|
|
140
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_tree.default, {
|
|
141
|
+
data: resources,
|
|
142
|
+
value: selectedResourceIds,
|
|
143
|
+
onChange: data => {
|
|
144
|
+
setSelectedResourceIds(data);
|
|
145
|
+
},
|
|
146
|
+
disabled: loading || readonly
|
|
147
|
+
}), !readonly && /*#__PURE__*/(0, _jsxRuntime.jsx)(_Box.default, {
|
|
148
|
+
className: "footer",
|
|
149
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Button.default, {
|
|
150
|
+
variant: "contained",
|
|
151
|
+
disabled: loading || !hasDiff,
|
|
152
|
+
onClick: () => onSave(),
|
|
153
|
+
children: t('common.save')
|
|
154
|
+
})
|
|
155
|
+
})]
|
|
61
156
|
})
|
|
62
157
|
});
|
|
63
158
|
}
|
|
@@ -75,4 +170,4 @@ Resource.defaultProps = {
|
|
|
75
170
|
id: ''
|
|
76
171
|
}
|
|
77
172
|
};
|
|
78
|
-
const Container = (0, _styled.default)(_Box.default)(_templateObject || (_templateObject = _taggedTemplateLiteral(["\n
|
|
173
|
+
const Container = (0, _styled.default)(_Box.default)(_templateObject || (_templateObject = _taggedTemplateLiteral(["\n border: 1px solid #ccc;\n border-radius: 4px;\n padding: 16px;\n padding-bottom: 0px;\n max-height: 600px;\n overflow-y: auto;\n .footer {\n border-top: 1px solid #ddd;\n display: flex;\n padding: 12px 0;\n margin-top: 12px;\n position: sticky;\n bottom: 0;\n background: #fff;\n }\n"])));
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = Tree;
|
|
7
|
+
var _propTypes = _interopRequireDefault(require("prop-types"));
|
|
8
|
+
var _styled = _interopRequireDefault(require("@emotion/styled"));
|
|
9
|
+
var _classnames = _interopRequireDefault(require("classnames"));
|
|
10
|
+
var _isUrl = _interopRequireDefault(require("is-url"));
|
|
11
|
+
var _Box = _interopRequireDefault(require("@mui/material/Box"));
|
|
12
|
+
var _FormControlLabel = _interopRequireDefault(require("@mui/material/FormControlLabel"));
|
|
13
|
+
var _TreeView = _interopRequireDefault(require("@mui/lab/TreeView"));
|
|
14
|
+
var _TreeItem = _interopRequireDefault(require("@mui/lab/TreeItem"));
|
|
15
|
+
var _Checkbox = _interopRequireDefault(require("@mui/material/Checkbox"));
|
|
16
|
+
var _ExpandMore = _interopRequireDefault(require("@mui/icons-material/ExpandMore"));
|
|
17
|
+
var _ChevronRight = _interopRequireDefault(require("@mui/icons-material/ChevronRight"));
|
|
18
|
+
var _OpenInNew = _interopRequireDefault(require("@mui/icons-material/OpenInNew"));
|
|
19
|
+
var _react = require("@iconify/react");
|
|
20
|
+
var _jsxRuntime = require("react/jsx-runtime");
|
|
21
|
+
var _templateObject; // BFS algorithm to find node by his ID
|
|
22
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
23
|
+
function _taggedTemplateLiteral(strings, raw) { if (!raw) { raw = strings.slice(0); } return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })); }
|
|
24
|
+
const bfsSearch = (graph, targetId) => {
|
|
25
|
+
const queue = [...graph];
|
|
26
|
+
while (queue.length > 0) {
|
|
27
|
+
const currNode = queue.shift();
|
|
28
|
+
if (currNode.id === targetId) {
|
|
29
|
+
return currNode;
|
|
30
|
+
}
|
|
31
|
+
if (currNode.children) {
|
|
32
|
+
queue.push(...currNode.children);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return []; // Target node not found
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
function ResourceIcon(_ref) {
|
|
39
|
+
let {
|
|
40
|
+
icon
|
|
41
|
+
} = _ref;
|
|
42
|
+
if (!icon) {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
if ((0, _isUrl.default)(icon)) {
|
|
46
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)("img", {
|
|
47
|
+
className: "resource-icon",
|
|
48
|
+
src: icon,
|
|
49
|
+
alt: "icon"
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_react.Icon, {
|
|
53
|
+
className: "resource-icon",
|
|
54
|
+
icon: icon
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
ResourceIcon.propTypes = {
|
|
58
|
+
icon: _propTypes.default.string
|
|
59
|
+
};
|
|
60
|
+
ResourceIcon.defaultProps = {
|
|
61
|
+
icon: ''
|
|
62
|
+
};
|
|
63
|
+
function Tree(_ref2) {
|
|
64
|
+
let {
|
|
65
|
+
disabled,
|
|
66
|
+
data,
|
|
67
|
+
onChange,
|
|
68
|
+
value
|
|
69
|
+
} = _ref2;
|
|
70
|
+
const selectedNodes = value;
|
|
71
|
+
|
|
72
|
+
// Retrieve all ids from node to his children's
|
|
73
|
+
function getAllIds(node) {
|
|
74
|
+
let idList = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
|
|
75
|
+
idList.push(node.id);
|
|
76
|
+
if (node.children) {
|
|
77
|
+
node.children.forEach(child => getAllIds(child, idList));
|
|
78
|
+
}
|
|
79
|
+
return idList;
|
|
80
|
+
}
|
|
81
|
+
// Get IDs of all children from specific node
|
|
82
|
+
const getAllChild = id => {
|
|
83
|
+
return getAllIds(bfsSearch(data, id));
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
// Get all father IDs from specific node
|
|
87
|
+
const getAllFathers = function getAllFathers(id) {
|
|
88
|
+
let list = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
|
|
89
|
+
const node = bfsSearch(data, id);
|
|
90
|
+
if (node.parent) {
|
|
91
|
+
list.push(node.parent);
|
|
92
|
+
return getAllFathers(node.parent, list);
|
|
93
|
+
}
|
|
94
|
+
return list;
|
|
95
|
+
};
|
|
96
|
+
function isAllChildrenChecked(node, list) {
|
|
97
|
+
const allChild = getAllChild(node.id);
|
|
98
|
+
const nodeIdIndex = allChild.indexOf(node.id);
|
|
99
|
+
allChild.splice(nodeIdIndex, 1);
|
|
100
|
+
return allChild.every(nodeId => selectedNodes.concat(list).includes(nodeId));
|
|
101
|
+
}
|
|
102
|
+
const handleNodeSelect = (event, nodeId) => {
|
|
103
|
+
event.stopPropagation();
|
|
104
|
+
const allChild = getAllChild(nodeId);
|
|
105
|
+
const fathers = getAllFathers(nodeId);
|
|
106
|
+
if (selectedNodes.includes(nodeId)) {
|
|
107
|
+
// Need to de-check
|
|
108
|
+
const newValue = selectedNodes.filter(id => !allChild.concat(fathers).includes(id));
|
|
109
|
+
onChange(newValue);
|
|
110
|
+
} else {
|
|
111
|
+
// Need to check
|
|
112
|
+
const ToBeChecked = allChild;
|
|
113
|
+
for (let i = 0; i < fathers.length; ++i) {
|
|
114
|
+
if (isAllChildrenChecked(bfsSearch(data, fathers[i]), ToBeChecked)) {
|
|
115
|
+
ToBeChecked.push(fathers[i]);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
onChange([...selectedNodes].concat(ToBeChecked));
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
const stopExpand = event => {
|
|
122
|
+
// prevent the click event from propagating to the checkbox
|
|
123
|
+
event.stopPropagation();
|
|
124
|
+
};
|
|
125
|
+
const hadChildren = data.some(node => {
|
|
126
|
+
var _node$children;
|
|
127
|
+
return ((_node$children = node.children) === null || _node$children === void 0 ? void 0 : _node$children.length) > 0;
|
|
128
|
+
});
|
|
129
|
+
const renderTree = node => /*#__PURE__*/(0, _jsxRuntime.jsx)(_TreeItem.default, {
|
|
130
|
+
nodeId: node.id,
|
|
131
|
+
label: /*#__PURE__*/(0, _jsxRuntime.jsx)(_FormControlLabel.default, {
|
|
132
|
+
onClick: stopExpand,
|
|
133
|
+
control: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Checkbox.default, {
|
|
134
|
+
size: "small",
|
|
135
|
+
checked: selectedNodes.indexOf(node.id) !== -1,
|
|
136
|
+
tabIndex: -1,
|
|
137
|
+
disableRipple: true,
|
|
138
|
+
onClick: event => handleNodeSelect(event, node.id),
|
|
139
|
+
disabled: disabled
|
|
140
|
+
}),
|
|
141
|
+
label: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_Box.default, {
|
|
142
|
+
className: "content",
|
|
143
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_Box.default, {
|
|
144
|
+
display: "flex",
|
|
145
|
+
alignItems: "center",
|
|
146
|
+
children: [node.icon && /*#__PURE__*/(0, _jsxRuntime.jsx)(ResourceIcon, {
|
|
147
|
+
icon: node.icon
|
|
148
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_Box.default, {
|
|
149
|
+
className: "name",
|
|
150
|
+
children: node.name
|
|
151
|
+
}), node.url && /*#__PURE__*/(0, _jsxRuntime.jsx)("a", {
|
|
152
|
+
href: node.url,
|
|
153
|
+
target: "_blank",
|
|
154
|
+
rel: "noreferrer",
|
|
155
|
+
className: "link",
|
|
156
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_OpenInNew.default, {
|
|
157
|
+
className: "link-icon"
|
|
158
|
+
})
|
|
159
|
+
})]
|
|
160
|
+
}), !!node.description && /*#__PURE__*/(0, _jsxRuntime.jsx)(_Box.default, {
|
|
161
|
+
className: "description",
|
|
162
|
+
children: node.description
|
|
163
|
+
})]
|
|
164
|
+
})
|
|
165
|
+
}),
|
|
166
|
+
children: Array.isArray(node.children) ? node.children.map(renderTree) : null
|
|
167
|
+
}, node.id);
|
|
168
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(StyledTreeView, {
|
|
169
|
+
className: (0, _classnames.default)(!hadChildren && 'no-children'),
|
|
170
|
+
multiSelect: true,
|
|
171
|
+
defaultCollapseIcon: /*#__PURE__*/(0, _jsxRuntime.jsx)(_ExpandMore.default, {}),
|
|
172
|
+
defaultExpandIcon: /*#__PURE__*/(0, _jsxRuntime.jsx)(_ChevronRight.default, {}),
|
|
173
|
+
selected: selectedNodes,
|
|
174
|
+
children: data.map(node => renderTree(node))
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
Tree.propTypes = {
|
|
178
|
+
data: _propTypes.default.array,
|
|
179
|
+
value: _propTypes.default.array,
|
|
180
|
+
onChange: _propTypes.default.func,
|
|
181
|
+
disabled: _propTypes.default.bool
|
|
182
|
+
};
|
|
183
|
+
Tree.defaultProps = {
|
|
184
|
+
data: [],
|
|
185
|
+
value: [],
|
|
186
|
+
onChange: () => {},
|
|
187
|
+
disabled: false
|
|
188
|
+
};
|
|
189
|
+
const StyledTreeView = (0, _styled.default)(_TreeView.default)(_templateObject || (_templateObject = _taggedTemplateLiteral(["\n &.no-children {\n .MuiTreeItem-content {\n padding: 0;\n .MuiTreeItem-iconContainer {\n display: none;\n }\n .MuiTreeItem-label {\n padding-left: 0;\n }\n }\n }\n .MuiTreeItem-content {\n align-items: flex-start;\n .MuiTreeItem-iconContainer {\n transform: translateY(10px);\n }\n &.Mui-selected {\n background-color: transparent;\n }\n }\n .MuiTreeItem-label {\n cursor: default;\n }\n .MuiFormControlLabel-root {\n align-items: flex-start;\n }\n .content {\n padding-top: 6px;\n }\n .name {\n font-size: 16px;\n font-weight: 700;\n }\n .resource-icon {\n margin-right: 2px;\n font-size: 16px;\n }\n img.resource-icon {\n width: 1rem;\n height: 1rem;\n }\n .link {\n margin-left: 8px;\n font-size: 16px;\n color: ", ";\n display: flex;\n }\n .link-icon {\n font-size: inherit;\n }\n .description {\n font-size: 14px;\n color: ", ";\n }\n"])), _ref3 => {
|
|
190
|
+
let {
|
|
191
|
+
theme
|
|
192
|
+
} = _ref3;
|
|
193
|
+
return theme.palette.primary.main;
|
|
194
|
+
}, _ref4 => {
|
|
195
|
+
let {
|
|
196
|
+
theme
|
|
197
|
+
} = _ref4;
|
|
198
|
+
return theme.palette.text.secondary;
|
|
199
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@abtnode/ux",
|
|
3
|
-
"version": "1.16.17-beta-
|
|
3
|
+
"version": "1.16.17-beta-5d4664f8",
|
|
4
4
|
"description": "UX components shared across abtnode packages",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -27,24 +27,24 @@
|
|
|
27
27
|
"author": "linchen <linchen1987@foxmail.com> (http://github.com/linchen1987)",
|
|
28
28
|
"license": "Apache-2.0",
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@abtnode/auth": "1.16.17-beta-
|
|
31
|
-
"@abtnode/constant": "1.16.17-beta-
|
|
32
|
-
"@abtnode/util": "1.16.17-beta-
|
|
30
|
+
"@abtnode/auth": "1.16.17-beta-5d4664f8",
|
|
31
|
+
"@abtnode/constant": "1.16.17-beta-5d4664f8",
|
|
32
|
+
"@abtnode/util": "1.16.17-beta-5d4664f8",
|
|
33
33
|
"@ahooksjs/use-url-state": "^3.5.1",
|
|
34
34
|
"@arcblock/did": "^1.18.92",
|
|
35
|
-
"@arcblock/did-connect": "^2.7.
|
|
35
|
+
"@arcblock/did-connect": "^2.7.29",
|
|
36
36
|
"@arcblock/did-motif": "^1.1.13",
|
|
37
|
-
"@arcblock/icons": "^2.7.
|
|
38
|
-
"@arcblock/nft-display": "2.7.
|
|
39
|
-
"@arcblock/react-hooks": "^2.7.
|
|
40
|
-
"@arcblock/terminal": "^2.7.
|
|
41
|
-
"@arcblock/ux": "^2.7.
|
|
42
|
-
"@blocklet/constant": "1.16.17-beta-
|
|
37
|
+
"@arcblock/icons": "^2.7.29",
|
|
38
|
+
"@arcblock/nft-display": "2.7.29",
|
|
39
|
+
"@arcblock/react-hooks": "^2.7.29",
|
|
40
|
+
"@arcblock/terminal": "^2.7.29",
|
|
41
|
+
"@arcblock/ux": "^2.7.29",
|
|
42
|
+
"@blocklet/constant": "1.16.17-beta-5d4664f8",
|
|
43
43
|
"@blocklet/launcher-layout": "2.2.21",
|
|
44
44
|
"@blocklet/list": "^0.12.45",
|
|
45
|
-
"@blocklet/meta": "1.16.17-beta-
|
|
46
|
-
"@blocklet/ui-react": "^2.7.
|
|
47
|
-
"@blocklet/uploader": "^0.0.
|
|
45
|
+
"@blocklet/meta": "1.16.17-beta-5d4664f8",
|
|
46
|
+
"@blocklet/ui-react": "^2.7.29",
|
|
47
|
+
"@blocklet/uploader": "^0.0.29",
|
|
48
48
|
"@emotion/react": "^11.10.4",
|
|
49
49
|
"@emotion/styled": "^11.10.4",
|
|
50
50
|
"@iconify/react": "^4.0.0",
|
|
@@ -100,7 +100,7 @@
|
|
|
100
100
|
"babel-plugin-inline-react-svg": "^1.1.2",
|
|
101
101
|
"glob": "^10.3.3"
|
|
102
102
|
},
|
|
103
|
-
"gitHead": "
|
|
103
|
+
"gitHead": "e03febafae50406a3fb12706a2349e87ef2c1caa",
|
|
104
104
|
"exports": {
|
|
105
105
|
".": {
|
|
106
106
|
"import": "./es/index.js",
|