diff options
author | Stas Vilchik <stas.vilchik@sonarsource.com> | 2018-10-29 15:24:06 +0100 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2018-10-30 12:42:03 +0100 |
commit | 440e9db98d7e1a748cb02c8839e21e94ebd2efa4 (patch) | |
tree | cddffbbae2f421bf8433663e5abb6bce7e993997 | |
parent | 39db83f50fc00ad01b2ed898bf6a8b39b51f4c9c (diff) | |
download | sonarqube-440e9db98d7e1a748cb02c8839e21e94ebd2efa4.tar.gz sonarqube-440e9db98d7e1a748cb02c8839e21e94ebd2efa4.zip |
SONAR-11204 Colorblind friendly banners (#899)
106 files changed, 680 insertions, 420 deletions
diff --git a/server/sonar-web/src/main/js/app/components/GlobalFooter.tsx b/server/sonar-web/src/main/js/app/components/GlobalFooter.tsx index d50fd613b48..be0881f79df 100644 --- a/server/sonar-web/src/main/js/app/components/GlobalFooter.tsx +++ b/server/sonar-web/src/main/js/app/components/GlobalFooter.tsx @@ -25,6 +25,7 @@ import InstanceMessage from '../../components/common/InstanceMessage'; import { EDITIONS, EditionKey } from '../../apps/marketplace/utils'; import { translate, translateWithParameters } from '../../helpers/l10n'; import { isSonarCloud } from '../../helpers/system'; +import { Alert } from '../../components/ui/Alert'; interface Props { hideLoggedInInfo?: boolean; @@ -48,14 +49,12 @@ export default function GlobalFooter({ return ( <div className="page-footer page-container" id="footer"> {productionDatabase === false && ( - <div className="alert alert-danger"> - <p className="big" id="evaluation_warning"> - {translate('footer.production_database_warning')} - </p> + <Alert display="inline" id="evaluation_warning" variant="warning"> + <p className="big">{translate('footer.production_database_warning')}</p> <p> <InstanceMessage message={translate('footer.production_database_explanation')} /> </p> - </div> + </Alert> )} <GlobalFooterBranding /> diff --git a/server/sonar-web/src/main/js/app/components/__tests__/GlobalFooter-test.tsx b/server/sonar-web/src/main/js/app/components/__tests__/GlobalFooter-test.tsx index 5d493f1c3c6..1a29a45e535 100644 --- a/server/sonar-web/src/main/js/app/components/__tests__/GlobalFooter-test.tsx +++ b/server/sonar-web/src/main/js/app/components/__tests__/GlobalFooter-test.tsx @@ -36,7 +36,7 @@ it('should not render the only logged in information', () => { }); it('should show the db warning message', () => { - expect(getWrapper({ productionDatabase: false }).find('.alert')).toMatchSnapshot(); + expect(getWrapper({ productionDatabase: false }).find('Alert')).toMatchSnapshot(); }); it('should display the sq version', () => { diff --git a/server/sonar-web/src/main/js/app/components/__tests__/__snapshots__/GlobalFooter-test.tsx.snap b/server/sonar-web/src/main/js/app/components/__tests__/__snapshots__/GlobalFooter-test.tsx.snap index edff04e27c5..43e65baec7c 100644 --- a/server/sonar-web/src/main/js/app/components/__tests__/__snapshots__/GlobalFooter-test.tsx.snap +++ b/server/sonar-web/src/main/js/app/components/__tests__/__snapshots__/GlobalFooter-test.tsx.snap @@ -236,12 +236,13 @@ exports[`should render the only logged in information 1`] = ` `; exports[`should show the db warning message 1`] = ` -<div - className="alert alert-danger" +<Alert + display="inline" + id="evaluation_warning" + variant="warning" > <p className="big" - id="evaluation_warning" > footer.production_database_warning </p> @@ -250,5 +251,5 @@ exports[`should show the db warning message 1`] = ` message="footer.production_database_explanation" /> </p> -</div> +</Alert> `; diff --git a/server/sonar-web/src/main/js/app/components/extensions/exposeLibraries.ts b/server/sonar-web/src/main/js/app/components/extensions/exposeLibraries.ts index c4fc23fa0db..b59d7943e60 100644 --- a/server/sonar-web/src/main/js/app/components/extensions/exposeLibraries.ts +++ b/server/sonar-web/src/main/js/app/components/extensions/exposeLibraries.ts @@ -63,6 +63,7 @@ import ConfirmButton from '../../../components/controls/ConfirmButton'; import SimpleModal from '../../../components/controls/SimpleModal'; import SearchSelect from '../../../components/controls/SearchSelect'; import RadioToggle from '../../../components/controls/RadioToggle'; +import { Alert } from '../../../components/ui/Alert'; const exposeLibraries = () => { const global = window as any; @@ -74,6 +75,7 @@ const exposeLibraries = () => { global.SonarComponents = { ActionsDropdown, ActionsDropdownItem, + Alert, AlertErrorIcon, AlertSuccessIcon, AlertWarnIcon, diff --git a/server/sonar-web/src/main/js/app/components/nav/component/ComponentNavBgTaskNotif.tsx b/server/sonar-web/src/main/js/app/components/nav/component/ComponentNavBgTaskNotif.tsx index b1c11892ac9..86ca810dcfd 100644 --- a/server/sonar-web/src/main/js/app/components/nav/component/ComponentNavBgTaskNotif.tsx +++ b/server/sonar-web/src/main/js/app/components/nav/component/ComponentNavBgTaskNotif.tsx @@ -65,14 +65,14 @@ export default class ComponentNavBgTaskNotif extends React.PureComponent<Props> const { currentTask, currentTaskOnSameBranch, isInProgress, isPending } = this.props; if (isInProgress) { return ( - <NavBarNotif className="alert alert-info"> + <NavBarNotif variant="info"> <i className="spinner spacer-right text-bottom" /> {this.renderMessage('component_navigation.status.in_progress')} </NavBarNotif> ); } else if (isPending) { return ( - <NavBarNotif className="alert alert-info"> + <NavBarNotif variant="info"> <PendingIcon className="spacer-right" /> {this.renderMessage('component_navigation.status.pending', STATUSES.ALL)} </NavBarNotif> @@ -100,7 +100,7 @@ export default class ComponentNavBgTaskNotif extends React.PureComponent<Props> message = this.renderMessage('component_navigation.status.failed'); } - return <NavBarNotif className="alert alert-danger">{message}</NavBarNotif>; + return <NavBarNotif variant="error">{message}</NavBarNotif>; } return null; } diff --git a/server/sonar-web/src/main/js/app/components/nav/component/ComponentNavLicenseNotif.tsx b/server/sonar-web/src/main/js/app/components/nav/component/ComponentNavLicenseNotif.tsx index 112158e5b2f..1fc44c1cbbb 100644 --- a/server/sonar-web/src/main/js/app/components/nav/component/ComponentNavLicenseNotif.tsx +++ b/server/sonar-web/src/main/js/app/components/nav/component/ComponentNavLicenseNotif.tsx @@ -78,7 +78,7 @@ export default class ComponentNavLicenseNotif extends React.PureComponent<Props, if (isValidLicense && currentTask.errorType !== 'LICENSING_LOC') { return ( - <NavBarNotif className="alert alert-danger"> + <NavBarNotif variant="error"> <span className="little-spacer-right"> {translate('component_navigation.status.last_blocked_due_to_bad_license')} </span> @@ -87,7 +87,7 @@ export default class ComponentNavLicenseNotif extends React.PureComponent<Props, } return ( - <NavBarNotif className="alert alert-danger"> + <NavBarNotif variant="error"> <span className="little-spacer-right">{currentTask.errorMessage}</span> {this.context.canAdmin ? ( <Link to="/admin/extension/license/app"> diff --git a/server/sonar-web/src/main/js/app/components/nav/component/__tests__/__snapshots__/ComponentNavBgTaskNotif-test.tsx.snap b/server/sonar-web/src/main/js/app/components/nav/component/__tests__/__snapshots__/ComponentNavBgTaskNotif-test.tsx.snap index 30951176dac..1386465802b 100644 --- a/server/sonar-web/src/main/js/app/components/nav/component/__tests__/__snapshots__/ComponentNavBgTaskNotif-test.tsx.snap +++ b/server/sonar-web/src/main/js/app/components/nav/component/__tests__/__snapshots__/ComponentNavBgTaskNotif-test.tsx.snap @@ -2,7 +2,7 @@ exports[`renders background task error correctly 1`] = ` <NavBarNotif - className="alert alert-danger" + variant="error" > <FormattedMessage defaultMessage="component_navigation.status.failed" @@ -19,7 +19,7 @@ exports[`renders background task error correctly 1`] = ` exports[`renders background task error correctly for a different branch/PR 1`] = ` <NavBarNotif - className="alert alert-danger" + variant="error" > <FormattedMessage defaultMessage="component_navigation.status.failed_branch" @@ -36,7 +36,7 @@ exports[`renders background task error correctly for a different branch/PR 1`] = exports[`renders background task error correctly for a different branch/PR 2`] = ` <NavBarNotif - className="alert alert-danger" + variant="error" > <FormattedMessage defaultMessage="component_navigation.status.failed_branch" @@ -53,7 +53,7 @@ exports[`renders background task error correctly for a different branch/PR 2`] = exports[`renders background task in progress info correctly 1`] = ` <NavBarNotif - className="alert alert-info" + variant="info" > <i className="spinner spacer-right text-bottom" @@ -85,7 +85,7 @@ exports[`renders background task license info correctly 1`] = ` exports[`renders background task pending info correctly 1`] = ` <NavBarNotif - className="alert alert-info" + variant="info" > <PendingIcon className="spacer-right" @@ -105,7 +105,7 @@ exports[`renders background task pending info correctly 1`] = ` exports[`renders background task pending info correctly for admin 1`] = ` <NavBarNotif - className="alert alert-info" + variant="info" > <PendingIcon className="spacer-right" diff --git a/server/sonar-web/src/main/js/app/components/nav/component/__tests__/__snapshots__/ComponentNavLicenseNotif-test.tsx.snap b/server/sonar-web/src/main/js/app/components/nav/component/__tests__/__snapshots__/ComponentNavLicenseNotif-test.tsx.snap index b9da1de4908..94c8f9251da 100644 --- a/server/sonar-web/src/main/js/app/components/nav/component/__tests__/__snapshots__/ComponentNavLicenseNotif-test.tsx.snap +++ b/server/sonar-web/src/main/js/app/components/nav/component/__tests__/__snapshots__/ComponentNavLicenseNotif-test.tsx.snap @@ -2,7 +2,7 @@ exports[`renders a different message if the license is valid 1`] = ` <NavBarNotif - className="alert alert-danger" + variant="error" > <span className="little-spacer-right" @@ -14,7 +14,7 @@ exports[`renders a different message if the license is valid 1`] = ` exports[`renders background task license info correctly 1`] = ` <NavBarNotif - className="alert alert-danger" + variant="error" > <span className="little-spacer-right" @@ -34,7 +34,7 @@ exports[`renders background task license info correctly 1`] = ` exports[`renders background task license info correctly 2`] = ` <NavBarNotif - className="alert alert-danger" + variant="error" > <span className="little-spacer-right" @@ -47,7 +47,7 @@ exports[`renders background task license info correctly 2`] = ` exports[`renders correctly for LICENSING_LOC error 1`] = ` <NavBarNotif - className="alert alert-danger" + variant="error" > <span className="little-spacer-right" diff --git a/server/sonar-web/src/main/js/app/components/nav/settings/PendingPluginsActionNotif.tsx b/server/sonar-web/src/main/js/app/components/nav/settings/PendingPluginsActionNotif.tsx index 5f475b3d27a..0e591a980b2 100644 --- a/server/sonar-web/src/main/js/app/components/nav/settings/PendingPluginsActionNotif.tsx +++ b/server/sonar-web/src/main/js/app/components/nav/settings/PendingPluginsActionNotif.tsx @@ -58,7 +58,7 @@ export default class PendingPluginsActionNotif extends React.PureComponent<Props } return ( - <NavBarNotif className="alert alert-info js-pending"> + <NavBarNotif className="js-pending" variant="info"> <span className="little-spacer-right"> <InstanceMessage message={translate('marketplace.instance_needs_to_be_restarted_to')} /> </span> diff --git a/server/sonar-web/src/main/js/app/components/nav/settings/__tests__/__snapshots__/PendingPluginsActionNotif-test.tsx.snap b/server/sonar-web/src/main/js/app/components/nav/settings/__tests__/__snapshots__/PendingPluginsActionNotif-test.tsx.snap index 404b2a96734..4deb78f7135 100644 --- a/server/sonar-web/src/main/js/app/components/nav/settings/__tests__/__snapshots__/PendingPluginsActionNotif-test.tsx.snap +++ b/server/sonar-web/src/main/js/app/components/nav/settings/__tests__/__snapshots__/PendingPluginsActionNotif-test.tsx.snap @@ -2,7 +2,8 @@ exports[`should display pending actions 1`] = ` <NavBarNotif - className="alert alert-info js-pending" + className="js-pending" + variant="info" > <span className="little-spacer-right" diff --git a/server/sonar-web/src/main/js/app/styles/components/alerts.css b/server/sonar-web/src/main/js/app/styles/components/alerts.css index 97457fe8dd6..f5276040c32 100644 --- a/server/sonar-web/src/main/js/app/styles/components/alerts.css +++ b/server/sonar-web/src/main/js/app/styles/components/alerts.css @@ -18,69 +18,78 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ .alert { - display: block; - margin-bottom: 8px; - padding: 5px 8px; - border: 1px solid var(--secondFontColor); + display: flex; + align-items: stretch; + margin-bottom: var(--gridSize); + border: 1px solid; + border-radius: 2px; +} + +.alert.is-inline { + display: inline-flex; } .alert:empty { display: none; } -.modal-alert { - margin: -10px -10px 16px; - padding: 10px; - border-top: none; - border-left: none; - border-right: none; +.alert-icon { + flex: 0 0 auto; + display: flex; + justify-content: center; + align-items: center; + width: calc(4 * var(--gridSize)); + border-right: 1px solid; } -.alert-danger { - border-color: #ebccd1; - background-color: #f2dede; - color: #a94442; +.alert-content { + flex: 1 0 0; + padding: var(--gridSize) calc(2 * var(--gridSize)); + overflow: auto; + text-align: left; } -.alert-warning { - border-color: #faebcc; - background-color: #fcf8e3; - color: #8a6d3b; +.alert-content a, +.alert-content .button-link { + border-color: var(--darkBlue); } -.alert-info { - border-color: #bce8f1; - background-color: #d9edf7; - color: #666666; +.alert-error { + border-color: var(--alertBorderError); + background-color: var(--alertBackgroundError); + color: var(--alertTextError); } -.alert-success { - border-color: #d6e9c6; - background-color: #dff0d8; - color: #3c763d; +.alert-error .alert-icon { + border-color: var(--alertBorderError); } -.alert-muted { - color: var(--disableGrayText); - border-color: var(--disableGrayBorder); - background-color: var(--disableGrayBg); +.alert-warning { + border-color: var(--alertBorderWarning); + background-color: var(--alertBackgroundWarning); + color: var(--alertTextWarning); } -.alert-big { - font-size: var(--mediumFontSize); - padding: 10px 16px; +.alert-warning .alert-icon { + border-color: var(--alertBorderWarning); } -.alert-small { - font-size: var(--verySmallFontSize); - margin-bottom: 0; - padding: 2px 4px; +.alert-info { + border-color: var(--alertBorderInfo); + background-color: var(--alertBackgroundInfo); + color: var(--alertTextInfo); } -.page-notifs .alert { - padding: 8px 10px; +.alert-info .alert-icon { + border-color: var(--alertBorderInfo); +} + +.alert-success { + border-color: var(--alertBorderSuccess); + background-color: var(--alertBackgroundSuccess); + color: var(--alertTextSuccess); } -.page-notifs .alert:last-child { - margin-bottom: 16px; +.alert-success .alert-icon { + border-color: var(--alertBorderSuccess); } diff --git a/server/sonar-web/src/main/js/app/styles/components/boxed-group.css b/server/sonar-web/src/main/js/app/styles/components/boxed-group.css index 08e25e19aa9..f816952395e 100644 --- a/server/sonar-web/src/main/js/app/styles/components/boxed-group.css +++ b/server/sonar-web/src/main/js/app/styles/components/boxed-group.css @@ -92,8 +92,8 @@ padding-bottom: calc(2 * var(--gridSize)); } -.boxed-group-accordion .boxed-group-header > .alert { - display: inline-block; +.boxed-group-accordion-alert.boxed-group-accordion-alert { + vertical-align: middle; margin-bottom: -6px; margin-top: -6px; } @@ -103,6 +103,9 @@ } .boxed-group-accordion-title { + display: inline-flex; + align-items: center; + vertical-align: middle; font-weight: bold; transition: color 0.3s ease; } diff --git a/server/sonar-web/src/main/js/app/styles/sonarcloud.css b/server/sonar-web/src/main/js/app/styles/sonarcloud.css index aa5ab408659..4be34dc3c7a 100644 --- a/server/sonar-web/src/main/js/app/styles/sonarcloud.css +++ b/server/sonar-web/src/main/js/app/styles/sonarcloud.css @@ -68,3 +68,19 @@ color: var(--blue); border-bottom-color: var(--blue); } + +.beta-badge { + display: inline-block; + padding: 2px 4px; + border: 1px solid var(--alertBorderInfo); + border-radius: 2px; + background-color: var(--alertBackgroundInfo); + color: var(--alertTextInfo); + font-size: 10px; +} + +.beta-badge.is-muted { + border-color: var(--disableGrayBorder); + background-color: var(--disableGrayBg); + color: var(--disableGrayText); +} diff --git a/server/sonar-web/src/main/js/app/styles/style.css b/server/sonar-web/src/main/js/app/styles/style.css index 61be8927c26..e8835cae098 100644 --- a/server/sonar-web/src/main/js/app/styles/style.css +++ b/server/sonar-web/src/main/js/app/styles/style.css @@ -65,11 +65,11 @@ line-height: 1.5; } -.markdown.cut-margins > *:first-child { +.cut-margins > *:first-child { margin-top: 0 !important; } -.markdown.cut-margins > *:last-child { +.cut-margins > *:last-child { margin-bottom: 0 !important; } diff --git a/server/sonar-web/src/main/js/app/theme.js b/server/sonar-web/src/main/js/app/theme.js index ccaff6a1bf0..09c8c994264 100644 --- a/server/sonar-web/src/main/js/app/theme.js +++ b/server/sonar-web/src/main/js/app/theme.js @@ -59,6 +59,26 @@ module.exports = { // alerts warningIconColor: '#e2bf41', + alertBorderError: '#ebccd1', + alertBackgroundError: '#f2dede', + alertTextError: '#862422', + alertIconError: '#b81723', + + alertBorderWarning: '#faebcc', + alertBackgroundWarning: '#fcf8e3', + alertTextWarning: '#6f4f17', + alertIconWarning: '#db781a', + + alertBorderSuccess: '#d6e9c6', + alertBackgroundSuccess: '#dff0d8', + alertTextSuccess: '#215821', + alertIconSuccess: '#6d9867', + + alertBorderInfo: '#b1dff3', + alertBackgroundInfo: '#d9edf7', + alertTextInfo: '#0e516f', + alertIconInfo: '#0271b9', + // sizes grid, gridSize: `${grid}px`, diff --git a/server/sonar-web/src/main/js/apps/about/sonarcloud/Contact.tsx b/server/sonar-web/src/main/js/apps/about/sonarcloud/Contact.tsx index 3471efb6982..c3b1863ea79 100644 --- a/server/sonar-web/src/main/js/apps/about/sonarcloud/Contact.tsx +++ b/server/sonar-web/src/main/js/apps/about/sonarcloud/Contact.tsx @@ -23,6 +23,7 @@ import { Location } from 'history'; import SonarCloudPage from './SonarCloudPage'; import Select from '../../../components/controls/Select'; import { isLoggedIn, Organization } from '../../../app/types'; +import { Alert } from '../../../components/ui/Alert'; import './style.css'; const CATEGORIES = [ @@ -83,7 +84,7 @@ export default class Contact extends React.PureComponent<Props, State> { {({ currentUser, userOrganizations }) => ( <div className="page page-limited sc-page sc-contact-page"> <h1 className="sc-page-title">Contact us</h1> - <p className="alert alert-warning alert-big display-inline-block"> + <Alert display="inline" variant="warning"> If you are looking for help with SonarCloud, our{' '} <a href="https://community.sonarsource.com/c/help/sc" @@ -92,11 +93,11 @@ export default class Contact extends React.PureComponent<Props, State> { <strong>Support forum</strong> </a>{' '} is the best place to get help. - </p> + </Alert> <br /> - <p className="alert alert-warning alert-big display-inline-block"> + <Alert display="inline" variant="warning"> Please contact us only if you couldn't solve your problem with the forum help. - </p> + </Alert> {!isLoggedIn(currentUser) && ( <p> You can{' '} diff --git a/server/sonar-web/src/main/js/apps/account/components/Password.tsx b/server/sonar-web/src/main/js/apps/account/components/Password.tsx index 5834e143db4..b3cc2f831ae 100644 --- a/server/sonar-web/src/main/js/apps/account/components/Password.tsx +++ b/server/sonar-web/src/main/js/apps/account/components/Password.tsx @@ -22,6 +22,7 @@ import { changePassword } from '../../../api/users'; import { SubmitButton } from '../../../components/ui/buttons'; import { translate } from '../../../helpers/l10n'; import { LoggedInUser } from '../../../app/types'; +import { Alert } from '../../../components/ui/Alert'; interface Props { user: LoggedInUser; @@ -78,15 +79,13 @@ export default class Password extends React.Component<Props, State> { <h2 className="spacer-bottom">{translate('my_profile.password.title')}</h2> <form className="boxed-group-inner" onSubmit={this.handleChangePassword}> - {success && ( - <div className="alert alert-success">{translate('my_profile.password.changed')}</div> - )} + {success && <Alert variant="success">{translate('my_profile.password.changed')}</Alert>} {errors && errors.map((e, i) => ( - <div className="alert alert-danger" key={i}> + <Alert key={i} variant="error"> {e} - </div> + </Alert> ))} <div className="modal-field"> diff --git a/server/sonar-web/src/main/js/apps/account/notifications/Notifications.tsx b/server/sonar-web/src/main/js/apps/account/notifications/Notifications.tsx index a6c2c76b631..949b0285c7e 100644 --- a/server/sonar-web/src/main/js/apps/account/notifications/Notifications.tsx +++ b/server/sonar-web/src/main/js/apps/account/notifications/Notifications.tsx @@ -28,6 +28,7 @@ import * as api from '../../../api/notifications'; import { Notification } from '../../../app/types'; import DeferredSpinner from '../../../components/common/DeferredSpinner'; import { translate } from '../../../helpers/l10n'; +import { Alert } from '../../../components/ui/Alert'; export interface Props { fetchOrganizations: (organizations: string[]) => void; @@ -147,7 +148,7 @@ export default class Notifications extends React.PureComponent<Props, State> { return ( <div className="account-body account-container"> <Helmet title={translate('my_account.notifications')} /> - <p className="alert alert-info">{translate('notification.dispatcher.information')}</p> + <Alert variant="info">{translate('notification.dispatcher.information')}</Alert> <DeferredSpinner loading={this.state.loading}> {this.state.notifications && ( <> diff --git a/server/sonar-web/src/main/js/apps/account/notifications/__tests__/__snapshots__/Notifications-test.tsx.snap b/server/sonar-web/src/main/js/apps/account/notifications/__tests__/__snapshots__/Notifications-test.tsx.snap index 96d1877f480..a24b8456f1d 100644 --- a/server/sonar-web/src/main/js/apps/account/notifications/__tests__/__snapshots__/Notifications-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/account/notifications/__tests__/__snapshots__/Notifications-test.tsx.snap @@ -9,11 +9,11 @@ exports[`should fetch notifications and render 1`] = ` encodeSpecialCharacters={true} title="my_account.notifications" /> - <p - className="alert alert-info" + <Alert + variant="info" > notification.dispatcher.information - </p> + </Alert> <DeferredSpinner loading={false} timeout={100} diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/WorkersForm.tsx b/server/sonar-web/src/main/js/apps/background-tasks/components/WorkersForm.tsx index c36c882e7ca..62603d021bb 100644 --- a/server/sonar-web/src/main/js/apps/background-tasks/components/WorkersForm.tsx +++ b/server/sonar-web/src/main/js/apps/background-tasks/components/WorkersForm.tsx @@ -23,6 +23,7 @@ import Modal from '../../../components/controls/Modal'; import Select from '../../../components/controls/Select'; import { SubmitButton, ResetButtonLink } from '../../../components/ui/buttons'; import { translate } from '../../../helpers/l10n'; +import { Alert } from '../../../components/ui/Alert'; const MAX_WORKERS = 10; @@ -103,9 +104,9 @@ export default class WorkersForm extends React.PureComponent<Props, State> { searchable={false} value={this.state.newWorkerCount} /> - <div className="big-spacer-top alert alert-success markdown"> + <Alert className="big-spacer-top" variant="info"> {translate('background_tasks.change_number_of_workers.hint')} - </div> + </Alert> </div> <footer className="modal-foot"> <div> diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/__snapshots__/WorkersForm-test.tsx.snap b/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/__snapshots__/WorkersForm-test.tsx.snap index 0b1320c6cb2..527175beff3 100644 --- a/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/__snapshots__/WorkersForm-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/__snapshots__/WorkersForm-test.tsx.snap @@ -69,11 +69,12 @@ exports[`changes select 1`] = ` searchable={false} value={1} /> - <div - className="big-spacer-top alert alert-success markdown" + <Alert + className="big-spacer-top" + variant="info" > background_tasks.change_number_of_workers.hint - </div> + </Alert> </div> <footer className="modal-foot" @@ -164,11 +165,12 @@ exports[`changes select 2`] = ` searchable={false} value={7} /> - <div - className="big-spacer-top alert alert-success markdown" + <Alert + className="big-spacer-top" + variant="info" > background_tasks.change_number_of_workers.hint - </div> + </Alert> </div> <footer className="modal-foot" diff --git a/server/sonar-web/src/main/js/apps/coding-rules/components/ActivationFormModal.tsx b/server/sonar-web/src/main/js/apps/coding-rules/components/ActivationFormModal.tsx index 3d265133d95..d72adba3402 100644 --- a/server/sonar-web/src/main/js/apps/coding-rules/components/ActivationFormModal.tsx +++ b/server/sonar-web/src/main/js/apps/coding-rules/components/ActivationFormModal.tsx @@ -27,6 +27,7 @@ import { SEVERITIES } from '../../../helpers/constants'; import { translate } from '../../../helpers/l10n'; import { sortProfiles } from '../../quality-profiles/utils'; import { SubmitButton, ResetButtonLink } from '../../../components/ui/buttons'; +import { Alert } from '../../../components/ui/Alert'; interface Props { activation?: RuleActivation; @@ -163,9 +164,7 @@ export default class ActivationFormModal extends React.PureComponent<Props, Stat <div className="modal-body"> {!isUpdateMode && activeInAllProfiles && ( - <div className="alert alert-info"> - {translate('coding_rules.active_in_all_profiles')} - </div> + <Alert variant="info">{translate('coding_rules.active_in_all_profiles')}</Alert> )} <div className="modal-field"> diff --git a/server/sonar-web/src/main/js/apps/coding-rules/components/BulkChangeModal.tsx b/server/sonar-web/src/main/js/apps/coding-rules/components/BulkChangeModal.tsx index 1840cc0ec90..e16077643e7 100644 --- a/server/sonar-web/src/main/js/apps/coding-rules/components/BulkChangeModal.tsx +++ b/server/sonar-web/src/main/js/apps/coding-rules/components/BulkChangeModal.tsx @@ -18,7 +18,6 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import * as React from 'react'; -import * as classNames from 'classnames'; import { Query, serializeQuery } from '../query'; import { Profile, bulkActivateRules, bulkDeactivateRules } from '../../../api/quality-profiles'; import Modal from '../../../components/controls/Modal'; @@ -27,6 +26,7 @@ import { translate, translateWithParameters } from '../../../helpers/l10n'; import { formatMeasure } from '../../../helpers/measures'; import { SubmitButton, ResetButtonLink } from '../../../components/ui/buttons'; import { Languages } from '../../../app/types'; +import { Alert } from '../../../components/ui/Alert'; interface Props { action: string; @@ -155,12 +155,7 @@ export default class BulkChangeModal extends React.PureComponent<Props, State> { ? languages[profile.language].name : profile.language; return ( - <div - className={classNames('alert', { - 'alert-warning': result.failed > 0, - 'alert-success': result.failed === 0 - })} - key={result.profile}> + <Alert key={result.profile} variant={result.failed === 0 ? 'success' : 'warning'}> {result.failed ? translateWithParameters( 'coding_rules.bulk_change.warning', @@ -175,7 +170,7 @@ export default class BulkChangeModal extends React.PureComponent<Props, State> { language, result.succeeded )} - </div> + </Alert> ); }; diff --git a/server/sonar-web/src/main/js/apps/coding-rules/components/CustomRuleFormModal.tsx b/server/sonar-web/src/main/js/apps/coding-rules/components/CustomRuleFormModal.tsx index 19dc50eb809..76723ce03cb 100644 --- a/server/sonar-web/src/main/js/apps/coding-rules/components/CustomRuleFormModal.tsx +++ b/server/sonar-web/src/main/js/apps/coding-rules/components/CustomRuleFormModal.tsx @@ -30,6 +30,7 @@ import SeverityHelper from '../../../components/shared/SeverityHelper'; import { createRule, updateRule } from '../../../api/rules'; import { csvEscape } from '../../../helpers/csv'; import { SubmitButton, ResetButtonLink } from '../../../components/ui/buttons'; +import { Alert } from '../../../components/ui/Alert'; interface Props { customRule?: RuleDetails; @@ -372,7 +373,7 @@ export default class CustomRuleFormModal extends React.PureComponent<Props, Stat <div className="modal-body modal-container"> {reactivating && ( - <div className="alert alert-warning">{translate('coding_rules.reactivate.help')}</div> + <Alert variant="warning">{translate('coding_rules.reactivate.help')}</Alert> )} <table> <tbody> diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/MetricNotFound.tsx b/server/sonar-web/src/main/js/apps/component-measures/components/MetricNotFound.tsx index 6009d74a6c9..f892db8a8d3 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/components/MetricNotFound.tsx +++ b/server/sonar-web/src/main/js/apps/component-measures/components/MetricNotFound.tsx @@ -19,11 +19,13 @@ */ import * as React from 'react'; import { translate } from '../../../helpers/l10n'; +import { Alert } from '../../../components/ui/Alert'; +// TODO seems like this component is used by never rendered in real life export default function MetricNotFound({ className }: { className?: string }) { return ( <div className={className}> - <div className="alert alert-danger">{translate('component_measures.not_found')}</div> + <Alert variant="error">{translate('component_measures.not_found')}</Alert> </div> ); } diff --git a/server/sonar-web/src/main/js/apps/component-measures/drilldown/FilesView.tsx b/server/sonar-web/src/main/js/apps/component-measures/drilldown/FilesView.tsx index ce19d48ae3f..0413514857e 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/drilldown/FilesView.tsx +++ b/server/sonar-web/src/main/js/apps/component-measures/drilldown/FilesView.tsx @@ -33,6 +33,7 @@ import { import { translate, translateWithParameters } from '../../../helpers/l10n'; import { isPeriodBestValue, isDiffMetric, formatMeasure } from '../../../helpers/measures'; import { scrollToElement } from '../../../helpers/scrolling'; +import { Alert } from '../../../components/ui/Alert'; interface Props { branchLike?: BranchLike; @@ -177,7 +178,7 @@ export default class ListView extends React.PureComponent<Props, State> { selectedComponent={this.props.selectedKey} /> {hidingBestMeasures && ( - <div className="alert alert-info spacer-top"> + <Alert className="spacer-top" variant="info"> {translateWithParameters( 'component_measures.hidden_best_score_metrics', components.length - filteredComponents.length, @@ -186,7 +187,7 @@ export default class ListView extends React.PureComponent<Props, State> { <Button className="button-link spacer-left" onClick={this.handleShowBestMeasures}> {translate('show_all')} </Button> - </div> + </Alert> )} {!hidingBestMeasures && this.props.paging && diff --git a/server/sonar-web/src/main/js/apps/component-measures/drilldown/__tests__/__snapshots__/FilesView-test.tsx.snap b/server/sonar-web/src/main/js/apps/component-measures/drilldown/__tests__/__snapshots__/FilesView-test.tsx.snap index b63601b1b71..e9c91714593 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/drilldown/__tests__/__snapshots__/FilesView-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/component-measures/drilldown/__tests__/__snapshots__/FilesView-test.tsx.snap @@ -43,8 +43,9 @@ exports[`should render with best values hidden 1`] = ` } } /> - <div - className="alert alert-info spacer-top" + <Alert + className="spacer-top" + variant="info" > component_measures.hidden_best_score_metrics.1. <Button @@ -53,7 +54,7 @@ exports[`should render with best values hidden 1`] = ` > show_all </Button> - </div> + </Alert> </div> `; diff --git a/server/sonar-web/src/main/js/apps/custom-measures/components/Form.tsx b/server/sonar-web/src/main/js/apps/custom-measures/components/Form.tsx index 2ceb90694d8..40c2a87f64e 100644 --- a/server/sonar-web/src/main/js/apps/custom-measures/components/Form.tsx +++ b/server/sonar-web/src/main/js/apps/custom-measures/components/Form.tsx @@ -25,6 +25,7 @@ import Select from '../../../components/controls/Select'; import SimpleModal from '../../../components/controls/SimpleModal'; import { SubmitButton, ResetButtonLink } from '../../../components/ui/buttons'; import { translate } from '../../../helpers/l10n'; +import { Alert } from '../../../components/ui/Alert'; interface Props { confirmButtonText: string; @@ -109,9 +110,7 @@ export default class Form extends React.PureComponent<Props, State> { renderMetricSelect = (options: { label: string; value: string }[]) => { if (!options.length && !this.state.loading) { - return ( - <div className="alert alert-warning">{translate('custom_measures.all_metrics_taken')}</div> - ); + return <Alert variant="warning">{translate('custom_measures.all_metrics_taken')}</Alert>; } return ( <div className="modal-field"> diff --git a/server/sonar-web/src/main/js/apps/custom-measures/components/Header.tsx b/server/sonar-web/src/main/js/apps/custom-measures/components/Header.tsx index 1cff05b53e5..bf393f4589f 100644 --- a/server/sonar-web/src/main/js/apps/custom-measures/components/Header.tsx +++ b/server/sonar-web/src/main/js/apps/custom-measures/components/Header.tsx @@ -21,6 +21,7 @@ import * as React from 'react'; import CreateButton from './CreateButton'; import DeferredSpinner from '../../../components/common/DeferredSpinner'; import { translate } from '../../../helpers/l10n'; +import { Alert } from '../../../components/ui/Alert'; interface Props { loading: boolean; @@ -37,7 +38,9 @@ export default function Header({ loading, onCreate, skipMetrics }: Props) { <CreateButton onCreate={onCreate} skipMetrics={skipMetrics} /> </div> <div className="page-description"> - <div className="alert alert-danger">{translate('custom_measures.deprecated')}</div> + <Alert display="inline" variant="error"> + {translate('custom_measures.deprecated')} + </Alert> <p>{translate('custom_measures.page.description')}</p> </div> </header> diff --git a/server/sonar-web/src/main/js/apps/custom-measures/components/__tests__/__snapshots__/Header-test.tsx.snap b/server/sonar-web/src/main/js/apps/custom-measures/components/__tests__/__snapshots__/Header-test.tsx.snap index b974d7b7ad5..f1b8a7f46e1 100644 --- a/server/sonar-web/src/main/js/apps/custom-measures/components/__tests__/__snapshots__/Header-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/custom-measures/components/__tests__/__snapshots__/Header-test.tsx.snap @@ -25,11 +25,12 @@ exports[`should create new custom measure 1`] = ` <div className="page-description" > - <div - className="alert alert-danger" + <Alert + display="inline" + variant="error" > custom_measures.deprecated - </div> + </Alert> <p> custom_measures.page.description </p> diff --git a/server/sonar-web/src/main/js/apps/custom-metrics/components/Header.tsx b/server/sonar-web/src/main/js/apps/custom-metrics/components/Header.tsx index 38e9d2222b0..2092881cd03 100644 --- a/server/sonar-web/src/main/js/apps/custom-metrics/components/Header.tsx +++ b/server/sonar-web/src/main/js/apps/custom-metrics/components/Header.tsx @@ -22,6 +22,7 @@ import CreateButton from './CreateButton'; import { MetricProps } from './Form'; import DeferredSpinner from '../../../components/common/DeferredSpinner'; import { translate } from '../../../helpers/l10n'; +import { Alert } from '../../../components/ui/Alert'; interface Props { domains: string[] | undefined; @@ -39,7 +40,9 @@ export default function Header({ domains, loading, onCreate, types }: Props) { {domains && types && <CreateButton domains={domains} onCreate={onCreate} types={types} />} </div> <div className="page-description"> - <div className="alert alert-danger">{translate('custom_metrics.deprecated')}</div> + <Alert display="inline" variant="error"> + {translate('custom_metrics.deprecated')} + </Alert> <p>{translate('custom_metrics.page.description')}</p> </div> </header> diff --git a/server/sonar-web/src/main/js/apps/custom-metrics/components/__tests__/__snapshots__/Header-test.tsx.snap b/server/sonar-web/src/main/js/apps/custom-metrics/components/__tests__/__snapshots__/Header-test.tsx.snap index dbc5eeb2123..f740b43b9e4 100644 --- a/server/sonar-web/src/main/js/apps/custom-metrics/components/__tests__/__snapshots__/Header-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/custom-metrics/components/__tests__/__snapshots__/Header-test.tsx.snap @@ -36,11 +36,12 @@ exports[`should create new metric 1`] = ` <div className="page-description" > - <div - className="alert alert-danger" + <Alert + display="inline" + variant="error" > custom_metrics.deprecated - </div> + </Alert> <p> custom_metrics.page.description </p> diff --git a/server/sonar-web/src/main/js/apps/documentation/styles.css b/server/sonar-web/src/main/js/apps/documentation/styles.css index 05f6eb50ff8..f2222eefebe 100644 --- a/server/sonar-web/src/main/js/apps/documentation/styles.css +++ b/server/sonar-web/src/main/js/apps/documentation/styles.css @@ -92,8 +92,9 @@ vertical-align: text-bottom; } -.documentation-content.markdown .alert p { - margin: 0; +.documentation-content.markdown .alert { + display: block; + padding: var(--gridSize) calc(2 * var(--gridSize)); } .documentation-content.markdown .collapse-container { diff --git a/server/sonar-web/src/main/js/apps/issues/components/BulkChangeModal.tsx b/server/sonar-web/src/main/js/apps/issues/components/BulkChangeModal.tsx index 64e770d506f..e06f3a4fed1 100644 --- a/server/sonar-web/src/main/js/apps/issues/components/BulkChangeModal.tsx +++ b/server/sonar-web/src/main/js/apps/issues/components/BulkChangeModal.tsx @@ -34,6 +34,7 @@ import Avatar from '../../../components/ui/Avatar'; import { SubmitButton } from '../../../components/ui/buttons'; import IssueTypeIcon from '../../../components/ui/IssueTypeIcon'; import { translate, translateWithParameters } from '../../../helpers/l10n'; +import { Alert } from '../../../components/ui/Alert'; interface AssigneeOption { avatar?: string; @@ -501,9 +502,9 @@ export default class BulkChangeModal extends React.PureComponent<Props, State> { <div className="modal-body"> {limitReached && ( - <div className="alert alert-warning"> + <Alert variant="warning"> {translateWithParameters('issue_bulk_change.max_issues_reached', issues.length)} - </div> + </Alert> )} {this.renderAssigneeField()} @@ -515,7 +516,7 @@ export default class BulkChangeModal extends React.PureComponent<Props, State> { {this.renderCommentField()} {issues.length > 0 && this.renderNotificationsField()} {issues.length === 0 && ( - <span className="alert alert-warning">{translate('issue_bulk_change.no_match')}</span> + <Alert variant="warning">{translate('issue_bulk_change.no_match')}</Alert> )} </div> diff --git a/server/sonar-web/src/main/js/apps/issues/components/__tests__/__snapshots__/BulkChangeModal-test.tsx.snap b/server/sonar-web/src/main/js/apps/issues/components/__tests__/__snapshots__/BulkChangeModal-test.tsx.snap index 0f4f7d38440..120b9dff93b 100644 --- a/server/sonar-web/src/main/js/apps/issues/components/__tests__/__snapshots__/BulkChangeModal-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/issues/components/__tests__/__snapshots__/BulkChangeModal-test.tsx.snap @@ -19,11 +19,11 @@ exports[`should display error message when no issues available 1`] = ` <div className="modal-body" > - <span - className="alert alert-warning" + <Alert + variant="warning" > issue_bulk_change.no_match - </span> + </Alert> </div> <div className="modal-foot" diff --git a/server/sonar-web/src/main/js/apps/organizations/components/OrganizationDelete.tsx b/server/sonar-web/src/main/js/apps/organizations/components/OrganizationDelete.tsx index b3b7eb5711b..7e506f92d8c 100644 --- a/server/sonar-web/src/main/js/apps/organizations/components/OrganizationDelete.tsx +++ b/server/sonar-web/src/main/js/apps/organizations/components/OrganizationDelete.tsx @@ -29,6 +29,7 @@ import { Organization } from '../../../app/types'; import { Button } from '../../../components/ui/buttons'; import { getOrganizationBilling } from '../../../api/organizations'; import { isSonarCloud } from '../../../helpers/system'; +import { Alert } from '../../../components/ui/Alert'; interface DispatchToProps { deleteOrganization: (key: string) => Promise<void>; @@ -105,9 +106,9 @@ export class OrganizationDelete extends React.PureComponent<Props, State> { modalBody={ <div> {hasPaidPlan && ( - <div className="alert alert-warning modal-alert"> + <Alert variant="warning"> {translate('organization.delete.sonarcloud.paid_plan_info')} - </div> + </Alert> )} <p>{translate('organization.delete.question')}</p> </div> diff --git a/server/sonar-web/src/main/js/apps/organizations/components/__tests__/__snapshots__/OrganizationDelete-test.tsx.snap b/server/sonar-web/src/main/js/apps/organizations/components/__tests__/__snapshots__/OrganizationDelete-test.tsx.snap index 5d12a0519c4..265c332c4f2 100644 --- a/server/sonar-web/src/main/js/apps/organizations/components/__tests__/__snapshots__/OrganizationDelete-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/organizations/components/__tests__/__snapshots__/OrganizationDelete-test.tsx.snap @@ -31,11 +31,11 @@ exports[`should show a info message for paying organization 1`] = ` isDestructive={true} modalBody={ <div> - <div - className="alert alert-warning modal-alert" + <Alert + variant="warning" > organization.delete.sonarcloud.paid_plan_info - </div> + </Alert> <p> organization.delete.question </p> diff --git a/server/sonar-web/src/main/js/apps/overview/components/EmptyOverview.tsx b/server/sonar-web/src/main/js/apps/overview/components/EmptyOverview.tsx index 69c3d81ae27..a5db1cb7e6a 100644 --- a/server/sonar-web/src/main/js/apps/overview/components/EmptyOverview.tsx +++ b/server/sonar-web/src/main/js/apps/overview/components/EmptyOverview.tsx @@ -23,6 +23,7 @@ import { FormattedMessage } from 'react-intl'; import { translate } from '../../../helpers/l10n'; import { BranchLike } from '../../../app/types'; import { isBranch, isLongLivingBranch } from '../../../helpers/branches'; +import { Alert } from '../../../components/ui/Alert'; interface Props { branchLike?: BranchLike; @@ -45,7 +46,7 @@ export default function EmptyOverview({ branchLike, branchLikes, component, show <div className="page page-limited"> {showWarning && ( <div className="big-spacer-bottom"> - <div className="alert alert-warning"> + <Alert variant="warning"> {hasBranches && isBranch(branchLike) ? ( <FormattedMessage defaultMessage={branchWarnMsg} @@ -62,7 +63,7 @@ export default function EmptyOverview({ branchLike, branchLikes, component, show ) : ( translate('provisioning.no_analysis') )} - </div> + </Alert> {!hasBranches && ( <div className="big-spacer-top"> diff --git a/server/sonar-web/src/main/js/apps/overview/components/SonarCloudEmptyOverview.tsx b/server/sonar-web/src/main/js/apps/overview/components/SonarCloudEmptyOverview.tsx index 5cf37a984c5..c72610e8991 100644 --- a/server/sonar-web/src/main/js/apps/overview/components/SonarCloudEmptyOverview.tsx +++ b/server/sonar-web/src/main/js/apps/overview/components/SonarCloudEmptyOverview.tsx @@ -27,6 +27,7 @@ import { isLongLivingBranch, isBranch, isMainBranch } from '../../../helpers/bra import { translate } from '../../../helpers/l10n'; import { getCurrentUser, Store } from '../../../store/rootReducer'; import '../../../app/styles/sonarcloud.css'; +import { Alert } from '../../../components/ui/Alert'; interface OwnProps { branchLike?: BranchLike; @@ -104,7 +105,7 @@ export function WarningMessage({ return null; } return ( - <div className="alert alert-warning"> + <Alert variant="warning"> <FormattedMessage defaultMessage={message} id={message} @@ -115,7 +116,7 @@ export function WarningMessage({ ) }} /> - </div> + </Alert> ); } diff --git a/server/sonar-web/src/main/js/apps/overview/components/__tests__/__snapshots__/EmptyOverview-test.tsx.snap b/server/sonar-web/src/main/js/apps/overview/components/__tests__/__snapshots__/EmptyOverview-test.tsx.snap index cede657480c..3b26289dea4 100644 --- a/server/sonar-web/src/main/js/apps/overview/components/__tests__/__snapshots__/EmptyOverview-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/overview/components/__tests__/__snapshots__/EmptyOverview-test.tsx.snap @@ -22,11 +22,11 @@ exports[`renders 1`] = ` <div className="big-spacer-bottom" > - <div - className="alert alert-warning" + <Alert + variant="warning" > provisioning.no_analysis - </div> + </Alert> <div className="big-spacer-top" > @@ -73,8 +73,8 @@ exports[`should render another message when there are branches 1`] = ` <div className="big-spacer-bottom" > - <div - className="alert alert-warning" + <Alert + variant="warning" > <FormattedMessage defaultMessage="provisioning.no_analysis_on_main_branch" @@ -90,7 +90,7 @@ exports[`should render another message when there are branches 1`] = ` } } /> - </div> + </Alert> </div> <div> <h4> @@ -110,8 +110,8 @@ exports[`should render another message when there are branches 2`] = ` <div className="big-spacer-bottom" > - <div - className="alert alert-warning" + <Alert + variant="warning" > <FormattedMessage defaultMessage="provisioning.no_analysis_on_main_branch.bad_configuration" @@ -127,7 +127,7 @@ exports[`should render another message when there are branches 2`] = ` } } /> - </div> + </Alert> </div> <div> <h4> diff --git a/server/sonar-web/src/main/js/apps/overview/components/__tests__/__snapshots__/SonarCloudEmptyOverview-test.tsx.snap b/server/sonar-web/src/main/js/apps/overview/components/__tests__/__snapshots__/SonarCloudEmptyOverview-test.tsx.snap index 6670cee7c45..28eda6a8c39 100644 --- a/server/sonar-web/src/main/js/apps/overview/components/__tests__/__snapshots__/SonarCloudEmptyOverview-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/overview/components/__tests__/__snapshots__/SonarCloudEmptyOverview-test.tsx.snap @@ -200,8 +200,8 @@ exports[`should render another message when there are branches 2`] = ` `; exports[`should render warning message 1`] = ` -<div - className="alert alert-warning" +<Alert + variant="warning" > <FormattedMessage defaultMessage="foo" @@ -217,5 +217,5 @@ exports[`should render warning message 1`] = ` } } /> -</div> +</Alert> `; diff --git a/server/sonar-web/src/main/js/apps/overview/qualityGate/QualityGate.tsx b/server/sonar-web/src/main/js/apps/overview/qualityGate/QualityGate.tsx index 6f6c292dcfb..b49ea0000a2 100644 --- a/server/sonar-web/src/main/js/apps/overview/qualityGate/QualityGate.tsx +++ b/server/sonar-web/src/main/js/apps/overview/qualityGate/QualityGate.tsx @@ -25,6 +25,7 @@ import Level from '../../../components/ui/Level'; import HelpTooltip from '../../../components/controls/HelpTooltip'; import DocTooltip from '../../../components/docs/DocTooltip'; import { Component, BranchLike, MeasureEnhanced } from '../../../app/types'; +import { Alert } from '../../../components/ui/Alert'; interface Props { branchLike?: BranchLike; @@ -62,7 +63,7 @@ export default function QualityGate({ branchLike, component, measures }: Props) </div> {ignoredConditions && ( - <div className="alert alert-info display-inline-block big-spacer-top"> + <Alert className="big-spacer-top" display="inline" variant="info"> <span className="text-middle"> {translate('overview.quality_gate.ignored_conditions')} </span> @@ -70,7 +71,7 @@ export default function QualityGate({ branchLike, component, measures }: Props) className="spacer-left" overlay={translate('overview.quality_gate.ignored_conditions.tooltip')} /> - </div> + </Alert> )} {conditions.length > 0 && ( diff --git a/server/sonar-web/src/main/js/apps/overview/qualityGate/__tests__/__snapshots__/QualityGate-test.tsx.snap b/server/sonar-web/src/main/js/apps/overview/qualityGate/__tests__/__snapshots__/QualityGate-test.tsx.snap index f95d36d808b..8c92b7fbd40 100644 --- a/server/sonar-web/src/main/js/apps/overview/qualityGate/__tests__/__snapshots__/QualityGate-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/overview/qualityGate/__tests__/__snapshots__/QualityGate-test.tsx.snap @@ -22,8 +22,10 @@ exports[`renders message about ignored conditions 1`] = ` level="OK" /> </div> - <div - className="alert alert-info display-inline-block big-spacer-top" + <Alert + className="big-spacer-top" + display="inline" + variant="info" > <span className="text-middle" @@ -34,6 +36,6 @@ exports[`renders message about ignored conditions 1`] = ` className="spacer-left" overlay="overview.quality_gate.ignored_conditions.tooltip" /> - </div> + </Alert> </div> `; diff --git a/server/sonar-web/src/main/js/apps/permission-templates/components/ListHeader.js b/server/sonar-web/src/main/js/apps/permission-templates/components/ListHeader.js index 4ac07fa0988..50807d7d2de 100644 --- a/server/sonar-web/src/main/js/apps/permission-templates/components/ListHeader.js +++ b/server/sonar-web/src/main/js/apps/permission-templates/components/ListHeader.js @@ -22,6 +22,7 @@ import PropTypes from 'prop-types'; import HelpTooltip from '../../../components/controls/HelpTooltip'; import { translate } from '../../../helpers/l10n'; import InstanceMessage from '../../../components/common/InstanceMessage'; +import { Alert } from '../../../components/ui/Alert'; export default class ListHeader extends React.PureComponent { static propTypes = { @@ -33,9 +34,9 @@ export default class ListHeader extends React.PureComponent { permission.key === 'user' || permission.key === 'codeviewer' ? ( <div> <InstanceMessage message={translate('projects_role', permission.key, 'desc')} /> - <div className="alert alert-warning spacer-top"> + <Alert className="spacer-top" variant="warning"> {translate('projects_role.public_projects_warning')} - </div> + </Alert> </div> ) : ( <InstanceMessage message={translate('projects_role', permission.key, 'desc')} /> diff --git a/server/sonar-web/src/main/js/apps/permissions/project/components/ApplyTemplate.tsx b/server/sonar-web/src/main/js/apps/permissions/project/components/ApplyTemplate.tsx index 94fe7d09868..37cbecb1251 100644 --- a/server/sonar-web/src/main/js/apps/permissions/project/components/ApplyTemplate.tsx +++ b/server/sonar-web/src/main/js/apps/permissions/project/components/ApplyTemplate.tsx @@ -25,6 +25,7 @@ import SimpleModal from '../../../../components/controls/SimpleModal'; import Select from '../../../../components/controls/Select'; import { SubmitButton, ResetButtonLink } from '../../../../components/ui/buttons'; import { translateWithParameters, translate } from '../../../../helpers/l10n'; +import { Alert } from '../../../../components/ui/Alert'; interface Props { onApply?: () => void; @@ -107,9 +108,7 @@ export default class ApplyTemplate extends React.PureComponent<Props, State> { <div className="modal-body"> {this.state.done ? ( - <div className="alert alert-success"> - {translate('projects_role.apply_template.success')} - </div> + <Alert variant="success">{translate('projects_role.apply_template.success')}</Alert> ) : ( <> {this.state.loading ? ( diff --git a/server/sonar-web/src/main/js/apps/permissions/project/components/PublicProjectDisclaimer.tsx b/server/sonar-web/src/main/js/apps/permissions/project/components/PublicProjectDisclaimer.tsx index 51557cb7a67..fc9a1bec42d 100644 --- a/server/sonar-web/src/main/js/apps/permissions/project/components/PublicProjectDisclaimer.tsx +++ b/server/sonar-web/src/main/js/apps/permissions/project/components/PublicProjectDisclaimer.tsx @@ -20,6 +20,7 @@ import * as React from 'react'; import ConfirmModal from '../../../../components/controls/ConfirmModal'; import { translate, translateWithParameters } from '../../../../helpers/l10n'; +import { Alert } from '../../../../components/ui/Alert'; interface Props { component: { @@ -38,9 +39,9 @@ export default function PublicProjectDisclaimer({ component, onClose, onConfirm header={translateWithParameters('projects_role.turn_x_to_public', component.name)} onClose={onClose} onConfirm={onConfirm}> - <div className="alert alert-warning modal-alert"> + <Alert variant="warning"> {translate('projects_role.are_you_sure_to_turn_project_to_public.warning', qualifier)} - </div> + </Alert> <p>{translate('projects_role.are_you_sure_to_turn_project_to_public', qualifier)}</p> </ConfirmModal> ); diff --git a/server/sonar-web/src/main/js/apps/permissions/shared/components/PermissionHeader.tsx b/server/sonar-web/src/main/js/apps/permissions/shared/components/PermissionHeader.tsx index 35fd48be2ff..69e2a082b75 100644 --- a/server/sonar-web/src/main/js/apps/permissions/shared/components/PermissionHeader.tsx +++ b/server/sonar-web/src/main/js/apps/permissions/shared/components/PermissionHeader.tsx @@ -25,6 +25,7 @@ import { translate, translateWithParameters } from '../../../../helpers/l10n'; import { PermissionDefinition, PermissionDefinitionGroup } from '../../../../app/types'; import { isPermissionDefinitionGroup } from '../../utils'; import Tooltip from '../../../../components/controls/Tooltip'; +import { Alert } from '../../../../components/ui/Alert'; interface Props { onSelectPermission?: (permission: string) => void; @@ -59,9 +60,9 @@ export default class PermissionHeader extends React.PureComponent<Props> { return ( <div> <InstanceMessage message={permission.description} /> - <div className="alert alert-warning spacer-top"> + <Alert className="spacer-top" variant="warning"> {translate('projects_role.public_projects_warning')} - </div> + </Alert> </div> ); } diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/forms/AddGraphMetricPopup.tsx b/server/sonar-web/src/main/js/apps/projectActivity/components/forms/AddGraphMetricPopup.tsx index 31f581f9427..d92a1301ac9 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/components/forms/AddGraphMetricPopup.tsx +++ b/server/sonar-web/src/main/js/apps/projectActivity/components/forms/AddGraphMetricPopup.tsx @@ -20,6 +20,7 @@ import * as React from 'react'; import MultiSelect from '../../../../components/common/MultiSelect'; import { translate, translateWithParameters } from '../../../../helpers/l10n'; +import { Alert } from '../../../../components/ui/Alert'; interface Props { elements: string[]; @@ -38,13 +39,13 @@ export default function AddGraphMetricPopup({ elements, metricsTypeFilter, ...pr if (props.selectedElements.length >= 6) { footerNode = ( - <span className="alert alert-info spacer-left spacer-right spacer-top"> + <Alert className="spacer-left spacer-right spacer-top" variant="info"> {translate('project_activity.graphs.custom.add_metric_info')} - </span> + </Alert> ); } else if (metricsTypeFilter && metricsTypeFilter.length > 0) { footerNode = ( - <span className="alert alert-info spacer-left spacer-right spacer-top"> + <Alert className="spacer-left spacer-right spacer-top" variant="info"> {translateWithParameters( 'project_activity.graphs.custom.type_x_message', metricsTypeFilter @@ -52,7 +53,7 @@ export default function AddGraphMetricPopup({ elements, metricsTypeFilter, ...pr .sort() .join(', ') )} - </span> + </Alert> ); } diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/projectActivity.css b/server/sonar-web/src/main/js/apps/projectActivity/components/projectActivity.css index f4613f78b97..e8953145857 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/components/projectActivity.css +++ b/server/sonar-web/src/main/js/apps/projectActivity/components/projectActivity.css @@ -97,10 +97,6 @@ border-radius: 12px; } -.project-activity-graph-legend-actionable:not(.alert-warning) { - border-color: var(--barBorderColor); -} - .project-activity-graph-tooltip { padding: 8px; } diff --git a/server/sonar-web/src/main/js/apps/projects/create/AutoProjectCreate.tsx b/server/sonar-web/src/main/js/apps/projects/create/AutoProjectCreate.tsx index 920be163938..74677605d41 100644 --- a/server/sonar-web/src/main/js/apps/projects/create/AutoProjectCreate.tsx +++ b/server/sonar-web/src/main/js/apps/projects/create/AutoProjectCreate.tsx @@ -25,6 +25,7 @@ import { getRepositories, provisionProject } from '../../../api/alm-integration' import { IdentityProvider, AlmRepository } from '../../../app/types'; import { SubmitButton } from '../../../components/ui/buttons'; import { translateWithParameters, translate } from '../../../helpers/l10n'; +import { Alert } from '../../../components/ui/Alert'; interface Props { identityProvider: IdentityProvider; @@ -166,12 +167,12 @@ export default class AutoProjectCreate extends React.PureComponent<Props, State> return ( <> - <p className="alert alert-info width-60 big-spacer-bottom"> + <Alert className="width-60 big-spacer-bottom" variant="info"> {translateWithParameters( 'onboarding.create_project.beta_feature_x', identityProvider.name )} - </p> + </Alert> {loading ? <DeferredSpinner /> : this.renderContent()} </> ); diff --git a/server/sonar-web/src/main/js/apps/projects/create/CreateProjectPage.tsx b/server/sonar-web/src/main/js/apps/projects/create/CreateProjectPage.tsx index 4245f80b144..1b1840e1381 100644 --- a/server/sonar-web/src/main/js/apps/projects/create/CreateProjectPage.tsx +++ b/server/sonar-web/src/main/js/apps/projects/create/CreateProjectPage.tsx @@ -175,16 +175,12 @@ export class CreateProjectPage extends React.PureComponent<Props, State> { href="#" onClick={this.showAuto}> {translate('onboarding.create_project.select_repositories')} - <span - className={classNames( - 'rounded alert alert-small spacer-left display-inline-block', - { - 'alert-info': !displayManual, - 'alert-muted': displayManual - } - )}> + <div + className={classNames('beta-badge spacer-left', { + 'is-muted': displayManual + })}> {translate('beta')} - </span> + </div> </a> </li> <li> diff --git a/server/sonar-web/src/main/js/apps/projects/create/__tests__/__snapshots__/AutoProjectCreate-test.tsx.snap b/server/sonar-web/src/main/js/apps/projects/create/__tests__/__snapshots__/AutoProjectCreate-test.tsx.snap index 03dd876b7c2..619285b02fa 100644 --- a/server/sonar-web/src/main/js/apps/projects/create/__tests__/__snapshots__/AutoProjectCreate-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/projects/create/__tests__/__snapshots__/AutoProjectCreate-test.tsx.snap @@ -2,11 +2,12 @@ exports[`should display the list of repositories 1`] = ` <Fragment> - <p - className="alert alert-info width-60 big-spacer-bottom" + <Alert + className="width-60 big-spacer-bottom" + variant="info" > onboarding.create_project.beta_feature_x.Foo Provider - </p> + </Alert> <form onSubmit={[Function]} > @@ -76,11 +77,12 @@ exports[`should display the list of repositories 1`] = ` exports[`should display the provider app install button 1`] = ` <Fragment> - <p - className="alert alert-info width-60 big-spacer-bottom" + <Alert + className="width-60 big-spacer-bottom" + variant="info" > onboarding.create_project.beta_feature_x.Foo Provider - </p> + </Alert> <DeferredSpinner timeout={100} /> @@ -89,11 +91,12 @@ exports[`should display the provider app install button 1`] = ` exports[`should display the provider app install button 2`] = ` <Fragment> - <p - className="alert alert-info width-60 big-spacer-bottom" + <Alert + className="width-60 big-spacer-bottom" + variant="info" > onboarding.create_project.beta_feature_x.Foo Provider - </p> + </Alert> <div> <p className="spacer-bottom" diff --git a/server/sonar-web/src/main/js/apps/projects/create/__tests__/__snapshots__/CreateProjectPage-test.tsx.snap b/server/sonar-web/src/main/js/apps/projects/create/__tests__/__snapshots__/CreateProjectPage-test.tsx.snap index ebb5ee82d74..a1eaa7bbd49 100644 --- a/server/sonar-web/src/main/js/apps/projects/create/__tests__/__snapshots__/CreateProjectPage-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/projects/create/__tests__/__snapshots__/CreateProjectPage-test.tsx.snap @@ -57,11 +57,11 @@ exports[`should render correctly 2`] = ` onClick={[Function]} > onboarding.create_project.select_repositories - <span - className="rounded alert alert-small spacer-left display-inline-block alert-info" + <div + className="beta-badge spacer-left" > beta - </span> + </div> </a> </li> <li> @@ -156,11 +156,11 @@ exports[`should switch tabs 1`] = ` onClick={[Function]} > onboarding.create_project.select_repositories - <span - className="rounded alert alert-small spacer-left display-inline-block alert-info" + <div + className="beta-badge spacer-left" > beta - </span> + </div> </a> </li> <li> diff --git a/server/sonar-web/src/main/js/apps/projectsManagement/BulkApplyTemplateModal.tsx b/server/sonar-web/src/main/js/apps/projectsManagement/BulkApplyTemplateModal.tsx index 50fdb9e1039..0e8fe28995c 100644 --- a/server/sonar-web/src/main/js/apps/projectsManagement/BulkApplyTemplateModal.tsx +++ b/server/sonar-web/src/main/js/apps/projectsManagement/BulkApplyTemplateModal.tsx @@ -21,11 +21,11 @@ import * as React from 'react'; import { getPermissionTemplates, bulkApplyTemplate } from '../../api/permissions'; import { PermissionTemplate } from '../../app/types'; import { translate, translateWithParameters } from '../../helpers/l10n'; -import AlertWarnIcon from '../../components/icons-components/AlertWarnIcon'; import Modal from '../../components/controls/Modal'; import Select from '../../components/controls/Select'; import { Button, ResetButtonLink } from '../../components/ui/buttons'; import { toNotSoISOString } from '../../helpers/dates'; +import { Alert } from '../../components/ui/Alert'; export interface Props { analyzedBefore: Date | undefined; @@ -119,8 +119,7 @@ export default class BulkApplyTemplateModal extends React.PureComponent<Props, S }; renderWarning = () => ( - <div className="alert alert-warning modal-alert"> - <AlertWarnIcon className="spacer-right" /> + <Alert variant="warning"> {this.props.selection.length ? translateWithParameters( 'permission_templates.bulk_apply_permission_template.apply_to_selected', @@ -130,7 +129,7 @@ export default class BulkApplyTemplateModal extends React.PureComponent<Props, S 'permission_templates.bulk_apply_permission_template.apply_to_all', this.props.total )} - </div> + </Alert> ); renderSelect = () => ( @@ -161,9 +160,7 @@ export default class BulkApplyTemplateModal extends React.PureComponent<Props, S <div className="modal-body"> {done && ( - <div className="alert alert-success"> - {translate('projects_role.apply_template.success')} - </div> + <Alert variant="success">{translate('projects_role.apply_template.success')}</Alert> )} {loading && <i className="spinner" />} diff --git a/server/sonar-web/src/main/js/apps/projectsManagement/ChangeVisibilityForm.tsx b/server/sonar-web/src/main/js/apps/projectsManagement/ChangeVisibilityForm.tsx index d603ab0a5d4..15fd04cf537 100644 --- a/server/sonar-web/src/main/js/apps/projectsManagement/ChangeVisibilityForm.tsx +++ b/server/sonar-web/src/main/js/apps/projectsManagement/ChangeVisibilityForm.tsx @@ -24,6 +24,7 @@ import UpgradeOrganizationBox from '../../components/common/UpgradeOrganizationB import Modal from '../../components/controls/Modal'; import { Button, ResetButtonLink } from '../../components/ui/buttons'; import { translate } from '../../helpers/l10n'; +import { Alert } from '../../components/ui/Alert'; export interface Props { onClose: () => void; @@ -97,9 +98,9 @@ export default class ChangeVisibilityForm extends React.PureComponent<Props, Sta ))} {canUpdateProjectsVisibilityToPrivate ? ( - <div className="alert alert-warning"> + <Alert variant="warning"> {translate('organization.change_visibility_form.warning')} - </div> + </Alert> ) : ( <UpgradeOrganizationBox organization={this.props.organization.key} /> )} diff --git a/server/sonar-web/src/main/js/apps/projectsManagement/CreateProjectForm.tsx b/server/sonar-web/src/main/js/apps/projectsManagement/CreateProjectForm.tsx index b721a8f7e76..d48e5cf0300 100644 --- a/server/sonar-web/src/main/js/apps/projectsManagement/CreateProjectForm.tsx +++ b/server/sonar-web/src/main/js/apps/projectsManagement/CreateProjectForm.tsx @@ -28,6 +28,7 @@ import Modal from '../../components/controls/Modal'; import { SubmitButton, ResetButtonLink } from '../../components/ui/buttons'; import { translate } from '../../helpers/l10n'; import { getProjectUrl } from '../../helpers/urls'; +import { Alert } from '../../components/ui/Alert'; interface Props { onClose: () => void; @@ -124,7 +125,7 @@ export default class CreateProjectForm extends React.PureComponent<Props, State> </header> <div className="modal-body"> - <div className="alert alert-success"> + <Alert variant="success"> <FormattedMessage defaultMessage={translate( 'projects_management.project_has_been_successfully_created' @@ -136,7 +137,7 @@ export default class CreateProjectForm extends React.PureComponent<Props, State> ) }} /> - </div> + </Alert> </div> <footer className="modal-foot"> diff --git a/server/sonar-web/src/main/js/apps/projectsManagement/DeleteModal.tsx b/server/sonar-web/src/main/js/apps/projectsManagement/DeleteModal.tsx index 6eaf827ec80..62863717599 100644 --- a/server/sonar-web/src/main/js/apps/projectsManagement/DeleteModal.tsx +++ b/server/sonar-web/src/main/js/apps/projectsManagement/DeleteModal.tsx @@ -20,10 +20,10 @@ import * as React from 'react'; import { bulkDeleteProjects } from '../../api/components'; import Modal from '../../components/controls/Modal'; -import AlertWarnIcon from '../../components/icons-components/AlertWarnIcon'; import { Button, ResetButtonLink } from '../../components/ui/buttons'; import { translate, translateWithParameters } from '../../helpers/l10n'; import { toNotSoISOString } from '../../helpers/dates'; +import { Alert } from '../../components/ui/Alert'; export interface Props { analyzedBefore: Date | undefined; @@ -83,15 +83,14 @@ export default class DeleteModal extends React.PureComponent<Props, State> { }; renderWarning = () => ( - <div className="alert alert-warning modal-alert"> - <AlertWarnIcon className="spacer-right" /> + <Alert variant="warning"> {this.props.selection.length ? translateWithParameters( 'projects_management.delete_selected_warning', this.props.selection.length ) : translateWithParameters('projects_management.delete_all_warning', this.props.total)} - </div> + </Alert> ); render() { diff --git a/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/__snapshots__/BulkApplyTemplateModal-test.tsx.snap b/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/__snapshots__/BulkApplyTemplateModal-test.tsx.snap index bfb800cdd1c..3582abeb9cf 100644 --- a/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/__snapshots__/BulkApplyTemplateModal-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/__snapshots__/BulkApplyTemplateModal-test.tsx.snap @@ -47,14 +47,11 @@ exports[`bulk applies template to all results 2`] = ` <div className="modal-body" > - <div - className="alert alert-warning modal-alert" + <Alert + variant="warning" > - <AlertWarnIcon - className="spacer-right" - /> permission_templates.bulk_apply_permission_template.apply_to_all.17 - </div> + </Alert> <div className="modal-field" > @@ -120,14 +117,11 @@ exports[`bulk applies template to all results 3`] = ` <div className="modal-body" > - <div - className="alert alert-warning modal-alert" + <Alert + variant="warning" > - <AlertWarnIcon - className="spacer-right" - /> permission_templates.bulk_apply_permission_template.apply_to_all.17 - </div> + </Alert> <div className="modal-field" > @@ -196,11 +190,11 @@ exports[`bulk applies template to all results 4`] = ` <div className="modal-body" > - <div - className="alert alert-success" + <Alert + variant="success" > projects_role.apply_template.success - </div> + </Alert> </div> <footer className="modal-foot" @@ -262,14 +256,11 @@ exports[`bulk applies template to selected results 2`] = ` <div className="modal-body" > - <div - className="alert alert-warning modal-alert" + <Alert + variant="warning" > - <AlertWarnIcon - className="spacer-right" - /> permission_templates.bulk_apply_permission_template.apply_to_selected.2 - </div> + </Alert> <div className="modal-field" > @@ -335,14 +326,11 @@ exports[`bulk applies template to selected results 3`] = ` <div className="modal-body" > - <div - className="alert alert-warning modal-alert" + <Alert + variant="warning" > - <AlertWarnIcon - className="spacer-right" - /> permission_templates.bulk_apply_permission_template.apply_to_selected.2 - </div> + </Alert> <div className="modal-field" > @@ -411,11 +399,11 @@ exports[`bulk applies template to selected results 4`] = ` <div className="modal-body" > - <div - className="alert alert-success" + <Alert + variant="success" > projects_role.apply_template.success - </div> + </Alert> </div> <footer className="modal-foot" diff --git a/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/__snapshots__/ChangeVisibilityForm-test.tsx.snap b/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/__snapshots__/ChangeVisibilityForm-test.tsx.snap index 0375c6c07e8..0c5b0d3ed6b 100644 --- a/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/__snapshots__/ChangeVisibilityForm-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/__snapshots__/ChangeVisibilityForm-test.tsx.snap @@ -71,11 +71,11 @@ exports[`changes visibility 1`] = ` visibility.private.description.short </p> </div> - <div - className="alert alert-warning" + <Alert + variant="warning" > organization.change_visibility_form.warning - </div> + </Alert> </div> <footer className="modal-foot" @@ -167,11 +167,11 @@ exports[`changes visibility 2`] = ` visibility.private.description.short </p> </div> - <div - className="alert alert-warning" + <Alert + variant="warning" > organization.change_visibility_form.warning - </div> + </Alert> </div> <footer className="modal-foot" diff --git a/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/__snapshots__/CreateProjectForm-test.tsx.snap b/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/__snapshots__/CreateProjectForm-test.tsx.snap index aead0a2ce17..a7ce31e715c 100644 --- a/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/__snapshots__/CreateProjectForm-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/__snapshots__/CreateProjectForm-test.tsx.snap @@ -337,8 +337,8 @@ exports[`creates project 4`] = ` <div className="modal-body" > - <div - className="alert alert-success" + <Alert + variant="success" > <FormattedMessage defaultMessage="projects_management.project_has_been_successfully_created" @@ -363,7 +363,7 @@ exports[`creates project 4`] = ` } } /> - </div> + </Alert> </div> <footer className="modal-foot" diff --git a/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/__snapshots__/DeleteModal-test.tsx.snap b/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/__snapshots__/DeleteModal-test.tsx.snap index 3fed0f28acd..f8b3ea48727 100644 --- a/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/__snapshots__/DeleteModal-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/__snapshots__/DeleteModal-test.tsx.snap @@ -15,14 +15,11 @@ exports[`deletes all projects 1`] = ` <div className="modal-body" > - <div - className="alert alert-warning modal-alert" + <Alert + variant="warning" > - <AlertWarnIcon - className="spacer-right" - /> projects_management.delete_all_warning.17 - </div> + </Alert> qualifiers.delete_confirm.TRK </div> <footer @@ -60,14 +57,11 @@ exports[`deletes all projects 2`] = ` <div className="modal-body" > - <div - className="alert alert-warning modal-alert" + <Alert + variant="warning" > - <AlertWarnIcon - className="spacer-right" - /> projects_management.delete_all_warning.17 - </div> + </Alert> qualifiers.delete_confirm.TRK </div> <footer @@ -108,14 +102,11 @@ exports[`deletes selected projects 1`] = ` <div className="modal-body" > - <div - className="alert alert-warning modal-alert" + <Alert + variant="warning" > - <AlertWarnIcon - className="spacer-right" - /> projects_management.delete_selected_warning.2 - </div> + </Alert> qualifiers.delete_confirm.TRK </div> <footer @@ -153,14 +144,11 @@ exports[`deletes selected projects 2`] = ` <div className="modal-body" > - <div - className="alert alert-warning modal-alert" + <Alert + variant="warning" > - <AlertWarnIcon - className="spacer-right" - /> projects_management.delete_selected_warning.2 - </div> + </Alert> qualifiers.delete_confirm.TRK </div> <footer diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/ConditionModal.tsx b/server/sonar-web/src/main/js/apps/quality-gates/components/ConditionModal.tsx index 1d337c61e2f..5c11c927d00 100644 --- a/server/sonar-web/src/main/js/apps/quality-gates/components/ConditionModal.tsx +++ b/server/sonar-web/src/main/js/apps/quality-gates/components/ConditionModal.tsx @@ -28,6 +28,7 @@ import { createCondition, updateCondition } from '../../../api/quality-gates'; import { isDiffMetric } from '../../../helpers/measures'; import { parseError } from '../../../helpers/request'; import ConfirmModal from '../../../components/controls/ConfirmModal'; +import { Alert } from '../../../components/ui/Alert'; interface Props { condition?: Condition; @@ -142,9 +143,7 @@ export default class ConditionModal extends React.PureComponent<Props, State> { header={header} onClose={onClose} onConfirm={this.handleFormSubmit}> - {this.state.errorMessage && ( - <div className="alert alert-danger modal-alert">{this.state.errorMessage}</div> - )} + {this.state.errorMessage && <Alert variant="error">{this.state.errorMessage}</Alert>} <div className="modal-field"> <label htmlFor="create-user-login">{translate('quality_gates.conditions.metric')}</label> {metrics && ( 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 df0daf2024f..fd422093e2f 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 @@ -26,6 +26,7 @@ import { translate, getLocalizedMetricName } from '../../../helpers/l10n'; import { Condition as ICondition, Metric, QualityGate } from '../../../app/types'; import ModalButton from '../../../components/controls/ModalButton'; import { Button } from '../../../components/ui/buttons'; +import { Alert } from '../../../components/ui/Alert'; interface Props { canEdit: boolean; @@ -109,14 +110,14 @@ export default class Conditions extends React.PureComponent<Props> { <div className="big-spacer-bottom">{translate('quality_gates.introduction')}</div> {uniqDuplicates.length > 0 && ( - <div className="alert alert-warning"> + <Alert variant="warning"> <p>{translate('quality_gates.duplicated_conditions')}</p> <ul className="list-styled spacer-top"> {uniqDuplicates.map(d => ( <li key={d.metric.key}>{getLocalizedMetricName(d.metric)}</li> ))} </ul> - </div> + </Alert> )} {sortedConditions.length ? ( diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/components/DeleteProfileForm.tsx b/server/sonar-web/src/main/js/apps/quality-profiles/components/DeleteProfileForm.tsx index 941d82c311f..348f038723e 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/components/DeleteProfileForm.tsx +++ b/server/sonar-web/src/main/js/apps/quality-profiles/components/DeleteProfileForm.tsx @@ -23,6 +23,7 @@ import { deleteProfile } from '../../../api/quality-profiles'; import Modal from '../../../components/controls/Modal'; import { SubmitButton, ResetButtonLink } from '../../../components/ui/buttons'; import { translate, translateWithParameters } from '../../../helpers/l10n'; +import { Alert } from '../../../components/ui/Alert'; interface Props { onClose: () => void; @@ -71,9 +72,9 @@ export default class DeleteProfileForm extends React.PureComponent<Props, State> <div className="js-modal-messages" /> {profile.childrenCount > 0 ? ( <div> - <div className="alert alert-warning"> + <Alert variant="warning"> {translate('quality_profiles.this_profile_has_descendants')} - </div> + </Alert> <p> {translateWithParameters( 'quality_profiles.are_you_sure_want_delete_profile_x_and_descendants', diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/home/ProfilesList.tsx b/server/sonar-web/src/main/js/apps/quality-profiles/home/ProfilesList.tsx index 599c0f398d8..db19da4d2e7 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/home/ProfilesList.tsx +++ b/server/sonar-web/src/main/js/apps/quality-profiles/home/ProfilesList.tsx @@ -24,6 +24,7 @@ import ProfilesListHeader from './ProfilesListHeader'; import DocTooltip from '../../../components/docs/DocTooltip'; import { translate, translateWithParameters } from '../../../helpers/l10n'; import { Profile } from '../types'; +import { Alert } from '../../../components/ui/Alert'; interface Props { languages: Array<{ key: string; name: string }>; @@ -109,7 +110,9 @@ export default class ProfilesList extends React.PureComponent<Props> { /> {Object.keys(profilesToShow).length === 0 && ( - <div className="alert alert-warning spacer-top">{translate('no_results')}</div> + <Alert className="spacer-top" variant="warning"> + {translate('no_results')} + </Alert> )} {languagesToShow.map(languageKey => diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/home/RestoreProfileForm.tsx b/server/sonar-web/src/main/js/apps/quality-profiles/home/RestoreProfileForm.tsx index ce22a7a15fa..dbb48820936 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/home/RestoreProfileForm.tsx +++ b/server/sonar-web/src/main/js/apps/quality-profiles/home/RestoreProfileForm.tsx @@ -22,6 +22,7 @@ import { restoreQualityProfile } from '../../../api/quality-profiles'; import Modal from '../../../components/controls/Modal'; import { translate, translateWithParameters } from '../../../helpers/l10n'; import { SubmitButton, ResetButtonLink } from '../../../components/ui/buttons'; +import { Alert } from '../../../components/ui/Alert'; interface Props { onClose: () => void; @@ -93,22 +94,22 @@ export default class RestoreProfileForm extends React.PureComponent<Props, State <div className="modal-body"> {profile != null && ruleSuccesses != null ? ( ruleFailures ? ( - <div className="alert alert-warning"> + <Alert variant="warning"> {translateWithParameters( 'quality_profiles.restore_profile.warning', profile.name, ruleSuccesses, ruleFailures )} - </div> + </Alert> ) : ( - <div className="alert alert-success"> + <Alert variant="success"> {translateWithParameters( 'quality_profiles.restore_profile.success', profile.name, ruleSuccesses )} - </div> + </Alert> ) ) : ( <div className="modal-field"> diff --git a/server/sonar-web/src/main/js/apps/securityReports/components/App.tsx b/server/sonar-web/src/main/js/apps/securityReports/components/App.tsx index 58f78b0526d..ed50bf28c72 100755 --- a/server/sonar-web/src/main/js/apps/securityReports/components/App.tsx +++ b/server/sonar-web/src/main/js/apps/securityReports/components/App.tsx @@ -33,6 +33,7 @@ import { getSecurityHotspots } from '../../../api/security-reports'; import { isLongLivingBranch } from '../../../helpers/branches'; import DocTooltip from '../../../components/docs/DocTooltip'; import { StandardType } from '../utils'; +import { Alert } from '../../../components/ui/Alert'; import '../style.css'; interface Props { @@ -136,9 +137,9 @@ export default class App extends React.PureComponent<Props, State> { } return ( - <div className="alert alert-info spacer-top display-inline-block"> + <Alert className="spacer-top" display="inline" variant="info"> {translate('security_reports.more_rules')} - </div> + </Alert> ); }; diff --git a/server/sonar-web/src/main/js/apps/securityReports/components/__tests__/__snapshots__/App-test.tsx.snap b/server/sonar-web/src/main/js/apps/securityReports/components/__tests__/__snapshots__/App-test.tsx.snap index ace4a652592..4d50db28396 100644 --- a/server/sonar-web/src/main/js/apps/securityReports/components/__tests__/__snapshots__/App-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/securityReports/components/__tests__/__snapshots__/App-test.tsx.snap @@ -121,11 +121,13 @@ exports[`handle checkbox for cwe display 2`] = ` > learn_more </Link> - <div - className="alert alert-info spacer-top display-inline-block" + <Alert + className="spacer-top" + display="inline" + variant="info" > security_reports.more_rules - </div> + </Alert> </div> </header> <div @@ -266,11 +268,13 @@ exports[`renders owaspTop10 1`] = ` > learn_more </Link> - <div - className="alert alert-info spacer-top display-inline-block" + <Alert + className="spacer-top" + display="inline" + variant="info" > security_reports.more_rules - </div> + </Alert> </div> </header> <div diff --git a/server/sonar-web/src/main/js/apps/sessions/components/EmailAlreadyExists.tsx b/server/sonar-web/src/main/js/apps/sessions/components/EmailAlreadyExists.tsx index e1099044232..e8bc0c13bae 100644 --- a/server/sonar-web/src/main/js/apps/sessions/components/EmailAlreadyExists.tsx +++ b/server/sonar-web/src/main/js/apps/sessions/components/EmailAlreadyExists.tsx @@ -25,6 +25,7 @@ import { IdentityProvider } from '../../../app/types'; import { getTextColor } from '../../../helpers/colors'; import { translate } from '../../../helpers/l10n'; import { getBaseUrl } from '../../../helpers/urls'; +import { Alert } from '../../../components/ui/Alert'; interface Props { location: { @@ -120,14 +121,14 @@ export default class EmailAlreadyExists extends React.PureComponent<Props, State {this.renderIdentityProvier(query.provider, query.login)} </div> - <div className="alert alert-warning"> + <Alert variant="warning"> {translate('sessions.email_already_exists.3')} <ul className="list-styled"> <li className="spacer-top">{translate('sessions.email_already_exists.4')}</li> <li className="spacer-top">{translate('sessions.email_already_exists.5')}</li> <li className="spacer-top">{translate('sessions.email_already_exists.6')}</li> </ul> - </div> + </Alert> <div className="big-spacer-top text-right"> <a diff --git a/server/sonar-web/src/main/js/apps/sessions/components/UpdateLogin.tsx b/server/sonar-web/src/main/js/apps/sessions/components/UpdateLogin.tsx index 048f0d27516..6aac2f2e318 100644 --- a/server/sonar-web/src/main/js/apps/sessions/components/UpdateLogin.tsx +++ b/server/sonar-web/src/main/js/apps/sessions/components/UpdateLogin.tsx @@ -25,6 +25,7 @@ import { IdentityProvider } from '../../../app/types'; import { getTextColor } from '../../../helpers/colors'; import { translate } from '../../../helpers/l10n'; import { getBaseUrl } from '../../../helpers/urls'; +import { Alert } from '../../../components/ui/Alert'; interface Props { location: { @@ -119,7 +120,7 @@ export default class UpdateLogin extends React.PureComponent<Props, State> { {this.renderIdentityProvier(query.providerKey, query.login)} </div> - <div className="alert alert-warning"> + <Alert variant="warning"> {translate('sessions.update_login.3')} <ul className="list-styled"> <li className="spacer-top js-old-organization-key"> @@ -137,7 +138,7 @@ export default class UpdateLogin extends React.PureComponent<Props, State> { /> </li> </ul> - </div> + </Alert> <div className="big-spacer-top text-right"> <a diff --git a/server/sonar-web/src/main/js/apps/sessions/components/__tests__/__snapshots__/EmailAlreadyExists-test.tsx.snap b/server/sonar-web/src/main/js/apps/sessions/components/__tests__/__snapshots__/EmailAlreadyExists-test.tsx.snap index f2da9104731..26c56ed365c 100644 --- a/server/sonar-web/src/main/js/apps/sessions/components/__tests__/__snapshots__/EmailAlreadyExists-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/sessions/components/__tests__/__snapshots__/EmailAlreadyExists-test.tsx.snap @@ -73,8 +73,8 @@ exports[`render 1`] = ` foo </div> </div> - <div - className="alert alert-warning" + <Alert + variant="warning" > sessions.email_already_exists.3 <ul @@ -96,7 +96,7 @@ exports[`render 1`] = ` sessions.email_already_exists.6 </li> </ul> - </div> + </Alert> <div className="big-spacer-top text-right" > diff --git a/server/sonar-web/src/main/js/apps/sessions/components/__tests__/__snapshots__/UpdateLogin-test.tsx.snap b/server/sonar-web/src/main/js/apps/sessions/components/__tests__/__snapshots__/UpdateLogin-test.tsx.snap index e6bdf411e64..550e585a059 100644 --- a/server/sonar-web/src/main/js/apps/sessions/components/__tests__/__snapshots__/UpdateLogin-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/sessions/components/__tests__/__snapshots__/UpdateLogin-test.tsx.snap @@ -55,8 +55,8 @@ exports[`render 1`] = ` foo </div> </div> - <div - className="alert alert-warning" + <Alert + variant="warning" > sessions.update_login.3 <ul @@ -93,7 +93,7 @@ exports[`render 1`] = ` /> </li> </ul> - </div> + </Alert> <div className="big-spacer-top text-right" > diff --git a/server/sonar-web/src/main/js/apps/settings/components/EmailForm.js b/server/sonar-web/src/main/js/apps/settings/components/EmailForm.js index 83b624c8e5f..e3777e25633 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/EmailForm.js +++ b/server/sonar-web/src/main/js/apps/settings/components/EmailForm.js @@ -24,6 +24,7 @@ import { sendTestEmail } from '../../../api/settings'; import { parseError } from '../../../helpers/request'; import { getCurrentUser } from '../../../store/rootReducer'; import { SubmitButton } from '../../../components/ui/buttons'; +import { Alert } from '../../../components/ui/Alert'; class EmailForm extends React.PureComponent { constructor(props) { @@ -56,18 +57,18 @@ class EmailForm extends React.PureComponent { <form onSubmit={this.handleFormSubmit} style={{ marginLeft: 201 }}> {this.state.success && ( <div className="modal-field"> - <div className="alert alert-success"> + <Alert variant="success"> {translateWithParameters( 'email_configuration.test.email_was_sent_to_x', this.state.recipient )} - </div> + </Alert> </div> )} {this.state.error != null && ( <div className="modal-field"> - <div className="alert alert-danger">{this.state.error}</div> + <Alert variant="error">{this.state.error}</Alert> </div> )} diff --git a/server/sonar-web/src/main/js/apps/system/components/ChangeLogLevelForm.tsx b/server/sonar-web/src/main/js/apps/system/components/ChangeLogLevelForm.tsx index fd80e756d09..0de7515ad08 100644 --- a/server/sonar-web/src/main/js/apps/system/components/ChangeLogLevelForm.tsx +++ b/server/sonar-web/src/main/js/apps/system/components/ChangeLogLevelForm.tsx @@ -23,6 +23,7 @@ import { setLogLevel } from '../../../api/system'; import Modal from '../../../components/controls/Modal'; import { SubmitButton, ResetButtonLink } from '../../../components/ui/buttons'; import { translate } from '../../../helpers/l10n'; +import { Alert } from '../../../components/ui/Alert'; interface Props { infoMsg: string; @@ -83,11 +84,13 @@ export default class ChangeLogLevelForm extends React.PureComponent<Props, State </label> </p> ))} - <div className="alert alert-info spacer-top">{this.props.infoMsg}</div> + <Alert className="spacer-top" variant="info"> + {this.props.infoMsg} + </Alert> {newLevel !== 'INFO' && ( - <div className="alert alert-danger spacer-top"> + <Alert className="spacer-top" variant="warning"> {translate('system.log_level.warning')} - </div> + </Alert> )} </div> <div className="modal-foot"> diff --git a/server/sonar-web/src/main/js/apps/system/components/__tests__/__snapshots__/ChangeLogLevelForm-test.tsx.snap b/server/sonar-web/src/main/js/apps/system/components/__tests__/__snapshots__/ChangeLogLevelForm-test.tsx.snap index d65fc8d4872..35853191a1a 100644 --- a/server/sonar-web/src/main/js/apps/system/components/__tests__/__snapshots__/ChangeLogLevelForm-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/system/components/__tests__/__snapshots__/ChangeLogLevelForm-test.tsx.snap @@ -79,16 +79,18 @@ exports[`should display some warning messages for non INFO levels 1`] = ` TRACE </label> </p> - <div - className="alert alert-info spacer-top" + <Alert + className="spacer-top" + variant="info" > Foo - </div> - <div - className="alert alert-danger spacer-top" + </Alert> + <Alert + className="spacer-top" + variant="warning" > system.log_level.warning - </div> + </Alert> </div> <div className="modal-foot" @@ -189,11 +191,12 @@ exports[`should render correctly 1`] = ` TRACE </label> </p> - <div - className="alert alert-info spacer-top" + <Alert + className="spacer-top" + variant="info" > Foo - </div> + </Alert> </div> <div className="modal-foot" diff --git a/server/sonar-web/src/main/js/apps/system/components/info-items/HealthCard.tsx b/server/sonar-web/src/main/js/apps/system/components/info-items/HealthCard.tsx index 8b621c3d4a6..71df00cef28 100644 --- a/server/sonar-web/src/main/js/apps/system/components/info-items/HealthCard.tsx +++ b/server/sonar-web/src/main/js/apps/system/components/info-items/HealthCard.tsx @@ -25,6 +25,7 @@ import BoxedGroupAccordion from '../../../../components/controls/BoxedGroupAccor import { HealthType, SysValueObject } from '../../../../api/system'; import { LOGS_LEVELS, groupSections, getLogsLevel } from '../../utils'; import { translate } from '../../../../helpers/l10n'; +import { Alert } from '../../../../components/ui/Alert'; interface Props { biggerHealth?: boolean; @@ -58,9 +59,12 @@ export default function HealthCard({ renderHeader={() => ( <> {showLogLevelWarning && ( - <span className="alert alert-danger spacer-left"> + <Alert + className="boxed-group-accordion-alert spacer-left" + display="inline" + variant="warning"> {translate('system.log_level.warning.short')} - </span> + </Alert> )} {health && ( <HealthItem diff --git a/server/sonar-web/src/main/js/apps/system/components/info-items/HealthCauseItem.tsx b/server/sonar-web/src/main/js/apps/system/components/info-items/HealthCauseItem.tsx index c644e75bf96..698a4f142f5 100644 --- a/server/sonar-web/src/main/js/apps/system/components/info-items/HealthCauseItem.tsx +++ b/server/sonar-web/src/main/js/apps/system/components/info-items/HealthCauseItem.tsx @@ -20,6 +20,7 @@ import * as React from 'react'; import * as classNames from 'classnames'; import { HealthType } from '../../../../api/system'; +import { Alert } from '../../../../components/ui/Alert'; interface Props { className?: string; @@ -29,13 +30,11 @@ interface Props { export default function HealthCauseItem({ className, health, healthCause }: Props) { return ( - <span - className={classNames( - 'alert', - health === HealthType.RED ? 'alert-danger' : 'alert-warning', - className - )}> + <Alert + className={classNames('boxed-group-accordion-alert', className)} + display="inline" + variant={health === HealthType.RED ? 'error' : 'warning'}> {healthCause} - </span> + </Alert> ); } diff --git a/server/sonar-web/src/main/js/apps/system/components/info-items/__tests__/HealthCard-test.tsx b/server/sonar-web/src/main/js/apps/system/components/info-items/__tests__/HealthCard-test.tsx index 08ea6b5f66d..1679562e8e8 100644 --- a/server/sonar-web/src/main/js/apps/system/components/info-items/__tests__/HealthCard-test.tsx +++ b/server/sonar-web/src/main/js/apps/system/components/info-items/__tests__/HealthCard-test.tsx @@ -40,7 +40,7 @@ it('should display the log level alert', () => { expect( getWrapper({ sysInfoData: { 'Logs Level': 'DEBUG' } }) .dive() - .find('.alert') + .find('Alert') ).toMatchSnapshot(); }); diff --git a/server/sonar-web/src/main/js/apps/system/components/info-items/__tests__/__snapshots__/HealthCard-test.tsx.snap b/server/sonar-web/src/main/js/apps/system/components/info-items/__tests__/__snapshots__/HealthCard-test.tsx.snap index 8ce1a5d4f14..b4210356c2e 100644 --- a/server/sonar-web/src/main/js/apps/system/components/info-items/__tests__/__snapshots__/HealthCard-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/system/components/info-items/__tests__/__snapshots__/HealthCard-test.tsx.snap @@ -1,11 +1,13 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`should display the log level alert 1`] = ` -<span - className="alert alert-danger spacer-left" +<Alert + className="boxed-group-accordion-alert spacer-left" + display="inline" + variant="warning" > system.log_level.warning.short -</span> +</Alert> `; exports[`should render correctly 1`] = ` diff --git a/server/sonar-web/src/main/js/apps/system/components/info-items/__tests__/__snapshots__/HealthCauseItem-test.tsx.snap b/server/sonar-web/src/main/js/apps/system/components/info-items/__tests__/__snapshots__/HealthCauseItem-test.tsx.snap index 3202387cf1c..900bbd1a029 100644 --- a/server/sonar-web/src/main/js/apps/system/components/info-items/__tests__/__snapshots__/HealthCauseItem-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/system/components/info-items/__tests__/__snapshots__/HealthCauseItem-test.tsx.snap @@ -1,17 +1,21 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`should render correctly 1`] = ` -<span - className="alert alert-danger" +<Alert + className="boxed-group-accordion-alert" + display="inline" + variant="error" > foo -</span> +</Alert> `; exports[`should render correctly 2`] = ` -<span - className="alert alert-warning" +<Alert + className="boxed-group-accordion-alert" + display="inline" + variant="warning" > foo -</span> +</Alert> `; diff --git a/server/sonar-web/src/main/js/apps/system/components/system-upgrade/SystemUpgradeNotif.tsx b/server/sonar-web/src/main/js/apps/system/components/system-upgrade/SystemUpgradeNotif.tsx index 15f4e8a3b10..59407b300a3 100644 --- a/server/sonar-web/src/main/js/apps/system/components/system-upgrade/SystemUpgradeNotif.tsx +++ b/server/sonar-web/src/main/js/apps/system/components/system-upgrade/SystemUpgradeNotif.tsx @@ -23,6 +23,7 @@ import { sortUpgrades, groupUpgrades } from '../../utils'; import { getSystemUpgrades, SystemUpgrade } from '../../../../api/system'; import { Button } from '../../../../components/ui/buttons'; import { translate } from '../../../../helpers/l10n'; +import { Alert } from '../../../../components/ui/Alert'; interface State { systemUpgrades: SystemUpgrade[][]; @@ -69,12 +70,12 @@ export default class SystemUpgradeNotif extends React.PureComponent<{}, State> { return ( <div className="page-notifs"> - <div className="alert alert-info"> + <Alert variant="info"> {translate('system.new_version_available')} <Button className="spacer-left" onClick={this.handleOpenSystemUpgradeForm}> {translate('learn_more')} </Button> - </div> + </Alert> {this.state.openSystemUpgradeForm && ( <SystemUpgradeForm onClose={this.handleCloseSystemUpgradeForm} diff --git a/server/sonar-web/src/main/js/apps/system/components/system-upgrade/__tests__/__snapshots__/SystemUpgradeNotif-test.tsx.snap b/server/sonar-web/src/main/js/apps/system/components/system-upgrade/__tests__/__snapshots__/SystemUpgradeNotif-test.tsx.snap index 50c3d8ee70e..6e9ef3d00dd 100644 --- a/server/sonar-web/src/main/js/apps/system/components/system-upgrade/__tests__/__snapshots__/SystemUpgradeNotif-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/system/components/system-upgrade/__tests__/__snapshots__/SystemUpgradeNotif-test.tsx.snap @@ -4,8 +4,8 @@ exports[`should display correctly 1`] = ` <div className="page-notifs" > - <div - className="alert alert-info" + <Alert + variant="info" > system.new_version_available <Button @@ -14,6 +14,6 @@ exports[`should display correctly 1`] = ` > learn_more </Button> - </div> + </Alert> </div> `; diff --git a/server/sonar-web/src/main/js/apps/system/styles.css b/server/sonar-web/src/main/js/apps/system/styles.css index 3c332eaa7c1..d3d644e8a51 100644 --- a/server/sonar-web/src/main/js/apps/system/styles.css +++ b/server/sonar-web/src/main/js/apps/system/styles.css @@ -31,10 +31,6 @@ top: 8px; } -.system-info-health-info .alert { - display: inline-block; -} - .system-info-health-info.no-margin .status-indicator { margin: 0; } diff --git a/server/sonar-web/src/main/js/apps/tutorials/analyzeProject/AnalyzeTutorialSuggestion.tsx b/server/sonar-web/src/main/js/apps/tutorials/analyzeProject/AnalyzeTutorialSuggestion.tsx index c12288a152b..d433da91112 100644 --- a/server/sonar-web/src/main/js/apps/tutorials/analyzeProject/AnalyzeTutorialSuggestion.tsx +++ b/server/sonar-web/src/main/js/apps/tutorials/analyzeProject/AnalyzeTutorialSuggestion.tsx @@ -22,11 +22,12 @@ import { FormattedMessage } from 'react-intl'; import { isBitbucket, isGithub, isVSTS } from '../../../helpers/almIntegrations'; import { translate } from '../../../helpers/l10n'; import { getBaseUrl } from '../../../helpers/urls'; +import { Alert } from '../../../components/ui/Alert'; export default function AnalyzeTutorialSuggestion({ almId }: { almId?: string }) { if (isBitbucket(almId)) { return ( - <div className="alert alert-info big-spacer-bottom"> + <Alert className="big-spacer-bottom" variant="info"> <p>{translate('onboarding.project_analysis.commands_for_analysis')}</p> <p>{translate('onboarding.project_analysis.suggestions.bitbucket')}</p> <FormattedMessage @@ -39,17 +40,18 @@ export default function AnalyzeTutorialSuggestion({ almId }: { almId?: string }) getBaseUrl() + '/documentation/integrations/bitbucketcloud/#analyzing-with-pipelines' } + rel="noopener noreferrer" target="_blank"> {translate('onboarding.project_analysis.guide_to_integrate_piplines')} </a> ) }} /> - </div> + </Alert> ); } else if (isGithub(almId)) { return ( - <div className="alert alert-info big-spacer-bottom"> + <Alert className="big-spacer-bottom" variant="info"> <p>{translate('onboarding.project_analysis.commands_for_analysis')} </p> <p>{translate('onboarding.project_analysis.suggestions.github')}</p> <FormattedMessage @@ -66,23 +68,26 @@ export default function AnalyzeTutorialSuggestion({ almId }: { almId?: string }) ) }} /> - </div> + </Alert> ); } else if (isVSTS(almId)) { return ( - <p className="alert alert-info big-spacer-bottom"> + <Alert className="big-spacer-bottom" variant="info"> <FormattedMessage defaultMessage={translate('onboarding.project_analysis.simply_link')} id={'onboarding.project_analysis.simply_link'} values={{ link: ( - <a href={getBaseUrl() + '/documentation/integrations/vsts/'} target="_blank"> + <a + href={getBaseUrl() + '/documentation/integrations/vsts/'} + rel="noopener noreferrer" + target="_blank"> {translate('onboarding.project_analysis.guide_to_integrate_vsts')} </a> ) }} /> - </p> + </Alert> ); } return null; diff --git a/server/sonar-web/src/main/js/apps/tutorials/analyzeProject/__tests__/__snapshots__/AnalyzeTutorialSuggestion-test.tsx.snap b/server/sonar-web/src/main/js/apps/tutorials/analyzeProject/__tests__/__snapshots__/AnalyzeTutorialSuggestion-test.tsx.snap index 885aa00d882..b917e6c7a44 100644 --- a/server/sonar-web/src/main/js/apps/tutorials/analyzeProject/__tests__/__snapshots__/AnalyzeTutorialSuggestion-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/tutorials/analyzeProject/__tests__/__snapshots__/AnalyzeTutorialSuggestion-test.tsx.snap @@ -1,8 +1,9 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`renders bitbucket suggestions correctly 1`] = ` -<div - className="alert alert-info big-spacer-bottom" +<Alert + className="big-spacer-bottom" + variant="info" > <p> onboarding.project_analysis.commands_for_analysis @@ -17,6 +18,7 @@ exports[`renders bitbucket suggestions correctly 1`] = ` Object { "link": <a href="/documentation/integrations/bitbucketcloud/#analyzing-with-pipelines" + rel="noopener noreferrer" target="_blank" > onboarding.project_analysis.guide_to_integrate_piplines @@ -24,12 +26,13 @@ exports[`renders bitbucket suggestions correctly 1`] = ` } } /> -</div> +</Alert> `; exports[`renders github suggestions correctly 1`] = ` -<div - className="alert alert-info big-spacer-bottom" +<Alert + className="big-spacer-bottom" + variant="info" > <p> onboarding.project_analysis.commands_for_analysis @@ -53,12 +56,13 @@ exports[`renders github suggestions correctly 1`] = ` } } /> -</div> +</Alert> `; exports[`renders vsts suggestions correctly 1`] = ` -<p - className="alert alert-info big-spacer-bottom" +<Alert + className="big-spacer-bottom" + variant="info" > <FormattedMessage defaultMessage="onboarding.project_analysis.simply_link" @@ -67,6 +71,7 @@ exports[`renders vsts suggestions correctly 1`] = ` Object { "link": <a href="/documentation/integrations/vsts/" + rel="noopener noreferrer" target="_blank" > onboarding.project_analysis.guide_to_integrate_vsts @@ -74,5 +79,5 @@ exports[`renders vsts suggestions correctly 1`] = ` } } /> -</p> +</Alert> `; diff --git a/server/sonar-web/src/main/js/apps/tutorials/teamOnboarding/TeamOnboardingModal.tsx b/server/sonar-web/src/main/js/apps/tutorials/teamOnboarding/TeamOnboardingModal.tsx index c3a6be5b14c..335fac4c0e3 100644 --- a/server/sonar-web/src/main/js/apps/tutorials/teamOnboarding/TeamOnboardingModal.tsx +++ b/server/sonar-web/src/main/js/apps/tutorials/teamOnboarding/TeamOnboardingModal.tsx @@ -23,6 +23,7 @@ import { Link } from 'react-router'; import Modal from '../../../components/controls/Modal'; import { translate } from '../../../helpers/l10n'; import { ResetButtonLink } from '../../../components/ui/buttons'; +import { Alert } from '../../../components/ui/Alert'; interface Props { onFinish: () => void; @@ -41,9 +42,7 @@ export default class TeamOnboardingModal extends React.PureComponent<Props> { <h2>{header}</h2> </header> <div className="modal-body"> - <div className="alert alert-info modal-alert"> - {translate('onboarding.team.work_in_progress')} - </div> + <Alert variant="info">{translate('onboarding.team.work_in_progress')}</Alert> <p className="spacer-top big-spacer-bottom">{translate('onboarding.team.first_step')}</p> <p className="spacer-top big-spacer-bottom"> <FormattedMessage diff --git a/server/sonar-web/src/main/js/apps/tutorials/teamOnboarding/__tests__/__snapshots__/TeamOnboardingModal-test.tsx.snap b/server/sonar-web/src/main/js/apps/tutorials/teamOnboarding/__tests__/__snapshots__/TeamOnboardingModal-test.tsx.snap index 362251e8c42..b9217d73929 100644 --- a/server/sonar-web/src/main/js/apps/tutorials/teamOnboarding/__tests__/__snapshots__/TeamOnboardingModal-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/tutorials/teamOnboarding/__tests__/__snapshots__/TeamOnboardingModal-test.tsx.snap @@ -17,11 +17,11 @@ exports[`renders correctly 1`] = ` <div className="modal-body" > - <div - className="alert alert-info modal-alert" + <Alert + variant="info" > onboarding.team.work_in_progress - </div> + </Alert> <p className="spacer-top big-spacer-bottom" > diff --git a/server/sonar-web/src/main/js/apps/users/components/GroupsForm.tsx b/server/sonar-web/src/main/js/apps/users/components/GroupsForm.tsx index 75c98f1a131..c09f4297e9c 100644 --- a/server/sonar-web/src/main/js/apps/users/components/GroupsForm.tsx +++ b/server/sonar-web/src/main/js/apps/users/components/GroupsForm.tsx @@ -33,14 +33,13 @@ interface Props { } interface State { - error: string; groups: UserGroup[]; selectedGroups: string[]; } export default class GroupsForm extends React.PureComponent<Props> { container?: HTMLDivElement | null; - state: State = { error: '', groups: [], selectedGroups: [] }; + state: State = { groups: [], selectedGroups: [] }; componentDidMount() { this.handleSearch('', Filter.Selected); @@ -112,11 +111,6 @@ export default class GroupsForm extends React.PureComponent<Props> { </div> <div className="modal-body"> - {this.state.error !== '' && ( - <div className="alert alert-danger"> - <p>{this.state.error}</p> - </div> - )} <SelectList elements={this.state.groups.map(group => group.name)} onSearch={this.handleSearch} diff --git a/server/sonar-web/src/main/js/apps/users/components/PasswordForm.tsx b/server/sonar-web/src/main/js/apps/users/components/PasswordForm.tsx index 00872246c35..5ee73668115 100644 --- a/server/sonar-web/src/main/js/apps/users/components/PasswordForm.tsx +++ b/server/sonar-web/src/main/js/apps/users/components/PasswordForm.tsx @@ -26,6 +26,7 @@ import Modal from '../../../components/controls/Modal'; import { SubmitButton, ResetButtonLink } from '../../../components/ui/buttons'; import { translate } from '../../../helpers/l10n'; import { parseError } from '../../../helpers/request'; +import { Alert } from '../../../components/ui/Alert'; interface Props { isCurrentUser: boolean; @@ -107,7 +108,7 @@ export default class PasswordForm extends React.PureComponent<Props, State> { <h2>{header}</h2> </header> <div className="modal-body"> - {error && <p className="alert alert-danger">{error}</p>} + {error && <Alert variant="error">{error}</Alert>} {this.props.isCurrentUser && ( <div className="modal-field"> <label htmlFor="old-user-password"> diff --git a/server/sonar-web/src/main/js/apps/users/components/TokensFormNewToken.tsx b/server/sonar-web/src/main/js/apps/users/components/TokensFormNewToken.tsx index f7b744e9c1f..22e0506b164 100644 --- a/server/sonar-web/src/main/js/apps/users/components/TokensFormNewToken.tsx +++ b/server/sonar-web/src/main/js/apps/users/components/TokensFormNewToken.tsx @@ -20,6 +20,7 @@ import * as React from 'react'; import ClipboardButton from '../../../components/controls/ClipboardButton'; import { translateWithParameters } from '../../../helpers/l10n'; +import { Alert } from '../../../components/ui/Alert'; interface Props { token: { name: string; token: string }; @@ -28,9 +29,9 @@ interface Props { export default function TokensFormNewToken({ token }: Props) { return ( <div className="panel panel-white big-spacer-top"> - <p className="alert alert-warning"> + <Alert variant="warning"> {translateWithParameters('users.tokens.new_token_created', token.name)} - </p> + </Alert> <ClipboardButton copyValue={token.token} /> <code className="big-spacer-left text-success">{token.token}</code> </div> diff --git a/server/sonar-web/src/main/js/apps/users/components/UserForm.tsx b/server/sonar-web/src/main/js/apps/users/components/UserForm.tsx index 75b581deea3..381d58ff3df 100644 --- a/server/sonar-web/src/main/js/apps/users/components/UserForm.tsx +++ b/server/sonar-web/src/main/js/apps/users/components/UserForm.tsx @@ -27,6 +27,7 @@ import Modal from '../../../components/controls/Modal'; import { Button, ResetButtonLink, SubmitButton } from '../../../components/ui/buttons'; import { translate, translateWithParameters } from '../../../helpers/l10n'; import { parseError } from '../../../helpers/request'; +import { Alert } from '../../../components/ui/Alert'; export interface Props { user?: User; @@ -163,7 +164,7 @@ export default class UserForm extends React.PureComponent<Props, State> { </header> <div className="modal-body"> - {error && <p className="alert alert-danger">{error}</p>} + {error && <Alert variant="error">{error}</Alert>} {!user && ( <div className="modal-field"> diff --git a/server/sonar-web/src/main/js/components/SourceViewer/SourceViewerBase.tsx b/server/sonar-web/src/main/js/components/SourceViewer/SourceViewerBase.tsx index 021f46232bf..23dc626afc0 100644 --- a/server/sonar-web/src/main/js/components/SourceViewer/SourceViewerBase.tsx +++ b/server/sonar-web/src/main/js/components/SourceViewer/SourceViewerBase.tsx @@ -49,6 +49,7 @@ import { } from '../../app/types'; import { isSameBranchLike, getBranchLikeQuery } from '../../helpers/branches'; import { translate } from '../../helpers/l10n'; +import { Alert } from '../ui/Alert'; import './styles.css'; // TODO react-virtualized @@ -683,17 +684,17 @@ export default class SourceViewerBase extends React.PureComponent<Props, State> if (this.state.notExist) { return ( - <div className="alert alert-warning spacer-top"> + <Alert className="spacer-top" variant="warning"> {translate('component_viewer.no_component')} - </div> + </Alert> ); } if (notAccessible) { return ( - <div className="alert alert-warning spacer-top"> + <Alert className="spacer-top" variant="warning"> {translate('code_viewer.no_source_code_displayed_due_to_security')} - </div> + </Alert> ); } @@ -714,9 +715,9 @@ export default class SourceViewerBase extends React.PureComponent<Props, State> /> )} {sourceRemoved && ( - <div className="alert alert-warning spacer-top"> + <Alert className="spacer-top" variant="warning"> {translate('code_viewer.no_source_code_displayed_due_to_source_removed')} - </div> + </Alert> )} {!sourceRemoved && sources !== undefined && this.renderCode(sources)} </div> diff --git a/server/sonar-web/src/main/js/components/SourceViewer/components/DuplicationPopup.tsx b/server/sonar-web/src/main/js/components/SourceViewer/components/DuplicationPopup.tsx index c8cd8ce6658..ec3ec9bf4cb 100644 --- a/server/sonar-web/src/main/js/components/SourceViewer/components/DuplicationPopup.tsx +++ b/server/sonar-web/src/main/js/components/SourceViewer/components/DuplicationPopup.tsx @@ -29,6 +29,7 @@ import { WorkspaceContext } from '../../workspace/context'; import { translate } from '../../../helpers/l10n'; import { collapsedDirFromPath, fileFromPath } from '../../../helpers/path'; import { getProjectUrl } from '../../../helpers/urls'; +import { Alert } from '../../ui/Alert'; interface Props { blocks: DuplicationBlock[]; @@ -94,9 +95,9 @@ export default class DuplicationPopup extends React.PureComponent<Props> { <DropdownOverlay placement={PopupPlacement.RightTop}> <div className="source-viewer-bubble-popup abs-width-400"> {this.props.inRemovedComponent && ( - <div className="alert alert-warning"> + <Alert variant="warning"> {translate('duplications.dups_found_on_deleted_resource')} - </div> + </Alert> )} {duplications.length > 0 && ( <> diff --git a/server/sonar-web/src/main/js/components/docs/DocMarkdownBlock.tsx b/server/sonar-web/src/main/js/components/docs/DocMarkdownBlock.tsx index 1480de4352c..f4369bb14ea 100644 --- a/server/sonar-web/src/main/js/components/docs/DocMarkdownBlock.tsx +++ b/server/sonar-web/src/main/js/components/docs/DocMarkdownBlock.tsx @@ -60,6 +60,7 @@ export default class DocMarkdownBlock extends React.PureComponent<Props> { { remark() .use(remarkToc, { maxDepth: 3 }) + // TODO find a way to replace these custom blocks with real Alert components .use(remarkCustomBlocks, { danger: { classes: 'alert alert-danger' }, warning: { classes: 'alert alert-warning' }, diff --git a/server/sonar-web/src/main/js/components/facet/ListStyleFacet.tsx b/server/sonar-web/src/main/js/components/facet/ListStyleFacet.tsx index 347f4d3bb46..473a4cc19b4 100644 --- a/server/sonar-web/src/main/js/components/facet/ListStyleFacet.tsx +++ b/server/sonar-web/src/main/js/components/facet/ListStyleFacet.tsx @@ -32,6 +32,7 @@ import SearchBox from '../controls/SearchBox'; import ListFooter from '../controls/ListFooter'; import { formatMeasure } from '../../helpers/measures'; import { queriesEqual, RawQuery } from '../../helpers/query'; +import { Alert } from '../ui/Alert'; interface SearchResponse<S> { maxResults?: boolean; @@ -297,9 +298,9 @@ export default class ListStyleFacet<S> extends React.Component<Props<S>, State<S /> {mightHaveMoreResults && this.state.showFullList && ( - <div className="alert alert-warning spacer-top"> + <Alert className="spacer-top" variant="warning"> {translate('facet_might_have_more_results')} - </div> + </Alert> )} </> ); @@ -341,9 +342,9 @@ export default class ListStyleFacet<S> extends React.Component<Props<S>, State<S {searchResults.map(result => this.renderSearchResult(result))} </FacetItemsList> {searchMaxResults && ( - <div className="alert alert-warning spacer-top"> + <Alert className="spacer-top" variant="warning"> {translate('facet_might_have_more_results')} - </div> + </Alert> )} {searchPaging && ( <ListFooter diff --git a/server/sonar-web/src/main/js/components/facet/__tests__/ListStyleFacet-test.tsx b/server/sonar-web/src/main/js/components/facet/__tests__/ListStyleFacet-test.tsx index 825919a3a3f..9dfb153df91 100644 --- a/server/sonar-web/src/main/js/components/facet/__tests__/ListStyleFacet-test.tsx +++ b/server/sonar-web/src/main/js/components/facet/__tests__/ListStyleFacet-test.tsx @@ -140,7 +140,7 @@ it('should show warning that there might be more results', () => { const wrapper = shallowRender({ maxInitialItems: 2, maxItems: 3 }); wrapper.find('ListStyleFacetFooter').prop<Function>('showMore')(); wrapper.update(); - expect(wrapper.find('.alert-warning').exists()).toBe(true); + expect(wrapper.find('Alert').exists()).toBe(true); }); it('should reset state when closes', () => { diff --git a/server/sonar-web/src/main/js/components/icons-components/InfoIcon.tsx b/server/sonar-web/src/main/js/components/icons-components/InfoIcon.tsx new file mode 100644 index 00000000000..afbbf7bb8e0 --- /dev/null +++ b/server/sonar-web/src/main/js/components/icons-components/InfoIcon.tsx @@ -0,0 +1,32 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import * as React from 'react'; +import Icon, { IconProps } from './Icon'; + +export default function InfoIcon({ className, fill = 'currentColor', size }: IconProps) { + return ( + <Icon className={className} size={size}> + <path + d="M10.333 12.375v-1.458a.288.288 0 0 0-.291-.292h-.875V5.958a.288.288 0 0 0-.292-.291H5.958a.288.288 0 0 0-.291.291v1.459c0 .164.127.291.291.291h.875v2.917h-.875a.288.288 0 0 0-.291.292v1.458c0 .164.127.292.291.292h4.084a.288.288 0 0 0 .291-.292zM9.167 4.208V2.75a.288.288 0 0 0-.292-.292h-1.75a.288.288 0 0 0-.292.292v1.458c0 .164.128.292.292.292h1.75a.288.288 0 0 0 .292-.292zM15 8c0 3.865-3.135 7-7 7s-7-3.135-7-7 3.135-7 7-7 7 3.135 7 7z" + style={{ fill }} + /> + </Icon> + ); +} diff --git a/server/sonar-web/src/main/js/components/lazyLoad.tsx b/server/sonar-web/src/main/js/components/lazyLoad.tsx index 2b4268bf08a..65eac059f8a 100644 --- a/server/sonar-web/src/main/js/components/lazyLoad.tsx +++ b/server/sonar-web/src/main/js/components/lazyLoad.tsx @@ -18,6 +18,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import * as React from 'react'; +import { Alert } from './ui/Alert'; import { translate } from '../helpers/l10n'; import { get, save } from '../helpers/storage'; @@ -84,7 +85,7 @@ export function lazyLoad<P>(loader: Loader<P>, displayName?: string) { const { Component, error } = this.state; if (error && error.request) { - return <div className="alert alert-danger">{translate('default_error_message')}</div>; + return <Alert variant="error">{translate('default_error_message')}</Alert>; } if (!Component) { diff --git a/server/sonar-web/src/main/js/components/nav/NavBar.css b/server/sonar-web/src/main/js/components/nav/NavBar.css index 8e199e96cc8..7b61b442dad 100644 --- a/server/sonar-web/src/main/js/components/nav/NavBar.css +++ b/server/sonar-web/src/main/js/components/nav/NavBar.css @@ -41,14 +41,3 @@ padding-left: 20px; padding-right: 20px; } - -.navbar-notif.alert { - border-left: none; - border-right: none; - padding: 6px 0; -} - -.navbar-notif-cancelable { - display: flex; - justify-content: space-between; -} diff --git a/server/sonar-web/src/main/js/components/nav/NavBarNotif.css b/server/sonar-web/src/main/js/components/nav/NavBarNotif.css new file mode 100644 index 00000000000..ad753aae001 --- /dev/null +++ b/server/sonar-web/src/main/js/components/nav/NavBarNotif.css @@ -0,0 +1,43 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +.navbar-notif { + margin-bottom: var(--gridSize); + border: 1px solid; + border-left: none; + border-right: none; + padding: var(--gridSize) 0; +} + +.navbar-notif a, +.navbar-notif .button-link { + border-color: var(--darkBlue); +} + +.navbar-notif-error { + border-color: var(--alertBorderError); + background-color: var(--alertBackgroundError); + color: var(--alertTextError); +} + +.navbar-notif-info { + border-color: var(--alertBorderInfo); + background-color: var(--alertBackgroundInfo); + color: var(--alertTextInfo); +} diff --git a/server/sonar-web/src/main/js/components/nav/NavBarNotif.tsx b/server/sonar-web/src/main/js/components/nav/NavBarNotif.tsx index 835b51831e1..41d563b23c0 100644 --- a/server/sonar-web/src/main/js/components/nav/NavBarNotif.tsx +++ b/server/sonar-web/src/main/js/components/nav/NavBarNotif.tsx @@ -19,12 +19,14 @@ */ import * as React from 'react'; import * as classNames from 'classnames'; -import { DeleteButton } from '../ui/buttons'; +import './NavBarNotif.css'; + +type NavBarNotifVariant = 'error' | 'info'; interface Props { children?: React.ReactNode; className?: string; - onCancel?: () => {}; + variant: NavBarNotifVariant; } export default function NavBarNotif(props: Props) { @@ -32,16 +34,8 @@ export default function NavBarNotif(props: Props) { return null; } return ( - <div className={classNames('navbar-notif', props.className)}> - <div className="navbar-limited clearfix"> - <div - className={classNames('display-flex-center', { - 'navbar-notif-cancelable': !!props.onCancel - })}> - {props.children} - {props.onCancel && <DeleteButton className="button-small" onClick={props.onCancel} />} - </div> - </div> + <div className={classNames('navbar-notif', `navbar-notif-${props.variant}`, props.className)}> + <div className="navbar-limited clearfix">{props.children}</div> </div> ); } diff --git a/server/sonar-web/src/main/js/components/ui/Alert.tsx b/server/sonar-web/src/main/js/components/ui/Alert.tsx new file mode 100644 index 00000000000..d7699877bd1 --- /dev/null +++ b/server/sonar-web/src/main/js/components/ui/Alert.tsx @@ -0,0 +1,59 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import * as React from 'react'; +import * as classNames from 'classnames'; +import * as theme from '../../app/theme'; +import AlertErrorIcon from '../icons-components/AlertErrorIcon'; +import InfoIcon from '../icons-components/InfoIcon'; +import AlertWarnIcon from '../icons-components/AlertWarnIcon'; +import AlertSuccessIcon from '../icons-components/AlertSuccessIcon'; +import Tooltip from '../controls/Tooltip'; +import { translate } from '../../helpers/l10n'; + +type AlertDisplay = 'block' | 'inline'; +type AlertVariant = 'error' | 'warning' | 'success' | 'info'; + +export interface AlertProps { + display?: AlertDisplay; + variant: AlertVariant; +} + +export function Alert(props: AlertProps & React.HTMLAttributes<HTMLElement>) { + const { className, display, variant, ...domProps } = props; + return ( + <div + className={classNames('alert', `alert-${variant}`, className, { + 'is-inline': display === 'inline' + })} + role="alert" + {...domProps}> + <Tooltip overlay={translate('alert.tooltip', variant)}> + <div className="alert-icon"> + {variant === 'error' && <AlertErrorIcon fill={theme.alertIconError} />} + {variant === 'warning' && <AlertWarnIcon fill={theme.alertIconWarning} />} + {variant === 'success' && <AlertSuccessIcon fill={theme.alertIconSuccess} />} + {variant === 'info' && <InfoIcon fill={theme.alertIconInfo} />} + </div> + </Tooltip> + + <div className="alert-content">{props.children}</div> + </div> + ); +} diff --git a/server/sonar-web/src/main/js/components/ui/__tests__/Alert-test.tsx b/server/sonar-web/src/main/js/components/ui/__tests__/Alert-test.tsx new file mode 100644 index 00000000000..9c1881cfffb --- /dev/null +++ b/server/sonar-web/src/main/js/components/ui/__tests__/Alert-test.tsx @@ -0,0 +1,32 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import * as React from 'react'; +import { shallow } from 'enzyme'; +import { Alert } from '../Alert'; + +it('should render', () => { + expect( + shallow( + <Alert id="error-message" variant="error"> + This is an error! + </Alert> + ) + ).toMatchSnapshot(); +}); diff --git a/server/sonar-web/src/main/js/components/ui/__tests__/__snapshots__/Alert-test.tsx.snap b/server/sonar-web/src/main/js/components/ui/__tests__/__snapshots__/Alert-test.tsx.snap new file mode 100644 index 00000000000..d7528abbc59 --- /dev/null +++ b/server/sonar-web/src/main/js/components/ui/__tests__/__snapshots__/Alert-test.tsx.snap @@ -0,0 +1,26 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`should render 1`] = ` +<div + className="alert alert-error" + id="error-message" + role="alert" +> + <Tooltip + overlay="alert.tooltip.error" + > + <div + className="alert-icon" + > + <AlertErrorIcon + fill="#b81723" + /> + </div> + </Tooltip> + <div + className="alert-content" + > + This is an error! + </div> +</div> +`; diff --git a/server/sonar-web/src/main/js/components/ui/buttons.css b/server/sonar-web/src/main/js/components/ui/buttons.css index 47b16168539..c5e8be870f9 100644 --- a/server/sonar-web/src/main/js/components/ui/buttons.css +++ b/server/sonar-web/src/main/js/components/ui/buttons.css @@ -122,6 +122,7 @@ margin: 0; padding: 0; border: none; + border-radius: 0; background: transparent; color: var(--darkBlue); border-bottom: 1px solid var(--lightBlue); diff --git a/sonar-core/src/main/resources/org/sonar/l10n/core.properties b/sonar-core/src/main/resources/org/sonar/l10n/core.properties index 7687de09648..9bf2fb3085e 100644 --- a/sonar-core/src/main/resources/org/sonar/l10n/core.properties +++ b/sonar-core/src/main/resources/org/sonar/l10n/core.properties @@ -1424,6 +1424,12 @@ alerts.operator.\==equals alerts.operator.!\==is not +alert.tooltip.error=This is an error message. +alert.tooltip.warning=This is a warning message. +alert.tooltip.success=This is a success message. +alert.tooltip.info=This is an info message. + + #------------------------------------------------------------------------------ # # USER |