From cb8126d2d05acc3605fb233c68b935de4dc74214 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Gr=C3=A9goire=20Aubert?= Date: Wed, 4 Oct 2017 18:14:49 +0200 Subject: [PATCH] SONAR-9925 Rewrite session to typescript --- server/sonar-web/src/main/js/api/users.ts | 9 ++- ...SimpleContainer.js => SimpleContainer.tsx} | 19 +++--- .../{LoginForm.js => LoginForm.tsx} | 59 +++++++++---------- ...ormContainer.js => LoginFormContainer.tsx} | 37 ++++++------ .../components/{Logout.js => Logout.tsx} | 28 +++++---- .../{OAuthProviders.js => OAuthProviders.tsx} | 41 +++++-------- ...ntainer.js => SimpleSessionsContainer.tsx} | 13 ++-- .../apps/sessions/components/Unauthorized.tsx | 13 ++-- .../{LoginForm-test.js => LoginForm-test.tsx} | 3 +- ...m-test.js.snap => LoginForm-test.tsx.snap} | 23 ++++---- .../resources/org/sonar/l10n/core.properties | 3 + ...ot_in_log_when_unauthorized_exception.html | 2 +- ...henticate_when_not_allowed_to_sign_up.html | 2 +- ...ot_in_log_when_unauthorized_exception.html | 2 +- ...henticate_when_not_allowed_to_sign_up.html | 2 +- 15 files changed, 125 insertions(+), 131 deletions(-) rename server/sonar-web/src/main/js/app/components/{SimpleContainer.js => SimpleContainer.tsx} (87%) rename server/sonar-web/src/main/js/apps/sessions/components/{LoginForm.js => LoginForm.tsx} (76%) rename server/sonar-web/src/main/js/apps/sessions/components/{LoginFormContainer.js => LoginFormContainer.tsx} (72%) rename server/sonar-web/src/main/js/apps/sessions/components/{Logout.js => Logout.tsx} (81%) rename server/sonar-web/src/main/js/apps/sessions/components/{OAuthProviders.js => OAuthProviders.tsx} (61%) rename server/sonar-web/src/main/js/apps/sessions/components/{SimpleSessionsContainer.js => SimpleSessionsContainer.tsx} (83%) rename server/sonar-web/src/main/js/apps/sessions/components/__tests__/{LoginForm-test.js => LoginForm-test.tsx} (98%) rename server/sonar-web/src/main/js/apps/sessions/components/__tests__/__snapshots__/{LoginForm-test.js.snap => LoginForm-test.tsx.snap} (93%) diff --git a/server/sonar-web/src/main/js/api/users.ts b/server/sonar-web/src/main/js/api/users.ts index 07a5d7996d3..f42c362fc74 100644 --- a/server/sonar-web/src/main/js/api/users.ts +++ b/server/sonar-web/src/main/js/api/users.ts @@ -19,6 +19,13 @@ */ import { getJSON, post, RequestData } from '../helpers/request'; +export interface IdentityProvider { + backgroundColor: string; + iconPath: string; + key: string; + name: string; +} + export function getCurrentUser(): Promise { return getJSON('/api/users/current'); } @@ -43,7 +50,7 @@ export function getUserGroups(login: string, organization?: string): Promise { +export function getIdentityProviders(): Promise<{ identityProviders: IdentityProvider[] }> { return getJSON('/api/users/identity_providers'); } diff --git a/server/sonar-web/src/main/js/app/components/SimpleContainer.js b/server/sonar-web/src/main/js/app/components/SimpleContainer.tsx similarity index 87% rename from server/sonar-web/src/main/js/app/components/SimpleContainer.js rename to server/sonar-web/src/main/js/app/components/SimpleContainer.tsx index 02596356d31..51c4336afde 100644 --- a/server/sonar-web/src/main/js/app/components/SimpleContainer.js +++ b/server/sonar-web/src/main/js/app/components/SimpleContainer.tsx @@ -17,21 +17,16 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -// @flow -import React from 'react'; +import * as React from 'react'; import GlobalFooterContainer from './GlobalFooterContainer'; import NavBar from '../../components/nav/NavBar'; -/*:: -type Props = { - children?: React.Element<*> | Array>, - hideLoggedInInfo?: boolean -}; -*/ - -export default class SimpleContainer extends React.PureComponent { - /*:: props: Props; */ +interface Props { + children?: React.ReactNode; + hideLoggedInInfo?: boolean; +} +export default class SimpleContainer extends React.PureComponent { componentDidMount() { const html = document.querySelector('html'); if (html) { @@ -50,7 +45,7 @@ export default class SimpleContainer extends React.PureComponent { return (
- +
diff --git a/server/sonar-web/src/main/js/apps/sessions/components/LoginForm.js b/server/sonar-web/src/main/js/apps/sessions/components/LoginForm.tsx similarity index 76% rename from server/sonar-web/src/main/js/apps/sessions/components/LoginForm.js rename to server/sonar-web/src/main/js/apps/sessions/components/LoginForm.tsx index 4ae970f2481..362e7f86dba 100644 --- a/server/sonar-web/src/main/js/apps/sessions/components/LoginForm.js +++ b/server/sonar-web/src/main/js/apps/sessions/components/LoginForm.tsx @@ -17,37 +17,26 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -// @flow -import React from 'react'; +import * as React from 'react'; +import { Link } from 'react-router'; import OAuthProviders from './OAuthProviders'; import GlobalMessagesContainer from '../../../app/components/GlobalMessagesContainer'; import { translate } from '../../../helpers/l10n'; +import { IdentityProvider } from '../../../api/users'; -/*:: -type Props = { - identityProviders: Array<{ - backgroundColor: string, - iconPath: string, - key: string, - name: string - }>, - onSubmit: (string, string) => void -}; -*/ - -/*:: -type State = { - collapsed: boolean, - login: string, - password: string -}; -*/ +interface Props { + identityProviders: IdentityProvider[]; + onSubmit: (login: string, password: string) => void; +} -export default class LoginForm extends React.PureComponent { - /*:: props: Props; */ - /*:: state: State; */ +interface State { + collapsed: boolean; + login: string; + password: string; +} - constructor(props /*: Props */) { +export default class LoginForm extends React.PureComponent { + constructor(props: Props) { super(props); this.state = { collapsed: props.identityProviders.length > 0, @@ -56,16 +45,22 @@ export default class LoginForm extends React.PureComponent { }; } - handleSubmit = (event /*: Event */) => { + handleSubmit = (event: React.SyntheticEvent) => { event.preventDefault(); this.props.onSubmit(this.state.login, this.state.password); }; - handleMoreOptionsClick = (event /*: Event */) => { + handleMoreOptionsClick = (event: React.SyntheticEvent) => { event.preventDefault(); this.setState({ collapsed: false }); }; + handleLoginChange = (event: React.SyntheticEvent) => + this.setState({ login: event.currentTarget.value }); + + handlePwdChange = (event: React.SyntheticEvent) => + this.setState({ password: event.currentTarget.value }); + render() { return (
@@ -97,12 +92,12 @@ export default class LoginForm extends React.PureComponent { id="login" name="login" className="login-input" - maxLength="255" + maxLength={255} required={true} autoFocus={true} placeholder={translate('login')} value={this.state.login} - onChange={e => this.setState({ login: e.target.value })} + onChange={this.handleLoginChange} />
@@ -118,7 +113,7 @@ export default class LoginForm extends React.PureComponent { required={true} placeholder={translate('password')} value={this.state.password} - onChange={e => this.setState({ password: e.target.value })} + onChange={this.handlePwdChange} />
@@ -127,9 +122,9 @@ export default class LoginForm extends React.PureComponent { - + {translate('cancel')} - +
diff --git a/server/sonar-web/src/main/js/apps/sessions/components/LoginFormContainer.js b/server/sonar-web/src/main/js/apps/sessions/components/LoginFormContainer.tsx similarity index 72% rename from server/sonar-web/src/main/js/apps/sessions/components/LoginFormContainer.js rename to server/sonar-web/src/main/js/apps/sessions/components/LoginFormContainer.tsx index fe2197fdf6f..2c2152bb61b 100644 --- a/server/sonar-web/src/main/js/apps/sessions/components/LoginFormContainer.js +++ b/server/sonar-web/src/main/js/apps/sessions/components/LoginFormContainer.tsx @@ -17,23 +17,26 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -// @flow -import React from 'react'; -import PropTypes from 'prop-types'; +import * as React from 'react'; import { connect } from 'react-redux'; import LoginForm from './LoginForm'; import { doLogin } from '../../../store/rootActions'; import { getAppState } from '../../../store/rootReducer'; -import { getIdentityProviders } from '../../../api/users'; +import { IdentityProvider, getIdentityProviders } from '../../../api/users'; +import { getBaseUrl } from '../../../helpers/urls'; -class LoginFormContainer extends React.PureComponent { - /*:: mounted: boolean; */ +interface Props { + doLogin: (login: string, password: string) => Promise; + location: { hash?: string; pathName: string; query: { return_to?: string } }; +} - static propTypes = { - location: PropTypes.object.isRequired - }; +interface State { + identityProviders?: IdentityProvider[]; +} - state = {}; +class LoginFormContainer extends React.PureComponent { + mounted: boolean; + state: State = {}; componentDidMount() { this.mounted = true; @@ -51,14 +54,12 @@ class LoginFormContainer extends React.PureComponent { handleSuccessfulLogin = () => { const { location } = this.props; const queryReturnTo = location.query['return_to']; - const returnTo = queryReturnTo ? `${queryReturnTo}${location.hash}` : `${window.baseUrl}/`; - window.location = returnTo; + const returnTo = queryReturnTo ? `${queryReturnTo}${location.hash}` : `${getBaseUrl()}/`; + window.location.href = returnTo; }; - handleSubmit = (login /*: string */, password /*: string */) => { - this.props.doLogin(login, password).then(this.handleSuccessfulLogin, () => { - /* do nothing */ - }); + handleSubmit = (login: string, password: string) => { + this.props.doLogin(login, password).then(this.handleSuccessfulLogin, () => {}); }; render() { @@ -72,10 +73,10 @@ class LoginFormContainer extends React.PureComponent { } } -const mapStateToProps = state => ({ +const mapStateToProps = (state: any) => ({ appState: getAppState(state) }); const mapDispatchToProps = { doLogin }; -export default connect(mapStateToProps, mapDispatchToProps)(LoginFormContainer); +export default connect(mapStateToProps, mapDispatchToProps)(LoginFormContainer as any); diff --git a/server/sonar-web/src/main/js/apps/sessions/components/Logout.js b/server/sonar-web/src/main/js/apps/sessions/components/Logout.tsx similarity index 81% rename from server/sonar-web/src/main/js/apps/sessions/components/Logout.js rename to server/sonar-web/src/main/js/apps/sessions/components/Logout.tsx index 736c4cc6372..b90ff4c42ae 100644 --- a/server/sonar-web/src/main/js/apps/sessions/components/Logout.js +++ b/server/sonar-web/src/main/js/apps/sessions/components/Logout.tsx @@ -17,25 +17,27 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -// @flow -import React from 'react'; +import * as React from 'react'; import { connect } from 'react-redux'; import GlobalMessagesContainer from '../../../app/components/GlobalMessagesContainer'; +import RecentHistory from '../../../app/components/RecentHistory'; import { doLogout } from '../../../store/rootActions'; import { translate } from '../../../helpers/l10n'; -import RecentHistory from '../../../app/components/RecentHistory'; +import { getBaseUrl } from '../../../helpers/urls'; -class Logout extends React.PureComponent { +interface Props { + doLogout: () => Promise; +} + +class Logout extends React.PureComponent { componentDidMount() { - this.props - .doLogout() - .then(() => { + this.props.doLogout().then( + () => { RecentHistory.clear(); - window.location = window.baseUrl + '/'; - }) - .catch(() => { - /* do nothing */ - }); + window.location.href = getBaseUrl() + '/'; + }, + () => {} + ); } render() { @@ -52,4 +54,4 @@ const mapStateToProps = () => ({}); const mapDispatchToProps = { doLogout }; -export default connect(mapStateToProps, mapDispatchToProps)(Logout); +export default connect(mapStateToProps, mapDispatchToProps)(Logout as any); diff --git a/server/sonar-web/src/main/js/apps/sessions/components/OAuthProviders.js b/server/sonar-web/src/main/js/apps/sessions/components/OAuthProviders.tsx similarity index 61% rename from server/sonar-web/src/main/js/apps/sessions/components/OAuthProviders.js rename to server/sonar-web/src/main/js/apps/sessions/components/OAuthProviders.tsx index d06a2019558..973f8b31021 100644 --- a/server/sonar-web/src/main/js/apps/sessions/components/OAuthProviders.js +++ b/server/sonar-web/src/main/js/apps/sessions/components/OAuthProviders.tsx @@ -17,43 +17,34 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -// @flow -import React from 'react'; +import * as React from 'react'; import { translateWithParameters } from '../../../helpers/l10n'; +import { IdentityProvider } from '../../../api/users'; +import { getBaseUrl } from '../../../helpers/urls'; -/*:: -type Props = { - formatLabel?: string => string, - identityProviders: Array<{ - backgroundColor: string, - iconPath: string, - key: string, - name: string - }> -}; -*/ +interface Props { + formatLabel?: (name: string) => string; + identityProviders: IdentityProvider[]; +} -export default function OAuthProviders(props /*: Props */) { +export default function OAuthProviders(props: Props) { + const formatLabel = props.formatLabel || defaultFormatLabel; return (
    {props.identityProviders.map(identityProvider => (
  • + title={formatLabel(identityProvider.name)}> {identityProvider.name} - - {/* $FlowFixMe formatLabel is always defined through defaultProps */} - {props.formatLabel(identityProvider.name)} - + {formatLabel(identityProvider.name)}
  • ))} @@ -62,6 +53,6 @@ export default function OAuthProviders(props /*: Props */) { ); } -OAuthProviders.defaultProps = { - formatLabel: (name /*: string */) => translateWithParameters('login.login_with_x', name) -}; +function defaultFormatLabel(name: string) { + return translateWithParameters('login.login_with_x', name); +} diff --git a/server/sonar-web/src/main/js/apps/sessions/components/SimpleSessionsContainer.js b/server/sonar-web/src/main/js/apps/sessions/components/SimpleSessionsContainer.tsx similarity index 83% rename from server/sonar-web/src/main/js/apps/sessions/components/SimpleSessionsContainer.js rename to server/sonar-web/src/main/js/apps/sessions/components/SimpleSessionsContainer.tsx index 29efdcd38a9..b29c1e494ee 100644 --- a/server/sonar-web/src/main/js/apps/sessions/components/SimpleSessionsContainer.js +++ b/server/sonar-web/src/main/js/apps/sessions/components/SimpleSessionsContainer.tsx @@ -17,16 +17,13 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -// @flow -import React from 'react'; +import * as React from 'react'; import SimpleContainer from '../../../app/components/SimpleContainer'; -/*:: -type Props = { - children?: React.Element<*> | Array> -}; -*/ +interface Props { + children?: React.ReactElement; +} -export default function SimpleSessionsContainer({ children } /*: Props */) { +export default function SimpleSessionsContainer({ children }: Props) { return {children}; } diff --git a/server/sonar-web/src/main/js/apps/sessions/components/Unauthorized.tsx b/server/sonar-web/src/main/js/apps/sessions/components/Unauthorized.tsx index 12bc8b8724c..cb12caa296e 100644 --- a/server/sonar-web/src/main/js/apps/sessions/components/Unauthorized.tsx +++ b/server/sonar-web/src/main/js/apps/sessions/components/Unauthorized.tsx @@ -19,6 +19,7 @@ */ import * as React from 'react'; import { Link } from 'react-router'; +import { translate } from '../../../helpers/l10n'; interface Props { location: { @@ -33,14 +34,16 @@ export default function Unauthorized(props: Props) { return (
    -

    - {"You're not authorized to access this page. Please contact the administrator."} -

    +

    {translate('unauthorized.message')}

    - {!!message &&

    Reason : {message}

    } + {!!message && ( +

    + {translate('unauthorized.reason')} {message} +

    + )}
    - Home + {translate('layout.home')}
    ); diff --git a/server/sonar-web/src/main/js/apps/sessions/components/__tests__/LoginForm-test.js b/server/sonar-web/src/main/js/apps/sessions/components/__tests__/LoginForm-test.tsx similarity index 98% rename from server/sonar-web/src/main/js/apps/sessions/components/__tests__/LoginForm-test.js rename to server/sonar-web/src/main/js/apps/sessions/components/__tests__/LoginForm-test.tsx index 6eea8123a99..47f1add3ed3 100644 --- a/server/sonar-web/src/main/js/apps/sessions/components/__tests__/LoginForm-test.js +++ b/server/sonar-web/src/main/js/apps/sessions/components/__tests__/LoginForm-test.tsx @@ -17,8 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -// @flow -import React from 'react'; +import * as React from 'react'; import { shallow } from 'enzyme'; import LoginForm from '../LoginForm'; import { change, click, submit } from '../../../../helpers/testUtils'; diff --git a/server/sonar-web/src/main/js/apps/sessions/components/__tests__/__snapshots__/LoginForm-test.js.snap b/server/sonar-web/src/main/js/apps/sessions/components/__tests__/__snapshots__/LoginForm-test.tsx.snap similarity index 93% rename from server/sonar-web/src/main/js/apps/sessions/components/__tests__/__snapshots__/LoginForm-test.js.snap rename to server/sonar-web/src/main/js/apps/sessions/components/__tests__/__snapshots__/LoginForm-test.tsx.snap index 42113f43dc0..295059922ee 100644 --- a/server/sonar-web/src/main/js/apps/sessions/components/__tests__/__snapshots__/LoginForm-test.js.snap +++ b/server/sonar-web/src/main/js/apps/sessions/components/__tests__/__snapshots__/LoginForm-test.tsx.snap @@ -10,7 +10,6 @@ exports[`expands more options 1`] = ` login.login_to_sonarqube sessions.log_in - cancel - +
@@ -136,7 +136,6 @@ exports[`logs in with identity provider 1`] = ` login.login_to_sonarqube sessions.log_in - cancel - + diff --git a/sonar-core/src/main/resources/org/sonar/l10n/core.properties b/sonar-core/src/main/resources/org/sonar/l10n/core.properties index 13443aa12e9..60cec37405f 100644 --- a/sonar-core/src/main/resources/org/sonar/l10n/core.properties +++ b/sonar-core/src/main/resources/org/sonar/l10n/core.properties @@ -1350,6 +1350,9 @@ login.login_to_sonarqube=Log In to SonarQube login.more_options=More options login.login_with_x=Log in with {0} +unauthorized.message=You're not authorized to access this page. Please contact the administrator. +unauthorized.reason=Reason: + #------------------------------------------------------------------------------ # # USERS & GROUPS PAGE diff --git a/tests/src/test/resources/user/BaseIdentityProviderTest/display_message_in_ui_but_not_in_log_when_unauthorized_exception.html b/tests/src/test/resources/user/BaseIdentityProviderTest/display_message_in_ui_but_not_in_log_when_unauthorized_exception.html index b62763fb7c9..d202404dfd1 100644 --- a/tests/src/test/resources/user/BaseIdentityProviderTest/display_message_in_ui_but_not_in_log_when_unauthorized_exception.html +++ b/tests/src/test/resources/user/BaseIdentityProviderTest/display_message_in_ui_but_not_in_log_when_unauthorized_exception.html @@ -36,7 +36,7 @@ assertText bd - *Reason : A functional error has happened* + *Reason: A functional error has happened* diff --git a/tests/src/test/resources/user/BaseIdentityProviderTest/fail_to_authenticate_when_not_allowed_to_sign_up.html b/tests/src/test/resources/user/BaseIdentityProviderTest/fail_to_authenticate_when_not_allowed_to_sign_up.html index 40c300bd701..ddf1b837078 100644 --- a/tests/src/test/resources/user/BaseIdentityProviderTest/fail_to_authenticate_when_not_allowed_to_sign_up.html +++ b/tests/src/test/resources/user/BaseIdentityProviderTest/fail_to_authenticate_when_not_allowed_to_sign_up.html @@ -31,7 +31,7 @@ waitForText bd - *You're not authorized to access this page. Please contact the administrator.*Reason : 'fake-base-id-provider' users are not allowed to sign up* + *You're not authorized to access this page. Please contact the administrator.*Reason: 'fake-base-id-provider' users are not allowed to sign up* diff --git a/tests/src/test/resources/user/OAuth2IdentityProviderTest/display_message_in_ui_but_not_in_log_when_unauthorized_exception.html b/tests/src/test/resources/user/OAuth2IdentityProviderTest/display_message_in_ui_but_not_in_log_when_unauthorized_exception.html index 6a38ed69063..a78424c7a91 100644 --- a/tests/src/test/resources/user/OAuth2IdentityProviderTest/display_message_in_ui_but_not_in_log_when_unauthorized_exception.html +++ b/tests/src/test/resources/user/OAuth2IdentityProviderTest/display_message_in_ui_but_not_in_log_when_unauthorized_exception.html @@ -36,7 +36,7 @@ assertText bd - *Reason : A functional error has happened* + *Reason: A functional error has happened* diff --git a/tests/src/test/resources/user/OAuth2IdentityProviderTest/fail_to_authenticate_when_not_allowed_to_sign_up.html b/tests/src/test/resources/user/OAuth2IdentityProviderTest/fail_to_authenticate_when_not_allowed_to_sign_up.html index a3da2de8ed0..addc1e7818b 100644 --- a/tests/src/test/resources/user/OAuth2IdentityProviderTest/fail_to_authenticate_when_not_allowed_to_sign_up.html +++ b/tests/src/test/resources/user/OAuth2IdentityProviderTest/fail_to_authenticate_when_not_allowed_to_sign_up.html @@ -31,7 +31,7 @@ waitForText bd - *You're not authorized to access this page. Please contact the administrator.*Reason : 'fake-oauth2-id-provider' users are not allowed to sign up* + *You're not authorized to access this page. Please contact the administrator.*Reason: 'fake-oauth2-id-provider' users are not allowed to sign up* -- 2.39.5