@abtnode/ux 1.16.27-beta-74c4e335 → 1.16.27-beta-4022dde0

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.
Files changed (42) hide show
  1. package/lib/blocklet/component/add-component/add-component-core.js +4 -5
  2. package/lib/blocklet/component/add-component/step-connect.js +8 -0
  3. package/lib/blocklet/publish/{select-components.js → create-release/blocklets.js} +41 -20
  4. package/lib/blocklet/publish/create-release/branding.js +390 -0
  5. package/lib/blocklet/publish/{connect-store-list.js → create-release/connect-store-list.js} +2 -2
  6. package/lib/blocklet/publish/create-release/header.js +407 -0
  7. package/lib/blocklet/publish/create-release/index.js +575 -0
  8. package/lib/blocklet/publish/create-release/introduction-preview.js +28 -0
  9. package/lib/blocklet/publish/create-release/introduction.js +109 -0
  10. package/lib/blocklet/publish/create-release/release-stepper.js +161 -0
  11. package/lib/blocklet/publish/{resource.js → create-release/resources.js} +37 -21
  12. package/lib/blocklet/publish/create-release/step-icon.js +63 -0
  13. package/lib/blocklet/publish/{stop-box.js → create-release/stop-box.js} +13 -6
  14. package/lib/blocklet/publish/{tree.js → create-release/tree.js} +1 -1
  15. package/lib/blocklet/publish/create-release/version.js +93 -0
  16. package/lib/blocklet/publish/index.js +1 -1
  17. package/lib/blocklet/publish/project-list.js +3 -3
  18. package/lib/blocklet/publish/release-list.js +2 -2
  19. package/lib/blocklet/publish/utils/validate-params.js +92 -0
  20. package/lib/blocklet/router/add-domain.js +3 -2
  21. package/lib/hooks/use-bundle-logo.js +3 -2
  22. package/lib/layout/addon.js +3 -17
  23. package/lib/locales/ar.js +16 -2
  24. package/lib/locales/de.js +16 -2
  25. package/lib/locales/en.js +13 -0
  26. package/lib/locales/es.js +16 -2
  27. package/lib/locales/fr.js +16 -2
  28. package/lib/locales/hi.js +16 -2
  29. package/lib/locales/i18n.db +0 -0
  30. package/lib/locales/id.js +16 -2
  31. package/lib/locales/ja.js +16 -2
  32. package/lib/locales/ko.js +16 -2
  33. package/lib/locales/pt.js +16 -2
  34. package/lib/locales/ru.js +16 -2
  35. package/lib/locales/th.js +16 -2
  36. package/lib/locales/vi.js +16 -2
  37. package/lib/locales/zh-tw.js +16 -2
  38. package/lib/locales/zh.js +16 -2
  39. package/lib/util/index.js +7 -5
  40. package/package.json +18 -18
  41. package/lib/blocklet/publish/create-release.js +0 -1207
  42. /package/lib/blocklet/publish/{connect-store-button.js → create-release/connect-store-button.js} +0 -0
@@ -0,0 +1,407 @@
1
+ import { UNOWNED_DID, WELLKNOWN_SERVICE_PATH_PREFIX } from '@abtnode/constant';
2
+ import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
3
+ import { Box, Breadcrumbs, Button, Typography, Dialog as MaterialDialog } from '@mui/material';
4
+ import styled from '@emotion/styled';
5
+ import { Link, useNavigate } from 'react-router-dom';
6
+ import PropTypes from 'prop-types';
7
+ import { joinURL } from 'ufo';
8
+ import { PROJECT } from '@blocklet/constant';
9
+ import Spinner from '@mui/material/CircularProgress';
10
+ import CloudUploadRoundedIcon from '@mui/icons-material/CloudUploadRounded';
11
+ import semver from 'semver';
12
+ import { useState } from 'react';
13
+ import Toast from '@arcblock/ux/lib/Toast/index';
14
+ import pAll from 'p-all';
15
+ import Dialog from '@arcblock/ux/lib/Dialog';
16
+ import pick from 'lodash/pick';
17
+ import ConnectStoreList from './connect-store-list';
18
+ import { validateParams } from '../utils/validate-params';
19
+ import { waitGetConnectedStore } from '../utils/wait-connect';
20
+ import uploadImageToProject from '../utils/upload-image-to-project';
21
+ import { uploadResource } from './resources';
22
+ import ClickToCopy from '../../../click-to-copy';
23
+ import { formatError } from '../../../util';
24
+ import { useNodeContext } from '../../../contexts/node';
25
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
26
+ const serverEndpoint = window.env?.serverEndpoint;
27
+ function Header({
28
+ projectId,
29
+ params,
30
+ setParamsErrTip,
31
+ initUrl,
32
+ setParams,
33
+ mode,
34
+ loading,
35
+ blocklet,
36
+ release,
37
+ isPublished,
38
+ releaseId,
39
+ getData,
40
+ getRelease,
41
+ componentDid,
42
+ resourceRelateComponents,
43
+ disabledSelectComponents,
44
+ saveSelectedEventsRef,
45
+ isSelectedResources,
46
+ initLogoUrl,
47
+ setLoading,
48
+ releaseUsedLast,
49
+ setReleaseUsedLast,
50
+ projectType
51
+ }) {
52
+ const {
53
+ t,
54
+ locale
55
+ } = useLocaleContext();
56
+ const {
57
+ api
58
+ } = useNodeContext();
59
+ const navigate = useNavigate();
60
+ const [showStoreDialog, setShowStoreDialog] = useState(false);
61
+ const [installResourceTip, setInstallResourceTip] = useState();
62
+ const onPublish = () => {
63
+ window.parent.postMessage({
64
+ event: 'studioDialog.uploaded',
65
+ componentDid
66
+ }, '*');
67
+ getRelease();
68
+ };
69
+ const onRelease = async status => {
70
+ const errors = validateParams({
71
+ params,
72
+ isSelectedResources,
73
+ projectId,
74
+ status,
75
+ t
76
+ });
77
+ if (errors) {
78
+ Toast.error(errors.map(x => x.message).join('; '));
79
+ setParamsErrTip(errors.reduce((acc, x) => ({
80
+ ...acc,
81
+ [x.param]: x.message
82
+ }), {}));
83
+ return;
84
+ }
85
+ const _params = {
86
+ ...params
87
+ };
88
+ const componentMaps = (blocklet?.children || []).reduce((acc, curr) => {
89
+ acc[curr.meta.did] = true;
90
+ return acc;
91
+ }, {});
92
+ Object.keys(resourceRelateComponents).forEach(blockletDid => {
93
+ if (!componentMaps[blockletDid]) {
94
+ return;
95
+ }
96
+ let included = false;
97
+ if (!disabledSelectComponents) {
98
+ _params.blockletComponents.forEach(item => {
99
+ if (item.did === blockletDid) {
100
+ item.included = true;
101
+ item.required = true;
102
+ included = true;
103
+ }
104
+ });
105
+ }
106
+ if (!included) {
107
+ _params.blockletComponents.push({
108
+ did: blockletDid,
109
+ included: true,
110
+ required: true
111
+ });
112
+ }
113
+ });
114
+ _params.blockletVersion = semver.valid(_params.blockletVersion);
115
+ if (!_params.blockletVersion) {
116
+ Toast.error('Invalid Blocklet Version');
117
+ setParamsErrTip({
118
+ blockletVersion: 'Invalid Blocklet Version'
119
+ });
120
+ return;
121
+ }
122
+ if (initLogoUrl) {
123
+ try {
124
+ const filename = await uploadImageToProject({
125
+ did: blocklet.meta.did,
126
+ projectId,
127
+ imageUrl: initLogoUrl
128
+ });
129
+ _params.blockletLogo = filename;
130
+ setParams({
131
+ blockletLogo: filename
132
+ });
133
+ } catch (err) {
134
+ Toast.error(err.message);
135
+ return;
136
+ }
137
+ }
138
+ setLoading(true);
139
+ const saveKeys = Object.keys(saveSelectedEventsRef.current);
140
+ try {
141
+ await pAll(saveKeys.map(x => {
142
+ return () => {
143
+ const item = saveSelectedEventsRef.current[x];
144
+ return uploadResource({
145
+ api,
146
+ locale,
147
+ projectId,
148
+ releaseId: releaseUsedLast ? '' : releaseId,
149
+ appDid: blocklet.meta.did,
150
+ component: item.component,
151
+ resources: item.resources,
152
+ initUrl
153
+ });
154
+ };
155
+ }), {
156
+ concurrency: 2
157
+ });
158
+ } catch (err) {
159
+ Toast.error(err.message);
160
+ setLoading(false);
161
+ setParamsErrTip({
162
+ resources: 'Invalid save the resource'
163
+ });
164
+ return;
165
+ }
166
+ _params.blockletTitle = (_params.blockletTitle || '').trim();
167
+ _params.blockletDescription = (_params.blockletDescription || '').trim();
168
+ _params.blockletIntroduction = (_params.blockletIntroduction || '').trim();
169
+ _params.note = (_params.note || '').trim();
170
+ _params.blockletComponents = (_params?.blockletComponents || []).filter(x => x.included).map(x => pick(x, ['did', 'required'])).map(JSON.stringify);
171
+ setLoading(true);
172
+ api.createRelease({
173
+ input: {
174
+ ..._params,
175
+ did: blocklet.meta.did,
176
+ projectId,
177
+ releaseId: releaseUsedLast ? '' : releaseId,
178
+ status
179
+ }
180
+ }).then(res => {
181
+ if (status === 'draft') {
182
+ Toast.success(t('blocklet.publish.saveDraftSuccess'));
183
+ } else {
184
+ setReleaseUsedLast(false);
185
+ Toast.success(t('blocklet.publish.createReleaseSuccess'));
186
+ window.parent.postMessage({
187
+ event: 'studioDialog.released',
188
+ componentDid
189
+ }, '*');
190
+ }
191
+ if (mode === 'create') {
192
+ const id = res?.release?.id;
193
+ navigate(`../${projectId}/view/${id}`, {
194
+ replace: true
195
+ });
196
+ } else {
197
+ getRelease();
198
+ }
199
+ }).catch(err => {
200
+ const msg = formatError(err);
201
+ Toast.error(msg);
202
+ if (/resource.*empty/.test(msg)) {
203
+ setParamsErrTip({
204
+ blockletResource: msg
205
+ });
206
+ }
207
+ }).finally(() => {
208
+ setLoading(false);
209
+ });
210
+ };
211
+ const onOpenConnectStore = async param => {
212
+ await waitGetConnectedStore(api, param);
213
+ getData();
214
+ };
215
+ let installButton = null;
216
+ if (isPublished && serverEndpoint) {
217
+ const blockletMetaUrl = joinURL(serverEndpoint, `/api/project/${blocklet.meta.did}/${projectId}/${releaseId}/release/blocklet.json`);
218
+ if (projectType === 'pack') {
219
+ const url = new URL(serverEndpoint);
220
+ url.pathname = joinURL(url.pathname, '/launch-blocklet/agreement');
221
+ url.searchParams.set('blocklet_meta_url', blockletMetaUrl);
222
+ installButton = /*#__PURE__*/_jsx("a", {
223
+ href: url.href,
224
+ target: "_blank",
225
+ rel: "noreferrer",
226
+ children: /*#__PURE__*/_jsx(Button, {
227
+ variant: "outlined",
228
+ style: {
229
+ marginRight: 8
230
+ },
231
+ children: t('common.install')
232
+ })
233
+ });
234
+ } else {
235
+ installButton = /*#__PURE__*/_jsxs(_Fragment, {
236
+ children: [/*#__PURE__*/_jsx(Button, {
237
+ variant: "outlined",
238
+ style: {
239
+ marginRight: 8
240
+ },
241
+ onClick: () => setInstallResourceTip(blockletMetaUrl),
242
+ children: t('blocklet.publish.copyInstallUrl')
243
+ }), /*#__PURE__*/_jsx(MaterialDialog, {
244
+ fullWidth: true,
245
+ maxWidth: "sm",
246
+ open: installResourceTip,
247
+ onClose: () => setInstallResourceTip(''),
248
+ children: /*#__PURE__*/_jsxs(Box, {
249
+ sx: {
250
+ py: 5,
251
+ px: 4,
252
+ wordBreak: 'break-all'
253
+ },
254
+ children: [/*#__PURE__*/_jsx(Typography, {
255
+ variant: "h6",
256
+ sx: {
257
+ mb: 2
258
+ },
259
+ children: t('blocklet.publish.installResourceTip')
260
+ }), /*#__PURE__*/_jsx(ClickToCopy, {
261
+ children: installResourceTip
262
+ }), /*#__PURE__*/_jsxs(Typography, {
263
+ sx: {
264
+ mt: 2
265
+ },
266
+ children: [t('blocklet.publish.installResourceTip2'), /*#__PURE__*/_jsx("a", {
267
+ style: {
268
+ marginLeft: 4
269
+ },
270
+ href: "https://www.arcblock.io/docs/blocklet-developer/R3weqCy7WPI8ggudt0C2alWv",
271
+ target: "_blank",
272
+ rel: "noreferrer",
273
+ children: t('blocklet.publish.installResourceHelp')
274
+ })]
275
+ })]
276
+ })
277
+ })]
278
+ });
279
+ }
280
+ }
281
+ return /*#__PURE__*/_jsxs(_Fragment, {
282
+ children: [/*#__PURE__*/_jsx(Content, {
283
+ className: "sticky-header",
284
+ children: /*#__PURE__*/_jsxs(Box, {
285
+ display: "flex",
286
+ alignItems: "center",
287
+ flexDirection: "row",
288
+ children: [/*#__PURE__*/_jsxs(Breadcrumbs, {
289
+ className: "breadcrumbs",
290
+ "aria-label": "breadcrumb",
291
+ children: [/*#__PURE__*/_jsx(Link, {
292
+ to: "../",
293
+ children: t('common.blockletStudio')
294
+ }), projectId === UNOWNED_DID ? /*#__PURE__*/_jsx(Typography, {
295
+ color: "text.primary",
296
+ children: params?.blockletTitle || 'Blocklet'
297
+ }) : /*#__PURE__*/_jsx(Link, {
298
+ to: `../${projectId}`,
299
+ children: params?.blockletTitle
300
+ }), /*#__PURE__*/_jsx(Typography, {
301
+ color: "text.primary",
302
+ children: mode === 'create' ? t('common.create') : params?.blockletVersion || t('common.edit')
303
+ })]
304
+ }), /*#__PURE__*/_jsx(Box, {
305
+ flex: "1"
306
+ }), !isPublished && /*#__PURE__*/_jsxs(Button, {
307
+ variant: "contained",
308
+ disabled: loading,
309
+ style: {
310
+ marginRight: 12
311
+ },
312
+ onClick: () => onRelease(PROJECT.RELEASE_STATUS.published),
313
+ children: [loading && /*#__PURE__*/_jsx(Spinner, {
314
+ size: 14,
315
+ sx: {
316
+ mr: 0.5
317
+ },
318
+ color: "inherit"
319
+ }), t('common.release')]
320
+ }), isPublished && /*#__PURE__*/_jsxs(_Fragment, {
321
+ children: [installButton, /*#__PURE__*/_jsx("a", {
322
+ href: joinURL(`${WELLKNOWN_SERVICE_PATH_PREFIX}/api/project/${blocklet.meta.did}/${projectId}/${releaseId}/download/${(release.files || [])[0]}`),
323
+ children: /*#__PURE__*/_jsx(Button, {
324
+ variant: "outlined",
325
+ style: {
326
+ marginRight: 12
327
+ },
328
+ children: t('common.download')
329
+ })
330
+ }), /*#__PURE__*/_jsxs(Button, {
331
+ variant: "contained",
332
+ onClick: () => setShowStoreDialog(true),
333
+ children: [/*#__PURE__*/_jsx(CloudUploadRoundedIcon, {
334
+ style: {
335
+ fontSize: '1.3em',
336
+ marginRight: 4
337
+ }
338
+ }), t('common.uploadToStore')]
339
+ })]
340
+ })]
341
+ })
342
+ }), /*#__PURE__*/_jsx(Dialog, {
343
+ title: t('common.connectToStore'),
344
+ disableEscapeKeyDown: true,
345
+ disablePortal: false,
346
+ fullWidth: true,
347
+ open: showStoreDialog,
348
+ onClose: () => setShowStoreDialog(false),
349
+ children: /*#__PURE__*/_jsx(ConnectStoreList, {
350
+ projectType: projectType,
351
+ blocklet: blocklet,
352
+ releaseType: params?.blockletComponents?.length > 0 ? 'pack' : 'resource',
353
+ projectId: projectId,
354
+ releaseId: releaseId,
355
+ componentDid: componentDid,
356
+ onPublish: onPublish,
357
+ onOpenConnectStore: onOpenConnectStore,
358
+ onDelete: getData,
359
+ connectedStores: params.connectedStores || [],
360
+ publishedStoreIds: release?.publishedStoreIds
361
+ })
362
+ })]
363
+ });
364
+ }
365
+ Header.propTypes = {
366
+ projectId: PropTypes.string.isRequired,
367
+ params: PropTypes.object.isRequired,
368
+ mode: PropTypes.string.isRequired,
369
+ loading: PropTypes.bool.isRequired,
370
+ blocklet: PropTypes.object.isRequired,
371
+ release: PropTypes.object.isRequired,
372
+ isPublished: PropTypes.bool.isRequired,
373
+ releaseId: PropTypes.string.isRequired,
374
+ getData: PropTypes.func.isRequired,
375
+ getRelease: PropTypes.func.isRequired,
376
+ componentDid: PropTypes.string.isRequired,
377
+ resourceRelateComponents: PropTypes.object.isRequired,
378
+ disabledSelectComponents: PropTypes.bool.isRequired,
379
+ saveSelectedEventsRef: PropTypes.object.isRequired,
380
+ isSelectedResources: PropTypes.bool.isRequired,
381
+ initLogoUrl: PropTypes.string.isRequired,
382
+ setLoading: PropTypes.func.isRequired,
383
+ releaseUsedLast: PropTypes.bool.isRequired,
384
+ setReleaseUsedLast: PropTypes.func.isRequired,
385
+ projectType: PropTypes.string.isRequired,
386
+ setParamsErrTip: PropTypes.func.isRequired,
387
+ setParams: PropTypes.func.isRequired,
388
+ initUrl: PropTypes.object.isRequired
389
+ };
390
+ const Content = styled.div`
391
+ .sticky-header {
392
+ margin-top: -12px;
393
+ padding: 12px 0;
394
+ position: sticky;
395
+ top: 0;
396
+ z-index: 99;
397
+ display: flex;
398
+ align-items: center;
399
+ justify-content: space-between;
400
+ background-color: #fff;
401
+ padding-bottom: 12px;
402
+ border-bottom: ${({
403
+ theme
404
+ }) => `1px solid ${theme.palette.divider}`};
405
+ }
406
+ `;
407
+ export default Header;