]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-22224 Update the wording + prioritized rule mark in rule details
authorViktor Vorona <viktor.vorona@sonarsource.com>
Fri, 7 Jun 2024 12:03:37 +0000 (14:03 +0200)
committersonartech <sonartech@sonarsource.com>
Tue, 11 Jun 2024 20:02:44 +0000 (20:02 +0000)
server/sonar-web/src/main/js/apps/coding-rules/__tests__/CodingRules-it.ts
server/sonar-web/src/main/js/apps/coding-rules/components/RuleDetailsProfiles.tsx
server/sonar-web/src/main/js/apps/coding-rules/utils-tests.tsx
sonar-core/src/main/resources/org/sonar/l10n/core.properties

index 27b251d703c9b1f666b16537e6fedec0edf88333..193053a36606a0c7236d6cd700e86ab9ca5b1ccf 100644 (file)
@@ -636,13 +636,13 @@ describe('Rule app details', () => {
     expect(ui.qpLink('QP Foo').get()).toBeInTheDocument();
 
     // Activate rule in quality profile
-    expect(ui.prioritizedYesCell.query()).not.toBeInTheDocument();
+    expect(ui.prioritizedRuleCell.query()).not.toBeInTheDocument();
     await user.click(ui.activateButton.get());
     await selectEvent.select(ui.qualityProfileSelect.get(), 'QP FooBar');
     await user.click(ui.prioritizedSwitch.get());
     await user.click(ui.activateButton.get(ui.activateQPDialog.get()));
     expect(ui.qpLink('QP FooBar').get()).toBeInTheDocument();
-    expect(ui.prioritizedYesCell.get()).toBeInTheDocument();
+    expect(ui.prioritizedRuleCell.get()).toBeInTheDocument();
 
     // Activate last java rule
     await user.click(ui.activateButton.get());
index b70fadb44bb66b6a08ba08c4b8ce826a2f0cf0b2..8b7b29110af96a9d2ccde1afa680b294e7542224 100644 (file)
@@ -27,23 +27,23 @@ import {
   InheritanceIcon,
   Link,
   Note,
+  SeparatorCircleIcon,
   SubTitle,
   Table,
   TableRow,
   TableRowInteractive,
+  TextSubdued,
 } from 'design-system';
 import { filter } from 'lodash';
 import * as React from 'react';
 import { FormattedMessage } from 'react-intl';
 import { Profile } from '../../../api/quality-profiles';
-import { useAvailableFeatures } from '../../../app/components/available-features/withAvailableFeatures';
 import { translate } from '../../../helpers/l10n';
 import { getQualityProfileUrl } from '../../../helpers/urls';
 import {
   useActivateRuleMutation,
   useDeactivateRuleMutation,
 } from '../../../queries/quality-profiles';
-import { Feature } from '../../../types/features';
 import { Dict, RuleActivation, RuleDetails } from '../../../types/types';
 import BuiltInQualityProfileBadge from '../../quality-profiles/components/BuiltInQualityProfileBadge';
 import ActivatedRuleActions from './ActivatedRuleActions';
@@ -66,7 +66,6 @@ export default function RuleDetailsProfiles(props: Readonly<Props>) {
   const { activations = [], referencedProfiles, ruleDetails, canDeactivateInherited } = props;
   const { mutate: activateRule } = useActivateRuleMutation(props.onActivate);
   const { mutate: deactivateRule } = useDeactivateRuleMutation(props.onDeactivate);
-  const { hasFeature } = useAvailableFeatures();
 
   const canActivate = Object.values(referencedProfiles).some((profile) =>
     Boolean(profile.actions?.edit && profile.language === ruleDetails.lang),
@@ -75,8 +74,6 @@ export default function RuleDetailsProfiles(props: Readonly<Props>) {
     ruleDetails.templateKey === undefined &&
     ruleDetails?.params !== undefined &&
     ruleDetails.params.length > 0;
-  const showPrioritizedRuleColumn =
-    hasFeature(Feature.PrioritizedRules) && activations.some((a) => a.prioritizedRule);
 
   const handleDeactivate = (key?: string) => {
     if (key !== undefined) {
@@ -143,21 +140,25 @@ export default function RuleDetailsProfiles(props: Readonly<Props>) {
 
     return (
       <TableRowInteractive key={profile.key}>
-        <ContentCell className="sw-flex sw-flex-col sw-gap-2 sw-w-64">
-          <div
-            className="sw-truncate sw-w-full"
-            title={`${profile.name}${
-              profile.isBuiltIn ? ` (${translate('quality_profiles.built_in')})` : ''
-            }`}
-          >
+        <ContentCell className="sw-flex sw-flex-col sw-gap-2">
+          <div className="sw-self-start sw-flex sw-gap-2 sw-items-center">
             <Link
+              className="sw-truncate sw-max-w-64"
               aria-label={profile.name}
+              title={profile.name}
               to={getQualityProfileUrl(profile.name, profile.language)}
             >
               {profile.name}
             </Link>
 
-            {profile.isBuiltIn && <BuiltInQualityProfileBadge className="sw-ml-2" />}
+            {activation.prioritizedRule && (
+              <>
+                <SeparatorCircleIcon />
+                <TextSubdued>{translate('coding_rules.prioritized_rule.title')}</TextSubdued>
+              </>
+            )}
+
+            {profile.isBuiltIn && <BuiltInQualityProfileBadge />}
           </div>
 
           {inheritedProfileSection}
@@ -194,10 +195,6 @@ export default function RuleDetailsProfiles(props: Readonly<Props>) {
           </CellComponent>
         )}
 
-        {showPrioritizedRuleColumn && (
-          <ContentCell>{activation.prioritizedRule && <span>{translate('yes')}</span>}</ContentCell>
-        )}
-
         {renderRowActions(activation, profile)}
       </TableRowInteractive>
     );
@@ -205,36 +202,39 @@ export default function RuleDetailsProfiles(props: Readonly<Props>) {
 
   return (
     <div className="js-rule-profiles sw-mb-8">
-      <SubTitle id={PROFILES_HEADING_ID}>
-        <FormattedMessage id="coding_rules.quality_profiles" />
-      </SubTitle>
+      <div className="sw-flex sw-justify-between sw-items-end">
+        <div>
+          <SubTitle id={PROFILES_HEADING_ID}>
+            <FormattedMessage id="coding_rules.quality_profiles" />
+          </SubTitle>
+          <Note>
+            <FormattedMessage id="coding_rules.quality_profiles.description" />
+          </Note>
+        </div>
 
-      {canActivate && (
-        <ActivationButton
-          buttonText={translate('coding_rules.activate')}
-          className="sw-mt-6"
-          modalHeader={translate('coding_rules.activate_in_quality_profile')}
-          onDone={props.onActivate}
-          profiles={filter(
-            referencedProfiles,
-            (profile) => !activations.find((activation) => activation.qProfile === profile.key),
-          )}
-          rule={ruleDetails}
-        />
-      )}
+        {canActivate && (
+          <ActivationButton
+            buttonText={translate('coding_rules.activate')}
+            modalHeader={translate('coding_rules.activate_in_quality_profile')}
+            onDone={props.onActivate}
+            profiles={filter(
+              referencedProfiles,
+              (profile) => !activations.find((activation) => activation.qProfile === profile.key),
+            )}
+            rule={ruleDetails}
+          />
+        )}
+      </div>
 
       {activations.length > 0 && (
         <Table
           aria-labelledby={PROFILES_HEADING_ID}
           className="sw-my-6"
-          columnCount={MANDATORY_COLUMNS_COUNT + +showParamsColumn + +showPrioritizedRuleColumn}
+          columnCount={MANDATORY_COLUMNS_COUNT + +showParamsColumn}
           header={
             <TableRow>
               <ContentCell>{translate('profile_name')}</ContentCell>
               {showParamsColumn && <ContentCell>{translate('parameters')}</ContentCell>}
-              {showPrioritizedRuleColumn && (
-                <ContentCell>{translate('coding_rules.prioritized_rule.title')}</ContentCell>
-              )}
               <ActionCell>{translate('actions')}</ActionCell>
             </TableRow>
           }
index 89a63e1ae82932eb449fdaa9371ec5433c1fc79b..eec6400700a1f94971a1731bdc206fce0aed13c1 100644 (file)
@@ -115,7 +115,7 @@ const selectors = {
   caycNotificationButton: byRole('button', { name: 'coding_rules.more_info.scroll_message' }),
   extendDescriptionButton: byRole('button', { name: 'coding_rules.extend_description' }),
   extendDescriptionTextbox: byRole('textbox', { name: 'coding_rules.extend_description' }),
-  prioritizedYesCell: byRole('cell', { name: 'yes' }),
+  prioritizedRuleCell: byRole('cell', { name: /coding_rules.prioritized_rule.title/ }),
   saveButton: byRole('button', { name: 'save' }),
   cancelButton: byRole('button', { name: 'cancel' }),
   removeButton: byRole('button', { name: 'remove' }),
index 80151c38d2b0890f6a746cb529826360c35b762a..836f7912b0303346b0a7307fffc450c72d094d28 100644 (file)
@@ -2420,6 +2420,7 @@ coding_rules.parameter.empty=(empty)
 coding_rules.parameters=Parameters
 coding_rules.parameters.default_value=Default Value:
 coding_rules.quality_profiles=Quality Profiles
+coding_rules.quality_profiles.description=List of all Quality Profiles where this rule is activated. Built-in profiles can't be changed.
 coding_rules.quality_profiles.template_caption=This rule template was activated on the following profiles in previous versions of {instance}. It is not possible anymore to do so. Instead, please create a custom rule.
 coding_rules.quality_profile=Quality Profile
 coding_rules.reactivate=Reactivate
@@ -2448,7 +2449,7 @@ coding_rules.severity.deprecation.filter_by=You can now filter rules by Software
 coding_rules.prioritized_rule.title=Prioritized rule
 coding_rules.prioritized_rule.label={state, select, on {Mark} other {Unmark}} as Prioritized
 coding_rules.prioritized_rule.switch_label=Indicates that all corresponding issues in Overall Code should be fixed
-coding_rules.prioritized_rule.note=You need to add a condition to your Quality Gate that checks whether any issues have been raised from the prioritized rules.
+coding_rules.prioritized_rule.note=For your Quality Gate to fail when corresponding issues exist in the overall code, you must add a condition that checks whether any issues have been raised from prioritized rules.
 
 coding_rules.update_custom_rule=Update Custom Rule