geonetwork-ui 2.3.0-dev.6083baae → 2.3.0-dev.61774f7d

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 (124) hide show
  1. package/esm2022/libs/api/metadata-converter/src/lib/gn4/gn4.field.mapper.mjs +3 -3
  2. package/esm2022/libs/api/repository/src/lib/gn4/auth/avatar.service.interface.mjs +1 -1
  3. package/esm2022/libs/api/repository/src/lib/gn4/auth/gravatar.service.mjs +12 -1
  4. package/esm2022/libs/api/repository/src/lib/gn4/platform/gn4-platform.mapper.mjs +36 -3
  5. package/esm2022/libs/api/repository/src/lib/gn4/platform/gn4-platform.service.mjs +19 -7
  6. package/esm2022/libs/common/domain/src/lib/model/record/index.mjs +2 -1
  7. package/esm2022/libs/common/domain/src/lib/model/record/user-feedbacks.model.mjs +2 -0
  8. package/esm2022/libs/common/domain/src/lib/model/user/index.mjs +2 -0
  9. package/esm2022/libs/common/domain/src/lib/platform.service.interface.mjs +1 -1
  10. package/esm2022/libs/feature/editor/src/lib/components/record-form/form-field/form-field-rich/form-field-rich.component.mjs +3 -3
  11. package/esm2022/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.mjs +24 -10
  12. package/esm2022/libs/feature/editor/src/lib/components/record-form/record-form.component.mjs +3 -13
  13. package/esm2022/libs/feature/editor/src/lib/components/wizard-field/wizard-field.component.mjs +1 -1
  14. package/esm2022/libs/feature/map/src/lib/add-layer-from-ogc-api/add-layer-from-ogc-api.component.mjs +1 -1
  15. package/esm2022/libs/feature/map/src/lib/add-layer-from-wfs/add-layer-from-wfs.component.mjs +1 -1
  16. package/esm2022/libs/feature/map/src/lib/add-layer-from-wms/add-layer-from-wms.component.mjs +1 -1
  17. package/esm2022/libs/feature/record/src/lib/feature-record.module.mjs +4 -4
  18. package/esm2022/libs/feature/record/src/lib/state/mdview.actions.mjs +22 -4
  19. package/esm2022/libs/feature/record/src/lib/state/mdview.effects.mjs +37 -10
  20. package/esm2022/libs/feature/record/src/lib/state/mdview.facade.mjs +22 -7
  21. package/esm2022/libs/feature/record/src/lib/state/mdview.reducer.mjs +52 -17
  22. package/esm2022/libs/feature/record/src/lib/state/mdview.selectors.mjs +18 -3
  23. package/esm2022/libs/feature/router/src/lib/default/state/router.effects.mjs +2 -2
  24. package/esm2022/libs/ui/elements/src/lib/markdown-editor/markdown-editor.component.mjs +2 -2
  25. package/esm2022/libs/ui/elements/src/lib/record-api-form/record-api-form.component.mjs +1 -1
  26. package/esm2022/libs/ui/elements/src/lib/ui-elements.module.mjs +10 -2
  27. package/esm2022/libs/ui/elements/src/lib/user-feedback-item/time-since.pipe.mjs +59 -0
  28. package/esm2022/libs/ui/elements/src/lib/user-feedback-item/user-feedback-item.component.mjs +62 -0
  29. package/esm2022/libs/ui/inputs/src/lib/text-area/text-area.component.mjs +27 -4
  30. package/esm2022/libs/ui/inputs/src/lib/text-input/text-input.component.mjs +19 -3
  31. package/esm2022/libs/ui/layout/src/lib/form-field-wrapper/form-field-wrapper.component.mjs +3 -3
  32. package/esm2022/translations/de.json +15 -0
  33. package/esm2022/translations/en.json +15 -0
  34. package/esm2022/translations/es.json +15 -0
  35. package/esm2022/translations/fr.json +15 -0
  36. package/esm2022/translations/it.json +15 -0
  37. package/esm2022/translations/nl.json +15 -0
  38. package/esm2022/translations/pt.json +15 -0
  39. package/fesm2022/geonetwork-ui.mjs +505 -79
  40. package/fesm2022/geonetwork-ui.mjs.map +1 -1
  41. package/libs/api/repository/src/lib/gn4/auth/avatar.service.interface.d.ts +1 -0
  42. package/libs/api/repository/src/lib/gn4/auth/avatar.service.interface.d.ts.map +1 -1
  43. package/libs/api/repository/src/lib/gn4/auth/gravatar.service.d.ts +1 -0
  44. package/libs/api/repository/src/lib/gn4/auth/gravatar.service.d.ts.map +1 -1
  45. package/libs/api/repository/src/lib/gn4/platform/gn4-platform.mapper.d.ts +6 -2
  46. package/libs/api/repository/src/lib/gn4/platform/gn4-platform.mapper.d.ts.map +1 -1
  47. package/libs/api/repository/src/lib/gn4/platform/gn4-platform.service.d.ts +9 -6
  48. package/libs/api/repository/src/lib/gn4/platform/gn4-platform.service.d.ts.map +1 -1
  49. package/libs/common/domain/src/lib/model/record/index.d.ts +1 -0
  50. package/libs/common/domain/src/lib/model/record/index.d.ts.map +1 -1
  51. package/libs/common/domain/src/lib/model/record/user-feedbacks.model.d.ts +15 -0
  52. package/libs/common/domain/src/lib/model/record/user-feedbacks.model.d.ts.map +1 -0
  53. package/libs/common/domain/src/lib/model/user/index.d.ts +2 -0
  54. package/libs/common/domain/src/lib/model/user/index.d.ts.map +1 -0
  55. package/libs/common/domain/src/lib/platform.service.interface.d.ts +3 -0
  56. package/libs/common/domain/src/lib/platform.service.interface.d.ts.map +1 -1
  57. package/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.d.ts +5 -1
  58. package/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.d.ts.map +1 -1
  59. package/libs/feature/editor/src/lib/components/record-form/record-form.component.d.ts.map +1 -1
  60. package/libs/feature/record/src/lib/feature-record.module.d.ts.map +1 -1
  61. package/libs/feature/record/src/lib/state/mdview.actions.d.ts +40 -6
  62. package/libs/feature/record/src/lib/state/mdview.actions.d.ts.map +1 -1
  63. package/libs/feature/record/src/lib/state/mdview.effects.d.ts +24 -4
  64. package/libs/feature/record/src/lib/state/mdview.effects.d.ts.map +1 -1
  65. package/libs/feature/record/src/lib/state/mdview.facade.d.ts +14 -4
  66. package/libs/feature/record/src/lib/state/mdview.facade.d.ts.map +1 -1
  67. package/libs/feature/record/src/lib/state/mdview.reducer.d.ts +8 -5
  68. package/libs/feature/record/src/lib/state/mdview.reducer.d.ts.map +1 -1
  69. package/libs/feature/record/src/lib/state/mdview.selectors.d.ts +12 -9
  70. package/libs/feature/record/src/lib/state/mdview.selectors.d.ts.map +1 -1
  71. package/libs/ui/elements/src/lib/ui-elements.module.d.ts +16 -14
  72. package/libs/ui/elements/src/lib/ui-elements.module.d.ts.map +1 -1
  73. package/libs/ui/elements/src/lib/user-feedback-item/time-since.pipe.d.ts +11 -0
  74. package/libs/ui/elements/src/lib/user-feedback-item/time-since.pipe.d.ts.map +1 -0
  75. package/libs/ui/elements/src/lib/user-feedback-item/user-feedback-item.component.d.ts +22 -0
  76. package/libs/ui/elements/src/lib/user-feedback-item/user-feedback-item.component.d.ts.map +1 -0
  77. package/libs/ui/inputs/src/lib/text-area/text-area.component.d.ts +7 -1
  78. package/libs/ui/inputs/src/lib/text-area/text-area.component.d.ts.map +1 -1
  79. package/libs/ui/inputs/src/lib/text-input/text-input.component.d.ts +4 -1
  80. package/libs/ui/inputs/src/lib/text-input/text-input.component.d.ts.map +1 -1
  81. package/package.json +1 -1
  82. package/src/libs/api/metadata-converter/src/lib/gn4/gn4.field.mapper.ts +2 -2
  83. package/src/libs/api/repository/src/lib/gn4/auth/avatar.service.interface.ts +1 -0
  84. package/src/libs/api/repository/src/lib/gn4/auth/gravatar.service.ts +12 -1
  85. package/src/libs/api/repository/src/lib/gn4/platform/gn4-platform.mapper.ts +51 -1
  86. package/src/libs/api/repository/src/lib/gn4/platform/gn4-platform.service.ts +34 -7
  87. package/src/libs/common/domain/src/lib/model/record/index.ts +1 -0
  88. package/src/libs/common/domain/src/lib/model/record/user-feedbacks.model.ts +15 -0
  89. package/src/libs/common/domain/src/lib/platform.service.interface.ts +3 -0
  90. package/src/libs/common/fixtures/src/index.ts +8 -6
  91. package/src/libs/common/fixtures/src/lib/records.fixtures.ts +1 -1
  92. package/src/libs/common/fixtures/src/lib/user-feedbacks.fixtures.ts +83 -0
  93. package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-rich/form-field-rich.component.css +0 -5
  94. package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-rich/form-field-rich.component.html +1 -1
  95. package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.html +24 -0
  96. package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.ts +19 -4
  97. package/src/libs/feature/editor/src/lib/components/record-form/record-form.component.ts +2 -21
  98. package/src/libs/feature/record/src/lib/feature-record.module.ts +5 -2
  99. package/src/libs/feature/record/src/lib/state/mdview.actions.ts +51 -6
  100. package/src/libs/feature/record/src/lib/state/mdview.effects.ts +82 -7
  101. package/src/libs/feature/record/src/lib/state/mdview.facade.ts +49 -8
  102. package/src/libs/feature/record/src/lib/state/mdview.reducer.ts +81 -24
  103. package/src/libs/feature/record/src/lib/state/mdview.selectors.ts +40 -10
  104. package/src/libs/feature/router/src/lib/default/state/router.effects.ts +2 -2
  105. package/src/libs/ui/elements/src/lib/ui-elements.module.ts +5 -0
  106. package/src/libs/ui/elements/src/lib/user-feedback-item/time-since.pipe.ts +54 -0
  107. package/src/libs/ui/elements/src/lib/user-feedback-item/user-feedback-item.component.css +0 -0
  108. package/src/libs/ui/elements/src/lib/user-feedback-item/user-feedback-item.component.html +75 -0
  109. package/src/libs/ui/elements/src/lib/user-feedback-item/user-feedback-item.component.ts +63 -0
  110. package/src/libs/ui/inputs/src/lib/text-area/text-area.component.html +2 -1
  111. package/src/libs/ui/inputs/src/lib/text-area/text-area.component.ts +29 -0
  112. package/src/libs/ui/inputs/src/lib/text-input/text-input.component.html +1 -1
  113. package/src/libs/ui/inputs/src/lib/text-input/text-input.component.ts +16 -1
  114. package/src/libs/ui/layout/src/lib/form-field-wrapper/form-field-wrapper.component.css +0 -5
  115. package/src/libs/ui/layout/src/lib/form-field-wrapper/form-field-wrapper.component.html +1 -1
  116. package/tailwind.base.css +7 -0
  117. package/translations/de.json +15 -0
  118. package/translations/en.json +15 -0
  119. package/translations/es.json +15 -0
  120. package/translations/fr.json +15 -0
  121. package/translations/it.json +15 -0
  122. package/translations/nl.json +15 -0
  123. package/translations/pt.json +15 -0
  124. package/translations/sk.json +15 -0
@@ -0,0 +1,22 @@
1
+ import { EventEmitter, OnInit } from '@angular/core';
2
+ import { UserFeedback, UserFeedbackViewModel } from '../../../../../../libs/common/domain/src/lib/model/record';
3
+ import { UserModel } from '../../../../../../libs/common/domain/src/lib/model/user';
4
+ import * as i0 from "@angular/core";
5
+ export declare class UserFeedbackItemComponent implements OnInit {
6
+ userFeedbackParent: UserFeedbackViewModel;
7
+ userFeedBacksAnswers: UserFeedbackViewModel[];
8
+ isActiveUserEditor: boolean;
9
+ activeUser: UserModel;
10
+ isLastComment: boolean;
11
+ isAddUserFeedbackLoading: boolean;
12
+ newUserFeedbackAnswer: EventEmitter<UserFeedback>;
13
+ isAnAnswer: boolean;
14
+ newAnswer: string;
15
+ isAnswerEmpty: boolean;
16
+ ngOnInit(): void;
17
+ onNewAnswerValueChange(): void;
18
+ publishNewAnswer(): void;
19
+ static ɵfac: i0.ɵɵFactoryDeclaration<UserFeedbackItemComponent, never>;
20
+ static ɵcmp: i0.ɵɵComponentDeclaration<UserFeedbackItemComponent, "gn-ui-user-feedback-item", never, { "userFeedbackParent": { "alias": "userFeedbackParent"; "required": false; }; "userFeedBacksAnswers": { "alias": "userFeedBacksAnswers"; "required": false; }; "isActiveUserEditor": { "alias": "isActiveUserEditor"; "required": false; }; "activeUser": { "alias": "activeUser"; "required": false; }; "isLastComment": { "alias": "isLastComment"; "required": false; }; "isAddUserFeedbackLoading": { "alias": "isAddUserFeedbackLoading"; "required": false; }; }, { "newUserFeedbackAnswer": "newUserFeedbackAnswer"; }, never, never, false, never>;
21
+ }
22
+ //# sourceMappingURL=user-feedback-item.component.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"user-feedback-item.component.d.ts","sourceRoot":"","sources":["../../../../../../src/libs/ui/elements/src/lib/user-feedback-item/user-feedback-item.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,YAAY,EAEZ,MAAM,EAEP,MAAM,eAAe,CAAA;AACtB,OAAO,EACL,YAAY,EACZ,qBAAqB,EACtB,MAAM,2DAA2D,CAAA;AAClE,OAAO,EAAE,SAAS,EAAE,MAAM,yDAAyD,CAAA;;AAEnF,qBAMa,yBAA0B,YAAW,MAAM;IAC7C,kBAAkB,EAAE,qBAAqB,CAAA;IACzC,oBAAoB,EAAE,qBAAqB,EAAE,CAAA;IAC7C,kBAAkB,EAAE,OAAO,CAAA;IAC3B,UAAU,EAAE,SAAS,CAAA;IACrB,aAAa,EAAE,OAAO,CAAA;IACtB,wBAAwB,EAAE,OAAO,CAAA;IAEhC,qBAAqB,6BAAmC;IAElE,UAAU,UAAQ;IAClB,SAAS,SAAK;IACd,aAAa,UAAO;IAEpB,QAAQ,IAAI,IAAI;IAIhB,sBAAsB;IAItB,gBAAgB;yCAtBL,yBAAyB;2CAAzB,yBAAyB;CA0CrC"}
@@ -2,16 +2,22 @@ import { AfterViewInit } from '@angular/core';
2
2
  import { Subject } from 'rxjs';
3
3
  import * as i0 from "@angular/core";
4
4
  export declare class TextAreaComponent implements AfterViewInit {
5
+ private readonly baseClasses;
6
+ private readonly disabledClasses;
5
7
  value: string;
8
+ disabled: boolean;
9
+ extraClass: string;
6
10
  placeholder: string;
7
11
  required: boolean;
8
12
  rawChange: Subject<string>;
9
13
  valueChange: import("rxjs").Observable<string>;
10
14
  input: any;
15
+ constructor();
16
+ get classList(): string;
11
17
  ngAfterViewInit(): void;
12
18
  checkRequired(value: any): void;
13
19
  handleChange($event: any): void;
14
20
  static ɵfac: i0.ɵɵFactoryDeclaration<TextAreaComponent, never>;
15
- static ɵcmp: i0.ɵɵComponentDeclaration<TextAreaComponent, "gn-ui-text-area", never, { "value": { "alias": "value"; "required": false; }; "placeholder": { "alias": "placeholder"; "required": false; }; "required": { "alias": "required"; "required": false; }; }, { "valueChange": "valueChange"; }, never, never, true, never>;
21
+ static ɵcmp: i0.ɵɵComponentDeclaration<TextAreaComponent, "gn-ui-text-area", never, { "value": { "alias": "value"; "required": false; }; "disabled": { "alias": "disabled"; "required": false; }; "extraClass": { "alias": "extraClass"; "required": false; }; "placeholder": { "alias": "placeholder"; "required": false; }; "required": { "alias": "required"; "required": false; }; }, { "valueChange": "valueChange"; }, never, never, true, never>;
16
22
  }
17
23
  //# sourceMappingURL=text-area.component.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"text-area.component.d.ts","sourceRoot":"","sources":["../../../../../../src/libs/ui/inputs/src/lib/text-area/text-area.component.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EAKd,MAAM,eAAe,CAAA;AACtB,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;;AAG9B,qBAMa,iBAAkB,YAAW,aAAa;IAC5C,KAAK,SAAK;IACV,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,UAAQ;IAEzB,SAAS,kBAAwB;IACvB,WAAW,oCAA8C;IAE/C,KAAK,MAAA;IAEzB,eAAe;IAIf,aAAa,CAAC,KAAK,KAAA;IAOnB,YAAY,CAAC,MAAM,KAAA;yCArBR,iBAAiB;2CAAjB,iBAAiB;CA0B7B"}
1
+ {"version":3,"file":"text-area.component.d.ts","sourceRoot":"","sources":["../../../../../../src/libs/ui/inputs/src/lib/text-area/text-area.component.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EAKd,MAAM,eAAe,CAAA;AACtB,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;;AAG9B,qBAMa,iBAAkB,YAAW,aAAa;IACrD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAQ;IACpC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAQ;IAE/B,KAAK,SAAK;IACV,QAAQ,UAAQ;IAChB,UAAU,SAAK;IACf,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,UAAQ;IAEzB,SAAS,kBAAwB;IACvB,WAAW,oCAA8C;IAE/C,KAAK,MAAA;;IAoBzB,IAAI,SAAS,WAIZ;IAED,eAAe;IAIf,aAAa,CAAC,KAAK,KAAA;IAOnB,YAAY,CAAC,MAAM,KAAA;yCAlDR,iBAAiB;2CAAjB,iBAAiB;CAuD7B"}
@@ -2,16 +2,19 @@ import { AfterViewInit } from '@angular/core';
2
2
  import { Subject } from 'rxjs';
3
3
  import * as i0 from "@angular/core";
4
4
  export declare class TextInputComponent implements AfterViewInit {
5
+ private readonly baseClass;
5
6
  value: string;
7
+ extraClass: string;
6
8
  hint: string;
7
9
  required: boolean;
8
10
  rawChange: Subject<string>;
9
11
  valueChange: import("rxjs").Observable<string>;
10
12
  input: any;
13
+ get classList(): string;
11
14
  ngAfterViewInit(): void;
12
15
  checkRequired(value: any): void;
13
16
  handleChange($event: any): void;
14
17
  static ɵfac: i0.ɵɵFactoryDeclaration<TextInputComponent, never>;
15
- static ɵcmp: i0.ɵɵComponentDeclaration<TextInputComponent, "gn-ui-text-input", never, { "value": { "alias": "value"; "required": false; }; "hint": { "alias": "hint"; "required": false; }; "required": { "alias": "required"; "required": false; }; }, { "valueChange": "valueChange"; }, never, never, false, never>;
18
+ static ɵcmp: i0.ɵɵComponentDeclaration<TextInputComponent, "gn-ui-text-input", never, { "value": { "alias": "value"; "required": false; }; "extraClass": { "alias": "extraClass"; "required": false; }; "hint": { "alias": "hint"; "required": false; }; "required": { "alias": "required"; "required": false; }; }, { "valueChange": "valueChange"; }, never, never, false, never>;
16
19
  }
17
20
  //# sourceMappingURL=text-input.component.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"text-input.component.d.ts","sourceRoot":"","sources":["../../../../../../src/libs/ui/inputs/src/lib/text-input/text-input.component.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EAKd,MAAM,eAAe,CAAA;AAEtB,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;;AAE9B,qBAKa,kBAAmB,YAAW,aAAa;IAC7C,KAAK,SAAK;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,UAAQ;IACzB,SAAS,kBAAwB;IACvB,WAAW,oCAA8C;IAE/C,KAAK,MAAA;IAEzB,eAAe;IAIf,aAAa,CAAC,KAAK,KAAA;IAOnB,YAAY,CAAC,MAAM,KAAA;yCApBR,kBAAkB;2CAAlB,kBAAkB;CAyB9B"}
1
+ {"version":3,"file":"text-input.component.d.ts","sourceRoot":"","sources":["../../../../../../src/libs/ui/inputs/src/lib/text-input/text-input.component.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EAKd,MAAM,eAAe,CAAA;AAEtB,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;;AAE9B,qBAKa,kBAAmB,YAAW,aAAa;IACtD,OAAO,CAAC,QAAQ,CAAC,SAAS,CASf;IAEF,KAAK,SAAK;IACV,UAAU,SAAK;IACf,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,UAAQ;IACzB,SAAS,kBAAwB;IACvB,WAAW,oCAA8C;IAC/C,KAAK,MAAA;IAEzB,IAAI,SAAS,WAEZ;IAED,eAAe;IAIf,aAAa,CAAC,KAAK,KAAA;IAOnB,YAAY,CAAC,MAAM,KAAA;yCAnCR,kBAAkB;2CAAlB,kBAAkB;CAwC9B"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "geonetwork-ui",
3
- "version": "2.3.0-dev.6083baae",
3
+ "version": "2.3.0-dev.61774f7d",
4
4
  "engines": {
5
5
  "node": ">=14.17.0"
6
6
  },
@@ -120,13 +120,13 @@ export class Gn4FieldMapper {
120
120
  }),
121
121
  creationDateForResource: (output, source) => ({
122
122
  ...output,
123
- datasetCreated: toDate(
123
+ resourceCreated: toDate(
124
124
  getFirstValue(selectField<string>(source, 'creationDateForResource'))
125
125
  ),
126
126
  }),
127
127
  revisionDateForResource: (output, source) => ({
128
128
  ...output,
129
- datasetUpdated: toDate(
129
+ resourceUpdated: toDate(
130
130
  getFirstValue(selectField<string>(source, 'revisionDateForResource'))
131
131
  ),
132
132
  }),
@@ -3,4 +3,5 @@ import { Observable } from 'rxjs'
3
3
  export abstract class AvatarServiceInterface {
4
4
  public abstract getPlaceholder(): Observable<string>
5
5
  public abstract getProfileIcon(...args): Observable<string>
6
+ public abstract getProfileIconUrl(userId: string): Promise<string>
6
7
  }
@@ -2,7 +2,7 @@ import { Injectable } from '@angular/core'
2
2
  import { AvatarServiceInterface } from './avatar.service.interface'
3
3
  import { Gn4SettingsService } from '../settings/gn4-settings.service'
4
4
  import { map } from 'rxjs/operators'
5
- import { Observable } from 'rxjs'
5
+ import { firstValueFrom, Observable } from 'rxjs'
6
6
 
7
7
  @Injectable({
8
8
  providedIn: 'root',
@@ -14,6 +14,7 @@ export class GravatarService implements AvatarServiceInterface {
14
14
  private readonly identicon$ = this.gn4SettingsService.identicon$.pipe(
15
15
  map((identicon) => identicon?.replace('gravatar:', ''))
16
16
  )
17
+
17
18
  constructor(private gn4SettingsService: Gn4SettingsService) {}
18
19
 
19
20
  getPlaceholder(): Observable<string> {
@@ -26,4 +27,14 @@ export class GravatarService implements AvatarServiceInterface {
26
27
  map((identicon) => `${this.GRAVATAR_URL}${hash}?d=${identicon}`)
27
28
  )
28
29
  }
30
+
31
+ async getProfileIconUrl(userId: string) {
32
+ let iconUrl = ''
33
+ try {
34
+ iconUrl = await firstValueFrom(this.getProfileIcon(userId))
35
+ } catch (error) {
36
+ return ''
37
+ }
38
+ return iconUrl
39
+ }
29
40
  }
@@ -1,17 +1,23 @@
1
1
  import {
2
2
  MeResponseApiModel,
3
3
  UserApiModel,
4
+ UserFeedbackDTOApiModel,
4
5
  } from '../../../../../../../libs/data-access/gn4/src'
5
6
  import { UserModel } from '../../../../../../../libs/common/domain/src/lib/model/user/user.model'
6
7
  import { Injectable } from '@angular/core'
7
- import { AvatarServiceInterface } from '../auth/avatar.service.interface'
8
+ import { AvatarServiceInterface } from '../auth'
8
9
  import { map } from 'rxjs/operators'
9
10
  import { Observable, of } from 'rxjs'
10
11
  import { ThesaurusModel } from '../../../../../../../libs/common/domain/src/lib/model/thesaurus/thesaurus.model'
12
+ import {
13
+ UserFeedback,
14
+ UserFeedbackViewModel,
15
+ } from '../../../../../../../libs/common/domain/src/lib/model/record'
11
16
 
12
17
  @Injectable()
13
18
  export class Gn4PlatformMapper {
14
19
  constructor(private avatarService: AvatarServiceInterface) {}
20
+
15
21
  userFromMeApi(apiUser: MeResponseApiModel): Observable<UserModel | null> {
16
22
  if (!apiUser) return of(null)
17
23
  const {
@@ -28,6 +34,7 @@ export class Gn4PlatformMapper {
28
34
  .getProfileIcon(hash)
29
35
  .pipe(map((profileIcon) => ({ ...user, profileIcon } as UserModel)))
30
36
  }
37
+
31
38
  userFromApi(apiUser: UserApiModel): UserModel {
32
39
  if (!apiUser) return null
33
40
  const {
@@ -65,4 +72,47 @@ export class Gn4PlatformMapper {
65
72
  }
66
73
  })
67
74
  }
75
+
76
+ userFeedbacksFromApi(userFeedback: any): UserFeedback {
77
+ return {
78
+ uuid: userFeedback.uuid,
79
+ metadataUUID: userFeedback.metadataUUID,
80
+ comment: userFeedback.comment,
81
+ authorUserId: userFeedback.authorUserId.toString(),
82
+ authorName: userFeedback.authorName,
83
+ authorEmail: userFeedback.authorEmail,
84
+ published: userFeedback.published,
85
+ parentUuid: userFeedback.parentUuid ?? undefined,
86
+ date: new Date(userFeedback.date),
87
+ }
88
+ }
89
+
90
+ userFeedbacksToApi(
91
+ userFeedback: UserFeedback
92
+ ): Partial<UserFeedbackDTOApiModel> {
93
+ return {
94
+ uuid: userFeedback.uuid,
95
+ metadataUUID: userFeedback.metadataUUID,
96
+ comment: userFeedback.comment,
97
+ authorUserId: Number.parseInt(userFeedback.authorUserId),
98
+ authorName: userFeedback.authorName,
99
+ authorEmail: userFeedback.authorEmail,
100
+ published: userFeedback.published,
101
+ parentUuid: userFeedback.parentUuid,
102
+ date: userFeedback.date.getTime().toString(),
103
+ }
104
+ }
105
+
106
+ async createUserFeedbackViewModel(
107
+ baseUserFeedback: UserFeedback
108
+ ): Promise<UserFeedbackViewModel> {
109
+ const userAvatarUrl = await this.avatarService.getProfileIconUrl(
110
+ baseUserFeedback.authorUserId?.toString()
111
+ )
112
+
113
+ return {
114
+ ...baseUserFeedback,
115
+ avatarUrl: userAvatarUrl,
116
+ }
117
+ }
68
118
  }
@@ -6,11 +6,15 @@ import {
6
6
  RegistriesApiService,
7
7
  SiteApiService,
8
8
  ToolsApiService,
9
+ UserfeedbackApiService,
9
10
  UsersApiService,
10
11
  } from '../../../../../../../libs/data-access/gn4/src'
11
12
  import { PlatformServiceInterface } from '../../../../../../../libs/common/domain/src/lib/platform.service.interface'
12
13
  import { UserModel } from '../../../../../../../libs/common/domain/src/lib/model/user/user.model'
13
- import { Organization } from '../../../../../../../libs/common/domain/src/lib/model/record'
14
+ import {
15
+ Organization,
16
+ UserFeedback,
17
+ } from '../../../../../../../libs/common/domain/src/lib/model/record'
14
18
  import { Gn4PlatformMapper } from './gn4-platform.mapper'
15
19
  import { ltr } from 'semver'
16
20
  import { ThesaurusModel } from '../../../../../../../libs/common/domain/src/lib/model/thesaurus/thesaurus.model'
@@ -21,9 +25,9 @@ const minApiVersion = '4.2.2'
21
25
  @Injectable()
22
26
  export class Gn4PlatformService implements PlatformServiceInterface {
23
27
  private readonly type = 'GeoNetwork'
24
- private me$: Observable<UserModel>
25
- private users$: Observable<UserModel[]>
26
- private isAnonymous$: Observable<boolean>
28
+ private readonly me$: Observable<UserModel>
29
+ private readonly users$: Observable<UserModel[]>
30
+ private readonly isUserAnonymous$: Observable<boolean>
27
31
 
28
32
  private keyTranslations$ = this.toolsApiService
29
33
  .getTranslationsPackage1('gnui')
@@ -65,13 +69,18 @@ export class Gn4PlatformService implements PlatformServiceInterface {
65
69
  private mapper: Gn4PlatformMapper,
66
70
  private toolsApiService: ToolsApiService,
67
71
  private registriesApiService: RegistriesApiService,
68
- private langService: LangService
72
+ private langService: LangService,
73
+ private userfeedbackApiService: UserfeedbackApiService
69
74
  ) {
70
75
  this.me$ = this.meApi.getMe().pipe(
71
76
  switchMap((apiUser) => this.mapper.userFromMeApi(apiUser)),
72
77
  shareReplay({ bufferSize: 1, refCount: true })
73
78
  )
74
- this.isAnonymous$ = this.me$.pipe(map((user) => !user || !('id' in user)))
79
+
80
+ this.isUserAnonymous$ = this.me$.pipe(
81
+ map((user) => !user || !('id' in user))
82
+ )
83
+
75
84
  this.users$ = this.usersApi.getUsers().pipe(
76
85
  map((users) => users.map((user) => this.mapper.userFromApi(user))),
77
86
  shareReplay()
@@ -91,7 +100,7 @@ export class Gn4PlatformService implements PlatformServiceInterface {
91
100
  }
92
101
 
93
102
  isAnonymous(): Observable<boolean> {
94
- return this.isAnonymous$
103
+ return this.isUserAnonymous$
95
104
  }
96
105
 
97
106
  getOrganizations(): Observable<Organization[]> {
@@ -148,6 +157,24 @@ export class Gn4PlatformService implements PlatformServiceInterface {
148
157
  ),
149
158
  shareReplay(1)
150
159
  )
160
+
151
161
  return this.thesauri[uri]
152
162
  }
163
+
164
+ getUserFeedbacks(uuid: string): Observable<UserFeedback[]> {
165
+ return this.userfeedbackApiService
166
+ .getUserComments(uuid)
167
+ .pipe(
168
+ map((userFeedbacks) =>
169
+ userFeedbacks.map(this.mapper.userFeedbacksFromApi)
170
+ )
171
+ )
172
+ }
173
+
174
+ postUserFeedbacks(userFeedback: UserFeedback): Observable<void> {
175
+ const mappedUserFeedBack = this.mapper.userFeedbacksToApi(userFeedback)
176
+ return this.userfeedbackApiService
177
+ .newUserFeedback(mappedUserFeedBack)
178
+ .pipe(map(() => undefined))
179
+ }
153
180
  }
@@ -1,3 +1,4 @@
1
1
  export * from './contact.model'
2
2
  export * from './organization.model'
3
3
  export * from './metadata.model'
4
+ export * from './user-feedbacks.model'
@@ -0,0 +1,15 @@
1
+ export interface UserFeedback {
2
+ uuid: string
3
+ comment: string
4
+ metadataUUID: string
5
+ authorUserId: string
6
+ authorName: string
7
+ authorEmail: string
8
+ published: boolean
9
+ parentUuid?: string
10
+ date: Date
11
+ }
12
+
13
+ export interface UserFeedbackViewModel extends UserFeedback {
14
+ avatarUrl: string
15
+ }
@@ -2,6 +2,7 @@ import type { Observable } from 'rxjs'
2
2
  import type { UserModel } from './model/user/user.model'
3
3
  import type { Organization } from './model/record/organization.model'
4
4
  import type { ThesaurusModel } from './model/thesaurus/'
5
+ import { UserFeedback } from './model/record'
5
6
 
6
7
  export abstract class PlatformServiceInterface {
7
8
  abstract getType(): string
@@ -16,4 +17,6 @@ export abstract class PlatformServiceInterface {
16
17
  abstract getOrganizations(): Observable<Organization[]>
17
18
  abstract translateKey(key: string): Observable<string>
18
19
  abstract getThesaurusByUri(uri: string): Observable<ThesaurusModel>
20
+ abstract getUserFeedbacks(recordUuid: string): Observable<UserFeedback[]>
21
+ abstract postUserFeedbacks(recordUuid: UserFeedback): Observable<void>
19
22
  }
@@ -1,11 +1,13 @@
1
+ export * from './lib/elasticsearch'
2
+ export * from './lib/gn4'
3
+ export * from './lib/search'
4
+
1
5
  export * from './lib/geojson.fixtures'
6
+ export * from './lib/link.fixtures'
2
7
  export * from './lib/ol-feature.fixture'
8
+ export * from './lib/organisations.fixture'
3
9
  export * from './lib/record-link.fixtures'
4
- export * from './lib/link.fixtures'
5
10
  export * from './lib/records.fixtures'
6
- export * from './lib/organisations.fixture'
7
- export * from './lib/elasticsearch'
8
- export * from './lib/search'
9
- export * from './lib/user.fixtures'
10
11
  export * from './lib/repository.fixtures'
11
- export * from './lib/gn4'
12
+ export * from './lib/user.fixtures'
13
+ export * from './lib/user-feedbacks.fixtures'
@@ -1,5 +1,5 @@
1
1
  import { DatasetRecord } from '../../../../../libs/common/domain/src/lib/model/record'
2
- import { deepFreeze } from './utils/freeze'
2
+ import { deepFreeze } from './utils'
3
3
 
4
4
  export const DATASET_RECORDS: DatasetRecord[] = deepFreeze([
5
5
  {
@@ -0,0 +1,83 @@
1
+ import { UserFeedback } from '../../../../../libs/common/domain/src/lib/model/record'
2
+ import { deepFreeze } from './utils'
3
+
4
+ export const SOME_USER_FEEDBACKS: UserFeedback[] = deepFreeze([
5
+ {
6
+ uuid: '4ad03fb7-1728-424c-bdaa-aedd531b07a8',
7
+ comment: 'A nice comment.',
8
+ metadataUUID: 'my-dataset-001',
9
+ authorUserId: '46798',
10
+ authorName: 'Arnaud De Maison',
11
+ authorEmail: 'a.demaison@geo2france.fr',
12
+ published: true,
13
+ parentUuid: undefined,
14
+ date: new Date('2023-01-01T08:00:00Z'),
15
+ },
16
+ {
17
+ uuid: '52cbd0f1-9cb9-4409-8e85-bc608f049af4',
18
+ comment: 'A very nice comment that is a reply.',
19
+ metadataUUID: 'my-dataset-001',
20
+ authorUserId: '46798',
21
+ authorName: 'Arnaud De Maison',
22
+ authorEmail: 'a.demaison@geo2france.fr',
23
+ published: true,
24
+ parentUuid: '4ad03fb7-1728-424c-bdaa-aedd531b07a8',
25
+ date: new Date('2023-01-01T09:00:00Z'),
26
+ },
27
+ {
28
+ uuid: 'b48f62ec-b5e6-4d27-a396-2c2b44f6dcb5',
29
+ comment: 'Another nice comment.',
30
+ metadataUUID: 'my-dataset-001',
31
+ authorUserId: '46798',
32
+ authorName: 'Arnaud De Maison',
33
+ authorEmail: 'a.demaison@geo2france.fr',
34
+ published: true,
35
+ parentUuid: undefined,
36
+ date: new Date('2023-01-01T10:00:00Z'),
37
+ },
38
+ {
39
+ uuid: '1f12a3be-fc8a-4e83-968f-9b88ffbcab02',
40
+ comment: 'Another very nice reply.',
41
+ metadataUUID: 'my-dataset-001',
42
+ authorUserId: '46798',
43
+ authorName: 'Arnaud De Maison',
44
+ authorEmail: 'a.demaison@geo2france.fr',
45
+ published: true,
46
+ parentUuid: '4ad03fb7-1728-424c-bdaa-aedd531b07a8',
47
+ date: new Date('2023-01-01T11:00:00Z'),
48
+ },
49
+ {
50
+ uuid: 'f8dd778d-e93c-4b3c-ba9b-9574be070f46',
51
+ comment: 'Another nice comment.',
52
+ metadataUUID: 'my-dataset-001',
53
+ authorUserId: '46798',
54
+ authorName: 'Arnaud De Maison',
55
+ authorEmail: 'a.demaison@geo2france.fr',
56
+ published: true,
57
+ parentUuid: undefined,
58
+ date: new Date('2023-01-01T10:00:00Z'),
59
+ },
60
+ {
61
+ uuid: 'df3b8872-61d1-4ae9-8822-bb070b94d7d1',
62
+ comment: 'Another nice comment.',
63
+ metadataUUID: 'my-dataset-001',
64
+ authorUserId: '46798',
65
+ authorName: 'Arnaud De Maison',
66
+ authorEmail: 'a.demaison@geo2france.fr',
67
+ published: true,
68
+ parentUuid: undefined,
69
+ date: new Date('2023-01-01T11:00:00Z'),
70
+ },
71
+ ])
72
+
73
+ export const A_USER_FEEDBACK: UserFeedback = deepFreeze({
74
+ uuid: '4ad03fb7-1728-424c-bdaa-aedd531b07a8',
75
+ comment: 'A nice comment.',
76
+ metadataUUID: 'my-dataset-001',
77
+ authorUserId: '46798',
78
+ authorName: 'Arnaud De Maison',
79
+ authorEmail: 'a.demaison@geo2france.fr',
80
+ published: true,
81
+ parentUuid: undefined,
82
+ date: new Date('2023-01-01T08:00:00Z'),
83
+ })
@@ -1,5 +0,0 @@
1
- .icon-small {
2
- font-size: 16px;
3
- height: 16px;
4
- width: 16px;
5
- }
@@ -4,7 +4,7 @@
4
4
  [extraClass]="getButtonExtraClass()"
5
5
  (buttonClick)="togglePreview()"
6
6
  >
7
- <span class="material-symbols-outlined mr-1 icon-small">{{
7
+ <span class="material-symbols-outlined mr-1 gn-ui-icon-small">{{
8
8
  preview ? 'visibility' : 'visibility_off'
9
9
  }}</span>
10
10
  {{ preview ? 'WYSIWYG' : 'Markdown' }}
@@ -24,6 +24,30 @@
24
24
  >cancel</mat-icon
25
25
  >
26
26
  </div>
27
+ <ng-container *ngIf="isTitle">
28
+ <div class="flex justify-between items-center gap-3">
29
+ <h2
30
+ #titleInput
31
+ class="grow text-3xl font-normal"
32
+ [gnUiEditableLabel]="true"
33
+ (editableLabelChanged)="formControl.setValue($event)"
34
+ >
35
+ {{ formControl.value }}
36
+ </h2>
37
+ <span
38
+ class="material-symbols-outlined gn-ui-icon-small m-2 cursor-pointer"
39
+ (click)="focusTitleInput()"
40
+ >edit</span
41
+ >
42
+ <span
43
+ class="material-symbols-outlined gn-ui-icon-small m-2"
44
+ [matTooltip]="config.hintKey | translate"
45
+ matTooltipPosition="above"
46
+ >
47
+ help
48
+ </span>
49
+ </div>
50
+ </ng-container>
27
51
  <ng-container *ngIf="isSimpleField">
28
52
  <gn-ui-form-field-simple
29
53
  [type]="simpleType"
@@ -1,11 +1,16 @@
1
+ import { CommonModule } from '@angular/common'
1
2
  import {
2
3
  ChangeDetectionStrategy,
3
4
  Component,
5
+ ElementRef,
4
6
  Input,
5
7
  Output,
8
+ ViewChild,
6
9
  } from '@angular/core'
7
10
  import { FormControl, ReactiveFormsModule } from '@angular/forms'
8
11
  import { MatIconModule } from '@angular/material/icon'
12
+ import { MatTooltipModule } from '@angular/material/tooltip'
13
+ import { EditableLabelDirective } from '../../../../../../../../libs/ui/inputs/src'
9
14
  import { TranslateModule } from '@ngx-translate/core'
10
15
  import { Observable } from 'rxjs'
11
16
  import { FormFieldArrayComponent } from './form-field-array/form-field-array.component'
@@ -16,7 +21,6 @@ import { FormFieldSimpleComponent } from './form-field-simple/form-field-simple.
16
21
  import { FormFieldSpatialExtentComponent } from './form-field-spatial-extent/form-field-spatial-extent.component'
17
22
  import { FormFieldTemporalExtentComponent } from './form-field-temporal-extent/form-field-temporal-extent.component'
18
23
  import { FormFieldConfig } from './form-field.model'
19
- import { CommonModule } from '@angular/common'
20
24
 
21
25
  @Component({
22
26
  selector: 'gn-ui-form-field',
@@ -25,6 +29,11 @@ import { CommonModule } from '@angular/common'
25
29
  changeDetection: ChangeDetectionStrategy.OnPush,
26
30
  standalone: true,
27
31
  imports: [
32
+ CommonModule,
33
+ ReactiveFormsModule,
34
+ EditableLabelDirective,
35
+ MatIconModule,
36
+ MatTooltipModule,
28
37
  FormFieldSimpleComponent,
29
38
  FormFieldRichComponent,
30
39
  FormFieldObjectComponent,
@@ -32,10 +41,7 @@ import { CommonModule } from '@angular/common'
32
41
  FormFieldTemporalExtentComponent,
33
42
  FormFieldFileComponent,
34
43
  FormFieldArrayComponent,
35
- CommonModule,
36
- ReactiveFormsModule,
37
44
  TranslateModule,
38
- MatIconModule,
39
45
  ],
40
46
  })
41
47
  export class FormFieldComponent {
@@ -48,12 +54,18 @@ export class FormFieldComponent {
48
54
  }
49
55
  @Output() valueChange: Observable<unknown>
50
56
 
57
+ @ViewChild('titleInput') titleInput: ElementRef
58
+
51
59
  formControl = new FormControl()
52
60
 
53
61
  constructor() {
54
62
  this.valueChange = this.formControl.valueChanges
55
63
  }
56
64
 
65
+ focusTitleInput() {
66
+ this.titleInput.nativeElement.children[0].focus()
67
+ }
68
+
57
69
  get simpleType() {
58
70
  return this.config.type as
59
71
  | 'date'
@@ -100,6 +112,9 @@ export class FormFieldComponent {
100
112
  return !this.config.locked && this.config.invalid
101
113
  }
102
114
 
115
+ get isTitle() {
116
+ return this.model === 'title'
117
+ }
103
118
  get isAbstract() {
104
119
  return this.model === 'abstract'
105
120
  }
@@ -2,16 +2,7 @@ import { CommonModule } from '@angular/common'
2
2
  import { ChangeDetectionStrategy, Component } from '@angular/core'
3
3
  import { EditorFacade } from '../../+state/editor.facade'
4
4
  import { EditorFieldState, EditorFieldValue } from '../../models/fields.model'
5
- import {
6
- FormFieldArrayComponent,
7
- FormFieldComponent,
8
- FormFieldFileComponent,
9
- FormFieldObjectComponent,
10
- FormFieldRichComponent,
11
- FormFieldSimpleComponent,
12
- FormFieldSpatialExtentComponent,
13
- FormFieldTemporalExtentComponent,
14
- } from './form-field'
5
+ import { FormFieldComponent } from './form-field'
15
6
 
16
7
  @Component({
17
8
  selector: 'gn-ui-record-form',
@@ -19,17 +10,7 @@ import {
19
10
  styleUrls: ['./record-form.component.css'],
20
11
  changeDetection: ChangeDetectionStrategy.OnPush,
21
12
  standalone: true,
22
- imports: [
23
- CommonModule,
24
- FormFieldComponent,
25
- FormFieldArrayComponent,
26
- FormFieldFileComponent,
27
- FormFieldObjectComponent,
28
- FormFieldRichComponent,
29
- FormFieldSimpleComponent,
30
- FormFieldSpatialExtentComponent,
31
- FormFieldTemporalExtentComponent,
32
- ],
13
+ imports: [CommonModule, FormFieldComponent],
33
14
  })
34
15
  export class RecordFormComponent {
35
16
  fields$ = this.facade.recordFields$
@@ -11,7 +11,10 @@ import { MdViewFacade } from './state'
11
11
  import { MdViewEffects } from './state/mdview.effects'
12
12
  import { MapViewComponent } from './map-view/map-view.component'
13
13
  import { DataViewComponent } from './data-view/data-view.component'
14
- import { MD_VIEW_FEATURE_STATE_KEY, reducer } from './state/mdview.reducer'
14
+ import {
15
+ METADATA_VIEW_FEATURE_STATE_KEY,
16
+ reducer,
17
+ } from './state/mdview.reducer'
15
18
  import { MatTabsModule } from '@angular/material/tabs'
16
19
  import { MatIconModule } from '@angular/material/icon'
17
20
  import { UiWidgetsModule } from '../../../../../libs/ui/widgets/src'
@@ -35,7 +38,7 @@ import { DataViewShareComponent } from './data-view-share/data-view-share.compon
35
38
  ],
36
39
  imports: [
37
40
  CommonModule,
38
- StoreModule.forFeature(MD_VIEW_FEATURE_STATE_KEY, reducer),
41
+ StoreModule.forFeature(METADATA_VIEW_FEATURE_STATE_KEY, reducer),
39
42
  EffectsModule.forFeature([MdViewEffects]),
40
43
  UiLayoutModule,
41
44
  FeatureMapModule,