Skip to content

Commit

Permalink
feat: implement my-record in datahub and metadata-editor
Browse files Browse the repository at this point in the history
  • Loading branch information
f-necas committed Oct 5, 2023
1 parent 7c8b49c commit 9b4b506
Show file tree
Hide file tree
Showing 25 changed files with 234 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ <h2 class="text-xl mr-4 font-title" translate>
></gn-ui-filter-dropdown>
<div
class="spatial-filter-toggle sm:col-span-2"
*ngIf="isOpen && searchFacade.hasSpatialFilter$ | async"
*ngIf="isOpen && (searchFacade.hasSpatialFilter$ | async)"
>
<gn-ui-check-toggle
[title]="'search.filters.useSpatialFilterHelp' | translate"
Expand All @@ -63,6 +63,30 @@ <h2 class="text-xl mr-4 font-title" translate>
(toggled)="toggleSpatialFilter($event)"
></gn-ui-check-toggle>
</div>
<div class="sm:col-span-2" *ngIf="userId && isOpen">
<gn-ui-check-toggle
[title]="'search.filters.myRecordsHelp' | translate"
[label]="'search.filters.myRecords' | translate"
[color]="'secondary'"
[value]="myRecordsFilterEnabled$ | async"
(toggled)="toggleMyRecordsFilter($event)"
></gn-ui-check-toggle>
</div>
<div
class="sm:col-span-2"
*ngIf="!userId && (myRecordsFilterEnabled$ | async) && isOpen"
>
<gn-ui-button
type="light"
extraClass="text-sm align-middle"
(buttonClick)="toggleMyRecordsFilter(false)"
>
<span>{{ 'search.filters.otherRecords' | translate }}</span>
<mat-icon class="material-symbols-outlined ml-3 opacity-40"
>close</mat-icon
>
</gn-ui-button>
</div>
</div>
<div
class="col-span-2 flex flex-col justify-between"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,9 @@ import { SearchFiltersComponent } from './search-filters.component'
import { TranslateModule } from '@ngx-translate/core'
import { By } from '@angular/platform-browser'
import { FormsModule } from '@angular/forms'
import {
AggregationsTypes,
FieldFilters,
} from '@geonetwork-ui/common/domain/search'
import { FieldFilters } from '@geonetwork-ui/common/domain/search'
import { USER_FIXTURE } from '@geonetwork-ui/common/fixtures'
import { AuthService } from '@geonetwork-ui/api/repository/gn4'

jest.mock('@geonetwork-ui/util/app-config', () => ({
getOptionalSearchConfig: () => ({
Expand Down Expand Up @@ -67,6 +66,7 @@ export class MockFilterDropdownComponent {
@Input() title: string
}
const state = { OrgForResource: { mel: true } } as FieldFilters
const user = USER_FIXTURE()
class SearchFacadeMock {
searchFilters$ = new BehaviorSubject(state)
hasSpatialFilter$ = new BehaviorSubject(false)
Expand Down Expand Up @@ -103,6 +103,12 @@ class FieldsServiceMock {
}
}

class AuthServiceMock {
user$ = new BehaviorSubject(user)
authReady = jest.fn(() => this._authSubject$)
_authSubject$ = new BehaviorSubject({})
}

describe('SearchFiltersComponent', () => {
let component: SearchFiltersComponent
let fixture: ComponentFixture<SearchFiltersComponent>
Expand Down Expand Up @@ -131,6 +137,10 @@ describe('SearchFiltersComponent', () => {
provide: FieldsService,
useClass: FieldsServiceMock,
},
{
provide: AuthService,
useClass: AuthServiceMock,
},
],
})
.overrideComponent(SearchFiltersComponent, {
Expand All @@ -155,7 +165,9 @@ describe('SearchFiltersComponent', () => {

describe('spatial filter button', () => {
function getCheckToggleDebugElement() {
return fixture.debugElement.query(By.directive(MockCheckToggleComponent))
return fixture.debugElement.queryAll(
By.directive(MockCheckToggleComponent)
)
}

describe('when panel is closed', () => {
Expand All @@ -164,7 +176,7 @@ describe('SearchFiltersComponent', () => {
fixture.detectChanges()
})
it('does not show up', () => {
expect(getCheckToggleDebugElement()).toBeFalsy()
expect(getCheckToggleDebugElement().length).toBeFalsy()
})
})
describe('when panel is opened & a spatial filter is unavailable', () => {
Expand All @@ -174,7 +186,7 @@ describe('SearchFiltersComponent', () => {
fixture.detectChanges()
})
it('does not show up', () => {
expect(getCheckToggleDebugElement()).toBeFalsy()
expect(getCheckToggleDebugElement().length).toBe(1)
})
})
describe('when panel is opened & a spatial filter is available', () => {
Expand All @@ -185,11 +197,11 @@ describe('SearchFiltersComponent', () => {
fixture.detectChanges()
})
it('does show up', () => {
expect(getCheckToggleDebugElement()).toBeTruthy()
expect(getCheckToggleDebugElement().length).toBe(2)
})
it('has the value set in the state', () => {
expect(
getCheckToggleDebugElement().componentInstance.value
getCheckToggleDebugElement()[0].componentInstance.value
).toBeTruthy()
})
})
Expand All @@ -201,7 +213,7 @@ describe('SearchFiltersComponent', () => {
})
it('emits a SetSpatialFilterEnabled action', () => {
const checkToggleComponent =
getCheckToggleDebugElement().componentInstance
getCheckToggleDebugElement()[0].componentInstance
checkToggleComponent.toggled.emit(false)
expect(searchFacade.setSpatialFilterEnabled).toHaveBeenCalledWith(false)
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,16 @@ import {
QueryList,
ViewChildren,
} from '@angular/core'
import { AuthService } from '@geonetwork-ui/api/repository/gn4'
import {
FieldsService,
FilterDropdownComponent,
SearchFacade,
SearchService,
} from '@geonetwork-ui/feature/search'
import { getOptionalSearchConfig } from '@geonetwork-ui/util/app-config'
import { Observable, switchMap } from 'rxjs'
import { map } from 'rxjs/operators'

@Component({
selector: 'datahub-search-filters',
Expand All @@ -24,14 +27,28 @@ export class SearchFiltersComponent implements OnInit {
filters: QueryList<FilterDropdownComponent>
searchConfig: { fieldName: string; title: string }[]
isOpen = false
userId: string
myRecordsFilterEnabled$: Observable<boolean> =
this.searchFacade.searchFilters$.pipe(
switchMap((filters) => {
return this.fieldsService.readFieldValuesFromFilters(filters)
}),
map((fieldValues) =>
fieldValues['owner'] && Array.isArray(fieldValues['owner'])
? fieldValues['owner'].length > 0
: !!fieldValues['owner']
)
)

constructor(
public searchFacade: SearchFacade,
private searchService: SearchService,
private fieldsService: FieldsService
private fieldsService: FieldsService,
private authService: AuthService
) {}

ngOnInit(): void {
this.authService.user$.subscribe((user) => (this.userId = user?.id))
this.searchConfig = (
getOptionalSearchConfig().ADVANCED_FILTERS || [
'publisher',
Expand Down Expand Up @@ -70,6 +87,12 @@ export class SearchFiltersComponent implements OnInit {
this.searchFacade.setSpatialFilterEnabled(enabled)
}

toggleMyRecordsFilter(enabled: boolean) {
this.fieldsService
.buildFiltersFromFieldValues({ owner: enabled ? this.userId : [] })
.subscribe((filters) => this.searchService.updateFilters(filters))
}

clearFilters() {
const fieldNames = this.filters.map((component) => component.fieldName)
const fieldValues = fieldNames.reduce(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
<md-editor-records-list [title]="'dashboard.records.myRecords' | translate">
<md-editor-records-list
[title]="'dashboard.records.myRecords' | translate"
[linkToDatahub]="getDatahubUrl()"
>
</md-editor-records-list>
Original file line number Diff line number Diff line change
@@ -1,20 +1,41 @@
import { ComponentFixture, TestBed } from '@angular/core/testing'
import { MyRecordsComponent } from './my-records.component'
import { SearchFacade } from '@geonetwork-ui/feature/search'
import { Component, importProvidersFrom } from '@angular/core'
import { FieldsService, SearchFacade } from '@geonetwork-ui/feature/search'
import { Component, importProvidersFrom, Input } from '@angular/core'
import { TranslateModule } from '@ngx-translate/core'
import { RecordsListComponent } from '../records-list.component'
import { BehaviorSubject, of } from 'rxjs'
import { USER_FIXTURE } from '@geonetwork-ui/common/fixtures'
import { AuthService } from '@geonetwork-ui/api/repository/gn4'
import { EditorRouterService } from '../../router.service'

@Component({
// eslint-disable-next-line
selector: 'md-editor-records-list',
template: '',
standalone: true,
})
export class MockRecordsListComponent {}
export class MockRecordsListComponent {
@Input() linkToDatahub: string
}
const user = USER_FIXTURE()

class SearchFacadeMock {
resetSearch = jest.fn()
updateFilters = jest.fn()
}
class EditorRouterServiceMock {
getDatahubSearchRoute = jest.fn(() => `/datahub/`)
}

class AuthServiceMock {
user$ = new BehaviorSubject(user)
authReady = jest.fn(() => this._authSubject$)
_authSubject$ = new BehaviorSubject({})
}

class FieldsServiceMock {
buildFiltersFromFieldValues = jest.fn((val) => of(val))
}

describe('MyRecordsComponent', () => {
Expand All @@ -26,10 +47,22 @@ describe('MyRecordsComponent', () => {
TestBed.configureTestingModule({
providers: [
importProvidersFrom(TranslateModule.forRoot()),
{
provide: FieldsService,
useClass: FieldsServiceMock,
},
{
provide: SearchFacade,
useClass: SearchFacadeMock,
},
{
provide: AuthService,
useClass: AuthServiceMock,
},
{
provide: EditorRouterService,
useClass: EditorRouterServiceMock,
},
],
}).overrideComponent(MyRecordsComponent, {
remove: {
Expand All @@ -53,5 +86,18 @@ describe('MyRecordsComponent', () => {
it('clears filters on init', () => {
expect(searchFacade.resetSearch).toHaveBeenCalled()
})
it('Update filters on init', () => {
expect(searchFacade.updateFilters).toHaveBeenCalledWith({
owner: user.id,
})
})
})

describe('datahub url', () => {
it('get correct url', () => {
expect(component.getDatahubUrl()).toEqual(
'http://localhost/datahub/?owner=46798'
)
})
})
})
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import { Component } from '@angular/core'
import { Component, OnDestroy, OnInit } from '@angular/core'
import { CommonModule } from '@angular/common'
import { TranslateModule } from '@ngx-translate/core'
import { RecordsListComponent } from '../records-list.component'
import { SearchFacade } from '@geonetwork-ui/feature/search'
import { FieldsService, SearchFacade } from '@geonetwork-ui/feature/search'
import { AuthService } from '@geonetwork-ui/api/repository/gn4'
import { EditorRouterService } from '../../router.service'
import { Subscription } from 'rxjs'

@Component({
selector: 'md-editor-my-records',
Expand All @@ -11,8 +14,41 @@ import { SearchFacade } from '@geonetwork-ui/feature/search'
standalone: true,
imports: [CommonModule, TranslateModule, RecordsListComponent],
})
export class MyRecordsComponent {
constructor(public searchFacade: SearchFacade) {
export class MyRecordsComponent implements OnInit, OnDestroy {
private sub: Subscription
private ownerId: string

constructor(
public fieldsService: FieldsService,
public searchFacade: SearchFacade,
private authService: AuthService,
private router: EditorRouterService
) {}

ngOnInit() {
this.searchFacade.resetSearch()
this.sub = this.authService.user$.subscribe((user) => {
this.ownerId = user.id
this.fieldsService
.buildFiltersFromFieldValues({ owner: user.id })
.subscribe((filters) => {
this.searchFacade.updateFilters(filters)
})
})
}

getDatahubUrl(): string {
const url = new URL(
`${this.router.getDatahubSearchRoute()}`,
this.router.getDatahubSearchRoute().startsWith('http')
? this.router.getDatahubSearchRoute()
: window.location.toString()
)
url.searchParams.append('owner', this.ownerId)
return url.toString()
}

ngOnDestroy(): void {
this.sub.unsubscribe()
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
<main class="grow bg-gray-100 p-12 flex flex-col justify-between gap-12">
<div class="flex justify-center gap-8 items-baseline">
<h1 class="text-[56px] font-title grow">{{ title }}</h1>
<a
class="text-[30px] hover:underline"
*ngIf="linkToDatahub"
[href]="linkToDatahub"
target="_blank"
>
{{ searchFacade.resultsHits$ | async }}
<span>{{ 'record.metadata.publications' | translate }}</span>
</a>
</div>
<div
class="shadow rounded bg-white grow"
Expand Down
Loading

0 comments on commit 9b4b506

Please sign in to comment.