diff options
author | Grégoire Aubert <gregoire.aubert@sonarsource.com> | 2017-10-04 18:14:49 +0200 |
---|---|---|
committer | Grégoire Aubert <gregoire.aubert@sonarsource.com> | 2017-10-10 06:39:29 -0700 |
commit | cb8126d2d05acc3605fb233c68b935de4dc74214 (patch) | |
tree | e6c3e85696630f6101ce7d6ca080ef3d5485e113 | |
parent | 3bcf9ea40fe7dc563a1c8e438c0f6e3b5226466d (diff) | |
download | sonarqube-cb8126d2d05acc3605fb233c68b935de4dc74214.tar.gz sonarqube-cb8126d2d05acc3605fb233c68b935de4dc74214.zip |
SONAR-9925 Rewrite session to typescript
15 files changed, 125 insertions, 131 deletions
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<any> { return getJSON('/api/users/current'); } @@ -43,7 +50,7 @@ export function getUserGroups(login: string, organization?: string): Promise<any return getJSON('/api/users/groups', data); } -export function getIdentityProviders(): Promise<any> { +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 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<React.Element<*>>, - 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<Props> { componentDidMount() { const html = document.querySelector('html'); if (html) { @@ -50,7 +45,7 @@ export default class SimpleContainer extends React.PureComponent { return ( <div className="global-container"> <div className="page-wrapper" id="container"> - <NavBar className="navbar-global" id="global-navigation" height={30} /> + <NavBar className="navbar-global" height={30} /> <div id="bd" className="page-wrapper-simple"> <div id="nonav" className="page-simple"> 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 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<Props, State> { + 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<HTMLFormElement>) => { event.preventDefault(); this.props.onSubmit(this.state.login, this.state.password); }; - handleMoreOptionsClick = (event /*: Event */) => { + handleMoreOptionsClick = (event: React.SyntheticEvent<HTMLAnchorElement>) => { event.preventDefault(); this.setState({ collapsed: false }); }; + handleLoginChange = (event: React.SyntheticEvent<HTMLInputElement>) => + this.setState({ login: event.currentTarget.value }); + + handlePwdChange = (event: React.SyntheticEvent<HTMLInputElement>) => + this.setState({ password: event.currentTarget.value }); + render() { return ( <div id="login_form"> @@ -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} /> </div> @@ -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} /> </div> @@ -127,9 +122,9 @@ export default class LoginForm extends React.PureComponent { <button name="commit" type="submit"> {translate('sessions.log_in')} </button> - <a className="spacer-left" href={window.baseUrl + '/'}> + <Link className="spacer-left" to="/"> {translate('cancel')} - </a> + </Link> </div> </div> </form> 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 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<void>; + 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<Props, State> { + 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 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<void>; +} + +class Logout extends React.PureComponent<Props> { 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 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 ( <section className="oauth-providers"> <ul> {props.identityProviders.map(identityProvider => ( <li key={identityProvider.key}> <a - href={`${window.baseUrl}/sessions/init/${identityProvider.key}`} + href={`${getBaseUrl()}/sessions/init/${identityProvider.key}`} style={{ backgroundColor: identityProvider.backgroundColor }} - // $FlowFixMe formatLabel is always defined through defaultProps - title={props.formatLabel(identityProvider.name)}> + title={formatLabel(identityProvider.name)}> <img alt={identityProvider.name} width="20" height="20" - src={window.baseUrl + identityProvider.iconPath} + src={getBaseUrl() + identityProvider.iconPath} /> - <span> - {/* $FlowFixMe formatLabel is always defined through defaultProps */} - {props.formatLabel(identityProvider.name)} - </span> + <span>{formatLabel(identityProvider.name)}</span> </a> </li> ))} @@ -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 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<React.Element<*>> -}; -*/ +interface Props { + children?: React.ReactElement<any>; +} -export default function SimpleSessionsContainer({ children } /*: Props */) { +export default function SimpleSessionsContainer({ children }: Props) { return <SimpleContainer hideLoggedInInfo={true}>{children}</SimpleContainer>; } 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 ( <div className="text-center"> - <p id="unauthorized"> - {"You're not authorized to access this page. Please contact the administrator."} - </p> + <p id="unauthorized">{translate('unauthorized.message')}</p> - {!!message && <p className="spacer-top">Reason : {message}</p>} + {!!message && ( + <p className="spacer-top"> + {translate('unauthorized.reason')} {message} + </p> + )} <div className="big-spacer-top"> - <Link to="/">Home</Link> + <Link to="/">{translate('layout.home')}</Link> </div> </div> ); 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 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 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 </h1> <OAuthProviders - formatLabel={[Function]} identityProviders={ Array [ Object { @@ -46,7 +45,6 @@ exports[`expands more options 2`] = ` login.login_to_sonarqube </h1> <OAuthProviders - formatLabel={[Function]} identityProviders={ Array [ Object { @@ -75,7 +73,7 @@ exports[`expands more options 2`] = ` autoFocus={true} className="login-input" id="login" - maxLength="255" + maxLength={255} name="login" onChange={[Function]} placeholder="login" @@ -114,12 +112,14 @@ exports[`expands more options 2`] = ` > sessions.log_in </button> - <a + <Link className="spacer-left" - href="/" + onlyActiveOnIndex={false} + style={Object {}} + to="/" > cancel - </a> + </Link> </div> </div> </form> @@ -136,7 +136,6 @@ exports[`logs in with identity provider 1`] = ` login.login_to_sonarqube </h1> <OAuthProviders - formatLabel={[Function]} identityProviders={ Array [ Object { @@ -188,7 +187,7 @@ exports[`logs in with simple credentials 1`] = ` autoFocus={true} className="login-input" id="login" - maxLength="255" + maxLength={255} name="login" onChange={[Function]} placeholder="login" @@ -227,12 +226,14 @@ exports[`logs in with simple credentials 1`] = ` > sessions.log_in </button> - <a + <Link className="spacer-left" - href="/" + onlyActiveOnIndex={false} + style={Object {}} + to="/" > cancel - </a> + </Link> </div> </div> </form> 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 @@ <tr> <td>assertText</td> <td>bd</td> - <td>*Reason : A functional error has happened*</td> + <td>*Reason: A functional error has happened*</td> </tr> </tbody> </table> 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 @@ <tr> <td>waitForText</td> <td>bd</td> - <td>*You're not authorized to access this page. Please contact the administrator.*Reason : 'fake-base-id-provider' users are not allowed to sign up*</td> + <td>*You're not authorized to access this page. Please contact the administrator.*Reason: 'fake-base-id-provider' users are not allowed to sign up*</td> </tr> </tbody> </table> 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 @@ <tr> <td>assertText</td> <td>bd</td> - <td>*Reason : A functional error has happened*</td> + <td>*Reason: A functional error has happened*</td> </tr> </tbody> </table> 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 @@ <tr> <td>waitForText</td> <td>bd</td> - <td>*You're not authorized to access this page. Please contact the administrator.*Reason : 'fake-oauth2-id-provider' users are not allowed to sign up*</td> + <td>*You're not authorized to access this page. Please contact the administrator.*Reason: 'fake-oauth2-id-provider' users are not allowed to sign up*</td> </tr> </tbody> </table> |