QualityGateProjectStatus,
SearchPermissionsParameters
} from '../types/quality-gates';
-import { Condition, Paging, QualityGate, UserBase } from '../types/types';
+import { Condition, Paging, QualityGate } from '../types/types';
+import { UserBase } from '../types/users';
export function fetchQualityGates(): Promise<{
actions: { create: boolean };
HotspotSetStatusRequest,
HotspotStatus
} from '../types/security-hotspots';
-import { UserBase } from '../types/types';
+import { UserBase } from '../types/users';
const HOTSPOTS_SEARCH_URL = '/api/hotspots/search';
*/
import throwGlobalError from '../app/utils/throwGlobalError';
import { getJSON, post, postJSON } from '../helpers/request';
-import {
- CurrentUser,
- CurrentUserSetting,
- HomePage,
- IdentityProvider,
- Paging,
- User
-} from '../types/types';
+import { IdentityProvider, Paging } from '../types/types';
+import { CurrentUser, HomePage, User } from '../types/users';
export function getCurrentUser(): Promise<CurrentUser> {
return getJSON('/api/users/current');
return post('/api/users/set_homepage', homepage).catch(throwGlobalError);
}
-export function setUserSetting(setting: CurrentUserSetting): Promise<void | Response> {
- return post('/api/users/set_setting', setting).catch(throwGlobalError);
-}
-
export function dismissSonarlintAd(): Promise<void | Response> {
return post('/api/users/dismiss_sonarlint_ad').catch(throwGlobalError);
}
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
-import { withCurrentUser } from '../../components/hoc/withCurrentUser';
import { Router, withRouter } from '../../components/hoc/withRouter';
import { getHomePageUrl } from '../../helpers/urls';
-import { isLoggedIn } from '../../helpers/users';
-import { CurrentUser } from '../../types/types';
+import { CurrentUser, isLoggedIn } from '../../types/users';
+import withCurrentUserContext from './current-user/withCurrentUserContext';
export interface LandingProps {
currentUser: CurrentUser;
}
}
-export default withRouter(withCurrentUser(Landing));
+export default withRouter(withCurrentUserContext(Landing));
import { Permissions } from '../../types/permissions';
import { RiskConsent } from '../../types/plugins';
import { SettingsKey } from '../../types/settings';
-import { LoggedInUser } from '../../types/types';
+import { LoggedInUser } from '../../types/users';
import GlobalMessagesContainer from './GlobalMessagesContainer';
import './PluginRiskConsent.css';
import { whenLoggedIn } from '../../components/hoc/whenLoggedIn';
import { translate } from '../../helpers/l10n';
import { getBaseUrl } from '../../helpers/system';
-import { LoggedInUser } from '../../types/types';
+import { LoggedInUser } from '../../types/users';
import GlobalMessagesContainer from './GlobalMessagesContainer';
export interface ResetPasswordProps {
*/
import { differenceInDays } from 'date-fns';
import * as React from 'react';
-import { connect } from 'react-redux';
import { showLicense } from '../../api/marketplace';
import { Location, Router, withRouter } from '../../components/hoc/withRouter';
import { lazyLoadComponent } from '../../components/lazyLoadComponent';
import { parseDate, toShortNotSoISOString } from '../../helpers/dates';
import { hasMessage } from '../../helpers/l10n';
import { get, save } from '../../helpers/storage';
-import { isLoggedIn } from '../../helpers/users';
-import { getCurrentUser, Store } from '../../store/rootReducer';
import { AppState } from '../../types/appstate';
import { EditionKey } from '../../types/editions';
-import { CurrentUser } from '../../types/types';
+import { CurrentUser, isLoggedIn } from '../../types/users';
import withAppStateContext from './app-state/withAppStateContext';
+import withCurrentUserContext from './current-user/withCurrentUserContext';
const LicensePromptModal = lazyLoadComponent(
() => import('../../apps/marketplace/components/LicensePromptModal'),
}
}
-const mapStateToProps = (state: Store): StateProps => ({
- currentUser: getCurrentUser(state)
-});
-
-export default connect(mapStateToProps)(withRouter(withAppStateContext(StartupModal)));
+export default withCurrentUserContext(withRouter(withAppStateContext(StartupModal)));
import { shallow } from 'enzyme';
import * as React from 'react';
import { mockCurrentUser, mockLoggedInUser, mockRouter } from '../../../helpers/testMocks';
-import { CurrentUser } from '../../../types/types';
+import { CurrentUser } from '../../../types/users';
import { Landing } from '../Landing';
it.each([
import { mockAppState } from '../../../helpers/testMocks';
import { waitAndUpdate } from '../../../helpers/testUtils';
import { EditionKey } from '../../../types/editions';
-import { LoggedInUser } from '../../../types/types';
+import { LoggedInUser } from '../../../types/users';
import { StartupModal } from '../StartupModal';
jest.mock('../../../api/marketplace', () => ({
exports[`should render correctly 1`] = `
<SuggestionsProvider>
<A11yProvider>
- <Connect(withRouter(withAppStateContext(StartupModal)))>
+ <withCurrentUserContext(withRouter(withAppStateContext(StartupModal)))>
<A11ySkipLinks />
<div
className="global-container"
<withAppStateContext(IndexationContextProvider)>
<LanguagesContextProvider>
<MetricsContextProvider>
- <Connect(GlobalNav)
+ <withCurrentUserContext(GlobalNav)
location={
Object {
"action": "PUSH",
}
/>
<Connect(GlobalMessages) />
- <Connect(withCurrentUser(withIndexationContext(IndexationNotification))) />
- <Connect(withCurrentUser(withAppStateContext(UpdateNotification)))
+ <withCurrentUserContext(withIndexationContext(IndexationNotification)) />
+ <withCurrentUserContext(withAppStateContext(UpdateNotification))
dismissable={true}
/>
<ChildComponent />
</withAppStateContext(IndexationContextProvider)>
</Workspace>
</div>
- <Connect(Connect(withCurrentUser(PromotionNotification))) />
+ <withCurrentUserContext(PromotionNotification) />
</div>
<withAppStateContext(GlobalFooter) />
</div>
- </Connect(withRouter(withAppStateContext(StartupModal)))>
+ </withCurrentUserContext(withRouter(withAppStateContext(StartupModal)))>
</A11yProvider>
</SuggestionsProvider>
`;
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2022 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 { CurrentUser, HomePage } from '../../../types/users';
+
+export interface CurrentUserContextInterface {
+ currentUser: CurrentUser;
+ updateCurrentUserHomepage: (homepage: HomePage) => void;
+ updateCurrentUserSonarLintAdSeen: () => void;
+}
+
+export const CurrentUserContext = React.createContext<CurrentUserContextInterface | undefined>(
+ undefined
+);
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2022 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 { CurrentUser, HomePage } from '../../../types/users';
+import { CurrentUserContext } from './CurrentUserContext';
+
+interface Props {
+ currentUser?: CurrentUser;
+}
+
+interface State {
+ currentUser: CurrentUser;
+}
+
+export default class CurrentUserContextProvider extends React.PureComponent<Props, State> {
+ constructor(props: Props) {
+ super(props);
+ this.state = { currentUser: props.currentUser ?? { isLoggedIn: false } };
+ }
+
+ updateCurrentUserHomepage = (homepage: HomePage) => {
+ this.setState(prevState => ({
+ currentUser: { ...prevState.currentUser, homepage }
+ }));
+ };
+
+ updateCurrentUserSonarLintAdSeen = () => {
+ this.setState(prevState => ({
+ currentUser: { ...prevState.currentUser, sonarLintAdSeen: true }
+ }));
+ };
+
+ render() {
+ return (
+ <CurrentUserContext.Provider
+ value={{
+ currentUser: this.state.currentUser,
+ updateCurrentUserHomepage: this.updateCurrentUserHomepage,
+ updateCurrentUserSonarLintAdSeen: this.updateCurrentUserSonarLintAdSeen
+ }}>
+ {this.props.children}
+ </CurrentUserContext.Provider>
+ );
+ }
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2022 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 { getWrappedDisplayName } from '../../../components/hoc/utils';
+import { CurrentUserContext, CurrentUserContextInterface } from './CurrentUserContext';
+
+export default function withCurrentUserContext<P>(
+ WrappedComponent: React.ComponentType<P & Pick<CurrentUserContextInterface, 'currentUser'>>
+) {
+ return class WithCurrentUserContext extends React.PureComponent<
+ Omit<P, keyof CurrentUserContextInterface>
+ > {
+ static displayName = getWrappedDisplayName(WrappedComponent, 'withCurrentUserContext');
+
+ render() {
+ return (
+ <CurrentUserContext.Consumer>
+ {(currentUserContext: CurrentUserContextInterface) => (
+ <WrappedComponent {...currentUserContext} {...(this.props as P)} />
+ )}
+ </CurrentUserContext.Consumer>
+ );
+ }
+ };
+}
import { getCurrentL10nBundle, translate } from '../../../helpers/l10n';
import { getBaseUrl } from '../../../helpers/system';
import { addGlobalErrorMessage } from '../../../store/globalMessages';
-import { getCurrentUser, Store } from '../../../store/rootReducer';
import { AppState } from '../../../types/appstate';
import { ExtensionStartMethod } from '../../../types/extension';
-import { CurrentUser, Dict, Extension as TypeExtension } from '../../../types/types';
+import { Dict, Extension as TypeExtension } from '../../../types/types';
+import { CurrentUser } from '../../../types/users';
import * as theme from '../../theme';
import getStore from '../../utils/getStore';
import withAppStateContext from '../app-state/withAppStateContext';
+import withCurrentUserContext from '../current-user/withCurrentUserContext';
interface Props extends WrappedComponentProps {
appState: AppState;
}
}
-const mapStateToProps = (state: Store) => ({ currentUser: getCurrentUser(state) });
-const mapDispatchToProps = { onFail: addGlobalErrorMessage };
-
export default injectIntl(
- withRouter(withAppStateContext(connect(mapStateToProps, mapDispatchToProps)(Extension)))
+ withRouter(
+ withAppStateContext(
+ withCurrentUserContext(connect(null, { onFail: addGlobalErrorMessage })(Extension))
+ )
+ )
);
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should render correctly: extension exists 1`] = `
-<injectIntl(withRouter(withAppStateContext(Connect(Extension))))
+<injectIntl(withRouter(withAppStateContext(withCurrentUserContext(Connect(Extension)))))
extension={
Object {
"key": "foo/bar",
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should render correctly 1`] = `
-<injectIntl(withRouter(withAppStateContext(Connect(Extension))))
+<injectIntl(withRouter(withAppStateContext(withCurrentUserContext(Connect(Extension)))))
extension={
Object {
"key": "plugin-key/extension-key",
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
-import { withCurrentUser } from '../../../components/hoc/withCurrentUser';
import withIndexationContext, {
WithIndexationContextProps
} from '../../../components/hoc/withIndexationContext';
-import { hasGlobalPermission, isLoggedIn } from '../../../helpers/users';
+import { hasGlobalPermission } from '../../../helpers/users';
import { IndexationNotificationType } from '../../../types/indexation';
import { Permissions } from '../../../types/permissions';
-import { CurrentUser } from '../../../types/types';
+import { CurrentUser, isLoggedIn } from '../../../types/users';
+import withCurrentUserContext from '../current-user/withCurrentUserContext';
import './IndexationNotification.css';
import IndexationNotificationHelper from './IndexationNotificationHelper';
import IndexationNotificationRenderer from './IndexationNotificationRenderer';
}
}
-export default withCurrentUser(withIndexationContext(IndexationNotification));
+export default withCurrentUserContext(withIndexationContext(IndexationNotification));
*/
import * as React from 'react';
import { Helmet } from 'react-helmet-async';
-import { connect } from 'react-redux';
import Favorite from '../../../../components/controls/Favorite';
-import { isLoggedIn } from '../../../../helpers/users';
-import { getCurrentUser, Store } from '../../../../store/rootReducer';
import { ProjectAlmBindingResponse } from '../../../../types/alm-settings';
import { BranchLike } from '../../../../types/branch-like';
-import { Component, CurrentUser } from '../../../../types/types';
+import { Component } from '../../../../types/types';
+import { CurrentUser, isLoggedIn } from '../../../../types/users';
+import withCurrentUserContext from '../../current-user/withCurrentUserContext';
import BranchLikeNavigation from './branch-like/BranchLikeNavigation';
import CurrentBranchLikeMergeInformation from './branch-like/CurrentBranchLikeMergeInformation';
import { Breadcrumb } from './Breadcrumb';
);
}
-const mapStateToProps = (state: Store) => ({
- currentUser: getCurrentUser(state)
-});
-
-export default connect(mapStateToProps)(React.memo(Header));
+export default withCurrentUserContext(React.memo(Header));
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
-import { connect } from 'react-redux';
import BranchStatus from '../../../../components/common/BranchStatus';
import HomePageSelect from '../../../../components/controls/HomePageSelect';
import DetachIcon from '../../../../components/icons/DetachIcon';
import DateTimeFormatter from '../../../../components/intl/DateTimeFormatter';
import { isBranch, isPullRequest } from '../../../../helpers/branch-like';
import { translate } from '../../../../helpers/l10n';
-import { isLoggedIn } from '../../../../helpers/users';
-import { getCurrentUser, Store } from '../../../../store/rootReducer';
import { BranchLike } from '../../../../types/branch-like';
import { ComponentQualifier } from '../../../../types/component';
import { TaskWarning } from '../../../../types/tasks';
-import { Component, CurrentUser, HomePage } from '../../../../types/types';
+import { Component } from '../../../../types/types';
+import { CurrentUser, HomePage, isLoggedIn } from '../../../../types/users';
+import withCurrentUserContext from '../../current-user/withCurrentUserContext';
import ComponentNavWarnings from './ComponentNavWarnings';
import './HeaderMeta.css';
return currentPage;
}
-const mapStateToProps = (state: Store) => ({
- currentUser: getCurrentUser(state)
-});
-
-export default connect(mapStateToProps)(HeaderMeta);
+export default withCurrentUserContext(HeaderMeta);
<div
className="display-flex-center display-flex-space-between little-padded-top padded-bottom"
>
- <Connect(Component)
+ <withCurrentUserContext(Component)
branchLikes={Array []}
component={
Object {
}
}
/>
- <Connect(HeaderMeta)
+ <withCurrentUserContext(HeaderMeta)
component={
Object {
"breadcrumbs": Array [
onClose={[Function]}
top={120}
>
- <Connect(withMetricsContext(ProjectInformation))
+ <withCurrentUserContext(withMetricsContext(ProjectInformation))
component={
Object {
"breadcrumbs": Array [
<div
className="display-flex-center display-flex-space-between little-padded-top padded-bottom"
>
- <Connect(Component)
+ <withCurrentUserContext(Component)
branchLikes={Array []}
component={
Object {
}
}
/>
- <Connect(HeaderMeta)
+ <withCurrentUserContext(HeaderMeta)
component={
Object {
"breadcrumbs": Array [
onClose={[Function]}
top={120}
>
- <Connect(withMetricsContext(ProjectInformation))
+ <withCurrentUserContext(withMetricsContext(ProjectInformation))
component={
Object {
"breadcrumbs": Array [
<div
className="display-flex-center display-flex-space-between little-padded-top padded-bottom"
>
- <Connect(Component)
+ <withCurrentUserContext(Component)
branchLikes={Array []}
component={
Object {
}
}
/>
- <Connect(HeaderMeta)
+ <withCurrentUserContext(HeaderMeta)
component={
Object {
"breadcrumbs": Array [
onClose={[Function]}
top={120}
>
- <Connect(withMetricsContext(ProjectInformation))
+ <withCurrentUserContext(withMetricsContext(ProjectInformation))
component={
Object {
"breadcrumbs": Array [
<div
className="display-flex-center display-flex-space-between little-padded-top padded-bottom"
>
- <Connect(Component)
+ <withCurrentUserContext(Component)
branchLikes={Array []}
component={
Object {
}
}
/>
- <Connect(HeaderMeta)
+ <withCurrentUserContext(HeaderMeta)
component={
Object {
"breadcrumbs": Array [
onClose={[Function]}
top={120}
>
- <Connect(withMetricsContext(ProjectInformation))
+ <withCurrentUserContext(withMetricsContext(ProjectInformation))
component={
Object {
"breadcrumbs": Array [
<div
className="display-flex-center display-flex-space-between little-padded-top padded-bottom"
>
- <Connect(Component)
+ <withCurrentUserContext(Component)
branchLikes={Array []}
component={
Object {
}
}
/>
- <Connect(HeaderMeta)
+ <withCurrentUserContext(HeaderMeta)
component={
Object {
"breadcrumbs": Array [
onClose={[Function]}
top={120}
>
- <Connect(withMetricsContext(ProjectInformation))
+ <withCurrentUserContext(withMetricsContext(ProjectInformation))
component={
Object {
"breadcrumbs": Array [
<div
className="display-flex-center display-flex-space-between little-padded-top"
>
- <Connect(Component)
+ <withCurrentUserContext(Component)
branchLikes={Array []}
component={
Object {
}
}
/>
- <Connect(HeaderMeta)
+ <withCurrentUserContext(HeaderMeta)
component={
Object {
"breadcrumbs": Array [
onClose={[Function]}
top={120}
>
- <Connect(withMetricsContext(ProjectInformation))
+ <withCurrentUserContext(withMetricsContext(ProjectInformation))
component={
Object {
"breadcrumbs": Array [
>
version 0.0.1
</span>
- <Connect(HomePageSelect)
+ <withCurrentUserContext(HomePageSelect)
className="spacer-left"
currentPage={
Object {
>
version 0.0.1
</span>
- <Connect(HomePageSelect)
+ <withCurrentUserContext(HomePageSelect)
className="spacer-left"
currentPage={
Object {
}
/>
</span>
- <Connect(HomePageSelect)
+ <withCurrentUserContext(HomePageSelect)
className="spacer-left"
currentPage={
Object {
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
-import { connect } from 'react-redux';
import { getMeasures } from '../../../../../api/measures';
-import { isLoggedIn } from '../../../../../helpers/users';
-import { getCurrentUser, Store } from '../../../../../store/rootReducer';
import { BranchLike } from '../../../../../types/branch-like';
import { ComponentQualifier } from '../../../../../types/component';
import { MetricKey } from '../../../../../types/metrics';
-import { Component, CurrentUser, Dict, Measure, Metric } from '../../../../../types/types';
+import { Component, Dict, Measure, Metric } from '../../../../../types/types';
+import { CurrentUser, isLoggedIn } from '../../../../../types/users';
+import withCurrentUserContext from '../../../current-user/withCurrentUserContext';
import withMetricsContext from '../../../metrics/withMetricsContext';
import ProjectBadges from './badges/ProjectBadges';
import InfoDrawerPage from './InfoDrawerPage';
}
}
-const mapStateToProps = (state: Store) => ({
- currentUser: getCurrentUser(state)
-});
-
-export default connect(mapStateToProps)(withMetricsContext(ProjectInformation));
+export default withCurrentUserContext(withMetricsContext(ProjectInformation));
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
-import { connect } from 'react-redux';
import NavBar from '../../../../components/ui/NavBar';
-import { getCurrentUser, Store } from '../../../../store/rootReducer';
-import { CurrentUser } from '../../../../types/types';
+import { CurrentUser } from '../../../../types/users';
import { rawSizes } from '../../../theme';
+import withCurrentUserContext from '../../current-user/withCurrentUserContext';
import EmbedDocsPopupHelper from '../../embed-docs-modal/EmbedDocsPopupHelper';
import Search from '../../search/Search';
import './GlobalNav.css';
);
}
-const mapStateToProps = (state: Store) => {
- return {
- currentUser: getCurrentUser(state)
- };
-};
-
-export default connect(mapStateToProps)(GlobalNav);
+export default withCurrentUserContext(GlobalNav);
import { getQualityGatesUrl } from '../../../../helpers/urls';
import { AppState } from '../../../../types/appstate';
import { ComponentQualifier } from '../../../../types/component';
-import { CurrentUser, Extension } from '../../../../types/types';
+import { Extension } from '../../../../types/types';
+import { CurrentUser } from '../../../../types/users';
import withAppStateContext from '../../app-state/withAppStateContext';
interface Props {
import Avatar from '../../../../components/ui/Avatar';
import { translate } from '../../../../helpers/l10n';
import { getBaseUrl } from '../../../../helpers/system';
-import { isLoggedIn } from '../../../../helpers/users';
-import { CurrentUser, LoggedInUser } from '../../../../types/types';
+import { CurrentUser, isLoggedIn, LoggedInUser } from '../../../../types/users';
import { rawSizes } from '../../../theme';
interface Props {
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
-import { connect } from 'react-redux';
import { dismissSonarlintAd } from '../../../api/users';
import { ButtonLink } from '../../../components/controls/buttons';
-import { withCurrentUser } from '../../../components/hoc/withCurrentUser';
import { translate } from '../../../helpers/l10n';
import { getBaseUrl } from '../../../helpers/system';
-import { isLoggedIn } from '../../../helpers/users';
-import { setSonarlintAd } from '../../../store/users';
-import { CurrentUser } from '../../../types/types';
+import { isLoggedIn } from '../../../types/users';
+import { CurrentUserContextInterface } from '../current-user/CurrentUserContext';
+import withCurrentUserContext from '../current-user/withCurrentUserContext';
import './PromotionNotification.css';
-export interface PromotionNotificationProps {
- setSonarlintAd: () => void;
- currentUser: CurrentUser;
-}
+export interface PromotionNotificationProps
+ extends Pick<CurrentUserContextInterface, 'currentUser' | 'updateCurrentUserSonarLintAdSeen'> {}
export function PromotionNotification(props: PromotionNotificationProps) {
const { currentUser } = props;
const onClick = () => {
dismissSonarlintAd();
- props.setSonarlintAd();
+ props.updateCurrentUserSonarLintAdSeen();
};
return (
);
}
-const dispatchToProps = { setSonarlintAd };
-
-export default connect(null, dispatchToProps)(withCurrentUser(PromotionNotification));
+export default withCurrentUserContext(PromotionNotification);
});
it('should remove the toaster when click on dismiss', () => {
- const setSonarlintAd = jest.fn();
+ const updateCurrentUserSonarLintAdSeen = jest.fn();
const wrapper = shallowRender({
currentUser: mockLoggedInUser({ sonarLintAdSeen: false }),
- setSonarlintAd
+ updateCurrentUserSonarLintAdSeen
});
wrapper.find('.toaster-actions ButtonLink').simulate('click');
expect(dismissSonarlintAd).toBeCalled();
- expect(setSonarlintAd).toBeCalled();
+ expect(updateCurrentUserSonarLintAdSeen).toBeCalled();
});
it('should remove the toaster and navigate to sonarlint when click on learn more', () => {
- const setSonarlintAd = jest.fn();
+ const updateCurrentUserSonarLintAdSeen = jest.fn();
const wrapper = shallowRender({
currentUser: mockLoggedInUser({ sonarLintAdSeen: false }),
- setSonarlintAd
+ updateCurrentUserSonarLintAdSeen
});
wrapper.find('.toaster-actions .button-primary').simulate('click');
expect(dismissSonarlintAd).toBeCalled();
- expect(setSonarlintAd).toBeCalled();
+ expect(updateCurrentUserSonarLintAdSeen).toBeCalled();
});
function shallowRender(props: Partial<PromotionNotificationProps> = {}) {
return shallow(
- <PromotionNotification currentUser={mockCurrentUser()} setSonarlintAd={jest.fn()} {...props} />
+ <PromotionNotification
+ currentUser={mockCurrentUser()}
+ updateCurrentUserSonarLintAdSeen={jest.fn()}
+ {...props}
+ />
);
}
import { scrollToElement } from '../../../helpers/scrolling';
import { getComponentOverviewUrl } from '../../../helpers/urls';
import { ComponentQualifier } from '../../../types/component';
-import { CurrentUser, Dict } from '../../../types/types';
+import { Dict } from '../../../types/types';
+import { CurrentUser } from '../../../types/users';
import RecentHistory from '../RecentHistory';
import './Search.css';
import { ComponentResult, More, Results, sortQualifiers } from './utils';
import { groupBy, isEmpty, mapValues } from 'lodash';
import * as React from 'react';
import { getSystemUpgrades } from '../../../api/system';
-import { withCurrentUser } from '../../../components/hoc/withCurrentUser';
import { Alert, AlertVariant } from '../../../components/ui/Alert';
import DismissableAlert from '../../../components/ui/DismissableAlert';
import SystemUpgradeButton from '../../../components/upgrade/SystemUpgradeButton';
import { sortUpgrades, UpdateUseCase } from '../../../components/upgrade/utils';
import { translate } from '../../../helpers/l10n';
-import { hasGlobalPermission, isLoggedIn } from '../../../helpers/users';
+import { hasGlobalPermission } from '../../../helpers/users';
import { AppState } from '../../../types/appstate';
import { Permissions } from '../../../types/permissions';
import { SystemUpgrade } from '../../../types/system';
-import { CurrentUser, Dict } from '../../../types/types';
+import { Dict } from '../../../types/types';
+import { CurrentUser, isLoggedIn } from '../../../types/users';
import withAppStateContext from '../app-state/withAppStateContext';
+import withCurrentUserContext from '../current-user/withCurrentUserContext';
import './UpdateNotification.css';
const MONTH_BEFOR_PREVIOUS_LTS_NOTIFICATION = 6;
canSeeNotification: false,
useCase: UpdateUseCase.NewMinorVersion
};
- this.fetchSystemUpgradeInformation();
}
componentDidMount() {
this.mounted = true;
- }
- componentDidUpdate(prevProps: Props) {
- if (
- prevProps.currentUser !== this.props.currentUser ||
- this.props.appState.version !== prevProps.appState.version
- ) {
- this.fetchSystemUpgradeInformation();
- }
+ this.fetchSystemUpgradeInformation();
}
componentWillUnmount() {
}
}
-export default withCurrentUser(withAppStateContext(UpdateNotification));
+export default withCurrentUserContext(withAppStateContext(UpdateNotification));
}
it('should render correctly', async () => {
- const wrapper = shallowRender({
+ let wrapper = shallowRender({
appState: mockAppState({ version: '9.0' }),
currentUser: mockLoggedInUser({ permissions: { global: [Permissions.Admin] } })
});
await waitAndUpdate(wrapper);
expect(wrapper).toMatchSnapshot('default');
- expect(wrapper.setProps({ currentUser: mockCurrentUser() })).toMatchSnapshot('anonymous user');
+
+ wrapper = shallowRender({
+ appState: mockAppState({ version: '9.0' }),
+ currentUser: mockCurrentUser()
+ });
+ expect(wrapper.type()).toBeNull();
});
it('should not show prompt when not admin', async () => {
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[`should render correctly: anonymous user 1`] = `""`;
-
exports[`should render correctly: default 1`] = `
<DismissableAlert
alertKey="new_minor_version9.1"
*/
import { Store } from 'redux';
import rootReducer, { Store as State } from '../../store/rootReducer';
-import { receiveCurrentUser } from '../../store/users';
import configureStore from '../../store/utils/configureStore';
-import { CurrentUser } from '../../types/types';
let store: Store<State, any>;
-const createStore = (currentUser?: CurrentUser) => {
+const createStore = () => {
store = configureStore(rootReducer);
- if (currentUser) {
- store.dispatch(receiveCurrentUser(currentUser));
- }
return store;
};
-export default (currentUser?: CurrentUser) => (store ? store : createStore(currentUser));
+export default () => (store ? store : createStore());
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-/* eslint-disable react/jsx-sort-props */
+
import { Location } from 'history';
import { pick } from 'lodash';
import * as React from 'react';
import { lazyLoadComponent } from '../../components/lazyLoadComponent';
import getHistory from '../../helpers/getHistory';
import { AppState } from '../../types/appstate';
-import { CurrentUser } from '../../types/types';
+import { CurrentUser } from '../../types/users';
import App from '../components/App';
import AppStateContextProvider from '../components/app-state/AppStateContextProvider';
+import CurrentUserContextProvider from '../components/current-user/CurrentUserContextProvider';
import GlobalContainer from '../components/GlobalContainer';
import { PageContext } from '../components/indexation/PageUnavailableDueToIndexation';
import MigrationContainer from '../components/MigrationContainer';
const el = document.getElementById('content');
const history = getHistory();
- const store = getStore(currentUser);
+ const store = getStore();
render(
<HelmetProvider>
<Provider store={store}>
<AppStateContextProvider appState={appState}>
- <IntlProvider defaultLocale={lang} locale={lang}>
- <Router history={history} onUpdate={handleUpdate}>
- {renderRedirects()}
-
- <Route
- path="formatting/help"
- component={lazyLoadComponent(() => import('../components/FormattingHelp'))}
- />
+ <CurrentUserContextProvider currentUser={currentUser}>
+ <IntlProvider defaultLocale={lang} locale={lang}>
+ <Router history={history} onUpdate={handleUpdate}>
+ {renderRedirects()}
- <Route component={lazyLoadComponent(() => import('../components/SimpleContainer'))}>
- <Route path="maintenance">{maintenanceRoutes}</Route>
- <Route path="setup">{setupRoutes}</Route>
- </Route>
-
- <Route component={MigrationContainer}>
<Route
- component={lazyLoadComponent(() =>
- import('../components/SimpleSessionsContainer')
- )}>
- <RouteWithChildRoutes path="/sessions" childRoutes={sessionsRoutes} />
+ path="formatting/help"
+ component={lazyLoadComponent(() => import('../components/FormattingHelp'))}
+ />
+
+ <Route component={lazyLoadComponent(() => import('../components/SimpleContainer'))}>
+ <Route path="maintenance">{maintenanceRoutes}</Route>
+ <Route path="setup">{setupRoutes}</Route>
</Route>
- <Route path="/" component={App}>
- <IndexRoute
- component={lazyLoadComponent(() => import('../components/Landing'))}
- />
+ <Route component={MigrationContainer}>
+ <Route
+ component={lazyLoadComponent(() =>
+ import('../components/SimpleSessionsContainer')
+ )}>
+ <RouteWithChildRoutes path="/sessions" childRoutes={sessionsRoutes} />
+ </Route>
- <Route component={GlobalContainer}>
- <RouteWithChildRoutes path="account" childRoutes={accountRoutes} />
- <RouteWithChildRoutes path="coding_rules" childRoutes={codingRulesRoutes} />
- <RouteWithChildRoutes path="documentation" childRoutes={documentationRoutes} />
+ <Route path="/" component={App}>
+ <IndexRoute
+ component={lazyLoadComponent(() => import('../components/Landing'))}
+ />
+
+ <Route component={GlobalContainer}>
+ <RouteWithChildRoutes path="account" childRoutes={accountRoutes} />
+ <RouteWithChildRoutes path="coding_rules" childRoutes={codingRulesRoutes} />
+ <RouteWithChildRoutes
+ path="documentation"
+ childRoutes={documentationRoutes}
+ />
+ <Route
+ path="extension/:pluginKey/:extensionKey"
+ component={lazyLoadComponent(() =>
+ import('../components/extensions/GlobalPageExtension')
+ )}
+ />
+ <Route
+ path="issues"
+ component={withIndexationGuard(Issues, PageContext.Issues)}
+ />
+ <RouteWithChildRoutes path="projects" childRoutes={projectsRoutes} />
+ <RouteWithChildRoutes path="quality_gates" childRoutes={qualityGatesRoutes} />
+ <Route
+ path="portfolios"
+ component={lazyLoadComponent(() =>
+ import('../components/extensions/PortfoliosPage')
+ )}
+ />
+ <RouteWithChildRoutes path="profiles" childRoutes={qualityProfilesRoutes} />
+ <RouteWithChildRoutes path="web_api" childRoutes={webAPIRoutes} />
+
+ {renderComponentRoutes()}
+
+ {renderAdminRoutes()}
+ </Route>
+ <Route
+ // We don't want this route to have any menu.
+ // That is why we can not have it under the accountRoutes
+ path="account/reset_password"
+ component={lazyLoadComponent(() => import('../components/ResetPassword'))}
+ />
<Route
- path="extension/:pluginKey/:extensionKey"
+ // We don't want this route to have any menu. This is why we define it here
+ // rather than under the admin routes.
+ path="admin/change_admin_password"
component={lazyLoadComponent(() =>
- import('../components/extensions/GlobalPageExtension')
+ import('../../apps/change-admin-password/ChangeAdminPasswordApp')
)}
/>
<Route
- path="issues"
- component={withIndexationGuard(Issues, PageContext.Issues)}
+ // We don't want this route to have any menu. This is why we define it here
+ // rather than under the admin routes.
+ path="admin/plugin_risk_consent"
+ component={lazyLoadComponent(() => import('../components/PluginRiskConsent'))}
/>
- <RouteWithChildRoutes path="projects" childRoutes={projectsRoutes} />
- <RouteWithChildRoutes path="quality_gates" childRoutes={qualityGatesRoutes} />
<Route
- path="portfolios"
- component={lazyLoadComponent(() =>
- import('../components/extensions/PortfoliosPage')
- )}
+ path="not_found"
+ component={lazyLoadComponent(() => import('../components/NotFound'))}
+ />
+ <Route
+ path="*"
+ component={lazyLoadComponent(() => import('../components/NotFound'))}
/>
- <RouteWithChildRoutes path="profiles" childRoutes={qualityProfilesRoutes} />
- <RouteWithChildRoutes path="web_api" childRoutes={webAPIRoutes} />
-
- {renderComponentRoutes()}
-
- {renderAdminRoutes()}
</Route>
- <Route
- // We don't want this route to have any menu.
- // That is why we can not have it under the accountRoutes
- path="account/reset_password"
- component={lazyLoadComponent(() => import('../components/ResetPassword'))}
- />
- <Route
- // We don't want this route to have any menu. This is why we define it here
- // rather than under the admin routes.
- path="admin/change_admin_password"
- component={lazyLoadComponent(() =>
- import('../../apps/change-admin-password/ChangeAdminPasswordApp')
- )}
- />
- <Route
- // We don't want this route to have any menu. This is why we define it here
- // rather than under the admin routes.
- path="admin/plugin_risk_consent"
- component={lazyLoadComponent(() => import('../components/PluginRiskConsent'))}
- />
- <Route
- path="not_found"
- component={lazyLoadComponent(() => import('../components/NotFound'))}
- />
- <Route
- path="*"
- component={lazyLoadComponent(() => import('../components/NotFound'))}
- />
</Route>
- </Route>
- </Router>
- </IntlProvider>
+ </Router>
+ </IntlProvider>
+ </CurrentUserContextProvider>
</AppStateContextProvider>
</Provider>
</HelmetProvider>,
import * as React from 'react';
import { Helmet } from 'react-helmet-async';
import A11ySkipTarget from '../../../app/components/a11y/A11ySkipTarget';
+import withCurrentUserContext from '../../../app/components/current-user/withCurrentUserContext';
import Suggestions from '../../../app/components/embed-docs-modal/Suggestions';
-import { withCurrentUser } from '../../../components/hoc/withCurrentUser';
import handleRequiredAuthentication from '../../../helpers/handleRequiredAuthentication';
import { translate } from '../../../helpers/l10n';
-import { CurrentUser, LoggedInUser } from '../../../types/types';
+import { CurrentUser, LoggedInUser } from '../../../types/users';
import '../account.css';
import Nav from './Nav';
import UserCard from './UserCard';
}
}
-export default withCurrentUser(Account);
+export default withCurrentUserContext(Account);
*/
import * as React from 'react';
import { Helmet } from 'react-helmet-async';
-import { connect } from 'react-redux';
+import withCurrentUserContext from '../../../app/components/current-user/withCurrentUserContext';
import ResetPasswordForm from '../../../components/common/ResetPasswordForm';
import { translate } from '../../../helpers/l10n';
-import { getCurrentUser, Store } from '../../../store/rootReducer';
-import { LoggedInUser } from '../../../types/types';
+import { LoggedInUser } from '../../../types/users';
import Tokens from './Tokens';
export interface SecurityProps {
- user: LoggedInUser;
+ currentUser: LoggedInUser;
}
-export function Security({ user }: SecurityProps) {
+export function Security({ currentUser }: SecurityProps) {
return (
<div className="account-body account-container">
<Helmet defer={false} title={translate('my_account.security')} />
- <Tokens login={user.login} />
- {user.local && (
+ <Tokens login={currentUser.login} />
+ {currentUser.local && (
<section className="boxed-group">
<h2 className="spacer-bottom">{translate('my_profile.password.title')}</h2>
- <ResetPasswordForm className="boxed-group-inner" user={user} />
+ <ResetPasswordForm className="boxed-group-inner" user={currentUser} />
</section>
)}
</div>
);
}
-const mapStateToProps = (state: Store) => ({
- user: getCurrentUser(state) as LoggedInUser
-});
-
-export default connect(mapStateToProps)(Security);
+export default withCurrentUserContext(Security);
*/
import * as React from 'react';
import Avatar from '../../../components/ui/Avatar';
-import { LoggedInUser } from '../../../types/types';
+import { LoggedInUser } from '../../../types/users';
interface Props {
user: LoggedInUser;
it('should render correctly', () => {
expect(shallowRender()).toMatchSnapshot('local user');
- expect(shallowRender({ user: mockLoggedInUser({ local: false }) })).toMatchSnapshot(
+ expect(shallowRender({ currentUser: mockLoggedInUser({ local: false }) })).toMatchSnapshot(
'non-local user'
);
});
function shallowRender(props: Partial<SecurityProps> = {}) {
- return shallow(<Security user={mockLoggedInUser({ local: true })} {...props} />);
+ return shallow(<Security currentUser={mockLoggedInUser({ local: true })} {...props} />);
}
*/
import * as React from 'react';
import { translate } from '../../../helpers/l10n';
-import { isSonarCloud } from '../../../helpers/system';
import { Notification } from '../../../types/types';
import NotificationsList from './NotificationsList';
-import SonarCloudNotifications from './SonarCloudNotifications';
interface Props {
addNotification: (n: Notification) => void;
export default function GlobalNotifications(props: Props) {
return (
- <>
- <section className="boxed-group">
- <h2>{translate('my_profile.overall_notifications.title')}</h2>
+ <section className="boxed-group">
+ <h2>{translate('my_profile.overall_notifications.title')}</h2>
- <div className="boxed-group-inner">
- <table className="data zebra">
- <thead>
- <tr>
- <th />
- {props.channels.map(channel => (
- <th className="text-center" key={channel}>
- <h4>{translate('notification.channel', channel)}</h4>
- </th>
- ))}
- </tr>
- </thead>
+ <div className="boxed-group-inner">
+ <table className="data zebra">
+ <thead>
+ <tr>
+ <th />
+ {props.channels.map(channel => (
+ <th className="text-center" key={channel}>
+ <h4>{translate('notification.channel', channel)}</h4>
+ </th>
+ ))}
+ </tr>
+ </thead>
- <NotificationsList
- channels={props.channels}
- checkboxId={getCheckboxId}
- notifications={props.notifications}
- onAdd={props.addNotification}
- onRemove={props.removeNotification}
- types={props.types}
- />
- </table>
- </div>
- </section>
- {isSonarCloud() && <SonarCloudNotifications />}
- </>
+ <NotificationsList
+ channels={props.channels}
+ checkboxId={getCheckboxId}
+ notifications={props.notifications}
+ onAdd={props.addNotification}
+ onRemove={props.removeNotification}
+ types={props.types}
+ />
+ </table>
+ </div>
+ </section>
);
}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2022 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 { connect } from 'react-redux';
-import Checkbox from '../../../components/controls/Checkbox';
-import { translate } from '../../../helpers/l10n';
-import { getCurrentUserSetting, Store } from '../../../store/rootReducer';
-import { setCurrentUserSetting } from '../../../store/users';
-import { CurrentUserSetting } from '../../../types/types';
-
-interface Props {
- notificationsOptOut?: boolean;
- setCurrentUserSetting: (setting: CurrentUserSetting) => void;
-}
-
-export class SonarCloudNotifications extends React.PureComponent<Props> {
- handleCheckOptOut = (checked: boolean) => {
- this.props.setCurrentUserSetting({
- key: 'notifications.optOut',
- value: checked ? 'false' : 'true'
- });
- };
-
- render() {
- return (
- <section className="boxed-group">
- <h2>{translate('my_profile.sonarcloud_feature_notifications.title')}</h2>
- <div className="boxed-group-inner">
- <table className="data zebra">
- <thead>
- <tr>
- <th />
- <th className="text-center">
- <h4>{translate('activate')}</h4>
- </th>
- </tr>
- </thead>
- <tbody>
- <tr>
- <td>{translate('my_profile.sonarcloud_feature_notifications.description')}</td>
- <td className="text-center">
- <Checkbox
- checked={!this.props.notificationsOptOut}
- onCheck={this.handleCheckOptOut}
- />
- </td>
- </tr>
- </tbody>
- </table>
- </div>
- </section>
- );
- }
-}
-
-const mapStateToProps = (state: Store) => {
- const notificationsOptOut = getCurrentUserSetting(state, 'notifications.optOut') === 'true';
-
- return {
- notificationsOptOut
- };
-};
-
-const mapDispatchToProps = {
- setCurrentUserSetting
-};
-
-export default connect(mapStateToProps, mapDispatchToProps)(SonarCloudNotifications);
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2022 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 { shallow } from 'enzyme';
-import * as React from 'react';
-import { SonarCloudNotifications } from '../SonarCloudNotifications';
-
-it('should match snapshot', () => {
- expect(shallowRender()).toMatchSnapshot();
-});
-
-function shallowRender(props: Partial<SonarCloudNotifications['props']> = {}) {
- return shallow(
- <SonarCloudNotifications
- notificationsOptOut={true}
- setCurrentUserSetting={jest.fn()}
- {...props}
- />
- );
-}
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should match snapshot 1`] = `
-<Fragment>
- <section
- className="boxed-group"
+<section
+ className="boxed-group"
+>
+ <h2>
+ my_profile.overall_notifications.title
+ </h2>
+ <div
+ className="boxed-group-inner"
>
- <h2>
- my_profile.overall_notifications.title
- </h2>
- <div
- className="boxed-group-inner"
+ <table
+ className="data zebra"
>
- <table
- className="data zebra"
- >
- <thead>
- <tr>
- <th />
- <th
- className="text-center"
- key="channel1"
- >
- <h4>
- notification.channel.channel1
- </h4>
- </th>
- <th
- className="text-center"
- key="channel2"
- >
- <h4>
- notification.channel.channel2
- </h4>
- </th>
- </tr>
- </thead>
- <NotificationsList
- channels={
- Array [
- "channel1",
- "channel2",
- ]
- }
- checkboxId={[Function]}
- notifications={
- Array [
- Object {
- "channel": "channel1",
- "type": "type1",
- },
- Object {
- "channel": "channel1",
- "type": "type2",
- },
- Object {
- "channel": "channel2",
- "type": "type2",
- },
- ]
- }
- onAdd={[MockFunction]}
- onRemove={[MockFunction]}
- types={
- Array [
- "type1",
- "type2",
- ]
- }
- />
- </table>
- </div>
- </section>
-</Fragment>
+ <thead>
+ <tr>
+ <th />
+ <th
+ className="text-center"
+ key="channel1"
+ >
+ <h4>
+ notification.channel.channel1
+ </h4>
+ </th>
+ <th
+ className="text-center"
+ key="channel2"
+ >
+ <h4>
+ notification.channel.channel2
+ </h4>
+ </th>
+ </tr>
+ </thead>
+ <NotificationsList
+ channels={
+ Array [
+ "channel1",
+ "channel2",
+ ]
+ }
+ checkboxId={[Function]}
+ notifications={
+ Array [
+ Object {
+ "channel": "channel1",
+ "type": "type1",
+ },
+ Object {
+ "channel": "channel1",
+ "type": "type2",
+ },
+ Object {
+ "channel": "channel2",
+ "type": "type2",
+ },
+ ]
+ }
+ onAdd={[MockFunction]}
+ onRemove={[MockFunction]}
+ types={
+ Array [
+ "type1",
+ "type2",
+ ]
+ }
+ />
+ </table>
+ </div>
+</section>
`;
exports[`should show SonarCloud options if in SC context 1`] = `
-<Fragment>
- <section
- className="boxed-group"
+<section
+ className="boxed-group"
+>
+ <h2>
+ my_profile.overall_notifications.title
+ </h2>
+ <div
+ className="boxed-group-inner"
>
- <h2>
- my_profile.overall_notifications.title
- </h2>
- <div
- className="boxed-group-inner"
+ <table
+ className="data zebra"
>
- <table
- className="data zebra"
- >
- <thead>
- <tr>
- <th />
- <th
- className="text-center"
- key="channel1"
- >
- <h4>
- notification.channel.channel1
- </h4>
- </th>
- <th
- className="text-center"
- key="channel2"
- >
- <h4>
- notification.channel.channel2
- </h4>
- </th>
- </tr>
- </thead>
- <NotificationsList
- channels={
- Array [
- "channel1",
- "channel2",
- ]
- }
- checkboxId={[Function]}
- notifications={
- Array [
- Object {
- "channel": "channel1",
- "type": "type1",
- },
- Object {
- "channel": "channel1",
- "type": "type2",
- },
- Object {
- "channel": "channel2",
- "type": "type2",
- },
- ]
- }
- onAdd={[MockFunction]}
- onRemove={[MockFunction]}
- types={
- Array [
- "type1",
- "type2",
- ]
- }
- />
- </table>
- </div>
- </section>
- <Connect(SonarCloudNotifications) />
-</Fragment>
+ <thead>
+ <tr>
+ <th />
+ <th
+ className="text-center"
+ key="channel1"
+ >
+ <h4>
+ notification.channel.channel1
+ </h4>
+ </th>
+ <th
+ className="text-center"
+ key="channel2"
+ >
+ <h4>
+ notification.channel.channel2
+ </h4>
+ </th>
+ </tr>
+ </thead>
+ <NotificationsList
+ channels={
+ Array [
+ "channel1",
+ "channel2",
+ ]
+ }
+ checkboxId={[Function]}
+ notifications={
+ Array [
+ Object {
+ "channel": "channel1",
+ "type": "type1",
+ },
+ Object {
+ "channel": "channel1",
+ "type": "type2",
+ },
+ Object {
+ "channel": "channel2",
+ "type": "type2",
+ },
+ ]
+ }
+ onAdd={[MockFunction]}
+ onRemove={[MockFunction]}
+ types={
+ Array [
+ "type1",
+ "type2",
+ ]
+ }
+ />
+ </table>
+ </div>
+</section>
`;
+++ /dev/null
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should match snapshot 1`] = `
-<section
- className="boxed-group"
->
- <h2>
- my_profile.sonarcloud_feature_notifications.title
- </h2>
- <div
- className="boxed-group-inner"
- >
- <table
- className="data zebra"
- >
- <thead>
- <tr>
- <th />
- <th
- className="text-center"
- >
- <h4>
- activate
- </h4>
- </th>
- </tr>
- </thead>
- <tbody>
- <tr>
- <td>
- my_profile.sonarcloud_feature_notifications.description
- </td>
- <td
- className="text-center"
- >
- <Checkbox
- checked={false}
- onCheck={[Function]}
- thirdState={false}
- />
- </td>
- </tr>
- </tbody>
- </table>
- </div>
-</section>
-`;
import HelpTooltip from '../../../components/controls/HelpTooltip';
import { whenLoggedIn } from '../../../components/hoc/whenLoggedIn';
import { translate } from '../../../helpers/l10n';
-import { LoggedInUser } from '../../../types/types';
+import { LoggedInUser } from '../../../types/users';
import UserExternalIdentity from './UserExternalIdentity';
export interface ProfileProps {
import { colors } from '../../../app/theme';
import { getTextColor } from '../../../helpers/colors';
import { getBaseUrl } from '../../../helpers/system';
-import { IdentityProvider, LoggedInUser } from '../../../types/types';
+import { IdentityProvider } from '../../../types/types';
+import { LoggedInUser } from '../../../types/users';
export interface UserExternalIdentityProps {
user: LoggedInUser;
import { keyBy } from 'lodash';
import * as React from 'react';
import { Helmet } from 'react-helmet-async';
-import { connect } from 'react-redux';
import { withRouter, WithRouterProps } from 'react-router';
import { Profile, searchQualityProfiles } from '../../../api/quality-profiles';
import { getRulesApp, searchRules } from '../../../api/rules';
import A11ySkipTarget from '../../../app/components/a11y/A11ySkipTarget';
+import withCurrentUserContext from '../../../app/components/current-user/withCurrentUserContext';
import Suggestions from '../../../app/components/embed-docs-modal/Suggestions';
import FiltersHeader from '../../../components/common/FiltersHeader';
import ScreenPositionHelper from '../../../components/common/ScreenPositionHelper';
removeWhitePageClass
} from '../../../helpers/pages';
import { scrollToElement } from '../../../helpers/scrolling';
-import { isLoggedIn } from '../../../helpers/users';
-import { getCurrentUser, Store } from '../../../store/rootReducer';
import { SecurityStandard } from '../../../types/security';
-import { CurrentUser, Dict, Paging, RawQuery, Rule, RuleActivation } from '../../../types/types';
+import { Dict, Paging, RawQuery, Rule, RuleActivation } from '../../../types/types';
+import { CurrentUser, isLoggedIn } from '../../../types/users';
import {
shouldOpenSonarSourceSecurityFacet,
shouldOpenStandardsChildFacet,
return facets;
}
-const mapStateToProps = (state: Store) => ({
- currentUser: getCurrentUser(state)
-});
-
-export default withRouter(connect(mapStateToProps)(App));
+export default withRouter(withCurrentUserContext(App));
import { getProjectUrl } from '../../../helpers/urls';
import { AlmKeys, AlmSettingsInstance } from '../../../types/alm-settings';
import { AppState } from '../../../types/appstate';
-import { LoggedInUser } from '../../../types/types';
+import { LoggedInUser } from '../../../types/users';
import AlmBindingDefinitionForm from '../../settings/components/almIntegration/AlmBindingDefinitionForm';
import AzureProjectCreate from './AzureProjectCreate';
import BitbucketCloudProjectCreate from './BitbucketCloudProjectCreate';
*/
import { connect } from 'react-redux';
import { searchIssues } from '../../../api/issues';
+import withCurrentUserContext from '../../../app/components/current-user/withCurrentUserContext';
import { withRouter } from '../../../components/hoc/withRouter';
import { lazyLoadComponent } from '../../../components/lazyLoadComponent';
import { parseIssueFromResponse } from '../../../helpers/issues';
import { fetchBranchStatus } from '../../../store/rootActions';
-import { getCurrentUser, Store } from '../../../store/rootReducer';
+import { Store } from '../../../store/rootReducer';
import { FetchIssuesPromise } from '../../../types/issues';
import { RawQuery } from '../../../types/types';
const IssuesAppContainer = lazyLoadComponent(() => import('./IssuesApp'), 'IssuesAppContainer');
-const mapStateToProps = (state: Store) => ({
- currentUser: getCurrentUser(state),
- fetchIssues
-});
-
const fetchIssues = (query: RawQuery) => {
return searchIssues({
...query,
});
};
+const mapStateToProps = (_state: Store) => ({
+ fetchIssues
+});
+
const mapDispatchToProps = { fetchBranchStatus };
-export default withRouter(connect(mapStateToProps, mapDispatchToProps)(IssuesAppContainer));
+export default withRouter(
+ withCurrentUserContext(connect(mapStateToProps, mapDispatchToProps)(IssuesAppContainer))
+);
import { Alert } from '../../../components/ui/Alert';
import Avatar from '../../../components/ui/Avatar';
import { translate, translateWithParameters } from '../../../helpers/l10n';
-import { isLoggedIn, isUserActive } from '../../../helpers/users';
-import { Component, CurrentUser, Dict, Issue, IssueType, Paging } from '../../../types/types';
+import { Component, Dict, Issue, IssueType, Paging } from '../../../types/types';
+import { CurrentUser, isLoggedIn, isUserActive } from '../../../types/users';
import { searchAssignees } from '../utils';
interface AssigneeOption {
ReferencedRule
} from '../../../types/issues';
import { SecurityStandard } from '../../../types/security';
-import {
- Component,
- CurrentUser,
- Dict,
- Issue,
- Paging,
- RawQuery,
- UserBase
-} from '../../../types/types';
+import { Component, Dict, Issue, Paging, RawQuery } from '../../../types/types';
+import { CurrentUser, UserBase } from '../../../types/users';
import * as actions from '../actions';
import ConciseIssuesList from '../conciseIssuesList/ConciseIssuesList';
import ConciseIssuesListHeader from '../conciseIssuesList/ConciseIssuesListHeader';
*/
import { connect } from 'react-redux';
import { searchIssues } from '../../../../api/issues';
-import { mockCurrentUser } from '../../../../helpers/testMocks';
import { fetchBranchStatus } from '../../../../store/rootActions';
import '../AppContainer';
parseIssueFromResponse: jest.fn(() => 'parsedIssue')
}));
-jest.mock('../../../../store/rootReducer', () => {
- const { mockCurrentUser } = jest.requireActual('../../../../helpers/testMocks');
- return {
- getCurrentUser: jest.fn(() => mockCurrentUser())
- };
-});
-
describe('redux', () => {
it('should correctly map state and dispatch props', async () => {
const [mapStateToProps, mapDispatchToProps] = (connect as jest.Mock).mock.calls[0];
- const { currentUser, fetchIssues } = mapStateToProps({});
+ const { fetchIssues } = mapStateToProps({});
- expect(currentUser).toEqual(mockCurrentUser());
expect(mapDispatchToProps).toEqual(expect.objectContaining({ fetchBranchStatus }));
const result = await fetchIssues({ foo: 'bar' });
effort={125}
/>
</div>
- <Connect(HomePageSelect)
+ <withCurrentUserContext(HomePageSelect)
className="huge-spacer-left"
currentPage={
Object {
import Avatar from '../../../components/ui/Avatar';
import { translate, translateWithParameters } from '../../../helpers/l10n';
import { highlightTerm } from '../../../helpers/search';
-import { isUserActive } from '../../../helpers/users';
import { Facet } from '../../../types/issues';
-import { Dict, UserBase } from '../../../types/types';
+import { Dict } from '../../../types/types';
+import { isUserActive, UserBase } from '../../../types/users';
import { Query, searchAssignees } from '../utils';
interface Props {
ReferencedRule
} from '../../../types/issues';
import { GlobalSettingKeys } from '../../../types/settings';
-import { Component, Dict, UserBase } from '../../../types/types';
+import { Component, Dict } from '../../../types/types';
+import { UserBase } from '../../../types/users';
import { Query } from '../utils';
import AssigneeFacet from './AssigneeFacet';
import AuthorFacet from './AuthorFacet';
import { isDefined } from '../../helpers/types';
import { Facet, RawFacet } from '../../types/issues';
import { SecurityStandard, StandardType } from '../../types/security';
-import { Dict, Issue, Paging, RawQuery, UserBase } from '../../types/types';
+import { Dict, Issue, Paging, RawQuery } from '../../types/types';
+import { UserBase } from '../../types/users';
export interface Query {
assigned: boolean;
import * as React from 'react';
import { FormattedMessage } from 'react-intl';
import { Link } from 'react-router';
-import { withCurrentUser } from '../../../components/hoc/withCurrentUser';
+import withCurrentUserContext from '../../../app/components/current-user/withCurrentUserContext';
import DismissableAlert from '../../../components/ui/DismissableAlert';
import { translate } from '../../../helpers/l10n';
-import { isLoggedIn } from '../../../helpers/users';
import { ProjectAlmBindingResponse } from '../../../types/alm-settings';
import { ComponentQualifier } from '../../../types/component';
-import { Component, CurrentUser } from '../../../types/types';
+import { Component } from '../../../types/types';
+import { CurrentUser, isLoggedIn } from '../../../types/users';
import { PULL_REQUEST_DECORATION_BINDING_CATEGORY } from '../../settings/components/AdditionalCategoryKeys';
export interface FirstAnalysisNextStepsNotifProps {
);
}
-export default withCurrentUser(FirstAnalysisNextStepsNotif);
+export default withCurrentUserContext(FirstAnalysisNextStepsNotif);
exports[`should render correctly: default 1`] = `
<Fragment>
- <Connect(withCurrentUser(FirstAnalysisNextStepsNotif))
+ <withCurrentUserContext(FirstAnalysisNextStepsNotif)
component={
Object {
"breadcrumbs": Array [],
exports[`should render correctly: empty project 1`] = `
<Fragment>
- <Connect(withCurrentUser(FirstAnalysisNextStepsNotif))
+ <withCurrentUserContext(FirstAnalysisNextStepsNotif)
component={
Object {
"breadcrumbs": Array [],
exports[`should render correctly: loading 1`] = `
<Fragment>
- <Connect(withCurrentUser(FirstAnalysisNextStepsNotif))
+ <withCurrentUserContext(FirstAnalysisNextStepsNotif)
component={
Object {
"breadcrumbs": Array [],
>
overview.measures
</h2>
- <Connect(withCurrentUser(withAppStateContext(ComponentReportActions)))
+ <withCurrentUserContext(withAppStateContext(ComponentReportActions))
branch={
Object {
"analysisDate": "2018-01-01",
>
overview.measures
</h2>
- <Connect(withCurrentUser(withAppStateContext(ComponentReportActions)))
+ <withCurrentUserContext(withAppStateContext(ComponentReportActions))
branch={
Object {
"analysisDate": "2018-01-01",
>
overview.measures
</h2>
- <Connect(withCurrentUser(withAppStateContext(ComponentReportActions)))
+ <withCurrentUserContext(withAppStateContext(ComponentReportActions))
branch={
Object {
"analysisDate": "2018-01-01",
>
overview.measures
</h2>
- <Connect(withCurrentUser(withAppStateContext(ComponentReportActions)))
+ <withCurrentUserContext(withAppStateContext(ComponentReportActions))
branch={
Object {
"analysisDate": "2018-01-01",
>
overview.measures
</h2>
- <Connect(withCurrentUser(withAppStateContext(ComponentReportActions)))
+ <withCurrentUserContext(withAppStateContext(ComponentReportActions))
branch={
Object {
"analysisDate": "2018-01-01",
>
overview.measures
</h2>
- <Connect(withCurrentUser(withAppStateContext(ComponentReportActions)))
+ <withCurrentUserContext(withAppStateContext(ComponentReportActions))
branch={
Object {
"analysisDate": "2018-01-01",
>
overview.measures
</h2>
- <Connect(withCurrentUser(withAppStateContext(ComponentReportActions)))
+ <withCurrentUserContext(withAppStateContext(ComponentReportActions))
branch={
Object {
"analysisDate": "2018-01-01",
>
overview.measures
</h2>
- <Connect(withCurrentUser(withAppStateContext(ComponentReportActions)))
+ <withCurrentUserContext(withAppStateContext(ComponentReportActions))
branch={
Object {
"analysisDate": "2018-01-01",
>
overview.measures
</h2>
- <Connect(withCurrentUser(withAppStateContext(ComponentReportActions)))
+ <withCurrentUserContext(withAppStateContext(ComponentReportActions))
branch={
Object {
"analysisDate": "2018-01-01",
/>
</div>
</div>
- <Connect(withCurrentUser(SonarLintPromotion))
+ <withCurrentUserContext(SonarLintPromotion)
qgConditions={
Array [
Object {
/>
</div>
</div>
- <Connect(withCurrentUser(SonarLintPromotion))
+ <withCurrentUserContext(SonarLintPromotion)
qgConditions={
Array [
Object {
/>
</div>
</div>
- <Connect(withCurrentUser(SonarLintPromotion))
+ <withCurrentUserContext(SonarLintPromotion)
qgConditions={
Array [
Object {
</span>
</div>
</div>
- <Connect(withCurrentUser(SonarLintPromotion))
+ <withCurrentUserContext(SonarLintPromotion)
qgConditions={Array []}
/>
</div>
/>
</div>
</div>
- <Connect(withCurrentUser(SonarLintPromotion))
+ <withCurrentUserContext(SonarLintPromotion)
qgConditions={
Array [
Object {
*/
import * as React from 'react';
import { FormattedMessage } from 'react-intl';
-import { connect } from 'react-redux';
+import withCurrentUserContext from '../../../app/components/current-user/withCurrentUserContext';
import TutorialSelection from '../../../components/tutorials/TutorialSelection';
import { Alert } from '../../../components/ui/Alert';
import { getBranchLikeDisplayName, isBranch, isMainBranch } from '../../../helpers/branch-like';
import { translate } from '../../../helpers/l10n';
-import { isLoggedIn } from '../../../helpers/users';
-import { getCurrentUser, Store } from '../../../store/rootReducer';
import { ProjectAlmBindingResponse } from '../../../types/alm-settings';
import { BranchLike } from '../../../types/branch-like';
import { ComponentQualifier } from '../../../types/component';
-import { Component, CurrentUser } from '../../../types/types';
+import { Component } from '../../../types/types';
+import { CurrentUser, isLoggedIn } from '../../../types/users';
export interface EmptyOverviewProps {
branchLike?: BranchLike;
);
}
-const mapStateToProps = (state: Store) => ({
- currentUser: getCurrentUser(state)
-});
-
-export default connect(mapStateToProps)(EmptyOverview);
+export default withCurrentUserContext(EmptyOverview);
*/
import * as React from 'react';
import { FormattedMessage } from 'react-intl';
-import { withCurrentUser } from '../../../components/hoc/withCurrentUser';
+import withCurrentUserContext from '../../../app/components/current-user/withCurrentUserContext';
import SonarLintIcon from '../../../components/icons/SonarLintIcon';
import { translate } from '../../../helpers/l10n';
import { MetricKey } from '../../../types/metrics';
import { QualityGateStatusCondition } from '../../../types/quality-gates';
-import { CurrentUser } from '../../../types/types';
+import { CurrentUser } from '../../../types/users';
export interface SonarLintPromotionProps {
currentUser: CurrentUser;
);
}
-export default withCurrentUser(SonarLintPromotion);
+export default withCurrentUserContext(SonarLintPromotion);
}
level="ERROR"
/>
- <Connect(withCurrentUser(SonarLintPromotion))
+ <withCurrentUserContext(SonarLintPromotion)
qgConditions={
Array [
Object {
}
level="OK"
/>
- <Connect(withCurrentUser(SonarLintPromotion))
+ <withCurrentUserContext(SonarLintPromotion)
qgConditions={Array []}
/>
</div>
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2022 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 { connect } from 'react-redux';
-import { getCurrentUser, Store } from '../../../../store/rootReducer';
-import App from './App';
-
-const mapStateToProps = (state: Store) => ({
- currentUser: getCurrentUser(state)
-});
-
-export default connect(mapStateToProps)(App);
export const projectPermissionsRoutes = [
{
- indexRoute: { component: lazyLoadComponent(() => import('./project/components/AppContainer')) }
+ indexRoute: { component: lazyLoadComponent(() => import('./project/components/App')) }
}
];
import { Helmet } from 'react-helmet-async';
import A11ySkipTarget from '../../../app/components/a11y/A11ySkipTarget';
import withAppStateContext from '../../../app/components/app-state/withAppStateContext';
+import withCurrentUserContext from '../../../app/components/current-user/withCurrentUserContext';
import Suggestions from '../../../app/components/embed-docs-modal/Suggestions';
import ScreenPositionHelper from '../../../components/common/ScreenPositionHelper';
import ListFooter from '../../../components/controls/ListFooter';
import { translate } from '../../../helpers/l10n';
import { addSideBarClass, removeSideBarClass } from '../../../helpers/pages';
import { get, save } from '../../../helpers/storage';
-import { isLoggedIn } from '../../../helpers/users';
import { AppState } from '../../../types/appstate';
import { ComponentQualifier } from '../../../types/component';
-import { CurrentUser, RawQuery } from '../../../types/types';
+import { RawQuery } from '../../../types/types';
+import { CurrentUser, isLoggedIn } from '../../../types/users';
import { hasFilterParams, hasViewParams, parseUrlQuery, Query } from '../query';
import '../styles.css';
import { Facets, Project } from '../types';
}
}
-export default withRouter(withAppStateContext(AllProjects));
+export default withRouter(withCurrentUserContext(withAppStateContext(AllProjects)));
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-import { connect } from 'react-redux';
import { lazyLoadComponent } from '../../../components/lazyLoadComponent';
-import { getCurrentUser, Store } from '../../../store/rootReducer';
-const stateToProps = (state: Store) => ({
- currentUser: getCurrentUser(state)
-});
-
-export default connect(stateToProps)(lazyLoadComponent(() => import('./AllProjects')));
+export default lazyLoadComponent(() => import('./AllProjects'));
import * as React from 'react';
import { getComponentNavigation } from '../../../api/nav';
import withAppStateContext from '../../../app/components/app-state/withAppStateContext';
+import withCurrentUserContext from '../../../app/components/current-user/withCurrentUserContext';
import CreateApplicationForm from '../../../app/components/extensions/CreateApplicationForm';
import { Button } from '../../../components/controls/buttons';
-import { withCurrentUser } from '../../../components/hoc/withCurrentUser';
import { Router, withRouter } from '../../../components/hoc/withRouter';
import { translate } from '../../../helpers/l10n';
import { getComponentAdminUrl, getComponentOverviewUrl } from '../../../helpers/urls';
import { AppState } from '../../../types/appstate';
import { ComponentQualifier } from '../../../types/component';
import { Permissions } from '../../../types/permissions';
-import { LoggedInUser } from '../../../types/types';
+import { LoggedInUser } from '../../../types/users';
export interface ApplicationCreationProps {
appState: AppState;
);
}
-export default withCurrentUser(withRouter(withAppStateContext(ApplicationCreation)));
+export default withCurrentUserContext(withRouter(withAppStateContext(ApplicationCreation)));
*/
import * as React from 'react';
import { searchProjects } from '../../../api/components';
-import { withCurrentUser } from '../../../components/hoc/withCurrentUser';
+import withCurrentUserContext from '../../../app/components/current-user/withCurrentUserContext';
import { Location, Router, withRouter } from '../../../components/hoc/withRouter';
import { get } from '../../../helpers/storage';
-import { hasGlobalPermission, isLoggedIn } from '../../../helpers/users';
-import { CurrentUser } from '../../../types/types';
+import { hasGlobalPermission } from '../../../helpers/users';
+import { CurrentUser, isLoggedIn } from '../../../types/users';
import { PROJECTS_ALL, PROJECTS_DEFAULT_FILTER, PROJECTS_FAVORITE } from '../utils';
import AllProjectsContainer from './AllProjectsContainer';
}
}
-export default withCurrentUser(withRouter(DefaultPageSelector));
+export default withCurrentUserContext(withRouter(DefaultPageSelector));
import { Button } from '../../../components/controls/buttons';
import { withRouter } from '../../../components/hoc/withRouter';
import { translate } from '../../../helpers/l10n';
-import { hasGlobalPermission, isLoggedIn } from '../../../helpers/users';
+import { hasGlobalPermission } from '../../../helpers/users';
import { Permissions } from '../../../types/permissions';
-import { CurrentUser } from '../../../types/types';
+import { CurrentUser, isLoggedIn } from '../../../types/users';
export interface EmptyInstanceProps {
currentUser: CurrentUser;
*/
import * as React from 'react';
import { IndexLink, Link } from 'react-router';
+import withCurrentUserContext from '../../../app/components/current-user/withCurrentUserContext';
import { translate } from '../../../helpers/l10n';
import { save } from '../../../helpers/storage';
-import { isLoggedIn } from '../../../helpers/users';
-import { CurrentUser, RawQuery } from '../../../types/types';
+import { RawQuery } from '../../../types/types';
+import { CurrentUser, isLoggedIn } from '../../../types/users';
import { PROJECTS_ALL, PROJECTS_DEFAULT_FILTER, PROJECTS_FAVORITE } from '../utils';
interface Props {
query?: RawQuery;
}
-export default class FavoriteFilter extends React.PureComponent<Props> {
+export class FavoriteFilter extends React.PureComponent<Props> {
handleSaveFavorite = () => {
save(PROJECTS_DEFAULT_FILTER, PROJECTS_FAVORITE);
};
);
}
}
+
+export default withCurrentUserContext(FavoriteFilter);
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2022 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 { connect } from 'react-redux';
-import { getCurrentUser, Store } from '../../../store/rootReducer';
-import FavoriteFilter from './FavoriteFilter';
-
-function mapStateToProps(state: Store) {
- return { currentUser: getCurrentUser(state) };
-}
-
-export default connect(mapStateToProps)(FavoriteFilter);
import * as React from 'react';
import HomePageSelect from '../../../components/controls/HomePageSelect';
import { translate } from '../../../helpers/l10n';
-import { isLoggedIn } from '../../../helpers/users';
-import { CurrentUser, RawQuery } from '../../../types/types';
+import { RawQuery } from '../../../types/types';
+import { CurrentUser, isLoggedIn } from '../../../types/users';
import SearchFilterContainer from '../filters/SearchFilterContainer';
import ApplicationCreation from './ApplicationCreation';
import PerspectiveSelect from './PerspectiveSelect';
import { hasFilterParams } from '../query';
import { Facets } from '../types';
import ClearAll from './ClearAll';
-import FavoriteFilterContainer from './FavoriteFilterContainer';
+import FavoriteFilter from './FavoriteFilter';
export interface PageSidebarProps {
applicationsEnabled: boolean;
return (
<div>
- <FavoriteFilterContainer query={linkQuery} />
+ <FavoriteFilter query={linkQuery} />
<div className="projects-facets-header clearfix">
{isFiltered && <ClearAll onClearAll={props.onClearAll} />}
import * as React from 'react';
import { Link } from 'react-router';
import { getAlmSettings } from '../../../api/alm-settings';
+import withCurrentUserContext from '../../../app/components/current-user/withCurrentUserContext';
import { Button } from '../../../components/controls/buttons';
import Dropdown from '../../../components/controls/Dropdown';
-import { withCurrentUser } from '../../../components/hoc/withCurrentUser';
import DropdownIcon from '../../../components/icons/DropdownIcon';
import EllipsisIcon from '../../../components/icons/EllipsisIcon';
import { IMPORT_COMPATIBLE_ALMS, IMPORT_COMPATIBLE_ALM_COUNT } from '../../../helpers/constants';
import { hasGlobalPermission } from '../../../helpers/users';
import { AlmKeys, AlmSettingsInstance } from '../../../types/alm-settings';
import { Permissions } from '../../../types/permissions';
-import { LoggedInUser } from '../../../types/types';
+import { LoggedInUser } from '../../../types/users';
import ProjectCreationMenuItem from './ProjectCreationMenuItem';
interface Props {
}
}
-export default withCurrentUser(ProjectCreationMenu);
+export default withCurrentUserContext(ProjectCreationMenu);
import { WindowScroller } from 'react-virtualized/dist/commonjs/WindowScroller';
import EmptySearch from '../../../components/common/EmptySearch';
import { translate } from '../../../helpers/l10n';
-import { CurrentUser } from '../../../types/types';
+import { CurrentUser } from '../../../types/users';
import { Query } from '../query';
import { Project } from '../types';
import EmptyFavoriteSearch from './EmptyFavoriteSearch';
} from '../../../../helpers/testMocks';
import { waitAndUpdate } from '../../../../helpers/testUtils';
import { hasGlobalPermission } from '../../../../helpers/users';
-import { CurrentUser } from '../../../../types/types';
+import { CurrentUser } from '../../../../types/users';
import { DefaultPageSelector } from '../DefaultPageSelector';
jest.mock(
import * as React from 'react';
import { save } from '../../../../helpers/storage';
import { click } from '../../../../helpers/testUtils';
-import FavoriteFilter from '../FavoriteFilter';
+import { FavoriteFilter } from '../FavoriteFilter';
jest.mock('../../../../helpers/storage', () => ({
save: jest.fn()
<div
className="display-flex-center"
>
- <Connect(withCurrentUser(ProjectCreationMenu))
+ <withCurrentUserContext(ProjectCreationMenu)
className="little-spacer-right"
/>
- <Connect(withCurrentUser(withRouter(withAppStateContext(ApplicationCreation))))
+ <withCurrentUserContext(withRouter(withAppStateContext(ApplicationCreation)))
className="little-spacer-right"
/>
- <Connect(HomePageSelect)
+ <withCurrentUserContext(HomePageSelect)
className="spacer-left little-spacer-right"
currentPage={
Object {
<div
className="display-flex-center"
>
- <Connect(withCurrentUser(ProjectCreationMenu))
+ <withCurrentUserContext(ProjectCreationMenu)
className="little-spacer-right"
/>
- <Connect(withCurrentUser(withRouter(withAppStateContext(ApplicationCreation))))
+ <withCurrentUserContext(withRouter(withAppStateContext(ApplicationCreation)))
className="little-spacer-right"
/>
- <Connect(HomePageSelect)
+ <withCurrentUserContext(HomePageSelect)
className="spacer-left little-spacer-right"
currentPage={
Object {
exports[`should render \`leak\` view correctly 1`] = `
<div>
- <Connect(FavoriteFilter)
+ <withCurrentUserContext(FavoriteFilter)
query={
Object {
"view": "leak",
exports[`should render \`leak\` view correctly with no applications 1`] = `
<div>
- <Connect(FavoriteFilter)
+ <withCurrentUserContext(FavoriteFilter)
query={
Object {
"view": "leak",
exports[`should render correctly 1`] = `
<div>
- <Connect(FavoriteFilter) />
+ <withCurrentUserContext(FavoriteFilter) />
<div
className="projects-facets-header clearfix"
>
exports[`should render correctly with no applications 1`] = `
<div>
- <Connect(FavoriteFilter) />
+ <withCurrentUserContext(FavoriteFilter) />
<div
className="projects-facets-header clearfix"
>
import SizeRating from '../../../../components/ui/SizeRating';
import { translate, translateWithParameters } from '../../../../helpers/l10n';
import { getProjectUrl } from '../../../../helpers/urls';
-import { isLoggedIn } from '../../../../helpers/users';
import { ComponentQualifier } from '../../../../types/component';
import { MetricKey } from '../../../../types/metrics';
-import { CurrentUser } from '../../../../types/types';
+import { CurrentUser, isLoggedIn } from '../../../../types/users';
import { Project } from '../../types';
import './ProjectCard.css';
import ProjectCardLanguages from './ProjectCardLanguages';
import TagsList from '../../../../../components/tags/TagsList';
import { mockCurrentUser, mockLoggedInUser } from '../../../../../helpers/testMocks';
import { ComponentQualifier } from '../../../../../types/component';
-import { CurrentUser } from '../../../../../types/types';
+import { CurrentUser } from '../../../../../types/users';
import { Project } from '../../../types';
import ProjectCard from '../ProjectCard';
import ProjectCardQualityGate from '../ProjectCardQualityGate';
import { debounce, uniq, without } from 'lodash';
import * as React from 'react';
import { Helmet } from 'react-helmet-async';
-import { connect } from 'react-redux';
import { getComponents, Project } from '../../api/components';
import { changeProjectDefaultVisibility } from '../../api/permissions';
import { getValues } from '../../api/settings';
+import withCurrentUserContext from '../../app/components/current-user/withCurrentUserContext';
import Suggestions from '../../app/components/embed-docs-modal/Suggestions';
import ListFooter from '../../components/controls/ListFooter';
import { toShortNotSoISOString } from '../../helpers/dates';
import { translate } from '../../helpers/l10n';
import { hasGlobalPermission } from '../../helpers/users';
-import { getCurrentUser, Store } from '../../store/rootReducer';
import { Permissions } from '../../types/permissions';
import { SettingsKey } from '../../types/settings';
-import { LoggedInUser, Visibility } from '../../types/types';
+import { Visibility } from '../../types/types';
+import { LoggedInUser } from '../../types/users';
import CreateProjectForm from './CreateProjectForm';
import Header from './Header';
import Projects from './Projects';
}
}
-const mapStateToProps = (state: Store) => ({
- currentUser: getCurrentUser(state) as LoggedInUser
-});
-
-export default connect(mapStateToProps)(App);
+export default withCurrentUserContext(App);
import QualifierIcon from '../../components/icons/QualifierIcon';
import DateFormatter from '../../components/intl/DateFormatter';
import { getComponentOverviewUrl } from '../../helpers/urls';
-import { LoggedInUser } from '../../types/types';
+import { LoggedInUser } from '../../types/users';
import './ProjectRow.css';
import ProjectRowActions from './ProjectRowActions';
import DeferredSpinner from '../../components/ui/DeferredSpinner';
import { translate } from '../../helpers/l10n';
import { getComponentPermissionsUrl } from '../../helpers/urls';
-import { LoggedInUser } from '../../types/types';
+import { LoggedInUser } from '../../types/users';
import ApplyTemplate from '../permissions/project/components/ApplyTemplate';
import RestoreAccessModal from './RestoreAccessModal';
import * as React from 'react';
import { Project } from '../../api/components';
import { translate } from '../../helpers/l10n';
-import { LoggedInUser } from '../../types/types';
+import { LoggedInUser } from '../../types/users';
import ProjectRow from './ProjectRow';
interface Props {
import { ResetButtonLink, SubmitButton } from '../../components/controls/buttons';
import Modal from '../../components/controls/Modal';
import { translate } from '../../helpers/l10n';
-import { LoggedInUser } from '../../types/types';
+import { LoggedInUser } from '../../types/users';
interface Props {
currentUser: Pick<LoggedInUser, 'login'>;
import GroupIcon from '../../../components/icons/GroupIcon';
import Avatar from '../../../components/ui/Avatar';
import { Group, isUser } from '../../../types/quality-gates';
-import { UserBase } from '../../../types/types';
+import { UserBase } from '../../../types/users';
export interface PermissionItemProps {
onClickDelete: (item: UserBase | Group) => void;
searchUsers
} from '../../../api/quality-gates';
import { Group, isUser, SearchPermissionsParameters } from '../../../types/quality-gates';
-import { QualityGate, UserBase } from '../../../types/types';
+import { QualityGate } from '../../../types/types';
+import { UserBase } from '../../../types/users';
import QualityGatePermissionsRenderer from './QualityGatePermissionsRenderer';
interface Props {
import * as React from 'react';
import { searchGroups, searchUsers } from '../../../api/quality-gates';
import { Group, SearchPermissionsParameters } from '../../../types/quality-gates';
-import { QualityGate, UserBase } from '../../../types/types';
+import { QualityGate } from '../../../types/types';
+import { UserBase } from '../../../types/users';
import QualityGatePermissionsAddModalRenderer from './QualityGatePermissionsAddModalRenderer';
interface Props {
import Avatar from '../../../components/ui/Avatar';
import { translate } from '../../../helpers/l10n';
import { Group, isUser } from '../../../types/quality-gates';
-import { UserBase } from '../../../types/types';
+import { UserBase } from '../../../types/users';
export interface QualityGatePermissionsAddModalRendererProps {
onClose: () => void;
import DeferredSpinner from '../../../components/ui/DeferredSpinner';
import { translate } from '../../../helpers/l10n';
import { Group, isUser } from '../../../types/quality-gates';
-import { QualityGate, UserBase } from '../../../types/types';
+import { QualityGate } from '../../../types/types';
+import { UserBase } from '../../../types/users';
import PermissionItem from './PermissionItem';
import QualityGatePermissionsAddModal from './QualityGatePermissionsAddModal';
import { connect } from 'react-redux';
import { getMeasures } from '../../api/measures';
import { getSecurityHotspotList, getSecurityHotspots } from '../../api/security-hotspots';
-import { withCurrentUser } from '../../components/hoc/withCurrentUser';
+import withCurrentUserContext from '../../app/components/current-user/withCurrentUserContext';
import { Router } from '../../components/hoc/withRouter';
import { getLeakValue } from '../../components/measure/utils';
import { getBranchLikeQuery, isPullRequest, isSameBranchLike } from '../../helpers/branch-like';
import { KeyboardCodes, KeyboardKeys } from '../../helpers/keycodes';
import { scrollToElement } from '../../helpers/scrolling';
import { getStandards } from '../../helpers/security-standard';
-import { isLoggedIn } from '../../helpers/users';
import { fetchBranchStatus } from '../../store/rootActions';
import { BranchLike } from '../../types/branch-like';
import { SecurityStandard, Standards } from '../../types/security';
HotspotStatusFilter,
RawHotspot
} from '../../types/security-hotspots';
-import { Component, CurrentUser, Dict } from '../../types/types';
+import { Component, Dict } from '../../types/types';
+import { CurrentUser, isLoggedIn } from '../../types/users';
import SecurityHotspotsAppRenderer from './SecurityHotspotsAppRenderer';
import './styles.css';
import { getLocations, SECURITY_STANDARDS } from './utils';
const mapDispatchToProps = { fetchBranchStatus };
-export default withCurrentUser(connect(null, mapDispatchToProps)(SecurityHotspotsApp));
+export default withCurrentUserContext(connect(null, mapDispatchToProps)(SecurityHotspotsApp));
<A11ySkipTarget
anchor="security_hotspots_main"
/>
- <Connect(withCurrentUser(FilterBar))
+ <withCurrentUserContext(FilterBar)
component={
Object {
"breadcrumbs": Array [],
<A11ySkipTarget
anchor="security_hotspots_main"
/>
- <Connect(withCurrentUser(FilterBar))
+ <withCurrentUserContext(FilterBar)
component={
Object {
"breadcrumbs": Array [],
<A11ySkipTarget
anchor="security_hotspots_main"
/>
- <Connect(withCurrentUser(FilterBar))
+ <withCurrentUserContext(FilterBar)
component={
Object {
"breadcrumbs": Array [],
<A11ySkipTarget
anchor="security_hotspots_main"
/>
- <Connect(withCurrentUser(FilterBar))
+ <withCurrentUserContext(FilterBar)
component={
Object {
"breadcrumbs": Array [],
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
+import withCurrentUserContext from '../../../app/components/current-user/withCurrentUserContext';
import HelpTooltip from '../../../components/controls/HelpTooltip';
import RadioToggle from '../../../components/controls/RadioToggle';
import SelectLegacy from '../../../components/controls/SelectLegacy';
-import { withCurrentUser } from '../../../components/hoc/withCurrentUser';
import Measure from '../../../components/measure/Measure';
import CoverageRating from '../../../components/ui/CoverageRating';
import DeferredSpinner from '../../../components/ui/DeferredSpinner';
import { translate } from '../../../helpers/l10n';
-import { isLoggedIn } from '../../../helpers/users';
import { ComponentQualifier } from '../../../types/component';
import { HotspotFilters, HotspotStatusFilter } from '../../../types/security-hotspots';
-import { Component, CurrentUser } from '../../../types/types';
+import { Component } from '../../../types/types';
+import { CurrentUser, isLoggedIn } from '../../../types/users';
export interface FilterBarProps {
currentUser: CurrentUser;
);
}
-export default withCurrentUser(FilterBar);
+export default withCurrentUserContext(FilterBar);
*/
import classNames from 'classnames';
import * as React from 'react';
+import withCurrentUserContext from '../../../app/components/current-user/withCurrentUserContext';
import { ButtonLink } from '../../../components/controls/buttons';
-import { withCurrentUser } from '../../../components/hoc/withCurrentUser';
import { translate } from '../../../helpers/l10n';
-import { isLoggedIn } from '../../../helpers/users';
import { Hotspot } from '../../../types/security-hotspots';
-import { CurrentUser } from '../../../types/types';
+import { CurrentUser, isLoggedIn } from '../../../types/users';
import './HotspotPrimaryLocationBox.css';
export interface HotspotPrimaryLocationBoxProps {
);
}
-export default withCurrentUser(HotspotPrimaryLocationBox);
+export default withCurrentUserContext(HotspotPrimaryLocationBox);
import FormattingTips from '../../../components/common/FormattingTips';
import { Button } from '../../../components/controls/buttons';
import { translate } from '../../../helpers/l10n';
-import { isLoggedIn } from '../../../helpers/users';
import { Hotspot } from '../../../types/security-hotspots';
-import { CurrentUser } from '../../../types/types';
+import { CurrentUser, isLoggedIn } from '../../../types/users';
import HotspotReviewHistory from './HotspotReviewHistory';
interface Props {
import styled from '@emotion/styled';
import React from 'react';
+import withCurrentUserContext from '../../../app/components/current-user/withCurrentUserContext';
import { colors, sizes } from '../../../app/theme';
import { ClipboardButton, ClipboardIconButton } from '../../../components/controls/clipboard';
-import { withCurrentUser } from '../../../components/hoc/withCurrentUser';
import LinkIcon from '../../../components/icons/LinkIcon';
import QualifierIcon from '../../../components/icons/QualifierIcon';
import { getBranchLikeQuery } from '../../../helpers/branch-like';
import { translate } from '../../../helpers/l10n';
import { collapsedDirFromPath, fileFromPath } from '../../../helpers/path';
import { getComponentSecurityHotspotsUrl, getPathUrlAsString } from '../../../helpers/urls';
-import { isLoggedIn } from '../../../helpers/users';
import { BranchLike } from '../../../types/branch-like';
import { ComponentQualifier } from '../../../types/component';
import { Hotspot } from '../../../types/security-hotspots';
-import { Component, CurrentUser } from '../../../types/types';
+import { Component } from '../../../types/types';
+import { CurrentUser, isLoggedIn } from '../../../types/users';
import HotspotOpenInIdeButton from './HotspotOpenInIdeButton';
export interface HotspotSnippetHeaderProps {
}
`;
-export default withCurrentUser(HotspotSnippetHeader);
+export default withCurrentUserContext(HotspotSnippetHeader);
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
-import { withCurrentUser } from '../../../components/hoc/withCurrentUser';
+import withCurrentUserContext from '../../../app/components/current-user/withCurrentUserContext';
import DeferredSpinner from '../../../components/ui/DeferredSpinner';
import { fillBranchLike } from '../../../helpers/branch-like';
import { Hotspot, HotspotStatusOption } from '../../../types/security-hotspots';
-import { Component, CurrentUser } from '../../../types/types';
+import { Component } from '../../../types/types';
+import { CurrentUser } from '../../../types/users';
import { HotspotHeader } from './HotspotHeader';
import HotspotReviewHistoryAndComments from './HotspotReviewHistoryAndComments';
import HotspotSnippetContainer from './HotspotSnippetContainer';
);
}
-export default withCurrentUser(HotspotViewerRenderer);
+export default withCurrentUserContext(HotspotViewerRenderer);
import { mockHotspot } from '../../../../helpers/mocks/security-hotspots';
import { mockCurrentUser } from '../../../../helpers/testMocks';
import { waitAndUpdate } from '../../../../helpers/testUtils';
-import { isLoggedIn } from '../../../../helpers/users';
+import { isLoggedIn } from '../../../../types/users';
import HotspotReviewHistory from '../HotspotReviewHistory';
import HotspotReviewHistoryAndComments from '../HotspotReviewHistoryAndComments';
editSecurityHotspotComment: jest.fn().mockResolvedValue({})
}));
-jest.mock('../../../../helpers/users', () => ({ isLoggedIn: jest.fn(() => true) }));
+jest.mock('../../../../types/users', () => ({ isLoggedIn: jest.fn(() => true) }));
it('should render correctly', () => {
const wrapper = shallowRender();
<div
className="display-flex-space-between"
>
- <Connect(withCurrentUser(Status))
+ <withCurrentUserContext(Status)
hotspot={
Object {
"assignee": "assignee",
>
assignee:
</div>
- <Connect(withCurrentUser(Assignee))
+ <withCurrentUserContext(Assignee)
hotspot={
Object {
"assignee": "assignee",
>
hotspots.no_associated_lines
</p>
- <Connect(withCurrentUser(HotspotSnippetHeader))
+ <withCurrentUserContext(HotspotSnippetHeader)
branchLike={
Object {
"analysisDate": "2018-01-01",
>
hotspots.no_associated_lines
</p>
- <Connect(withCurrentUser(HotspotSnippetHeader))
+ <withCurrentUserContext(HotspotSnippetHeader)
branchLike={
Object {
"analysisDate": "2018-01-01",
exports[`should render correctly: with sourcelines 1`] = `
<Fragment>
- <Connect(withCurrentUser(HotspotSnippetHeader))
+ <withCurrentUserContext(HotspotSnippetHeader)
branchLike={
Object {
"analysisDate": "2018-01-01",
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should render correctly 1`] = `
-<Connect(withCurrentUser(HotspotViewerRenderer))
+<withCurrentUserContext(HotspotViewerRenderer)
commentTextRef={
Object {
"current": null,
`;
exports[`should render correctly 2`] = `
-<Connect(withCurrentUser(HotspotViewerRenderer))
+<withCurrentUserContext(HotspotViewerRenderer)
commentTextRef={
Object {
"current": null,
*/
import * as React from 'react';
import { assignSecurityHotspot } from '../../../../api/security-hotspots';
+import withCurrentUserContext from '../../../../app/components/current-user/withCurrentUserContext';
import addGlobalSuccessMessage from '../../../../app/utils/addGlobalSuccessMessage';
-import { withCurrentUser } from '../../../../components/hoc/withCurrentUser';
import { translate, translateWithParameters } from '../../../../helpers/l10n';
-import { isLoggedIn } from '../../../../helpers/users';
import { Hotspot, HotspotStatus } from '../../../../types/security-hotspots';
-import { CurrentUser, UserActive } from '../../../../types/types';
+import { CurrentUser, isLoggedIn, UserActive } from '../../../../types/users';
import AssigneeRenderer from './AssigneeRenderer';
interface Props {
}
}
-export default withCurrentUser(Assignee);
+export default withCurrentUserContext(Assignee);
import OutsideClickHandler from '../../../../components/controls/OutsideClickHandler';
import DeferredSpinner from '../../../../components/ui/DeferredSpinner';
import { translate, translateWithParameters } from '../../../../helpers/l10n';
-import { LoggedInUser, UserActive, UserBase } from '../../../../types/types';
+import { LoggedInUser, UserActive, UserBase } from '../../../../types/users';
import AssigneeSelection from './AssigneeSelection';
export interface AssigneeRendererProps {
import { searchUsers } from '../../../../api/users';
import { KeyboardCodes } from '../../../../helpers/keycodes';
import { translate } from '../../../../helpers/l10n';
-import { isUserActive } from '../../../../helpers/users';
-import { LoggedInUser, UserActive } from '../../../../types/types';
+import { isUserActive, LoggedInUser, UserActive } from '../../../../types/users';
import AssigneeSelectionRenderer from './AssigneeSelectionRenderer';
interface Props {
import DeferredSpinner from '../../../../components/ui/DeferredSpinner';
import { PopupPlacement } from '../../../../components/ui/popups';
import { translate } from '../../../../helpers/l10n';
-import { UserActive } from '../../../../types/types';
+import { UserActive } from '../../../../types/users';
import './AssigneeSelection.css';
export interface HotspotAssigneeSelectRendererProps {
import { mockCurrentUser, mockUser } from '../../../../../helpers/testMocks';
import { waitAndUpdate } from '../../../../../helpers/testUtils';
import { HotspotStatus } from '../../../../../types/security-hotspots';
-import { UserActive } from '../../../../../types/types';
+import { UserActive } from '../../../../../types/users';
import { Assignee } from '../Assignee';
import AssigneeRenderer from '../AssigneeRenderer';
import OutsideClickHandler from '../../../../../components/controls/OutsideClickHandler';
import { mockLoggedInUser, mockUser } from '../../../../../helpers/testMocks';
import { click } from '../../../../../helpers/testUtils';
-import { UserActive } from '../../../../../types/types';
+import { UserActive } from '../../../../../types/users';
import AssigneeRenderer, { AssigneeRendererProps } from '../AssigneeRenderer';
import AssigneeSelection from '../AssigneeSelection';
import { KeyboardCodes } from '../../../../../helpers/keycodes';
import { mockLoggedInUser, mockUser } from '../../../../../helpers/testMocks';
import { waitAndUpdate } from '../../../../../helpers/testUtils';
-import { UserActive } from '../../../../../types/types';
+import { UserActive } from '../../../../../types/users';
import AssigneeSelection from '../AssigneeSelection';
jest.mock('../../../../../api/users', () => ({
import { shallow } from 'enzyme';
import * as React from 'react';
import { mockUser } from '../../../../../helpers/testMocks';
-import { UserActive } from '../../../../../types/types';
+import { UserActive } from '../../../../../types/users';
import AssigneeSelectionRenderer, {
HotspotAssigneeSelectRendererProps
} from '../AssigneeSelectionRenderer';
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
+import withCurrentUserContext from '../../../../app/components/current-user/withCurrentUserContext';
import { Button } from '../../../../components/controls/buttons';
import { DropdownOverlay } from '../../../../components/controls/Dropdown';
import Toggler from '../../../../components/controls/Toggler';
import Tooltip from '../../../../components/controls/Tooltip';
-import { withCurrentUser } from '../../../../components/hoc/withCurrentUser';
import DropdownIcon from '../../../../components/icons/DropdownIcon';
import { PopupPlacement } from '../../../../components/ui/popups';
import { translate } from '../../../../helpers/l10n';
-import { isLoggedIn } from '../../../../helpers/users';
import { Hotspot, HotspotStatusOption } from '../../../../types/security-hotspots';
-import { CurrentUser } from '../../../../types/types';
+import { CurrentUser, isLoggedIn } from '../../../../types/users';
import { getStatusOptionFromStatusAndResolution } from '../../utils';
import StatusDescription from './StatusDescription';
import StatusSelection from './StatusSelection';
);
}
-export default withCurrentUser(Status);
+export default withCurrentUserContext(Status);
*/
import * as React from 'react';
import { sendTestEmail } from '../../../api/settings';
+import withCurrentUserContext from '../../../app/components/current-user/withCurrentUserContext';
import { SubmitButton } from '../../../components/controls/buttons';
-import { withCurrentUser } from '../../../components/hoc/withCurrentUser';
import { Alert } from '../../../components/ui/Alert';
import DeferredSpinner from '../../../components/ui/DeferredSpinner';
import MandatoryFieldMarker from '../../../components/ui/MandatoryFieldMarker';
import MandatoryFieldsExplanation from '../../../components/ui/MandatoryFieldsExplanation';
import { translate, translateWithParameters } from '../../../helpers/l10n';
import { parseError } from '../../../helpers/request';
-import { LoggedInUser } from '../../../types/types';
+import { LoggedInUser } from '../../../types/users';
interface Props {
currentUser: LoggedInUser;
}
}
-export default withCurrentUser(EmailForm);
+export default withCurrentUserContext(EmailForm);
`;
exports[`should render additional categories component correctly 5`] = `
-<Connect(withCurrentUser(PRDecorationBinding))
+<withCurrentUserContext(PRDecorationBinding)
component={
Object {
"breadcrumbs": Array [],
]
}
/>
- <Connect(withCurrentUser(EmailForm)) />
+ <withCurrentUserContext(EmailForm) />
</li>
<li
key="qg"
setProjectGitlabBinding,
validateProjectAlmBinding
} from '../../../../api/alm-settings';
+import withCurrentUserContext from '../../../../app/components/current-user/withCurrentUserContext';
import throwGlobalError from '../../../../app/utils/throwGlobalError';
-import { withCurrentUser } from '../../../../components/hoc/withCurrentUser';
import { HttpStatus } from '../../../../helpers/request';
import { hasGlobalPermission } from '../../../../helpers/users';
import {
ProjectAlmBindingResponse
} from '../../../../types/alm-settings';
import { Permissions } from '../../../../types/permissions';
-import { Component, CurrentUser } from '../../../../types/types';
+import { Component } from '../../../../types/types';
+import { CurrentUser } from '../../../../types/users';
import PRDecorationBindingRenderer from './PRDecorationBindingRenderer';
type FormData = Omit<ProjectAlmBindingResponse, 'alm'>;
}
}
-export default withCurrentUser(PRDecorationBinding);
+export default withCurrentUserContext(PRDecorationBinding);
<div
className="page-notifs"
>
- <Connect(withCurrentUser(withAppStateContext(UpdateNotification)))
+ <withCurrentUserContext(withAppStateContext(UpdateNotification))
dismissable={false}
/>
</div>
<div
className="page-notifs"
>
- <Connect(withCurrentUser(withAppStateContext(UpdateNotification)))
+ <withCurrentUserContext(withAppStateContext(UpdateNotification))
dismissable={false}
/>
</div>
<div
className="page-notifs"
>
- <Connect(withCurrentUser(withAppStateContext(UpdateNotification)))
+ <withCurrentUserContext(withAppStateContext(UpdateNotification))
dismissable={false}
/>
</div>
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
-import { withCurrentUser } from '../../../components/hoc/withCurrentUser';
+import withCurrentUserContext from '../../../app/components/current-user/withCurrentUserContext';
import TutorialSelection from '../../../components/tutorials/TutorialSelection';
import handleRequiredAuthentication from '../../../helpers/handleRequiredAuthentication';
-import { isLoggedIn } from '../../../helpers/users';
import { ProjectAlmBindingResponse } from '../../../types/alm-settings';
-import { Component, CurrentUser } from '../../../types/types';
+import { Component } from '../../../types/types';
+import { CurrentUser, isLoggedIn } from '../../../types/users';
export interface TutorialsAppProps {
component: Component;
);
}
-export default withCurrentUser(TutorialsApp);
+export default withCurrentUserContext(TutorialsApp);
import * as React from 'react';
import { Helmet } from 'react-helmet-async';
import { getIdentityProviders, searchUsers } from '../../api/users';
+import withCurrentUserContext from '../../app/components/current-user/withCurrentUserContext';
import Suggestions from '../../app/components/embed-docs-modal/Suggestions';
import ListFooter from '../../components/controls/ListFooter';
-import { withCurrentUser } from '../../components/hoc/withCurrentUser';
import { Location, Router, withRouter } from '../../components/hoc/withRouter';
import { translate } from '../../helpers/l10n';
-import { IdentityProvider, Paging, User } from '../../types/types';
+import { IdentityProvider, Paging } from '../../types/types';
+import { User } from '../../types/users';
import Header from './Header';
import Search from './Search';
import UsersList from './UsersList';
}
}
-export default withRouter(withCurrentUser(UsersApp));
+export default withRouter(withCurrentUserContext(UsersApp));
*/
import * as React from 'react';
import { translate } from '../../helpers/l10n';
-import { IdentityProvider, User } from '../../types/types';
+import { IdentityProvider } from '../../types/types';
+import { User } from '../../types/users';
import UserListItem from './components/UserListItem';
interface Props {
import { ResetButtonLink, SubmitButton } from '../../../components/controls/buttons';
import Modal from '../../../components/controls/Modal';
import { translate, translateWithParameters } from '../../../helpers/l10n';
-import { UserActive } from '../../../types/types';
+import { UserActive } from '../../../types/users';
export interface Props {
onClose: () => void;
SelectListSearchParams
} from '../../../components/controls/SelectList';
import { translate } from '../../../helpers/l10n';
-import { User } from '../../../types/types';
+import { User } from '../../../types/users';
interface Props {
onClose: () => void;
import MandatoryFieldsExplanation from '../../../components/ui/MandatoryFieldsExplanation';
import { translate } from '../../../helpers/l10n';
import { parseError } from '../../../helpers/request';
-import { User } from '../../../types/types';
+import { User } from '../../../types/users';
interface Props {
isCurrentUser: boolean;
import { ResetButtonLink } from '../../../components/controls/buttons';
import Modal from '../../../components/controls/Modal';
import { translate } from '../../../helpers/l10n';
-import { User } from '../../../types/types';
+import { User } from '../../../types/users';
import TokensForm from './TokensForm';
interface Props {
ActionsDropdownItem
} from '../../../components/controls/ActionsDropdown';
import { translate } from '../../../helpers/l10n';
-import { isUserActive } from '../../../helpers/users';
-import { User } from '../../../types/types';
+import { isUserActive, User } from '../../../types/users';
import DeactivateForm from './DeactivateForm';
import PasswordForm from './PasswordForm';
import UserForm from './UserForm';
import MandatoryFieldsExplanation from '../../../components/ui/MandatoryFieldsExplanation';
import { translate, translateWithParameters } from '../../../helpers/l10n';
import { parseError } from '../../../helpers/request';
-import { User } from '../../../types/types';
+import { User } from '../../../types/users';
import UserScmAccountInput from './UserScmAccountInput';
export interface Props {
import { ButtonIcon } from '../../../components/controls/buttons';
import BulletListIcon from '../../../components/icons/BulletListIcon';
import { translate, translateWithParameters } from '../../../helpers/l10n';
-import { User } from '../../../types/types';
+import { User } from '../../../types/users';
import GroupsForm from './GroupsForm';
interface Props {
import DateFromNow from '../../../components/intl/DateFromNow';
import Avatar from '../../../components/ui/Avatar';
import { translate } from '../../../helpers/l10n';
-import { IdentityProvider, User } from '../../../types/types';
+import { IdentityProvider } from '../../../types/types';
+import { User } from '../../../types/users';
import TokensFormModal from './TokensFormModal';
import UserActions from './UserActions';
import UserGroups from './UserGroups';
import { colors } from '../../../app/theme';
import { getTextColor } from '../../../helpers/colors';
import { getBaseUrl } from '../../../helpers/system';
-import { IdentityProvider, User } from '../../../types/types';
+import { IdentityProvider } from '../../../types/types';
+import { User } from '../../../types/users';
export interface Props {
identityProvider?: IdentityProvider;
import { shallow } from 'enzyme';
import * as React from 'react';
import { click } from '../../../../helpers/testUtils';
-import { User } from '../../../../types/types';
+import { User } from '../../../../types/users';
import UserListItem from '../UserListItem';
jest.mock('../../../../components/intl/DateFromNow');
*/
import * as React from 'react';
import { dismissAnalysisWarning, getTask } from '../../api/ce';
+import withCurrentUserContext from '../../app/components/current-user/withCurrentUserContext';
import { ButtonLink } from '../../components/controls/buttons';
import Modal from '../../components/controls/Modal';
import WarningIcon from '../../components/icons/WarningIcon';
import { translate } from '../../helpers/l10n';
import { sanitizeStringRestricted } from '../../helpers/sanitize';
import { TaskWarning } from '../../types/tasks';
-import { CurrentUser } from '../../types/types';
-import { withCurrentUser } from '../hoc/withCurrentUser';
+import { CurrentUser } from '../../types/users';
interface Props {
componentKey?: string;
}
}
-export default withCurrentUser(AnalysisWarningsModal);
+export default withCurrentUserContext(AnalysisWarningsModal);
import MandatoryFieldMarker from '../../components/ui/MandatoryFieldMarker';
import MandatoryFieldsExplanation from '../../components/ui/MandatoryFieldsExplanation';
import { translate } from '../../helpers/l10n';
-import { LoggedInUser } from '../../types/types';
+import { LoggedInUser } from '../../types/users';
interface Props {
className?: string;
unsubscribeFromEmailReport
} from '../../api/component-report';
import withAppStateContext from '../../app/components/app-state/withAppStateContext';
+import withCurrentUserContext from '../../app/components/current-user/withCurrentUserContext';
import addGlobalSuccessMessage from '../../app/utils/addGlobalSuccessMessage';
import { translate, translateWithParameters } from '../../helpers/l10n';
-import { isLoggedIn } from '../../helpers/users';
import { AppState } from '../../types/appstate';
import { Branch } from '../../types/branch-like';
import { ComponentQualifier } from '../../types/component';
import { ComponentReportStatus } from '../../types/component-report';
-import { Component, CurrentUser } from '../../types/types';
-import { withCurrentUser } from '../hoc/withCurrentUser';
+import { Component } from '../../types/types';
+import { CurrentUser, isLoggedIn } from '../../types/users';
import ComponentReportActionsRenderer from './ComponentReportActionsRenderer';
interface Props {
}
}
-export default withCurrentUser(withAppStateContext(ComponentReportActions));
+export default withCurrentUserContext(withAppStateContext(ComponentReportActions));
*/
import classNames from 'classnames';
import * as React from 'react';
-import { connect } from 'react-redux';
+import { setHomePage } from '../../api/users';
+import { CurrentUserContextInterface } from '../../app/components/current-user/CurrentUserContext';
+import withCurrentUserContext from '../../app/components/current-user/withCurrentUserContext';
import { ButtonLink } from '../../components/controls/buttons';
import Tooltip from '../../components/controls/Tooltip';
import HomeIcon from '../../components/icons/HomeIcon';
import { translate } from '../../helpers/l10n';
-import { isLoggedIn } from '../../helpers/users';
-import { getCurrentUser, Store } from '../../store/rootReducer';
-import { setHomePage } from '../../store/users';
-import { CurrentUser, HomePage } from '../../types/types';
+import { isSameHomePage } from '../../helpers/users';
+import { HomePage, isLoggedIn } from '../../types/users';
-interface StateProps {
- currentUser: CurrentUser;
-}
-
-interface DispatchProps {
- setHomePage: (homepage: HomePage) => void;
-}
-
-interface Props extends StateProps, DispatchProps {
+interface Props
+ extends Pick<CurrentUserContextInterface, 'currentUser' | 'updateCurrentUserHomepage'> {
className?: string;
currentPage: HomePage;
}
export const DEFAULT_HOMEPAGE: HomePage = { type: 'PROJECTS' };
export class HomePageSelect extends React.PureComponent<Props> {
+ async setCurrentUserHomepage(homepage: HomePage) {
+ const { currentUser } = this.props;
+
+ if (currentUser && isLoggedIn(currentUser)) {
+ await setHomePage(homepage);
+
+ this.props.updateCurrentUserHomepage(homepage);
+ }
+ }
+
handleClick = () => {
- this.props.setHomePage(this.props.currentPage);
+ this.setCurrentUserHomepage(this.props.currentPage);
};
handleReset = () => {
- this.props.setHomePage(DEFAULT_HOMEPAGE);
+ this.setCurrentUserHomepage(DEFAULT_HOMEPAGE);
};
render() {
}
}
-const mapStateToProps = (state: Store): StateProps => ({
- currentUser: getCurrentUser(state)
-});
-
-const mapDispatchToProps: DispatchProps = { setHomePage };
-
-export default connect(mapStateToProps, mapDispatchToProps)(HomePageSelect);
-
-function isSameHomePage(a: HomePage, b: HomePage) {
- return (
- a.type === b.type &&
- (a as any).branch === (b as any).branch &&
- (a as any).component === (b as any).component
- );
-}
+export default withCurrentUserContext(HomePageSelect);
import { ButtonLink } from '../../../components/controls/buttons';
import { mockCurrentUser, mockLoggedInUser } from '../../../helpers/testMocks';
import { click, waitAndUpdate } from '../../../helpers/testUtils';
-import { HomePage } from '../../../types/types';
+import { HomePage } from '../../../types/users';
import { DEFAULT_HOMEPAGE, HomePageSelect } from '../HomePageSelect';
+jest.mock('../../../api/users', () => ({
+ setHomePage: jest.fn().mockResolvedValue(null)
+}));
+
it('should render correctly', () => {
expect(shallowRender()).toMatchSnapshot('unchecked');
expect(
});
it('should correctly call webservices', async () => {
- const setHomePage = jest.fn();
+ const updateCurrentUserHomepage = jest.fn();
const currentPage: HomePage = { type: 'MY_ISSUES' };
- const wrapper = shallowRender({ setHomePage, currentPage });
+ const wrapper = shallowRender({ updateCurrentUserHomepage, currentPage });
// Set homepage.
click(wrapper.find(ButtonLink));
await waitAndUpdate(wrapper);
- expect(setHomePage).toHaveBeenLastCalledWith(currentPage);
+ expect(updateCurrentUserHomepage).toHaveBeenLastCalledWith(currentPage);
// Reset.
wrapper.setProps({ currentUser: mockLoggedInUser({ homepage: currentPage }) });
click(wrapper.find(ButtonLink));
await waitAndUpdate(wrapper);
- expect(setHomePage).toHaveBeenLastCalledWith(DEFAULT_HOMEPAGE);
+ expect(updateCurrentUserHomepage).toHaveBeenLastCalledWith(DEFAULT_HOMEPAGE);
});
function shallowRender(props: Partial<HomePageSelect['props']> = {}) {
<HomePageSelect
currentPage={{ type: 'MY_PROJECTS' }}
currentUser={mockLoggedInUser()}
- setHomePage={jest.fn()}
+ updateCurrentUserHomepage={jest.fn()}
{...props}
/>
);
*/
import { shallow, ShallowWrapper } from 'enzyme';
import * as React from 'react';
+import { CurrentUserContext } from '../../../app/components/current-user/CurrentUserContext';
import handleRequiredAuthentication from '../../../helpers/handleRequiredAuthentication';
-import { mockStore } from '../../../helpers/testMocks';
import { whenLoggedIn } from '../whenLoggedIn';
jest.mock('../../../helpers/handleRequiredAuthentication', () => jest.fn());
function getRenderedType(wrapper: ShallowWrapper) {
return wrapper
+ .dive()
.dive()
.dive()
.type();
}
function shallowRender(isLoggedIn = true) {
- return shallow(<UnderTest />, {
- context: { store: mockStore({ users: { currentUser: { isLoggedIn } } }) }
- });
+ return shallow(
+ <CurrentUserContext.Provider
+ value={{
+ currentUser: { isLoggedIn },
+ updateCurrentUserHomepage: () => {},
+ updateCurrentUserSonarLintAdSeen: () => {}
+ }}>
+ <UnderTest />
+ </CurrentUserContext.Provider>
+ );
}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2022 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 { shallow } from 'enzyme';
-import * as React from 'react';
-import { mockStore } from '../../../helpers/testMocks';
-import { CurrentUser } from '../../../types/types';
-import { withCurrentUser } from '../withCurrentUser';
-
-class X extends React.Component<{ currentUser: CurrentUser }> {
- render() {
- return <div />;
- }
-}
-
-const UnderTest = withCurrentUser(X);
-
-it('should pass logged in user', () => {
- const currentUser = { isLoggedIn: false };
- const wrapper = shallow(<UnderTest />, {
- context: { store: mockStore({ users: { currentUser } }) }
- });
- expect(wrapper.dive().type()).toBe(X);
- expect(wrapper.dive().prop('currentUser')).toBe(currentUser);
-});
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
+import withCurrentUserContext from '../../app/components/current-user/withCurrentUserContext';
import handleRequiredAuthentication from '../../helpers/handleRequiredAuthentication';
-import { isLoggedIn } from '../../helpers/users';
-import { CurrentUser } from '../../types/types';
+import { CurrentUser, isLoggedIn } from '../../types/users';
import { getWrappedDisplayName } from './utils';
-import { withCurrentUser } from './withCurrentUser';
export function whenLoggedIn<P>(WrappedComponent: React.ComponentType<P>) {
class Wrapper extends React.Component<P & { currentUser: CurrentUser }> {
render() {
if (isLoggedIn(this.props.currentUser)) {
return <WrappedComponent {...this.props} />;
- } else {
- return null;
}
+ return null;
}
}
- return withCurrentUser(Wrapper);
+ return withCurrentUserContext(Wrapper);
}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2022 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 { connect } from 'react-redux';
-import { getCurrentUser, Store } from '../../store/rootReducer';
-import { CurrentUser } from '../../types/types';
-import { getWrappedDisplayName } from './utils';
-
-export function withCurrentUser<P>(
- WrappedComponent: React.ComponentType<P & { currentUser: CurrentUser }>
-) {
- class Wrapper extends React.Component<P & { currentUser: CurrentUser }> {
- static displayName = getWrappedDisplayName(WrappedComponent, 'withCurrentUser');
-
- render() {
- return <WrappedComponent {...this.props} />;
- }
- }
-
- function mapStateToProps(state: Store) {
- return { currentUser: getCurrentUser(state) };
- }
-
- return connect(mapStateToProps)(Wrapper);
-}
onRequestClose={[Function]}
open={true}
overlay={
- <Connect(withCurrentUser(SetAssigneePopup))
+ <withCurrentUserContext(SetAssigneePopup)
onSelect={[MockFunction]}
/>
}
onRequestClose={[Function]}
open={false}
overlay={
- <Connect(withCurrentUser(SetAssigneePopup))
+ <withCurrentUserContext(SetAssigneePopup)
onSelect={[MockFunction]}
/>
}
onRequestClose={[Function]}
open={false}
overlay={
- <Connect(withCurrentUser(SetAssigneePopup))
+ <withCurrentUserContext(SetAssigneePopup)
onSelect={[MockFunction]}
/>
}
import { map } from 'lodash';
import * as React from 'react';
import { searchUsers } from '../../../api/users';
+import withCurrentUserContext from '../../../app/components/current-user/withCurrentUserContext';
import { DropdownOverlay } from '../../../components/controls/Dropdown';
import SearchBox from '../../../components/controls/SearchBox';
import { translate } from '../../../helpers/l10n';
-import { isLoggedIn, isUserActive } from '../../../helpers/users';
-import { CurrentUser, UserActive, UserBase } from '../../../types/types';
+import { CurrentUser, isLoggedIn, isUserActive, UserActive, UserBase } from '../../../types/users';
import SelectList from '../../common/SelectList';
import SelectListItem from '../../common/SelectListItem';
-import { withCurrentUser } from '../../hoc/withCurrentUser';
import Avatar from '../../ui/Avatar';
interface Props {
}
}
-export default withCurrentUser(SetAssigneePopup);
+export default withCurrentUserContext(SetAssigneePopup);
import { getHostUrl } from '../../helpers/urls';
import { AlmSettingsInstance, ProjectAlmBindingResponse } from '../../types/alm-settings';
import { SettingsKey } from '../../types/settings';
-import { Component, LoggedInUser } from '../../types/types';
+import { Component } from '../../types/types';
+import { LoggedInUser } from '../../types/users';
import { withRouter } from '../hoc/withRouter';
import TutorialSelectionRenderer from './TutorialSelectionRenderer';
import { TutorialModes } from './types';
import { translate } from '../../helpers/l10n';
import { getBaseUrl } from '../../helpers/system';
import { AlmKeys, AlmSettingsInstance, ProjectAlmBindingResponse } from '../../types/alm-settings';
-import { Component, LoggedInUser } from '../../types/types';
+import { Component } from '../../types/types';
+import { LoggedInUser } from '../../types/users';
import AzurePipelinesTutorial from './azure-pipelines/AzurePipelinesTutorial';
import BitbucketPipelinesTutorial from './bitbucket-pipelines/BitbucketPipelinesTutorial';
import GitHubActionTutorial from './github-action/GitHubActionTutorial';
exports[`should render correctly: jenkins tutorial 1`] = `
<Fragment>
- <Connect(withAppStateContext(JenkinsTutorial))
+ <withAppStateContext(JenkinsTutorial)
almBinding={
Object {
"alm": "github",
import { Button } from '../../../components/controls/buttons';
import { translate } from '../../../helpers/l10n';
import { AlmKeys } from '../../../types/alm-settings';
-import { Component, LoggedInUser } from '../../../types/types';
+import { Component } from '../../../types/types';
+import { LoggedInUser } from '../../../types/users';
import AllSetStep from '../components/AllSetStep';
import FinishButton from '../components/FinishButton';
import Step from '../components/Step';
import { Button } from '../../../components/controls/buttons';
import { ClipboardIconButton } from '../../../components/controls/clipboard';
import { translate } from '../../../helpers/l10n';
-import { Component, LoggedInUser } from '../../../types/types';
+import { Component } from '../../../types/types';
+import { LoggedInUser } from '../../../types/users';
import EditTokenModal from '../components/EditTokenModal';
import SentenceWithHighlights from '../components/SentenceWithHighlights';
AlmSettingsInstance,
ProjectAlmBindingResponse
} from '../../../types/alm-settings';
-import { Component, LoggedInUser } from '../../../types/types';
+import { Component } from '../../../types/types';
+import { LoggedInUser } from '../../../types/users';
import AllSetStep from '../components/AllSetStep';
import FinishButton from '../components/FinishButton';
import GithubCFamilyExampleRepositories from '../components/GithubCFamilyExampleRepositories';
import { ClipboardIconButton } from '../../../components/controls/clipboard';
import { translate } from '../../../helpers/l10n';
import { AlmSettingsInstance, ProjectAlmBindingResponse } from '../../../types/alm-settings';
-import { Component, LoggedInUser } from '../../../types/types';
+import { Component } from '../../../types/types';
+import { LoggedInUser } from '../../../types/users';
import SentenceWithHighlights from '../components/SentenceWithHighlights';
import TokenStepGenerator from '../components/TokenStepGenerator';
import { buildBitbucketCloudLink } from '../utils';
import { Alert } from '../../../components/ui/Alert';
import DeferredSpinner from '../../../components/ui/DeferredSpinner';
import { translate, translateWithParameters } from '../../../helpers/l10n';
-import { Component, LoggedInUser } from '../../../types/types';
+import { Component } from '../../../types/types';
+import { LoggedInUser } from '../../../types/users';
import { getUniqueTokenName } from '../utils';
interface State {
import { FormattedMessage } from 'react-intl';
import { Button } from '../../../components/controls/buttons';
import { translate } from '../../../helpers/l10n';
-import { Component, LoggedInUser } from '../../../types/types';
+import { Component } from '../../../types/types';
+import { LoggedInUser } from '../../../types/users';
import EditTokenModal from './EditTokenModal';
export interface TokenStepGeneratorProps {
AlmSettingsInstance,
ProjectAlmBindingResponse
} from '../../../types/alm-settings';
-import { Component, LoggedInUser } from '../../../types/types';
+import { Component } from '../../../types/types';
+import { LoggedInUser } from '../../../types/users';
import AllSetStep from '../components/AllSetStep';
import Step from '../components/Step';
import YamlFileStep from '../components/YamlFileStep';
import { ClipboardIconButton } from '../../../components/controls/clipboard';
import { translate } from '../../../helpers/l10n';
import { AlmSettingsInstance, ProjectAlmBindingResponse } from '../../../types/alm-settings';
-import { Component, LoggedInUser } from '../../../types/types';
+import { Component } from '../../../types/types';
+import { LoggedInUser } from '../../../types/users';
import SentenceWithHighlights from '../components/SentenceWithHighlights';
import TokenStepGenerator from '../components/TokenStepGenerator';
import { buildGithubLink } from '../utils';
import { Button } from '../../../components/controls/buttons';
import { ClipboardIconButton } from '../../../components/controls/clipboard';
import { translate } from '../../../helpers/l10n';
-import { Component, LoggedInUser } from '../../../types/types';
+import { Component } from '../../../types/types';
+import { LoggedInUser } from '../../../types/users';
import Step from '../components/Step';
import TokenStepGenerator from '../components/TokenStepGenerator';
import * as React from 'react';
import { translate } from '../../../helpers/l10n';
import { AlmKeys } from '../../../types/alm-settings';
-import { Component, LoggedInUser } from '../../../types/types';
+import { Component } from '../../../types/types';
+import { LoggedInUser } from '../../../types/users';
import AllSetStep from '../components/AllSetStep';
import { BuildTools } from '../types';
import EnvironmentVariablesStep from './EnvironmentVariablesStep';
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
-import { connect } from 'react-redux';
import withAppStateContext from '../../../app/components/app-state/withAppStateContext';
import { translate } from '../../../helpers/l10n';
-import { getCurrentUserSetting, Store } from '../../../store/rootReducer';
-import { setCurrentUserSetting } from '../../../store/users';
import {
AlmKeys,
AlmSettingsInstance,
ProjectAlmBindingResponse
} from '../../../types/alm-settings';
import { AppState } from '../../../types/appstate';
-import { Component, CurrentUserSetting } from '../../../types/types';
+import { Component } from '../../../types/types';
import AllSetStep from '../components/AllSetStep';
import JenkinsfileStep from './JenkinsfileStep';
import MultiBranchPipelineStep from './MultiBranchPipelineStep';
appState: AppState;
component: Component;
projectBinding?: ProjectAlmBindingResponse;
- setCurrentUserSetting: (setting: CurrentUserSetting) => void;
- skipPreReqs: boolean;
willRefreshAutomatically?: boolean;
}
AllSet = 5
}
-const USER_SETTING_SKIP_BITBUCKET_PREREQS = 'tutorials.jenkins.skipBitbucketPreReqs';
-
export function JenkinsTutorial(props: JenkinsTutorialProps) {
const {
almBinding,
appState,
component,
projectBinding,
- skipPreReqs,
willRefreshAutomatically
} = props;
const hasSelectAlmStep = projectBinding?.alm === undefined;
const [alm, setAlm] = React.useState<AlmKeys | undefined>(projectBinding?.alm);
-
- let startStep;
- if (alm) {
- startStep = skipPreReqs ? Steps.MultiBranchPipeline : Steps.PreRequisites;
- } else {
- startStep = Steps.SelectAlm;
- }
- const [step, setStep] = React.useState(startStep);
+ const [step, setStep] = React.useState(alm ? Steps.PreRequisites : Steps.SelectAlm);
return (
<>
finished={step > Steps.PreRequisites}
onDone={() => setStep(Steps.MultiBranchPipeline)}
onOpen={() => setStep(Steps.PreRequisites)}
- onChangeSkipNextTime={skip => {
- props.setCurrentUserSetting({
- key: USER_SETTING_SKIP_BITBUCKET_PREREQS,
- value: skip.toString()
- });
- }}
open={step === Steps.PreRequisites}
- skipNextTime={skipPreReqs}
/>
{appState.branchesEnabled ? (
);
}
-const mapStateToProps = (state: Store): Pick<JenkinsTutorialProps, 'skipPreReqs'> => {
- return {
- skipPreReqs: getCurrentUserSetting(state, USER_SETTING_SKIP_BITBUCKET_PREREQS) === 'true'
- };
-};
-
-const mapDispatchToProps = { setCurrentUserSetting };
-
-export default connect(mapStateToProps, mapDispatchToProps)(withAppStateContext(JenkinsTutorial));
+export default withAppStateContext(JenkinsTutorial);
import { Link } from 'react-router';
import { rawSizes } from '../../../app/theme';
import { Button } from '../../../components/controls/buttons';
-import Checkbox from '../../../components/controls/Checkbox';
import ChevronRightIcon from '../../../components/icons/ChevronRightIcon';
import { Alert } from '../../../components/ui/Alert';
import { translate } from '../../../helpers/l10n';
alm: AlmKeys;
branchesEnabled: boolean;
finished: boolean;
- onChangeSkipNextTime: (skip: boolean) => void;
onDone: () => void;
onOpen: () => void;
open: boolean;
- skipNextTime: boolean;
}
export default function PreRequisitesStep(props: PreRequisitesStepProps) {
- const { alm, branchesEnabled, finished, open, skipNextTime } = props;
+ const { alm, branchesEnabled, finished, open } = props;
return (
<Step
finished={finished}
<p className="big-spacer-bottom">
{translate('onboarding.tutorial.with.jenkins.prereqs.following_are_recommendations')}
</p>
- <p className="big-spacer-bottom display-flex-center">
- <label
- className="cursor-pointer"
- htmlFor="skip-prereqs"
- onClick={() => {
- props.onChangeSkipNextTime(!skipNextTime);
- }}>
- {translate('onboarding.tutorial.with.jenkins.prereqs.skip_next_time')}
- </label>
- <Checkbox
- checked={skipNextTime}
- className="little-spacer-left"
- id="skip-prereqs"
- onCheck={props.onChangeSkipNextTime}
- />
- </p>
<Button className="big-spacer-top" onClick={props.onDone}>
{translate('onboarding.tutorial.with.jenkins.prereqs.done')}
<ChevronRightIcon size={rawSizes.baseFontSizeRaw} />
expect(wrapper.find(WebhookStep).props().open).toBe(true);
});
-it('should correctly store the user setting', () => {
- const setCurrentUserSetting = jest.fn();
- const wrapper = shallowRender({ setCurrentUserSetting });
-
- wrapper.find(PreRequisitesStep).prop('onChangeSkipNextTime')(true);
- expect(setCurrentUserSetting).toBeCalledWith({
- key: 'tutorials.jenkins.skipBitbucketPreReqs',
- value: 'true'
- });
-
- wrapper.find(PreRequisitesStep).prop('onChangeSkipNextTime')(false);
- expect(setCurrentUserSetting).toBeCalledWith({
- key: 'tutorials.jenkins.skipBitbucketPreReqs',
- value: 'false'
- });
-});
-
-it('should correctly skip the pre-reqs step if the user requested it', () => {
- const wrapper = shallowRender({ skipPreReqs: true });
- expect(wrapper.find(PreRequisitesStep).props().open).toBe(false);
- expect(wrapper.find(MultiBranchPipelineStep).props().open).toBe(true);
-});
-
it('should correctly select an ALM if no project is bound', () => {
const wrapper = shallowRender({ projectBinding: undefined });
expect(wrapper.find(PreRequisitesStep).exists()).toBe(false);
appState={mockAppState({ branchesEnabled: true })}
component={mockComponent()}
projectBinding={mockProjectBitbucketBindingResponse()}
- setCurrentUserSetting={jest.fn()}
- skipPreReqs={false}
willRefreshAutomatically={true}
{...props}
/>
alm={AlmKeys.BitbucketServer}
branchesEnabled={true}
finished={false}
- onChangeSkipNextTime={jest.fn()}
onDone={jest.fn()}
onOpen={jest.fn()}
open={false}
- skipNextTime={true}
{...props}
/>
);
alm="bitbucket"
branchesEnabled={false}
finished={false}
- onChangeSkipNextTime={[Function]}
onDone={[Function]}
onOpen={[Function]}
open={true}
- skipNextTime={false}
/>
<PipelineStep
alm="bitbucket"
alm="bitbucket"
branchesEnabled={true}
finished={false}
- onChangeSkipNextTime={[Function]}
onDone={[Function]}
onOpen={[Function]}
open={true}
- skipNextTime={false}
/>
<MultiBranchPipelineStep
alm="bitbucket"
>
onboarding.tutorial.with.jenkins.prereqs.following_are_recommendations
</p>
- <p
- className="big-spacer-bottom display-flex-center"
- >
- <label
- className="cursor-pointer"
- htmlFor="skip-prereqs"
- onClick={[Function]}
- >
- onboarding.tutorial.with.jenkins.prereqs.skip_next_time
- </label>
- <Checkbox
- checked={true}
- className="little-spacer-left"
- id="skip-prereqs"
- onCheck={[MockFunction]}
- thirdState={false}
- />
- </p>
<Button
className="big-spacer-top"
onClick={[MockFunction]}
>
onboarding.tutorial.with.jenkins.prereqs.following_are_recommendations
</p>
- <p
- className="big-spacer-bottom display-flex-center"
- >
- <label
- className="cursor-pointer"
- htmlFor="skip-prereqs"
- onClick={[Function]}
- >
- onboarding.tutorial.with.jenkins.prereqs.skip_next_time
- </label>
- <Checkbox
- checked={true}
- className="little-spacer-left"
- id="skip-prereqs"
- onCheck={[MockFunction]}
- thirdState={false}
- />
- </p>
<Button
className="big-spacer-top"
onClick={[MockFunction]}
>
onboarding.tutorial.with.jenkins.prereqs.following_are_recommendations
</p>
- <p
- className="big-spacer-bottom display-flex-center"
- >
- <label
- className="cursor-pointer"
- htmlFor="skip-prereqs"
- onClick={[Function]}
- >
- onboarding.tutorial.with.jenkins.prereqs.skip_next_time
- </label>
- <Checkbox
- checked={true}
- className="little-spacer-left"
- id="skip-prereqs"
- onCheck={[MockFunction]}
- thirdState={false}
- />
- </p>
<Button
className="big-spacer-top"
onClick={[MockFunction]}
*/
import * as React from 'react';
import { translate } from '../../../helpers/l10n';
-import { Component, LoggedInUser } from '../../../types/types';
+import { Component } from '../../../types/types';
+import { LoggedInUser } from '../../../types/users';
import InstanceMessage from '../../common/InstanceMessage';
import ProjectAnalysisStep from './ProjectAnalysisStep';
import TokenStep from './TokenStep';
import Radio from '../../../components/controls/Radio';
import AlertSuccessIcon from '../../../components/icons/AlertSuccessIcon';
import { translate } from '../../../helpers/l10n';
-import { LoggedInUser, UserToken } from '../../../types/types';
+import { UserToken } from '../../../types/types';
+import { LoggedInUser } from '../../../types/users';
import AlertErrorIcon from '../../icons/AlertErrorIcon';
import Step from '../components/Step';
import { getUniqueTokenName } from '../utils';
import { shallow } from 'enzyme';
import * as React from 'react';
import { change, click, submit, waitAndUpdate } from '../../../../helpers/testUtils';
-import { LoggedInUser } from '../../../../types/types';
+import { LoggedInUser } from '../../../../types/users';
import TokenStep from '../TokenStep';
jest.mock('../../../../api/user-tokens', () => ({
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2022 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 { isSameHomePage } from '../users';
+
+describe('isSameHomePage', () => {
+ it('should homepage equality properly', () => {
+ expect(
+ isSameHomePage(
+ {
+ type: 'APPLICATION',
+ branch: 'test-branch',
+ component: 'test-component'
+ },
+ {
+ type: 'APPLICATION',
+ branch: 'test-branch',
+ component: 'test-component'
+ }
+ )
+ ).toBe(true);
+
+ expect(
+ isSameHomePage(
+ {
+ type: 'APPLICATION',
+ branch: 'test-branch',
+ component: 'test-component'
+ },
+ {
+ type: 'ISSUES'
+ }
+ )
+ ).toBe(false);
+
+ expect(
+ isSameHomePage(
+ {
+ type: 'APPLICATION',
+ branch: 'test-branch',
+ component: 'test-component'
+ },
+ {
+ type: 'APPLICATION',
+ branch: 'test-branch-1',
+ component: 'test-component'
+ }
+ )
+ ).toBe(false);
+
+ expect(
+ isSameHomePage(
+ {
+ type: 'APPLICATION',
+ branch: 'test-branch',
+ component: 'test-component'
+ },
+ {
+ type: 'APPLICATION',
+ branch: 'test-branch',
+ component: 'test-component-1'
+ }
+ )
+ ).toBe(false);
+ });
+});
import VulnerabilityIcon from '../components/icons/VulnerabilityIcon';
import { IssueType, RawIssue } from '../types/issues';
import { MetricKey } from '../types/metrics';
-import { Dict, FlowLocation, Issue, TextRange, UserBase } from '../types/types';
+import { Dict, FlowLocation, Issue, TextRange } from '../types/types';
+import { UserBase } from '../types/users';
import { ISSUE_TYPES } from './constants';
interface Rule {}
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-import { UserBase } from '../../types/types';
+import { UserBase } from '../../types/users';
export function mockUserBase(overrides: Partial<UserBase> = {}): UserBase {
return {
Analysis,
AnalysisEvent,
Condition,
- CurrentUser,
FlowLocation,
Group,
HealthType,
IdentityProvider,
Issue,
- LoggedInUser,
Measure,
MeasureEnhanced,
Metric,
SourceViewerFile,
SysInfoBase,
SysInfoCluster,
- SysInfoStandalone,
- User
+ SysInfoStandalone
} from '../types/types';
+import { CurrentUser, LoggedInUser, User } from '../types/users';
export function mockAlmApplication(overrides: Partial<AlmApplication> = {}): AlmApplication {
return {
import { MeasurePageView } from '../types/measures';
import { GraphType } from '../types/project-activity';
import { SecurityStandard } from '../types/security';
-import { Dict, HomePage } from '../types/types';
+import { Dict } from '../types/types';
+import { HomePage } from '../types/users';
import { getBranchLikeQuery, isBranch, isMainBranch, isPullRequest } from './branch-like';
import { IS_SSR } from './browser';
import { serializeOptionalBoolean } from './query';
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-import { CurrentUser, LoggedInUser, UserActive, UserBase } from '../types/types';
+import { CurrentUser, HomePage } from '../types/users';
export function hasGlobalPermission(user: CurrentUser, permission: string): boolean {
if (!user.permissions) {
return user.permissions.global.includes(permission);
}
-export function isLoggedIn(user: CurrentUser): user is LoggedInUser {
- return user.isLoggedIn;
-}
-
-export function isUserActive(user: UserBase): user is UserActive {
- return user.active !== false && Boolean(user.name);
+export function isSameHomePage(a: HomePage, b: HomePage) {
+ return (
+ a.type === b.type &&
+ (a as any).branch === (b as any).branch &&
+ (a as any).component === (b as any).component
+ );
}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2022 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 { mockCurrentUser, mockLoggedInUser, mockUser } from '../../helpers/testMocks';
-import { isLoggedIn } from '../../helpers/users';
-import { CurrentUserSetting, HomePage, LoggedInUser } from '../../types/types';
-import reducer, {
- getCurrentUser,
- getCurrentUserSetting,
- getUserByLogin,
- getUsersByLogins,
- receiveCurrentUser,
- setCurrentUserSettingAction,
- setHomePageAction,
- setSonarlintAd,
- State
-} from '../users';
-
-describe('reducer and actions', () => {
- it('should allow to receive the current user', () => {
- const initialState: State = createState();
-
- const currentUser = mockCurrentUser();
- const newState = reducer(initialState, receiveCurrentUser(currentUser));
- expect(newState).toEqual(createState({ currentUser }));
- });
-
- it('should allow to set the homepage', () => {
- const homepage: HomePage = { type: 'PROJECTS' };
- const currentUser = mockLoggedInUser({ homepage: undefined });
- const initialState: State = createState({ currentUser });
-
- const newState = reducer(initialState, setHomePageAction(homepage));
- expect(newState).toEqual(
- createState({ currentUser: { ...currentUser, homepage } as LoggedInUser })
- );
- });
-
- it('should allow to set a user setting', () => {
- const setting1: CurrentUserSetting = { key: 'notifications.optOut', value: '1' };
- const setting2: CurrentUserSetting = { key: 'notifications.readDate', value: '2' };
- const setting3: CurrentUserSetting = { key: 'notifications.optOut', value: '2' };
- const currentUser = mockLoggedInUser();
- const initialState: State = createState({ currentUser });
-
- const newState = reducer(initialState, setCurrentUserSettingAction(setting1));
- expect(newState).toEqual(
- createState({ currentUser: { ...currentUser, settings: [setting1] } as LoggedInUser })
- );
-
- const newerState = reducer(newState, setCurrentUserSettingAction(setting2));
- expect(newerState).toEqual(
- createState({
- currentUser: { ...currentUser, settings: [setting1, setting2] } as LoggedInUser
- })
- );
-
- const newestState = reducer(newerState, setCurrentUserSettingAction(setting3));
- expect(newestState).toEqual(
- createState({
- currentUser: { ...currentUser, settings: [setting3, setting2] } as LoggedInUser
- })
- );
- });
-
- it('should allow to set the sonarLintAdSeen flag', () => {
- const currentUser = mockLoggedInUser();
- const initialState: State = createState({ currentUser });
-
- const newState = reducer(initialState, setSonarlintAd());
- expect(isLoggedIn(newState.currentUser) && newState.currentUser.sonarLintAdSeen).toBe(true);
- });
-});
-
-describe('getters', () => {
- const currentUser = mockLoggedInUser({ settings: [{ key: 'notifications.optOut', value: '1' }] });
- const jane = mockUser({ login: 'jane', name: 'Jane Doe' });
- const john = mockUser({ login: 'john' });
- const state = createState({ currentUser, usersByLogin: { jane, john } });
-
- it('getCurrentUser', () => {
- expect(getCurrentUser(state)).toBe(currentUser);
- });
-
- it('getCurrentUserSetting', () => {
- expect(getCurrentUserSetting(state, 'notifications.optOut')).toBe('1');
- expect(getCurrentUserSetting(state, 'notifications.readDate')).toBeUndefined();
- });
-
- it('getUserByLogin', () => {
- expect(getUserByLogin(state, 'jane')).toBe(jane);
- expect(getUserByLogin(state, 'steve')).toBeUndefined();
- });
-
- it('getUsersByLogins', () => {
- expect(getUsersByLogins(state, ['jane', 'john'])).toEqual([jane, john]);
- });
-});
-
-function createState(overrides: Partial<State> = {}): State {
- return { usersByLogin: {}, userLogins: [], currentUser: mockCurrentUser(), ...overrides };
-}
*/
import { combineReducers } from 'redux';
import { BranchLike } from '../types/branch-like';
-import { CurrentUserSettingNames } from '../types/types';
import branches, * as fromBranches from './branches';
import globalMessages, * as fromGlobalMessages from './globalMessages';
-import users, * as fromUsers from './users';
export type Store = {
branches: fromBranches.State;
globalMessages: fromGlobalMessages.State;
- users: fromUsers.State;
};
export default combineReducers<Store>({
branches,
- globalMessages,
- users
+ globalMessages
});
export function getGlobalMessages(state: Store) {
return fromGlobalMessages.getGlobalMessages(state.globalMessages);
}
-export function getCurrentUserSetting(state: Store, key: CurrentUserSettingNames) {
- return fromUsers.getCurrentUserSetting(state.users, key);
-}
-
-export function getCurrentUser(state: Store) {
- return fromUsers.getCurrentUser(state.users);
-}
-
export function getBranchStatusByBranchLike(
state: Store,
component: string,
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2022 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 { uniq } from 'lodash';
-import { combineReducers, Dispatch } from 'redux';
-import * as api from '../api/users';
-import { isLoggedIn } from '../helpers/users';
-import {
- CurrentUser,
- CurrentUserSetting,
- CurrentUserSettingNames,
- Dict,
- HomePage,
- LoggedInUser
-} from '../types/types';
-import { ActionType } from './utils/actions';
-
-const enum Actions {
- ReceiveCurrentUser = 'RECEIVE_CURRENT_USER',
- SetCurrentUserSetting = 'SET_CURRENT_USER_SETTING',
- SetHomePageAction = 'SET_HOMEPAGE',
- SetSonarlintAd = 'SET_SONARLINT_AD'
-}
-
-type Action =
- | ActionType<typeof receiveCurrentUser, Actions.ReceiveCurrentUser>
- | ActionType<typeof setCurrentUserSettingAction, Actions.SetCurrentUserSetting>
- | ActionType<typeof setHomePageAction, Actions.SetHomePageAction>
- | ActionType<typeof setSonarlintAd, Actions.SetSonarlintAd>;
-
-export interface State {
- usersByLogin: Dict<any>;
- userLogins: string[];
- currentUser: CurrentUser;
-}
-
-export function receiveCurrentUser(user: CurrentUser) {
- return { type: Actions.ReceiveCurrentUser, user };
-}
-
-export function setHomePageAction(homepage: HomePage) {
- return { type: Actions.SetHomePageAction, homepage };
-}
-
-export function setCurrentUserSettingAction(setting: CurrentUserSetting) {
- return { type: Actions.SetCurrentUserSetting, setting };
-}
-
-export function setSonarlintAd() {
- return { type: Actions.SetSonarlintAd };
-}
-
-export function setHomePage(homepage: HomePage) {
- return (dispatch: Dispatch) => {
- api.setHomePage(homepage).then(
- () => {
- dispatch(setHomePageAction(homepage));
- },
- () => {}
- );
- };
-}
-
-export function setCurrentUserSetting(setting: CurrentUserSetting) {
- return (dispatch: Dispatch, getState: () => { users: State }) => {
- const oldSetting = getCurrentUserSetting(getState().users, setting.key);
- dispatch(setCurrentUserSettingAction(setting));
- api.setUserSetting(setting).then(
- () => {},
- () => {
- dispatch(setCurrentUserSettingAction({ ...setting, value: oldSetting || '' }));
- }
- );
- };
-}
-
-function usersByLogin(state: State['usersByLogin'] = {}, action: Action): State['usersByLogin'] {
- if (action.type === Actions.ReceiveCurrentUser && isLoggedIn(action.user)) {
- return { ...state, [action.user.login]: action.user };
- } else {
- return state;
- }
-}
-
-function userLogins(state: State['userLogins'] = [], action: Action): State['userLogins'] {
- if (action.type === Actions.ReceiveCurrentUser && isLoggedIn(action.user)) {
- return uniq([...state, action.user.login]);
- } else {
- return state;
- }
-}
-
-function currentUser(
- state: State['currentUser'] = { isLoggedIn: false },
- action: Action
-): State['currentUser'] {
- if (action.type === Actions.ReceiveCurrentUser) {
- return action.user;
- }
- if (action.type === Actions.SetHomePageAction && isLoggedIn(state)) {
- return { ...state, homepage: action.homepage } as LoggedInUser;
- }
- if (action.type === Actions.SetCurrentUserSetting && isLoggedIn(state)) {
- let settings: CurrentUserSetting[];
- if (state.settings) {
- settings = [...state.settings];
- const index = settings.findIndex(setting => setting.key === action.setting.key);
- if (index === -1) {
- settings.push(action.setting);
- } else {
- settings[index] = action.setting;
- }
- } else {
- settings = [action.setting];
- }
- return { ...state, settings } as LoggedInUser;
- }
- if (action.type === Actions.SetSonarlintAd && isLoggedIn(state)) {
- return { ...state, sonarLintAdSeen: true } as LoggedInUser;
- }
- return state;
-}
-
-export default combineReducers({ usersByLogin, userLogins, currentUser });
-
-export function getCurrentUser(state: State) {
- return state.currentUser;
-}
-
-export function getCurrentUserSetting(state: State, key: CurrentUserSettingNames) {
- let setting;
- if (isLoggedIn(state.currentUser) && state.currentUser.settings) {
- setting = state.currentUser.settings.find(setting => setting.key === key);
- }
- return setting && setting.value;
-}
-
-export function getUserByLogin(state: State, login: string) {
- return state.usersByLogin[login];
-}
-
-export function getUsersByLogins(state: State, logins: string[]) {
- return logins.map(login => getUserByLogin(state, login));
-}
import { Store } from '../store/rootReducer';
import { AppState } from './appstate';
import { L10nBundle } from './l10n';
-import { CurrentUser, Dict } from './types';
+import { Dict } from './types';
+import { CurrentUser } from './users';
export enum AdminPageExtension {
GovernanceConsole = 'governance/views_console'
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-import { FlowLocation, Issue, Paging, TextRange, UserBase } from './types';
+import { FlowLocation, Issue, Paging, TextRange } from './types';
+import { UserBase } from './users';
export enum IssueType {
CodeSmell = 'CODE_SMELL',
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import { BranchLike } from './branch-like';
-import { MeasureEnhanced, Metric, Status, UserBase } from './types';
+import { MeasureEnhanced, Metric, Status } from './types';
+import { UserBase } from './users';
export interface QualityGateProjectStatus {
conditions?: QualityGateProjectStatusCondition[];
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import { ComponentQualifier } from './component';
-import {
- FlowLocation,
- IssueChangelog,
- IssueChangelogDiff,
- Paging,
- TextRange,
- UserBase
-} from './types';
+import { FlowLocation, IssueChangelog, IssueChangelogDiff, Paging, TextRange } from './types';
+import { UserBase } from './users';
export enum RiskExposure {
LOW = 'LOW',
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+
+import { UserActive, UserBase } from './users';
+
export type Dict<T> = { [key: string]: T };
export type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
op?: string;
}
-export interface CoveredFile {
- key: string;
- longName: string;
- coveredLines: number;
-}
-
-export interface Coupon {
- billing?: {
- address?: string;
- country?: string;
- email?: string;
- name?: string;
- use?: string;
- };
- maxNcloc: number;
- planActiveUntil: string;
-}
-
-export interface CurrentUser {
- isLoggedIn: boolean;
- permissions?: { global: string[] };
- usingSonarLintConnectedMode?: boolean;
-}
-
-export interface CurrentUserSetting {
- key: CurrentUserSettingNames;
- value: string;
-}
-
-export type CurrentUserSettingNames =
- | 'notifications.optOut'
- | 'notifications.readDate'
- | 'tutorials.jenkins.skipBitbucketPreReqs';
-
export interface CustomMeasure {
createdAt?: string;
description?: string;
export type HealthType = 'RED' | 'YELLOW' | 'GREEN';
-export type HomePage =
- | { type: 'APPLICATION'; branch: string | undefined; component: string }
- | { type: 'ISSUES' }
- | { type: 'MY_ISSUES' }
- | { type: 'MY_PROJECTS' }
- | { type: 'PORTFOLIO'; component: string }
- | { type: 'PORTFOLIOS' }
- | { type: 'PROJECT'; branch: string | undefined; component: string }
- | { type: 'PROJECTS' };
-
-export type HomePageType =
- | 'APPLICATION'
- | 'ISSUES'
- | 'MY_ISSUES'
- | 'MY_PROJECTS'
- | 'PORTFOLIO'
- | 'PORTFOLIOS'
- | 'PROJECT'
- | 'PROJECTS';
-
export interface IdentityProvider {
backgroundColor: string;
helpMessage?: string;
open?: boolean;
}
-export interface LoggedInUser extends CurrentUser, UserActive {
- externalIdentity?: string;
- externalProvider?: string;
- groups: string[];
- homepage?: HomePage;
- isLoggedIn: true;
- local?: boolean;
- scmAccounts: string[];
- settings?: CurrentUserSetting[];
- sonarLintAdSeen?: boolean;
-}
-
export interface Measure extends MeasureIntern {
metric: string;
}
endOffset: number;
}
-export interface User extends UserBase {
- externalIdentity?: string;
- externalProvider?: string;
- groups?: string[];
- lastConnectionDate?: string;
- local: boolean;
- scmAccounts?: string[];
- tokensCount?: number;
-}
-
-export interface UserActive extends UserBase {
- active?: true;
- name: string;
-}
-
-export interface UserBase {
- active?: boolean;
- avatar?: string;
- email?: string;
- login: string;
- name?: string;
-}
-
export interface UserSelected extends UserActive {
selected: boolean;
}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2022 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.
+ */
+
+export interface CurrentUser {
+ isLoggedIn: boolean;
+ permissions?: { global: string[] };
+ usingSonarLintConnectedMode?: boolean;
+}
+
+export interface LoggedInUser extends CurrentUser, UserActive {
+ externalIdentity?: string;
+ externalProvider?: string;
+ groups: string[];
+ homepage?: HomePage;
+ isLoggedIn: true;
+ local?: boolean;
+ scmAccounts: string[];
+ settings?: CurrentUserSetting[];
+ sonarLintAdSeen?: boolean;
+}
+
+export type HomePage =
+ | { type: 'APPLICATION'; branch: string | undefined; component: string }
+ | { type: 'ISSUES' }
+ | { type: 'MY_ISSUES' }
+ | { type: 'MY_PROJECTS' }
+ | { type: 'PORTFOLIO'; component: string }
+ | { type: 'PORTFOLIOS' }
+ | { type: 'PROJECT'; branch: string | undefined; component: string }
+ | { type: 'PROJECTS' };
+
+export interface CurrentUserSetting {
+ key: CurrentUserSettingNames;
+ value: string;
+}
+
+export type CurrentUserSettingNames =
+ | 'notifications.optOut'
+ | 'notifications.readDate'
+ | 'tutorials.jenkins.skipBitbucketPreReqs';
+
+export interface UserActive extends UserBase {
+ active?: true;
+ name: string;
+}
+
+export interface User extends UserBase {
+ externalIdentity?: string;
+ externalProvider?: string;
+ groups?: string[];
+ lastConnectionDate?: string;
+ local: boolean;
+ scmAccounts?: string[];
+ tokensCount?: number;
+}
+
+export interface UserBase {
+ active?: boolean;
+ avatar?: string;
+ email?: string;
+ login: string;
+ name?: string;
+}
+
+export function isUserActive(user: UserBase): user is UserActive {
+ return user.active !== false && Boolean(user.name);
+}
+
+export function isLoggedIn(user: CurrentUser): user is LoggedInUser {
+ return user.isLoggedIn;
+}
onboarding.tutorial.with.jenkins.prereqs.step_by_step_guide=For a step by step guide on installing and configuring those plugins in Jenkins, visit the {link} documentation page.
onboarding.tutorial.with.jenkins.prereqs.step_by_step_guide.link=Analysis Prerequisites
onboarding.tutorial.with.jenkins.prereqs.following_are_recommendations=We recommend using the configuration in the following steps for the best results, but you can customize it as needed.
-onboarding.tutorial.with.jenkins.prereqs.skip_next_time=Don't show me the prerequisites next time
onboarding.tutorial.with.jenkins.prereqs.done=Configure Analysis
onboarding.tutorial.with.jenkins.multi_branch_pipeline.title=Create a Multibranch Pipeline Job
onboarding.tutorial.with.jenkins.multi_branch_pipeline.intro=Create a Multibranch Pipeline in order to automatically analyze all your branches and pull requests.