From 7b757f90537d99f1863407dfd2667874561d53aa Mon Sep 17 00:00:00 2001 From: Stas Vilchik Date: Thu, 14 Dec 2017 12:20:38 +0100 Subject: [PATCH] SONAR-10188 Update project/organization header --- .../components/ComponentContainerNotFound.tsx | 38 +- .../js/app/components/SimpleContainer.tsx | 38 +- .../extensions/ExtensionNotFound.tsx | 42 +- .../components/nav/component/ComponentNav.css | 8 +- .../components/nav/component/ComponentNav.tsx | 20 +- ...Breadcrumbs.tsx => ComponentNavHeader.tsx} | 92 +-- .../nav/component/ComponentNavMeta.tsx | 16 +- .../component/__tests__/ComponentNav-test.tsx | 4 +- ...s-test.tsx => ComponentNavHeader-test.tsx} | 9 +- .../__snapshots__/ComponentNav-test.tsx.snap | 4 +- .../ComponentNavBreadcrumbs-test.tsx.snap | 98 --- .../ComponentNavHeader-test.tsx.snap | 104 +++ .../ComponentNavMeta-test.tsx.snap | 32 +- .../main/js/app/styles/components/page.css | 7 +- .../src/main/js/app/styles/init/base.css | 2 +- .../src/main/js/app/styles/init/icons.css | 1 + .../src/main/js/app/styles/print.css | 7 +- .../src/main/js/app/styles/style.css | 5 - server/sonar-web/src/main/js/app/types.ts | 25 +- .../main/js/apps/about/components/AboutApp.js | 4 + .../src/main/js/apps/account/account.css | 2 +- .../js/apps/account/components/Password.js | 4 +- .../js/apps/account/components/Security.js | 4 - .../notifications/GlobalNotifications.js | 46 +- .../account/notifications/Notifications.js | 7 +- .../js/apps/account/notifications/Projects.js | 50 +- .../GlobalNotifications-test.js.snap | 126 ++-- .../__snapshots__/Notifications-test.js.snap | 5 +- .../__snapshots__/Projects-test.js.snap | 288 ++++---- .../organizations/OrganizationsList.tsx | 5 + .../organizations/UserOrganizations.tsx | 33 +- .../main/js/apps/account/profile/Profile.js | 36 +- .../apps/account/templates/account-tokens.hbs | 142 ++-- .../apps/background-tasks/components/Tasks.js | 58 +- .../src/main/js/apps/code/components/App.tsx | 4 +- .../main/js/apps/code/components/Search.tsx | 14 +- .../components/CodingRulesAppContainer.js | 6 + .../apps/component-measures/components/App.js | 4 + .../templates/custom-measures-list.hbs | 26 +- .../js/apps/groups/templates/groups-list.hbs | 2 +- .../apps/groups/templates/groups-search.hbs | 2 +- .../src/main/js/apps/issues/components/App.js | 6 + .../js/apps/issues/components/PageActions.js | 6 +- .../main/js/apps/marketplace/PluginsList.tsx | 2 +- .../src/main/js/apps/marketplace/Search.tsx | 2 +- .../src/main/js/apps/marketplace/style.css | 1 - .../apps/metrics/templates/metrics-layout.hbs | 2 +- .../organizations/components/MembersList.js | 30 +- .../components/OrganizationEdit.js | 154 ++--- .../__snapshots__/MembersList-test.js.snap | 74 +- .../OrganizationEdit-test.js.snap | 638 +++++++++--------- .../navigation/OrganizationNavigationMeta.tsx | 32 +- .../OrganizationNavigationMeta-test.tsx | 3 +- .../OrganizationNavigation-test.tsx.snap | 2 +- .../OrganizationNavigationMeta-test.tsx.snap | 4 +- .../apps/overview/components/OverviewApp.js | 8 - .../permission-templates/components/List.js | 10 +- .../shared/components/HoldersList.tsx | 18 +- .../main/js/apps/portfolio/components/App.tsx | 8 - .../src/main/js/apps/project-admin/key/Key.js | 2 +- .../main/js/apps/project-admin/links/Table.js | 10 +- .../components/ProjectActivityAppContainer.js | 4 - .../apps/projectBranches/components/App.tsx | 44 +- .../__tests__/__snapshots__/App-test.tsx.snap | 124 ++-- .../js/apps/projectQualityProfiles/Table.tsx | 24 +- .../__snapshots__/Table-test.tsx.snap | 160 ++--- .../apps/projects/components/AllProjects.tsx | 10 - .../apps/projects/components/PageHeader.tsx | 14 +- .../projects/components/ProjectCardLeak.tsx | 1 + .../components/ProjectCardOverall.tsx | 1 + .../js/apps/projectsManagement/Projects.tsx | 54 +- .../__snapshots__/Projects-test.tsx.snap | 120 ++-- .../components/QualityGatesApp.js | 4 + .../apps/quality-profiles/components/App.tsx | 11 - .../main/js/apps/settings/components/App.js | 11 - .../src/main/js/apps/users/UsersList.tsx | 54 +- .../__snapshots__/UsersList.tsx.snap | 118 ++-- .../js/apps/web-api/components/Action.tsx | 40 +- .../__snapshots__/Action-test.tsx.snap | 82 +-- .../main/js/apps/web-api/styles/web-api.css | 5 +- .../js/components/SourceViewer/styles.css | 2 +- .../js/components/common/BranchStatus.css | 3 + .../js/components/common/BranchStatus.tsx | 10 +- .../__snapshots__/BranchStatus-test.tsx.snap | 42 +- .../main/js/components/controls/Favorite.tsx | 4 +- .../js/components/controls/FavoriteBase.tsx | 9 +- .../controls/FavoriteIssueFilter.js | 42 -- .../js/components/controls/HomePageSelect.tsx | 20 +- .../controls/__tests__/Favorite-test.tsx | 2 +- .../controls/__tests__/FavoriteBase-test.tsx | 12 +- .../__snapshots__/Favorite-test.tsx.snap | 1 + .../__snapshots__/FavoriteBase-test.tsx.snap | 8 +- .../main/js/components/nav/ContextNavBar.css | 5 +- server/sonar-web/src/main/js/helpers/urls.ts | 14 +- .../resources/org/sonar/l10n/core.properties | 25 +- 95 files changed, 1789 insertions(+), 1723 deletions(-) rename server/sonar-web/src/main/js/app/components/nav/component/{ComponentNavBreadcrumbs.tsx => ComponentNavHeader.tsx} (64%) rename server/sonar-web/src/main/js/app/components/nav/component/__tests__/{ComponentNavBreadcrumbs-test.tsx => ComponentNavHeader-test.tsx} (87%) delete mode 100644 server/sonar-web/src/main/js/app/components/nav/component/__tests__/__snapshots__/ComponentNavBreadcrumbs-test.tsx.snap create mode 100644 server/sonar-web/src/main/js/app/components/nav/component/__tests__/__snapshots__/ComponentNavHeader-test.tsx.snap delete mode 100644 server/sonar-web/src/main/js/components/controls/FavoriteIssueFilter.js diff --git a/server/sonar-web/src/main/js/app/components/ComponentContainerNotFound.tsx b/server/sonar-web/src/main/js/app/components/ComponentContainerNotFound.tsx index e87bea11cce..c097f03da96 100644 --- a/server/sonar-web/src/main/js/app/components/ComponentContainerNotFound.tsx +++ b/server/sonar-web/src/main/js/app/components/ComponentContainerNotFound.tsx @@ -21,32 +21,16 @@ import * as React from 'react'; import { Link } from 'react-router'; import { translate } from '../../helpers/l10n'; -export default class ComponentContainerNotFound extends React.PureComponent { - componentDidMount() { - const html = document.querySelector('html'); - if (html) { - html.classList.add('dashboard-page'); - } - } - - componentWillUnmount() { - const html = document.querySelector('html'); - if (html) { - html.classList.remove('dashboard-page'); - } - } - - render() { - return ( -
-
-

{translate('dashboard.project_not_found')}

-

{translate('dashboard.project_not_found.2')}

-

- Go back to the homepage -

-
+export default function ComponentContainerNotFound() { + return ( +
+
+

{translate('dashboard.project_not_found')}

+

{translate('dashboard.project_not_found.2')}

+

+ Go back to the homepage +

- ); - } +
+ ); } diff --git a/server/sonar-web/src/main/js/app/components/SimpleContainer.tsx b/server/sonar-web/src/main/js/app/components/SimpleContainer.tsx index 4e5e35b7cce..8c2efc977af 100644 --- a/server/sonar-web/src/main/js/app/components/SimpleContainer.tsx +++ b/server/sonar-web/src/main/js/app/components/SimpleContainer.tsx @@ -27,35 +27,19 @@ interface Props { hideLoggedInInfo?: boolean; } -export default class SimpleContainer extends React.PureComponent { - componentDidMount() { - const html = document.querySelector('html'); - if (html) { - html.classList.add('dashboard-page'); - } - } +export default function SimpleContainer(props: Props) { + return ( +
+
+ - componentWillUnmount() { - const html = document.querySelector('html'); - if (html) { - html.classList.remove('dashboard-page'); - } - } - - render() { - return ( -
-
- - -
-
- {this.props.children} -
+
+
+ {props.children}
-
- ); - } + +
+ ); } diff --git a/server/sonar-web/src/main/js/app/components/extensions/ExtensionNotFound.tsx b/server/sonar-web/src/main/js/app/components/extensions/ExtensionNotFound.tsx index 154b674f6b9..1cad19e3d20 100644 --- a/server/sonar-web/src/main/js/app/components/extensions/ExtensionNotFound.tsx +++ b/server/sonar-web/src/main/js/app/components/extensions/ExtensionNotFound.tsx @@ -20,34 +20,18 @@ import * as React from 'react'; import { Link } from 'react-router'; -export default class ExtensionNotFound extends React.PureComponent { - componentDidMount() { - const html = document.querySelector('html'); - if (html) { - html.classList.add('dashboard-page'); - } - } - - componentWillUnmount() { - const html = document.querySelector('html'); - if (html) { - html.classList.remove('dashboard-page'); - } - } - - render() { - return ( -
-
-

The page you were looking for does not exist.

-

- You may have mistyped the address or the page may have moved. -

-

- Go back to the homepage -

-
+export default function ExtensionNotFound() { + return ( +
+
+

The page you were looking for does not exist.

+

+ You may have mistyped the address or the page may have moved. +

+

+ Go back to the homepage +

- ); - } +
+ ); } diff --git a/server/sonar-web/src/main/js/app/components/nav/component/ComponentNav.css b/server/sonar-web/src/main/js/app/components/nav/component/ComponentNav.css index fd0f3a46df1..f9488b415e3 100644 --- a/server/sonar-web/src/main/js/app/components/nav/component/ComponentNav.css +++ b/server/sonar-web/src/main/js/app/components/nav/component/ComponentNav.css @@ -1,9 +1,9 @@ .navbar-context-branches { - display: inline-block; - vertical-align: top; - padding: var(--gridSize) 0; + display: inline-flex; + justify-content: center; + line-height: calc(2 * var(--gridSize)); margin-left: calc(2 * var(--gridSize)); - line-height: 16px; + font-size: var(--baseFontSize); } .navbar-context-meta-branch-menu-item { diff --git a/server/sonar-web/src/main/js/app/components/nav/component/ComponentNav.tsx b/server/sonar-web/src/main/js/app/components/nav/component/ComponentNav.tsx index ff2205adbb6..7d4cd235925 100644 --- a/server/sonar-web/src/main/js/app/components/nav/component/ComponentNav.tsx +++ b/server/sonar-web/src/main/js/app/components/nav/component/ComponentNav.tsx @@ -18,8 +18,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import * as React from 'react'; -import ComponentNavBranch from './ComponentNavBranch'; -import ComponentNavBreadcrumbs from './ComponentNavBreadcrumbs'; +import ComponentNavHeader from './ComponentNavHeader'; import ComponentNavMeta from './ComponentNavMeta'; import ComponentNavMenu from './ComponentNavMenu'; import ComponentNavBgTaskNotif from './ComponentNavBgTaskNotif'; @@ -111,16 +110,13 @@ export default class ComponentNav extends React.PureComponent { id="context-navigation" height={notifComponent ? theme.contextNavHeightRaw + 20 : theme.contextNavHeightRaw} notif={notifComponent}> - - {this.props.currentBranch && ( - - )} + { - const isPath = item.qualifier === 'DIR'; - const itemName = isPath ? collapsePath(item.name, 15) : limitComponentName(item.name); - - if (index === 0) { - items.push( - - ); - } - - items.push( - - {itemName} - - ); - - if (index < breadcrumbs.length - 1) { - items.push(); - } - }); return (
@@ -83,29 +54,60 @@ export function ComponentNavBreadcrumbs(props: Props) { title={component.name} organization={organization && shouldOrganizationBeDisplayed ? organization : undefined} /> - {organization && - shouldOrganizationBeDisplayed && } {organization && shouldOrganizationBeDisplayed && ( - - {organization.name} - + <> + + + {organization.name} + + + )} - {organization && shouldOrganizationBeDisplayed && } - {items} + {renderBreadcrumbs(component.breadcrumbs)} {component.visibility === 'private' && ( )} + {props.currentBranch && ( + + )}
); } +function renderBreadcrumbs(breadcrumbs: Breadcrumb[]) { + const lastItem = breadcrumbs[breadcrumbs.length - 1]; + return breadcrumbs.map((item, index) => { + const isPath = item.qualifier === 'DIR'; + const itemName = isPath ? collapsePath(item.name, 15) : limitComponentName(item.name); + + return ( + + {index === 0 && } + + {itemName} + + {index < breadcrumbs.length - 1 && } + + ); + }); +} + const mapStateToProps = (state: any, ownProps: OwnProps): StateProps => ({ organization: ownProps.component.organization && getOrganizationByKey(state, ownProps.component.organization), shouldOrganizationBeDisplayed: areThereCustomOrganizations(state) }); -export default connect(mapStateToProps)(ComponentNavBreadcrumbs); +export default connect(mapStateToProps)(ComponentNavHeader); diff --git a/server/sonar-web/src/main/js/app/components/nav/component/ComponentNavMeta.tsx b/server/sonar-web/src/main/js/app/components/nav/component/ComponentNavMeta.tsx index 01be74777a6..3b080ac9d4b 100644 --- a/server/sonar-web/src/main/js/app/components/nav/component/ComponentNavMeta.tsx +++ b/server/sonar-web/src/main/js/app/components/nav/component/ComponentNavMeta.tsx @@ -19,7 +19,7 @@ */ import * as React from 'react'; import { connect } from 'react-redux'; -import { Branch, Component, CurrentUser, isLoggedIn } from '../../../types'; +import { Branch, Component, CurrentUser, isLoggedIn, HomePageType } from '../../../types'; import BranchStatus from '../../../../components/common/BranchStatus'; import DateTimeFormatter from '../../../../components/intl/DateTimeFormatter'; import Favorite from '../../../../components/controls/Favorite'; @@ -60,14 +60,22 @@ export function ComponentNavMeta({ branch, component, currentUser }: Props) { {isLoggedIn(currentUser) && mainBranch && (
- +
)} - {shortBranch && } + {shortBranch && ( +
+ +
+ )}
); } diff --git a/server/sonar-web/src/main/js/app/components/nav/component/__tests__/ComponentNav-test.tsx b/server/sonar-web/src/main/js/app/components/nav/component/__tests__/ComponentNav-test.tsx index 26f876d34f0..4c30ef3b3a4 100644 --- a/server/sonar-web/src/main/js/app/components/nav/component/__tests__/ComponentNav-test.tsx +++ b/server/sonar-web/src/main/js/app/components/nav/component/__tests__/ComponentNav-test.tsx @@ -29,9 +29,9 @@ jest.mock('../ComponentNavMeta', () => ({ } })); -jest.mock('../ComponentNavBreadcrumbs', () => ({ +jest.mock('../ComponentNavHeader', () => ({ // eslint-disable-next-line - default: function ComponentNavBreadcrumbs() { + default: function ComponentNavHeader() { return null; } })); diff --git a/server/sonar-web/src/main/js/app/components/nav/component/__tests__/ComponentNavBreadcrumbs-test.tsx b/server/sonar-web/src/main/js/app/components/nav/component/__tests__/ComponentNavHeader-test.tsx similarity index 87% rename from server/sonar-web/src/main/js/app/components/nav/component/__tests__/ComponentNavBreadcrumbs-test.tsx rename to server/sonar-web/src/main/js/app/components/nav/component/__tests__/ComponentNavHeader-test.tsx index 78a2eed1234..89d10f4ac78 100644 --- a/server/sonar-web/src/main/js/app/components/nav/component/__tests__/ComponentNavBreadcrumbs-test.tsx +++ b/server/sonar-web/src/main/js/app/components/nav/component/__tests__/ComponentNavHeader-test.tsx @@ -19,7 +19,7 @@ */ import * as React from 'react'; import { shallow } from 'enzyme'; -import { ComponentNavBreadcrumbs } from '../ComponentNavBreadcrumbs'; +import { ComponentNavHeader } from '../ComponentNavHeader'; import { Visibility } from '../../../../types'; it('should not render breadcrumbs with one element', () => { @@ -32,7 +32,7 @@ it('should not render breadcrumbs with one element', () => { visibility: 'public' }; const result = shallow( - + ); expect(result).toMatchSnapshot(); }); @@ -52,7 +52,8 @@ it('should render organization', () => { projectVisibility: Visibility.Public }; const result = shallow( - { visibility: 'private' }; const result = shallow( - + ); expect(result.find('PrivateBadge')).toHaveLength(1); }); diff --git a/server/sonar-web/src/main/js/app/components/nav/component/__tests__/__snapshots__/ComponentNav-test.tsx.snap b/server/sonar-web/src/main/js/app/components/nav/component/__tests__/__snapshots__/ComponentNav-test.tsx.snap index 6fea2eff38e..25470b77544 100644 --- a/server/sonar-web/src/main/js/app/components/nav/component/__tests__/__snapshots__/ComponentNav-test.tsx.snap +++ b/server/sonar-web/src/main/js/app/components/nav/component/__tests__/__snapshots__/ComponentNav-test.tsx.snap @@ -27,7 +27,8 @@ exports[`renders 1`] = ` /> } > - - - - - My Project - - -`; - -exports[`should render organization 1`] = ` -
- - - - The Foo Organization - - - - - My Project - -
-`; diff --git a/server/sonar-web/src/main/js/app/components/nav/component/__tests__/__snapshots__/ComponentNavHeader-test.tsx.snap b/server/sonar-web/src/main/js/app/components/nav/component/__tests__/__snapshots__/ComponentNavHeader-test.tsx.snap new file mode 100644 index 00000000000..eb990ac6401 --- /dev/null +++ b/server/sonar-web/src/main/js/app/components/nav/component/__tests__/__snapshots__/ComponentNavHeader-test.tsx.snap @@ -0,0 +1,104 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`should not render breadcrumbs with one element 1`] = ` +
+ + + + + My Project + + +
+`; + +exports[`should render organization 1`] = ` +
+ + + + + The Foo Organization + + + + + + + My Project + + +
+`; diff --git a/server/sonar-web/src/main/js/app/components/nav/component/__tests__/__snapshots__/ComponentNavMeta-test.tsx.snap b/server/sonar-web/src/main/js/app/components/nav/component/__tests__/__snapshots__/ComponentNavMeta-test.tsx.snap index 726f3168f9f..437ab7a3477 100644 --- a/server/sonar-web/src/main/js/app/components/nav/component/__tests__/__snapshots__/ComponentNavMeta-test.tsx.snap +++ b/server/sonar-web/src/main/js/app/components/nav/component/__tests__/__snapshots__/ComponentNavMeta-test.tsx.snap @@ -38,20 +38,24 @@ exports[`renders status of short-living branch 1`] = ` date="2017-01-02T00:00:00.000Z" />
- + + /> +
`; diff --git a/server/sonar-web/src/main/js/app/styles/components/page.css b/server/sonar-web/src/main/js/app/styles/components/page.css index 53855c6747f..1ef923cf2b9 100644 --- a/server/sonar-web/src/main/js/app/styles/components/page.css +++ b/server/sonar-web/src/main/js/app/styles/components/page.css @@ -17,6 +17,10 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +.white-page { + background-color: #fff !important; +} + .global-container { display: flex; flex-direction: column; @@ -150,7 +154,8 @@ padding-left: calc(50vw - 370px + 10px) !important; } -.page-footer-with-sidebar div { +.page-footer-with-sidebar div, +.page-footer-with-sidebar .page-footer-menu { max-width: 980px; } diff --git a/server/sonar-web/src/main/js/app/styles/init/base.css b/server/sonar-web/src/main/js/app/styles/init/base.css index 4b290fb3096..72a57e214d2 100644 --- a/server/sonar-web/src/main/js/app/styles/init/base.css +++ b/server/sonar-web/src/main/js/app/styles/init/base.css @@ -26,7 +26,7 @@ html, body { - background-color: #fff; + background-color: var(--barBackgroundColor); } body { diff --git a/server/sonar-web/src/main/js/app/styles/init/icons.css b/server/sonar-web/src/main/js/app/styles/init/icons.css index 2033873f784..407f8237df7 100644 --- a/server/sonar-web/src/main/js/app/styles/init/icons.css +++ b/server/sonar-web/src/main/js/app/styles/init/icons.css @@ -485,6 +485,7 @@ a:hover > .icon-radio { stroke-width: 1.41421356; stroke-opacity: 1; fill-opacity: 0; + vector-effect: non-scaling-stroke; transition: all 0.2s ease; } diff --git a/server/sonar-web/src/main/js/app/styles/print.css b/server/sonar-web/src/main/js/app/styles/print.css index 63fcfb1ee50..696c300636a 100644 --- a/server/sonar-web/src/main/js/app/styles/print.css +++ b/server/sonar-web/src/main/js/app/styles/print.css @@ -31,11 +31,10 @@ display: none !important; } - .dashboard-page, - .dashboard-page body { - background-color: #fff; + html, + body { + background-color: #fff !important; } - .widget thead, .widget tfoot { display: table-row-group; 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 921f952f4ee..a60b872bbc7 100644 --- a/server/sonar-web/src/main/js/app/styles/style.css +++ b/server/sonar-web/src/main/js/app/styles/style.css @@ -17,11 +17,6 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -.dashboard-page, -.dashboard-page body { - background-color: var(--barBackgroundColor); -} - .tabs { height: 20px; border-bottom: 1px solid #ddd; diff --git a/server/sonar-web/src/main/js/app/types.ts b/server/sonar-web/src/main/js/app/types.ts index 70df316dea2..f9f9be013ac 100644 --- a/server/sonar-web/src/main/js/app/types.ts +++ b/server/sonar-web/src/main/js/app/types.ts @@ -62,13 +62,15 @@ export interface Extension { name: string; } +export interface Breadcrumb { + key: string; + name: string; + qualifier: string; +} + export interface Component { analysisDate?: string; - breadcrumbs: Array<{ - key: string; - name: string; - qualifier: string; - }>; + breadcrumbs: Breadcrumb[]; configuration?: ComponentConfiguration; description?: string; extensions?: Extension[]; @@ -141,13 +143,20 @@ export interface CurrentUser { showOnboardingTutorial?: boolean; } +export enum HomePageType { + Project = 'PROJECT', + Organization = 'ORGANIZATION', + MyProjects = 'MY_PROJECTS', + MyIssues = 'MY_ISSUES' +} + export interface HomePage { - key?: string; - type: string; + parameter?: string; + type: HomePageType; } export function isSameHomePage(a: HomePage, b: HomePage) { - return a.type === b.type && a.key === b.key; + return a.type === b.type && a.parameter === b.parameter; } export interface LoggedInUser extends CurrentUser { diff --git a/server/sonar-web/src/main/js/apps/about/components/AboutApp.js b/server/sonar-web/src/main/js/apps/about/components/AboutApp.js index 267d0fc7cf1..d0369971567 100644 --- a/server/sonar-web/src/main/js/apps/about/components/AboutApp.js +++ b/server/sonar-web/src/main/js/apps/about/components/AboutApp.js @@ -76,11 +76,15 @@ class AboutApp extends React.PureComponent { window.location = 'https://about.sonarcloud.io'; } else { this.loadData(); + // $FlowFixMe + document.body.classList.add('white-page'); } } componentWillUnmount() { this.mounted = false; + // $FlowFixMe + document.body.classList.remove('white-page'); } loadProjects() { diff --git a/server/sonar-web/src/main/js/apps/account/account.css b/server/sonar-web/src/main/js/apps/account/account.css index 12c3cabf574..73d42282e13 100644 --- a/server/sonar-web/src/main/js/apps/account/account.css +++ b/server/sonar-web/src/main/js/apps/account/account.css @@ -8,7 +8,7 @@ padding-top: 20px; padding-bottom: 20px; border-bottom: 1px solid var(--barBorderColor); - background-color: var(--barBackgroundColor); + background-color: #fff; } .account-nav { diff --git a/server/sonar-web/src/main/js/apps/account/components/Password.js b/server/sonar-web/src/main/js/apps/account/components/Password.js index dec082bc69b..6e3bb3c3c69 100644 --- a/server/sonar-web/src/main/js/apps/account/components/Password.js +++ b/server/sonar-web/src/main/js/apps/account/components/Password.js @@ -70,10 +70,10 @@ export default class Password extends Component { const { success, errors } = this.state; return ( -
+

{translate('my_profile.password.title')}

-
+ {success && (
{translate('my_profile.password.changed')}
)} diff --git a/server/sonar-web/src/main/js/apps/account/components/Security.js b/server/sonar-web/src/main/js/apps/account/components/Security.js index d52a3b6e1ea..3006ca55f1a 100644 --- a/server/sonar-web/src/main/js/apps/account/components/Security.js +++ b/server/sonar-web/src/main/js/apps/account/components/Security.js @@ -31,11 +31,7 @@ function Security(props) { return (
- - - {user.local &&
} - {user.local && }
); diff --git a/server/sonar-web/src/main/js/apps/account/notifications/GlobalNotifications.js b/server/sonar-web/src/main/js/apps/account/notifications/GlobalNotifications.js index d7ba3d35197..294c2c209c6 100644 --- a/server/sonar-web/src/main/js/apps/account/notifications/GlobalNotifications.js +++ b/server/sonar-web/src/main/js/apps/account/notifications/GlobalNotifications.js @@ -46,30 +46,32 @@ type Props = { function GlobalNotifications(props /*: Props */) { return ( -
-

{translate('my_profile.overall_notifications.title')}

+
+

{translate('my_profile.overall_notifications.title')}

- - - - - ))} - - +
+
- {props.channels.map(channel => ( - -

{translate('notification.channel', channel)}

-
+ + + + ))} + + - `global-notification-${d}-${c}`} - onAdd={props.addNotification} - onRemove={props.removeNotification} - /> -
+ {props.channels.map(channel => ( + +

{translate('notification.channel', channel)}

+
+ `global-notification-${d}-${c}`} + onAdd={props.addNotification} + onRemove={props.removeNotification} + /> + +
); } diff --git a/server/sonar-web/src/main/js/apps/account/notifications/Notifications.js b/server/sonar-web/src/main/js/apps/account/notifications/Notifications.js index aa2c8d1179e..6e5fed53bcc 100644 --- a/server/sonar-web/src/main/js/apps/account/notifications/Notifications.js +++ b/server/sonar-web/src/main/js/apps/account/notifications/Notifications.js @@ -40,13 +40,8 @@ class Notifications extends React.PureComponent { return (
- -

{translate('notification.dispatcher.information')}

- +

{translate('notification.dispatcher.information')}

- -
-
); diff --git a/server/sonar-web/src/main/js/apps/account/notifications/Projects.js b/server/sonar-web/src/main/js/apps/account/notifications/Projects.js index 14a7f74020c..5345b55591a 100644 --- a/server/sonar-web/src/main/js/apps/account/notifications/Projects.js +++ b/server/sonar-web/src/main/js/apps/account/notifications/Projects.js @@ -113,30 +113,32 @@ class Projects extends React.PureComponent { const allProjects = [...this.props.projects, ...this.state.addedProjects]; return ( -
-

{translate('my_profile.per_project_notifications.title')}

- - {allProjects.length === 0 && ( -
{translate('my_account.no_project_notifications')}
- )} - - {allProjects.map(project => )} - -
- - {translate('my_account.set_notifications_for')}: - - +
+

{translate('my_profile.per_project_notifications.title')}

+ +
+ {allProjects.length === 0 && ( +
{translate('my_account.no_project_notifications')}
+ )} + + {allProjects.map(project => )} + +
+ + {translate('my_account.set_notifications_for')}: + + +
); diff --git a/server/sonar-web/src/main/js/apps/account/notifications/__tests__/__snapshots__/GlobalNotifications-test.js.snap b/server/sonar-web/src/main/js/apps/account/notifications/__tests__/__snapshots__/GlobalNotifications-test.js.snap index 4a7d7d10c5a..64a62011d96 100644 --- a/server/sonar-web/src/main/js/apps/account/notifications/__tests__/__snapshots__/GlobalNotifications-test.js.snap +++ b/server/sonar-web/src/main/js/apps/account/notifications/__tests__/__snapshots__/GlobalNotifications-test.js.snap @@ -1,69 +1,73 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`should match snapshot 1`] = ` -
-

+
+

my_profile.overall_notifications.title

- - - - - - - - -
- -

- notification.channel.channel1 -

-
-

- notification.channel.channel2 -

-
+ + + + + + + + +
+ +

+ notification.channel.channel1 +

+
+

+ notification.channel.channel2 +

+
+

`; diff --git a/server/sonar-web/src/main/js/apps/account/notifications/__tests__/__snapshots__/Notifications-test.js.snap b/server/sonar-web/src/main/js/apps/account/notifications/__tests__/__snapshots__/Notifications-test.js.snap index 8541cc01be7..855ccecb356 100644 --- a/server/sonar-web/src/main/js/apps/account/notifications/__tests__/__snapshots__/Notifications-test.js.snap +++ b/server/sonar-web/src/main/js/apps/account/notifications/__tests__/__snapshots__/Notifications-test.js.snap @@ -10,14 +10,11 @@ exports[`should match snapshot 1`] = ` title="my_account.notifications" />

notification.dispatcher.information

-
`; diff --git a/server/sonar-web/src/main/js/apps/account/notifications/__tests__/__snapshots__/Projects-test.js.snap b/server/sonar-web/src/main/js/apps/account/notifications/__tests__/__snapshots__/Projects-test.js.snap index 3d6b8b28eb1..7f2fb250868 100644 --- a/server/sonar-web/src/main/js/apps/account/notifications/__tests__/__snapshots__/Projects-test.js.snap +++ b/server/sonar-web/src/main/js/apps/account/notifications/__tests__/__snapshots__/Projects-test.js.snap @@ -1,178 +1,190 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`should render projects 1`] = ` -
-

+
+

my_profile.per_project_notifications.title

- -
- - my_account.set_notifications_for - : - - + +
+ + my_account.set_notifications_for + : + + +
`; exports[`should render projects 2`] = ` -
-

+
+

my_profile.per_project_notifications.title

- - -
- - my_account.set_notifications_for - : - - + + +
+ + my_account.set_notifications_for + : + + +
`; exports[`should render projects 3`] = ` -
-

+
+

my_profile.per_project_notifications.title

- - -
- - my_account.set_notifications_for - : - - + + +
+ + my_account.set_notifications_for + : + + +
`; diff --git a/server/sonar-web/src/main/js/apps/account/organizations/OrganizationsList.tsx b/server/sonar-web/src/main/js/apps/account/organizations/OrganizationsList.tsx index 5b0b8ccc367..42273f32553 100644 --- a/server/sonar-web/src/main/js/apps/account/organizations/OrganizationsList.tsx +++ b/server/sonar-web/src/main/js/apps/account/organizations/OrganizationsList.tsx @@ -21,12 +21,17 @@ import * as React from 'react'; import { sortBy } from 'lodash'; import OrganizationCard from './OrganizationCard'; import { Organization } from '../../../app/types'; +import { translate } from '../../../helpers/l10n'; interface Props { organizations: Organization[]; } export default function OrganizationsList({ organizations }: Props) { + if (organizations.length === 0) { + return
{translate('my_account.organizations.no_results')}
; + } + return (
    {sortBy(organizations, organization => organization.name.toLocaleLowerCase()).map( diff --git a/server/sonar-web/src/main/js/apps/account/organizations/UserOrganizations.tsx b/server/sonar-web/src/main/js/apps/account/organizations/UserOrganizations.tsx index e6f34fbd8e2..d63555b1574 100644 --- a/server/sonar-web/src/main/js/apps/account/organizations/UserOrganizations.tsx +++ b/server/sonar-web/src/main/js/apps/account/organizations/UserOrganizations.tsx @@ -87,29 +87,22 @@ class UserOrganizations extends React.PureComponent {
    -
    -

    {translate('my_account.organizations')}

    +
    {canCreateOrganizations && ( -
    - +
    +
    + +
    )} - {this.props.organizations.length > 0 ? ( -
    - {translate('my_account.organizations.description')} -
    - ) : ( -
    - {translate('my_account.organizations.no_results')} -
    - )} -
    - - {this.state.loading ? ( - - ) : ( - - )} +
    + {this.state.loading ? ( + + ) : ( + + )} +
    +
    {this.state.createOrganization && ( -
    - {translate('login')}: {user.login} -
    +
    +
    + {translate('login')}: {user.login} +
    + + {!user.local && + user.externalProvider !== 'sonarqube' && ( +
    + +
    + )} - {!user.local && - user.externalProvider !== 'sonarqube' && ( -
    - + {!!user.email && ( +
    + {translate('my_profile.email')}: {user.email}
    )} - {!!user.email && ( -
    - {translate('my_profile.email')}: {user.email} -
    - )} + {!customOrganizations &&
    } + {!customOrganizations && } - {!customOrganizations &&
    } - {!customOrganizations && } +
    -
    - - + +
    ); } diff --git a/server/sonar-web/src/main/js/apps/account/templates/account-tokens.hbs b/server/sonar-web/src/main/js/apps/account/templates/account-tokens.hbs index 2c8da3e0297..65bbf91e160 100644 --- a/server/sonar-web/src/main/js/apps/account/templates/account-tokens.hbs +++ b/server/sonar-web/src/main/js/apps/account/templates/account-tokens.hbs @@ -1,77 +1,81 @@ -

    {{t 'users.tokens'}}

    +
    +

    {{t 'users.tokens'}}

    -
    -

    {{t 'my_account.tokens_description'}}

    -
    +
    +
    +

    {{t 'my_account.tokens_description'}}

    +
    -{{#notNull tokens}} - - - - - - - - - - {{#each tokens}} - - - - - - {{else}} + {{#notNull tokens}} +
    {{t 'name'}}{{t 'created'}} 
    -
    - {{limitString name}} -
    -
    - {{d createdAt}} - -
    - - {{#if deleting}} - - {{else}} - - {{/if}} - -
    -
    + - + + + - {{/each}} - -
    - {{t 'users.no_tokens'}} - {{t 'name'}}{{t 'created'}} 
    -{{/notNull}} + + + {{#each tokens}} + + +
    + {{limitString name}} +
    + + + {{d createdAt}} + + +
    +
    + {{#if deleting}} + + {{else}} + + {{/if}} +
    +
    + + + {{else}} + + + {{t 'users.no_tokens'}} + + + {{/each}} + + + {{/notNull}} -{{#each errors}} -
    {{msg}}
    -{{/each}} + {{#each errors}} +
    {{msg}}
    + {{/each}} -
    - - - -
    +
    + + + +
    -{{#if newToken}} -
    -
    - {{tp 'users.tokens.new_token_created' newToken.name}} -
    + {{#if newToken}} +
    +
    + {{tp 'users.tokens.new_token_created' newToken.name}} +
    - - - - - -
    - - -
    {{newToken.token}}
    -
    -
    -{{/if}} + + + + + +
    + + +
    {{newToken.token}}
    +
    +
    + {{/if}} +
    +
    diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/Tasks.js b/server/sonar-web/src/main/js/apps/background-tasks/components/Tasks.js index 0f0f843a1f5..56f9d0508db 100644 --- a/server/sonar-web/src/main/js/apps/background-tasks/components/Tasks.js +++ b/server/sonar-web/src/main/js/apps/background-tasks/components/Tasks.js @@ -49,34 +49,36 @@ export default class Tasks extends React.PureComponent { }); return ( - - - - - - - - - - - - - - - - {tasks.map((task, index, tasks) => ( - 0 ? tasks[index - 1] : undefined} - /> - ))} - -
    {translate('background_tasks.table.status')}{translate('background_tasks.table.task')}{translate('background_tasks.table.id')} {translate('background_tasks.table.submitted')}{translate('background_tasks.table.started')}{translate('background_tasks.table.finished')}{translate('background_tasks.table.duration')} 
    +
    + + + + + + + + + + + + + + + + {tasks.map((task, index, tasks) => ( + 0 ? tasks[index - 1] : undefined} + /> + ))} + +
    {translate('background_tasks.table.status')}{translate('background_tasks.table.task')}{translate('background_tasks.table.id')} {translate('background_tasks.table.submitted')}{translate('background_tasks.table.started')}{translate('background_tasks.table.finished')}{translate('background_tasks.table.duration')} 
    +
    ); } } diff --git a/server/sonar-web/src/main/js/apps/code/components/App.tsx b/server/sonar-web/src/main/js/apps/code/components/App.tsx index 77110f20481..0a5f41af961 100644 --- a/server/sonar-web/src/main/js/apps/code/components/App.tsx +++ b/server/sonar-web/src/main/js/apps/code/components/App.tsx @@ -200,7 +200,9 @@ export default class App extends React.PureComponent { const shouldShowBreadcrumbs = breadcrumbs.length > 1; - const componentsClassName = classNames('spacer-top', { 'new-loading': loading }); + const componentsClassName = classNames('boxed-group', 'boxed-group-inner', 'spacer-top', { + 'new-loading': loading + }); return (
    diff --git a/server/sonar-web/src/main/js/apps/code/components/Search.tsx b/server/sonar-web/src/main/js/apps/code/components/Search.tsx index 14539241c9a..fba3a124f5d 100644 --- a/server/sonar-web/src/main/js/apps/code/components/Search.tsx +++ b/server/sonar-web/src/main/js/apps/code/components/Search.tsx @@ -182,12 +182,14 @@ export default class Search extends React.PureComponent { {loading && } {results != null && ( - +
    + +
    )}
    ); diff --git a/server/sonar-web/src/main/js/apps/coding-rules/components/CodingRulesAppContainer.js b/server/sonar-web/src/main/js/apps/coding-rules/components/CodingRulesAppContainer.js index 7b8eb343c90..1c578244c01 100644 --- a/server/sonar-web/src/main/js/apps/coding-rules/components/CodingRulesAppContainer.js +++ b/server/sonar-web/src/main/js/apps/coding-rules/components/CodingRulesAppContainer.js @@ -44,6 +44,9 @@ class CodingRulesAppContainer extends React.PureComponent { */ componentDidMount() { + // $FlowFixMe + document.body.classList.add('white-page'); + if (this.props.appState.organizationsEnabled && !this.props.params.organizationKey) { // redirect to organization-level rules page this.props.router.replace( @@ -62,6 +65,9 @@ class CodingRulesAppContainer extends React.PureComponent { } componentWillUnmount() { + // $FlowFixMe + document.body.classList.remove('white-page'); + if (this.stop) { this.stop(); } diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/App.js b/server/sonar-web/src/main/js/apps/component-measures/components/App.js index 84bd294f9e9..7611ea8b4c8 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/components/App.js +++ b/server/sonar-web/src/main/js/apps/component-measures/components/App.js @@ -74,6 +74,8 @@ export default class App extends React.PureComponent { componentDidMount() { this.mounted = true; + // $FlowFixMe + document.body.classList.add('white-page'); this.props.fetchMetrics(); this.fetchMeasures(this.props); key.setScope('measures-files'); @@ -95,6 +97,8 @@ export default class App extends React.PureComponent { componentWillUnmount() { this.mounted = false; + // $FlowFixMe + document.body.classList.remove('white-page'); key.deleteScope('measures-files'); const footer = document.getElementById('footer'); if (footer) { diff --git a/server/sonar-web/src/main/js/apps/custom-measures/templates/custom-measures-list.hbs b/server/sonar-web/src/main/js/apps/custom-measures/templates/custom-measures-list.hbs index 20ca1491fa3..97c513248eb 100644 --- a/server/sonar-web/src/main/js/apps/custom-measures/templates/custom-measures-list.hbs +++ b/server/sonar-web/src/main/js/apps/custom-measures/templates/custom-measures-list.hbs @@ -1,12 +1,14 @@ - - - - - - - - - - - -
    {{t 'custom_measures.metric'}}{{t 'value'}}{{t 'description'}}{{t 'date'}} 
    +
    + + + + + + + + + + + +
    {{t 'custom_measures.metric'}}{{t 'value'}}{{t 'description'}}{{t 'date'}} 
    +
    diff --git a/server/sonar-web/src/main/js/apps/groups/templates/groups-list.hbs b/server/sonar-web/src/main/js/apps/groups/templates/groups-list.hbs index b96143e7caa..ac23f3c1f65 100644 --- a/server/sonar-web/src/main/js/apps/groups/templates/groups-list.hbs +++ b/server/sonar-web/src/main/js/apps/groups/templates/groups-list.hbs @@ -1,4 +1,4 @@ -
    +
    {{#isNull organization}}
    diff --git a/server/sonar-web/src/main/js/apps/groups/templates/groups-search.hbs b/server/sonar-web/src/main/js/apps/groups/templates/groups-search.hbs index e0d8614362f..ecf034da48e 100644 --- a/server/sonar-web/src/main/js/apps/groups/templates/groups-search.hbs +++ b/server/sonar-web/src/main/js/apps/groups/templates/groups-search.hbs @@ -1,4 +1,4 @@ -
    +
    {this.props.canSetHome && ( - + )}
    ); diff --git a/server/sonar-web/src/main/js/apps/marketplace/PluginsList.tsx b/server/sonar-web/src/main/js/apps/marketplace/PluginsList.tsx index 48924aba04e..c41ac4bf516 100644 --- a/server/sonar-web/src/main/js/apps/marketplace/PluginsList.tsx +++ b/server/sonar-web/src/main/js/apps/marketplace/PluginsList.tsx @@ -79,7 +79,7 @@ export default class PluginsList extends React.PureComponent { render() { return ( -
    +
      {this.props.plugins.map(plugin => (
    • diff --git a/server/sonar-web/src/main/js/apps/marketplace/Search.tsx b/server/sonar-web/src/main/js/apps/marketplace/Search.tsx index 1eaef17728e..c114ebb6643 100644 --- a/server/sonar-web/src/main/js/apps/marketplace/Search.tsx +++ b/server/sonar-web/src/main/js/apps/marketplace/Search.tsx @@ -48,7 +48,7 @@ export default class Search extends React.PureComponent { } ]; return ( -