componentDidMount() {
const { currentUser, onSonarCloud } = this.props;
if (isLoggedIn(currentUser)) {
- if (onSonarCloud && currentUser.homepage) {
+ if (currentUser.homepage) {
const homepage = getHomePageUrl(currentUser.homepage);
this.context.router.replace(homepage);
} else {
*/
import * as React from 'react';
import { connect } from 'react-redux';
-import { Branch, Component, CurrentUser, isLoggedIn, HomePageType } from '../../../types';
+import { Branch, Component, CurrentUser, isLoggedIn, HomePageType, HomePage } from '../../../types';
import BranchStatus from '../../../../components/common/BranchStatus';
import DateTimeFormatter from '../../../../components/intl/DateTimeFormatter';
import Favorite from '../../../../components/controls/Favorite';
import HomePageSelect from '../../../../components/controls/HomePageSelect';
import Tooltip from '../../../../components/controls/Tooltip';
-import { isShortLivingBranch } from '../../../../helpers/branches';
+import {
+ isShortLivingBranch,
+ isLongLivingBranch,
+ getBranchName
+} from '../../../../helpers/branches';
import { translate } from '../../../../helpers/l10n';
import { getCurrentUser } from '../../../../store/rootReducer';
export function ComponentNavMeta({ branch, component, currentUser }: Props) {
const shortBranch = isShortLivingBranch(branch);
const mainBranch = !branch || branch.isMain;
+ const longBranch = isLongLivingBranch(branch);
+
+ let currentPage: HomePage | undefined;
+ if (component.qualifier === 'VW' || component.qualifier === 'SVW') {
+ currentPage = { type: HomePageType.Portfolio, component: component.key };
+ } else if (component.qualifier === 'APP') {
+ currentPage = { type: HomePageType.Application, component: component.key };
+ } else if (component.qualifier === 'TRK') {
+ currentPage = {
+ type: HomePageType.Project,
+ component: component.key,
+ branch: getBranchName(branch)
+ };
+ }
return (
<div className="navbar-context-meta">
)}
{component.version &&
!shortBranch && (
- <Tooltip overlay={`${translate('version')} ${component.version}`} mouseEnterDelay={0.5}>
+ <Tooltip mouseEnterDelay={0.5} overlay={`${translate('version')} ${component.version}`}>
<div className="spacer-left text-limited">
{translate('version')} {component.version}
</div>
</Tooltip>
)}
- {isLoggedIn(currentUser) &&
- mainBranch && (
- <div className="navbar-context-meta-secondary">
+ {isLoggedIn(currentUser) && (
+ <div className="navbar-context-meta-secondary">
+ {mainBranch && (
<Favorite
component={component.key}
favorite={Boolean(component.isFavorite)}
qualifier={component.qualifier}
/>
- <HomePageSelect
- className="spacer-left"
- currentPage={{ type: HomePageType.Project, parameter: component.key }}
- />
- </div>
- )}
+ )}
+ {(mainBranch || longBranch) &&
+ currentPage !== undefined && (
+ <HomePageSelect className="spacer-left" currentPage={currentPage} />
+ )}
+ </div>
+ )}
{shortBranch && (
<div className="navbar-context-meta-secondary">
<BranchStatus branch={branch!} />
name: string;
}
-export interface HomePage {
- parameter?: string;
- type: HomePageType;
-}
+export type HomePage =
+ | { type: HomePageType.Application; component: string }
+ | { type: HomePageType.Issues }
+ | { type: HomePageType.MyIssues }
+ | { type: HomePageType.MyProjects }
+ | { type: HomePageType.Organization; organization: string }
+ | { type: HomePageType.Portfolio; component: string }
+ | { type: HomePageType.Portfolios }
+ | { type: HomePageType.Project; branch: string | undefined; component: string }
+ | { type: HomePageType.Projects };
export enum HomePageType {
- Project = 'PROJECT',
- Organization = 'ORGANIZATION',
+ Application = 'APPLICATION',
+ Issues = 'ISSUES',
+ MyIssues = 'MY_ISSUES',
MyProjects = 'MY_PROJECTS',
- MyIssues = 'MY_ISSUES'
+ Organization = 'ORGANIZATION',
+ Portfolio = 'PORTFOLIO',
+ Portfolios = 'PORTFOLIOS',
+ Project = 'PROJECT',
+ Projects = 'PROJECTS'
}
export interface IdentityProvider {
}
export function isSameHomePage(a: HomePage, b: HomePage) {
- return a.type === b.type && a.parameter === b.parameter;
+ return (
+ a.type === b.type &&
+ (a as any).branch === (b as any).branch &&
+ (a as any).component === (b as any).component &&
+ (a as any).organization === (b as any).organization
+ );
}
export interface LightComponent {
CurrentUser
} from '../utils'; */
import handleRequiredAuthentication from '../../../app/utils/handleRequiredAuthentication';
-import { isLoggedIn } from '../../../app/types';
import ListFooter from '../../../components/controls/ListFooter';
import EmptySearch from '../../../components/common/EmptySearch';
import FiltersHeader from '../../../components/common/FiltersHeader';
) : (
<PageActions
canSetHome={
- this.props.onSonarCloud &&
- isLoggedIn(this.props.currentUser) &&
- this.props.myIssues &&
!this.props.organization &&
- !this.props.component
+ !this.props.component &&
+ (!this.props.onSonarCloud || this.props.myIssues)
}
loading={this.state.loading}
onReload={this.handleReload}
+ onSonarCloud={this.props.onSonarCloud}
paging={paging}
selectedIndex={selectedIndex}
/>
canSetHome: bool,
loading: boolean,
onReload: () => void,
+ onSonarCloud: bool,
paging: ?Paging,
selectedIndex: ?number
|};
{this.props.canSetHome && (
<HomePageSelect
className="huge-spacer-left"
- currentPage={{ type: HomePageType.MyIssues }}
+ currentPage={{
+ type: this.props.onSonarCloud ? HomePageType.MyIssues : HomePageType.Issues
+ }}
/>
)}
</div>
<a
className="spacer-right text-limited"
href={organization.url}
- title={organization.url}
- rel="nofollow">
+ rel="nofollow"
+ title={organization.url}>
{organization.url}
</a>
)}
{onSonarCloud && (
<div className="navbar-context-meta-secondary">
<HomePageSelect
- currentPage={{ type: HomePageType.Organization, parameter: organization.key }}
+ currentPage={{ type: HomePageType.Organization, organization: organization.key }}
/>
</div>
)}
<Connect(HomePageSelect)
currentPage={
Object {
- "parameter": "foo",
+ "organization": "foo",
"type": "ORGANIZATION",
}
}
const { loading, total, projects, currentUser, view } = props;
const limitReached = projects != null && total != null && projects.length < total;
const defaultOption = isLoggedIn(currentUser) ? 'name' : 'analysis_date';
+ const showHomePageSelect = !props.onSonarCloud || props.isFavorite;
return (
<header className="page-header projects-topbar-items">
)}
</div>
- {props.isFavorite && (
+ {showHomePageSelect && (
<HomePageSelect
className="huge-spacer-left"
- currentPage={{ type: HomePageType.MyProjects }}
+ currentPage={
+ props.onSonarCloud ? { type: HomePageType.MyProjects } : { type: HomePageType.Projects }
+ }
/>
)}
</header>
projects._projects
</span>
</div>
+ <Connect(HomePageSelect)
+ className="huge-spacer-left"
+ currentPage={
+ Object {
+ "type": "PROJECTS",
+ }
+ }
+ />
</header>
`;
projects._projects
</span>
</div>
+ <Connect(HomePageSelect)
+ className="huge-spacer-left"
+ currentPage={
+ Object {
+ "type": "PROJECTS",
+ }
+ }
+ />
</header>
`;
<div
className="projects-topbar-item is-last"
/>
+ <Connect(HomePageSelect)
+ className="huge-spacer-left"
+ currentPage={
+ Object {
+ "type": "PROJECTS",
+ }
+ }
+ />
</header>
`;
import HomeIcon from '../icons-components/HomeIcon';
import { CurrentUser, isLoggedIn, HomePage, isSameHomePage } from '../../app/types';
import { translate } from '../../helpers/l10n';
-import { getCurrentUser, getGlobalSettingValue } from '../../store/rootReducer';
+import { getCurrentUser } from '../../store/rootReducer';
import { setHomePage } from '../../store/users/actions';
interface StateProps {
currentUser: CurrentUser;
- onSonarCloud: boolean;
}
interface DispatchProps {
};
render() {
- const { currentPage, currentUser, onSonarCloud } = this.props;
+ const { currentPage, currentUser } = this.props;
- if (!isLoggedIn(currentUser) || !onSonarCloud) {
+ if (!isLoggedIn(currentUser)) {
return null;
}
}
}
-const mapStateToProps = (state: any): StateProps => {
- const sonarCloudSetting = getGlobalSettingValue(state, 'sonar.sonarcloud.enabled');
-
- return {
- currentUser: getCurrentUser(state),
- onSonarCloud: Boolean(sonarCloudSetting && sonarCloudSetting.value === 'true')
- };
-};
+const mapStateToProps = (state: any): StateProps => ({
+ currentUser: getCurrentUser(state)
+});
const mapDispatchToProps: DispatchProps = { setHomePage };
--- /dev/null
+/*
+ * 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 HomePageSelect from '../HomePageSelect';
+import { setHomePage } from '../../../api/users';
+import { HomePageType, HomePage, LoggedInUser } from '../../../app/types';
+import { click } from '../../../helpers/testUtils';
+import rootReducer, { getCurrentUser } from '../../../store/rootReducer';
+import configureStore from '../../../store/utils/configureStore';
+
+jest.mock('../../../api/users', () => ({
+ setHomePage: jest.fn(() => Promise.resolve())
+}));
+
+const homepage: HomePage = { type: HomePageType.Projects };
+
+it('should render unchecked', () => {
+ const store = configureStore(rootReducer, { users: { currentUser: { isLoggedIn: true } } });
+ expect(getWrapper(homepage, store)).toMatchSnapshot();
+});
+
+it('should render checked', () => {
+ const store = configureStore(rootReducer, {
+ users: { currentUser: { isLoggedIn: true, homepage } }
+ });
+ expect(getWrapper(homepage, store)).toMatchSnapshot();
+});
+
+it('should set new home page', async () => {
+ const store = configureStore(rootReducer, { users: { currentUser: { isLoggedIn: true } } });
+ const wrapper = getWrapper(homepage, store);
+ click(wrapper.find('a'));
+ await new Promise(setImmediate);
+ const currentUser = getCurrentUser(store.getState()) as LoggedInUser;
+ expect(currentUser.homepage).toEqual(homepage);
+ expect(setHomePage).toBeCalledWith(homepage);
+});
+
+it('should not render for anonymous', () => {
+ const store = configureStore(rootReducer, { users: { currentUser: { isLoggedIn: false } } });
+ expect(getWrapper(homepage, store).type()).toBeNull();
+});
+
+function getWrapper(currentPage: HomePage, store: any) {
+ return shallow(<HomePageSelect currentPage={currentPage} />, {
+ context: { store }
+ }).dive();
+}
--- /dev/null
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render checked 1`] = `
+<Tooltip
+ overlay="homepage.current"
+ placement="left"
+>
+ <span
+ className="display-inline-block"
+ >
+ <HomeIcon
+ filled={true}
+ />
+ </span>
+</Tooltip>
+`;
+
+exports[`should render unchecked 1`] = `
+<Tooltip
+ overlay="homepage.check"
+ placement="left"
+>
+ <a
+ className="link-no-underline display-inline-block"
+ href="#"
+ onClick={[Function]}
+ >
+ <HomeIcon
+ filled={false}
+ />
+ </a>
+</Tooltip>
+`;
return { pathname: '/dashboard', query: { id: key, branch } };
}
+export function getPortfolioUrl(key: string): Location {
+ return { pathname: '/portfolio', query: { id: key } };
+}
+
export function getComponentBackgroundTaskUrl(componentKey: string, status?: string): Location {
return { pathname: '/project/background_tasks', query: { id: componentKey, status } };
}
export function getHomePageUrl(homepage: HomePage) {
switch (homepage.type) {
+ case HomePageType.Application:
+ return getProjectUrl(homepage.component);
case HomePageType.Project:
- return getProjectUrl(homepage.parameter!);
+ return getProjectUrl(homepage.component, homepage.branch);
case HomePageType.Organization:
- return getOrganizationUrl(homepage.parameter!);
+ return getOrganizationUrl(homepage.organization);
+ case HomePageType.Portfolio:
+ return getPortfolioUrl(homepage.component);
+ case HomePageType.Portfolios:
+ return '/portfolios';
case HomePageType.MyProjects:
return '/projects';
+ case HomePageType.Issues:
case HomePageType.MyIssues:
return { pathname: '/issues', query: { resolved: 'false' } };
}