Merge triggers and job rules into single view and remove dropdown triggers modal

This commit is contained in:
akhisud3195 2025-08-19 11:29:33 +05:30
parent 35c2f51c8e
commit 105d1ae190
6 changed files with 46 additions and 82 deletions

View file

@ -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>

View file

@ -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({
)}
</>
);
}
}

View file

@ -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(

View file

@ -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 ? (
<>

View file

@ -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>
);

View file

@ -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',