Refactor Time Selector and Scheduler UI; Implement TimePickerPopover Component
Some checks failed
Chore App Build, Test, and Push Docker Images / build-and-push (push) Failing after 1m5s
Some checks failed
Chore App Build, Test, and Push Docker Images / build-and-push (push) Failing after 1m5s
- Updated TimeSelector.vue styles for smaller dimensions and font sizes. - Added new API proxy for '/events' in vite.config.ts. - Created bug specifications for various UI issues and fixes in bugs-1.0.5-001.md and bugs-1.0.5-002.md. - Introduced TimePickerPopover.vue for a new time selection interface in the chore scheduler. - Refactored ScheduleModal.vue to replace checkbox rows with a chip-based design for selecting specific days. - Enhanced chore scheduling logic to ensure proper handling of time extensions and UI updates.
This commit is contained in:
@@ -4,7 +4,7 @@ from api.utils import get_validated_user_id, send_event_for_current_user
|
||||
from api.error_codes import ErrorCodes
|
||||
from db.db import child_db
|
||||
from db.chore_schedules import get_schedule, upsert_schedule, delete_schedule
|
||||
from db.task_extensions import get_extension, add_extension
|
||||
from db.task_extensions import get_extension, add_extension, delete_extension_for_child_task
|
||||
from models.chore_schedule import ChoreSchedule
|
||||
from models.task_extension import TaskExtension
|
||||
from events.types.event import Event
|
||||
@@ -58,11 +58,15 @@ def set_chore_schedule(child_id, task_id):
|
||||
day_configs = data.get('day_configs', [])
|
||||
if not isinstance(day_configs, list):
|
||||
return jsonify({'error': 'day_configs must be a list', 'code': ErrorCodes.INVALID_VALUE}), 400
|
||||
default_hour = data.get('default_hour', 8)
|
||||
default_minute = data.get('default_minute', 0)
|
||||
schedule = ChoreSchedule(
|
||||
child_id=child_id,
|
||||
task_id=task_id,
|
||||
mode='days',
|
||||
day_configs=day_configs,
|
||||
default_hour=default_hour,
|
||||
default_minute=default_minute,
|
||||
)
|
||||
else:
|
||||
interval_days = data.get('interval_days', 2)
|
||||
@@ -83,6 +87,7 @@ def set_chore_schedule(child_id, task_id):
|
||||
interval_minute=interval_minute,
|
||||
)
|
||||
|
||||
delete_extension_for_child_task(child_id, task_id)
|
||||
upsert_schedule(schedule)
|
||||
|
||||
send_event_for_current_user(Event(
|
||||
|
||||
@@ -25,3 +25,8 @@ def delete_extensions_for_child(child_id: str) -> None:
|
||||
def delete_extensions_for_task(task_id: str) -> None:
|
||||
q = Query()
|
||||
task_extensions_db.remove(q.task_id == task_id)
|
||||
|
||||
|
||||
def delete_extension_for_child_task(child_id: str, task_id: str) -> None:
|
||||
q = Query()
|
||||
task_extensions_db.remove((q.child_id == child_id) & (q.task_id == task_id))
|
||||
|
||||
@@ -59,9 +59,15 @@ def sse_response_for_user(user_id: str):
|
||||
def generate():
|
||||
try:
|
||||
while True:
|
||||
# Get message from queue (blocks until available)
|
||||
message = user_queue.get()
|
||||
yield message
|
||||
try:
|
||||
# Use a timeout so the thread yields periodically and keepalives are sent.
|
||||
# This prevents Werkzeug's dev server from starving other connections.
|
||||
message = user_queue.get(timeout=15)
|
||||
yield message
|
||||
logger.info(f"Sent message to {user_id} connection {connection_id}")
|
||||
except queue.Empty:
|
||||
# Send an SSE comment as a keepalive ping to maintain the connection.
|
||||
yield b': ping\n\n'
|
||||
except GeneratorExit:
|
||||
# Clean up when client disconnects
|
||||
if user_id in user_queues and connection_id in user_queues[user_id]:
|
||||
|
||||
@@ -33,6 +33,8 @@ class ChoreSchedule(BaseModel):
|
||||
|
||||
# mode='days' fields
|
||||
day_configs: list = field(default_factory=list) # list of DayConfig dicts
|
||||
default_hour: int = 8 # master deadline hour for 'days' mode
|
||||
default_minute: int = 0 # master deadline minute for 'days' mode
|
||||
|
||||
# mode='interval' fields
|
||||
interval_days: int = 2 # 2–7
|
||||
@@ -47,6 +49,8 @@ class ChoreSchedule(BaseModel):
|
||||
task_id=d.get('task_id'),
|
||||
mode=d.get('mode', 'days'),
|
||||
day_configs=d.get('day_configs', []),
|
||||
default_hour=d.get('default_hour', 8),
|
||||
default_minute=d.get('default_minute', 0),
|
||||
interval_days=d.get('interval_days', 2),
|
||||
anchor_weekday=d.get('anchor_weekday', 0),
|
||||
interval_hour=d.get('interval_hour', 0),
|
||||
@@ -63,6 +67,8 @@ class ChoreSchedule(BaseModel):
|
||||
'task_id': self.task_id,
|
||||
'mode': self.mode,
|
||||
'day_configs': self.day_configs,
|
||||
'default_hour': self.default_hour,
|
||||
'default_minute': self.default_minute,
|
||||
'interval_days': self.interval_days,
|
||||
'anchor_weekday': self.anchor_weekday,
|
||||
'interval_hour': self.interval_hour,
|
||||
|
||||
Reference in New Issue
Block a user