]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-20672 Display SonarQube upgrade message in Quality Profile changelog
authorDavid Cho-Lerat <david.cho-lerat@sonarsource.com>
Mon, 16 Oct 2023 12:50:04 +0000 (14:50 +0200)
committersonartech <sonartech@sonarsource.com>
Mon, 16 Oct 2023 20:02:49 +0000 (20:02 +0000)
server/sonar-web/src/main/js/apps/quality-profiles/changelog/Changelog.tsx
server/sonar-web/src/main/js/apps/quality-profiles/types.ts
server/sonar-web/src/main/js/helpers/testMocks.ts
sonar-core/src/main/resources/org/sonar/l10n/core.properties

index a651a5e413bf6f274d2b292c00a4f3e84b9b177a..47c25b4fd90f41652a4d8020166821b2b1b77dfb 100644 (file)
@@ -21,6 +21,7 @@ import { isSameMinute } from 'date-fns';
 import {
   CellComponent,
   ContentCell,
+  FlagMessage,
   Link,
   Note,
   Table,
@@ -29,7 +30,7 @@ import {
 } from 'design-system';
 import { sortBy } from 'lodash';
 import * as React from 'react';
-import { useIntl } from 'react-intl';
+import { FormattedMessage, useIntl } from 'react-intl';
 import DateTimeFormatter from '../../../components/intl/DateTimeFormatter';
 import { CleanCodeAttributePill } from '../../../components/shared/CleanCodeAttributePill';
 import SoftwareImpactPill from '../../../components/shared/SoftwareImpactPill';
@@ -52,19 +53,51 @@ export default function Changelog(props: Props) {
     (e) => e.action,
   );
 
+  const isSameEventDate = (thisEvent: ProfileChangelogEvent, otherEvent?: ProfileChangelogEvent) =>
+    otherEvent !== undefined && isSameMinute(parseDate(otherEvent.date), parseDate(thisEvent.date));
+
+  const isSameEventGroup = (thisEvent: ProfileChangelogEvent, otherEvent?: ProfileChangelogEvent) =>
+    otherEvent !== undefined &&
+    isSameEventDate(thisEvent, otherEvent) &&
+    otherEvent.authorName === thisEvent.authorName &&
+    otherEvent.action === thisEvent.action;
+
   const rows = sortedRows.map((event, index) => {
-    const prev = index > 0 ? sortedRows[index - 1] : null;
-    const isSameDate = prev != null && isSameMinute(parseDate(prev.date), parseDate(event.date));
-    const isBulkChange =
-      prev != null &&
-      isSameDate &&
-      prev.authorName === event.authorName &&
-      prev.action === event.action;
+    const prev = sortedRows[index - 1];
+    const isBulkChange = isSameEventGroup(event, prev);
+
+    const nextEventInDifferentGroup = sortedRows
+      .slice(index + 1)
+      .find((e) => !isSameEventGroup(event, e));
+
+    const isNewSonarQubeVersion =
+      !isBulkChange &&
+      nextEventInDifferentGroup !== undefined &&
+      nextEventInDifferentGroup.sonarQubeVersion !== event.sonarQubeVersion;
 
     return (
       <TableRowInteractive key={index}>
-        <ContentCell className="sw-whitespace-nowrap sw-align-top">
-          {!isBulkChange && <DateTimeFormatter date={event.date} />}
+        <ContentCell className="sw-align-top">
+          {!isBulkChange && (
+            <div>
+              <span className="sw-whitespace-nowrap">
+                <DateTimeFormatter date={event.date} />
+              </span>
+
+              {isNewSonarQubeVersion && (
+                <div className="sw-mt-2 sw-whitespace-nowrap">
+                  <FlagMessage variant="info">
+                    <FormattedMessage
+                      id="quality_profiles.changelog.sq_upgrade"
+                      values={{
+                        sqVersion: event.sonarQubeVersion,
+                      }}
+                    />
+                  </FlagMessage>
+                </div>
+              )}
+            </div>
+          )}
         </ContentCell>
 
         <ContentCell className="sw-whitespace-nowrap sw-align-top sw-max-w-[120px]">
index 2519b302053eb54fc5b619de888e3a7080ad9ac5..b361587f8ecb40a1068406f132bccf686c171702 100644 (file)
@@ -64,6 +64,7 @@ export interface ProfileChangelogEvent {
   } & Dict<string | ProfileChangelogEventImpactChange[] | null>;
   ruleKey: string;
   ruleName: string;
+  sonarQubeVersion: string;
 }
 
 export enum ProfileActionModals {
index 53fc466a14a8af0293d28011969df74f73957bb9..b353b7baea1d6db3153a99ad1d9559b44dfa1218 100644 (file)
@@ -538,6 +538,7 @@ export function mockQualityProfileChangelogEvent(
     ],
     ruleKey: 'rule-key',
     ruleName: 'rule-name',
+    sonarQubeVersion: '10.3',
     ...eventOverride,
   };
 }
index 465d8a04f79860e3350dde7be6b852ff069783e0..d7cce749480993afc3fd9f9c5954cc2afa61b0c7 100644 (file)
@@ -2023,6 +2023,7 @@ quality_profiles.changelog.cca_only_changed=Clean Code attribute set to {newClea
 quality_profiles.changelog.impact_changed=Software impact set to {newSoftwareQuality} with severity {newSeverity}, was {oldSoftwareQuality} with severity {oldSeverity}
 quality_profiles.changelog.impact_added=Software impact {newSoftwareQuality} with severity {newSeverity} was added
 quality_profiles.changelog.impact_removed=Software impact {oldSoftwareQuality} with severity {oldSeverity} was removed
+quality_profiles.changelog.sq_upgrade=Instance upgraded to SonarQube {sqVersion}
 quality_profiles.deleted_profile=The profile {0} doesn't exist anymore
 quality_profiles.projects_for_default=Every project not specifically associated with a quality profile will be associated to this one by default.
 quality_profile.x_rules={count} rule(s)