Skip to content

Commit

Permalink
Merge pull request #300 from geonetwork/datahub-show-favorites
Browse files Browse the repository at this point in the history
Datahub / Add the possibility to set records as favorites
  • Loading branch information
jahow authored Sep 5, 2022
2 parents c092f77 + ac16ad1 commit 9fb65e0
Show file tree
Hide file tree
Showing 29 changed files with 772 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
</div>
</div>
<div
class="content flex-grow grid grid-cols-1 auto-rows-min justify-between min-w-0 pr-6 sm:pl-6 sm:pr-12 sm:grid-cols-10"
class="content flex-grow grid grid-cols-1 auto-rows-min justify-between min-w-0 pr-6 sm:pl-6 sm:pr-12 sm:grid-cols-10 relative"
>
<div
class="order-1 mb-3 mt-5 font-title text-21 text-title line-clamp-2 sm:line-clamp-1 sm:col-span-10 sm:mt-2"
Expand Down Expand Up @@ -42,5 +42,10 @@
>map</mat-icon
>
</div>
<gn-ui-favorite-star
class="absolute"
style="top: -1.125em; right: 0.4em"
[record]="record"
></gn-ui-favorite-star>
</div>
</div>
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<div>
<span class="align-text-top mr-1.5 favorite-count" *ngIf="hasFavoriteCount">{{
favoriteCount
}}</span>
<gn-ui-star-toggle
[toggled]="isFavorite$ | async"
(newValue)="toggleFavorite($event)"
[disabled]="loading || (isAnonymous$ | async)"
[attr.title]="
(isAnonymous$ | async) ? ('favorite.not.authenticated' | translate) : null
"
></gn-ui-star-toggle>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
import { ComponentFixture, TestBed } from '@angular/core/testing'
import { FavoriteStarComponent } from './favorite-star.component'
import { BehaviorSubject, of, throwError } from 'rxjs'
import { AuthService } from '@geonetwork-ui/feature/auth'
import { FavoritesService } from '../favorites.service'
import { StarToggleComponent } from '@geonetwork-ui/ui/inputs'
import { RECORDS_SUMMARY_FIXTURE } from '@geonetwork-ui/util/shared'
import { By } from '@angular/platform-browser'
import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'
import { TranslateModule } from '@ngx-translate/core'

class AuthServiceMock {
authReady = jest.fn(() => this._authSubject)
_authSubject = new BehaviorSubject({
id: '1234',
name: 'fakeuser',
})
}

class FavoritesServiceMock {
myFavoritesUuid$ = new BehaviorSubject<string[]>([])
removeFromFavorites = jest.fn(() => of(true))
addToFavorites = jest.fn(() => of(true))
}

describe('FavoriteStarComponent', () => {
let component: FavoriteStarComponent
let fixture: ComponentFixture<FavoriteStarComponent>
let authService: AuthService
let favoritesService: FavoritesService
let favoriteCountEl: HTMLElement
let starToggle: StarToggleComponent

beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [FavoriteStarComponent, StarToggleComponent],
imports: [TranslateModule.forRoot()],
providers: [
{
provide: AuthService,
useClass: AuthServiceMock,
},
{
provide: FavoritesService,
useClass: FavoritesServiceMock,
},
],
schemas: [NO_ERRORS_SCHEMA],
})
.overrideComponent(FavoriteStarComponent, {
set: {
changeDetection: ChangeDetectionStrategy.Default,
},
})
.compileComponents()

authService = TestBed.inject(AuthService)
favoritesService = TestBed.inject(FavoritesService)
fixture = TestBed.createComponent(FavoriteStarComponent)
component = fixture.componentInstance
component.record = { ...RECORDS_SUMMARY_FIXTURE[0], favoriteCount: 42 }
fixture.detectChanges()
starToggle = fixture.debugElement.query(
By.directive(StarToggleComponent)
).componentInstance
})

it('should create', () => {
expect(component).toBeTruthy()
})

describe('when a record has a favorite count', () => {
beforeEach(() => {
favoriteCountEl = fixture.debugElement.query(
By.css('.favorite-count')
).nativeElement
})
it('shows the amount of favorites on the record', () => {
expect(favoriteCountEl).toBeTruthy()
expect(favoriteCountEl.textContent).toEqual(
component.record.favoriteCount.toString()
)
})
})
describe('when a record does not have a favorite count', () => {
beforeEach(() => {
component.record = { ...RECORDS_SUMMARY_FIXTURE[0] }
delete component.record.favoriteCount
fixture.detectChanges()
})
it('does not show the amount of favorites on the record', () => {
expect(fixture.debugElement.query(By.css('.favorite-count'))).toBeFalsy()
})
})
describe('when not authenticated', () => {
beforeEach(() => {
;(authService as any)._authSubject.next(null)
fixture.detectChanges()
})
it('star toggle is disabled', () => {
expect(starToggle.disabled).toBe(true)
})
})
describe('when authenticated', () => {
it('star toggle is enabled', () => {
expect(starToggle.disabled).toBe(false)
})
describe('on toggle state change', () => {
beforeEach(() => {
favoriteCountEl = fixture.debugElement.query(
By.css('.favorite-count')
).nativeElement
})
describe('if record is not part of favorite', () => {
beforeEach(() => {
;(favoritesService as any).myFavoritesUuid$.next([
'aaa',
'bbb',
'ccc',
])
starToggle.newValue.emit(true)
fixture.detectChanges()
})
it('adds record to favorites', () => {
expect(favoritesService.addToFavorites).toHaveBeenCalledWith([
component.record.uuid,
])
expect(favoritesService.removeFromFavorites).not.toHaveBeenCalled()
})
it('increase record favorite count by one', () => {
expect(favoriteCountEl.textContent).toEqual(
(component.record.favoriteCount + 1).toString()
)
})
})
describe('if record is part of favorite', () => {
beforeEach(() => {
;(favoritesService as any).myFavoritesUuid$.next([
'aaa',
'bbb',
component.record.uuid,
])
starToggle.newValue.emit(false)
fixture.detectChanges()
})
it('removes record from favorites', () => {
expect(favoritesService.removeFromFavorites).toHaveBeenCalledWith([
component.record.uuid,
])
expect(favoritesService.addToFavorites).not.toHaveBeenCalled()
})
it('decrease record favorite count by one', () => {
expect(favoriteCountEl.textContent).toEqual(
(component.record.favoriteCount - 1).toString()
)
})
})
describe('two subsequent changes', () => {
beforeEach(() => {
;(favoritesService as any).myFavoritesUuid$.next([
'aaa',
'bbb',
component.record.uuid,
])
starToggle.newValue.emit(false)
starToggle.newValue.emit(true)
fixture.detectChanges()
})
it('removes and adds record to favorites', () => {
expect(favoritesService.removeFromFavorites).toHaveBeenCalledWith([
component.record.uuid,
])
expect(favoritesService.addToFavorites).toHaveBeenCalledWith([
component.record.uuid,
])
})
it('record favorite count stays the same', () => {
expect(favoriteCountEl.textContent).toEqual(
component.record.favoriteCount.toString()
)
})
})
describe('if favorite modification fails', () => {
beforeEach(() => {
favoritesService.addToFavorites = () => throwError('blargz')
starToggle.newValue.emit(true)
fixture.detectChanges()
})
it('does not change record favorite count', () => {
expect(favoriteCountEl.textContent).toEqual(
component.record.favoriteCount.toString()
)
})
})
})
})
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { ChangeDetectionStrategy, Component, Input } from '@angular/core'
import { FavoritesService } from '../favorites.service'
import { MetadataRecord } from '@geonetwork-ui/util/shared'
import { map } from 'rxjs/operators'
import { AuthService } from '@geonetwork-ui/feature/auth'

@Component({
selector: 'gn-ui-favorite-star',
templateUrl: './favorite-star.component.html',
styleUrls: ['./favorite-star.component.css'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class FavoriteStarComponent {
@Input() set record(value) {
this.record_ = value
this.favoriteCount =
'favoriteCount' in this.record_ ? this.record_.favoriteCount : null
}
get record() {
return this.record_
}
isFavorite$ = this.favoritesService.myFavoritesUuid$.pipe(
map((favorites) => favorites.indexOf(this.record.uuid) > -1)
)
isAnonymous$ = this.authService
.authReady()
.pipe(map((user) => !user || !('id' in user)))
record_: MetadataRecord
favoriteCount: number | null
loading = false

get hasFavoriteCount() {
return this.favoriteCount !== null
}

constructor(
private favoritesService: FavoritesService,
private authService: AuthService
) {}

toggleFavorite(isFavorite) {
this.loading = true
;(isFavorite
? this.favoritesService.addToFavorites([this.record.uuid])
: this.favoritesService.removeFromFavorites([this.record.uuid])
).subscribe({
complete: () => {
if (this.hasFavoriteCount) {
this.favoriteCount += isFavorite ? 1 : -1
}
this.loading = false
},
error: () => {
this.loading = false
},
})
}
}
Loading

0 comments on commit 9fb65e0

Please sign in to comment.