Skip to content

Commit

Permalink
Add import function from other apps
Browse files Browse the repository at this point in the history
  • Loading branch information
daya0576 committed Oct 1, 2024
1 parent 834b925 commit 827e917
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 23 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ Options:
- [x] Unit tests & deployment pipeline
4. Others:
- [x] Export
- [ ] Import
- [x] [Import](https://github.com/daya0576/beaverhabits/wiki/Import-Habits-and-Records)
- [x] User management
- [x] User timezone

Expand Down
56 changes: 54 additions & 2 deletions beaverhabits/frontend/import_page.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import json
import logging
import csv
from io import StringIO

from nicegui import events, ui

Expand All @@ -12,17 +14,66 @@


async def import_from_json(text: str) -> HabitList:
"""Import from JSON
Example:
{
"habits": [
{
"name": "habit1",
"records": [
{"day": "2021-01-01", "done": true},
{"day": "2021-01-02", "done": false}
]
},
...
"""
habit_list = DictHabitList(json.loads(text))
if not habit_list.habits:
raise ValueError("No habits found")
return habit_list


async def import_from_csv(text: str) -> HabitList:
"""Import from CSV
Example:
Date,a,b,c,d,e,
2024-01-22,-1,-1,-1,-1,
2024-01-21,2,-1,-1,-1,
"""
data = []
reader = csv.DictReader(StringIO(text))
for row in reader:
data.append(row)

headers = list(data[0].keys())

habits = []
for habit_name in headers[1:]:
if not habit_name:
continue
habit = {"name": habit_name, "records": []}
for row in data:
day = row["Date"]
done = True if row[habit_name] and int(row[habit_name]) > 0 else False
habit["records"].append({"day": day, "done": done})
habits.append(habit)

output = {"habits": habits}
return DictHabitList(output)


def import_ui_page(user: User):
async def handle_upload(e: events.UploadEventArguments):
try:
text = e.content.read().decode("utf-8")
other = await import_from_json(text)
if e.name.endswith(".json"):
other = await import_from_json(text)
elif e.name.endswith(".csv"):
other = await import_from_csv(text)
else:
raise ValueError("Unsupported format")

from_habit_list = await user_storage.get_user_habit_list(user)
if not from_habit_list:
Expand Down Expand Up @@ -68,5 +119,6 @@ async def handle_upload(e: events.UploadEventArguments):
menu_header("Import", target=get_root_path())

# Upload: https://nicegui.io/documentation/upload
ui.upload(on_upload=handle_upload, max_files=1).props("accept=.json")
upload = ui.upload(on_upload=handle_upload, max_files=1)
upload.props("accept=.json,.csv")
return
25 changes: 5 additions & 20 deletions beaverhabits/storage/dict.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,13 +85,15 @@ async def tick(self, day: datetime.date, done: bool) -> None:
self.data["records"].append(data)

async def merge(self, other: "DictHabit") -> "DictHabit":
self_ticks = {r.data["day"] for r in self.records if r.done}
other_ticks = {r.data["day"] for r in other.records if r.done}
self_ticks = {r.day for r in self.records if r.done}
other_ticks = {r.day for r in other.records if r.done}
result = sorted(list(self_ticks | other_ticks))

d = {
"name": self.name,
"records": [{"day": day, "done": True} for day in result],
"records": [
{"day": day.strftime(DAY_MASK), "done": True} for day in result
],
}
return DictHabit(d)

Expand All @@ -104,23 +106,6 @@ def __hash__(self) -> int:

@dataclass
class DictHabitList(HabitList[DictHabit], DictStorage):
"""Dict storage for HabitList
Example:
{
"habits": [
{
"name": "habit1",
"records": [
{"day": "2021-01-01", "done": true},
{"day": "2021-01-02", "done": false}
]
},
{
"name": "habit2",
"records": []
...
"""

@property
def habits(self) -> list[DictHabit]:
Expand Down

0 comments on commit 827e917

Please sign in to comment.