diff options
author | Kevin Silva <kevin.silva@sonarsource.com> | 2023-09-18 11:41:23 +0200 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2023-09-19 20:02:46 +0000 |
commit | c13c409e59105e0187da35c14e7ba1d2e76a39a7 (patch) | |
tree | f4c99499f1380e7f350cbec5d98ef6f6ea72b351 /server/sonar-web/src | |
parent | 1fc0c6cbdf4b31d8d62e91545bb6a5b3660f3949 (diff) | |
download | sonarqube-c13c409e59105e0187da35c14e7ba1d2e76a39a7.tar.gz sonarqube-c13c409e59105e0187da35c14e7ba1d2e76a39a7.zip |
SONAR-20337 Validation fixes for QG
Diffstat (limited to 'server/sonar-web/src')
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} |