@powerhousedao/academy 5.1.0-dev.1 → 5.1.0-dev.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/CHANGELOG.md +74 -0
- package/blog/BeyondCommunication-ABlueprintForDevelopment.md +2 -1
- package/blog/TheChallengeOfChange.md +1 -0
- package/docs/academy/01-GetStarted/00-ExploreDemoPackage.mdx +24 -27
- package/docs/academy/01-GetStarted/01-CreateNewPowerhouseProject.md +118 -9
- package/docs/academy/01-GetStarted/02-DefineToDoListDocumentModel.md +110 -28
- package/docs/academy/01-GetStarted/03-ImplementOperationReducers.md +191 -145
- package/docs/academy/01-GetStarted/04-WriteDocumentModelTests.md +378 -0
- package/docs/academy/01-GetStarted/05-BuildToDoListEditor.md +560 -0
- package/docs/academy/01-GetStarted/_04-BuildToDoListEditor +1 -1
- package/docs/academy/02-MasteryTrack/01-BuilderEnvironment/03-BuilderTools.md +2 -2
- package/docs/academy/{01-GetStarted → 02-MasteryTrack/01-BuilderEnvironment}/05-VetraStudio.md +48 -6
- package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/02-SpecifyTheStateSchema.md +75 -44
- package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/03-SpecifyDocumentOperations.md +28 -22
- package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/04-UseTheDocumentModelGenerator.md +28 -31
- package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/05-ImplementDocumentReducers.md +211 -206
- package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/06-ImplementDocumentModelTests.md +176 -62
- package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/07-ExampleToDoListRepository.md +21 -0
- package/docs/academy/02-MasteryTrack/03-BuildingUserExperiences/01-BuildingDocumentEditors.md +309 -319
- package/docs/academy/02-MasteryTrack/03-BuildingUserExperiences/06-DocumentTools/00-DocumentToolbar.mdx +4 -0
- package/docs/academy/02-MasteryTrack/03-BuildingUserExperiences/06-DocumentTools/01-OperationHistory.md +4 -0
- package/docs/academy/02-MasteryTrack/05-Launch/04-ConfigureEnvironment.md +1 -1
- package/docs/academy/03-ExampleUsecases/Chatroom/02-CreateNewPowerhouseProject.md +111 -35
- package/docs/academy/03-ExampleUsecases/Chatroom/03-DefineChatroomDocumentModel.md +255 -76
- package/docs/academy/03-ExampleUsecases/Chatroom/04-ImplementOperationReducers.md +281 -160
- package/docs/academy/03-ExampleUsecases/Chatroom/05-ImplementChatroomEditor.md +188 -35
- package/docs/academy/03-ExampleUsecases/Chatroom/06-LaunchALocalReactor.md +95 -7
- package/docs/academy/03-ExampleUsecases/Chatroom/_category_.json +1 -1
- package/docs/academy/03-ExampleUsecases/TodoList/00-GetTheStarterCode.md +24 -0
- package/docs/academy/03-ExampleUsecases/TodoList/01-GenerateTodoListDocumentModel.md +211 -0
- package/docs/academy/03-ExampleUsecases/TodoList/02-ImplementTodoListDocumentModelReducerOperationHandlers.md +171 -0
- package/docs/academy/03-ExampleUsecases/TodoList/03-AddTestsForTodoListActions.md +462 -0
- package/docs/academy/03-ExampleUsecases/TodoList/04-GenerateTodoListDocumentEditor.md +45 -0
- package/docs/academy/03-ExampleUsecases/TodoList/05-ImplementTodoListDocumentEditorUIComponents.md +422 -0
- package/docs/academy/03-ExampleUsecases/TodoList/06-GenerateTodoDriveExplorer.md +61 -0
- package/docs/academy/03-ExampleUsecases/TodoList/07-AddSharedComponentForShowingTodoListStats.md +384 -0
- package/docs/academy/03-ExampleUsecases/TodoList/_category_.json +8 -0
- package/docs/academy/03-ExampleUsecases/VetraPackageLibrary/VetraPackageLibrary.md +7 -0
- package/docs/academy/03-ExampleUsecases/VetraPackageLibrary/_category_.json +9 -0
- package/docs/academy/04-APIReferences/00-PowerhouseCLI.md +6 -2
- package/docs/academy/04-APIReferences/01-ReactHooks.md +2 -2
- package/docs/academy/04-APIReferences/06-VetraRemoteDrive.md +160 -0
- package/docs/academy/04-APIReferences/renown-sdk/00-Overview.md +316 -0
- package/docs/academy/04-APIReferences/renown-sdk/01-Authentication.md +672 -0
- package/docs/academy/04-APIReferences/renown-sdk/02-APIReference.md +957 -0
- package/docs/academy/04-APIReferences/renown-sdk/_category_.json +8 -0
- package/docs/academy/05-Architecture/00-PowerhouseArchitecture.md +7 -39
- package/docs/academy/06-ComponentLibrary/00-DocumentEngineering.md +72 -24
- package/docs/academy/08-Glossary.md +7 -0
- package/docs/academy/10-TodoListTutorial/02-ImplementTodoListDocumentModelReducerOperationHandlers.md +171 -0
- package/docs/academy/10-TodoListTutorial/03-AddTestsForTodoListActions.md +462 -0
- package/docs/academy/10-TodoListTutorial/05-ImplementTodoListDocumentEditorUIComponents.md +422 -0
- package/docs/academy/10-TodoListTutorial/07-AddSharedComponentForShowingTodoListStats.md +370 -0
- package/docusaurus.config.ts +28 -3
- package/package.json +1 -1
- package/sidebars.ts +49 -12
- package/src/css/custom.css +26 -18
- package/static/img/Vetra-logo-dark.svg +11 -0
- package/static/img/vetra-logo-light.svg +11 -0
- package/docs/academy/00-EthereumArgentinaHackathon.md +0 -207
- package/docs/academy/01-GetStarted/04-BuildToDoListEditor.md +0 -218
- package/docs/academy/01-GetStarted/06-ReactorMCP.md +0 -58
- package/docs/academy/05-Architecture/02-ReferencingMonorepoPackages +0 -65
- package/docs/academy/05-Architecture/04-MovingBeyondCRUD +0 -61
- /package/docs/academy/{01-GetStarted → 02-MasteryTrack/01-BuilderEnvironment}/images/Modules.png +0 -0
- /package/docs/academy/{01-GetStarted → 02-MasteryTrack/01-BuilderEnvironment}/images/VetraStudioDrive.png +0 -0
- /package/docs/academy/02-MasteryTrack/03-BuildingUserExperiences/06-DocumentTools/{02-RevisionHistoryTimeline → 02-RevisionHistoryTimeline/360/237/232/247"} +0 -0
- /package/docs/academy/05-Architecture/05-DocumentModelTheory/{01-WhatIsADocumentModel → 360/237/232/247 /01-WhatIsADocumentModel"} +0 -0
- /package/docs/academy/05-Architecture/05-DocumentModelTheory/{02-DAOandDocumentsModelsQ+A → 360/237/232/247 /02-DAOandDocumentsModelsQ+A"} +0 -0
- /package/docs/academy/05-Architecture/05-DocumentModelTheory/{02-domain-modeling → 360/237/232/247 /02-domain-modeling"} +0 -0
- /package/docs/academy/05-Architecture/05-DocumentModelTheory/{03-BenefitsOfDocumentModels → 360/237/232/247 /03-BenefitsOfDocumentModels"} +0 -0
- /package/docs/academy/05-Architecture/05-DocumentModelTheory/{04-UtilitiesAndTips → 360/237/232/247 /04-UtilitiesAndTips"} +0 -0
- /package/docs/academy/05-Architecture/05-DocumentModelTheory/{05-best-practices → 360/237/232/247 /05-best-practices"} +0 -0
- /package/docs/academy/05-Architecture/05-DocumentModelTheory/{_category_.json → 360/237/232/247 /_category_.json"} +0 -0
- /package/docs/academy/05-Architecture/05-DocumentModelTheory/{three-data-layers.png → 360/237/232/247 /three-data-layers.png"} +0 -0
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
# Powerhouse Architecture
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**Vetra is part of the Powerhouse Ecosystem** and acts as the builder platform and builder tooling for scalable network organizations.
|
|
4
|
+
|
|
5
|
+
The Powerhouse ecosystem makes use of 4 core host applications that together form a modular, scalable operating system for decentralized organizations.
|
|
6
|
+
Each application serves a distinct role, yet they are interdependent, working as a unified system to streamline operations, enhance collaboration, and drive automation.
|
|
4
7
|
|
|
5
8
|
These five applications are:
|
|
6
9
|
|
|
@@ -8,45 +11,10 @@ These five applications are:
|
|
|
8
11
|
2. **Switchboard** – The data infrastructure and API engine.
|
|
9
12
|
3. **Fusion** – The public-facing collaboration hub.
|
|
10
13
|
4. **Renown** – The decentralized reputation and identity system.
|
|
11
|
-
5. **Academy** – The onboarding and learning modules.
|
|
12
|
-
|
|
13
|
-
Each application is designed to be modular yet complementary, ensuring smooth data flows, structured collaboration, and scalable automation. The functionality of the four host apps offers an integrated experience for running decentralized operations.
|
|
14
14
|
|
|
15
15
|

|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
The Powerhouse ecosystem functions as a decentralized operating system, where each of the four core applications works in synergy to ensure seamless collaboration, structured data management, and automated workflows. Each application has a distinct purpose, yet their interconnectivity is what makes the system powerful.
|
|
20
|
-
|
|
21
|
-
### 1. Connect: The Contributor's Workspace and Data Capture Point
|
|
22
|
-
|
|
23
|
-
Connect is the entry point for individual contributors, where they install apps and packages tailored to specific business solutions, enabling collaboration in public or private settings.
|
|
24
|
-
|
|
25
|
-
- All work in Connect is captured as document models, ensuring that data is structured, traceable, and immediately available for processing.
|
|
26
|
-
- This structured data flows into Switchboard, making it accessible for analytics, automation, and API-driven integrations.
|
|
27
|
-
- Fusion then utilizes this data to generate dashboards, summaries, and insights for decision-making.
|
|
28
|
-
- Renown serves as the authentication and access gateway, ensuring that contributors can securely interact with the system.
|
|
29
|
-
|
|
30
|
-
### 2. Switchboard: The Data Processing and Automation Engine
|
|
31
|
-
|
|
32
|
-
Switchboard acts as the central nervous system, ensuring that data flows efficiently between applications and powers real-time coordination.
|
|
33
|
-
|
|
34
|
-
- It ingests structured data from Connect and makes it available for further analysis, automation, and integrations.
|
|
35
|
-
- The API interface allows developers and data engineers to fuel the broader system, providing insights and feeding data-driven workflows.
|
|
36
|
-
- The processed data is then transmitted to Fusion, where it is transformed into dashboards, analytics, and key performance indicators (KPIs).
|
|
37
|
-
|
|
38
|
-
### 3. Fusion: The Public Collaboration and Data Visualization Layer
|
|
39
|
-
|
|
40
|
-
Fusion serves as the public-facing marketplace and collaboration hub, allowing contributors and organizations to interact with structured data captured from Connect and processed through Switchboard.
|
|
41
|
-
|
|
42
|
-
- Fusion structures, summarizes, and visualizes key metrics, enabling users to make data-driven decisions.
|
|
43
|
-
- It pulls relevant operational insights, helping stakeholders navigate and act on real-time data.
|
|
44
|
-
- Users can directly access work completed in Connect, viewing reports, summaries, and discussions within Fusion's public and private environments.
|
|
45
|
-
|
|
46
|
-
### 4. Renown: Authentication, Reputation, and Access Control
|
|
47
|
-
|
|
48
|
-
Renown is the trust and identity layer, ensuring security, reputation tracking, and access control across the ecosystem.
|
|
17
|
+
With the help of these host applications Powerhouse is launching 2 platforms that form an example of the infrastructure that can be build with the Powerhouse techstack.
|
|
49
18
|
|
|
50
|
-
-
|
|
51
|
-
-
|
|
52
|
-
- Fusion utilizes Renown to verify contributor credibility, ensuring that data-driven decisions are based on trusted and authenticated inputs.
|
|
19
|
+
- [Vetra Builder Platform](https://vetra.io/): Sovereign infrastructure for scalable network organizations that is local first, built to scale.
|
|
20
|
+
- [Achra Decentralized Operations Platform](https://achra.com/): Where open organizations can procure and purchase services.
|
|
@@ -112,38 +112,86 @@ While Storybook aims for accuracy, there might occasionally be discrepancies or
|
|
|
112
112
|
|
|
113
113
|
## Implementing a Component
|
|
114
114
|
|
|
115
|
-
Let's walk through the typical workflow for using a component from the document-engineering system, using
|
|
115
|
+
Let's walk through the typical workflow for using a component from the document-engineering system, using `BooleanField` for a checkbox in the [TodoList editor](/academy/MasteryTrack/BuildingUserExperiences/BuildingDocumentEditors).
|
|
116
116
|
|
|
117
|
-
1. **Identify the Need:** While building your feature (e.g., the
|
|
117
|
+
1. **Identify the Need:** While building your feature (e.g., the TodoList editor), you determine the need for a standard UI element, like a checkbox to mark items as complete.
|
|
118
118
|
2. **Consult the Document Engineering Components in Storybook:**
|
|
119
119
|
- Open the Powerhouse Storybook instance. [https://storybook.powerhouse.academy](https://storybook.powerhouse.academy)
|
|
120
|
-
- Navigate or search to find the `
|
|
120
|
+
- Navigate or search to find the `BooleanField` component (used for checkboxes).
|
|
121
121
|
- Review the visual examples and interactive demo.
|
|
122
|
-
- Examine the "Usage" snippet and the **Props table** to understand the basic implementation and available configuration options (`
|
|
123
|
-
3. **Import the Component:** In your code editor, open the relevant file (e.g., `editors/
|
|
122
|
+
- Examine the "Usage" snippet and the **Props table** to understand the basic implementation and available configuration options (`name`, `value`, `onChange`, etc.).
|
|
123
|
+
3. **Import the Component:** In your code editor, open the relevant file (e.g., `editors/todo-list-editor/components/Checkbox.tsx`). Add an import statement at the top to bring the component into your file's scope:
|
|
124
124
|
```typescript
|
|
125
|
-
import {
|
|
126
|
-
// Or import other components as needed:
|
|
127
|
-
// import { Checkbox, InputField, Button } from '@powerhousedao/document-engineering/scalars';
|
|
125
|
+
import { Form, BooleanField } from "@powerhousedao/document-engineering/scalars";
|
|
128
126
|
```
|
|
129
|
-
This line instructs the build process to locate the `
|
|
130
|
-
|
|
127
|
+
This line instructs the build process to locate the `Form` and `BooleanField` components within the installed `@powerhousedao/document-engineering/scalars` package and make them available for use.
|
|
128
|
+
|
|
129
|
+
:::info Form Wrapper Required
|
|
130
|
+
Scalar components like `BooleanField` must be wrapped in a `Form` component from the same package. This provides built-in validation and form state management.
|
|
131
|
+
:::
|
|
132
|
+
|
|
133
|
+
4. **Use and Configure the Component:** Place the component tag in your JSX where needed. Use the information from Storybook (usage snippet and props table) as a guide, but adapt the props to your specific requirements:
|
|
134
|
+
|
|
135
|
+
**Step 4a: Create a reusable Checkbox component**
|
|
136
|
+
```typescript
|
|
137
|
+
// editors/todo-list-editor/components/Checkbox.tsx
|
|
138
|
+
import { Form, BooleanField } from "@powerhousedao/document-engineering/scalars";
|
|
139
|
+
|
|
140
|
+
interface CheckboxProps {
|
|
141
|
+
value: boolean;
|
|
142
|
+
onChange: (value: boolean) => void;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export const Checkbox = ({ value, onChange }: CheckboxProps) => {
|
|
146
|
+
return (
|
|
147
|
+
<Form onSubmit={() => {}}>
|
|
148
|
+
<BooleanField
|
|
149
|
+
name="checked"
|
|
150
|
+
description="Mark as complete"
|
|
151
|
+
value={value}
|
|
152
|
+
onChange={onChange}
|
|
153
|
+
/>
|
|
154
|
+
</Form>
|
|
155
|
+
);
|
|
156
|
+
};
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
**Step 4b: Use it in your Todo component with the document model hook**
|
|
131
160
|
```typescript
|
|
132
|
-
//
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
161
|
+
// editors/todo-list-editor/components/Todo.tsx
|
|
162
|
+
import { useSelectedTodoListDocument, updateTodoItem } from "todo-tutorial/document-models/todo-list";
|
|
163
|
+
import type { TodoItem } from "todo-tutorial/document-models/todo-list";
|
|
164
|
+
import { Checkbox } from "./Checkbox.js";
|
|
165
|
+
|
|
166
|
+
type Props = { todo: TodoItem };
|
|
167
|
+
|
|
168
|
+
export function Todo({ todo }: Props) {
|
|
169
|
+
// Use the hook to get dispatch function
|
|
170
|
+
const [todoList, dispatch] = useSelectedTodoListDocument();
|
|
171
|
+
|
|
172
|
+
if (!todoList) return null;
|
|
173
|
+
|
|
174
|
+
return (
|
|
175
|
+
<div className="flex items-center gap-2">
|
|
176
|
+
<Checkbox
|
|
177
|
+
value={todo.checked}
|
|
178
|
+
onChange={() => {
|
|
179
|
+
dispatch(updateTodoItem({
|
|
180
|
+
id: todo.id,
|
|
181
|
+
checked: !todo.checked,
|
|
182
|
+
}));
|
|
183
|
+
}}
|
|
184
|
+
/>
|
|
185
|
+
<span className={todo.checked ? "line-through" : ""}>
|
|
186
|
+
{todo.text}
|
|
187
|
+
</span>
|
|
188
|
+
</div>
|
|
189
|
+
);
|
|
190
|
+
}
|
|
145
191
|
```
|
|
146
|
-
|
|
192
|
+
|
|
193
|
+
You configure the component's appearance and behavior by passing the appropriate values to its props. Note the use of the `useSelectedTodoListDocument` hook to access the dispatch function.
|
|
194
|
+
|
|
147
195
|
5. **Test and Refine:** Run your application (e.g., using `ph connect`) to see the component in context. Verify its appearance and functionality.
|
|
148
196
|
|
|
149
197
|
## Usage
|
|
@@ -13,13 +13,17 @@
|
|
|
13
13
|
|
|
14
14
|
## Software Components
|
|
15
15
|
|
|
16
|
+
- **Model Context Protocol (MCP)** – A standardized protocol that enables AI agents and external tools to interact with systems through structured operations. Powerhouse uses MCP to provide AI access to document management capabilities.
|
|
16
17
|
- **Reactor** – A storage node for Powerhouse documents and files with multiple storage adapters (local, cloud, decentralized).
|
|
18
|
+
- **Reactor-MCP** – A Model Context Protocol server for the Powerhouse ecosystem that provides AI agents and tools with structured access to document model operations, serving as a bridge between AI systems and Powerhouse document management infrastructure.
|
|
17
19
|
- **Powerhouse Switchboard** – A scalable API service that aggregates and processes document data.
|
|
18
20
|
- **Powerhouse Fusion** – A platform front-end that hosts the public marketplace for SNO interactions.
|
|
19
21
|
- **Powerhouse Renown** – A decentralized authentication system managing contributor reputation.
|
|
20
22
|
- **Powerhouse Academy** – A training platform for onboarding and upskilling SNO contributors.
|
|
21
23
|
- **Connect** – The contributor's public or private workspace, serving as the entry point for individual contributors to install apps and packages for specific business solutions.
|
|
22
24
|
- **Powergrid** – A decentralized network of reactors that sync with each other.
|
|
25
|
+
- **Preview Drive** – A local drive created in `--watch` mode during `ph vetra` development, used for testing local document models and editors without affecting the main synced drive.
|
|
26
|
+
- **Remote Drive** – A Powerhouse drive hosted on a remote server (e.g., Vetra) that syncs across team members, enabling collaborative development on shared documents and document models.
|
|
23
27
|
- **Powerhouse CLI (ph)** – The command-line tool for Powerhouse project initialization, code generation, package management, and running local development environments (Connect Studio). It also manages services, ensuring the terminology aligns with the updated setup guide.
|
|
24
28
|
- **Connect App (Connect Studio)** – The primary Powerhouse application for defining document models, building/testing editors (in Studio mode), and collaborating on documents.
|
|
25
29
|
- **Document Tools** – Built-in features within Powerhouse applications (e.g., Connect) that assist with document management, inspection, and interaction, such as Operations History.
|
|
@@ -74,10 +78,13 @@
|
|
|
74
78
|
- **State (Local State in Editor)** – Temporary, UI-specific data within an editor (e.g., form inputs), not persisted in the global document state.
|
|
75
79
|
- **Storybook (for Powerhouse Design System)** – Interactive environment for browsing and testing Powerhouse Design System UI components.
|
|
76
80
|
- **Tailwind CSS (in Connect Studio)** – Utility CSS framework integrated into Connect Studio for styling document editors.
|
|
81
|
+
- **Vetra** – A Powerhouse platform for hosting remote drives, enabling collaborative development and document synchronization across team members.
|
|
82
|
+
- **Watch Mode (`--watch`)** – A development mode flag for `ph vetra` that enables dynamic loading of local document models and editors, creating a separate Preview Drive for testing changes in real-time.
|
|
77
83
|
|
|
78
84
|
## AI & Automation
|
|
79
85
|
|
|
80
86
|
- **AI Assistants** – AI-powered contributors paired with human contributors to automate tasks and improve productivity.
|
|
87
|
+
- **Document Model Agent** – A specialized AI agent that guides users through creating document models, handling requirements gathering, design confirmation, and implementation using MCP tools for state schema definition, operation creation, and code generation.
|
|
81
88
|
- **AI Contributor Modes** – Configurable states that determine the AI assistant's behavior, permissions, and task focus.
|
|
82
89
|
- **Task Automation & Scaling** – The use of AI to streamline repetitive tasks, improve communications, and enhance decision-making.
|
|
83
90
|
- **Decentralized Identifier (DID)** – A user-controlled, globally unique ID, used in Renown to link a user's blockchain key to actions pseudonymously.
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
# Step 2 — Implement the `TodoList` document model reducer operation handlers
|
|
2
|
+
|
|
3
|
+
## Adding the logic for handling operations with reducers
|
|
4
|
+
|
|
5
|
+
Your document model update's the state of a given document by applying a set of append-only actions. Once these have been applied to the document, we call them operations.
|
|
6
|
+
|
|
7
|
+
The document model does this with a reducer — a function which takes the existing state and a given action, and then returns the new state with the action applied.
|
|
8
|
+
|
|
9
|
+
## What we have so far
|
|
10
|
+
|
|
11
|
+
The operation handler logic for each module is found in `document-models/SOME-DOCUMENT-MODEL/src/reducers/SOME-MODULE-NAME.ts`.
|
|
12
|
+
|
|
13
|
+
So for our todos module, we will implement our handler logic in `document-models/todo-list/src/reducers/todos.ts`
|
|
14
|
+
|
|
15
|
+
When you generated your document model code, we created a boilerplate implementation of the reducer logic for each of the operations we defined in step 1. You will see that there are functions for handling each of the operations, but all they do is throw "not implemented" errors.
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
import type { TodoListTodosOperations } from "todo-tutorial/document-models/todo-list";
|
|
19
|
+
|
|
20
|
+
export const todoListTodosOperations: TodoListTodosOperations = {
|
|
21
|
+
addTodoItemOperation(state, action) {
|
|
22
|
+
// TODO: Implement "addTodoItemOperation" reducer
|
|
23
|
+
throw new Error('Reducer "addTodoItemOperation" not yet implemented');
|
|
24
|
+
},
|
|
25
|
+
updateTodoItemOperation(state, action) {
|
|
26
|
+
// TODO: Implement "updateTodoItemOperation" reducer
|
|
27
|
+
throw new Error('Reducer "updateTodoItemOperation" not yet implemented');
|
|
28
|
+
},
|
|
29
|
+
deleteTodoItemOperation(state, action) {
|
|
30
|
+
// TODO: Implement "deleteTodoItemOperation" reducer
|
|
31
|
+
throw new Error('Reducer "deleteTodoItemOperation" not yet implemented');
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Let's add the handler logic for each operation in the same order we defined them in the previous step.
|
|
37
|
+
|
|
38
|
+
To handle the `addTodoItemOperation`, all we need to do is create an `id` for our new operation, and then push an object with that `id` and the rest of the action input into the `items` array in our state.
|
|
39
|
+
|
|
40
|
+
Update your `addTodoItemOperation` like so:
|
|
41
|
+
|
|
42
|
+
```typescript
|
|
43
|
+
import type { TodoListTodosOperations } from "todo-tutorial/document-models/todo-list";
|
|
44
|
+
|
|
45
|
+
export const todoListTodosOperations: TodoListTodosOperations = {
|
|
46
|
+
// removed-start
|
|
47
|
+
addTodoItemOperation(state, action) {
|
|
48
|
+
// TODO: Implement "addTodoItemOperation" reducer
|
|
49
|
+
throw new Error('Reducer "addTodoItemOperation" not yet implemented');
|
|
50
|
+
},
|
|
51
|
+
// removed-end
|
|
52
|
+
// added-start
|
|
53
|
+
addTodoItemOperation(state, action) {
|
|
54
|
+
const id = generateId();
|
|
55
|
+
state.items.push({ ...action.input, id, checked: false });
|
|
56
|
+
},
|
|
57
|
+
// added-end
|
|
58
|
+
updateTodoItemOperation(state, action) {
|
|
59
|
+
// TODO: Implement "updateTodoItemOperation" reducer
|
|
60
|
+
throw new Error('Reducer "updateTodoItemOperation" not yet implemented');
|
|
61
|
+
},
|
|
62
|
+
deleteTodoItemOperation(state, action) {
|
|
63
|
+
// TODO: Implement "deleteTodoItemOperation" reducer
|
|
64
|
+
throw new Error('Reducer "deleteTodoItemOperation" not yet implemented');
|
|
65
|
+
},
|
|
66
|
+
};
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Under the hood, we use a library for making the functions always create and return new copies of the state, i.e. they are always _immutable_. This is why you don't actually have to return your new state, the newly created copy of the state is used automatically.
|
|
70
|
+
|
|
71
|
+
The `updateTodoOperation` works in much the same way, except this time instead of creating a new `id`, we find the item in the items array which has the given id. Then we spread out the rest of the values we get from the action input, same as when creating.
|
|
72
|
+
|
|
73
|
+
Update your `updateTodoOperation` to be like so:
|
|
74
|
+
|
|
75
|
+
```typescript
|
|
76
|
+
export const todoListTodosOperations: TodoListTodosOperations = {
|
|
77
|
+
addTodoItemOperation(state, action) {
|
|
78
|
+
const id = generateId();
|
|
79
|
+
state.items.push({ ...action.input, id, checked: false });
|
|
80
|
+
},
|
|
81
|
+
// removed-start
|
|
82
|
+
updateTodoItemOperation(state, action) {
|
|
83
|
+
// TODO: Implement "updateTodoItemOperation" reducer
|
|
84
|
+
throw new Error('Reducer "updateTodoItemOperation" not yet implemented');
|
|
85
|
+
},
|
|
86
|
+
// removed-end
|
|
87
|
+
// added-start
|
|
88
|
+
updateTodoItemOperation(state, action) {
|
|
89
|
+
const item = state.items.find((item) => item.id === action.input.id);
|
|
90
|
+
if (!item) return;
|
|
91
|
+
item.text = action.input.text ?? item.text;
|
|
92
|
+
item.checked = action.input.checked ?? item.checked;
|
|
93
|
+
},
|
|
94
|
+
// added-end
|
|
95
|
+
deleteTodoItemOperation(state, action) {
|
|
96
|
+
// TODO: Implement "deleteTodoItemOperation" reducer
|
|
97
|
+
throw new Error('Reducer "deleteTodoItemOperation" not yet implemented');
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
The delete operation is the simplest of the three. All we need to do is filter the items array so that it no longer contains the item with the given id.
|
|
103
|
+
|
|
104
|
+
```typescript
|
|
105
|
+
export const todoListTodosOperations: TodoListTodosOperations = {
|
|
106
|
+
addTodoItemOperation(state, action) {
|
|
107
|
+
const id = generateId();
|
|
108
|
+
state.items.push({ ...action.input, id, checked: false });
|
|
109
|
+
},
|
|
110
|
+
updateTodoItemOperation(state, action) {
|
|
111
|
+
const item = state.items.find((item) => item.id === action.input.id);
|
|
112
|
+
if (!item) return;
|
|
113
|
+
item.text = action.input.text ?? item.text;
|
|
114
|
+
item.checked = action.input.checked ?? item.checked;
|
|
115
|
+
},
|
|
116
|
+
// removed-start
|
|
117
|
+
deleteTodoItemOperation(state, action) {
|
|
118
|
+
// TODO: Implement "deleteTodoItemOperation" reducer
|
|
119
|
+
throw new Error('Reducer "deleteTodoItemOperation" not yet implemented');
|
|
120
|
+
},
|
|
121
|
+
// removed-end
|
|
122
|
+
// added-start
|
|
123
|
+
deleteTodoItemOperation(state, action) {
|
|
124
|
+
state.items = state.items.filter((item) => item.id !== action.input.id);
|
|
125
|
+
},
|
|
126
|
+
// added-end
|
|
127
|
+
};
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
With that all done, your final result should look like this:
|
|
131
|
+
|
|
132
|
+
```ts
|
|
133
|
+
import { generateId } from "document-model/core";
|
|
134
|
+
import type { TodoListTodosOperations } from "todo-tutorial/document-models/todo-list";
|
|
135
|
+
|
|
136
|
+
export const todoListTodosOperations: TodoListTodosOperations = {
|
|
137
|
+
addTodoItemOperation(state, action) {
|
|
138
|
+
const id = generateId();
|
|
139
|
+
state.items.push({ ...action.input, id, checked: false });
|
|
140
|
+
},
|
|
141
|
+
updateTodoItemOperation(state, action) {
|
|
142
|
+
const item = state.items.find((item) => item.id === action.input.id);
|
|
143
|
+
if (!item) return;
|
|
144
|
+
item.text = action.input.text ?? item.text;
|
|
145
|
+
item.checked = action.input.checked ?? item.checked;
|
|
146
|
+
},
|
|
147
|
+
deleteTodoItemOperation(state, action) {
|
|
148
|
+
state.items = state.items.filter((item) => item.id !== action.input.id);
|
|
149
|
+
},
|
|
150
|
+
};
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## Check your work
|
|
154
|
+
|
|
155
|
+
To make sure all works as expected, we should:
|
|
156
|
+
|
|
157
|
+
- check types
|
|
158
|
+
run: `pnpm tsc`
|
|
159
|
+
|
|
160
|
+
- check linting
|
|
161
|
+
run: `pnpm lint`
|
|
162
|
+
|
|
163
|
+
- check tests
|
|
164
|
+
run: `pnpm test`
|
|
165
|
+
|
|
166
|
+
- make sure your code matches the code in the completed step branch
|
|
167
|
+
run: `git diff your-branch-name step-2-complete-implemented-todo-list-document-model-reducer-operation-handlers`
|
|
168
|
+
|
|
169
|
+
### Up next: tests for our new operation handlers
|
|
170
|
+
|
|
171
|
+
Up next, you'll implement some custom tests to check the behavior of our new code.
|