|
| 1 | +# Recipes & Scheduler Merge Implementation Plan |
| 2 | + |
| 3 | +## Overview |
| 4 | +Merging the Scheduler functionality into the Recipes view to create a unified interface where recipes can optionally have schedules. |
| 5 | + |
| 6 | +## Current State |
| 7 | +- **RecipesView** (`/recipes`): Shows saved recipes with Use/Preview/Delete actions |
| 8 | +- **SchedulesView** (`/schedules`): Shows scheduled jobs with cron expressions and management |
| 9 | +- **Problem**: Schedules ARE recipes with timing, so having two separate views is redundant |
| 10 | + |
| 11 | +## Implementation Status |
| 12 | + |
| 13 | +### ✅ Completed |
| 14 | +1. Created helper file `recipeScheduleHelpers.ts` with merge logic |
| 15 | +2. Added schedule-related imports to RecipesView |
| 16 | +3. Added schedule state variables to RecipesView |
| 17 | +4. Backed up original RecipesView.tsx |
| 18 | + |
| 19 | +### 🔄 In Progress - RecipesView.tsx Updates |
| 20 | + |
| 21 | +#### Need to Add: |
| 22 | +1. **Data Fetching** - Load both recipes AND schedules |
| 23 | + ```typescript |
| 24 | + const loadRecipesAndSchedules = async () => { |
| 25 | + const [recipes, schedules] = await Promise.all([ |
| 26 | + listSavedRecipes(), |
| 27 | + listSchedules() |
| 28 | + ]); |
| 29 | + const merged = mergeRecipesWithSchedules(recipes, schedules); |
| 30 | + // Apply filter |
| 31 | + const filtered = filterRecipesByScheduleStatus(merged, filterType); |
| 32 | + }; |
| 33 | + ``` |
| 34 | + |
| 35 | +2. **Filter Tabs** - Add UI to switch between All/Scheduled/Unscheduled |
| 36 | + ```tsx |
| 37 | + <div className="flex gap-2 mb-4"> |
| 38 | + <Button onClick={() => setFilterType('all')}>All</Button> |
| 39 | + <Button onClick={() => setFilterType('scheduled')}>Scheduled</Button> |
| 40 | + <Button onClick={() => setFilterType('unscheduled')}>Unscheduled</Button> |
| 41 | + </div> |
| 42 | + ``` |
| 43 | + |
| 44 | +3. **Enhanced RecipeItem** - Show schedule info and add schedule actions |
| 45 | + - Badge showing if recipe is scheduled |
| 46 | + - Display cron expression (human-readable) |
| 47 | + - Show running status |
| 48 | + - Add "Schedule" button for unscheduled recipes |
| 49 | + - Add "Edit Schedule" / "Pause" / "Resume" / "Kill" for scheduled ones |
| 50 | + |
| 51 | +4. **Schedule Handlers** - Add functions for schedule management |
| 52 | + - `handleCreateSchedule(recipe)` - Open CreateScheduleModal |
| 53 | + - `handleEditSchedule(schedule)` - Open EditScheduleModal |
| 54 | + - `handlePauseSchedule(scheduleId)` |
| 55 | + - `handleUnpauseSchedule(scheduleId)` |
| 56 | + - `handleDeleteSchedule(scheduleId)` |
| 57 | + - `handleKillRunningJob(scheduleId)` |
| 58 | + - `handleInspectRunningJob(scheduleId)` |
| 59 | + |
| 60 | +5. **Modals** - Add schedule modals at bottom |
| 61 | + ```tsx |
| 62 | + <CreateScheduleModal |
| 63 | + isOpen={showScheduleModal} |
| 64 | + onClose={() => setShowScheduleModal(false)} |
| 65 | + onSubmit={handleCreateScheduleSubmit} |
| 66 | + prefilledRecipePath={selectedRecipeForSchedule?.path} |
| 67 | + /> |
| 68 | + <EditScheduleModal ... /> |
| 69 | + ``` |
| 70 | + |
| 71 | +6. **Schedule Detail View** - Handle viewing schedule history |
| 72 | + ```tsx |
| 73 | + if (viewingScheduleId) { |
| 74 | + return <ScheduleDetailView |
| 75 | + scheduleId={viewingScheduleId} |
| 76 | + onNavigateBack={() => setViewingScheduleId(null)} |
| 77 | + />; |
| 78 | + } |
| 79 | + ``` |
| 80 | + |
| 81 | +### 📋 TODO - Navigation Updates |
| 82 | + |
| 83 | +1. **AppSidebar.tsx** - Remove "Scheduler" menu item |
| 84 | + - Remove the schedules navigation item from `menuItems` array |
| 85 | + - Keep only: Home, Chat, History, Recipes, Extensions, Settings |
| 86 | + |
| 87 | +2. **App.tsx** - Remove `/schedules` route |
| 88 | + - Remove `<Route path="schedules" element={<SchedulesRoute />} />` |
| 89 | + - Remove `SchedulesRoute` component definition |
| 90 | + |
| 91 | +3. **navigationUtils.ts** - Remove 'schedules' view type |
| 92 | + - Remove `'schedules'` from `View` type union |
| 93 | + - Remove `case 'schedules':` from `createNavigationHandler` |
| 94 | + |
| 95 | +## File Structure |
| 96 | + |
| 97 | +``` |
| 98 | +ui/desktop/src/components/ |
| 99 | +├── recipes/ |
| 100 | +│ ├── RecipesView.tsx # Main unified view (IN PROGRESS) |
| 101 | +│ ├── recipeScheduleHelpers.ts # Helper functions (✅ DONE) |
| 102 | +│ ├── CreateRecipeForm.tsx # Existing |
| 103 | +│ └── ImportRecipeForm.tsx # Existing |
| 104 | +├── schedule/ |
| 105 | +│ ├── SchedulesView.tsx # Will be deprecated/removed |
| 106 | +│ ├── ScheduleDetailView.tsx # Reused in RecipesView |
| 107 | +│ ├── CreateScheduleModal.tsx # Reused in RecipesView |
| 108 | +│ └── EditScheduleModal.tsx # Reused in RecipesView |
| 109 | +└── GooseSidebar/ |
| 110 | + └── AppSidebar.tsx # Remove Scheduler item (TODO) |
| 111 | +``` |
| 112 | + |
| 113 | +## Testing Checklist |
| 114 | +- [ ] View all recipes with schedule indicators |
| 115 | +- [ ] Filter by All/Scheduled/Unscheduled |
| 116 | +- [ ] Create a schedule for an unscheduled recipe |
| 117 | +- [ ] Edit an existing schedule |
| 118 | +- [ ] Pause/Resume a schedule |
| 119 | +- [ ] Kill a running scheduled job |
| 120 | +- [ ] Inspect a running job |
| 121 | +- [ ] Delete a schedule (recipe should remain) |
| 122 | +- [ ] Delete a recipe that has a schedule |
| 123 | +- [ ] View schedule detail/history |
| 124 | +- [ ] Navigate back from schedule detail to recipes |
| 125 | +- [ ] Verify Scheduler no longer appears in sidebar |
| 126 | +- [ ] Verify /schedules route is removed |
| 127 | + |
| 128 | +## Key Design Decisions |
| 129 | + |
| 130 | +1. **Recipes are primary** - The view is called "Recipes" not "Recipes & Schedules" |
| 131 | +2. **Schedules are optional** - A recipe can exist without a schedule |
| 132 | +3. **Schedule info is inline** - No need to navigate away to see if recipe is scheduled |
| 133 | +4. **Reuse existing components** - CreateScheduleModal, EditScheduleModal, ScheduleDetailView |
| 134 | +5. **Keep schedule history** - ScheduleDetailView still accessible for viewing past runs |
| 135 | + |
| 136 | +## Next Steps |
| 137 | + |
| 138 | +1. Complete RecipesView.tsx implementation (large file, doing incrementally) |
| 139 | +2. Update navigation (AppSidebar, App.tsx, navigationUtils.ts) |
| 140 | +3. Test all functionality |
| 141 | +4. Remove/deprecate SchedulesView.tsx |
| 142 | +5. Update any documentation |
| 143 | + |
| 144 | +## Notes |
| 145 | +- RecipesView.tsx is 763 lines - implementing changes incrementally |
| 146 | +- Backup created at RecipesView.tsx.backup |
| 147 | +- Helper file created to keep main component cleaner |
0 commit comments