@blocklet/launcher-workflow 2.2.53 → 2.2.55

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/es/checkout.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /* eslint-disable react-hooks/exhaustive-deps */
2
2
  import Dialog from '@arcblock/ux/lib/Dialog';
3
- import { BLOCKLET_SERVER_OWNERSHIP_NFT, NFT_TYPE_SERVERLESS } from '@blocklet/launcher-util/es/constant';
3
+ import { NFT_TYPE_DEDICATE, NFT_TYPE_SERVERLESS } from '@blocklet/launcher-util/es/constant';
4
4
  import { getBlockletDisplayName } from '@blocklet/launcher-util/es/util';
5
5
  import Button from '@blocklet/launcher-ux/lib/button';
6
6
  import useMobile from '@blocklet/launcher-ux/lib/use-mobile';
@@ -65,9 +65,7 @@ import useRequest from './contexts/request';
65
65
  import { useSessionContext } from './contexts/session';
66
66
  import { useWorkflowContext } from './contexts/workflow';
67
67
  import { BLOCKLET_STORE_URL, getPrice, launchSession } from './util';
68
- import { jsx as _jsx } from "react/jsx-runtime";
69
- import { jsxs as _jsxs } from "react/jsx-runtime";
70
- import { Fragment as _Fragment } from "react/jsx-runtime";
68
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
71
69
  function CheckoutPage({
72
70
  blocklet
73
71
  }) {
@@ -241,7 +239,7 @@ function CheckoutPage({
241
239
  }
242
240
  params.set('launchType', 'serverless');
243
241
  }
244
- if (isPurchaseOnly && !(nftState.tags || []).includes(BLOCKLET_SERVER_OWNERSHIP_NFT)) {
242
+ if (isPurchaseOnly && !(nftState.tags || []).includes(NFT_TYPE_DEDICATE)) {
245
243
  handleCancelPay();
246
244
  dsbridge.call('arcClosePage');
247
245
  return;
@@ -41,8 +41,7 @@ UncheckedIcon.defaultProps = {
41
41
  xmlns: "http://www.w3.org/2000/svg"
42
42
  };
43
43
  import { useLocaleContext } from '../contexts/locale';
44
- import { jsx as _jsx } from "react/jsx-runtime";
45
- import { jsxs as _jsxs } from "react/jsx-runtime";
44
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
46
45
  export default function CheckBox({
47
46
  label,
48
47
  checked,
@@ -10,8 +10,7 @@ import DialogTitle from '@mui/material/DialogTitle';
10
10
  import { useTheme } from '@mui/material/styles';
11
11
  import useMediaQuery from '@mui/material/useMediaQuery';
12
12
  import { LocaleContext } from '../contexts/locale';
13
- import { jsx as _jsx } from "react/jsx-runtime";
14
- import { jsxs as _jsxs } from "react/jsx-runtime";
13
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
15
14
  const translations = {
16
15
  en: {
17
16
  confirm: 'Confirm',
@@ -11,8 +11,7 @@ import useRequest from '../contexts/request';
11
11
  import { useWorkflowContext } from '../contexts/workflow';
12
12
 
13
13
  // 不考虑 localstorage 的过期时间
14
- import { jsx as _jsx } from "react/jsx-runtime";
15
- import { jsxs as _jsxs } from "react/jsx-runtime";
14
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
16
15
  const IGNORE_LAUNCH_SESSION_KEY = 'launcher-ignore-launch-session';
17
16
  export default function InProgressSession() {
18
17
  const {
@@ -1,24 +1,24 @@
1
- import { useContext, useEffect, useState } from 'react';
2
- import { useNavigate, useParams } from 'react-router-dom';
3
- import PropTypes from 'prop-types';
4
- import get from 'lodash.get';
5
- import useInterval from 'react-use/lib/useInterval';
6
- import throttle from 'lodash.throttle';
7
- import styled from '@emotion/styled';
8
- import Button from '@arcblock/ux/lib/Button';
9
- import Spinner from '@mui/material/CircularProgress';
10
1
  import AnimationWaiter from '@arcblock/ux/lib/AnimationWaiter';
11
- import { INSTANCE_STATUS } from '@blocklet/launcher-util/es/constant';
2
+ import Button from '@arcblock/ux/lib/Button';
12
3
  import Toast from '@arcblock/ux/lib/Toast';
13
- import PageHeader from '@blocklet/launcher-layout/lib/page-header';
4
+ import { INSTANCE_STATUS } from '@blocklet/launcher-util/es/constant';
5
+ import styled from '@emotion/styled';
6
+ import Spinner from '@mui/material/CircularProgress';
7
+ import { useSetState } from 'ahooks';
8
+ import get from 'lodash.get';
9
+ import throttle from 'lodash.throttle';
10
+ import PropTypes from 'prop-types';
11
+ import { useContext, useEffect, useState } from 'react';
12
+ import { useNavigate } from 'react-router-dom';
13
+ import useInterval from 'react-use/lib/useInterval';
14
14
  import LaunchResultMessage from '@blocklet/launcher-layout/lib/launch-result-message';
15
+ import PageHeader from '@blocklet/launcher-layout/lib/page-header';
15
16
  import ProgressMessage from '@blocklet/launcher-ux/lib/progress-message';
16
- import { getAPIResponseError, getLaunchBlockletUrl, loadURL } from '../util';
17
- import useQuery from '../hooks/query';
18
- import useRequest from '../contexts/request';
19
17
  import { LocaleContext } from '../contexts/locale';
20
- import { jsx as _jsx } from "react/jsx-runtime";
21
- import { jsxs as _jsxs } from "react/jsx-runtime";
18
+ import useRequest from '../contexts/request';
19
+ import useQuery from '../hooks/query';
20
+ import { getAPIResponseError, getLaunchBlockletUrl, loadURL } from '../util';
21
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
22
22
  const STATUS = {
23
23
  waiting: 0,
24
24
  // 未使用
@@ -30,6 +30,7 @@ const STATUS = {
30
30
  launchFailedError: 12
31
31
  };
32
32
  export default function LaunchDedicated({
33
+ sessionId,
33
34
  type
34
35
  }) {
35
36
  const query = useQuery();
@@ -38,23 +39,21 @@ export default function LaunchDedicated({
38
39
  t,
39
40
  locale
40
41
  } = useContext(LocaleContext);
41
- const [launchState, setLaunchState] = useState({
42
+ const [launchState, setLaunchState] = useSetState({
43
+ instanceId: '',
42
44
  appUrl: '',
43
45
  status: STATUS.waiting
44
46
  });
45
- const {
46
- nftId
47
- } = useParams();
48
47
  const {
49
48
  api
50
49
  } = useRequest();
51
50
  const [progressStepIndex, setProgressStepIndex] = useState(0);
52
51
  const [isDone, setIsDone] = useState(false);
53
52
  const navigate = useNavigate();
54
- let createServerTime = sessionStorage.getItem(`launcher-create-server-${nftId}-time`);
53
+ let createServerTime = sessionStorage.getItem(`launcher-create-server-${sessionId}-time`);
55
54
  if (!createServerTime) {
56
55
  createServerTime = Date.now();
57
- sessionStorage.setItem(`launcher-create-server-${nftId}-time`, createServerTime);
56
+ sessionStorage.setItem(`launcher-create-server-${sessionId}-time`, createServerTime);
58
57
  }
59
58
  const handleInstance = instance => {
60
59
  if (instance.status >= INSTANCE_STATUS.running) {
@@ -67,11 +66,10 @@ export default function LaunchDedicated({
67
66
  });
68
67
  setIsDone(true);
69
68
  setTimeout(() => {
70
- setLaunchState(pre => ({
71
- ...pre,
69
+ setLaunchState({
72
70
  status: STATUS.success,
73
71
  appUrl: url
74
- }));
72
+ });
75
73
  loadURL(url).finally(() => {
76
74
  setTimeout(() => {
77
75
  window.location.href = url;
@@ -82,22 +80,23 @@ export default function LaunchDedicated({
82
80
  };
83
81
  const launch = async () => {
84
82
  try {
85
- setLaunchState(pre => ({
86
- ...pre,
83
+ setLaunchState({
87
84
  status: STATUS.launching
88
- }));
85
+ });
89
86
  const {
90
87
  data: {
91
88
  instance
92
89
  }
93
90
  } = await api.post('/instances/launch', {
94
- nftId
91
+ launchId: sessionId
95
92
  }, {
96
93
  params: {
97
- launchType: query.get('launchType'),
98
- sessionId: query.get('sessionId')
94
+ launchType: query.get('launchType')
99
95
  }
100
96
  });
97
+ setLaunchState({
98
+ instanceId: instance._id
99
+ });
101
100
  handleInstance(instance);
102
101
  } catch (err) {
103
102
  const errDesc = getAPIResponseError(err);
@@ -115,27 +114,25 @@ export default function LaunchDedicated({
115
114
  data: {
116
115
  instance
117
116
  }
118
- } = await api.get(`/public/instances/${nftId}/status`);
117
+ } = await api.get(`/instances/${launchState.instanceId}`);
119
118
  handleInstance(instance);
120
119
  } catch (error) {
121
- sessionStorage.removeItem(`launcher-create-server-${nftId}-time`);
120
+ sessionStorage.removeItem(`launcher-create-server-${sessionId}-time`);
122
121
  if (get(error, 'response.status') === 404 && launchState.status !== STATUS.launching) {
123
- setLaunchState(state => ({
124
- ...state,
122
+ setLaunchState({
125
123
  status: STATUS.notFoundError
126
- }));
124
+ });
127
125
  throw error;
128
126
  }
129
- setLaunchState(state => ({
130
- ...state,
127
+ setLaunchState({
131
128
  status: STATUS.error
132
- }));
129
+ });
133
130
  console.warn('load instance status error', error);
134
131
  throw error;
135
132
  }
136
133
  };
137
134
  const poll = throttle(getInstanceStatus, 5000);
138
- useInterval(poll, launchState.status === STATUS.launching && nftId ? 5000 : null);
135
+ useInterval(poll, launchState.status === STATUS.launching && launchState.instanceId ? 5000 : null);
139
136
  const successful = launchState.status === STATUS.success;
140
137
  const progressSteps = [t('launch.waiting.starting'), t('launch.waiting.securing'), t('launch.waiting.prepare'), t('launch.waiting.waiting'), t('launch.waiting.done')];
141
138
  const messageDuration = 40000;
@@ -281,6 +278,7 @@ const Content = styled.div`
281
278
  }
282
279
  `;
283
280
  LaunchDedicated.propTypes = {
281
+ sessionId: PropTypes.string.isRequired,
284
282
  type: PropTypes.oneOf(['launch', 'start'])
285
283
  };
286
284
  LaunchDedicated.defaultProps = {
@@ -10,10 +10,9 @@ import Button from '@blocklet/launcher-ux/lib/button';
10
10
  import { useLocaleContext } from '../contexts/locale';
11
11
  import useRequest from '../contexts/request';
12
12
  import { getLaunchBlockletUrl } from '../util';
13
- import { jsx as _jsx } from "react/jsx-runtime";
14
- import { jsxs as _jsxs } from "react/jsx-runtime";
13
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
15
14
  export default function LaunchServerless({
16
- nftId
15
+ sessionId
17
16
  }) {
18
17
  const {
19
18
  t,
@@ -23,20 +22,21 @@ export default function LaunchServerless({
23
22
  api
24
23
  } = useRequest();
25
24
  const [searchParams] = useSearchParams();
26
- const sessionId = searchParams.get('sessionId');
27
25
  const state = useAsync(async () => {
28
26
  const {
29
27
  data: {
30
28
  instance
31
29
  }
32
- } = await api.post(`/serverless/${nftId}/allocate?sessionId=${sessionId}`);
30
+ } = await api.post('/serverless/allocate', {
31
+ launchId: sessionId
32
+ });
33
33
  setTimeout(() => {
34
34
  window.location = getLaunchBlockletUrl({
35
35
  serverUrl: instance.adminURL,
36
36
  blockletMetaUrl: searchParams.get('blocklet_meta_url'),
37
37
  locale,
38
38
  launchType: 'serverless',
39
- nftId,
39
+ nftId: instance.nftId,
40
40
  sessionId,
41
41
  chainHost: window.blocklet?.CHAIN_HOST,
42
42
  from: searchParams.get('from')
@@ -109,5 +109,5 @@ const Container = styled.div`
109
109
  }
110
110
  `;
111
111
  LaunchServerless.propTypes = {
112
- nftId: PropTypes.string.isRequired
112
+ sessionId: PropTypes.string.isRequired
113
113
  };
@@ -98,9 +98,7 @@ UnCheckReverseIcon.defaultProps = {
98
98
  };
99
99
  import { getPrice } from '../util';
100
100
  import { useLocaleContext } from '../contexts/locale';
101
- import { jsx as _jsx } from "react/jsx-runtime";
102
- import { jsxs as _jsxs } from "react/jsx-runtime";
103
- import { Fragment as _Fragment } from "react/jsx-runtime";
101
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
104
102
  function Feature({
105
103
  feature,
106
104
  locale,
package/es/launch.js CHANGED
@@ -6,7 +6,7 @@ import { useSessionContext } from './contexts/session';
6
6
  import { jsx as _jsx } from "react/jsx-runtime";
7
7
  export default function Launch() {
8
8
  const {
9
- nftId
9
+ sessionId
10
10
  } = useParams();
11
11
  const [searchParams] = useSearchParams();
12
12
  const {
@@ -27,10 +27,10 @@ export default function Launch() {
27
27
  const launchType = searchParams.get('launchType');
28
28
  if (launchType === 'serverless') {
29
29
  return /*#__PURE__*/_jsx(LaunchServerless, {
30
- nftId: nftId
30
+ sessionId: sessionId
31
31
  });
32
32
  }
33
33
  return /*#__PURE__*/_jsx(LaunchDedicated, {
34
- nftId: nftId
34
+ sessionId: sessionId
35
35
  });
36
36
  }
package/es/locales/en.js CHANGED
@@ -25,7 +25,11 @@ export default {
25
25
  pay: 'Pay',
26
26
  payWith: 'Pay with {currency}',
27
27
  popular: 'Popular',
28
- space: 'Space'
28
+ serviceError: 'Service Failed',
29
+ space: 'Space',
30
+ subscription: 'Subscription',
31
+ price: 'Pricing',
32
+ unitPrice: 'Unit'
29
33
  },
30
34
  license: {
31
35
  title: 'End User License Agreement',
@@ -105,6 +109,8 @@ export default {
105
109
  redeem: 'Select purchased space',
106
110
  noProducts: 'No products available for purchase, please check your payment-kit config',
107
111
  serverlessNotSupported: 'This app is not allowed in sigular and on-demand space, please select dedicated space',
112
+ componentCount: '{count} Component Included',
113
+ componentsCount: '{count} Components Included',
108
114
  dialog: {
109
115
  title: 'Purchase Blocklet Space NFT',
110
116
  scan: 'Scan the QR code below with your DID wallet to complete purchase',
@@ -121,6 +127,13 @@ export default {
121
127
  continue: 'Continue',
122
128
  content: 'You have an incomplete order {blockletName}, Continue this order?',
123
129
  notRemind: 'No more reminders'
130
+ },
131
+ productType: {
132
+ 'on-demand': 'On Demand Space',
133
+ dedicated: 'Dedicated Space'
134
+ },
135
+ paid: {
136
+ redirecting: 'Payment success, redirecting...'
124
137
  }
125
138
  },
126
139
  checkout: {
@@ -130,6 +143,8 @@ export default {
130
143
  paymentMethod: {
131
144
  title: 'Select payment currency'
132
145
  },
133
- agreement: '{name} User Agreement'
146
+ agreement: '{name} User Agreement',
147
+ estimatedCost: 'Estimated Cost',
148
+ estimatedCostHint: 'The total cost will vary depending on the actual number and duration of components used in the application. The calculation method is: Unit price of component * Number of components * Duration.'
134
149
  }
135
150
  };
@@ -1,8 +1,10 @@
1
1
  /* eslint-disable import/prefer-default-export */
2
+ import { translations as extraTranslations } from '@blocklet/payment-react';
2
3
  import flat from 'flat';
4
+ import merge from 'lodash.merge';
3
5
  import en from './en';
4
6
  import zh from './zh';
5
- export const translations = {
7
+ export const translations = merge({
6
8
  en: flat(en),
7
9
  zh: flat(zh)
8
- };
10
+ }, extraTranslations);
package/es/locales/zh.js CHANGED
@@ -24,8 +24,12 @@ export default {
24
24
  pay: '支付',
25
25
  previous: '上一步',
26
26
  popular: '推荐',
27
+ price: '价格',
28
+ serviceError: '服务出错',
27
29
  space: '空间',
28
- payWith: '用{currency}支付'
30
+ subscription: '订阅',
31
+ payWith: '用{currency}支付',
32
+ unitPrice: '单价'
29
33
  },
30
34
  license: {
31
35
  title: '空间用户协议',
@@ -63,7 +67,7 @@ export default {
63
67
  success: '正在启动'
64
68
  },
65
69
  error: {
66
- launchFailed: '空间空间失败',
70
+ launchFailed: '启动空间失败',
67
71
  launchFailedDescription: '您可以点击下面按钮重试',
68
72
  notFound: '没有正在启动的空间',
69
73
  notFoundDescription: '您可以点击下面按钮启动空间'
@@ -104,6 +108,8 @@ export default {
104
108
  hasPlan: '选用{name}',
105
109
  noProducts: '没有可购买的商品,请检查 PaymentKit 的配置',
106
110
  serverlessNotSupported: '该应用被禁止能在单应用或者按需空间中运行,请选择专用空间',
111
+ componentCount: '共 {count} 个组件',
112
+ componentsCount: '共 {count} 个组件',
107
113
  dialog: {
108
114
  title: '购买 Blocklet Server NFT',
109
115
  scan: '用您的 DID 钱包扫描下面的二维码完成购买',
@@ -120,6 +126,13 @@ export default {
120
126
  continue: '继续',
121
127
  content: '您有一个未完成的订单: {blockletName},继续该订单?',
122
128
  notRemind: '不再提醒'
129
+ },
130
+ productType: {
131
+ 'on-demand': '按需空间',
132
+ dedicated: '专用空间'
133
+ },
134
+ paid: {
135
+ redirecting: '支付成功,正在跳转...'
123
136
  }
124
137
  },
125
138
  checkout: {
@@ -129,6 +142,8 @@ export default {
129
142
  paymentMethod: {
130
143
  title: '选择支付货币'
131
144
  },
132
- agreement: '{name} 用户协议'
145
+ agreement: '{name} 用户协议',
146
+ estimatedCost: '估算成本',
147
+ estimatedCostHint: '总成本会根据应用实际使用的组件数量和时长而变化,计算方式为: 组件单价*组件数量*时长'
133
148
  }
134
149
  };
package/es/paid.js ADDED
@@ -0,0 +1,51 @@
1
+ import Center from '@arcblock/ux/lib/Center';
2
+ import { LAUNCH_STATUS } from '@blocklet/launcher-util/lib/constant';
3
+ import CircularProgress from '@mui/material/CircularProgress';
4
+ import { useRequest } from 'ahooks';
5
+ import { useEffect } from 'react';
6
+ import { useNavigate, useSearchParams } from 'react-router-dom';
7
+ import joinURL from 'url-join';
8
+ import { useLocaleContext } from './contexts/locale';
9
+ import useRequestContext from './contexts/request';
10
+ import { useWorkflowContext } from './contexts/workflow';
11
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
12
+ export default function PurchaseSuccess() {
13
+ const [params, setParams] = useSearchParams();
14
+ const navigate = useNavigate();
15
+ const {
16
+ routerPrefix
17
+ } = useWorkflowContext();
18
+ const {
19
+ t
20
+ } = useLocaleContext();
21
+ const {
22
+ api
23
+ } = useRequestContext();
24
+ const sessionId = params.get('sessionId');
25
+ const {
26
+ loading,
27
+ data,
28
+ cancel
29
+ } = useRequest(() => api.get(`/launches/${sessionId}`).then(res => res.data?.launch), {
30
+ pollingInterval: 2000
31
+ });
32
+ useEffect(() => {
33
+ if (data?.status >= LAUNCH_STATUS.nftMinted) {
34
+ cancel();
35
+ }
36
+ }, [data, cancel]);
37
+ useEffect(() => {
38
+ if (data?.status >= LAUNCH_STATUS.nftMinted) {
39
+ params.set('launchType', data.type);
40
+ navigate({
41
+ pathname: joinURL(routerPrefix, `/launch/${data._id}`),
42
+ search: params.toString()
43
+ });
44
+ }
45
+ }, [data, params, navigate, sessionId, routerPrefix, setParams]);
46
+ const completed = !loading && data?.status >= LAUNCH_STATUS.nftMinted;
47
+ return /*#__PURE__*/_jsxs(Center, {
48
+ relative: "parent",
49
+ children: [!completed && /*#__PURE__*/_jsx(CircularProgress, {}), completed && t('purchase.paid.redirecting')]
50
+ });
51
+ }