aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStas Vilchik <stas.vilchik@sonarsource.com>2018-10-29 15:24:06 +0100
committersonartech <sonartech@sonarsource.com>2018-10-30 12:42:03 +0100
commit440e9db98d7e1a748cb02c8839e21e94ebd2efa4 (patch)
treecddffbbae2f421bf8433663e5abb6bce7e993997
parent39db83f50fc00ad01b2ed898bf6a8b39b51f4c9c (diff)
downloadsonarqube-440e9db98d7e1a748cb02c8839e21e94ebd2efa4.tar.gz
sonarqube-440e9db98d7e1a748cb02c8839e21e94ebd2efa4.zip
SONAR-11204 Colorblind friendly banners (#899)
-rw-r--r--server/sonar-web/src/main/js/app/components/GlobalFooter.tsx9
-rw-r--r--server/sonar-web/src/main/js/app/components/__tests__/GlobalFooter-test.tsx2
-rw-r--r--server/sonar-web/src/main/js/app/components/__tests__/__snapshots__/GlobalFooter-test.tsx.snap9
-rw-r--r--server/sonar-web/src/main/js/app/components/extensions/exposeLibraries.ts2
-rw-r--r--server/sonar-web/src/main/js/app/components/nav/component/ComponentNavBgTaskNotif.tsx6
-rw-r--r--server/sonar-web/src/main/js/app/components/nav/component/ComponentNavLicenseNotif.tsx4
-rw-r--r--server/sonar-web/src/main/js/app/components/nav/component/__tests__/__snapshots__/ComponentNavBgTaskNotif-test.tsx.snap12
-rw-r--r--server/sonar-web/src/main/js/app/components/nav/component/__tests__/__snapshots__/ComponentNavLicenseNotif-test.tsx.snap8
-rw-r--r--server/sonar-web/src/main/js/app/components/nav/settings/PendingPluginsActionNotif.tsx2
-rw-r--r--server/sonar-web/src/main/js/app/components/nav/settings/__tests__/__snapshots__/PendingPluginsActionNotif-test.tsx.snap3
-rw-r--r--server/sonar-web/src/main/js/app/styles/components/alerts.css91
-rw-r--r--server/sonar-web/src/main/js/app/styles/components/boxed-group.css7
-rw-r--r--server/sonar-web/src/main/js/app/styles/sonarcloud.css16
-rw-r--r--server/sonar-web/src/main/js/app/styles/style.css4
-rw-r--r--server/sonar-web/src/main/js/app/theme.js20
-rw-r--r--server/sonar-web/src/main/js/apps/about/sonarcloud/Contact.tsx9
-rw-r--r--server/sonar-web/src/main/js/apps/account/components/Password.tsx9
-rw-r--r--server/sonar-web/src/main/js/apps/account/notifications/Notifications.tsx3
-rw-r--r--server/sonar-web/src/main/js/apps/account/notifications/__tests__/__snapshots__/Notifications-test.tsx.snap6
-rw-r--r--server/sonar-web/src/main/js/apps/background-tasks/components/WorkersForm.tsx5
-rw-r--r--server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/__snapshots__/WorkersForm-test.tsx.snap14
-rw-r--r--server/sonar-web/src/main/js/apps/coding-rules/components/ActivationFormModal.tsx5
-rw-r--r--server/sonar-web/src/main/js/apps/coding-rules/components/BulkChangeModal.tsx11
-rw-r--r--server/sonar-web/src/main/js/apps/coding-rules/components/CustomRuleFormModal.tsx3
-rw-r--r--server/sonar-web/src/main/js/apps/component-measures/components/MetricNotFound.tsx4
-rw-r--r--server/sonar-web/src/main/js/apps/component-measures/drilldown/FilesView.tsx5
-rw-r--r--server/sonar-web/src/main/js/apps/component-measures/drilldown/__tests__/__snapshots__/FilesView-test.tsx.snap7
-rw-r--r--server/sonar-web/src/main/js/apps/custom-measures/components/Form.tsx5
-rw-r--r--server/sonar-web/src/main/js/apps/custom-measures/components/Header.tsx5
-rw-r--r--server/sonar-web/src/main/js/apps/custom-measures/components/__tests__/__snapshots__/Header-test.tsx.snap7
-rw-r--r--server/sonar-web/src/main/js/apps/custom-metrics/components/Header.tsx5
-rw-r--r--server/sonar-web/src/main/js/apps/custom-metrics/components/__tests__/__snapshots__/Header-test.tsx.snap7
-rw-r--r--server/sonar-web/src/main/js/apps/documentation/styles.css5
-rw-r--r--server/sonar-web/src/main/js/apps/issues/components/BulkChangeModal.tsx7
-rw-r--r--server/sonar-web/src/main/js/apps/issues/components/__tests__/__snapshots__/BulkChangeModal-test.tsx.snap6
-rw-r--r--server/sonar-web/src/main/js/apps/organizations/components/OrganizationDelete.tsx5
-rw-r--r--server/sonar-web/src/main/js/apps/organizations/components/__tests__/__snapshots__/OrganizationDelete-test.tsx.snap6
-rw-r--r--server/sonar-web/src/main/js/apps/overview/components/EmptyOverview.tsx5
-rw-r--r--server/sonar-web/src/main/js/apps/overview/components/SonarCloudEmptyOverview.tsx5
-rw-r--r--server/sonar-web/src/main/js/apps/overview/components/__tests__/__snapshots__/EmptyOverview-test.tsx.snap18
-rw-r--r--server/sonar-web/src/main/js/apps/overview/components/__tests__/__snapshots__/SonarCloudEmptyOverview-test.tsx.snap6
-rw-r--r--server/sonar-web/src/main/js/apps/overview/qualityGate/QualityGate.tsx5
-rw-r--r--server/sonar-web/src/main/js/apps/overview/qualityGate/__tests__/__snapshots__/QualityGate-test.tsx.snap8
-rw-r--r--server/sonar-web/src/main/js/apps/permission-templates/components/ListHeader.js5
-rw-r--r--server/sonar-web/src/main/js/apps/permissions/project/components/ApplyTemplate.tsx5
-rw-r--r--server/sonar-web/src/main/js/apps/permissions/project/components/PublicProjectDisclaimer.tsx5
-rw-r--r--server/sonar-web/src/main/js/apps/permissions/shared/components/PermissionHeader.tsx5
-rw-r--r--server/sonar-web/src/main/js/apps/projectActivity/components/forms/AddGraphMetricPopup.tsx9
-rw-r--r--server/sonar-web/src/main/js/apps/projectActivity/components/projectActivity.css4
-rw-r--r--server/sonar-web/src/main/js/apps/projects/create/AutoProjectCreate.tsx5
-rw-r--r--server/sonar-web/src/main/js/apps/projects/create/CreateProjectPage.tsx14
-rw-r--r--server/sonar-web/src/main/js/apps/projects/create/__tests__/__snapshots__/AutoProjectCreate-test.tsx.snap21
-rw-r--r--server/sonar-web/src/main/js/apps/projects/create/__tests__/__snapshots__/CreateProjectPage-test.tsx.snap12
-rw-r--r--server/sonar-web/src/main/js/apps/projectsManagement/BulkApplyTemplateModal.tsx11
-rw-r--r--server/sonar-web/src/main/js/apps/projectsManagement/ChangeVisibilityForm.tsx5
-rw-r--r--server/sonar-web/src/main/js/apps/projectsManagement/CreateProjectForm.tsx5
-rw-r--r--server/sonar-web/src/main/js/apps/projectsManagement/DeleteModal.tsx7
-rw-r--r--server/sonar-web/src/main/js/apps/projectsManagement/__tests__/__snapshots__/BulkApplyTemplateModal-test.tsx.snap48
-rw-r--r--server/sonar-web/src/main/js/apps/projectsManagement/__tests__/__snapshots__/ChangeVisibilityForm-test.tsx.snap12
-rw-r--r--server/sonar-web/src/main/js/apps/projectsManagement/__tests__/__snapshots__/CreateProjectForm-test.tsx.snap6
-rw-r--r--server/sonar-web/src/main/js/apps/projectsManagement/__tests__/__snapshots__/DeleteModal-test.tsx.snap36
-rw-r--r--server/sonar-web/src/main/js/apps/quality-gates/components/ConditionModal.tsx5
-rw-r--r--server/sonar-web/src/main/js/apps/quality-gates/components/Conditions.tsx5
-rw-r--r--server/sonar-web/src/main/js/apps/quality-profiles/components/DeleteProfileForm.tsx5
-rw-r--r--server/sonar-web/src/main/js/apps/quality-profiles/home/ProfilesList.tsx5
-rw-r--r--server/sonar-web/src/main/js/apps/quality-profiles/home/RestoreProfileForm.tsx9
-rwxr-xr-xserver/sonar-web/src/main/js/apps/securityReports/components/App.tsx5
-rw-r--r--server/sonar-web/src/main/js/apps/securityReports/components/__tests__/__snapshots__/App-test.tsx.snap16
-rw-r--r--server/sonar-web/src/main/js/apps/sessions/components/EmailAlreadyExists.tsx5
-rw-r--r--server/sonar-web/src/main/js/apps/sessions/components/UpdateLogin.tsx5
-rw-r--r--server/sonar-web/src/main/js/apps/sessions/components/__tests__/__snapshots__/EmailAlreadyExists-test.tsx.snap6
-rw-r--r--server/sonar-web/src/main/js/apps/sessions/components/__tests__/__snapshots__/UpdateLogin-test.tsx.snap6
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/EmailForm.js7
-rw-r--r--server/sonar-web/src/main/js/apps/system/components/ChangeLogLevelForm.tsx9
-rw-r--r--server/sonar-web/src/main/js/apps/system/components/__tests__/__snapshots__/ChangeLogLevelForm-test.tsx.snap21
-rw-r--r--server/sonar-web/src/main/js/apps/system/components/info-items/HealthCard.tsx8
-rw-r--r--server/sonar-web/src/main/js/apps/system/components/info-items/HealthCauseItem.tsx13
-rw-r--r--server/sonar-web/src/main/js/apps/system/components/info-items/__tests__/HealthCard-test.tsx2
-rw-r--r--server/sonar-web/src/main/js/apps/system/components/info-items/__tests__/__snapshots__/HealthCard-test.tsx.snap8
-rw-r--r--server/sonar-web/src/main/js/apps/system/components/info-items/__tests__/__snapshots__/HealthCauseItem-test.tsx.snap16
-rw-r--r--server/sonar-web/src/main/js/apps/system/components/system-upgrade/SystemUpgradeNotif.tsx5
-rw-r--r--server/sonar-web/src/main/js/apps/system/components/system-upgrade/__tests__/__snapshots__/SystemUpgradeNotif-test.tsx.snap6
-rw-r--r--server/sonar-web/src/main/js/apps/system/styles.css4
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/analyzeProject/AnalyzeTutorialSuggestion.tsx19
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/analyzeProject/__tests__/__snapshots__/AnalyzeTutorialSuggestion-test.tsx.snap23
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/teamOnboarding/TeamOnboardingModal.tsx5
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/teamOnboarding/__tests__/__snapshots__/TeamOnboardingModal-test.tsx.snap6
-rw-r--r--server/sonar-web/src/main/js/apps/users/components/GroupsForm.tsx8
-rw-r--r--server/sonar-web/src/main/js/apps/users/components/PasswordForm.tsx3
-rw-r--r--server/sonar-web/src/main/js/apps/users/components/TokensFormNewToken.tsx5
-rw-r--r--server/sonar-web/src/main/js/apps/users/components/UserForm.tsx3
-rw-r--r--server/sonar-web/src/main/js/components/SourceViewer/SourceViewerBase.tsx13
-rw-r--r--server/sonar-web/src/main/js/components/SourceViewer/components/DuplicationPopup.tsx5
-rw-r--r--server/sonar-web/src/main/js/components/docs/DocMarkdownBlock.tsx1
-rw-r--r--server/sonar-web/src/main/js/components/facet/ListStyleFacet.tsx9
-rw-r--r--server/sonar-web/src/main/js/components/facet/__tests__/ListStyleFacet-test.tsx2
-rw-r--r--server/sonar-web/src/main/js/components/icons-components/InfoIcon.tsx32
-rw-r--r--server/sonar-web/src/main/js/components/lazyLoad.tsx3
-rw-r--r--server/sonar-web/src/main/js/components/nav/NavBar.css11
-rw-r--r--server/sonar-web/src/main/js/components/nav/NavBarNotif.css43
-rw-r--r--server/sonar-web/src/main/js/components/nav/NavBarNotif.tsx18
-rw-r--r--server/sonar-web/src/main/js/components/ui/Alert.tsx59
-rw-r--r--server/sonar-web/src/main/js/components/ui/__tests__/Alert-test.tsx32
-rw-r--r--server/sonar-web/src/main/js/components/ui/__tests__/__snapshots__/Alert-test.tsx.snap26
-rw-r--r--server/sonar-web/src/main/js/components/ui/buttons.css1
-rw-r--r--sonar-core/src/main/resources/org/sonar/l10n/core.properties6
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&apos;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