Skip to content

Commit

Permalink
feature(metadata-editor): added FormFieldOverviews component to the F…
Browse files Browse the repository at this point in the history
…ormFieldComponent.
  • Loading branch information
Romuald Caplier committed Jul 29, 2024
1 parent 1f5faaf commit 28c0b55
Show file tree
Hide file tree
Showing 13 changed files with 239 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export interface MetadataResourceApiModel {
metadataResourceExternalManagementProperties?: MetadataResourceExternalManagementPropertiesApiModel
lastModification?: string
version?: string
url?: string
url?: URL
filename?: string
id?: string
size?: number
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
[maxSizeMB]="5"
[previewUrl]="resourceUrl"
[altText]="imageAltText"
[formControl]="formControl"
(fileChange)="handleFileChange($event)"
(urlChange)="handleUrlChange($event)"
(delete)="handleDelete()"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,27 @@ import {
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
EventEmitter,
Input,
OnDestroy,
OnInit,
Output,
} from '@angular/core'
import { CommonModule } from '@angular/common'
import { RecordsApiService } from '@geonetwork-ui/data-access/gn4'
import { UiInputsModule } from '@geonetwork-ui/ui/inputs'
import { FormControl } from '@angular/forms'
import { GraphicOverview } from '@geonetwork-ui/common/domain/model/record'
import { Subject, takeUntil } from 'rxjs'

const extractFileNameFormUrl = (url: URL, metadataUuid: string): string => {
const pattern = new RegExp(
`records/${metadataUuid}/attachments/([^/?#]+)(?:[/?#]|$)`,
'i'
)
const match = url.href.match(pattern)
return match ? match[1] : ''
}

@Component({
selector: 'gn-ui-overview-upload',
Expand All @@ -17,11 +32,15 @@ import { UiInputsModule } from '@geonetwork-ui/ui/inputs'
styleUrls: ['./overview-upload.component.css'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class OverviewUploadComponent implements OnInit {
export class OverviewUploadComponent implements OnInit, OnDestroy {
@Input() metadataUuid: string
@Input() formControl!: FormControl
@Output() overviewChange = new EventEmitter<GraphicOverview | null>()

imageAltText: string
resourceUrl: string
resourceUrl: URL

private destroy$ = new Subject<void>()

constructor(
private recordsApiService: RecordsApiService,
Expand All @@ -31,40 +50,98 @@ export class OverviewUploadComponent implements OnInit {
ngOnInit(): void {
this.recordsApiService
.getAllResources(this.metadataUuid)
.subscribe((resources) => {
this.imageAltText = resources[0]?.filename
this.resourceUrl = resources[0]?.url
this.cd.markForCheck()
.pipe(takeUntil(this.destroy$))
.subscribe({
next: (resources) => {
if (resources && resources.length > 0) {
this.resourceUrl = new URL(resources[0]?.url)
this.imageAltText = resources[0].filename
} else if (this.formControl.value[0]) {
this.resourceUrl = new URL(this.formControl.value[0].url.href)
this.imageAltText = this.formControl.value[0].description
} else {
this.resourceUrl = null
this.imageAltText = ''
}

this.cd.markForCheck()
},
error: this.errorHandle,
})
}

handleFileChange(file: File) {
this.recordsApiService
.putResource(this.metadataUuid, file, 'public')
.subscribe((resource) => {
this.imageAltText = resource.filename
this.resourceUrl = resource.url
this.cd.markForCheck()
.pipe(takeUntil(this.destroy$))
.subscribe({
next: (resource) => {
this.resourceUrl = new URL(resource.url)
this.imageAltText = resource.filename

this.overviewChange.emit({
url: new URL(resource.url),
description: resource.filename,
})

this.cd.markForCheck()
},
error: this.errorHandle,
})
}

handleUrlChange(url: string) {
this.recordsApiService
.putResourceFromURL(this.metadataUuid, url, 'public')
.subscribe((resource) => {
this.imageAltText = resource.filename
this.resourceUrl = resource.url
this.cd.markForCheck()
.pipe(takeUntil(this.destroy$))
.subscribe({
next: (resource) => {
this.resourceUrl = new URL(resource.url)
this.imageAltText = resource.filename

this.overviewChange.emit({
url: new URL(resource.url),
description: resource.filename,
})

this.cd.markForCheck()
},
error: this.errorHandle,
})
}

handleDelete() {
const fileName = extractFileNameFormUrl(this.resourceUrl, this.metadataUuid)

this.recordsApiService
.delResource(this.metadataUuid, this.imageAltText)
.subscribe(() => {
this.imageAltText = null
this.resourceUrl = null
this.cd.markForCheck()
.delResource(this.metadataUuid, fileName)
.pipe(takeUntil(this.destroy$))
.subscribe({
next: () => {
this.imageAltText = null
this.resourceUrl = null

this.overviewChange.emit(null)

this.cd.markForCheck()
},
error: this.errorHandle,
})
}

private errorHandle = (error: never) => {
console.error(error)

this.resourceUrl = null
this.imageAltText = ''

this.overviewChange.emit(null)

this.cd.markForCheck()
}

ngOnDestroy(): void {
this.destroy$.next()
this.destroy$.complete()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<gn-ui-overview-upload
[metadataUuid]="metadataUuid"
[formControl]="control"
(overviewChange)="handleOverViewChange($event)"
></gn-ui-overview-upload>
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { ComponentFixture, TestBed } from '@angular/core/testing'

import { FormFieldOverviewsComponent } from './form-field-overviews.component'
import { HttpClientTestingModule } from '@angular/common/http/testing'
import { TranslateModule } from '@ngx-translate/core'
import { FormControl } from '@angular/forms'

describe('FormFieldOverviewsComponent', () => {
let component: FormFieldOverviewsComponent
let fixture: ComponentFixture<FormFieldOverviewsComponent>

beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [
FormFieldOverviewsComponent,
HttpClientTestingModule,
TranslateModule.forRoot(),
],
}).compileComponents()

fixture = TestBed.createComponent(FormFieldOverviewsComponent)
component = fixture.componentInstance
component.metadataUuid = '8505d991-e38f-4704-a47a-e7d335dfbef5'
const control = new FormControl()
control.setValue([
{
description: 'doge.jpg',
url: new URL(
'http://localhost:8080/geonetwork/srv/api/0.1/records/8505d991-e38f-4704-a47a-e7d335dfbef5/attachments/doge.jpg'
),
},
])
component.control = control
fixture.detectChanges()
})

it('should create', () => {
expect(component).toBeTruthy()
})
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { CommonModule } from '@angular/common'
import { ChangeDetectionStrategy, Component, Input } from '@angular/core'
import { OverviewUploadComponent } from '../../../overview-upload/overview-upload.component'
import { FormControl } from '@angular/forms'
import { GraphicOverview } from '@geonetwork-ui/common/domain/model/record'

@Component({
selector: 'gn-ui-form-field-overviews',
templateUrl: './form-field-overviews.component.html',
styleUrls: ['./form-field-overviews.component.css'],
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true,
imports: [CommonModule, OverviewUploadComponent],
})
export class FormFieldOverviewsComponent {
@Input() metadataUuid: string
@Input() control!: FormControl

handleOverViewChange(overView: GraphicOverview | null) {
this.control.setValue(overView ? [overView] : [])
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,12 @@
<ng-container *ngIf="isSpatialExtentField">
<gn-ui-form-field-spatial-extent></gn-ui-form-field-spatial-extent>
</ng-container>
<ng-container *ngIf="isGraphicOverview">
<gn-ui-form-field-overviews
[control]="formControl"
[metadataUuid]="metadataUuid$ | async"
></gn-ui-form-field-overviews>
</ng-container>
<ng-container *ngIf="isKeywords">
<gn-ui-form-field-keywords
[control]="formControl"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,35 @@ import { FormFieldSpatialExtentComponent } from './form-field-spatial-extent/for
import { FormFieldUpdateFrequencyComponent } from './form-field-update-frequency/form-field-update-frequency.component'
import { FormFieldComponent } from './form-field.component'
import { FormFieldTemporalExtentsComponent } from './form-field-temporal-extents/form-field-temporal-extents.component'
import { FormFieldOverviewsComponent } from './form-field-overviews/form-field-overviews.component'
import { BehaviorSubject } from 'rxjs'
import { EditorFacade } from '../../../+state/editor.facade'
import { DATASET_RECORDS } from '@geonetwork-ui/common/fixtures'
import { NO_ERRORS_SCHEMA } from '@angular/core'
import { HttpClientTestingModule } from '@angular/common/http/testing'

class EditorFacadeMock {
record$ = new BehaviorSubject(DATASET_RECORDS[0])
}

describe('FormFieldComponent', () => {
let component: FormFieldComponent
let fixture: ComponentFixture<FormFieldComponent>

beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [FormFieldComponent, TranslateModule.forRoot()],
imports: [
FormFieldComponent,
TranslateModule.forRoot(),
HttpClientTestingModule,
],
schemas: [NO_ERRORS_SCHEMA],
providers: [
{
provide: EditorFacade,
useClass: EditorFacadeMock,
},
],
}).compileComponents()

fixture = TestBed.createComponent(FormFieldComponent)
Expand Down Expand Up @@ -149,4 +170,17 @@ describe('FormFieldComponent', () => {
expect(formField).toBeTruthy()
})
})
describe('overviews field', () => {
let formField
beforeEach(() => {
component.model = 'overviews'
fixture.detectChanges()
formField = fixture.debugElement.query(
By.directive(FormFieldOverviewsComponent)
).componentInstance
})
it('creates an array form field', () => {
expect(formField).toBeTruthy()
})
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ import { FormFieldSpatialExtentComponent } from './form-field-spatial-extent/for
import { FormFieldUpdateFrequencyComponent } from './form-field-update-frequency/form-field-update-frequency.component'
import { CatalogRecordKeys } from '@geonetwork-ui/common/domain/model/record'
import { FormFieldKeywordsComponent } from './form-field-keywords/form-field-keywords.component'
import { FormFieldConfig } from '../../../models'
import { FormFieldOverviewsComponent } from './form-field-overviews/form-field-overviews.component'
import { map, take } from 'rxjs/operators'
import { EditorFacade } from '../../../+state/editor.facade'

@Component({
selector: 'gn-ui-form-field',
Expand All @@ -55,6 +57,7 @@ import { FormFieldConfig } from '../../../models'
FormFieldArrayComponent,
FormFieldKeywordsComponent,
TranslateModule,
FormFieldOverviewsComponent,
],
})
export class FormFieldComponent {
Expand All @@ -70,9 +73,14 @@ export class FormFieldComponent {

@ViewChild('titleInput') titleInput: ElementRef

metadataUuid$ = this.facade.record$.pipe(
take(1),
map((record) => record.uniqueIdentifier)
)

formControl = new FormControl()

constructor() {
constructor(private facade: EditorFacade) {
this.valueChange = this.formControl.valueChanges
}

Expand Down Expand Up @@ -101,6 +109,9 @@ export class FormFieldComponent {
get isSpatialExtentField() {
return this.model === 'spatialExtents'
}
get isGraphicOverview() {
return this.model === 'overviews'
}
get isSimpleField() {
return this.model === 'uniqueIdentifier' || this.model === 'recordUpdated'
}
Expand Down
12 changes: 12 additions & 0 deletions libs/feature/editor/src/lib/fields.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,18 @@ export const DEFAULT_CONFIGURATION: EditorConfig = {
{
labelKey: marker('editor.record.form.page.description'),
sections: [TITLE_SECTION, ABOUT_SECTION, GEOGRAPHICAL_COVERAGE_SECTION],
{
model: 'overviews',
formFieldConfig: {
labelKey: marker('editor.record.form.overviews'),
type: 'list',
},
},
{
model: 'keywords',
formFieldConfig: {
labelKey: marker('editor.record.form.keywords'),
type: 'list',
},
{
labelKey: marker('editor.record.form.page.ressources'),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
<div class="w-full h-full flex flex-col gap-2">
<label
gnUiFilesDrop
class="block flex-1 border-2 border-dashed border-gray-300 rounded-lg p-6 flex flex-col items-center justify-center gap-4"
class="block flex-1 border-2 border-dashed border-gray-300 rounded-lg p-6 flex flex-col items-center justify-center gap-4 hover:cursor-pointer"
(dragFilesOver)="handleDragFilesOver($event)"
(dropFiles)="handleDropFiles($event)"
>
Expand Down
Loading

0 comments on commit 28c0b55

Please sign in to comment.