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
1 change: 1 addition & 0 deletions client/.eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@
"text-success",
"text-success-foreground",
"text-surface-brand-primary",
"text-content-warning",
"w-112",
"w-appearance-theme-choice-skeleton-large-width",
"w-appearance-theme-choice-skeleton-small-width",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import {Button} from '@/components/ui/button';
import {Skeleton} from '@/components/ui/skeleton';
import {Tooltip, TooltipContent, TooltipTrigger} from '@/components/ui/tooltip';
import ProjectVersionHistorySheet from '@/pages/automation/project/components/ProjectVersionHistorySheet';
import ProjectHeaderDeleteProjectAlertDialog from '@/pages/automation/project/components/project-header/ProjectHeaderDeleteProjectAlertDialog';
import ProjectHeaderDeleteWorkflowAlertDialog from '@/pages/automation/project/components/project-header/ProjectHeaderDeleteWorkflowAlertDialog';
import ProjectHeaderOutputButton from '@/pages/automation/project/components/project-header/ProjectHeaderOutputButton';
import ProjectHeaderPublishPopover from '@/pages/automation/project/components/project-header/ProjectHeaderPublishPopover';
import ProjectHeaderSettingsMenu from '@/pages/automation/project/components/project-header/ProjectHeaderSettingsMenu';
import ProjectHeaderTitle from '@/pages/automation/project/components/project-header/ProjectHeaderTitle';
import ProjectHeaderWorkflowActionsButton from '@/pages/automation/project/components/project-header/ProjectHeaderWorkflowActionsButton';
import ProjectHeaderWorkflowSelect from '@/pages/automation/project/components/project-header/ProjectHeaderWorkflowSelect';
Expand Down Expand Up @@ -32,12 +34,12 @@ import {ProjectKeys, useGetProjectQuery} from '@/shared/queries/automation/proje
import {WorkflowKeys, useGetWorkflowQuery} from '@/shared/queries/automation/workflows.queries';
import {UpdateWorkflowMutationType} from '@/shared/types';
import {PlusIcon} from '@radix-ui/react-icons';
import {useQueryClient} from '@tanstack/react-query';
import {onlineManager, useIsFetching, useQueryClient} from '@tanstack/react-query';
import {CircleIcon, LoaderCircleIcon} from 'lucide-react';
import {RefObject, useCallback, useEffect, useState} from 'react';
import {ImperativePanelHandle} from 'react-resizable-panels';
import {useLoaderData, useNavigate, useSearchParams} from 'react-router-dom';

import ProjectHeaderSettingsMenu from './ProjectHeaderSettingsMenu';
import {twMerge} from 'tailwind-merge';

const workflowTestApi = new WorkflowTestApi();

Expand All @@ -59,6 +61,7 @@ const ProjectHeader = ({
const [showDeleteProjectAlertDialog, setShowDeleteProjectAlertDialog] = useState(false);
const [showDeleteWorkflowAlertDialog, setShowDeleteWorkflowAlertDialog] = useState(false);
const [showEditProjectDialog, setShowEditProjectDialog] = useState(false);
const [showProjectVersionHistorySheet, setShowProjectVersionHistorySheet] = useState(false);

const {
setShowBottomPanelOpen,
Expand All @@ -84,6 +87,10 @@ const ProjectHeader = ({

const queryClient = useQueryClient();

const isFetching = useIsFetching();

const isOnline = onlineManager.isOnline();

const createProjectWorkflowMutation = useCreateProjectWorkflowMutation({
onSuccess: (projectWorkflowId) => {
captureProjectWorkflowCreated();
Expand Down Expand Up @@ -274,11 +281,35 @@ const ProjectHeader = ({

<CopilotButton source={Source.WORKFLOW_EDITOR} />

<Tooltip>
<TooltipTrigger className="inline-flex size-9 cursor-pointer items-center justify-center rounded-md hover:bg-surface-neutral-primary-hover">
{isOnline && isFetching ? (
<LoaderCircleIcon className="size-3 animate-spin text-content-warning" />
) : (
<CircleIcon
className={twMerge(
'size-3 cursor-pointer fill-content-destructive text-content-destructive',
isOnline && !isFetching && 'fill-content-success text-content-success'
)}
/>
)}
</TooltipTrigger>

<TooltipContent>
{isOnline ? (
<>{!isFetching ? 'All changes are saved' : 'Saving your progress'}</>
) : (
'You are offline'
)}
</TooltipContent>
</Tooltip>

<ProjectHeaderSettingsMenu
project={project}
setShowDeleteProjectAlertDialog={setShowDeleteProjectAlertDialog}
setShowDeleteWorkflowAlertDialog={setShowDeleteWorkflowAlertDialog}
setShowEditProjectDialog={setShowEditProjectDialog}
setShowProjectVersionHistorySheet={setShowProjectVersionHistorySheet}
workflowId={workflow.id!}
/>

Expand Down Expand Up @@ -319,6 +350,15 @@ const ProjectHeader = ({
workflowId={workflow.id!}
/>
)}

{showProjectVersionHistorySheet && (
<ProjectVersionHistorySheet
onClose={() => {
setShowProjectVersionHistorySheet(false);
}}
projectId={Number(project.id!)}
/>
)}
</header>
);
};
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,29 +1,29 @@
import {Button} from '@/components/ui/button';
import {Separator} from '@/components/ui/separator';
import {useToast} from '@/hooks/use-toast';
import ProjectVersionHistorySheet from '@/pages/automation/project/components/ProjectVersionHistorySheet';
import ProjectHeaderHistoryButton from '@/pages/automation/project/components/project-header/ProjectHeaderHistoryButton';
import {useAnalytics} from '@/shared/hooks/useAnalytics';
import {Project} from '@/shared/middleware/automation/configuration';
import {useDuplicateProjectMutation} from '@/shared/mutations/automation/projects.mutations';
import {useCreateProjectWorkflowMutation} from '@/shared/mutations/automation/workflows.mutations';
import {ProjectKeys} from '@/shared/queries/automation/projects.queries';
import {useQueryClient} from '@tanstack/react-query';
import {CopyIcon, DownloadIcon, EditIcon, Trash2Icon} from 'lucide-react';
import {ChangeEvent, useRef, useState} from 'react';
import {CopyIcon, DownloadIcon, EditIcon, HistoryIcon, Trash2Icon} from 'lucide-react';
import {ChangeEvent, useRef} from 'react';
import {useNavigate} from 'react-router-dom';

const ProjectHeaderProjectTabButtons = ({
handleCloseDropdownMenu,
handleDeleteProject,
handleEditProject,
handleShowProjectVersionHistorySheet,
project,
}: {
handleCloseDropdownMenu: () => void;
handleDeleteProject: () => void;
handleEditProject: () => void;
handleShowProjectVersionHistorySheet: () => void;
project: Project;
}) => {
const [showProjectVersionHistorySheet, setShowProjectVersionHistorySheet] = useState(false);

const hiddenFileInputRef = useRef<HTMLInputElement>(null);

const {captureProjectWorkflowImported} = useAnalytics();
Expand Down Expand Up @@ -69,26 +69,32 @@ const ProjectHeaderProjectTabButtons = ({
}
};

const handleButtonClick = (event: React.MouseEvent<HTMLDivElement>) => {
if ((event.target as HTMLElement).tagName === 'BUTTON') {
handleCloseDropdownMenu();
}
};

return (
<div className="flex flex-col">
<div className="flex flex-col" onClick={handleButtonClick}>
<Button
className="justify-start hover:bg-surface-neutral-primary-hover"
className="justify-start rounded-none hover:bg-surface-neutral-primary-hover"
onClick={() => handleEditProject()}
variant="ghost"
>
<EditIcon /> Edit
</Button>

<Button
className="justify-start hover:bg-surface-neutral-primary-hover"
className="justify-start rounded-none hover:bg-surface-neutral-primary-hover"
onClick={() => duplicateProjectMutation.mutate(project.id!)}
variant="ghost"
>
<CopyIcon /> Duplicate
</Button>

<Button
className="justify-start hover:bg-surface-neutral-primary-hover"
className="justify-start rounded-none hover:bg-surface-neutral-primary-hover"
onClick={() => {
if (hiddenFileInputRef.current) {
hiddenFileInputRef.current.click();
Expand All @@ -101,30 +107,25 @@ const ProjectHeaderProjectTabButtons = ({

<Separator />

<ProjectHeaderHistoryButton
handleShowProjectVersionHistorySheet={() => setShowProjectVersionHistorySheet(true)}
/>
<Button
className="justify-start rounded-none hover:bg-surface-neutral-primary-hover"
onClick={() => handleShowProjectVersionHistorySheet()}
variant="ghost"
>
<HistoryIcon /> Project History
</Button>

<Separator />

<Button
className="justify-start text-destructive hover:bg-surface-error-secondary hover:text-destructive"
className="justify-start rounded-none text-destructive hover:bg-surface-error-secondary hover:text-destructive"
onClick={() => handleDeleteProject()}
variant="ghost"
>
<Trash2Icon /> Delete
</Button>

<input className="hidden" onChange={handleFileChange} ref={hiddenFileInputRef} type="file" />

{showProjectVersionHistorySheet && (
<ProjectVersionHistorySheet
onClose={() => {
setShowProjectVersionHistorySheet(false);
}}
projectId={Number(project.id!)}
/>
)}
</div>
);
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
import {Button} from '@/components/ui/button';
import {DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger} from '@/components/ui/dropdown-menu';
import {DropdownMenu, DropdownMenuContent, DropdownMenuTrigger} from '@/components/ui/dropdown-menu';
import {Tabs, TabsContent, TabsList, TabsTrigger} from '@/components/ui/tabs';
import {Tooltip, TooltipContent, TooltipTrigger} from '@/components/ui/tooltip';
import ProjectHeaderProjectTabButtons from '@/pages/automation/project/components/project-header/ProjectHeaderProjectTabButtons';
import ProjectHeaderWorkflowTabButtons from '@/pages/automation/project/components/project-header/ProjectHeaderWorkflowTabButtons';
import {Project} from '@/shared/middleware/automation/configuration';
import {SettingsIcon} from 'lucide-react';
import {useState} from 'react';

interface ProjectHeaderSettingsMenuProps {
project: Project;
setShowDeleteProjectAlertDialog: (value: boolean) => void;
setShowEditProjectDialog: (value: boolean) => void;
setShowDeleteWorkflowAlertDialog: (value: boolean) => void;
setShowProjectVersionHistorySheet: (value: boolean) => void;
workflowId: string;
}

Expand All @@ -19,49 +22,53 @@ const ProjectHeaderSettingsMenu = ({
setShowDeleteProjectAlertDialog,
setShowDeleteWorkflowAlertDialog,
setShowEditProjectDialog,
setShowProjectVersionHistorySheet,
workflowId,
}: ProjectHeaderSettingsMenuProps) => {
const handleTabClick = (event: React.MouseEvent) => {
event.stopPropagation();
};
const [openDropdownMenu, setOpenDropdownMenu] = useState(false);

return (
<Tabs defaultValue="workflow">
<DropdownMenu>
<DropdownMenuTrigger
asChild
className="cursor-pointer [&[data-state=open]]:bg-surface-brand-secondary [&[data-state=open]]:text-content-brand-primary-pressed"
>
<Button
className="hover:bg-surface-neutral-primary-hover active:bg-surface-brand-secondary active:text-content-brand-primary-pressed [&_svg]:size-5"
size="icon"
variant="ghost"
<DropdownMenu onOpenChange={setOpenDropdownMenu} open={openDropdownMenu}>
<Tooltip>
<TooltipTrigger asChild>
<DropdownMenuTrigger
asChild
className="cursor-pointer [&[data-state=open]]:bg-surface-brand-secondary [&[data-state=open]]:text-content-brand-primary-pressed"
>
<SettingsIcon />
</Button>
</DropdownMenuTrigger>
<Button
className="hover:bg-surface-neutral-primary-hover active:bg-surface-brand-secondary active:text-content-brand-primary-pressed [&_svg]:size-5"
size="icon"
variant="ghost"
>
<SettingsIcon />

<DropdownMenuContent className="p-0">
<DropdownMenuItem className="p-0">
<TabsList className="rounded-none" onClick={handleTabClick}>
<TabsTrigger
className="w-1/2 rounded-sm px-9 py-1 data-[state=active]:shadow-none"
value="workflow"
>
Workflow
</TabsTrigger>
<TooltipContent>Project and workflow settings</TooltipContent>
</Button>
</DropdownMenuTrigger>
</TooltipTrigger>
</Tooltip>

<TabsTrigger
className="w-1/2 rounded-sm px-9 py-1 data-[state=active]:shadow-none"
value="project"
>
Project
</TabsTrigger>
</TabsList>
</DropdownMenuItem>
<DropdownMenuContent className="p-0">
<Tabs defaultValue="workflow">
<TabsList className="rounded-none">
<TabsTrigger
className="w-1/2 rounded-sm px-9 py-1 data-[state=active]:shadow-none"
value="workflow"
>
Workflow
</TabsTrigger>

<TabsTrigger
className="w-1/2 rounded-sm px-9 py-1 data-[state=active]:shadow-none"
value="project"
>
Project
</TabsTrigger>
</TabsList>

<TabsContent className="mt-0" value="workflow">
<ProjectHeaderWorkflowTabButtons
handleCloseDropdownMenu={() => setOpenDropdownMenu(false)}
handleShowDeleteWorkflowAlertDialog={() => setShowDeleteWorkflowAlertDialog(true)}
project={project}
workflowId={workflowId}
Expand All @@ -70,14 +77,16 @@ const ProjectHeaderSettingsMenu = ({

<TabsContent className="mt-0" value="project">
<ProjectHeaderProjectTabButtons
handleCloseDropdownMenu={() => setOpenDropdownMenu(false)}
handleDeleteProject={() => setShowDeleteProjectAlertDialog(true)}
handleEditProject={() => setShowEditProjectDialog(true)}
handleShowProjectVersionHistorySheet={() => setShowProjectVersionHistorySheet(true)}
project={project}
/>
</TabsContent>
</DropdownMenuContent>
</DropdownMenu>
</Tabs>
</Tabs>
</DropdownMenuContent>
</DropdownMenu>
);
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,16 +45,19 @@ const ProjectHeaderWorkflowActionsButton = ({
</div>
</TooltipTrigger>

{workflowIsRunning && <TooltipContent>Stop the current workflow</TooltipContent>}
<TooltipContent className="mr-2 max-w-xs px-2">
{!runDisabled ? (
<>
{workflowIsRunning && 'Stop the current workflow'}

{!workflowIsRunning && (
<TooltipContent className="max-w-sm px-2">
{runDisabled
? `The workflow cannot be executed. Please set all required workflow input parameters, connections and
component properties.`
: `Run the current workflow`}
</TooltipContent>
)}
{!workflowIsRunning && chatTrigger && 'Start the chat'}

{!workflowIsRunning && !chatTrigger && 'Run the current workflow'}
</>
) : (
'The workflow cannot be executed. Please set all required workflow input parameters, connections and component properties.'
)}
</TooltipContent>
</Tooltip>
);
};
Expand Down
Loading
Loading