@abtnode/ux 1.16.14-beta-c308dc3b → 1.16.14-beta-cb53c14b

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 (202) hide show
  1. package/es/actions.js +97 -0
  2. package/es/analytics/card.js +92 -0
  3. package/es/analytics/chart.js +96 -0
  4. package/es/analytics/cpu.js +36 -0
  5. package/es/analytics/disk.js +111 -0
  6. package/es/analytics/memory.js +72 -0
  7. package/es/analytics/runtime.js +173 -0
  8. package/es/analytics/traffic.js +259 -0
  9. package/es/blocklet/access/config-access.js +307 -0
  10. package/es/blocklet/access/index.js +216 -0
  11. package/es/blocklet/actions.js +474 -0
  12. package/es/blocklet/add-cert.js +177 -0
  13. package/es/blocklet/agreement-app.js +21 -0
  14. package/es/blocklet/agreement.js +127 -0
  15. package/es/blocklet/app-avatar.js +57 -0
  16. package/es/blocklet/audit-logs.js +259 -0
  17. package/es/blocklet/blocklet-source.js +48 -0
  18. package/es/blocklet/bundle-avatar.js +64 -0
  19. package/es/blocklet/component/add.js +1308 -0
  20. package/es/blocklet/component/configuration.js +122 -0
  21. package/es/blocklet/component/delete.js +134 -0
  22. package/es/blocklet/component/environment.js +370 -0
  23. package/es/blocklet/component/index.js +975 -0
  24. package/es/blocklet/component/line.js +20 -0
  25. package/es/blocklet/component/navigation/locale-tabs.js +225 -0
  26. package/es/blocklet/component/navigation/navigation-actions.js +112 -0
  27. package/es/blocklet/component/navigation/navigation-dialog.js +607 -0
  28. package/es/blocklet/component/navigation/navigation-preview.js +101 -0
  29. package/es/blocklet/component/navigation/simple-select.js +124 -0
  30. package/es/blocklet/component/select-store.js +155 -0
  31. package/es/blocklet/component/setting.js +109 -0
  32. package/es/blocklet/component/sortable-tree.js +126 -0
  33. package/es/blocklet/component/space-connector.js +199 -0
  34. package/es/blocklet/component/space-selector.js +178 -0
  35. package/es/blocklet/component/start.js +101 -0
  36. package/es/blocklet/component/store-blocklet-list.js +200 -0
  37. package/es/blocklet/component/switch-control.js +57 -0
  38. package/es/blocklet/config-navigation.js +331 -0
  39. package/es/blocklet/configuration.js +603 -0
  40. package/es/blocklet/disk-info.js +75 -0
  41. package/es/blocklet/icons.js +18 -0
  42. package/es/blocklet/install-from-url.js +337 -0
  43. package/es/blocklet/log.js +90 -0
  44. package/es/blocklet/migration.js +149 -0
  45. package/es/blocklet/mode.js +19 -0
  46. package/es/blocklet/notification/email.js +257 -0
  47. package/es/blocklet/notification/index.js +49 -0
  48. package/es/blocklet/oauth/auth0.js +145 -0
  49. package/es/blocklet/oauth/common-settings.js +133 -0
  50. package/es/blocklet/oauth/federated-detail-dialog.js +175 -0
  51. package/es/blocklet/oauth/federated-invite-dialog.js +83 -0
  52. package/es/blocklet/oauth/federated-join-dialog.js +111 -0
  53. package/es/blocklet/oauth/federated-site-list.js +338 -0
  54. package/es/blocklet/oauth/federated.js +81 -0
  55. package/es/blocklet/oauth/index.js +69 -0
  56. package/es/blocklet/overview.js +293 -0
  57. package/es/blocklet/page-group.js +19 -0
  58. package/es/blocklet/preferences/app-sk.js +142 -0
  59. package/es/blocklet/preferences/index.js +305 -0
  60. package/es/blocklet/purchase/common.js +95 -0
  61. package/es/blocklet/purchase/component-purchase.js +237 -0
  62. package/es/blocklet/purchase/index.js +4 -0
  63. package/es/blocklet/router/action/add-domain-alias.js +167 -0
  64. package/es/blocklet/router/action/add-rule.js +211 -0
  65. package/es/blocklet/router/action/config-routing-rule.js +232 -0
  66. package/es/blocklet/router/action/delete-domain-alias.js +99 -0
  67. package/es/blocklet/router/action/delete-rule.js +108 -0
  68. package/es/blocklet/router/action/update-rule.js +209 -0
  69. package/es/blocklet/router/domain-actions.js +64 -0
  70. package/es/blocklet/router/domain-status.js +88 -0
  71. package/es/blocklet/router/rule-actions.js +66 -0
  72. package/es/blocklet/router/rule-list.js +190 -0
  73. package/es/blocklet/router/util.js +131 -0
  74. package/es/blocklet/runtime-info.js +68 -0
  75. package/es/blocklet/status.js +91 -0
  76. package/es/blocklet/storage/action.js +134 -0
  77. package/es/blocklet/storage/backups.js +241 -0
  78. package/es/blocklet/storage/connect-to.js +373 -0
  79. package/es/blocklet/storage/connected.js +198 -0
  80. package/es/blocklet/storage/delete.js +113 -0
  81. package/es/blocklet/storage/disconnect.js +243 -0
  82. package/es/blocklet/storage/index.js +19 -0
  83. package/es/blocklet/storage/item.js +558 -0
  84. package/es/blocklet/storage/preview-nft.js +286 -0
  85. package/es/blocklet/transfer-owner.js +198 -0
  86. package/es/blocklet/types.js +18 -0
  87. package/es/blocklet/util.js +145 -0
  88. package/es/blocklet/version.js +141 -0
  89. package/es/card-selector.js +134 -0
  90. package/es/certificate.js +105 -0
  91. package/es/chain.js +13 -0
  92. package/es/click-to-copy.js +22 -0
  93. package/es/confirm.js +149 -0
  94. package/es/contexts/audit-log.js +152 -0
  95. package/es/contexts/blocklet.js +10 -0
  96. package/es/contexts/deleting-blocklets.js +70 -0
  97. package/es/contexts/node.js +17 -0
  98. package/es/contexts/session.js +8 -0
  99. package/es/contexts/team.js +10 -0
  100. package/es/delete-confirm.js +121 -0
  101. package/es/did-address.js +46 -0
  102. package/es/dot.js +14 -0
  103. package/es/exchange-passport.js +102 -0
  104. package/es/form/form-select-input.js +184 -0
  105. package/es/form/form-text-input.js +178 -0
  106. package/es/form/form-wrapper.js +88 -0
  107. package/es/form/input-triggers.js +98 -0
  108. package/es/form/required.js +8 -0
  109. package/es/hooks/blocklet.js +229 -0
  110. package/es/hooks/confirm.js +90 -0
  111. package/es/hooks/mobile-width.js +11 -0
  112. package/es/hooks/url-evaluation.js +155 -0
  113. package/es/hooks/use-app-logo.js +16 -0
  114. package/es/hooks/use-backup-progress.js +31 -0
  115. package/es/hooks/use-blocklet-info-for-connect-did-spaces.js +50 -0
  116. package/es/hooks/use-bundle-logo.js +27 -0
  117. package/es/hooks/use-navigation.js +347 -0
  118. package/es/hooks/use-passport-id.js +14 -0
  119. package/es/hooks/use-subscription.js +22 -0
  120. package/es/icons/empty-space-nft.svg +59 -0
  121. package/es/icons/empty-spaces-nft.svg +58 -0
  122. package/es/icons/long-arrow.svg +5 -0
  123. package/es/icons/space-connected.svg +3 -0
  124. package/es/icons/space-disconnect.svg +3 -0
  125. package/es/index.js +3 -0
  126. package/es/invitation/invitation-app.js +58 -0
  127. package/es/invitation/invitation-login.js +68 -0
  128. package/es/invitation/invitation-passport.js +144 -0
  129. package/es/invitation/invitation-receive.js +138 -0
  130. package/es/invitation/invitation-success.js +93 -0
  131. package/es/invitation/invitation-user.js +90 -0
  132. package/es/invitation/invitation.js +90 -0
  133. package/es/issue-passport.js +142 -0
  134. package/es/launch-blocklet/content-layout.js +58 -0
  135. package/es/launch-blocklet/page-header.js +43 -0
  136. package/es/layout/addon.js +114 -0
  137. package/es/layout/feedback.js +55 -0
  138. package/es/locales/en.js +1534 -0
  139. package/es/locales/index.js +9 -0
  140. package/es/locales/zh.js +1537 -0
  141. package/es/logs/clock.js +11 -0
  142. package/es/logs/download.js +132 -0
  143. package/es/logs/log-terminal.js +253 -0
  144. package/es/lost-passport.js +452 -0
  145. package/es/nav-logo.js +219 -0
  146. package/es/passport-tag.js +43 -0
  147. package/es/permission.js +57 -0
  148. package/es/relative-time.js +53 -0
  149. package/es/result-message.js +11 -0
  150. package/es/schema-form/color-input.js +98 -0
  151. package/es/schema-form/common-prop-types.js +13 -0
  152. package/es/schema-form/index.js +215 -0
  153. package/es/schema-form/passport-input.js +54 -0
  154. package/es/schema-form/text-input.js +57 -0
  155. package/es/store/add.js +179 -0
  156. package/es/store/delete.js +96 -0
  157. package/es/store/item.js +76 -0
  158. package/es/subscription.js +144 -0
  159. package/es/table-icons.js +34 -0
  160. package/es/table.js +52 -0
  161. package/es/tag.js +21 -0
  162. package/es/team/members/actions.js +89 -0
  163. package/es/team/members/index.js +636 -0
  164. package/es/team/members/invitations.js +188 -0
  165. package/es/team/members/invite-member.js +208 -0
  166. package/es/team/members/issue-passport.js +152 -0
  167. package/es/team/members/member.js +408 -0
  168. package/es/team/members/passport-issuances.js +155 -0
  169. package/es/team/members/passports.js +364 -0
  170. package/es/team/members/toggle-user-approval.js +122 -0
  171. package/es/team/members/transfer-node.js +256 -0
  172. package/es/team/members/util.js +14 -0
  173. package/es/team/passports/color.js +126 -0
  174. package/es/team/passports/detail.js +312 -0
  175. package/es/team/passports/index.js +282 -0
  176. package/es/team/passports/mutate-role.js +198 -0
  177. package/es/team/passports/trusted-factories.js +221 -0
  178. package/es/team/passports/trusted-factory.js +343 -0
  179. package/es/team/passports/trusted-issuer.js +296 -0
  180. package/es/team/passports/trusted-issuers.js +226 -0
  181. package/es/team/search-input.js +46 -0
  182. package/es/team/styles/dialog.js +72 -0
  183. package/es/team/styles/list-header.js +31 -0
  184. package/es/util/api.js +6 -0
  185. package/es/util/constants.js +2 -0
  186. package/es/util/index.js +598 -0
  187. package/es/util/mode.js +4 -0
  188. package/es/util/space-gateway.js +51 -0
  189. package/es/util/spaces.js +151 -0
  190. package/es/who-can-access/config.js +38 -0
  191. package/es/wrap-locale.js +15 -0
  192. package/lib/blocklet/component/space-connector.js +1 -1
  193. package/lib/blocklet/component/space-selector.js +1 -1
  194. package/lib/blocklet/storage/backups.js +1 -1
  195. package/lib/blocklet/storage/connect-to.js +1 -1
  196. package/lib/blocklet/storage/connected.js +1 -1
  197. package/lib/blocklet/storage/disconnect.js +1 -1
  198. package/lib/blocklet/storage/index.js +1 -1
  199. package/lib/blocklet/storage/item.js +1 -1
  200. package/lib/invitation/invitation-receive.js +1 -1
  201. package/lib/team/passports/trusted-factory.js +1 -1
  202. package/package.json +81 -18
@@ -0,0 +1,216 @@
1
+ import { useState } from 'react';
2
+ import styled from '@emotion/styled';
3
+ import PropTypes from 'prop-types';
4
+ import useTheme from '@mui/material/styles/useTheme';
5
+ import Box from '@mui/material/Box';
6
+ import Tooltip from '@mui/material/Tooltip';
7
+ import IconButton from '@mui/material/IconButton';
8
+ import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
9
+ import ChevronRightIcon from '@mui/icons-material/ChevronRight';
10
+ import Collapse from '@mui/material/Collapse';
11
+ import LaunchIcon from '@mui/icons-material/Launch';
12
+ import EditIcon from '@arcblock/icons/lib/EditIcon';
13
+ import { getDisplayName } from '@blocklet/meta/lib/util';
14
+ import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
15
+ import Empty from '@arcblock/ux/lib/Empty';
16
+ import { useBlockletContext } from '../../contexts/blocklet';
17
+ import { useTeamContext } from '../../contexts/team';
18
+ import { getBlockletUrl, getBlockletUrlParams } from '../../util';
19
+ import Line from '../component/line';
20
+ import BlockletBundleAvatar from '../bundle-avatar';
21
+ import ConfigAccess, { getComponentWhoCanAccess } from './config-access';
22
+ import AccessConfig from '../../who-can-access/config';
23
+ import { jsx as _jsx } from "react/jsx-runtime";
24
+ import { jsxs as _jsxs } from "react/jsx-runtime";
25
+ function ComponentItem({
26
+ blocklet,
27
+ ancestors,
28
+ depth
29
+ }) {
30
+ const theme = useTheme();
31
+ const {
32
+ t,
33
+ locale
34
+ } = useLocaleContext();
35
+ const {
36
+ roles: roleList
37
+ } = useTeamContext();
38
+ const [expand, setExpand] = useState(true);
39
+ const {
40
+ recommendedDomain: domain
41
+ } = useBlockletContext();
42
+ const app = ancestors[0] || blocklet;
43
+ const mountPoint = `/${ancestors.map(x => x.mountPoint || '/').join('/')}/${blocklet.mountPoint || '/'}`.replace(/\/+/g, '/');
44
+ const href = getBlockletUrl({
45
+ blocklet: app,
46
+ domain: {
47
+ value: domain
48
+ },
49
+ mountPoint,
50
+ params: getBlockletUrlParams(app, locale)
51
+ });
52
+ const iconStyle = {
53
+ fill: theme.palette.text.secondary
54
+ };
55
+ const canExpand = depth > 0 && blocklet.children.length > 0;
56
+ const expandIcon = /*#__PURE__*/_jsx(IconButton, {
57
+ size: "small",
58
+ children: expand ? /*#__PURE__*/_jsx(ExpandMoreIcon, {
59
+ fontSize: "inherit"
60
+ }) : /*#__PURE__*/_jsx(ChevronRightIcon, {
61
+ fontSize: "inherit"
62
+ })
63
+ });
64
+ const {
65
+ access: whoCanAccess,
66
+ roles
67
+ } = getComponentWhoCanAccess(blocklet, app, {
68
+ roles: roleList
69
+ });
70
+ let accessConfig;
71
+ if (whoCanAccess !== 'roles') {
72
+ accessConfig = AccessConfig.find(x => x.value === whoCanAccess) || AccessConfig[2];
73
+ } else {
74
+ const str = roles.map(x => x.title).join('/');
75
+ accessConfig = {
76
+ title: {
77
+ zh: `只有 ${str} 可以访问`,
78
+ en: `Only ${str} can access`
79
+ }
80
+ };
81
+ }
82
+ return [(depth > 0 || blocklet.meta.group !== 'gateway') && /*#__PURE__*/_jsxs(Box, {
83
+ display: "flex",
84
+ py: 2,
85
+ className: "component-item",
86
+ justifyContent: "space-between",
87
+ alignItems: "center",
88
+ children: [/*#__PURE__*/_jsxs(Box, {
89
+ pl: Math.max((depth - 1) * 2, 0),
90
+ width: {
91
+ xs: 300,
92
+ md: 400
93
+ },
94
+ display: "flex",
95
+ alignItems: "center",
96
+ style: {
97
+ cursor: canExpand ? 'pointer' : 'cursor'
98
+ },
99
+ onClick: () => canExpand && setExpand(!expand),
100
+ children: [canExpand ? expandIcon : /*#__PURE__*/_jsx(Box, {
101
+ width: 28
102
+ }), /*#__PURE__*/_jsx(BlockletBundleAvatar, {
103
+ blocklet: blocklet,
104
+ ancestors: ancestors
105
+ }), /*#__PURE__*/_jsxs(Box, {
106
+ ml: "16px",
107
+ children: [/*#__PURE__*/_jsx(Box, {
108
+ style: {
109
+ color: '#222',
110
+ fontSize: 18
111
+ },
112
+ children: getDisplayName(blocklet, true)
113
+ }), /*#__PURE__*/_jsx(Box, {
114
+ display: "flex",
115
+ alignItems: "center",
116
+ children: /*#__PURE__*/_jsx(Box, {
117
+ color: "text.secondary",
118
+ children: accessConfig.title[locale]
119
+ })
120
+ })]
121
+ })]
122
+ }, blocklet), /*#__PURE__*/_jsxs(Box, {
123
+ children: [/*#__PURE__*/_jsx(Tooltip, {
124
+ title: t('common.visit'),
125
+ children: /*#__PURE__*/_jsx("a", {
126
+ target: "_blank",
127
+ href: href,
128
+ rel: "noopener noreferrer",
129
+ title: href,
130
+ children: /*#__PURE__*/_jsx(IconButton, {
131
+ children: /*#__PURE__*/_jsx(LaunchIcon, {})
132
+ })
133
+ })
134
+ }), /*#__PURE__*/_jsx(ConfigAccess, {
135
+ blocklet: blocklet,
136
+ ancestors: ancestors,
137
+ children: ({
138
+ open
139
+ }) => /*#__PURE__*/_jsx(Tooltip, {
140
+ title: t('common.edit'),
141
+ children: /*#__PURE__*/_jsx(IconButton, {
142
+ onClick: open,
143
+ "data-cy": `btn-edit-${blocklet.meta.did}`,
144
+ children: /*#__PURE__*/_jsx(EditIcon, {
145
+ style: iconStyle
146
+ })
147
+ })
148
+ })
149
+ })]
150
+ }, "actions")]
151
+ }, "group-not-gateway-box"), /*#__PURE__*/_jsx(Line, {
152
+ depth: depth
153
+ }), blocklet.children?.length ? /*#__PURE__*/_jsx(Collapse, {
154
+ in: expand,
155
+ children: blocklet.children.map(x => /*#__PURE__*/_jsx(ComponentItem, {
156
+ blocklet: x,
157
+ ancestors: [...ancestors, blocklet],
158
+ depth: depth + 1
159
+ }, `${depth + 1}-${x.meta.did}`))
160
+ }, "blocklet-collapse") : null];
161
+ }
162
+ ComponentItem.propTypes = {
163
+ blocklet: PropTypes.object.isRequired,
164
+ ancestors: PropTypes.array,
165
+ depth: PropTypes.number
166
+ };
167
+ ComponentItem.defaultProps = {
168
+ ancestors: [],
169
+ depth: 0
170
+ };
171
+ export default function BlockletAccess() {
172
+ const {
173
+ t
174
+ } = useLocaleContext();
175
+ const {
176
+ blocklet
177
+ } = useBlockletContext();
178
+ const components = [...blocklet.children] || [];
179
+ if (blocklet.meta.group !== 'gateway') {
180
+ // add root blocklet to table list
181
+ components.unshift(blocklet);
182
+ }
183
+ return /*#__PURE__*/_jsx(Div, {
184
+ component: "div",
185
+ children: components && components.length ? [/*#__PURE__*/_jsx(Box, {
186
+ mt: 2,
187
+ ml: {
188
+ xs: '-12px',
189
+ md: '-24px'
190
+ },
191
+ style: {
192
+ maxWidth: 1080
193
+ },
194
+ children: /*#__PURE__*/_jsx(ComponentItem, {
195
+ blocklet: blocklet
196
+ }, `0-${blocklet.meta.did}`)
197
+ }, `top-blocklet-${blocklet.meta.did}`)] : /*#__PURE__*/_jsx(Box, {
198
+ mt: 8,
199
+ children: /*#__PURE__*/_jsx(Empty, {
200
+ children: t('blocklet.component.noComponent')
201
+ })
202
+ })
203
+ });
204
+ }
205
+ BlockletAccess.propTypes = {};
206
+ const Div = styled(Box)`
207
+ .title {
208
+ font-size: 1.2rem;
209
+ font-weight: bold;
210
+ margin-top: ${props => props.theme.spacing(5)};
211
+ margin-bottom: ${props => props.theme.spacing(3)};
212
+ &.first {
213
+ margin-top: 0;
214
+ }
215
+ }
216
+ `;
@@ -0,0 +1,474 @@
1
+ /* eslint-disable react/no-unstable-nested-components */
2
+ /* eslint-disable operator-linebreak */
3
+ import { useState, useContext } from 'react';
4
+ import PropTypes from 'prop-types';
5
+ import styled from '@emotion/styled';
6
+ import { useNavigate, Link } from 'react-router-dom';
7
+ import useLocalStorage from 'react-use/lib/useLocalStorage';
8
+ import IconButton from '@mui/material/IconButton';
9
+ import Menu from '@mui/material/Menu';
10
+ import Divider from '@mui/material/Divider';
11
+ import ButtonGroup from '@mui/material/ButtonGroup';
12
+ import Spinner from '@mui/material/CircularProgress';
13
+ import MenuItem from '@mui/material/MenuItem';
14
+ import MoreVertIcon from '@mui/icons-material/MoreVert';
15
+ import ListItemIcon from '@mui/material/ListItemIcon';
16
+ import ListItemText from '@mui/material/ListItemText';
17
+ import Typography from '@mui/material/Typography';
18
+ import Radio from '@mui/material/Radio';
19
+ import RadioGroup from '@mui/material/RadioGroup';
20
+ import FormControlLabel from '@mui/material/FormControlLabel';
21
+ import Alert from '@mui/material/Alert';
22
+ import Button from '@arcblock/ux/lib/Button';
23
+ import { getAppMissingConfigs, isDeletableBlocklet, hasRunnableComponent, getDisplayName, isInProgress } from '@blocklet/meta/lib/util';
24
+ import { LocaleContext } from '@arcblock/ux/lib/Locale/context';
25
+ import { BLOCKLET_CONTROLLER_STATUS, BLOCKLET_MODES, SUSPENDED_REASON } from '@blocklet/constant';
26
+ import { APP_STRUCT_VERSION } from '@abtnode/constant';
27
+ import Toast from '@arcblock/ux/lib/Toast';
28
+ import { sleep, formatError, isDownloading } from '../util';
29
+ import { getServerUrl } from './util';
30
+ import { useNodeContext } from '../contexts/node';
31
+ import Confirm from '../confirm';
32
+ import Icons from './icons';
33
+ import { useBlockletContext } from '../contexts/blocklet';
34
+ import { jsx as _jsx } from "react/jsx-runtime";
35
+ import { jsxs as _jsxs } from "react/jsx-runtime";
36
+ export default function BlockletActions({
37
+ blocklet,
38
+ onStart,
39
+ onComplete,
40
+ variant,
41
+ hasPermission,
42
+ useBlockletUrlEvaluation,
43
+ ...rest
44
+ }) {
45
+ const navigate = useNavigate();
46
+ const node = useNodeContext();
47
+ const [anchorEl, setAnchorEl] = useState(null);
48
+ const [currentAction, setCurrentAction] = useState(null);
49
+ const [loading, setLoading] = useState(false);
50
+ const [confirmSetting, setConfirmSetting] = useState(null);
51
+ const {
52
+ t
53
+ } = useContext(LocaleContext);
54
+ const [skipSetup] = useLocalStorage('skip-blocklet-setup', false);
55
+ const {
56
+ loading: recommendedUrlLoading,
57
+ recommendedUrl
58
+ } = useBlockletUrlEvaluation(blocklet);
59
+ const {
60
+ nftState
61
+ } = useBlockletContext();
62
+ const inProgress = isInProgress(blocklet.status);
63
+ let disableStart = blocklet?.controller?.status?.value === BLOCKLET_CONTROLLER_STATUS.suspended;
64
+ if (!nftState?.expired && blocklet?.controller?.status?.reason === SUSPENDED_REASON.expired) {
65
+ disableStart = false;
66
+ }
67
+ const {
68
+ inService
69
+ } = node;
70
+ const createHandler = (action, fn, requireUserConfirm = false) => async () => {
71
+ const onConfirm = async params => {
72
+ onStart({
73
+ action,
74
+ blocklet
75
+ });
76
+ setLoading(true);
77
+ setCurrentAction(action);
78
+ setConfirmSetting(null);
79
+ let isRemoved = false;
80
+ try {
81
+ if (action === 'remove') {
82
+ await fn(params);
83
+ } else if (action === 'start') {
84
+ if (!hasRunnableComponent(blocklet)) {
85
+ Toast.error(t('blocklet.noComponent'));
86
+ return;
87
+ }
88
+ if (!inService && !skipSetup && !blocklet.settings?.initialized && blocklet.mode !== BLOCKLET_MODES.DEVELOPMENT) {
89
+ // 跳转到 setup 流程界面时携带 serverUrl 查询参数
90
+ const serverUrl = getServerUrl(node.info);
91
+ const url = new URL(recommendedUrl);
92
+ url.searchParams.set('serverUrl', serverUrl);
93
+ window.open(url.href);
94
+ onComplete({
95
+ action,
96
+ blocklet
97
+ });
98
+ return;
99
+ }
100
+ const componentDids = blocklet.children.filter(x => !isInProgress(x.status) && x.status !== 'running').map(x => x.meta.did);
101
+ const input = {
102
+ did: blocklet.meta.did,
103
+ componentDids
104
+ };
105
+ await fn({
106
+ input
107
+ });
108
+ } else if (['stop', 'restart', 'reload'].includes(action)) {
109
+ const componentDids = blocklet.children.filter(x => x.status === 'running').map(x => x.meta.did);
110
+ const input = {
111
+ did: blocklet.meta.did,
112
+ componentDids
113
+ };
114
+ await fn({
115
+ input
116
+ });
117
+ } else {
118
+ const input = {
119
+ did: blocklet.meta.did
120
+ };
121
+ await fn({
122
+ input
123
+ });
124
+ }
125
+ if (action === 'remove') {
126
+ isRemoved = true; // Deleted send request and succeeded
127
+ } else {
128
+ await sleep(1000); // just avoid user feeling so fast
129
+ }
130
+
131
+ if (action === 'reload') {
132
+ Toast.success(t('blocklet.reloadSuccess'));
133
+ }
134
+ onComplete({
135
+ action,
136
+ blocklet
137
+ });
138
+ } catch (err) {
139
+ const errMsg = `Blocklet ${action} failed: ${formatError(err)}`;
140
+ onComplete({
141
+ action,
142
+ blocklet,
143
+ error: new Error(errMsg)
144
+ });
145
+ } finally {
146
+ if (!isRemoved) {
147
+ setLoading(false);
148
+ }
149
+ }
150
+ };
151
+ const onCancel = () => {
152
+ setLoading(false);
153
+ setConfirmSetting(null);
154
+ };
155
+ const name = getDisplayName(blocklet, true);
156
+ const removeSetting = blocklet.mode === BLOCKLET_MODES.DEVELOPMENT ? {
157
+ description: () => /*#__PURE__*/_jsx(Typography, {
158
+ component: "div",
159
+ children: /*#__PURE__*/_jsx(Typography, {
160
+ gutterBottom: true,
161
+ children: t('blocklet.action.removeApplicationDescription')
162
+ })
163
+ }),
164
+ params: {
165
+ removeType: 'complete'
166
+ }
167
+ } : {
168
+ description: (params, setParams) => /*#__PURE__*/_jsxs(Typography, {
169
+ component: "div",
170
+ children: [/*#__PURE__*/_jsx(Typography, {
171
+ gutterBottom: true,
172
+ children: t('blocklet.action.removeApplicationDescription')
173
+ }), /*#__PURE__*/_jsxs(RadioGroup, {
174
+ name: "removeType",
175
+ value: params.removeType,
176
+ onChange: e => setParams({
177
+ ...params,
178
+ removeType: e.target.value
179
+ }),
180
+ children: [/*#__PURE__*/_jsx(FormControlLabel, {
181
+ value: "backup",
182
+ control: /*#__PURE__*/_jsx(Radio, {}),
183
+ label: t('blocklet.action.removeApplicationAfterBackup')
184
+ }), /*#__PURE__*/_jsx(FormControlLabel, {
185
+ value: "complete",
186
+ control: /*#__PURE__*/_jsx(Radio, {}),
187
+ label: t('blocklet.action.removeApplicationComplete')
188
+ })]
189
+ })]
190
+ }),
191
+ params: {
192
+ removeType: 'backup'
193
+ }
194
+ };
195
+ const confirmSettings = {
196
+ stop: {
197
+ title: `${t('common.stop')} ${name}`,
198
+ description: t('blocklet.action.stopDescription'),
199
+ confirm: t('blocklet.action.confirmStop'),
200
+ cancel: t('common.cancel'),
201
+ onConfirm,
202
+ onCancel
203
+ },
204
+ restart: {
205
+ title: `${t('common.restart')} ${name}`,
206
+ description: t('blocklet.action.restartDescription'),
207
+ confirm: t('blocklet.action.confirmRestart'),
208
+ cancel: t('common.cancel'),
209
+ onConfirm,
210
+ onCancel
211
+ },
212
+ remove: {
213
+ title: `${t('common.remove')} ${name}`,
214
+ confirm: t('blocklet.action.confirmRemove'),
215
+ cancel: t('common.cancel'),
216
+ onConfirm,
217
+ onCancel,
218
+ ...removeSetting
219
+ },
220
+ cancelDownload: {
221
+ title: `${t('common.cancel')}`,
222
+ description: t('blocklet.action.cancelDownloadDescription', {
223
+ name
224
+ }),
225
+ confirm: t('common.confirm'),
226
+ cancel: t('common.cancel'),
227
+ onConfirm,
228
+ onCancel
229
+ }
230
+ };
231
+ if (requireUserConfirm) {
232
+ setConfirmSetting(confirmSettings[action]);
233
+ } else {
234
+ await onConfirm();
235
+ }
236
+ };
237
+ const open = Boolean(anchorEl);
238
+ const onOpen = e => {
239
+ try {
240
+ e.stopPropagation();
241
+ e.preventDefault();
242
+ // eslint-disable-next-line no-empty
243
+ } catch {}
244
+ setAnchorEl(e.currentTarget);
245
+ };
246
+ const onClose = e => {
247
+ try {
248
+ e.stopPropagation();
249
+ e.preventDefault();
250
+ // eslint-disable-next-line no-empty
251
+ } catch {}
252
+ setAnchorEl(null);
253
+ };
254
+ const onAction = async (action, e) => {
255
+ try {
256
+ e.stopPropagation();
257
+ e.preventDefault();
258
+ // eslint-disable-next-line no-empty
259
+ } catch {}
260
+ setAnchorEl(null);
261
+ if (typeof action.handler === 'function') {
262
+ try {
263
+ setLoading(true);
264
+ setCurrentAction(action.action);
265
+ await action.handler();
266
+ } catch (err) {
267
+ // eslint-disable-next-line no-console
268
+ console.error(`Blocklet ${action.name} failed: `, err);
269
+ } finally {
270
+ setLoading(false);
271
+ }
272
+ }
273
+ };
274
+ const removeAction = !inService && isDeletableBlocklet(blocklet) && blocklet.structVersion === APP_STRUCT_VERSION ? {
275
+ action: 'remove',
276
+ icon: Icons.Remove,
277
+ name: t('common.remove'),
278
+ handler: createHandler('remove', async ({
279
+ removeType
280
+ }) => {
281
+ if (removeType === 'backup') {
282
+ await node.api.backupBlocklet({
283
+ input: {
284
+ appDid: blocklet.appDid,
285
+ to: 'disk'
286
+ }
287
+ });
288
+ }
289
+ await node.api.deleteBlocklet({
290
+ input: {
291
+ did: blocklet.meta.did,
292
+ keepData: false
293
+ }
294
+ });
295
+ }, true),
296
+ disabled: inProgress
297
+ } : null;
298
+ const cancelDownloadAction = {
299
+ action: 'remove',
300
+ icon: Icons.Remove,
301
+ name: t('common.cancel'),
302
+ handler: createHandler('cancelDownload', node.api.cancelDownloadBlocklet, true)
303
+ };
304
+ const missingRequiredConfigs = getAppMissingConfigs(blocklet);
305
+ const actions = [{
306
+ action: 'start',
307
+ icon: Icons.Start,
308
+ name: t('common.start'),
309
+ handler: createHandler('start', node.api.startBlocklet),
310
+ disabled: disableStart || blocklet.children.every(x => x.status === 'running') || isDownloading(blocklet.status) || recommendedUrlLoading || inProgress
311
+ }, {
312
+ action: 'stop',
313
+ icon: Icons.Stop,
314
+ name: t('common.stop'),
315
+ handler: createHandler('stop', node.api.stopBlocklet, true),
316
+ disabled: !['running', 'starting'].includes(blocklet.status)
317
+ }, {
318
+ action: 'restart',
319
+ icon: Icons.Restart,
320
+ name: t('common.restart'),
321
+ handler: createHandler('restart', node.api.restartBlocklet, true),
322
+ disabled: disableStart || blocklet.status !== 'running'
323
+ }, {
324
+ action: 'reload',
325
+ icon: Icons.Reload,
326
+ name: t('common.reload'),
327
+ handler: createHandler('reload', node.api.reloadBlocklet),
328
+ disabled: disableStart || blocklet.status !== 'running'
329
+ }, isDownloading(blocklet.status) ? cancelDownloadAction : removeAction, {
330
+ separator: true
331
+ }, {
332
+ onlyInMenu: true,
333
+ action: 'config',
334
+ icon: Icons.Config,
335
+ name: t('common.config'),
336
+ handler: () => {
337
+ navigate(`/blocklets/${blocklet.meta.did}/configuration`);
338
+ },
339
+ disabled: isDownloading(blocklet.status)
340
+ }, {
341
+ onlyInMenu: true,
342
+ action: 'team',
343
+ icon: Icons.Group,
344
+ name: t('common.manageTeam'),
345
+ handler: () => {
346
+ navigate(`/blocklets/${blocklet.meta.did}/members`);
347
+ },
348
+ disabled: isDownloading(blocklet.status)
349
+ }, {
350
+ onlyInMenu: true,
351
+ action: 'log',
352
+ icon: Icons.Log,
353
+ name: t('common.log'),
354
+ handler: () => {
355
+ navigate(`/logs/blocklet-${blocklet.meta.did}`);
356
+ },
357
+ disabled: isDownloading(blocklet.status)
358
+ }].filter(Boolean);
359
+ if (variant === 'menu') {
360
+ return /*#__PURE__*/_jsxs(Div, {
361
+ "data-cy": "blocklet-actions",
362
+ children: [/*#__PURE__*/_jsx(IconButton, {
363
+ "aria-label": "more",
364
+ "aria-controls": "actions-menu",
365
+ "aria-haspopup": "true",
366
+ "data-cy": "trigger-blocklet-actions",
367
+ "actions-blocklet-did": blocklet.meta.did,
368
+ onClick: onOpen,
369
+ size: "small",
370
+ disabled: !hasPermission || !isDownloading(blocklet.status) && loading,
371
+ children: /*#__PURE__*/_jsx(MoreVertIcon, {})
372
+ }), /*#__PURE__*/_jsxs(Menu, {
373
+ id: "actions-menu",
374
+ anchorEl: anchorEl,
375
+ keepMounted: true,
376
+ open: open,
377
+ onClose: onClose,
378
+ PaperProps: {},
379
+ children: [missingRequiredConfigs.length > 0 && /*#__PURE__*/_jsxs(Alert, {
380
+ style: {
381
+ maxWidth: '400px'
382
+ },
383
+ severity: "error",
384
+ children: [t('blocklet.config.missingRequired'), /*#__PURE__*/_jsx("br", {}), /*#__PURE__*/_jsx(Link, {
385
+ to: `/blocklets/${blocklet.meta.did}/components`,
386
+ children: t('blocklet.config.gotoFix')
387
+ })]
388
+ }), actions.map((action, i) => {
389
+ if (action.separator) {
390
+ // eslint-disable-next-line react/no-array-index-key
391
+ return /*#__PURE__*/_jsx(Divider, {}, `separator-${i}`);
392
+ }
393
+ return /*#__PURE__*/_jsxs(MenuItem, {
394
+ dense: true,
395
+ onClick: e => onAction(action, e),
396
+ disabled: action.disabled,
397
+ "data-cy": `${action.action}-blocklet`,
398
+ children: [/*#__PURE__*/_jsx(ListItemIcon, {
399
+ style: {
400
+ minWidth: 24
401
+ },
402
+ children: /*#__PURE__*/_jsx(action.icon, {
403
+ fontSize: "small"
404
+ })
405
+ }), /*#__PURE__*/_jsx(ListItemText, {
406
+ primary: action.name
407
+ })]
408
+ }, action.name);
409
+ })]
410
+ }), confirmSetting && /*#__PURE__*/_jsx(Confirm, {
411
+ title: confirmSetting.title,
412
+ description: confirmSetting.description,
413
+ confirm: confirmSetting.confirm,
414
+ cancel: confirmSetting.cancel,
415
+ params: confirmSetting.params,
416
+ onConfirm: confirmSetting.onConfirm,
417
+ onCancel: confirmSetting.onCancel
418
+ })]
419
+ });
420
+ }
421
+ return /*#__PURE__*/_jsxs(Div, {
422
+ "data-cy": "blocklet-actions",
423
+ ...rest,
424
+ children: [/*#__PURE__*/_jsx(ButtonGroup, {
425
+ children: actions.filter(x => !x.separator && !x.onlyInMenu).map(action => /*#__PURE__*/_jsxs(Button, {
426
+ title: action.name,
427
+ "data-cy": `${action.action}-blocklet`,
428
+ onClick: () => onAction(action),
429
+ disabled: Boolean(action.disabled) || loading,
430
+ children: [currentAction === action.action && loading && inProgress ? /*#__PURE__*/_jsx(Spinner, {
431
+ size: 16
432
+ }) : /*#__PURE__*/_jsx(action.icon, {}), /*#__PURE__*/_jsx("span", {
433
+ className: "blocklet-action-text",
434
+ children: action.name
435
+ })]
436
+ }, action.name))
437
+ }), confirmSetting && /*#__PURE__*/_jsx(Confirm, {
438
+ title: confirmSetting.title,
439
+ description: confirmSetting.description,
440
+ confirm: confirmSetting.confirm,
441
+ cancel: confirmSetting.cancel,
442
+ params: confirmSetting.params,
443
+ onConfirm: confirmSetting.onConfirm,
444
+ onCancel: confirmSetting.onCancel
445
+ })]
446
+ });
447
+ }
448
+ BlockletActions.propTypes = {
449
+ blocklet: PropTypes.object.isRequired,
450
+ onStart: PropTypes.func.isRequired,
451
+ onComplete: PropTypes.func.isRequired,
452
+ variant: PropTypes.oneOf(['menu', 'group']),
453
+ hasPermission: PropTypes.bool,
454
+ useBlockletUrlEvaluation: PropTypes.func
455
+ };
456
+ BlockletActions.defaultProps = {
457
+ variant: 'menu',
458
+ hasPermission: false,
459
+ useBlockletUrlEvaluation: () => ({
460
+ loading: false,
461
+ recommendedUrl: window?.location?.href
462
+ })
463
+ };
464
+ const Div = styled.div`
465
+ display: flex;
466
+ align-items: center;
467
+
468
+ @media (max-width: ${props => props.theme.breakpoints.values.sm}px) {
469
+ .MuiButton-root {
470
+ padding: 4px;
471
+ font-size: 10px;
472
+ }
473
+ }
474
+ `;