Skip to content

Commit 5decb76

Browse files
committed
チケット管理画面の実装
1 parent 36ba20d commit 5decb76

File tree

12 files changed

+379
-112
lines changed

12 files changed

+379
-112
lines changed

src/pm_kun/screen/bord.py

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
from typing import Union
2+
import flet as ft
3+
from flet import Draggable, DragTargetAcceptEvent
4+
from pm_kun.screen.component.ticket import Ticket
5+
from pm_kun.screen.util.create_view import create_view
6+
7+
8+
def view_chart(page: ft.Page):
9+
todos_high = ft.Column()
10+
todos_normal = ft.Column()
11+
todos_complete = ft.Column()
12+
13+
def complete_ticket(parent_container: Union[ft.Column, ft.Row], control_id: str):
14+
def handler(e):
15+
src = None
16+
for control in parent_container.controls:
17+
if isinstance(control, Draggable) and control.content.id == control_id:
18+
src = control
19+
break
20+
21+
if src:
22+
completed_task = Draggable(
23+
group="task",
24+
content=Ticket(
25+
title=src.content.title,
26+
id=src.content.id,
27+
),
28+
)
29+
todos_complete.controls.append(completed_task)
30+
todos_complete.update()
31+
32+
parent_container.controls.remove(src)
33+
parent_container.update()
34+
35+
return handler
36+
37+
def delete_ticket(parent_container: Union[ft.Column, ft.Row], control_id: str):
38+
def handler(e):
39+
for control in parent_container.controls:
40+
if isinstance(control, Draggable) and control.content.id == control_id:
41+
parent_container.controls.remove(control)
42+
parent_container.update()
43+
break
44+
45+
return handler
46+
47+
def drag_accept(
48+
target_container: ft.Column, from_container: str, e: DragTargetAcceptEvent
49+
):
50+
src = page.get_control(e.src_id)
51+
if (
52+
hasattr(src.content, "origin_container")
53+
and src.content.origin_container is not None
54+
):
55+
src.content.origin_container.controls.remove(src)
56+
src.content.origin_container.update()
57+
58+
if from_container == "high":
59+
src.content.origin_container = "high"
60+
elif from_container == "normal":
61+
src.content.origin_container = "normal"
62+
elif from_container == "complete":
63+
src.content.origin_container = "complete"
64+
accept_task = Draggable(
65+
group="task",
66+
content=Ticket(
67+
title=src.content.title,
68+
id=src.content.id,
69+
on_positive_button_click=complete_ticket(
70+
target_container, src.content.id
71+
),
72+
on_negative_button_click=delete_ticket(
73+
target_container, src.content.id
74+
),
75+
origin_container=target_container,
76+
),
77+
)
78+
target_container.controls.append(accept_task)
79+
target_container.update()
80+
81+
for control in unselected_todos.controls:
82+
if control.content.id == src.content.id:
83+
unselected_todos.controls.remove(control)
84+
break
85+
unselected_todos.update()
86+
87+
back_button = ft.ElevatedButton("メニューに戻る", on_click=lambda _: page.go("/"))
88+
89+
unselected_todos = ft.ListView(
90+
width=250,
91+
controls=[
92+
Draggable(
93+
data=f"{data['name']}|{data['id']}",
94+
group="task",
95+
content=Ticket(title=data["name"], id=data["id"]),
96+
)
97+
for data in page.data
98+
],
99+
expand=1,
100+
auto_scroll=True,
101+
)
102+
103+
label_high = ft.Text("重要", size=20, text_align="center")
104+
priority_high = ft.DragTarget(
105+
group="task",
106+
content=ft.Container(
107+
content=todos_high,
108+
width=250,
109+
height=600,
110+
bgcolor=ft.colors.BLUE_GREY_100,
111+
border_radius=5,
112+
),
113+
on_accept=lambda e: drag_accept(todos_high, "high", e),
114+
)
115+
area_high = ft.Column(
116+
controls=[label_high, priority_high],
117+
alignment="center",
118+
)
119+
120+
label_normal = ft.Text("標準", size=20, text_align="center")
121+
priority_normal = ft.DragTarget(
122+
group="task",
123+
content=ft.Container(
124+
content=todos_normal,
125+
width=250,
126+
height=600,
127+
bgcolor=ft.colors.BLUE_GREY_100,
128+
border_radius=5,
129+
),
130+
on_accept=lambda e: drag_accept(todos_normal, "normal", e),
131+
)
132+
area_normal = ft.Column(
133+
controls=[label_normal, priority_normal],
134+
alignment="center",
135+
)
136+
137+
label_complete = ft.Text("完了", size=20, text_align="center")
138+
complete = ft.DragTarget(
139+
group="task",
140+
content=ft.Container(
141+
content=todos_complete,
142+
width=250,
143+
height=600,
144+
bgcolor=ft.colors.BLUE_GREY_100,
145+
border_radius=5,
146+
),
147+
on_accept=lambda e: drag_accept(todos_complete, "complete", e),
148+
)
149+
area_complete = ft.Column(
150+
controls=[label_complete, complete],
151+
alignment="center",
152+
)
153+
154+
display = ft.Row(
155+
controls=[unselected_todos, area_high, area_normal, area_complete],
156+
alignment="center",
157+
)
158+
159+
return create_view("/chart", [ft.Column(controls=[display, back_button])])

src/pm_kun/screen/chart.py

Lines changed: 0 additions & 18 deletions
This file was deleted.

src/pm_kun/screen/component/__init__.py

Whitespace-only changes.
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
from typing import Union
2+
import flet as ft
3+
from flet import UserControl
4+
5+
6+
class Ticket(UserControl):
7+
"""
8+
・チケットの表示構成
9+
 ①TODO名:TextField
10+
 ②期限:DatePicker
11+
 ③完了/削除:IconButton
12+
 ④完了/削除ボタンを押したら、TODOを完了/削除する
13+
"""
14+
15+
def __init__(
16+
self,
17+
title: str,
18+
id: str,
19+
on_positive_button_click=None,
20+
on_negative_button_click=None,
21+
origin_container: ft.Column = None,
22+
):
23+
super().__init__()
24+
self.title = title
25+
self.id = id
26+
self.positive_button = "完了"
27+
self.negative_button = "削除"
28+
self.on_positive_button_click = on_positive_button_click
29+
self.on_negative_button_click = on_negative_button_click
30+
self.origin_container = origin_container
31+
32+
def build(self):
33+
return ft.Card(
34+
content=ft.Container(
35+
content=ft.Column(
36+
[
37+
ft.ListTile(
38+
title=ft.Text(self.title),
39+
),
40+
ft.Row(
41+
[
42+
ft.TextButton(
43+
self.positive_button,
44+
on_click=self.on_positive_button_click,
45+
),
46+
ft.TextButton(
47+
self.negative_button,
48+
on_click=self.on_negative_button_click,
49+
),
50+
],
51+
alignment=ft.MainAxisAlignment.END,
52+
),
53+
]
54+
),
55+
width=250,
56+
padding=10,
57+
)
58+
)
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
import uuid
2+
from flet import (
3+
Checkbox,
4+
Column,
5+
FloatingActionButton,
6+
IconButton,
7+
Row,
8+
TextField,
9+
UserControl,
10+
colors,
11+
icons,
12+
)
13+
14+
15+
class Task(UserControl):
16+
17+
def __init__(self, task_name, task_delete, update_task_data):
18+
super().__init__()
19+
self.id = str(uuid.uuid4())
20+
self.task_name = task_name
21+
self.task_delete = task_delete
22+
self.update_task_data = update_task_data
23+
24+
def build(self):
25+
self.display_task = Checkbox(value=False, label=self.task_name)
26+
self.edit_name = TextField(expand=1)
27+
28+
self.display_view = Row(
29+
alignment="spaceBetween",
30+
vertical_alignment="center",
31+
controls=[
32+
self.display_task,
33+
Row(
34+
spacing=0,
35+
controls=[
36+
IconButton(
37+
icon=icons.CREATE_OUTLINED,
38+
tooltip="編集",
39+
on_click=self.edit_clicked,
40+
),
41+
IconButton(
42+
icons.DELETE_OUTLINE,
43+
tooltip="削除",
44+
on_click=self.delete_clicked,
45+
),
46+
],
47+
),
48+
],
49+
)
50+
51+
self.edit_view = Row(
52+
visible=False,
53+
alignment="spaceBetween",
54+
vertical_alignment="center",
55+
controls=[
56+
self.edit_name,
57+
IconButton(
58+
icon=icons.DONE_OUTLINE_OUTLINED,
59+
icon_color=colors.GREEN,
60+
tooltip="編集完了",
61+
on_click=self.save_clicked,
62+
),
63+
],
64+
)
65+
return Column(controls=[self.display_view, self.edit_view])
66+
67+
def edit_clicked(self, e):
68+
self.edit_name.value = self.display_task.label
69+
self.display_view.visible = False
70+
self.edit_view.visible = True
71+
self.update()
72+
73+
def save_clicked(self, e):
74+
self.display_task.label = self.edit_name.value
75+
self.display_view.visible = True
76+
self.edit_view.visible = False
77+
self.update_task_data(self.id, self.display_task.label)
78+
self.update()
79+
80+
def delete_clicked(self, e):
81+
self.task_delete(self)
82+
83+
84+
class Todo(UserControl):
85+
def __init__(self):
86+
super().__init__()
87+
self._todos = []
88+
89+
def build(self):
90+
self.new_task = TextField(hint_text="TODO内容を入力してください", expand=True)
91+
self.tasks = Column()
92+
93+
return Column(
94+
width=600,
95+
controls=[
96+
Row(
97+
controls=[
98+
self.new_task,
99+
FloatingActionButton(icon=icons.ADD, on_click=self.add_clicked),
100+
],
101+
),
102+
self.tasks,
103+
],
104+
)
105+
106+
def add_clicked(self, e):
107+
task = Task(self.new_task.value, self.task_delete, self.update_task_data)
108+
self.tasks.controls.append(task)
109+
self._todos.append({"id": task.id, "name": task.task_name, "completed": False})
110+
self.new_task.value = ""
111+
self.update()
112+
113+
def update_task_data(self, task_id, new_name):
114+
for task in self._todos:
115+
if task["id"] == task_id:
116+
task["name"] = new_name
117+
break
118+
print(self._todos)
119+
120+
def task_delete(self, task):
121+
self._todos = [task for t in self._todos if t["id"] != task.id]
122+
self.tasks.controls.remove(task)
123+
self.update()
124+
125+
@property
126+
def todos(self):
127+
return self._todos

src/pm_kun/screen/home.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import flet as ft
22

3-
from pm_kun.screen.unit import create_view
3+
from pm_kun.screen.util.create_view import create_view
44

55

66
def view_home(page: ft.Page):
@@ -16,8 +16,8 @@ def navigate_pmk(e):
1616
page.go("/pmk")
1717
page.update()
1818

19-
todo_button = ft.FilledButton(text="タスク一覧", on_click=navigate_todo)
20-
chart_button = ft.FilledButton(text="ガントチャート", on_click=navigate_chart)
19+
todo_button = ft.FilledButton(text="TODO管理", on_click=navigate_todo)
20+
chart_button = ft.FilledButton(text="チケット作成", on_click=navigate_chart)
2121
pmk_button = ft.FilledButton(text="PMアドバイザー", on_click=navigate_pmk)
2222
title_text = ft.Text("プロマネ君", size=30, text_align="center")
2323

0 commit comments

Comments
 (0)