@abtnode/ux 1.16.18-beta-adeeb0b3 → 1.16.18-beta-aa01bd8e

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.
@@ -1,1017 +1,47 @@
1
1
  /* eslint-disable react/no-unstable-nested-components */
2
- import { useState, useRef, useImperativeHandle, forwardRef, useEffect } from 'react';
2
+ import { useState } from 'react';
3
3
  import PropTypes from 'prop-types';
4
- import uniqBy from 'lodash/uniqBy';
5
- import flatten from 'lodash/flatten';
6
- import isEmpty from 'lodash/isEmpty';
7
- import isNil from 'lodash/isNil';
8
- import PageHeader from '@blocklet/launcher-layout/lib/page-header';
9
4
  import Dialog from '@arcblock/ux/lib/Dialog';
10
- import Spinner from '@mui/material/CircularProgress';
11
- import DialogContentText from '@mui/material/DialogContentText';
12
- import Typography from '@mui/material/Typography';
13
- import TextField from '@mui/material/TextField';
14
5
  import MenuItem from '@mui/material/MenuItem';
15
6
  import AddIcon from '@mui/icons-material/Link';
16
- import CheckIcon from '@mui/icons-material/Check';
17
7
  import useMediaQuery from '@mui/material/useMediaQuery';
18
8
  import styled from '@emotion/styled';
19
9
  import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
20
- import { BLOCKLET_CONFIGURABLE_KEY, BlockletStatus, BlockletEvents } from '@blocklet/constant';
21
- import Layout from '@blocklet/launcher-layout';
22
- import { StepProvider, useStepContext } from '@blocklet/launcher-layout/lib/context/step';
23
- import Box from '@mui/material/Box';
24
- import { NODE_MODES } from '@abtnode/constant';
25
- import Button from '@arcblock/ux/lib/Button';
26
- import Alert from '@arcblock/ux/lib/Alert';
27
- import AnimationWaiter from '@arcblock/ux/lib/AnimationWaiter';
28
- import ResultMessage from '@blocklet/launcher-layout/lib/launch-result-message';
29
- import { getDisplayName, isFreeBlocklet, getSharedConfigObj, hasStartEngine } from '@blocklet/meta/lib/util';
30
- import urlPathFriendly from '@blocklet/meta/lib/url-path-friendly';
31
- import Toast from '@arcblock/ux/lib/Toast';
10
+ import { getDisplayName } from '@blocklet/meta/lib/util';
11
+ import { STORAGE_KEY_STORE_BLOCKLET, STORAGE_KEY_STORE_SERVER } from '../../util/constants';
32
12
  import { useNodeContext } from '../../contexts/node';
33
- import { useBlockletContext } from '../../contexts/blocklet';
34
- import { getBlockletLogoUrl, getBlockletMetaUrl, isNewStoreUrl, getStoreList, formatError, formatMountPoint } from '../../util';
35
- import SchemaForm from '../../schema-form';
36
- import Required from '../../form/required';
37
- import { ComponentPurchaseSelect } from '../purchase';
38
- import { validatePathPrefix } from '../router/util';
39
- import Agreement from '../agreement';
40
- import InstallFromUrl from '../install-from-url';
41
- import SelectStore from './select-store';
42
- import BlockletList from './store-blocklet-list';
43
- import SpaceConnector from './space-connector';
13
+ import AddComponentCore from './add-component-core';
44
14
  import { jsx as _jsx } from "react/jsx-runtime";
45
15
  import { jsxs as _jsxs } from "react/jsx-runtime";
46
16
  import { Fragment as _Fragment } from "react/jsx-runtime";
47
- const requirePurchase = meta => meta.inStore && isFreeBlocklet(meta) === false;
48
- const getDIDSpaceCapability = meta => {
49
- return meta?.capabilities?.didSpace;
50
- };
51
- /**
52
- * @description
53
- * @param {import('@abtnode/client').BlockletState} blocklet
54
- * @return {string}
55
- */
56
- const getDIDSpaceEndpoint = blocklet => {
57
- return blocklet?.configs?.find(item => item.key === BLOCKLET_CONFIGURABLE_KEY.BLOCKLET_APP_SPACE_ENDPOINT)?.value || null;
58
- };
59
- const hasRequiredEnvironments = meta => (meta.environments || []).some(x => x.required);
60
- const hasMissRequiredConfigs = (configsList, sharedValueMap) => {
61
- return configsList?.some(item => {
62
- return item.required && !sharedValueMap[item.key];
63
- });
64
- };
65
- const getParamsName = (params = {}) => {
66
- return params.title || params.name;
67
- };
68
- const StepContent = /*#__PURE__*/forwardRef(({
69
- meta,
70
- isMobile,
71
- onStepChange
72
- }, ref) => {
73
- const {
74
- steps,
75
- activeStep,
76
- setActiveStepByKey,
77
- setActiveStepByIndex
78
- } = useStepContext();
79
- const {
80
- t,
81
- locale
82
- } = useLocaleContext();
83
- const step = steps[activeStep];
84
- useEffect(() => {
85
- onStepChange(activeStep);
86
- }, [onStepChange, activeStep]);
87
-
88
- // expose the func and activeStep
89
- useImperativeHandle(ref, () => ({
90
- setActiveStepByKey,
91
- setActiveStepByIndex
92
- }));
93
- return /*#__PURE__*/_jsx(DialogContentWrapper, {
94
- component: "div",
95
- className: isMobile ? 'mobileStyle' : '',
96
- children: /*#__PURE__*/_jsx(Layout, {
97
- locale: locale,
98
- blockletMeta: {
99
- title: ' ',
100
- ...meta
101
- },
102
- pcWidth: "100%",
103
- pcHeight: "100%",
104
- logoUrl: meta && meta.logo && meta.registryUrl ? getBlockletLogoUrl({
105
- did: meta.did,
106
- baseUrl: meta.registryUrl,
107
- logoPath: meta.logo
108
- }) : null,
109
- stepTip: t('blocklet.component.add'),
110
- children: /*#__PURE__*/_jsx(RightContent, {
111
- children: step?.body && typeof step.body === 'function' ? step.body() : step.body
112
- })
113
- })
114
- });
115
- });
116
- StepContent.propTypes = {
117
- meta: PropTypes.any,
118
- onStepChange: PropTypes.func.isRequired,
119
- isMobile: PropTypes.bool.isRequired
120
- };
121
- StepContent.defaultProps = {
122
- meta: null
123
- };
124
17
  export default function AddComponent({
125
18
  blocklet,
126
19
  children
127
20
  }) {
128
21
  const {
129
- t,
130
- locale
22
+ t
131
23
  } = useLocaleContext();
132
- const [loading, setLoading] = useState(false);
133
- const [editingItem, setEditingItem] = useState(null);
134
- const [error, setError] = useState('');
135
- const [showDialog, setShowDialog] = useState('');
136
- const [mountPointHelperText, setMountPointHelperText] = useState('');
137
- const {
138
- api,
139
- ws: {
140
- useSubscription
141
- },
142
- inService,
143
- info: nodeInfo
144
- } = useNodeContext();
145
- const {
146
- actions: {
147
- refreshBlocklet: refreshApp
148
- }
149
- } = useBlockletContext();
150
- const [purchaseData, setPurchaseData] = useState(null);
151
- const [isWaitingPurchase, setIsWaitingPurchase] = useState(false);
152
- const initParams = {
153
- bundleDid: '',
154
- componentDid: '',
155
- componentName: '',
156
- pathPrefix: '',
157
- name: '',
158
- title: '',
159
- configsList: [],
160
- configsValue: {},
161
- hasMissRequiredConfigs: false,
162
- hasEnvironmentsStep: false,
163
- hasRequiredEnvironments: false,
164
- requirePurchase: false,
165
- didSpaceCapability: null,
166
- installResultProps: {},
167
- purchaseResultProps: {},
168
- showFromUrlDialog: false
169
- };
170
- const [params, setParams] = useState(initParams);
171
- const [activeStep, setActiveStep] = useState(0);
172
- const component = useRef({});
173
- const stepRef = useRef({});
174
- const purchaseRef = useRef({});
24
+ const [showDialog, setShowDialog] = useState(false);
175
25
  const isMobile = useMediaQuery(theme => theme.breakpoints.down('md'));
176
26
  const {
177
- meta
178
- } = component.current;
179
- // eslint-disable-next-line no-unused-vars
180
- const {
181
- setActiveStepByIndex
182
- } = stepRef.current || {};
183
- const isServerlessMode = nodeInfo.mode === NODE_MODES.SERVERLESS;
184
- const updateParams = obj => setParams(x => ({
185
- ...x,
186
- ...obj
187
- }));
188
- useEffect(() => {
189
- if (params.pathPrefix) {
190
- const {
191
- errMsg
192
- } = validateInput({
193
- ...params,
194
- pathPrefix: params.pathPrefix,
195
- locale
196
- });
197
- setError(errMsg);
198
- }
199
- }, [params.pathPrefix]); // eslint-disable-line
200
-
201
- useEffect(() => {
202
- if (activeStep === 0) {
203
- // reset params, when step change to select component
204
- setParams(initParams);
205
- }
206
- }, [activeStep]); // eslint-disable-line
207
-
208
- const getComponentName = () => {
209
- if (component?.current?.meta) {
210
- return getDisplayName(component.current);
211
- }
212
- return '';
213
- };
214
- const setInstallErrorResult = errorMessage => {
215
- const update = _loading => {
216
- updateParams({
217
- installResultProps: {
218
- variant: 'error',
219
- title: getComponentName(),
220
- subTitle: errorMessage,
221
- footer: /*#__PURE__*/_jsx(Button, {
222
- className: "bottom-button",
223
- disabled: _loading,
224
- "data-cy": "retry-install-component",
225
- onClick: async () => {
226
- // set button disabled and show spinner
227
- update(true);
228
- await onInstall(component.current.installInput);
229
- },
230
- children: /*#__PURE__*/_jsxs(Box, {
231
- display: "flex",
232
- alignItems: "center",
233
- children: [_loading && /*#__PURE__*/_jsx(Spinner, {
234
- size: 16,
235
- style: {
236
- marginRight: 8
237
- }
238
- }), t('common.retry')]
239
- })
240
- })
241
- }
242
- });
243
- };
244
- update();
245
- };
246
- const createBlockletEventHandler = handler => {
247
- return b => {
248
- if ((b?.meta?.did || b?.meta) === blocklet?.meta?.did) {
249
- handler(b);
250
- }
251
- };
252
- };
253
- useSubscription(BlockletEvents.statusChange, createBlockletEventHandler(e => {
254
- switch (e.status) {
255
- case BlockletStatus.upgrading:
256
- updateParams({
257
- installResultProps: {
258
- variant: 'success',
259
- title: getComponentName(),
260
- subTitle: t('blocklet.component.installSuccessTip')
261
- }
262
- });
263
- break;
264
- default:
265
- }
266
- }), [blocklet?.meta?.did]);
267
- useSubscription(BlockletEvents.downloadFailed, createBlockletEventHandler(() => {
268
- setInstallErrorResult(t('blocklet.component.installComponentError'));
269
- }), [blocklet?.meta?.did]);
270
- useSubscription(BlockletEvents.installFailed, createBlockletEventHandler(() => {
271
- setInstallErrorResult(t('blocklet.component.installComponentError'));
272
- }), [blocklet?.meta?.did]);
27
+ inService
28
+ } = useNodeContext();
273
29
  const onClose = () => {
274
- setLoading(false);
275
30
  setShowDialog(false);
276
- setParams({});
277
- component.current = {};
278
- };
279
- const onInstall = async payload => {
280
- const {
281
- pathPrefix: mountPoint,
282
- bundleDid,
283
- title,
284
- componentName = '',
285
- componentDid = ''
286
- } = params;
287
- // eslint-disable-next-line no-shadow
288
- const {
289
- configs = [],
290
- registryUrl,
291
- inStore,
292
- inputUrl
293
- } = component.current?.meta || {};
294
- const downloadTokenList = component.current?.downloadTokenList;
295
- const url = inStore ? getBlockletMetaUrl(registryUrl, bundleDid) : inputUrl;
296
- setLoading(true);
297
- const installInput = {
298
- rootDid: blocklet.meta.did,
299
- url,
300
- mountPoint: urlPathFriendly(mountPoint),
301
- title,
302
- name: componentName,
303
- did: componentDid,
304
- // if blocklet has config, provide the configs
305
- ...(params.hasEnvironmentsStep && configs.length > 0 ? {
306
- configs: configs.map(item => {
307
- return {
308
- ...item,
309
- value: params.configsValue[item.key] || ''
310
- };
311
- })
312
- } : {}),
313
- ...(downloadTokenList ? {
314
- downloadTokenList
315
- } : {}),
316
- ...payload
317
- };
318
- try {
319
- await api.installComponent({
320
- input: installInput
321
- });
322
- if (registryUrl) {
323
- const {
324
- teamDid,
325
- storeList
326
- } = getStoreList({
327
- fromBlocklet: inService,
328
- nodeInfo,
329
- blocklet
330
- });
331
- const {
332
- isNew,
333
- decoded
334
- } = isNewStoreUrl(registryUrl, storeList);
335
- if (isNew) {
336
- await api.addBlockletStore({
337
- input: {
338
- teamDid,
339
- url: decoded
340
- }
341
- });
342
- }
343
- }
344
- updateParams({
345
- installResultProps: {}
346
- });
347
-
348
- // let app state refresh fast before receive subscribe event
349
- refreshApp({
350
- showError: false,
351
- attachRuntimeInfo: false
352
- });
353
- } catch (err) {
354
- const errMsg = formatError(err);
355
- Toast.error(errMsg);
356
- console.error('installComponent error: ', err);
357
- setInstallErrorResult(errMsg);
358
- } finally {
359
- setLoading(false);
360
- component.current.installInput = installInput;
361
- }
362
- };
363
- const validateInput = input => {
364
- // FIXME: validatePathPrefix should be updated
365
- const errMsg = validatePathPrefix({
366
- params: {
367
- ...input,
368
- did: input.bundleDid
369
- },
370
- blocklets: [blocklet],
371
- // blocklets: component.current?.blocklets?.map(x => ({ meta: x })) || [],
372
- blocklet,
373
- locale
374
- });
375
- return {
376
- errMsg
377
- };
378
- };
379
- const onNext = async payload => {
380
- const {
381
- errMsg
382
- } = validateInput({
383
- ...params,
384
- locale
385
- });
386
- setError(errMsg);
387
-
388
- // the step can complete, install component
389
- if (activeStep === steps.length - 2) {
390
- await onInstall(payload);
391
- }
392
- setActiveStepByIndex(x => x + 1);
393
- };
394
- const onCancel = () => {
395
- setActiveStepByIndex(x => x - 1);
396
- };
397
- const onGeneratePurchaseData = () => {
398
- const {
399
- pathPrefix: mountPoint,
400
- bundleDid,
401
- title,
402
- componentName = '',
403
- componentDid = ''
404
- } = params;
405
-
406
- // eslint-disable-next-line no-shadow
407
- const {
408
- meta = {}
409
- } = component.current || {};
410
- const {
411
- registryUrl,
412
- inStore,
413
- inputUrl
414
- } = meta;
415
- const url = inStore ? getBlockletMetaUrl(registryUrl, bundleDid) : inputUrl;
416
- setPurchaseData({
417
- meta,
418
- installOpts: {
419
- type: 'component',
420
- rootDid: blocklet.meta.did,
421
- mountPoint,
422
- url,
423
- title,
424
- name: componentName,
425
- did: componentDid
426
- }
427
- });
428
- };
429
- const onCancelPurchase = errorMessage => {
430
- setIsWaitingPurchase(false);
431
- updateParams({
432
- purchaseResultProps: {
433
- variant: 'error',
434
- title: getComponentName(),
435
- subTitle: errorMessage,
436
- style: {
437
- paddingTop: 120
438
- },
439
- footer: /*#__PURE__*/_jsx(Button, {
440
- className: "bottom-button",
441
- "data-cy": "retry-purchase-component",
442
- onClick: () => {
443
- updateParams({
444
- purchaseResultProps: {}
445
- });
446
- },
447
- children: t('common.retry')
448
- })
449
- }
450
- });
451
- };
452
- const onSuccessPurchase = ({
453
- downloadTokenList
454
- }) => {
455
- component.current.downloadTokenList = downloadTokenList;
456
- setIsWaitingPurchase(false);
457
- onNext();
458
- };
459
- const setConfigValue = ({
460
- chooseParams = component.current,
461
- componentDid: componentDidValue,
462
- isInit = false
463
- }) => {
464
- // eslint-disable-next-line no-shadow
465
- const {
466
- meta,
467
- registryUrl,
468
- inStore,
469
- inputUrl
470
- } = chooseParams;
471
- const {
472
- did: bundleDid,
473
- title,
474
- name
475
- } = meta;
476
-
477
- // deleted history list
478
- const list = (blocklet.settings?.children || []).filter(x => x.status === 'deleted' && x.meta.bundleDid === bundleDid);
479
- const componentDid = componentDidValue || '';
480
- const newConfigs = meta.environments?.map(item => {
481
- const {
482
- name: key,
483
- validation,
484
- ...rest
485
- } = item;
486
- const formatItem = {
487
- // if the blocklet has validation, provide the validation (fix not inStore)
488
- validation: isNil(validation) ? '' : validation
489
- };
490
- return {
491
- ...rest,
492
- key,
493
- ...formatItem
494
- };
495
- });
496
- component.current = {
497
- ...chooseParams,
498
- meta: {
499
- ...meta,
500
- // init configs from environments
501
- configs: newConfigs,
502
- registryUrl,
503
- inStore,
504
- inputUrl
505
- }
506
- };
507
- let doc = {};
508
-
509
- // if is init, should update configs
510
- if (isInit) {
511
- const ancestors = [blocklet];
512
-
513
- // component config
514
- const componentSelfConfigs = newConfigs || [];
515
-
516
- // TODO: meta not include children environments/configs before install, waiting for next sprint to design
517
- const componentChildrenConfigs = [];
518
-
519
- // eslint-disable-next-line
520
- // chooseBlocklet?.children?.map(childBlocklet => {
521
- // // eslint-disable-next-line no-shadow
522
- // forEachChildSync(childBlocklet, (b, { ancestors }) => {
523
- // const ancestorDids = ancestors.slice(1).map(x => x.meta.did);
524
-
525
- // componentChildrenConfigs.push(
526
- // (b.configs || []).map(x => ({ ...x, childDid: ancestorDids.concat(b.meta.did) }))
527
- // );
528
- // });
529
-
530
- // return false;
531
- // });
532
-
533
- const componentAllConfigs = uniqBy(flatten([...componentSelfConfigs, ...componentChildrenConfigs]), 'key').filter(x => !!x.key).sort((a, b) => {
534
- if (a.required && !b.required) {
535
- return -1;
536
- }
537
- if (b.required && !a.required) {
538
- return 1;
539
- }
540
- return 0;
541
- });
542
- const sharedConfigObj = getSharedConfigObj(ancestors[0], {
543
- configs: componentAllConfigs
544
- });
545
- const configsValue = {};
546
- const configsList = componentAllConfigs.map(item => {
547
- const {
548
- default: defaultValue,
549
- key,
550
- ...rest
551
- } = item;
552
- configsValue[key] = sharedConfigObj[key] || defaultValue;
553
- return {
554
- ...rest,
555
- key,
556
- hidden: !!BLOCKLET_CONFIGURABLE_KEY[key]
557
- };
558
- });
559
- doc = {
560
- ...doc,
561
- configsList,
562
- configsValue,
563
- hasMissRequiredConfigs: hasMissRequiredConfigs(configsList, configsValue)
564
- };
565
- }
566
- const hasRootPath = blocklet.children.some(x => x.mountPoint === '/');
567
-
568
- // use deleted history
569
- const config = list.find(x => x.meta.bundleDid === bundleDid);
570
- if (config) {
571
- doc = {
572
- ...doc,
573
- pathPrefix: config.mountPoint,
574
- title: title || '',
575
- componentName: config.meta.name,
576
- // use history's environments
577
- hasEnvironmentsStep: false
578
- };
579
- } else {
580
- doc = {
581
- ...doc,
582
- pathPrefix: hasRootPath ? `/${urlPathFriendly(title) || urlPathFriendly(name)}` : '/',
583
- title: title || '',
584
- componentName: '',
585
- hasEnvironmentsStep: component.current.meta?.environments?.length > 0
586
- };
587
- }
588
-
589
- // eslint-disable-next-line no-shadow
590
- const componentRequirePurchase = requirePurchase(component.current.meta);
591
- const componentDIDSpaceCapability = getDIDSpaceCapability(component.current.meta);
592
- const didSpaceEndpoint = getDIDSpaceEndpoint(blocklet);
593
- updateParams({
594
- bundleDid,
595
- componentDid,
596
- ...doc,
597
- hasRequiredEnvironments: hasRequiredEnvironments(component.current.meta),
598
- requirePurchase: componentRequirePurchase,
599
- didSpaceCapability: componentDIDSpaceCapability,
600
- didSpaceEndpoint
601
- });
602
- if (isInit && componentRequirePurchase) {
603
- onGeneratePurchaseData();
604
- }
605
31
  };
606
- const steps = [{
607
- key: 'selectComponent',
608
- name: t('blocklet.component.selectComponent'),
609
- body: /*#__PURE__*/_jsxs(TypographyWrapper, {
610
- component: "div",
611
- children: [params.showFromUrlDialog && /*#__PURE__*/_jsx(InstallFromUrl
612
- // if not set defaultUrl, the dialog will always show step 1 when the dialog is opened
613
- // defaultUrl={meta?.inputUrl}
614
- , {
615
- mode: "component",
616
- onCancel: () => {
617
- updateParams({
618
- showFromUrlDialog: false
619
- });
620
- }
621
- // eslint-disable-next-line no-shadow
622
- ,
623
- onSuccess: ({
624
- meta,
625
- inputUrl,
626
- inStore,
627
- registryUrl
628
- }) => {
629
- setConfigValue({
630
- chooseParams: {
631
- meta,
632
- inputUrl,
633
- inStore,
634
- registryUrl
635
- },
636
- isInit: true
637
- });
638
- updateParams({
639
- showFromUrlDialog: false
640
- });
641
- onNext();
642
- },
643
- handleText: {
644
- title: t('blocklet.component.addComponentTip.fromUrl'),
645
- confirm: t('blocklet.component.choose')
646
- }
647
- }), /*#__PURE__*/_jsx(SelectStore, {
648
- extra: !isServerlessMode ? /*#__PURE__*/_jsxs(Button, {
649
- variant: "text",
650
- color: "primary",
651
- "data-cy": "add-component-from-url",
652
- onClick: () => {
653
- updateParams({
654
- showFromUrlDialog: true
655
- });
656
- },
657
- style: {
658
- padding: '0 2px'
659
- },
660
- children: [/*#__PURE__*/_jsx(AddIcon, {
661
- style: {
662
- fontSize: 20,
663
- marginRight: 4
664
- }
665
- }), " ", t('blocklet.component.addComponentTip.fromUrl'), ' ']
666
- }) : null,
667
- loading: loading,
668
- onChange: () => {
669
- setParams({});
670
- component.current = {};
671
- },
672
- children: ({
673
- currentRegistry
674
- }) => {
675
- return /*#__PURE__*/_jsx(BlockletList, {
676
- serverVersion: nodeInfo?.version,
677
- style: isMobile ? {
678
- // should remove other dom height/margin
679
- height: 'calc(100vh - 56px - 80px - 32px - 40px )'
680
- } : {
681
- height: 'calc(100% - 40px)'
682
- },
683
- storeUrl: currentRegistry.url,
684
- handleButtonClick: chooseParams => {
685
- setConfigValue({
686
- chooseParams: {
687
- ...chooseParams,
688
- inStore: true // choose from store, must be inStore
689
- },
690
-
691
- isInit: true
692
- });
693
- },
694
- handleBlockletRender: ({
695
- blocklet: blockletItem,
696
- defaultRender
697
- }) => {
698
- const isChosen = params?.bundleDid && params?.bundleDid === blockletItem?.did;
699
- return /*#__PURE__*/_jsxs(StoreBlockletItemWrapper, {
700
- children: [isChosen && /*#__PURE__*/_jsx("div", {
701
- className: "check-container",
702
- children: /*#__PURE__*/_jsx(CheckIcon, {
703
- className: "check-icon"
704
- })
705
- }), /*#__PURE__*/_jsx("div", {
706
- className: isChosen ? 'choose-blocklet' : '',
707
- style: {
708
- marginLeft: 16
709
- },
710
- children: defaultRender
711
- })]
712
- });
713
- },
714
- extraFilter: allBlocklets => {
715
- // only use blocklets that are component
716
- return allBlocklets?.filter(x => {
717
- if ((blocklet.children || []).some(y => y.meta.did === x.did)) {
718
- return false;
719
- }
720
- return true;
721
- });
722
- }
723
- });
724
- }
725
- })]
726
- }),
727
- cancel: t('common.cancel'),
728
- confirm: getParamsName(params) ? t('blocklet.component.addNext', {
729
- name: getParamsName(params)
730
- }) : t('common.next'),
731
- onCancel: onClose,
732
- onConfirm: () => {
733
- onNext();
734
- }
735
- }, {
736
- key: 'agreement',
737
- name: t('launchBlocklet.introduction'),
738
- body: /*#__PURE__*/_jsxs(TypographyWrapper, {
739
- component: "div",
740
- className: "agreement-wrapper",
741
- children: [/*#__PURE__*/_jsx(PageHeader, {
742
- title: t('launchBlocklet.introduction'),
743
- subTitle: t('blocklet.component.addComponentTip.introduction')
744
- }), /*#__PURE__*/_jsx(Agreement, {
745
- meta: meta,
746
- onClickNext: onNext,
747
- handleDescEle: /*#__PURE__*/_jsxs(_Fragment, {
748
- children: [/*#__PURE__*/_jsx("p", {
749
- children: /*#__PURE__*/_jsx("div", {
750
- // eslint-disable-next-line
751
- dangerouslySetInnerHTML: {
752
- __html: t(`blocklet.component.addComponentTip.${params.requirePurchase ? 'isPurchase' : 'isFree'}`, {
753
- name: getComponentName()
754
- })
755
- }
756
- })
757
- }), /*#__PURE__*/_jsx("p", {
758
- children: t('blocklet.component.addComponentTip.belowInformation')
759
- })]
760
- })
761
- })]
762
- }),
763
- cancel: t('common.pre'),
764
- confirm: t('launchBlocklet.next'),
765
- onCancel,
766
- onConfirm: () => {
767
- setIsWaitingPurchase(false);
768
- onNext();
769
- }
770
- }, meta && params.requirePurchase && {
771
- key: 'purchase',
772
- name: /*#__PURE__*/_jsxs(_Fragment, {
773
- children: [t('common.verifyNFT'), /*#__PURE__*/_jsx(Required, {})]
774
- }),
775
- body: /*#__PURE__*/_jsxs(TypographyWrapper, {
776
- component: "div",
777
- className: "flex-align-center",
778
- style: {
779
- flexDirection: 'column'
780
- },
781
- children: [!(purchaseRef.current?.getCurrentStep?.() === 2 || isWaitingPurchase) && /*#__PURE__*/_jsx(PageHeaderWrapper, {
782
- title: t('common.verifyNFT'),
783
- subTitle: t('blocklet.component.addComponentTip.verifyNFT')
784
- }), !isEmpty(params.purchaseResultProps) ? /*#__PURE__*/_jsx("div", {
785
- className: "flex-align-center flex-justify-center",
786
- children: /*#__PURE__*/_jsx(ResultMessage, {
787
- ...params.purchaseResultProps
788
- })
789
- }) : purchaseData && /*#__PURE__*/_jsx(ComponentPurchaseSelect, {
790
- ref: purchaseRef,
791
- meta: purchaseData.meta
792
- // if select deleted history, use verify mode
793
- ,
794
- mode: params.componentDid ? 'verify' : 'both',
795
- onCancel: onCancelPurchase,
796
- installOpts: purchaseData.installOpts,
797
- handlePaySuccess: onSuccessPurchase
798
- })]
799
- }),
800
- disabled: purchaseRef.current?.getCurrentStep?.() === 2 || isWaitingPurchase,
801
- cancel: t('common.pre'),
802
- confirm: t('common.next'),
803
- onConfirm: () => {
804
- if (typeof purchaseRef.current.onNext === 'function') {
805
- purchaseRef.current.onNext();
806
- setIsWaitingPurchase(true);
807
- }
808
- },
809
- onCancel: () => {
810
- onCancel();
811
- }
812
- }, hasStartEngine(meta) && {
813
- key: 'config',
814
- name: t('common.config'),
815
- error,
816
- body: /*#__PURE__*/_jsxs(TypographyWrapper, {
817
- component: "div",
818
- children: [/*#__PURE__*/_jsx(PageHeaderWrapper, {
819
- title: t('common.config'),
820
- subTitle: t('blocklet.component.addComponentTip.config')
821
- }), /*#__PURE__*/_jsx(TextField, {
822
- label: t('blocklet.component.mountPoint'),
823
- autoComplete: "off",
824
- variant: "outlined",
825
- name: "pathPrefix",
826
- inputProps: {
827
- 'data-cy': 'mount-point-input'
828
- },
829
- fullWidth: true,
830
- helperText: mountPointHelperText || t('blocklet.component.mountPointTip'),
831
- style: {
832
- marginBottom: 32
833
- },
834
- margin: "normal",
835
- value: params.pathPrefix,
836
- onChange: e => {
837
- const pathPrefix = e.target.value;
838
- updateParams({
839
- pathPrefix
840
- });
841
- setMountPointHelperText(t('common.slugifyHint', {
842
- value: formatMountPoint(pathPrefix)
843
- }));
844
- }
845
- }), !!error && /*#__PURE__*/_jsx(Alert, {
846
- type: "error",
847
- style: {
848
- width: '100%',
849
- marginTop: 8
850
- },
851
- children: error
852
- })]
853
- }),
854
- cancel: t('common.pre'),
855
- confirm: t('common.next'),
856
- onCancel,
857
- onConfirm: () => {
858
- onNext();
859
- }
860
- }, meta && params?.hasEnvironmentsStep && {
861
- key: 'environment',
862
- name: /*#__PURE__*/_jsxs(_Fragment, {
863
- children: [t('common.environment'), " ", params.hasRequiredEnvironments && /*#__PURE__*/_jsx(Required, {})]
864
- }),
865
- disabled: !!editingItem || params?.hasMissRequiredConfigs,
866
- body: () => {
867
- return /*#__PURE__*/_jsxs(TypographyWrapper, {
868
- component: "div",
869
- children: [/*#__PURE__*/_jsx(PageHeaderWrapper, {
870
- title: t('common.environment'),
871
- subTitle: t('blocklet.component.addComponentTip.environment')
872
- }), /*#__PURE__*/_jsx(SchemaForm, {
873
- style: {
874
- marginTop: -12,
875
- width: '100%'
876
- },
877
- schema: params.configsList,
878
- defaultValue: params.configsValue
879
- // eslint-disable-next-line
880
- ,
881
- onChange: (changeValue, {
882
- action,
883
- currentItem,
884
- allValues
885
- }) => {
886
- if (action === 'confirm') {
887
- updateParams({
888
- hasMissRequiredConfigs: hasMissRequiredConfigs(params.configsList, allValues),
889
- configsValue: allValues
890
- });
891
- }
892
- if (action === 'edit') {
893
- setEditingItem(currentItem);
894
- } else if (['cancel', 'confirm'].includes(action)) {
895
- setEditingItem(null);
896
- }
897
- }
898
- })]
899
- });
900
- },
901
- cancel: t('common.pre'),
902
- confirm: t('common.next'),
903
- onCancel,
904
- onConfirm: onNext
905
- }, meta && params?.didSpaceCapability && {
906
- key: 'didSpace',
907
- name: /*#__PURE__*/_jsxs(_Fragment, {
908
- children: [t('blocklet.component.didSpaceConfig'), " ", params.didSpaceCapability === 'required' && /*#__PURE__*/_jsx(Required, {})]
909
- }),
910
- disabled: params.didSpaceCapability === 'required' && !params.didSpaceEndpoint,
911
- body: () => {
912
- return /*#__PURE__*/_jsxs(TypographyWrapper, {
913
- component: "div",
914
- children: [/*#__PURE__*/_jsx(PageHeaderWrapper, {
915
- title: t('blocklet.component.didSpaceConfig'),
916
- subTitle: t('blocklet.component.didSpaceConfigTip')
917
- }), /*#__PURE__*/_jsx(Box, {
918
- sx: {
919
- mt: '36px',
920
- '& > div': {
921
- maxWidth: 'unset !important',
922
- '& .MuiAutocomplete-root': {
923
- maxWidth: 'unset !important'
924
- }
925
- }
926
- },
927
- children: /*#__PURE__*/_jsx(SpaceConnector, {
928
- sx: {
929
- '& .MuiFormHelperText-root': {
930
- wordBreak: 'break-all'
931
- }
932
- },
933
- helperText: params.didSpaceEndpoint && t('blocklet.component.didSpaceConnected', {
934
- endpoint: params.didSpaceEndpoint
935
- }),
936
- onConnect: () => {
937
- onNext();
938
- }
939
- })
940
- })]
941
- });
942
- },
943
- cancel: t('common.pre'),
944
- confirm: t('common.next'),
945
- onCancel,
946
- onConfirm: onNext
947
- }, {
948
- key: 'install',
949
- name: t('common.install'),
950
- disabled: false,
951
- loading: false,
952
- body: /*#__PURE__*/_jsx(TypographyWrapper, {
953
- component: "div",
954
- className: "flex-justify-center flex-align-center",
955
- style: {
956
- flexDirection: 'column'
957
- },
958
- children: isEmpty(params.installResultProps) ? /*#__PURE__*/_jsx(AnimationWaiter, {
959
- message: /*#__PURE__*/_jsx(MessageDiv, {
960
- children: t('blocklet.component.installingCanCloseWindowTip')
961
- }),
962
- increaseSpeed: 0.3,
963
- messageLoop: false
964
- }) : /*#__PURE__*/_jsx("div", {
965
- style: {
966
- marginTop: 120
967
- },
968
- children: /*#__PURE__*/_jsx(ResultMessage, {
969
- ...params.installResultProps
970
- })
971
- })
972
- }),
973
- confirm: t('common.complete'),
974
- // onCancel: onClose,
975
- onConfirm: () => {
976
- onClose();
977
- // scroll to bottom
978
- setTimeout(() => {
979
- const scrollDom = document.getElementsByClassName('dashboard-main')[0];
980
- if (scrollDom) {
981
- scrollDom.scrollTop = scrollDom.scrollHeight;
982
- }
983
- }, 200);
984
- }
985
- }].filter(item => item);
986
- const step = steps[activeStep] || {};
987
32
  const onMenuItemClick = e => {
988
33
  e.stopPropagation();
989
34
  // eslint-disable-next-line no-unused-expressions
990
35
  setShowDialog(true);
991
36
  };
992
- const isDisabled = () => {
993
- if (loading || step.error || !params.bundleDid) {
994
- return true;
995
- }
996
- if (activeStep > 0) {
997
- return !params.pathPrefix;
998
- }
999
- return false;
1000
- };
1001
-
1002
- // show close button when step is not the last one
1003
- const showCloseButton = activeStep < steps.length - 1;
1004
37
  return /*#__PURE__*/_jsxs(_Fragment, {
1005
38
  children: [typeof children === 'function' ? children({
1006
- loading,
1007
39
  open: onMenuItemClick
1008
40
  }) : /*#__PURE__*/_jsxs(MenuItem, {
1009
41
  onClick: onMenuItemClick,
1010
42
  className: "component-action",
1011
43
  "data-cy": "action-add-component",
1012
- children: [loading ? /*#__PURE__*/_jsx(Spinner, {
1013
- size: 16
1014
- }) : /*#__PURE__*/_jsx(AddIcon, {
44
+ children: [/*#__PURE__*/_jsx(AddIcon, {
1015
45
  style: {
1016
46
  fontSize: 18,
1017
47
  marginRight: 5
@@ -1040,63 +70,14 @@ export default function AddComponent({
1040
70
  if (reason === 'backdropClick') {
1041
71
  return;
1042
72
  }
1043
- steps[0]?.onCancel?.();
73
+ onClose();
1044
74
  },
1045
- showCloseButton: showCloseButton,
75
+ showCloseButton: true,
1046
76
  disableEscapeKeyDown: true,
1047
77
  open: true,
1048
- actions: /*#__PURE__*/_jsxs(_Fragment, {
1049
- children: [step.cancel && /*#__PURE__*/_jsx(Button, {
1050
- onClick: e => {
1051
- e.stopPropagation();
1052
- step.onCancel();
1053
- },
1054
- disabled: activeStep === steps.length - 2 && loading,
1055
- color: "inherit",
1056
- children: step.cancel || t('common.cancel')
1057
- }), step.confirm && /*#__PURE__*/_jsx(Button, {
1058
- onClick: e => {
1059
- e.stopPropagation();
1060
- step.onConfirm();
1061
- },
1062
- color: "primary",
1063
- "data-cy": "submit-confirm-next",
1064
- disabled: loading || (typeof step.disabled === 'boolean' ? step.disabled : isDisabled()),
1065
- variant: "contained",
1066
- autoFocus: true,
1067
- title: step.confirm,
1068
- style: {
1069
- marginLeft: 8,
1070
- overflow: 'hidden',
1071
- textOverflow: 'ellipsis',
1072
- whiteSpace: 'nowrap',
1073
- minWidth: '140px',
1074
- maxWidth: '280px',
1075
- textAlign: 'center'
1076
- },
1077
- children: /*#__PURE__*/_jsxs(Box, {
1078
- display: "flex",
1079
- alignItems: "center",
1080
- children: [(typeof step.loading === 'boolean' ? step.loading : loading) && /*#__PURE__*/_jsx(Spinner, {
1081
- style: {
1082
- marginRight: 8
1083
- },
1084
- size: 16
1085
- }), step.confirm]
1086
- })
1087
- })]
1088
- }),
1089
- children: /*#__PURE__*/_jsx(StepProvider, {
1090
- steps: steps,
1091
- mode: "memory",
1092
- children: /*#__PURE__*/_jsx(StepContent, {
1093
- ref: stepRef,
1094
- meta: meta,
1095
- isMobile: isMobile,
1096
- onStepChange: newStep => {
1097
- setActiveStep(newStep);
1098
- }
1099
- })
78
+ children: /*#__PURE__*/_jsx(AddComponentCore, {
79
+ onClose: onClose,
80
+ storageKey: inService ? STORAGE_KEY_STORE_BLOCKLET : STORAGE_KEY_STORE_SERVER
1100
81
  })
1101
82
  })]
1102
83
  });
@@ -1110,218 +91,5 @@ AddComponent.defaultProps = {
1110
91
  };
1111
92
  const DialogWrapper = styled(Dialog)`
1112
93
  .MuiDialogContent-root {
1113
- padding-left: 0;
1114
- padding-right: 0;
1115
- padding-bottom: 0;
1116
- }
1117
-
1118
- .MuiDialogActions-root {
1119
- padding: 16px 24px;
1120
- }
1121
- `;
1122
- const TypographyWrapper = styled(Typography)`
1123
- width: 100%;
1124
- height: 100%;
1125
- `;
1126
- const RightContent = styled.div`
1127
- width: 100%;
1128
- height: 100%;
1129
- display: flex;
1130
- flex-direction: column;
1131
- justify-content: flex-start;
1132
- align-items: flex-start;
1133
-
1134
- .bottom-button {
1135
- min-width: 200px;
1136
- }
1137
-
1138
- // blocklet-select-side
1139
- aside {
1140
- width: 140px;
1141
- }
1142
- `;
1143
- const isMobileDialogContent = props => {
1144
- if (props.isMobile) {
1145
- return `
1146
- height: calc(100vh - 56px - 64px - 48px);
1147
- `;
1148
- }
1149
- return '';
1150
- };
1151
- const DialogContentWrapper = styled(DialogContentText)`
1152
- ${({
1153
- className
1154
- }) => {
1155
- // mobile extra style
1156
- if (className === 'mobileStyle') {
1157
- return `
1158
- height: 100%;
1159
-
1160
- & > div{
1161
- height: 100%;
1162
- }
1163
- .root-header {
1164
- .app-name-content {
1165
- display: none;
1166
- }
1167
- }
1168
-
1169
-
1170
-
1171
- // content-panel
1172
- .root-header + div{
1173
- padding-top: 0;
1174
- position: relative;
1175
- & > div {
1176
- padding-top: 0;
1177
- }
1178
- }
1179
-
1180
- header + div {
1181
- padding-top: 0;
1182
- }
1183
-
1184
- header {
1185
- .header-title {
1186
- margin-left: 0;
1187
- }
1188
-
1189
- .header-title-name {
1190
- max-width: 100% !important;
1191
- }
1192
- }
1193
- `;
1194
- }
1195
- return `
1196
- height: 72vh;
1197
- position: relative;
1198
- .root-header {
1199
- z-index: auto !important;
1200
- position: fixed !important;
1201
- }
1202
- & > div {
1203
- height: 100%;
1204
- width: 100%;
1205
- max-width: 100%;
1206
- & > div {
1207
- max-height: unset !important;
1208
- max-width: 100%;
1209
- & > div {
1210
- // left-panel
1211
- &:first-child {
1212
- padding-top: 0;
1213
- // padding-left: 0;
1214
- width: 25%;
1215
- min-width: 240px;
1216
- & > div:first-child {
1217
- display: none;
1218
- }
1219
- // step
1220
- & > div:last-child {
1221
- // margin-top: 32px;
1222
- margin-top: 0;
1223
- }
1224
- }
1225
- // right-panel
1226
- &:last-child {
1227
- padding-top: 0;
1228
- padding-right: 24px;
1229
- overflow-y: auto;
1230
- .app-content {
1231
- padding: 0 0 24px 0;
1232
- }
1233
- .button-container {
1234
- padding-right: 0;
1235
- }
1236
- }
1237
- }
1238
- }
1239
- }
1240
-
1241
- `;
1242
- }}
1243
-
1244
- & .flex-justify-center {
1245
- display: flex;
1246
- justify-content: center;
1247
- }
1248
-
1249
- & .flex-align-center {
1250
- display: flex;
1251
- height: 100%;
1252
- align-items: center;
1253
- ${props => isMobileDialogContent(props)}
1254
- }
1255
-
1256
- & .agreement-wrapper {
1257
- ${props => isMobileDialogContent(props)}
1258
- max-height: 60vh;
1259
- .eula-trigger {
1260
- padding-right: 0;
1261
- }
1262
- .next-button {
1263
- display: none;
1264
- }
1265
- }
1266
-
1267
- & .connect {
1268
- background: white;
1269
- }
1270
- `;
1271
- const PageHeaderWrapper = styled(PageHeader)`
1272
- margin-bottom: 24px;
1273
- `;
1274
- const StoreBlockletItemWrapper = styled.div`
1275
- position: relative;
1276
-
1277
- .choose-blocklet {
1278
- background-color: rgb(236, 251, 253);
1279
- border-color: rgb(236, 251, 253);
1280
- border-radius: 8px;
1281
- }
1282
-
1283
- .check-container {
1284
- position: absolute;
1285
- right: 0;
1286
- bottom: 0;
1287
- display: flex;
1288
- justify-content: flex-end;
1289
- align-items: flex-end;
1290
- width: 30px;
1291
- height: 30px;
1292
- border-radius: 0 0 8px 0;
1293
- color: ${props => props.theme.palette.common.white};
1294
- overflow: hidden;
1295
- transition: all ease 0.3s;
1296
- &:after {
1297
- position: absolute;
1298
- z-index: 0;
1299
- display: block;
1300
- width: 0;
1301
- height: 0;
1302
- border-top: transparent solid 15px;
1303
- border-left: transparent solid 15px;
1304
- border-bottom: ${props => props.theme.palette.primary.main} solid 15px;
1305
- border-right: ${props => props.theme.palette.primary.main} solid 15px;
1306
- transition: all ease 0.1s;
1307
- content: '';
1308
- }
1309
-
1310
- .check-icon {
1311
- position: relative;
1312
- z-index: 2;
1313
- margin: 0 1px 1px 0;
1314
- font-size: 16px;
1315
- transition: all ease 0.2s;
1316
- }
1317
- }
1318
- `;
1319
- const MessageDiv = styled.div`
1320
- color: ${props => props.theme.palette.primary.main};
1321
- .msg-before {
1322
- display: inline-block;
1323
- color: #aaa;
1324
- font-size: 14px;
1325
- margin-right: 6px;
1326
94
  }
1327
95
  `;