@abtnode/ux 1.16.19-beta-7d3ef675 → 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 +35 -27
- 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-release.js +14 -13
- package/es/blocklet/publish/project-list.js +1 -0
- package/es/blocklet/publish/release-list.js +1 -0
- 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 +2 -0
- package/es/locales/zh.js +2 -0
- package/es/util/index.js +5 -1
- package/es/util/spaces.js +66 -5
- package/lib/blocklet/component/add-component-core.js +44 -36
- 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-release.js +14 -13
- package/lib/blocklet/publish/project-list.js +1 -0
- package/lib/blocklet/publish/release-list.js +1 -0
- 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 +2 -0
- package/lib/locales/zh.js +2 -0
- 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
|
+
`;
|
|
@@ -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';
|
|
@@ -179,7 +179,7 @@ export default function CreateRelease({
|
|
|
179
179
|
Toast.error(formatError(err));
|
|
180
180
|
});
|
|
181
181
|
};
|
|
182
|
-
const getData = () => {
|
|
182
|
+
const getData = useCallback(() => {
|
|
183
183
|
if (mode === 'edit') {
|
|
184
184
|
if (!releaseId) {
|
|
185
185
|
Toast.error('Empty release id');
|
|
@@ -190,11 +190,11 @@ export default function CreateRelease({
|
|
|
190
190
|
if (mode === 'create') {
|
|
191
191
|
getProject();
|
|
192
192
|
}
|
|
193
|
-
|
|
193
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
194
|
+
}, [mode, releaseId]);
|
|
194
195
|
useEffect(() => {
|
|
195
196
|
getData();
|
|
196
|
-
}, []);
|
|
197
|
-
|
|
197
|
+
}, [getData]);
|
|
198
198
|
const onRelease = status => {
|
|
199
199
|
const errors = validateParams(params, status, t);
|
|
200
200
|
if (errors) {
|
|
@@ -234,15 +234,16 @@ export default function CreateRelease({
|
|
|
234
234
|
setCreateLoading(false);
|
|
235
235
|
setLoading(false);
|
|
236
236
|
if (status === 'draft') {
|
|
237
|
-
Toast.success('
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
}
|
|
237
|
+
Toast.success(t('blocklet.publish.saveDraftSuccess'));
|
|
238
|
+
} else {
|
|
239
|
+
Toast.success(t('blocklet.publish.createReleaseSuccess'));
|
|
240
|
+
}
|
|
241
|
+
if (mode === 'create') {
|
|
242
|
+
const id = res?.release?.id;
|
|
243
|
+
navigate(`../${projectId}/${id}`, {
|
|
244
|
+
replace: true
|
|
245
|
+
});
|
|
244
246
|
} else {
|
|
245
|
-
Toast.success('Create Release success');
|
|
246
247
|
getRelease();
|
|
247
248
|
}
|
|
248
249
|
}).catch(err => {
|
|
@@ -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 };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { useTheme } from '@mui/material/styles';
|
|
2
|
+
import useMediaQuery from '@mui/material/useMediaQuery';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @description
|
|
6
|
+
* @export
|
|
7
|
+
* @param {{ key: string | import('@mui/material').Breakpoint }} [{ key }={ key: 'md' }]
|
|
8
|
+
* @return {*}
|
|
9
|
+
*/
|
|
10
|
+
export default function useMobile({
|
|
11
|
+
key
|
|
12
|
+
} = {
|
|
13
|
+
key: 'sm'
|
|
14
|
+
}) {
|
|
15
|
+
const theme = useTheme();
|
|
16
|
+
return useMediaQuery(theme.breakpoints.down(key));
|
|
17
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { useEffect, useState } from 'react';
|
|
2
|
+
import { useBlockletContext } from '../contexts/blocklet';
|
|
3
|
+
import { getDIDSpaceEndpoint } from '../util/spaces';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @description
|
|
7
|
+
* @export
|
|
8
|
+
* @return {{
|
|
9
|
+
* storageEndpoint: string
|
|
10
|
+
* }}
|
|
11
|
+
*/
|
|
12
|
+
export default function useStorageEndpoint() {
|
|
13
|
+
const [storageEndpoint, setStorageEndpoint] = useState(null);
|
|
14
|
+
const {
|
|
15
|
+
blocklet
|
|
16
|
+
} = useBlockletContext();
|
|
17
|
+
useEffect(() => {
|
|
18
|
+
setStorageEndpoint(getDIDSpaceEndpoint(blocklet));
|
|
19
|
+
}, [blocklet]);
|
|
20
|
+
return {
|
|
21
|
+
storageEndpoint
|
|
22
|
+
};
|
|
23
|
+
}
|
package/es/images.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import PropTypes from 'prop-types';
|
|
2
|
+
import styled from '@emotion/styled';
|
|
3
|
+
import Box from '@mui/material/Box';
|
|
4
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
5
|
+
export default function Images({
|
|
6
|
+
data,
|
|
7
|
+
...props
|
|
8
|
+
}) {
|
|
9
|
+
if (!data || !data.length) {
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
return /*#__PURE__*/_jsx(StyledBox, {
|
|
13
|
+
...props,
|
|
14
|
+
children: data.map(item => /*#__PURE__*/_jsx("a", {
|
|
15
|
+
href: item.url,
|
|
16
|
+
target: "_blank",
|
|
17
|
+
rel: "noreferrer",
|
|
18
|
+
children: /*#__PURE__*/_jsx("img", {
|
|
19
|
+
src: item.url,
|
|
20
|
+
alt: item.alt || ''
|
|
21
|
+
})
|
|
22
|
+
}, item.url))
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
Images.propTypes = {
|
|
26
|
+
data: PropTypes.arrayOf(PropTypes.shape({
|
|
27
|
+
url: PropTypes.string,
|
|
28
|
+
alt: PropTypes.string
|
|
29
|
+
}))
|
|
30
|
+
};
|
|
31
|
+
Images.defaultProps = {
|
|
32
|
+
data: []
|
|
33
|
+
};
|
|
34
|
+
const StyledBox = styled(Box)`
|
|
35
|
+
display: flex;
|
|
36
|
+
justify-content: flex-start;
|
|
37
|
+
flex-wrap: wrap;
|
|
38
|
+
margin-bottom: -12px;
|
|
39
|
+
a {
|
|
40
|
+
display: flex;
|
|
41
|
+
}
|
|
42
|
+
img {
|
|
43
|
+
height: 128px;
|
|
44
|
+
cursor: pointer;
|
|
45
|
+
margin-right: 12px;
|
|
46
|
+
margin-bottom: 12px;
|
|
47
|
+
}
|
|
48
|
+
`;
|
package/es/locales/en.js
CHANGED
|
@@ -638,6 +638,8 @@ module.exports = {
|
|
|
638
638
|
createRelease: 'Create a new release',
|
|
639
639
|
deleteReleaseTip: 'The release cannot be recovered after deletion',
|
|
640
640
|
createBlockletDid: 'Create from DID Wallet',
|
|
641
|
+
createReleaseSuccess: 'Release created successfully',
|
|
642
|
+
saveDraftSuccess: 'Draft saved successfully',
|
|
641
643
|
connect: {
|
|
642
644
|
title: 'Create Blocklet DID',
|
|
643
645
|
scan: 'Scan the QR code below to generate Blocklet DID',
|
package/es/locales/zh.js
CHANGED
|
@@ -645,6 +645,8 @@ module.exports = {
|
|
|
645
645
|
createRelease: '创建新的发布',
|
|
646
646
|
deleteReleaseTip: '此发布删除后不可恢复,是否继续?',
|
|
647
647
|
createBlockletDid: '通过 DID 钱包创建',
|
|
648
|
+
createReleaseSuccess: '发布成功',
|
|
649
|
+
saveDraftSuccess: '保存成功',
|
|
648
650
|
connect: {
|
|
649
651
|
title: '创建 Blocklet DID',
|
|
650
652
|
scan: '扫描下面的二维码来生成 Blocklet DID',
|
package/es/util/index.js
CHANGED
|
@@ -615,4 +615,8 @@ export const getSubscriptionURL = async ({
|
|
|
615
615
|
};
|
|
616
616
|
export const nanoid = (length = 16) => [...Array(length)].map(() => Math.random().toString(36)[2]).join('');
|
|
617
617
|
export const getSystemDomains = domains => domains.filter(x => x.isProtected);
|
|
618
|
-
export const getLogoHash = logo => encodeURIComponent((logo || '').split('/').slice(-1)[0].slice(0, 7));
|
|
618
|
+
export const getLogoHash = logo => encodeURIComponent((logo || '').split('/').slice(-1)[0].slice(0, 7));
|
|
619
|
+
const hasRequiredEnvironments = meta => (meta.environments || []).some(x => x.required);
|
|
620
|
+
export const hasRequiredSteps = meta => {
|
|
621
|
+
return !!meta.requirements?.fuels?.length || hasRequiredEnvironments(meta);
|
|
622
|
+
};
|
package/es/util/spaces.js
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import isUrl from 'is-url';
|
|
2
2
|
import { BLOCKLET_CONFIGURABLE_KEY } from '@blocklet/constant';
|
|
3
|
-
import { isObject } from 'lodash';
|
|
3
|
+
import { isObject, isString } from 'lodash';
|
|
4
4
|
import { joinURL } from 'ufo';
|
|
5
5
|
import { api } from './api';
|
|
6
6
|
|
|
7
7
|
/* eslint-disable import/prefer-default-export */
|
|
8
8
|
|
|
9
|
+
/**
|
|
10
|
+
* @typedef {import('../contexts/config-space').SpaceGateway} SpaceGateway
|
|
11
|
+
*/
|
|
12
|
+
|
|
9
13
|
/**
|
|
10
14
|
* @FIXME 希望之后放在 sdk 中 @jianchao
|
|
11
15
|
* @description
|
|
@@ -82,7 +86,7 @@ export function getSpaceBackupEndpoint(environments) {
|
|
|
82
86
|
* @description
|
|
83
87
|
* @export
|
|
84
88
|
* @param {string} endpoint
|
|
85
|
-
* @return {
|
|
89
|
+
* @return {string}
|
|
86
90
|
*/
|
|
87
91
|
export function getSpaceGatewayFromEndpoint(endpoint) {
|
|
88
92
|
return endpoint?.replace(/\/api\/space\/.+/, '');
|
|
@@ -134,7 +138,11 @@ export async function isValidSpaceGatewayUrl(spaceGatewayUrl) {
|
|
|
134
138
|
* @param {string} endpoint
|
|
135
139
|
* @return {Promise<string >}
|
|
136
140
|
*/
|
|
137
|
-
export async function getSpaceNameByEndpoint(endpoint
|
|
141
|
+
export async function getSpaceNameByEndpoint(endpoint, {
|
|
142
|
+
timeout
|
|
143
|
+
} = {
|
|
144
|
+
timeout: 3000
|
|
145
|
+
}) {
|
|
138
146
|
try {
|
|
139
147
|
if (!isUrl(endpoint)) {
|
|
140
148
|
return '';
|
|
@@ -142,7 +150,7 @@ export async function getSpaceNameByEndpoint(endpoint) {
|
|
|
142
150
|
const {
|
|
143
151
|
headers
|
|
144
152
|
} = await api.head(endpoint, {
|
|
145
|
-
timeout
|
|
153
|
+
timeout
|
|
146
154
|
});
|
|
147
155
|
const spaceName = headers['x-space-name'];
|
|
148
156
|
return spaceName ? decodeURIComponent(spaceName) : '';
|
|
@@ -171,4 +179,57 @@ export function getSpaceNftDisplayUrlFromEndpoint(endpoint) {
|
|
|
171
179
|
*/
|
|
172
180
|
export const getDIDSpaceEndpoint = blocklet => {
|
|
173
181
|
return blocklet?.configs?.find(item => item.key === BLOCKLET_CONFIGURABLE_KEY.BLOCKLET_APP_SPACE_ENDPOINT)?.value || null;
|
|
174
|
-
};
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* @description
|
|
186
|
+
* @export
|
|
187
|
+
* @param {string} endpoint
|
|
188
|
+
* @returns {Promise<SpaceGateway>}
|
|
189
|
+
*/
|
|
190
|
+
export async function getSpaceGateway(endpoint) {
|
|
191
|
+
/** @type {SpaceGateway} */
|
|
192
|
+
const spaceGateway = {};
|
|
193
|
+
spaceGateway.did = getDIDSpaceDidFromEndpoint(endpoint);
|
|
194
|
+
spaceGateway.name = await getSpaceNameByEndpoint(endpoint);
|
|
195
|
+
spaceGateway.url = getSpaceGatewayFromEndpoint(endpoint);
|
|
196
|
+
spaceGateway.endpoint = endpoint;
|
|
197
|
+
return spaceGateway;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* @description
|
|
202
|
+
* @export
|
|
203
|
+
* @param {string} anyUrl
|
|
204
|
+
* @param {{
|
|
205
|
+
* timeout: number,
|
|
206
|
+
* withSearchParams: true | false,
|
|
207
|
+
* }} options
|
|
208
|
+
* @returns {Promise<string>}
|
|
209
|
+
*/
|
|
210
|
+
export async function getSpaceGatewayUrl(anyUrl, options = {
|
|
211
|
+
timeout: 30000,
|
|
212
|
+
withSearchParams: true
|
|
213
|
+
}) {
|
|
214
|
+
if (!isString(anyUrl)) {
|
|
215
|
+
throw new Error(`url(${anyUrl}) must be a string`);
|
|
216
|
+
}
|
|
217
|
+
const url = anyUrl.startsWith('http') ? anyUrl : `https://${anyUrl}`;
|
|
218
|
+
const u = new URL(url);
|
|
219
|
+
|
|
220
|
+
/** @type {{ data: import('@blocklet/sdk').WindowBlocklet }} */
|
|
221
|
+
const {
|
|
222
|
+
data: blockletMeta
|
|
223
|
+
} = await api.get(joinURL(u.origin, '/__blocklet__.js?type=json'), {
|
|
224
|
+
timeout: options.timeout
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
/** @type {string} */
|
|
228
|
+
const mountPoint = blockletMeta.componentMountPoints.findLast(x => x.did === 'z8iZnaYxnkMD5AKRjTKiCb8pQr1ut8UantAcf')?.mountPoint;
|
|
229
|
+
if (!mountPoint) {
|
|
230
|
+
throw new Error(`MountPoint(${mountPoint}) not found`);
|
|
231
|
+
}
|
|
232
|
+
const didSpacesCoreUrl = joinURL(u.origin, mountPoint);
|
|
233
|
+
const spaceGatewayUrl = options.withSearchParams && u.searchParams.get('spaceDid') ? joinURL(didSpacesCoreUrl, `?spaceDid=${u.searchParams.get('spaceDid')}`) : didSpacesCoreUrl;
|
|
234
|
+
return spaceGatewayUrl;
|
|
235
|
+
}
|