aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-web/src/main/js/apps
diff options
context:
space:
mode:
authorStas Vilchik <vilchiks@gmail.com>2016-03-30 10:09:32 +0200
committerStas Vilchik <vilchiks@gmail.com>2016-03-30 13:11:11 +0200
commit737b9fdfcc2cd876c34620a9cc228fe760366c7b (patch)
tree98aac8ed5536d5c227ef131c61e00cfbbd9c3d15 /server/sonar-web/src/main/js/apps
parent0c1c2ec4c0a6185b3c40782661078c2e581eb545 (diff)
downloadsonarqube-737b9fdfcc2cd876c34620a9cc228fe760366c7b.tar.gz
sonarqube-737b9fdfcc2cd876c34620a9cc228fe760366c7b.zip
SONAR-7238 Display external identity information on user
Diffstat (limited to 'server/sonar-web/src/main/js/apps')
-rw-r--r--server/sonar-web/src/main/js/apps/account/components/UserCard.js6
-rw-r--r--server/sonar-web/src/main/js/apps/account/components/UserExternalIdentity.js88
-rw-r--r--server/sonar-web/src/main/js/apps/users/app.js9
-rw-r--r--server/sonar-web/src/main/js/apps/users/list-item-view.js7
-rw-r--r--server/sonar-web/src/main/js/apps/users/list-view.js4
-rw-r--r--server/sonar-web/src/main/js/apps/users/templates/users-list-item.hbs24
6 files changed, 132 insertions, 6 deletions
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
index 0c848116e26..b680781a718 100644
--- a/server/sonar-web/src/main/js/apps/account/components/UserCard.js
+++ b/server/sonar-web/src/main/js/apps/account/components/UserCard.js
@@ -20,6 +20,7 @@
import React from 'react';
import { IndexLink } from 'react-router';
+import UserExternalIdentity from './UserExternalIdentity';
import Avatar from '../../../components/shared/avatar';
export default function UserCard ({ user }) {
@@ -35,6 +36,11 @@ export default function UserCard ({ user }) {
<h1 id="name" className="display-inline-block">{user.name}</h1>
</IndexLink>
<span id="login" className="note big-spacer-left">{user.login}</span>
+ {!user.local && (
+ <span id="identity-provider" className="big-spacer-left">
+ <UserExternalIdentity user={user}/>
+ </span>
+ )}
</div>
<div id="email" className="little-spacer-top">{user.email}</div>
</section>
diff --git a/server/sonar-web/src/main/js/apps/account/components/UserExternalIdentity.js b/server/sonar-web/src/main/js/apps/account/components/UserExternalIdentity.js
new file mode 100644
index 00000000000..c26d0418270
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/account/components/UserExternalIdentity.js
@@ -0,0 +1,88 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact 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';
+
+export default class UserExternalIdentity extends React.Component {
+ state = {
+ loading: true
+ };
+
+ componentDidMount () {
+ this.mounted = true;
+ this.fetchIdentityProviders();
+ }
+
+ componentDidUpdate (nextProps) {
+ if (nextProps.user !== this.props.user) {
+ this.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 (
+ <span className="note">
+ {user.externalProvider}{': '}{user.externalIdentity}
+ </span>
+ );
+ }
+
+ return (
+ <div
+ className="identity-provider"
+ style={{ backgroundColor: identityProvider.backgroundColor }}>
+ <img src={window.baseUrl + identityProvider.iconPath} width="14" height="14"/>
+ {' '}
+ {user.externalIdentity}
+ </div>
+ );
+ }
+}
diff --git a/server/sonar-web/src/main/js/apps/users/app.js b/server/sonar-web/src/main/js/apps/users/app.js
index f8d25051478..fcbe54cafb8 100644
--- a/server/sonar-web/src/main/js/apps/users/app.js
+++ b/server/sonar-web/src/main/js/apps/users/app.js
@@ -18,15 +18,18 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import Marionette from 'backbone.marionette';
+
import Layout from './layout';
import Users from './users';
import HeaderView from './header-view';
import SearchView from './search-view';
import ListView from './list-view';
import ListFooterView from './list-footer-view';
+import { getIdentityProviders } from '../../api/users';
const App = new Marionette.Application();
-const init = function () {
+
+const init = function (providers) {
const options = window.sonarqube;
// Layout
@@ -45,7 +48,7 @@ const init = function () {
this.layout.searchRegion.show(this.searchView);
// List View
- this.listView = new ListView({ collection: this.users });
+ this.listView = new ListView({ collection: this.users, providers });
this.layout.listRegion.show(this.listView);
// List Footer View
@@ -57,7 +60,7 @@ const init = function () {
};
App.on('start', function () {
- init.call(App);
+ getIdentityProviders().then(r => init.call(App, r.identityProviders));
});
window.sonarqube.appStarted.then(options => App.start(options));
diff --git a/server/sonar-web/src/main/js/apps/users/list-item-view.js b/server/sonar-web/src/main/js/apps/users/list-item-view.js
index 6e06fd37557..e5b45bdaba7 100644
--- a/server/sonar-web/src/main/js/apps/users/list-item-view.js
+++ b/server/sonar-web/src/main/js/apps/users/list-item-view.js
@@ -128,9 +128,16 @@ export default Marionette.ItemView.extend({
serializeData () {
const scmAccounts = this.model.get('scmAccounts');
const scmAccountsLimit = scmAccounts.length > this.scmLimit ? this.scmLimit - 1 : this.scmLimit;
+
const groups = this.model.get('groups');
const groupsLimit = groups.length > this.groupsLimit ? this.groupsLimit - 1 : this.groupsLimit;
+
+ const externalProvider = this.model.get('externalProvider');
+ const identityProvider = this.model.get('local') ? null :
+ this.options.providers.find(provider => externalProvider === provider.key);
+
return _.extend(Marionette.ItemView.prototype.serializeData.apply(this, arguments), {
+ identityProvider,
firstScmAccounts: _.first(scmAccounts, scmAccountsLimit),
moreScmAccountsCount: scmAccounts.length - scmAccountsLimit,
firstGroups: _.first(groups, groupsLimit),
diff --git a/server/sonar-web/src/main/js/apps/users/list-view.js b/server/sonar-web/src/main/js/apps/users/list-view.js
index 90f212af173..3bd5fd9060b 100644
--- a/server/sonar-web/src/main/js/apps/users/list-view.js
+++ b/server/sonar-web/src/main/js/apps/users/list-view.js
@@ -33,6 +33,10 @@ export default Marionette.CompositeView.extend({
'sync': 'hideLoading'
},
+ childViewOptions () {
+ return { providers: this.options.providers };
+ },
+
showLoading () {
this.$el.addClass('new-loading');
},
diff --git a/server/sonar-web/src/main/js/apps/users/templates/users-list-item.hbs b/server/sonar-web/src/main/js/apps/users/templates/users-list-item.hbs
index fb5987fbbd8..d59d649d1c8 100644
--- a/server/sonar-web/src/main/js/apps/users/templates/users-list-item.hbs
+++ b/server/sonar-web/src/main/js/apps/users/templates/users-list-item.hbs
@@ -9,7 +9,23 @@
<strong class="js-user-name">{{name}}</strong>
<span class="js-user-login note little-spacer-left">{{login}}</span>
</div>
- <div class="js-user-email little-spacer-top">{{email}}</div>
+
+ {{#if email}}
+ <div class="js-user-email little-spacer-top">{{email}}</div>
+ {{/if}}
+
+ {{#unless local}}
+ <div class="js-user-identity-provider little-spacer-top">
+ {{#if identityProvider}}
+ <div class="identity-provider" style="background-color: {{identityProvider.backgroundColor}}">
+ <img src="{{link identityProvider.iconPath}}" width="14" height="14"/>
+ {{externalIdentity}}
+ </div>
+ {{else}}
+ {{externalProvider}}: {{externalIdentity}}
+ {{/if}}
+ </div>
+ {{/unless}}
</td>
<td>
@@ -46,7 +62,9 @@
<td class="thin nowrap text-right">
<a class="js-user-update icon-edit little-spacer-right" title="Update Details" data-toggle="tooltip" href="#"></a>
- <a class="js-user-change-password icon-lock little-spacer-right" title="Change Password" data-toggle="tooltip"
- href="#"></a>
+ {{#if local}}
+ <a class="js-user-change-password icon-lock little-spacer-right" title="Change Password" data-toggle="tooltip"
+ href="#"></a>
+ {{/if}}
<a class="js-user-deactivate icon-delete" title="Deactivate" data-toggle="tooltip" href="#"></a>
</td>