@powerhousedao/academy 4.1.0-staging.1 → 5.0.0-staging.10
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/.vscode/settings.json +1 -1
- package/CHANGELOG.md +127 -1
- package/README.md +3 -3
- package/babel.config.js +1 -1
- package/blog/BeyondCommunication-ABlueprintForDevelopment.md +25 -24
- package/blog/TheChallengeOfChange.md +21 -21
- package/docs/academy/01-GetStarted/00-ExploreDemoPackage.mdx +61 -24
- package/docs/academy/01-GetStarted/01-CreateNewPowerhouseProject.md +21 -12
- package/docs/academy/01-GetStarted/02-DefineToDoListDocumentModel.md +24 -19
- package/docs/academy/01-GetStarted/03-ImplementOperationReducers.md +44 -41
- package/docs/academy/01-GetStarted/04-BuildToDoListEditor.md +10 -10
- package/docs/academy/01-GetStarted/05-SpecDrivenAI.md +143 -0
- package/docs/academy/01-GetStarted/home.mdx +185 -90
- package/docs/academy/01-GetStarted/styles.module.css +5 -5
- package/docs/academy/02-MasteryTrack/01-BuilderEnvironment/01-Prerequisites.md +46 -18
- package/docs/academy/02-MasteryTrack/01-BuilderEnvironment/02-StandardDocumentModelWorkflow.md +118 -68
- package/docs/academy/02-MasteryTrack/01-BuilderEnvironment/03-BuilderTools.md +75 -33
- package/docs/academy/02-MasteryTrack/01-BuilderEnvironment/_category_.json +6 -6
- package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/01-WhatIsADocumentModel.md +30 -21
- package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/02-SpecifyTheStateSchema.md +41 -37
- package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/03-SpecifyDocumentOperations.md +29 -25
- package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/04-UseTheDocumentModelGenerator.md +36 -37
- package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/05-ImplementDocumentReducers.md +128 -109
- package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/06-ImplementDocumentModelTests.md +95 -86
- package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/07-ExampleToDoListRepository.md +7 -9
- package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/_category_.json +6 -6
- package/docs/academy/02-MasteryTrack/03-BuildingUserExperiences/01-BuildingDocumentEditors.md +65 -47
- package/docs/academy/02-MasteryTrack/03-BuildingUserExperiences/02-ConfiguringDrives.md +77 -62
- package/docs/academy/02-MasteryTrack/03-BuildingUserExperiences/03-BuildingADriveExplorer.md +360 -349
- package/docs/academy/02-MasteryTrack/03-BuildingUserExperiences/06-DocumentTools/00-DocumentToolbar.mdx +16 -10
- package/docs/academy/02-MasteryTrack/03-BuildingUserExperiences/06-DocumentTools/01-OperationHistory.md +10 -7
- package/docs/academy/02-MasteryTrack/03-BuildingUserExperiences/06-DocumentTools/02-RevisionHistoryTimeline.md +26 -11
- package/docs/academy/02-MasteryTrack/03-BuildingUserExperiences/06-DocumentTools/_category_.json +6 -6
- package/docs/academy/02-MasteryTrack/03-BuildingUserExperiences/07-Authorization/01-RenownAuthenticationFlow.md +14 -7
- package/docs/academy/02-MasteryTrack/03-BuildingUserExperiences/07-Authorization/02-Authorization.md +0 -1
- package/docs/academy/02-MasteryTrack/03-BuildingUserExperiences/07-Authorization/_category_.json +5 -5
- package/docs/academy/02-MasteryTrack/03-BuildingUserExperiences/_category_.json +1 -1
- package/docs/academy/02-MasteryTrack/04-WorkWithData/01-GraphQLAtPowerhouse.md +45 -33
- package/docs/academy/02-MasteryTrack/04-WorkWithData/02-UsingTheAPI.mdx +61 -18
- package/docs/academy/02-MasteryTrack/04-WorkWithData/03-UsingSubgraphs.md +50 -54
- package/docs/academy/02-MasteryTrack/04-WorkWithData/04-analytics-processor.md +126 -110
- package/docs/academy/02-MasteryTrack/04-WorkWithData/05-RelationalDbProcessor.md +75 -45
- package/docs/academy/02-MasteryTrack/04-WorkWithData/06-Analytics Engine/GraphQL References/QueryingADocumentWithGraphQL.md +23 -21
- package/docs/academy/02-MasteryTrack/04-WorkWithData/06-Analytics Engine/best-practices.md +9 -9
- package/docs/academy/02-MasteryTrack/04-WorkWithData/06-Analytics Engine/graphql/index.md +11 -23
- package/docs/academy/02-MasteryTrack/04-WorkWithData/06-Analytics Engine/graphql/integration.md +25 -9
- package/docs/academy/02-MasteryTrack/04-WorkWithData/06-Analytics Engine/intro.md +10 -10
- package/docs/academy/02-MasteryTrack/04-WorkWithData/06-Analytics Engine/typescript/benchmarks.md +1 -1
- package/docs/academy/02-MasteryTrack/04-WorkWithData/06-Analytics Engine/typescript/index.md +16 -11
- package/docs/academy/02-MasteryTrack/04-WorkWithData/06-Analytics Engine/typescript/memory.md +6 -5
- package/docs/academy/02-MasteryTrack/04-WorkWithData/06-Analytics Engine/typescript/schema.md +2 -2
- package/docs/academy/02-MasteryTrack/04-WorkWithData/06-Analytics Engine/typescript/utilities.md +7 -5
- package/docs/academy/02-MasteryTrack/04-WorkWithData/06-Analytics Engine/use-cases/maker.md +32 -58
- package/docs/academy/02-MasteryTrack/04-WorkWithData/06-Analytics Engine/use-cases/processors.md +1 -1
- package/docs/academy/02-MasteryTrack/04-WorkWithData/07-drive-analytics.md +105 -71
- package/docs/academy/02-MasteryTrack/04-WorkWithData/_ARCHIVE-AnalyticsProcessorTutorial/_01-SetupBuilderEnvironment.md +22 -0
- package/docs/academy/02-MasteryTrack/04-WorkWithData/_ARCHIVE-AnalyticsProcessorTutorial/_02-CreateNewPowerhouseProject.md +9 -8
- package/docs/academy/02-MasteryTrack/04-WorkWithData/_ARCHIVE-AnalyticsProcessorTutorial/_03-GenerateAnAnalyticsProcessor.md +28 -32
- package/docs/academy/02-MasteryTrack/04-WorkWithData/_ARCHIVE-AnalyticsProcessorTutorial/_04-UpdateAnalyticsProcessor.md +25 -26
- package/docs/academy/02-MasteryTrack/04-WorkWithData/_ARCHIVE-AnalyticsProcessorTutorial/_category_.json +1 -1
- package/docs/academy/02-MasteryTrack/04-WorkWithData/_category_.json +7 -7
- package/docs/academy/02-MasteryTrack/05-Launch/01-IntroductionToPackages.md +3 -4
- package/docs/academy/02-MasteryTrack/05-Launch/02-PublishYourProject.md +69 -45
- package/docs/academy/02-MasteryTrack/05-Launch/03-SetupEnvironment.md +70 -40
- package/docs/academy/02-MasteryTrack/05-Launch/04-ConfigureEnvironment.md +1 -0
- package/docs/academy/02-MasteryTrack/05-Launch/_category_.json +7 -7
- package/docs/academy/02-MasteryTrack/_category_.json +6 -6
- package/docs/academy/03-ExampleUsecases/Chatroom/02-CreateNewPowerhouseProject.md +5 -3
- package/docs/academy/03-ExampleUsecases/Chatroom/03-DefineChatroomDocumentModel.md +38 -37
- package/docs/academy/03-ExampleUsecases/Chatroom/04-ImplementOperationReducers.md +45 -41
- package/docs/academy/03-ExampleUsecases/Chatroom/05-ImplementChatroomEditor.md +14 -14
- package/docs/academy/03-ExampleUsecases/Chatroom/06-LaunchALocalReactor.md +6 -6
- package/docs/academy/03-ExampleUsecases/Chatroom/_category_.json +1 -1
- package/docs/academy/04-APIReferences/00-PowerhouseCLI.md +9 -7
- package/docs/academy/04-APIReferences/01-ReactHooks.md +177 -129
- package/docs/academy/04-APIReferences/04-RelationalDatabase.md +121 -113
- package/docs/academy/04-APIReferences/05-PHDocumentMigrationGuide.md +48 -41
- package/docs/academy/04-APIReferences/_category_.json +6 -6
- package/docs/academy/05-Architecture/00-PowerhouseArchitecture.md +1 -2
- package/docs/academy/05-Architecture/01-WorkingWithTheReactor.md +11 -8
- package/docs/academy/05-Architecture/05-DocumentModelTheory/_category_.json +1 -1
- package/docs/academy/05-Architecture/_category_.json +6 -6
- package/docs/academy/06-ComponentLibrary/00-DocumentEngineering.md +25 -23
- package/docs/academy/06-ComponentLibrary/02-CreateCustomScalars.md +105 -93
- package/docs/academy/06-ComponentLibrary/03-IntegrateIntoAReactComponent.md +1 -0
- package/docs/academy/06-ComponentLibrary/_category_.json +7 -7
- package/docs/academy/07-Cookbook.md +267 -34
- package/docs/academy/08-Glossary.md +7 -1
- package/docs/bookofpowerhouse/01-Overview.md +2 -2
- package/docs/bookofpowerhouse/02-GeneralFrameworkAndPhilosophy.md +1 -7
- package/docs/bookofpowerhouse/03-PowerhouseSoftwareArchitecture.md +10 -7
- package/docs/bookofpowerhouse/04-DevelopmentApproaches.md +10 -4
- package/docs/bookofpowerhouse/05-SNOsandANewModelForOSSandPublicGoods.md +23 -30
- package/docs/bookofpowerhouse/06-SNOsInActionAndPlatformEconomies.md +0 -7
- package/docusaurus.config.ts +64 -66
- package/package.json +1 -1
- package/scripts/generate-combined-cli-docs.ts +43 -13
- package/sidebars.ts +1 -0
- package/src/components/HomepageFeatures/index.tsx +171 -78
- package/src/components/HomepageFeatures/styles.module.css +1 -2
- package/src/css/custom.css +89 -89
- package/src/pages/_archive-homepage.tsx +17 -16
- package/src/theme/DocCardList/index.tsx +9 -8
- package/static.json +6 -6
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
|
|
2
1
|
# Implement Operation Reducers
|
|
3
2
|
|
|
4
|
-
In this section, we will implement and test the operation reducers for the `ChatRoom` document model. In order to do this, you have to export the document model from the Connect application and import it into your powerhouse project directory.
|
|
3
|
+
In this section, we will implement and test the operation reducers for the `ChatRoom` document model. In order to do this, you have to export the document model from the Connect application and import it into your powerhouse project directory.
|
|
5
4
|
|
|
6
5
|
To export the document model, follow the steps in the `Define Chatroom Document Model` section.
|
|
7
6
|
|
|
8
7
|
## Import Document Model and Generate Code
|
|
9
8
|
|
|
10
9
|
To import the document model into your powerhouse project, you can either:
|
|
11
|
-
|
|
10
|
+
|
|
12
11
|
- Copy&Paste the file directly into the root of your powerhouse project.
|
|
13
12
|
- Or drag&drop the file into the powerhouse project directory in the VSCode editor as seen in the image below:
|
|
14
13
|
|
|
@@ -16,8 +15,7 @@ Either step will import the document model into your powerhouse project.
|
|
|
16
15
|
|
|
17
16
|

|
|
18
17
|
|
|
19
|
-
The next steps will take place in the VSCode editor. Make sure to have it open and the terminal window inside vscode open as well.
|
|
20
|
-
|
|
18
|
+
The next steps will take place in the VSCode editor. Make sure to have it open and the terminal window inside vscode open as well.
|
|
21
19
|
|
|
22
20
|
To write the opearation reducers of the `ChatRoom` document model, you need to generate the document model code from the document model file you have exported into the powerhouse project directory.
|
|
23
21
|
|
|
@@ -26,8 +24,9 @@ To do this, run the following command in the terminal:
|
|
|
26
24
|
```bash
|
|
27
25
|
ph generate ChatRoom.phdm.zip
|
|
28
26
|
```
|
|
27
|
+
|
|
29
28
|
You will see that this action created a range of files for you. Before diving in we'll look at this simple schema to make you familiar with the structure you've defined in the document model once more. It shows how each type is connected to the next one.
|
|
30
|
-
|
|
29
|
+
|
|
31
30
|

|
|
32
31
|
|
|
33
32
|
Now you can navigate to `/document-models/chat-room/src/reducers/general-operations.ts` and start writing the operation reducers.
|
|
@@ -41,7 +40,6 @@ Open the `general-operations.ts` file and you should see the code that needs to
|
|
|
41
40
|
1. Copy&paste the code below into the `general-operations.ts` file in the `reducers` folder.
|
|
42
41
|
2. Save the `general-operations.ts` file.
|
|
43
42
|
|
|
44
|
-
|
|
45
43
|
```typescript
|
|
46
44
|
/**
|
|
47
45
|
* This is a scaffold file meant for customization:
|
|
@@ -55,7 +53,7 @@ import { MessageContentCannotBeEmpty } from "../../gen/add-message/error";
|
|
|
55
53
|
export const reducer: ChatRoomAddMessageOperations = {
|
|
56
54
|
addMessageOperation(state, action, dispatch) {
|
|
57
55
|
if (action.input.content === "") {
|
|
58
|
-
throw new MessageContentCannotBeEmpty();
|
|
56
|
+
throw new MessageContentCannotBeEmpty(); // Your reducer exception is used here as a custom error.
|
|
59
57
|
}
|
|
60
58
|
|
|
61
59
|
state.messages.push({
|
|
@@ -68,11 +66,11 @@ export const reducer: ChatRoomAddMessageOperations = {
|
|
|
68
66
|
},
|
|
69
67
|
addEmojiReactionOperation(state, action, dispatch) {
|
|
70
68
|
const message = state.messages.find(
|
|
71
|
-
(message) => message.id === action.input.messageId,
|
|
69
|
+
(message) => message.id === action.input.messageId, // the reducer checks the existence of the message you want to react to.
|
|
72
70
|
);
|
|
73
71
|
|
|
74
72
|
if (!message) {
|
|
75
|
-
throw new Error("Message not found");
|
|
73
|
+
throw new Error("Message not found");
|
|
76
74
|
}
|
|
77
75
|
|
|
78
76
|
const reactions = message.reactions || [];
|
|
@@ -81,7 +79,8 @@ export const reducer: ChatRoomAddMessageOperations = {
|
|
|
81
79
|
(reaction) => reaction.type === action.input.type,
|
|
82
80
|
);
|
|
83
81
|
|
|
84
|
-
if (existingReaction) {
|
|
82
|
+
if (existingReaction) {
|
|
83
|
+
// if the message reaction exists a new reactedBy gets added.
|
|
85
84
|
message.reactions = reactions.map((reaction) => {
|
|
86
85
|
if (reaction.type === action.input.type) {
|
|
87
86
|
return {
|
|
@@ -96,13 +95,14 @@ export const reducer: ChatRoomAddMessageOperations = {
|
|
|
96
95
|
message.reactions = [
|
|
97
96
|
...reactions,
|
|
98
97
|
{
|
|
99
|
-
reactedBy: [action.input.reactedBy],
|
|
98
|
+
reactedBy: [action.input.reactedBy], // if the message reaction doesn't exist yet a new reaction gets created
|
|
100
99
|
type: action.input.type,
|
|
101
100
|
},
|
|
102
101
|
];
|
|
103
102
|
}
|
|
104
103
|
|
|
105
|
-
state.messages = state.messages.map((_message) => {
|
|
104
|
+
state.messages = state.messages.map((_message) => {
|
|
105
|
+
// the state of the chatroom documents messages gets updated
|
|
106
106
|
if (_message.id === message.id) {
|
|
107
107
|
return message;
|
|
108
108
|
}
|
|
@@ -110,7 +110,8 @@ export const reducer: ChatRoomAddMessageOperations = {
|
|
|
110
110
|
return _message;
|
|
111
111
|
});
|
|
112
112
|
},
|
|
113
|
-
removeEmojiReactionOperation(state, action, dispatch) {
|
|
113
|
+
removeEmojiReactionOperation(state, action, dispatch) {
|
|
114
|
+
// To remove a reaction the address is removed from the reactedBy object in the reactions type.
|
|
114
115
|
state.messages = state.messages.map((message) => {
|
|
115
116
|
if (message.id === action.input.messageId) {
|
|
116
117
|
message.reactions = (message.reactions || []).map((reaction) => {
|
|
@@ -118,7 +119,7 @@ export const reducer: ChatRoomAddMessageOperations = {
|
|
|
118
119
|
return {
|
|
119
120
|
...reaction,
|
|
120
121
|
reactedBy: reaction.reactedBy.filter(
|
|
121
|
-
(reactedBy) => reactedBy !== action.input.senderId,
|
|
122
|
+
(reactedBy) => reactedBy !== action.input.senderId, // We're removing the sender of the reaction from the the reactedBy object
|
|
122
123
|
),
|
|
123
124
|
};
|
|
124
125
|
}
|
|
@@ -127,7 +128,7 @@ export const reducer: ChatRoomAddMessageOperations = {
|
|
|
127
128
|
});
|
|
128
129
|
}
|
|
129
130
|
|
|
130
|
-
return message;
|
|
131
|
+
return message; // We're updating the document state with our changes
|
|
131
132
|
});
|
|
132
133
|
},
|
|
133
134
|
editChatNameOperation(state, action, dispatch) {
|
|
@@ -143,11 +144,11 @@ export const reducer: ChatRoomAddMessageOperations = {
|
|
|
143
144
|
|
|
144
145
|
In order to make sure the operation reducers are working as expected before implementing an editor interface, you need to write tests for them.
|
|
145
146
|
|
|
146
|
-
The auto generated test will only validate if an action or message in our case is included but will not verify if the reducer mutation is succesfull. This is the type of test you'll have to write as a developer.
|
|
147
|
+
The auto generated test will only validate if an action or message in our case is included but will not verify if the reducer mutation is succesfull. This is the type of test you'll have to write as a developer.
|
|
147
148
|
|
|
148
149
|
Navigate to `/document-models/chat-room/src/tests/general-operations.test.ts` and copy&paste the code below into the file. Save the file.
|
|
149
150
|
|
|
150
|
-
Here are the tests for the five operations written in the reducers file.
|
|
151
|
+
Here are the tests for the five operations written in the reducers file.
|
|
151
152
|
|
|
152
153
|
```typescript
|
|
153
154
|
/**
|
|
@@ -178,7 +179,8 @@ describe("AddMessage Operations", () => {
|
|
|
178
179
|
document = utils.createDocument();
|
|
179
180
|
});
|
|
180
181
|
|
|
181
|
-
const addMessage = (): [ChatRoomDocument, AddMessageInput] => {
|
|
182
|
+
const addMessage = (): [ChatRoomDocument, AddMessageInput] => {
|
|
183
|
+
// This is a helper function for our upcoming test
|
|
182
184
|
const input: AddMessageInput = {
|
|
183
185
|
content: "Hello, World!",
|
|
184
186
|
messageId: documentModelUtils.hashKey(),
|
|
@@ -195,26 +197,27 @@ describe("AddMessage Operations", () => {
|
|
|
195
197
|
return [updatedDocument, input];
|
|
196
198
|
};
|
|
197
199
|
|
|
198
|
-
it("should handle addMessage operation", () => {
|
|
200
|
+
it("should handle addMessage operation", () => {
|
|
199
201
|
const [updatedDocument, input] = addMessage();
|
|
200
202
|
|
|
201
|
-
expect(updatedDocument.operations.global).toHaveLength(1);
|
|
203
|
+
expect(updatedDocument.operations.global).toHaveLength(1); // We're validating that the message is being added to the operations history
|
|
202
204
|
expect(updatedDocument.operations.global[0].type).toBe("ADD_MESSAGE");
|
|
203
205
|
expect(updatedDocument.operations.global[0].input).toStrictEqual(input);
|
|
204
206
|
expect(updatedDocument.operations.global[0].index).toEqual(0);
|
|
205
|
-
|
|
206
|
-
expect(updatedDocument.state.global.messages).toHaveLength(1);
|
|
207
|
+
|
|
208
|
+
expect(updatedDocument.state.global.messages).toHaveLength(1); // We're validating that the message is present in the message state of the document
|
|
207
209
|
expect(updatedDocument.state.global.messages[0]).toMatchObject({
|
|
208
210
|
id: input.messageId,
|
|
209
211
|
content: input.content,
|
|
210
212
|
sender: input.sender,
|
|
211
213
|
sentAt: input.sentAt,
|
|
212
|
-
reactions: [],
|
|
214
|
+
reactions: [], // We also want to make sure that reaction object is an empty array
|
|
213
215
|
});
|
|
214
216
|
});
|
|
215
217
|
|
|
216
|
-
it("should handle addEmojiReaction operation", () => {
|
|
217
|
-
|
|
218
|
+
it("should handle addEmojiReaction operation", () => {
|
|
219
|
+
// We're validating that we can react using an emoji with a helper function
|
|
220
|
+
const [doc, addMessageInput] = addMessage();
|
|
218
221
|
|
|
219
222
|
let updatedDocument = doc;
|
|
220
223
|
|
|
@@ -229,7 +232,7 @@ describe("AddMessage Operations", () => {
|
|
|
229
232
|
creators.addEmojiReaction(addEmojiReactionInput),
|
|
230
233
|
);
|
|
231
234
|
|
|
232
|
-
expect(updatedDocument.operations.global).toHaveLength(2);
|
|
235
|
+
expect(updatedDocument.operations.global).toHaveLength(2); // We're validating that the emoji reaction is added to the operation history of the doc.
|
|
233
236
|
expect(updatedDocument.operations.global[1].type).toBe(
|
|
234
237
|
"ADD_EMOJI_REACTION",
|
|
235
238
|
);
|
|
@@ -238,16 +241,17 @@ describe("AddMessage Operations", () => {
|
|
|
238
241
|
);
|
|
239
242
|
expect(updatedDocument.operations.global[1].index).toEqual(1);
|
|
240
243
|
|
|
241
|
-
expect(updatedDocument.state.global.messages[0].reactions).toHaveLength(1);
|
|
244
|
+
expect(updatedDocument.state.global.messages[0].reactions).toHaveLength(1); // We're validating that the message we created has only one reaction
|
|
242
245
|
expect(
|
|
243
246
|
updatedDocument.state.global.messages[0].reactions?.[0],
|
|
244
247
|
).toMatchObject({
|
|
245
|
-
reactedBy: [addEmojiReactionInput.reactedBy],
|
|
246
|
-
type: addEmojiReactionInput.type,
|
|
248
|
+
reactedBy: [addEmojiReactionInput.reactedBy], // We're validating that reactedBy object only contains the right address
|
|
249
|
+
type: addEmojiReactionInput.type,
|
|
247
250
|
});
|
|
248
251
|
});
|
|
249
252
|
|
|
250
|
-
it("should handle addEmojiReaction operation to a non existing message", () => {
|
|
253
|
+
it("should handle addEmojiReaction operation to a non existing message", () => {
|
|
254
|
+
// We're testing that an error is thrown when reacting to a non-existing message
|
|
251
255
|
const input: AddEmojiReactionInput = {
|
|
252
256
|
messageId: "invalid-message-id",
|
|
253
257
|
reactedBy: "anon-user",
|
|
@@ -266,7 +270,8 @@ describe("AddMessage Operations", () => {
|
|
|
266
270
|
expect(updatedDocument.state.global.messages).toHaveLength(0);
|
|
267
271
|
});
|
|
268
272
|
|
|
269
|
-
it("should handle removeEmojiReaction operation", () => {
|
|
273
|
+
it("should handle removeEmojiReaction operation", () => {
|
|
274
|
+
// We're making use of a helper function to check if we can remove an EmojiReaction
|
|
270
275
|
const [doc, addMessageInput] = addMessage();
|
|
271
276
|
|
|
272
277
|
let updatedDocument = doc;
|
|
@@ -282,7 +287,8 @@ describe("AddMessage Operations", () => {
|
|
|
282
287
|
creators.addEmojiReaction(addEmojiReactionInput),
|
|
283
288
|
);
|
|
284
289
|
|
|
285
|
-
const input: RemoveEmojiReactionInput = {
|
|
290
|
+
const input: RemoveEmojiReactionInput = {
|
|
291
|
+
// We're validating the removal of a message by our anon-user with a specific messageId
|
|
286
292
|
messageId: addMessageInput.messageId,
|
|
287
293
|
senderId: "anon-user",
|
|
288
294
|
type: "THUMBS_UP",
|
|
@@ -293,27 +299,27 @@ describe("AddMessage Operations", () => {
|
|
|
293
299
|
creators.removeEmojiReaction(input),
|
|
294
300
|
);
|
|
295
301
|
|
|
296
|
-
expect(updatedDocument.operations.global).toHaveLength(3);
|
|
302
|
+
expect(updatedDocument.operations.global).toHaveLength(3); // We're validating that the operation was added to the operation history.
|
|
297
303
|
expect(updatedDocument.operations.global[2].type).toBe(
|
|
298
304
|
"REMOVE_EMOJI_REACTION",
|
|
299
305
|
);
|
|
300
306
|
expect(updatedDocument.operations.global[2].input).toStrictEqual(input);
|
|
301
307
|
expect(updatedDocument.operations.global[2].index).toEqual(2);
|
|
302
308
|
|
|
303
|
-
expect(updatedDocument.state.global.messages[0].reactions).toHaveLength(1);
|
|
309
|
+
expect(updatedDocument.state.global.messages[0].reactions).toHaveLength(1); // The reaction should still exist but no-one should have reacted to it
|
|
304
310
|
expect(
|
|
305
311
|
updatedDocument.state.global.messages[0].reactions?.[0]?.reactedBy,
|
|
306
312
|
).toHaveLength(0);
|
|
307
313
|
});
|
|
308
314
|
|
|
309
|
-
it("should handle editChatName operation", () => {
|
|
315
|
+
it("should handle editChatName operation", () => {
|
|
310
316
|
const input: EditChatNameInput = {
|
|
311
317
|
name: "New Chat Name",
|
|
312
318
|
};
|
|
313
319
|
|
|
314
320
|
const updatedDocument = reducer(document, creators.editChatName(input));
|
|
315
321
|
|
|
316
|
-
expect(updatedDocument.operations.global).toHaveLength(1);
|
|
322
|
+
expect(updatedDocument.operations.global).toHaveLength(1); // We're validating that the operation is added to the operations history
|
|
317
323
|
expect(updatedDocument.operations.global[0].type).toBe("EDIT_CHAT_NAME");
|
|
318
324
|
expect(updatedDocument.operations.global[0].input).toStrictEqual(input);
|
|
319
325
|
expect(updatedDocument.operations.global[0].index).toEqual(0);
|
|
@@ -331,7 +337,7 @@ describe("AddMessage Operations", () => {
|
|
|
331
337
|
creators.editChatDescription(input),
|
|
332
338
|
);
|
|
333
339
|
|
|
334
|
-
expect(updatedDocument.operations.global).toHaveLength(1);
|
|
340
|
+
expect(updatedDocument.operations.global).toHaveLength(1); // We're validating that the operation is added to the operations history
|
|
335
341
|
expect(updatedDocument.operations.global[0].type).toBe(
|
|
336
342
|
"EDIT_CHAT_DESCRIPTION",
|
|
337
343
|
);
|
|
@@ -343,8 +349,6 @@ describe("AddMessage Operations", () => {
|
|
|
343
349
|
});
|
|
344
350
|
```
|
|
345
351
|
|
|
346
|
-
|
|
347
|
-
|
|
348
352
|
Now you can run the tests to make sure the operation reducers are working as expected.
|
|
349
353
|
|
|
350
354
|
```bash
|
|
@@ -361,4 +365,4 @@ Output should be as follows:
|
|
|
361
365
|
```
|
|
362
366
|
|
|
363
367
|
If you got the same output, you have successfully implemented the operation reducers and tests for the `ChatRoom` document model.
|
|
364
|
-
Continue to the next section to learn how to implement the document model editor so you can see a simple user interface for the `ChatRoom` document model in action.
|
|
368
|
+
Continue to the next section to learn how to implement the document model editor so you can see a simple user interface for the `ChatRoom` document model in action.
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
|
|
2
1
|
# Implement Chatroom Editor
|
|
3
2
|
|
|
4
|
-
In this section you will implement the `Chatroom` document model editor. This means you will create a simple user interface for the `Chatroom` document model which will be used inside the Connect app to visualise our chatroom, send messages and emoji reactions.
|
|
3
|
+
In this section you will implement the `Chatroom` document model editor. This means you will create a simple user interface for the `Chatroom` document model which will be used inside the Connect app to visualise our chatroom, send messages and emoji reactions.
|
|
5
4
|
|
|
6
5
|
## Generate the editor template
|
|
7
6
|
|
|
@@ -15,24 +14,25 @@ ph generate -- --editor ChatRoomEditor --document-types powerhouse/chat-room
|
|
|
15
14
|
|
|
16
15
|
Once complete, navigate to the `editors/chat-room/editor.tsx` file and open it in your editor.
|
|
17
16
|
|
|
18
|
-
As you'll see you will need to add more complex logic to make the chatroom functional and interact with our document model.
|
|
17
|
+
As you'll see you will need to add more complex logic to make the chatroom functional and interact with our document model.
|
|
19
18
|
|
|
20
19
|
## Add the necessary components for your editor first
|
|
21
20
|
|
|
22
21
|
Download the repository of the chatroom-demo as a zip file https://github.com/powerhouse-inc/chatroom-demo
|
|
23
|
-
and navigate to .../chatroom-demo-main/editors/chat-room-editor to copy both the components folder & utils function. In this repository you will also find all of the other code snippets we've been using in this tutorial.
|
|
22
|
+
and navigate to .../chatroom-demo-main/editors/chat-room-editor to copy both the components folder & utils function. In this repository you will also find all of the other code snippets we've been using in this tutorial.
|
|
24
23
|
|
|
25
24
|
Drag the folder with react components & utils functions into your VSCode of your chat-room-editor.
|
|
26
25
|
|
|
27
26
|
In this folder you'll find:
|
|
27
|
+
|
|
28
28
|
- An avatar to be set for each chat room participant
|
|
29
29
|
- The chatroom environment itself
|
|
30
30
|
- A header for the chatroom
|
|
31
|
-
- The UI for rendering the message, username and reaction popup.
|
|
32
|
-
- The emoji reaction interface
|
|
33
|
-
- A UI for a text input field
|
|
31
|
+
- The UI for rendering the message, username and reaction popup.
|
|
32
|
+
- The emoji reaction interface
|
|
33
|
+
- A UI for a text input field
|
|
34
34
|
|
|
35
|
-
The utils function will help you with mapping information from the document model to your chatroom components. Such as your emoji values to the relevant emoji to be displayed.
|
|
35
|
+
The utils function will help you with mapping information from the document model to your chatroom components. Such as your emoji values to the relevant emoji to be displayed.
|
|
36
36
|
|
|
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
|
|
|
@@ -60,7 +60,7 @@ export default function Editor(props: IProps) {
|
|
|
60
60
|
const disableChatRoom = !props.context.user; // we're disabling the chatroom when a user is not logged in.
|
|
61
61
|
|
|
62
62
|
const messages: ChatRoomProps["messages"] =
|
|
63
|
-
props.document.state.global.messages.map((message) => ({ // this object comes from the document state with a mapping that validates which message which user has send.
|
|
63
|
+
props.document.state.global.messages.map((message) => ({ // this object comes from the document state with a mapping that validates which message which user has send.
|
|
64
64
|
id: message.id,
|
|
65
65
|
message: message.content || "",
|
|
66
66
|
timestamp: message.sentAt,
|
|
@@ -75,13 +75,13 @@ export default function Editor(props: IProps) {
|
|
|
75
75
|
return;
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
-
props.dispatch(
|
|
78
|
+
props.dispatch(
|
|
79
79
|
actions.addMessage({
|
|
80
80
|
messageId: documentModelUtils.hashKey(),
|
|
81
81
|
content: message,
|
|
82
82
|
sender: {
|
|
83
|
-
id: props.context.user?.address || "anon-user",
|
|
84
|
-
name: props.context.user?.ens?.name || null, // The context of the editor allows us to get hold of the users profile information.
|
|
83
|
+
id: props.context.user?.address || "anon-user",
|
|
84
|
+
name: props.context.user?.ens?.name || null, // The context of the editor allows us to get hold of the users profile information.
|
|
85
85
|
avatarUrl: props.context.user?.ens?.avatarUrl || null,
|
|
86
86
|
},
|
|
87
87
|
sentAt: new Date().toISOString(),
|
|
@@ -183,7 +183,7 @@ Now you can run the Connect app and see the `Chatroom` editor in action.
|
|
|
183
183
|
ph connect
|
|
184
184
|
```
|
|
185
185
|
|
|
186
|
-
In connect, in the bottom right corner you'll find a new Document Model that you can create: `ChatRoom`. Click on it to create a new Chat Room document. A warning will prompt you to login before you are able to send messages.
|
|
186
|
+
In connect, in the bottom right corner you'll find a new Document Model that you can create: `ChatRoom`. Click on it to create a new Chat Room document. A warning will prompt you to login before you are able to send messages.
|
|
187
187
|
|
|
188
188
|
Login with an ethereum address via Renown to start sending messages.
|
|
189
189
|
|
|
@@ -191,4 +191,4 @@ Below GIF shows the `Chatroom` editor in action.
|
|
|
191
191
|
|
|
192
192
|

|
|
193
193
|
|
|
194
|
-
If you managed to follow this tutorial until this point, you have successfully implemented the `ChatRoom` document model with its reducer operations and editor.
|
|
194
|
+
If you managed to follow this tutorial until this point, you have successfully implemented the `ChatRoom` document model with its reducer operations and editor.
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
# Launch a local Reactor
|
|
2
2
|
|
|
3
|
-
Now we'll create a local Reactor instance to simulate the behaviour of the chatroom synchronising messages between two nodes or users in the network.
|
|
3
|
+
Now we'll create a local Reactor instance to simulate the behaviour of the chatroom synchronising messages between two nodes or users in the network.
|
|
4
4
|
|
|
5
|
-
Wind down connect and run the following command in your terminal.
|
|
5
|
+
Wind down connect and run the following command in your terminal.
|
|
6
6
|
|
|
7
7
|
`ph reactor`
|
|
8
8
|
|
|
9
|
-
This spins up a reactor, which represents a node that is usally hosted as a remote server, but in our case we run it locally on our machine. The reactor you've created will become available as a public drive in your left hand side bar.
|
|
9
|
+
This spins up a reactor, which represents a node that is usally hosted as a remote server, but in our case we run it locally on our machine. The reactor you've created will become available as a public drive in your left hand side bar.
|
|
10
10
|
|
|
11
|
-
If you would now open up two different browser windows you will be able to login into two version of connect, with two different ethereum addresses to start validating the functionality of your chatroom.
|
|
11
|
+
If you would now open up two different browser windows you will be able to login into two version of connect, with two different ethereum addresses to start validating the functionality of your chatroom.
|
|
12
12
|
|
|
13
|
-
Please go ahead now and send a message to yourself, give yourself a thumbs up or try to make your ENS name appear as your profile when logging in. Also remind yourself that you are able to see the revision history of your document and all it's operation history in the top right corner.
|
|
13
|
+
Please go ahead now and send a message to yourself, give yourself a thumbs up or try to make your ENS name appear as your profile when logging in. Also remind yourself that you are able to see the revision history of your document and all it's operation history in the top right corner.
|
|
14
14
|
|
|
15
|
-
Congratulations! You've now explored one of the many ways to use document models within the powerhouse ecosystem.
|
|
15
|
+
Congratulations! You've now explored one of the many ways to use document models within the powerhouse ecosystem.
|
|
@@ -5,4 +5,4 @@
|
|
|
5
5
|
"type": "generated-index",
|
|
6
6
|
"description": "Get started with the Chatroom tutoria: Jump into creating a new Powerhouse project if you have NodeJs, VSCode, and Git installed. Whe are going to create a new document model that represents a chat. So you as a user can post messages into that chat room, react to the messages. This chatroom will be synchronized between different connect instances. Let's explore the potential of the tools available in the powerhouse toolkit"
|
|
7
7
|
}
|
|
8
|
-
}
|
|
8
|
+
}
|
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
# Powerhouse CLI
|
|
2
2
|
|
|
3
|
-
### Installing the Powerhouse CLI
|
|
3
|
+
### Installing the Powerhouse CLI
|
|
4
|
+
|
|
4
5
|
:::tip
|
|
5
|
-
The **Powerhouse CLI tool** is the only essential tool to install on this page. Install it with the command below.
|
|
6
|
+
The **Powerhouse CLI tool** is the only essential tool to install on this page. Install it with the command below.
|
|
6
7
|
|
|
7
|
-
You can find all of the commands on this page, similar to what would displayed when using ph --help or ph
|
|
8
|
-
Use the table of content or the search function to find what you are looking for.
|
|
8
|
+
You can find all of the commands on this page, similar to what would displayed when using ph --help or ph _command_ --help.
|
|
9
|
+
Use the table of content or the search function to find what you are looking for.
|
|
9
10
|
|
|
10
11
|
The Powerhouse CLI (`ph-cmd`) is a command-line interface tool that provides essential commands for managing Powerhouse projects. You can get access to the Powerhouse ecosystem tools by installing them globally.
|
|
11
12
|
|
|
12
13
|
```bash
|
|
13
14
|
pnpm install -g ph-cmd
|
|
14
|
-
```
|
|
15
|
-
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
:::
|
|
16
18
|
|
|
17
19
|
<!-- AUTO-GENERATED-CLI-COMMANDS-START -->\n<!-- This content is automatically generated. Do not edit directly. -->\n### ph-cmd Commands\n\n- [Init](#init)
|
|
18
20
|
- [Setup Globals](#setup-globals)
|
|
@@ -768,4 +770,4 @@ Examples:
|
|
|
768
770
|
|
|
769
771
|
---
|
|
770
772
|
|
|
771
|
-
*This document was automatically generated from the help text in the codebase.*\n<!-- AUTO-GENERATED-CLI-COMMANDS-END -->
|
|
773
|
+
*This document was automatically generated from the help text in the codebase.*\n<!-- AUTO-GENERATED-CLI-COMMANDS-END -->
|