mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-07-24 17:32:15 +00:00
[ADF-4552][ADF-4482] Social component refactoring, add ability to unRate, added e2e automation (#4749)
* [ADF-4552] Rating component refactoring, add ability to unRate * [ADF-4552] RTL support added * [ADF-4552] Improve behaviour and styling structure in RTL languages * [ADF-4552] Improve behaviour and styling structure in RTL languages * [ADF-4552] Added refresh rating when the node Id input changes * [ADF-4552][ADF-4482] Refactor social component, add ability to unrate, add e2e automation * [ADF-4552][ADF-4482] Added unsibscribe from Observables, added css variables, removed unused class id's * [ADF-4552][ADF-4482] Improve structure and behaviour of e2e automation tests * [ADF-4552][ADF-4482] Improve structure and behaviour of e2e automation tests * [ADF-4552][ADF-4482] fix expected single space * [ADF-4552][ADF-4482] fix lint check failure * Fix circular dependency error
This commit is contained in:
committed by
Eugenio Romano
parent
b19646d201
commit
3d67d9dc75
@@ -5,7 +5,9 @@
|
||||
<mat-icon>thumb_up</mat-icon>
|
||||
</span>
|
||||
</div>
|
||||
<div id="adf-like-counter" class="adf-like-counter">{{likesCounter}}</div>
|
||||
<div class="adf-left" *ngIf="likesCounter<=1">Like</div>
|
||||
<div class="adf-left" *ngIf="likesCounter>1">Likes</div>
|
||||
<div class="adf-like-counter-container">
|
||||
<div id="adf-like-counter" class="adf-like-counter">{{likesCounter}}</div>
|
||||
<div class="adf-left" *ngIf="likesCounter<=1">Like</div>
|
||||
<div class="adf-left" *ngIf="likesCounter>1">Likes</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -1,42 +1,41 @@
|
||||
@mixin selected {
|
||||
color: #2196f3;
|
||||
}
|
||||
|
||||
@mixin unselected {
|
||||
color: #808080;
|
||||
}
|
||||
|
||||
.adf-like-container {
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
align-items: center;
|
||||
margin-top: 13px;
|
||||
|
||||
.adf-like {
|
||||
padding: 5px;
|
||||
cursor: pointer;
|
||||
float: left;
|
||||
margin: 5px 0 5px 5px;
|
||||
.adf-like-counter-container {
|
||||
display: inherit;
|
||||
padding: 0 6px;
|
||||
}
|
||||
|
||||
.adf-left {
|
||||
padding: 0 6px;
|
||||
}
|
||||
|
||||
.adf-like-select {
|
||||
cursor: pointer;
|
||||
color: #2196f3;
|
||||
}
|
||||
|
||||
.adf-like-select:hover {
|
||||
cursor: pointer;
|
||||
color: #808080;
|
||||
@include selected;
|
||||
&:hover {
|
||||
@include unselected;
|
||||
}
|
||||
}
|
||||
|
||||
.adf-like-grey {
|
||||
cursor: pointer;
|
||||
color: #808080;
|
||||
}
|
||||
|
||||
.adf-like-grey:hover {
|
||||
cursor: pointer;
|
||||
color: #2196f3;
|
||||
}
|
||||
|
||||
.adf-like-counter {
|
||||
float: left;
|
||||
padding: 13px 0 0;
|
||||
}
|
||||
|
||||
.adf-left {
|
||||
float: left;
|
||||
padding: 13px 0 0 4px;
|
||||
@include unselected;
|
||||
&:hover {
|
||||
@include selected;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -1,12 +1,18 @@
|
||||
<mat-list id="adf-rating-container" class="adf-rating-container">
|
||||
<mat-list-item class="adf-rating-star" *ngFor="let currentRate of stars; let idx = index">
|
||||
<mat-list-item class="adf-rating-star" *ngFor="let currentRate of stars; let idx = index;">
|
||||
<span id="adf-rate-{{idx}}">
|
||||
<mat-icon id="adf-grey-star-{{idx}}" *ngIf="currentRate.fill" class="adf-colored-star"
|
||||
(click)="updateVote(idx + 1)">star_rate
|
||||
<mat-icon id="adf-colored-star-{{idx}}" *ngIf="currentRate.fill" class="adf-colored-star"
|
||||
[ngClass]="{'adf-average-star': !ratingValue}"
|
||||
(click)="updateVote(idx + 1)">star_rate
|
||||
</mat-icon>
|
||||
<mat-icon id="adf-colored-star-{{idx}}" *ngIf="!currentRate.fill" class="adf-grey-star"
|
||||
(click)="updateVote(idx + 1)">star_border
|
||||
<mat-icon id="adf-grey-star-{{idx}}" *ngIf="!currentRate.fill" class="adf-grey-star"
|
||||
(click)="updateVote(idx + 1)">star_border
|
||||
</mat-icon>
|
||||
</span>
|
||||
</mat-list-item>
|
||||
<div class="adf-rating-counter-container">
|
||||
<div id="adf-rating-counter" class="adf-rating-counter">{{ratingsCounter}}</div>
|
||||
<div class="adf-rating-left" *ngIf="ratingsCounter<=1">Rating</div>
|
||||
<div class="adf-rating-left" *ngIf="ratingsCounter>1">Ratings</div>
|
||||
</div>
|
||||
</mat-list>
|
||||
|
@@ -1,35 +1,54 @@
|
||||
$adf-rated-star-color: #ffe944;
|
||||
$adf-average-star-color: #808080;
|
||||
|
||||
.adf-rating-container {
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
|
||||
.adf-rating-counter-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 6px;
|
||||
}
|
||||
|
||||
.adf-rating-left {
|
||||
padding: 0 6px;
|
||||
}
|
||||
|
||||
.adf-rating-star {
|
||||
float: left;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
transition: all 0.3s;
|
||||
padding: 1px;
|
||||
cursor: pointer;
|
||||
width: 25px !important;
|
||||
width: 25px;
|
||||
|
||||
.mat-list-item-content {
|
||||
padding: 0 2px !important;
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
transform: rotate(13deg) scale(1.2);
|
||||
}
|
||||
}
|
||||
|
||||
.adf-colored-star {
|
||||
color: #ffe944;
|
||||
color: $adf-rated-star-color;
|
||||
}
|
||||
|
||||
.adf-grey-star {
|
||||
color: #808080;
|
||||
}
|
||||
|
||||
.adf-stars-container {
|
||||
padding: 0 !important;
|
||||
margin: 0 !important;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.adf-rating-star:hover {
|
||||
transform: rotate(13deg) scale(1.2);
|
||||
.adf-grey-star, .adf-average-star {
|
||||
color: $adf-average-star-color !important;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[dir='rtl'] .adf-rating-container {
|
||||
|
||||
.adf-rating-star {
|
||||
transform: rotate(145deg);
|
||||
}
|
||||
|
||||
.adf-rating-star:hover {
|
||||
transform: rotate(158deg) scale(1.2);
|
||||
}
|
||||
}
|
||||
|
@@ -61,75 +61,87 @@ describe('Rating component', () => {
|
||||
}
|
||||
}));
|
||||
|
||||
component.ngOnChanges();
|
||||
|
||||
fixture.detectChanges();
|
||||
|
||||
component.ngOnChanges().subscribe(() => {
|
||||
expect(element.querySelector('#adf-rating-container')).not.toBe(null);
|
||||
done();
|
||||
});
|
||||
expect(element.querySelector('#adf-rating-container')).not.toBe(null);
|
||||
done();
|
||||
});
|
||||
|
||||
it('should the star rating filled with the right grey/colored star', (done) => {
|
||||
spyOn(service, 'getRating').and.returnValue(of({
|
||||
entry: {
|
||||
id: 'fiveStar',
|
||||
aggregate: {
|
||||
numberOfRatings: 4,
|
||||
average: 3
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
fixture.detectChanges();
|
||||
|
||||
component.ngOnChanges().subscribe(() => {
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(element.querySelectorAll('.adf-colored-star').length).toBe(3);
|
||||
expect(element.querySelectorAll('.adf-grey-star').length).toBe(2);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should click on a star change your vote', (done) => {
|
||||
spyOn(service, 'getRating').and.returnValue(of({
|
||||
'entry': {
|
||||
myRating: 1,
|
||||
myRating: 3,
|
||||
'ratedAt': '2017-04-06T14:34:28.061+0000',
|
||||
'id': 'fiveStar',
|
||||
'aggregate': { 'numberOfRatings': 1, 'average': 1.0 }
|
||||
'aggregate': {'numberOfRatings': 1, 'average': 3.0}
|
||||
}
|
||||
}));
|
||||
|
||||
spyOn(service, 'postRating').and.returnValue(of({
|
||||
'entry': {
|
||||
'myRating': 3,
|
||||
'ratedAt': '2017-04-06T14:36:40.731+0000',
|
||||
'id': 'fiveStar',
|
||||
'aggregate': { 'numberOfRatings': 1, 'average': 3.0 }
|
||||
}
|
||||
}));
|
||||
component.ngOnChanges();
|
||||
|
||||
fixture.detectChanges();
|
||||
|
||||
component.ngOnChanges().subscribe(() => {
|
||||
fixture.detectChanges();
|
||||
expect(element.querySelectorAll('.adf-colored-star').length).toBe(3);
|
||||
expect(element.querySelectorAll('.adf-grey-star').length).toBe(2);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
expect(element.querySelectorAll('.adf-colored-star').length).toBe(1);
|
||||
it('should click on a star to change your vote', (done) => {
|
||||
spyOn(service, 'getRating').and.returnValue(of({
|
||||
'entry': {
|
||||
myRating: 1,
|
||||
'ratedAt': '2017-04-06T14:34:28.061+0000',
|
||||
'id': 'fiveStar',
|
||||
'aggregate': {'numberOfRatings': 1, 'average': 1.0}
|
||||
}
|
||||
}));
|
||||
|
||||
component.changeVote.subscribe(() => {
|
||||
fixture.detectChanges();
|
||||
const rateSpy = spyOn(service, 'postRating').and.returnValue(of({
|
||||
'entry': {
|
||||
'myRating': 3,
|
||||
'ratedAt': '2017-04-06T14:36:40.731+0000',
|
||||
'id': 'fiveStar',
|
||||
'aggregate': {'numberOfRatings': 1, 'average': 3.0}
|
||||
}
|
||||
}));
|
||||
|
||||
expect(element.querySelectorAll('.adf-colored-star').length).toBe(3);
|
||||
component.ngOnChanges();
|
||||
fixture.detectChanges();
|
||||
|
||||
done();
|
||||
});
|
||||
expect(element.querySelectorAll('.adf-colored-star').length).toBe(1);
|
||||
|
||||
const starThree: any = element.querySelector('#adf-colored-star-3');
|
||||
starThree.click();
|
||||
});
|
||||
component.changeVote.subscribe(() => {
|
||||
fixture.detectChanges();
|
||||
expect(rateSpy).toHaveBeenCalled();
|
||||
expect(element.querySelectorAll('.adf-colored-star').length).toBe(3);
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
const starThree: any = element.querySelector('#adf-grey-star-2');
|
||||
starThree.click();
|
||||
});
|
||||
|
||||
it('should click on the rated star to remove your vote', () => {
|
||||
spyOn(service, 'getRating').and.returnValue(of({
|
||||
'entry': {
|
||||
myRating: 3,
|
||||
'ratedAt': '2017-04-06T14:34:28.061+0000',
|
||||
'id': 'fiveStar',
|
||||
'aggregate': {'numberOfRatings': 1, 'average': 3.0}
|
||||
}
|
||||
}));
|
||||
|
||||
const deleteSpy = spyOn(service, 'deleteRating');
|
||||
|
||||
component.ngOnChanges();
|
||||
fixture.detectChanges();
|
||||
const starThree: any = element.querySelector('#adf-colored-star-2');
|
||||
starThree.click();
|
||||
expect(element.querySelectorAll('.adf-colored-star').length).toBe(3);
|
||||
expect(deleteSpy).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
@@ -18,6 +18,8 @@
|
||||
import { Component, EventEmitter, Input, OnChanges, Output, ViewEncapsulation } from '@angular/core';
|
||||
import { RatingService } from './services/rating.service';
|
||||
import { RatingEntry } from '@alfresco/js-api';
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
import { Subject } from 'rxjs';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-rating',
|
||||
@@ -33,56 +35,87 @@ export class RatingComponent implements OnChanges {
|
||||
|
||||
average: number = 0;
|
||||
|
||||
ratingsCounter = 0;
|
||||
|
||||
ratingType: string = 'fiveStar';
|
||||
|
||||
ratingValue: number;
|
||||
|
||||
/** Emitted when the "vote" gets changed. */
|
||||
@Output()
|
||||
changeVote = new EventEmitter();
|
||||
|
||||
stars: Array<any> = [];
|
||||
|
||||
onDestroy$ = new Subject<boolean>();
|
||||
|
||||
constructor(private ratingService: RatingService) {
|
||||
}
|
||||
|
||||
ngOnChanges() {
|
||||
const ratingObserver = this.ratingService.getRating(this.nodeId, this.ratingType);
|
||||
|
||||
ratingObserver.subscribe(
|
||||
this.ratingService.getRating(this.nodeId, this.ratingType)
|
||||
.pipe(takeUntil(this.onDestroy$))
|
||||
.subscribe(
|
||||
(ratingEntry: RatingEntry) => {
|
||||
if (ratingEntry.entry.aggregate) {
|
||||
this.average = ratingEntry.entry.aggregate.average;
|
||||
this.calculateStars();
|
||||
}
|
||||
this.refreshRating(ratingEntry);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
return ratingObserver;
|
||||
ngOnDestroy() {
|
||||
this.onDestroy$.next(true);
|
||||
this.onDestroy$.complete();
|
||||
}
|
||||
|
||||
calculateStars() {
|
||||
this.stars = [];
|
||||
const roundedAverage = Math.round(this.average);
|
||||
|
||||
for (let i = 0; i < 5; i++) {
|
||||
if (i < this.average) {
|
||||
this.stars.push({ fill: true });
|
||||
if (i < roundedAverage) {
|
||||
this.stars.push({fill: true});
|
||||
} else {
|
||||
this.stars.push({ fill: false });
|
||||
this.stars.push({fill: false});
|
||||
}
|
||||
}
|
||||
|
||||
this.changeVote.emit(this.average);
|
||||
}
|
||||
|
||||
updateVote(vote: number) {
|
||||
this.ratingService.postRating(this.nodeId, this.ratingType, vote).subscribe(
|
||||
if (this.ratingValue === vote) {
|
||||
this.unRateItem();
|
||||
} else {
|
||||
this.rateItem(vote);
|
||||
}
|
||||
}
|
||||
|
||||
rateItem(vote: number) {
|
||||
this.ratingService.postRating(this.nodeId, this.ratingType, vote)
|
||||
.pipe(takeUntil(this.onDestroy$))
|
||||
.subscribe(
|
||||
(ratingEntry: RatingEntry) => {
|
||||
if (ratingEntry.entry.aggregate) {
|
||||
if (this.average !== ratingEntry.entry.aggregate.average) {
|
||||
this.average = ratingEntry.entry.aggregate.average;
|
||||
this.calculateStars();
|
||||
}
|
||||
}
|
||||
this.refreshRating(ratingEntry);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
unRateItem() {
|
||||
this.ratingService.deleteRating(this.nodeId, this.ratingType).subscribe(
|
||||
() => {
|
||||
this.ratingService.getRating(this.nodeId, this.ratingType)
|
||||
.pipe(takeUntil(this.onDestroy$))
|
||||
.subscribe(
|
||||
(ratingEntry: RatingEntry) => {
|
||||
this.refreshRating(ratingEntry);
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
refreshRating(ratingEntry: RatingEntry) {
|
||||
this.ratingValue = Number.parseFloat(ratingEntry.entry.myRating);
|
||||
this.average = ratingEntry.entry.aggregate.average;
|
||||
this.ratingsCounter = ratingEntry.entry.aggregate.numberOfRatings;
|
||||
this.calculateStars();
|
||||
this.changeVote.emit(this.average);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user