From: Stas Vilchik Date: Thu, 20 Sep 2018 10:05:07 +0000 (+0200) Subject: rewrite account app in ts X-Git-Tag: 7.5~449 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=64d76164768f4b74d6bdc714191f65567baf8d10;p=sonarqube.git rewrite account app in ts --- diff --git a/server/sonar-web/src/main/js/api/users.ts b/server/sonar-web/src/main/js/api/users.ts index f266f79bd41..1954f192c50 100644 --- a/server/sonar-web/src/main/js/api/users.ts +++ b/server/sonar-web/src/main/js/api/users.ts @@ -29,8 +29,8 @@ export function changePassword(data: { login: string; password: string; previousPassword?: string; -}): Promise { - return post('/api/users/change_password', data); +}) { + return post('/api/users/change_password', data).catch(throwGlobalError); } export interface UserGroup { diff --git a/server/sonar-web/src/main/js/app/components/__tests__/StartupModal-test.tsx b/server/sonar-web/src/main/js/app/components/__tests__/StartupModal-test.tsx index 7a1e2bf2d3d..374be478fcd 100644 --- a/server/sonar-web/src/main/js/app/components/__tests__/StartupModal-test.tsx +++ b/server/sonar-web/src/main/js/app/components/__tests__/StartupModal-test.tsx @@ -48,9 +48,11 @@ jest.mock('../../../helpers/dates', () => ({ })); const LOGGED_IN_USER: LoggedInUser = { + groups: [], isLoggedIn: true, login: 'luke', name: 'Skywalker', + scmAccounts: [], showOnboardingTutorial: false }; diff --git a/server/sonar-web/src/main/js/app/types.ts b/server/sonar-web/src/main/js/app/types.ts index 254817b7430..4df5d148def 100644 --- a/server/sonar-web/src/main/js/app/types.ts +++ b/server/sonar-web/src/main/js/app/types.ts @@ -362,10 +362,13 @@ export interface LoggedInUser extends CurrentUser { email?: string; externalIdentity?: string; externalProvider?: string; + groups: string[]; homepage?: HomePage; isLoggedIn: true; + local?: boolean; login: string; name: string; + scmAccounts: string[]; } export interface LongLivingBranch extends Branch { diff --git a/server/sonar-web/src/main/js/apps/account/components/Account.js b/server/sonar-web/src/main/js/apps/account/components/Account.js deleted file mode 100644 index bb4e8645692..00000000000 --- a/server/sonar-web/src/main/js/apps/account/components/Account.js +++ /dev/null @@ -1,68 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2018 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import React from 'react'; -import { connect } from 'react-redux'; -import Helmet from 'react-helmet'; -import Nav from './Nav'; -import UserCard from './UserCard'; -import { getCurrentUser, areThereCustomOrganizations } from '../../../store/rootReducer'; -import { translate } from '../../../helpers/l10n'; -import handleRequiredAuthentication from '../../../app/utils/handleRequiredAuthentication'; -import Suggestions from '../../../app/components/embed-docs-modal/Suggestions'; -import '../account.css'; - -class Account extends React.PureComponent { - componentDidMount() { - if (!this.props.currentUser.isLoggedIn) { - handleRequiredAuthentication(); - } - } - - render() { - const { currentUser, children } = this.props; - - if (!currentUser.isLoggedIn) { - return null; - } - - const title = translate('my_account.page'); - return ( -
- - -
-
- -
-
- - {children} -
- ); - } -} - -const mapStateToProps = state => ({ - currentUser: getCurrentUser(state), - customOrganizations: areThereCustomOrganizations(state) -}); - -export default connect(mapStateToProps)(Account); diff --git a/server/sonar-web/src/main/js/apps/account/components/Account.tsx b/server/sonar-web/src/main/js/apps/account/components/Account.tsx new file mode 100644 index 00000000000..02711b9d407 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/account/components/Account.tsx @@ -0,0 +1,74 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import * as React from 'react'; +import { connect } from 'react-redux'; +import Helmet from 'react-helmet'; +import Nav from './Nav'; +import UserCard from './UserCard'; +import { CurrentUser, LoggedInUser } from '../../../app/types'; +import { getCurrentUser, areThereCustomOrganizations, Store } from '../../../store/rootReducer'; +import { translate } from '../../../helpers/l10n'; +import handleRequiredAuthentication from '../../../app/utils/handleRequiredAuthentication'; +import Suggestions from '../../../app/components/embed-docs-modal/Suggestions'; +import '../account.css'; + +interface Props { + currentUser: CurrentUser; + customOrganizations?: boolean; +} + +class Account extends React.PureComponent { + componentDidMount() { + if (!this.props.currentUser.isLoggedIn) { + handleRequiredAuthentication(); + } + } + + render() { + const { currentUser, children } = this.props; + + if (!currentUser.isLoggedIn) { + return null; + } + + const title = translate('my_account.page'); + return ( +
+ + +
+
+ +
+
+ + {children} +
+ ); + } +} + +const mapStateToProps = (state: Store) => ({ + currentUser: getCurrentUser(state), + customOrganizations: areThereCustomOrganizations(state) +}); + +export default connect(mapStateToProps)(Account); diff --git a/server/sonar-web/src/main/js/apps/account/components/Nav.js b/server/sonar-web/src/main/js/apps/account/components/Nav.js deleted file mode 100644 index 8688985c311..00000000000 --- a/server/sonar-web/src/main/js/apps/account/components/Nav.js +++ /dev/null @@ -1,68 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2018 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -// @flow -import React from 'react'; -import { Link, IndexLink } from 'react-router'; -import NavBarTabs from '../../../components/nav/NavBarTabs'; -import { translate } from '../../../helpers/l10n'; - -/*:: -type Props = { - customOrganizations: boolean -}; -*/ - -export default function Nav({ customOrganizations } /*: Props */) { - return ( - - ); -} diff --git a/server/sonar-web/src/main/js/apps/account/components/Nav.tsx b/server/sonar-web/src/main/js/apps/account/components/Nav.tsx new file mode 100644 index 00000000000..304ddb10ded --- /dev/null +++ b/server/sonar-web/src/main/js/apps/account/components/Nav.tsx @@ -0,0 +1,65 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import * as React from 'react'; +import { Link, IndexLink } from 'react-router'; +import NavBarTabs from '../../../components/nav/NavBarTabs'; +import { translate } from '../../../helpers/l10n'; + +interface Props { + customOrganizations?: boolean; +} + +export default function Nav({ customOrganizations }: Props) { + return ( + + ); +} diff --git a/server/sonar-web/src/main/js/apps/account/components/Password.js b/server/sonar-web/src/main/js/apps/account/components/Password.js deleted file mode 100644 index 00c12a5e67a..00000000000 --- a/server/sonar-web/src/main/js/apps/account/components/Password.js +++ /dev/null @@ -1,140 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2018 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import React, { Component } from 'react'; -import { changePassword } from '../../../api/users'; -import { SubmitButton } from '../../../components/ui/buttons'; -import { translate } from '../../../helpers/l10n'; - -export default class Password extends Component { - state = { - success: false, - errors: null - }; - - handleSuccessfulChange = () => { - this.oldPassword.value = ''; - this.password.value = ''; - this.passwordConfirmation.value = ''; - this.setState({ success: true, errors: null }); - }; - - handleFailedChange = e => { - e.response.json().then(r => { - this.oldPassword.focus(); - this.setErrors(r.errors.map(e => e.msg)); - }); - }; - - setErrors = errors => { - this.setState({ - success: false, - errors - }); - }; - - handleChangePassword = e => { - e.preventDefault(); - - const { user } = this.props; - const previousPassword = this.oldPassword.value; - const password = this.password.value; - const passwordConfirmation = this.passwordConfirmation.value; - - if (password !== passwordConfirmation) { - this.password.focus(); - this.setErrors([translate('user.password_doesnt_match_confirmation')]); - } else { - changePassword({ login: user.login, password, previousPassword }) - .then(this.handleSuccessfulChange) - .catch(this.handleFailedChange); - } - }; - - render() { - const { success, errors } = this.state; - - return ( -
-

{translate('my_profile.password.title')}

- -
- {success && ( -
{translate('my_profile.password.changed')}
- )} - - {errors && - errors.map((e, i) => ( -
- {e} -
- ))} - -
- - (this.oldPassword = elem)} - required={true} - type="password" - /> -
-
- - (this.password = elem)} - required={true} - type="password" - /> -
-
- - (this.passwordConfirmation = elem)} - required={true} - type="password" - /> -
-
- - {translate('my_profile.password.submit')} - -
-
-
- ); - } -} diff --git a/server/sonar-web/src/main/js/apps/account/components/Password.tsx b/server/sonar-web/src/main/js/apps/account/components/Password.tsx new file mode 100644 index 00000000000..5834e143db4 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/account/components/Password.tsx @@ -0,0 +1,143 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import * as React from 'react'; +import { changePassword } from '../../../api/users'; +import { SubmitButton } from '../../../components/ui/buttons'; +import { translate } from '../../../helpers/l10n'; +import { LoggedInUser } from '../../../app/types'; + +interface Props { + user: LoggedInUser; +} + +interface State { + errors?: string[]; + success: boolean; +} + +export default class Password extends React.Component { + oldPassword!: HTMLInputElement; + password!: HTMLInputElement; + passwordConfirmation!: HTMLInputElement; + state: State = { + success: false + }; + + handleSuccessfulChange = () => { + this.oldPassword.value = ''; + this.password.value = ''; + this.passwordConfirmation.value = ''; + this.setState({ success: true, errors: undefined }); + }; + + setErrors = (errors: string[]) => { + this.setState({ success: false, errors }); + }; + + handleChangePassword = (event: React.FormEvent) => { + event.preventDefault(); + + const { user } = this.props; + const previousPassword = this.oldPassword.value; + const password = this.password.value; + const passwordConfirmation = this.passwordConfirmation.value; + + if (password !== passwordConfirmation) { + this.password.focus(); + this.setErrors([translate('user.password_doesnt_match_confirmation')]); + } else { + changePassword({ login: user.login, password, previousPassword }).then( + this.handleSuccessfulChange, + () => {} + ); + } + }; + + render() { + const { success, errors } = this.state; + + return ( +
+

{translate('my_profile.password.title')}

+ +
+ {success && ( +
{translate('my_profile.password.changed')}
+ )} + + {errors && + errors.map((e, i) => ( +
+ {e} +
+ ))} + +
+ + (this.oldPassword = elem!)} + required={true} + type="password" + /> +
+
+ + (this.password = elem!)} + required={true} + type="password" + /> +
+
+ + (this.passwordConfirmation = elem!)} + required={true} + type="password" + /> +
+
+ + {translate('my_profile.password.submit')} + +
+
+
+ ); + } +} diff --git a/server/sonar-web/src/main/js/apps/account/components/Security.js b/server/sonar-web/src/main/js/apps/account/components/Security.js deleted file mode 100644 index af77c5eff8d..00000000000 --- a/server/sonar-web/src/main/js/apps/account/components/Security.js +++ /dev/null @@ -1,40 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2018 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import React from 'react'; -import Helmet from 'react-helmet'; -import { connect } from 'react-redux'; -import Password from './Password'; -import Tokens from './Tokens'; -import { translate } from '../../../helpers/l10n'; -import { getCurrentUser } from '../../../store/rootReducer'; - -function Security(props) { - const { user } = props; - - return ( -
- - - {user.local && } -
- ); -} - -export default connect(state => ({ user: getCurrentUser(state) }))(Security); diff --git a/server/sonar-web/src/main/js/apps/account/components/Security.tsx b/server/sonar-web/src/main/js/apps/account/components/Security.tsx new file mode 100644 index 00000000000..bca85261333 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/account/components/Security.tsx @@ -0,0 +1,47 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import * as React from 'react'; +import Helmet from 'react-helmet'; +import { connect } from 'react-redux'; +import Password from './Password'; +import Tokens from './Tokens'; +import { translate } from '../../../helpers/l10n'; +import { getCurrentUser, Store } from '../../../store/rootReducer'; +import { LoggedInUser } from '../../../app/types'; + +interface Props { + user: LoggedInUser; +} + +function Security({ user }: Props) { + return ( +
+ + + {user.local && } +
+ ); +} + +const mapStateToProps = (state: Store) => ({ + user: getCurrentUser(state) as LoggedInUser +}); + +export default connect(mapStateToProps)(Security); diff --git a/server/sonar-web/src/main/js/apps/account/components/UserCard.js b/server/sonar-web/src/main/js/apps/account/components/UserCard.js deleted file mode 100644 index a67a2ef2eb0..00000000000 --- a/server/sonar-web/src/main/js/apps/account/components/UserCard.js +++ /dev/null @@ -1,43 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2018 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import React from 'react'; -import PropTypes from 'prop-types'; -import Avatar from '../../../components/ui/Avatar'; - -export default class UserCard extends React.PureComponent { - static propTypes = { - user: PropTypes.object.isRequired - }; - - render() { - const { user } = this.props; - - return ( -
-
- -
-

- {user.name} -

-
- ); - } -} diff --git a/server/sonar-web/src/main/js/apps/account/components/UserCard.tsx b/server/sonar-web/src/main/js/apps/account/components/UserCard.tsx new file mode 100644 index 00000000000..6afeeaaf967 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/account/components/UserCard.tsx @@ -0,0 +1,39 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import * as React from 'react'; +import Avatar from '../../../components/ui/Avatar'; +import { LoggedInUser } from '../../../app/types'; + +interface Props { + user: LoggedInUser; +} + +export default function UserCard({ user }: Props) { + return ( +
+
+ +
+

+ {user.name} +

+
+ ); +} diff --git a/server/sonar-web/src/main/js/apps/account/profile/Profile.js b/server/sonar-web/src/main/js/apps/account/profile/Profile.js deleted file mode 100644 index 3b91c7649dc..00000000000 --- a/server/sonar-web/src/main/js/apps/account/profile/Profile.js +++ /dev/null @@ -1,82 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2018 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -// @flow -import React from 'react'; -import { connect } from 'react-redux'; -import UserExternalIdentity from './UserExternalIdentity'; -import UserGroups from './UserGroups'; -import UserScmAccounts from './UserScmAccounts'; -import { getCurrentUser, areThereCustomOrganizations } from '../../../store/rootReducer'; -import { translate } from '../../../helpers/l10n'; - -/*:: -type Props = { - customOrganizations: boolean, - user: { - email?: string, - externalProvider?: string, - groups: Array<*>, - local: boolean, - login: string, - scmAccounts: Array<*> - } -}; -*/ - -function Profile(props /*: Props */) { - const { customOrganizations, user } = props; - - return ( -
-
-
- {translate('login')}: {user.login} -
- - {!user.local && - user.externalProvider !== 'sonarqube' && ( -
- -
- )} - - {!!user.email && ( -
- {translate('my_profile.email')}: {user.email} -
- )} - - {!customOrganizations &&
} - {!customOrganizations && } - -
- - -
-
- ); -} - -const mapStateToProps = state => ({ - customOrganizations: areThereCustomOrganizations(state), - user: getCurrentUser(state) -}); - -export default connect(mapStateToProps)(Profile); diff --git a/server/sonar-web/src/main/js/apps/account/profile/Profile.tsx b/server/sonar-web/src/main/js/apps/account/profile/Profile.tsx new file mode 100644 index 00000000000..f03d64cac11 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/account/profile/Profile.tsx @@ -0,0 +1,75 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import * as React from 'react'; +import { connect } from 'react-redux'; +import UserExternalIdentity from './UserExternalIdentity'; +import UserGroups from './UserGroups'; +import UserScmAccounts from './UserScmAccounts'; +import { getCurrentUser, areThereCustomOrganizations, Store } from '../../../store/rootReducer'; +import { translate } from '../../../helpers/l10n'; +import { LoggedInUser } from '../../../app/types'; + +interface Props { + customOrganizations?: boolean; + user: LoggedInUser; +} + +function Profile({ customOrganizations, user }: Props) { + return ( +
+
+
+ {translate('login')}: {user.login} +
+ + {!user.local && + user.externalProvider !== 'sonarqube' && ( +
+ +
+ )} + + {!!user.email && ( +
+ {translate('my_profile.email')}: {user.email} +
+ )} + + {!customOrganizations && ( + <> +
+ + + )} + +
+ + +
+
+ ); +} + +const mapStateToProps = (state: Store) => ({ + customOrganizations: areThereCustomOrganizations(state), + user: getCurrentUser(state) as LoggedInUser +}); + +export default connect(mapStateToProps)(Profile); diff --git a/server/sonar-web/src/main/js/apps/account/profile/UserExternalIdentity.js b/server/sonar-web/src/main/js/apps/account/profile/UserExternalIdentity.js deleted file mode 100644 index 8e0536fe3ac..00000000000 --- a/server/sonar-web/src/main/js/apps/account/profile/UserExternalIdentity.js +++ /dev/null @@ -1,100 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2018 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import React from 'react'; -import { getIdentityProviders } from '../../../api/users'; -import * as theme from '../../../app/theme'; -import { getTextColor } from '../../../helpers/colors'; - -export default class UserExternalIdentity extends React.PureComponent { - state = { - loading: true - }; - - componentDidMount() { - this.mounted = true; - this.fetchIdentityProviders(); - } - - componentDidUpdate(prevProps) { - if (prevProps.user !== this.props.user) { - this.fetchIdentityProviders(); - } - } - - componentWillUnmount() { - this.mounted = false; - } - - fetchIdentityProviders() { - this.setState({ loading: true }); - getIdentityProviders() - .then(r => r.identityProviders) - .then(providers => { - if (this.mounted) { - const identityProvider = providers.find( - provider => provider.key === this.props.user.externalProvider - ); - this.setState({ loading: false, identityProvider }); - } - }) - .catch(() => { - if (this.mounted) { - this.setState({ loading: false }); - } - }); - } - - render() { - const { user } = this.props; - const { loading, identityProvider } = this.state; - - if (loading) { - return null; - } - - if (!identityProvider) { - return ( -
- {user.externalProvider} - {': '} - {user.externalIdentity} -
- ); - } - - return ( -
- {identityProvider.name}{' '} - {user.externalIdentity} -
- ); - } -} diff --git a/server/sonar-web/src/main/js/apps/account/profile/UserExternalIdentity.tsx b/server/sonar-web/src/main/js/apps/account/profile/UserExternalIdentity.tsx new file mode 100644 index 00000000000..a71dad75ff4 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/account/profile/UserExternalIdentity.tsx @@ -0,0 +1,112 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import * as React from 'react'; +import { getIdentityProviders } from '../../../api/users'; +import * as theme from '../../../app/theme'; +import { getTextColor } from '../../../helpers/colors'; +import { LoggedInUser, IdentityProvider } from '../../../app/types'; +import { getBaseUrl } from '../../../helpers/urls'; + +interface Props { + user: LoggedInUser; +} + +interface State { + identityProvider?: IdentityProvider; + loading: boolean; +} + +export default class UserExternalIdentity extends React.PureComponent { + mounted = false; + state: State = { + loading: true + }; + + componentDidMount() { + this.mounted = true; + this.fetchIdentityProviders(); + } + + componentDidUpdate(prevProps: Props) { + if (prevProps.user !== this.props.user) { + this.fetchIdentityProviders(); + } + } + + componentWillUnmount() { + this.mounted = false; + } + + fetchIdentityProviders() { + this.setState({ loading: true }); + getIdentityProviders() + .then(r => r.identityProviders) + .then(providers => { + if (this.mounted) { + const identityProvider = providers.find( + provider => provider.key === this.props.user.externalProvider + ); + this.setState({ loading: false, identityProvider }); + } + }) + .catch(() => { + if (this.mounted) { + this.setState({ loading: false }); + } + }); + } + + render() { + const { user } = this.props; + const { loading, identityProvider } = this.state; + + if (loading) { + return null; + } + + if (!identityProvider) { + return ( +
+ {user.externalProvider} + {': '} + {user.externalIdentity} +
+ ); + } + + return ( +
+ {identityProvider.name}{' '} + {user.externalIdentity} +
+ ); + } +} diff --git a/server/sonar-web/src/main/js/apps/account/profile/UserGroups.js b/server/sonar-web/src/main/js/apps/account/profile/UserGroups.js deleted file mode 100644 index f81ba233119..00000000000 --- a/server/sonar-web/src/main/js/apps/account/profile/UserGroups.js +++ /dev/null @@ -1,45 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2018 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import React from 'react'; -import PropTypes from 'prop-types'; -import { translate } from '../../../helpers/l10n'; - -export default class UserGroups extends React.PureComponent { - static propTypes = { - groups: PropTypes.arrayOf(PropTypes.string).isRequired - }; - - render() { - const { groups } = this.props; - - return ( -
-

{translate('my_profile.groups')}

-
    - {groups.map(group => ( -
  • - {group} -
  • - ))} -
-
- ); - } -} diff --git a/server/sonar-web/src/main/js/apps/account/profile/UserGroups.tsx b/server/sonar-web/src/main/js/apps/account/profile/UserGroups.tsx new file mode 100644 index 00000000000..a8a5e235a34 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/account/profile/UserGroups.tsx @@ -0,0 +1,40 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import * as React from 'react'; +import { translate } from '../../../helpers/l10n'; + +interface Props { + groups: string[]; +} + +export default function UserGroups({ groups }: Props) { + return ( +
+

{translate('my_profile.groups')}

+
    + {groups.map(group => ( +
  • + {group} +
  • + ))} +
+
+ ); +} diff --git a/server/sonar-web/src/main/js/apps/account/profile/UserScmAccounts.js b/server/sonar-web/src/main/js/apps/account/profile/UserScmAccounts.js deleted file mode 100644 index a306959eade..00000000000 --- a/server/sonar-web/src/main/js/apps/account/profile/UserScmAccounts.js +++ /dev/null @@ -1,56 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2018 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import React from 'react'; -import PropTypes from 'prop-types'; -import { translate } from '../../../helpers/l10n'; - -export default class UserScmAccounts extends React.PureComponent { - static propTypes = { - user: PropTypes.object.isRequired, - scmAccounts: PropTypes.arrayOf(PropTypes.string).isRequired - }; - - render() { - const { user, scmAccounts } = this.props; - - return ( -
-

{translate('my_profile.scm_accounts')}

-
    -
  • - {user.login} -
  • - - {user.email && ( -
  • - {user.email} -
  • - )} - - {scmAccounts.map(scmAccount => ( -
  • - {scmAccount} -
  • - ))} -
-
- ); - } -} diff --git a/server/sonar-web/src/main/js/apps/account/profile/UserScmAccounts.tsx b/server/sonar-web/src/main/js/apps/account/profile/UserScmAccounts.tsx new file mode 100644 index 00000000000..13be6a89f97 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/account/profile/UserScmAccounts.tsx @@ -0,0 +1,52 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import * as React from 'react'; +import { translate } from '../../../helpers/l10n'; +import { LoggedInUser } from '../../../app/types'; + +interface Props { + scmAccounts: string[]; + user: LoggedInUser; +} + +export default function UserScmAccounts({ user, scmAccounts }: Props) { + return ( +
+

{translate('my_profile.scm_accounts')}

+
    +
  • + {user.login} +
  • + + {user.email && ( +
  • + {user.email} +
  • + )} + + {scmAccounts.map(scmAccount => ( +
  • + {scmAccount} +
  • + ))} +
+
+ ); +} diff --git a/server/sonar-web/src/main/js/apps/projects/create/__tests__/CreateProjectPage-test.tsx b/server/sonar-web/src/main/js/apps/projects/create/__tests__/CreateProjectPage-test.tsx index c4dd1380821..d20c0fd9ac8 100644 --- a/server/sonar-web/src/main/js/apps/projects/create/__tests__/CreateProjectPage-test.tsx +++ b/server/sonar-web/src/main/js/apps/projects/create/__tests__/CreateProjectPage-test.tsx @@ -40,9 +40,11 @@ jest.mock('../../../../api/users', () => ({ const user: LoggedInUser = { externalProvider: 'github', + groups: [], isLoggedIn: true, login: 'foo', - name: 'Foo' + name: 'Foo', + scmAccounts: [] }; beforeEach(() => { diff --git a/server/sonar-web/src/main/js/apps/projects/create/__tests__/ManualProjectCreate-test.tsx b/server/sonar-web/src/main/js/apps/projects/create/__tests__/ManualProjectCreate-test.tsx index f67db69e464..b2051ab3f53 100644 --- a/server/sonar-web/src/main/js/apps/projects/create/__tests__/ManualProjectCreate-test.tsx +++ b/server/sonar-web/src/main/js/apps/projects/create/__tests__/ManualProjectCreate-test.tsx @@ -69,7 +69,7 @@ it('should correctly create a project', async () => { function getWrapper(props = {}) { return shallow( { diff --git a/server/sonar-web/src/main/js/apps/tutorials/analyzeProject/__tests__/__snapshots__/AnalyzeTutorial-test.tsx.snap b/server/sonar-web/src/main/js/apps/tutorials/analyzeProject/__tests__/__snapshots__/AnalyzeTutorial-test.tsx.snap index af09b977a36..b7838005879 100644 --- a/server/sonar-web/src/main/js/apps/tutorials/analyzeProject/__tests__/__snapshots__/AnalyzeTutorial-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/tutorials/analyzeProject/__tests__/__snapshots__/AnalyzeTutorial-test.tsx.snap @@ -21,9 +21,11 @@ exports[`renders correctly 1`] = `