geonetwork-ui 2.6.0-dev.600519f47 → 2.6.0-dev.6e0b3d33d

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 (101) hide show
  1. package/esm2022/libs/api/metadata-converter/src/lib/gn4/gn4.field.mapper.mjs +4 -1
  2. package/esm2022/libs/api/repository/src/lib/gn4/gn4-repository.mjs +45 -15
  3. package/esm2022/libs/api/repository/src/lib/gn4/platform/gn4-platform.service.mjs +7 -1
  4. package/esm2022/libs/api/repository/src/lib/gn4/settings/gn4-settings.service.mjs +2 -1
  5. package/esm2022/libs/common/domain/src/lib/model/record/metadata.model.mjs +1 -1
  6. package/esm2022/libs/common/domain/src/lib/repository/records-repository.interface.mjs +1 -1
  7. package/esm2022/libs/feature/editor/src/lib/components/multilingual-panel/multilingual-panel.component.mjs +4 -3
  8. package/esm2022/libs/feature/search/src/lib/results-table/results-table-container.component.mjs +13 -10
  9. package/esm2022/libs/ui/elements/src/lib/internal-link-card/internal-link-card.component.mjs +19 -34
  10. package/esm2022/libs/ui/elements/src/lib/internal-link-card-contact/internal-link-card-contact.component.mjs +59 -0
  11. package/esm2022/libs/ui/elements/src/lib/record-feature-catalog/feature-catalog-list/feature-catalog-list.component.mjs +50 -29
  12. package/esm2022/libs/ui/elements/src/lib/ui-elements.module.mjs +7 -3
  13. package/esm2022/libs/ui/layout/src/index.mjs +2 -1
  14. package/esm2022/libs/ui/layout/src/lib/cell-popin/cell-popin.component.mjs +110 -0
  15. package/esm2022/libs/ui/layout/src/lib/interactive-table/interactive-table.component.mjs +20 -10
  16. package/esm2022/libs/ui/layout/src/lib/truncated-text/truncated-text.component.mjs +15 -49
  17. package/esm2022/libs/ui/layout/src/lib/ui-layout.module.mjs +2 -2
  18. package/esm2022/libs/ui/search/src/lib/results-table/action-menu/action-menu.component.mjs +5 -3
  19. package/esm2022/libs/ui/search/src/lib/results-table/results-table.component.mjs +16 -8
  20. package/esm2022/translations/de.json +15 -6
  21. package/esm2022/translations/en.json +15 -6
  22. package/esm2022/translations/es.json +14 -5
  23. package/esm2022/translations/fr.json +15 -6
  24. package/esm2022/translations/it.json +14 -5
  25. package/esm2022/translations/nl.json +14 -5
  26. package/esm2022/translations/pt.json +14 -5
  27. package/fesm2022/geonetwork-ui.mjs +867 -624
  28. package/fesm2022/geonetwork-ui.mjs.map +1 -1
  29. package/libs/api/metadata-converter/src/lib/gn4/gn4.field.mapper.d.ts.map +1 -1
  30. package/libs/api/repository/src/lib/gn4/gn4-repository.d.ts +8 -2
  31. package/libs/api/repository/src/lib/gn4/gn4-repository.d.ts.map +1 -1
  32. package/libs/api/repository/src/lib/gn4/platform/gn4-platform.service.d.ts +2 -0
  33. package/libs/api/repository/src/lib/gn4/platform/gn4-platform.service.d.ts.map +1 -1
  34. package/libs/api/repository/src/lib/gn4/settings/gn4-settings.service.d.ts +1 -0
  35. package/libs/api/repository/src/lib/gn4/settings/gn4-settings.service.d.ts.map +1 -1
  36. package/libs/common/domain/src/lib/model/record/metadata.model.d.ts +20 -17
  37. package/libs/common/domain/src/lib/model/record/metadata.model.d.ts.map +1 -1
  38. package/libs/common/domain/src/lib/repository/records-repository.interface.d.ts +3 -0
  39. package/libs/common/domain/src/lib/repository/records-repository.interface.d.ts.map +1 -1
  40. package/libs/feature/editor/src/lib/components/multilingual-panel/multilingual-panel.component.d.ts.map +1 -1
  41. package/libs/feature/search/src/lib/results-table/results-table-container.component.d.ts +6 -5
  42. package/libs/feature/search/src/lib/results-table/results-table-container.component.d.ts.map +1 -1
  43. package/libs/ui/elements/src/lib/internal-link-card/internal-link-card.component.d.ts +3 -6
  44. package/libs/ui/elements/src/lib/internal-link-card/internal-link-card.component.d.ts.map +1 -1
  45. package/libs/ui/elements/src/lib/internal-link-card-contact/internal-link-card-contact.component.d.ts +14 -0
  46. package/libs/ui/elements/src/lib/internal-link-card-contact/internal-link-card-contact.component.d.ts.map +1 -0
  47. package/libs/ui/elements/src/lib/record-feature-catalog/feature-catalog-list/feature-catalog-list.component.d.ts +20 -9
  48. package/libs/ui/elements/src/lib/record-feature-catalog/feature-catalog-list/feature-catalog-list.component.d.ts.map +1 -1
  49. package/libs/ui/elements/src/lib/ui-elements.module.d.ts +2 -1
  50. package/libs/ui/elements/src/lib/ui-elements.module.d.ts.map +1 -1
  51. package/libs/ui/layout/src/index.d.ts +1 -0
  52. package/libs/ui/layout/src/index.d.ts.map +1 -1
  53. package/libs/ui/layout/src/lib/cell-popin/cell-popin.component.d.ts +28 -0
  54. package/libs/ui/layout/src/lib/cell-popin/cell-popin.component.d.ts.map +1 -0
  55. package/libs/ui/layout/src/lib/interactive-table/interactive-table.component.d.ts +4 -2
  56. package/libs/ui/layout/src/lib/interactive-table/interactive-table.component.d.ts.map +1 -1
  57. package/libs/ui/layout/src/lib/truncated-text/truncated-text.component.d.ts +5 -10
  58. package/libs/ui/layout/src/lib/truncated-text/truncated-text.component.d.ts.map +1 -1
  59. package/libs/ui/search/src/lib/results-table/action-menu/action-menu.component.d.ts +2 -1
  60. package/libs/ui/search/src/lib/results-table/action-menu/action-menu.component.d.ts.map +1 -1
  61. package/libs/ui/search/src/lib/results-table/results-table.component.d.ts +5 -3
  62. package/libs/ui/search/src/lib/results-table/results-table.component.d.ts.map +1 -1
  63. package/package.json +1 -1
  64. package/src/libs/api/metadata-converter/src/lib/gn4/gn4.field.mapper.ts +7 -0
  65. package/src/libs/api/repository/src/lib/gn4/gn4-repository.ts +57 -14
  66. package/src/libs/api/repository/src/lib/gn4/platform/gn4-platform.service.ts +11 -0
  67. package/src/libs/api/repository/src/lib/gn4/settings/gn4-settings.service.ts +3 -0
  68. package/src/libs/common/domain/src/lib/model/record/metadata.model.ts +20 -14
  69. package/src/libs/common/domain/src/lib/repository/records-repository.interface.ts +3 -0
  70. package/src/libs/common/fixtures/src/lib/records.fixtures.ts +63 -0
  71. package/src/libs/feature/editor/src/lib/components/multilingual-panel/multilingual-panel.component.html +1 -1
  72. package/src/libs/feature/editor/src/lib/components/multilingual-panel/multilingual-panel.component.ts +1 -0
  73. package/src/libs/feature/search/src/lib/results-table/results-table-container.component.html +1 -0
  74. package/src/libs/feature/search/src/lib/results-table/results-table-container.component.ts +13 -3
  75. package/src/libs/ui/elements/src/lib/internal-link-card/internal-link-card.component.html +7 -75
  76. package/src/libs/ui/elements/src/lib/internal-link-card/internal-link-card.component.ts +20 -51
  77. package/src/libs/ui/elements/src/lib/internal-link-card-contact/internal-link-card-contact.component.html +69 -0
  78. package/src/libs/ui/elements/src/lib/internal-link-card-contact/internal-link-card-contact.component.ts +61 -0
  79. package/src/libs/ui/elements/src/lib/record-feature-catalog/feature-catalog-list/feature-catalog-list.component.html +96 -37
  80. package/src/libs/ui/elements/src/lib/record-feature-catalog/feature-catalog-list/feature-catalog-list.component.ts +60 -29
  81. package/src/libs/ui/elements/src/lib/ui-elements.module.ts +2 -0
  82. package/src/libs/ui/layout/src/index.ts +1 -0
  83. package/src/libs/ui/layout/src/lib/cell-popin/cell-popin.component.html +40 -0
  84. package/src/libs/ui/layout/src/lib/cell-popin/cell-popin.component.ts +141 -0
  85. package/src/libs/ui/layout/src/lib/interactive-table/interactive-table.component.html +2 -2
  86. package/src/libs/ui/layout/src/lib/interactive-table/interactive-table.component.ts +13 -6
  87. package/src/libs/ui/layout/src/lib/truncated-text/truncated-text.component.html +25 -42
  88. package/src/libs/ui/layout/src/lib/truncated-text/truncated-text.component.ts +10 -49
  89. package/src/libs/ui/layout/src/lib/ui-layout.module.ts +1 -1
  90. package/src/libs/ui/search/src/lib/results-table/action-menu/action-menu.component.html +6 -4
  91. package/src/libs/ui/search/src/lib/results-table/action-menu/action-menu.component.ts +1 -0
  92. package/src/libs/ui/search/src/lib/results-table/results-table.component.html +14 -20
  93. package/src/libs/ui/search/src/lib/results-table/results-table.component.ts +13 -5
  94. package/translations/de.json +15 -6
  95. package/translations/en.json +15 -6
  96. package/translations/es.json +14 -5
  97. package/translations/fr.json +15 -6
  98. package/translations/it.json +14 -5
  99. package/translations/nl.json +14 -5
  100. package/translations/pt.json +14 -5
  101. package/translations/sk.json +14 -5
@@ -4,6 +4,7 @@ import { SortByField } from '../../../../../../libs/common/domain/src/lib/model/
4
4
  import { DateService, FileFormat } from '../../../../../../libs/util/shared/src';
5
5
  import { TranslateService } from '@ngx-translate/core';
6
6
  import { Overlay } from '@angular/cdk/overlay';
7
+ import { Observable } from 'rxjs';
7
8
  import * as i0 from "@angular/core";
8
9
  export declare class ResultsTableComponent {
9
10
  private overlay;
@@ -16,7 +17,8 @@ export declare class ResultsTableComponent {
16
17
  sortOrder: SortByField;
17
18
  hasDraft: (record: CatalogRecord) => boolean;
18
19
  canDuplicate: (record: CatalogRecord) => boolean;
19
- canDelete: (record: CatalogRecord) => boolean;
20
+ canDelete: (record: CatalogRecord) => Observable<boolean>;
21
+ canEdit: (record: CatalogRecord) => Observable<boolean>;
20
22
  isDraftPage: boolean;
21
23
  isDuplicating: boolean;
22
24
  sortByChange: EventEmitter<[string, "desc" | "asc"]>;
@@ -35,7 +37,7 @@ export declare class ResultsTableComponent {
35
37
  getRecordFormats(record: CatalogRecord): FileFormat[];
36
38
  formatUserInfo(userInfo: string | unknown): string;
37
39
  getBadgeColor(format: FileFormat): string;
38
- handleRecordClick(item: CatalogRecord): void;
40
+ handleRecordClick(item: unknown): void;
39
41
  handleDuplicate(item: unknown): void;
40
42
  handleDelete(item: unknown): void;
41
43
  handleRollback(item: unknown): void;
@@ -46,6 +48,6 @@ export declare class ResultsTableComponent {
46
48
  isMultilingual(record: CatalogRecord): boolean;
47
49
  getTxtHoverMultilingual(record: CatalogRecord): any;
48
50
  static ɵfac: i0.ɵɵFactoryDeclaration<ResultsTableComponent, never>;
49
- static ɵcmp: i0.ɵɵComponentDeclaration<ResultsTableComponent, "gn-ui-results-table", never, { "records": { "alias": "records"; "required": false; }; "selectedRecordsIdentifiers": { "alias": "selectedRecordsIdentifiers"; "required": false; }; "sortOrder": { "alias": "sortOrder"; "required": false; }; "hasDraft": { "alias": "hasDraft"; "required": false; }; "canDuplicate": { "alias": "canDuplicate"; "required": false; }; "canDelete": { "alias": "canDelete"; "required": false; }; "isDraftPage": { "alias": "isDraftPage"; "required": false; }; "isDuplicating": { "alias": "isDuplicating"; "required": false; }; }, { "sortByChange": "sortByChange"; "recordClick": "recordClick"; "duplicateRecord": "duplicateRecord"; "deleteRecord": "deleteRecord"; "rollbackDraft": "rollbackDraft"; "recordsSelectedChange": "recordsSelectedChange"; }, never, never, true, never>;
51
+ static ɵcmp: i0.ɵɵComponentDeclaration<ResultsTableComponent, "gn-ui-results-table", never, { "records": { "alias": "records"; "required": false; }; "selectedRecordsIdentifiers": { "alias": "selectedRecordsIdentifiers"; "required": false; }; "sortOrder": { "alias": "sortOrder"; "required": false; }; "hasDraft": { "alias": "hasDraft"; "required": false; }; "canDuplicate": { "alias": "canDuplicate"; "required": false; }; "canDelete": { "alias": "canDelete"; "required": false; }; "canEdit": { "alias": "canEdit"; "required": false; }; "isDraftPage": { "alias": "isDraftPage"; "required": false; }; "isDuplicating": { "alias": "isDuplicating"; "required": false; }; }, { "sortByChange": "sortByChange"; "recordClick": "recordClick"; "duplicateRecord": "duplicateRecord"; "deleteRecord": "deleteRecord"; "rollbackDraft": "rollbackDraft"; "recordsSelectedChange": "recordsSelectedChange"; }, never, never, true, never>;
50
52
  }
51
53
  //# sourceMappingURL=results-table.component.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"results-table.component.d.ts","sourceRoot":"","sources":["../../../../../../src/libs/ui/search/src/lib/results-table/results-table.component.ts"],"names":[],"mappings":"AACA,OAAO,EACL,iBAAiB,EAEjB,UAAU,EACV,YAAY,EAGZ,SAAS,EAET,gBAAgB,EACjB,MAAM,eAAe,CAAA;AACtB,OAAO,EAAE,aAAa,EAAE,MAAM,2DAA2D,CAAA;AACzF,OAAO,EAEL,WAAW,EACZ,MAAM,2DAA2D,CAAA;AAMlE,OAAO,EACL,WAAW,EACX,UAAU,EAKX,MAAM,wCAAwC,CAAA;AAC/C,OAAO,EAAmB,gBAAgB,EAAE,MAAM,qBAAqB,CAAA;AAIvE,OAAO,EAAoB,OAAO,EAAc,MAAM,sBAAsB,CAAA;;AAI5E,qBAoBa,qBAAqB;IA2B9B,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,gBAAgB;IACxB,OAAO,CAAC,GAAG;IACX,OAAO,CAAC,WAAW;IACnB,OAAO,CAAC,gBAAgB;IA9BjB,OAAO,EAAE,aAAa,EAAE,CAAK;IAC7B,0BAA0B,EAAE,MAAM,EAAE,CAAK;IACzC,SAAS,EAAE,WAAW,CAAO;IAC7B,QAAQ,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,OAAO,CAAc;IAC1D,YAAY,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,OAAO,CAAa;IAC7D,SAAS,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,OAAO,CAAa;IAC1D,WAAW,UAAQ;IACnB,aAAa,UAAQ;IAGpB,YAAY,yCAA+C;IAC3D,WAAW,8BAAoC;IAC/C,eAAe,8BAAoC;IACnD,YAAY,8BAAoC;IAChD,aAAa,8BAAoC;IACjD,qBAAqB,2CAE5B;IAGH,iBAAiB,EAAG,SAAS,CAAC,UAAU,CAAC,CAAA;IACzC,OAAO,CAAC,UAAU,CAAa;IAE/B,gBAAgB,UAAQ;gBAGd,OAAO,EAAE,OAAO,EAChB,gBAAgB,EAAE,gBAAgB,EAClC,GAAG,EAAE,iBAAiB,EACtB,WAAW,EAAE,WAAW,EACxB,gBAAgB,EAAE,gBAAgB;IAG5C,cAAc,CAAC,IAAI,KAAA,EAAE,QAAQ,KAAA;IAyC7B,eAAe;IAQf,YAAY,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM;IAShC,gBAAgB,CAAC,MAAM,EAAE,aAAa,GAAG,UAAU,EAAE;IAerD,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM;IAIlD,aAAa,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM;IAIzC,iBAAiB,CAAC,IAAI,EAAE,aAAa;IAMrC,eAAe,CAAC,IAAI,EAAE,OAAO;IAI7B,YAAY,CAAC,IAAI,EAAE,OAAO;IAK1B,cAAc,CAAC,IAAI,EAAE,OAAO;IAK5B,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,GAAG,MAAM;IAI5C,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,KAAK,GAAG,IAAI;IAe9C,SAAS,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO;IAIzC,0BAA0B,CAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,aAAa;IAInE,cAAc,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO;IAI9C,uBAAuB,CAAC,MAAM,EAAE,aAAa;yCAtKlC,qBAAqB;2CAArB,qBAAqB;CA6KjC"}
1
+ {"version":3,"file":"results-table.component.d.ts","sourceRoot":"","sources":["../../../../../../src/libs/ui/search/src/lib/results-table/results-table.component.ts"],"names":[],"mappings":"AACA,OAAO,EACL,iBAAiB,EAEjB,UAAU,EACV,YAAY,EAGZ,SAAS,EAET,gBAAgB,EACjB,MAAM,eAAe,CAAA;AACtB,OAAO,EAAE,aAAa,EAAE,MAAM,2DAA2D,CAAA;AACzF,OAAO,EAEL,WAAW,EACZ,MAAM,2DAA2D,CAAA;AAMlE,OAAO,EACL,WAAW,EACX,UAAU,EAKX,MAAM,wCAAwC,CAAA;AAC/C,OAAO,EAAmB,gBAAgB,EAAE,MAAM,qBAAqB,CAAA;AAIvE,OAAO,EAAoB,OAAO,EAAc,MAAM,sBAAsB,CAAA;AAG5E,OAAO,EAAE,UAAU,EAAY,MAAM,MAAM,CAAA;;AAE3C,qBAoBa,qBAAqB;IA8B9B,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,gBAAgB;IACxB,OAAO,CAAC,GAAG;IACX,OAAO,CAAC,WAAW;IACnB,OAAO,CAAC,gBAAgB;IAjCjB,OAAO,EAAE,aAAa,EAAE,CAAK;IAC7B,0BAA0B,EAAE,MAAM,EAAE,CAAK;IACzC,SAAS,EAAE,WAAW,CAAO;IAC7B,QAAQ,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,OAAO,CAAc;IAC1D,YAAY,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,OAAO,CAAa;IAC7D,SAAS,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,UAAU,CAAC,OAAO,CAAC,CACxD;IACD,OAAO,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,UAAU,CAAC,OAAO,CAAC,CACtD;IACD,WAAW,UAAQ;IACnB,aAAa,UAAQ;IAGpB,YAAY,yCAA+C;IAC3D,WAAW,8BAAoC;IAC/C,eAAe,8BAAoC;IACnD,YAAY,8BAAoC;IAChD,aAAa,8BAAoC;IACjD,qBAAqB,2CAE5B;IAGH,iBAAiB,EAAG,SAAS,CAAC,UAAU,CAAC,CAAA;IACzC,OAAO,CAAC,UAAU,CAAa;IAE/B,gBAAgB,UAAQ;gBAGd,OAAO,EAAE,OAAO,EAChB,gBAAgB,EAAE,gBAAgB,EAClC,GAAG,EAAE,iBAAiB,EACtB,WAAW,EAAE,WAAW,EACxB,gBAAgB,EAAE,gBAAgB;IAG5C,cAAc,CAAC,IAAI,KAAA,EAAE,QAAQ,KAAA;IAyC7B,eAAe;IAQf,YAAY,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM;IAShC,gBAAgB,CAAC,MAAM,EAAE,aAAa,GAAG,UAAU,EAAE;IAerD,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM;IAIlD,aAAa,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM;IAIzC,iBAAiB,CAAC,IAAI,EAAE,OAAO;IAU/B,eAAe,CAAC,IAAI,EAAE,OAAO;IAI7B,YAAY,CAAC,IAAI,EAAE,OAAO;IAK1B,cAAc,CAAC,IAAI,EAAE,OAAO;IAK5B,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,GAAG,MAAM;IAI5C,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,KAAK,GAAG,IAAI;IAe9C,SAAS,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO;IAIzC,0BAA0B,CAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,aAAa;IAInE,cAAc,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO;IAI9C,uBAAuB,CAAC,MAAM,EAAE,aAAa;yCA7KlC,qBAAqB;2CAArB,qBAAqB;CAoLjC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "geonetwork-ui",
3
- "version": "2.6.0-dev.600519f47",
3
+ "version": "2.6.0-dev.6e0b3d33d",
4
4
  "engines": {
5
5
  "node": ">=20"
6
6
  },
@@ -359,6 +359,13 @@ export class Gn4FieldMapper {
359
359
  },
360
360
  output
361
361
  ),
362
+ isHarvested: (output, source) =>
363
+ this.addExtra(
364
+ {
365
+ isHarvested: selectField(source, 'isHarvested') !== 'false',
366
+ },
367
+ output
368
+ ),
362
369
  edit: (output, source) =>
363
370
  this.addExtra(
364
371
  {
@@ -14,8 +14,8 @@ import {
14
14
  import { PublicationVersionError } from '../../../../../../libs/common/domain/src/lib/model/error'
15
15
  import {
16
16
  CatalogRecord,
17
- DatasetFeatureType,
18
17
  DatasetFeatureCatalog,
18
+ DatasetFeatureType,
19
19
  } from '../../../../../../libs/common/domain/src/lib/model/record'
20
20
  import {
21
21
  Aggregations,
@@ -29,10 +29,11 @@ import {
29
29
  import { PlatformServiceInterface } from '../../../../../../libs/common/domain/src/lib/platform.service.interface'
30
30
  import { RecordsRepositoryInterface } from '../../../../../../libs/common/domain/src/lib/repository/records-repository.interface'
31
31
  import {
32
+ LanguagesApiService,
32
33
  RecordsApiService,
33
34
  SearchApiService,
34
- LanguagesApiService,
35
35
  } from '../../../../../../libs/data-access/gn4/src'
36
+ import { LANG_3_TO_2_MAPPER } from '../../../../../../libs/util/i18n/src'
36
37
  import {
37
38
  combineLatest,
38
39
  exhaustMap,
@@ -47,7 +48,7 @@ import {
47
48
  import { catchError, map, tap } from 'rxjs/operators'
48
49
  import { lt } from 'semver'
49
50
  import { ElasticsearchService } from './elasticsearch'
50
- import { LANG_3_TO_2_MAPPER } from '../../../../../../libs/util/i18n/src'
51
+ import { Gn4SettingsService } from './settings/gn4-settings.service'
51
52
 
52
53
  const minPublicationApiVersion = '4.2.5'
53
54
 
@@ -67,7 +68,8 @@ export class Gn4Repository implements RecordsRepositoryInterface {
67
68
  private gn4Mapper: Gn4Converter,
68
69
  private gn4RecordsApi: RecordsApiService,
69
70
  private platformService: PlatformServiceInterface,
70
- private gn4LanguagesApi: LanguagesApiService
71
+ private gn4LanguagesApi: LanguagesApiService,
72
+ private settingsService: Gn4SettingsService
71
73
  ) {}
72
74
 
73
75
  search({
@@ -173,12 +175,21 @@ export class Gn4Repository implements RecordsRepositoryInterface {
173
175
  name: featureType.typeName || '',
174
176
  definition: featureType.definition || '',
175
177
  attributes: Array.isArray(featureType.attributeTable)
176
- ? featureType.attributeTable.map((attr) => ({
177
- name: attr.name,
178
- code: attr.code,
179
- title: attr.definition,
180
- type: attr.type,
181
- }))
178
+ ? featureType.attributeTable.map((attr) => {
179
+ const values = attr.values
180
+ ?.filter((v) => v.code || v.label)
181
+ .map((v) => ({
182
+ code: v.code,
183
+ label: v.label,
184
+ }))
185
+ return {
186
+ name: attr.name,
187
+ code: attr.code,
188
+ definition: attr.definition,
189
+ type: attr.type,
190
+ ...(values?.length > 0 ? { values } : {}),
191
+ }
192
+ })
182
193
  : [],
183
194
  })),
184
195
  }
@@ -296,14 +307,46 @@ export class Gn4Repository implements RecordsRepositoryInterface {
296
307
  : of(true)
297
308
  }
298
309
 
299
- canEditRecord(uniqueIdentifier: string): Observable<boolean> {
300
- return this.getRecord(uniqueIdentifier).pipe(
301
- map((record) => {
302
- return record.extras['edit'] as boolean
310
+ canDuplicate(record: CatalogRecord): boolean {
311
+ return record.kind === 'dataset'
312
+ }
313
+
314
+ canDelete(record: CatalogRecord): Observable<boolean> {
315
+ return this.settingsService.allowEditHarvested$.pipe(
316
+ map((allowEditHarvested) => {
317
+ return (
318
+ record.extras['edit'] &&
319
+ (!record.extras['isHarvested'] || allowEditHarvested)
320
+ )
303
321
  })
304
322
  )
305
323
  }
306
324
 
325
+ private canEdit(record: CatalogRecord, allowEditHarvested: boolean): boolean {
326
+ return (
327
+ record.kind === 'dataset' &&
328
+ record.extras['edit'] &&
329
+ (!record.extras['isHarvested'] || allowEditHarvested)
330
+ )
331
+ }
332
+
333
+ canEditRecord(uniqueIdentifier: string): Observable<boolean> {
334
+ return combineLatest([
335
+ this.getRecord(uniqueIdentifier),
336
+ this.settingsService.allowEditHarvested$,
337
+ ]).pipe(
338
+ map(([record, allowEditHarvested]) =>
339
+ record ? this.canEdit(record, allowEditHarvested) : false
340
+ )
341
+ )
342
+ }
343
+
344
+ canEditIndexedRecord(record: CatalogRecord): Observable<boolean> {
345
+ return this.settingsService.allowEditHarvested$.pipe(
346
+ map((allowEditHarvested) => this.canEdit(record, allowEditHarvested))
347
+ )
348
+ }
349
+
307
350
  openRecordForEdition(
308
351
  uniqueIdentifier: string
309
352
  ): Observable<[CatalogRecord, string, boolean] | null> {
@@ -82,6 +82,13 @@ export class Gn4PlatformService implements PlatformServiceInterface {
82
82
  shareReplay(1)
83
83
  )
84
84
 
85
+ private readonly allowEditHarvestedMd$ = this.settings$.pipe(
86
+ map((info) => {
87
+ return info['system/harvester/enableEditing'] as boolean
88
+ }),
89
+ shareReplay(1)
90
+ )
91
+
85
92
  /**
86
93
  * A map of already loaded thesauri (groups of keywords); the key is a URI
87
94
  * @private
@@ -123,6 +130,10 @@ export class Gn4PlatformService implements PlatformServiceInterface {
123
130
  return this.apiVersion$
124
131
  }
125
132
 
133
+ getAllowEditHarvestedMd(): Observable<boolean> {
134
+ return this.allowEditHarvestedMd$
135
+ }
136
+
126
137
  getMe(): Observable<UserModel> {
127
138
  return this.me$
128
139
  }
@@ -11,6 +11,9 @@ export class Gn4SettingsService {
11
11
  'system/users/identicon'
12
12
  )
13
13
 
14
+ public allowEditHarvested$: Observable<boolean> =
15
+ this.getSettingsSetValueByKey('system/harvester/enableEditing')
16
+
14
17
  constructor(private siteApiService: SiteApiService) {}
15
18
 
16
19
  private getSettingsSetValueByKey(key: string) {
@@ -233,14 +233,6 @@ export interface DatasetRecord extends BaseRecord {
233
233
  spatialRepresentation?: SpatialRepresentationType
234
234
  }
235
235
 
236
- export type DatasetFeatureCatalog = {
237
- featureTypes: Array<{
238
- name: string
239
- definition: string
240
- attributes: Array<{ name: string; title: string; code: string }>
241
- }>
242
- }
243
-
244
236
  export interface ServiceEndpoint {
245
237
  url: URL
246
238
  accessServiceProtocol: ServiceProtocol
@@ -268,18 +260,32 @@ export interface ReuseRecord extends BaseRecord {
268
260
  temporalExtents: Array<DatasetTemporalExtent>
269
261
  }
270
262
 
263
+ export type DatasetFeatureCatalog = {
264
+ featureTypes: Array<{
265
+ name: string
266
+ definition: string
267
+ attributes: DatasetFeatureAttribute[]
268
+ }>
269
+ }
270
+ export interface DatasetFeatureAttributeValue {
271
+ code?: string
272
+ definition?: string
273
+ label?: string
274
+ }
275
+ export interface DatasetFeatureAttribute {
276
+ name: string
277
+ definition: string
278
+ type: string
279
+ code: string
280
+ values?: Array<DatasetFeatureAttributeValue>
281
+ }
271
282
  export interface DatasetFeatureType {
272
283
  aliases: string
273
284
  code: string
274
285
  isAbstract: string
275
286
  typeName: string
276
287
  definition: string
277
- attributeTable: Array<{
278
- name: string
279
- definition: string
280
- type: string
281
- code: string
282
- }>
288
+ attributeTable: Array<DatasetFeatureAttribute>
283
289
  }
284
290
 
285
291
  export type ReuseType = 'application' | 'map' | 'other'
@@ -22,7 +22,10 @@ export abstract class RecordsRepositoryInterface {
22
22
  abstract getSources(record: CatalogRecord): Observable<CatalogRecord[]>
23
23
  abstract getSourceOf(record: CatalogRecord): Observable<CatalogRecord[]>
24
24
  abstract fuzzySearch(query: string): Observable<SearchResults>
25
+ abstract canDuplicate(record: CatalogRecord): boolean
26
+ abstract canDelete(record: CatalogRecord): Observable<boolean>
25
27
  abstract canEditRecord(uniqueIdentifier: string): Observable<boolean>
28
+ abstract canEditIndexedRecord(record: CatalogRecord): Observable<boolean>
26
29
  /**
27
30
  * This emits once:
28
31
  * - record object; if a draft exists, this will return it
@@ -3,6 +3,7 @@ import {
3
3
  DatasetRecord,
4
4
  DatasetSpatialExtent,
5
5
  Keyword,
6
+ ServiceRecord,
6
7
  } from '../../../../../libs/common/domain/src/lib/model/record'
7
8
 
8
9
  export const datasetRecordsFixture: () => CatalogRecord[] = () => [
@@ -176,6 +177,20 @@ As such, **it is not very interesting at all.**`,
176
177
  link: '',
177
178
  definition: 'Nom de la rue',
178
179
  type: 'String (48)',
180
+ values: [
181
+ {
182
+ code: 'Pomme',
183
+ label: 'Les Pommiers',
184
+ description: 'Sous les pommiers',
185
+ },
186
+ {
187
+ code: 'Cotton',
188
+ label: 'Rue Cotton',
189
+ description: 'Rue Cotton',
190
+ },
191
+ { code: "Passage de l'échiquier" },
192
+ { description: 'Rue du Charlieu' },
193
+ ],
179
194
  },
180
195
  {
181
196
  code: 'RUE',
@@ -811,6 +826,54 @@ export const importDatasetRecordAsXmlFixture = (): string => `
811
826
  </gmd:identificationInfo>
812
827
  </gmd:MD_Metadata>`
813
828
 
829
+ export const simpleServiceRecordFixture = (): ServiceRecord => ({
830
+ kind: 'service',
831
+ status: null,
832
+ lineage: null,
833
+ recordUpdated: new Date('2023-03-17T07:38:08.875Z'),
834
+ recordPublished: null,
835
+ ownerOrganization: null,
836
+ licenses: [],
837
+ legalConstraints: [],
838
+ securityConstraints: [],
839
+ otherConstraints: [],
840
+ contacts: [],
841
+ contactsForResource: [],
842
+ keywords: [],
843
+ topics: [],
844
+ spatialExtents: [],
845
+ temporalExtents: [],
846
+ overviews: [],
847
+ defaultLanguage: null,
848
+ otherLanguages: [],
849
+ title: 'Sites de gestion des déchets miniers - Service de visualisation WMS',
850
+ onlineResources: [
851
+ {
852
+ name: 'Service de visualisation WMS',
853
+ description:
854
+ 'Adresse de connexion au service de visualisation WMS de la série de couches de données "Sites de gestion des déchets miniers"',
855
+ type: 'service',
856
+ url: new URL(
857
+ 'https://geoservices.wallonie.be/arcgis/services/SOL_SOUS_SOL/DECHETS_MINIERS/MapServer/WMSServer?request=GetCapabilities&service=WMS'
858
+ ),
859
+ accessServiceProtocol: 'wms',
860
+ accessRestricted: false,
861
+ },
862
+ ],
863
+ uniqueIdentifier: '00b22798-ec8e-4500-89e8-90eeeda45919',
864
+ landingPage: new URL(
865
+ 'http://localhost:4200/geonetwork/srv/fre/catalog.search#/metadata/00b22798-ec8e-4500-89e8-90eeeda45919'
866
+ ),
867
+ extras: {
868
+ isPublishedToAll: true,
869
+ id: '723',
870
+ isHarvested: true,
871
+ ownerInfo: 'admin|admin|admin|Administrator',
872
+ edit: true,
873
+ },
874
+ recordCreated: new Date('2023-03-17T07:38:08.875Z'),
875
+ })
876
+
814
877
  export const NATIONAL_KEYWORD = {
815
878
  key: 'http://inspire.ec.europa.eu/metadata-codelist/SpatialScope/national',
816
879
  label: 'National',
@@ -110,7 +110,7 @@
110
110
  page="record"
111
111
  (delete)="confirmDeleteAction(recordLang)"
112
112
  (closeActionMenu)="closeActionMenu()"
113
- (switch)="switchDefaultLang(item)"
113
+ (switch)="switchDefaultLang(recordLang)"
114
114
  >
115
115
  </gn-ui-action-menu>
116
116
  </ng-template>
@@ -208,6 +208,7 @@ export class MultilingualPanelComponent implements OnDestroy {
208
208
  'otherLanguages',
209
209
  this.selectedLanguages.filter((lang) => lang !== this.formLanguage)
210
210
  )
211
+ this.closeActionMenu()
211
212
  }
212
213
 
213
214
  confirmDeleteAction(lang?: string[] | string) {
@@ -7,6 +7,7 @@
7
7
  [canDelete]="canDelete"
8
8
  [canDuplicate]="canDuplicate"
9
9
  [isDuplicating]="isDuplicating"
10
+ [canEdit]="canEdit"
10
11
  (recordClick)="handleRecordClick($event)"
11
12
  (duplicateRecord)="handleDuplicateRecord($event)"
12
13
  (deleteRecord)="handleDeleteRecord($event)"
@@ -12,7 +12,7 @@ import { SearchService } from '../utils/service/search.service'
12
12
  import { RecordsRepositoryInterface } from '../../../../../../libs/common/domain/src/lib/repository/records-repository.interface'
13
13
  import { ResultsTableComponent } from '../../../../../../libs/ui/search/src'
14
14
  import { CommonModule } from '@angular/common'
15
- import { Subscription } from 'rxjs'
15
+ import { Observable, Subscription } from 'rxjs'
16
16
  import { NotificationsService } from '../../../../../../libs/feature/notifications/src'
17
17
  import { TranslateService } from '@ngx-translate/core'
18
18
 
@@ -24,8 +24,6 @@ import { TranslateService } from '@ngx-translate/core'
24
24
  imports: [CommonModule, ResultsTableComponent],
25
25
  })
26
26
  export class ResultsTableContainerComponent implements OnDestroy {
27
- @Input() canDuplicate: (record: CatalogRecord) => boolean = () => true
28
- @Input() canDelete: (record: CatalogRecord) => boolean = () => true
29
27
  @Input() isDuplicating: false
30
28
 
31
29
  @Output() recordClick = new EventEmitter<CatalogRecord>()
@@ -39,6 +37,18 @@ export class ResultsTableContainerComponent implements OnDestroy {
39
37
  hasDraft = (record: CatalogRecord): boolean =>
40
38
  this.recordsRepository.recordHasDraft(record.uniqueIdentifier)
41
39
 
40
+ canDuplicate = (record: CatalogRecord): boolean => {
41
+ return this.recordsRepository.canDuplicate(record)
42
+ }
43
+
44
+ canDelete = (record: CatalogRecord): Observable<boolean> => {
45
+ return this.recordsRepository.canDelete(record)
46
+ }
47
+
48
+ canEdit = (record: CatalogRecord): Observable<boolean> => {
49
+ return this.recordsRepository.canEditIndexedRecord(record)
50
+ }
51
+
42
52
  constructor(
43
53
  protected searchFacade: SearchFacade,
44
54
  private searchService: SearchService,
@@ -60,8 +60,9 @@
60
60
  </h4>
61
61
  </div>
62
62
  <div
63
- *ngIf="size === 'L'"
64
- class="mr-6 text-xs text-gray-900 line-clamp-2 overflow-hidden"
63
+ *ngIf="displayAbstract()"
64
+ class="mr-6 text-xs text-gray-900 overflow-hidden"
65
+ [ngClass]="getAbstractClass()"
65
66
  data-cy="recordAbstract"
66
67
  >
67
68
  <gn-ui-markdown-parser
@@ -71,80 +72,11 @@
71
72
  </div>
72
73
  </div>
73
74
 
74
- <div
75
- data-cy="recordOrg"
75
+ <gn-ui-internal-link-card-contact
76
76
  *ngIf="size !== 'XS' && record.ownerOrganization?.name"
77
- class="flex items-center justify-evenly bg-gray-50 rounded-lg h-[53px] px-2"
78
- >
79
- <div class="flex items-center flex-1 min-w-0">
80
- <div
81
- class="w-[45px] h-[45px] rounded-lg overflow-hidden shrink-0 mr-3"
82
- >
83
- <gn-ui-thumbnail
84
- [thumbnailUrl]="
85
- record.ownerOrganization?.logoUrl?.toString() || ''
86
- "
87
- [fit]="'contain'"
88
- class="w-full h-full rounded-lg"
89
- ></gn-ui-thumbnail>
90
- </div>
91
- <div *ngIf="organization?.name" class="flex-1 w-0 overflow-hidden">
92
- <div
93
- class="text-xs text-black font-normal leading-tight truncate"
94
- translate
95
- >
96
- record.card.metadata.contact
97
- </div>
98
- <div
99
- data-cy="recordOrgName"
100
- class="text-xl text-primary-black font-medium truncate"
101
- >
102
- {{ organization.name }}
103
- </div>
104
- </div>
105
- </div>
106
- <div *ngIf="size === 'L'" class="ml-2 flex space-x-2">
107
- <div *ngIf="organization?.website" class="flex">
108
- <button
109
- [title]="organization.website"
110
- class="w-[40px] h-[32px] flex items-center justify-center rounded-lg border border-[#D4D3D7] px-[8px] py-[4px] hover:bg-primary-lightest"
111
- (click)="openExternalUrl($event, organization.website)"
112
- >
113
- <ng-icon name="iconoirInternet"></ng-icon>
114
- </button>
115
- </div>
116
- <div *ngIf="contacts[0]?.email" class="flex">
117
- <button
118
- [title]="contacts[0].email"
119
- class="w-[40px] h-[32px] flex items-center justify-center rounded-lg border border-[#D4D3D7] px-[8px] py-[4px] hover:bg-primary-lightest"
120
- data-cy="contact-email"
121
- (click)="openMailto($event, contacts[0].email)"
122
- >
123
- <ng-icon name="matEmailOutline"></ng-icon>
124
- </button>
125
- </div>
126
- <div *ngIf="contacts[0]?.phone" class="flex">
127
- <button
128
- [title]="'Copy to clipboard'"
129
- class="w-[40px] h-[32px] flex items-center justify-center rounded-lg border border-[#D4D3D7] px-[8px] py-[4px] hover:bg-primary-lightest relative group"
130
- data-cy="contact-phone"
131
- (click)="copyToClipboard($event, contacts[0].phone)"
132
- >
133
- <ng-icon name="matPhoneOutline"></ng-icon>
134
- </button>
135
- </div>
136
- <div *ngIf="contacts[0]?.address" class="flex">
137
- <button
138
- [title]="'Copy to clipboard'"
139
- class="w-[40px] h-[32px] flex items-center justify-center rounded-lg border border-[#D4D3D7] px-[8px] py-[4px] hover:bg-primary-lightest relative group"
140
- data-cy="contact-phone"
141
- (click)="copyToClipboard($event, contacts[0].address)"
142
- >
143
- <ng-icon name="matLocationOnOutline"></ng-icon>
144
- </button>
145
- </div>
146
- </div>
147
- </div>
77
+ [record]="record"
78
+ [size]="size"
79
+ ></gn-ui-internal-link-card-contact>
148
80
  </div>
149
81
  </div>
150
82
  </div>
@@ -7,35 +7,20 @@ import {
7
7
  EventEmitter,
8
8
  ElementRef,
9
9
  } from '@angular/core'
10
- import {
11
- CatalogRecord,
12
- Organization,
13
- } from '../../../../../../libs/common/domain/src/lib/model/record'
10
+ import { CatalogRecord } from '../../../../../../libs/common/domain/src/lib/model/record'
14
11
  import { NgClass, NgIf, NgTemplateOutlet } from '@angular/common'
15
12
  import { GeoDataBadgeComponent } from '../geo-data-badge/geo-data-badge.component'
16
13
  import { KindBadgeComponent } from '../kind-badge/kind-badge.component'
17
14
  import { MarkdownParserComponent } from '../markdown-parser/markdown-parser.component'
18
15
  import { MetadataQualityComponent } from '../metadata-quality/metadata-quality.component'
19
- import { ThumbnailComponent } from '../thumbnail/thumbnail.component'
20
- import {
21
- propagateToDocumentOnly,
22
- removeWhitespace,
23
- stripHtml,
24
- } from '../../../../../../libs/util/shared/src'
25
- import {
26
- NgIconComponent,
27
- provideIcons,
28
- provideNgIconsConfig,
29
- } from '@ng-icons/core'
30
- import {
31
- matLocationSearchingOutline,
32
- matEmailOutline,
33
- matPhoneOutline,
34
- matLocationOnOutline,
35
- } from '@ng-icons/material-icons/outline'
16
+ import { InternalLinkCardContactComponent } from '../internal-link-card-contact/internal-link-card-contact.component'
17
+ import { removeWhitespace, stripHtml } from '../../../../../../libs/util/shared/src'
18
+ import { provideIcons, provideNgIconsConfig } from '@ng-icons/core'
19
+ import { matLocationSearchingOutline } from '@ng-icons/material-icons/outline'
36
20
  import { iconoirInternet } from '@ng-icons/iconoir'
37
21
  import { TranslateModule } from '@ngx-translate/core'
38
22
  import { fromEvent, Subscription } from 'rxjs'
23
+ import { ThumbnailComponent } from '../thumbnail/thumbnail.component'
39
24
 
40
25
  type CardSize = 'L' | 'M' | 'S' | 'XS'
41
26
 
@@ -45,22 +30,19 @@ type CardSize = 'L' | 'M' | 'S' | 'XS'
45
30
  imports: [
46
31
  NgClass,
47
32
  NgIf,
48
- ThumbnailComponent,
49
33
  MetadataQualityComponent,
50
34
  NgTemplateOutlet,
51
- NgIconComponent,
52
35
  TranslateModule,
53
36
  GeoDataBadgeComponent,
54
37
  KindBadgeComponent,
55
38
  MarkdownParserComponent,
39
+ InternalLinkCardContactComponent,
40
+ ThumbnailComponent,
56
41
  ],
57
42
  providers: [
58
43
  provideIcons({
59
44
  iconoirInternet,
60
45
  matLocationSearchingOutline,
61
- matEmailOutline,
62
- matPhoneOutline,
63
- matLocationOnOutline,
64
46
  }),
65
47
  provideNgIconsConfig({
66
48
  size: '1.2em',
@@ -125,35 +107,22 @@ export class InternalLinkCardComponent implements OnInit {
125
107
  )
126
108
  }
127
109
 
128
- get organization(): Organization {
129
- return this.record.ownerOrganization
130
- }
131
-
132
- get contacts() {
133
- return (
134
- (this.record.kind === 'dataset'
135
- ? this.record.contactsForResource
136
- : this.record.contacts) || []
137
- )
138
- }
139
-
140
110
  getTitleClass() {
141
111
  return this.titleClassMap[this._size]
142
112
  }
143
-
144
- openExternalUrl(event: Event, url: URL): void {
145
- event.stopPropagation()
146
- window.open(url, '_blank')
147
- }
148
-
149
- openMailto(event: Event, email: string): void {
150
- event.stopPropagation()
151
- window.open(`mailto:${email}`, '_blank')
113
+ getAbstractClass(): string {
114
+ const marginClass = ['S', 'XS'].includes(this.size) ? 'ml-2' : ''
115
+ const clampClass =
116
+ this.size === 'L' && !this.record.ownerOrganization?.name
117
+ ? 'line-clamp-6'
118
+ : 'line-clamp-2'
119
+ return `${clampClass} ${marginClass}`.trim()
152
120
  }
153
-
154
- copyToClipboard(event: Event, text: string): void {
155
- event.stopPropagation()
156
- navigator.clipboard.writeText(text)
121
+ displayAbstract(): boolean {
122
+ return (
123
+ this.size === 'L' ||
124
+ (['M', 'S'].includes(this.size) && !this.record.ownerOrganization?.name)
125
+ )
157
126
  }
158
127
 
159
128
  get shouldShowThumbnail(): boolean {