CHE-5802: fixes related to Codenvy parts transplantation (#6509)

* fixes related to Codenvy parts transplantation

- use username instead of full name for organization's members;
- fix getting user's first and last name on Account page;
- fix tabs alignment on Organization details page;
- use api/profile endpoint to get current user's profile info for navbar;

Signed-off-by: Oleksii Kurinnyi <okurinny@redhat.com>

* code clean-up

Signed-off-by: Oleksii Kurinnyi <okurinny@redhat.com>
6.19.x
Oleksii Kurinnyi 2017-10-02 10:01:42 +03:00 committed by GitHub
parent 1f639c0557
commit 5ee2914e95
8 changed files with 80 additions and 58 deletions

View File

@ -162,7 +162,7 @@ initModule.config(['$routeProvider', ($routeProvider: che.route.IRouteProvider)
const DEV = false;
// configs
initModule.config(['$routeProvider', ($routeProvider) => {
initModule.config(['$routeProvider', ($routeProvider: che.route.IRouteProvider) => {
// config routes (add demo page)
if (DEV) {
$routeProvider.accessWhen('/demo-components', {

View File

@ -10,7 +10,7 @@
*/
'use strict';
import {CheAPI} from '../../components/api/che-api.factory';
import {CheKeycloak, keycloakUserInfo} from '../../components/api/che-keycloak.factory';
import {CheKeycloak} from '../../components/api/che-keycloak.factory';
export class CheNavBarController {
private menuItemUrl = {
@ -53,7 +53,6 @@ export class CheNavBarController {
private hasPersonalAccount: boolean;
private organizations: Array<che.IOrganization>;
private cheKeycloak: CheKeycloak;
private userInfo: keycloakUserInfo;
/**
* Default constructor
@ -75,7 +74,6 @@ export class CheNavBarController {
this.$window = $window;
this.chePermissions = chePermissions;
this.cheKeycloak = cheKeycloak;
this.userInfo = null;
this.profile = cheAPI.getProfile().getProfile();
@ -90,12 +88,6 @@ export class CheNavBarController {
cheAPI.getWorkspace().fetchWorkspaces();
cheAPI.getFactory().fetchFactories();
if (this.cheKeycloak.isPresent()) {
this.cheKeycloak.fetchUserInfo().then((userInfo: keycloakUserInfo) => {
this.userInfo = userInfo;
});
}
if (this.chePermissions.getSystemPermissions()) {
this.updateData();
} else {
@ -123,6 +115,17 @@ export class CheNavBarController {
this.$route.reload();
}
/**
* Returns user nickname.
* @return {string}
*/
getUserName(): string {
const {attributes, email} = this.profile;
const fullName = this.cheAPI.getProfile().getFullName(attributes).trim();
return fullName ? fullName : email;
}
/**
* Toggle the left menu
*/
@ -161,17 +164,24 @@ export class CheNavBarController {
return this.organizations.length;
}
openLinkInNewTab(url: string): void {
this.$window.open(url, '_blank');
/**
* Returns number of root organizations.
*
* @return {number}
*/
getRootOrganizationsNumber(): number {
if (!this.organizations) {
return 0;
}
let rootOrganizations = this.organizations.filter((organization: any) => {
return !organization.parent;
});
return rootOrganizations.length;
}
/**
* Returns <code>true</code> if Keycloak is present.
*
* @returns {boolean}
*/
isKeycloakPresent(): boolean {
return this.cheKeycloak.isPresent();
openLinkInNewTab(url: string): void {
this.$window.open(url, '_blank');
}
/**

View File

@ -123,8 +123,7 @@
<navbar-teams flex layout="column" layout-aling="start strength"></navbar-teams>
<div class="admin-navbar-menu"
layout="column" layout-align="end stretch" flex
ng-if="navbarController.isKeycloakPresent() && navbarController.userInfo">
layout="column" layout-align="end stretch" flex>
<section class="left-sidebar-menu navbar-account-section">
<md-list layout="column" flex>
@ -136,9 +135,9 @@
<div class="navbar-item navbar-identity" layout="row" layout-align="start center">
<i class="navbar-icon" flex="none">
<img class="developers-face" gravatar-src="navbarController.userInfo.email"/>
<img class="developers-face" gravatar-src="navbarController.profile.email"/>
</i>
<span flex style="text-align: left;">{{navbarController.userInfo.name}}</span>
<span flex style="text-align: left;">{{navbarController.getUserName()}}</span>
<i class="fa fa-angle-up navbar-icon" aria-hidden="true"></i>
</div>
</md-button>

View File

@ -14,7 +14,7 @@
ng-if="organizationDetailsController.organization">
<md-tabs md-dynamic-height md-stretch-tabs="auto"
md-selected="organizationDetailsController.selectedTabIndex"
md-center-tabs="">
md-no-ink-bar>
<!-- Settings Tab -->
<md-tab md-on-select="organizationDetailsController.onSelectTab(organizationDetailsController.tab.Settings);">

View File

@ -10,6 +10,14 @@
*/
'use strict';
import {OrganizationsPermissionService} from '../../organizations-permission.service';
import {CheUser} from '../../../../components/api/che-user.factory';
import {CheNotification} from '../../../../components/notification/che-notification.factory';
import {ConfirmDialogService} from '../../../../components/service/confirm-dialog/confirm-dialog.service';
import {CheProfile} from '../../../../components/api/che-profile.factory';
interface IOrganizationMember extends che.IUser {
permissions: che.IPermissions;
}
/**
* @ngdoc controller
@ -25,7 +33,7 @@ export class ListOrganizationMembersController {
/**
* User API interaction.
*/
private cheUser: any;
private cheUser: CheUser;
/**
* Organization API interaction.
*/
@ -45,15 +53,19 @@ export class ListOrganizationMembersController {
/**
* Notifications service.
*/
private cheNotification: any;
private cheNotification: CheNotification;
/**
* Confirm dialog service.
*/
private confirmDialogService: any;
private confirmDialogService: ConfirmDialogService;
/**
* Promises service.
*/
private $q: ng.IQService;
/**
* Logging service.
*/
private $log: ng.ILogService;
/**
* Lodash library.
*/
@ -61,7 +73,7 @@ export class ListOrganizationMembersController {
/**
* Organization's members list.
*/
private members: Array<che.IMember>;
private members: Array<IOrganizationMember>;
/**
* Members list of parent organization (comes from directive's scope)
*/
@ -103,10 +115,10 @@ export class ListOrganizationMembersController {
* Default constructor that is using resource
* @ngInject for Dependency injection
*/
constructor(chePermissions: che.api.IChePermissions, cheUser: any, cheProfile: any, cheOrganization: che.api.ICheOrganization,
confirmDialogService: any, $mdDialog: angular.material.IDialogService, $q: ng.IQService, cheNotification: any,
constructor(chePermissions: che.api.IChePermissions, cheUser: CheUser, cheProfile: CheProfile, cheOrganization: che.api.ICheOrganization,
confirmDialogService: ConfirmDialogService, $mdDialog: angular.material.IDialogService, $q: ng.IQService, cheNotification: CheNotification,
lodash: any, $location: ng.ILocationService, organizationsPermissionService: OrganizationsPermissionService,
$scope: ng.IScope, cheListHelperFactory: che.widget.ICheListHelperFactory, resourcesService: che.service.IResourcesService) {
$scope: ng.IScope, cheListHelperFactory: che.widget.ICheListHelperFactory, resourcesService: che.service.IResourcesService, $log: ng.ILogService) {
this.chePermissions = chePermissions;
this.cheProfile = cheProfile;
this.cheUser = cheUser;
@ -120,6 +132,7 @@ export class ListOrganizationMembersController {
this.organizationsPermissionService = organizationsPermissionService;
this.organizationActions = resourcesService.getOrganizationActions();
this.organizationRoles = resourcesService.getOrganizationRoles();
this.$log = $log;
this.members = [];
@ -130,7 +143,7 @@ export class ListOrganizationMembersController {
cheListHelperFactory.removeHelper(helperId);
});
this.formUsersList();
this.formMemberList();
}
/**
@ -153,7 +166,7 @@ export class ListOrganizationMembersController {
}
this.isLoading = true;
this.chePermissions.fetchOrganizationPermissions(this.organization.id).then(() => {
this.formUsersList();
this.formMemberList();
}, (error: any) => {
let errorMessage = error && error.data && error.data.message ? error.data.message : 'Failed to retrieve organization permissions.';
this.cheNotification.showError(errorMessage);
@ -165,28 +178,28 @@ export class ListOrganizationMembersController {
/**
* Combines permissions and users data in one list.
*/
formUsersList(): void {
const permissions = this.chePermissions.getOrganizationPermissions(this.organization.id);
formMemberList(): void {
this.members = [];
const promises: Array<ng.IPromise<any>> = [];
const permissions = this.chePermissions.getOrganizationPermissions(this.organization.id);
permissions.forEach((permission: any) => {
let userId = permission.userId;
let userProfile = this.cheProfile.getProfileById(userId);
const promises = permissions.map((permission: che.IPermissions) => {
const userId = permission.userId;
if (userProfile) {
this.formUserItem(userProfile, permission);
} else {
const promise = this.cheProfile.fetchProfileById(userId).then(() => {
this.formUserItem(this.cheProfile.getProfileById(userId), permission);
});
promises.push(promise);
if (this.cheUser.getUserFromId(userId)) {
this.formMemberItem(this.cheUser.getUserFromId(userId), permission);
return this.$q.when();
}
return this.cheUser.fetchUserId(userId).then(() => {
this.formMemberItem(this.cheUser.getUserFromId(userId), permission);
}, (error: any) => {
this.$log.error(`Failed to fetch user by ID with error ${error}`);
});
});
this.$q.all(promises).finally(() => {
this.cheListHelper.setList(this.members, 'id');
this.cheListHelper.setList(this.members, 'email');
});
this.hasUpdatePermission = this.organizationsPermissionService.isUserAllowedTo(this.organizationActions.UPDATE.toString(), this.organization.id);
@ -195,13 +208,11 @@ export class ListOrganizationMembersController {
/**
* Forms item to display with permissions and user data.
*
* @param userProfile {che.IProfile} user's profile
* @param userInfo {che.IUser} user's profile
* @param permissions {che.IPermissions} data
*/
formUserItem(userProfile: che.IProfile, permissions: che.IPermissions): void {
const member = <che.IMember>angular.copy(userProfile);
member.id = userProfile.userId;
member.name = this.cheProfile.getFullName(userProfile.attributes);
formMemberItem(userInfo: che.IUser, permissions: che.IPermissions): void {
const member = angular.copy(userInfo) as IOrganizationMember;
member.permissions = permissions;
this.members.push(member);
}

View File

@ -34,7 +34,7 @@
<che-list-header-column flex-gt-xs="25"
che-sort-value='listOrganizationMembersController.memberOrderBy'
che-sort-item='name'
che-column-title='Name'></che-list-header-column>
che-column-title='Username'></che-list-header-column>
<che-list-header-column flex-gt-xs="25"
che-sort-value='listOrganizationMembersController.memberOrderBy'
che-sort-item='email'
@ -71,7 +71,7 @@
class="che-list-item-details">
<div flex-gt-xs="25"
class="che-list-item-name">
<span class="che-xs-header noselect" hide-gt-xs>Name</span>
<span class="che-xs-header noselect" hide-gt-xs>Username</span>
<span class="member-email che-hover">{{member.name}}</span>
</div>
<div flex-gt-xs="25"

View File

@ -33,8 +33,8 @@ export class ProfileController {
this.profileUrl = cheKeycloak.getProfileUrl();
let profile = cheProfile.getProfile();
this.firstName = <string>profile.attributes['given_name'];
this.lastName = <string>profile.attributes['family_name'];
this.firstName = <string>profile.attributes['firstName'];
this.lastName = <string>profile.attributes['lastName'];
this.email = profile.email;
this.userName = <string>profile.attributes['preferred_username'];
}

View File

@ -10,8 +10,10 @@
*/
'use strict';
// This class solves problem with losing the `this` binding of instance methods.
// See http://www.couchcoder.com/angular-1-interceptors-using-typescript/
/**
* This class solves problem with losing the `this` binding of instance methods.
* See http://www.couchcoder.com/angular-1-interceptors-using-typescript/
*/
export abstract class HttpInterceptorBase {
constructor() {