Skip to content

Commit

Permalink
Add support for exporting all records
Browse files Browse the repository at this point in the history
  • Loading branch information
daya0576 committed Sep 1, 2024
1 parent 1d0cada commit 396f919
Show file tree
Hide file tree
Showing 11 changed files with 156 additions and 106 deletions.
172 changes: 84 additions & 88 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -1,87 +1,86 @@
# flyctl launch added from .gitignore
# Byte-compiled / optimized / DLL files
**/__pycache__
**/*.py[cod]
**/*$py.class
__pycache__/
*.py[cod]
*$py.class

# C extensions
**/*.so
*.so

# Distribution / packaging
**/.Python
**/build
**/develop-eggs
**/dist
**/downloads
**/eggs
**/.eggs
**/lib
**/lib64
**/parts
**/sdist
**/var
**/wheels
**/share/python-wheels
**/*.egg-info
**/.installed.cfg
**/*.egg
**/MANIFEST
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
**/*.manifest
**/*.spec
*.manifest
*.spec

# Installer logs
**/pip-log.txt
**/pip-delete-this-directory.txt
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
**/htmlcov
**/.tox
**/.nox
**/.coverage
**/.coverage.*
**/.cache
**/nosetests.xml
**/coverage.xml
**/*.cover
**/*.py,cover
**/.hypothesis
**/.pytest_cache
**/cover
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/

# Translations
**/*.mo
**/*.pot
*.mo
*.pot

# Django stuff:
**/*.log
**/local_settings.py
**/db.sqlite3
**/db.sqlite3-journal
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal

# Flask stuff:
**/instance
**/.webassets-cache
instance/
.webassets-cache

# Scrapy stuff:
**/.scrapy
.scrapy

# Sphinx documentation
**/docs/_build
docs/_build/

# PyBuilder
**/.pybuilder
**/target
.pybuilder/
target/

# Jupyter Notebook
**/.ipynb_checkpoints
.ipynb_checkpoints

# IPython
**/profile_default
**/ipython_config.py
profile_default/
ipython_config.py

# pyenv
# For a library or package, you might want to ignore these files since the code is
Expand All @@ -108,56 +107,53 @@
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/#use-with-ide
**/.pdm.toml
.pdm.toml

# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
**/__pypackages__
__pypackages__/

# Celery stuff
**/celerybeat-schedule
**/celerybeat.pid
celerybeat-schedule
celerybeat.pid

# SageMath parsed files
**/*.sage.py
*.sage.py

# Environments
**/.env
**/.venv
**/env
**/venv
**/ENV
**/env.bak
**/venv.bak
.env
.venv*
env/
venv/
ENV/
env.bak/
venv.bak/

# Spyder project settings
**/.spyderproject
**/.spyproject
.spyderproject
.spyproject

# Rope project settings
**/.ropeproject
.ropeproject

# mypy
**/.mypy_cache
**/.dmypy.json
**/dmypy.json
.mypy_cache/
.dmypy.json
dmypy.json

# Pyre type checker
**/.pyre
.pyre/

# pytype static type analyzer
**/.pytype
.pytype/

# Cython debug symbols
**/cython_debug

**/*.swp
**/.nicegui
**/test.db
**/.idea


# flyctl launch added from .idea/.gitignore
# Default ignored files
.idea/shelf
.idea/workspace.xml
fly.toml
cython_debug/

*.swp
*.db
.nicegui
test.db
.idea/
.user/
screenshots/
tags
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ dmypy.json
cython_debug/

*.swp
*.db
.nicegui
test.db
.idea/
Expand Down
1 change: 0 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ FROM python:3.12.2-slim

LABEL maintainer="Henry Zhu <[email protected]>"


COPY . .

RUN pip install --upgrade pip \
Expand Down
35 changes: 29 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,39 @@
# Beaver Habit Tracker

A minimalistic web app to track your fleeting life.
Self-hosting habit tracker web app to track your fleeting life.

<img src='https://github.com/daya0576/beaverhabits/assets/6239652/0418fa41-8985-46ef-b623-333b62b2f92e' width='250'>
<img src='https://github.com/daya0576/beaverhabits/assets/6239652/c0ce98cf-5a44-4bbc-8cd3-c7afb20af671' width='250'>
<img src='https://github.com/daya0576/beaverhabits/assets/6239652/516c19ca-9f55-4c21-9e6d-c8f0361a5eb2' width='250'>

# Getting Started

[Demo](https://beaverhabits.com/demo) | [Login](https://beaverhabits.com)
## Cloud Service

# Work in Progress
- Demo: https://beaverhabits.com/demo
- Login: https://beaverhabits.com

## Self-hosting

### Ship with Docker

Example:

```bash
docker run -d --name beaverhabits \
-e FIRST_DAY_OF_WEEK=0
-p 8080:8080 \
--restart unless-stopped \
daya0576/beaverhabits:latest
```

Options:

- **HABITS_STORAGE**(str): `DATABASE`(default), `USER_DISK`
- **DATABASE_URL**(str): The database url for storage backend, e.g. `sqlite:///habits.db`
- **FIRST_DAY_OF_WEEK**(int): `0`(default), `6`

# Features

1. Pages
- [x] Index page
Expand All @@ -24,11 +47,11 @@ A minimalistic web app to track your fleeting life.
- [x] User-based sqlite storage
3. CICD:
- [x] Custom domain
- [ ] Global CDN with edge instances
- [ ] Self-hosting option
- [x] Self-hosting option
- [x] Unit tests & deployment pipeline
4. Others:
- [ ] Export & Import
- [x] Export
- [ ] Import
- [x] User management
- [x] User timezone

Expand Down
2 changes: 1 addition & 1 deletion beaverhabits/app/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ async def user_create_token(user: User) -> Optional[str]:
return None


async def user_check_token(token: str) -> bool:
async def user_check_token(token: str | None) -> bool:
try:
async with get_async_session_context() as session:
async with get_user_db_context(session) as user_db:
Expand Down
11 changes: 7 additions & 4 deletions beaverhabits/configs.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@

import logging

import dotenv

logging.getLogger("niceGUI").setLevel(logging.INFO)
dotenv.load_dotenv()


class StorageType(Enum):
Expand All @@ -24,12 +27,12 @@ class Settings(BaseSettings):
GUI_MOUNT_PATH: str = "/gui"
DEMO_MOUNT_PATH: str = "/demo"

# Quasar custom
FIRST_DAY_OF_WEEK: int = calendar.MONDAY

# Storage
DATABASE_URL: str = "sqlite+aiosqlite:///./test.db"
HABITS_STORAGE: StorageType = StorageType.USER_DATABASE
DATABASE_URL: str = "sqlite+aiosqlite:///./habits.db"

# Customization
FIRST_DAY_OF_WEEK: int = calendar.MONDAY

def is_dev(self):
return self.ENV == "dev"
Expand Down
2 changes: 0 additions & 2 deletions beaverhabits/frontend/habit_page.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import calendar
import datetime
from contextlib import contextmanager
from typing import List

from nicegui import ui

Expand All @@ -15,7 +14,6 @@
from beaverhabits.frontend.layout import layout
from beaverhabits.storage.meta import get_habit_heatmap_path
from beaverhabits.storage.storage import Habit
from beaverhabits.utils import get_user_today_date

WEEKS_TO_DISPLAY = 15

Expand Down
8 changes: 7 additions & 1 deletion beaverhabits/frontend/layout.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,13 @@ def layout(title: str | None = None):
with menu_icon_button(icons.MENU):
with ui.menu():
compat_menu("Add", lambda: ui.open(os.path.join(root_path, "add")))
# compat_menu("Menu2", lambda: True)
ui.separator()
compat_menu(
"Export",
lambda: ui.open(
os.path.join(root_path, "export"), new_tab=True
),
)
ui.separator()
compat_menu("Logout", lambda: user_logout() and ui.open("/login"))

Expand Down
8 changes: 7 additions & 1 deletion beaverhabits/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,11 @@ async def gui_habit_page_heatmap(
today = await get_user_today_date()
heatmap_page(today, habit)

@ui.page("/gui/export")
async def export(
user: User = Depends(current_active_user)
) -> None:
await views.export_user_habit_list(user)

@ui.page("/login")
async def login_page() -> Optional[RedirectResponse]:
Expand Down Expand Up @@ -137,6 +142,7 @@ async def try_register():
def init_gui_routes(fastapi_app: FastAPI):
@app.middleware("http")
async def AuthMiddleware(request: Request, call_next):
# Redirect unauthorized request
client_page_routes = [
route.path for route in app.routes if isinstance(route, APIRoute)
]
Expand All @@ -155,7 +161,7 @@ async def AuthMiddleware(request: Request, call_next):
request.scope["headers"] = [
e for e in request.scope["headers"] if not e[0] == b"authorization"
]
# # add new authorization header
# add new authorization header
request.scope["headers"].append(
(b"authorization", f"Bearer {app.storage.user.get('auth_token')}".encode())
)
Expand Down
Loading

0 comments on commit 396f919

Please sign in to comment.