@abtnode/ux 1.16.19-beta-710018ca → 1.16.19-beta-ba354e01
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-component-core.js +49 -36
- package/es/blocklet/component/button.js +12 -0
- package/es/blocklet/component/did-space/connect-to.js +355 -0
- package/es/blocklet/component/did-space/connected.js +42 -0
- package/es/blocklet/component/did-space/delete.js +104 -0
- package/es/blocklet/component/did-space/disconnect.js +230 -0
- package/es/blocklet/component/did-space/index.js +73 -0
- package/es/blocklet/component/did-space/item.js +233 -0
- package/es/blocklet/component/index.js +3 -3
- package/es/blocklet/component/step-actions.js +99 -0
- package/es/blocklet/publish/create-project.js +1 -1
- package/es/blocklet/publish/create-release.js +39 -20
- package/es/blocklet/publish/index.js +15 -2
- package/es/blocklet/publish/project-list.js +32 -1
- package/es/blocklet/publish/release-list.js +1 -0
- package/es/blocklet/publish/resource.js +2 -13
- package/es/blocklet/publish/tree.js +4 -0
- package/es/blocklet/resource-type.js +34 -0
- package/es/blocklet/storage/connect-to.js +11 -15
- package/es/contexts/config-space.js +160 -0
- package/es/hooks/use-mobile.js +17 -0
- package/es/hooks/use-storage-endpoint.js +23 -0
- package/es/images.js +48 -0
- package/es/locales/en.js +5 -0
- package/es/locales/zh.js +5 -0
- package/es/util/constants.js +2 -1
- package/es/util/index.js +5 -1
- package/es/util/spaces.js +66 -5
- package/lib/blocklet/component/add-component-core.js +59 -45
- package/lib/blocklet/component/button.js +23 -0
- package/lib/blocklet/component/did-space/connect-to.js +362 -0
- package/lib/blocklet/component/did-space/connected.js +49 -0
- package/lib/blocklet/component/did-space/delete.js +111 -0
- package/lib/blocklet/component/did-space/disconnect.js +241 -0
- package/lib/blocklet/component/did-space/index.js +82 -0
- package/lib/blocklet/component/did-space/item.js +197 -0
- package/lib/blocklet/component/index.js +3 -3
- package/lib/blocklet/component/step-actions.js +63 -0
- package/lib/blocklet/publish/create-project.js +1 -1
- package/lib/blocklet/publish/create-release.js +39 -19
- package/lib/blocklet/publish/index.js +18 -4
- package/lib/blocklet/publish/project-list.js +32 -1
- package/lib/blocklet/publish/release-list.js +1 -0
- package/lib/blocklet/publish/resource.js +1 -12
- package/lib/blocklet/publish/tree.js +45 -38
- package/lib/blocklet/resource-type.js +51 -0
- package/lib/blocklet/storage/connect-to.js +11 -15
- package/lib/contexts/config-space.js +169 -0
- package/lib/hooks/use-mobile.js +24 -0
- package/lib/hooks/use-storage-endpoint.js +28 -0
- package/lib/images.js +51 -0
- package/lib/locales/en.js +5 -0
- package/lib/locales/zh.js +5 -0
- package/lib/util/constants.js +4 -2
- package/lib/util/index.js +8 -2
- package/lib/util/spaces.js +69 -3
- package/package.json +11 -7
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import styled from '@emotion/styled';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import Box from '@mui/material/Box';
|
|
4
|
+
import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
|
|
5
|
+
import Button from './button';
|
|
6
|
+
import useMobile from '../../hooks/use-mobile';
|
|
7
|
+
import { hasRequiredSteps } from '../../util';
|
|
8
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
9
|
+
import { jsxs as _jsxs } from "react/jsx-runtime";
|
|
10
|
+
export default function StepActions({
|
|
11
|
+
blocklet,
|
|
12
|
+
onStartNow,
|
|
13
|
+
children,
|
|
14
|
+
disabled
|
|
15
|
+
}) {
|
|
16
|
+
const {
|
|
17
|
+
t
|
|
18
|
+
} = useLocaleContext();
|
|
19
|
+
const isMobile = useMobile();
|
|
20
|
+
if (!blocklet || hasRequiredSteps(blocklet.meta)) {
|
|
21
|
+
return /*#__PURE__*/_jsx(Center, {
|
|
22
|
+
children: children
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
return /*#__PURE__*/_jsxs(Between, {
|
|
26
|
+
isMobile: isMobile,
|
|
27
|
+
children: [/*#__PURE__*/_jsx(Button, {
|
|
28
|
+
className: "start-now",
|
|
29
|
+
variant: "contained",
|
|
30
|
+
color: "primary",
|
|
31
|
+
disabled: disabled,
|
|
32
|
+
onClick: () => onStartNow(),
|
|
33
|
+
children: t('setup.startNow')
|
|
34
|
+
}), /*#__PURE__*/_jsx(Box, {
|
|
35
|
+
display: "flex",
|
|
36
|
+
alignItems: "center",
|
|
37
|
+
children: children
|
|
38
|
+
})]
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
StepActions.propTypes = {
|
|
42
|
+
blocklet: PropTypes.object,
|
|
43
|
+
onStartNow: PropTypes.func,
|
|
44
|
+
children: PropTypes.any,
|
|
45
|
+
disabled: PropTypes.bool
|
|
46
|
+
};
|
|
47
|
+
StepActions.defaultProps = {
|
|
48
|
+
blocklet: null,
|
|
49
|
+
onStartNow: () => {},
|
|
50
|
+
children: null,
|
|
51
|
+
disabled: false
|
|
52
|
+
};
|
|
53
|
+
const Center = styled(Box)`
|
|
54
|
+
width: 100%;
|
|
55
|
+
margin-top: auto;
|
|
56
|
+
padding-top: 24px;
|
|
57
|
+
display: flex;
|
|
58
|
+
align-items: center;
|
|
59
|
+
justify-content: center;
|
|
60
|
+
.bottom-button {
|
|
61
|
+
min-width: 200px;
|
|
62
|
+
}
|
|
63
|
+
${props => props.theme.breakpoints.down('md')} {
|
|
64
|
+
.bottom-button {
|
|
65
|
+
width: 100%;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
`;
|
|
69
|
+
const Between = styled(Box)`
|
|
70
|
+
padding-top: 24px;
|
|
71
|
+
margin-top: auto;
|
|
72
|
+
width: 100%;
|
|
73
|
+
display: flex;
|
|
74
|
+
align-items: center;
|
|
75
|
+
justify-content: space-between;
|
|
76
|
+
.start-now {
|
|
77
|
+
min-width: 140px;
|
|
78
|
+
}
|
|
79
|
+
.bottom-button {
|
|
80
|
+
min-width: 120px;
|
|
81
|
+
}
|
|
82
|
+
${props => props.theme.breakpoints.down('lg')} {
|
|
83
|
+
width: 100%;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
${props => props.theme.breakpoints.down('md')} {
|
|
87
|
+
.start-now {
|
|
88
|
+
min-width: inherit;
|
|
89
|
+
}
|
|
90
|
+
.bottom-button {
|
|
91
|
+
min-width: 100px;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
${props => props.isMobile} {
|
|
96
|
+
justify-content: space-between;
|
|
97
|
+
gap: '32px',
|
|
98
|
+
}}
|
|
99
|
+
`;
|
|
@@ -53,7 +53,7 @@ export default function CreateProject({
|
|
|
53
53
|
const [blockletDid, setBlockletDid] = useState();
|
|
54
54
|
const [openConnect, setOpenConnect] = useState(false);
|
|
55
55
|
const {
|
|
56
|
-
componentDid
|
|
56
|
+
componentDid = ''
|
|
57
57
|
} = useParams();
|
|
58
58
|
const handleCreateBlockletDidError = err => {
|
|
59
59
|
Toast.error(err.message);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useState, useEffect, lazy, useRef } from 'react';
|
|
1
|
+
import { useState, useEffect, lazy, useRef, useCallback } from 'react';
|
|
2
2
|
import { Link, useNavigate, useParams } from 'react-router-dom';
|
|
3
3
|
import styled from '@emotion/styled';
|
|
4
4
|
import useSetState from 'react-use/lib/useSetState';
|
|
@@ -13,6 +13,7 @@ import Box from '@mui/material/Box';
|
|
|
13
13
|
import IconButton from '@mui/material/IconButton';
|
|
14
14
|
import DeleteOutlineIcon from '@mui/icons-material/DeleteOutline';
|
|
15
15
|
import InputAdornment from '@mui/material/InputAdornment';
|
|
16
|
+
import Spinner from '@mui/material/CircularProgress';
|
|
16
17
|
import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
|
|
17
18
|
import Button from '@arcblock/ux/lib/Button';
|
|
18
19
|
import Toast from '@arcblock/ux/lib/Toast';
|
|
@@ -120,6 +121,7 @@ export default function CreateRelease({
|
|
|
120
121
|
const [params, setParams] = useSetState(null);
|
|
121
122
|
const [paramsErrTip, setParamsErrTip] = useState({});
|
|
122
123
|
const [loading, setLoading] = useState(false);
|
|
124
|
+
const [createLoading, setCreateLoading] = useState(false);
|
|
123
125
|
const [release, setRelease] = useState(null);
|
|
124
126
|
const {
|
|
125
127
|
api
|
|
@@ -177,7 +179,7 @@ export default function CreateRelease({
|
|
|
177
179
|
Toast.error(formatError(err));
|
|
178
180
|
});
|
|
179
181
|
};
|
|
180
|
-
const getData = () => {
|
|
182
|
+
const getData = useCallback(() => {
|
|
181
183
|
if (mode === 'edit') {
|
|
182
184
|
if (!releaseId) {
|
|
183
185
|
Toast.error('Empty release id');
|
|
@@ -188,11 +190,11 @@ export default function CreateRelease({
|
|
|
188
190
|
if (mode === 'create') {
|
|
189
191
|
getProject();
|
|
190
192
|
}
|
|
191
|
-
|
|
193
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
194
|
+
}, [mode, releaseId]);
|
|
192
195
|
useEffect(() => {
|
|
193
196
|
getData();
|
|
194
|
-
}, []);
|
|
195
|
-
|
|
197
|
+
}, [getData]);
|
|
196
198
|
const onRelease = status => {
|
|
197
199
|
const errors = validateParams(params, status, t);
|
|
198
200
|
if (errors) {
|
|
@@ -218,6 +220,8 @@ export default function CreateRelease({
|
|
|
218
220
|
_params.blockletDescription = (_params.blockletDescription || '').trim();
|
|
219
221
|
_params.blockletIntroduction = (_params.blockletIntroduction || '').trim();
|
|
220
222
|
_params.note = (_params.note || '').trim();
|
|
223
|
+
setCreateLoading(status);
|
|
224
|
+
setLoading(true);
|
|
221
225
|
api.createRelease({
|
|
222
226
|
input: {
|
|
223
227
|
..._params,
|
|
@@ -226,21 +230,25 @@ export default function CreateRelease({
|
|
|
226
230
|
releaseId,
|
|
227
231
|
status
|
|
228
232
|
}
|
|
229
|
-
}).then(
|
|
233
|
+
}).then(res => {
|
|
234
|
+
setCreateLoading(false);
|
|
235
|
+
setLoading(false);
|
|
230
236
|
if (status === 'draft') {
|
|
231
|
-
Toast.success('
|
|
232
|
-
if (mode === 'create') {
|
|
233
|
-
navigate(`../${projectId}`, {
|
|
234
|
-
replace: true
|
|
235
|
-
});
|
|
236
|
-
}
|
|
237
|
+
Toast.success(t('blocklet.publish.saveDraftSuccess'));
|
|
237
238
|
} else {
|
|
238
|
-
Toast.success('
|
|
239
|
-
|
|
239
|
+
Toast.success(t('blocklet.publish.createReleaseSuccess'));
|
|
240
|
+
}
|
|
241
|
+
if (mode === 'create') {
|
|
242
|
+
const id = res?.release?.id;
|
|
243
|
+
navigate(`../${projectId}/${id}`, {
|
|
240
244
|
replace: true
|
|
241
245
|
});
|
|
246
|
+
} else {
|
|
247
|
+
getRelease();
|
|
242
248
|
}
|
|
243
249
|
}).catch(err => {
|
|
250
|
+
setCreateLoading(false);
|
|
251
|
+
setLoading(false);
|
|
244
252
|
Toast.error(formatError(err));
|
|
245
253
|
});
|
|
246
254
|
};
|
|
@@ -295,19 +303,30 @@ export default function CreateRelease({
|
|
|
295
303
|
}), /*#__PURE__*/_jsxs(Box, {
|
|
296
304
|
display: "flex",
|
|
297
305
|
children: [!isPublished && /*#__PURE__*/_jsxs(_Fragment, {
|
|
298
|
-
children: [/*#__PURE__*/
|
|
306
|
+
children: [/*#__PURE__*/_jsxs(Button, {
|
|
299
307
|
variant: "outlined",
|
|
300
|
-
disabled: loading,
|
|
308
|
+
disabled: loading || createLoading,
|
|
301
309
|
onClick: () => onRelease(PROJECT.RELEASE_STATUS.draft),
|
|
302
310
|
style: {
|
|
303
311
|
marginRight: 12
|
|
304
312
|
},
|
|
305
|
-
children:
|
|
306
|
-
|
|
313
|
+
children: [createLoading === PROJECT.RELEASE_STATUS.draft && /*#__PURE__*/_jsx(Spinner, {
|
|
314
|
+
size: 14,
|
|
315
|
+
sx: {
|
|
316
|
+
mr: 0.5
|
|
317
|
+
}
|
|
318
|
+
}), t('blocklet.publish.saveDraft')]
|
|
319
|
+
}), /*#__PURE__*/_jsxs(Button, {
|
|
307
320
|
variant: "contained",
|
|
308
|
-
disabled: loading,
|
|
321
|
+
disabled: loading || createLoading,
|
|
309
322
|
onClick: () => onRelease(PROJECT.RELEASE_STATUS.published),
|
|
310
|
-
children:
|
|
323
|
+
children: [createLoading === PROJECT.RELEASE_STATUS.published && /*#__PURE__*/_jsx(Spinner, {
|
|
324
|
+
size: 14,
|
|
325
|
+
sx: {
|
|
326
|
+
mr: 0.5
|
|
327
|
+
},
|
|
328
|
+
color: "inherit"
|
|
329
|
+
}), t('common.release')]
|
|
311
330
|
})]
|
|
312
331
|
}), isPublished && /*#__PURE__*/_jsx(Button, {
|
|
313
332
|
variant: "contained",
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import React, { useEffect } from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
2
3
|
import { Routes, Route, useLocation, useParams } from 'react-router-dom';
|
|
3
4
|
import styled from '@emotion/styled';
|
|
4
5
|
import Box from '@mui/material/Box';
|
|
@@ -9,7 +10,9 @@ import ReleasesList from './release-list';
|
|
|
9
10
|
import CreateRelease from './create-release';
|
|
10
11
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
11
12
|
import { jsxs as _jsxs } from "react/jsx-runtime";
|
|
12
|
-
export default function BlockletPublish(
|
|
13
|
+
export default function BlockletPublish({
|
|
14
|
+
padding
|
|
15
|
+
}) {
|
|
13
16
|
const {
|
|
14
17
|
blocklet
|
|
15
18
|
} = useBlockletContext();
|
|
@@ -33,7 +36,12 @@ export default function BlockletPublish() {
|
|
|
33
36
|
if (!blocklet) {
|
|
34
37
|
return null;
|
|
35
38
|
}
|
|
39
|
+
const style = {};
|
|
40
|
+
if (padding) {
|
|
41
|
+
style.padding = padding;
|
|
42
|
+
}
|
|
36
43
|
return /*#__PURE__*/_jsx(Main, {
|
|
44
|
+
style: style,
|
|
37
45
|
children: /*#__PURE__*/_jsxs(Routes, {
|
|
38
46
|
children: [/*#__PURE__*/_jsx(Route, {
|
|
39
47
|
path: "/",
|
|
@@ -51,7 +59,12 @@ export default function BlockletPublish() {
|
|
|
51
59
|
})
|
|
52
60
|
});
|
|
53
61
|
}
|
|
54
|
-
BlockletPublish.propTypes = {
|
|
62
|
+
BlockletPublish.propTypes = {
|
|
63
|
+
padding: PropTypes.oneOfType([PropTypes.string, PropTypes.number])
|
|
64
|
+
};
|
|
65
|
+
BlockletPublish.defaultProps = {
|
|
66
|
+
padding: ''
|
|
67
|
+
};
|
|
55
68
|
const Main = styled(Box)`
|
|
56
69
|
a {
|
|
57
70
|
color: ${({
|
|
@@ -16,6 +16,7 @@ import { useNodeContext } from '../../contexts/node';
|
|
|
16
16
|
import EmptySpinner from '../../empty-spinner';
|
|
17
17
|
import DidAddress from '../../did-address';
|
|
18
18
|
import Confirm from '../../confirm';
|
|
19
|
+
import BlockletBundleAvatar from '../bundle-avatar';
|
|
19
20
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
20
21
|
import { jsxs as _jsxs } from "react/jsx-runtime";
|
|
21
22
|
export default function ProjectList() {
|
|
@@ -65,6 +66,7 @@ export default function ProjectList() {
|
|
|
65
66
|
setLoading(false);
|
|
66
67
|
getProjects();
|
|
67
68
|
Toast.success(t('common.removeSuccess'));
|
|
69
|
+
setDeleteConfirm(null);
|
|
68
70
|
}).catch(err => {
|
|
69
71
|
setLoading(false);
|
|
70
72
|
Toast.error(err.message);
|
|
@@ -144,6 +146,35 @@ export default function ProjectList() {
|
|
|
144
146
|
}) : '';
|
|
145
147
|
}
|
|
146
148
|
}
|
|
149
|
+
}, componentDid ? null : {
|
|
150
|
+
label: t('common.scope'),
|
|
151
|
+
name: 'componentDid',
|
|
152
|
+
options: {
|
|
153
|
+
customBodyRender: value => {
|
|
154
|
+
const component = (blocklet.children || []).find(x => x.meta.did === value);
|
|
155
|
+
if (!component) {
|
|
156
|
+
return '';
|
|
157
|
+
}
|
|
158
|
+
return /*#__PURE__*/_jsxs(Box, {
|
|
159
|
+
display: "flex",
|
|
160
|
+
alignItems: "center",
|
|
161
|
+
justifyContent: "flex-start",
|
|
162
|
+
children: [/*#__PURE__*/_jsx(BlockletBundleAvatar, {
|
|
163
|
+
size: 14,
|
|
164
|
+
blocklet: component,
|
|
165
|
+
ancestors: [blocklet]
|
|
166
|
+
}), /*#__PURE__*/_jsx(Box, {
|
|
167
|
+
ml: 0.5,
|
|
168
|
+
sx: {
|
|
169
|
+
ml: 0.5,
|
|
170
|
+
color: 'text.primary',
|
|
171
|
+
fontSize: 14
|
|
172
|
+
},
|
|
173
|
+
children: component.meta.title
|
|
174
|
+
})]
|
|
175
|
+
}, value);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
147
178
|
}, {
|
|
148
179
|
label: t('common.updatedAt'),
|
|
149
180
|
name: 'updatedAt',
|
|
@@ -176,7 +207,7 @@ export default function ProjectList() {
|
|
|
176
207
|
});
|
|
177
208
|
}
|
|
178
209
|
}
|
|
179
|
-
}];
|
|
210
|
+
}].filter(Boolean);
|
|
180
211
|
return /*#__PURE__*/_jsxs(Main, {
|
|
181
212
|
children: [/*#__PURE__*/_jsx(Box, {
|
|
182
213
|
sx: {
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { useState, useEffect
|
|
1
|
+
import { useState, useEffect } from 'react';
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
3
|
import styled from '@emotion/styled';
|
|
4
|
-
import difference from 'lodash/difference';
|
|
5
4
|
import joinUrl from 'url-join';
|
|
6
5
|
import Box from '@mui/material/Box';
|
|
7
6
|
import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
|
|
@@ -24,12 +23,6 @@ const fillParent = (nodes, parentId) => {
|
|
|
24
23
|
});
|
|
25
24
|
return nodes;
|
|
26
25
|
};
|
|
27
|
-
const checkDiff = (a, b) => {
|
|
28
|
-
if (a.length !== b.length) {
|
|
29
|
-
return true;
|
|
30
|
-
}
|
|
31
|
-
return !!difference(a, b || []).length;
|
|
32
|
-
};
|
|
33
26
|
export default function Resource({
|
|
34
27
|
app,
|
|
35
28
|
component,
|
|
@@ -45,14 +38,12 @@ export default function Resource({
|
|
|
45
38
|
} = useNodeContext();
|
|
46
39
|
const [resources, setResources] = useState([]);
|
|
47
40
|
const [selectedResourceIds, setSelectedResourceIds] = useState([]);
|
|
48
|
-
const [savedResourceIds, setSavedResourceIds] = useState([]);
|
|
49
41
|
const [loading, setLoading] = useState(false);
|
|
50
42
|
const releaseId = release.id;
|
|
51
43
|
const readonly = release.status === 'published';
|
|
52
44
|
const {
|
|
53
45
|
resourceExportApi = '/'
|
|
54
46
|
} = component?.meta.capabilities || {};
|
|
55
|
-
const hasDiff = useMemo(() => checkDiff(savedResourceIds, selectedResourceIds), [savedResourceIds, selectedResourceIds]);
|
|
56
47
|
const urlObj = new URL(joinUrl('http://127.0.0.1', component.mountPoint, resourceExportApi || '/').replace(/\/+/g, '/'));
|
|
57
48
|
urlObj.searchParams.set('projectId', projectId);
|
|
58
49
|
urlObj.searchParams.set('releaseId', releaseId);
|
|
@@ -69,7 +60,6 @@ export default function Resource({
|
|
|
69
60
|
resources: data
|
|
70
61
|
}
|
|
71
62
|
});
|
|
72
|
-
setSavedResourceIds(data);
|
|
73
63
|
} catch (err) {
|
|
74
64
|
Toast.error(err.message);
|
|
75
65
|
}
|
|
@@ -109,7 +99,6 @@ export default function Resource({
|
|
|
109
99
|
}).then(res => {
|
|
110
100
|
const list = res?.resources || [];
|
|
111
101
|
setSelectedResourceIds(list);
|
|
112
|
-
setSavedResourceIds(list);
|
|
113
102
|
}).catch(err => {
|
|
114
103
|
Toast.error(err.message);
|
|
115
104
|
});
|
|
@@ -138,7 +127,7 @@ export default function Resource({
|
|
|
138
127
|
className: "footer",
|
|
139
128
|
children: /*#__PURE__*/_jsx(Button, {
|
|
140
129
|
variant: "contained",
|
|
141
|
-
disabled: loading
|
|
130
|
+
disabled: loading,
|
|
142
131
|
onClick: () => onSave(),
|
|
143
132
|
children: t('common.save')
|
|
144
133
|
})
|
|
@@ -11,6 +11,7 @@ import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
|
|
|
11
11
|
import ChevronRightIcon from '@mui/icons-material/ChevronRight';
|
|
12
12
|
import OpenInNewIcon from '@mui/icons-material/OpenInNew';
|
|
13
13
|
import { Icon } from '@iconify/react';
|
|
14
|
+
import Images from '../../images';
|
|
14
15
|
|
|
15
16
|
// BFS algorithm to find node by his ID
|
|
16
17
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
@@ -147,6 +148,9 @@ export default function Tree({
|
|
|
147
148
|
}), !!node.description && /*#__PURE__*/_jsx(Box, {
|
|
148
149
|
className: "description",
|
|
149
150
|
children: node.description
|
|
151
|
+
}), !!node.images?.length && /*#__PURE__*/_jsx(Images, {
|
|
152
|
+
className: "images",
|
|
153
|
+
data: node.images
|
|
150
154
|
})]
|
|
151
155
|
})
|
|
152
156
|
}),
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { useMemo } from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import uniq from 'lodash/uniq';
|
|
4
|
+
import upperFirst from 'lodash/upperFirst';
|
|
5
|
+
import Box from '@mui/material/Box';
|
|
6
|
+
import Tag from '@arcblock/ux/lib/Tag';
|
|
7
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
8
|
+
export default function ResourceType({
|
|
9
|
+
blocklet,
|
|
10
|
+
...rest
|
|
11
|
+
}) {
|
|
12
|
+
const types = useMemo(() => {
|
|
13
|
+
return uniq((blocklet?.meta?.resources || []).map(x => upperFirst(x.split('.').slice(-1)[0])).filter(Boolean));
|
|
14
|
+
}, [blocklet]);
|
|
15
|
+
const style = {
|
|
16
|
+
color: '#FFF',
|
|
17
|
+
backgroundColor: '#5B9BD5',
|
|
18
|
+
marginRight: '4px'
|
|
19
|
+
};
|
|
20
|
+
return /*#__PURE__*/_jsx(Box, {
|
|
21
|
+
display: "flex",
|
|
22
|
+
mr: "-4px",
|
|
23
|
+
...rest,
|
|
24
|
+
children: types.map(x => /*#__PURE__*/_jsx(Tag, {
|
|
25
|
+
type: "custom",
|
|
26
|
+
style: style,
|
|
27
|
+
children: x
|
|
28
|
+
}, x))
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
ResourceType.propTypes = {
|
|
32
|
+
blocklet: PropTypes.object.isRequired
|
|
33
|
+
};
|
|
34
|
+
ResourceType.defaultProps = {};
|
|
@@ -14,7 +14,7 @@ import { axios } from '../../util/api';
|
|
|
14
14
|
import { formatError, getWebWalletUrl } from '../../util';
|
|
15
15
|
import { useNodeContext } from '../../contexts/node';
|
|
16
16
|
import useBlockletInfoForConnectDIDSpaces from '../../hooks/use-blocklet-info-for-connect-did-spaces';
|
|
17
|
-
import { extraDIDSpacesCoreUrl, getDIDSpaceDidFromEndpoint, isValidSpaceGatewayUrl } from '../../util/spaces';
|
|
17
|
+
import { extraDIDSpacesCoreUrl, getDIDSpaceDidFromEndpoint, getSpaceGatewayUrl, isValidSpaceGatewayUrl } from '../../util/spaces';
|
|
18
18
|
import { useBlockletStorageContext } from '../../contexts/blocklet-storage';
|
|
19
19
|
/**
|
|
20
20
|
* @description
|
|
@@ -148,12 +148,8 @@ function ConnectTo({
|
|
|
148
148
|
name,
|
|
149
149
|
did
|
|
150
150
|
}) => {
|
|
151
|
-
|
|
152
|
-
if (!
|
|
153
|
-
// eslint-disable-next-line no-param-reassign
|
|
154
|
-
normalizeUrl = `https://${normalizeUrl}`;
|
|
155
|
-
}
|
|
156
|
-
if (!(await isValidSpaceGatewayUrl(normalizeUrl))) {
|
|
151
|
+
const spaceGatewayUrl = await getSpaceGatewayUrl(endpoint);
|
|
152
|
+
if (!(await isValidSpaceGatewayUrl(spaceGatewayUrl))) {
|
|
157
153
|
toast.error(t('storage.spaces.gateway.add.invalidUrl'));
|
|
158
154
|
return;
|
|
159
155
|
}
|
|
@@ -167,7 +163,7 @@ function ConnectTo({
|
|
|
167
163
|
const spaceGateway = {
|
|
168
164
|
name,
|
|
169
165
|
did,
|
|
170
|
-
url:
|
|
166
|
+
url: spaceGatewayUrl,
|
|
171
167
|
endpoint
|
|
172
168
|
};
|
|
173
169
|
await addSpaceGateway(spaceGateway, endpoint);
|
|
@@ -193,19 +189,19 @@ function ConnectTo({
|
|
|
193
189
|
const handleUseSpaceGatewayConnect = async () => {
|
|
194
190
|
try {
|
|
195
191
|
setLoading(true);
|
|
196
|
-
const
|
|
197
|
-
const
|
|
198
|
-
const spaceDid = new URL(
|
|
199
|
-
if (!(await isValidSpaceGatewayUrl(
|
|
192
|
+
const spaceGatewayUrl = await getSpaceGatewayUrl(url);
|
|
193
|
+
const didSpacesCoreUrl = extraDIDSpacesCoreUrl(spaceGatewayUrl);
|
|
194
|
+
const spaceDid = new URL(spaceGatewayUrl).searchParams.get('spaceDid');
|
|
195
|
+
if (!(await isValidSpaceGatewayUrl(didSpacesCoreUrl))) {
|
|
200
196
|
throw new Error(t('storage.spaces.gateway.add.invalidUrl'));
|
|
201
197
|
}
|
|
202
198
|
setAuthorizeConnect(preValue => ({
|
|
203
199
|
...preValue,
|
|
204
200
|
open: true,
|
|
205
|
-
prefix: joinUrl(
|
|
206
|
-
baseUrl: new URL(
|
|
201
|
+
prefix: joinUrl(didSpacesCoreUrl, 'space/api/did'),
|
|
202
|
+
baseUrl: new URL(didSpacesCoreUrl).origin,
|
|
207
203
|
checkFn: axios.create({
|
|
208
|
-
baseURL: joinUrl(
|
|
204
|
+
baseURL: joinUrl(didSpacesCoreUrl, 'space')
|
|
209
205
|
}).get,
|
|
210
206
|
extraParams: {
|
|
211
207
|
appDid: blockletInfo.appDid,
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { createContext, useContext, useEffect, useState } from 'react';
|
|
2
|
+
import { node } from 'prop-types';
|
|
3
|
+
import { isEmpty, merge } from 'lodash';
|
|
4
|
+
import { BLOCKLET_CONFIGURABLE_KEY } from '@blocklet/constant';
|
|
5
|
+
import { useAsyncEffect } from 'ahooks';
|
|
6
|
+
import Toast from '@arcblock/ux/lib/Toast';
|
|
7
|
+
import { useNodeContext } from './node';
|
|
8
|
+
import { getSpaceGateway, getSpaceNameByEndpoint } from '../util/spaces';
|
|
9
|
+
import { useBlockletContext } from './blocklet';
|
|
10
|
+
import useStorageEndpoint from '../hooks/use-storage-endpoint';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @typedef {{
|
|
14
|
+
* did: string,
|
|
15
|
+
* url: string,
|
|
16
|
+
* name: string,
|
|
17
|
+
* endpoint: string,
|
|
18
|
+
* }} SpaceGateway
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @typedef {{
|
|
23
|
+
* loading: boolean,
|
|
24
|
+
* spaceGateway: SpaceGateway,
|
|
25
|
+
* deleteSpaceGateway: (spaceGateway: SpaceGateway) => void | Promise<void>,
|
|
26
|
+
* updateSpaceGateway: (updateSpaceGateway: SpaceGateway) => void | Promise<void>,
|
|
27
|
+
* storageEndpoint: string,
|
|
28
|
+
* settingStorageEndpoint: (endpoint: string) => void | Promise<void>,
|
|
29
|
+
* hasStorageEndpoint: boolean,
|
|
30
|
+
* }} ConfigSpaceContextType
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
/** @type {import('react').Context<ConfigSpaceContextType>} */
|
|
34
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
35
|
+
const ConfigSpaceContext = /*#__PURE__*/createContext({});
|
|
36
|
+
const {
|
|
37
|
+
Provider,
|
|
38
|
+
Consumer
|
|
39
|
+
} = ConfigSpaceContext;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* @description
|
|
43
|
+
* @param {{
|
|
44
|
+
* children: React.ReactNode,
|
|
45
|
+
* }} { children }
|
|
46
|
+
* @return {any}
|
|
47
|
+
*/
|
|
48
|
+
function ConfigSpaceProvider({
|
|
49
|
+
children
|
|
50
|
+
}) {
|
|
51
|
+
const [loading, setLoading] = useState(false);
|
|
52
|
+
const [spaceGateway, setSpaceGateway] = useState(null);
|
|
53
|
+
/**
|
|
54
|
+
* @type {{
|
|
55
|
+
* blocklet: import('@abtnode/client').BlockletState,
|
|
56
|
+
* actions: { refreshBlocklet: Function }
|
|
57
|
+
* }}
|
|
58
|
+
*/
|
|
59
|
+
const {
|
|
60
|
+
blocklet,
|
|
61
|
+
actions: {
|
|
62
|
+
refreshBlocklet
|
|
63
|
+
}
|
|
64
|
+
} = useBlockletContext();
|
|
65
|
+
const {
|
|
66
|
+
storageEndpoint
|
|
67
|
+
} = useStorageEndpoint();
|
|
68
|
+
const {
|
|
69
|
+
api: nodeApi
|
|
70
|
+
} = useNodeContext();
|
|
71
|
+
useAsyncEffect(async () => {
|
|
72
|
+
try {
|
|
73
|
+
setLoading(true);
|
|
74
|
+
if (isEmpty(storageEndpoint)) {
|
|
75
|
+
setSpaceGateway(null);
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
const $spaceGateway = await getSpaceGateway(storageEndpoint);
|
|
79
|
+
setSpaceGateway($spaceGateway);
|
|
80
|
+
} catch (error) {
|
|
81
|
+
console.error(error);
|
|
82
|
+
Toast.error(error.message);
|
|
83
|
+
} finally {
|
|
84
|
+
setLoading(false);
|
|
85
|
+
}
|
|
86
|
+
}, [storageEndpoint]);
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* @description
|
|
90
|
+
* @param {SpaceGateway} spaceGateway
|
|
91
|
+
*/
|
|
92
|
+
const deleteSpaceGateway = () => {
|
|
93
|
+
setSpaceGateway(null);
|
|
94
|
+
refreshBlocklet();
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* @description
|
|
99
|
+
* @param {SpaceGateway} x
|
|
100
|
+
*/
|
|
101
|
+
const updateSpaceGateway = async x => {
|
|
102
|
+
setSpaceGateway(x);
|
|
103
|
+
// eslint-disable-next-line no-use-before-define
|
|
104
|
+
await settingStorageEndpoint(x.endpoint);
|
|
105
|
+
refreshBlocklet();
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* @description
|
|
110
|
+
* @param {string} endpoint
|
|
111
|
+
*/
|
|
112
|
+
const settingStorageEndpoint = async endpoint => {
|
|
113
|
+
await nodeApi.configBlocklet({
|
|
114
|
+
input: {
|
|
115
|
+
did: [blocklet.meta.did],
|
|
116
|
+
configs: [{
|
|
117
|
+
key: BLOCKLET_CONFIGURABLE_KEY.BLOCKLET_APP_SPACE_ENDPOINT,
|
|
118
|
+
value: endpoint
|
|
119
|
+
}]
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
refreshBlocklet();
|
|
123
|
+
};
|
|
124
|
+
useEffect(() => {
|
|
125
|
+
async function syncSpaceGateway() {
|
|
126
|
+
if (!spaceGateway) {
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
const name = await getSpaceNameByEndpoint(spaceGateway.endpoint, spaceGateway.name);
|
|
130
|
+
const latestSpaceGateway = merge(spaceGateway, {
|
|
131
|
+
name
|
|
132
|
+
});
|
|
133
|
+
setSpaceGateway(latestSpaceGateway);
|
|
134
|
+
}
|
|
135
|
+
syncSpaceGateway();
|
|
136
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
137
|
+
}, []);
|
|
138
|
+
const hasStorageEndpoint = Boolean(storageEndpoint && spaceGateway);
|
|
139
|
+
return /*#__PURE__*/_jsx(Provider, {
|
|
140
|
+
value: {
|
|
141
|
+
loading,
|
|
142
|
+
spaceGateway,
|
|
143
|
+
deleteSpaceGateway,
|
|
144
|
+
updateSpaceGateway,
|
|
145
|
+
storageEndpoint,
|
|
146
|
+
settingStorageEndpoint,
|
|
147
|
+
hasStorageEndpoint
|
|
148
|
+
},
|
|
149
|
+
children: children
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
ConfigSpaceProvider.propTypes = {
|
|
153
|
+
children: node.isRequired
|
|
154
|
+
};
|
|
155
|
+
ConfigSpaceProvider.defaultProps = {};
|
|
156
|
+
function useConfigSpaceContext() {
|
|
157
|
+
const res = useContext(ConfigSpaceContext);
|
|
158
|
+
return res;
|
|
159
|
+
}
|
|
160
|
+
export { ConfigSpaceContext, ConfigSpaceProvider, Consumer as ConfigSpaceConsumer, useConfigSpaceContext };
|