Revert "Mnovich/temporal scheduler (#2745)" (#2839)

This commit is contained in:
Max Novich
2025-06-09 15:41:46 -07:00
committed by GitHub
parent e6f89cde76
commit 996f727ec5
35 changed files with 172 additions and 4896 deletions
+1 -1
View File
@@ -336,7 +336,7 @@ export default function RecipeEditor({ config }: RecipeEditorProps) {
<button
onClick={() => setIsScheduleModalOpen(true)}
disabled={!requiredFieldsAreFilled()}
className="w-full h-[60px] rounded-none border-t text-gray-900 dark:text-white hover:bg-gray-50 dark:border-gray-600 text-lg font-medium"
className="w-full p-3 bg-green-500 text-white rounded-lg hover:bg-green-600 disabled:opacity-50 disabled:hover:bg-green-500"
>
Create Schedule from Recipe
</button>
@@ -7,7 +7,6 @@ import cronstrue from 'cronstrue';
import * as yaml from 'yaml';
import { Buffer } from 'buffer';
import { Recipe } from '../../recipe';
import ClockIcon from '../../assets/clock-icon.svg';
type FrequencyValue = 'once' | 'hourly' | 'daily' | 'weekly' | 'monthly';
@@ -500,24 +499,17 @@ export const CreateScheduleModal: React.FC<CreateScheduleModalProps> = ({
return (
<div className="fixed inset-0 bg-black/20 backdrop-blur-sm z-40 flex items-center justify-center p-4">
<Card className="w-full max-w-md bg-bgApp shadow-xl rounded-3xl z-50 flex flex-col max-h-[90vh] overflow-hidden">
<div className="px-8 pt-8 pb-4 flex-shrink-0 text-center">
<div className="flex flex-col items-center">
<img src={ClockIcon} alt="Clock" className="w-11 h-11 mb-2" />
<h2 className="text-base font-semibold text-gray-900 dark:text-white">
Create New Schedule
</h2>
<p className="text-base text-gray-500 dark:text-gray-400 mt-2 max-w-sm">
Create a new schedule using the settings below to do things like automatically run
tasks or create files
</p>
</div>
<Card className="w-full max-w-md bg-bgApp shadow-xl rounded-lg z-50 flex flex-col max-h-[90vh] overflow-hidden">
<div className="px-6 pt-6 pb-4 flex-shrink-0">
<h2 className="text-xl font-semibold text-gray-900 dark:text-white">
Create New Schedule
</h2>
</div>
<form
id="new-schedule-form"
onSubmit={handleLocalSubmit}
className="px-8 py-4 space-y-4 flex-grow overflow-y-auto"
className="px-6 py-4 space-y-4 flex-grow overflow-y-auto"
>
{apiErrorExternally && (
<p className="text-red-500 text-sm mb-3 p-2 bg-red-100 dark:bg-red-900/30 rounded-md border border-red-500/50">
@@ -532,7 +524,7 @@ export const CreateScheduleModal: React.FC<CreateScheduleModalProps> = ({
<div>
<label htmlFor="scheduleId-modal" className={modalLabelClassName}>
Name:
Schedule ID:
</label>
<Input
type="text"
@@ -545,30 +537,30 @@ export const CreateScheduleModal: React.FC<CreateScheduleModalProps> = ({
</div>
<div>
<label className={modalLabelClassName}>Source:</label>
<label className={modalLabelClassName}>Recipe Source:</label>
<div className="space-y-2">
<div className="flex bg-gray-100 dark:bg-gray-700 rounded-full p-1">
<div className="flex gap-2">
<button
type="button"
onClick={() => setSourceType('file')}
className={`flex-1 px-4 py-2 text-sm font-medium rounded-full transition-all ${
className={`px-3 py-2 text-sm rounded-md border ${
sourceType === 'file'
? 'bg-white dark:bg-gray-800 text-gray-900 dark:text-white shadow-sm'
: 'text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white'
? 'bg-blue-500 text-white border-blue-500'
: 'bg-gray-100 dark:bg-gray-700 text-gray-700 dark:text-gray-300 border-gray-300 dark:border-gray-600'
}`}
>
YAML
YAML File
</button>
<button
type="button"
onClick={() => setSourceType('deeplink')}
className={`flex-1 px-4 py-2 text-sm font-medium rounded-full transition-all ${
className={`px-3 py-2 text-sm rounded-md border ${
sourceType === 'deeplink'
? 'bg-white dark:bg-gray-800 text-gray-900 dark:text-white shadow-sm'
: 'text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white'
? 'bg-blue-500 text-white border-blue-500'
: 'bg-gray-100 dark:bg-gray-700 text-gray-700 dark:text-gray-300 border-gray-300 dark:border-gray-600'
}`}
>
Deep link
Deep Link
</button>
</div>
@@ -578,7 +570,7 @@ export const CreateScheduleModal: React.FC<CreateScheduleModalProps> = ({
type="button"
variant="outline"
onClick={handleBrowseFile}
className="w-full justify-center rounded-full"
className="w-full justify-center"
>
Browse for YAML file...
</Button>
@@ -597,7 +589,6 @@ export const CreateScheduleModal: React.FC<CreateScheduleModalProps> = ({
value={deepLinkInput}
onChange={(e) => handleDeepLinkChange(e.target.value)}
placeholder="Paste goose://bot or goose://recipe link here..."
className="rounded-full"
/>
{parsedRecipe && (
<div className="mt-2 p-2 bg-green-100 dark:bg-green-900/30 rounded-md border border-green-500/50">
@@ -748,15 +739,6 @@ export const CreateScheduleModal: React.FC<CreateScheduleModalProps> = ({
{/* Actions */}
<div className="mt-[8px] ml-[-24px] mr-[-24px] pt-[16px]">
<Button
type="submit"
form="new-schedule-form"
variant="ghost"
disabled={isLoadingExternally}
className="w-full h-[60px] rounded-none border-t text-gray-900 dark:text-white hover:bg-gray-50 dark:border-gray-600 text-lg font-medium"
>
{isLoadingExternally ? 'Creating...' : 'Create Schedule'}
</Button>
<Button
type="button"
variant="ghost"
@@ -766,6 +748,15 @@ export const CreateScheduleModal: React.FC<CreateScheduleModalProps> = ({
>
Cancel
</Button>
<Button
type="submit"
form="new-schedule-form"
variant="default"
disabled={isLoadingExternally}
className="w-full h-[60px] rounded-none border-t dark:border-gray-600 text-lg dark:text-white dark:border-gray-600 font-regular"
>
{isLoadingExternally ? 'Creating...' : 'Create Schedule'}
</Button>
</div>
</Card>
</div>
@@ -86,8 +86,12 @@ export const ScheduleFromRecipeModal: React.FC<ScheduleFromRecipeModalProps> = (
Recipe Details:
</h3>
<div className="bg-gray-50 dark:bg-gray-800 p-3 rounded-md">
<p className="text-sm font-medium text-gray-900 dark:text-white">{recipe.title}</p>
<p className="text-xs text-gray-600 dark:text-gray-400 mt-1">{recipe.description}</p>
<p className="text-sm font-medium text-gray-900 dark:text-white">
{recipe.title}
</p>
<p className="text-xs text-gray-600 dark:text-gray-400 mt-1">
{recipe.description}
</p>
</div>
</div>
@@ -96,13 +100,22 @@ export const ScheduleFromRecipeModal: React.FC<ScheduleFromRecipeModalProps> = (
Recipe Deep Link:
</label>
<div className="flex items-center">
<Input type="text" value={deepLink} readOnly className="flex-1 text-xs font-mono" />
<Input
type="text"
value={deepLink}
readOnly
className="flex-1 text-xs font-mono"
/>
<Button
type="button"
onClick={handleCopy}
className="ml-2 px-3 py-2 bg-blue-500 text-white rounded-md hover:bg-blue-600 flex items-center"
>
{copied ? <Check className="w-4 h-4" /> : <Copy className="w-4 h-4" />}
{copied ? (
<Check className="w-4 h-4" />
) : (
<Copy className="w-4 h-4" />
)}
</Button>
</div>
<p className="text-xs text-gray-500 dark:text-gray-400 mt-1">
@@ -116,14 +129,14 @@ export const ScheduleFromRecipeModal: React.FC<ScheduleFromRecipeModalProps> = (
type="button"
variant="outline"
onClick={handleClose}
className="flex-1 rounded-xl hover:bg-bgSubtle text-textSubtle"
className="flex-1"
>
Cancel
</Button>
<Button
type="button"
onClick={handleCreateSchedule}
className="flex-1 bg-bgAppInverse text-sm text-textProminentInverse rounded-xl hover:bg-bgStandardInverse transition-colors"
className="flex-1 bg-green-500 hover:bg-green-600 text-white"
>
Create Schedule
</Button>
@@ -16,12 +16,11 @@ import MoreMenuLayout from '../more_menu/MoreMenuLayout';
import { Card } from '../ui/card';
import { Button } from '../ui/button';
import { TrashIcon } from '../icons/TrashIcon';
import { Plus, RefreshCw, Pause, Play, Edit, Square, Eye, MoreHorizontal } from 'lucide-react';
import { Plus, RefreshCw, Pause, Play, Edit, Square, Eye } from 'lucide-react';
import { CreateScheduleModal, NewSchedulePayload } from './CreateScheduleModal';
import { EditScheduleModal } from './EditScheduleModal';
import ScheduleDetailView from './ScheduleDetailView';
import { toastError, toastSuccess } from '../../toasts';
import { Popover, PopoverContent, PopoverTrigger } from '../ui/popover';
import cronstrue from 'cronstrue';
interface SchedulesViewProps {
@@ -68,7 +67,7 @@ const SchedulesView: React.FC<SchedulesViewProps> = ({ onClose }) => {
useEffect(() => {
if (viewingScheduleId === null) {
fetchSchedules();
// Check for pending deep link from recipe editor
const pendingDeepLink = localStorage.getItem('pendingScheduleDeepLink');
if (pendingDeepLink) {
@@ -383,7 +382,7 @@ const SchedulesView: React.FC<SchedulesViewProps> = ({ onClose }) => {
onClick={handleRefresh}
disabled={isRefreshing || isLoading}
variant="outline"
className="w-full md:w-auto flex items-center gap-2 justify-center rounded-full [&>svg]:!size-4"
className="w-full md:w-auto flex items-center gap-2 justify-center"
>
<RefreshCw className={`h-4 w-4 ${isRefreshing ? 'animate-spin' : ''}`} />
{isRefreshing ? 'Refreshing...' : 'Refresh'}
@@ -454,118 +453,111 @@ const SchedulesView: React.FC<SchedulesViewProps> = ({ onClose }) => {
</p>
)}
</div>
<div className="flex-shrink-0">
<Popover>
<PopoverTrigger asChild>
<div className="flex-shrink-0 flex items-center gap-1">
{!job.currently_running && (
<>
<Button
variant="ghost"
size="icon"
onClick={(e) => {
e.stopPropagation();
handleOpenEditModal(job);
}}
className="text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300 hover:bg-gray-100/50 dark:hover:bg-gray-800/50"
className="text-gray-500 dark:text-gray-400 hover:text-blue-500 dark:hover:text-blue-400 hover:bg-blue-100/50 dark:hover:bg-blue-900/30"
title={`Edit schedule ${job.id}`}
disabled={
pausingScheduleIds.has(job.id) ||
deletingScheduleIds.has(job.id) ||
isSubmitting
}
>
<MoreHorizontal className="w-4 h-4" />
<Edit className="w-4 h-4" />
</Button>
</PopoverTrigger>
<PopoverContent
className="w-48 p-1 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-600 shadow-lg"
align="end"
>
<div className="space-y-1">
{!job.currently_running && (
<>
<button
onClick={(e) => {
e.stopPropagation();
handleOpenEditModal(job);
}}
disabled={
pausingScheduleIds.has(job.id) ||
deletingScheduleIds.has(job.id) ||
isSubmitting
}
className="w-full flex items-center justify-between px-3 py-2 text-sm text-gray-900 dark:text-white hover:bg-gray-100 dark:hover:bg-gray-700 rounded-md disabled:opacity-50 disabled:cursor-not-allowed"
>
<span>Edit</span>
<Edit className="w-4 h-4" />
</button>
<button
onClick={(e) => {
e.stopPropagation();
if (job.paused) {
handleUnpauseSchedule(job.id);
} else {
handlePauseSchedule(job.id);
}
}}
disabled={
pausingScheduleIds.has(job.id) ||
deletingScheduleIds.has(job.id)
}
className="w-full flex items-center justify-between px-3 py-2 text-sm text-gray-900 dark:text-white hover:bg-gray-100 dark:hover:bg-gray-700 rounded-md disabled:opacity-50 disabled:cursor-not-allowed"
>
<span>{job.paused ? 'Resume schedule' : 'Stop schedule'}</span>
{job.paused ? (
<Play className="w-4 h-4" />
) : (
<Pause className="w-4 h-4" />
)}
</button>
</>
)}
{job.currently_running && (
<>
<button
onClick={(e) => {
e.stopPropagation();
handleInspectRunningJob(job.id);
}}
disabled={
inspectingScheduleIds.has(job.id) ||
killingScheduleIds.has(job.id)
}
className="w-full flex items-center justify-between px-3 py-2 text-sm text-gray-900 dark:text-white hover:bg-gray-100 dark:hover:bg-gray-700 rounded-md disabled:opacity-50 disabled:cursor-not-allowed"
>
<span>Inspect</span>
<Eye className="w-4 h-4" />
</button>
<button
onClick={(e) => {
e.stopPropagation();
handleKillRunningJob(job.id);
}}
disabled={
killingScheduleIds.has(job.id) ||
inspectingScheduleIds.has(job.id)
}
className="w-full flex items-center justify-between px-3 py-2 text-sm text-gray-900 dark:text-white hover:bg-gray-100 dark:hover:bg-gray-700 rounded-md disabled:opacity-50 disabled:cursor-not-allowed"
>
<span>Kill job</span>
<Square className="w-4 h-4" />
</button>
</>
)}
<hr className="border-gray-200 dark:border-gray-600 my-1" />
<button
onClick={(e) => {
e.stopPropagation();
handleDeleteSchedule(job.id);
}}
disabled={
pausingScheduleIds.has(job.id) ||
deletingScheduleIds.has(job.id) ||
killingScheduleIds.has(job.id) ||
inspectingScheduleIds.has(job.id)
<Button
variant="ghost"
size="icon"
onClick={(e) => {
e.stopPropagation();
if (job.paused) {
handleUnpauseSchedule(job.id);
} else {
handlePauseSchedule(job.id);
}
className="w-full flex items-center justify-between px-3 py-2 text-sm text-red-600 dark:text-red-400 hover:bg-red-50 dark:hover:bg-red-900/20 rounded-md disabled:opacity-50 disabled:cursor-not-allowed"
>
<span>Delete</span>
<TrashIcon className="w-4 h-4" />
</button>
</div>
</PopoverContent>
</Popover>
}}
className={`${
job.paused
? 'text-green-500 dark:text-green-400 hover:text-green-600 dark:hover:text-green-300 hover:bg-green-100/50 dark:hover:bg-green-900/30'
: 'text-orange-500 dark:text-orange-400 hover:text-orange-600 dark:hover:text-orange-300 hover:bg-orange-100/50 dark:hover:bg-orange-900/30'
}`}
title={
job.paused
? `Unpause schedule ${job.id}`
: `Pause schedule ${job.id}`
}
disabled={
pausingScheduleIds.has(job.id) || deletingScheduleIds.has(job.id)
}
>
{job.paused ? (
<Play className="w-4 h-4" />
) : (
<Pause className="w-4 h-4" />
)}
</Button>
</>
)}
{job.currently_running && (
<>
<Button
variant="ghost"
size="icon"
onClick={(e) => {
e.stopPropagation();
handleInspectRunningJob(job.id);
}}
className="text-blue-500 dark:text-blue-400 hover:text-blue-600 dark:hover:text-blue-300 hover:bg-blue-100/50 dark:hover:bg-blue-900/30"
title={`Inspect running job ${job.id}`}
disabled={
inspectingScheduleIds.has(job.id) || killingScheduleIds.has(job.id)
}
>
<Eye className="w-4 h-4" />
</Button>
<Button
variant="ghost"
size="icon"
onClick={(e) => {
e.stopPropagation();
handleKillRunningJob(job.id);
}}
className="text-red-500 dark:text-red-400 hover:text-red-600 dark:hover:text-red-300 hover:bg-red-100/50 dark:hover:bg-red-900/30"
title={`Kill running job ${job.id}`}
disabled={
killingScheduleIds.has(job.id) || inspectingScheduleIds.has(job.id)
}
>
<Square className="w-4 h-4" />
</Button>
</>
)}
<Button
variant="ghost"
size="icon"
onClick={(e) => {
e.stopPropagation();
handleDeleteSchedule(job.id);
}}
className="text-gray-500 dark:text-gray-400 hover:text-red-500 dark:hover:text-red-400 hover:bg-red-100/50 dark:hover:bg-red-900/30"
title={`Delete schedule ${job.id}`}
disabled={
pausingScheduleIds.has(job.id) ||
deletingScheduleIds.has(job.id) ||
killingScheduleIds.has(job.id) ||
inspectingScheduleIds.has(job.id)
}
>
<TrashIcon className="w-5 h-5" />
</Button>
</div>
</div>
</Card>