@powerhousedao/academy 5.1.0-dev.1 → 5.1.0-dev.11
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 +78 -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
|
@@ -0,0 +1,560 @@
|
|
|
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
|
+
|
|
@@ -10,7 +10,7 @@ This command reads the **To-do List** document model definition from the `docume
|
|
|
10
10
|
Notice the `--editor` flag which specifies the **To-do List** document model, and the `--document-types` flag defines the document type `powerhouse/todolist`.
|
|
11
11
|
|
|
12
12
|
```bash
|
|
13
|
-
|
|
13
|
+
pnpm generate --editor Todo-List-editor --document-types powerhouse/todolist
|
|
14
14
|
```
|
|
15
15
|
|
|
16
16
|
Once complete, navigate to the `editors/to-do-list/editor.tsx` file and open it in your editor.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Vetra builder tooling
|
|
2
2
|
|
|
3
|
-
This page provides an overview of all the builder tooling offered
|
|
3
|
+
This page provides an overview of all the builder tooling offered in the Vetra ecosystem by Powerhouse.
|
|
4
4
|
This list will be maintained and updated as our toolkit grows.
|
|
5
5
|
|
|
6
6
|
## Powerhouse command line interface
|
package/docs/academy/{01-GetStarted → 02-MasteryTrack/01-BuilderEnvironment}/05-VetraStudio.md
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Vetra Studio
|
|
2
2
|
|
|
3
3
|
:::tip Important
|
|
4
4
|
|
|
@@ -77,6 +77,28 @@ You could then add the specific remote Vetra drive to your powerhouse configurat
|
|
|
77
77
|
|
|
78
78
|
An example of a builder team building on the Powerhouse Vetra Ecosystem and it's complementary Vetra Studio Drive specifications for the different packages be found [here](https://vetra.io/builders/bai)
|
|
79
79
|
|
|
80
|
+
<details>
|
|
81
|
+
<summary>📦 Vetra Remote Drive Commands</summary>
|
|
82
|
+
|
|
83
|
+
Remote drives enable collaborative development by syncing specifications across team members.
|
|
84
|
+
|
|
85
|
+
**Key Commands:**
|
|
86
|
+
- `ph init --remote-drive <url>` - Create a NEW project connected to a remote drive
|
|
87
|
+
- `ph checkout --remote-drive <url>` - Clone an EXISTING project from a remote drive
|
|
88
|
+
- `ph vetra --watch` - Start development with a preview drive for testing local changes
|
|
89
|
+
|
|
90
|
+
**Workflows:**
|
|
91
|
+
- **Project Owner**: `ph init --remote-drive` → Create GitHub repo → Push → `ph vetra` to configure
|
|
92
|
+
- **Collaborator**: `ph checkout --remote-drive` → `ph vetra` to start developing
|
|
93
|
+
|
|
94
|
+
**Preview Drive (`--watch` mode):**
|
|
95
|
+
- Main "Vetra" drive syncs with remote and contains stable package configuration
|
|
96
|
+
- "Vetra Preview" drive is created locally for testing document models before syncing
|
|
97
|
+
|
|
98
|
+
→ [Full Vetra Remote Drive Reference](/academy/APIReferences/VetraRemoteDrive)
|
|
99
|
+
|
|
100
|
+
</details>
|
|
101
|
+
|
|
80
102
|
## Vetra Studio Workflow
|
|
81
103
|
|
|
82
104
|
### 1. Launch Vetra Studio
|
|
@@ -146,16 +168,35 @@ Connected to MCP successfully! I can see there's a
|
|
|
146
168
|
running and ready for document model operations.
|
|
147
169
|
```
|
|
148
170
|
|
|
149
|
-
- To learn what is a [Reactor](apps/academy/docs/academy/Architecture/WorkingWithTheReactor) read the reactor article
|
|
150
|
-
- To learn more about the [Reactor MCP](apps/academy/docs/academy/GetStarted/ReactorMCP) read the reactor MCP article
|
|
151
|
-
|
|
152
171
|
### Key Reactor MCP Features
|
|
153
172
|
|
|
154
173
|
- It supports automatic document model creation from natural language descriptions
|
|
155
174
|
- It implements a smart editor based on the underlying document models
|
|
156
175
|
- It automatically triggers code generation when documents reach valid state
|
|
157
|
-
- The MCP server enables the agent to work with both existing and newly created document models
|
|
158
|
-
- Vetra supports integration with custom remote drives, allowing users to create, share and manage documents within these drives
|
|
176
|
+
- The MCP server enables the agent to work with both existing and newly created document models
|
|
177
|
+
- Vetra supports integration with custom remote drives, allowing users to create, share and manage documents within these drives
|
|
178
|
+
|
|
179
|
+
<details>
|
|
180
|
+
<summary>🤖 Reactor MCP Overview</summary>
|
|
181
|
+
|
|
182
|
+
**Reactor-mcp** is a Model Context Protocol (MCP) server that bridges AI agents with Powerhouse document operations.
|
|
183
|
+
|
|
184
|
+
**Document Operations:**
|
|
185
|
+
- `createDocument` / `getDocument` / `deleteDocument` - Manage documents
|
|
186
|
+
- `addActions` - Modify document state through operations
|
|
187
|
+
|
|
188
|
+
**Drive Operations:**
|
|
189
|
+
- `getDrives` / `addDrive` / `getDrive` - Manage document drives
|
|
190
|
+
- `addRemoteDrive` - Connect to remote drives
|
|
191
|
+
|
|
192
|
+
**Document Model Operations:**
|
|
193
|
+
- `getDocumentModels` - List available document model types
|
|
194
|
+
- `getDocumentModelSchema` - Get schema for specific models
|
|
195
|
+
|
|
196
|
+
**Document Model Agent:**
|
|
197
|
+
A specialized AI agent that guides users through document model creation with requirements gathering, design confirmation, and implementation including state schema definition, operation creation, and code generation.
|
|
198
|
+
|
|
199
|
+
</details>
|
|
159
200
|
|
|
160
201
|
|
|
161
202
|
### 3. Vetra Studio Package Creation Workflow
|
|
@@ -211,3 +252,4 @@ Support for:
|
|
|
211
252
|
- Verify implementation details in generated code before continuing.
|
|
212
253
|
- Always double-check proposed next actions
|
|
213
254
|
|
|
255
|
+
|