@powerhousedao/academy 5.0.3 → 5.0.5
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/CHANGELOG.md +8 -0
- package/docs/academy/00-EthereumArgentinaHackathon.md +207 -0
- package/docs/academy/01-GetStarted/00-ExploreDemoPackage.mdx +1 -1
- package/docs/academy/01-GetStarted/05-VetraStudio.md +76 -27
- package/docs/academy/01-GetStarted/home.mdx +4 -4
- package/docs/academy/02-MasteryTrack/01-BuilderEnvironment/01-Prerequisites.md +24 -8
- package/docs/academy/02-MasteryTrack/01-BuilderEnvironment/02-StandardDocumentModelWorkflow.md +25 -7
- package/docs/academy/02-MasteryTrack/01-BuilderEnvironment/03-BuilderTools.md +17 -3
- package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/01-WhatIsADocumentModel.md +5 -2
- package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/06-ImplementDocumentModelTests.md +7 -1
- package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/07-ExampleToDoListRepository.md +5 -5
- package/docs/academy/03-ExampleUsecases/Chatroom/02-CreateNewPowerhouseProject.md +4 -1
- package/docs/academy/03-ExampleUsecases/Chatroom/03-DefineChatroomDocumentModel.md +21 -9
- package/docs/academy/03-ExampleUsecases/Chatroom/04-ImplementOperationReducers.md +132 -129
- package/docs/academy/03-ExampleUsecases/Chatroom/05-ImplementChatroomEditor.md +50 -44
- package/docs/academy/03-ExampleUsecases/Chatroom/image-4.png +0 -0
- package/docs/academy/03-ExampleUsecases/Chatroom/image-5.png +0 -0
- package/docs/academy/03-ExampleUsecases/Chatroom/images/ChatRoomConnectApp.gif +0 -0
- package/docs/academy/03-ExampleUsecases/Chatroom/images/ChatRoomTest.gif +0 -0
- package/docs/academy/04-APIReferences/00-PowerhouseCLI.md +39 -5
- package/docs/academy/05-Architecture/01-WorkingWithTheReactor.md +0 -2
- package/package.json +1 -1
- package/sidebars.ts +8 -0
- package/src/css/custom.css +20 -0
- package/static/img/ethereum-logo.jpeg +0 -0
- package/docs/academy/09-AIResources +0 -131
- package/docs/academy/TUTORIAL_VERIFICATION_ARCHITECTURE +0 -325
- /package/docs/academy/02-MasteryTrack/03-BuildingUserExperiences/06-DocumentTools/{02-RevisionHistoryTimeline.md → 02-RevisionHistoryTimeline} +0 -0
|
@@ -9,7 +9,7 @@ Run below command to generate the editor template for the `Chatroom` document mo
|
|
|
9
9
|
Notice the `--editor` flag which defines the `chatroom` document model editor. And the `--document-types` flag which defines the document type `powerhouse/chatroom`.
|
|
10
10
|
|
|
11
11
|
```bash
|
|
12
|
-
ph generate --
|
|
12
|
+
ph generate --editor ChatRoomEditor --document-types powerhouse/chat-room
|
|
13
13
|
```
|
|
14
14
|
|
|
15
15
|
Once complete, navigate to the `editors/chat-room/editor.tsx` file and open it in your editor.
|
|
@@ -37,36 +37,41 @@ The utils function will help you with mapping information from the document mode
|
|
|
37
37
|
Now, let's copy & paste the code below into the `editor.tsx` file located at `editors/chat-room-editor`and save the file.
|
|
38
38
|
|
|
39
39
|
```typescript
|
|
40
|
-
|
|
41
|
-
import {
|
|
40
|
+
import { generateId } from "document-model/core";
|
|
41
|
+
import { useUser } from "@powerhousedao/reactor-browser/connect";
|
|
42
|
+
import { useSelectedChatRoomDocument } from "../../document-models/chat-room/hooks.js";
|
|
42
43
|
import {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
} from "../../document-models/chat-room";
|
|
49
|
-
import {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
const disableChatRoom = !
|
|
44
|
+
addMessage,
|
|
45
|
+
addEmojiReaction,
|
|
46
|
+
removeEmojiReaction,
|
|
47
|
+
editChatName,
|
|
48
|
+
editChatDescription,
|
|
49
|
+
} from "../../document-models/chat-room/gen/creators.js";
|
|
50
|
+
import {
|
|
51
|
+
ChatRoom,
|
|
52
|
+
type ChatRoomProps,
|
|
53
|
+
type MessageProps,
|
|
54
|
+
} from "./components/index.js";
|
|
55
|
+
import { reactionKeyToReactionType, mapReactions } from "./utils.js";
|
|
56
|
+
|
|
57
|
+
export default function Editor() {
|
|
58
|
+
const [document, dispatch] = useSelectedChatRoomDocument();
|
|
59
|
+
const user = useUser();
|
|
60
|
+
|
|
61
|
+
const disableChatRoom = !user;
|
|
62
|
+
|
|
63
|
+
if (!document) {
|
|
64
|
+
return <div>Loading...</div>;
|
|
65
|
+
}
|
|
61
66
|
|
|
62
67
|
const messages: ChatRoomProps["messages"] =
|
|
63
|
-
|
|
68
|
+
document.state.global.messages.map((message) => ({
|
|
64
69
|
id: message.id,
|
|
65
70
|
message: message.content || "",
|
|
66
71
|
timestamp: message.sentAt,
|
|
67
72
|
userName: message.sender.name || message.sender.id,
|
|
68
|
-
imgUrl: message.sender.avatarUrl || undefined,
|
|
69
|
-
isCurrentUser: message.sender.id ===
|
|
73
|
+
imgUrl: message.sender.avatarUrl || undefined,
|
|
74
|
+
isCurrentUser: message.sender.id === user?.address,
|
|
70
75
|
reactions: mapReactions(message.reactions),
|
|
71
76
|
}));
|
|
72
77
|
|
|
@@ -75,14 +80,14 @@ export default function Editor(props: IProps) {
|
|
|
75
80
|
return;
|
|
76
81
|
}
|
|
77
82
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
messageId:
|
|
83
|
+
dispatch(
|
|
84
|
+
addMessage({
|
|
85
|
+
messageId: generateId(),
|
|
81
86
|
content: message,
|
|
82
87
|
sender: {
|
|
83
|
-
id:
|
|
84
|
-
name:
|
|
85
|
-
avatarUrl:
|
|
88
|
+
id: user?.address || "anon-user",
|
|
89
|
+
name: user?.ens?.name || null,
|
|
90
|
+
avatarUrl: user?.ens?.avatarUrl || null,
|
|
86
91
|
},
|
|
87
92
|
sentAt: new Date().toISOString(),
|
|
88
93
|
}),
|
|
@@ -92,10 +97,10 @@ export default function Editor(props: IProps) {
|
|
|
92
97
|
const addReaction = (
|
|
93
98
|
messageId: string,
|
|
94
99
|
userId: string,
|
|
95
|
-
reactionType:
|
|
100
|
+
reactionType: "HEART" | "THUMBS_UP" | "THUMBS_DOWN" | "LAUGH" | "CRY",
|
|
96
101
|
) => {
|
|
97
|
-
|
|
98
|
-
|
|
102
|
+
dispatch(
|
|
103
|
+
addEmojiReaction({
|
|
99
104
|
messageId,
|
|
100
105
|
reactedBy: userId,
|
|
101
106
|
type: reactionType,
|
|
@@ -106,10 +111,10 @@ export default function Editor(props: IProps) {
|
|
|
106
111
|
const removeReaction = (
|
|
107
112
|
messageId: string,
|
|
108
113
|
userId: string,
|
|
109
|
-
reactionType:
|
|
114
|
+
reactionType: "HEART" | "THUMBS_UP" | "THUMBS_DOWN" | "LAUGH" | "CRY",
|
|
110
115
|
) => {
|
|
111
|
-
|
|
112
|
-
|
|
116
|
+
dispatch(
|
|
117
|
+
removeEmojiReaction({
|
|
113
118
|
messageId,
|
|
114
119
|
senderId: userId,
|
|
115
120
|
type: reactionType,
|
|
@@ -117,7 +122,7 @@ export default function Editor(props: IProps) {
|
|
|
117
122
|
);
|
|
118
123
|
};
|
|
119
124
|
|
|
120
|
-
const onClickReaction: MessageProps["onClickReaction"] = (reaction) => {
|
|
125
|
+
const onClickReaction: MessageProps["onClickReaction"] = (reaction) => {
|
|
121
126
|
const message = messages.find(
|
|
122
127
|
(message) => message.id === reaction.messageId,
|
|
123
128
|
);
|
|
@@ -128,7 +133,7 @@ export default function Editor(props: IProps) {
|
|
|
128
133
|
|
|
129
134
|
const messageId = reaction.messageId;
|
|
130
135
|
const reactionType = reactionKeyToReactionType(reaction.type);
|
|
131
|
-
const currentUserId =
|
|
136
|
+
const currentUserId = user?.address || "anon-user";
|
|
132
137
|
|
|
133
138
|
const existingReaction = message.reactions?.find(
|
|
134
139
|
(r) => r.type === reaction.type,
|
|
@@ -146,13 +151,13 @@ export default function Editor(props: IProps) {
|
|
|
146
151
|
};
|
|
147
152
|
|
|
148
153
|
const onSubmitTitle: ChatRoomProps["onSubmitTitle"] = (title) => {
|
|
149
|
-
|
|
154
|
+
dispatch(editChatName({ name: title }));
|
|
150
155
|
};
|
|
151
156
|
|
|
152
157
|
const onSubmitDescription: ChatRoomProps["onSubmitDescription"] = (
|
|
153
158
|
description,
|
|
154
159
|
) => {
|
|
155
|
-
|
|
160
|
+
dispatch(editChatDescription({ description }));
|
|
156
161
|
};
|
|
157
162
|
|
|
158
163
|
return (
|
|
@@ -163,18 +168,19 @@ export default function Editor(props: IProps) {
|
|
|
163
168
|
>
|
|
164
169
|
<ChatRoom
|
|
165
170
|
description={
|
|
166
|
-
|
|
171
|
+
document.state.global.description || "This is a chat room demo"
|
|
167
172
|
}
|
|
168
|
-
disabled={disableChatRoom}
|
|
169
|
-
messages={messages}
|
|
173
|
+
disabled={disableChatRoom}
|
|
174
|
+
messages={messages}
|
|
170
175
|
onClickReaction={onClickReaction}
|
|
171
176
|
onSendMessage={onSendMessage}
|
|
172
177
|
onSubmitDescription={onSubmitDescription}
|
|
173
178
|
onSubmitTitle={onSubmitTitle}
|
|
174
|
-
title={
|
|
179
|
+
title={document.state.global.name || "Chat Room Demo"}
|
|
175
180
|
/>
|
|
176
181
|
</div>
|
|
177
182
|
);
|
|
183
|
+
}
|
|
178
184
|
```
|
|
179
185
|
|
|
180
186
|
Now you can run the Connect app and see the `Chatroom` editor in action.
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -16,11 +16,43 @@ pnpm install -g ph-cmd
|
|
|
16
16
|
|
|
17
17
|
:::
|
|
18
18
|
|
|
19
|
-
<!-- AUTO-GENERATED-CLI-COMMANDS-START -->\n<!-- This content is automatically generated. Do not edit directly. -->\n### ph-cmd Commands\n\n- [
|
|
19
|
+
<!-- AUTO-GENERATED-CLI-COMMANDS-START -->\n<!-- This content is automatically generated. Do not edit directly. -->\n### ph-cmd Commands\n\n- [Checkout](#checkout)
|
|
20
|
+
- [Init](#init)
|
|
20
21
|
- [Setup Globals](#setup-globals)
|
|
21
22
|
- [Update](#update)
|
|
22
23
|
- [Use](#use)
|
|
23
24
|
|
|
25
|
+
## Checkout
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
Command Overview:
|
|
29
|
+
The checkout command clones an existing Powerhouse project from a remote Vetra drive.
|
|
30
|
+
This allows you to work on projects that have been initialized and configured by others.
|
|
31
|
+
|
|
32
|
+
This command:
|
|
33
|
+
1. Fetches the GitHub repository URL from the specified Vetra remote drive
|
|
34
|
+
2. Clones the repository to your local machine
|
|
35
|
+
3. Installs all project dependencies
|
|
36
|
+
|
|
37
|
+
Required Options:
|
|
38
|
+
-r, --remote-drive <url> URL of the Vetra remote drive containing the project.
|
|
39
|
+
The drive must have a Vetra package with a configured GitHub URL.
|
|
40
|
+
|
|
41
|
+
Options:
|
|
42
|
+
--package-manager <pm> Specify which package manager to use for installing dependencies.
|
|
43
|
+
Supported: npm, yarn, pnpm, bun
|
|
44
|
+
If not specified, uses the detected package manager from your environment.
|
|
45
|
+
|
|
46
|
+
Examples:
|
|
47
|
+
$ ph checkout --remote-drive https://vetra.example.com/d/abc123 # Clone project using default package manager
|
|
48
|
+
$ ph checkout --remote-drive https://vetra.example.com/d/abc123 --package-manager pnpm # Clone and install with pnpm
|
|
49
|
+
|
|
50
|
+
Notes:
|
|
51
|
+
- The remote drive must contain a Vetra package document with a GitHub URL configured
|
|
52
|
+
- If no GitHub URL is found, you'll need to use 'ph init --remote-drive' instead to create a new project
|
|
53
|
+
- The repository will be cloned into a directory named after the repository
|
|
54
|
+
```
|
|
55
|
+
|
|
24
56
|
## Init
|
|
25
57
|
|
|
26
58
|
```
|
|
@@ -44,12 +76,14 @@ Options:
|
|
|
44
76
|
|
|
45
77
|
-i, --interactive Run the command in interactive mode, which will guide you
|
|
46
78
|
through the project setup with customizable options.
|
|
79
|
+
|
|
80
|
+
-t, --tag Version of the Powerhouse dependencies to use. Defaults to "main"
|
|
47
81
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
--dev Use the "development" version of the boilerplate.
|
|
82
|
+
--dev Use the "development" version.
|
|
51
83
|
|
|
52
|
-
--staging Use the "staging" version
|
|
84
|
+
--staging Use the "staging" version.
|
|
85
|
+
|
|
86
|
+
-b, --branch Specify custom boilerplate branch to use.
|
|
53
87
|
|
|
54
88
|
--package-manager Override the auto-detected package manager with the specified one.
|
|
55
89
|
|
|
@@ -47,5 +47,3 @@ In addition to the choice of storage, Reactors also have other configurations.
|
|
|
47
47
|
|
|
48
48
|
- The **operational data** and **read models** associated with the document models inside a reactor allow to query the gathered data inside a document model or quickly visualize the crucial insights at a glance.
|
|
49
49
|
- **Listeners**, which continuously listen to any changes in a document model, help us to connect additional tools such as codegenerators and scripts to the reactors and the document models it holds
|
|
50
|
-
|
|
51
|
-
> Jump to: Configure a listener for your reactor and add a codegenerator
|
package/package.json
CHANGED
package/sidebars.ts
CHANGED
|
@@ -11,6 +11,14 @@
|
|
|
11
11
|
const sidebars = {
|
|
12
12
|
// By default, Docusaurus generates a sidebar from the docs folder structure
|
|
13
13
|
academySidebar: [
|
|
14
|
+
{
|
|
15
|
+
type: "doc",
|
|
16
|
+
id: "academy/EthereumArgentinaHackathon",
|
|
17
|
+
label: "ETH Argentina Hackathon",
|
|
18
|
+
customProps: {
|
|
19
|
+
icon: "/img/ethereum-logo.jpg",
|
|
20
|
+
},
|
|
21
|
+
},
|
|
14
22
|
{
|
|
15
23
|
type: "category",
|
|
16
24
|
label: "Get started",
|
package/src/css/custom.css
CHANGED
|
@@ -525,3 +525,23 @@ html[data-theme="dark"] .DocSearch-Hits > *:empty {
|
|
|
525
525
|
margin-top: 0.5rem;
|
|
526
526
|
font-style: italic;
|
|
527
527
|
}
|
|
528
|
+
|
|
529
|
+
/* Ethereum Argentina Hackathon sidebar icon */
|
|
530
|
+
.menu__link[href*="EthereumArgentinaHackathon"] {
|
|
531
|
+
display: flex !important;
|
|
532
|
+
align-items: center !important;
|
|
533
|
+
gap: 8px !important;
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
.menu__link[href*="EthereumArgentinaHackathon"]::before {
|
|
537
|
+
content: "" !important;
|
|
538
|
+
display: inline-block !important;
|
|
539
|
+
width: 24px !important;
|
|
540
|
+
height: 24px !important;
|
|
541
|
+
min-width: 24px !important;
|
|
542
|
+
background-image: url("/img/ethereum-logo.jpeg") !important;
|
|
543
|
+
background-size: cover !important;
|
|
544
|
+
background-position: center !important;
|
|
545
|
+
border-radius: 50% !important;
|
|
546
|
+
flex-shrink: 0 !important;
|
|
547
|
+
}
|
|
Binary file
|
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
# AI Resources
|
|
2
|
-
|
|
3
|
-
We have a couple of AI resources to help you with your daily work or exploring our ecosystem.
|
|
4
|
-
|
|
5
|
-
:::warning
|
|
6
|
-
- Be aware that AI tooling can make mistakes.
|
|
7
|
-
- Documentation can be out of date or code can be work in progress.
|
|
8
|
-
- Always verify your coding agent's suggestions.
|
|
9
|
-
:::
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
| Tool | Description |
|
|
13
|
-
|---|---|
|
|
14
|
-
| [**Deepwiki**](https://deepwiki.com/powerhouse-inc/powerhouse) | A searchable/queriable wiki to understand our growing Powerhouse **Monorepository** better. <br /> DeepWiki provides up-to-date documentation you can talk to, for every repo in the world. Think Deep Research for GitHub. |
|
|
15
|
-
| [**Context7**](https://context7.com/powerhouse-inc/powerhouse) | The Powerhouse **Academy Documentation** is also available as context through the context7 MCP Server. <br /> LLMs rely on outdated or generic information about the libraries you use. <br /> Context7 pulls up-to-date, version-specific documentation and code examples directly from the source. <br /> Paste accurate, relevant documentation directly into tools like Cursor, Claude, or any LLM. <br /> The official repository can be found [here](https://github.com/upstash/context7). |
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
### Context7 Installation
|
|
19
|
-
|
|
20
|
-
<details>
|
|
21
|
-
<summary><b>Install in Cursor</b></summary>
|
|
22
|
-
|
|
23
|
-
Go to: `Settings` -> `Cursor Settings` -> `MCP` -> `Add new global MCP server`
|
|
24
|
-
|
|
25
|
-
Pasting the following configuration into your Cursor `~/.cursor/mcp.json` file is the recommended approach. You may also install in a specific project by creating `.cursor/mcp.json` in your project folder.
|
|
26
|
-
|
|
27
|
-
**Cursor Local Server Connection**
|
|
28
|
-
|
|
29
|
-
```json
|
|
30
|
-
{
|
|
31
|
-
"mcpServers": {
|
|
32
|
-
"context7": {
|
|
33
|
-
"command": "npx",
|
|
34
|
-
"args": ["-y", "@upstash/context7-mcp"]
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
</details>
|
|
41
|
-
|
|
42
|
-
<details>
|
|
43
|
-
<summary><b>Install in VS Code</b></summary>
|
|
44
|
-
|
|
45
|
-
Add this to your VS Code MCP config file. See [VS Code MCP docs](https://code.visualstudio.com/docs/copilot/chat/mcp-servers) for more info.
|
|
46
|
-
|
|
47
|
-
**VS Code Local Server Connection**
|
|
48
|
-
|
|
49
|
-
```json
|
|
50
|
-
"mcp": {
|
|
51
|
-
"servers": {
|
|
52
|
-
"context7": {
|
|
53
|
-
"type": "stdio",
|
|
54
|
-
"command": "npx",
|
|
55
|
-
"args": ["-y", "@upstash/context7-mcp"]
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
```
|
|
60
|
-
</details>
|
|
61
|
-
|
|
62
|
-
For other editors, please refer to the [official documentation](https://github.com/upstash/context7#%-installation).
|
|
63
|
-
|
|
64
|
-
### Context7 Troubleshooting
|
|
65
|
-
|
|
66
|
-
<details>
|
|
67
|
-
<summary><b>MCP, Documentation or Module Not Found Errors</b></summary>
|
|
68
|
-
|
|
69
|
-
If you encounter `ERR_MODULE_NOT_FOUND`, try using `bunx` instead of `npx`:
|
|
70
|
-
|
|
71
|
-
```json
|
|
72
|
-
{
|
|
73
|
-
"mcpServers": {
|
|
74
|
-
"context7": {
|
|
75
|
-
"command": "bunx",
|
|
76
|
-
"args": ["-y", "@upstash/context7-mcp"]
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
This often resolves module resolution issues in environments where `npx` doesn't properly install or resolve packages.
|
|
83
|
-
|
|
84
|
-
</details>
|
|
85
|
-
|
|
86
|
-
<details>
|
|
87
|
-
<summary><b>ESM Resolution Issues</b></summary>
|
|
88
|
-
|
|
89
|
-
For errors like `Error: Cannot find module 'uriTemplate.js'`, try the `--experimental-vm-modules` flag:
|
|
90
|
-
|
|
91
|
-
```json
|
|
92
|
-
{
|
|
93
|
-
"mcpServers": {
|
|
94
|
-
"context7": {
|
|
95
|
-
"command": "npx",
|
|
96
|
-
"args": ["-y", "--node-options=--experimental-vm-modules", "@upstash/context7-mcp@1.0.6"]
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
</details>
|
|
103
|
-
|
|
104
|
-
<details>
|
|
105
|
-
<summary><b>TLS/Certificate Issues</b></summary>
|
|
106
|
-
|
|
107
|
-
Use the `--experimental-fetch` flag to bypass TLS-related problems:
|
|
108
|
-
|
|
109
|
-
```json
|
|
110
|
-
{
|
|
111
|
-
"mcpServers": {
|
|
112
|
-
"context7": {
|
|
113
|
-
"command": "npx",
|
|
114
|
-
"args": ["-y", "--node-options=--experimental-fetch", "@upstash/context7-mcp"]
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
```
|
|
119
|
-
|
|
120
|
-
</details>
|
|
121
|
-
|
|
122
|
-
<details>
|
|
123
|
-
<summary><b>General MCP Client Errors</b></summary>
|
|
124
|
-
|
|
125
|
-
1. Try adding `@latest` to the package name
|
|
126
|
-
2. Use `bunx` as an alternative to `npx`
|
|
127
|
-
3. Consider using `deno` as another alternative
|
|
128
|
-
4. Ensure you're using Node.js v18 or higher for native fetch support
|
|
129
|
-
|
|
130
|
-
</details>
|
|
131
|
-
|