raztodo-web 0.1.0__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 (49) hide show
  1. raztodo_web-0.1.0/PKG-INFO +126 -0
  2. raztodo_web-0.1.0/README.md +100 -0
  3. raztodo_web-0.1.0/pyproject.toml +68 -0
  4. raztodo_web-0.1.0/pyproject.toml.orig +61 -0
  5. raztodo_web-0.1.0/src/raztodo_web/__init__.py +0 -0
  6. raztodo_web-0.1.0/src/raztodo_web/__main__.py +36 -0
  7. raztodo_web-0.1.0/src/raztodo_web/app/__init__.py +0 -0
  8. raztodo_web-0.1.0/src/raztodo_web/app/dependencies.py +40 -0
  9. raztodo_web-0.1.0/src/raztodo_web/app/factory.py +39 -0
  10. raztodo_web-0.1.0/src/raztodo_web/features/explain/__init__.py +0 -0
  11. raztodo_web-0.1.0/src/raztodo_web/features/explain/routes.py +42 -0
  12. raztodo_web-0.1.0/src/raztodo_web/features/tasks/helpers.py +23 -0
  13. raztodo_web-0.1.0/src/raztodo_web/features/tasks/routes.py +202 -0
  14. raztodo_web-0.1.0/src/raztodo_web/features/tasks/schemas.py +48 -0
  15. raztodo_web-0.1.0/src/raztodo_web/web/static/css/base.css +22 -0
  16. raztodo_web-0.1.0/src/raztodo_web/web/static/css/components/forms.css +216 -0
  17. raztodo_web-0.1.0/src/raztodo_web/web/static/css/components/modal.css +157 -0
  18. raztodo_web-0.1.0/src/raztodo_web/web/static/css/components/sidebar.css +88 -0
  19. raztodo_web-0.1.0/src/raztodo_web/web/static/css/components/toast.css +32 -0
  20. raztodo_web-0.1.0/src/raztodo_web/web/static/css/features/tasks.css +251 -0
  21. raztodo_web-0.1.0/src/raztodo_web/web/static/css/layout.css +79 -0
  22. raztodo_web-0.1.0/src/raztodo_web/web/static/css/responsive.css +44 -0
  23. raztodo_web-0.1.0/src/raztodo_web/web/static/css/style.css +28 -0
  24. raztodo_web-0.1.0/src/raztodo_web/web/static/css/theme.css +90 -0
  25. raztodo_web-0.1.0/src/raztodo_web/web/static/css/tokens.css +59 -0
  26. raztodo_web-0.1.0/src/raztodo_web/web/static/img/export.svg +1 -0
  27. raztodo_web-0.1.0/src/raztodo_web/web/static/img/favicon.ico +0 -0
  28. raztodo_web-0.1.0/src/raztodo_web/web/static/img/import.svg +1 -0
  29. raztodo_web-0.1.0/src/raztodo_web/web/static/img/search.svg +1 -0
  30. raztodo_web-0.1.0/src/raztodo_web/web/static/img/trash.svg +1 -0
  31. raztodo_web-0.1.0/src/raztodo_web/web/static/js/app.js +11 -0
  32. raztodo_web-0.1.0/src/raztodo_web/web/static/js/explain/index.js +19 -0
  33. raztodo_web-0.1.0/src/raztodo_web/web/static/js/explain/modal.js +111 -0
  34. raztodo_web-0.1.0/src/raztodo_web/web/static/js/shared/api.js +13 -0
  35. raztodo_web-0.1.0/src/raztodo_web/web/static/js/shared/priority.js +94 -0
  36. raztodo_web-0.1.0/src/raztodo_web/web/static/js/shared/state.js +12 -0
  37. raztodo_web-0.1.0/src/raztodo_web/web/static/js/shared/theme.js +30 -0
  38. raztodo_web-0.1.0/src/raztodo_web/web/static/js/shared/toast.js +23 -0
  39. raztodo_web-0.1.0/src/raztodo_web/web/static/js/tasks/actions.js +142 -0
  40. raztodo_web-0.1.0/src/raztodo_web/web/static/js/tasks/edit.js +55 -0
  41. raztodo_web-0.1.0/src/raztodo_web/web/static/js/tasks/index.js +70 -0
  42. raztodo_web-0.1.0/src/raztodo_web/web/static/js/tasks/render.js +143 -0
  43. raztodo_web-0.1.0/src/raztodo_web/web/templates/index.html +49 -0
  44. raztodo_web-0.1.0/src/raztodo_web/web/templates/partials/_explain_modal.html +20 -0
  45. raztodo_web-0.1.0/src/raztodo_web/web/templates/partials/_main_header.html +18 -0
  46. raztodo_web-0.1.0/src/raztodo_web/web/templates/partials/_sidebar_new_task.html +70 -0
  47. raztodo_web-0.1.0/src/raztodo_web/web/templates/partials/_sidebar_search.html +27 -0
  48. raztodo_web-0.1.0/src/raztodo_web/web/templates/partials/_sidebar_tools.html +41 -0
  49. raztodo_web-0.1.0/src/raztodo_web/web/templates/partials/_toast.html +1 -0
@@ -0,0 +1,126 @@
1
+ Metadata-Version: 2.4
2
+ Name: raztodo-web
3
+ Version: 0.1.0
4
+ Summary: Web UI for RazTodo
5
+ Keywords: raztodo,web-ui,fastapi,task-manager,local-first
6
+ License-Expression: MIT
7
+ Classifier: Development Status :: 4 - Beta
8
+ Classifier: Intended Audience :: Developers
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Programming Language :: Python :: 3.10
11
+ Classifier: Programming Language :: Python :: 3.11
12
+ Classifier: Programming Language :: Python :: 3.12
13
+ Classifier: Programming Language :: Python :: 3.13
14
+ Classifier: Programming Language :: Python :: 3.14
15
+ Requires-Dist: raztodo>=0.11.0
16
+ Requires-Dist: fastapi[standard]>=0.141.1
17
+ Maintainer: Raz
18
+ Maintainer-email: Raz <real.raz.dev@gmail.com>
19
+ Requires-Python: >=3.10
20
+ Project-URL: Homepage, https://github.com/razbuild/raztodo-web
21
+ Project-URL: Documentation, https://github.com/razbuild/raztodo-web#readme
22
+ Project-URL: Repository, https://github.com/razbuild/raztodo-web
23
+ Project-URL: Issues, https://github.com/razbuild/raztodo-web/issues
24
+ Project-URL: Changelog, https://github.com/razbuild/raztodo-web/releases
25
+ Description-Content-Type: text/markdown
26
+
27
+ <div align="center">
28
+
29
+ <h1>RazTodo Web</h1>
30
+
31
+ <img src="https://raw.githubusercontent.com/razbuild/raztodo-web/main/assets/preview.png" alt="RazTodo Web task management interface">
32
+
33
+ <p>
34
+ RazTodo Web adds a browser-based UI and a REST API on top of
35
+ <a href="https://github.com/razbuild/raztodo">RazTodo</a>.<br>
36
+ It's a presentation layer, not a replacement.
37
+ </p>
38
+
39
+ <br>
40
+
41
+ </div>
42
+
43
+ ## What is RazTodo Web?
44
+
45
+ RazTodo Web is a Vanilla **JavaScript + FastAPI** web interface for [RazTodo](https://github.com/razbuild/raztodo), built directly on top of its core.
46
+
47
+ ## Features
48
+
49
+ | Type | Item | Details |
50
+ | ----------- | ---------------------- | ------------------------------------------ |
51
+ | ๐Ÿค– Optional | **Ollama** | Access RazTodo's AI-powered task explanations |
52
+ | ๐Ÿ“‹ Feature | **Task Management** | Create, update, complete, and delete tasks |
53
+ | ๐Ÿ”Ž Feature | **Search & Filtering** | Search and filter by status |
54
+ | ๐Ÿท๏ธ Feature | **Organization** | Priorities, tags, projects, and due dates |
55
+ | ๐Ÿ“ฅ Feature | **Import / Export** | Import and export tasks as JSON |
56
+ | ๐Ÿงน Feature | **Clean All** | Delete all tasks at once |
57
+ | ๐ŸŒ Feature | **Responsive Web UI** | Browser-based interface |
58
+ | ๐Ÿ”Œ Feature | **REST API** | FastAPI-powered API |
59
+ | ๐ŸŒ“ Feature | **Light / Dark Theme** | Light and dark themes |
60
+ | ๐Ÿ’พ Feature | **Local-first** | Runs locally without an external backend |
61
+
62
+
63
+ ## Requirements
64
+
65
+ * Python 3.10+
66
+ * RazTodo 0.11.x
67
+
68
+ ## Architecture
69
+
70
+ ```text
71
+ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
72
+ โ”‚ RazTodo Web โ”‚
73
+ โ”‚ Web UI - FastAPI - REST โ”‚
74
+ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
75
+ โ”‚
76
+ โ–ผ
77
+ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
78
+ โ”‚ RazTodo โ”‚
79
+ โ”‚ Domain - Application - Storage โ”‚
80
+ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
81
+ ```
82
+
83
+ ## Quick Start
84
+
85
+ ### 1. Install
86
+
87
+ ```bash
88
+ pip install raztodo-web
89
+ ```
90
+
91
+ RazTodo is installed automatically as a dependency.
92
+
93
+ ### 2. Run
94
+
95
+ ```bash
96
+ rt-web
97
+ ```
98
+
99
+ The server starts on `http://127.0.0.1:8000` by default.
100
+
101
+ ### 3. Access
102
+
103
+ Once the server is running:
104
+
105
+ | Service | URL |
106
+ | ------------- | --------------------------- |
107
+ | ๐ŸŒ Web UI | http://127.0.0.1:8000 |
108
+ | ๐Ÿ“– Swagger UI | http://127.0.0.1:8000/docs |
109
+ | ๐Ÿ“š ReDoc | http://127.0.0.1:8000/redoc |
110
+
111
+ ### 4. Configure
112
+
113
+ Set a custom host or port with environment variables:
114
+
115
+ ```bash
116
+ RAZTODO_WEB_HOST=0.0.0.0 RAZTODO_WEB_PORT=8080 rt-web
117
+ ```
118
+
119
+
120
+ ## License
121
+
122
+ [![License](https://img.shields.io/github/license/razbuild/raztodo-web)](https://github.com/razbuild/raztodo-web/blob/main/LICENSE)
123
+
124
+ <div align="center">
125
+ <img src="https://raw.githubusercontent.com/razbuild/.github/main/assets/badge.svg" alt="Made by RazBuild" width="160">
126
+ </div>
@@ -0,0 +1,100 @@
1
+ <div align="center">
2
+
3
+ <h1>RazTodo Web</h1>
4
+
5
+ <img src="https://raw.githubusercontent.com/razbuild/raztodo-web/main/assets/preview.png" alt="RazTodo Web task management interface">
6
+
7
+ <p>
8
+ RazTodo Web adds a browser-based UI and a REST API on top of
9
+ <a href="https://github.com/razbuild/raztodo">RazTodo</a>.<br>
10
+ It's a presentation layer, not a replacement.
11
+ </p>
12
+
13
+ <br>
14
+
15
+ </div>
16
+
17
+ ## What is RazTodo Web?
18
+
19
+ RazTodo Web is a Vanilla **JavaScript + FastAPI** web interface for [RazTodo](https://github.com/razbuild/raztodo), built directly on top of its core.
20
+
21
+ ## Features
22
+
23
+ | Type | Item | Details |
24
+ | ----------- | ---------------------- | ------------------------------------------ |
25
+ | ๐Ÿค– Optional | **Ollama** | Access RazTodo's AI-powered task explanations |
26
+ | ๐Ÿ“‹ Feature | **Task Management** | Create, update, complete, and delete tasks |
27
+ | ๐Ÿ”Ž Feature | **Search & Filtering** | Search and filter by status |
28
+ | ๐Ÿท๏ธ Feature | **Organization** | Priorities, tags, projects, and due dates |
29
+ | ๐Ÿ“ฅ Feature | **Import / Export** | Import and export tasks as JSON |
30
+ | ๐Ÿงน Feature | **Clean All** | Delete all tasks at once |
31
+ | ๐ŸŒ Feature | **Responsive Web UI** | Browser-based interface |
32
+ | ๐Ÿ”Œ Feature | **REST API** | FastAPI-powered API |
33
+ | ๐ŸŒ“ Feature | **Light / Dark Theme** | Light and dark themes |
34
+ | ๐Ÿ’พ Feature | **Local-first** | Runs locally without an external backend |
35
+
36
+
37
+ ## Requirements
38
+
39
+ * Python 3.10+
40
+ * RazTodo 0.11.x
41
+
42
+ ## Architecture
43
+
44
+ ```text
45
+ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
46
+ โ”‚ RazTodo Web โ”‚
47
+ โ”‚ Web UI - FastAPI - REST โ”‚
48
+ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
49
+ โ”‚
50
+ โ–ผ
51
+ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
52
+ โ”‚ RazTodo โ”‚
53
+ โ”‚ Domain - Application - Storage โ”‚
54
+ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
55
+ ```
56
+
57
+ ## Quick Start
58
+
59
+ ### 1. Install
60
+
61
+ ```bash
62
+ pip install raztodo-web
63
+ ```
64
+
65
+ RazTodo is installed automatically as a dependency.
66
+
67
+ ### 2. Run
68
+
69
+ ```bash
70
+ rt-web
71
+ ```
72
+
73
+ The server starts on `http://127.0.0.1:8000` by default.
74
+
75
+ ### 3. Access
76
+
77
+ Once the server is running:
78
+
79
+ | Service | URL |
80
+ | ------------- | --------------------------- |
81
+ | ๐ŸŒ Web UI | http://127.0.0.1:8000 |
82
+ | ๐Ÿ“– Swagger UI | http://127.0.0.1:8000/docs |
83
+ | ๐Ÿ“š ReDoc | http://127.0.0.1:8000/redoc |
84
+
85
+ ### 4. Configure
86
+
87
+ Set a custom host or port with environment variables:
88
+
89
+ ```bash
90
+ RAZTODO_WEB_HOST=0.0.0.0 RAZTODO_WEB_PORT=8080 rt-web
91
+ ```
92
+
93
+
94
+ ## License
95
+
96
+ [![License](https://img.shields.io/github/license/razbuild/raztodo-web)](https://github.com/razbuild/raztodo-web/blob/main/LICENSE)
97
+
98
+ <div align="center">
99
+ <img src="https://raw.githubusercontent.com/razbuild/.github/main/assets/badge.svg" alt="Made by RazBuild" width="160">
100
+ </div>
@@ -0,0 +1,68 @@
1
+ [build-system]
2
+ requires = ["uv_build>=0.12.5,<0.13"]
3
+ build-backend = "uv_build"
4
+
5
+ [project]
6
+ name = "raztodo-web"
7
+ version = "0.1.0"
8
+ description = "Web UI for RazTodo"
9
+ license = "MIT"
10
+ requires-python = ">=3.10"
11
+ keywords = [
12
+ "raztodo",
13
+ "web-ui",
14
+ "fastapi",
15
+ "task-manager",
16
+ "local-first",
17
+ ]
18
+ classifiers = [
19
+ "Development Status :: 4 - Beta",
20
+ "Intended Audience :: Developers",
21
+ "Programming Language :: Python :: 3",
22
+ "Programming Language :: Python :: 3.10",
23
+ "Programming Language :: Python :: 3.11",
24
+ "Programming Language :: Python :: 3.12",
25
+ "Programming Language :: Python :: 3.13",
26
+ "Programming Language :: Python :: 3.14",
27
+ ]
28
+ dependencies = [
29
+ "raztodo>=0.11.0",
30
+ "fastapi[standard]>=0.141.1",
31
+ ]
32
+
33
+ [project.readme]
34
+ file = "README.md"
35
+ content-type = "text/markdown"
36
+
37
+ [[project.maintainers]]
38
+ name = "Raz"
39
+ email = "real.raz.dev@gmail.com"
40
+
41
+ [project.urls]
42
+ Homepage = "https://github.com/razbuild/raztodo-web"
43
+ Documentation = "https://github.com/razbuild/raztodo-web#readme"
44
+ Repository = "https://github.com/razbuild/raztodo-web"
45
+ Issues = "https://github.com/razbuild/raztodo-web/issues"
46
+ Changelog = "https://github.com/razbuild/raztodo-web/releases"
47
+
48
+ [project.scripts]
49
+ rt-web = "raztodo_web.__main__:main"
50
+
51
+ [dependency-groups]
52
+ dev = [
53
+ "ruff",
54
+ "ty",
55
+ "pytest",
56
+ ]
57
+
58
+ [tool.uv.build-backend]
59
+ module-name = "raztodo_web"
60
+ module-root = "src"
61
+
62
+ [tool.pytest.ini_options]
63
+ addopts = [
64
+ "--strict-config",
65
+ "--strict-markers",
66
+ ]
67
+ xfail_strict = true
68
+ filterwarnings = ["error"]
@@ -0,0 +1,61 @@
1
+ [build-system]
2
+ requires = ["uv_build>=0.12.5,<0.13"]
3
+ build-backend = "uv_build"
4
+
5
+ [project]
6
+ name = "raztodo-web"
7
+ version = "0.1.0"
8
+ description = "Web UI for RazTodo"
9
+ readme = { file = "README.md", content-type = "text/markdown" }
10
+ license = "MIT"
11
+ requires-python = ">=3.10"
12
+ maintainers = [
13
+ { name = "Raz", email = "real.raz.dev@gmail.com" },
14
+ ]
15
+ keywords = [
16
+ "raztodo",
17
+ "web-ui",
18
+ "fastapi",
19
+ "task-manager",
20
+ "local-first",
21
+ ]
22
+ classifiers = [
23
+ "Development Status :: 4 - Beta",
24
+ "Intended Audience :: Developers",
25
+ "Programming Language :: Python :: 3",
26
+ "Programming Language :: Python :: 3.10",
27
+ "Programming Language :: Python :: 3.11",
28
+ "Programming Language :: Python :: 3.12",
29
+ "Programming Language :: Python :: 3.13",
30
+ "Programming Language :: Python :: 3.14",
31
+ ]
32
+ dependencies = [
33
+ "raztodo>=0.11.0",
34
+ "fastapi[standard]>=0.141.1",
35
+ ]
36
+
37
+ [project.urls]
38
+ Homepage = "https://github.com/razbuild/raztodo-web"
39
+ Documentation = "https://github.com/razbuild/raztodo-web#readme"
40
+ Repository = "https://github.com/razbuild/raztodo-web"
41
+ Issues = "https://github.com/razbuild/raztodo-web/issues"
42
+ Changelog = "https://github.com/razbuild/raztodo-web/releases"
43
+
44
+ [project.scripts]
45
+ rt-web = "raztodo_web.__main__:main"
46
+
47
+ [dependency-groups]
48
+ dev = [
49
+ "ruff",
50
+ "ty",
51
+ "pytest",
52
+ ]
53
+
54
+ [tool.uv.build-backend]
55
+ module-name = "raztodo_web"
56
+ module-root = "src"
57
+
58
+ [tool.pytest.ini_options]
59
+ addopts = ["--strict-config", "--strict-markers"]
60
+ xfail_strict = true
61
+ filterwarnings = ["error"]
File without changes
@@ -0,0 +1,36 @@
1
+ from __future__ import annotations
2
+
3
+ import os
4
+
5
+
6
+ def web_host() -> str:
7
+ return os.getenv("RAZTODO_WEB_HOST", "127.0.0.1")
8
+
9
+
10
+ def web_port() -> int:
11
+ return int(os.getenv("RAZTODO_WEB_PORT", "8000"))
12
+
13
+
14
+ def main() -> None:
15
+ import importlib.util
16
+
17
+ if (
18
+ importlib.util.find_spec("fastapi") is None
19
+ or importlib.util.find_spec("uvicorn") is None
20
+ ):
21
+ raise SystemExit(
22
+ "Web dependencies are not installed. Install with: pip install 'raztodo[web]'"
23
+ )
24
+
25
+ import uvicorn # type: ignore[import]
26
+
27
+ uvicorn.run(
28
+ "raztodo_web.app.factory:app",
29
+ host=web_host(),
30
+ port=web_port(),
31
+ reload=False,
32
+ )
33
+
34
+
35
+ if __name__ == "__main__":
36
+ main()
File without changes
@@ -0,0 +1,40 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Annotated, Any
4
+
5
+ from fastapi import Depends
6
+ from raztodo.application.factory import DefaultUseCaseFactory
7
+ from raztodo.infrastructure.container import build_container
8
+ from raztodo.infrastructure.sqlite.task_repository import SQLiteTaskRepository
9
+
10
+ _container = build_container()
11
+
12
+
13
+ def get_storage() -> SQLiteTaskRepository:
14
+ return _container.repo_singleton()
15
+
16
+
17
+ def get_factory() -> DefaultUseCaseFactory:
18
+ return DefaultUseCaseFactory()
19
+
20
+
21
+ StorageDep = Annotated[SQLiteTaskRepository, Depends(get_storage)]
22
+ FactoryDep = Annotated[DefaultUseCaseFactory, Depends(get_factory)]
23
+
24
+
25
+ def get_use_case(factory_method: str):
26
+ def _dependency(storage: StorageDep, factory: FactoryDep) -> Any:
27
+ return getattr(factory, factory_method)(storage)
28
+
29
+ return _dependency
30
+
31
+
32
+ get_list_uc = get_use_case("create_list_tasks")
33
+ get_create_uc = get_use_case("create_create_task")
34
+ get_update_uc = get_use_case("create_update_task")
35
+ get_delete_uc = get_use_case("create_delete_task")
36
+ get_clear_uc = get_use_case("create_clear_tasks")
37
+ get_mark_done_uc = get_use_case("create_mark_done")
38
+ get_export_uc = get_use_case("create_export_tasks")
39
+ get_import_uc = get_use_case("create_import_tasks")
40
+ get_explain_uc = get_use_case("create_explain_task")
@@ -0,0 +1,39 @@
1
+ from __future__ import annotations
2
+
3
+ from pathlib import Path
4
+
5
+ from fastapi import FastAPI, Request
6
+ from fastapi.staticfiles import StaticFiles
7
+ from fastapi.templating import Jinja2Templates
8
+ from raztodo.infrastructure.version import get_version
9
+
10
+ from raztodo_web.features.explain.routes import router as explain_router
11
+ from raztodo_web.features.tasks.routes import router as tasks_router
12
+
13
+ _WEB_DIR = Path(__file__).resolve().parent.parent / "web"
14
+ _STATIC_DIR = _WEB_DIR / "static"
15
+ _TEMPLATES_DIR = _WEB_DIR / "templates"
16
+
17
+
18
+ app = FastAPI(
19
+ title="RazTodo",
20
+ description="Local web interface for RazTodo",
21
+ version=get_version(),
22
+ )
23
+
24
+ app.mount(
25
+ "/static",
26
+ StaticFiles(directory=_STATIC_DIR),
27
+ name="static",
28
+ )
29
+
30
+ templates = Jinja2Templates(directory=_TEMPLATES_DIR)
31
+
32
+ app.include_router(tasks_router)
33
+ app.include_router(explain_router)
34
+
35
+
36
+ @app.get("/", include_in_schema=False)
37
+ async def index(request: Request):
38
+ """Serve the single-page UI, rendered from templates/index.html."""
39
+ return templates.TemplateResponse(request, "index.html")
@@ -0,0 +1,42 @@
1
+ from typing import Any
2
+
3
+ from fastapi import APIRouter, Depends, HTTPException
4
+ from fastapi.responses import StreamingResponse
5
+ from raztodo.domain.exceptions import RazTodoException
6
+
7
+ from raztodo_web.app.dependencies import get_explain_uc
8
+
9
+ router = APIRouter(prefix="/api/tasks", tags=["tasks"])
10
+
11
+
12
+ @router.get("/{task_id}/explain")
13
+ def explain_task(
14
+ task_id: int,
15
+ mode: str = "short",
16
+ uc: Any = Depends(get_explain_uc), # noqa: B008
17
+ ) -> StreamingResponse:
18
+ """
19
+ Stream the LLM explanation as Server-Sent Events (SSE).
20
+ Each event: data: <token>\n\n
21
+ Final event: data: [DONE]\n\n
22
+ """
23
+ if mode not in ("short", "deep", "plan"):
24
+ raise HTTPException(
25
+ status_code=422, detail="mode must be: short, deep, or plan"
26
+ )
27
+
28
+ def _sse_generator():
29
+ try:
30
+ for token in uc.stream(task_id, mode=mode):
31
+ safe = token.replace("\n", "\\n")
32
+ yield f"data: {safe}\n\n"
33
+ except RazTodoException as _exc:
34
+ yield "event: error\ndata: An internal error occurred.\n\n"
35
+ finally:
36
+ yield "data: [DONE]\n\n"
37
+
38
+ return StreamingResponse(
39
+ _sse_generator(),
40
+ media_type="text/event-stream",
41
+ headers={"Cache-Control": "no-cache", "X-Accel-Buffering": "no"},
42
+ )
@@ -0,0 +1,23 @@
1
+ import os
2
+ from typing import Any
3
+
4
+ from raztodo_web.features.tasks.schemas import TaskResponse
5
+
6
+
7
+ def remove_file(path: str) -> None:
8
+ if os.path.exists(path):
9
+ os.unlink(path)
10
+
11
+
12
+ def task_to_response(task: Any) -> TaskResponse:
13
+ return TaskResponse(
14
+ id=task.id,
15
+ title=task.title,
16
+ description=getattr(task, "description", "") or "",
17
+ done=getattr(task, "done", False),
18
+ created_at=getattr(task, "created_at", "") or "",
19
+ priority=getattr(task, "priority", "") or "",
20
+ due_date=getattr(task, "due_date", None),
21
+ tags=list(getattr(task, "tags", None) or []),
22
+ project=getattr(task, "project", None),
23
+ )