diff options
author | Jeremy Davis <jeremy.davis@sonarsource.com> | 2022-03-15 17:45:43 +0100 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2022-03-23 20:02:45 +0000 |
commit | 9a35b0e3e65302ee4f6c1b4cc2c5db71df5b0a5d (patch) | |
tree | 3c7dfb98f45b43a7165b3de25d1463903f16b29f /server | |
parent | 71f680aa1c432ea8bb18e1f5fd4e2d2d40a3ab8d (diff) | |
download | sonarqube-9a35b0e3e65302ee4f6c1b4cc2c5db71df5b0a5d.tar.gz sonarqube-9a35b0e3e65302ee4f6c1b4cc2c5db71df5b0a5d.zip |
SONAR-15914 Clean up redux
Diffstat (limited to 'server')
21 files changed, 171 insertions, 241 deletions
diff --git a/server/sonar-web/src/main/js/api/auth.ts b/server/sonar-web/src/main/js/api/auth.ts index d556401ff8d..958dc9f4175 100644 --- a/server/sonar-web/src/main/js/api/auth.ts +++ b/server/sonar-web/src/main/js/api/auth.ts @@ -19,7 +19,7 @@ */ import { request } from '../helpers/request'; -export function login(login: string, password: string): Promise<Response> { +export function logIn(login: string, password: string): Promise<Response> { return request('/api/authentication/login') .setMethod('POST') .setData({ login, password }) @@ -27,7 +27,7 @@ export function login(login: string, password: string): Promise<Response> { .then(basicCheckStatus); } -export function logout(): Promise<Response> { +export function logOut(): Promise<Response> { return request('/api/authentication/logout') .setMethod('POST') .submit() diff --git a/server/sonar-web/src/main/js/app/components/ComponentContainer.tsx b/server/sonar-web/src/main/js/app/components/ComponentContainer.tsx index e663080820a..fc98bc60e17 100644 --- a/server/sonar-web/src/main/js/app/components/ComponentContainer.tsx +++ b/server/sonar-web/src/main/js/app/components/ComponentContainer.tsx @@ -34,7 +34,7 @@ import { } from '../../helpers/branch-like'; import { HttpStatus } from '../../helpers/request'; import { getPortfolioUrl } from '../../helpers/urls'; -import { registerBranchStatus } from '../../store/rootActions'; +import { registerBranchStatus } from '../../store/branches'; import { ProjectAlmBindingConfigurationErrors, ProjectAlmBindingResponse diff --git a/server/sonar-web/src/main/js/apps/code/components/CodeApp.tsx b/server/sonar-web/src/main/js/apps/code/components/CodeApp.tsx index 34f37f04af9..57bb881e842 100644 --- a/server/sonar-web/src/main/js/apps/code/components/CodeApp.tsx +++ b/server/sonar-web/src/main/js/apps/code/components/CodeApp.tsx @@ -35,7 +35,7 @@ import { Alert } from '../../../components/ui/Alert'; import { isPullRequest, isSameBranchLike } from '../../../helpers/branch-like'; import { translate } from '../../../helpers/l10n'; import { getCodeUrl, getProjectUrl } from '../../../helpers/urls'; -import { fetchBranchStatus } from '../../../store/rootActions'; +import { fetchBranchStatus } from '../../../store/branches'; import { BranchLike } from '../../../types/branch-like'; import { isPortfolioLike } from '../../../types/component'; import { Breadcrumb, Component, ComponentMeasure, Dict, Issue, Metric } from '../../../types/types'; diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/App.tsx b/server/sonar-web/src/main/js/apps/component-measures/components/App.tsx index 4078382e7f9..ce61093edf2 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/components/App.tsx +++ b/server/sonar-web/src/main/js/apps/component-measures/components/App.tsx @@ -44,7 +44,7 @@ import { removeSideBarClass, removeWhitePageClass } from '../../../helpers/pages'; -import { fetchBranchStatus } from '../../../store/rootActions'; +import { fetchBranchStatus } from '../../../store/branches'; import { BranchLike } from '../../../types/branch-like'; import { ComponentQualifier, isPortfolioLike } from '../../../types/component'; import { diff --git a/server/sonar-web/src/main/js/apps/issues/components/AppContainer.tsx b/server/sonar-web/src/main/js/apps/issues/components/AppContainer.tsx index 1e3578afcb1..49e326575cb 100644 --- a/server/sonar-web/src/main/js/apps/issues/components/AppContainer.tsx +++ b/server/sonar-web/src/main/js/apps/issues/components/AppContainer.tsx @@ -23,7 +23,7 @@ import withCurrentUserContext from '../../../app/components/current-user/withCur import { withRouter } from '../../../components/hoc/withRouter'; import { lazyLoadComponent } from '../../../components/lazyLoadComponent'; import { parseIssueFromResponse } from '../../../helpers/issues'; -import { fetchBranchStatus } from '../../../store/rootActions'; +import { fetchBranchStatus } from '../../../store/branches'; import { Store } from '../../../store/rootReducer'; import { FetchIssuesPromise } from '../../../types/issues'; import { RawQuery } from '../../../types/types'; diff --git a/server/sonar-web/src/main/js/apps/issues/components/__tests__/AppContainer-test.tsx b/server/sonar-web/src/main/js/apps/issues/components/__tests__/AppContainer-test.tsx index b1543639017..bc78aeab32e 100644 --- a/server/sonar-web/src/main/js/apps/issues/components/__tests__/AppContainer-test.tsx +++ b/server/sonar-web/src/main/js/apps/issues/components/__tests__/AppContainer-test.tsx @@ -19,7 +19,7 @@ */ import { connect } from 'react-redux'; import { searchIssues } from '../../../../api/issues'; -import { fetchBranchStatus } from '../../../../store/rootActions'; +import { fetchBranchStatus } from '../../../../store/branches'; import '../AppContainer'; jest.mock('react-redux', () => ({ diff --git a/server/sonar-web/src/main/js/apps/overview/pullRequests/PullRequestOverview.tsx b/server/sonar-web/src/main/js/apps/overview/pullRequests/PullRequestOverview.tsx index a2866c937e1..bfb4c232ec3 100644 --- a/server/sonar-web/src/main/js/apps/overview/pullRequests/PullRequestOverview.tsx +++ b/server/sonar-web/src/main/js/apps/overview/pullRequests/PullRequestOverview.tsx @@ -28,7 +28,7 @@ import { getBranchLikeQuery } from '../../../helpers/branch-like'; import { translate } from '../../../helpers/l10n'; import { enhanceConditionWithMeasure, enhanceMeasuresWithMetrics } from '../../../helpers/measures'; import { isDefined } from '../../../helpers/types'; -import { fetchBranchStatus } from '../../../store/rootActions'; +import { fetchBranchStatus } from '../../../store/branches'; import { getBranchStatusByBranchLike, Store } from '../../../store/rootReducer'; import { BranchLike, PullRequest } from '../../../types/branch-like'; import { IssueType } from '../../../types/issues'; diff --git a/server/sonar-web/src/main/js/apps/security-hotspots/SecurityHotspotsApp.tsx b/server/sonar-web/src/main/js/apps/security-hotspots/SecurityHotspotsApp.tsx index e774afc2b45..2eaf52d2950 100644 --- a/server/sonar-web/src/main/js/apps/security-hotspots/SecurityHotspotsApp.tsx +++ b/server/sonar-web/src/main/js/apps/security-hotspots/SecurityHotspotsApp.tsx @@ -31,7 +31,7 @@ import { getBranchLikeQuery, isPullRequest, isSameBranchLike } from '../../helpe import { KeyboardCodes, KeyboardKeys } from '../../helpers/keycodes'; import { scrollToElement } from '../../helpers/scrolling'; import { getStandards } from '../../helpers/security-standard'; -import { fetchBranchStatus } from '../../store/rootActions'; +import { fetchBranchStatus } from '../../store/branches'; import { BranchLike } from '../../types/branch-like'; import { SecurityStandard, Standards } from '../../types/security'; import { diff --git a/server/sonar-web/src/main/js/apps/sessions/components/LoginContainer.tsx b/server/sonar-web/src/main/js/apps/sessions/components/LoginContainer.tsx index 197caadbd43..294c57e47e8 100644 --- a/server/sonar-web/src/main/js/apps/sessions/components/LoginContainer.tsx +++ b/server/sonar-web/src/main/js/apps/sessions/components/LoginContainer.tsx @@ -19,25 +19,18 @@ */ import { Location } from 'history'; import * as React from 'react'; -import { connect } from 'react-redux'; +import { logIn } from '../../../api/auth'; import { getIdentityProviders } from '../../../api/users'; +import addGlobalErrorMessage from '../../../app/utils/addGlobalErrorMessage'; import { getReturnUrl } from '../../../helpers/urls'; -import { doLogin } from '../../../store/rootActions'; import { IdentityProvider } from '../../../types/types'; import Login from './Login'; -interface OwnProps { +interface Props { location: Pick<Location, 'hash' | 'pathname' | 'query'> & { query: { advanced?: string; return_to?: string }; }; } - -interface DispatchToProps { - doLogin: (login: string, password: string) => Promise<void>; -} - -type Props = OwnProps & DispatchToProps; - interface State { identityProviders?: IdentityProvider[]; } @@ -55,7 +48,9 @@ export class LoginContainer extends React.PureComponent<Props, State> { this.setState({ identityProviders }); } }, - () => {} + () => { + /* already handled */ + } ); } @@ -67,8 +62,13 @@ export class LoginContainer extends React.PureComponent<Props, State> { window.location.href = getReturnUrl(this.props.location); }; - handleSubmit = (login: string, password: string) => { - return this.props.doLogin(login, password).then(this.handleSuccessfulLogin, () => {}); + handleSubmit = (id: string, password: string) => { + return logIn(id, password) + .then(this.handleSuccessfulLogin) + .catch(() => { + addGlobalErrorMessage('Authentication failed'); + return Promise.reject(); + }); }; render() { @@ -89,7 +89,4 @@ export class LoginContainer extends React.PureComponent<Props, State> { } } -const mapStateToProps = null; -const mapDispatchToProps = { doLogin: doLogin as any }; - -export default connect(mapStateToProps, mapDispatchToProps)(LoginContainer); +export default LoginContainer; diff --git a/server/sonar-web/src/main/js/apps/sessions/components/Logout.tsx b/server/sonar-web/src/main/js/apps/sessions/components/Logout.tsx index 3d5d250ec47..4e4cae3b245 100644 --- a/server/sonar-web/src/main/js/apps/sessions/components/Logout.tsx +++ b/server/sonar-web/src/main/js/apps/sessions/components/Logout.tsx @@ -18,26 +18,23 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import * as React from 'react'; -import { connect } from 'react-redux'; +import { logOut } from '../../../api/auth'; import GlobalMessagesContainer from '../../../app/components/GlobalMessagesContainer'; import RecentHistory from '../../../app/components/RecentHistory'; +import addGlobalErrorMessage from '../../../app/utils/addGlobalErrorMessage'; import { translate } from '../../../helpers/l10n'; import { getBaseUrl } from '../../../helpers/system'; -import { doLogout } from '../../../store/rootActions'; -interface Props { - doLogout: () => Promise<void>; -} - -export class Logout extends React.PureComponent<Props> { +export class Logout extends React.PureComponent<{}> { componentDidMount() { - this.props.doLogout().then( - () => { + logOut() + .then(() => { RecentHistory.clear(); window.location.replace(getBaseUrl() + '/'); - }, - () => {} - ); + }) + .catch(() => { + addGlobalErrorMessage('Logout failed'); + }); } render() { @@ -50,8 +47,4 @@ export class Logout extends React.PureComponent<Props> { } } -const mapStateToProps = () => ({}); - -const mapDispatchToProps = { doLogout }; - -export default connect(mapStateToProps, mapDispatchToProps)(Logout as any); +export default Logout; diff --git a/server/sonar-web/src/main/js/apps/sessions/components/__tests__/LoginContainer-test.tsx b/server/sonar-web/src/main/js/apps/sessions/components/__tests__/LoginContainer-test.tsx index f09d24aba35..510f7c4074f 100644 --- a/server/sonar-web/src/main/js/apps/sessions/components/__tests__/LoginContainer-test.tsx +++ b/server/sonar-web/src/main/js/apps/sessions/components/__tests__/LoginContainer-test.tsx @@ -19,6 +19,7 @@ */ import { shallow } from 'enzyme'; import * as React from 'react'; +import { logIn } from '../../../../api/auth'; import { getIdentityProviders } from '../../../../api/users'; import { mockLocation } from '../../../../helpers/testMocks'; import { waitAndUpdate } from '../../../../helpers/testUtils'; @@ -33,6 +34,10 @@ jest.mock('../../../../api/users', () => { }; }); +jest.mock('../../../../api/auth', () => ({ + logIn: jest.fn().mockResolvedValue({}) +})); + beforeEach(jest.clearAllMocks); it('should render correctly', async () => { @@ -53,14 +58,12 @@ it('should not provide any options if no IdPs are present', async () => { }); it('should handle submission', () => { - const doLogin = jest.fn().mockResolvedValue(null); - const wrapper = shallowRender({ doLogin }); + (logIn as jest.Mock).mockResolvedValue(null); + const wrapper = shallowRender(); wrapper.instance().handleSubmit('user', 'pass'); - expect(doLogin).toBeCalledWith('user', 'pass'); + expect(logIn).toBeCalledWith('user', 'pass'); }); function shallowRender(props: Partial<LoginContainer['props']> = {}) { - return shallow<LoginContainer>( - <LoginContainer doLogin={jest.fn()} location={mockLocation()} {...props} /> - ); + return shallow<LoginContainer>(<LoginContainer location={mockLocation()} {...props} />); } diff --git a/server/sonar-web/src/main/js/apps/sessions/components/__tests__/Logout-test.tsx b/server/sonar-web/src/main/js/apps/sessions/components/__tests__/Logout-test.tsx index dcb44bf2ed9..5b0d0012913 100644 --- a/server/sonar-web/src/main/js/apps/sessions/components/__tests__/Logout-test.tsx +++ b/server/sonar-web/src/main/js/apps/sessions/components/__tests__/Logout-test.tsx @@ -19,11 +19,21 @@ */ import { shallow } from 'enzyme'; import * as React from 'react'; +import { logOut } from '../../../../api/auth'; +import addGlobalErrorMessage from '../../../../app/utils/addGlobalErrorMessage'; import { waitAndUpdate } from '../../../../helpers/testUtils'; import { Logout } from '../Logout'; -const originalLocation = window.location; +jest.mock('../../../../api/auth', () => ({ + logOut: jest.fn().mockResolvedValue(true) +})); + +jest.mock('../../../../app/utils/addGlobalErrorMessage', () => ({ + __esModule: true, + default: jest.fn() +})); +const originalLocation = window.location; beforeAll(() => { const location = { ...window.location, @@ -47,26 +57,28 @@ afterAll(() => { }); it('should logout correctly', async () => { - const doLogout = jest.fn().mockResolvedValue(true); + (logOut as jest.Mock).mockResolvedValue(true); - const wrapper = shallowRender({ doLogout }); + const wrapper = shallowRender(); await waitAndUpdate(wrapper); - expect(doLogout).toHaveBeenCalled(); + expect(logOut).toHaveBeenCalled(); expect(window.location.replace).toHaveBeenCalledWith('/'); + expect(addGlobalErrorMessage).not.toHaveBeenCalled(); }); it('should not redirect if logout fails', async () => { - const doLogout = jest.fn().mockRejectedValue(false); + (logOut as jest.Mock).mockRejectedValue(false); - const wrapper = shallowRender({ doLogout }); + const wrapper = shallowRender(); await waitAndUpdate(wrapper); - expect(doLogout).toHaveBeenCalled(); + expect(logOut).toHaveBeenCalled(); expect(window.location.replace).not.toHaveBeenCalled(); + expect(addGlobalErrorMessage).toHaveBeenCalled(); expect(wrapper).toMatchSnapshot(); }); -function shallowRender(props: Partial<Logout['props']> = {}) { - return shallow(<Logout doLogout={jest.fn()} {...props} />); +function shallowRender() { + return shallow(<Logout />); } diff --git a/server/sonar-web/src/main/js/components/workspace/WorkspaceComponentViewer.tsx b/server/sonar-web/src/main/js/components/workspace/WorkspaceComponentViewer.tsx index ae5700e8cc9..23cf4dfcd3c 100644 --- a/server/sonar-web/src/main/js/components/workspace/WorkspaceComponentViewer.tsx +++ b/server/sonar-web/src/main/js/components/workspace/WorkspaceComponentViewer.tsx @@ -23,7 +23,7 @@ import { connect } from 'react-redux'; import { getParents } from '../../api/components'; import { isPullRequest } from '../../helpers/branch-like'; import { scrollToElement } from '../../helpers/scrolling'; -import { fetchBranchStatus } from '../../store/rootActions'; +import { fetchBranchStatus } from '../../store/branches'; import { BranchLike } from '../../types/branch-like'; import { Issue, SourceViewerFile } from '../../types/types'; import SourceViewer from '../SourceViewer/SourceViewer'; diff --git a/server/sonar-web/src/main/js/helpers/__tests__/branches-test.ts b/server/sonar-web/src/main/js/helpers/__tests__/branch-like-test.ts index 639a3ea96b6..639a3ea96b6 100644 --- a/server/sonar-web/src/main/js/helpers/__tests__/branches-test.ts +++ b/server/sonar-web/src/main/js/helpers/__tests__/branch-like-test.ts diff --git a/server/sonar-web/src/main/js/store/__tests__/branches-test.ts b/server/sonar-web/src/main/js/store/__tests__/branches-test.ts index 9ef4f9d1ae6..eb52257e42a 100644 --- a/server/sonar-web/src/main/js/store/__tests__/branches-test.ts +++ b/server/sonar-web/src/main/js/store/__tests__/branches-test.ts @@ -24,7 +24,9 @@ import { BranchLike } from '../../types/branch-like'; import { QualityGateStatusCondition } from '../../types/quality-gates'; import { Status } from '../../types/types'; import reducer, { + fetchBranchStatus, getBranchStatusByBranchLike, + registerBranchStatus, registerBranchStatusAction, State } from '../branches'; @@ -82,3 +84,66 @@ function convertToState(items: TestArgs[] = []) { return state; } + +jest.mock('../../app/utils/addGlobalErrorMessage', () => ({ + __esModule: true, + default: jest.fn() +})); + +jest.mock('../../api/quality-gates', () => { + const { mockQualityGateProjectStatus } = jest.requireActual('../../helpers/mocks/quality-gates'); + return { + getQualityGateProjectStatus: jest.fn().mockResolvedValue( + mockQualityGateProjectStatus({ + conditions: [ + { + actualValue: '10', + comparator: 'GT', + errorThreshold: '0', + metricKey: 'foo', + periodIndex: 1, + status: 'ERROR' + } + ] + }) + ) + }; +}); + +describe('branch store actions', () => { + const branchLike = mockBranch(); + const component = 'foo'; + const status = 'OK'; + + it('correctly registers a new branch status', () => { + const dispatch = jest.fn(); + + registerBranchStatus(branchLike, component, status)(dispatch); + expect(dispatch).toBeCalledWith({ + branchLike, + component, + status, + type: 'REGISTER_BRANCH_STATUS' + }); + }); + + it('correctly fetches a branch status', async () => { + const dispatch = jest.fn(); + + fetchBranchStatus(branchLike, component)(dispatch); + await new Promise(setImmediate); + + expect(dispatch).toBeCalledWith({ + branchLike, + component, + status, + conditions: [ + mockQualityGateStatusCondition({ + period: 1 + }) + ], + ignoredConditions: false, + type: 'REGISTER_BRANCH_STATUS' + }); + }); +}); diff --git a/server/sonar-web/src/main/js/store/__tests__/rootActions-test.tsx b/server/sonar-web/src/main/js/store/__tests__/rootActions-test.tsx deleted file mode 100644 index f53d45a86ed..00000000000 --- a/server/sonar-web/src/main/js/store/__tests__/rootActions-test.tsx +++ /dev/null @@ -1,82 +0,0 @@ -/* - * 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 { mockBranch } from '../../helpers/mocks/branch-like'; -import { mockQualityGateStatusCondition } from '../../helpers/mocks/quality-gates'; -import { registerBranchStatusAction } from '../branches'; -import { fetchBranchStatus, registerBranchStatus } from '../rootActions'; - -jest.mock('../branches', () => ({ - ...jest.requireActual('../branches'), - registerBranchStatusAction: jest.fn() -})); - -jest.mock('../../api/quality-gates', () => { - const { mockQualityGateProjectStatus } = jest.requireActual('../../helpers/mocks/quality-gates'); - return { - getQualityGateProjectStatus: jest.fn().mockResolvedValue( - mockQualityGateProjectStatus({ - conditions: [ - { - actualValue: '10', - comparator: 'GT', - errorThreshold: '0', - metricKey: 'foo', - periodIndex: 1, - status: 'ERROR' - } - ] - }) - ) - }; -}); - -describe('branch store actions', () => { - const branchLike = mockBranch(); - const component = 'foo'; - const status = 'OK'; - - it('correctly registers a new branch status', () => { - const dispatch = jest.fn(); - - registerBranchStatus(branchLike, component, status)(dispatch); - expect(registerBranchStatusAction).toBeCalledWith(branchLike, component, status); - expect(dispatch).toBeCalled(); - }); - - it('correctly fetches a branch status', async () => { - const dispatch = jest.fn(); - - fetchBranchStatus(branchLike, component)(dispatch); - await new Promise(setImmediate); - - expect(registerBranchStatusAction).toBeCalledWith( - branchLike, - component, - status, - [ - mockQualityGateStatusCondition({ - period: 1 - }) - ], - false - ); - expect(dispatch).toBeCalled(); - }); -}); diff --git a/server/sonar-web/src/main/js/store/__tests__/rootReducers-test.tsx b/server/sonar-web/src/main/js/store/__tests__/rootReducers-test.tsx index 0f97725f12a..c6cffde06bd 100644 --- a/server/sonar-web/src/main/js/store/__tests__/rootReducers-test.tsx +++ b/server/sonar-web/src/main/js/store/__tests__/rootReducers-test.tsx @@ -21,17 +21,12 @@ import { mockPullRequest } from '../../helpers/mocks/branch-like'; import * as fromBranches from '../branches'; import { getBranchStatusByBranchLike, Store } from '../rootReducer'; -jest.mock('../branches', () => { - return { - ...jest.requireActual('../branches'), - getBranchStatusByBranchLike: jest.fn() - }; -}); - it('correctly reduce state for branches', () => { - const branches = {}; + const spiedOn = jest.spyOn(fromBranches, 'getBranchStatusByBranchLike').mockReturnValueOnce({}); + + const branches = { byComponent: {} }; const component = 'foo'; const branchLike = mockPullRequest(); getBranchStatusByBranchLike({ branches } as Store, component, branchLike); - expect(fromBranches.getBranchStatusByBranchLike).toBeCalledWith(branches, component, branchLike); + expect(spiedOn).toBeCalledWith(branches, component, branchLike); }); diff --git a/server/sonar-web/src/main/js/store/branches.ts b/server/sonar-web/src/main/js/store/branches.ts index c24b94bceb7..e6e4dada333 100644 --- a/server/sonar-web/src/main/js/store/branches.ts +++ b/server/sonar-web/src/main/js/store/branches.ts @@ -17,11 +17,15 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -import { getBranchLikeKey } from '../helpers/branch-like'; +import { Dispatch } from 'redux'; +import { getQualityGateProjectStatus } from '../api/quality-gates'; +import addGlobalErrorMessage from '../app/utils/addGlobalErrorMessage'; +import { getBranchLikeKey, getBranchLikeQuery } from '../helpers/branch-like'; +import { extractStatusConditionsFromProjectStatus } from '../helpers/qualityGates'; +import { ActionType } from '../types/actions'; import { BranchLike } from '../types/branch-like'; import { QualityGateStatusCondition } from '../types/quality-gates'; import { Dict, Status } from '../types/types'; -import { ActionType } from './utils/actions'; export interface BranchStatusData { conditions?: QualityGateStatusCondition[]; @@ -56,7 +60,7 @@ export function registerBranchStatusAction( }; } -export default function(state: State = { byComponent: {} }, action: Action): State { +export default function branchesReducer(state: State = { byComponent: {} }, action: Action): State { if (action.type === Actions.RegisterBranchStatus) { const { component, conditions, branchLike, ignoredConditions, status } = action; const branchLikeKey = getBranchLikeKey(branchLike); @@ -86,3 +90,26 @@ export function getBranchStatusByBranchLike( const branchLikeKey = getBranchLikeKey(branchLike); return state.byComponent[component] && state.byComponent[component][branchLikeKey]; } + +export function fetchBranchStatus(branchLike: BranchLike, projectKey: string) { + return (dispatch: Dispatch) => { + getQualityGateProjectStatus({ projectKey, ...getBranchLikeQuery(branchLike) }).then( + projectStatus => { + const { ignoredConditions, status } = projectStatus; + const conditions = extractStatusConditionsFromProjectStatus(projectStatus); + dispatch( + registerBranchStatusAction(branchLike, projectKey, status, conditions, ignoredConditions) + ); + }, + () => { + addGlobalErrorMessage('Fetching Quality Gate status failed'); + } + ); + }; +} + +export function registerBranchStatus(branchLike: BranchLike, component: string, status: Status) { + return (dispatch: Dispatch) => { + dispatch(registerBranchStatusAction(branchLike, component, status)); + }; +} diff --git a/server/sonar-web/src/main/js/store/globalMessages.ts b/server/sonar-web/src/main/js/store/globalMessages.ts index a220d15cb47..c64ac9dafdb 100644 --- a/server/sonar-web/src/main/js/store/globalMessages.ts +++ b/server/sonar-web/src/main/js/store/globalMessages.ts @@ -19,7 +19,7 @@ */ import { uniqueId } from 'lodash'; import { Dispatch } from 'redux'; -import { ActionType } from './utils/actions'; +import { ActionType } from '../types/actions'; enum MessageLevel { Error = 'ERROR', @@ -32,6 +32,10 @@ interface Message { level: MessageLevel; } +const MESSAGE_DISPLAY_TIME = 5000; + +/* Action creators */ + function addGlobalMessageActionCreator(id: string, message: string, level: MessageLevel) { return { type: 'ADD_GLOBAL_MESSAGE', message, level, id }; } @@ -40,20 +44,15 @@ export function closeGlobalMessage(id: string) { return { type: 'CLOSE_GLOBAL_MESSAGE', id }; } -export function closeAllGlobalMessages() { - return { type: 'CLOSE_ALL_GLOBAL_MESSAGES' }; -} - type Action = | ActionType<typeof addGlobalMessageActionCreator, 'ADD_GLOBAL_MESSAGE'> - | ActionType<typeof closeGlobalMessage, 'CLOSE_GLOBAL_MESSAGE'> - | ActionType<typeof closeAllGlobalMessages, 'CLOSE_ALL_GLOBAL_MESSAGES'>; + | ActionType<typeof closeGlobalMessage, 'CLOSE_GLOBAL_MESSAGE'>; function addGlobalMessage(message: string, level: MessageLevel) { return (dispatch: Dispatch) => { const id = uniqueId('global-message-'); dispatch(addGlobalMessageActionCreator(id, message, level)); - setTimeout(() => dispatch(closeGlobalMessage(id)), 5000); + setTimeout(() => dispatch(closeGlobalMessage(id)), MESSAGE_DISPLAY_TIME); }; } @@ -67,7 +66,7 @@ export function addGlobalSuccessMessage(message: string) { export type State = Message[]; -export default function(state: State = [], action: Action): State { +export default function globalMessagesReducer(state: State = [], action: Action): State { switch (action.type) { case 'ADD_GLOBAL_MESSAGE': return [{ id: action.id, message: action.message, level: action.level }]; @@ -75,8 +74,6 @@ export default function(state: State = [], action: Action): State { case 'CLOSE_GLOBAL_MESSAGE': return state.filter(message => message.id !== action.id); - case 'CLOSE_ALL_GLOBAL_MESSAGES': - return []; default: return state; } diff --git a/server/sonar-web/src/main/js/store/rootActions.ts b/server/sonar-web/src/main/js/store/rootActions.ts deleted file mode 100644 index fd2d12cc351..00000000000 --- a/server/sonar-web/src/main/js/store/rootActions.ts +++ /dev/null @@ -1,77 +0,0 @@ -/* - * 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 { Dispatch } from 'redux'; -import * as auth from '../api/auth'; -import { getQualityGateProjectStatus } from '../api/quality-gates'; -import { getBranchLikeQuery } from '../helpers/branch-like'; -import { extractStatusConditionsFromProjectStatus } from '../helpers/qualityGates'; -import { BranchLike } from '../types/branch-like'; -import { Status } from '../types/types'; -import { registerBranchStatusAction } from './branches'; -import { addGlobalErrorMessage } from './globalMessages'; - -export function fetchBranchStatus(branchLike: BranchLike, projectKey: string) { - return (dispatch: Dispatch<any>) => { - getQualityGateProjectStatus({ projectKey, ...getBranchLikeQuery(branchLike) }).then( - projectStatus => { - const { ignoredConditions, status } = projectStatus; - const conditions = extractStatusConditionsFromProjectStatus(projectStatus); - dispatch( - registerBranchStatusAction(branchLike, projectKey, status, conditions, ignoredConditions) - ); - }, - () => { - dispatch(addGlobalErrorMessage('Fetching Quality Gate status failed')); - } - ); - }; -} - -export function doLogin(login: string, password: string) { - return (dispatch: Dispatch<any>) => - auth.login(login, password).then( - () => { - /* everything is fine */ - }, - () => { - dispatch(addGlobalErrorMessage('Authentication failed')); - return Promise.reject(); - } - ); -} - -export function doLogout() { - return (dispatch: Dispatch<any>) => - auth.logout().then( - () => { - /* everything is fine */ - }, - () => { - dispatch(addGlobalErrorMessage('Logout failed')); - return Promise.reject(); - } - ); -} - -export function registerBranchStatus(branchLike: BranchLike, component: string, status: Status) { - return (dispatch: Dispatch) => { - dispatch(registerBranchStatusAction(branchLike, component, status)); - }; -} diff --git a/server/sonar-web/src/main/js/store/utils/actions.ts b/server/sonar-web/src/main/js/types/actions.ts index 1e340e07cf0..1e340e07cf0 100644 --- a/server/sonar-web/src/main/js/store/utils/actions.ts +++ b/server/sonar-web/src/main/js/types/actions.ts |