geonetwork-ui 2.3.0 → 2.4.0-dev.cd525aa1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm2022/libs/api/repository/src/lib/gn4/gn4-repository.mjs +57 -9
- package/esm2022/libs/common/domain/src/lib/repository/records-repository.interface.mjs +1 -1
- package/esm2022/libs/data-access/gn4/src/openapi/api/records.api.service.mjs +2 -2
- package/esm2022/libs/feature/editor/src/lib/+state/editor.actions.mjs +1 -1
- package/esm2022/libs/feature/editor/src/lib/+state/editor.effects.mjs +11 -3
- package/esm2022/libs/feature/editor/src/lib/+state/editor.facade.mjs +5 -3
- package/esm2022/libs/feature/editor/src/lib/+state/editor.reducer.mjs +6 -2
- package/esm2022/libs/feature/editor/src/lib/+state/editor.selectors.mjs +3 -1
- package/esm2022/libs/feature/editor/src/lib/services/editor.service.mjs +20 -40
- package/esm2022/libs/feature/record/src/lib/state/mdview.effects.mjs +2 -2
- package/esm2022/libs/feature/search/src/lib/results-table/results-table.component.mjs +18 -10
- package/esm2022/libs/ui/elements/src/lib/metadata-info/metadata-info.component.mjs +7 -7
- package/esm2022/libs/ui/elements/src/lib/ui-elements.module.mjs +7 -4
- package/esm2022/libs/ui/widgets/src/lib/badge/badge.component.mjs +4 -3
- package/esm2022/libs/ui/widgets/src/lib/ui-widgets.module.mjs +1 -6
- package/esm2022/translations/de.json +5 -1
- package/esm2022/translations/en.json +5 -1
- package/esm2022/translations/es.json +5 -1
- package/esm2022/translations/fr.json +5 -1
- package/esm2022/translations/it.json +5 -1
- package/esm2022/translations/nl.json +5 -1
- package/esm2022/translations/pt.json +5 -1
- package/fesm2022/geonetwork-ui.mjs +156 -77
- package/fesm2022/geonetwork-ui.mjs.map +1 -1
- package/libs/api/repository/src/lib/gn4/gn4-repository.d.ts +15 -3
- package/libs/api/repository/src/lib/gn4/gn4-repository.d.ts.map +1 -1
- package/libs/common/domain/src/lib/repository/records-repository.interface.d.ts +24 -1
- package/libs/common/domain/src/lib/repository/records-repository.interface.d.ts.map +1 -1
- package/libs/data-access/gn4/src/openapi/api/records.api.service.d.ts +6 -6
- package/libs/data-access/gn4/src/openapi/api/records.api.service.d.ts.map +1 -1
- package/libs/feature/editor/src/lib/+state/editor.actions.d.ts +4 -0
- package/libs/feature/editor/src/lib/+state/editor.actions.d.ts.map +1 -1
- package/libs/feature/editor/src/lib/+state/editor.effects.d.ts +5 -0
- package/libs/feature/editor/src/lib/+state/editor.effects.d.ts.map +1 -1
- package/libs/feature/editor/src/lib/+state/editor.facade.d.ts +9 -8
- package/libs/feature/editor/src/lib/+state/editor.facade.d.ts.map +1 -1
- package/libs/feature/editor/src/lib/+state/editor.reducer.d.ts +10 -0
- package/libs/feature/editor/src/lib/+state/editor.reducer.d.ts.map +1 -1
- package/libs/feature/editor/src/lib/+state/editor.selectors.d.ts +2 -0
- package/libs/feature/editor/src/lib/+state/editor.selectors.d.ts.map +1 -1
- package/libs/feature/editor/src/lib/services/editor.service.d.ts +6 -9
- package/libs/feature/editor/src/lib/services/editor.service.d.ts.map +1 -1
- package/libs/feature/record/src/lib/state/mdview.effects.d.ts.map +1 -1
- package/libs/feature/search/src/lib/results-table/results-table.component.d.ts +4 -1
- package/libs/feature/search/src/lib/results-table/results-table.component.d.ts.map +1 -1
- package/libs/ui/elements/src/lib/ui-elements.module.d.ts +2 -1
- package/libs/ui/elements/src/lib/ui-elements.module.d.ts.map +1 -1
- package/libs/ui/widgets/src/lib/badge/badge.component.d.ts +2 -2
- package/libs/ui/widgets/src/lib/badge/badge.component.d.ts.map +1 -1
- package/libs/ui/widgets/src/lib/ui-widgets.module.d.ts +10 -11
- package/libs/ui/widgets/src/lib/ui-widgets.module.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/libs/api/repository/src/lib/gn4/gn4-repository.ts +145 -7
- package/src/libs/common/domain/src/lib/repository/records-repository.interface.ts +36 -3
- package/src/libs/common/fixtures/src/lib/records.fixtures.ts +203 -0
- package/src/libs/data-access/gn4/src/openapi/api/records.api.service.ts +9 -9
- package/src/libs/data-access/gn4/src/spec.yaml +4 -5
- package/src/libs/feature/editor/src/lib/+state/editor.actions.ts +5 -1
- package/src/libs/feature/editor/src/lib/+state/editor.effects.ts +31 -3
- package/src/libs/feature/editor/src/lib/+state/editor.facade.ts +13 -3
- package/src/libs/feature/editor/src/lib/+state/editor.reducer.ts +22 -5
- package/src/libs/feature/editor/src/lib/+state/editor.selectors.ts +10 -0
- package/src/libs/feature/editor/src/lib/services/editor.service.ts +17 -52
- package/src/libs/feature/record/src/lib/state/mdview.effects.ts +1 -3
- package/src/libs/feature/search/src/lib/results-table/results-table.component.html +12 -1
- package/src/libs/feature/search/src/lib/results-table/results-table.component.ts +9 -1
- package/src/libs/ui/elements/src/lib/ui-elements.module.ts +2 -1
- package/src/libs/ui/widgets/src/lib/badge/badge.component.html +1 -1
- package/src/libs/ui/widgets/src/lib/badge/badge.component.ts +4 -1
- package/src/libs/ui/widgets/src/lib/ui-widgets.module.ts +0 -3
- package/tailwind.base.css +21 -1
- package/translations/de.json +5 -1
- package/translations/en.json +5 -1
- package/translations/es.json +5 -1
- package/translations/fr.json +5 -1
- package/translations/it.json +5 -1
- package/translations/nl.json +5 -1
- package/translations/pt.json +5 -1
- package/translations/sk.json +5 -1
|
@@ -252,3 +252,206 @@ Ce lot de données produit en 2019, a été numérisé à partir du PCI Vecteur
|
|
|
252
252
|
languages: ['fr', 'de'],
|
|
253
253
|
},
|
|
254
254
|
])
|
|
255
|
+
|
|
256
|
+
export const DATASET_RECORD_SIMPLE: DatasetRecord = {
|
|
257
|
+
uniqueIdentifier: 'my-dataset-001',
|
|
258
|
+
kind: 'dataset',
|
|
259
|
+
languages: [],
|
|
260
|
+
recordUpdated: new Date('2022-02-01T14:12:00.000Z'),
|
|
261
|
+
resourceCreated: new Date('2022-09-01T12:18:19.000Z'),
|
|
262
|
+
resourceUpdated: new Date('2022-12-04T14:12:00.000Z'),
|
|
263
|
+
status: 'ongoing',
|
|
264
|
+
title: 'A very interesting dataset (un jeu de données très intéressant)',
|
|
265
|
+
abstract: `This dataset has been established for testing purposes.`,
|
|
266
|
+
ownerOrganization: { name: 'MyOrganization' },
|
|
267
|
+
contacts: [
|
|
268
|
+
{
|
|
269
|
+
email: 'bob@org.net',
|
|
270
|
+
position: 'developer',
|
|
271
|
+
organization: { name: 'MyOrganization' },
|
|
272
|
+
role: 'point_of_contact',
|
|
273
|
+
firstName: 'Bob',
|
|
274
|
+
lastName: 'TheGreat',
|
|
275
|
+
},
|
|
276
|
+
],
|
|
277
|
+
contactsForResource: [],
|
|
278
|
+
keywords: [],
|
|
279
|
+
topics: ['testData'],
|
|
280
|
+
licenses: [],
|
|
281
|
+
legalConstraints: [],
|
|
282
|
+
securityConstraints: [],
|
|
283
|
+
otherConstraints: [],
|
|
284
|
+
lineage: 'This record was edited manually to test the conversion processes',
|
|
285
|
+
spatialRepresentation: 'grid',
|
|
286
|
+
overviews: [],
|
|
287
|
+
spatialExtents: [],
|
|
288
|
+
temporalExtents: [],
|
|
289
|
+
distributions: [
|
|
290
|
+
{
|
|
291
|
+
type: 'download',
|
|
292
|
+
url: new URL('http://my-org.net/download/1.zip'),
|
|
293
|
+
name: 'Direct download',
|
|
294
|
+
description: 'Dataset downloaded as a shapefile',
|
|
295
|
+
mimeType: 'x-gis/x-shapefile',
|
|
296
|
+
},
|
|
297
|
+
],
|
|
298
|
+
updateFrequency: { per: 'month', updatedTimes: 3 },
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
export const DATASET_RECORD_SIMPLE_AS_XML = `<?xml version="1.0" encoding="UTF-8"?>
|
|
302
|
+
<mdb:MD_Metadata xmlns:mdb="http://standards.iso.org/iso/19115/-3/mdb/2.0" xmlns:mcc="http://standards.iso.org/iso/19115/-3/mcc/1.0" xmlns:gco="http://standards.iso.org/iso/19115/-3/gco/1.0" xmlns:cit="http://standards.iso.org/iso/19115/-3/cit/2.0" xmlns:mri="http://standards.iso.org/iso/19115/-3/mri/1.0" xmlns:mco="http://standards.iso.org/iso/19115/-3/mco/1.0" xmlns:gcx="http://standards.iso.org/iso/19115/-3/gcx/1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:mmi="http://standards.iso.org/iso/19115/-3/mmi/1.0" xmlns:mrd="http://standards.iso.org/iso/19115/-3/mrd/1.0" xmlns:mrl="http://standards.iso.org/iso/19115/-3/mrl/2.0">
|
|
303
|
+
<mdb:metadataIdentifier>
|
|
304
|
+
<mcc:MD_Identifier>
|
|
305
|
+
<mcc:code>
|
|
306
|
+
<gco:CharacterString>my-dataset-001</gco:CharacterString>
|
|
307
|
+
</mcc:code>
|
|
308
|
+
</mcc:MD_Identifier>
|
|
309
|
+
</mdb:metadataIdentifier>
|
|
310
|
+
<mdb:metadataScope>
|
|
311
|
+
<mdb:MD_MetadataScope>
|
|
312
|
+
<mdb:resourceScope>
|
|
313
|
+
<mcc:MD_ScopeCode codeList="https://standards.iso.org/iso/19115/resources/Codelists/cat/codelists.xml#MD_ScopeCode" codeListValue="dataset">dataset</mcc:MD_ScopeCode>
|
|
314
|
+
</mdb:resourceScope>
|
|
315
|
+
</mdb:MD_MetadataScope>
|
|
316
|
+
</mdb:metadataScope>
|
|
317
|
+
<mdb:contact>
|
|
318
|
+
<cit:CI_Responsibility>
|
|
319
|
+
<cit:role>
|
|
320
|
+
<cit:CI_RoleCode codeList="https://standards.iso.org/iso/19115/resources/Codelists/cat/codelists.xml#CI_RoleCode" codeListValue="pointOfContact">pointOfContact</cit:CI_RoleCode>
|
|
321
|
+
</cit:role>
|
|
322
|
+
<cit:party>
|
|
323
|
+
<cit:CI_Organisation>
|
|
324
|
+
<cit:name>
|
|
325
|
+
<gco:CharacterString>MyOrganization</gco:CharacterString>
|
|
326
|
+
</cit:name>
|
|
327
|
+
<cit:contactInfo>
|
|
328
|
+
<cit:CI_Contact>
|
|
329
|
+
<cit:address>
|
|
330
|
+
<cit:CI_Address>
|
|
331
|
+
<cit:electronicMailAddress>
|
|
332
|
+
<gco:CharacterString>bob@org.net</gco:CharacterString>
|
|
333
|
+
</cit:electronicMailAddress>
|
|
334
|
+
</cit:CI_Address>
|
|
335
|
+
</cit:address>
|
|
336
|
+
</cit:CI_Contact>
|
|
337
|
+
</cit:contactInfo>
|
|
338
|
+
<cit:individual>
|
|
339
|
+
<cit:CI_Individual>
|
|
340
|
+
<cit:name>
|
|
341
|
+
<gco:CharacterString>Bob TheGreat</gco:CharacterString>
|
|
342
|
+
</cit:name>
|
|
343
|
+
<cit:positionName>
|
|
344
|
+
<gco:CharacterString>developer</gco:CharacterString>
|
|
345
|
+
</cit:positionName>
|
|
346
|
+
</cit:CI_Individual>
|
|
347
|
+
</cit:individual>
|
|
348
|
+
</cit:CI_Organisation>
|
|
349
|
+
</cit:party>
|
|
350
|
+
</cit:CI_Responsibility>
|
|
351
|
+
</mdb:contact>
|
|
352
|
+
<mdb:dateInfo>
|
|
353
|
+
<cit:CI_Date>
|
|
354
|
+
<cit:date>
|
|
355
|
+
<gco:DateTime>2022-02-01T15:12:00</gco:DateTime>
|
|
356
|
+
</cit:date>
|
|
357
|
+
<cit:dateType>
|
|
358
|
+
<cit:CI_DateTypeCode codeList="https://standards.iso.org/iso/19115/resources/Codelists/cat/codelists.xml#CI_DateTypeCode" codeListValue="revision">revision</cit:CI_DateTypeCode>
|
|
359
|
+
</cit:dateType>
|
|
360
|
+
</cit:CI_Date>
|
|
361
|
+
</mdb:dateInfo>
|
|
362
|
+
<mdb:identificationInfo>
|
|
363
|
+
<mri:MD_DataIdentification>
|
|
364
|
+
<mri:citation>
|
|
365
|
+
<cit:CI_Citation>
|
|
366
|
+
<cit:title>
|
|
367
|
+
<gco:CharacterString>A very interesting dataset (un jeu de données très intéressant)</gco:CharacterString>
|
|
368
|
+
</cit:title>
|
|
369
|
+
<cit:date>
|
|
370
|
+
<cit:CI_Date>
|
|
371
|
+
<cit:date>
|
|
372
|
+
<gco:DateTime>2022-09-01T14:18:19</gco:DateTime>
|
|
373
|
+
</cit:date>
|
|
374
|
+
<cit:dateType>
|
|
375
|
+
<cit:CI_DateTypeCode codeList="https://standards.iso.org/iso/19115/resources/Codelists/cat/codelists.xml#CI_DateTypeCode" codeListValue="creation">creation</cit:CI_DateTypeCode>
|
|
376
|
+
</cit:dateType>
|
|
377
|
+
</cit:CI_Date>
|
|
378
|
+
</cit:date>
|
|
379
|
+
<cit:date>
|
|
380
|
+
<cit:CI_Date>
|
|
381
|
+
<cit:date>
|
|
382
|
+
<gco:DateTime>2022-12-04T15:12:00</gco:DateTime>
|
|
383
|
+
</cit:date>
|
|
384
|
+
<cit:dateType>
|
|
385
|
+
<cit:CI_DateTypeCode codeList="https://standards.iso.org/iso/19115/resources/Codelists/cat/codelists.xml#CI_DateTypeCode" codeListValue="revision">revision</cit:CI_DateTypeCode>
|
|
386
|
+
</cit:dateType>
|
|
387
|
+
</cit:CI_Date>
|
|
388
|
+
</cit:date>
|
|
389
|
+
</cit:CI_Citation>
|
|
390
|
+
</mri:citation>
|
|
391
|
+
<mri:abstract>
|
|
392
|
+
<gco:CharacterString>This dataset has been established for testing purposes.</gco:CharacterString>
|
|
393
|
+
</mri:abstract>
|
|
394
|
+
<mri:topicCategory>
|
|
395
|
+
<mri:MD_TopicCategoryCode>testData</mri:MD_TopicCategoryCode>
|
|
396
|
+
</mri:topicCategory>
|
|
397
|
+
<mri:status>
|
|
398
|
+
<mcc:MD_ProgressCode codeList="https://standards.iso.org/iso/19115/resources/Codelists/cat/codelists.xml#MD_ProgressCode" codeListValue="onGoing">onGoing</mcc:MD_ProgressCode>
|
|
399
|
+
</mri:status>
|
|
400
|
+
<mri:resourceMaintenance>
|
|
401
|
+
<mmi:MD_MaintenanceInformation>
|
|
402
|
+
<mmi:userDefinedMaintenanceFrequency>
|
|
403
|
+
<gco:TM_PeriodDuration>P0Y0M10D</gco:TM_PeriodDuration>
|
|
404
|
+
</mmi:userDefinedMaintenanceFrequency>
|
|
405
|
+
</mmi:MD_MaintenanceInformation>
|
|
406
|
+
</mri:resourceMaintenance>
|
|
407
|
+
<mri:spatialRepresentationType>
|
|
408
|
+
<mcc:MD_SpatialRepresentationTypeCode codeList="https://standards.iso.org/iso/19115/resources/Codelists/cat/codelists.xml#MD_SpatialRepresentationTypeCode" codeListValue="grid">grid</mcc:MD_SpatialRepresentationTypeCode>
|
|
409
|
+
</mri:spatialRepresentationType>
|
|
410
|
+
</mri:MD_DataIdentification>
|
|
411
|
+
</mdb:identificationInfo>
|
|
412
|
+
<mdb:distributionInfo>
|
|
413
|
+
<mrd:MD_Distribution>
|
|
414
|
+
<mrd:distributionFormat>
|
|
415
|
+
<mrd:MD_Format>
|
|
416
|
+
<mrd:formatSpecificationCitation>
|
|
417
|
+
<cit:CI_Citation>
|
|
418
|
+
<cit:title>
|
|
419
|
+
<gco:CharacterString>x-gis/x-shapefile</gco:CharacterString>
|
|
420
|
+
</cit:title>
|
|
421
|
+
</cit:CI_Citation>
|
|
422
|
+
</mrd:formatSpecificationCitation>
|
|
423
|
+
</mrd:MD_Format>
|
|
424
|
+
</mrd:distributionFormat>
|
|
425
|
+
<mrd:transferOptions>
|
|
426
|
+
<mrd:MD_DigitalTransferOptions>
|
|
427
|
+
<mrd:onLine>
|
|
428
|
+
<cit:CI_OnlineResource>
|
|
429
|
+
<cit:linkage>
|
|
430
|
+
<gco:CharacterString>http://my-org.net/download/1.zip</gco:CharacterString>
|
|
431
|
+
</cit:linkage>
|
|
432
|
+
<cit:description>
|
|
433
|
+
<gco:CharacterString>Dataset downloaded as a shapefile</gco:CharacterString>
|
|
434
|
+
</cit:description>
|
|
435
|
+
<cit:name>
|
|
436
|
+
<gco:CharacterString>Direct download</gco:CharacterString>
|
|
437
|
+
</cit:name>
|
|
438
|
+
<cit:protocol>
|
|
439
|
+
<gco:CharacterString>WWW:DOWNLOAD</gco:CharacterString>
|
|
440
|
+
</cit:protocol>
|
|
441
|
+
<cit:function>
|
|
442
|
+
<cit:CI_OnLineFunctionCode codeList="http://standards.iso.org/iso/19139/resources/gmxCodelists.xml#CI_OnLineFunctionCode" codeListValue="download"/>
|
|
443
|
+
</cit:function>
|
|
444
|
+
</cit:CI_OnlineResource>
|
|
445
|
+
</mrd:onLine>
|
|
446
|
+
</mrd:MD_DigitalTransferOptions>
|
|
447
|
+
</mrd:transferOptions>
|
|
448
|
+
</mrd:MD_Distribution>
|
|
449
|
+
</mdb:distributionInfo>
|
|
450
|
+
<mdb:resourceLineage>
|
|
451
|
+
<mrl:LI_Lineage>
|
|
452
|
+
<mrl:statement>
|
|
453
|
+
<gco:CharacterString>This record was edited manually to test the conversion processes</gco:CharacterString>
|
|
454
|
+
</mrl:statement>
|
|
455
|
+
</mrl:LI_Lineage>
|
|
456
|
+
</mdb:resourceLineage>
|
|
457
|
+
</mdb:MD_Metadata>`
|
|
@@ -4586,8 +4586,8 @@ export class RecordsApiService {
|
|
|
4586
4586
|
accept?: string,
|
|
4587
4587
|
observe?: 'body',
|
|
4588
4588
|
reportProgress?: boolean,
|
|
4589
|
-
options?: { httpHeaderAccept?: 'application/
|
|
4590
|
-
): Observable<
|
|
4589
|
+
options?: { httpHeaderAccept?: 'application/xml' | 'application/json' }
|
|
4590
|
+
): Observable<string>
|
|
4591
4591
|
public getRecordAs(
|
|
4592
4592
|
metadataUuid: string,
|
|
4593
4593
|
addSchemaLocation?: boolean,
|
|
@@ -4598,8 +4598,8 @@ export class RecordsApiService {
|
|
|
4598
4598
|
accept?: string,
|
|
4599
4599
|
observe?: 'response',
|
|
4600
4600
|
reportProgress?: boolean,
|
|
4601
|
-
options?: { httpHeaderAccept?: 'application/
|
|
4602
|
-
): Observable<HttpResponse<
|
|
4601
|
+
options?: { httpHeaderAccept?: 'application/xml' | 'application/json' }
|
|
4602
|
+
): Observable<HttpResponse<string>>
|
|
4603
4603
|
public getRecordAs(
|
|
4604
4604
|
metadataUuid: string,
|
|
4605
4605
|
addSchemaLocation?: boolean,
|
|
@@ -4610,8 +4610,8 @@ export class RecordsApiService {
|
|
|
4610
4610
|
accept?: string,
|
|
4611
4611
|
observe?: 'events',
|
|
4612
4612
|
reportProgress?: boolean,
|
|
4613
|
-
options?: { httpHeaderAccept?: 'application/
|
|
4614
|
-
): Observable<HttpEvent<
|
|
4613
|
+
options?: { httpHeaderAccept?: 'application/xml' | 'application/json' }
|
|
4614
|
+
): Observable<HttpEvent<string>>
|
|
4615
4615
|
public getRecordAs(
|
|
4616
4616
|
metadataUuid: string,
|
|
4617
4617
|
addSchemaLocation?: boolean,
|
|
@@ -4622,7 +4622,7 @@ export class RecordsApiService {
|
|
|
4622
4622
|
accept?: string,
|
|
4623
4623
|
observe: any = 'body',
|
|
4624
4624
|
reportProgress: boolean = false,
|
|
4625
|
-
options?: { httpHeaderAccept?: 'application/
|
|
4625
|
+
options?: { httpHeaderAccept?: 'application/xml' | 'application/json' }
|
|
4626
4626
|
): Observable<any> {
|
|
4627
4627
|
if (metadataUuid === null || metadataUuid === undefined) {
|
|
4628
4628
|
throw new Error(
|
|
@@ -4677,8 +4677,8 @@ export class RecordsApiService {
|
|
|
4677
4677
|
if (httpHeaderAcceptSelected === undefined) {
|
|
4678
4678
|
// to determine the Accept header
|
|
4679
4679
|
const httpHeaderAccepts: string[] = [
|
|
4680
|
-
'application/json',
|
|
4681
4680
|
'application/xml',
|
|
4681
|
+
'application/json',
|
|
4682
4682
|
]
|
|
4683
4683
|
httpHeaderAcceptSelected =
|
|
4684
4684
|
this.configuration.selectHeaderAccept(httpHeaderAccepts)
|
|
@@ -4695,7 +4695,7 @@ export class RecordsApiService {
|
|
|
4695
4695
|
responseType_ = 'text'
|
|
4696
4696
|
}
|
|
4697
4697
|
|
|
4698
|
-
return this.httpClient.get<
|
|
4698
|
+
return this.httpClient.get<string>(
|
|
4699
4699
|
`${this.configuration.basePath}/records/${encodeURIComponent(
|
|
4700
4700
|
String(metadataUuid)
|
|
4701
4701
|
)}/formatters/xml`,
|
|
@@ -11114,16 +11114,15 @@ paths:
|
|
|
11114
11114
|
default:
|
|
11115
11115
|
description: default response
|
|
11116
11116
|
content:
|
|
11117
|
-
application/
|
|
11117
|
+
application/xml:
|
|
11118
|
+
schema:
|
|
11119
|
+
type: string
|
|
11118
11120
|
"200":
|
|
11119
11121
|
description: Return the record.
|
|
11120
11122
|
content:
|
|
11121
11123
|
application/xml:
|
|
11122
11124
|
schema:
|
|
11123
|
-
type:
|
|
11124
|
-
application/json:
|
|
11125
|
-
schema:
|
|
11126
|
-
type: object
|
|
11125
|
+
type: string
|
|
11127
11126
|
"403":
|
|
11128
11127
|
description: Operation not allowed. User needs to be able to view the resource.
|
|
11129
11128
|
content:
|
|
@@ -4,7 +4,11 @@ import { SaveRecordError } from './editor.models'
|
|
|
4
4
|
|
|
5
5
|
export const openRecord = createAction(
|
|
6
6
|
'[Editor] Open record',
|
|
7
|
-
props<{
|
|
7
|
+
props<{
|
|
8
|
+
record: CatalogRecord
|
|
9
|
+
alreadySavedOnce: boolean
|
|
10
|
+
recordSource?: string | null
|
|
11
|
+
}>()
|
|
8
12
|
)
|
|
9
13
|
|
|
10
14
|
export const updateRecordField = createAction(
|
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
import { inject, Injectable } from '@angular/core'
|
|
2
2
|
import { Actions, createEffect, ofType } from '@ngrx/effects'
|
|
3
|
-
import { of, withLatestFrom } from 'rxjs'
|
|
3
|
+
import { debounceTime, filter, of, withLatestFrom } from 'rxjs'
|
|
4
4
|
import { catchError, map, switchMap } from 'rxjs/operators'
|
|
5
5
|
import * as EditorActions from './editor.actions'
|
|
6
6
|
import { EditorService } from '../services/editor.service'
|
|
7
7
|
import { Store } from '@ngrx/store'
|
|
8
8
|
import { selectRecord, selectRecordFieldsConfig } from './editor.selectors'
|
|
9
|
+
import { RecordsRepositoryInterface } from '../../../../../../libs/common/domain/src/lib/repository/records-repository.interface'
|
|
9
10
|
|
|
10
11
|
@Injectable()
|
|
11
12
|
export class EditorEffects {
|
|
12
13
|
private actions$ = inject(Actions)
|
|
13
14
|
private editorService = inject(EditorService)
|
|
15
|
+
private recordsRepository = inject(RecordsRepositoryInterface)
|
|
14
16
|
private store = inject(Store)
|
|
15
17
|
|
|
16
18
|
saveRecord$ = createEffect(() =>
|
|
@@ -22,10 +24,14 @@ export class EditorEffects {
|
|
|
22
24
|
),
|
|
23
25
|
switchMap(([, record, fieldsConfig]) =>
|
|
24
26
|
this.editorService.saveRecord(record, fieldsConfig).pipe(
|
|
25
|
-
switchMap((
|
|
27
|
+
switchMap(([record, recordSource]) =>
|
|
26
28
|
of(
|
|
27
29
|
EditorActions.saveRecordSuccess(),
|
|
28
|
-
EditorActions.openRecord({
|
|
30
|
+
EditorActions.openRecord({
|
|
31
|
+
record,
|
|
32
|
+
alreadySavedOnce: true,
|
|
33
|
+
recordSource,
|
|
34
|
+
})
|
|
29
35
|
)
|
|
30
36
|
),
|
|
31
37
|
catchError((error) =>
|
|
@@ -46,4 +52,26 @@ export class EditorEffects {
|
|
|
46
52
|
map(() => EditorActions.markRecordAsChanged())
|
|
47
53
|
)
|
|
48
54
|
)
|
|
55
|
+
|
|
56
|
+
saveRecordDraft$ = createEffect(
|
|
57
|
+
() =>
|
|
58
|
+
this.actions$.pipe(
|
|
59
|
+
ofType(EditorActions.updateRecordField),
|
|
60
|
+
debounceTime(1000),
|
|
61
|
+
withLatestFrom(this.store.select(selectRecord)),
|
|
62
|
+
switchMap(([, record]) => this.editorService.saveRecordAsDraft(record))
|
|
63
|
+
),
|
|
64
|
+
{ dispatch: false }
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
checkHasChangesOnOpen$ = createEffect(() =>
|
|
68
|
+
this.actions$.pipe(
|
|
69
|
+
ofType(EditorActions.openRecord),
|
|
70
|
+
map(({ record }) =>
|
|
71
|
+
this.recordsRepository.recordHasDraft(record.uniqueIdentifier)
|
|
72
|
+
),
|
|
73
|
+
filter((hasDraft) => hasDraft),
|
|
74
|
+
map(() => EditorActions.markRecordAsChanged())
|
|
75
|
+
)
|
|
76
|
+
)
|
|
49
77
|
}
|
|
@@ -3,7 +3,7 @@ import { select, Store } from '@ngrx/store'
|
|
|
3
3
|
import * as EditorActions from './editor.actions'
|
|
4
4
|
import * as EditorSelectors from './editor.selectors'
|
|
5
5
|
import { CatalogRecord } from '../../../../../../libs/common/domain/src/lib/model/record'
|
|
6
|
-
import { filter
|
|
6
|
+
import { filter } from 'rxjs'
|
|
7
7
|
import { Actions, ofType } from '@ngrx/effects'
|
|
8
8
|
|
|
9
9
|
@Injectable()
|
|
@@ -12,6 +12,10 @@ export class EditorFacade {
|
|
|
12
12
|
private actions$ = inject(Actions)
|
|
13
13
|
|
|
14
14
|
record$ = this.store.pipe(select(EditorSelectors.selectRecord))
|
|
15
|
+
recordSource$ = this.store.pipe(select(EditorSelectors.selectRecordSource))
|
|
16
|
+
alreadySavedOnce$ = this.store.pipe(
|
|
17
|
+
select(EditorSelectors.selectRecordAlreadySavedOnce)
|
|
18
|
+
)
|
|
15
19
|
saving$ = this.store.pipe(select(EditorSelectors.selectRecordSaving))
|
|
16
20
|
saveError$ = this.store.pipe(
|
|
17
21
|
select(EditorSelectors.selectRecordSaveError),
|
|
@@ -23,8 +27,14 @@ export class EditorFacade {
|
|
|
23
27
|
)
|
|
24
28
|
recordFields$ = this.store.pipe(select(EditorSelectors.selectRecordFields))
|
|
25
29
|
|
|
26
|
-
openRecord(
|
|
27
|
-
|
|
30
|
+
openRecord(
|
|
31
|
+
record: CatalogRecord,
|
|
32
|
+
recordSource: string,
|
|
33
|
+
alreadySavedOnce: boolean
|
|
34
|
+
) {
|
|
35
|
+
this.store.dispatch(
|
|
36
|
+
EditorActions.openRecord({ record, recordSource, alreadySavedOnce })
|
|
37
|
+
)
|
|
28
38
|
}
|
|
29
39
|
|
|
30
40
|
saveRecord() {
|
|
@@ -7,8 +7,18 @@ import { DEFAULT_FIELDS } from '../fields.config'
|
|
|
7
7
|
|
|
8
8
|
export const EDITOR_FEATURE_KEY = 'editor'
|
|
9
9
|
|
|
10
|
+
/**
|
|
11
|
+
* @property record The record being edited
|
|
12
|
+
* @property recordSource Original representation of the record as text, used as a reference; null means the record hasn't be serialized yet
|
|
13
|
+
* @property saving
|
|
14
|
+
* @property saveError
|
|
15
|
+
* @property changedSinceSave
|
|
16
|
+
* @property fieldsConfig Configuration for the fields in the editor
|
|
17
|
+
*/
|
|
10
18
|
export interface EditorState {
|
|
11
19
|
record: CatalogRecord | null
|
|
20
|
+
recordSource: string | null
|
|
21
|
+
alreadySavedOnce: boolean
|
|
12
22
|
saving: boolean
|
|
13
23
|
saveError: SaveRecordError | null
|
|
14
24
|
changedSinceSave: boolean
|
|
@@ -21,6 +31,8 @@ export interface EditorPartialState {
|
|
|
21
31
|
|
|
22
32
|
export const initialEditorState: EditorState = {
|
|
23
33
|
record: null,
|
|
34
|
+
recordSource: null,
|
|
35
|
+
alreadySavedOnce: false,
|
|
24
36
|
saving: false,
|
|
25
37
|
saveError: null,
|
|
26
38
|
changedSinceSave: false,
|
|
@@ -29,11 +41,16 @@ export const initialEditorState: EditorState = {
|
|
|
29
41
|
|
|
30
42
|
const reducer = createReducer(
|
|
31
43
|
initialEditorState,
|
|
32
|
-
on(
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
44
|
+
on(
|
|
45
|
+
EditorActions.openRecord,
|
|
46
|
+
(state, { record, recordSource, alreadySavedOnce }) => ({
|
|
47
|
+
...state,
|
|
48
|
+
changedSinceSave: false,
|
|
49
|
+
recordSource: recordSource ?? null,
|
|
50
|
+
alreadySavedOnce,
|
|
51
|
+
record,
|
|
52
|
+
})
|
|
53
|
+
),
|
|
37
54
|
on(EditorActions.saveRecord, (state) => ({
|
|
38
55
|
...state,
|
|
39
56
|
saving: true,
|
|
@@ -9,6 +9,11 @@ export const selectRecord = createSelector(
|
|
|
9
9
|
(state: EditorState) => state.record
|
|
10
10
|
)
|
|
11
11
|
|
|
12
|
+
export const selectRecordSource = createSelector(
|
|
13
|
+
selectEditorState,
|
|
14
|
+
(state: EditorState) => state.recordSource
|
|
15
|
+
)
|
|
16
|
+
|
|
12
17
|
export const selectRecordSaving = createSelector(
|
|
13
18
|
selectEditorState,
|
|
14
19
|
(state: EditorState) => state.saving
|
|
@@ -24,6 +29,11 @@ export const selectRecordChangedSinceSave = createSelector(
|
|
|
24
29
|
(state: EditorState) => state.changedSinceSave
|
|
25
30
|
)
|
|
26
31
|
|
|
32
|
+
export const selectRecordAlreadySavedOnce = createSelector(
|
|
33
|
+
selectEditorState,
|
|
34
|
+
(state: EditorState) => state.alreadySavedOnce
|
|
35
|
+
)
|
|
36
|
+
|
|
27
37
|
export const selectRecordFieldsConfig = createSelector(
|
|
28
38
|
selectEditorState,
|
|
29
39
|
(state: EditorState) => state.fieldsConfig
|
|
@@ -1,50 +1,22 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
Iso19139Converter,
|
|
5
|
-
} from '../../../../../../libs/api/metadata-converter/src'
|
|
6
|
-
import { Configuration } from '../../../../../../libs/data-access/gn4/src'
|
|
7
|
-
import { from, Observable } from 'rxjs'
|
|
8
|
-
import { map, switchMap } from 'rxjs/operators'
|
|
9
|
-
import { HttpClient } from '@angular/common/http'
|
|
1
|
+
import { Injectable } from '@angular/core'
|
|
2
|
+
import { Observable } from 'rxjs'
|
|
3
|
+
import { map } from 'rxjs/operators'
|
|
10
4
|
import { CatalogRecord } from '../../../../../../libs/common/domain/src/lib/model/record'
|
|
11
5
|
import { EditorFieldsConfig } from '../models/fields.model'
|
|
12
6
|
import { evaluate } from '../expressions'
|
|
7
|
+
import { RecordsRepositoryInterface } from '../../../../../../libs/common/domain/src/lib/repository/records-repository.interface'
|
|
13
8
|
|
|
14
9
|
@Injectable({
|
|
15
10
|
providedIn: 'root',
|
|
16
11
|
})
|
|
17
12
|
export class EditorService {
|
|
18
|
-
private
|
|
13
|
+
constructor(private recordsRepository: RecordsRepositoryInterface) {}
|
|
19
14
|
|
|
20
|
-
|
|
21
|
-
private http: HttpClient,
|
|
22
|
-
@Optional()
|
|
23
|
-
@Inject(Configuration)
|
|
24
|
-
private apiConfiguration: Configuration
|
|
25
|
-
) {}
|
|
26
|
-
|
|
27
|
-
// TODO: use the catalog repository instead
|
|
28
|
-
loadRecordByUuid(uuid: string): Observable<CatalogRecord> {
|
|
29
|
-
return this.http
|
|
30
|
-
.get(`${this.apiUrl}/records/${uuid}/formatters/xml`, {
|
|
31
|
-
responseType: 'text',
|
|
32
|
-
headers: {
|
|
33
|
-
Accept: 'application/xml',
|
|
34
|
-
},
|
|
35
|
-
})
|
|
36
|
-
.pipe(
|
|
37
|
-
switchMap((response) =>
|
|
38
|
-
findConverterForDocument(response).readRecord(response.toString())
|
|
39
|
-
)
|
|
40
|
-
)
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// returns the record as it was when saved
|
|
15
|
+
// returns the record as it was when saved, alongside its source
|
|
44
16
|
saveRecord(
|
|
45
17
|
record: CatalogRecord,
|
|
46
18
|
fieldsConfig: EditorFieldsConfig
|
|
47
|
-
): Observable<CatalogRecord> {
|
|
19
|
+
): Observable<[CatalogRecord, string]> {
|
|
48
20
|
const savedRecord = { ...record }
|
|
49
21
|
|
|
50
22
|
// run onSave processes
|
|
@@ -57,23 +29,16 @@ export class EditorService {
|
|
|
57
29
|
})
|
|
58
30
|
}
|
|
59
31
|
}
|
|
32
|
+
return this.recordsRepository
|
|
33
|
+
.saveRecord(savedRecord)
|
|
34
|
+
.pipe(map((recordSource) => [savedRecord, recordSource]))
|
|
35
|
+
}
|
|
60
36
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
recordXml,
|
|
68
|
-
{
|
|
69
|
-
headers: {
|
|
70
|
-
'Content-Type': 'application/xml',
|
|
71
|
-
},
|
|
72
|
-
withCredentials: true,
|
|
73
|
-
}
|
|
74
|
-
)
|
|
75
|
-
),
|
|
76
|
-
map(() => savedRecord)
|
|
77
|
-
)
|
|
37
|
+
// emits and completes once saving is done
|
|
38
|
+
// note: onSave processes are not run for drafts
|
|
39
|
+
saveRecordAsDraft(record: CatalogRecord): Observable<void> {
|
|
40
|
+
return this.recordsRepository
|
|
41
|
+
.saveRecordAsDraft(record)
|
|
42
|
+
.pipe(map(() => undefined))
|
|
78
43
|
}
|
|
79
44
|
}
|
|
@@ -20,9 +20,7 @@ export class MdViewEffects {
|
|
|
20
20
|
loadFullMetadata$ = createEffect(() =>
|
|
21
21
|
this.actions$.pipe(
|
|
22
22
|
ofType(MdViewActions.loadFullMetadata),
|
|
23
|
-
switchMap(({ uuid }) =>
|
|
24
|
-
this.recordsRepository.getByUniqueIdentifier(uuid)
|
|
25
|
-
),
|
|
23
|
+
switchMap(({ uuid }) => this.recordsRepository.getRecord(uuid)),
|
|
26
24
|
map((record) => {
|
|
27
25
|
if (record === null) {
|
|
28
26
|
return MdViewActions.loadFullMetadataFailure({ notFound: true })
|
|
@@ -34,7 +34,18 @@
|
|
|
34
34
|
<span translate>record.metadata.title</span>
|
|
35
35
|
</ng-template>
|
|
36
36
|
<ng-template #cell let-item>
|
|
37
|
-
|
|
37
|
+
<div class="flex flex-row items-center gap-2 max-w-full">
|
|
38
|
+
<span class="overflow-hidden text-ellipsis">{{ item.title }}</span>
|
|
39
|
+
<gn-ui-badge
|
|
40
|
+
*ngIf="hasDraft(item)"
|
|
41
|
+
[style.--gn-ui-badge-padding]="'0.4em 0.6em'"
|
|
42
|
+
[style.--gn-ui-badge-text-color]="'#3d2006'"
|
|
43
|
+
[style.--gn-ui-badge-background-color]="'#ffbc7b'"
|
|
44
|
+
[style.--gn-ui-badge-rounded]="'4px'"
|
|
45
|
+
>
|
|
46
|
+
<span translate>dashboard.records.hasDraft</span>
|
|
47
|
+
</gn-ui-badge>
|
|
48
|
+
</div>
|
|
38
49
|
</ng-template>
|
|
39
50
|
</gn-ui-interactive-table-column>
|
|
40
51
|
|
|
@@ -20,6 +20,8 @@ import { CommonModule } from '@angular/common'
|
|
|
20
20
|
import { map, take } from 'rxjs/operators'
|
|
21
21
|
import { FieldSort } from '../../../../../../libs/common/domain/src/lib/model/search'
|
|
22
22
|
import { SearchService } from '../utils/service/search.service'
|
|
23
|
+
import { BadgeComponent } from '../../../../../../libs/ui/widgets/src'
|
|
24
|
+
import { RecordsRepositoryInterface } from '../../../../../../libs/common/domain/src/lib/repository/records-repository.interface'
|
|
23
25
|
|
|
24
26
|
@Component({
|
|
25
27
|
selector: 'gn-ui-results-table',
|
|
@@ -33,6 +35,7 @@ import { SearchService } from '../utils/service/search.service'
|
|
|
33
35
|
InteractiveTableColumnComponent,
|
|
34
36
|
MatIconModule,
|
|
35
37
|
TranslateModule,
|
|
38
|
+
BadgeComponent,
|
|
36
39
|
],
|
|
37
40
|
})
|
|
38
41
|
export class ResultsTableComponent {
|
|
@@ -44,7 +47,8 @@ export class ResultsTableComponent {
|
|
|
44
47
|
constructor(
|
|
45
48
|
private searchFacade: SearchFacade,
|
|
46
49
|
private searchService: SearchService,
|
|
47
|
-
private selectionService: SelectionService
|
|
50
|
+
private selectionService: SelectionService,
|
|
51
|
+
private recordsRepository: RecordsRepositoryInterface
|
|
48
52
|
) {}
|
|
49
53
|
|
|
50
54
|
dateToString(date: Date): string {
|
|
@@ -161,4 +165,8 @@ export class ResultsTableComponent {
|
|
|
161
165
|
})
|
|
162
166
|
)
|
|
163
167
|
}
|
|
168
|
+
|
|
169
|
+
hasDraft(record: CatalogRecord): boolean {
|
|
170
|
+
return this.recordsRepository.recordHasDraft(record.uniqueIdentifier)
|
|
171
|
+
}
|
|
164
172
|
}
|
|
@@ -9,7 +9,7 @@ import { ContentGhostComponent } from './content-ghost/content-ghost.component'
|
|
|
9
9
|
import { DownloadItemComponent } from './download-item/download-item.component'
|
|
10
10
|
import { DownloadsListComponent } from './downloads-list/downloads-list.component'
|
|
11
11
|
import { ApiCardComponent } from './api-card/api-card.component'
|
|
12
|
-
import { UiWidgetsModule } from '../../../../../libs/ui/widgets/src'
|
|
12
|
+
import { BadgeComponent, UiWidgetsModule } from '../../../../../libs/ui/widgets/src'
|
|
13
13
|
import { UiLayoutModule } from '../../../../../libs/ui/layout/src'
|
|
14
14
|
import { TranslateModule } from '@ngx-translate/core'
|
|
15
15
|
import { RelatedRecordCardComponent } from './related-record-card/related-record-card.component'
|
|
@@ -49,6 +49,7 @@ import { TimeSincePipe } from './user-feedback-item/time-since.pipe'
|
|
|
49
49
|
MarkdownParserComponent,
|
|
50
50
|
ThumbnailComponent,
|
|
51
51
|
TimeSincePipe,
|
|
52
|
+
BadgeComponent,
|
|
52
53
|
],
|
|
53
54
|
declarations: [
|
|
54
55
|
MetadataInfoComponent,
|