]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-18257 Remove deprecated param ID from QG show and create endpoints
author7PH <benjamin.raymond@sonarsource.com>
Fri, 27 Jan 2023 10:30:12 +0000 (11:30 +0100)
committersonartech <sonartech@sonarsource.com>
Mon, 30 Jan 2023 20:03:00 +0000 (20:03 +0000)
19 files changed:
server/sonar-web/src/main/js/api/mocks/QualityGatesServiceMock.ts
server/sonar-web/src/main/js/api/quality-gates.ts
server/sonar-web/src/main/js/app/components/nav/component/projectInformation/meta/MetaQualityGate.tsx
server/sonar-web/src/main/js/apps/overview/branches/CleanAsYouCodeWarning.tsx
server/sonar-web/src/main/js/apps/overview/pullRequests/LargeQualityGateBadge.tsx
server/sonar-web/src/main/js/apps/overview/pullRequests/__tests__/__snapshots__/LargeQualityGateBadge-test.tsx.snap
server/sonar-web/src/main/js/apps/projectQualityGate/ProjectQualityGateApp.tsx
server/sonar-web/src/main/js/apps/projectQualityGate/ProjectQualityGateAppRenderer.tsx
server/sonar-web/src/main/js/apps/projectQualityGate/__tests__/__snapshots__/ProjectQualityGateApp-test.tsx.snap
server/sonar-web/src/main/js/apps/projectQualityGate/__tests__/__snapshots__/ProjectQualityGateAppRenderer-test.tsx.snap
server/sonar-web/src/main/js/apps/quality-gates/components/App.tsx
server/sonar-web/src/main/js/apps/quality-gates/components/CopyQualityGateForm.tsx
server/sonar-web/src/main/js/apps/quality-gates/components/CreateQualityGateForm.tsx
server/sonar-web/src/main/js/apps/quality-gates/components/Details.tsx
server/sonar-web/src/main/js/apps/quality-gates/components/DetailsHeader.tsx
server/sonar-web/src/main/js/apps/quality-gates/components/List.tsx
server/sonar-web/src/main/js/apps/quality-gates/components/RenameQualityGateForm.tsx
server/sonar-web/src/main/js/apps/quality-gates/routes.tsx
server/sonar-web/src/main/js/helpers/urls.ts

index 7644707dfb5c08b44b7d842b2aef19e0fd9e63cd..0fedec86c3674794eebe587f84d3104dee4e31e7 100644 (file)
@@ -215,9 +215,9 @@ export class QualityGatesServiceMock {
     });
   };
 
-  showHandler = ({ id }: { id: string }) => {
+  showHandler = ({ name }: { name: string }) => {
     const qualityGate = omit(
-      this.list.find((q) => q.id === id),
+      this.list.find((q) => q.name === name),
       'isDefault'
     );
     return this.reply({ ...qualityGate, actions: this.computeActions(qualityGate) });
index e5082466b3613a425c86ee985a7f36db8ff5c9fb..513cdd06599452a111c22cbb6573ec1e1866d3f7 100644 (file)
@@ -38,7 +38,7 @@ export function fetchQualityGates(): Promise<{
   return getJSON('/api/qualitygates/list').catch(throwGlobalError);
 }
 
-export function fetchQualityGate(data: { id: number | string }): Promise<QualityGate> {
+export function fetchQualityGate(data: { name: string }): Promise<QualityGate> {
   return getJSON('/api/qualitygates/show', data).catch(throwGlobalError);
 }
 
index 20ce0057017eb01d37df454aa1876682965835e0..a6f4637962c4d18681cbc113c518c5eb4b6d6980 100644 (file)
@@ -23,7 +23,7 @@ import { translate } from '../../../../../../helpers/l10n';
 import { getQualityGateUrl } from '../../../../../../helpers/urls';
 
 interface Props {
-  qualityGate: { isDefault?: boolean; key: string; name: string };
+  qualityGate: { isDefault?: boolean; name: string };
 }
 
 export default function MetaQualityGate({ qualityGate }: Props) {
@@ -36,7 +36,7 @@ export default function MetaQualityGate({ qualityGate }: Props) {
           {qualityGate.isDefault && (
             <span className="note spacer-right">({translate('default')})</span>
           )}
-          <Link to={getQualityGateUrl(qualityGate.key)}>{qualityGate.name}</Link>
+          <Link to={getQualityGateUrl(qualityGate.name)}>{qualityGate.name}</Link>
         </li>
       </ul>
     </>
index 9dbb28caa5c81419c9f2afcea5f6a54752ee68cd..d72d68a4066f934920fc73efb7cad3fb37f98ec9 100644 (file)
@@ -40,7 +40,7 @@ export default function CleanAsYouCodeWarning({ component }: Props) {
 
       {component.qualityGate && (
         <div className="big-spacer-bottom">
-          <Link className="button" to={getQualityGateUrl(component.qualityGate.key)}>
+          <Link className="button" to={getQualityGateUrl(component.qualityGate.name)}>
             {translate('overview.quality_gate.conditions.cayc.review')}
           </Link>
         </div>
index 3093eb6cafbfd42e72767c39f3a9a1a80cef3213..31a4e536cd02c061eaa8ab0932abc24179ebc47c 100644 (file)
@@ -39,7 +39,7 @@ export function LargeQualityGateBadge({ component, level }: Props) {
   const path =
     component.qualityGate === undefined
       ? getQualityGatesUrl()
-      : getQualityGateUrl(component.qualityGate.key);
+      : getQualityGateUrl(component.qualityGate.name);
 
   return (
     <div
index c6b39b9252178d364e25f06b7b0751f2f4f3f139..5d17f34fe398f463d6e96acbfd3b43f7aef17ed7 100644 (file)
@@ -21,7 +21,7 @@ exports[`should render correctly for SQ 1`] = `
               "link": <ForwardRef(Link)
                 to={
                   {
-                    "pathname": "/quality_gates/show/30",
+                    "pathname": "/quality_gates/show/Sonar%20way",
                   }
                 }
               >
@@ -67,7 +67,7 @@ exports[`should render correctly for SQ 2`] = `
               "link": <ForwardRef(Link)
                 to={
                   {
-                    "pathname": "/quality_gates/show/30",
+                    "pathname": "/quality_gates/show/Sonar%20way",
                   }
                 }
               >
index fc9c7170fd7e92cbc4cc0284317e35bd64f1e25b..3af87aaae6caae139f3d61cab08343b4a683a9fe 100644 (file)
@@ -100,7 +100,7 @@ export class ProjectQualityGateApp extends React.PureComponent<Props, State> {
     const { qualitygates } = await fetchQualityGates();
     return Promise.all(
       qualitygates.map(async (qg) => {
-        const detailedQp = await fetchQualityGate({ id: qg.id }).catch(() => qg);
+        const detailedQp = await fetchQualityGate({ name: qg.name }).catch(() => qg);
         return { ...detailedQp, ...qg };
       })
     );
index f8a38aae6821ff45042effdcaa4f0a5a901ffd9e..809bc392819e03c72a6d6f37ddb2da5b94a24dd5 100644 (file)
@@ -32,6 +32,7 @@ import Suggestions from '../../components/embed-docs-modal/Suggestions';
 import { Alert } from '../../components/ui/Alert';
 import { translate } from '../../helpers/l10n';
 import { isDiffMetric } from '../../helpers/measures';
+import { getQualityGateUrl } from '../../helpers/urls';
 import { QualityGate } from '../../types/types';
 import BuiltInQualityGateBadge from '../quality-gates/components/BuiltInQualityGateBadge';
 import { USE_SYSTEM_DEFAULT } from './constants';
@@ -68,7 +69,7 @@ function renderQualitygateOption(props: OptionProps<QualityGateOption, false>) {
               defaultMessage={translate('project_quality_gate.no_condition')}
               values={{
                 link: (
-                  <Link to={{ pathname: `/quality_gates/show/${props.data.value}` }}>
+                  <Link to={getQualityGateUrl(props.data.label)}>
                     {translate('project_quality_gate.no_condition.link')}
                   </Link>
                 ),
@@ -210,7 +211,7 @@ export default function ProjectQualityGateAppRenderer(props: ProjectQualityGateA
                   defaultMessage={translate('project_quality_gate.no_condition_on_new_code')}
                   values={{
                     link: (
-                      <Link to={{ pathname: `/quality_gates/show/${selectedQualityGate.id}` }}>
+                      <Link to={getQualityGateUrl(selectedQualityGate.name)}>
                         {translate('project_quality_gate.no_condition.link')}
                       </Link>
                     ),
index b230554e23bad3a3257ebd45c529fded8a9f8445..49c8689d5c89bf020cc105291935b2fb3f0beb5b 100644 (file)
@@ -61,6 +61,20 @@ exports[`renders correctly 1`] = `
         "name": "qualitygate",
       },
       {
+        "conditions": [
+          {
+            "error": "10",
+            "id": "1",
+            "metric": "coverage",
+            "op": "LT",
+          },
+          {
+            "error": "10",
+            "id": "1",
+            "metric": "new_bugs",
+            "op": "LT",
+          },
+        ],
         "id": "gate4",
         "name": "qualitygate",
       },
index 47db1cc08decc9bf18aa6d250a44c1c9f447006b..a2da5f6692f10c3aa5e983e035fb33d62d783454 100644 (file)
@@ -481,7 +481,7 @@ exports[`should render correctly: show new code warning 1`] = `
                 "link": <ForwardRef(Link)
                   to={
                     {
-                      "pathname": "/quality_gates/show/3",
+                      "pathname": "/quality_gates/show/qualitygate",
                     }
                   }
                 >
index 60bbc9fa6381e963510b6adce22f608d6174a8e5..899a9ba858eb70eb4ef884f44030400cff92db55 100644 (file)
@@ -40,7 +40,7 @@ import List from './List';
 import ListHeader from './ListHeader';
 
 interface Props {
-  id?: string;
+  name?: string;
   navigate: NavigateFunction;
 }
 
@@ -62,7 +62,7 @@ class App extends React.PureComponent<Props, State> {
   }
 
   componentDidUpdate(prevProps: Props) {
-    if (prevProps.id !== undefined && this.props.id === undefined) {
+    if (prevProps.name !== undefined && this.props.name === undefined) {
       this.openDefault(this.state.qualityGates);
     }
   }
@@ -79,7 +79,7 @@ class App extends React.PureComponent<Props, State> {
         if (this.mounted) {
           this.setState({ canCreate: actions.create, loading: false, qualityGates });
 
-          if (!this.props.id) {
+          if (!this.props.name) {
             this.openDefault(qualityGates);
           }
         }
@@ -94,7 +94,7 @@ class App extends React.PureComponent<Props, State> {
 
   openDefault(qualityGates: QualityGate[]) {
     const defaultQualityGate = qualityGates.find((gate) => Boolean(gate.isDefault))!;
-    this.props.navigate(getQualityGateUrl(String(defaultQualityGate.id)), { replace: true });
+    this.props.navigate(getQualityGateUrl(defaultQualityGate.name), { replace: true });
   }
 
   handleSetDefault = (qualityGate: QualityGate) => {
@@ -111,7 +111,7 @@ class App extends React.PureComponent<Props, State> {
   };
 
   render() {
-    const { id } = this.props;
+    const { name } = this.props;
     const { canCreate, qualityGates } = this.state;
     const defaultTitle = translate('quality_gates.page');
 
@@ -131,7 +131,7 @@ class App extends React.PureComponent<Props, State> {
                       refreshQualityGates={this.fetchQualityGates}
                     />
                     <DeferredSpinner loading={this.state.loading}>
-                      <List qualityGates={qualityGates} currentQualityGate={id} />
+                      <List qualityGates={qualityGates} currentQualityGate={name} />
                     </DeferredSpinner>
                   </div>
                 </div>
@@ -139,9 +139,9 @@ class App extends React.PureComponent<Props, State> {
             )}
           </ScreenPositionHelper>
 
-          {id !== undefined && (
+          {name !== undefined && (
             <Details
-              id={id}
+              qualityGateName={name}
               onSetDefault={this.handleSetDefault}
               qualityGates={this.state.qualityGates}
               refreshQualityGates={this.fetchQualityGates}
@@ -157,5 +157,5 @@ export default function AppWrapper() {
   const params = useParams();
   const navigate = useNavigate();
 
-  return <App id={params['id']} navigate={navigate} />;
+  return <App name={params['name']} navigate={navigate} />;
 }
index 8a95ef41e6e921c0c9b83f7f7b73da6fc8cee6cf..34da6914e320578d26a224349633090f928ff261 100644 (file)
@@ -54,7 +54,7 @@ export class CopyQualityGateForm extends React.PureComponent<Props, State> {
 
     return copyQualityGate({ sourceName: qualityGate.name, name }).then((newQualityGate) => {
       this.props.onCopy();
-      this.props.router.push(getQualityGateUrl(String(newQualityGate.id)));
+      this.props.router.push(getQualityGateUrl(newQualityGate.name));
     });
   };
 
index 73eea99e439c6902e45f87eda73b3210f7ce795e..56ce7cc527db191d77ed7617e188ca06fdd72cb2 100644 (file)
@@ -51,7 +51,7 @@ export class CreateQualityGateForm extends React.PureComponent<Props, State> {
 
       await this.props.onCreate();
 
-      this.props.router.push(getQualityGateUrl(String(qualityGate.id)));
+      this.props.router.push(getQualityGateUrl(qualityGate.name));
     }
   };
 
index 48e22abfe162b0c8eef6eb74adf91628e2c3c7c3..b6e8ff4a23494958b27201a462fae0bb0df8e2e6 100644 (file)
@@ -30,7 +30,7 @@ import DetailsContent from './DetailsContent';
 import DetailsHeader from './DetailsHeader';
 
 interface Props {
-  id: string;
+  qualityGateName: string;
   onSetDefault: (qualityGate: QualityGate) => void;
   qualityGates: QualityGate[];
   refreshQualityGates: () => Promise<void>;
@@ -52,7 +52,7 @@ export default class Details extends React.PureComponent<Props, State> {
   }
 
   componentDidUpdate(prevProps: Props) {
-    if (prevProps.id !== this.props.id) {
+    if (prevProps.qualityGateName !== this.props.qualityGateName) {
       this.fetchDetails();
     }
   }
@@ -62,9 +62,9 @@ export default class Details extends React.PureComponent<Props, State> {
   }
 
   fetchDetails = () => {
-    const { id } = this.props;
+    const { qualityGateName } = this.props;
     this.setState({ loading: true });
-    return fetchQualityGate({ id }).then(
+    return fetchQualityGate({ name: qualityGateName }).then(
       (qualityGate) => {
         if (this.mounted) {
           this.setState({ loading: false, qualityGate, updatedConditionId: undefined });
index ad9ec48f95b98d99294235920f14d0cbc3bf84ac..0276c9f7df25940a6863a6df896320c1b249b2aa 100644 (file)
@@ -86,7 +86,7 @@ export default class DetailsHeader extends React.PureComponent<Props> {
                   modal={({ onClose }) => (
                     <RenameQualityGateForm
                       onClose={onClose}
-                      onRename={this.handleActionRefresh}
+                      onRename={this.props.refreshList}
                       qualityGate={qualityGate}
                     />
                   )}
index f3f8614bf9d043acc6d3f71f060c459a6e64a137..b1f4ffe15bd9860ffd0836a4c158bdb1d85cca47 100644 (file)
@@ -37,10 +37,10 @@ export default function List({ qualityGates, currentQualityGate }: Props) {
       {qualityGates.map((qualityGate) => (
         <NavLink
           className="list-group-item display-flex-center"
-          aria-current={currentQualityGate === qualityGate.id && 'page'}
+          aria-current={currentQualityGate === qualityGate.name && 'page'}
           data-id={qualityGate.id}
           key={qualityGate.id}
-          to={getQualityGateUrl(String(qualityGate.id))}
+          to={getQualityGateUrl(qualityGate.name)}
         >
           <span className="flex-1 text-ellipsis" title={qualityGate.name}>
             {qualityGate.name}
index ba33c44617630e70b233c531618049edeb0a8c34..76ed4083772272625c69760dbe1d54537471ce08 100644 (file)
 import * as React from 'react';
 import { renameQualityGate } from '../../../api/quality-gates';
 import ConfirmModal from '../../../components/controls/ConfirmModal';
+import { withRouter, WithRouterProps } from '../../../components/hoc/withRouter';
 import MandatoryFieldMarker from '../../../components/ui/MandatoryFieldMarker';
 import MandatoryFieldsExplanation from '../../../components/ui/MandatoryFieldsExplanation';
 import { translate } from '../../../helpers/l10n';
+import { getQualityGateUrl } from '../../../helpers/urls';
 import { QualityGate } from '../../../types/types';
 
-interface Props {
+interface Props extends WithRouterProps {
   onClose: () => void;
   onRename: () => Promise<void>;
   qualityGate: QualityGate;
@@ -35,7 +37,7 @@ interface State {
   name: string;
 }
 
-export default class RenameQualityGateForm extends React.PureComponent<Props, State> {
+class RenameQualityGateForm extends React.PureComponent<Props, State> {
   constructor(props: Props) {
     super(props);
     this.state = { name: props.qualityGate.name };
@@ -46,12 +48,13 @@ export default class RenameQualityGateForm extends React.PureComponent<Props, St
   };
 
   handleRename = () => {
-    const { qualityGate } = this.props;
+    const { qualityGate, router } = this.props;
     const { name } = this.state;
 
-    return renameQualityGate({ currentName: qualityGate.name, name }).then(() =>
-      this.props.onRename()
-    );
+    return renameQualityGate({ currentName: qualityGate.name, name }).then(() => {
+      this.props.onRename();
+      router.push(getQualityGateUrl(name));
+    });
   };
 
   render() {
@@ -89,3 +92,5 @@ export default class RenameQualityGateForm extends React.PureComponent<Props, St
     );
   }
 }
+
+export default withRouter(RenameQualityGateForm);
index 791a5eb7ae31572ce514d3007faa5d146f60283c..a04f00386015a478f003df3e35e521ce075cc61d 100644 (file)
@@ -24,7 +24,7 @@ import App from './components/App';
 const routes = () => (
   <Route path="quality_gates">
     <Route index={true} element={<App />} />
-    <Route path="show/:id" element={<App />} />
+    <Route path="show/:name" element={<App />} />
   </Route>
 );
 
index 57d7ae2c12d7d7fdbee4a16718f1c9f879b192f0..9f5f6fa4a8f7b1ca029db05668ebc7c5cc532d15 100644 (file)
@@ -313,9 +313,9 @@ export function getQualityProfileUrl(name: string, language: string): To {
   return getProfilePath(name, language);
 }
 
-export function getQualityGateUrl(key: string): To {
+export function getQualityGateUrl(name: string): To {
   return {
-    pathname: '/quality_gates/show/' + encodeURIComponent(key),
+    pathname: '/quality_gates/show/' + encodeURIComponent(name),
   };
 }