diff options
author | Ismail Cherri <ismail.cherri@sonarsource.com> | 2024-11-28 17:52:19 +0100 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2024-11-29 20:03:08 +0000 |
commit | 2183264c5d8cf31afc1fe8c54c32e59d9ebe118c (patch) | |
tree | fde0a1b80d3a3c243010ae47fe8a48ed8723b6cc | |
parent | 326ba4497003b65eea83f55087ca79df9bd2a6ad (diff) | |
download | sonarqube-2183264c5d8cf31afc1fe8c54c32e59d9ebe118c.tar.gz sonarqube-2183264c5d8cf31afc1fe8c54c32e59d9ebe118c.zip |
SONAR-23619 Invalidate project list cache when updating AI code status for project
3 files changed, 71 insertions, 45 deletions
diff --git a/server/sonar-web/src/main/js/apps/projectQualityGate/ProjectQualityGateApp.tsx b/server/sonar-web/src/main/js/apps/projectQualityGate/ProjectQualityGateApp.tsx index 73440e8f568..6456062b96b 100644 --- a/server/sonar-web/src/main/js/apps/projectQualityGate/ProjectQualityGateApp.tsx +++ b/server/sonar-web/src/main/js/apps/projectQualityGate/ProjectQualityGateApp.tsx @@ -21,8 +21,6 @@ import * as React from 'react'; import { addGlobalSuccessMessage } from '~design-system'; import { - associateGateWithProject, - dissociateGateWithProject, fetchQualityGate, fetchQualityGates, getGateForProject, @@ -46,7 +44,6 @@ interface State { currentQualityGate?: QualityGate; loading: boolean; selectedQualityGateName: string; - submitting: boolean; } class ProjectQualityGateApp extends React.PureComponent<Props, State> { @@ -54,7 +51,6 @@ class ProjectQualityGateApp extends React.PureComponent<Props, State> { state: State = { loading: true, selectedQualityGateName: USE_SYSTEM_DEFAULT, - submitting: false, }; componentDidMount() { @@ -140,41 +136,19 @@ class ProjectQualityGateApp extends React.PureComponent<Props, State> { this.setState({ selectedQualityGateName }); }; - handleSubmit = async () => { - const { component } = this.props; - const { allQualityGates, currentQualityGate, selectedQualityGateName } = this.state; - - if (allQualityGates === undefined || currentQualityGate === undefined) { - return; - } - - this.setState({ submitting: true }); - - if (selectedQualityGateName === USE_SYSTEM_DEFAULT) { - await dissociateGateWithProject({ - projectKey: component.key, - }).catch(() => { - /* noop */ - }); - } else { - await associateGateWithProject({ - gateName: selectedQualityGateName, - projectKey: component.key, - }).catch(() => { - /* noop */ - }); - } + handleSubmit = () => { + const { allQualityGates, selectedQualityGateName } = this.state; if (this.mounted) { addGlobalSuccessMessage(translate('project_quality_gate.successfully_updated')); const newGate = selectedQualityGateName === USE_SYSTEM_DEFAULT - ? allQualityGates.find((gate) => gate.isDefault) - : allQualityGates.find((gate) => gate.name === selectedQualityGateName); + ? allQualityGates?.find((gate) => gate.isDefault) + : allQualityGates?.find((gate) => gate.name === selectedQualityGateName); if (newGate) { - this.setState({ currentQualityGate: newGate, submitting: false }); + this.setState({ currentQualityGate: newGate }); this.props.onComponentChange({ qualityGate: newGate }); } } @@ -187,8 +161,7 @@ class ProjectQualityGateApp extends React.PureComponent<Props, State> { const { component } = this.props; - const { allQualityGates, currentQualityGate, loading, selectedQualityGateName, submitting } = - this.state; + const { allQualityGates, currentQualityGate, loading, selectedQualityGateName } = this.state; return ( <ProjectQualityGateAppRenderer @@ -199,7 +172,6 @@ class ProjectQualityGateApp extends React.PureComponent<Props, State> { onSubmit={this.handleSubmit} onSelect={this.handleSelect} selectedQualityGateName={selectedQualityGateName} - submitting={submitting} /> ); } diff --git a/server/sonar-web/src/main/js/apps/projectQualityGate/ProjectQualityGateAppRenderer.tsx b/server/sonar-web/src/main/js/apps/projectQualityGate/ProjectQualityGateAppRenderer.tsx index 40f9711c118..0f45c794ee7 100644 --- a/server/sonar-web/src/main/js/apps/projectQualityGate/ProjectQualityGateAppRenderer.tsx +++ b/server/sonar-web/src/main/js/apps/projectQualityGate/ProjectQualityGateAppRenderer.tsx @@ -53,6 +53,10 @@ import { isDiffMetric } from '../../helpers/measures'; import { LabelValueSelectOption } from '../../helpers/search'; import { getQualityGateUrl } from '../../helpers/urls'; import { useProjectAiCodeAssuranceStatusQuery } from '../../queries/ai-code-assurance'; +import { + useAssociateGateWithProjectMutation, + useDissociateGateWithProjectMutation, +} from '../../queries/quality-gates'; import { ComponentQualifier } from '../../sonar-aligned/types/component'; import { Feature } from '../../types/features'; import { Component, QualityGate } from '../../types/types'; @@ -67,9 +71,8 @@ export interface ProjectQualityGateAppRendererProps extends WithAvailableFeature currentQualityGate?: QualityGate; loading: boolean; onSelect: (id: string) => void; - onSubmit: () => Promise<void>; + onSubmit: () => void; selectedQualityGateName: string; - submitting: boolean; } function hasConditionOnNewCode(qualityGate: QualityGate): boolean { @@ -123,14 +126,8 @@ function singleValueRenderer(props: SingleValueProps<QualityGateOption, false>) } function ProjectQualityGateAppRenderer(props: Readonly<ProjectQualityGateAppRendererProps>) { - const { - allQualityGates, - component, - currentQualityGate, - loading, - selectedQualityGateName, - submitting, - } = props; + const { allQualityGates, component, currentQualityGate, loading, selectedQualityGateName } = + props; const defaultQualityGate = allQualityGates?.find((g) => g.isDefault); const [isUserEditing, setIsUserEditing] = useState(false); @@ -144,6 +141,33 @@ function ProjectQualityGateAppRenderer(props: Readonly<ProjectQualityGateAppRend }, ); + const { mutateAsync: associateGateWithProject, isPending: associateIsPending } = + useAssociateGateWithProjectMutation(); + const { mutateAsync: dissociateGateWithProject, isPending: dissociateisPending } = + useDissociateGateWithProjectMutation(); + const submitting = associateIsPending || dissociateisPending; + + const handleSubmit = async () => { + const { allQualityGates, currentQualityGate, selectedQualityGateName } = props; + + if (allQualityGates === undefined || currentQualityGate === undefined) { + return; + } + + if (selectedQualityGateName === USE_SYSTEM_DEFAULT) { + await dissociateGateWithProject({ + projectKey: component.key, + }); + } else { + await associateGateWithProject({ + gateName: selectedQualityGateName, + projectKey: component.key, + }); + } + + props.onSubmit(); + }; + if (loading) { return <Spinner />; } @@ -272,7 +296,7 @@ function ProjectQualityGateAppRenderer(props: Readonly<ProjectQualityGateAppRend <form onSubmit={async (e) => { e.preventDefault(); - await props.onSubmit(); + await handleSubmit(); setIsUserEditing(false); refetchAiCodeAssuranceStatus(); }} diff --git a/server/sonar-web/src/main/js/queries/quality-gates.ts b/server/sonar-web/src/main/js/queries/quality-gates.ts index caff5bb8257..448755f2872 100644 --- a/server/sonar-web/src/main/js/queries/quality-gates.ts +++ b/server/sonar-web/src/main/js/queries/quality-gates.ts @@ -23,11 +23,13 @@ import { useIntl } from 'react-intl'; import { addGlobalSuccessMessage } from '~design-system'; import { BranchParameters } from '~sonar-aligned/types/branch-like'; import { + associateGateWithProject, copyQualityGate, createCondition, createQualityGate, deleteCondition, deleteQualityGate, + dissociateGateWithProject, fetchQualityGate, fetchQualityGates, getAllQualityGateProjects, @@ -200,6 +202,34 @@ export function useSetAiSupportedQualityGateMutation(name: string) { }); } +export function useAssociateGateWithProjectMutation() { + const queryClient = useQueryClient(); + + return useMutation({ + mutationFn: (data: { gateName: string; projectKey: string }) => { + return associateGateWithProject(data); + }, + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: qualityQuery.projectsAssoc() }); + queryClient.invalidateQueries({ queryKey: ['project', 'list'] }); + }, + }); +} + +export function useDissociateGateWithProjectMutation() { + const queryClient = useQueryClient(); + + return useMutation({ + mutationFn: (data: { projectKey: string }) => { + return dissociateGateWithProject(data); + }, + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: qualityQuery.projectsAssoc() }); + queryClient.invalidateQueries({ queryKey: ['project', 'list'] }); + }, + }); +} + export function useFixQualityGateMutation(gateName: string) { const queryClient = useQueryClient(); |