home · contact · privacy
Add GET /todo and Todo retrieval by ID.
authorChristian Heller <c.heller@plomlompom.de>
Fri, 12 Apr 2024 20:17:25 +0000 (22:17 +0200)
committerChristian Heller <c.heller@plomlompom.de>
Fri, 12 Apr 2024 20:17:25 +0000 (22:17 +0200)
plomtask/http.py
plomtask/todos.py
scripts/init.sql
templates/day.html
tests/todos.py

index 1743b9042982dd910eff100c70ba230472c1ee1f..91c3224eb0369e81b9e146970f4b548781ecb8d4 100644 (file)
@@ -10,6 +10,7 @@ from plomtask.exceptions import HandledException, BadFormatException, \
         NotFoundException
 from plomtask.db import DatabaseConnection, DatabaseFile
 from plomtask.processes import Process
+from plomtask.todos import Todo
 
 TEMPLATES_DIR = 'templates'
 
@@ -110,7 +111,7 @@ class TaskHandler(BaseHTTPRequestHandler):
         """Handle any GET request."""
         try:
             conn, site, params = self._init_handling()
-            if site in {'calendar', 'day', 'process', 'processes'}:
+            if site in {'calendar', 'day', 'process', 'processes', 'todo'}:
                 html = getattr(self, f'do_GET_{site}')(conn, params)
             elif '' == site:
                 self._redirect('/day')
@@ -137,7 +138,18 @@ class TaskHandler(BaseHTTPRequestHandler):
         """Show single Day of ?date=."""
         date = params.get_str('date', todays_date())
         day = Day.by_date(conn, date, create=True)
-        return self.server.jinja.get_template('day.html').render(day=day)
+        todos = Todo.by_date(conn, date)
+        return self.server.jinja.get_template('day.html').render(
+                day=day, processes=Process.all(conn), todos=todos)
+
+    def do_GET_todo(self, conn: DatabaseConnection, params:
+                    ParamsParser) -> str:
+        """Show single Todo of ?id=."""
+        id_ = params.get_int_or_none('id')
+        if id_ is None:
+            raise NotFoundException('Todo of ID not found.')
+        todo = Todo.by_id(conn, id_)
+        return self.server.jinja.get_template('todo.html').render(todo=todo)
 
     def do_GET_process(self, conn: DatabaseConnection,
                        params: ParamsParser) -> str:
@@ -177,11 +189,16 @@ class TaskHandler(BaseHTTPRequestHandler):
 
     def do_POST_day(self, conn: DatabaseConnection, params: ParamsParser,
                     form_data: PostvarsParser) -> None:
-        """Update or insert Day of date and fields defined in postvars."""
+        """Update or insert Day of date and Todos mapped to it."""
         date = params.get_str('date')
         day = Day.by_date(conn, date, create=True)
         day.comment = form_data.get_str('comment')
         day.save(conn)
+        process_id = form_data.get_int_or_none('new_todo')
+        if process_id is not None:
+            process = Process.by_id(conn, process_id)
+            todo = Todo(None, process, False, day)
+            todo.save(conn)
 
     def do_POST_process(self, conn: DatabaseConnection, params: ParamsParser,
                         form_data: PostvarsParser) -> None:
index 1b6b740c97930862b8867d5229e01685713e6595..7150f0d702c44ec89e170e5381b20c8e61ea42ae 100644 (file)
@@ -28,6 +28,13 @@ class Todo:
                    is_done=row[2],
                    day=Day.by_date(db_conn, row[3]))
 
+    @classmethod
+    def by_id(cls, db_conn: DatabaseConnection, id_: int) -> Todo:
+        """Get Todo of .id_=id_."""
+        for row in db_conn.exec('SELECT * FROM todos WHERE id = ?', (id_,)):
+            return cls.from_table_row(row, db_conn)
+        raise NotFoundException(f'Todo of ID not found: {id_}')
+
     @classmethod
     def by_date(cls, db_conn: DatabaseConnection, date: str) -> list[Todo]:
         """Collect all Todos for Day of date."""
index 12450302ab084356fb2cbede95106027445c329a..6dca3729e8ef6f7408c32ecc1466d674fcaa0c41 100644 (file)
@@ -35,3 +35,11 @@ CREATE TABLE process_titles (
 CREATE TABLE processes (
     id INTEGER PRIMARY KEY
 );
+CREATE TABLE todos (
+    id INTEGER PRIMARY KEY,
+    process_id INTEGER NOT NULL,
+    is_done BOOLEAN NOT NULL,
+    day TEXT NOT NULL,
+    FOREIGN KEY (process_id) REFERENCES processes(id),
+    FOREIGN KEY (day) REFERENCES days(date)
+);
index 7a34e58544f1c93a871bc316962d2bf60040b5d2..44fd90d17f884050bd90b8231a9041d4dd3571a4 100644 (file)
@@ -7,7 +7,18 @@
 </p>
 <form action="day?date={{day.date}}" method="POST">
 comment: <input name="comment" value="{{day.comment|e}}" />
-<input type="submit" value="OK" />
+<input type="submit" value="OK" /><br />
+add todo: <input name="new_todo" list="processes" autocomplete="off" />
+<datalist id="processes">
+{% for process in processes %}
+<option value="{{process.id_}}">{{process.title.newest|e}}</option>
+{% endfor %}
+</datalist>
 </form>
+<ul>
+{% for todo in todos %}
+<li><a href="todo?id={{todo.id_}}">{{todo.process.title.newest|e}}</a>
+{% endfor %}
+</ul>
 {% endblock %}
 
index 93b34d197f33aebbd5b096619c3804ca0b8f75ce..8bcd181e97ae06348f028a5f273a00ea7c53dcb2 100644 (file)
@@ -9,20 +9,36 @@ from plomtask.exceptions import NotFoundException
 class TestsWithDB(TestCaseWithDB):
     """Tests not requiring DB setup."""
 
-    def test_Todo_by_date(self) -> None:
+    def test_Todo_by_id(self) -> None:
         """Test creation and findability of Todos."""
+        day = Day('2024-01-01')
+        process = Process(None)
+        todo = Todo(None, process, False, day)
+        with self.assertRaises(NotFoundException):
+            todo.save(self.db_conn)
+        process.save_without_steps(self.db_conn)
+        todo.save(self.db_conn)
+        with self.assertRaises(NotFoundException):
+            _ = Todo.by_id(self.db_conn, 1)
+        day.save(self.db_conn)
+        self.assertEqual(Todo.by_id(self.db_conn, 1), todo)
+        with self.assertRaises(NotFoundException):
+            self.assertEqual(Todo.by_id(self.db_conn, 0), todo)
+        with self.assertRaises(NotFoundException):
+            self.assertEqual(Todo.by_id(self.db_conn, 2), todo)
+
+    def test_Todo_by_date(self) -> None:
+        """Test findability of Todos by date."""
         day1 = Day('2024-01-01')
         day2 = Day('2024-01-02')
-        process1 = Process(None)
-        todo1 = Todo(None, process1, False, day1)
-        with self.assertRaises(NotFoundException):
-            todo1.save(self.db_conn)
-        process1.save_without_steps(self.db_conn)
+        process = Process(None)
+        process.save_without_steps(self.db_conn)
+        todo1 = Todo(None, process, False, day1)
         todo1.save(self.db_conn)
-        todo2 = Todo(None, process1, False, day1)
+        todo2 = Todo(None, process, False, day1)
         todo2.save(self.db_conn)
         with self.assertRaises(NotFoundException):
-            Todo.by_date(self.db_conn, day1.date),
+            _ = Todo.by_date(self.db_conn, day1.date)
         day1.save(self.db_conn)
         day2.save(self.db_conn)
         self.assertEqual(Todo.by_date(self.db_conn, day1.date), [todo1, todo2])
@@ -58,3 +74,15 @@ class TestsWithServer(TestCaseWithServer):
         self.assertEqual(todo1.id_, 2)
         self.assertEqual(todo1.process.id_, process2.id_)
         self.assertEqual(todo1.is_done, False)
+
+    def test_do_GET_todo(self) -> None:
+        """Test GET /todo response codes."""
+        form_data = {'title': '', 'description': '', 'effort': 1}
+        self.check_post(form_data, '/process?id=', 302, '/')
+        form_data = {'comment': '', 'new_todo': 1}
+        self.check_post(form_data, '/day?date=2024-01-01', 302, '/')
+        self.check_get('/todo', 404)
+        self.check_get('/todo?id=', 404)
+        self.check_get('/todo?id=foo', 400)
+        self.check_get('/todo?id=0', 404)
+        self.check_get('/todo?id=1', 200)