}
export function getMeasuresPageMetricKeys(metrics: Dict<Metric>, branch?: BranchLike) {
- // ToDo rollback once new metrics are available
- const metricKeys = [
- ...getDisplayMetrics(Object.values(metrics)).map((metric) => metric.key),
- ...SOFTWARE_QUALITY_RATING_METRICS,
- ];
+ const metricKeys = getDisplayMetrics(Object.values(metrics)).map((metric) => metric.key);
if (isPullRequest(branch)) {
return metricKeys.filter((key) => isDiffMetric(key));
])
: BRANCH_OVERVIEW_METRICS
: BRANCH_OVERVIEW_METRICS,
- branchParameters: getBranchLikeQuery(branch),
});
const getEnhancedConditions = (
import { withRouter } from '~sonar-aligned/components/hoc/withRouter';
import { isPortfolioLike } from '~sonar-aligned/helpers/component';
import { Router } from '~sonar-aligned/types/router';
-import { deleteApplication } from '../../api/application';
-import { deletePortfolio, deleteProject } from '../../api/project-management';
import ConfirmButton from '../../components/controls/ConfirmButton';
import { translate, translateWithParameters } from '../../helpers/l10n';
+import { useDeleteApplicationMutation } from '../../queries/applications';
+import { useDeletePortfolioMutation } from '../../queries/portfolios';
+import { useDeleteProjectMutation } from '../../queries/projects';
import { isApplication } from '../../types/component';
import { Component } from '../../types/types';
router: Router;
}
-export class Form extends React.PureComponent<Props> {
- handleDelete = async () => {
- const { component } = this.props;
+export function Form({ component, router }: Readonly<Props>) {
+ const { mutate: deleteProject } = useDeleteProjectMutation();
+ const { mutate: deleteApplication } = useDeleteApplicationMutation();
+ const { mutate: deletePortfolio } = useDeletePortfolioMutation();
+
+ const handleDelete = () => {
let deleteMethod = deleteProject;
let redirectTo = '/';
deleteMethod = deleteApplication;
}
- await deleteMethod(component.key);
-
- addGlobalSuccessMessage(
- translateWithParameters('project_deletion.resource_deleted', component.name),
- );
+ deleteMethod(component.key, {
+ onSuccess: () => {
+ addGlobalSuccessMessage(
+ translateWithParameters('project_deletion.resource_deleted', component.name),
+ );
- this.props.router.replace(redirectTo);
+ router.replace(redirectTo);
+ },
+ });
};
- render() {
- const { component } = this.props;
- return (
- <ConfirmButton
- confirmButtonText={translate('delete')}
- isDestructive
- modalBody={translateWithParameters(
- 'project_deletion.delete_resource_confirmation',
- component.name,
- )}
- modalHeader={translate('qualifier.delete', component.qualifier)}
- onConfirm={this.handleDelete}
- >
- {({ onClick }) => (
- <Button id="delete-project" onClick={onClick} variety={ButtonVariety.Danger}>
- {translate('delete')}
- </Button>
- )}
- </ConfirmButton>
- );
- }
+ return (
+ <ConfirmButton
+ confirmButtonText={translate('delete')}
+ isDestructive
+ modalBody={translateWithParameters(
+ 'project_deletion.delete_resource_confirmation',
+ component.name,
+ )}
+ modalHeader={translate('qualifier.delete', component.qualifier)}
+ onConfirm={handleDelete}
+ >
+ {({ onClick }) => (
+ <Button id="delete-project" onClick={onClick} variety={ButtonVariety.Danger}>
+ {translate('delete')}
+ </Button>
+ )}
+ </ConfirmButton>
+ );
}
export default withRouter(Form);
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-import { useQuery } from '@tanstack/react-query';
-import { getApplicationLeak } from '../api/application';
+import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
+import { deleteApplication, getApplicationLeak } from '../api/application';
+import { invalidateMeasuresByComponentKey } from './measures';
export default function useApplicationLeakQuery(application: string, enabled = true) {
return useQuery({
enabled,
});
}
+
+export function useDeleteApplicationMutation() {
+ const queryClient = useQueryClient();
+ return useMutation({
+ mutationFn: (key: string) => deleteApplication(key),
+ onSuccess: (_, key) => {
+ invalidateMeasuresByComponentKey(key, queryClient);
+ },
+ });
+}
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-import { infiniteQueryOptions, queryOptions, useQueryClient } from '@tanstack/react-query';
+import {
+ infiniteQueryOptions,
+ QueryClient,
+ queryOptions,
+ useQueryClient,
+} from '@tanstack/react-query';
import { groupBy, isUndefined, omitBy } from 'lodash';
import { BranchParameters } from '~sonar-aligned/types/branch-like';
import { getComponentTree } from '../api/components';
import { getBranchLikeQuery } from '../sonar-aligned/helpers/branch-like';
import { BranchLike } from '../types/branch-like';
import { Measure } from '../types/types';
-import { createInfiniteQueryHook, createQueryHook, StaleTime } from './common';
+import { createInfiniteQueryHook, createQueryHook } from './common';
+
+export const invalidateMeasuresByComponentKey = (
+ componentKey: string,
+ queryClient: QueryClient,
+) => {
+ queryClient.invalidateQueries({ queryKey: ['measures', 'history', componentKey] });
+ queryClient.invalidateQueries({ queryKey: ['measures', 'component', componentKey] });
+ queryClient.invalidateQueries({ queryKey: ['measures', 'details', componentKey] });
+ queryClient.invalidateQueries({ queryKey: ['measures', 'list', componentKey] });
+ queryClient.invalidateQueries({
+ predicate: (query) =>
+ query.queryKey[0] === 'measures' &&
+ query.queryKey[1] === 'list' &&
+ query.queryKey[2] === 'projects' &&
+ Array.isArray(query.queryKey[3]) &&
+ query.queryKey[3].includes(componentKey),
+ });
+};
+
+export const invalidateAllMeasures = (queryClient: QueryClient) => {
+ queryClient.invalidateQueries({ queryKey: ['measures'] });
+};
export const useAllMeasuresHistoryQuery = createQueryHook(
({
const branchLikeQuery = getBranchLikeQuery(branchLike);
return queryOptions({
- queryKey: ['measures', 'component', componentKey, 'branchLike', branchLikeQuery, metricKeys],
+ queryKey: [
+ 'measures',
+ 'component',
+ componentKey,
+ 'branchLike',
+ { ...branchLikeQuery },
+ metricKeys,
+ ],
queryFn: async () => {
const data = await getMeasuresWithPeriodAndMetrics(
componentKey,
const measure =
data.component.measures?.find((measure) => measure.metric === metricKey) ?? null;
queryClient.setQueryData<Measure | null>(
- ['measures', 'details', componentKey, 'branchLike', branchLikeQuery, metricKey],
+ ['measures', 'details', componentKey, 'branchLike', { ...branchLikeQuery }, metricKey],
measure,
);
});
const queryClient = useQueryClient();
return infiniteQueryOptions({
- queryKey: ['component', component, 'tree', strategy, { metrics, additionalData }],
+ queryKey: ['measures', 'component', component, 'tree', strategy, { metrics, additionalData }],
queryFn: async ({ pageParam }) => {
const result = await getComponentTree(strategy, component, metrics, {
...additionalData,
'details',
result.baseComponent.key,
'branchLike',
- branchLikeQuery,
+ { ...branchLikeQuery },
metricKey,
],
measure,
metrics?.forEach((metricKey) => {
const measure = measuresMapByMetricKeyForChildComponent[metricKey]?.[0] ?? null;
queryClient.setQueryData<Measure>(
- ['measures', 'details', childComponent.key, 'branchLike', branchLikeQuery, metricKey],
+ [
+ 'measures',
+ 'details',
+ childComponent.key,
+ 'branchLike',
+ { ...branchLikeQuery },
+ metricKey,
+ ],
measure,
);
});
componentKey,
metricKeys,
branchLike,
- branchParameters,
}: {
branchLike?: BranchLike;
- branchParameters?: BranchParameters;
componentKey: string;
metricKeys: string[];
}) => {
const queryClient = useQueryClient();
+ const branchParameters = getBranchLikeQuery(branchLike);
return queryOptions({
queryKey: [
'measures',
'details',
- 'component',
componentKey,
+ 'branchLike',
+ { ...branchParameters },
metricKeys,
- branchLike,
- branchParameters,
],
queryFn: async () => {
const { component, metrics, period } = await getMeasuresWithPeriodAndMetrics(
metricKeys.forEach((metricKey) => {
const measure = measuresMapByMetricKey[metricKey]?.[0] ?? null;
queryClient.setQueryData<Measure>(
- ['measures', 'details', componentKey, 'branchLike', branchLike, metricKey],
+ ['measures', 'details', componentKey, 'branchLike', { ...branchParameters }, metricKey],
measure,
);
});
const branchLikeQuery = getBranchLikeQuery(branchLike);
return queryOptions({
- queryKey: ['measures', 'details', componentKey, 'branchLike', branchLikeQuery, metricKey],
+ queryKey: [
+ 'measures',
+ 'details',
+ componentKey,
+ 'branchLike',
+ { ...branchLikeQuery },
+ metricKey,
+ ],
queryFn: () =>
getMeasures({ component: componentKey, metricKeys: metricKey }).then(
(measures) => measures[0] ?? null,
const branchLikeQuery = getBranchLikeQuery(branchLike);
return queryOptions({
- queryKey: ['measures', 'list', componentKey, 'branchLike', branchLikeQuery, metricKeys],
+ queryKey: [
+ 'measures',
+ 'list',
+ componentKey,
+ 'branchLike',
+ { ...branchLikeQuery },
+ metricKeys,
+ ],
queryFn: async () => {
const measures = await getMeasures({
component: componentKey,
metricKeys.split(',').forEach((metricKey) => {
const measure = measuresMapByMetricKey[metricKey]?.[0] ?? null;
queryClient.setQueryData<Measure>(
- ['measures', 'details', componentKey, 'branchLike', branchLike ?? {}, metricKey],
+ ['measures', 'details', componentKey, 'branchLike', { ...branchLikeQuery }, metricKey],
measure,
);
});
return measures;
},
- staleTime: StaleTime.LONG,
});
},
);
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2024 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+import { useMutation, useQueryClient } from '@tanstack/react-query';
+import { deletePortfolio } from '../api/project-management';
+import { invalidateMeasuresByComponentKey } from './measures';
+
+export function useDeletePortfolioMutation() {
+ const queryClient = useQueryClient();
+ return useMutation({
+ mutationFn: (key: string) => deletePortfolio(key),
+ onSuccess: (_, key) => {
+ invalidateMeasuresByComponentKey(key, queryClient);
+ },
+ });
+}
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-import { queryOptions } from '@tanstack/react-query';
+import { queryOptions, useMutation, useQueryClient } from '@tanstack/react-query';
import { searchProjects } from '../api/components';
+import { deleteProject } from '../api/project-management';
import { createQueryHook } from './common';
+import { invalidateMeasuresByComponentKey } from './measures';
export const useProjectQuery = createQueryHook((key: string) => {
return queryOptions({
queryFn: ({ queryKey: [, key] }) => searchProjects({ filter: `query=${key}` }),
});
});
+
+export function useDeleteProjectMutation() {
+ const queryClient = useQueryClient();
+ return useMutation({
+ mutationFn: (key: string) => deleteProject(key),
+ onSuccess: (_, key) => {
+ invalidateMeasuresByComponentKey(key, queryClient);
+ },
+ });
+}
import { translate } from '../helpers/l10n';
import { ExtendedSettingDefinition, SettingsKey } from '../types/settings';
import { createQueryHook } from './common';
+import { invalidateAllMeasures } from './measures';
type SettingValue = string | boolean | string[];
onSuccess: (_, { definition }) => {
queryClient.invalidateQueries({ queryKey: ['settings', 'details', definition.key] });
queryClient.invalidateQueries({ queryKey: ['settings', 'values'] });
+ invalidateAllMeasures(queryClient);
addGlobalSuccessMessage(translate('settings.authentication.form.settings.save_success'));
},
});
new org.sonarqube.ws.client.permissions.AddUserRequest()
.setLogin(u.getLogin())
.setPermission("portfoliocreator"));
+ session.wsClient().permissions().addUser(
+ new org.sonarqube.ws.client.permissions.AddUserRequest()
+ .setLogin(u.getLogin())
+ .setPermission("admin"));
return u;
}