Skip to content

Commit 7819e2c

Browse files
committed
example async drag-n-drop
1 parent 7b94666 commit 7819e2c

File tree

1 file changed

+92
-0
lines changed

1 file changed

+92
-0
lines changed

examples/trello_cards/async-main.py

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

0 commit comments

Comments
 (0)