Skip to content

Commit 38d8566

Browse files
committed
example async drag-n-drop
1 parent 7b94666 commit 38d8566

File tree

1 file changed

+93
-0
lines changed

1 file changed

+93
-0
lines changed

examples/trello_cards/async-main.py

+93
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
#!/usr/bin/env python3
2+
import asyncio
3+
from dataclasses import dataclass
4+
from functools import partial
5+
from typing import Optional, Tuple
6+
7+
from nicegui import app, ui
8+
9+
10+
@dataclass
11+
class ToDo:
12+
title: str
13+
14+
15+
@ui.page('/')
16+
def main():
17+
def make_droppable_column(name: str) -> ui.column:
18+
col = ui.column().classes('bg-blue-grey-2 w-60 p-4 rounded shadow-2')
19+
with col:
20+
ui.label(name).classes('text-bold ml-1')
21+
col.on('dragover.prevent', partial(on_dragover, col))
22+
col.on('dragleave', partial(on_dragleave, col))
23+
col.on('drop', partial(on_drop, col, name))
24+
return col
25+
26+
def make_draggable_card(todo: ToDo) -> ui.card:
27+
card = ui.card().props('draggable').classes('w-full cursor-pointer bg-grey-1')
28+
with card:
29+
ui.label(todo.title)
30+
card.on('dragstart', partial(on_dragstart, card, todo))
31+
return card
32+
33+
def on_dragstart(card: ui.card, todo: ToDo) -> None:
34+
app.storage.tab['dragging-todo'] = (card, todo)
35+
36+
def on_dragover(col: ui.column) -> None:
37+
col.classes(remove='bg-blue-grey-2', add='bg-blue-grey-3')
38+
39+
def on_dragleave(col: ui.column) -> None:
40+
col.classes(remove='bg-blue-grey-3', add='bg-blue-grey-2')
41+
42+
async def on_drop(tgt_col: ui.column, col_name: str) -> None:
43+
dragging: Optional[Tuple[ui.card, ToDo]] = app.storage.tab.get(
44+
'dragging-todo', None
45+
)
46+
if not dragging:
47+
return
48+
(card, todo) = dragging
49+
del app.storage.tab['dragging-todo']
50+
tgt_col.classes(remove='bg-blue-grey-3', add='bg-blue-grey-2')
51+
if not card.parent_slot:
52+
return
53+
src_col = card.parent_slot.parent
54+
if tgt_col == src_col:
55+
# no change, nothing to do
56+
return
57+
src_skel = ui.skeleton().classes('w-full')
58+
if False:
59+
# This might benefit from a new ui.column.replace(old_element, new_element)
60+
src_col.replace(card, src_skel)
61+
else:
62+
src_idx = card.parent_slot.children.index(card)
63+
src_skel.move(src_col, src_idx)
64+
card.parent_slot.children.remove(card)
65+
tgt_skel = ui.skeleton().classes('w-full')
66+
tgt_skel.move(tgt_col)
67+
68+
await asyncio.sleep(1.0)
69+
70+
src_col.remove(src_skel)
71+
if False:
72+
# This might benefit from a new ui.column.replace(old_element, new_element)
73+
tgt_col.replace(tgt_skel, card)
74+
else:
75+
tgt_idx = tgt_col.default_slot.children.index(tgt_skel)
76+
tgt_col.remove(tgt_skel)
77+
tgt_col.default_slot.children.insert(tgt_idx, card)
78+
card.parent_slot = tgt_col.default_slot
79+
ui.notify(f'"{todo.title}" is now in {col_name}')
80+
81+
with ui.row():
82+
with make_droppable_column('Next'):
83+
make_draggable_card(ToDo('Provide Deployment'))
84+
with make_droppable_column('Doing'):
85+
make_draggable_card(ToDo('Improve Documentation'))
86+
with make_droppable_column('Done'):
87+
make_draggable_card(ToDo('Invent NiceGUI'))
88+
make_draggable_card(ToDo('Test in own Projects'))
89+
make_draggable_card(ToDo('Publish as Open Source'))
90+
make_draggable_card(ToDo('Release Native-Mode'))
91+
92+
93+
ui.run()

0 commit comments

Comments
 (0)