akhaliq's picture
akhaliq HF Staff
Upload folder using huggingface_hub
b6e792e verified
import gradio as gr
from typing import List, Dict, Tuple
import time
class TodoApp:
def __init__(self):
self.todos = []
def add_todo(self, todo_text: str, current_todos: List[Dict]) -> Tuple[List[Dict], str]:
"""Add a new todo item to the list."""
if not todo_text.strip():
raise gr.Warning("Please enter a todo item!")
new_todo = {
"id": len(current_todos) + 1,
"text": todo_text.strip(),
"completed": False,
"created_at": time.strftime("%Y-%m-%d %H:%M")
}
updated_todos = current_todos + [new_todo]
return updated_todos, ""
def toggle_todo(self, todo_indices: List[int], current_todos: List[Dict]) -> List[Dict]:
"""Toggle the completion status of selected todos."""
if not todo_indices:
return current_todos
updated_todos = current_todos.copy()
for idx in todo_indices:
if 0 <= idx < len(updated_todos):
updated_todos[idx]["completed"] = not updated_todos[idx]["completed"]
return updated_todos
def delete_todos(self, todo_indices: List[int], current_todos: List[Dict]) -> List[Dict]:
"""Delete selected todos from the list."""
if not todo_indices:
return current_todos
# Sort indices in reverse to avoid index shifting issues
todo_indices_sorted = sorted(todo_indices, reverse=True)
updated_todos = current_todos.copy()
for idx in todo_indices_sorted:
if 0 <= idx < len(updated_todos):
del updated_todos[idx]
# Reassign IDs
for i, todo in enumerate(updated_todos):
todo["id"] = i + 1
return updated_todos
def clear_all(self) -> List[Dict]:
"""Clear all todos from the list."""
return []
def get_todo_display(self, todos: List[Dict]) -> List[str]:
"""Format todos for display in CheckboxGroup."""
display_list = []
for todo in todos:
status = "βœ…" if todo["completed"] else "β­•"
display_text = f"{status} {todo['text']} (Created: {todo['created_at']})"
display_list.append(display_text)
return display_list
# Initialize the TodoApp
todo_manager = TodoApp()
def create_todo_app():
"""Create and configure the Gradio Todo App interface."""
with gr.Blocks(
title="Todo App",
theme=gr.themes.Soft(),
css="""
.todo-container {
border: 2px solid #e5e7eb;
border-radius: 8px;
padding: 16px;
margin: 8px 0;
background: #f9fafb;
}
.header-text {
text-align: center;
margin-bottom: 20px;
}
"""
) as demo:
# Header with attribution
gr.HTML("""
<div class="header-text">
<h1>πŸ“ Todo App</h1>
<p>Manage your tasks efficiently with this simple todo application!</p>
<p style="font-size: 0.9em; color: #666;">
Built with <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank">anycoder</a>
</p>
</div>
""")
# State to manage the todo list
todo_state = gr.State(value=[])
with gr.Row():
with gr.Column(scale=3):
# Input section
with gr.Group():
gr.Markdown("### Add New Todo")
todo_input = gr.Textbox(
placeholder="Enter your todo item here...",
label="Todo Item",
lines=1,
max_lines=1,
autofocus=True,
show_label=False
)
with gr.Row():
add_btn = gr.Button(
"βž• Add Todo",
variant="primary",
size="sm"
)
clear_input_btn = gr.Button(
"πŸ—‘οΈ Clear Input",
variant="secondary",
size="sm"
)
with gr.Column(scale=2):
# Statistics
with gr.Group():
gr.Markdown("### Statistics")
total_count = gr.Number(
label="Total Todos",
value=0,
interactive=False
)
completed_count = gr.Number(
label="Completed",
value=0,
interactive=False
)
pending_count = gr.Number(
label="Pending",
value=0,
interactive=False
)
# Todo list display and actions
with gr.Group():
gr.Markdown("### Todo List")
todo_display = gr.CheckboxGroup(
choices=[],
label="Select todos to toggle or delete",
info="Check items to mark as complete/incomplete or delete them",
interactive=True
)
with gr.Row():
toggle_btn = gr.Button(
"πŸ”„ Toggle Selected",
variant="secondary",
size="sm"
)
delete_btn = gr.Button(
"πŸ—‘οΈ Delete Selected",
variant="stop",
size="sm"
)
clear_all_btn = gr.Button(
"🧹 Clear All",
variant="stop",
size="sm"
)
# Hidden component to trigger updates
update_trigger = gr.Number(visible=False)
# Functions
def add_todo_handler(todo_text, current_todos):
"""Handle adding a new todo."""
updated_todos, cleared_input = todo_manager.add_todo(todo_text, current_todos)
display_choices = todo_manager.get_todo_display(updated_todos)
# Calculate statistics
total = len(updated_todos)
completed = sum(1 for todo in updated_todos if todo["completed"])
pending = total - completed
return (
updated_todos,
display_choices,
cleared_input,
total,
completed,
pending,
time.time() # Trigger update
)
def toggle_todo_handler(selected_indices, current_todos):
"""Handle toggling todo completion status."""
if not selected_indices:
return current_todos, todo_manager.get_todo_display(current_todos)
updated_todos = todo_manager.toggle_todo(selected_indices, current_todos)
display_choices = todo_manager.get_todo_display(updated_todos)
# Calculate statistics
total = len(updated_todos)
completed = sum(1 for todo in updated_todos if todo["completed"])
pending = total - completed
return (
updated_todos,
display_choices,
total,
completed,
pending,
time.time() # Trigger update
)
def delete_todo_handler(selected_indices, current_todos):
"""Handle deleting selected todos."""
if not selected_indices:
return current_todos, todo_manager.get_todo_display(current_todos)
updated_todos = todo_manager.delete_todos(selected_indices, current_todos)
display_choices = todo_manager.get_todo_display(updated_todos)
# Calculate statistics
total = len(updated_todos)
completed = sum(1 for todo in updated_todos if todo["completed"])
pending = total - completed
return (
updated_todos,
display_choices,
total,
completed,
pending,
time.time() # Trigger update
)
def clear_all_handler():
"""Handle clearing all todos."""
updated_todos = todo_manager.clear_all()
display_choices = todo_manager.get_todo_display(updated_todos)
return (
updated_todos,
display_choices,
0,
0,
0,
time.time() # Trigger update
)
def clear_input_handler():
"""Clear the input textbox."""
return ""
def update_display(current_todos):
"""Update the display when todos change."""
display_choices = todo_manager.get_todo_display(current_todos)
# Calculate statistics
total = len(current_todos)
completed = sum(1 for todo in current_todos if todo["completed"])
pending = total - completed
return display_choices, total, completed, pending
# Event handlers
add_btn.click(
fn=add_todo_handler,
inputs=[todo_input, todo_state],
outputs=[todo_state, todo_display, todo_input, total_count, completed_count, pending_count, update_trigger]
)
todo_input.submit(
fn=add_todo_handler,
inputs=[todo_input, todo_state],
outputs=[todo_state, todo_display, todo_input, total_count, completed_count, pending_count, update_trigger]
)
clear_input_btn.click(
fn=clear_input_handler,
outputs=[todo_input]
)
toggle_btn.click(
fn=toggle_todo_handler,
inputs=[todo_display, todo_state],
outputs=[todo_state, todo_display, total_count, completed_count, pending_count, update_trigger]
)
delete_btn.click(
fn=delete_todo_handler,
inputs=[todo_display, todo_state],
outputs=[todo_state, todo_display, total_count, completed_count, pending_count, update_trigger]
)
clear_all_btn.click(
fn=clear_all_handler,
outputs=[todo_state, todo_display, total_count, completed_count, pending_count, update_trigger]
)
# Update display when state changes
update_trigger.change(
fn=update_display,
inputs=[todo_state],
outputs=[todo_display, total_count, completed_count, pending_count]
)
# Examples
gr.Examples(
examples=[
["Buy groceries"],
["Finish project report"],
["Call mom"],
["Schedule dentist appointment"],
["Learn Gradio"]
],
inputs=[todo_input],
examples_per_page=3,
label="Example todos (click to use)"
)
# Instructions
with gr.Accordion("πŸ“– How to Use", open=False):
gr.Markdown("""
### Instructions:
1. **Add Todo**: Type your task in the input box and press Enter or click "Add Todo"
2. **Mark Complete**: Check the box next to a todo and click "Toggle Selected"
3. **Delete Todos**: Select todos and click "Delete Selected"
4. **Clear All**: Click "Clear All" to remove all todos at once
5. **Statistics**: View real-time counts of total, completed, and pending todos
### Tips:
- βœ… indicates completed tasks
- β­• indicates pending tasks
- Each todo shows its creation time
- Select multiple todos to perform bulk actions
""")
return demo
# Create and launch the app
if __name__ == "__main__":
demo = create_todo_app()
demo.launch(
share=False,
show_error=True,
show_tips=True,
height=600,
width="100%"
)