[ADF - 1681] Added username and created initials pipe for user info (#2479)

* [ADF-1681] appling design spec to userinfo component

* [ADF-1681] added default pipe to userinfo

* [ADF-1681] fixed pipe name and added pipe test

* [ADF-168] fixed test for new userinfo feature

* [ADF-1681] fixed test

* [ADF-1681] fixed style for initials image

* [ADF-1681] fixed button for new material design spec

* [ADF - 1681] Added documentation for the new values

* [ADF - 1681] added some test to check new input attributes
This commit is contained in:
Vito
2017-10-16 22:55:40 +01:00
committed by Eugenio Romano
parent bf05b5df05
commit 3023d30d38
15 changed files with 325 additions and 90 deletions

View File

@@ -57,7 +57,7 @@ export let fakeBpmUser = {
lastUpdate: 'fake-update-date',
latestSyncTimeStamp: 'fake-timestamp',
password: 'fake-password',
pictureId: 'src/assets/bpmImg.gif',
pictureId: 12,
status: 'fake-status',
tenantId: 'fake-tenant-id',
tenantName: 'fake-tenant-name',

View File

@@ -1,9 +1,26 @@
<div id="userinfo_container" *ngIf="isLoggedIn()">
<div id="userinfo_container"
[class.adf-userinfo-name-right]="showOnRight()"
class="adf-userinfo-container" *ngIf="isLoggedIn()">
<span *ngIf="ecmUser && showName" id="adf-userinfo-ecm-name-display"
class="adf-userinfo-name">{{ecmUser.fullNameDisplay}}</span>
<span *ngIf="bpmUser && !ecmUser && showName" id="adf-userinfo-bpm-name-display"
class="adf-userinfo-name">{{bpmUser.fullNameDisplay}}</span>
<button mat-button [matMenuTriggerFor]="menu" class="adf-userinfo-menu_button">
<div class="adf-userinfo-button-profile" id="user-profile" data-automation-id="user-profile">
<img id="logged-user-img" [src]="getUserAvatar()"
alt="user-info-profile-button"
(error)="onImageLoadingError($event)" class="adf-userinfo-profile-image"/>
<div class="adf-userinfo-button-profile" id="user-profile" data-automation-id="user-profile">
<div *ngIf="bpmUser && !ecmUser" id="bpm-user-image">
<div [outerHTML]="bpmUser | usernameInitials:'adf-userinfo-pic'"></div>
<div *ngIf="bpmUser.pictureId" class="adf-userinfo-profile-container">
<img id="logged-user-img" [src]="bpmUserImage" alt="user-info-profile-button"
class="adf-userinfo-profile-image"/>
</div>
</div>
<div *ngIf="ecmUser" id="ecm-user-image">
<div [outerHTML]="ecmUser | usernameInitials:'adf-userinfo-pic'"></div>
<div *ngIf="ecmUser.avatarId" class="adf-userinfo-profile-container">
<img id="logged-user-img" [src]="ecmUserImage" alt="user-info-profile-button"
class="adf-userinfo-profile-image"/>
</div>
</div>
</div>
</button>
<mat-menu #menu="matMenu" id="user-profile-lists" [xPosition]="menuPositionX" [yPosition]="menuPositionY" [overlapTrigger]="false" class="adf-userinfo-menu">
@@ -12,11 +29,11 @@
<mat-tab id="ecm-panel" label="Content Services" *ngIf="ecmUser">
<mat-card class="adf-userinfo-card">
<mat-card-header class="adf-userinfo-card-header" [style.background-image]="'url(' + ecmBackgroundImage + ')'">
<img class="adf-userinfo-profile-picture"
id="ecm-user-detail-image"
alt="ecm-profile-image"
(error)="onImageLoadingError($event)"
[src]="getEcmUserAvatar()" />
<div [outerHTML]="ecmUser | usernameInitials:'adf-userinfo-profile-initials'"></div>
<div *ngIf="ecmUser.avatarId" class="adf-userinfo-profile-container">
<img class="adf-userinfo-profile-picture" id="ecm-user-detail-image"
alt="ecm-profile-image" [src]="ecmUserImage" />
</div>
<div class="adf-userinfo-title" id="ecm-username">{{ecmUser.fullNameDisplay}}</div>
</mat-card-header>
<mat-card-content>
@@ -38,11 +55,9 @@
<mat-tab label="Process Services" id="bpm-panel" *ngIf="bpmUser">
<mat-card class="adf-userinfo-card">
<mat-card-header class="adf-userinfo-card-header" [style.background-image]="'url(' + bpmBackgroundImage + ')'">
<img class="adf-userinfo-profile-picture"
id="bpm-user-detail-image"
alt="bpm-profile-image"
(error)="onImageLoadingError($event)"
[src]="getBpmUserAvatar()"/>
<div [outerHTML]="bpmUser | usernameInitials:'adf-userinfo-profile-initials'"></div>
<img *ngIf="bpmUser.pictureId" class="adf-userinfo-profile-picture" id="bpm-user-detail-image"
alt="bpm-profile-image" [src]="bpmUserImage"/>
<div class="adf-userinfo-title" id="bpm-username">{{bpmUser.fullNameDisplay}}</div>
</mat-card-header>
<mat-card-content>

View File

@@ -2,9 +2,38 @@
$primary: map-get($theme, primary);
$accent: map-get($theme, accent);
$warn: map-get($theme, warn);
$foreground: map-get($theme, foreground);
.adf {
&-userinfo-container {
display: flex;
align-items: center;
padding: 0 5px 0 5px;
}
&-userinfo-name-right {
flex-direction: row-reverse;
}
&-userinfo-name {
padding: 0 5px 0 5px;
}
&-userinfo-pic {
background: mat-color($primary, 300);
display: inline-block;
width: 40px;
height: 40px;
border-radius: 100px;
text-align: center;
font-weight: bolder;
font-size: 18px;
text-transform: uppercase;
vertical-align: middle;
line-height: 40px
}
&-userinfo-profile-image {
text-align: center;
border-radius: 90%;
@@ -13,6 +42,11 @@
margin-right: 0;
cursor: pointer;
vertical-align: middle;
margin-left: -45px;
}
&-userinfo-profile-container{
display: inline-block;
}
&-userinfo-menu_button.mat-button {
@@ -101,9 +135,25 @@
border-radius: 50%;
height: 80px;
width: 80px;
z-index: 3;
margin-left: -88px;
margin-right: 8px;
}
&-userinfo-profile-initials {
background-size: cover;
background: mat-color($primary, 300);
border-radius: 50%;
height: 80px;
width: 80px;
margin-left: 0;
margin-right: 8px;
font-size: 35px;
font-weight: 400;
letter-spacing: 0;
line-height: 78px;
overflow: hidden;
display: flex;
justify-content: space-around;
}
&-userinfo-button-profile {

View File

@@ -81,17 +81,6 @@ describe('User info component', () => {
expect(element.querySelector('#user-profile-lists')).toBeNull();
});
it('should return the anonymous avatar when users do not have images', () => {
let event = <any> {
target: {
src: ''
}
};
userInfoComp.onImageLoadingError(event);
expect(event.target.src).toContain('assets/images/anonymous');
expect(event.target.src).toContain('.gif');
});
describe('when user is logged on ecm', () => {
beforeEach(() => {
@@ -113,6 +102,7 @@ describe('User info component', () => {
});
fixture.whenStable().then(() => {
fixture.detectChanges();
let imageButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#logged-user-img');
imageButton.click();
fixture.detectChanges();
@@ -125,6 +115,65 @@ describe('User info component', () => {
});
}));
it('should show the username when showName attribute is true', async(() => {
fixture.detectChanges();
jasmine.Ajax.requests.mostRecent().respondWith({
status: 200,
contentType: 'application/json',
responseText: JSON.stringify({entry: fakeEcmEditedUser})
});
fixture.whenStable().then(() => {
fixture.detectChanges();
expect(userInfoComp.showName).toBeTruthy();
expect(element.querySelector('#adf-userinfo-ecm-name-display')).not.toBeNull();
});
}));
it('should hide the username when showName attribute is false', async(() => {
userInfoComp.showName = false;
fixture.detectChanges();
jasmine.Ajax.requests.mostRecent().respondWith({
status: 200,
contentType: 'application/json',
responseText: JSON.stringify({entry: fakeEcmEditedUser})
});
fixture.whenStable().then(() => {
fixture.detectChanges();
expect(element.querySelector('#adf-userinfo-ecm-name-display')).toBeNull();
});
}));
it('should have the defined class to show the name on the right side', async(() => {
fixture.detectChanges();
jasmine.Ajax.requests.mostRecent().respondWith({
status: 200,
contentType: 'application/json',
responseText: JSON.stringify({entry: fakeEcmEditedUser})
});
fixture.whenStable().then(() => {
fixture.detectChanges();
expect(element.querySelector('#userinfo_container').classList).toContain('adf-userinfo-name-right');
});
}));
it('should not have the defined class to show the name on the left side', async(() => {
userInfoComp.namePosition = 'left';
fixture.detectChanges();
jasmine.Ajax.requests.mostRecent().respondWith({
status: 200,
contentType: 'application/json',
responseText: JSON.stringify({entry: fakeEcmEditedUser})
});
fixture.whenStable().then(() => {
fixture.detectChanges();
expect(element.querySelector('#userinfo_container').classList).not.toContain('adf-userinfo-name-right');
});
}));
describe('and has image', () => {
beforeEach(async(() => {
@@ -139,6 +188,7 @@ describe('User info component', () => {
it('should get the ecm current user image from the service', async(() => {
fixture.whenStable().then(() => {
fixture.detectChanges();
let imageButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#logged-user-img');
imageButton.click();
fixture.detectChanges();
@@ -152,6 +202,7 @@ describe('User info component', () => {
it('should get the ecm user informations from the service', () => {
fixture.whenStable().then(() => {
fixture.detectChanges();
let imageButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#logged-user-img');
imageButton.click();
fixture.detectChanges();
@@ -172,17 +223,17 @@ describe('User info component', () => {
describe('and has no image', () => {
beforeEach(async(() => {
userInfoComp.anonymousImageUrl = userInfoComp.anonymousImageUrl.replace('/base/dist', '');
fixture.detectChanges();
jasmine.Ajax.requests.mostRecent().respondWith({
status: 200,
contentType: 'application/json',
responseText: JSON.stringify({entry: fakeEcmUserNoImage})
});
fixture.whenStable().then(() => fixture.detectChanges());
}));
it('should show N/A when the job title is null', async(() => {
let imageButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#logged-user-img');
let imageButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#user-initials-image');
imageButton.click();
fixture.detectChanges();
expect(element.querySelector('#userinfo_container')).not.toBeNull();
@@ -193,7 +244,7 @@ describe('User info component', () => {
}));
it('should not show the tabs', () => {
let imageButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#logged-user-img');
let imageButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#user-initials-image');
imageButton.click();
fixture.detectChanges();
let tabHeader = fixture.debugElement.query(By.css('#tab-group-env'));
@@ -209,8 +260,6 @@ describe('User info component', () => {
spyOn(stubAuthService, 'isBpmLoggedIn').and.returnValue(true);
spyOn(stubAuthService, 'isLoggedIn').and.returnValue(true);
jasmine.Ajax.install();
userInfoComp.anonymousImageUrl = userInfoComp.anonymousImageUrl.replace('/base/dist', '');
}));
afterEach(() => {
@@ -226,6 +275,7 @@ describe('User info component', () => {
});
fixture.whenStable().then(() => {
fixture.detectChanges();
let imageButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#logged-user-img');
imageButton.click();
fixture.detectChanges();
@@ -323,7 +373,6 @@ describe('User info component', () => {
spyOn(stubAuthService, 'isBpmLoggedIn').and.returnValue(true);
spyOn(stubAuthService, 'isLoggedIn').and.returnValue(true);
spyOn(stubContent, 'getContentUrl').and.returnValue('src/assets/images/ecmImg.gif');
userInfoComp.anonymousImageUrl = userInfoComp.anonymousImageUrl.replace('/base/dist', '');
jasmine.Ajax.install();
}));
@@ -342,6 +391,7 @@ describe('User info component', () => {
}));
beforeEach(() => {
fixture.detectChanges();
let imageButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#logged-user-img');
imageButton.click();
fixture.detectChanges();
@@ -387,9 +437,12 @@ describe('User info component', () => {
it('should show the bpm image if ecm does not have it', () => {
userInfoComp.ecmUserImage = null;
fixture.detectChanges();
expect(element.querySelector('#userinfo_container')).toBeDefined();
expect(element.querySelector('#logged-user-img')).toBeDefined();
expect(element.querySelector('#logged-user-img').getAttribute('src')).toContain('rest/admin/profile-picture');
fixture.whenStable().then(() => {
fixture.detectChanges();
expect(element.querySelector('#userinfo_container')).toBeDefined();
expect(element.querySelector('#logged-user-img')).toBeDefined();
expect(element.querySelector('#logged-user-img').getAttribute('src')).toContain('rest/admin/profile-picture');
});
});
it('should show the tabs for the env', () => {

View File

@@ -45,7 +45,10 @@ export class UserInfoComponent implements OnInit {
menuPositionY: string = 'below';
@Input()
fallBackThumbnailImage: string;
showName: boolean = true;
@Input()
namePosition: string = 'right';
ecmUser: EcmUserModel;
bpmUser: BpmUserModel;
@@ -78,9 +81,9 @@ export class UserInfoComponent implements OnInit {
if (this.authService.isEcmLoggedIn()) {
this.ecmUserService.getCurrentUserInfo()
.subscribe((res) => {
this.ecmUser = new EcmUserModel(res);
this.getEcmAvatar();
}
this.ecmUser = new EcmUserModel(res);
this.getEcmAvatar();
}
);
} else {
this.ecmUser = null;
@@ -101,13 +104,6 @@ export class UserInfoComponent implements OnInit {
}
}
onImageLoadingError(event) {
if (event) {
let element = <any> event.target;
element.src = this.fallBackThumbnailImage || this.anonymousImageUrl;
}
}
stopClosing(event) {
event.stopPropagation();
}
@@ -116,15 +112,7 @@ export class UserInfoComponent implements OnInit {
this.ecmUserImage = this.ecmUserService.getUserProfileImage(this.ecmUser.avatarId);
}
getUserAvatar() {
return this.ecmUserImage || this.bpmUserImage;
}
getBpmUserAvatar() {
return this.bpmUserImage;
}
getEcmUserAvatar() {
return this.ecmUserImage;
showOnRight() {
return this.namePosition === 'right';
}
}