@blocklet/ui-react 3.1.47 → 3.1.49
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/.aigne/doc-smith/config.yaml +76 -0
- package/.aigne/doc-smith/history.yaml +9 -0
- package/.aigne/doc-smith/output/structure-plan.json +249 -0
- package/.aigne/doc-smith/upload-cache.yaml +528 -0
- package/docs/_sidebar.md +19 -0
- package/docs/components-component-management-blocklet-studio.ja.md +194 -0
- package/docs/components-component-management-blocklet-studio.md +194 -0
- package/docs/components-component-management-blocklet-studio.zh-TW.md +194 -0
- package/docs/components-component-management-blocklet-studio.zh.md +194 -0
- package/docs/components-component-management-component-installer.ja.md +256 -0
- package/docs/components-component-management-component-installer.md +256 -0
- package/docs/components-component-management-component-installer.zh-TW.md +256 -0
- package/docs/components-component-management-component-installer.zh.md +256 -0
- package/docs/components-component-management.ja.md +59 -0
- package/docs/components-component-management.md +59 -0
- package/docs/components-component-management.zh-TW.md +59 -0
- package/docs/components-component-management.zh.md +59 -0
- package/docs/components-layout-dashboard.ja.md +231 -0
- package/docs/components-layout-dashboard.md +231 -0
- package/docs/components-layout-dashboard.zh-TW.md +231 -0
- package/docs/components-layout-dashboard.zh.md +231 -0
- package/docs/components-layout-footer.ja.md +165 -0
- package/docs/components-layout-footer.md +165 -0
- package/docs/components-layout-footer.zh-TW.md +165 -0
- package/docs/components-layout-footer.zh.md +165 -0
- package/docs/components-layout-header.ja.md +233 -0
- package/docs/components-layout-header.md +233 -0
- package/docs/components-layout-header.zh-TW.md +233 -0
- package/docs/components-layout-header.zh.md +233 -0
- package/docs/components-layout.ja.md +50 -0
- package/docs/components-layout.md +50 -0
- package/docs/components-layout.zh-TW.md +50 -0
- package/docs/components-layout.zh.md +50 -0
- package/docs/components-notifications.ja.md +173 -0
- package/docs/components-notifications.md +173 -0
- package/docs/components-notifications.zh-TW.md +174 -0
- package/docs/components-notifications.zh.md +173 -0
- package/docs/components-user-management-user-center.ja.md +183 -0
- package/docs/components-user-management-user-center.md +183 -0
- package/docs/components-user-management-user-center.zh-TW.md +183 -0
- package/docs/components-user-management-user-center.zh.md +183 -0
- package/docs/components-user-management-user-sessions.ja.md +164 -0
- package/docs/components-user-management-user-sessions.md +164 -0
- package/docs/components-user-management-user-sessions.zh-TW.md +164 -0
- package/docs/components-user-management-user-sessions.zh.md +164 -0
- package/docs/components-user-management.ja.md +76 -0
- package/docs/components-user-management.md +76 -0
- package/docs/components-user-management.zh-TW.md +76 -0
- package/docs/components-user-management.zh.md +76 -0
- package/docs/components-utilities-icon.ja.md +106 -0
- package/docs/components-utilities-icon.md +106 -0
- package/docs/components-utilities-icon.zh-TW.md +106 -0
- package/docs/components-utilities-icon.zh.md +106 -0
- package/docs/components-utilities.ja.md +136 -0
- package/docs/components-utilities.md +136 -0
- package/docs/components-utilities.zh-TW.md +136 -0
- package/docs/components-utilities.zh.md +136 -0
- package/docs/components.ja.md +27 -0
- package/docs/components.md +27 -0
- package/docs/components.zh-TW.md +27 -0
- package/docs/components.zh.md +27 -0
- package/docs/core-concepts.ja.md +164 -0
- package/docs/core-concepts.md +164 -0
- package/docs/core-concepts.zh-TW.md +164 -0
- package/docs/core-concepts.zh.md +164 -0
- package/docs/getting-started.ja.md +132 -0
- package/docs/getting-started.md +132 -0
- package/docs/getting-started.zh-TW.md +132 -0
- package/docs/getting-started.zh.md +132 -0
- package/docs/hooks-api.ja.md +214 -0
- package/docs/hooks-api.md +214 -0
- package/docs/hooks-api.zh-TW.md +214 -0
- package/docs/hooks-api.zh.md +214 -0
- package/docs/how-to-guides.ja.md +413 -0
- package/docs/how-to-guides.md +413 -0
- package/docs/how-to-guides.zh-TW.md +413 -0
- package/docs/how-to-guides.zh.md +413 -0
- package/docs/overview.ja.md +91 -0
- package/docs/overview.md +91 -0
- package/docs/overview.zh-TW.md +91 -0
- package/docs/overview.zh.md +91 -0
- package/glossary.md +12 -0
- package/lib/Dashboard/index.js +46 -42
- package/lib/Footer/index.js +51 -36
- package/lib/Header/index.js +48 -44
- package/lib/UserCenter/components/settings.js +1 -0
- package/lib/UserCenter/components/user-center.js +133 -133
- package/lib/blocklets.d.ts +13 -2
- package/lib/blocklets.js +40 -40
- package/lib/common/header-addons.js +37 -33
- package/package.json +7 -7
- package/src/Dashboard/index.jsx +8 -3
- package/src/Footer/index.jsx +22 -4
- package/src/Header/index.tsx +7 -2
- package/src/UserCenter/components/settings.tsx +1 -0
- package/src/UserCenter/components/user-center.tsx +6 -6
- package/src/blocklets.js +18 -9
- package/src/common/header-addons.jsx +7 -2
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
# ComponentInstaller
|
|
2
|
+
|
|
3
|
+
The `ComponentInstaller` is a utility component that acts as a gatekeeper for features that depend on other blocklets. It verifies whether specified component dependencies are installed. If they are not, it provides a user-friendly interface for administrators (`owner` or `admin` roles by default) to install them directly. If the user lacks the necessary permissions, it displays a message advising them to contact an administrator.
|
|
4
|
+
|
|
5
|
+
This component is essential for creating robust applications that can gracefully handle missing optional dependencies, improving the user experience by guiding administrators through the installation process.
|
|
6
|
+
|
|
7
|
+
## How It Works
|
|
8
|
+
|
|
9
|
+
The component's logic follows a clear, sequential process to ensure dependencies are met before rendering its child components.
|
|
10
|
+
|
|
11
|
+
```d2
|
|
12
|
+
direction: down
|
|
13
|
+
|
|
14
|
+
start: {
|
|
15
|
+
label: "Start"
|
|
16
|
+
shape: oval
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
check_dependencies: {
|
|
20
|
+
label: "Check dependencies defined in 'did' prop"
|
|
21
|
+
shape: rectangle
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
is_installed: {
|
|
25
|
+
label: "Are all dependencies installed?"
|
|
26
|
+
shape: diamond
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
render_children: {
|
|
30
|
+
label: "Render child components"
|
|
31
|
+
shape: rectangle
|
|
32
|
+
style.fill: "#d4edda"
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
check_permission: {
|
|
36
|
+
label: "Check user's role against 'roles' prop"
|
|
37
|
+
shape: rectangle
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
has_permission: {
|
|
41
|
+
label: "Does user have permission?"
|
|
42
|
+
shape: diamond
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
display_installer: {
|
|
46
|
+
label: "Display Installer UI"
|
|
47
|
+
shape: rectangle
|
|
48
|
+
style.fill: "#cce5ff"
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
is_mute: {
|
|
52
|
+
label: "Is 'noPermissionMute' prop true?"
|
|
53
|
+
shape: diamond
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
display_suggestion: {
|
|
57
|
+
label: "Display 'Contact Admin' suggestion"
|
|
58
|
+
shape: rectangle
|
|
59
|
+
style.fill: "#f8d7da"
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
render_fallback: {
|
|
63
|
+
label: "Render fallback component or null"
|
|
64
|
+
shape: rectangle
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
end: {
|
|
68
|
+
label: "End"
|
|
69
|
+
shape: oval
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
start -> check_dependencies
|
|
73
|
+
check_dependencies -> is_installed
|
|
74
|
+
is_installed -> render_children: "Yes"
|
|
75
|
+
is_installed -> check_permission: "No"
|
|
76
|
+
render_children -> end
|
|
77
|
+
|
|
78
|
+
check_permission -> has_permission
|
|
79
|
+
has_permission -> display_installer: "Yes"
|
|
80
|
+
has_permission -> is_mute: "No"
|
|
81
|
+
display_installer -> end
|
|
82
|
+
|
|
83
|
+
is_mute -> render_fallback: "Yes"
|
|
84
|
+
is_mute -> display_suggestion: "No"
|
|
85
|
+
render_fallback -> end
|
|
86
|
+
display_suggestion -> end
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
1. **Dependency Check**: It reads the `did` prop and checks against the blocklet's metadata (`window.blocklet.optionalComponents`) to determine if the required components are installed.
|
|
90
|
+
2. **Permission Check**: If any components are missing, it uses the `SessionPermission` component to verify if the current user's role matches those specified in the `roles` prop.
|
|
91
|
+
3. **Conditional Rendering**:
|
|
92
|
+
* If all dependencies are installed, it renders its `children`.
|
|
93
|
+
* If dependencies are missing and the user has permission, it displays a pop-up installation panel.
|
|
94
|
+
* If dependencies are missing and the user lacks permission, it either shows a suggestion to contact an admin or renders a `fallback` component if `noPermissionMute` is enabled.
|
|
95
|
+
|
|
96
|
+
## Basic Usage
|
|
97
|
+
|
|
98
|
+
Wrap any component or feature that relies on an optional blocklet with `ComponentInstaller`. Provide the DID of the required component.
|
|
99
|
+
|
|
100
|
+
```jsx "MyFeature.jsx" icon=logos:react
|
|
101
|
+
import ComponentInstaller from '@arcblock/blocklet-ui-react/lib/ComponentInstaller';
|
|
102
|
+
import MyDependentComponent from './MyDependentComponent';
|
|
103
|
+
|
|
104
|
+
export default function MyFeature() {
|
|
105
|
+
// Replace with the actual DID of the required component
|
|
106
|
+
const requiredComponentDid = 'z8ia2427634f1e909a304e2b963715a18';
|
|
107
|
+
|
|
108
|
+
return (
|
|
109
|
+
<ComponentInstaller did={requiredComponentDid}>
|
|
110
|
+
{/* This component will only be rendered if the dependency is met */}
|
|
111
|
+
<MyDependentComponent />
|
|
112
|
+
</ComponentInstaller>
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Props
|
|
118
|
+
|
|
119
|
+
The `ComponentInstaller` accepts the following props to customize its behavior.
|
|
120
|
+
|
|
121
|
+
<x-field-group>
|
|
122
|
+
<x-field data-name="did" data-type="string | string[]" data-required="true">
|
|
123
|
+
<x-field-desc markdown>The DID (or an array of DIDs) of the component dependencies to check. This is the primary identifier for the blocklet(s) you need.</x-field-desc>
|
|
124
|
+
</x-field>
|
|
125
|
+
<x-field data-name="children" data-type="any" data-required="true">
|
|
126
|
+
<x-field-desc markdown>The content to render once all dependencies are confirmed to be installed. Can be a standard React node or a render function.</x-field-desc>
|
|
127
|
+
</x-field>
|
|
128
|
+
<x-field data-name="roles" data-type="string[]" data-default='["owner", "admin"]'>
|
|
129
|
+
<x-field-desc markdown>An array of user roles that are permitted to see the installation UI and install missing components.</x-field-desc>
|
|
130
|
+
</x-field>
|
|
131
|
+
<x-field data-name="fallback" data-type="React.ReactNode" data-required="false">
|
|
132
|
+
<x-field-desc markdown>A fallback component to display while checking for dependencies or when `noPermissionMute` is active for a user without installation rights.</x-field-desc>
|
|
133
|
+
</x-field>
|
|
134
|
+
<x-field data-name="noPermissionMute" data-type="boolean" data-default="false">
|
|
135
|
+
<x-field-desc markdown>If `true`, users without permission will see the `fallback` component (or nothing) instead of the "contact admin" message.</x-field-desc>
|
|
136
|
+
</x-field>
|
|
137
|
+
<x-field data-name="disabled" data-type="boolean" data-default="false">
|
|
138
|
+
<x-field-desc markdown>If `true`, the component bypasses all checks and immediately renders its `children`.</x-field-desc>
|
|
139
|
+
</x-field>
|
|
140
|
+
<x-field data-name="onInstalled" data-type="function" data-required="false">
|
|
141
|
+
<x-field-desc markdown>A callback function that is triggered after the dependency check is complete. It receives the list of installed components.</x-field-desc>
|
|
142
|
+
</x-field>
|
|
143
|
+
<x-field data-name="onError" data-type="function" data-required="false">
|
|
144
|
+
<x-field-desc markdown>A callback function that is triggered if an error occurs during the dependency check. It receives the list of components that caused the error.</x-field-desc>
|
|
145
|
+
</x-field>
|
|
146
|
+
<x-field data-name="onClose" data-type="function" data-required="false">
|
|
147
|
+
<x-field-desc markdown>A callback function invoked when the installation pop-up is closed.</x-field-desc>
|
|
148
|
+
</x-field>
|
|
149
|
+
<x-field data-name="closeByOutSize" data-type="boolean" data-default="false">
|
|
150
|
+
<x-field-desc markdown>If `true`, the installation pop-up will close when the user clicks outside of it.</x-field-desc>
|
|
151
|
+
</x-field>
|
|
152
|
+
<x-field data-name="warnIcon" data-type="React.ReactNode" data-required="false">
|
|
153
|
+
<x-field-desc markdown>A custom React node to replace the default warning icon in the installation pop-up.</x-field-desc>
|
|
154
|
+
</x-field>
|
|
155
|
+
</x-field-group>
|
|
156
|
+
|
|
157
|
+
## Advanced Usage
|
|
158
|
+
|
|
159
|
+
### Checking Multiple Components
|
|
160
|
+
|
|
161
|
+
You can pass an array of DIDs to the `did` prop to check for multiple dependencies at once. The children will only render if all specified components are installed.
|
|
162
|
+
|
|
163
|
+
```jsx "MyDashboard.jsx" icon=logos:react
|
|
164
|
+
import ComponentInstaller from '@arcblock/blocklet-ui-react/lib/ComponentInstaller';
|
|
165
|
+
import AnalyticsWidget from './AnalyticsWidget';
|
|
166
|
+
import CmsWidget from './CmsWidget';
|
|
167
|
+
|
|
168
|
+
export default function MyDashboard() {
|
|
169
|
+
const requiredDids = [
|
|
170
|
+
'z8ia2427634f1e909a304e2b963715a18', // Analytics Service
|
|
171
|
+
'z8ia3c1f2e4b8e6a1b2c3d4e5f6a7b8c9', // CMS Service
|
|
172
|
+
];
|
|
173
|
+
|
|
174
|
+
return (
|
|
175
|
+
<ComponentInstaller did={requiredDids}>
|
|
176
|
+
<AnalyticsWidget />
|
|
177
|
+
<CmsWidget />
|
|
178
|
+
</ComponentInstaller>
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### Using a Fallback for Loading States
|
|
184
|
+
|
|
185
|
+
Provide a `fallback` component to improve the user experience while the dependency check is in progress. This is also useful with `noPermissionMute` to display a placeholder for unauthorized users.
|
|
186
|
+
|
|
187
|
+
```jsx "FeatureWithLoading.jsx" icon=logos:react
|
|
188
|
+
import ComponentInstaller from '@arcblock/blocklet-ui-react/lib/ComponentInstaller';
|
|
189
|
+
import CircularProgress from '@mui/material/CircularProgress';
|
|
190
|
+
import Box from '@mui/material/Box';
|
|
191
|
+
import MyDependentComponent from './MyDependentComponent';
|
|
192
|
+
|
|
193
|
+
export default function FeatureWithLoading() {
|
|
194
|
+
const LoadingSpinner = (
|
|
195
|
+
<Box sx={{ display: 'flex', justifyContent: 'center', p: 4 }}>
|
|
196
|
+
<CircularProgress />
|
|
197
|
+
</Box>
|
|
198
|
+
);
|
|
199
|
+
|
|
200
|
+
return (
|
|
201
|
+
<ComponentInstaller
|
|
202
|
+
did="z8ia2427634f1e909a304e2b963715a18"
|
|
203
|
+
fallback={LoadingSpinner}
|
|
204
|
+
noPermissionMute={true}
|
|
205
|
+
>
|
|
206
|
+
<MyDependentComponent />
|
|
207
|
+
</ComponentInstaller>
|
|
208
|
+
);
|
|
209
|
+
}
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### Custom UI with Render Props
|
|
213
|
+
|
|
214
|
+
For full control over the UI, you can pass a function as `children`. This function receives an object with `hasPermission`, `optComponents`, and `installStatus`, allowing you to build a completely custom installation interface.
|
|
215
|
+
|
|
216
|
+
```jsx "CustomInstallerButton.jsx" icon=logos:react
|
|
217
|
+
import ComponentInstaller from '@arcblock/blocklet-ui-react/lib/ComponentInstaller';
|
|
218
|
+
import Button from '@mui/material/Button';
|
|
219
|
+
|
|
220
|
+
export default function CustomInstallerButton() {
|
|
221
|
+
const requiredDid = 'z8ia2427634f1e909a304e2b963715a18';
|
|
222
|
+
|
|
223
|
+
return (
|
|
224
|
+
<ComponentInstaller did={requiredDid}>
|
|
225
|
+
{({ hasPermission, optComponents, installStatus }) => {
|
|
226
|
+
const isMissing = optComponents.length > 0;
|
|
227
|
+
const status = installStatus[requiredDid] || 'not_installed';
|
|
228
|
+
|
|
229
|
+
if (!isMissing) {
|
|
230
|
+
return <p>Feature is ready to use!</p>;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
if (!hasPermission) {
|
|
234
|
+
return <p>Please ask an admin to install the required component.</p>;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
return (
|
|
238
|
+
<Button
|
|
239
|
+
variant="contained"
|
|
240
|
+
disabled={status !== 'not_installed'}
|
|
241
|
+
onClick={() => window.open(optComponents[0].installUrl, '_blank')}
|
|
242
|
+
>
|
|
243
|
+
{status === 'not_installed' ? `Install ${optComponents[0].meta.title}` : `Installing... (${status})`}
|
|
244
|
+
</Button>
|
|
245
|
+
);
|
|
246
|
+
}}
|
|
247
|
+
</ComponentInstaller>
|
|
248
|
+
);
|
|
249
|
+
}
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
## Summary
|
|
253
|
+
|
|
254
|
+
The `ComponentInstaller` is a powerful component for managing optional dependencies within a blocklet application. It provides a structured and user-friendly way to ensure that required components are available, guiding administrators through the installation process when necessary. By using this component, you can build more resilient and feature-rich applications that adapt to the user's environment.
|
|
255
|
+
|
|
256
|
+
For further details on managing components, you may also be interested in the [BlockletStudio](./components-component-management-blocklet-studio.md) component, which offers a more comprehensive interface for resource and component management.
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
# ComponentInstaller
|
|
2
|
+
|
|
3
|
+
`ComponentInstaller` 是一個實用工具元件,對於依賴其他 blocklet 的功能扮演著守門員的角色。它會驗證指定的元件相依性是否已安裝。如果尚未安裝,它會為管理員(預設為 `owner` 或 `admin` 角色)提供一個使用者友善的介面,讓他們可以直接安裝。如果使用者缺乏必要的權限,它會顯示一則訊息,建議他們聯絡管理員。
|
|
4
|
+
|
|
5
|
+
此元件對於建立穩健的應用程式至關重要,能夠優雅地處理缺失的選用相依性,並透過引導管理員完成安裝過程來改善使用者體驗。
|
|
6
|
+
|
|
7
|
+
## 運作方式
|
|
8
|
+
|
|
9
|
+
該元件的邏輯遵循一個清晰的順序流程,以確保在渲染其子元件之前滿足所有相依性。
|
|
10
|
+
|
|
11
|
+
```d2
|
|
12
|
+
direction: down
|
|
13
|
+
|
|
14
|
+
start: {
|
|
15
|
+
label: "開始"
|
|
16
|
+
shape: oval
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
check_dependencies: {
|
|
20
|
+
label: "檢查 'did' prop 中定義的相依性"
|
|
21
|
+
shape: rectangle
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
is_installed: {
|
|
25
|
+
label: "是否所有相依性都已安裝?"
|
|
26
|
+
shape: diamond
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
render_children: {
|
|
30
|
+
label: "渲染子元件"
|
|
31
|
+
shape: rectangle
|
|
32
|
+
style.fill: "#d4edda"
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
check_permission: {
|
|
36
|
+
label: "根據 'roles' prop 檢查使用者角色"
|
|
37
|
+
shape: rectangle
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
has_permission: {
|
|
41
|
+
label: "使用者是否有權限?"
|
|
42
|
+
shape: diamond
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
display_installer: {
|
|
46
|
+
label: "顯示安裝程式 UI"
|
|
47
|
+
shape: rectangle
|
|
48
|
+
style.fill: "#cce5ff"
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
is_mute: {
|
|
52
|
+
label: "'noPermissionMute' prop 是否為 true?"
|
|
53
|
+
shape: diamond
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
display_suggestion: {
|
|
57
|
+
label: "顯示『聯絡管理員』建議"
|
|
58
|
+
shape: rectangle
|
|
59
|
+
style.fill: "#f8d7da"
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
render_fallback: {
|
|
63
|
+
label: "渲染備用元件或 null"
|
|
64
|
+
shape: rectangle
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
end: {
|
|
68
|
+
label: "結束"
|
|
69
|
+
shape: oval
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
start -> check_dependencies
|
|
73
|
+
check_dependencies -> is_installed
|
|
74
|
+
is_installed -> render_children: "是"
|
|
75
|
+
is_installed -> check_permission: "否"
|
|
76
|
+
render_children -> end
|
|
77
|
+
|
|
78
|
+
check_permission -> has_permission
|
|
79
|
+
has_permission -> display_installer: "是"
|
|
80
|
+
has_permission -> is_mute: "否"
|
|
81
|
+
display_installer -> end
|
|
82
|
+
|
|
83
|
+
is_mute -> render_fallback: "是"
|
|
84
|
+
is_mute -> display_suggestion: "否"
|
|
85
|
+
render_fallback -> end
|
|
86
|
+
display_suggestion -> end
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
1. **相依性檢查**:它會讀取 `did` prop,並對照 blocklet 的元資料(`window.blocklet.optionalComponents`)進行檢查,以確定所需元件是否已安裝。
|
|
90
|
+
2. **權限檢查**:如果有任何元件缺失,它會使用 `SessionPermission` 元件來驗證目前使用者的角色是否與 `roles` prop 中指定的角色相符。
|
|
91
|
+
3. **條件式渲染**:
|
|
92
|
+
* 如果所有相依性都已安裝,它會渲染其 `children`。
|
|
93
|
+
* 如果相依性缺失且使用者擁有權限,它會顯示一個彈出式安裝面板。
|
|
94
|
+
* 如果相依性缺失且使用者缺乏權限,它會顯示聯絡管理員的建議,或者在啟用 `noPermissionMute` 的情況下渲染一個 `fallback` 元件。
|
|
95
|
+
|
|
96
|
+
## 基本用法
|
|
97
|
+
|
|
98
|
+
將任何依賴選用 blocklet 的元件或功能用 `ComponentInstaller` 包裹起來。提供所需元件的 DID。
|
|
99
|
+
|
|
100
|
+
```jsx "MyFeature.jsx" icon=logos:react
|
|
101
|
+
import ComponentInstaller from '@arcblock/blocklet-ui-react/lib/ComponentInstaller';
|
|
102
|
+
import MyDependentComponent from './MyDependentComponent';
|
|
103
|
+
|
|
104
|
+
export default function MyFeature() {
|
|
105
|
+
// 請替換為所需元件的實際 DID
|
|
106
|
+
const requiredComponentDid = 'z8ia2427634f1e909a304e2b963715a18';
|
|
107
|
+
|
|
108
|
+
return (
|
|
109
|
+
<ComponentInstaller did={requiredComponentDid}>
|
|
110
|
+
{/* 只有在滿足相依性條件時,此元件才會被渲染 */}
|
|
111
|
+
<MyDependentComponent />
|
|
112
|
+
</ComponentInstaller>
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## 屬性 (Props)
|
|
118
|
+
|
|
119
|
+
`ComponentInstaller` 接受以下屬性 (props) 來自訂其行為。
|
|
120
|
+
|
|
121
|
+
<x-field-group>
|
|
122
|
+
<x-field data-name="did" data-type="string | string[]" data-required="true">
|
|
123
|
+
<x-field-desc markdown>要檢查的元件相依性的 DID (或 DID 陣列)。這是您所需 blocklet 的主要識別碼。</x-field-desc>
|
|
124
|
+
</x-field>
|
|
125
|
+
<x-field data-name="children" data-type="any" data-required="true">
|
|
126
|
+
<x-field-desc markdown>一旦確認所有相依性都已安裝,要渲染的內容。可以是標準的 React 節點或渲染函數。</x-field-desc>
|
|
127
|
+
</x-field>
|
|
128
|
+
<x-field data-name="roles" data-type="string[]" data-default='["owner", "admin"]'>
|
|
129
|
+
<x-field-desc markdown>允許查看安裝 UI 並安裝缺失元件的使用者角色陣列。</x-field-desc>
|
|
130
|
+
</x-field>
|
|
131
|
+
<x-field data-name="fallback" data-type="React.ReactNode" data-required="false">
|
|
132
|
+
<x-field-desc markdown>一個備用元件,用於在檢查相依性期間,或當 `noPermissionMute` 對於沒有安裝權限的使用者啟用時顯示。</x-field-desc>
|
|
133
|
+
</x-field>
|
|
134
|
+
<x-field data-name="noPermissionMute" data-type="boolean" data-default="false">
|
|
135
|
+
<x-field-desc markdown>如果為 `true`,沒有權限的使用者將看到 `fallback` 元件(或什麼都不顯示),而不是「聯絡管理員」的訊息。</x-field-desc>
|
|
136
|
+
</x-field>
|
|
137
|
+
<x-field data-name="disabled" data-type="boolean" data-default="false">
|
|
138
|
+
<x-field-desc markdown>如果為 `true`,該元件會繞過所有檢查並立即渲染其 `children`。</x-field-desc>
|
|
139
|
+
</x-field>
|
|
140
|
+
<x-field data-name="onInstalled" data-type="function" data-required="false">
|
|
141
|
+
<x-field-desc markdown>在相依性檢查完成後觸發的回呼函數。它會接收已安裝元件的列表。</x-field-desc>
|
|
142
|
+
</x-field>
|
|
143
|
+
<x-field data-name="onError" data-type="function" data-required="false">
|
|
144
|
+
<x-field-desc markdown>如果在相依性檢查期間發生錯誤時觸發的回呼函數。它會接收導致錯誤的元件列表。</x-field-desc>
|
|
145
|
+
</x-field>
|
|
146
|
+
<x-field data-name="onClose" data-type="function" data-required="false">
|
|
147
|
+
<x-field-desc markdown>當安裝彈出視窗關閉時調用的回呼函數。</x-field-desc>
|
|
148
|
+
</x-field>
|
|
149
|
+
<x-field data-name="closeByOutSize" data-type="boolean" data-default="false">
|
|
150
|
+
<x-field-desc markdown>如果為 `true`,當使用者點擊安裝彈出視窗外部時,該視窗將會關閉。</x-field-desc>
|
|
151
|
+
</x-field>
|
|
152
|
+
<x-field data-name="warnIcon" data-type="React.ReactNode" data-required="false">
|
|
153
|
+
<x-field-desc markdown>一個自訂的 React 節點,用於替換安裝彈出視窗中的預設警告圖示。</x-field-desc>
|
|
154
|
+
</x-field>
|
|
155
|
+
</x-field-group>
|
|
156
|
+
|
|
157
|
+
## 進階用法
|
|
158
|
+
|
|
159
|
+
### 檢查多個元件
|
|
160
|
+
|
|
161
|
+
您可以將一個 DID 陣列傳遞給 `did` prop,以一次性檢查多個相依性。只有在所有指定的元件都已安裝的情況下,子元件才會被渲染。
|
|
162
|
+
|
|
163
|
+
```jsx "MyDashboard.jsx" icon=logos:react
|
|
164
|
+
import ComponentInstaller from '@arcblock/blocklet-ui-react/lib/ComponentInstaller';
|
|
165
|
+
import AnalyticsWidget from './AnalyticsWidget';
|
|
166
|
+
import CmsWidget from './CmsWidget';
|
|
167
|
+
|
|
168
|
+
export default function MyDashboard() {
|
|
169
|
+
const requiredDids = [
|
|
170
|
+
'z8ia2427634f1e909a304e2b963715a18', // 分析服務
|
|
171
|
+
'z8ia3c1f2e4b8e6a1b2c3d4e5f6a7b8c9', // 內容管理系統服務
|
|
172
|
+
];
|
|
173
|
+
|
|
174
|
+
return (
|
|
175
|
+
<ComponentInstaller did={requiredDids}>
|
|
176
|
+
<AnalyticsWidget />
|
|
177
|
+
<CmsWidget />
|
|
178
|
+
</ComponentInstaller>
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### 使用備用元件處理載入狀態
|
|
184
|
+
|
|
185
|
+
提供一個 `fallback` 元件,以在相依性檢查進行中時改善使用者體驗。這對於搭配 `noPermissionMute` 為未經授權的使用者顯示佔位符也很有用。
|
|
186
|
+
|
|
187
|
+
```jsx "FeatureWithLoading.jsx" icon=logos:react
|
|
188
|
+
import ComponentInstaller from '@arcblock/blocklet-ui-react/lib/ComponentInstaller';
|
|
189
|
+
import CircularProgress from '@mui/material/CircularProgress';
|
|
190
|
+
import Box from '@mui/material/Box';
|
|
191
|
+
import MyDependentComponent from './MyDependentComponent';
|
|
192
|
+
|
|
193
|
+
export default function FeatureWithLoading() {
|
|
194
|
+
const LoadingSpinner = (
|
|
195
|
+
<Box sx={{ display: 'flex', justifyContent: 'center', p: 4 }}>
|
|
196
|
+
<CircularProgress />
|
|
197
|
+
</Box>
|
|
198
|
+
);
|
|
199
|
+
|
|
200
|
+
return (
|
|
201
|
+
<ComponentInstaller
|
|
202
|
+
did="z8ia2427634f1e909a304e2b963715a18"
|
|
203
|
+
fallback={LoadingSpinner}
|
|
204
|
+
noPermissionMute={true}
|
|
205
|
+
>
|
|
206
|
+
<MyDependentComponent />
|
|
207
|
+
</ComponentInstaller>
|
|
208
|
+
);
|
|
209
|
+
}
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### 使用渲染屬性 (Render Props) 自訂 UI
|
|
213
|
+
|
|
214
|
+
為了完全控制 UI,您可以傳遞一個函數作為 `children`。此函數會接收一個包含 `hasPermission`、`optComponents` 和 `installStatus` 的物件,讓您可以建立完全自訂的安裝介面。
|
|
215
|
+
|
|
216
|
+
```jsx "CustomInstallerButton.jsx" icon=logos:react
|
|
217
|
+
import ComponentInstaller from '@arcblock/blocklet-ui-react/lib/ComponentInstaller';
|
|
218
|
+
import Button from '@mui/material/Button';
|
|
219
|
+
|
|
220
|
+
export default function CustomInstallerButton() {
|
|
221
|
+
const requiredDid = 'z8ia2427634f1e909a304e2b963715a18';
|
|
222
|
+
|
|
223
|
+
return (
|
|
224
|
+
<ComponentInstaller did={requiredDid}>
|
|
225
|
+
{({ hasPermission, optComponents, installStatus }) => {
|
|
226
|
+
const isMissing = optComponents.length > 0;
|
|
227
|
+
const status = installStatus[requiredDid] || 'not_installed';
|
|
228
|
+
|
|
229
|
+
if (!isMissing) {
|
|
230
|
+
return <p>功能已準備就緒!</p>;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
if (!hasPermission) {
|
|
234
|
+
return <p>請要求管理員安裝所需元件。</p>;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
return (
|
|
238
|
+
<Button
|
|
239
|
+
variant="contained"
|
|
240
|
+
disabled={status !== 'not_installed'}
|
|
241
|
+
onClick={() => window.open(optComponents[0].installUrl, '_blank')}
|
|
242
|
+
>
|
|
243
|
+
{status === 'not_installed' ? `安裝 ${optComponents[0].meta.title}` : `安裝中... (${status})`}
|
|
244
|
+
</Button>
|
|
245
|
+
);
|
|
246
|
+
}}
|
|
247
|
+
</ComponentInstaller>
|
|
248
|
+
);
|
|
249
|
+
}
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
## 總結
|
|
253
|
+
|
|
254
|
+
`ComponentInstaller` 是一個強大的元件,用於管理 blocklet 應用程式中的選用相依性。它提供了一種結構化且使用者友善的方式,以確保所需元件可用,並在必要時引導管理員完成安裝過程。透過使用此元件,您可以建立更具彈性、功能更豐富且能適應使用者環境的應用程式。
|
|
255
|
+
|
|
256
|
+
有關管理元件的更多詳細資訊,您可能也會對 [BlockletStudio](./components-component-management-blocklet-studio.md) 元件感興趣,它為資源和元件管理提供了更全面的介面。
|