-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathtodo_03.py
More file actions
138 lines (108 loc) · 3.66 KB
/
todo_03.py
File metadata and controls
138 lines (108 loc) · 3.66 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
from functools import partial
import json
from textual import on, work
from textual.app import App
from textual.containers import Center, Container, Horizontal
from textual.message import Message
from textual.reactive import reactive
from textual.screen import ModalScreen
from textual.widget import Widget
from textual.widgets import Button, Footer, Header, Input, Label
class TodoItemDetailsScreen(ModalScreen):
DEFAULT_CSS = """
TodoItemDetailsScreen {
align: center middle;
}
"""
def compose(self):
self.description_input = Input(placeholder="Description")
self.date_input = Input(placeholder="Due date dd/mm/yyyy")
with Container():
yield Label("Type description and due date in the format dd/mm/yyyy.")
yield self.description_input
yield self.date_input
with Center():
yield Button("Submit")
def on_button_pressed(self):
data = (self.description_input.value, self.date_input.value)
self.dismiss(data)
class TodoItem(Widget):
DEFAULT_CSS = """
TodoItem {
height: 2;
}
"""
description = reactive("")
date = reactive("")
class Edit(Message):
def __init__(self, item):
super().__init__()
self.item = item
class Delete(Message):
def __init__(self, item):
super().__init__()
self.item = item
def __init__(self):
super().__init__()
self.description_label = Label(id="description")
self.date_label = Label(id="date")
def compose(self):
with Horizontal():
yield Button("✅", classes="emoji-button", id="delete")
yield Button("📝", classes="emoji-button", id="edit")
yield self.description_label
yield self.date_label
def watch_description(self, description):
self.description_label.update(description)
def watch_date(self, date):
self.date_label.update(date)
@on(Button.Pressed, "#edit")
def edit_request(self):
self.post_message(self.Edit(self))
@on(Button.Pressed, "#delete")
def delete_request(self):
self.post_message(self.Delete(self))
class TodoApp(App):
BINDINGS = [("n", "new_item", "New")]
CSS_PATH = "todo.css"
def compose(self):
yield Header(show_clock=True)
yield Footer()
def on_mount(self):
self.load_data()
def action_new_item(self):
self.push_screen(TodoItemDetailsScreen(), self.new_item_callback)
def new_item_callback(self, data):
item = TodoItem()
description, date = data
item.description = description
item.date = date
self.mount(item)
self.save_data()
def edit_item_callback(self, item, data):
description, date = data
item.description = description
item.date = date
self.save_data()
def on_todo_item_delete(self, message):
message.item.remove()
self.save_data()
def on_todo_item_edit(self, message):
self.push_screen(
TodoItemDetailsScreen(), partial(self.edit_item_callback, message.item)
)
@work
def save_data(self):
to_dump = [(item.description, item.date) for item in self.query(TodoItem)]
with open("data.json", "w") as f:
json.dump(to_dump, f, indent=4)
@work
def load_data(self):
with open("data.json", "r") as f:
loaded = json.load(f)
for description, date in loaded:
item = TodoItem()
item.description = description
item.date = date
self.call_from_thread(self.mount, item)
TodoApp().run()