Skip to content

Commit 46b9b71

Browse files
authored
Spence/channels (#5952)
1 parent cc945ef commit 46b9b71

File tree

8 files changed

+2483
-18
lines changed

8 files changed

+2483
-18
lines changed

RECIPES_SCHEDULER_MERGE_PLAN.md

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
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

ui/desktop/src/App.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ import ExtensionsView, { ExtensionsViewOptions } from './components/extensions/E
4545
import RecipesView from './components/recipes/RecipesView';
4646
import RecipeEditor from './components/recipes/RecipeEditor';
4747
import PeersView from './components/peers/PeersView';
48+
import ChannelsView from './components/channels/ChannelsView';
4849
import { createNavigationHandler, View, ViewOptions } from './utils/navigationUtils';
4950
import {
5051
AgentState,
@@ -318,6 +319,11 @@ const PeersRoute = () => {
318319
return <PeersView onClose={() => navigate('/')} />;
319320
};
320321

322+
const ChannelsRoute = () => {
323+
const navigate = useNavigate();
324+
return <ChannelsView onClose={() => navigate('/')} />;
325+
};
326+
321327
export function AppInner() {
322328
const [fatalError, setFatalError] = useState<string | null>(null);
323329
const [isGoosehintsModalOpen, setIsGoosehintsModalOpen] = useState(false);
@@ -661,6 +667,7 @@ export function AppInner() {
661667
<Route path="settings" element={<SettingsRoute />} />
662668
<Route path="extensions" element={<ExtensionsRoute />} />
663669
<Route path="peers" element={<PeersRoute />} />
670+
<Route path="channels" element={<ChannelsRoute />} />
664671
<Route path="sessions" element={<SessionsRoute />} />
665672
<Route path="schedules" element={<SchedulesRoute />} />
666673
<Route path="recipes" element={<RecipesView />} />

0 commit comments

Comments
 (0)