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
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,12 @@ export const useSettingsMenu = ({project, workflow}: {project: Project; workflow
const queryClient = useQueryClient();

const deleteProjectMutation = useDeleteProjectMutation({
onSuccess: () => {
onSuccess: (_, projectId) => {
navigate('/automation/projects');

queryClient.cancelQueries({queryKey: ProjectKeys.project(projectId)});
queryClient.removeQueries({queryKey: ProjectKeys.project(projectId)});

queryClient.invalidateQueries({queryKey: ProjectKeys.projects});
queryClient.invalidateQueries({
queryKey: ProjectCategoryKeys.projectCategories,
Expand Down
9 changes: 6 additions & 3 deletions client/src/pages/automation/projects/Projects.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import Header from '@/shared/layout/Header';
import LayoutContainer from '@/shared/layout/LayoutContainer';
import {useGetProjectCategoriesQuery} from '@/shared/queries/automation/projectCategories.queries';
import {useGetProjectTagsQuery} from '@/shared/queries/automation/projectTags.queries';
import {useGetWorkspaceProjectsQuery} from '@/shared/queries/automation/projects.queries';
import {ProjectKeys, useGetWorkspaceProjectsQuery} from '@/shared/queries/automation/projects.queries';
import {useApplicationInfoStore} from '@/shared/stores/useApplicationInfoStore';
import {useFeatureFlagsStore} from '@/shared/stores/useFeatureFlagsStore';
import {useQueryClient} from '@tanstack/react-query';
Expand All @@ -36,6 +36,8 @@ const Projects = () => {
const fileInputRef = useRef<HTMLInputElement>(null);
const navigate = useNavigate();

const queryClient = useQueryClient();

const ff_1039 = useFeatureFlagsStore()('ff-1039');
const ff_1041 = useFeatureFlagsStore()('ff-1041');
const ff_2482 = useFeatureFlagsStore()('ff-2482');
Expand Down Expand Up @@ -66,9 +68,9 @@ const Projects = () => {
tagId: searchParams.get('tagId') ? parseInt(searchParams.get('tagId')!) : undefined,
});

const {data: tags, error: tagsError, isLoading: tagsIsLoading} = useGetProjectTagsQuery();
const isRefetchingProjects = queryClient.isFetching({queryKey: ProjectKeys.projects}) > 0;

const queryClient = useQueryClient();
const {data: tags, error: tagsError, isLoading: tagsIsLoading} = useGetProjectTagsQuery();

return (
<LayoutContainer
Expand Down Expand Up @@ -128,6 +130,7 @@ const Projects = () => {
>
{projects && projects?.length > 0 && tags ? (
<ProjectList
isRefetchingProjects={isRefetchingProjects}
projectGitConfigurations={projectGitConfigurations ?? []}
projects={projects}
tags={tags}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@ import {Project, Tag} from '@/shared/middleware/automation/configuration';
import ProjectWorkflowList from '../project-workflow-list/ProjectWorkflowList';

const ProjectList = ({
isRefetchingProjects,
projectGitConfigurations,
projects,
tags,
}: {
isRefetchingProjects?: boolean;
projectGitConfigurations: ProjectGitConfiguration[];
projects: Project[];
tags: Tag[];
Expand All @@ -31,7 +33,7 @@ const ProjectList = ({
/>

<CollapsibleContent>
<ProjectWorkflowList project={project} />
<ProjectWorkflowList project={project} queryEnabled={!isRefetchingProjects} />
</CollapsibleContent>
</Collapsible>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ import {
UploadIcon,
WorkflowIcon,
} from 'lucide-react';
import {useCallback, useRef, useState} from 'react';
import {MouseEvent, useCallback, useRef, useState} from 'react';
import {Link, useNavigate, useSearchParams} from 'react-router-dom';

import TagList from '../../../../../shared/components/TagList';
Expand Down Expand Up @@ -109,7 +109,10 @@ const ProjectListItem = ({project, projectGitConfiguration, remainingTags}: Proj
});

const deleteProjectMutation = useDeleteProjectMutation({
onSuccess: () => {
onSuccess: (_, projectId) => {
queryClient.cancelQueries({queryKey: ProjectKeys.project(projectId)});
queryClient.removeQueries({queryKey: ProjectKeys.project(projectId)});

queryClient.invalidateQueries({queryKey: ProjectKeys.projects});
queryClient.invalidateQueries({
queryKey: ProjectCategoryKeys.projectCategories,
Expand Down Expand Up @@ -490,7 +493,11 @@ const ProjectListItem = ({project, projectGitConfiguration, remainingTags}: Proj

<DropdownMenuItem
className="dropdown-menu-item-destructive"
onClick={() => setShowDeleteDialog(true)}
onClick={(event: MouseEvent) => {
setShowDeleteDialog(true);

event.stopPropagation();
}}
Comment on lines +496 to +500
Copy link

Copilot AI Dec 23, 2025

Choose a reason for hiding this comment

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

The Delete dropdown menu item now includes event.stopPropagation(), but other dropdown menu items in the same menu (Publish, Edit, Duplicate, View Workflows, Share, Export, Pull Project from Git, Git Configuration) do not. While the handleProjectListItemClick function checks for .dropdown-menu-item selector to prevent propagation, this creates an inconsistency in how events are handled.

For consistency and clarity, either all dropdown menu items should call stopPropagation(), or none should (relying only on the selector-based check in handleProjectListItemClick). If there's a specific issue with the Delete button that required this fix, the same issue likely affects other menu items as well.

Copilot uses AI. Check for mistakes.
>
<Trash2Icon /> Delete
</DropdownMenuItem>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import {ChevronDownIcon, LayoutTemplateIcon, UploadIcon, WorkflowIcon} from 'luc
import {useRef, useState} from 'react';
import {useNavigate} from 'react-router-dom';

const ProjectWorkflowList = ({project}: {project: Project}) => {
const ProjectWorkflowList = ({project, queryEnabled}: {project: Project; queryEnabled?: boolean}) => {
const [showWorkflowDialog, setShowWorkflowDialog] = useState(false);

const {captureProjectWorkflowCreated, captureProjectWorkflowImported} = useAnalytics();
Expand All @@ -47,7 +47,7 @@ const ProjectWorkflowList = ({project}: {project: Project}) => {

const {data: workflows, isLoading: isProjectWorkflowsLoading} = useGetProjectWorkflowsQuery(
project.id!,
!!project.id
queryEnabled && !!project.id
Copy link

Copilot AI Dec 23, 2025

Choose a reason for hiding this comment

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

The logic queryEnabled && !!project.id will evaluate to undefined (falsy) when queryEnabled is undefined, which would disable the query by default. This is problematic because the prop is optional (queryEnabled?: boolean), meaning if this component is used elsewhere without explicitly passing this prop, the query would be unexpectedly disabled.

Consider using a default value to make the behavior more predictable. The condition should be (queryEnabled ?? true) && !!project.id or set a default parameter value in the function signature.

Suggested change
queryEnabled && !!project.id
(queryEnabled ?? true) && !!project.id

Copilot uses AI. Check for mistakes.
);

const workflowTaskDispatcherDefinitions: {
Expand Down
Loading