@powerhousedao/academy 5.1.0-dev.9 → 5.1.0
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 +43 -1108
- package/blog/BeyondCommunication-ABlueprintForDevelopment.md +1 -2
- package/blog/TheChallengeOfChange.md +0 -1
- package/docs/academy/00-EthereumArgentinaHackathon.md +207 -0
- package/docs/academy/01-GetStarted/00-ExploreDemoPackage.mdx +27 -24
- package/docs/academy/01-GetStarted/01-CreateNewPowerhouseProject.md +9 -118
- package/docs/academy/01-GetStarted/02-DefineToDoListDocumentModel.md +28 -110
- package/docs/academy/01-GetStarted/03-ImplementOperationReducers.md +145 -191
- package/docs/academy/01-GetStarted/04-BuildToDoListEditor.md +218 -0
- package/docs/academy/{02-MasteryTrack/01-BuilderEnvironment → 01-GetStarted}/05-VetraStudio.md +6 -48
- package/docs/academy/01-GetStarted/06-ReactorMCP.md +58 -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/02-MasteryTrack/02-DocumentModelCreation/02-SpecifyTheStateSchema.md +44 -75
- package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/03-SpecifyDocumentOperations.md +22 -28
- package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/04-UseTheDocumentModelGenerator.md +31 -28
- package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/05-ImplementDocumentReducers.md +206 -211
- package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/06-ImplementDocumentModelTests.md +62 -176
- package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/07-ExampleToDoListRepository.md +0 -21
- package/docs/academy/02-MasteryTrack/03-BuildingUserExperiences/01-BuildingDocumentEditors.md +319 -309
- package/docs/academy/02-MasteryTrack/03-BuildingUserExperiences/06-DocumentTools/00-DocumentToolbar.mdx +0 -4
- package/docs/academy/02-MasteryTrack/03-BuildingUserExperiences/06-DocumentTools/01-OperationHistory.md +0 -4
- package/docs/academy/02-MasteryTrack/05-Launch/04-ConfigureEnvironment.md +1 -1
- package/docs/academy/03-ExampleUsecases/Chatroom/02-CreateNewPowerhouseProject.md +35 -111
- package/docs/academy/03-ExampleUsecases/Chatroom/03-DefineChatroomDocumentModel.md +76 -255
- package/docs/academy/03-ExampleUsecases/Chatroom/04-ImplementOperationReducers.md +160 -281
- package/docs/academy/03-ExampleUsecases/Chatroom/05-ImplementChatroomEditor.md +35 -188
- package/docs/academy/03-ExampleUsecases/Chatroom/06-LaunchALocalReactor.md +7 -95
- package/docs/academy/03-ExampleUsecases/Chatroom/_category_.json +1 -1
- package/docs/academy/04-APIReferences/00-PowerhouseCLI.md +2 -6
- package/docs/academy/04-APIReferences/01-ReactHooks.md +501 -291
- package/docs/academy/05-Architecture/00-PowerhouseArchitecture.md +39 -7
- package/docs/academy/05-Architecture/02-ReferencingMonorepoPackages +65 -0
- package/docs/academy/05-Architecture/04-MovingBeyondCRUD +61 -0
- package/docs/academy/06-ComponentLibrary/00-DocumentEngineering.md +24 -72
- package/docs/academy/08-Glossary.md +0 -7
- package/docusaurus.config.ts +3 -28
- package/package.json +1 -1
- package/sidebars.ts +12 -49
- package/src/css/custom.css +18 -26
- package/docs/academy/01-GetStarted/04-WriteDocumentModelTests.md +0 -378
- package/docs/academy/01-GetStarted/05-BuildToDoListEditor.md +0 -560
- package/docs/academy/03-ExampleUsecases/TodoList/00-GetTheStarterCode.md +0 -24
- package/docs/academy/03-ExampleUsecases/TodoList/01-GenerateTodoListDocumentModel.md +0 -211
- package/docs/academy/03-ExampleUsecases/TodoList/02-ImplementTodoListDocumentModelReducerOperationHandlers.md +0 -171
- package/docs/academy/03-ExampleUsecases/TodoList/03-AddTestsForTodoListActions.md +0 -462
- package/docs/academy/03-ExampleUsecases/TodoList/04-GenerateTodoListDocumentEditor.md +0 -45
- package/docs/academy/03-ExampleUsecases/TodoList/05-ImplementTodoListDocumentEditorUIComponents.md +0 -422
- package/docs/academy/03-ExampleUsecases/TodoList/06-GenerateTodoDriveExplorer.md +0 -61
- package/docs/academy/03-ExampleUsecases/TodoList/07-AddSharedComponentForShowingTodoListStats.md +0 -384
- package/docs/academy/03-ExampleUsecases/TodoList/_category_.json +0 -8
- package/docs/academy/03-ExampleUsecases/VetraPackageLibrary/VetraPackageLibrary.md +0 -7
- package/docs/academy/03-ExampleUsecases/VetraPackageLibrary/_category_.json +0 -9
- package/docs/academy/04-APIReferences/06-VetraRemoteDrive.md +0 -160
- package/docs/academy/04-APIReferences/renown-sdk/00-Overview.md +0 -316
- package/docs/academy/04-APIReferences/renown-sdk/01-Authentication.md +0 -672
- package/docs/academy/04-APIReferences/renown-sdk/02-APIReference.md +0 -957
- package/docs/academy/04-APIReferences/renown-sdk/_category_.json +0 -8
- package/docs/academy/10-TodoListTutorial/02-ImplementTodoListDocumentModelReducerOperationHandlers.md +0 -171
- package/docs/academy/10-TodoListTutorial/03-AddTestsForTodoListActions.md +0 -462
- package/docs/academy/10-TodoListTutorial/05-ImplementTodoListDocumentEditorUIComponents.md +0 -422
- package/docs/academy/10-TodoListTutorial/07-AddSharedComponentForShowingTodoListStats.md +0 -370
- package/static/img/Vetra-logo-dark.svg +0 -11
- package/static/img/vetra-logo-light.svg +0 -11
- /package/docs/academy/{02-MasteryTrack/01-BuilderEnvironment → 01-GetStarted}/images/Modules.png +0 -0
- /package/docs/academy/{02-MasteryTrack/01-BuilderEnvironment → 01-GetStarted}/images/VetraStudioDrive.png +0 -0
- /package/docs/academy/02-MasteryTrack/03-BuildingUserExperiences/06-DocumentTools/{02-RevisionHistoryTimeline/360/237/232/247" → 02-RevisionHistoryTimeline} +0 -0
- /package/docs/academy/05-Architecture/05-DocumentModelTheory/{360/237/232/247 /01-WhatIsADocumentModel" → 01-WhatIsADocumentModel} +0 -0
- /package/docs/academy/05-Architecture/05-DocumentModelTheory/{360/237/232/247 /02-DAOandDocumentsModelsQ+A" → 02-DAOandDocumentsModelsQ+A} +0 -0
- /package/docs/academy/05-Architecture/05-DocumentModelTheory/{360/237/232/247 /02-domain-modeling" → 02-domain-modeling} +0 -0
- /package/docs/academy/05-Architecture/05-DocumentModelTheory/{360/237/232/247 /03-BenefitsOfDocumentModels" → 03-BenefitsOfDocumentModels} +0 -0
- /package/docs/academy/05-Architecture/05-DocumentModelTheory/{360/237/232/247 /04-UtilitiesAndTips" → 04-UtilitiesAndTips} +0 -0
- /package/docs/academy/05-Architecture/05-DocumentModelTheory/{360/237/232/247 /05-best-practices" → 05-best-practices} +0 -0
- /package/docs/academy/05-Architecture/05-DocumentModelTheory/{360/237/232/247 /_category_.json" → _category_.json} +0 -0
- /package/docs/academy/05-Architecture/05-DocumentModelTheory/{360/237/232/247 /three-data-layers.png" → three-data-layers.png} +0 -0
|
@@ -1,560 +0,0 @@
|
|
|
1
|
-
# Build a to-do list editor
|
|
2
|
-
|
|
3
|
-
:::tip Tutorial Repository
|
|
4
|
-
📦 **Reference Code**:
|
|
5
|
-
- **Editor Scaffolding**: [step-5-generate-todo-list-document-editor](https://github.com/powerhouse-inc/todo-tutorial/tree/step-5-generate-todo-list-document-editor)
|
|
6
|
-
- **Complete Editor UI**: [step-6-add-basic-todo-editor-ui-components](https://github.com/powerhouse-inc/todo-tutorial/tree/step-6-add-basic-todo-editor-ui-components)
|
|
7
|
-
|
|
8
|
-
This tutorial covers two steps:
|
|
9
|
-
1. **Step 5**: Generating the editor template with `ph generate --editor`
|
|
10
|
-
2. **Step 6**: Building a complete, interactive UI with components for adding, editing, and deleting todos
|
|
11
|
-
|
|
12
|
-
Compare implementations: `git diff step-5-generate-todo-list-document-editor step-6-add-basic-todo-editor-ui-components`
|
|
13
|
-
:::
|
|
14
|
-
|
|
15
|
-
<details>
|
|
16
|
-
<summary>📖 How to use this tutorial</summary>
|
|
17
|
-
|
|
18
|
-
This tutorial shows building from **generated scaffolding** (step-5) to **complete UI** (step-6).
|
|
19
|
-
|
|
20
|
-
### Compare your generated editor
|
|
21
|
-
|
|
22
|
-
After running `ph generate --editor`:
|
|
23
|
-
|
|
24
|
-
```bash
|
|
25
|
-
# Compare generated scaffolding with step-5
|
|
26
|
-
git diff tutorial/step-5-generate-todo-list-document-editor -- editors/
|
|
27
|
-
|
|
28
|
-
# View the generated editor template
|
|
29
|
-
git show tutorial/step-5-generate-todo-list-document-editor:editors/todo-list-editor/editor.tsx
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
### Compare your custom components
|
|
33
|
-
|
|
34
|
-
After building your UI:
|
|
35
|
-
|
|
36
|
-
```bash
|
|
37
|
-
# Compare your complete editor with step-6
|
|
38
|
-
git diff tutorial/step-6-add-basic-todo-editor-ui-components -- editors/
|
|
39
|
-
|
|
40
|
-
# See what was added from scaffolding to complete UI
|
|
41
|
-
git diff tutorial/step-5-generate-todo-list-document-editor..tutorial/step-6-add-basic-todo-editor-ui-components
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
### Browse the complete implementation
|
|
45
|
-
|
|
46
|
-
Explore the production-ready component structure:
|
|
47
|
-
|
|
48
|
-
```bash
|
|
49
|
-
# List all components in step-6
|
|
50
|
-
git ls-tree -r --name-only tutorial/step-6-add-basic-todo-editor-ui-components editors/todo-list-editor/components/
|
|
51
|
-
|
|
52
|
-
# View a specific component
|
|
53
|
-
git show tutorial/step-6-add-basic-todo-editor-ui-components:editors/todo-list-editor/components/TodoList.tsx
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
### Visual comparison with GitHub Desktop
|
|
57
|
-
|
|
58
|
-
After committing your editor code:
|
|
59
|
-
1. **Branch** menu → **"Compare to Branch..."**
|
|
60
|
-
2. Select `tutorial/step-5-generate-todo-list-document-editor` or `tutorial/step-6-add-basic-todo-editor-ui-components`
|
|
61
|
-
3. See all your custom components vs. the reference implementation
|
|
62
|
-
|
|
63
|
-
See step 1 for detailed GitHub Desktop instructions.
|
|
64
|
-
|
|
65
|
-
</details>
|
|
66
|
-
|
|
67
|
-
In this chapter we will continue with the interface or editor implementation of the **To-do List** document model. This means you will create a simple user interface for the **To-do List** document model which will be used inside the Connect app to create, update and delete your ToDoList items.
|
|
68
|
-
|
|
69
|
-
## Generate the editor template
|
|
70
|
-
|
|
71
|
-
Run the command below to generate the editor template for the **To-do List** document model.
|
|
72
|
-
This command reads the **To-do List** document model definition from the `document-models` folder and generates the editor template in the `editors/todo-list-editor` folder.
|
|
73
|
-
|
|
74
|
-
```bash
|
|
75
|
-
pnpm generate --editor todo-list-editor --document-types powerhouse/todo-list
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
Notice the `--editor` flag which specifies the editor name, and the `--document-types` flag defines the document type `powerhouse/todo-list`.
|
|
79
|
-
|
|
80
|
-
Once complete, you'll have a new directory structure:
|
|
81
|
-
|
|
82
|
-
```
|
|
83
|
-
editors/todo-list-editor/
|
|
84
|
-
├── components/
|
|
85
|
-
│ └── EditName.tsx # Auto-generated component for editing document name
|
|
86
|
-
├── editor.tsx # Main editor component (to be customized)
|
|
87
|
-
└── module.ts # Editor module configuration
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
Navigate to the `editors/todo-list-editor/editor.tsx` file and open it in your editor. You'll see a basic template ready for customization.
|
|
91
|
-
|
|
92
|
-
### Editor implementation options
|
|
93
|
-
|
|
94
|
-
When building your editor component within the Powerhouse ecosystem, you have several options for styling, allowing you to leverage your preferred methods:
|
|
95
|
-
|
|
96
|
-
1. **Default HTML Styling:** Standard HTML tags (`<h1>`, `<p>`, `<button>`, etc.) will render with default styles offered through the boilerplate.
|
|
97
|
-
2. **Tailwind CSS:** Connect Studio comes with Tailwind CSS integrated. You can directly use Tailwind utility classes for rapid, consistent styling without writing separate CSS files.
|
|
98
|
-
3. **Custom CSS Files:** You can import traditional CSS files (`.css`) to apply custom styles or integrate existing style libraries.
|
|
99
|
-
|
|
100
|
-
Connect Studio provides a dynamic local environment, by running `ph connect` to visualize your components instantly as you build them, regardless of the styling method you choose.
|
|
101
|
-
Manual build steps are typically only needed when publishing packages.
|
|
102
|
-
|
|
103
|
-
## Build the editor with components
|
|
104
|
-
|
|
105
|
-
We'll build the editor using a component-based approach for better organization and reusability. We'll create separate components for different UI features, making the code more maintainable and easier to understand.
|
|
106
|
-
|
|
107
|
-
### Component-based architecture
|
|
108
|
-
|
|
109
|
-
The editor structure we'll build includes:
|
|
110
|
-
- `editor.tsx` - Main editor wrapper (imports TodoList)
|
|
111
|
-
- `TodoList.tsx` - Main container component that orchestrates all other components
|
|
112
|
-
- `AddTodo.tsx` - Form component for adding new todos
|
|
113
|
-
- `Todo.tsx` - Individual todo item component with edit/delete functionality
|
|
114
|
-
- `Todos.tsx` - List wrapper component for rendering all todos
|
|
115
|
-
|
|
116
|
-
:::tip
|
|
117
|
-
The tutorial repository (step-6) includes additional components like `TodoListName`, `CloseButton`, and `UndoRedoButtons`. We'll focus on the core components here, but you can explore the complete implementation using the git commands shown above.
|
|
118
|
-
:::
|
|
119
|
-
|
|
120
|
-
### Step 1: Update the main editor file
|
|
121
|
-
|
|
122
|
-
First, update `editors/todo-list-editor/editor.tsx` to import and render the main `TodoList` component:
|
|
123
|
-
|
|
124
|
-
```tsx
|
|
125
|
-
// removed-line
|
|
126
|
-
import { EditTodoListName } from "./components/EditName.js";
|
|
127
|
-
// added-line
|
|
128
|
-
import { TodoList } from "./components/TodoList.js";
|
|
129
|
-
|
|
130
|
-
/** Editor component for the Todo List document type */
|
|
131
|
-
export function Editor() {
|
|
132
|
-
return (
|
|
133
|
-
<div className="py-4 px-8">
|
|
134
|
-
// removed-line
|
|
135
|
-
<EditTodoListName />
|
|
136
|
-
// added-line
|
|
137
|
-
<TodoList />
|
|
138
|
-
</div>
|
|
139
|
-
);
|
|
140
|
-
}
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
### Step 2: Create the TodoList container component
|
|
144
|
-
|
|
145
|
-
Create `editors/todo-list-editor/components/TodoList.tsx`. This is the main orchestrator that brings together all child components:
|
|
146
|
-
|
|
147
|
-
```tsx
|
|
148
|
-
import { useSelectedTodoListDocument } from "todo-tutorial/document-models/todo-list";
|
|
149
|
-
import { TodoListName } from "./TodoListName.js";
|
|
150
|
-
import { Todos } from "./Todos.js";
|
|
151
|
-
import { AddTodo } from "./AddTodo.js";
|
|
152
|
-
|
|
153
|
-
/** Displays the selected todo list */
|
|
154
|
-
export function TodoList() {
|
|
155
|
-
const [selectedTodoList] = useSelectedTodoListDocument();
|
|
156
|
-
|
|
157
|
-
if (!selectedTodoList) return null;
|
|
158
|
-
|
|
159
|
-
const todos = selectedTodoList.state.global.items;
|
|
160
|
-
|
|
161
|
-
return (
|
|
162
|
-
<div>
|
|
163
|
-
<section className="mb-4">
|
|
164
|
-
<TodoListName />
|
|
165
|
-
</section>
|
|
166
|
-
<section className="mb-4">
|
|
167
|
-
<Todos todos={todos} />
|
|
168
|
-
</section>
|
|
169
|
-
<section>
|
|
170
|
-
<AddTodo />
|
|
171
|
-
</section>
|
|
172
|
-
</div>
|
|
173
|
-
);
|
|
174
|
-
}
|
|
175
|
-
```
|
|
176
|
-
|
|
177
|
-
:::info Key Concept: useSelectedTodoListDocument hook
|
|
178
|
-
The `useSelectedTodoListDocument` hook is generated by the Powerhouse CLI. It provides:
|
|
179
|
-
1. The current document state (`selectedTodoList`)
|
|
180
|
-
2. A dispatch function to send actions to the reducer
|
|
181
|
-
|
|
182
|
-
This hook connects your React components to the document model's state and operations.
|
|
183
|
-
:::
|
|
184
|
-
|
|
185
|
-
### Step 3: Create the AddTodo form component
|
|
186
|
-
|
|
187
|
-
Create `editors/todo-list-editor/components/AddTodo.tsx` to handle adding new todo items:
|
|
188
|
-
|
|
189
|
-
```tsx
|
|
190
|
-
import type { FormEventHandler } from "react";
|
|
191
|
-
import { addTodoItem } from "todo-tutorial/document-models/todo-list";
|
|
192
|
-
import { useSelectedTodoListDocument } from "todo-tutorial/document-models/todo-list";
|
|
193
|
-
|
|
194
|
-
/** Component for adding a new todo item to the selected todo list */
|
|
195
|
-
export function AddTodo() {
|
|
196
|
-
const [todoList, dispatch] = useSelectedTodoListDocument();
|
|
197
|
-
|
|
198
|
-
if (!todoList) return null;
|
|
199
|
-
|
|
200
|
-
const onSubmitAddTodo: FormEventHandler<HTMLFormElement> = (event) => {
|
|
201
|
-
event.preventDefault();
|
|
202
|
-
|
|
203
|
-
const form = event.currentTarget;
|
|
204
|
-
const addTodoInput = form.elements.namedItem("addTodo") as HTMLInputElement;
|
|
205
|
-
const text = addTodoInput.value;
|
|
206
|
-
if (!text) return;
|
|
207
|
-
|
|
208
|
-
dispatch(addTodoItem({ text }));
|
|
209
|
-
|
|
210
|
-
form.reset();
|
|
211
|
-
};
|
|
212
|
-
|
|
213
|
-
return (
|
|
214
|
-
<form onSubmit={onSubmitAddTodo} className="flex mx-auto min-w-fit gap-2">
|
|
215
|
-
<input
|
|
216
|
-
className="py-1 px-2 grow min-w-fit placeholder:text-gray-600 rounded border border-gray-600 text-gray-800"
|
|
217
|
-
type="text"
|
|
218
|
-
name="addTodo"
|
|
219
|
-
placeholder="What needs to be done?"
|
|
220
|
-
autoFocus
|
|
221
|
-
/>
|
|
222
|
-
<button
|
|
223
|
-
type="submit"
|
|
224
|
-
className="text-gray-600 rounded border border-gray-600 px-3 py-1"
|
|
225
|
-
>
|
|
226
|
-
Add
|
|
227
|
-
</button>
|
|
228
|
-
</form>
|
|
229
|
-
);
|
|
230
|
-
}
|
|
231
|
-
```
|
|
232
|
-
|
|
233
|
-
**What's happening here:**
|
|
234
|
-
- We use a form with `onSubmit` handler for better UX (Enter key support)
|
|
235
|
-
- We extract the text value from the input field
|
|
236
|
-
- We dispatch the `addTodoItem` action (generated from our SDL)
|
|
237
|
-
- We reset the form after submission
|
|
238
|
-
|
|
239
|
-
### Step 4: Create the Todos list component
|
|
240
|
-
|
|
241
|
-
Create `editors/todo-list-editor/components/Todos.tsx` to render the list of todos:
|
|
242
|
-
|
|
243
|
-
```tsx
|
|
244
|
-
import type { TodoItem } from "todo-tutorial/document-models/todo-list";
|
|
245
|
-
import { Todo } from "./Todo.js";
|
|
246
|
-
|
|
247
|
-
type Props = {
|
|
248
|
-
todos: TodoItem[];
|
|
249
|
-
};
|
|
250
|
-
|
|
251
|
-
/** Shows a list of the todo items in the selected todo list */
|
|
252
|
-
export function Todos({ todos }: Props) {
|
|
253
|
-
const hasTodos = todos.length > 0;
|
|
254
|
-
|
|
255
|
-
if (!hasTodos) {
|
|
256
|
-
return <p>Start adding things to your todo list</p>;
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
return (
|
|
260
|
-
<ul>
|
|
261
|
-
{todos.map((todo) => (
|
|
262
|
-
<li key={todo.id}>
|
|
263
|
-
<Todo todo={todo} />
|
|
264
|
-
</li>
|
|
265
|
-
))}
|
|
266
|
-
</ul>
|
|
267
|
-
);
|
|
268
|
-
}
|
|
269
|
-
```
|
|
270
|
-
|
|
271
|
-
**What's happening here:**
|
|
272
|
-
- We accept `todos` as a prop (passed from `TodoList` parent)
|
|
273
|
-
- We show a helpful message if the list is empty
|
|
274
|
-
- We map over todos and render a `Todo` component for each item
|
|
275
|
-
|
|
276
|
-
### Step 5: Create the Todo item component
|
|
277
|
-
|
|
278
|
-
Create `editors/todo-list-editor/components/Todo.tsx` for individual todo items with edit and delete functionality:
|
|
279
|
-
|
|
280
|
-
```tsx
|
|
281
|
-
import {
|
|
282
|
-
useState,
|
|
283
|
-
type ChangeEventHandler,
|
|
284
|
-
type FormEventHandler,
|
|
285
|
-
type MouseEventHandler,
|
|
286
|
-
} from "react";
|
|
287
|
-
import {
|
|
288
|
-
deleteTodoItem,
|
|
289
|
-
updateTodoItem,
|
|
290
|
-
} from "todo-tutorial/document-models/todo-list";
|
|
291
|
-
import type { TodoItem } from "todo-tutorial/document-models/todo-list";
|
|
292
|
-
import { useSelectedTodoListDocument } from "todo-tutorial/document-models/todo-list";
|
|
293
|
-
|
|
294
|
-
type Props = {
|
|
295
|
-
todo: TodoItem;
|
|
296
|
-
};
|
|
297
|
-
|
|
298
|
-
/** Displays a single todo item in the selected todo list
|
|
299
|
-
*
|
|
300
|
-
* Allows checking/unchecking the todo item.
|
|
301
|
-
* Allows editing the todo item text.
|
|
302
|
-
* Allows deleting the todo item.
|
|
303
|
-
*/
|
|
304
|
-
export function Todo({ todo }: Props) {
|
|
305
|
-
const [isEditing, setIsEditing] = useState(false);
|
|
306
|
-
const [todoList, dispatch] = useSelectedTodoListDocument();
|
|
307
|
-
|
|
308
|
-
if (!todoList) return null;
|
|
309
|
-
|
|
310
|
-
const todoId = todo.id;
|
|
311
|
-
const todoText = todo.text;
|
|
312
|
-
const todoChecked = todo.checked;
|
|
313
|
-
|
|
314
|
-
const onSubmitUpdateTodoText: FormEventHandler<HTMLFormElement> = (event) => {
|
|
315
|
-
event.preventDefault();
|
|
316
|
-
|
|
317
|
-
const form = event.currentTarget;
|
|
318
|
-
const textInput = form.elements.namedItem("todoText") as HTMLInputElement;
|
|
319
|
-
const text = textInput.value;
|
|
320
|
-
if (!text) return;
|
|
321
|
-
dispatch(updateTodoItem({ id: todo.id, text }));
|
|
322
|
-
setIsEditing(false);
|
|
323
|
-
};
|
|
324
|
-
|
|
325
|
-
const onChangeTodoChecked: ChangeEventHandler<HTMLInputElement> = (event) => {
|
|
326
|
-
dispatch(
|
|
327
|
-
updateTodoItem({
|
|
328
|
-
id: todo.id,
|
|
329
|
-
checked: event.target.checked,
|
|
330
|
-
}),
|
|
331
|
-
);
|
|
332
|
-
};
|
|
333
|
-
|
|
334
|
-
const onClickDeleteTodo: MouseEventHandler<HTMLButtonElement> = () => {
|
|
335
|
-
dispatch(deleteTodoItem({ id: todoId }));
|
|
336
|
-
};
|
|
337
|
-
|
|
338
|
-
const onClickEditTodo: MouseEventHandler<HTMLButtonElement> = () => {
|
|
339
|
-
setIsEditing(true);
|
|
340
|
-
};
|
|
341
|
-
|
|
342
|
-
const onClickCancelEditTodo: MouseEventHandler<HTMLButtonElement> = () => {
|
|
343
|
-
setIsEditing(false);
|
|
344
|
-
};
|
|
345
|
-
|
|
346
|
-
if (isEditing)
|
|
347
|
-
return (
|
|
348
|
-
<form
|
|
349
|
-
className="flex gap-2 items-center justify-between"
|
|
350
|
-
onSubmit={onSubmitUpdateTodoText}
|
|
351
|
-
>
|
|
352
|
-
<input
|
|
353
|
-
className="p-1 grow"
|
|
354
|
-
type="text"
|
|
355
|
-
name="todoText"
|
|
356
|
-
defaultValue={todoText}
|
|
357
|
-
autoFocus
|
|
358
|
-
/>
|
|
359
|
-
<div className="flex gap-2 grow-0">
|
|
360
|
-
<button type="submit" className="text-sm text-gray-600">
|
|
361
|
-
Save
|
|
362
|
-
</button>
|
|
363
|
-
<button
|
|
364
|
-
className="text-sm text-red-800"
|
|
365
|
-
onClick={onClickCancelEditTodo}
|
|
366
|
-
>
|
|
367
|
-
Cancel
|
|
368
|
-
</button>
|
|
369
|
-
</div>
|
|
370
|
-
</form>
|
|
371
|
-
);
|
|
372
|
-
|
|
373
|
-
return (
|
|
374
|
-
<div className="flex justify-between items-center">
|
|
375
|
-
<div className="flex items-center gap-2 p-1">
|
|
376
|
-
<input
|
|
377
|
-
type="checkbox"
|
|
378
|
-
checked={todoChecked}
|
|
379
|
-
onChange={onChangeTodoChecked}
|
|
380
|
-
/>
|
|
381
|
-
<span className={todoChecked ? "line-through" : ""}>{todoText}</span>
|
|
382
|
-
</div>
|
|
383
|
-
<span className="flex place-items-center gap-2 text-sm">
|
|
384
|
-
<button className="text-gray-600" onClick={onClickEditTodo}>
|
|
385
|
-
Edit
|
|
386
|
-
</button>
|
|
387
|
-
<button className="text-red-800" onClick={onClickDeleteTodo}>
|
|
388
|
-
Delete
|
|
389
|
-
</button>
|
|
390
|
-
</span>
|
|
391
|
-
</div>
|
|
392
|
-
);
|
|
393
|
-
}
|
|
394
|
-
```
|
|
395
|
-
|
|
396
|
-
**What's happening here:**
|
|
397
|
-
- We use local state (`isEditing`) to toggle between view and edit modes
|
|
398
|
-
- We dispatch `updateTodoItem` for both checking and text editing
|
|
399
|
-
- We dispatch `deleteTodoItem` to remove items
|
|
400
|
-
- We use TypeScript event handlers for type safety
|
|
401
|
-
|
|
402
|
-
### Step 6: Create the TodoListName component
|
|
403
|
-
|
|
404
|
-
Finally, create `editors/todo-list-editor/components/TodoListName.tsx` for displaying and editing the document name:
|
|
405
|
-
|
|
406
|
-
```tsx
|
|
407
|
-
import { useState, type FormEventHandler } from "react";
|
|
408
|
-
import { useSelectedTodoListDocument } from "todo-tutorial/document-models/todo-list";
|
|
409
|
-
import { setName } from "document-model/document";
|
|
410
|
-
|
|
411
|
-
/** Allows editing the name of the selected todo list */
|
|
412
|
-
export function TodoListName() {
|
|
413
|
-
const [isEditing, setIsEditing] = useState(false);
|
|
414
|
-
const [selectedTodoList, dispatch] = useSelectedTodoListDocument();
|
|
415
|
-
|
|
416
|
-
if (!selectedTodoList) return null;
|
|
417
|
-
|
|
418
|
-
const documentName = selectedTodoList.name;
|
|
419
|
-
|
|
420
|
-
const onSubmitEditName: FormEventHandler<HTMLFormElement> = (event) => {
|
|
421
|
-
event.preventDefault();
|
|
422
|
-
|
|
423
|
-
const form = event.currentTarget;
|
|
424
|
-
const nameInput = form.elements.namedItem("name") as HTMLInputElement;
|
|
425
|
-
const name = nameInput.value;
|
|
426
|
-
|
|
427
|
-
if (name) {
|
|
428
|
-
dispatch(setName(name));
|
|
429
|
-
setIsEditing(false);
|
|
430
|
-
}
|
|
431
|
-
};
|
|
432
|
-
|
|
433
|
-
if (isEditing) {
|
|
434
|
-
return (
|
|
435
|
-
<form onSubmit={onSubmitEditName}>
|
|
436
|
-
<input
|
|
437
|
-
name="name"
|
|
438
|
-
defaultValue={documentName}
|
|
439
|
-
className="text-xl font-bold"
|
|
440
|
-
autoFocus
|
|
441
|
-
/>
|
|
442
|
-
</form>
|
|
443
|
-
);
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
return (
|
|
447
|
-
<h1
|
|
448
|
-
className="text-xl font-bold cursor-pointer"
|
|
449
|
-
onClick={() => setIsEditing(true)}
|
|
450
|
-
>
|
|
451
|
-
{documentName}
|
|
452
|
-
</h1>
|
|
453
|
-
);
|
|
454
|
-
}
|
|
455
|
-
```
|
|
456
|
-
|
|
457
|
-
**What's happening here:**
|
|
458
|
-
- We use the `setName` action from `document-model/document` (a built-in action)
|
|
459
|
-
- We toggle between viewing and editing the name
|
|
460
|
-
- Click the name to edit it
|
|
461
|
-
|
|
462
|
-
## Test your editor
|
|
463
|
-
|
|
464
|
-
Now you can run the Connect app and see the **To-do List** editor in action:
|
|
465
|
-
|
|
466
|
-
```bash
|
|
467
|
-
ph connect
|
|
468
|
-
```
|
|
469
|
-
|
|
470
|
-
In Connect, in the bottom right corner you'll find a new Document Model that you can create: **To-do List**.
|
|
471
|
-
Click on it to create a new To-do List document.
|
|
472
|
-
|
|
473
|
-
:::info Live Development
|
|
474
|
-
The editor will update dynamically as you make changes, so you can experiment with styling and functionality while seeing your results appear in Connect Studio in real-time.
|
|
475
|
-
:::
|
|
476
|
-
|
|
477
|
-
**Try it out:**
|
|
478
|
-
1. Add some todo items using the input form
|
|
479
|
-
2. Click on the document name to edit it
|
|
480
|
-
3. Check/uncheck items to mark them as complete
|
|
481
|
-
4. Click "Edit" on any item to modify its text
|
|
482
|
-
5. Click "Delete" to remove items
|
|
483
|
-
|
|
484
|
-
Congratulations! 🎉
|
|
485
|
-
If you managed to follow this tutorial until this point, you have successfully implemented the **To-do List** document model with its reducer operations and editor.
|
|
486
|
-
|
|
487
|
-
## Compare with the reference implementation
|
|
488
|
-
|
|
489
|
-
The tutorial repository's step-6 branch includes additional enhancements you can explore:
|
|
490
|
-
|
|
491
|
-
**Additional components in step-6:**
|
|
492
|
-
```
|
|
493
|
-
editors/todo-list-editor/components/
|
|
494
|
-
├── CloseButton.tsx # Editor close functionality
|
|
495
|
-
├── UndoRedoButtons.tsx # Operation history navigation
|
|
496
|
-
└── Stats.tsx # Display metadata (creation/modification times)
|
|
497
|
-
```
|
|
498
|
-
|
|
499
|
-
**View individual components from the reference:**
|
|
500
|
-
|
|
501
|
-
```bash
|
|
502
|
-
# See the enhanced TodoList component with all features
|
|
503
|
-
git show tutorial/step-6-add-basic-todo-editor-ui-components:editors/todo-list-editor/components/TodoList.tsx
|
|
504
|
-
|
|
505
|
-
# Explore the UndoRedoButtons component
|
|
506
|
-
git show tutorial/step-6-add-basic-todo-editor-ui-components:editors/todo-list-editor/components/UndoRedoButtons.tsx
|
|
507
|
-
|
|
508
|
-
# Compare your implementation with the reference
|
|
509
|
-
git diff tutorial/step-6-add-basic-todo-editor-ui-components -- editors/todo-list-editor/
|
|
510
|
-
```
|
|
511
|
-
|
|
512
|
-
:::tip Check your work
|
|
513
|
-
|
|
514
|
-
To make sure everything works as expected:
|
|
515
|
-
|
|
516
|
-
```bash
|
|
517
|
-
# Check types compile correctly
|
|
518
|
-
pnpm tsc
|
|
519
|
-
|
|
520
|
-
# Check linting passes
|
|
521
|
-
pnpm lint
|
|
522
|
-
|
|
523
|
-
# Run tests
|
|
524
|
-
pnpm test
|
|
525
|
-
|
|
526
|
-
# Test in Connect Studio
|
|
527
|
-
ph connect
|
|
528
|
-
|
|
529
|
-
# Compare with reference implementation
|
|
530
|
-
git diff tutorial/step-6-add-basic-todo-editor-ui-components -- editors/todo-list-editor/
|
|
531
|
-
```
|
|
532
|
-
|
|
533
|
-
In Connect, you should be able to:
|
|
534
|
-
- Create a new To-do List document
|
|
535
|
-
- Add, edit, and delete todo items
|
|
536
|
-
- Check/uncheck items to mark them complete
|
|
537
|
-
|
|
538
|
-
:::
|
|
539
|
-
|
|
540
|
-
## Key concepts learned
|
|
541
|
-
|
|
542
|
-
In this tutorial you've learned:
|
|
543
|
-
|
|
544
|
-
✅ **Component-based architecture** - Breaking down complex UIs into reusable components
|
|
545
|
-
✅ **Document model hooks** - Using `useSelectedTodoListDocument` to connect React to your document state
|
|
546
|
-
✅ **Action dispatching** - How to dispatch operations (`addTodoItem`, `updateTodoItem`, `deleteTodoItem`) from your UI
|
|
547
|
-
✅ **Type-safe development** - Leveraging TypeScript with generated types from your SDL
|
|
548
|
-
✅ **Form handling** - Using React forms with proper event handlers
|
|
549
|
-
✅ **Local vs. document state** - When to use React `useState` vs. document model state
|
|
550
|
-
|
|
551
|
-
### Up next: Mastery Track
|
|
552
|
-
|
|
553
|
-
In the [Mastery Track chapter: Document Model Creation](/academy/MasteryTrack/DocumentModelCreation/WhatIsADocumentModel) we guide you through the theoretics of the previous steps while creating a more advanced version of the To-do List.
|
|
554
|
-
|
|
555
|
-
You will learn:
|
|
556
|
-
|
|
557
|
-
- The in's & out's of a document model.
|
|
558
|
-
- How to use UI & Scalar components from the Document Engineering system.
|
|
559
|
-
- How to build Custom Drive Apps or Drive Explorers.
|
|
560
|
-
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
# Step 0 - get the starter code
|
|
2
|
-
|
|
3
|
-
Normally you would initialize a new powerhouse project by running `ph init` with your project name. But since this is a tutorial, we want to provide branches with the final code for each step.
|
|
4
|
-
|
|
5
|
-
Just for the tutorial, please instead make a fork of [this repository](https://github.com/powerhouse-inc/todo-tutorial).
|
|
6
|
-
|
|
7
|
-
*NOTE:* please _uncheck_ the checkbox that says "copy the main branch only" when making your fork — we want to keep the other branches for each step.
|
|
8
|
-
|
|
9
|
-
Once you have your fork, clone it to your machine with `git clone`, the GitHub desktop app or the GitHub cli.
|
|
10
|
-
|
|
11
|
-
The starter branch of this tutorial is: `step-1-generate-todo-list-document-model`.
|
|
12
|
-
|
|
13
|
-
Checkout that branch, and then create your own branch from it with whatever name you want, something like `do-the-tutorial` will work nicely.
|
|
14
|
-
|
|
15
|
-
The code at the step 1 branch of this repository is exactly the same as what you would get if you ran `ph init todo-tutorial`.
|
|
16
|
-
|
|
17
|
-
Each step in this tutorial has two branches associated with it. One is the starting point and the other is the final code after the step is complete. They each have names like `step-1-` for the starting point and `step-1-complete-` for the complete code. You can use the starting point branches if you want to start at a later step or skip a step, and you can use the complete code to compare with your branch if you get stuck.
|
|
18
|
-
|
|
19
|
-
To compare your branch, either do `git diff my-branch step-complete-branch` or use the "compare with branch" option in the GitHub desktop app.
|
|
20
|
-
|
|
21
|
-
Finally, run `pnpm install` to install the project dependencies.
|
|
22
|
-
|
|
23
|
-
Now we're ready to get started.
|
|
24
|
-
|