@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,422 +0,0 @@
|
|
|
1
|
-
# Step 5 — Implement `TodoList` document editor UI components
|
|
2
|
-
|
|
3
|
-
Out of the box, we have a component for updating our `TodoList` documents' names, but we would like to create, read, update, and delete all of the data in our documents.
|
|
4
|
-
|
|
5
|
-
## Add a component for showing our todo list in the document editor
|
|
6
|
-
|
|
7
|
-
Let's start by adding a `<TodoList />` component that will be the main container we show when you open a TodoList document.
|
|
8
|
-
|
|
9
|
-
Create a new file at `editors/todo-list-editor/components/TodoList.tsx` and add this:
|
|
10
|
-
|
|
11
|
-
```jsx
|
|
12
|
-
import { useSelectedTodoListDocument } from "todo-tutorial/document-models/todo-list";
|
|
13
|
-
import { EditTodoListName } from "./EditName.js";
|
|
14
|
-
|
|
15
|
-
/** Displays the selected todo list */
|
|
16
|
-
export function TodoList() {
|
|
17
|
-
// this hook returns the currently selected TodoList document
|
|
18
|
-
const [selectedTodoList] = useSelectedTodoListDocument();
|
|
19
|
-
|
|
20
|
-
if (!selectedTodoList) return null;
|
|
21
|
-
|
|
22
|
-
return (
|
|
23
|
-
<div>
|
|
24
|
-
<EditTodoListName />
|
|
25
|
-
<pre>
|
|
26
|
-
{JSON.stringify(selectedTodoListDocument)}
|
|
27
|
-
</pre>
|
|
28
|
-
</div>
|
|
29
|
-
);
|
|
30
|
-
}
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
We've moved the `<EditTodoListName />` component here, so replace it in `editors/todo-list-editor/editor.tsx` with this component we just created.
|
|
34
|
-
|
|
35
|
-
```tsx
|
|
36
|
-
// removed-line
|
|
37
|
-
import { EditTodoListName } from "./components/EditName.js";
|
|
38
|
-
// added-line
|
|
39
|
-
import { TodoList } from "./components/TodoList.js";
|
|
40
|
-
|
|
41
|
-
export default function Editor() {
|
|
42
|
-
return (
|
|
43
|
-
<div className="py-4 px-8">
|
|
44
|
-
// removed-line
|
|
45
|
-
<EditTodoListName />
|
|
46
|
-
// added-line
|
|
47
|
-
<TodoList />
|
|
48
|
-
</div>
|
|
49
|
-
);
|
|
50
|
-
}
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
Now when you open a TodoList document in Connect, you will see an (albeit ugly for now) representation of your whole document in JSON.
|
|
54
|
-
|
|
55
|
-
## Add a component for adding todo items to a todo list
|
|
56
|
-
|
|
57
|
-
Next, let's add a component for adding todos to a todo list.
|
|
58
|
-
|
|
59
|
-
Create a new file at `editors/todo-list-editor/components/AddTodo.tsx` and add this to it:
|
|
60
|
-
|
|
61
|
-
```jsx
|
|
62
|
-
import type { FormEventHandler } from "react";
|
|
63
|
-
import { addTodoItem } from "todo-tutorial/document-models/todo-list";
|
|
64
|
-
import { useSelectedTodoListDocument } from "todo-tutorial/document-models/todo-list";
|
|
65
|
-
|
|
66
|
-
export function AddTodo() {
|
|
67
|
-
// The hooks for getting documents also return a dispatch function for dispatching actions to modify the document.
|
|
68
|
-
|
|
69
|
-
// This is the same pattern you will have seen in React's `useReducer` hook, except you don't need to pass the initial state.
|
|
70
|
-
|
|
71
|
-
// The document we are working with _is_ the initial state.
|
|
72
|
-
const [todoList, dispatch] = useSelectedTodoListDocument();
|
|
73
|
-
|
|
74
|
-
if (!todoList) return null;
|
|
75
|
-
|
|
76
|
-
const onSubmitAddTodo: FormEventHandler<HTMLFormElement> = (event) => {
|
|
77
|
-
event.preventDefault();
|
|
78
|
-
|
|
79
|
-
const form = event.currentTarget;
|
|
80
|
-
const addTodoInput = form.elements.namedItem("addTodo") as HTMLInputElement;
|
|
81
|
-
const text = addTodoInput.value;
|
|
82
|
-
if (!text) return;
|
|
83
|
-
|
|
84
|
-
dispatch(addTodoItem({ text }));
|
|
85
|
-
|
|
86
|
-
form.reset();
|
|
87
|
-
};
|
|
88
|
-
|
|
89
|
-
return (
|
|
90
|
-
<form onSubmit={onSubmitAddTodo} className="flex mx-auto min-w-fit gap-2">
|
|
91
|
-
<input
|
|
92
|
-
className="py-1 px-2 grow min-w-fit placeholder:text-gray-600 rounded border border-gray-600 text-gray-800"
|
|
93
|
-
type="text"
|
|
94
|
-
name="addTodo"
|
|
95
|
-
placeholder="What needs to be done?"
|
|
96
|
-
autoFocus
|
|
97
|
-
/>
|
|
98
|
-
<button
|
|
99
|
-
type="submit"
|
|
100
|
-
className="text-gray-600 rounded border border-gray-600 px-3 py-1"
|
|
101
|
-
>
|
|
102
|
-
Add
|
|
103
|
-
</button>
|
|
104
|
-
</form>
|
|
105
|
-
);
|
|
106
|
-
}
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
We have provided some basic Tailwind styles but you are welcome to style your components however you wish. This hooks and functions also work with other component libraries like Radix etc.
|
|
110
|
-
|
|
111
|
-
Let's add this component to our `<TodoList />` component.
|
|
112
|
-
|
|
113
|
-
```tsx
|
|
114
|
-
import { useSelectedTodoListDocument } from "todo-tutorial/document-models/todo-list";
|
|
115
|
-
import { EditTodoListName } from "./EditName.js";
|
|
116
|
-
// added-line
|
|
117
|
-
import { AddTodo } from "./AddTodo.js";
|
|
118
|
-
|
|
119
|
-
/** Displays the selected todo list */
|
|
120
|
-
export function TodoList() {
|
|
121
|
-
// this hook returns the currently selected TodoList document
|
|
122
|
-
const [selectedTodoList] = useSelectedTodoListDocument();
|
|
123
|
-
|
|
124
|
-
if (!selectedTodoList) return null;
|
|
125
|
-
|
|
126
|
-
return (
|
|
127
|
-
<div>
|
|
128
|
-
<EditTodoListName />
|
|
129
|
-
// added-line
|
|
130
|
-
<AddTodo />
|
|
131
|
-
<pre>
|
|
132
|
-
{JSON.stringify(selectedTodoListDocument)}
|
|
133
|
-
</pre>
|
|
134
|
-
</div>
|
|
135
|
-
);
|
|
136
|
-
}
|
|
137
|
-
```
|
|
138
|
-
|
|
139
|
-
Now when you open a TodoList document in Connect, you can add more todos.
|
|
140
|
-
|
|
141
|
-
## Add a button for closing the open `TodoList` document
|
|
142
|
-
|
|
143
|
-
Of course it's all well and good to be able to open TodoList documents, but we would also like to be able to close them.
|
|
144
|
-
|
|
145
|
-
Let's add a `<CloseButton />` component that closes the selected document when clicked.
|
|
146
|
-
|
|
147
|
-
Create a new file at `editors/todo-list-editor/components/CloseButton.tsx` and add this content:
|
|
148
|
-
|
|
149
|
-
```jsx
|
|
150
|
-
import { setSelectedNode } from "@powerhousedao/reactor-browser";
|
|
151
|
-
import type { MouseEventHandler } from "react";
|
|
152
|
-
|
|
153
|
-
/** Closes the selected todo list document editor */
|
|
154
|
-
export function CloseButton() {
|
|
155
|
-
const onCloseButtonClick: MouseEventHandler<HTMLButtonElement> = () => {
|
|
156
|
-
// this function sets the selected node in Connect.
|
|
157
|
-
// a node can be either a file or a folder, and the same function works for both.
|
|
158
|
-
// notably, this is not a hook and therefore does not need to abide by the rules of hooks.
|
|
159
|
-
setSelectedNode(undefined);
|
|
160
|
-
};
|
|
161
|
-
|
|
162
|
-
return (
|
|
163
|
-
<button onClick={onCloseButtonClick} className="text-sm text-gray-600">
|
|
164
|
-
Close
|
|
165
|
-
</button>
|
|
166
|
-
);
|
|
167
|
-
}
|
|
168
|
-
```
|
|
169
|
-
|
|
170
|
-
Let's add this component to our `<TodoList />` component:
|
|
171
|
-
|
|
172
|
-
```tsx
|
|
173
|
-
import { useSelectedTodoListDocument } from "todo-tutorial/document-models/todo-list";
|
|
174
|
-
import { EditTodoListName } from "./EditName.js";
|
|
175
|
-
import { AddTodo } from "./AddTodo.js";
|
|
176
|
-
// added-line
|
|
177
|
-
import { CloseButton } from "./CloseButton.js";
|
|
178
|
-
|
|
179
|
-
/** Displays the selected todo list */
|
|
180
|
-
export function TodoList() {
|
|
181
|
-
// this hook returns the currently selected TodoList document
|
|
182
|
-
const [selectedTodoList] = useSelectedTodoListDocument();
|
|
183
|
-
|
|
184
|
-
if (!selectedTodoList) return null;
|
|
185
|
-
|
|
186
|
-
return (
|
|
187
|
-
<div>
|
|
188
|
-
<EditTodoListName />
|
|
189
|
-
// added-line
|
|
190
|
-
<CloseButton />
|
|
191
|
-
<AddTodo />
|
|
192
|
-
<pre>
|
|
193
|
-
{JSON.stringify(selectedTodoListDocument)}
|
|
194
|
-
</pre>
|
|
195
|
-
</div>
|
|
196
|
-
);
|
|
197
|
-
}
|
|
198
|
-
```
|
|
199
|
-
|
|
200
|
-
Now you have a button you can click to close the selected document.
|
|
201
|
-
|
|
202
|
-
## Add components for todo items and the list of todo items
|
|
203
|
-
|
|
204
|
-
Finally, let's add a component for showing and editing and individual todo item in a todo list, and another one for showing the list of todo items.
|
|
205
|
-
|
|
206
|
-
Create a new file at `editors/todo-list-editor/components/Todo.tsx` and add this content:
|
|
207
|
-
|
|
208
|
-
```jsx
|
|
209
|
-
import {
|
|
210
|
-
useState,
|
|
211
|
-
type ChangeEventHandler,
|
|
212
|
-
type FormEventHandler,
|
|
213
|
-
type MouseEventHandler,
|
|
214
|
-
} from "react";
|
|
215
|
-
import {
|
|
216
|
-
deleteTodoItem,
|
|
217
|
-
updateTodoItem,
|
|
218
|
-
} from "todo-tutorial/document-models/todo-list";
|
|
219
|
-
import type { TodoItem } from "todo-tutorial/document-models/todo-list";
|
|
220
|
-
import { useSelectedTodoListDocument } from "todo-tutorial/document-models/todo-list";
|
|
221
|
-
|
|
222
|
-
type Props = {
|
|
223
|
-
todo: TodoItem;
|
|
224
|
-
};
|
|
225
|
-
/** Displays a single todo item in the selected todo list
|
|
226
|
-
*
|
|
227
|
-
* Allows checking/unchecking the todo item.
|
|
228
|
-
* Allows editing the todo item text.
|
|
229
|
-
* Allows deleting the todo item.
|
|
230
|
-
*/
|
|
231
|
-
export function Todo({ todo }: Props) {
|
|
232
|
-
const [isEditing, setIsEditing] = useState(false);
|
|
233
|
-
// even though this component is for a todo item and not a whole list, we can use the exact same hook for dispatching updates to it.
|
|
234
|
-
const [todoList, dispatch] = useSelectedTodoListDocument();
|
|
235
|
-
|
|
236
|
-
if (!todoList) return null;
|
|
237
|
-
|
|
238
|
-
const todoId = todo.id;
|
|
239
|
-
const todoText = todo.text;
|
|
240
|
-
const todoChecked = todo.checked;
|
|
241
|
-
|
|
242
|
-
const onSubmitUpdateTodoText: FormEventHandler<HTMLFormElement> = (event) => {
|
|
243
|
-
event.preventDefault();
|
|
244
|
-
|
|
245
|
-
const form = event.currentTarget;
|
|
246
|
-
const textInput = form.elements.namedItem("todoText") as HTMLInputElement;
|
|
247
|
-
const text = textInput.value;
|
|
248
|
-
if (!text) return;
|
|
249
|
-
// we can use this dispatch function for any of the actions supported by a TodoList document
|
|
250
|
-
dispatch(updateTodoItem({ id: todo.id, text }));
|
|
251
|
-
setIsEditing(false);
|
|
252
|
-
};
|
|
253
|
-
|
|
254
|
-
const onChangeTodoChecked: ChangeEventHandler<HTMLInputElement> = (event) => {
|
|
255
|
-
dispatch(
|
|
256
|
-
updateTodoItem({
|
|
257
|
-
id: todo.id,
|
|
258
|
-
checked: event.target.checked,
|
|
259
|
-
}),
|
|
260
|
-
);
|
|
261
|
-
};
|
|
262
|
-
|
|
263
|
-
const onClickDeleteTodo: MouseEventHandler<HTMLButtonElement> = () => {
|
|
264
|
-
dispatch(deleteTodoItem({ id: todoId }));
|
|
265
|
-
};
|
|
266
|
-
|
|
267
|
-
const onClickEditTodo: MouseEventHandler<HTMLButtonElement> = () => {
|
|
268
|
-
setIsEditing(true);
|
|
269
|
-
};
|
|
270
|
-
|
|
271
|
-
const onClickCancelEditTodo: MouseEventHandler<HTMLButtonElement> = () => {
|
|
272
|
-
setIsEditing(false);
|
|
273
|
-
};
|
|
274
|
-
|
|
275
|
-
if (isEditing)
|
|
276
|
-
return (
|
|
277
|
-
<form
|
|
278
|
-
className="flex gap-2 items-center justify-between"
|
|
279
|
-
onSubmit={onSubmitUpdateTodoText}
|
|
280
|
-
>
|
|
281
|
-
<input
|
|
282
|
-
className="p-1 grow"
|
|
283
|
-
type="text"
|
|
284
|
-
name="todoText"
|
|
285
|
-
defaultValue={todoText}
|
|
286
|
-
autoFocus
|
|
287
|
-
/>
|
|
288
|
-
<div className="flex gap-2 grow-0">
|
|
289
|
-
<button type="submit" className="text-sm text-gray-600">
|
|
290
|
-
Save
|
|
291
|
-
</button>
|
|
292
|
-
<button
|
|
293
|
-
className="text-sm text-red-800"
|
|
294
|
-
onClick={onClickCancelEditTodo}
|
|
295
|
-
>
|
|
296
|
-
Cancel
|
|
297
|
-
</button>
|
|
298
|
-
</div>
|
|
299
|
-
</form>
|
|
300
|
-
);
|
|
301
|
-
|
|
302
|
-
return (
|
|
303
|
-
<div className="flex justify-between items-center">
|
|
304
|
-
<div className="flex items-center gap-2 p-1">
|
|
305
|
-
<input
|
|
306
|
-
type="checkbox"
|
|
307
|
-
checked={todoChecked}
|
|
308
|
-
onChange={onChangeTodoChecked}
|
|
309
|
-
/>
|
|
310
|
-
<span className={todoChecked ? "line-through" : ""}>{todoText}</span>
|
|
311
|
-
</div>
|
|
312
|
-
<span className="flex place-items-center gap-2 text-sm">
|
|
313
|
-
<button className="text-gray-600" onClick={onClickEditTodo}>
|
|
314
|
-
Edit
|
|
315
|
-
</button>
|
|
316
|
-
<button className="text-red-800" onClick={onClickDeleteTodo}>
|
|
317
|
-
Delete
|
|
318
|
-
</button>
|
|
319
|
-
</span>
|
|
320
|
-
</div>
|
|
321
|
-
);
|
|
322
|
-
}
|
|
323
|
-
```
|
|
324
|
-
|
|
325
|
-
Now create another new file at `editors/todo-list-document/Todos.tsx` and give it this content:
|
|
326
|
-
|
|
327
|
-
```jsx
|
|
328
|
-
import type { TodoItem } from "todo-tutorial/document-models/todo-list";
|
|
329
|
-
import { Todo } from "./Todo.js";
|
|
330
|
-
|
|
331
|
-
type Props = {
|
|
332
|
-
todos: TodoItem[];
|
|
333
|
-
};
|
|
334
|
-
|
|
335
|
-
/** Shows a list of the todo items in the selected todo list */
|
|
336
|
-
export function Todos({ todos }: Props) {
|
|
337
|
-
const hasTodos = todos.length > 0;
|
|
338
|
-
|
|
339
|
-
if (!hasTodos) {
|
|
340
|
-
return <p>Start adding things to your todo list</p>;
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
return (
|
|
344
|
-
<ul>
|
|
345
|
-
{todos.map((todo) => (
|
|
346
|
-
<li key={todo.id}>
|
|
347
|
-
<Todo todo={todo} />
|
|
348
|
-
</li>
|
|
349
|
-
))}
|
|
350
|
-
</ul>
|
|
351
|
-
);
|
|
352
|
-
}
|
|
353
|
-
```
|
|
354
|
-
|
|
355
|
-
And replace the content of your `TodoList.tsx` file with this:
|
|
356
|
-
|
|
357
|
-
```jsx
|
|
358
|
-
import { useSelectedTodoListDocument } from "todo-tutorial/document-models/todo-list";
|
|
359
|
-
import { EditTodoListName } from "./EditName.js";
|
|
360
|
-
import { Todos } from "./Todos.js";
|
|
361
|
-
import { AddTodo } from "./AddTodo.js";
|
|
362
|
-
import { CloseButton } from "./CloseButton.js";
|
|
363
|
-
|
|
364
|
-
/** Displays the selected todo list */
|
|
365
|
-
export function TodoList() {
|
|
366
|
-
const [selectedTodoList] = useSelectedTodoListDocument();
|
|
367
|
-
|
|
368
|
-
if (!selectedTodoList) return null;
|
|
369
|
-
|
|
370
|
-
const todos = selectedTodoList.state.global.items;
|
|
371
|
-
|
|
372
|
-
return (
|
|
373
|
-
<div>
|
|
374
|
-
<section className="mb-4 flex gap-2 items-center">
|
|
375
|
-
<div className="grow">
|
|
376
|
-
<EditTodoListName />
|
|
377
|
-
</div>
|
|
378
|
-
<div className="flex-none">
|
|
379
|
-
<CloseButton />
|
|
380
|
-
</div>
|
|
381
|
-
</section>
|
|
382
|
-
<section className="mb-4">
|
|
383
|
-
<Todos todos={todos} />
|
|
384
|
-
</section>
|
|
385
|
-
<section>
|
|
386
|
-
<AddTodo />
|
|
387
|
-
</section>
|
|
388
|
-
</div>
|
|
389
|
-
);
|
|
390
|
-
}
|
|
391
|
-
```
|
|
392
|
-
|
|
393
|
-
```
|
|
394
|
-
editors/todo-list-editor/
|
|
395
|
-
├── components/
|
|
396
|
-
│ └── EditName.tsx # Auto-generated component for editing document name
|
|
397
|
-
├── editor.tsx # Main editor component (do not change this)
|
|
398
|
-
└── module.ts # Editor module export (do not change this)
|
|
399
|
-
```
|
|
400
|
-
|
|
401
|
-
## Check your work
|
|
402
|
-
|
|
403
|
-
To make sure all works as expected, we should:
|
|
404
|
-
|
|
405
|
-
- check types
|
|
406
|
-
run: `pnpm tsc`
|
|
407
|
-
|
|
408
|
-
- check linting
|
|
409
|
-
run: `pnpm lint`
|
|
410
|
-
|
|
411
|
-
- check tests
|
|
412
|
-
run: `pnpm test`
|
|
413
|
-
|
|
414
|
-
- test in connect
|
|
415
|
-
run: `pnpm connect` — you should now be able to open a `TodoList` document and update all of the fields we defined in the `TodoList` document model schema
|
|
416
|
-
|
|
417
|
-
- make sure your code matches the code in the completed step branch
|
|
418
|
-
run: `git diff your-branch-name step-5-complete-added-basic-todo-list-document-editor-ui-components`
|
|
419
|
-
|
|
420
|
-
## Up next: generating a custom drive explorer for managing our `TodoList` documents
|
|
421
|
-
|
|
422
|
-
Next, we will generate a special kind of editor called a "drive editor" which we will use instead of the generic drive explorer.
|