geonetwork-ui 2.7.0-dev.d500b08cc → 2.7.0-dev.d6c0958d7

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.
Files changed (144) hide show
  1. package/esm2022/libs/api/metadata-converter/src/lib/iso19139/utils/status.mapper.mjs +4 -1
  2. package/esm2022/libs/api/metadata-converter/src/lib/iso19139/write-parts.mjs +5 -1
  3. package/esm2022/libs/api/repository/src/lib/gn4/elasticsearch/constant.mjs +4 -6
  4. package/esm2022/libs/api/repository/src/lib/gn4/platform/gn4-platform.service.mjs +28 -4
  5. package/esm2022/libs/common/domain/src/lib/model/dataviz/dataviz-configuration.model.mjs +1 -1
  6. package/esm2022/libs/common/domain/src/lib/model/record/metadata.model.mjs +5 -1
  7. package/esm2022/libs/common/domain/src/lib/platform.service.interface.mjs +1 -1
  8. package/esm2022/libs/feature/dataviz/src/lib/chart-view/chart-view.component.mjs +10 -2
  9. package/esm2022/libs/feature/editor/src/index.mjs +2 -1
  10. package/esm2022/libs/feature/editor/src/lib/components/metadata-quality-panel/metadata-quality-panel.component.mjs +80 -0
  11. package/esm2022/libs/feature/editor/src/lib/components/multilingual-panel/multilingual-panel.component.mjs +3 -3
  12. package/esm2022/libs/feature/editor/src/lib/fields.config.mjs +1 -3
  13. package/esm2022/libs/feature/record/src/lib/data-view/data-view.component.mjs +31 -12
  14. package/esm2022/libs/feature/record/src/lib/map-view/map-view.component.mjs +76 -27
  15. package/esm2022/libs/feature/record/src/lib/state/mdview.effects.mjs +4 -2
  16. package/esm2022/libs/ui/dataviz/src/lib/data-table/data-table.component.mjs +4 -3
  17. package/esm2022/libs/ui/elements/src/lib/downloads-list/downloads-list.component.mjs +5 -4
  18. package/esm2022/libs/ui/elements/src/lib/geo-data-badge/geo-data-badge.component.mjs +5 -4
  19. package/esm2022/libs/ui/elements/src/lib/internal-link-card/internal-link-card.component.mjs +4 -4
  20. package/esm2022/libs/ui/elements/src/lib/metadata-quality/metadata-quality.component.mjs +21 -43
  21. package/esm2022/libs/ui/inputs/src/lib/search-feature-catalog/search-feature-catalog.component.mjs +5 -4
  22. package/esm2022/libs/ui/map/src/lib/components/map-legend/map-legend.component.mjs +2 -2
  23. package/esm2022/libs/util/app-config/src/lib/app-config.mjs +3 -1
  24. package/esm2022/libs/util/app-config/src/lib/model.mjs +1 -1
  25. package/esm2022/libs/util/shared/src/index.mjs +2 -2
  26. package/esm2022/libs/util/shared/src/lib/links/link-utils.mjs +12 -2
  27. package/esm2022/libs/util/shared/src/lib/record/index.mjs +3 -0
  28. package/esm2022/libs/util/shared/src/lib/record/quality-score.util.mjs +45 -0
  29. package/esm2022/libs/util/shared/src/lib/record/record.util.mjs +56 -0
  30. package/esm2022/libs/util/shared/src/lib/utils/index.mjs +2 -1
  31. package/esm2022/libs/util/shared/src/lib/utils/mobile-screen.mjs +9 -0
  32. package/esm2022/translations/de.json +9 -1
  33. package/esm2022/translations/en.json +9 -1
  34. package/esm2022/translations/es.json +9 -1
  35. package/esm2022/translations/fr.json +10 -2
  36. package/esm2022/translations/it.json +9 -1
  37. package/esm2022/translations/nl.json +9 -1
  38. package/esm2022/translations/pt.json +9 -1
  39. package/esm2022/translations/sk.json +9 -1
  40. package/fesm2022/geonetwork-ui.mjs +403 -114
  41. package/fesm2022/geonetwork-ui.mjs.map +1 -1
  42. package/libs/api/metadata-converter/src/lib/iso19139/utils/status.mapper.d.ts.map +1 -1
  43. package/libs/api/metadata-converter/src/lib/iso19139/write-parts.d.ts.map +1 -1
  44. package/libs/api/repository/src/lib/gn4/elasticsearch/constant.d.ts.map +1 -1
  45. package/libs/api/repository/src/lib/gn4/platform/gn4-platform.service.d.ts +2 -0
  46. package/libs/api/repository/src/lib/gn4/platform/gn4-platform.service.d.ts.map +1 -1
  47. package/libs/common/domain/src/lib/model/dataviz/dataviz-configuration.model.d.ts +1 -0
  48. package/libs/common/domain/src/lib/model/dataviz/dataviz-configuration.model.d.ts.map +1 -1
  49. package/libs/common/domain/src/lib/model/record/metadata.model.d.ts.map +1 -1
  50. package/libs/common/domain/src/lib/platform.service.interface.d.ts +1 -0
  51. package/libs/common/domain/src/lib/platform.service.interface.d.ts.map +1 -1
  52. package/libs/feature/dataviz/src/lib/chart-view/chart-view.component.d.ts +3 -2
  53. package/libs/feature/dataviz/src/lib/chart-view/chart-view.component.d.ts.map +1 -1
  54. package/libs/feature/editor/src/index.d.ts +1 -0
  55. package/libs/feature/editor/src/index.d.ts.map +1 -1
  56. package/libs/feature/editor/src/lib/components/metadata-quality-panel/metadata-quality-panel.component.d.ts +19 -0
  57. package/libs/feature/editor/src/lib/components/metadata-quality-panel/metadata-quality-panel.component.d.ts.map +1 -0
  58. package/libs/feature/editor/src/lib/fields.config.d.ts.map +1 -1
  59. package/libs/feature/record/src/lib/data-view/data-view.component.d.ts +8 -4
  60. package/libs/feature/record/src/lib/data-view/data-view.component.d.ts.map +1 -1
  61. package/libs/feature/record/src/lib/map-view/map-view.component.d.ts +12 -5
  62. package/libs/feature/record/src/lib/map-view/map-view.component.d.ts.map +1 -1
  63. package/libs/feature/record/src/lib/state/mdview.effects.d.ts.map +1 -1
  64. package/libs/ui/dataviz/src/lib/data-table/data-table.component.d.ts.map +1 -1
  65. package/libs/ui/elements/src/lib/downloads-list/downloads-list.component.d.ts +1 -0
  66. package/libs/ui/elements/src/lib/downloads-list/downloads-list.component.d.ts.map +1 -1
  67. package/libs/ui/elements/src/lib/geo-data-badge/geo-data-badge.component.d.ts +1 -0
  68. package/libs/ui/elements/src/lib/geo-data-badge/geo-data-badge.component.d.ts.map +1 -1
  69. package/libs/ui/elements/src/lib/internal-link-card/internal-link-card.component.d.ts.map +1 -1
  70. package/libs/ui/elements/src/lib/metadata-quality/metadata-quality.component.d.ts +7 -6
  71. package/libs/ui/elements/src/lib/metadata-quality/metadata-quality.component.d.ts.map +1 -1
  72. package/libs/ui/inputs/src/lib/search-feature-catalog/search-feature-catalog.component.d.ts +1 -0
  73. package/libs/ui/inputs/src/lib/search-feature-catalog/search-feature-catalog.component.d.ts.map +1 -1
  74. package/libs/util/app-config/src/lib/app-config.d.ts.map +1 -1
  75. package/libs/util/app-config/src/lib/model.d.ts +1 -0
  76. package/libs/util/app-config/src/lib/model.d.ts.map +1 -1
  77. package/libs/util/shared/src/index.d.ts +1 -1
  78. package/libs/util/shared/src/index.d.ts.map +1 -1
  79. package/libs/util/shared/src/lib/links/link-utils.d.ts +2 -1
  80. package/libs/util/shared/src/lib/links/link-utils.d.ts.map +1 -1
  81. package/libs/util/shared/src/lib/record/index.d.ts +3 -0
  82. package/libs/util/shared/src/lib/record/index.d.ts.map +1 -0
  83. package/libs/util/shared/src/lib/record/quality-score.util.d.ts +13 -0
  84. package/libs/util/shared/src/lib/record/quality-score.util.d.ts.map +1 -0
  85. package/libs/util/shared/src/lib/record/record.util.d.ts +3 -0
  86. package/libs/util/shared/src/lib/record/record.util.d.ts.map +1 -0
  87. package/libs/util/shared/src/lib/utils/index.d.ts +1 -0
  88. package/libs/util/shared/src/lib/utils/index.d.ts.map +1 -1
  89. package/libs/util/shared/src/lib/utils/mobile-screen.d.ts +2 -0
  90. package/libs/util/shared/src/lib/utils/mobile-screen.d.ts.map +1 -0
  91. package/package.json +1 -1
  92. package/src/libs/api/metadata-converter/src/lib/dcat-ap/utils/status.mapper.ts +3 -0
  93. package/src/libs/api/metadata-converter/src/lib/iso19139/utils/status.mapper.ts +3 -0
  94. package/src/libs/api/metadata-converter/src/lib/iso19139/write-parts.ts +4 -0
  95. package/src/libs/api/repository/src/lib/gn4/elasticsearch/constant.ts +3 -5
  96. package/src/libs/api/repository/src/lib/gn4/platform/gn4-platform.service.ts +36 -4
  97. package/src/libs/common/domain/src/lib/model/dataviz/dataviz-configuration.model.ts +1 -0
  98. package/src/libs/common/domain/src/lib/model/record/metadata.model.ts +4 -0
  99. package/src/libs/common/domain/src/lib/platform.service.interface.ts +2 -0
  100. package/src/libs/common/fixtures/src/lib/editor/editor.fixtures.ts +0 -3
  101. package/src/libs/feature/dataviz/src/lib/chart-view/chart-view.component.ts +10 -1
  102. package/src/libs/feature/editor/src/index.ts +1 -0
  103. package/src/libs/feature/editor/src/lib/components/metadata-quality-panel/metadata-quality-panel.component.css +0 -0
  104. package/src/libs/feature/editor/src/lib/components/metadata-quality-panel/metadata-quality-panel.component.html +37 -0
  105. package/src/libs/feature/editor/src/lib/components/metadata-quality-panel/metadata-quality-panel.component.ts +90 -0
  106. package/src/libs/feature/editor/src/lib/components/multilingual-panel/multilingual-panel.component.html +2 -1
  107. package/src/libs/feature/editor/src/lib/fields.config.ts +0 -2
  108. package/src/libs/feature/record/src/lib/data-view/data-view.component.html +2 -0
  109. package/src/libs/feature/record/src/lib/data-view/data-view.component.ts +34 -15
  110. package/src/libs/feature/record/src/lib/map-view/map-view.component.html +5 -2
  111. package/src/libs/feature/record/src/lib/map-view/map-view.component.ts +70 -23
  112. package/src/libs/feature/record/src/lib/state/mdview.effects.ts +5 -1
  113. package/src/libs/ui/dataviz/src/lib/data-table/data-table.component.ts +6 -1
  114. package/src/libs/ui/elements/src/lib/downloads-list/downloads-list.component.html +12 -11
  115. package/src/libs/ui/elements/src/lib/downloads-list/downloads-list.component.ts +7 -1
  116. package/src/libs/ui/elements/src/lib/geo-data-badge/geo-data-badge.component.html +4 -1
  117. package/src/libs/ui/elements/src/lib/geo-data-badge/geo-data-badge.component.ts +7 -1
  118. package/src/libs/ui/elements/src/lib/internal-link-card/internal-link-card.component.html +1 -0
  119. package/src/libs/ui/elements/src/lib/internal-link-card/internal-link-card.component.ts +5 -1
  120. package/src/libs/ui/elements/src/lib/metadata-quality/metadata-quality.component.html +1 -0
  121. package/src/libs/ui/elements/src/lib/metadata-quality/metadata-quality.component.ts +21 -54
  122. package/src/libs/ui/inputs/src/lib/search-feature-catalog/search-feature-catalog.component.html +7 -1
  123. package/src/libs/ui/inputs/src/lib/search-feature-catalog/search-feature-catalog.component.ts +3 -1
  124. package/src/libs/ui/map/src/lib/components/map-legend/map-legend.component.ts +1 -1
  125. package/src/libs/util/app-config/src/lib/app-config.ts +2 -0
  126. package/src/libs/util/app-config/src/lib/model.ts +1 -0
  127. package/src/libs/util/shared/src/index.ts +1 -1
  128. package/src/libs/util/shared/src/lib/links/link-utils.ts +11 -1
  129. package/src/libs/util/shared/src/lib/record/index.ts +2 -0
  130. package/src/libs/util/shared/src/lib/record/quality-score.util.ts +69 -0
  131. package/src/libs/util/shared/src/lib/{record.util.ts → record/record.util.ts} +1 -1
  132. package/src/libs/util/shared/src/lib/utils/index.ts +1 -0
  133. package/src/libs/util/shared/src/lib/utils/mobile-screen.ts +14 -0
  134. package/translations/de.json +9 -1
  135. package/translations/en.json +9 -1
  136. package/translations/es.json +9 -1
  137. package/translations/fr.json +10 -2
  138. package/translations/it.json +9 -1
  139. package/translations/nl.json +9 -1
  140. package/translations/pt.json +9 -1
  141. package/translations/sk.json +9 -1
  142. package/esm2022/libs/util/shared/src/lib/record.util.mjs +0 -56
  143. package/libs/util/shared/src/lib/record.util.d.ts +0 -3
  144. package/libs/util/shared/src/lib/record.util.d.ts.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mobile-screen.d.ts","sourceRoot":"","sources":["../../../../../../src/libs/util/shared/src/lib/utils/mobile-screen.ts"],"names":[],"mappings":"AAOA,wBAAgB,WAAW,uCAM1B"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "geonetwork-ui",
3
- "version": "2.7.0-dev.d500b08cc",
3
+ "version": "2.7.0-dev.d6c0958d7",
4
4
  "engines": {
5
5
  "node": ">=20"
6
6
  },
@@ -11,8 +11,11 @@ export function getStatusFromStatusCode(statusCode: string): RecordStatus {
11
11
  case 'onGoing':
12
12
  return 'ongoing'
13
13
  case 'planned':
14
+ return 'planned'
14
15
  case 'required':
16
+ return 'required'
15
17
  case 'underDevelopment':
18
+ return 'under_development'
16
19
  default:
17
20
  return 'under_development'
18
21
  }
@@ -11,8 +11,11 @@ export function getStatusFromStatusCode(statusCode: string): RecordStatus {
11
11
  case 'onGoing':
12
12
  return 'ongoing'
13
13
  case 'planned':
14
+ return 'planned'
14
15
  case 'required':
16
+ return 'required'
15
17
  case 'underDevelopment':
18
+ return 'under_development'
16
19
  default:
17
20
  return 'under_development'
18
21
  }
@@ -183,6 +183,10 @@ export function getProgressCode(status: RecordStatus): string {
183
183
  return 'removed'
184
184
  case 'under_development':
185
185
  return 'underDevelopment'
186
+ case 'planned':
187
+ return 'planned'
188
+ case 'required':
189
+ return 'required'
186
190
  default:
187
191
  throw new Error(
188
192
  `Could not determine progress code from status: ${status}`
@@ -10,14 +10,12 @@ export const ES_SOURCE_SUMMARY = [
10
10
  'codelist_status_text',
11
11
  'link',
12
12
  'linkProtocol',
13
- 'contactForResource.organisation',
14
- 'contact.organisation',
15
- 'contact.email',
13
+ 'contactForResource*.organisation*',
14
+ 'contact*.organisation*',
15
+ 'contact*.email',
16
16
  'userSavedCount',
17
- 'updateFrequency',
18
17
  'cl_topic',
19
18
  'cl_maintenanceAndUpdateFrequency',
20
- 'tag',
21
19
  'MD_LegalConstraints*Object',
22
20
  'qualityScore',
23
21
  'allKeywords',
@@ -46,6 +46,7 @@ import {
46
46
  } from 'rxjs'
47
47
  import { TranslateService } from '@ngx-translate/core'
48
48
  import { getLang3FromLang2 } from '../../../../../../../libs/util/i18n/src'
49
+ import { DatavizConfigModel } from '../../../../../../../libs/common/domain/src/lib/model/dataviz/dataviz-configuration.model'
49
50
 
50
51
  const minApiVersion = '4.2.2'
51
52
 
@@ -323,10 +324,15 @@ export class Gn4PlatformService implements PlatformServiceInterface {
323
324
  ...(Array.isArray(onlines) ? onlines : []),
324
325
  ...(Array.isArray(thumbnails) ? thumbnails : []),
325
326
  ].map((resource) => Object.values(resource.url)[0])
326
-
327
- const fileToDelete = attachments
328
- .filter((attachment) => !urlsToKeep.includes(attachment.url))
329
- .map((attachment) => attachment.filename)
327
+ const fileToDelete = attachments.reduce<string[]>((acc, attachment) => {
328
+ if (
329
+ !urlsToKeep.includes(attachment.url) &&
330
+ attachment.filename !== 'datavizConfig.json'
331
+ ) {
332
+ acc.push(attachment.filename)
333
+ }
334
+ return acc
335
+ }, [])
330
336
 
331
337
  return fileToDelete
332
338
  }),
@@ -385,6 +391,32 @@ export class Gn4PlatformService implements PlatformServiceInterface {
385
391
  )
386
392
  }
387
393
 
394
+ getFileContent(url: URL | string): Observable<any> {
395
+ return this.httpClient.get(url.toString(), { responseType: 'text' }).pipe(
396
+ map((text) => {
397
+ const parsed = JSON.parse(text)
398
+
399
+ if (typeof parsed === 'object') {
400
+ return parsed
401
+ }
402
+
403
+ const decoded = this.decodeBase64(parsed)
404
+ return JSON.parse(decoded)
405
+ })
406
+ )
407
+ }
408
+
409
+ decodeBase64(base64) {
410
+ const text = atob(base64)
411
+ const length = text.length
412
+ const bytes = new Uint8Array(length)
413
+ for (let i = 0; i < length; i++) {
414
+ bytes[i] = text.charCodeAt(i)
415
+ }
416
+ const decoder = new TextDecoder()
417
+ return decoder.decode(bytes)
418
+ }
419
+
388
420
  attachFileToRecord(
389
421
  recordUuid: string,
390
422
  file: File,
@@ -24,4 +24,5 @@ export interface DatavizConfigModel {
24
24
  view: string
25
25
  source: DatasetOnlineResource
26
26
  chartConfig?: DatavizChartConfigModel
27
+ styleTMSIndex: number
27
28
  }
@@ -69,6 +69,8 @@ marker('domain.record.status.ongoing')
69
69
  marker('domain.record.status.under_development')
70
70
  marker('domain.record.status.deprecated')
71
71
  marker('domain.record.status.removed')
72
+ marker('domain.record.status.planned')
73
+ marker('domain.record.status.required')
72
74
 
73
75
  export const RecordStatusValues = [
74
76
  'completed',
@@ -76,6 +78,8 @@ export const RecordStatusValues = [
76
78
  'under_development',
77
79
  'deprecated',
78
80
  'removed',
81
+ 'planned',
82
+ 'required',
79
83
  ]
80
84
  export type RecordStatus = (typeof RecordStatusValues)[number]
81
85
 
@@ -3,6 +3,7 @@ import type { UserModel } from './model/user/user.model'
3
3
  import type { Organization } from './model/record/organization.model'
4
4
  import { CatalogRecord, Keyword, UserFeedback } from './model/record'
5
5
  import { KeywordType } from './model/thesaurus'
6
+ import { DatavizConfigModel } from './model/dataviz/dataviz-configuration.model'
6
7
 
7
8
  export interface RecordAttachment {
8
9
  url: URL
@@ -55,4 +56,5 @@ export abstract class PlatformServiceInterface {
55
56
  file: File,
56
57
  removeDuplicate?: boolean
57
58
  ): Observable<UploadEvent>
59
+ abstract getFileContent(url: URL): Observable<any>
58
60
  }
@@ -127,9 +127,6 @@ export const editorFieldSpatialExtentsFixture = () => ({
127
127
  export const editorFieldKeywordsFixture = () => ({
128
128
  model: 'keywords',
129
129
  hidden: false,
130
- formFieldConfig: {
131
- labelKey: 'editor.record.form.field.keywords',
132
- },
133
130
  })
134
131
 
135
132
  export const editorFieldUniqueIdentifierFixture = () => ({
@@ -28,7 +28,10 @@ import {
28
28
  tap,
29
29
  } from 'rxjs/operators'
30
30
  import { DataService } from '../service/data.service'
31
- import { InputChartType } from '../../../../../../libs/common/domain/src/lib/model/dataviz/dataviz-configuration.model'
31
+ import {
32
+ DatavizChartConfigModel,
33
+ InputChartType,
34
+ } from '../../../../../../libs/common/domain/src/lib/model/dataviz/dataviz-configuration.model'
32
35
  import {
33
36
  DatasetFeatureCatalog,
34
37
  DatasetOnlineResource,
@@ -104,6 +107,12 @@ export class ChartViewComponent {
104
107
  }
105
108
  chartType$ = new BehaviorSubject<InputChartType>('bar')
106
109
 
110
+ @Input() set userChartConfig(config: DatavizChartConfigModel) {
111
+ this.aggregation$.next(config.aggregation)
112
+ this.xProperty$.next(config.xProperty)
113
+ this.yProperty$.next(config.yProperty)
114
+ this.chartType$.next(config.chartType)
115
+ }
107
116
  @Output() chartConfig$ = combineLatest([
108
117
  this.xProperty$.pipe(filter((value) => value !== undefined)),
109
118
  this.yProperty$.pipe(filter((value) => value !== undefined)),
@@ -9,3 +9,4 @@ export * from './lib/components/import-record/import-record.component'
9
9
  export * from './lib/components/record-form/record-form.component'
10
10
  export * from './lib/components/record-form/form-field'
11
11
  export * from './lib/components/multilingual-panel/multilingual-panel.component'
12
+ export * from './lib/components/metadata-quality-panel/metadata-quality-panel.component'
@@ -0,0 +1,37 @@
1
+ <div
2
+ class="flex flex-col h-full w-[302px] border-l border-gray-300 py-8 px-3 gap-3 overflow-auto"
3
+ style="background-color: #fafaf9"
4
+ >
5
+ <div class="flex flex-row px-2 justify-between">
6
+ <span class="text-3xl font-title text-black/80" translate
7
+ >editor.record.form.metadataQuality.title</span
8
+ >
9
+ </div>
10
+ <div
11
+ *ngFor="let properties of propertiesByPage; let i = index"
12
+ class="flex flex-col gap-2"
13
+ >
14
+ <gn-ui-button
15
+ *ngFor="let property of properties"
16
+ [extraClass]="getExtraClass(property.value)"
17
+ type="outline"
18
+ attr.data-cy="md-quality-btn-{{ property.label }}"
19
+ >
20
+ <span>{{ property.label | translate }}</span>
21
+ <div class="flex flex-row gap-2 items-center">
22
+ <ng-icon
23
+ *ngIf="property.value; else notChecked"
24
+ class="text-primary"
25
+ name="iconoirBadgeCheck"
26
+ ></ng-icon>
27
+ <ng-template #notChecked>
28
+ <ng-icon class="text-neutral-300" name="iconoirSystemShut"></ng-icon>
29
+ </ng-template>
30
+ </div>
31
+ </gn-ui-button>
32
+ <hr
33
+ *ngIf="i !== propertiesByPage.length - 1"
34
+ class="border-gray-300 w-11/12 mx-auto"
35
+ />
36
+ </div>
37
+ </div>
@@ -0,0 +1,90 @@
1
+ import { CommonModule } from '@angular/common'
2
+ import { Component, Input, OnChanges } from '@angular/core'
3
+ import { CatalogRecord } from '../../../../../../../libs/common/domain/src/lib/model/record'
4
+ import { ButtonComponent } from '../../../../../../../libs/ui/inputs/src'
5
+ import {
6
+ getAllKeysValidator,
7
+ getQualityValidators,
8
+ ValidatorMapperKeys,
9
+ } from '../../../../../../../libs/util/shared/src'
10
+ import {
11
+ NgIconComponent,
12
+ provideIcons,
13
+ provideNgIconsConfig,
14
+ } from '@ng-icons/core'
15
+ import { iconoirBadgeCheck, iconoirSystemShut } from '@ng-icons/iconoir'
16
+ import { TranslateDirective, TranslatePipe } from '@ngx-translate/core'
17
+ import { EditorConfig } from '../../models'
18
+ import { marker } from '@biesbjerg/ngx-translate-extract-marker'
19
+
20
+ //forced translations that are not available in fields.config.ts
21
+ marker('editor.record.form.field.keywords')
22
+ marker('editor.record.form.field.topics')
23
+ marker('editor.record.form.field.contacts')
24
+ marker('editor.record.form.field.organisation')
25
+ @Component({
26
+ selector: 'gn-ui-metadata-quality-panel',
27
+ standalone: true,
28
+ imports: [
29
+ CommonModule,
30
+ TranslateDirective,
31
+ TranslatePipe,
32
+ ButtonComponent,
33
+ NgIconComponent,
34
+ ],
35
+ providers: [
36
+ provideIcons({
37
+ iconoirSystemShut,
38
+ iconoirBadgeCheck,
39
+ }),
40
+ provideNgIconsConfig({
41
+ size: '1.25em',
42
+ }),
43
+ ],
44
+ templateUrl: './metadata-quality-panel.component.html',
45
+ styleUrl: './metadata-quality-panel.component.css',
46
+ })
47
+ export class MetadataQualityPanelComponent implements OnChanges {
48
+ propsToValidate: ValidatorMapperKeys[] = getAllKeysValidator()
49
+ propertiesByPage: { label: string; value: boolean }[][] = []
50
+ @Input() editorConfig: EditorConfig
51
+ @Input() record: CatalogRecord
52
+
53
+ ngOnChanges() {
54
+ if (this.editorConfig && this.record) {
55
+ const fieldsByPage = this.editorConfig.pages.map((page) =>
56
+ page.sections.flatMap((section) =>
57
+ section.fields
58
+ .filter((field) => this.propsToValidate.includes(field.model))
59
+ .map((field) => field.model as ValidatorMapperKeys)
60
+ )
61
+ )
62
+ // FIXME: temporarily add topics and organisation to the first and third page
63
+ // as long as they are not handled by the editor
64
+ if (fieldsByPage.length > 0) {
65
+ fieldsByPage[0].includes('topics') || fieldsByPage[0].push('topics')
66
+ fieldsByPage[2].includes('organisation') ||
67
+ fieldsByPage[2].push('organisation')
68
+ }
69
+ this.propertiesByPage = fieldsByPage
70
+ .map((fields) =>
71
+ getQualityValidators(
72
+ this.record,
73
+ fields as ValidatorMapperKeys[]
74
+ ).map(({ name, validator }) => ({
75
+ label: `editor.record.form.field.${name}`, // use same translations as in fields.config.ts
76
+ value: validator(),
77
+ }))
78
+ )
79
+ .filter((arr) => arr.length > 0)
80
+ }
81
+ }
82
+
83
+ getExtraClass(checked: boolean): string {
84
+ const baseClasses =
85
+ 'flex flex-row justify-between rounded mb-1 h-[34px] w-full focus:ring-0 hover:border-none border-none hover:text-black text-black cursor-default'
86
+ return checked
87
+ ? `${baseClasses} bg-neutral-100 hover:bg-neutral-100`
88
+ : `${baseClasses} bg-transparent hover:bg-transparent`
89
+ }
90
+ }
@@ -1,5 +1,6 @@
1
1
  <div
2
- class="flex flex-col h-full w-[302px] bg-neutral-100 border-l border-gray-300 py-8 px-3 gap-6 overflow-auto"
2
+ class="flex flex-col h-full w-[302px] border-l border-gray-300 py-8 px-3 gap-6 overflow-auto"
3
+ style="background-color: #fafaf9"
3
4
  >
4
5
  <div class="flex flex-row px-2 justify-between">
5
6
  <span class="text-3xl font-title text-black/80" translate
@@ -63,8 +63,6 @@ export const RECORD_KEYWORDS_FIELD: EditorField = {
63
63
  model: 'keywords',
64
64
  formFieldConfig: {},
65
65
  }
66
- // keeping track of the label to not lose existing translation
67
- marker('editor.record.form.field.keywords')
68
66
 
69
67
  export const RECORD_RESOURCE_CREATED_FIELD: EditorField = {
70
68
  model: 'resourceCreated',
@@ -9,6 +9,7 @@
9
9
  class="h-[44px] w-full"
10
10
  extraBtnClass="font-sans font-bold"
11
11
  [choices]="choices"
12
+ [selected]="_selectedChoice"
12
13
  (selectValue)="selectLink($event)"
13
14
  ></gn-ui-dropdown-selector>
14
15
  </div>
@@ -35,6 +36,7 @@
35
36
  [cacheActive]="cacheActive$ | async"
36
37
  [link]="selectedLink$ | async"
37
38
  [featureCatalog]="mdViewFacade.featureCatalog$ | async"
39
+ [userChartConfig]="_chartConfig"
38
40
  ></gn-ui-chart-view>
39
41
  </div>
40
42
  </ng-template>
@@ -5,15 +5,16 @@ import {
5
5
  Input,
6
6
  Output,
7
7
  } from '@angular/core'
8
- import { getLinkLabel, getLinkPriority } from '../../../../../../libs/util/shared/src'
8
+ import {
9
+ getLinkId,
10
+ getLinkLabel,
11
+ getLinkPriority,
12
+ } from '../../../../../../libs/util/shared/src'
9
13
  import { BehaviorSubject, combineLatest } from 'rxjs'
10
14
  import { map, tap } from 'rxjs/operators'
11
15
  import { MdViewFacade } from '../state'
12
16
  import { DatavizChartConfigModel } from '../../../../../../libs/common/domain/src/lib/model/dataviz/dataviz-configuration.model'
13
- import {
14
- DatasetOnlineResource,
15
- DatasetServiceDistribution,
16
- } from '../../../../../../libs/common/domain/src/lib/model/record'
17
+ import { DatasetOnlineResource } from '../../../../../../libs/common/domain/src/lib/model/record'
17
18
  import { DropdownSelectorComponent } from '../../../../../../libs/ui/inputs/src'
18
19
  import {
19
20
  ChartViewComponent,
@@ -45,13 +46,28 @@ export class DataViewComponent {
45
46
  @Input() set exceedsLimit(value: boolean) {
46
47
  this.excludeWfs$.next(value)
47
48
  }
49
+ linkMap: Map<string, DatasetOnlineResource> = new Map()
48
50
  _selectedView = ''
51
+ _chartConfig = null
52
+ _selectedChoice = null
49
53
  @Input() set selectedView(value: string) {
50
54
  this._selectedView = value
51
- if (value !== 'map') {
55
+ if (this.mode === value) {
52
56
  this.linkSelected.emit(this.selectedLink$.value)
53
57
  }
54
58
  }
59
+ @Input() set datavizConfig(value: any) {
60
+ this._selectedView = value.view
61
+ if (this.mode === value.view) {
62
+ if (!value.source) {
63
+ this.linkSelected.emit(this.selectedLink$.value)
64
+ } else {
65
+ this._chartConfig = value.chartConfig
66
+ this._selectedChoice = getLinkId(value.source)
67
+ this.selectedLink$.next(value.source)
68
+ }
69
+ }
70
+ }
55
71
  @Output() chartConfig$ = new BehaviorSubject<DatavizChartConfigModel>(null)
56
72
  @Output() linkSelected = new EventEmitter<DatasetOnlineResource>()
57
73
  cacheActive$ = this.mdViewFacade.isHighUpdateFrequency$.pipe(
@@ -69,15 +85,19 @@ export class DataViewComponent {
69
85
  })
70
86
  )
71
87
  dropdownChoices$ = this.compatibleDataLinks$.pipe(
72
- tap((links) => {
73
- if (links.indexOf(this.selectedLink$.value) === -1) {
74
- this.selectLink(JSON.stringify(links[0]))
88
+ tap((links: DatasetOnlineResource[]) => {
89
+ this.linkMap.clear()
90
+ links.forEach((link: DatasetOnlineResource) =>
91
+ this.linkMap.set(getLinkId(link), link)
92
+ )
93
+ if (!links.some((l) => l.url === this.selectedLink$.value?.url)) {
94
+ this.selectLink(getLinkId(links[0]))
75
95
  }
76
96
  }),
77
97
  map((links) =>
78
- links.map((link) => ({
98
+ links.map((link: DatasetOnlineResource) => ({
79
99
  label: getLinkLabel(link),
80
- value: JSON.stringify(link),
100
+ value: getLinkId(link),
81
101
  }))
82
102
  )
83
103
  )
@@ -93,12 +113,11 @@ export class DataViewComponent {
93
113
  this.mdViewFacade.setChartConfig(event)
94
114
  }
95
115
 
96
- selectLink(linkAsString: string) {
97
- const link: DatasetOnlineResource = JSON.parse(linkAsString)
98
- if (this._selectedView && this._selectedView !== 'map') {
116
+ selectLink(linkId: string) {
117
+ const link = this.linkMap.get(linkId)
118
+ if (this._selectedView && this._selectedView === this.mode) {
99
119
  this.linkSelected.emit(link)
100
120
  }
101
- link.url = new URL(link.url)
102
121
  this.selectedLink$.next(link)
103
122
  }
104
123
  }
@@ -8,6 +8,7 @@
8
8
  extraBtnClass="font-sans font-bold"
9
9
  [title]="'map.select.layer' | translate"
10
10
  [choices]="dropdownChoices$ | async"
11
+ [selected]="_selectedChoice"
11
12
  (selectValue)="selectLinkToDisplay($event)"
12
13
  ></gn-ui-dropdown-selector>
13
14
 
@@ -17,6 +18,7 @@
17
18
  extraBtnClass="font-sans font-bold"
18
19
  [title]="'map.select.style' | translate"
19
20
  [choices]="styleDropdownChoices$ | async"
21
+ [selected]="_styleFromConfig"
20
22
  (selectValue)="selectStyleToDisplay($event)"
21
23
  ></gn-ui-dropdown-selector>
22
24
  </ng-container>
@@ -85,7 +87,7 @@
85
87
  [hidden]="!showLegend || !legendExists"
86
88
  >
87
89
  <div class="flex justify-between items-center mb-2">
88
- <div class="text-primary font-bold">Legend</div>
90
+ <div class="text-primary font-bold" translate>map.legend.title</div>
89
91
  <gn-ui-button
90
92
  type="light"
91
93
  (buttonClick)="toggleLegend()"
@@ -110,8 +112,9 @@
110
112
  type="outline"
111
113
  (buttonClick)="toggleLegend()"
112
114
  extraClass="absolute top-[1em] right-[1em] rounded p-1 text-xs bg-white"
115
+ translate
113
116
  >
114
- Legend
117
+ map.legend.title
115
118
  </gn-ui-button>
116
119
 
117
120
  <gn-ui-loading-mask
@@ -9,7 +9,7 @@ import {
9
9
  ViewChild,
10
10
  } from '@angular/core'
11
11
  import { MapUtilsService } from '../../../../../../libs/feature/map/src'
12
- import { getLinkLabel } from '../../../../../../libs/util/shared/src'
12
+ import { getLinkId, getLinkLabel } from '../../../../../../libs/util/shared/src'
13
13
  import {
14
14
  BehaviorSubject,
15
15
  combineLatest,
@@ -100,15 +100,28 @@ export class MapViewComponent implements AfterViewInit {
100
100
  @Input() set exceedsLimit(value: boolean) {
101
101
  this.excludeWfs$.next(value)
102
102
  }
103
+ linkFromConfig$ = new BehaviorSubject(null)
104
+ _selectedChoice = null
105
+ _styleFromConfig = null
106
+
107
+ linkMap: Map<string, DatasetOnlineResource> = new Map()
103
108
  @Input() set selectedView(value: string) {
104
- if (value === 'map') {
105
- this.selectedLink$.pipe(take(1)).subscribe((link) => {
106
- this.linkSelected.emit(link)
107
- })
109
+ this.selectedView$.next(value)
110
+ }
111
+ @Input() set datavizConfig(value: any) {
112
+ if (value.view === 'map') {
113
+ this.selectedView$.next(value.view)
114
+ if (value.styleTMSIndex) {
115
+ this._styleFromConfig = value.styleTMSIndex
116
+ }
117
+ if (value.source) {
118
+ this.linkFromConfig$.next(value.source)
119
+ }
108
120
  }
109
121
  }
110
122
  @Input() displaySource = true
111
123
  @Output() linkSelected = new EventEmitter<DatasetOnlineResource>()
124
+ @Output() styleSelected = new EventEmitter<number>()
112
125
  @ViewChild('mapContainer') mapContainer: MapContainerComponent
113
126
 
114
127
  excludeWfs$ = new BehaviorSubject(false)
@@ -119,12 +132,13 @@ export class MapViewComponent implements AfterViewInit {
119
132
  loading = false
120
133
  error = null
121
134
 
122
- selectLinkToDisplay(i: number) {
123
- this.selectedLinkIndex$.next(i)
135
+ selectLinkToDisplay(id: string) {
136
+ this.selectedLinkId$.next(id)
124
137
  }
125
138
 
126
139
  selectStyleToDisplay(i: number) {
127
- this.selectedStyleIndex$.next(i)
140
+ this.selectedStyleId$.next(i)
141
+ this.styleSelected.emit(i)
128
142
  }
129
143
 
130
144
  toggleLegend() {
@@ -146,29 +160,54 @@ export class MapViewComponent implements AfterViewInit {
146
160
  )
147
161
 
148
162
  dropdownChoices$ = this.compatibleMapLinks$.pipe(
149
- map((links) =>
150
- links.length
151
- ? links.map((link, index) => ({
163
+ map((links) => {
164
+ this.linkMap.clear()
165
+ links.forEach((link: DatasetOnlineResource) =>
166
+ this.linkMap.set(getLinkId(link), link)
167
+ )
168
+ return links.length
169
+ ? links.map((link) => ({
152
170
  label: getLinkLabel(link),
153
- value: index,
171
+ value: getLinkId(link),
154
172
  }))
155
- : [{ label: 'map.dropdown.placeholder', value: 0 }]
156
- )
173
+ : [{ label: 'map.dropdown.placeholder', value: '' }]
174
+ })
157
175
  )
158
176
 
159
- selectedLinkIndex$ = new BehaviorSubject(0)
160
- private selectedStyleIndex$ = new BehaviorSubject(0)
177
+ selectedView$ = new BehaviorSubject(null)
178
+ selectedLinkId$ = new BehaviorSubject(null)
179
+ selectedStyleId$ = new BehaviorSubject(null)
161
180
 
162
181
  selectedSourceLink$ = combineLatest([
163
182
  this.compatibleMapLinks$,
164
- this.selectedLinkIndex$.pipe(distinctUntilChanged()),
183
+ this.linkFromConfig$,
184
+ this.selectedLinkId$.pipe(distinctUntilChanged()),
185
+ this.selectedView$,
165
186
  ]).pipe(
166
187
  tap(() => {
167
188
  this.error = null
168
189
  }),
169
- map(([links, index]) => {
170
- this.linkSelected.emit(links[index])
171
- return links[index]
190
+ map(([compatibleLinks, configLink, id, view]) => {
191
+ if (view === 'map') {
192
+ if (
193
+ configLink &&
194
+ !id &&
195
+ compatibleLinks.some(
196
+ (link) => getLinkId(link) === getLinkId(configLink)
197
+ )
198
+ ) {
199
+ this._selectedChoice = getLinkId(configLink)
200
+ this.linkSelected.emit(configLink)
201
+ return configLink
202
+ } else if (id) {
203
+ this._selectedChoice = id
204
+ this.linkSelected.emit(this.linkMap.get(id))
205
+ return this.linkMap.get(id)
206
+ } else {
207
+ this.linkSelected.emit(compatibleLinks[0])
208
+ return compatibleLinks[0]
209
+ }
210
+ }
172
211
  })
173
212
  )
174
213
 
@@ -205,7 +244,13 @@ export class MapViewComponent implements AfterViewInit {
205
244
  }
206
245
  return of([])
207
246
  }),
208
- tap(() => this.selectedStyleIndex$.next(0)),
247
+ tap((styles) => {
248
+ if (this._styleFromConfig && this._styleFromConfig <= styles.length) {
249
+ this.selectedStyleId$.next(this._styleFromConfig)
250
+ } else {
251
+ this.selectedStyleId$.next(0)
252
+ }
253
+ }),
209
254
  shareReplay(1)
210
255
  )
211
256
 
@@ -228,7 +273,7 @@ export class MapViewComponent implements AfterViewInit {
228
273
  selectedLink$ = combineLatest([
229
274
  this.selectedSourceLink$,
230
275
  this.styleLinks$,
231
- this.selectedStyleIndex$.pipe(distinctUntilChanged()),
276
+ this.selectedStyleId$.pipe(distinctUntilChanged()),
232
277
  ]).pipe(
233
278
  map(([src, styles, styleIdx]) => (styles.length ? styles[styleIdx] : src)),
234
279
  shareReplay(1)
@@ -344,7 +389,9 @@ export class MapViewComponent implements AfterViewInit {
344
389
  ) {
345
390
  // FIXME: here we're assuming that the TMS serves vector tiles only; should be checked with ogc-client first
346
391
  return of({
347
- url: link.url.toString().replace(/\/?$/, '/{z}/{x}/{y}.pbf'),
392
+ url: link.url
393
+ .toString()
394
+ .replace(/\/?$/, `/${link.name}/{z}/{x}/{y}.pbf`),
348
395
  type: 'xyz',
349
396
  tileFormat: 'application/vnd.mapbox-vector-tile',
350
397
  name: link.name,