taskai-cli 1.4.3__tar.gz → 1.5.2__tar.gz

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.
Files changed (38) hide show
  1. {taskai_cli-1.4.3 → taskai_cli-1.5.2}/.gitignore +1 -0
  2. taskai_cli-1.5.2/.readthedocs.yaml +13 -0
  3. taskai_cli-1.5.2/DEVLOG.md +558 -0
  4. taskai_cli-1.5.2/DEVPLAN.md +402 -0
  5. taskai_cli-1.5.2/PKG-INFO +136 -0
  6. taskai_cli-1.5.2/README.md +123 -0
  7. taskai_cli-1.5.2/docs/conf.py +12 -0
  8. taskai_cli-1.5.2/docs/index.rst +8 -0
  9. taskai_cli-1.5.2/docs/requirements.txt +3 -0
  10. {taskai_cli-1.4.3 → taskai_cli-1.5.2}/pyproject.toml +4 -2
  11. taskai_cli-1.5.2/taskai/browser.py +78 -0
  12. {taskai_cli-1.4.3 → taskai_cli-1.5.2}/taskai/cli.py +79 -81
  13. taskai_cli-1.5.2/taskai/help_menu.py +68 -0
  14. {taskai_cli-1.4.3 → taskai_cli-1.5.2}/taskai/services/ai.py +42 -13
  15. taskai_cli-1.5.2/taskai/static/canvas.js +543 -0
  16. taskai_cli-1.5.2/taskai/static/console.js +53 -0
  17. taskai_cli-1.5.2/taskai/static/editpanel.js +171 -0
  18. taskai_cli-1.5.2/taskai/static/index.html +38 -0
  19. taskai_cli-1.5.2/taskai/static/style.css +220 -0
  20. {taskai_cli-1.4.3 → taskai_cli-1.5.2}/taskai/views.py +21 -7
  21. taskai_cli-1.4.3/DEVLOG.md +0 -390
  22. taskai_cli-1.4.3/PKG-INFO +0 -61
  23. taskai_cli-1.4.3/README.md +0 -50
  24. taskai_cli-1.4.3/docs/index.md +0 -17
  25. taskai_cli-1.4.3/mkdocs.yml +0 -1
  26. taskai_cli-1.4.3/taskai/help_menu.py +0 -35
  27. {taskai_cli-1.4.3 → taskai_cli-1.5.2}/.github/workflows/publish-to-pypi.yml +0 -0
  28. {taskai_cli-1.4.3 → taskai_cli-1.5.2}/scripts/bump_version.py +0 -0
  29. {taskai_cli-1.4.3 → taskai_cli-1.5.2}/taskai/config.py +0 -0
  30. {taskai_cli-1.4.3 → taskai_cli-1.5.2}/taskai/json_dir_database.py +0 -0
  31. {taskai_cli-1.4.3 → taskai_cli-1.5.2}/taskai/models.py +0 -0
  32. {taskai_cli-1.4.3 → taskai_cli-1.5.2}/taskai/services/pomodoro.py +0 -0
  33. {taskai_cli-1.4.3 → taskai_cli-1.5.2}/taskai/services/repair_database.py +0 -0
  34. {taskai_cli-1.4.3 → taskai_cli-1.5.2}/taskai/services/user_setup.py +0 -0
  35. {taskai_cli-1.4.3 → taskai_cli-1.5.2}/test/test_cli.py +0 -0
  36. {taskai_cli-1.4.3 → taskai_cli-1.5.2}/test/test_execution.py +0 -0
  37. {taskai_cli-1.4.3 → taskai_cli-1.5.2}/test/test_json_dir_database.py +0 -0
  38. {taskai_cli-1.4.3 → taskai_cli-1.5.2}/test/test_view.py +0 -0
@@ -17,3 +17,4 @@ _tmp_database_dir/
17
17
  .dev
18
18
  .prod
19
19
  *.swo
20
+ .*env
@@ -0,0 +1,13 @@
1
+ version: 2
2
+
3
+ build:
4
+ os: ubuntu-22.04
5
+ tools:
6
+ python: "3.12"
7
+
8
+ sphinx:
9
+ configuration: docs/conf.py
10
+
11
+ python:
12
+ install:
13
+ - requirements: docs/requirements.txt
@@ -0,0 +1,558 @@
1
+ # 8-18
2
+
3
+ Continued the browser/`canvas.js` work in a later session (DEVLOG is a
4
+ stack now — newest first within a date — so this sits above the earlier
5
+ entries from today):
6
+
7
+ - Console got wired up for real: `POST /api/command` now exists in
8
+ `browser.py` (design: branch on whether the parsed command is `show` —
9
+ `show` never touches `execute_commands`, it's read-only from the
10
+ browser's perspective, it just resolves a target id and returns it as
11
+ `focus` for the frontend to `focusOnNode` on; everything else runs
12
+ through `execute_commands` with stdout captured, always returning the
13
+ fresh full tree). Found a real landmine while building it:
14
+ `Controller.throw_error` calls `sys.exit(-1)`, raising `SystemExit`,
15
+ which `execute_commands`'s own `except Exception` doesn't catch — any
16
+ bad console command would've thrown that straight through the request
17
+ handler. Caught at the server boundary only, `cli.py` untouched. Console
18
+ input now actually POSTs, echoes output, and applies the returned tree.
19
+ - Node labels now wrap up to 3 lines before truncating (was single-line
20
+ truncate only) — `wrapText` in `canvas.js`, refactored `fitText`'s
21
+ trimming logic into a shared `truncateWithEllipsis` helper.
22
+ - `completed` items get a soft green fill/border
23
+ (`STYLE.colors.nodeFill/BorderDone`). Each node also shows its id
24
+ (top-left, small muted gray) and, when set, its `status` (top-right,
25
+ small warm orange, ellipsis-truncated if it'd collide with the id).
26
+ - Tuned double-click focus after it read as too aggressive: scale down
27
+ 1.4 → 0.85 (settles slightly zoomed *out*, not in), and it no longer
28
+ centers vertically — lands at 20% down from the top
29
+ (`STYLE.zoom.focusYRatio`) so there's room below to see a focused node's
30
+ children.
31
+ - Built the edit panel (right-side, collapsible, `editpanel.js` +
32
+ `.edit-panel` in `style.css`): collapsed is just a bare `44px` chevron
33
+ button pinned to its own top-left corner (no visible bar), expanded is a
34
+ `320px` white panel. Toggling animates the canvas's width/pan/zoom in
35
+ step with the panel's own 200ms CSS transition (`setRightPanelWidth` in
36
+ `canvas.js`), rescaling zoom in proportion to the width change (not just
37
+ re-panning) so the same amount of graph stays in view instead of getting
38
+ cropped. This required adding real click-to-select on the DAG first
39
+ (`selectedNode` in `canvas.js`, persistent blue border, re-resolved by
40
+ id after every tree refresh so it doesn't silently dangle) — the edit
41
+ panel piggybacks off that selection.
42
+ - Edit panel form: `name`, `description`, `status`, `priority`, `due_by`,
43
+ `completed`, `dependency_ids` ("Depends on"), each typed to match its
44
+ data (text/textarea/number/date/checkbox). No Save button — deliberate:
45
+ every field POSTs `update <id> --<field> <value>` to `/api/command`
46
+ directly. Checkbox sends immediately; everything else debounces 1s per
47
+ field (keyed by item+field) so typing doesn't spam a request per
48
+ keystroke.
49
+ - Confirmed against a throwaway test item (created + deleted, not real
50
+ data) that `name`/`description`/`priority`/`completed` all update
51
+ correctly end to end. `due_by` and `depends_on` don't — both trace to
52
+ `Controller.update_item` never calling `_parse_item_kwargs` the way
53
+ `create_item` does, so `due_by` throws a validation error and
54
+ `depends_on` silently no-ops. Documented in DEVPLAN's known quirks,
55
+ left unfixed on purpose (explicit call: wire the endpoint first, fix
56
+ bugs later).
57
+
58
+ Phase 1 status per the updated DEVPLAN checklist: only dependency/link
59
+ edges (1.4) and console up-arrow history (1.6) remain open. Everything
60
+ else in Phase 1 — tree render, pan/zoom, click-to-select, completed/status
61
+ display, the command endpoint, the edit panel, the console — is done.
62
+
63
+ ---
64
+
65
+ Working with Claude this session. Started a DEVPLAN.md with a roadmap
66
+ (Phase 0: bugfixes, Phase 1: browser UI, Phase 2: AI/aisuite rewrite,
67
+ Phase 3: polish) plus ground rules for how we want to work together.
68
+
69
+ Phase 0 (bugfixes), done:
70
+ - ai.py: the natural-language prompt was being built (with the command
71
+ grammar + task tree baked in) but the actual LLM call sent the raw
72
+ un-instructed prompt instead - fixed.
73
+ - ai.py: `_add_info` (used to build the task-tree context for the AI
74
+ prompt) referenced the wrong loop variable and would throw on the first
75
+ recursive call - fixed.
76
+ - ai.py: the natural-language service parsed the LLM's JSON command list
77
+ but never actually ran it - now it executes each parsed command through
78
+ `execute_commands`, same dispatcher the CLI uses.
79
+ - cli.py: `execute_commands` had a `raise e` ahead of the friendly
80
+ `throw_error` path, so errors always came out as raw tracebacks - removed.
81
+ - views.py: `view_item`/`view_items` called `db.read`/`db.items`, which
82
+ don't exist on `JsonDirectoryDatabase` - fixed to `get_item`/
83
+ `get_item_ids`. Also found and fixed a second bug on the same path:
84
+ `view_items` was passing the whole `TodoItem` object into `view_item`
85
+ instead of its `.id`.
86
+
87
+ Also did a pass on help_menu.py and the AI prompt in ai.py:
88
+ - help_menu.py's command reference was stale (referenced commands/syntax
89
+ that don't exist, missing others that do) - rewrote it to match
90
+ `execute_commands` exactly, including which commands need an id vs.
91
+ accept a name, and the `--field` table that wasn't documented anywhere.
92
+ - Added explicit rules to the AI prompt about not referencing items that
93
+ don't exist yet (create it first), preferring ids over names for the
94
+ commands that need them, and not inventing commands/fields.
95
+ - Removed "list" as a separate concept from both docs - it's a generic
96
+ item tree now. Clarified `create` = new root item, `add` = child of an
97
+ *existing* parent only.
98
+
99
+ Found (not fixed, tracked in DEVPLAN's "known quirks"): `update_item`
100
+ resolves a name to a model object but never unwraps `.id` before handing
101
+ it to the db layer, so `update`/`rename`/`status` only work with numeric
102
+ ids, not names.
103
+
104
+ Browser phase, started on the `browser` branch:
105
+ Already had FastAPI + uvicorn wired up (`task browser` -> launches
106
+ uvicorn on taskai.browser:app) and a canvas.js proof-of-concept
107
+ (hardcoded fake tree, circle nodes, click/hover hit-testing) from an
108
+ earlier session. Decided to build on that instead of the stdlib
109
+ http.server + SVG that DEVPLAN originally sketched, since it already ran
110
+ end to end. Wired it to real data:
111
+ - browser.py: added `GET /api/tree`, reusing the db connection already
112
+ established by importing `taskai.cli` (no second connection).
113
+ - canvas.js: replaced the hardcoded fake tree with `loadTree()`, which
114
+ fetches `/api/tree`, builds the real node tree from `parent_id`/
115
+ `child_ids`, and lays it out with a simple depth-first layout (y from
116
+ depth, x from a running leaf counter, parents centered over children).
117
+ Handles a forest of root items, not just a single root.
118
+ - Verified end to end against the real dev database.
119
+
120
+ Still open for Phase 1: the `/api/command` mutation endpoint, the edit
121
+ menu, the console panel, dependency/link edges, pan/zoom, node coloring.
122
+ Nothing there yet beyond the read-only tree render.
123
+
124
+ DEVPLAN.md now has a full "Project overview" section prepended (data
125
+ model, storage, CLI dispatch, known quirks, dev environment, etc.) so a
126
+ fresh session doesn't need to re-derive all of this by reading the whole
127
+ codebase. Also added a ground rule to keep this DEVLOG updated going
128
+ forward.
129
+
130
+ Kept going on the DAG view (`canvas.js`) in the same session, testing
131
+ live against `task browser` running throughout:
132
+ - Labels no longer overflow the node: truncated with an ellipsis to fit,
133
+ full label shown in a tooltip on hover. Hover also now visibly
134
+ highlights the node — previously tracked but had no effect.
135
+ - Added pan (drag) and zoom (wheel, zooms toward the cursor) via a `view`
136
+ {offsetX, offsetY, scale} object and canvas context transforms, not SVG
137
+ `viewBox` — same reasoning as the earlier canvas-not-SVG call. A drag
138
+ past a small threshold suppresses the trailing click so panning across
139
+ a node doesn't also fire its click handler.
140
+ - Added double-click a node to ease the view to center + zoom on it
141
+ (`focusOnNode`, ease-out cubic, ~250ms). Note: this is *not* the edit
142
+ menu trigger — double-click is now spoken for by center/zoom, so 1.5's
143
+ edit menu will open off a single-click "selected node" instead (that
144
+ selection state doesn't exist yet; today click only `console.log`s).
145
+ - Reworked the whole visual style: nodes went from small fixed circles to
146
+ much larger rounded squares (currently 160 world units), sized so
147
+ normal-length labels fit without truncating. Pulled every visual knob
148
+ (colors, node size/shape/font, spacing, zoom bounds, tooltip) out into
149
+ a `STYLE` config object at the top of `canvas.js` — deliberately plain
150
+ data, no functions, so it can later be swapped for a `GET /api/style`
151
+ response instead of hardcoded constants. Went through two style passes
152
+ with Alex: first a dark "sleek/modern" theme, then a full swap to a
153
+ TickTick-inspired light theme (off-white canvas, flat white node cards,
154
+ soft low-opacity shadow instead of a heavy one, blue accent on
155
+ hover/select, system font stack). Also made the canvas fill the
156
+ viewport (was a fixed 800x800 box) with a resize listener.
157
+ - Widened spacing to match the bigger nodes: sibling/parent-child spacing
158
+ up from 90/100 to 230/230, plus a dedicated extra gap (`treeGap`, 260)
159
+ inserted only *between* separate root trees in the forest, not between
160
+ siblings within one tree. Zoom's lower bound dropped 0.2 → 0.1 so a
161
+ bigger graph can still be zoomed out to fit; upper bound stayed at 4.
162
+
163
+ Still open for Phase 1, per the updated checklist in DEVPLAN.md: click-
164
+ to-select (persisted selection, needed before the edit menu can piggyback
165
+ off it), dependency/link edges, node coloring by status/completed, the
166
+ `/api/command` mutation endpoint, the edit menu itself, and the console
167
+ panel.
168
+
169
+ # 6-25
170
+
171
+ Alright let's start to think a bit about how I want to handle the pomo service.
172
+
173
+ task pomo 25 3
174
+
175
+
176
+ Let's start with spawning the timer, and then we can worry about logging and shit.
177
+
178
+ Pomo should spawn a process and write a log to a database. The process
179
+ should continuously monitor that log and see "am I active?"
180
+ - if so, it keeps running
181
+ - if not, we prompt the user for what they want to do?
182
+ - rest/reset/cancel
183
+ do I need this to be serialized even? maybe not if I'm just starting - we can start pomo in another thread (or just the same thread)
184
+
185
+ Yeah let's honestly not even worry about the multiprocessing part of it right now.
186
+
187
+ Let's just enter a loop and count down, while I keep clearing the screen
188
+
189
+ I need to figure out how to make it play a bell or have a screen pop up (if it's running in the background)
190
+
191
+ # 6-20
192
+
193
+ Let's think critically about what i want this API to lookk like. How should be people be
194
+ using the CLI?
195
+
196
+
197
+ task create {name} {**kwargs} -> create an item
198
+ task add {parent_id} ... -> create an item as a child
199
+ task show all
200
+ task show {id}
201
+
202
+
203
+
204
+ # 6-19
205
+
206
+ Really this whole thing should just be a tree abstraction, and I should have a root node class
207
+ and just built a tree database with some attrs depending on the type
208
+
209
+ idk why i'm being a dipshit
210
+ But that's gonna be the next iteration
211
+
212
+ # 6-18
213
+
214
+ Everything is fucked up anyways lol so might as qweell make some decisions about
215
+ the best way to do the database
216
+
217
+
218
+
219
+ ```python
220
+ class DB:
221
+
222
+ def get_item(id: int) -> TodoItem:
223
+ def get_comment(id: int) -> Comment:
224
+ def get_config() -> CLIConfig:
225
+ def create_item(name: str, parent: Optional[TodoItem]=None, ...) -> str:
226
+ def create_comment(content: str, parent: TodoItem) -> str:
227
+ def delete_item(name: str) -> bool:
228
+ def delete_comment(name: str) -> bool:
229
+ def update_item(id_: int, kwargs) -> bool:
230
+ def update_comment(id_: int, kwargs) -> bool:
231
+ def update_config(kwargs) -> bool:
232
+
233
+ def connect():
234
+ pass
235
+ def commit():
236
+ pass
237
+ def validate():
238
+ pass
239
+
240
+ ```
241
+
242
+ Important factors:
243
+ - do i want to serialize/deserialize every record twice? probably not
244
+ - so let's make sure that everything is read-only
245
+
246
+ How do i want to handle parentage?
247
+ i could:
248
+ - do it at the client level i.e. make sure to call (add parent)
249
+ - do it at the db level i.e. on every create, update, and delete method, validate
250
+
251
+ Let's do it at the db level - i want the database to be responsible for ensuring data
252
+ validation so I don't have to worry about it when I'm writing code downstream
253
+
254
+
255
+ # 6-17
256
+
257
+ Alright I find myself needing to make some design decisions about hierarchical lists.
258
+
259
+ I could:
260
+ - differentiate between child items and child lists, and have items only be leaf nodes
261
+ pros:
262
+ cons:
263
+ - treat everything as a single "item" and simply due away with the concept of lists as a
264
+ separate data point
265
+ - still distinguish between the two but treat them all as child ids - useful for sorting
266
+
267
+ Looking at it, i see no good reason to distinguish between items and lists - it complicates the
268
+ code without adding any additional functionality. There is nothing that a list does that an item
269
+ can't do apart from be a container, and there's no reason why an item can't also be a container.
270
+
271
+ So let's just go ahead and implement that change.
272
+
273
+
274
+ # 6-14
275
+
276
+ Damn it's been a productive couple of weeks. App is deployed on PyPi and I'm starting to think
277
+ a bit more about phase 2, how to rewrite it for ultimate success. What I'm thinking is that
278
+ things like help, argument patterns, and service logics should be bundled into one unit -
279
+
280
+ the core infrastructure should basically load all of the services in the config, and pull their
281
+ argument pattern matching, help menus, etc. That way, the core of the app just works as a dispatcher
282
+
283
+ Things I need to have clearly in mind before I start rearchitecting:
284
+ - How i'm going to handle modularity and reuse for major components
285
+ - How i'm going to handle multiple threads and processes
286
+ - a note on this - i'm leaning towards having a core metadata file that just keeps track
287
+ of all processes, that we just read/write to (with some sort of locking mechanism). That
288
+ will maintain process ids and any other shared state
289
+
290
+ But before all that good stuff, let's take what we have and polish the hell out of it
291
+
292
+
293
+ Also, as I'm doing this, it's becoming clear to me that I need to have records be a bit
294
+ more object oriented, as the number of different interactions that have to take place is
295
+ getting more and more annoying to keep track of and the best place for everything to be
296
+ put would be as methods on the objects, i.e. "item.updateList()", etc.
297
+
298
+
299
+ # 6-3
300
+
301
+ Alright so how are comments gonna look here:
302
+
303
+ ```
304
+ Name:
305
+ Due By:
306
+ Description:
307
+ Depends On:
308
+ Comments
309
+
310
+ ```
311
+
312
+
313
+ Let's think about what this cli refactor is gonna look like:
314
+
315
+
316
+ arg
317
+ arg
318
+ ...
319
+ endpoint, *args, **kwargs
320
+
321
+
322
+
323
+ # 5-28
324
+
325
+ A couple things that I need to deal with:
326
+ - recursive deletes (so deleting hierarchical items)
327
+ - recursive completes
328
+ - better recurrence strategies
329
+ - how to deal with linking tasks that are recurrence of the same task
330
+ - database server
331
+
332
+ # 5-27
333
+
334
+ Let's think about this cli:
335
+
336
+ what do i want to be able to do?
337
+
338
+
339
+
340
+
341
+ - task add item|list|comment
342
+ - task show item|list|comment
343
+ - task complete {id}
344
+ - task delete {id}
345
+ - task {id} depends_on {id}
346
+ - task dependency_chain
347
+
348
+
349
+ - task {id} delete|done|show|edit
350
+
351
+
352
+ Let's start with some views
353
+
354
+ need to have recursive delete for lists
355
+
356
+ # 5-26
357
+
358
+ What can I build right now?
359
+
360
+ I want to have a basic CLI version of what I want. So we can use a pickle database,
361
+ define our models, and add the basic functionality to the core business logic.
362
+
363
+
364
+ How can we design this?
365
+
366
+ - I could have a core app session that is built through some composition
367
+ - for different concurrent users, we could spin up different processes?
368
+ - why don't I worry about scaling when it comes time to scale, let's just build osmething cool and useful right now
369
+
370
+ - So we have the app session object, and we can spin it up:
371
+ - on startup
372
+ - connect to a database
373
+ - call methods to perform the actions we care about
374
+ - commit changes as we want
375
+ OR
376
+ - have a plugin architecture where we can add views/operations that take in the session object
377
+ - on exit
378
+
379
+ CLI version
380
+ - do I want it to run in the background and communicate via pipes?
381
+ - feels like that falls under premature optimization, maybe just try running everything at once to start
382
+ - though that could be fun? maybe next start
383
+ - maybe not a pickle database, can do a local folder json database
384
+
385
+
386
+
387
+ so:
388
+ Session:
389
+ def __init__(
390
+ user: User,
391
+ database: Database
392
+ )
393
+
394
+ def on_exit():
395
+ ...
396
+
397
+ cli/
398
+ views/ --> views of the core data
399
+ services/ --> core business operations we can perform
400
+ cli.py
401
+
402
+
403
+
404
+
405
+
406
+
407
+
408
+
409
+
410
+
411
+
412
+ # 5-11
413
+
414
+ Alright let's think about backend
415
+
416
+ What is the point of this app? What do I want to be able to support?
417
+ -
418
+
419
+
420
+
421
+ # 4-29
422
+
423
+ Alright let's think about frontend:
424
+
425
+ - Login Page:
426
+ - Page 1: login
427
+ - if logged in, show main
428
+
429
+ - Main Page
430
+ - SideBar
431
+ - MainPanel
432
+ - MainPanelOptions
433
+
434
+ - TodoPanel
435
+ - EditPanel
436
+ - CanvasPanel
437
+
438
+
439
+ What I want to do:
440
+ - build the threads part
441
+ - build the login and user context part
442
+ - build the database backend interactions
443
+ - build the canvas part
444
+
445
+
446
+ How do I want to handle components?
447
+
448
+ Brainstorm:
449
+ - I could construct a component tree
450
+ - each component could have a render call? Or just be called in its constructor, so when you instantiate
451
+ it, it shows up
452
+ - I want to have statically defined models so that I don't have to reconstitute things (since that's a pain)
453
+
454
+
455
+
456
+ Alright yeah, components can also have a commit-esque method (although maybe that's case by case) where I
457
+ commit their data
458
+
459
+ In that sense, I don't even really need to predefine my HTML - I can just generate it on the fly and have my core
460
+ div structure be defined
461
+
462
+
463
+ So what would that look like?
464
+
465
+ <LoginForm>
466
+ <Main>
467
+ <div> flex-col
468
+ <TopPanel>
469
+
470
+ <div> flex-row
471
+ <SideBar>
472
+ <TodoPanel>
473
+ <EditPanel>
474
+ <CanvasPanel>
475
+
476
+ <footer>
477
+
478
+
479
+
480
+ I can just have so many classes:
481
+ components/
482
+ loginForm.js
483
+ sidebar.js
484
+ todopanel.js
485
+ editpanel.js
486
+ canvaspanel.js
487
+
488
+ lib/
489
+ component.js
490
+ database.js
491
+ utils.js
492
+
493
+
494
+ Alright let's start to sketch these out:
495
+
496
+ We have our base:
497
+
498
+
499
+ class Component extends HTMLComponent{
500
+
501
+ db attribute
502
+ state attribute
503
+
504
+ constructor (
505
+ super()
506
+ const shadow = this.attachShadow({mode: 'open'})
507
+ customElements.define(this.constructor.name, this.constructor)
508
+ )
509
+ }
510
+
511
+
512
+ class LoginForm extends Component {
513
+ constructor(
514
+ super()
515
+
516
+
517
+
518
+
519
+ )
520
+ }
521
+
522
+
523
+
524
+
525
+
526
+
527
+
528
+
529
+
530
+
531
+
532
+ # 4-27
533
+
534
+
535
+ Alright sick progress, I'm in the process of populating the database. Now I need to:
536
+ - write the startup() method that pulls lists from the database and populates them in the sidebar
537
+ ---> I'll put the populateDb method in there for now
538
+
539
+ - write the callback so that when I click on a list, it pulls its id from the database
540
+ - write the rendering functions so that the todo-list-panel renders the todos for the selected list
541
+
542
+
543
+ # 4-26
544
+
545
+ What do I want to add?
546
+
547
+ Pages:
548
+ - login page
549
+ - Main Page
550
+
551
+
552
+ # Features that I want to add
553
+
554
+ - Pop Up Card Editing
555
+ - Comments
556
+ - Text CLI
557
+ - Dockerize
558
+ -