aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-web/src
diff options
context:
space:
mode:
authorKevin Silva <kevin.silva@sonarsource.com>2023-09-18 11:41:23 +0200
committersonartech <sonartech@sonarsource.com>2023-09-19 20:02:46 +0000
commitc13c409e59105e0187da35c14e7ba1d2e76a39a7 (patch)
treef4c99499f1380e7f350cbec5d98ef6f6ea72b351 /server/sonar-web/src
parent1fc0c6cbdf4b31d8d62e91545bb6a5b3660f3949 (diff)
downloadsonarqube-c13c409e59105e0187da35c14e7ba1d2e76a39a7.tar.gz
sonarqube-c13c409e59105e0187da35c14e7ba1d2e76a39a7.zip
SONAR-20337 Validation fixes for QG
Diffstat (limited to 'server/sonar-web/src')
-rw-r--r--server/sonar-web/src/main/js/apps/quality-gates/components/App.tsx75
-rw-r--r--server/sonar-web/src/main/js/apps/quality-gates/components/CaycConditionsListItem.tsx5
-rw-r--r--server/sonar-web/src/main/js/apps/quality-gates/components/ConditionReviewAndUpdateModal.tsx6
-rw-r--r--server/sonar-web/src/main/js/apps/quality-gates/components/ConditionValueDescription.tsx2
-rw-r--r--server/sonar-web/src/main/js/apps/quality-gates/components/Conditions.tsx7
-rw-r--r--server/sonar-web/src/main/js/apps/quality-gates/components/CreateQualityGateForm.tsx1
-rw-r--r--server/sonar-web/src/main/js/apps/quality-gates/components/Details.tsx3
-rw-r--r--server/sonar-web/src/main/js/apps/quality-gates/components/DetailsContent.tsx2
-rw-r--r--server/sonar-web/src/main/js/apps/quality-gates/components/List.tsx4
-rw-r--r--server/sonar-web/src/main/js/apps/quality-gates/components/Projects.tsx6
-rw-r--r--server/sonar-web/src/main/js/apps/quality-gates/components/QualityGatePermissionsAddModalRenderer.tsx10
-rw-r--r--server/sonar-web/src/main/js/apps/quality-gates/components/QualityGatePermissionsRenderer.tsx7
-rw-r--r--server/sonar-web/src/main/js/components/controls/SelectListListContainer.tsx3
13 files changed, 74 insertions, 57 deletions
diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/App.tsx b/server/sonar-web/src/main/js/apps/quality-gates/components/App.tsx
index d2781723d6a..4eaeb02b60f 100644
--- a/server/sonar-web/src/main/js/apps/quality-gates/components/App.tsx
+++ b/server/sonar-web/src/main/js/apps/quality-gates/components/App.tsx
@@ -23,6 +23,8 @@ import {
LAYOUT_FOOTER_HEIGHT,
LAYOUT_GLOBAL_NAV_HEIGHT,
LargeCenteredLayout,
+ PageContentFontWrapper,
+ Spinner,
themeBorder,
themeColor,
} from 'design-system';
@@ -32,7 +34,6 @@ import { NavigateFunction, useNavigate, useParams } from 'react-router-dom';
import { fetchQualityGates } from '../../../api/quality-gates';
import Suggestions from '../../../components/embed-docs-modal/Suggestions';
import '../../../components/search-navigator.css';
-import Spinner from '../../../components/ui/Spinner';
import { translate, translateWithParameters } from '../../../helpers/l10n';
import {
addSideBarClass,
@@ -126,46 +127,48 @@ class App extends React.PureComponent<Props, State> {
return (
<LargeCenteredLayout id="quality-gates-page">
- <Helmet
- defer={false}
- titleTemplate={translateWithParameters(
- 'page_title.template.with_category',
- translate('quality_gates.page'),
- )}
- />
- <div className="sw-grid sw-gap-x-12 sw-gap-y-6 sw-grid-cols-12 sw-w-full">
- <Suggestions suggestions="quality_gates" />
-
- <StyledContentWrapper
- className="sw-col-span-3 sw-px-4 sw-py-6 sw-border-t-0 sw-rounded-0"
- style={{
- height: `calc(100vh - ${LAYOUT_GLOBAL_NAV_HEIGHT + LAYOUT_FOOTER_HEIGHT}px)`,
- }}
- >
- <ListHeader canCreate={canCreate} refreshQualityGates={this.fetchQualityGates} />
- <Spinner loading={this.state.loading}>
- <List qualityGates={qualityGates} currentQualityGate={name} />
- </Spinner>
- </StyledContentWrapper>
-
- {name !== undefined && (
+ <PageContentFontWrapper className="sw-body-sm">
+ <Helmet
+ defer={false}
+ titleTemplate={translateWithParameters(
+ 'page_title.template.with_category',
+ translate('quality_gates.page'),
+ )}
+ />
+ <div className="sw-grid sw-gap-x-12 sw-gap-y-6 sw-grid-cols-12 sw-w-full">
+ <Suggestions suggestions="quality_gates" />
+
<StyledContentWrapper
- className="sw-col-span-9 sw-overflow-y-auto sw-mt-12"
+ className="sw-col-span-3 sw-px-4 sw-py-6 sw-border-t-0 sw-rounded-0"
style={{
- height: `calc(100vh - ${
- LAYOUT_GLOBAL_NAV_HEIGHT + LAYOUT_FOOTER_HEIGHT
- }px - ${MAIN_CONTENT_TOP_PADDING}px)`,
+ height: `calc(100vh - ${LAYOUT_GLOBAL_NAV_HEIGHT + LAYOUT_FOOTER_HEIGHT}px)`,
}}
>
- <Details
- qualityGateName={name}
- onSetDefault={this.handleSetDefault}
- qualityGates={this.state.qualityGates}
- refreshQualityGates={this.fetchQualityGates}
- />
+ <ListHeader canCreate={canCreate} refreshQualityGates={this.fetchQualityGates} />
+ <Spinner loading={this.state.loading}>
+ <List qualityGates={qualityGates} currentQualityGate={name} />
+ </Spinner>
</StyledContentWrapper>
- )}
- </div>
+
+ {name !== undefined && (
+ <StyledContentWrapper
+ className="sw-col-span-9 sw-overflow-y-auto sw-mt-12"
+ style={{
+ height: `calc(100vh - ${
+ LAYOUT_GLOBAL_NAV_HEIGHT + LAYOUT_FOOTER_HEIGHT
+ }px - ${MAIN_CONTENT_TOP_PADDING}px)`,
+ }}
+ >
+ <Details
+ qualityGateName={name}
+ onSetDefault={this.handleSetDefault}
+ qualityGates={this.state.qualityGates}
+ refreshQualityGates={this.fetchQualityGates}
+ />
+ </StyledContentWrapper>
+ )}
+ </div>
+ </PageContentFontWrapper>
</LargeCenteredLayout>
);
}
diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/CaycConditionsListItem.tsx b/server/sonar-web/src/main/js/apps/quality-gates/components/CaycConditionsListItem.tsx
index 5dc0018f5f2..f3584343672 100644
--- a/server/sonar-web/src/main/js/apps/quality-gates/components/CaycConditionsListItem.tsx
+++ b/server/sonar-web/src/main/js/apps/quality-gates/components/CaycConditionsListItem.tsx
@@ -23,7 +23,10 @@ import { CheckIcon, LightLabel } from 'design-system';
import * as React from 'react';
import { translate } from '../../../helpers/l10n';
-export default function CaycConditionsListItem({ index, last }: { index: number; last: boolean }) {
+export default function CaycConditionsListItem({
+ index,
+ last,
+}: Readonly<{ index: number; last: boolean }>) {
return (
<li className={classNames('sw-flex', { 'sw-mb-2': !last })}>
<CheckIcon className="sw-mr-1 sw-pt-1/2" />
diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/ConditionReviewAndUpdateModal.tsx b/server/sonar-web/src/main/js/apps/quality-gates/components/ConditionReviewAndUpdateModal.tsx
index c65492aa462..1f9694811da 100644
--- a/server/sonar-web/src/main/js/apps/quality-gates/components/ConditionReviewAndUpdateModal.tsx
+++ b/server/sonar-web/src/main/js/apps/quality-gates/components/ConditionReviewAndUpdateModal.tsx
@@ -42,7 +42,7 @@ interface Props {
qualityGate: QualityGate;
}
-export default function CaycReviewUpdateConditionsModal(props: Props) {
+export default function CaycReviewUpdateConditionsModal(props: Readonly<Props>) {
const {
conditions,
qualityGate,
@@ -56,12 +56,12 @@ export default function CaycReviewUpdateConditionsModal(props: Props) {
const { weakConditions, missingConditions } = getWeakMissingAndNonCaycConditions(conditions);
const sortedWeakConditions = sortBy(
weakConditions,
- (condition) => metrics[condition.metric] && metrics[condition.metric].name,
+ (condition) => metrics[condition.metric]?.name,
);
const sortedMissingConditions = sortBy(
missingConditions,
- (condition) => metrics[condition.metric] && metrics[condition.metric].name,
+ (condition) => metrics[condition.metric]?.name,
);
const getDocUrl = useDocUrl();
diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/ConditionValueDescription.tsx b/server/sonar-web/src/main/js/apps/quality-gates/components/ConditionValueDescription.tsx
index 190f3bd8857..d3eb135958e 100644
--- a/server/sonar-web/src/main/js/apps/quality-gates/components/ConditionValueDescription.tsx
+++ b/server/sonar-web/src/main/js/apps/quality-gates/components/ConditionValueDescription.tsx
@@ -51,7 +51,7 @@ function ConditionValueDescription({
appState: { settings },
metric,
isToBeModified = false,
-}: Props) {
+}: Readonly<Props>) {
if (condition.metric === MetricKey.new_maintainability_rating) {
const maintainabilityGrid = getMaintainabilityGrid(
settings[GlobalSettingKeys.RatingGrid] ?? '',
diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/Conditions.tsx b/server/sonar-web/src/main/js/apps/quality-gates/components/Conditions.tsx
index 544c817564e..83d9dedee91 100644
--- a/server/sonar-web/src/main/js/apps/quality-gates/components/Conditions.tsx
+++ b/server/sonar-web/src/main/js/apps/quality-gates/components/Conditions.tsx
@@ -87,6 +87,7 @@ export function Conditions({
const [editing, setEditing] = React.useState<boolean>(
qualityGate.caycStatus === CaycStatus.NonCompliant,
);
+ const { name } = qualityGate;
const canEdit = Boolean(qualityGate.actions?.manageConditions);
const { conditions = [] } = qualityGate;
const existingConditions = conditions.filter((condition) => metrics[condition.metric]);
@@ -111,9 +112,11 @@ export function Conditions({
const getDocUrl = useDocUrl();
+ // set edit only when the name is change
+ // i.e when user changes the quality gate
React.useEffect(() => {
setEditing(qualityGate.caycStatus === CaycStatus.NonCompliant);
- }, [qualityGate]);
+ }, [name]); // eslint-disable-line react-hooks/exhaustive-deps
const renderConditionModal = React.useCallback(
({ onClose }: ModalProps) => {
@@ -322,7 +325,7 @@ export function Conditions({
)}
{qualityGate.caycStatus !== CaycStatus.NonCompliant && !editing && canEdit && (
- <div className="sw-mt-4 sw-mb-10 it__qg-unfollow-cayc">
+ <div className="sw-mt-4 it__qg-unfollow-cayc">
<SubHeading as="p" className="sw-mb-2 sw-body-sm">
<FormattedMessage
id="quality_gates.cayc_unfollow.description"
diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/CreateQualityGateForm.tsx b/server/sonar-web/src/main/js/apps/quality-gates/components/CreateQualityGateForm.tsx
index be2849cdf86..92b6c630ade 100644
--- a/server/sonar-web/src/main/js/apps/quality-gates/components/CreateQualityGateForm.tsx
+++ b/server/sonar-web/src/main/js/apps/quality-gates/components/CreateQualityGateForm.tsx
@@ -71,6 +71,7 @@ export class CreateQualityGateForm extends React.PureComponent<Props, State> {
requiredAriaLabel={translate('field_required')}
>
<InputField
+ className="sw-mb-1"
autoComplete="off"
id="quality-gate-form-name"
maxLength={256}
diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/Details.tsx b/server/sonar-web/src/main/js/apps/quality-gates/components/Details.tsx
index ac614d3f48f..198111715ec 100644
--- a/server/sonar-web/src/main/js/apps/quality-gates/components/Details.tsx
+++ b/server/sonar-web/src/main/js/apps/quality-gates/components/Details.tsx
@@ -17,11 +17,12 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+
+import { Spinner } from 'design-system';
import { clone } from 'lodash';
import * as React from 'react';
import { Helmet } from 'react-helmet-async';
import { fetchQualityGate } from '../../../api/quality-gates';
-import Spinner from '../../../components/ui/Spinner';
import { addGlobalSuccessMessage } from '../../../helpers/globalMessages';
import { translate } from '../../../helpers/l10n';
import { Condition, QualityGate } from '../../../types/types';
diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/DetailsContent.tsx b/server/sonar-web/src/main/js/apps/quality-gates/components/DetailsContent.tsx
index 24617cc3850..4afd92318dd 100644
--- a/server/sonar-web/src/main/js/apps/quality-gates/components/DetailsContent.tsx
+++ b/server/sonar-web/src/main/js/apps/quality-gates/components/DetailsContent.tsx
@@ -56,7 +56,7 @@ export function DetailsContent(props: DetailsContentProps) {
updatedConditionId={updatedConditionId}
/>
- <div>
+ <div className="sw-mt-10">
<div className="sw-flex sw-flex-col">
<SubTitle as="h3" className="sw-body-md-highlight">
{translate('quality_gates.projects')}
diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/List.tsx b/server/sonar-web/src/main/js/apps/quality-gates/components/List.tsx
index 92da185ae61..6c16f667f85 100644
--- a/server/sonar-web/src/main/js/apps/quality-gates/components/List.tsx
+++ b/server/sonar-web/src/main/js/apps/quality-gates/components/List.tsx
@@ -73,7 +73,9 @@ export default function List({ qualityGates, currentQualityGate }: Props) {
{(qualityGate.isDefault || qualityGate.isBuiltIn) && (
<div className="sw-mt-2">
- {qualityGate.isDefault && <Badge>{translate('default')}</Badge>}
+ {qualityGate.isDefault && (
+ <Badge className="sw-mr-2">{translate('default')}</Badge>
+ )}
{qualityGate.isBuiltIn && <BuiltInQualityGateBadge />}
</div>
)}
diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/Projects.tsx b/server/sonar-web/src/main/js/apps/quality-gates/components/Projects.tsx
index 7782337632b..0a7aef68925 100644
--- a/server/sonar-web/src/main/js/apps/quality-gates/components/Projects.tsx
+++ b/server/sonar-web/src/main/js/apps/quality-gates/components/Projects.tsx
@@ -17,6 +17,8 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+
+import { Note } from 'design-system';
import { find, without } from 'lodash';
import * as React from 'react';
import {
@@ -131,14 +133,14 @@ export default class Projects extends React.PureComponent<Props, State> {
renderElement = (key: string): React.ReactNode => {
const project = find(this.state.projects, { key });
return (
- <div className="select-list-list-item">
+ <div>
{project === undefined ? (
key
) : (
<>
{project.name}
<br />
- <span className="note">{project.key}</span>
+ <Note>{project.key}</Note>
</>
)}
</div>
diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/QualityGatePermissionsAddModalRenderer.tsx b/server/sonar-web/src/main/js/apps/quality-gates/components/QualityGatePermissionsAddModalRenderer.tsx
index 9dcfd8eb17a..42c02834648 100644
--- a/server/sonar-web/src/main/js/apps/quality-gates/components/QualityGatePermissionsAddModalRenderer.tsx
+++ b/server/sonar-web/src/main/js/apps/quality-gates/components/QualityGatePermissionsAddModalRenderer.tsx
@@ -23,6 +23,7 @@ import {
GenericAvatar,
LabelValueSelectOption,
Modal,
+ Note,
SearchSelectDropdown,
UserGroupIcon,
} from 'design-system';
@@ -49,7 +50,7 @@ const FORM_ID = 'quality-gate-permissions-add-modal';
const USER_SELECT_INPUT_ID = 'quality-gate-permissions-add-modal-select-input';
export default function QualityGatePermissionsAddModalRenderer(
- props: QualityGatePermissionsAddModalRendererProps,
+ props: Readonly<QualityGatePermissionsAddModalRendererProps>,
) {
const { selection, submitting } = props;
@@ -68,6 +69,7 @@ export default function QualityGatePermissionsAddModalRenderer(
htmlFor={USER_SELECT_INPUT_ID}
>
<SearchSelectDropdown
+ className="sw-mb-2"
controlAriaLabel={translate('quality_gates.permissions.search')}
inputId={USER_SELECT_INPUT_ID}
autoFocus
@@ -99,10 +101,10 @@ export default function QualityGatePermissionsAddModalRenderer(
function OptionRenderer({
option,
small = false,
-}: {
+}: Readonly<{
option?: UserBase | UserGroup;
small?: boolean;
-}) {
+}>) {
if (!option) {
return null;
}
@@ -118,7 +120,7 @@ function OptionRenderer({
/>
<span className="sw-ml-2">
<strong className="sw-body-sm-highlight sw-mr-1">{option.name}</strong>
- {option.login}
+ <Note>{option.login}</Note>
</span>
</>
) : (
diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/QualityGatePermissionsRenderer.tsx b/server/sonar-web/src/main/js/apps/quality-gates/components/QualityGatePermissionsRenderer.tsx
index 5434dd3736c..877bfa4aadc 100644
--- a/server/sonar-web/src/main/js/apps/quality-gates/components/QualityGatePermissionsRenderer.tsx
+++ b/server/sonar-web/src/main/js/apps/quality-gates/components/QualityGatePermissionsRenderer.tsx
@@ -17,6 +17,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+import classNames from 'classnames';
import {
ButtonSecondary,
DangerButtonPrimary,
@@ -60,8 +61,8 @@ export default function QualityGatePermissionsRenderer(props: QualityGatePermiss
<SubTitle as="h3" className="sw-body-md-highlight">
{translate('quality_gates.permissions')}
</SubTitle>
- <p className="sw-body-sm sw-mb-2">{translate('quality_gates.permissions.help')}</p>
- <div>
+ <p className="sw-body-sm">{translate('quality_gates.permissions.help')}</p>
+ <div className={classNames({ 'sw-my-2': users.length + groups.length > 0 })}>
<Spinner loading={loading}>
<Table columnCount={3} columnWidths={['40px', 'auto', '1%']} width="100%">
{users.map((user) => (
@@ -78,7 +79,7 @@ export default function QualityGatePermissionsRenderer(props: QualityGatePermiss
</Spinner>
</div>
- <ButtonSecondary className="sw-mt-4" onClick={props.onClickAddPermission}>
+ <ButtonSecondary className="sw-mt-2" onClick={props.onClickAddPermission}>
{translate('quality_gates.permissions.grant')}
</ButtonSecondary>
diff --git a/server/sonar-web/src/main/js/components/controls/SelectListListContainer.tsx b/server/sonar-web/src/main/js/components/controls/SelectListListContainer.tsx
index 033a6aeed1c..f68b0e6e623 100644
--- a/server/sonar-web/src/main/js/components/controls/SelectListListContainer.tsx
+++ b/server/sonar-web/src/main/js/components/controls/SelectListListContainer.tsx
@@ -19,7 +19,6 @@
*/
import styled from '@emotion/styled';
import { Checkbox, ListItem, UnorderedList, themeBorder } from 'design-system';
-import { uniqueId } from 'lodash';
import * as React from 'react';
import { translate } from '../../helpers/l10n';
import { SelectListFilter } from './SelectList';
@@ -111,7 +110,7 @@ export default class SelectListListContainer extends React.PureComponent<Props,
<SelectListListElement
disabled={this.isDisabled(element)}
element={element}
- key={uniqueId()}
+ key={element}
onSelect={this.props.onSelect}
onUnselect={this.props.onUnselect}
renderElement={this.props.renderElement}