mirror of
https://github.com/rowboatlabs/rowboat.git
synced 2026-04-30 19:06:23 +02:00
Merge triggers and job rules into single view and remove dropdown triggers modal
This commit is contained in:
parent
35c2f51c8e
commit
105d1ae190
6 changed files with 46 additions and 82 deletions
|
|
@ -4,9 +4,10 @@ import { useState } from "react";
|
|||
import { Tabs, Tab } from "@/components/ui/tabs";
|
||||
import { ScheduledJobRulesList } from "../scheduled/components/scheduled-job-rules-list";
|
||||
import { RecurringJobRulesList } from "./recurring-job-rules-list";
|
||||
import { TriggersTab } from "./triggers-tab";
|
||||
|
||||
export function JobRulesTabs({ projectId }: { projectId: string }) {
|
||||
const [activeTab, setActiveTab] = useState<string>("scheduled");
|
||||
const [activeTab, setActiveTab] = useState<string>("triggers");
|
||||
|
||||
const handleTabChange = (key: React.Key) => {
|
||||
setActiveTab(key.toString());
|
||||
|
|
@ -20,10 +21,13 @@ export function JobRulesTabs({ projectId }: { projectId: string }) {
|
|||
aria-label="Job Rules"
|
||||
fullWidth
|
||||
>
|
||||
<Tab key="scheduled" title="Scheduled Rules">
|
||||
<Tab key="triggers" title="Triggers">
|
||||
<TriggersTab projectId={projectId} />
|
||||
</Tab>
|
||||
<Tab key="scheduled" title="One-time">
|
||||
<ScheduledJobRulesList projectId={projectId} />
|
||||
</Tab>
|
||||
<Tab key="recurring" title="Recurring Rules">
|
||||
<Tab key="recurring" title="Recurring">
|
||||
<RecurringJobRulesList projectId={projectId} />
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
|
|
|||
|
|
@ -1,36 +1,23 @@
|
|||
'use client';
|
||||
|
||||
import React, { useState, useEffect, useCallback } from 'react';
|
||||
import { Modal, ModalContent, ModalHeader, ModalBody, ModalFooter, Button, Spinner, Card, CardBody, CardHeader } from '@heroui/react';
|
||||
import { Button, Spinner, Card, CardBody, CardHeader } from '@heroui/react';
|
||||
import { Plus, Trash2, ZapIcon } from 'lucide-react';
|
||||
import { z } from 'zod';
|
||||
import { ComposioTriggerDeployment } from '@/src/entities/models/composio-trigger-deployment';
|
||||
import { ComposioTriggerType } from '@/src/entities/models/composio-trigger-type';
|
||||
import { listComposioTriggerDeployments, deleteComposioTriggerDeployment, createComposioTriggerDeployment } from '@/app/actions/composio.actions';
|
||||
import { SelectComposioToolkit } from '../../tools/components/SelectComposioToolkit';
|
||||
import { ComposioTriggerTypesPanel } from './ComposioTriggerTypesPanel';
|
||||
import { TriggerConfigForm } from './TriggerConfigForm';
|
||||
import { ComposioTriggerTypesPanel } from '../../workflow/components/ComposioTriggerTypesPanel';
|
||||
import { TriggerConfigForm } from '../../workflow/components/TriggerConfigForm';
|
||||
import { ToolkitAuthModal } from '../../tools/components/ToolkitAuthModal';
|
||||
import { ZToolkit } from "@/src/application/lib/composio/types";
|
||||
import { Project } from "@/src/entities/models/project";
|
||||
|
||||
interface TriggersModalProps {
|
||||
isOpen: boolean;
|
||||
onClose: () => void;
|
||||
projectId: string;
|
||||
projectConfig: z.infer<typeof Project>;
|
||||
onProjectConfigUpdated?: () => void;
|
||||
}
|
||||
import { fetchProject } from '@/app/actions/project.actions';
|
||||
|
||||
type TriggerDeployment = z.infer<typeof ComposioTriggerDeployment>;
|
||||
|
||||
export function TriggersModal({
|
||||
isOpen,
|
||||
onClose,
|
||||
projectId,
|
||||
projectConfig,
|
||||
onProjectConfigUpdated,
|
||||
}: TriggersModalProps) {
|
||||
export function TriggersTab({ projectId }: { projectId: string }) {
|
||||
const [triggers, setTriggers] = useState<TriggerDeployment[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
|
@ -40,6 +27,16 @@ export function TriggersModal({
|
|||
const [showAuthModal, setShowAuthModal] = useState(false);
|
||||
const [isSubmittingTrigger, setIsSubmittingTrigger] = useState(false);
|
||||
const [deletingTrigger, setDeletingTrigger] = useState<string | null>(null);
|
||||
const [projectConfig, setProjectConfig] = useState<z.infer<typeof Project> | null>(null);
|
||||
|
||||
const loadProjectConfig = useCallback(async () => {
|
||||
try {
|
||||
const config = await fetchProject(projectId);
|
||||
setProjectConfig(config);
|
||||
} catch (err: any) {
|
||||
console.error('Error fetching project config:', err);
|
||||
}
|
||||
}, [projectId]);
|
||||
|
||||
const loadTriggers = useCallback(async () => {
|
||||
try {
|
||||
|
|
@ -115,7 +112,7 @@ export function TriggersModal({
|
|||
|
||||
const handleAuthComplete = async () => {
|
||||
setShowAuthModal(false);
|
||||
onProjectConfigUpdated?.();
|
||||
await loadProjectConfig(); // Refresh project config
|
||||
};
|
||||
|
||||
const handleTriggerSubmit = async (triggerConfig: Record<string, unknown>) => {
|
||||
|
|
@ -151,10 +148,14 @@ export function TriggersModal({
|
|||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (isOpen && !showCreateFlow) {
|
||||
loadProjectConfig();
|
||||
}, [loadProjectConfig]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!showCreateFlow) {
|
||||
loadTriggers();
|
||||
}
|
||||
}, [isOpen, showCreateFlow, loadTriggers]);
|
||||
}, [showCreateFlow, loadTriggers]);
|
||||
|
||||
const renderTriggerList = () => {
|
||||
if (loading) {
|
||||
|
|
@ -319,31 +320,11 @@ export function TriggersModal({
|
|||
|
||||
return (
|
||||
<>
|
||||
<Modal
|
||||
isOpen={isOpen}
|
||||
onClose={onClose}
|
||||
size="5xl"
|
||||
scrollBehavior="inside"
|
||||
>
|
||||
<ModalContent className="max-h-[90vh]">
|
||||
<ModalHeader>
|
||||
<div className="flex items-center gap-2">
|
||||
<ZapIcon className="w-5 h-5" />
|
||||
<span>Manage Triggers</span>
|
||||
</div>
|
||||
</ModalHeader>
|
||||
<ModalBody>
|
||||
{showCreateFlow ? renderCreateFlow() : renderTriggerList()}
|
||||
</ModalBody>
|
||||
{!showCreateFlow && (
|
||||
<ModalFooter>
|
||||
<Button variant="light" onPress={onClose}>
|
||||
Close
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
)}
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
<div className="h-full overflow-auto px-4 py-4">
|
||||
<div className="max-w-[1024px] mx-auto">
|
||||
{showCreateFlow ? renderCreateFlow() : renderTriggerList()}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Auth Modal */}
|
||||
{selectedToolkit && (
|
||||
|
|
@ -357,4 +338,4 @@ export function TriggersModal({
|
|||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -3,7 +3,7 @@ import { requireActiveBillingSubscription } from '@/app/lib/billing';
|
|||
import { JobRulesTabs } from "./components/job-rules-tabs";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Job Rules",
|
||||
title: "Triggers",
|
||||
};
|
||||
|
||||
export default async function Page(
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ interface TopBarProps {
|
|||
localProjectName: string;
|
||||
projectNameError: string | null;
|
||||
onProjectNameChange: (value: string) => void;
|
||||
onProjectNameCommit: (value: string) => void;
|
||||
onProjectNameCommit: (value: string) => Promise<void>;
|
||||
publishing: boolean;
|
||||
isLive: boolean;
|
||||
showCopySuccess: boolean;
|
||||
|
|
@ -23,7 +23,6 @@ interface TopBarProps {
|
|||
onRevertToLive: () => void;
|
||||
onToggleCopilot: () => void;
|
||||
onSettingsModalOpen: () => void;
|
||||
onTriggersModalOpen: () => void;
|
||||
}
|
||||
|
||||
export function TopBar({
|
||||
|
|
@ -45,7 +44,6 @@ export function TopBar({
|
|||
onRevertToLive,
|
||||
onToggleCopilot,
|
||||
onSettingsModalOpen,
|
||||
onTriggersModalOpen,
|
||||
}: TopBarProps) {
|
||||
const router = useRouter();
|
||||
const params = useParams();
|
||||
|
|
@ -168,16 +166,9 @@ export function TopBar({
|
|||
<DropdownItem
|
||||
key="manage-triggers"
|
||||
startContent={<ZapIcon size={16} />}
|
||||
onPress={onTriggersModalOpen}
|
||||
>
|
||||
Manage triggers
|
||||
</DropdownItem>
|
||||
<DropdownItem
|
||||
key="go-to-schedule-runs"
|
||||
startContent={<Clock size={16} />}
|
||||
onPress={() => { if (projectId) { router.push(`/projects/${projectId}/job-rules`); } }}
|
||||
>
|
||||
Go to schedule runs
|
||||
Manage triggers
|
||||
</DropdownItem>
|
||||
{!isLive ? (
|
||||
<>
|
||||
|
|
|
|||
|
|
@ -37,7 +37,6 @@ import { Button as CustomButton } from "@/components/ui/button";
|
|||
import { ConfigApp } from "../config/app";
|
||||
import { InputField } from "@/app/lib/components/input-field";
|
||||
import { VoiceSection } from "../config/components/voice";
|
||||
import { TriggersModal } from "./components/TriggersModal";
|
||||
import { TopBar } from "./components/TopBar";
|
||||
|
||||
enablePatches();
|
||||
|
|
@ -882,9 +881,6 @@ export function WorkflowEditor({
|
|||
// Modal state for chat widget configuration
|
||||
const { isOpen: isChatWidgetModalOpen, onOpen: onChatWidgetModalOpen, onClose: onChatWidgetModalClose } = useDisclosure();
|
||||
|
||||
// Modal state for triggers management
|
||||
const { isOpen: isTriggersModalOpen, onOpen: onTriggersModalOpen, onClose: onTriggersModalClose } = useDisclosure();
|
||||
|
||||
// Project name state
|
||||
const [localProjectName, setLocalProjectName] = useState<string>(projectConfig.name || '');
|
||||
const [projectNameError, setProjectNameError] = useState<string | null>(null);
|
||||
|
|
@ -1285,7 +1281,6 @@ export function WorkflowEditor({
|
|||
onRevertToLive={handleRevertToLive}
|
||||
onToggleCopilot={() => setShowCopilot(!showCopilot)}
|
||||
onSettingsModalOpen={onSettingsModalOpen}
|
||||
onTriggersModalOpen={onTriggersModalOpen}
|
||||
/>
|
||||
|
||||
{/* Content Area */}
|
||||
|
|
@ -1565,14 +1560,6 @@ export function WorkflowEditor({
|
|||
</Modal>
|
||||
*/}
|
||||
|
||||
{/* Triggers Management Modal */}
|
||||
<TriggersModal
|
||||
isOpen={isTriggersModalOpen}
|
||||
onClose={onTriggersModalClose}
|
||||
projectId={projectId}
|
||||
projectConfig={projectConfig}
|
||||
onProjectConfigUpdated={onProjectConfigUpdated}
|
||||
/>
|
||||
</div>
|
||||
</EntitySelectionContext.Provider>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -17,7 +17,8 @@ import {
|
|||
HelpCircle,
|
||||
MessageSquareIcon,
|
||||
LogsIcon,
|
||||
Clock
|
||||
Clock,
|
||||
ZapIcon
|
||||
} from "lucide-react";
|
||||
import { fetchProject } from "@/app/actions/project.actions";
|
||||
import { createProjectWithOptions } from "../../lib/project-creation-utils";
|
||||
|
|
@ -102,6 +103,12 @@ export default function Sidebar({ projectId, useAuth, collapsed = false, onToggl
|
|||
icon: WorkflowIcon,
|
||||
requiresProject: true
|
||||
},
|
||||
{
|
||||
href: 'job-rules',
|
||||
label: 'Triggers',
|
||||
icon: ZapIcon,
|
||||
requiresProject: true
|
||||
},
|
||||
{
|
||||
href: 'conversations',
|
||||
label: 'Conversations',
|
||||
|
|
@ -114,12 +121,6 @@ export default function Sidebar({ projectId, useAuth, collapsed = false, onToggl
|
|||
icon: LogsIcon,
|
||||
requiresProject: true
|
||||
},
|
||||
{
|
||||
href: 'job-rules',
|
||||
label: 'Job Rules',
|
||||
icon: Clock,
|
||||
requiresProject: true
|
||||
},
|
||||
{
|
||||
href: 'config',
|
||||
label: 'Settings',
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue