Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 5 additions & 12 deletions ui/desktop/src/components/recipes/CreateEditRecipeModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { Check, Save, Calendar, X, Play } from 'lucide-react';
import { ExtensionConfig } from '../ConfigContext';
import { ScheduleFromRecipeModal } from '../schedule/ScheduleFromRecipeModal';
import { Button } from '../ui/button';
import { useNavigation } from '../../hooks/useNavigation';

import { RecipeFormFields } from './shared/RecipeFormFields';
import { RecipeFormData } from './shared/recipeFormSchema';
Expand All @@ -28,6 +29,7 @@ export default function CreateEditRecipeModal({
isCreateMode = false,
recipeId,
}: CreateEditRecipeModalProps) {
const setView = useNavigation();
const getInitialValues = React.useCallback((): RecipeFormData => {
if (recipe) {
return {
Expand Down Expand Up @@ -452,18 +454,9 @@ export default function CreateEditRecipeModal({
onClose={() => setIsScheduleModalOpen(false)}
recipe={getCurrentRecipe()}
onCreateSchedule={(deepLink) => {
// Open the schedules view with the deep link pre-filled
window.electron.createChatWindow(
undefined,
undefined,
undefined,
undefined,
undefined,
'schedules',
undefined
);
// Store the deep link in localStorage for the schedules view to pick up
localStorage.setItem('pendingScheduleDeepLink', deepLink);
// Navigate to schedules view with the deep link in state
setView('schedules', { pendingScheduleDeepLink: deepLink });
setIsScheduleModalOpen(false);
}}
/>
</div>
Expand Down
9 changes: 4 additions & 5 deletions ui/desktop/src/components/recipes/RecipesView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@ import ImportRecipeForm, { ImportRecipeButton } from './ImportRecipeForm';
import CreateEditRecipeModal from './CreateEditRecipeModal';
import { generateDeepLink, Recipe } from '../../recipe';
import { ScheduleFromRecipeModal } from '../schedule/ScheduleFromRecipeModal';
import { useNavigation } from '../../hooks/useNavigation';

export default function RecipesView() {
const setView = useNavigation();
const [savedRecipes, setSavedRecipes] = useState<RecipeManifestResponse[]>([]);
const [loading, setLoading] = useState(true);
const [showSkeleton, setShowSkeleton] = useState(true);
Expand Down Expand Up @@ -160,11 +162,8 @@ export default function RecipesView() {
};

const handleCreateScheduleFromRecipe = async (deepLink: string) => {
// Store the deeplink for the schedule modal to pick up
localStorage.setItem('pendingScheduleDeepLink', deepLink);

// Navigate to schedules view and open create modal
window.location.hash = '#/schedules';
// Navigate to schedules view with the deep link in state
setView('schedules', { pendingScheduleDeepLink: deepLink });

setShowScheduleModal(false);
setSelectedRecipeForSchedule(null);
Expand Down
16 changes: 7 additions & 9 deletions ui/desktop/src/components/schedule/CreateScheduleModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ interface CreateScheduleModalProps {
onSubmit: (payload: NewSchedulePayload) => Promise<void>;
isLoadingExternally: boolean;
apiErrorExternally: string | null;
initialDeepLink?: string | null;
}

// Interface for clean extension in YAML
Expand Down Expand Up @@ -272,6 +273,7 @@ export const CreateScheduleModal: React.FC<CreateScheduleModalProps> = ({
onSubmit,
isLoadingExternally,
apiErrorExternally,
initialDeepLink,
}) => {
const [scheduleId, setScheduleId] = useState<string>('');
const [sourceType, setSourceType] = useState<SourceType>('file');
Expand Down Expand Up @@ -331,16 +333,12 @@ export const CreateScheduleModal: React.FC<CreateScheduleModalProps> = ({
);

useEffect(() => {
// Check for pending deep link when modal opens
if (isOpen) {
const pendingDeepLink = localStorage.getItem('pendingScheduleDeepLink');
if (pendingDeepLink) {
localStorage.removeItem('pendingScheduleDeepLink');
setSourceType('deeplink');
handleDeepLinkChange(pendingDeepLink);
}
// Check for initial deep link from props when modal opens
if (isOpen && initialDeepLink) {
setSourceType('deeplink');
handleDeepLinkChange(initialDeepLink);
}
}, [isOpen, handleDeepLinkChange]);
}, [isOpen, initialDeepLink, handleDeepLinkChange]);

const resetForm = () => {
setScheduleId('');
Expand Down
19 changes: 13 additions & 6 deletions ui/desktop/src/components/schedule/SchedulesView.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React, { useState, useEffect, useCallback, useMemo } from 'react';
import { useLocation } from 'react-router-dom';
import {
listSchedules,
createSchedule,
Expand All @@ -22,6 +23,7 @@ import { toastError, toastSuccess } from '../../toasts';
import cronstrue from 'cronstrue';
import { formatToLocalDateWithTimezone } from '../../utils/date';
import { MainPanelLayout } from '../Layout/MainPanelLayout';
import { ViewOptions } from '../../utils/navigationUtils';

interface SchedulesViewProps {
onClose?: () => void;
Expand Down Expand Up @@ -210,6 +212,7 @@ const ScheduleCard = React.memo<{
ScheduleCard.displayName = 'ScheduleCard';

const SchedulesView: React.FC<SchedulesViewProps> = ({ onClose: _onClose }) => {
const location = useLocation();
const [schedules, setSchedules] = useState<ScheduledJob[]>([]);
const [isLoading, setIsLoading] = useState(false);
const [isSubmitting, setIsSubmitting] = useState(false);
Expand All @@ -219,6 +222,7 @@ const SchedulesView: React.FC<SchedulesViewProps> = ({ onClose: _onClose }) => {
const [isEditModalOpen, setIsEditModalOpen] = useState(false);
const [editingSchedule, setEditingSchedule] = useState<ScheduledJob | null>(null);
const [isRefreshing, setIsRefreshing] = useState(false);
const [pendingDeepLink, setPendingDeepLink] = useState<string | null>(null);

// Individual loading states for each action to prevent double-clicks
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is pre-existing code below, but it feels like we should just have a state per schedule, no?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes good call, will come back to when we work on scheduler soon cc @amed-xyz

const [pausingScheduleIds, setPausingScheduleIds] = useState<Set<string>>(new Set());
Expand Down Expand Up @@ -257,15 +261,16 @@ const SchedulesView: React.FC<SchedulesViewProps> = ({ onClose: _onClose }) => {
if (viewingScheduleId === null) {
fetchSchedules();

// Check for pending deep link from recipe editor
const pendingDeepLink = localStorage.getItem('pendingScheduleDeepLink');
if (pendingDeepLink) {
localStorage.removeItem('pendingScheduleDeepLink');
// Check for pending deep link from navigation state
const locationState = location.state as ViewOptions | null;
if (locationState?.pendingScheduleDeepLink) {
setPendingDeepLink(locationState.pendingScheduleDeepLink);
setIsCreateModalOpen(true);
// The CreateScheduleModal will handle the deep link
// Clear the state after reading it
window.history.replaceState({}, document.title);
}
}
}, [viewingScheduleId, fetchSchedules]);
}, [viewingScheduleId, fetchSchedules, location.state]);

// Optimized periodic refresh - only refresh if not actively doing something
useEffect(() => {
Expand Down Expand Up @@ -320,6 +325,7 @@ const SchedulesView: React.FC<SchedulesViewProps> = ({ onClose: _onClose }) => {
const handleCloseCreateModal = () => {
setIsCreateModalOpen(false);
setSubmitApiError(null);
setPendingDeepLink(null);
};

const handleOpenEditModal = (schedule: ScheduledJob) => {
Expand Down Expand Up @@ -648,6 +654,7 @@ const SchedulesView: React.FC<SchedulesViewProps> = ({ onClose: _onClose }) => {
onSubmit={handleCreateScheduleSubmit}
isLoadingExternally={isSubmitting}
apiErrorExternally={submitApiError}
initialDeepLink={pendingDeepLink}
/>
<EditScheduleModal
isOpen={isEditModalOpen}
Expand Down
3 changes: 0 additions & 3 deletions ui/desktop/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -991,8 +991,6 @@ ipcMain.on('react-ready', () => {
log.info('No pending deep link to process');
}

// We don't need to handle pending deep links here anymore
// since we're handling them in the window creation flow
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good riddance

log.info('React ready - window is prepared for deep links');
});

Expand Down Expand Up @@ -1937,7 +1935,6 @@ async function appMain() {
// Log the recipe for debugging
console.log('Creating chat window with recipe:', recipe);

// Pass recipe as part of viewOptions when viewType is recipeEditor
createChat(
app,
query,
Expand Down
1 change: 1 addition & 0 deletions ui/desktop/src/utils/navigationUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export type ViewOptions = {
resetChat?: boolean;
shareToken?: string;
resumeSessionId?: string;
pendingScheduleDeepLink?: string;
};

export const createNavigationHandler = (navigate: NavigateFunction) => {
Expand Down
Loading