@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
@@ -1,1207 +0,0 @@
1
- import { useState, useEffect, lazy, useRef, useCallback, useMemo, Suspense } from 'react';
2
- import { Link, useNavigate, useParams } from 'react-router-dom';
3
- import styled from '@emotion/styled';
4
- import PropTypes from 'prop-types';
5
- import useSetState from 'react-use/lib/useSetState';
6
- import pick from 'lodash/pick';
7
- import joinUrl from 'url-join';
8
- import semver from 'semver';
9
- import pAll from 'p-all';
10
- import Avatar from '@mui/material/Avatar';
11
- import TextField from '@mui/material/TextField';
12
- import Typography from '@mui/material/Typography';
13
- import Breadcrumbs from '@mui/material/Breadcrumbs';
14
- import Box from '@mui/material/Box';
15
- import IconButton from '@mui/material/IconButton';
16
- import DeleteOutlineIcon from '@mui/icons-material/DeleteOutline';
17
- import CloudUploadRoundedIcon from '@mui/icons-material/CloudUploadRounded';
18
- import InputAdornment from '@mui/material/InputAdornment';
19
- import Spinner from '@mui/material/CircularProgress';
20
- import MaterialDialog from '@mui/material/Dialog';
21
- import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
22
- import Button from '@arcblock/ux/lib/Button';
23
- import Toast from '@arcblock/ux/lib/Toast';
24
- import Empty from '@arcblock/ux/lib/Empty';
25
- import Tabs from '@arcblock/ux/lib/Tabs';
26
- import Dialog from '@arcblock/ux/lib/Dialog';
27
- import Alert from '@arcblock/ux/lib/Alert';
28
- import { PROJECT } from '@blocklet/constant';
29
- import { WELLKNOWN_SERVICE_PATH_PREFIX, UNOWNED_DID } from '@abtnode/constant';
30
- import BlockletBundleAvatar from '../bundle-avatar';
31
- import { useNodeContext } from '../../contexts/node';
32
- import { useBlockletContext } from '../../contexts/blocklet';
33
- import EmptySpinner from '../../empty-spinner';
34
- import ClickToCopy from '../../click-to-copy';
35
- import { formatError } from '../../util';
36
- import Resource, { uploadResource } from './resource';
37
- import SelectComponents from './select-components';
38
- import ConnectStoreList from './connect-store-list';
39
- import { createMessageId, waitGetConnectedByStudio, waitGetConnectedStore } from './utils/wait-connect';
40
- import ConnectStoreButton from './connect-store-button';
41
- import uploadImageToProject from './utils/upload-image-to-project';
42
- import useWantToConnectStore from './hooks/use-want-to-connect-store';
43
- import usePromiseWindowOpen from '../../hooks/use-promise-window-open';
44
- import StopBox from './stop-box';
45
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
46
- const allowedFileTypes = ['image/*', '.jpg', '.jpeg', '.png', '.gif', '.svg'];
47
- const maxFileSize = 1024 * 1024 * 10; // 10 MB
48
-
49
- const serverEndpoint = window.env?.serverEndpoint;
50
-
51
- // eslint-disable-next-line import/no-unresolved
52
- const UploaderComponent = /*#__PURE__*/lazy(() => import('@blocklet/uploader/react').then(res => ({
53
- default: res.Uploader
54
- })));
55
- const validateParams = (params, status, t) => {
56
- const errors = [];
57
- if (!params.blockletTitle) {
58
- errors.push({
59
- param: 'blockletTitle',
60
- message: t('blocklet.publish.errorTip.noTitle')
61
- });
62
- }
63
- if (!params.blockletVersion) {
64
- errors.push({
65
- param: 'blockletVersion',
66
- message: t('blocklet.publish.errorTip.noVersion')
67
- });
68
- } else if (!semver.valid(params.blockletVersion)) {
69
- errors.push({
70
- param: 'blockletVersion',
71
- message: 'Invalid Blocklet Version'
72
- });
73
- }
74
- if (status === PROJECT.RELEASE_STATUS.published) {
75
- if (!params.blockletDescription) {
76
- errors.push({
77
- param: 'blockletDescription',
78
- message: t('blocklet.publish.errorTip.noDescription')
79
- });
80
- }
81
- if (!params.note) {
82
- errors.push({
83
- param: 'note',
84
- message: t('blocklet.publish.errorTip.noNote')
85
- });
86
- }
87
- }
88
- return errors.length ? errors : null;
89
- };
90
- const addComponentTabs = ({
91
- tabs,
92
- blocklet,
93
- ancestors = []
94
- }) => {
95
- const key = blocklet.meta.did;
96
- tabs.push({
97
- label: /*#__PURE__*/_jsxs(Box, {
98
- display: "flex",
99
- alignItems: "center",
100
- justifyContent: "flex-start",
101
- children: [/*#__PURE__*/_jsx(BlockletBundleAvatar, {
102
- size: 24,
103
- blocklet: blocklet,
104
- ancestors: ancestors
105
- }), /*#__PURE__*/_jsx(Box, {
106
- ml: "4px",
107
- className: "text",
108
- children: /*#__PURE__*/_jsx(Box, {
109
- children: blocklet.meta.title
110
- })
111
- })]
112
- }, key),
113
- value: key
114
- });
115
- };
116
- const pickParams = (baseParams, app) => {
117
- const params = pick(baseParams, ['blockletVersion', 'blockletTitle', 'blockletDescription', 'blockletLogo', 'blockletIntroduction', 'blockletScreenshots', 'connectedStores', 'blockletComponents', 'lastReleaseId', 'note']);
118
- if (!params.blockletComponents) {
119
- params.blockletComponents = (app.children || []).map(x => ({
120
- did: x.meta.did,
121
- included: false,
122
- required: false
123
- }));
124
- } else {
125
- params.blockletComponents = params.blockletComponents.map(x => ({
126
- ...x,
127
- included: true
128
- }));
129
- }
130
- return params;
131
- };
132
- export default function CreateRelease({
133
- initUrl,
134
- ...rest
135
- }) {
136
- const navigate = useNavigate();
137
- const {
138
- projectId,
139
- releaseId: inputReleaseId,
140
- componentDid = ''
141
- } = useParams();
142
- const {
143
- t,
144
- locale
145
- } = useLocaleContext();
146
- const {
147
- blocklet
148
- } = useBlockletContext();
149
- const [params, setParams] = useSetState({
150
- blockletScreenshots: [],
151
- publishedStoreIds: [],
152
- connectedStores: []
153
- });
154
- const [paramsErrTip, setParamsErrTip] = useState({});
155
- const [loading, setLoading] = useState(false);
156
- const [createLoading, setCreateLoading] = useState(false);
157
- const [release, setRelease] = useSetState(null);
158
- const {
159
- api
160
- } = useNodeContext();
161
- const uploaderLogoRef = useRef(null);
162
- const uploaderScreenshotRef = useRef(null);
163
- const [installResourceTip, setInstallResourceTip] = useState();
164
- const [showStoreDialog, setShowStoreDialog] = useState(false);
165
- const [initialResources, setInitialResources] = useState({});
166
- const [releaseUsedLast, setReleaseUsedLast] = useState(false);
167
- const saveSelectedEventsRef = useRef({});
168
- const [initLogoUrl, setInitLogoUrl] = useState('');
169
- const [wantToConnectStore, setWantToConnectStore] = useWantToConnectStore(blocklet);
170
- const [resourceComponentsMap, _setResourceComponentsMap] = useSetState({});
171
- const dependentComponentsMode = initUrl?.searchParams.get('dependentComponentsMode');
172
- const disabledSelectComponents = dependentComponentsMode === 'readonly';
173
- const setResourceComponentsMap = useCallback(setter => {
174
- if (disabledSelectComponents) {
175
- setParams({
176
- blockletComponents: []
177
- });
178
- }
179
- _setResourceComponentsMap(setter);
180
- }, [disabledSelectComponents, _setResourceComponentsMap, setParams]);
181
- const openWindow = usePromiseWindowOpen({
182
- onOpen: () => setLoading(true),
183
- onClose: () => setLoading(false)
184
- });
185
- const releaseId = inputReleaseId === 'create' ? params?.lastReleaseId || '' : inputReleaseId;
186
- const mode = inputReleaseId === 'create' ? 'create' : 'edit';
187
- const projectType = useMemo(() => params?.blockletComponents?.some(x => x.included) ? 'pack' : 'resource', [params?.blockletComponents]);
188
- const tabs = [];
189
- const resourceComponents = (blocklet?.children || []).filter(x => x.meta.resource?.exportApi).filter(x => !componentDid || x.meta.did === componentDid);
190
- resourceComponents.forEach(item => {
191
- addComponentTabs({
192
- tabs,
193
- blocklet: item,
194
- t,
195
- ancestors: [blocklet]
196
- });
197
- });
198
- const [tab, setTab] = useState(tabs[0]?.value);
199
- const isPublished = !releaseUsedLast && release?.status === 'published';
200
- const readOnly = isPublished;
201
- const resourceRelateComponents = useMemo(() => {
202
- const result = {};
203
- Object.keys(resourceComponentsMap).forEach(key => {
204
- const item = resourceComponentsMap[key];
205
- if (item) {
206
- item.forEach(k => {
207
- result[k] = true;
208
- });
209
- }
210
- });
211
- return result;
212
- }, [resourceComponentsMap]);
213
- const getRelease = async () => {
214
- try {
215
- const res = await api.getRelease({
216
- input: {
217
- did: blocklet.meta.did,
218
- projectId,
219
- releaseId
220
- }
221
- });
222
- setLoading(false);
223
- if (!res.release) {
224
- Toast.error('Release not found');
225
- return;
226
- }
227
- setParams(lastParams => pickParams({
228
- ...lastParams,
229
- ...res.release,
230
- blockletVersion: mode === 'create' ? semver.inc(res.release.blockletVersion, 'patch') : res.release.blockletVersion
231
- }, blocklet));
232
- setRelease(res.release);
233
- } catch (err) {
234
- setLoading(false);
235
- Toast.error(formatError(err));
236
- }
237
- };
238
- const getProject = async () => {
239
- if (projectId === UNOWNED_DID) {
240
- setParams({
241
- blockletVersion: '1.0.0',
242
- blockletTitle: ''
243
- });
244
- return;
245
- }
246
- if (!projectId) {
247
- Toast.error(t('blocklet.publish.errorTip.noDid'));
248
- return;
249
- }
250
- try {
251
- const res = await api.getProject({
252
- input: {
253
- did: blocklet.meta.did,
254
- projectId
255
- }
256
- });
257
- setLoading(false);
258
- const data = res.project || {};
259
- if (!data.blockletVersion) {
260
- data.blockletVersion = '1.0.0';
261
- } else if (mode === 'create' && semver.valid(data.blockletVersion)) {
262
- data.blockletVersion = semver.inc(data.blockletVersion, 'patch');
263
- }
264
- const theParams = pickParams(data, blocklet);
265
- setParams(theParams);
266
- } catch (err) {
267
- setLoading(false);
268
- Toast.error(formatError(err));
269
- }
270
- };
271
- const getData = useCallback(async () => {
272
- if (mode === 'edit') {
273
- if (!releaseId) {
274
- Toast.error('Empty release id');
275
- return;
276
- }
277
- await getProject();
278
- await getRelease();
279
- return;
280
- }
281
- await getProject();
282
- if (releaseId) {
283
- setReleaseUsedLast(true);
284
- await getRelease();
285
- }
286
- // eslint-disable-next-line react-hooks/exhaustive-deps
287
- }, [mode, releaseId]);
288
- const onPublish = () => {
289
- window.parent.postMessage({
290
- event: 'studioDialog.uploaded',
291
- componentDid
292
- }, '*');
293
- getRelease();
294
- };
295
- const onRelease = async status => {
296
- if (!projectId || projectId === UNOWNED_DID) {
297
- Toast.error(t('blocklet.publish.errorTip.noDid'));
298
- return;
299
- }
300
- const errors = validateParams(params, status, t);
301
- if (errors) {
302
- Toast.error(errors.map(x => x.message).join('; '));
303
- setParamsErrTip(errors.reduce((acc, x) => ({
304
- ...acc,
305
- [x.param]: x.message
306
- }), {}));
307
- return;
308
- }
309
- const _params = {
310
- ...params
311
- };
312
- const componentMaps = (blocklet?.children || []).reduce((acc, curr) => {
313
- acc[curr.meta.did] = true;
314
- return acc;
315
- }, {});
316
- Object.keys(resourceRelateComponents).forEach(blockletDid => {
317
- if (!componentMaps[blockletDid]) {
318
- return;
319
- }
320
- let included = false;
321
- if (!disabledSelectComponents) {
322
- _params.blockletComponents.forEach(item => {
323
- if (item.did === blockletDid) {
324
- item.included = true;
325
- item.required = true;
326
- included = true;
327
- }
328
- });
329
- }
330
- if (!included) {
331
- _params.blockletComponents.push({
332
- did: blockletDid,
333
- included: true,
334
- required: true
335
- });
336
- }
337
- });
338
- _params.blockletVersion = semver.valid(_params.blockletVersion);
339
- if (!_params.blockletVersion) {
340
- Toast.error('Invalid Blocklet Version');
341
- setParamsErrTip({
342
- blockletVersion: 'Invalid Blocklet Version'
343
- });
344
- return;
345
- }
346
- if (initLogoUrl) {
347
- try {
348
- const filename = await uploadImageToProject({
349
- did: blocklet.meta.did,
350
- projectId,
351
- imageUrl: initLogoUrl
352
- });
353
- _params.blockletLogo = filename;
354
- setParams({
355
- blockletLogo: filename
356
- });
357
- } catch (err) {
358
- Toast.error(err.message);
359
- return;
360
- }
361
- }
362
- const saveKeys = Object.keys(saveSelectedEventsRef.current);
363
- if (!saveKeys.length) {
364
- Toast.error('No resource selected');
365
- return;
366
- }
367
- setLoading(true);
368
- try {
369
- await pAll(saveKeys.map(x => {
370
- return () => {
371
- const item = saveSelectedEventsRef.current[x];
372
- return uploadResource({
373
- api,
374
- locale,
375
- projectId,
376
- releaseId: releaseUsedLast ? '' : releaseId,
377
- appDid: blocklet.meta.did,
378
- component: item.component,
379
- resources: item.resources,
380
- initUrl
381
- });
382
- };
383
- }), {
384
- concurrency: 2
385
- });
386
- } catch (err) {
387
- Toast.error(err.message);
388
- setLoading(false);
389
- setParamsErrTip({
390
- resources: 'Invalid save the resource'
391
- });
392
- return;
393
- }
394
- _params.blockletTitle = (_params.blockletTitle || '').trim();
395
- _params.blockletDescription = (_params.blockletDescription || '').trim();
396
- _params.blockletIntroduction = (_params.blockletIntroduction || '').trim();
397
- _params.note = (_params.note || '').trim();
398
- _params.blockletComponents = (_params?.blockletComponents || []).filter(x => x.included).map(x => pick(x, ['did', 'required'])).map(JSON.stringify);
399
- setCreateLoading(status);
400
- api.createRelease({
401
- input: {
402
- ..._params,
403
- did: blocklet.meta.did,
404
- projectId,
405
- releaseId: releaseUsedLast ? '' : releaseId,
406
- status
407
- }
408
- }).then(res => {
409
- if (status === 'draft') {
410
- Toast.success(t('blocklet.publish.saveDraftSuccess'));
411
- } else {
412
- setReleaseUsedLast(false);
413
- Toast.success(t('blocklet.publish.createReleaseSuccess'));
414
- window.parent.postMessage({
415
- event: 'studioDialog.released',
416
- componentDid
417
- }, '*');
418
- }
419
- if (mode === 'create') {
420
- const id = res?.release?.id;
421
- navigate(`../${projectId}/${id}`, {
422
- replace: true
423
- });
424
- } else {
425
- getRelease();
426
- }
427
- }).catch(err => {
428
- const msg = formatError(err);
429
- Toast.error(msg);
430
- if (/resource.*empty/.test(msg)) {
431
- setParamsErrTip({
432
- blockletResource: msg
433
- });
434
- }
435
- }).finally(() => {
436
- setCreateLoading(false);
437
- setLoading(false);
438
- });
439
- };
440
- const onOpenConnectStore = async param => {
441
- await waitGetConnectedStore(api, param);
442
- getData();
443
- };
444
- const onOpenConnectByStudio = async param => {
445
- const timer = setTimeout(() => {
446
- setLoading(false);
447
- }, 20000);
448
- const nextBlockletDid = await waitGetConnectedByStudio(api, param);
449
- setLoading(false);
450
- clearTimeout(timer);
451
- window.parent.postMessage({
452
- event: 'studioDialog.connected',
453
- componentDid
454
- }, '*');
455
- navigate(window.location.pathname.replace(`${UNOWNED_DID}/create`, `${nextBlockletDid}/create`), {
456
- replace: true
457
- });
458
- };
459
- const handleConnectByStudio = () => {
460
- if (!params.blockletTitle) {
461
- Toast.error(t('blocklet.publish.errorTip.noTitle'));
462
- return;
463
- }
464
- if (!wantToConnectStore) {
465
- Toast.error('No store found');
466
- return;
467
- }
468
- const messageId = createMessageId();
469
- openWindow(async (newWindow, open) => {
470
- try {
471
- const res = await api.connectByStudio({
472
- input: {
473
- did: blocklet?.meta?.did,
474
- blockletTitle: params?.blockletTitle,
475
- storeUrl: wantToConnectStore.url,
476
- storeId: wantToConnectStore.id,
477
- storeName: wantToConnectStore.name,
478
- type: params?.blockletComponents?.length > 0 ? 'pack' : 'resource',
479
- componentDid,
480
- messageId,
481
- tenantScope: initUrl?.searchParams.get('tenantScope') || ''
482
- }
483
- });
484
- if (!res?.url) {
485
- Toast.error('failed to connect to store');
486
- return;
487
- }
488
- open(res.url);
489
- onOpenConnectByStudio({
490
- did: blocklet?.meta?.did,
491
- projectId: '',
492
- messageId
493
- });
494
- } catch (err) {
495
- const error = formatError(err);
496
- Toast.error(error);
497
- newWindow.document.write(error);
498
- setLoading(false);
499
- }
500
- });
501
- };
502
- const handleChangeSelectedComponents = data => {
503
- setParams({
504
- blockletComponents: data
505
- });
506
- };
507
- useEffect(() => {
508
- getData();
509
- }, [getData]);
510
- useEffect(() => {
511
- if (projectId === UNOWNED_DID && mode === 'create' && initUrl) {
512
- setInitLogoUrl(initUrl.searchParams.get('logo'));
513
- setParams({
514
- blockletTitle: initUrl.searchParams.get('title'),
515
- // blockletLogo: initUrl.searchParams.get('logo'),
516
- blockletDescription: initUrl.searchParams.get('description'),
517
- blockletIntroduction: initUrl.searchParams.get('introduction'),
518
- blockletComponents: JSON.parse(initUrl.searchParams.get('components') || '[]'),
519
- note: initUrl.searchParams.get('note') || 'No note'
520
- });
521
- const resourcesString = initUrl.searchParams.get('resources');
522
- try {
523
- const resources = JSON.parse(resourcesString);
524
- setInitialResources(resources);
525
- } catch (_) {
526
- //
527
- }
528
- }
529
- }, [setParams, projectId, initUrl, mode]);
530
- if (!params && loading) {
531
- return /*#__PURE__*/_jsx(EmptySpinner, {});
532
- }
533
- if (!params) {
534
- return null;
535
- }
536
- const uploadLogoPrefix = `${WELLKNOWN_SERVICE_PATH_PREFIX}/api/project/${blocklet.meta.did}/${projectId}/logo/upload`;
537
- const uploadScreenshotPrefix = `${WELLKNOWN_SERVICE_PATH_PREFIX}/api/project/${blocklet.meta.did}/${projectId}/screenshot/upload`;
538
- const logoUrl = params?.blockletLogo ? `${uploadLogoPrefix}/${params.blockletLogo}` : `${WELLKNOWN_SERVICE_PATH_PREFIX}/static/images/logo.png`;
539
- const screenshotUrls = (params?.blockletScreenshots || []).filter(Boolean).map(x => `${uploadScreenshotPrefix}/${x}`);
540
- const resourceItem = resourceComponents.find(x => x.meta.did === tab);
541
- const allResourceComponentsStop = resourceComponents.every(x => x.status !== 'running');
542
- if (allResourceComponentsStop) {
543
- return /*#__PURE__*/_jsx(StopBox, {
544
- children: t('blocklet.publish.allComponentsNotRunning')
545
- });
546
- }
547
- const resourceContent = resourceItem ? /*#__PURE__*/_jsx(Box, {
548
- children: /*#__PURE__*/_jsx(Resource, {
549
- initialResources: initialResources,
550
- saveSelectedEventsRef: saveSelectedEventsRef,
551
- setResourceComponentsMap: setResourceComponentsMap,
552
- error: paramsErrTip.blockletResource,
553
- app: blocklet,
554
- readOnly: readOnly,
555
- component: resourceItem,
556
- componentDid: componentDid,
557
- initUrl: initUrl,
558
- projectId: projectId === UNOWNED_DID ? '' : projectId,
559
- releaseUsedLast: releaseUsedLast,
560
- release: {
561
- ...release,
562
- id: releaseId
563
- }
564
- })
565
- }) : /*#__PURE__*/_jsx(Box, {
566
- display: "flex",
567
- mt: -3,
568
- children: /*#__PURE__*/_jsx(Empty, {
569
- children: t('common.empty')
570
- })
571
- });
572
- const onTabChange = x => {
573
- setTab(x);
574
- };
575
- let installButton = null;
576
- if (isPublished && serverEndpoint) {
577
- const blockletMetaUrl = joinUrl(serverEndpoint, `/api/project/${blocklet.meta.did}/${projectId}/${releaseId}/release/blocklet.json`);
578
- if (projectType === 'pack') {
579
- const url = new URL(serverEndpoint);
580
- url.pathname = joinUrl(url.pathname, '/launch-blocklet/agreement');
581
- url.searchParams.set('blocklet_meta_url', blockletMetaUrl);
582
- installButton = /*#__PURE__*/_jsx(Button, {
583
- variant: "outlined",
584
- style: {
585
- marginRight: 8
586
- },
587
- children: /*#__PURE__*/_jsx("a", {
588
- href: url.href,
589
- target: "_blank",
590
- rel: "noreferrer",
591
- children: t('common.install')
592
- })
593
- });
594
- } else {
595
- installButton = /*#__PURE__*/_jsxs(_Fragment, {
596
- children: [/*#__PURE__*/_jsx(Button, {
597
- variant: "outlined",
598
- style: {
599
- marginRight: 8
600
- },
601
- onClick: () => setInstallResourceTip(blockletMetaUrl),
602
- children: t('blocklet.publish.copyInstallUrl')
603
- }), /*#__PURE__*/_jsx(MaterialDialog, {
604
- fullWidth: true,
605
- maxWidth: "sm",
606
- open: installResourceTip,
607
- onClose: () => setInstallResourceTip(''),
608
- children: /*#__PURE__*/_jsxs(Box, {
609
- sx: {
610
- py: 5,
611
- px: 4,
612
- wordBreak: 'break-all'
613
- },
614
- children: [/*#__PURE__*/_jsx(Typography, {
615
- variant: "h6",
616
- sx: {
617
- mb: 2
618
- },
619
- children: t('blocklet.publish.installResourceTip')
620
- }), /*#__PURE__*/_jsx(ClickToCopy, {
621
- children: installResourceTip
622
- }), /*#__PURE__*/_jsxs(Typography, {
623
- sx: {
624
- mt: 2
625
- },
626
- children: [t('blocklet.publish.installResourceTip2'), /*#__PURE__*/_jsx("a", {
627
- style: {
628
- marginLeft: 4
629
- },
630
- href: "https://www.arcblock.io/docs/blocklet-developer/R3weqCy7WPI8ggudt0C2alWv",
631
- target: "_blank",
632
- rel: "noreferrer",
633
- children: t('blocklet.publish.installResourceHelp')
634
- })]
635
- })]
636
- })
637
- })]
638
- });
639
- }
640
- }
641
- const resourcesUrlTitle = initUrl?.searchParams.get('resourcesTitle');
642
- const componentsUrlTitle = initUrl?.searchParams.get('componentsTitle');
643
- return /*#__PURE__*/_jsxs(Main, {
644
- ...rest,
645
- children: [/*#__PURE__*/_jsxs(Box, {
646
- className: "sticky-header",
647
- children: [/*#__PURE__*/_jsxs(Breadcrumbs, {
648
- className: "breadcrumbs",
649
- "aria-label": "breadcrumb",
650
- children: [/*#__PURE__*/_jsx(Link, {
651
- to: "../",
652
- children: t('common.blockletStudio')
653
- }), projectId === UNOWNED_DID ? /*#__PURE__*/_jsx(Typography, {
654
- color: "text.primary",
655
- children: params?.blockletTitle || 'Blocklet'
656
- }) : /*#__PURE__*/_jsx(Link, {
657
- to: `../${projectId}`,
658
- children: params?.blockletTitle
659
- }), /*#__PURE__*/_jsx(Typography, {
660
- color: "text.primary",
661
- children: mode === 'create' ? t('common.create') : params?.blockletVersion || t('common.edit')
662
- })]
663
- }), /*#__PURE__*/_jsxs(Box, {
664
- display: "flex",
665
- children: [!isPublished && /*#__PURE__*/_jsxs(Button, {
666
- variant: "contained",
667
- disabled: loading || createLoading,
668
- style: {
669
- marginRight: 12
670
- },
671
- onClick: () => onRelease(PROJECT.RELEASE_STATUS.published),
672
- children: [createLoading === PROJECT.RELEASE_STATUS.published && /*#__PURE__*/_jsx(Spinner, {
673
- size: 14,
674
- sx: {
675
- mr: 0.5
676
- },
677
- color: "inherit"
678
- }), t('common.release')]
679
- }), isPublished && /*#__PURE__*/_jsxs(_Fragment, {
680
- children: [installButton, /*#__PURE__*/_jsx(Button, {
681
- variant: "outlined",
682
- style: {
683
- marginRight: 12
684
- },
685
- children: /*#__PURE__*/_jsx("a", {
686
- href: joinUrl(`${WELLKNOWN_SERVICE_PATH_PREFIX}/api/project/${blocklet.meta.did}/${projectId}/${releaseId}/download/${(release.files || [])[0]}`),
687
- children: t('common.download')
688
- })
689
- }), /*#__PURE__*/_jsxs(Button, {
690
- variant: "contained",
691
- onClick: () => setShowStoreDialog(true),
692
- children: [/*#__PURE__*/_jsx(CloudUploadRoundedIcon, {
693
- style: {
694
- fontSize: '1.3em',
695
- marginRight: 4
696
- }
697
- }), t('common.uploadToStore')]
698
- })]
699
- })]
700
- })]
701
- }), /*#__PURE__*/_jsxs(Box, {
702
- children: [/*#__PURE__*/_jsx(Box, {
703
- pt: 5
704
- }), /*#__PURE__*/_jsxs(Box, {
705
- display: "flex",
706
- className: "section",
707
- children: [/*#__PURE__*/_jsx(Typography, {
708
- variant: "h3",
709
- className: "left",
710
- children: t('blocklet.publish.productTitle')
711
- }), /*#__PURE__*/_jsxs(Box, {
712
- sx: {
713
- flex: 1
714
- },
715
- children: [/*#__PURE__*/_jsx(TextField, {
716
- disabled: readOnly,
717
- label: `Blocklet ${t('common.title')}`,
718
- placeholder: `Blocklet ${t('common.title')}`,
719
- InputProps: {
720
- 'data-cy': 'blocklet-title',
721
- readOnly
722
- },
723
- autoComplete: "off",
724
- variant: "outlined",
725
- fullWidth: true,
726
- required: true,
727
- value: params.blockletTitle || '',
728
- onChange: e => {
729
- setParamsErrTip({
730
- blockletTitle: ''
731
- });
732
- setParams({
733
- blockletTitle: e.target.value
734
- });
735
- },
736
- error: !!paramsErrTip.blockletTitle,
737
- helperText: paramsErrTip.blockletTitle || ''
738
- }), /*#__PURE__*/_jsx(TextField, {
739
- required: true,
740
- label: "Blocklet DID",
741
- fullWidth: true,
742
- readonly: true,
743
- disabled: true,
744
- autoComplete: "off",
745
- variant: "outlined",
746
- InputProps: {
747
- 'data-cy': 'export-blocklet-did',
748
- endAdornment: projectId === UNOWNED_DID && /*#__PURE__*/_jsx(InputAdornment, {
749
- position: "end",
750
- children: /*#__PURE__*/_jsx(ConnectStoreButton, {
751
- blocklet: blocklet,
752
- store: wantToConnectStore,
753
- onChangeStore: setWantToConnectStore,
754
- disabled: !params.blockletTitle || readOnly || loading,
755
- loading: loading,
756
- onClick: handleConnectByStudio
757
- })
758
- })
759
- },
760
- helperText: "",
761
- value: projectId === UNOWNED_DID ? '' : projectId,
762
- sx: {
763
- mt: 3
764
- }
765
- }), /*#__PURE__*/_jsx(TextField, {
766
- disabled: readOnly,
767
- label: `Blocklet ${t('common.description')}`,
768
- placeholder: `Blocklet ${t('common.description')}`,
769
- InputProps: {
770
- 'data-cy': 'blocklet-description',
771
- readOnly
772
- },
773
- required: true,
774
- autoComplete: "off",
775
- variant: "outlined",
776
- fullWidth: true,
777
- value: params.blockletDescription || '',
778
- onChange: e => {
779
- setParamsErrTip({
780
- blockletDescription: ''
781
- });
782
- setParams({
783
- blockletDescription: e.target.value
784
- });
785
- },
786
- error: !!paramsErrTip.blockletDescription,
787
- helperText: paramsErrTip.blockletDescription || '',
788
- sx: {
789
- mt: 3
790
- }
791
- }), /*#__PURE__*/_jsx(TextField, {
792
- disabled: readOnly,
793
- label: `Blocklet ${t('common.introduction')}`,
794
- placeholder: `Blocklet ${t('common.introduction')}`,
795
- InputProps: {
796
- 'data-cy': 'export-blocklet-introduction',
797
- readOnly,
798
- endAdornment: /*#__PURE__*/_jsxs(InputAdornment, {
799
- position: "end",
800
- children: [params?.blockletIntroduction?.length || 0, " / ", PROJECT.MAX_INTRO_LENGTH]
801
- })
802
- },
803
- autoComplete: "off",
804
- variant: "outlined",
805
- fullWidth: true,
806
- multiline: true,
807
- minRows: 4,
808
- value: params.blockletIntroduction || '',
809
- onChange: e => {
810
- setParamsErrTip({
811
- blockletIntroduction: ''
812
- });
813
- setParams({
814
- blockletIntroduction: e.target.value.slice(0, PROJECT.MAX_INTRO_LENGTH)
815
- });
816
- },
817
- error: !!paramsErrTip.blockletIntroduction,
818
- helperText: paramsErrTip.blockletIntroduction || '',
819
- sx: {
820
- mt: 3
821
- }
822
- })]
823
- })]
824
- }), /*#__PURE__*/_jsxs(Box, {
825
- display: "flex",
826
- mt: 3,
827
- className: "section",
828
- children: [/*#__PURE__*/_jsx(Typography, {
829
- variant: "h3",
830
- className: "left",
831
- children: t('blocklet.publish.versionTitle')
832
- }), /*#__PURE__*/_jsxs(Box, {
833
- sx: {
834
- flex: 1
835
- },
836
- children: [/*#__PURE__*/_jsx(TextField, {
837
- required: true,
838
- disabled: readOnly,
839
- label: `Blocklet ${t('common.version')}`,
840
- placeholder: `Blocklet ${t('common.version')}`,
841
- InputProps: {
842
- 'data-cy': 'blocklet-version',
843
- readOnly
844
- },
845
- autoComplete: "off",
846
- variant: "outlined",
847
- fullWidth: true,
848
- value: params.blockletVersion || '',
849
- onChange: e => {
850
- setParamsErrTip({
851
- blockletVersion: ''
852
- });
853
- setParams({
854
- blockletVersion: e.target.value
855
- });
856
- },
857
- error: !!paramsErrTip.blockletVersion,
858
- helperText: paramsErrTip.blockletVersion || ''
859
- }), /*#__PURE__*/_jsx(TextField, {
860
- label: t('blocklet.publish.releaseNote'),
861
- autoComplete: "off",
862
- disabled: readOnly,
863
- variant: "outlined",
864
- InputProps: {
865
- 'data-cy': 'release-note',
866
- readOnly,
867
- endAdornment: /*#__PURE__*/_jsxs(InputAdornment, {
868
- position: "end",
869
- children: [params?.note?.length || 0, " / ", PROJECT.MAX_NOTE_LENGTH]
870
- })
871
- },
872
- fullWidth: true,
873
- multiline: true,
874
- minRows: 4,
875
- required: true,
876
- value: params.note || '',
877
- onChange: e => {
878
- setParamsErrTip({
879
- note: ''
880
- });
881
- setParams({
882
- note: e.target.value.slice(0, PROJECT.MAX_NOTE_LENGTH)
883
- });
884
- },
885
- error: !!paramsErrTip.note,
886
- helperText: paramsErrTip.note || '',
887
- sx: {
888
- mt: 3
889
- }
890
- })]
891
- })]
892
- }), /*#__PURE__*/_jsxs(Box, {
893
- display: "flex",
894
- mt: 3,
895
- className: "section full-width",
896
- children: [/*#__PURE__*/_jsx(Typography, {
897
- variant: "h3",
898
- className: "left",
899
- children: t('blocklet.publish.imgTitle')
900
- }), /*#__PURE__*/_jsxs(Box, {
901
- sx: {
902
- flex: 1
903
- },
904
- children: [/*#__PURE__*/_jsxs(Box, {
905
- display: "flex",
906
- children: [/*#__PURE__*/_jsx(Typography, {
907
- variant: "subtitle1",
908
- sx: {
909
- mr: 2
910
- },
911
- children: t('common.logo')
912
- }), /*#__PURE__*/_jsx(Box, {
913
- sx: {
914
- flex: 1,
915
- cursor: readOnly ? 'default' : 'pointer'
916
- },
917
- children: /*#__PURE__*/_jsx(Avatar, {
918
- variant: "square",
919
- sx: {
920
- width: 80,
921
- height: 80
922
- },
923
- alt: "Blocklet Logo",
924
- src: initLogoUrl || logoUrl,
925
- onClick: () => !readOnly && uploaderLogoRef.current.open()
926
- })
927
- })]
928
- }), /*#__PURE__*/_jsxs(Box, {
929
- display: "flex",
930
- mt: 3,
931
- children: [/*#__PURE__*/_jsx(Typography, {
932
- variant: "subtitle1",
933
- sx: {
934
- mr: 2
935
- },
936
- children: t('common.screenshot')
937
- }), /*#__PURE__*/_jsxs(Box, {
938
- display: "flex",
939
- alignItems: "center",
940
- sx: {
941
- flex: 1,
942
- flexWrap: 'wrap'
943
- },
944
- children: [screenshotUrls.map((x, index) => /*#__PURE__*/_jsxs(Box, {
945
- className: "screenshot",
946
- children: [/*#__PURE__*/_jsx("img", {
947
- alt: "screenshot",
948
- src: x
949
- }), !readOnly && /*#__PURE__*/_jsx(IconButton, {
950
- className: "action",
951
- onClick: () => {
952
- const arr = [...params.blockletScreenshots];
953
- arr.splice(index, 1);
954
- setParams({
955
- blockletScreenshots: arr
956
- });
957
- },
958
- children: /*#__PURE__*/_jsx(DeleteOutlineIcon, {})
959
- })]
960
- })), screenshotUrls.length < 5 && /*#__PURE__*/_jsx(Box, {
961
- sx: {
962
- width: 200,
963
- height: 140,
964
- background: '#eee',
965
- cursor: readOnly ? 'default' : 'pointer',
966
- color: '#999',
967
- mb: 2
968
- },
969
- display: "flex",
970
- justifyContent: "center",
971
- alignItems: "center",
972
- fontSize: 40,
973
- onClick: () => !readOnly && uploaderScreenshotRef.current.open(),
974
- children: "+"
975
- })]
976
- })]
977
- })]
978
- }), /*#__PURE__*/_jsx(Suspense, {
979
- fallback: /*#__PURE__*/_jsx(EmptySpinner, {}),
980
- children: /*#__PURE__*/_jsx(UploaderComponent, {
981
- ref: uploaderLogoRef,
982
- popup: true,
983
- onUploadFinish: result => {
984
- setParams({
985
- blockletLogo: result.data.filename
986
- });
987
- setInitLogoUrl('');
988
- uploaderLogoRef.current.close();
989
- },
990
- plugins: ['ImageEditor'],
991
- installerProps: {
992
- disabled: true
993
- },
994
- apiPathProps: {
995
- uploader: uploadLogoPrefix,
996
- disableMediaKitPrefix: true
997
- },
998
- coreProps: {
999
- restrictions: {
1000
- allowedFileTypes,
1001
- maxFileSize,
1002
- maxNumberOfFiles: 1
1003
- }
1004
- }
1005
- }, "uploader-logo")
1006
- }), /*#__PURE__*/_jsx(Suspense, {
1007
- fallback: /*#__PURE__*/_jsx(EmptySpinner, {}),
1008
- children: /*#__PURE__*/_jsx(UploaderComponent, {
1009
- ref: uploaderScreenshotRef,
1010
- popup: true,
1011
- onUploadFinish: result => {
1012
- const blockletScreenshots = params.blockletScreenshots || [];
1013
- blockletScreenshots.push(result.data?.filename);
1014
- setParams({
1015
- blockletScreenshots
1016
- });
1017
- uploaderScreenshotRef.current.close();
1018
- },
1019
- plugins: ['ImageEditor'],
1020
- apiPathProps: {
1021
- uploader: uploadScreenshotPrefix,
1022
- disableMediaKitPrefix: true
1023
- },
1024
- coreProps: {
1025
- restrictions: {
1026
- allowedFileTypes,
1027
- maxFileSize,
1028
- maxNumberOfFiles: 5 - screenshotUrls.length
1029
- }
1030
- }
1031
- }, "uploader-screenshot")
1032
- })]
1033
- }), /*#__PURE__*/_jsxs(Box, {
1034
- display: "flex",
1035
- mt: 3,
1036
- className: "section full-width",
1037
- children: [/*#__PURE__*/_jsx(Box, {
1038
- className: "left",
1039
- children: /*#__PURE__*/_jsx(Typography, {
1040
- variant: "h3",
1041
- children: resourcesUrlTitle || t('blocklet.publish.resourceTitle')
1042
- })
1043
- }), /*#__PURE__*/_jsxs(Box, {
1044
- sx: {
1045
- flex: 1
1046
- },
1047
- children: [!componentDid && /*#__PURE__*/_jsx(Tabs, {
1048
- tabs: tabs,
1049
- current: tab,
1050
- onChange: onTabChange,
1051
- sx: {
1052
- ml: -2,
1053
- mt: -1.5
1054
- }
1055
- }), /*#__PURE__*/_jsx(Box, {
1056
- children: resourceContent
1057
- })]
1058
- })]
1059
- }), /*#__PURE__*/_jsxs(Box, {
1060
- display: "flex",
1061
- mt: 3,
1062
- className: "section full-width",
1063
- children: [/*#__PURE__*/_jsx(Box, {
1064
- className: "left",
1065
- children: /*#__PURE__*/_jsx(Typography, {
1066
- variant: "h3",
1067
- children: componentsUrlTitle || t('common.components')
1068
- })
1069
- }), /*#__PURE__*/_jsx(Box, {
1070
- sx: {
1071
- flex: 1
1072
- },
1073
- children: /*#__PURE__*/_jsx(SelectComponents, {
1074
- disabled: loading || readOnly,
1075
- app: blocklet,
1076
- value: params?.blockletComponents || [],
1077
- onChange: handleChangeSelectedComponents,
1078
- resourceRelateComponents: resourceRelateComponents,
1079
- dependentComponentsMode: dependentComponentsMode
1080
- })
1081
- })]
1082
- }), /*#__PURE__*/_jsx(Alert, {
1083
- type: "info",
1084
- style: {
1085
- width: '100%'
1086
- },
1087
- children: /*#__PURE__*/_jsx(Box, {
1088
- display: "flex",
1089
- alignItems: "center",
1090
- rel: "noreferrer",
1091
- children: projectType === 'pack' ? t('blocklet.publish.packTip') : t('blocklet.publish.resourceTip')
1092
- })
1093
- })]
1094
- }), /*#__PURE__*/_jsx(Dialog, {
1095
- title: t('common.connectToStore'),
1096
- disableEscapeKeyDown: true,
1097
- disablePortal: false,
1098
- fullWidth: true,
1099
- open: showStoreDialog,
1100
- onClose: () => setShowStoreDialog(false),
1101
- children: /*#__PURE__*/_jsx(ConnectStoreList, {
1102
- projectType: projectType,
1103
- blocklet: blocklet,
1104
- releaseType: params?.blockletComponents?.length > 0 ? 'pack' : 'resource',
1105
- projectId: projectId,
1106
- releaseId: releaseId,
1107
- componentDid: componentDid,
1108
- onPublish: onPublish,
1109
- onOpenConnectStore: onOpenConnectStore,
1110
- onDelete: getData,
1111
- connectedStores: params.connectedStores || [],
1112
- publishedStoreIds: release?.publishedStoreIds
1113
- })
1114
- })]
1115
- });
1116
- }
1117
- CreateRelease.propTypes = {
1118
- initUrl: PropTypes.object
1119
- };
1120
- CreateRelease.defaultProps = {
1121
- initUrl: null
1122
- };
1123
- const Main = styled.div`
1124
- .sticky-header {
1125
- margin-top: -12px;
1126
- padding: 12px 0;
1127
- position: sticky;
1128
- top: 0;
1129
- z-index: 99;
1130
- display: flex;
1131
- align-items: center;
1132
- justify-content: space-between;
1133
- background-color: #fff;
1134
- padding-bottom: 12px;
1135
- border-bottom: ${({
1136
- theme
1137
- }) => `1px solid ${theme.palette.divider}`};
1138
- }
1139
- .screenshot {
1140
- margin-bottom: 16px;
1141
- max-width: 200px;
1142
- max-height: 140px;
1143
- width: 200px;
1144
- height: 140px;
1145
- overflow: hidden;
1146
- display: flex;
1147
- align-items: center;
1148
- justify-content: center;
1149
- background-color: #eee;
1150
- margin-right: 16px;
1151
- position: relative;
1152
- .action {
1153
- visibility: hidden;
1154
- position: absolute;
1155
- top: 0px;
1156
- right: 0px;
1157
- background-color: rgba(0, 0, 0, 0.2);
1158
- color: rgba(255, 255, 255, 0.8);
1159
- }
1160
- &:hover .action {
1161
- visibility: visible;
1162
- }
1163
- }
1164
- .screenshot img {
1165
- width: 100%; /* 图像宽度填充容器 */
1166
- height: auto; /* 图像高度自适应 */
1167
- }
1168
- .section {
1169
- max-width: 800px;
1170
- &.full-width {
1171
- max-width: 100%;
1172
- }
1173
- .MuiTypography-h3 {
1174
- font-size: 1.1rem;
1175
- font-weight: 700;
1176
- }
1177
- .left {
1178
- flex-shrink: 0;
1179
- width: 140px;
1180
- }
1181
- .MuiTabs-indicator {
1182
- display: none;
1183
- }
1184
- .MuiTypography-subtitle1 {
1185
- width: 120px;
1186
- font-weight: 700;
1187
- font-size: 1rem;
1188
- ${({
1189
- theme
1190
- }) => theme.breakpoints.down('sm')} {
1191
- width: 80px;
1192
- }
1193
- }
1194
- }
1195
- .MuiButtonBase-root {
1196
- a {
1197
- color: inherit;
1198
- }
1199
- }
1200
- .MuiInputBase-multiline .MuiInputAdornment-positionEnd {
1201
- align-self: flex-end;
1202
- .MuiTypography-root {
1203
- font-size: 0.8rem;
1204
- }
1205
- font-size: 0.8rem;
1206
- }
1207
- `;