Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ME]: Create record by duplicating remote record. #985

Merged
merged 1 commit into from
Sep 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 79 additions & 0 deletions apps/metadata-editor-e2e/src/e2e/import.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// eslint-disable-next-line @nx/enforce-module-boundaries
import { simpleDatasetRecordAsXmlFixture } from '@geonetwork-ui/common/fixtures'

describe('import', () => {
beforeEach(() => {
cy.login('admin', 'admin', false)
cy.visit('/catalog/search')
})

describe('import a record', () => {
beforeEach(() => {
// Open the import overlay
cy.get('[data-test="import-record"]').click()
})

it('should show the import menu overlay', () => {
cy.get('gn-ui-import-record').should('be.visible')
cy.get('[data-test="importMenuMainSection"]').should('be.visible')
})

describe('import by URL section', () => {
beforeEach(() => {
cy.get('[data-test="importFromUrlButton"]').click()
})

it('should show the import by URL section', () => {
cy.get('[data-test="importMenuImportExternalFileSection"]').should(
'be.visible'
)
})

it('should show the import by URL section', () => {
cy.get('[data-test="importMenuImportExternalFileSection"]').should(
'be.visible'
)
})

it('should import a record', () => {
cy.get('[data-test="importMenuImportExternalFileSection"]')
.find('gn-ui-url-input')
.type('http://www.marvelous-record/xml/download')

cy.intercept(
{
method: 'GET',
url: /\/xml\/download$/,
},
{
statusCode: 200,
body: simpleDatasetRecordAsXmlFixture(),
}
).as('importUrlRequest')

cy.get('gn-ui-url-input').find('gn-ui-button').find('button').click()

// Check that the record is correctly displayed
cy.get('gn-ui-record-form').should('be.visible')

cy.get('gn-ui-record-form')
.find('gn-ui-form-field')
.eq(0)
.find('input')
.invoke('val')
.should('contain', 'Copy')
})

it('should be able to navigate back to the main section', () => {
cy.get(
'[data-test="importMenuImportExternalFileSectionBackButton"]'
).click()

cy.get('[data-test="importMenuMainSection"]').should('be.visible')
cy.get('[data-test="importMenuImportExternalFileSection"]').should(
'not.exist'
)
})
})
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ export class RecordsListComponent {
paginate(page: number) {
this.searchService.setPage(page)
}

createRecord() {
this.router.navigate(['/create'])
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,30 @@ <h1 class="text-[16px] text-main font-title font-bold" translate>
<span class="uppercase" translate>dashboard.results.listResources</span>
</div>
<div class="grow"></div>
<gn-ui-button
cdkOverlayOrigin
#importRecordButton
(buttonClick)="duplicateExternalRecord()"
type="gray"
data-test="import-record"
>
<span translate>dashboard.importRecord</span>
<mat-icon
*ngIf="!isImportMenuOpen"
class="material-symbols-outlined text-primary"
>keyboard_arrow_down</mat-icon
>
<mat-icon
*ngIf="isImportMenuOpen"
class="material-symbols-outlined text-primary"
>keyboard_arrow_up</mat-icon
>
</gn-ui-button>
<ng-template #template>
<gn-ui-import-record
(closeImportMenu)="closeImportMenu()"
></gn-ui-import-record>
</ng-template>
<gn-ui-button
(buttonClick)="createRecord()"
type="primary"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { SearchFacade, SearchService } from '@geonetwork-ui/feature/search'
import { SearchRecordsComponent } from './search-records-list.component'
import {
Component,
CUSTOM_ELEMENTS_SCHEMA,
EventEmitter,
importProvidersFrom,
Input,
Expand Down Expand Up @@ -73,17 +74,19 @@ class SearchServiceMock {
}

class RouterMock {
navigate = jest.fn()
navigate = jest.fn(() => Promise.resolve(true))
}

describe('SearchRecordsComponent', () => {
let component: SearchRecordsComponent
let fixture: ComponentFixture<SearchRecordsComponent>
let router: Router
let searchService: SearchService
let searchFacade: SearchFacade

beforeEach(() => {
TestBed.configureTestingModule({
schemas: [CUSTOM_ELEMENTS_SCHEMA],
providers: [
importProvidersFrom(TranslateModule.forRoot()),
{
Expand Down Expand Up @@ -115,6 +118,8 @@ describe('SearchRecordsComponent', () => {
fixture = TestBed.createComponent(SearchRecordsComponent)
router = TestBed.inject(Router)
searchService = TestBed.inject(SearchService)
searchFacade = TestBed.inject(SearchFacade)

component = fixture.componentInstance
fixture.detectChanges()
})
Expand All @@ -123,6 +128,54 @@ describe('SearchRecordsComponent', () => {
expect(component).toBeTruthy()
})

it('should map search filters to searchText$', (done) => {
component.searchText$.subscribe((text) => {
expect(text).toBe('hello world')
done()
})
})

describe('when clicking createRecord', () => {
beforeEach(() => {
component.createRecord()
})

it('navigates to the create record page', () => {
expect(router.navigate).toHaveBeenCalledWith(['/create'])
})
})

describe('when importing a record', () => {
beforeEach(() => {
component.duplicateExternalRecord()
})

it('sets isImportMenuOpen to true', () => {
expect(component.isImportMenuOpen).toBe(true)
})
})

describe('when closing the import menu', () => {
let overlaySpy: any

beforeEach(() => {
overlaySpy = {
dispose: jest.fn(),
}
component['overlayRef'] = overlaySpy

component.closeImportMenu()
})

it('sets isImportMenuOpen to false', () => {
expect(component.isImportMenuOpen).toBe(false)
})

it('disposes the overlay', () => {
expect(overlaySpy.dispose).toHaveBeenCalled()
})
})

describe('when search results', () => {
let table, pagination
beforeEach(() => {
Expand All @@ -141,6 +194,7 @@ describe('SearchRecordsComponent', () => {
expect(pagination.currentPage).toEqual(currentPage)
expect(pagination.totalPages).toEqual(totalPages)
})

describe('when click on a record', () => {
const uniqueIdentifier = 123
const singleRecord = {
Expand All @@ -154,6 +208,7 @@ describe('SearchRecordsComponent', () => {
expect(router.navigate).toHaveBeenCalledWith(['/edit', 123])
})
})

describe('when asking for record duplication', () => {
const uniqueIdentifier = 123
const singleRecord = {
Expand All @@ -167,6 +222,7 @@ describe('SearchRecordsComponent', () => {
expect(router.navigate).toHaveBeenCalledWith(['/duplicate', 123])
})
})

describe('when click on pagination', () => {
beforeEach(() => {
pagination.newCurrentPageEvent.emit(3)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
import { CommonModule } from '@angular/common'
import { Component } from '@angular/core'
import {
ChangeDetectorRef,
Component,
ElementRef,
TemplateRef,
ViewChild,
ViewContainerRef,
} from '@angular/core'
import {
ResultsTableContainerComponent,
SearchFacade,
Expand All @@ -14,6 +21,14 @@ import { Observable } from 'rxjs'
import { UiElementsModule } from '@geonetwork-ui/ui/elements'
import { UiInputsModule } from '@geonetwork-ui/ui/inputs'
import { MatIconModule } from '@angular/material/icon'
import {
CdkConnectedOverlay,
CdkOverlayOrigin,
Overlay,
OverlayRef,
} from '@angular/cdk/overlay'
import { TemplatePortal } from '@angular/cdk/portal'
import { ImportRecordComponent } from '@geonetwork-ui/feature/editor'

@Component({
selector: 'md-editor-search-records-list',
Expand All @@ -28,32 +43,88 @@ import { MatIconModule } from '@angular/material/icon'
UiElementsModule,
UiInputsModule,
MatIconModule,
ImportRecordComponent,
CdkOverlayOrigin,
CdkConnectedOverlay,
],
})
export class SearchRecordsComponent {
@ViewChild('importRecordButton', { read: ElementRef })
private importRecordButton!: ElementRef
@ViewChild('template') template!: TemplateRef<any>
private overlayRef!: OverlayRef

searchText$: Observable<string | null> =
this.searchFacade.searchFilters$.pipe(
map((filters) => ('any' in filters ? (filters['any'] as string) : null))
)

isImportMenuOpen = false

constructor(
private router: Router,
public searchFacade: SearchFacade,
public searchService: SearchService
public searchService: SearchService,
private overlay: Overlay,
private viewContainerRef: ViewContainerRef,
private cdr: ChangeDetectorRef
) {
this.searchFacade.setPageSize(15)
this.searchFacade.resetSearch()
}

editRecord(record: CatalogRecord) {
this.router.navigate(['/edit', record.uniqueIdentifier])
this.router
.navigate(['/edit', record.uniqueIdentifier])
.catch((err) => console.error(err))
}

duplicateRecord(record: CatalogRecord) {
this.router.navigate(['/duplicate', record.uniqueIdentifier])
this.router
.navigate(['/duplicate', record.uniqueIdentifier])
.catch((err) => console.error(err))
}

createRecord() {
this.router.navigate(['/create'])
this.router.navigate(['/create']).catch((err) => console.error(err))
}

duplicateExternalRecord() {
this.isImportMenuOpen = true

const positionStrategy = this.overlay
.position()
.flexibleConnectedTo(this.importRecordButton)
.withPositions([
{
originX: 'end',
originY: 'bottom',
overlayX: 'end',
overlayY: 'top',
},
])

this.overlayRef = this.overlay.create({
hasBackdrop: true,
backdropClass: 'cdk-overlay-transparent-backdrop',
positionStrategy: positionStrategy,
scrollStrategy: this.overlay.scrollStrategies.reposition(),
})

const portal = new TemplatePortal(this.template, this.viewContainerRef)

this.overlayRef.attach(portal)

this.overlayRef.backdropClick().subscribe(() => {
this.closeImportMenu()
})
}

closeImportMenu() {
if (this.overlayRef) {
this.isImportMenuOpen = false
this.overlayRef.dispose()
this.cdr.markForCheck()
}
}
}
4 changes: 4 additions & 0 deletions apps/metadata-editor/src/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ body {
@apply text-2xl px-9 py-3;
}

.cdk-overlay-transparent-backdrop {
@apply bg-transparent;
}

.mat-mdc-button-base {
line-height: normal;
}
1 change: 1 addition & 0 deletions libs/api/metadata-converter/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ export * from './lib/iso19139'
export * from './lib/iso19115-3'
export * from './lib/find-converter'
export * from './lib/gn4'
export * from './lib/xml-utils'
Loading
Loading