-
-
+
+
+
+
+
+
+
+
+
+
+
+ {{ index }}
+
+
+ {{ page.label }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ selectedPage === 0 ? 'Revenir plus tard' : 'Precedent' }}
+
+ Suivant
-
-
+
diff --git a/apps/metadata-editor/src/app/edit/edit-page.component.ts b/apps/metadata-editor/src/app/edit/edit-page.component.ts
index 7327286a2c..7f3481e64a 100644
--- a/apps/metadata-editor/src/app/edit/edit-page.component.ts
+++ b/apps/metadata-editor/src/app/edit/edit-page.component.ts
@@ -15,6 +15,7 @@ import {
} from '@geonetwork-ui/feature/notifications'
import { TranslateService } from '@ngx-translate/core'
import { filter, Subscription, take } from 'rxjs'
+import { FilterPipe } from '../pipes/filter.pipe'
@Component({
selector: 'md-editor-edit',
@@ -29,18 +30,29 @@ import { filter, Subscription, take } from 'rxjs'
PublishButtonComponent,
TopToolbarComponent,
NotificationsContainerComponent,
+ FilterPipe,
],
})
export class EditPageComponent implements OnInit, OnDestroy {
subscription = new Subscription()
+ fields$ = this.facade.recordFields$
+ totalPages = 0
+ selectedPage = 0
+
constructor(
private route: ActivatedRoute,
private facade: EditorFacade,
private notificationsService: NotificationsService,
private translateService: TranslateService,
private router: Router
- ) {}
+ ) {
+ this.subscription.add(
+ this.fields$.subscribe((fields) => {
+ this.totalPages = fields.pages.length
+ })
+ )
+ }
ngOnInit(): void {
const [currentRecord, currentRecordSource, currentRecordAlreadySaved] =
@@ -109,4 +121,21 @@ export class EditPageComponent implements OnInit, OnDestroy {
ngOnDestroy() {
this.subscription.unsubscribe()
}
+
+ previousPageButtonHandler() {
+ if (this.selectedPage === 0) {
+ this.router.navigate(['catalog', 'search'])
+ } else {
+ this.selectedPage--
+ }
+ }
+
+ nextPageButtonHandler() {
+ if (this.selectedPage === this.totalPages - 1) return
+ this.selectedPage++
+ }
+
+ pageSectionClickHandler(index: number) {
+ this.selectedPage = index
+ }
}
diff --git a/libs/feature/editor/src/lib/+state/editor.selectors.ts b/libs/feature/editor/src/lib/+state/editor.selectors.ts
index e9a601da80..e240f5c5e3 100644
--- a/libs/feature/editor/src/lib/+state/editor.selectors.ts
+++ b/libs/feature/editor/src/lib/+state/editor.selectors.ts
@@ -41,9 +41,17 @@ export const selectRecordFieldsConfig = createSelector(
export const selectRecordFields = createSelector(
selectEditorState,
- (state: EditorState) =>
- state.fieldsConfig.map((fieldConfig) => ({
- config: fieldConfig,
- value: state.record?.[fieldConfig.model] ?? null,
- }))
+ (state: EditorState) => {
+ const fieldsConfig = state.fieldsConfig
+ fieldsConfig.pages.forEach((page) => {
+ page.sections.forEach((section) => {
+ section.fields.forEach((field) => {
+ if (state.record) {
+ field.value = state.record[field.model]
+ }
+ })
+ })
+ })
+ return fieldsConfig
+ }
)
diff --git a/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.html b/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.html
index 98f8503d27..8d30de79be 100644
--- a/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.html
+++ b/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.html
@@ -5,7 +5,7 @@
@@ -15,14 +15,14 @@
-
{{ formControl.value }}
-
+
help
@@ -42,7 +42,7 @@
class="h-[8rem]"
[control]="formControl"
[label]="config.labelKey | translate"
- [hint]="config.hintKey | translate"
+ [hint]="config.hintKey! | translate"
>
diff --git a/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.ts b/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.ts
index 5077db478e..61af9e011c 100644
--- a/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.ts
+++ b/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.ts
@@ -59,12 +59,14 @@ import { FormFieldKeywordsComponent } from './form-field-keywords/form-field-key
})
export class FormFieldComponent {
@Input() model: CatalogRecordKeys
+ @Input() selectedPage = 0
@Input() config: FormFieldConfig
@Input() set value(v: unknown) {
this.formControl.setValue(v, {
emitEvent: false,
})
}
+
@Output() valueChange: Observable
@ViewChild('titleInput') titleInput: ElementRef
diff --git a/libs/feature/editor/src/lib/components/record-form/record-form.component.html b/libs/feature/editor/src/lib/components/record-form/record-form.component.html
index 7b07459330..5b6715abe0 100644
--- a/libs/feature/editor/src/lib/components/record-form/record-form.component.html
+++ b/libs/feature/editor/src/lib/components/record-form/record-form.component.html
@@ -1,11 +1,37 @@
-
-
-
-
-
+
+
+
+
+
+
+
+ {{ section.label }}
+
+
+ {{ section.description }}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/libs/feature/editor/src/lib/components/record-form/record-form.component.ts b/libs/feature/editor/src/lib/components/record-form/record-form.component.ts
index 310fa77fea..08d6c32db0 100644
--- a/libs/feature/editor/src/lib/components/record-form/record-form.component.ts
+++ b/libs/feature/editor/src/lib/components/record-form/record-form.component.ts
@@ -1,7 +1,7 @@
import { CommonModule } from '@angular/common'
-import { ChangeDetectionStrategy, Component } from '@angular/core'
+import { ChangeDetectionStrategy, Component, Input } from '@angular/core'
import { EditorFacade } from '../../+state/editor.facade'
-import { EditorFieldState, EditorFieldValue } from '../../models/fields.model'
+import { EditorFieldPage, EditorFieldValue } from '../../models/fields.model'
import { FormFieldComponent } from './form-field'
@Component({
@@ -13,18 +13,15 @@ import { FormFieldComponent } from './form-field'
imports: [CommonModule, FormFieldComponent],
})
export class RecordFormComponent {
- fields$ = this.facade.recordFields$
+ @Input() selectedPage = 0
+ @Input() page: EditorFieldPage
constructor(public facade: EditorFacade) {}
- handleFieldValueChange(field: EditorFieldState, newValue: EditorFieldValue) {
- if (!field.config.model) {
+ handleFieldValueChange(model: string, newValue: EditorFieldValue) {
+ if (!model) {
return
}
- this.facade.updateRecordField(field.config.model, newValue)
- }
-
- fieldTracker(index: number, field: EditorFieldState) {
- return field.config.model
+ this.facade.updateRecordField(model, newValue)
}
}
diff --git a/libs/feature/editor/src/lib/expressions.spec.ts b/libs/feature/editor/src/lib/expressions.spec.ts
index 6de626a823..e36b9e7fc2 100644
--- a/libs/feature/editor/src/lib/expressions.spec.ts
+++ b/libs/feature/editor/src/lib/expressions.spec.ts
@@ -1,13 +1,4 @@
import { evaluate, ExpressionEvaluator } from './expressions'
-import { EditorFieldConfig } from './models/fields.model'
-
-const SAMPLE_CONFIG: EditorFieldConfig = {
- formFieldConfig: {
- labelKey: 'Metadata title',
- type: 'text',
- },
- model: 'myModel',
-}
const originalDate = window.Date
window.Date = function () {
@@ -22,7 +13,7 @@ describe('expressions', () => {
evaluator = evaluate('${dateNow()}')
})
it('returns the current time at evaluation', () => {
- expect(evaluator({ config: SAMPLE_CONFIG, value: 'bla' })).toEqual(
+ expect(evaluator({ model: 'keywords', value: 'bla' })).toEqual(
new Date()
)
})
diff --git a/libs/feature/editor/src/lib/fields.config.ts b/libs/feature/editor/src/lib/fields.config.ts
index cda10b5196..c641e4f724 100644
--- a/libs/feature/editor/src/lib/fields.config.ts
+++ b/libs/feature/editor/src/lib/fields.config.ts
@@ -1,71 +1,198 @@
import { marker } from '@biesbjerg/ngx-translate-extract-marker'
-import { EditorFieldsConfig } from './models/fields.model'
-
-export const DEFAULT_FIELDS: EditorFieldsConfig = [
- {
- model: 'title',
- formFieldConfig: {
- labelKey: 'Metadata title',
- type: 'text',
- },
+import {
+ EditorField,
+ EditorFieldsConfig,
+ EditorFieldSection,
+} from './models/fields.model'
+
+/**
+ * This file contains the configuration of the fields that will be displayed in the editor.
+ * To add a new field, you need to create a new EditorField object in the fields part of this file.
+ * Then add it to the corresponding section in the sections part of this file.
+ * Finally, add the section to the corresponding page in the pages part of this file.
+ */
+
+/************************************************************
+ *************** FIELDS *****************
+ ************************************************************
+ */
+
+export const RECORD_LICENSE_FIELD: EditorField = {
+ model: 'licenses',
+ formFieldConfig: {
+ labelKey: marker('editor.record.form.license'),
+ type: 'list',
},
- {
- model: 'abstract',
- formFieldConfig: {
- labelKey: 'Abstract',
- type: 'rich',
- },
+}
+
+export const RECORD_KEYWORDS_FIELD: EditorField = {
+ model: 'keywords',
+ formFieldConfig: {
+ labelKey: marker('editor.record.form.keywords'),
+ type: 'list',
},
- {
- model: 'uniqueIdentifier',
- formFieldConfig: {
- labelKey: 'Unique identifier',
- type: 'text',
- locked: true,
- },
+}
+
+export const RECORD_UNIQUE_IDENTIFIER_FIELD: EditorField = {
+ model: 'uniqueIdentifier',
+ formFieldConfig: {
+ labelKey: 'Unique identifier',
+ type: 'text',
+ locked: true,
},
- {
- model: 'recordUpdated',
- formFieldConfig: {
- labelKey: 'Record Updated',
- type: 'text',
- locked: true,
- },
- onSaveProcess: '${dateNow()}',
+}
+
+export const RECORD_RESOURCE_UPDATED_FIELD: EditorField = {
+ model: 'resourceUpdated',
+ formFieldConfig: {
+ labelKey: marker('editor.record.form.resourceUpdated'),
+ type: 'date',
},
- {
- model: 'licenses',
- formFieldConfig: {
- labelKey: marker('editor.record.form.license'),
- type: 'list',
- },
+}
+
+export const RECORD_UPDATED_FIELD: EditorField = {
+ model: 'recordUpdated',
+ formFieldConfig: {
+ labelKey: 'Record Updated',
+ type: 'text',
+ locked: true,
},
- {
- model: 'resourceUpdated',
- formFieldConfig: {
- labelKey: marker('editor.record.form.resourceUpdated'),
- type: 'date',
- },
+ onSaveProcess: '${dateNow()}',
+}
+
+export const RECORD_UPDATE_FREQUENCY_FIELD: EditorField = {
+ model: 'updateFrequency',
+ formFieldConfig: {
+ labelKey: marker('editor.record.form.updateFrequency'),
+ type: 'text',
},
- {
- model: 'updateFrequency',
- formFieldConfig: {
- labelKey: marker('editor.record.form.updateFrequency'),
- type: 'text',
- },
+}
+
+export const RECORD_TEMPORAL_EXTENTS_FIELD: EditorField = {
+ model: 'temporalExtents',
+ formFieldConfig: {
+ labelKey: marker('editor.record.form.temporalExtents'),
+ type: 'list',
},
- {
- model: 'temporalExtents',
- formFieldConfig: {
- labelKey: marker('editor.record.form.temporalExtents'),
- type: 'list',
- },
+}
+
+export const RECORD_TITLE_FIELD: EditorField = {
+ model: 'title',
+ formFieldConfig: {
+ labelKey: 'Metadata title',
+ type: 'text',
},
- {
- model: 'keywords',
- formFieldConfig: {
- labelKey: marker('editor.record.form.keywords'),
- type: 'list',
- },
+}
+
+export const RECORD_ABSTRACT_FIELD: EditorField = {
+ model: 'abstract',
+ formFieldConfig: {
+ labelKey: 'Abstract',
+ type: 'rich',
},
-]
+}
+
+/************************************************************
+ *************** SECTIONS *****************
+ ************************************************************
+ */
+
+export const TITLE_SECTION: EditorFieldSection = {
+ label: '',
+ description: '',
+ hidden: false,
+ fields: [RECORD_TITLE_FIELD, RECORD_ABSTRACT_FIELD],
+}
+
+export const ABOUT_SECTION: EditorFieldSection = {
+ label: 'A propos de la ressource',
+ description: 'Ces informations concernent la donnée.',
+ hidden: false,
+ fields: [
+ RECORD_UNIQUE_IDENTIFIER_FIELD,
+ RECORD_RESOURCE_UPDATED_FIELD,
+ RECORD_UPDATED_FIELD,
+ RECORD_UPDATE_FREQUENCY_FIELD,
+ RECORD_TEMPORAL_EXTENTS_FIELD,
+ ],
+}
+
+export const GEOGRAPHICAL_COVER_SECTION: EditorFieldSection = {
+ label: 'Couverture geographique',
+ description: '',
+ hidden: false,
+ fields: [],
+}
+
+export const ASSOCIATED_RESOURCES_SECTION: EditorFieldSection = {
+ label: 'Ressources associees',
+ description:
+ 'Déposez les jeux de données associées à cette fiche de métadonnée.',
+ hidden: false,
+ fields: [],
+}
+
+export const ANNEXES_SECTION: EditorFieldSection = {
+ label: 'Annexes',
+ description: '',
+ hidden: false,
+ fields: [],
+}
+
+export const CLASSIFICATION_SECTION: EditorFieldSection = {
+ label: 'Classification',
+ description:
+ 'La classification a un impact sur la recherche du jeux de données.',
+ hidden: false,
+ fields: [RECORD_KEYWORDS_FIELD],
+}
+
+export const USE_AND_ACCESS_CONDITIONS_SECTION: EditorFieldSection = {
+ label: "Conditions d'acces et usage",
+ description: '',
+ hidden: false,
+ fields: [RECORD_LICENSE_FIELD],
+}
+
+export const DATA_MANAGERS_SECTION: EditorFieldSection = {
+ label: 'Responsables de la donnee',
+ description: 'Cette information concerne la donnée.',
+ hidden: false,
+ fields: [],
+}
+
+export const DATA_POINT_OF_CONTACT_SECTION: EditorFieldSection = {
+ label: 'Point de contact de la metadonee',
+ description: 'Cette information concerne la fiche de métadonnée.',
+ hidden: false,
+ fields: [],
+}
+
+/************************************************************
+ *************** PAGES *****************
+ ************************************************************
+ */
+export const DEFAULT_FIELDS: EditorFieldsConfig = {
+ pages: [
+ {
+ index: 0,
+ label: 'Description de la ressource',
+ sections: [TITLE_SECTION, ABOUT_SECTION, GEOGRAPHICAL_COVER_SECTION],
+ },
+ {
+ index: 1,
+ label: 'Ressources',
+ sections: [ASSOCIATED_RESOURCES_SECTION, ANNEXES_SECTION],
+ },
+ {
+ index: 2,
+ label: 'Acces et contact',
+ sections: [
+ CLASSIFICATION_SECTION,
+ USE_AND_ACCESS_CONDITIONS_SECTION,
+ DATA_MANAGERS_SECTION,
+ DATA_POINT_OF_CONTACT_SECTION,
+ ],
+ },
+ ],
+}
diff --git a/libs/feature/editor/src/lib/models/fields.model.ts b/libs/feature/editor/src/lib/models/fields.model.ts
index 0dae06b007..dec4c9c382 100644
--- a/libs/feature/editor/src/lib/models/fields.model.ts
+++ b/libs/feature/editor/src/lib/models/fields.model.ts
@@ -1,15 +1,16 @@
import { FormFieldConfig } from '../components/record-form/form-field'
+import { CatalogRecordKeys } from '@geonetwork-ui/common/domain/model/record'
// Expressions should be enclosed in `${}` to be recognized as such
// eg. ${dateNow()}
export type EditorFieldExpression = `$\{${string}}`
-export interface EditorFieldConfig {
+export interface EditorField {
// configuration of the form field used as presentation; optional, nothing shown if not defined
- formFieldConfig?: FormFieldConfig
+ formFieldConfig: FormFieldConfig
// name of the target field in the record; will not change the record directly if not defined
- model?: string
+ model?: CatalogRecordKeys
// a hidden field won't show but can still be used to modify the record
// FIXME: currently this is redundant with an absence of formFieldConfig but necessary for clarity
@@ -17,13 +18,30 @@ export interface EditorFieldConfig {
// the result of this expression will replace the field value on save
onSaveProcess?: EditorFieldExpression
+
+ value?: EditorFieldValue
+}
+
+export interface EditorFieldSection {
+ label: string
+ description: string
+ hidden: boolean
+ fields: EditorField[]
}
-export type EditorFieldsConfig = EditorFieldConfig[]
+export interface EditorFieldPage {
+ index: number
+ label: string
+ sections: EditorFieldSection[]
+}
+
+export interface EditorFieldsConfig {
+ pages: EditorFieldPage[]
+}
export type EditorFieldValue = string | number | boolean | unknown
export interface EditorFieldState {
- config: EditorFieldConfig
- value: string | number | boolean | unknown
+ model: string
+ value: EditorFieldValue
}
diff --git a/libs/feature/editor/src/lib/services/editor.service.ts b/libs/feature/editor/src/lib/services/editor.service.ts
index 9b7c005438..6859864d44 100644
--- a/libs/feature/editor/src/lib/services/editor.service.ts
+++ b/libs/feature/editor/src/lib/services/editor.service.ts
@@ -20,12 +20,16 @@ export class EditorService {
): Observable<[CatalogRecord, string]> {
const savedRecord = { ...record }
+ const fields = fieldsConfig.pages
+ .map((page) => page.sections.map((section) => section.fields))
+ .flat(2)
+
// run onSave processes
- for (const field of fieldsConfig) {
+ for (const field of fields) {
if (field.onSaveProcess && field.model) {
const evaluator = evaluate(field.onSaveProcess)
savedRecord[field.model] = evaluator({
- config: field,
+ model: field.model,
value: record[field.model],
})
}