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.
- raztodo_web-0.1.0/PKG-INFO +126 -0
- raztodo_web-0.1.0/README.md +100 -0
- raztodo_web-0.1.0/pyproject.toml +68 -0
- raztodo_web-0.1.0/pyproject.toml.orig +61 -0
- raztodo_web-0.1.0/src/raztodo_web/__init__.py +0 -0
- raztodo_web-0.1.0/src/raztodo_web/__main__.py +36 -0
- raztodo_web-0.1.0/src/raztodo_web/app/__init__.py +0 -0
- raztodo_web-0.1.0/src/raztodo_web/app/dependencies.py +40 -0
- raztodo_web-0.1.0/src/raztodo_web/app/factory.py +39 -0
- raztodo_web-0.1.0/src/raztodo_web/features/explain/__init__.py +0 -0
- raztodo_web-0.1.0/src/raztodo_web/features/explain/routes.py +42 -0
- raztodo_web-0.1.0/src/raztodo_web/features/tasks/helpers.py +23 -0
- raztodo_web-0.1.0/src/raztodo_web/features/tasks/routes.py +202 -0
- raztodo_web-0.1.0/src/raztodo_web/features/tasks/schemas.py +48 -0
- raztodo_web-0.1.0/src/raztodo_web/web/static/css/base.css +22 -0
- raztodo_web-0.1.0/src/raztodo_web/web/static/css/components/forms.css +216 -0
- raztodo_web-0.1.0/src/raztodo_web/web/static/css/components/modal.css +157 -0
- raztodo_web-0.1.0/src/raztodo_web/web/static/css/components/sidebar.css +88 -0
- raztodo_web-0.1.0/src/raztodo_web/web/static/css/components/toast.css +32 -0
- raztodo_web-0.1.0/src/raztodo_web/web/static/css/features/tasks.css +251 -0
- raztodo_web-0.1.0/src/raztodo_web/web/static/css/layout.css +79 -0
- raztodo_web-0.1.0/src/raztodo_web/web/static/css/responsive.css +44 -0
- raztodo_web-0.1.0/src/raztodo_web/web/static/css/style.css +28 -0
- raztodo_web-0.1.0/src/raztodo_web/web/static/css/theme.css +90 -0
- raztodo_web-0.1.0/src/raztodo_web/web/static/css/tokens.css +59 -0
- raztodo_web-0.1.0/src/raztodo_web/web/static/img/export.svg +1 -0
- raztodo_web-0.1.0/src/raztodo_web/web/static/img/favicon.ico +0 -0
- raztodo_web-0.1.0/src/raztodo_web/web/static/img/import.svg +1 -0
- raztodo_web-0.1.0/src/raztodo_web/web/static/img/search.svg +1 -0
- raztodo_web-0.1.0/src/raztodo_web/web/static/img/trash.svg +1 -0
- raztodo_web-0.1.0/src/raztodo_web/web/static/js/app.js +11 -0
- raztodo_web-0.1.0/src/raztodo_web/web/static/js/explain/index.js +19 -0
- raztodo_web-0.1.0/src/raztodo_web/web/static/js/explain/modal.js +111 -0
- raztodo_web-0.1.0/src/raztodo_web/web/static/js/shared/api.js +13 -0
- raztodo_web-0.1.0/src/raztodo_web/web/static/js/shared/priority.js +94 -0
- raztodo_web-0.1.0/src/raztodo_web/web/static/js/shared/state.js +12 -0
- raztodo_web-0.1.0/src/raztodo_web/web/static/js/shared/theme.js +30 -0
- raztodo_web-0.1.0/src/raztodo_web/web/static/js/shared/toast.js +23 -0
- raztodo_web-0.1.0/src/raztodo_web/web/static/js/tasks/actions.js +142 -0
- raztodo_web-0.1.0/src/raztodo_web/web/static/js/tasks/edit.js +55 -0
- raztodo_web-0.1.0/src/raztodo_web/web/static/js/tasks/index.js +70 -0
- raztodo_web-0.1.0/src/raztodo_web/web/static/js/tasks/render.js +143 -0
- raztodo_web-0.1.0/src/raztodo_web/web/templates/index.html +49 -0
- raztodo_web-0.1.0/src/raztodo_web/web/templates/partials/_explain_modal.html +20 -0
- raztodo_web-0.1.0/src/raztodo_web/web/templates/partials/_main_header.html +18 -0
- raztodo_web-0.1.0/src/raztodo_web/web/templates/partials/_sidebar_new_task.html +70 -0
- raztodo_web-0.1.0/src/raztodo_web/web/templates/partials/_sidebar_search.html +27 -0
- raztodo_web-0.1.0/src/raztodo_web/web/templates/partials/_sidebar_tools.html +41 -0
- 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
|
+
[](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
|
+
[](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")
|
|
File without changes
|
|
@@ -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
|
+
)
|