From b4e3f98b67dd3113082d2abc39ee78bddd23e0b3 Mon Sep 17 00:00:00 2001
From: Angelika Kinas <angelika.kinas@camptocamp.com>
Date: Tue, 3 Dec 2024 13:07:40 +0100
Subject: [PATCH 1/9] feat(ui-inputs): Add optional disabled option

---
 ...line-service-resource-input.component.html |  2 ++
 ...online-service-resource-input.component.ts |  1 +
 .../lib/file-input/file-input.component.html  |  9 +++++----
 .../file-input.component.stories.ts           |  5 ++++-
 .../lib/file-input/file-input.component.ts    |  1 +
 .../image-input/image-input.component.html    | 20 ++++++++++++++-----
 .../image-input.component.stories.ts          |  5 ++++-
 .../lib/image-input/image-input.component.ts  |  1 +
 .../switch-toggle.component.html              |  1 +
 .../switch-toggle/switch-toggle.component.ts  |  1 +
 .../switch-toggle/switch-toggle.stories.ts    |  1 +
 11 files changed, 36 insertions(+), 11 deletions(-)

diff --git a/libs/feature/editor/src/lib/components/online-service-resource-input/online-service-resource-input.component.html b/libs/feature/editor/src/lib/components/online-service-resource-input/online-service-resource-input.component.html
index 4ee656c480..d7e845ff71 100644
--- a/libs/feature/editor/src/lib/components/online-service-resource-input/online-service-resource-input.component.html
+++ b/libs/feature/editor/src/lib/components/online-service-resource-input/online-service-resource-input.component.html
@@ -16,6 +16,7 @@ <h3 class="text-[16px] font-bold text-main mb-[12px]" translate>
     aria-labelledby="example-radio-group-label"
     class="flex flex-row gap-[8px]"
     [(ngModel)]="service.accessServiceProtocol"
+    [disabled]="disabled"
   >
     <mat-radio-button
       *ngFor="let protocolOption of protocolOptions"
@@ -28,4 +29,5 @@ <h3 class="text-[16px] font-bold text-main mb-[12px]" translate>
 <gn-ui-text-input
   [(value)]="service.identifierInService"
   data-cy="identifier-in-service"
+  [disabled]="disabled"
 ></gn-ui-text-input>
diff --git a/libs/feature/editor/src/lib/components/online-service-resource-input/online-service-resource-input.component.ts b/libs/feature/editor/src/lib/components/online-service-resource-input/online-service-resource-input.component.ts
index f75af603c8..9b4f6a187a 100644
--- a/libs/feature/editor/src/lib/components/online-service-resource-input/online-service-resource-input.component.ts
+++ b/libs/feature/editor/src/lib/components/online-service-resource-input/online-service-resource-input.component.ts
@@ -34,6 +34,7 @@ import { TranslateModule } from '@ngx-translate/core'
 export class OnlineServiceResourceInputComponent implements OnChanges {
   @Input() service: Omit<DatasetServiceDistribution, 'url'>
   @Input() protocolHint?: string
+  @Input() disabled? = false
 
   selectedProtocol: ServiceProtocol
 
diff --git a/libs/ui/inputs/src/lib/file-input/file-input.component.html b/libs/ui/inputs/src/lib/file-input/file-input.component.html
index 208946510f..946263e33c 100644
--- a/libs/ui/inputs/src/lib/file-input/file-input.component.html
+++ b/libs/ui/inputs/src/lib/file-input/file-input.component.html
@@ -5,9 +5,10 @@
     [ngClass]="{
       'border-primary-lighter bg-primary-white': dragFilesOver,
       'border-gray-300': !dragFilesOver,
-      'cursor-pointer hover:border-gray-500': !isUploadInProgress
+      'cursor-pointer hover:border-gray-500': !isUploadInProgress && !disabled,
+      'cursor-not-allowed': disabled
     }"
-    [attr.tabindex]="isUploadInProgress ? null : 0"
+    [attr.tabindex]="isUploadInProgress || disabled ? null : 0"
     (dragFilesOver)="handleDragFilesOver($event)"
     (dropFiles)="handleDropFiles($event)"
     (keydown.enter)="fileInput.click()"
@@ -17,7 +18,7 @@
       type="file"
       class="hidden"
       (change)="handleFileInput($event)"
-      [disabled]="isUploadInProgress"
+      [disabled]="isUploadInProgress || disabled"
     />
 
     <div
@@ -82,7 +83,7 @@
     </p>
     <gn-ui-url-input
       class="w-full"
-      [disabled]="isUploadInProgress"
+      [disabled]="isUploadInProgress || disabled"
       (uploadClick)="handleUrlChange($event)"
     ></gn-ui-url-input>
   </label>
diff --git a/libs/ui/inputs/src/lib/file-input/file-input.component.stories.ts b/libs/ui/inputs/src/lib/file-input/file-input.component.stories.ts
index fff22568cd..f85a230f2b 100644
--- a/libs/ui/inputs/src/lib/file-input/file-input.component.stories.ts
+++ b/libs/ui/inputs/src/lib/file-input/file-input.component.stories.ts
@@ -34,6 +34,7 @@ export default {
 export const Primary: StoryObj<FileInputComponent> = {
   args: {
     maxSizeMB: 5,
+    disabled: false,
   },
   render: (args) => ({
     props: {
@@ -44,7 +45,9 @@ export const Primary: StoryObj<FileInputComponent> = {
     },
     template: `
     <div style="width: 600px;height: 400px;">
-      <gn-ui-file-input [maxSizeMB]="maxSizeMB"
+      <gn-ui-file-input
+        [maxSizeMB]="maxSizeMB"
+        [disabled]="disabled"
         (fileChange)='fileChange($event)'
         (urlChange)='urlChange($event)'
         (uploadCancel)='uploadCancel($event)'>
diff --git a/libs/ui/inputs/src/lib/file-input/file-input.component.ts b/libs/ui/inputs/src/lib/file-input/file-input.component.ts
index 225b1e1f3b..4d5f72cb43 100644
--- a/libs/ui/inputs/src/lib/file-input/file-input.component.ts
+++ b/libs/ui/inputs/src/lib/file-input/file-input.component.ts
@@ -48,6 +48,7 @@ import { iconoirCloudUpload, iconoirFramePlusIn } from '@ng-icons/iconoir'
 export class FileInputComponent {
   @Input() maxSizeMB: number
   @Input() uploadProgress?: number
+  @Input() disabled? = false
   @Output() fileChange: EventEmitter<File> = new EventEmitter()
   @Output() urlChange: EventEmitter<string> = new EventEmitter()
   @Output() uploadCancel: EventEmitter<void> = new EventEmitter()
diff --git a/libs/ui/inputs/src/lib/image-input/image-input.component.html b/libs/ui/inputs/src/lib/image-input/image-input.component.html
index f17df3c221..ce80776cd8 100644
--- a/libs/ui/inputs/src/lib/image-input/image-input.component.html
+++ b/libs/ui/inputs/src/lib/image-input/image-input.component.html
@@ -15,6 +15,7 @@
         style="--gn-ui-button-height: 40px; --gn-ui-button-width: 40px"
         extraClass="absolute right-2 bottom-2 invisible group-hover:visible bg-background"
         (buttonClick)="handleDelete()"
+        [disabled]="disabled"
       >
         <ng-icon name="iconoirBin"></ng-icon>
       </gn-ui-button>
@@ -25,6 +26,7 @@
       [value]="altText ?? ''"
       (valueChange)="handleAltTextChange($event)"
       extraClass="gn-ui-editor-textarea"
+      [disabled]="disabled"
     ></gn-ui-text-input>
     <div class="flex flex-row gap-2 mt-2">
       <gn-ui-button type="gray" (buttonClick)="handleDelete()">
@@ -52,10 +54,11 @@
         'border-primary-lighter bg-primary-white': dragFilesOver,
         'border-gray-300': !dragFilesOver,
         'cursor-pointer hover:border-gray-500':
-          !isUploadInProgress && !uploadError && !showUrlInput
+          !isUploadInProgress && !uploadError && !showUrlInput && !disabled,
+        'cursor-not-allowed': disabled
       }"
       [attr.tabindex]="
-        isUploadInProgress || uploadError || showUrlInput ? null : 0
+        isUploadInProgress || uploadError || showUrlInput || disabled ? null : 0
       "
       (keydown.enter)="fileInput.click()"
       (dragFilesOver)="handleDragFilesOver($event)"
@@ -126,12 +129,19 @@
         type="file"
         class="hidden"
         (change)="handleFileInput($event)"
-        [disabled]="showUrlInput || isUploadInProgress || uploadError"
+        [disabled]="
+          showUrlInput || isUploadInProgress || uploadError || disabled
+        "
       />
     </label>
 
     <div *ngIf="!showUrlInput" class="flex-none mt-2">
-      <gn-ui-button (buttonClick)="displayUrlInput()" type="gray">
+      <gn-ui-button
+        (buttonClick)="displayUrlInput()"
+        type="gray"
+        [disabled]="disabled"
+        [extraClass]="disabled && 'cursor-not-allowed'"
+      >
         <ng-icon class="me-1 text-primary" name="iconoirLink"></ng-icon>
         {{ 'input.image.displayUrlInput' | translate }}
       </gn-ui-button>
@@ -141,7 +151,7 @@
       *ngIf="showUrlInput"
       class="mt-3.5"
       (uploadClick)="downloadUrl($event)"
-      [disabled]="isUploadInProgress"
+      [disabled]="isUploadInProgress || disabled"
     >
     </gn-ui-url-input>
   </div>
diff --git a/libs/ui/inputs/src/lib/image-input/image-input.component.stories.ts b/libs/ui/inputs/src/lib/image-input/image-input.component.stories.ts
index 450f12fa8e..0b463ea0a9 100644
--- a/libs/ui/inputs/src/lib/image-input/image-input.component.stories.ts
+++ b/libs/ui/inputs/src/lib/image-input/image-input.component.stories.ts
@@ -34,6 +34,7 @@ export default {
 export const WithoutImage: StoryObj<ImageInputComponent> = {
   args: {
     maxSizeMB: 5,
+    disabled: false,
   },
   render: (args) => ({
     props: {
@@ -46,7 +47,9 @@ export const WithoutImage: StoryObj<ImageInputComponent> = {
     },
     template: `
     <div style="width: 600px;height: 400px;">
-      <gn-ui-image-input [maxSizeMB]="maxSizeMB"
+      <gn-ui-image-input
+        [maxSizeMB]="maxSizeMB"
+        [disabled]="disabled"
         (fileChange)='fileChange($event)'
         (urlChange)='urlChange($event)'
         (uploadCancel)='uploadCancel($event)'
diff --git a/libs/ui/inputs/src/lib/image-input/image-input.component.ts b/libs/ui/inputs/src/lib/image-input/image-input.component.ts
index 6f403b3f82..1470f03809 100644
--- a/libs/ui/inputs/src/lib/image-input/image-input.component.ts
+++ b/libs/ui/inputs/src/lib/image-input/image-input.component.ts
@@ -67,6 +67,7 @@ export class ImageInputComponent {
   @Input() altText?: string
   @Input() uploadProgress?: number
   @Input() uploadError?: boolean
+  @Input() disabled?: boolean = false
   @Output() fileChange: EventEmitter<File> = new EventEmitter()
   @Output() urlChange: EventEmitter<string> = new EventEmitter()
   @Output() uploadCancel: EventEmitter<void> = new EventEmitter()
diff --git a/libs/ui/inputs/src/lib/switch-toggle/switch-toggle.component.html b/libs/ui/inputs/src/lib/switch-toggle/switch-toggle.component.html
index 5a144886eb..fae6a97a6f 100644
--- a/libs/ui/inputs/src/lib/switch-toggle/switch-toggle.component.html
+++ b/libs/ui/inputs/src/lib/switch-toggle/switch-toggle.component.html
@@ -2,6 +2,7 @@
   #group="matButtonToggleGroup"
   multiple="false"
   class="flex w-full"
+  [disabled]="disabled"
 >
   <mat-button-toggle
     *ngFor="let option of options"
diff --git a/libs/ui/inputs/src/lib/switch-toggle/switch-toggle.component.ts b/libs/ui/inputs/src/lib/switch-toggle/switch-toggle.component.ts
index 4a0df6ba02..60aa7ce397 100644
--- a/libs/ui/inputs/src/lib/switch-toggle/switch-toggle.component.ts
+++ b/libs/ui/inputs/src/lib/switch-toggle/switch-toggle.component.ts
@@ -27,6 +27,7 @@ export class SwitchToggleComponent {
   @Input() options: SwitchToggleOption[]
   @Input() ariaLabel? = ''
   @Input() extraClasses? = ''
+  @Input() disabled? = false
   @Output() selectedValue = new EventEmitter<SwitchToggleOption>()
 
   onChange(selectedOption: SwitchToggleOption) {
diff --git a/libs/ui/inputs/src/lib/switch-toggle/switch-toggle.stories.ts b/libs/ui/inputs/src/lib/switch-toggle/switch-toggle.stories.ts
index a71d587ed0..cdb9e64951 100644
--- a/libs/ui/inputs/src/lib/switch-toggle/switch-toggle.stories.ts
+++ b/libs/ui/inputs/src/lib/switch-toggle/switch-toggle.stories.ts
@@ -34,6 +34,7 @@ export const Primary: StoryObj<SwitchToggleComponent> = {
       { label: 'state', checked: false },
     ],
     extraClasses: 'grow',
+    disabled: false,
   },
   render: (args) => ({
     props: { ...args },

From 90b7acc08e2d19735c7a73f8fce25ae5d6bd764b Mon Sep 17 00:00:00 2001
From: Angelika Kinas <angelika.kinas@camptocamp.com>
Date: Tue, 3 Dec 2024 13:12:41 +0100
Subject: [PATCH 2/9] feat(editor): Use editor facade alreadySavedOnce to
 determine if the record is draft only or not and disable the upload of
 attachments in that case

---
 ...field-online-link-resources.component.html |  95 ++++++-----
 ...m-field-online-link-resources.component.ts |  10 +-
 ...form-field-online-resources.component.html | 149 ++++++++++--------
 .../form-field-online-resources.component.ts  |  10 +-
 .../form-field-overviews.component.html       |  32 ++--
 .../form-field-overviews.component.ts         |  14 +-
 6 files changed, 183 insertions(+), 127 deletions(-)

diff --git a/libs/feature/editor/src/lib/components/record-form/form-field/form-field-online-link-resources/form-field-online-link-resources.component.html b/libs/feature/editor/src/lib/components/record-form/form-field/form-field-online-link-resources/form-field-online-link-resources.component.html
index 7631601886..e29bf0db6a 100644
--- a/libs/feature/editor/src/lib/components/record-form/form-field/form-field-online-link-resources/form-field-online-link-resources.component.html
+++ b/libs/feature/editor/src/lib/components/record-form/form-field/form-field-online-link-resources/form-field-online-link-resources.component.html
@@ -1,44 +1,57 @@
-<gn-ui-file-input
-  [maxSizeMB]="MAX_UPLOAD_SIZE_MB"
-  (fileChange)="handleFileChange($event)"
-  (uploadCancel)="handleUploadCancel()"
-  [uploadProgress]="uploadProgress"
-  (urlChange)="handleUrlChange($event)"
-></gn-ui-file-input>
-<div class="h-[8px]"></div>
-<gn-ui-sortable-list
-  [items]="linkResources"
-  (itemsOrderChange)="handleResourcesChange($event)"
-  [elementTemplate]="template"
->
-</gn-ui-sortable-list>
-<ng-template #template let-onlineResource let-index="index">
-  <gn-ui-online-resource-card
-    [onlineResource]="onlineResource"
-    (modifyClick)="handleResourceModify(onlineResource, index)"
-  ></gn-ui-online-resource-card>
-</ng-template>
+<div class="flex flex-col">
+  <gn-ui-file-input
+    [maxSizeMB]="MAX_UPLOAD_SIZE_MB"
+    (fileChange)="handleFileChange($event)"
+    (uploadCancel)="handleUploadCancel()"
+    [uploadProgress]="uploadProgress"
+    (urlChange)="handleUrlChange($event)"
+    [disabled]="disabled$ | async"
+  ></gn-ui-file-input>
+  <div class="h-[8px]"></div>
+  <gn-ui-sortable-list
+    [items]="linkResources"
+    (itemsOrderChange)="handleResourcesChange($event)"
+    [elementTemplate]="template"
+  >
+  </gn-ui-sortable-list>
+  <ng-template #template let-onlineResource let-index="index">
+    <gn-ui-online-resource-card
+      [onlineResource]="onlineResource"
+      (modifyClick)="handleResourceModify(onlineResource, index)"
+    ></gn-ui-online-resource-card>
+  </ng-template>
 
-<ng-template #dialogTemplate let-onlineResource>
-  <div class="flex flex-col gap-[16px]">
-    <div>
-      <h3 class="text-[16px] font-bold text-main mb-[12px]" translate>
-        editor.record.form.field.onlineResource.edit.title
-      </h3>
-      <gn-ui-text-input [(value)]="onlineResource.name"></gn-ui-text-input>
+  <ng-template #dialogTemplate let-onlineResource>
+    <div class="flex flex-col gap-[16px]">
+      <div>
+        <h3 class="text-[16px] font-bold text-main mb-[12px]" translate>
+          editor.record.form.field.onlineResource.edit.title
+        </h3>
+        <gn-ui-text-input [(value)]="onlineResource.name"></gn-ui-text-input>
+      </div>
+      <div>
+        <h3 class="text-[16px] font-bold text-main mb-[12px]" translate>
+          editor.record.form.field.onlineResource.edit.description
+        </h3>
+        <gn-ui-text-area
+          [(value)]="onlineResource.description"
+        ></gn-ui-text-area>
+      </div>
+      <span class="w-full border-b border-gray-300"></span>
+      <gn-ui-url-input
+        class="w-full"
+        [disabled]="true"
+        [value]="onlineResource.url"
+        [showUploadButton]="false"
+        [disabled]="disabled$ | async"
+      ></gn-ui-url-input>
     </div>
-    <div>
-      <h3 class="text-[16px] font-bold text-main mb-[12px]" translate>
-        editor.record.form.field.onlineResource.edit.description
-      </h3>
-      <gn-ui-text-area [(value)]="onlineResource.description"></gn-ui-text-area>
-    </div>
-    <span class="w-full border-b border-gray-300"></span>
-    <gn-ui-url-input
-      class="w-full"
-      [disabled]="true"
-      [value]="onlineResource.url"
-      [showUploadButton]="false"
-    ></gn-ui-url-input>
+  </ng-template>
+  <div
+    *ngIf="disabled$ | async"
+    class="p-4 text-sm border border-primary bg-primary-lightest rounded-lg"
+    translate
+  >
+    editor.record.form.field.draft.only.disabled
   </div>
-</ng-template>
+</div>
diff --git a/libs/feature/editor/src/lib/components/record-form/form-field/form-field-online-link-resources/form-field-online-link-resources.component.ts b/libs/feature/editor/src/lib/components/record-form/form-field/form-field-online-link-resources/form-field-online-link-resources.component.ts
index 3000324226..44fc6d5e79 100644
--- a/libs/feature/editor/src/lib/components/record-form/form-field/form-field-online-link-resources/form-field-online-link-resources.component.ts
+++ b/libs/feature/editor/src/lib/components/record-form/form-field/form-field-online-link-resources/form-field-online-link-resources.component.ts
@@ -27,9 +27,10 @@ import {
 import { NotificationsService } from '@geonetwork-ui/feature/notifications'
 import { TranslateModule, TranslateService } from '@ngx-translate/core'
 import { PlatformServiceInterface } from '@geonetwork-ui/common/domain/platform.service.interface'
-import { Subscription } from 'rxjs'
+import { map, Subscription } from 'rxjs'
 import { MatDialog } from '@angular/material/dialog'
 import { MAX_UPLOAD_SIZE_MB } from '../../../../fields.config'
+import { EditorFacade } from '../../../../+state/editor.facade'
 
 @Component({
   selector: 'gn-ui-form-field-online-link-resources',
@@ -68,12 +69,17 @@ export class FormFieldOnlineLinkResourcesComponent {
 
   protected MAX_UPLOAD_SIZE_MB = MAX_UPLOAD_SIZE_MB
 
+  disabled$ = this.editorFacade.alreadySavedOnce$.pipe(
+    map((alreadySavedOnce) => !alreadySavedOnce)
+  )
+
   constructor(
     private notificationsService: NotificationsService,
     private translateService: TranslateService,
     private platformService: PlatformServiceInterface,
     private cd: ChangeDetectorRef,
-    private dialog: MatDialog
+    private dialog: MatDialog,
+    private editorFacade: EditorFacade
   ) {}
 
   handleFileChange(file: File) {
diff --git a/libs/feature/editor/src/lib/components/record-form/form-field/form-field-online-resources/form-field-online-resources.component.html b/libs/feature/editor/src/lib/components/record-form/form-field/form-field-online-resources/form-field-online-resources.component.html
index d8c6a7367b..5ba8d4c445 100644
--- a/libs/feature/editor/src/lib/components/record-form/form-field/form-field-online-resources/form-field-online-resources.component.html
+++ b/libs/feature/editor/src/lib/components/record-form/form-field/form-field-online-resources/form-field-online-resources.component.html
@@ -1,72 +1,87 @@
-<gn-ui-switch-toggle
-  [options]="typeOptions"
-  (selectedValue)="onSelectedTypeChange($event.value)"
-  extraClasses="grow text-sm"
-  data-cy="online-resources-type"
-></gn-ui-switch-toggle>
-<div class="h-[8px]"></div>
-<gn-ui-file-input
-  *ngIf="selectedType === 'download'"
-  [maxSizeMB]="MAX_UPLOAD_SIZE_MB"
-  (fileChange)="handleFileChange($event)"
-  (uploadCancel)="handleUploadCancel()"
-  [uploadProgress]="uploadProgress"
-  (urlChange)="handleDownloadUrlChange($event)"
-></gn-ui-file-input>
-<div
-  *ngIf="selectedType === 'service'"
-  class="w-full border-2 border-dashed rounded-lg p-6 flex flex-col gap-[16px]"
->
-  <gn-ui-online-service-resource-input
-    [service]="newService"
-  ></gn-ui-online-service-resource-input>
-  <span class="w-full border-b border-gray-300"></span>
-  <gn-ui-url-input
-    class="w-full"
-    [urlCanParse]="true"
-    (uploadClick)="handleServiceUrlChange($event)"
-  ></gn-ui-url-input>
-</div>
-<div class="h-[8px]"></div>
-<gn-ui-sortable-list
-  [items]="notLinkResources"
-  (itemsOrderChange)="handleResourcesChange($event)"
-  [elementTemplate]="template"
->
-</gn-ui-sortable-list>
-<ng-template #template let-onlineResource let-index="index">
-  <gn-ui-online-resource-card
-    [onlineResource]="onlineResource"
-    (modifyClick)="handleResourceModify(onlineResource, index)"
-  ></gn-ui-online-resource-card>
-</ng-template>
-
-<ng-template #dialogTemplate let-onlineResource>
-  <div class="flex flex-col gap-[16px]">
-    <div>
-      <h3 class="text-[16px] font-bold text-main mb-[12px]" translate>
-        editor.record.form.field.onlineResource.edit.title
-      </h3>
-      <gn-ui-text-input [(value)]="onlineResource.name"></gn-ui-text-input>
-    </div>
-    <div>
-      <h3 class="text-[16px] font-bold text-main mb-[12px]" translate>
-        editor.record.form.field.onlineResource.edit.description
-      </h3>
-      <gn-ui-text-area [(value)]="onlineResource.description"></gn-ui-text-area>
-    </div>
-    <ng-container *ngIf="onlineResource.type === 'service'">
-      <span class="w-full border-b border-gray-300"></span>
-      <gn-ui-online-service-resource-input
-        [service]="onlineResource"
-      ></gn-ui-online-service-resource-input>
-    </ng-container>
+<div class="flex flex-col">
+  <gn-ui-switch-toggle
+    [options]="typeOptions"
+    (selectedValue)="onSelectedTypeChange($event.value)"
+    extraClasses="grow text-sm"
+    data-cy="online-resources-type"
+    [disabled]="disabled$ | async"
+  ></gn-ui-switch-toggle>
+  <div class="h-[8px]"></div>
+  <gn-ui-file-input
+    *ngIf="selectedType === 'download'"
+    [maxSizeMB]="MAX_UPLOAD_SIZE_MB"
+    (fileChange)="handleFileChange($event)"
+    (uploadCancel)="handleUploadCancel()"
+    [uploadProgress]="uploadProgress"
+    (urlChange)="handleDownloadUrlChange($event)"
+    [disabled]="disabled$ | async"
+  ></gn-ui-file-input>
+  <div
+    *ngIf="selectedType === 'service'"
+    class="w-full border-2 border-dashed rounded-lg p-6 flex flex-col gap-[16px]"
+  >
+    <gn-ui-online-service-resource-input
+      [service]="newService"
+      [disabled]="disabled$ | async"
+    ></gn-ui-online-service-resource-input>
     <span class="w-full border-b border-gray-300"></span>
     <gn-ui-url-input
       class="w-full"
-      [disabled]="true"
-      [value]="onlineResource.url"
-      [showUploadButton]="false"
+      (uploadClick)="handleServiceUrlChange($event)"
+      [disabled]="disabled$ | async"
     ></gn-ui-url-input>
   </div>
-</ng-template>
+  <div class="h-[8px]"></div>
+  <gn-ui-sortable-list
+    [items]="notLinkResources"
+    (itemsOrderChange)="handleResourcesChange($event)"
+    [elementTemplate]="template"
+  >
+  </gn-ui-sortable-list>
+  <ng-template #template let-onlineResource let-index="index">
+    <gn-ui-online-resource-card
+      [onlineResource]="onlineResource"
+      (modifyClick)="handleResourceModify(onlineResource, index)"
+    ></gn-ui-online-resource-card>
+  </ng-template>
+
+  <ng-template #dialogTemplate let-onlineResource>
+    <div class="flex flex-col gap-[16px]">
+      <div>
+        <h3 class="text-[16px] font-bold text-main mb-[12px]" translate>
+          editor.record.form.field.onlineResource.edit.title
+        </h3>
+        <gn-ui-text-input [(value)]="onlineResource.name"></gn-ui-text-input>
+      </div>
+      <div>
+        <h3 class="text-[16px] font-bold text-main mb-[12px]" translate>
+          editor.record.form.field.onlineResource.edit.description
+        </h3>
+        <gn-ui-text-area
+          [(value)]="onlineResource.description"
+        ></gn-ui-text-area>
+      </div>
+      <ng-container *ngIf="onlineResource.type === 'service'">
+        <span class="w-full border-b border-gray-300"></span>
+        <gn-ui-online-service-resource-input
+          [service]="onlineResource"
+          [disabled]="disabled$ | async"
+        ></gn-ui-online-service-resource-input>
+      </ng-container>
+      <span class="w-full border-b border-gray-300"></span>
+      <gn-ui-url-input
+        class="w-full"
+        [disabled]="true"
+        [value]="onlineResource.url"
+        [showUploadButton]="false"
+      ></gn-ui-url-input>
+    </div>
+  </ng-template>
+  <div
+    *ngIf="disabled$ | async"
+    class="p-4 text-sm border border-primary bg-primary-lightest rounded-lg"
+    translate
+  >
+    editor.record.form.field.draft.only.disabled
+  </div>
+</div>
diff --git a/libs/feature/editor/src/lib/components/record-form/form-field/form-field-online-resources/form-field-online-resources.component.ts b/libs/feature/editor/src/lib/components/record-form/form-field/form-field-online-resources/form-field-online-resources.component.ts
index 6079095018..5e87060b09 100644
--- a/libs/feature/editor/src/lib/components/record-form/form-field/form-field-online-resources/form-field-online-resources.component.ts
+++ b/libs/feature/editor/src/lib/components/record-form/form-field/form-field-online-resources/form-field-online-resources.component.ts
@@ -32,10 +32,11 @@ import {
   SortableListComponent,
 } from '@geonetwork-ui/ui/layout'
 import { TranslateModule, TranslateService } from '@ngx-translate/core'
-import { Subscription } from 'rxjs'
+import { map, Subscription } from 'rxjs'
 import { MAX_UPLOAD_SIZE_MB } from '../../../../fields.config'
 import { OnlineResourceCardComponent } from '../../../online-resource-card/online-resource-card.component'
 import { OnlineServiceResourceInputComponent } from '../../../online-service-resource-input/online-service-resource-input.component'
+import { EditorFacade } from '../../../../+state/editor.facade'
 
 type OnlineNotLinkResource =
   | DatasetDownloadDistribution
@@ -100,12 +101,17 @@ export class FormFieldOnlineResourcesComponent {
 
   protected MAX_UPLOAD_SIZE_MB = MAX_UPLOAD_SIZE_MB
 
+  disabled$ = this.editorFacade.alreadySavedOnce$.pipe(
+    map((alreadySavedOnce) => !alreadySavedOnce)
+  )
+
   constructor(
     private notificationsService: NotificationsService,
     private translateService: TranslateService,
     private platformService: PlatformServiceInterface,
     private cd: ChangeDetectorRef,
-    private dialog: MatDialog
+    private dialog: MatDialog,
+    private editorFacade: EditorFacade
   ) {}
 
   onSelectedTypeChange(selectedType: unknown) {
diff --git a/libs/feature/editor/src/lib/components/record-form/form-field/form-field-overviews/form-field-overviews.component.html b/libs/feature/editor/src/lib/components/record-form/form-field/form-field-overviews/form-field-overviews.component.html
index 0e10c3e88c..51ec69c759 100644
--- a/libs/feature/editor/src/lib/components/record-form/form-field/form-field-overviews/form-field-overviews.component.html
+++ b/libs/feature/editor/src/lib/components/record-form/form-field/form-field-overviews/form-field-overviews.component.html
@@ -1,11 +1,21 @@
-<gn-ui-image-input
-  [maxSizeMB]="MAX_UPLOAD_SIZE_MB"
-  [previewUrl]="firstOverview.url"
-  [altText]="firstOverview.description"
-  (fileChange)="handleFileChange($event)"
-  (urlChange)="handleUrlChange($event)"
-  (altTextChange)="handleAltTextChange($event)"
-  (delete)="handleDelete()"
-  [uploadProgress]="uploadProgress"
-  (uploadCancel)="handleUploadCancel()"
-></gn-ui-image-input>
+<div class="flex flex-col gap-2">
+  <gn-ui-image-input
+    [maxSizeMB]="MAX_UPLOAD_SIZE_MB"
+    [previewUrl]="firstOverview.url"
+    [altText]="firstOverview.description"
+    (fileChange)="handleFileChange($event)"
+    (urlChange)="handleUrlChange($event)"
+    (altTextChange)="handleAltTextChange($event)"
+    (delete)="handleDelete()"
+    [uploadProgress]="uploadProgress"
+    (uploadCancel)="handleUploadCancel()"
+    [disabled]="disabled$ | async"
+  ></gn-ui-image-input>
+  <div
+    *ngIf="disabled$ | async"
+    class="p-4 text-sm border border-primary bg-primary-lightest rounded-lg"
+    translate
+  >
+    editor.record.form.field.draft.only.disabled
+  </div>
+</div>
diff --git a/libs/feature/editor/src/lib/components/record-form/form-field/form-field-overviews/form-field-overviews.component.ts b/libs/feature/editor/src/lib/components/record-form/form-field/form-field-overviews/form-field-overviews.component.ts
index ae56250a87..f2af52dc5e 100644
--- a/libs/feature/editor/src/lib/components/record-form/form-field/form-field-overviews/form-field-overviews.component.ts
+++ b/libs/feature/editor/src/lib/components/record-form/form-field/form-field-overviews/form-field-overviews.component.ts
@@ -11,9 +11,10 @@ import { GraphicOverview } from '@geonetwork-ui/common/domain/model/record'
 import { ImageInputComponent } from '@geonetwork-ui/ui/inputs'
 import { PlatformServiceInterface } from '@geonetwork-ui/common/domain/platform.service.interface'
 import { NotificationsService } from '@geonetwork-ui/feature/notifications'
-import { TranslateService } from '@ngx-translate/core'
-import { Subscription } from 'rxjs'
+import { TranslateModule, TranslateService } from '@ngx-translate/core'
+import { map, Subscription } from 'rxjs'
 import { MAX_UPLOAD_SIZE_MB } from '../../../../fields.config'
+import { EditorFacade } from '../../../../+state/editor.facade'
 
 @Component({
   selector: 'gn-ui-form-field-overviews',
@@ -21,7 +22,7 @@ import { MAX_UPLOAD_SIZE_MB } from '../../../../fields.config'
   styleUrls: ['./form-field-overviews.component.css'],
   changeDetection: ChangeDetectionStrategy.OnPush,
   standalone: true,
-  imports: [CommonModule, ImageInputComponent],
+  imports: [CommonModule, ImageInputComponent, TranslateModule],
 })
 export class FormFieldOverviewsComponent {
   @Input() metadataUuid: string
@@ -29,6 +30,10 @@ export class FormFieldOverviewsComponent {
   @Output() valueChange: EventEmitter<Array<GraphicOverview>> =
     new EventEmitter()
 
+  disabled$ = this.editorFacade.alreadySavedOnce$.pipe(
+    map((alreadySavedOnce) => !alreadySavedOnce)
+  )
+
   uploadProgress = undefined
   uploadSubscription: Subscription = null
 
@@ -47,7 +52,8 @@ export class FormFieldOverviewsComponent {
     private platformService: PlatformServiceInterface,
     private notificationsService: NotificationsService,
     private translateService: TranslateService,
-    private cd: ChangeDetectorRef
+    private cd: ChangeDetectorRef,
+    private editorFacade: EditorFacade
   ) {}
 
   handleFileChange(file: File) {

From 35e7ab2457ceed8c451c10806502285b28bd5607 Mon Sep 17 00:00:00 2001
From: Angelika Kinas <angelika.kinas@camptocamp.com>
Date: Tue, 3 Dec 2024 13:16:40 +0100
Subject: [PATCH 3/9] chore(i18n): update translations

---
 translations/de.json | 2 +-
 translations/en.json | 2 +-
 translations/es.json | 2 +-
 translations/fr.json | 2 +-
 translations/it.json | 2 +-
 translations/nl.json | 2 +-
 translations/pt.json | 2 +-
 translations/sk.json | 2 +-
 8 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/translations/de.json b/translations/de.json
index 28414b901d..7f725a4a75 100644
--- a/translations/de.json
+++ b/translations/de.json
@@ -26,7 +26,6 @@
   "dashboard.importRecord": "",
   "dashboard.importRecord.importExternal": "",
   "dashboard.importRecord.importExternalLabel": "",
-  "dashboard.importRecord.useModel": "",
   "dashboard.labels.catalog": "Katalog",
   "dashboard.labels.mySpace": "Mein Bereich",
   "dashboard.records.all": "Metadatenkatalog",
@@ -216,6 +215,7 @@
   "editor.record.form.field.constraintsShortcuts": "",
   "editor.record.form.field.contacts.noContact": "",
   "editor.record.form.field.contactsForResource.noContact": "",
+  "editor.record.form.field.draft.only.disabled": "Dieses Feld wird aktiviert, sobald die Daten veröffentlicht wurden.",
   "editor.record.form.field.keywords": "Schlagwörter",
   "editor.record.form.field.legalConstraints": "Rechtliche Einschränkung",
   "editor.record.form.field.license": "Lizenz",
diff --git a/translations/en.json b/translations/en.json
index 62ea740aaa..9f1e8218da 100644
--- a/translations/en.json
+++ b/translations/en.json
@@ -26,7 +26,6 @@
   "dashboard.importRecord": "Import",
   "dashboard.importRecord.importExternal": "Import an external file",
   "dashboard.importRecord.importExternalLabel": "External file URL",
-  "dashboard.importRecord.useModel": "Use a model",
   "dashboard.labels.catalog": "Catalog",
   "dashboard.labels.mySpace": "My space",
   "dashboard.records.all": "Metadata records",
@@ -216,6 +215,7 @@
   "editor.record.form.field.constraintsShortcuts": "",
   "editor.record.form.field.contacts.noContact": "Please provide at least one point of contact.",
   "editor.record.form.field.contactsForResource.noContact": "Please provide at least one point of contact responsible for the data.",
+  "editor.record.form.field.draft.only.disabled": "This field will be enabled once published",
   "editor.record.form.field.keywords": "Keywords",
   "editor.record.form.field.legalConstraints": "Legal constraint",
   "editor.record.form.field.license": "License",
diff --git a/translations/es.json b/translations/es.json
index 5f21daf824..07de708576 100644
--- a/translations/es.json
+++ b/translations/es.json
@@ -26,7 +26,6 @@
   "dashboard.importRecord": "",
   "dashboard.importRecord.importExternal": "",
   "dashboard.importRecord.importExternalLabel": "",
-  "dashboard.importRecord.useModel": "",
   "dashboard.labels.catalog": "Catálogo",
   "dashboard.labels.mySpace": "Mi espacio",
   "dashboard.records.all": "Catálogo",
@@ -216,6 +215,7 @@
   "editor.record.form.field.constraintsShortcuts": "",
   "editor.record.form.field.contacts.noContact": "",
   "editor.record.form.field.contactsForResource.noContact": "",
+  "editor.record.form.field.draft.only.disabled": "",
   "editor.record.form.field.keywords": "",
   "editor.record.form.field.legalConstraints": "",
   "editor.record.form.field.license": "",
diff --git a/translations/fr.json b/translations/fr.json
index 612edba300..1aac8312ee 100644
--- a/translations/fr.json
+++ b/translations/fr.json
@@ -26,7 +26,6 @@
   "dashboard.importRecord": "Importer",
   "dashboard.importRecord.importExternal": "Importer une fiche externe",
   "dashboard.importRecord.importExternalLabel": "URL de la fiche externe",
-  "dashboard.importRecord.useModel": "Utiliser un modèle",
   "dashboard.labels.catalog": "Catalogue",
   "dashboard.labels.mySpace": "Mon espace",
   "dashboard.records.all": "Fiches de métadonnées",
@@ -216,6 +215,7 @@
   "editor.record.form.field.constraintsShortcuts": "",
   "editor.record.form.field.contacts.noContact": "Veuillez renseigner au moins un point de contact.",
   "editor.record.form.field.contactsForResource.noContact": "Veuillez renseigner au moins un point de contact responsable de la donnée.",
+  "editor.record.form.field.draft.only.disabled": "",
   "editor.record.form.field.keywords": "Mots-clés",
   "editor.record.form.field.legalConstraints": "Contrainte légale",
   "editor.record.form.field.license": "Licence",
diff --git a/translations/it.json b/translations/it.json
index faaa3ae872..68b30d3d33 100644
--- a/translations/it.json
+++ b/translations/it.json
@@ -26,7 +26,6 @@
   "dashboard.importRecord": "",
   "dashboard.importRecord.importExternal": "",
   "dashboard.importRecord.importExternalLabel": "",
-  "dashboard.importRecord.useModel": "",
   "dashboard.labels.catalog": "Catalogo",
   "dashboard.labels.mySpace": "Il mio spazio",
   "dashboard.records.all": "Catalogo",
@@ -216,6 +215,7 @@
   "editor.record.form.field.constraintsShortcuts": "",
   "editor.record.form.field.contacts.noContact": "",
   "editor.record.form.field.contactsForResource.noContact": "",
+  "editor.record.form.field.draft.only.disabled": "",
   "editor.record.form.field.keywords": "",
   "editor.record.form.field.legalConstraints": "",
   "editor.record.form.field.license": "Licenza",
diff --git a/translations/nl.json b/translations/nl.json
index ef84e7e547..10600d5903 100644
--- a/translations/nl.json
+++ b/translations/nl.json
@@ -26,7 +26,6 @@
   "dashboard.importRecord": "",
   "dashboard.importRecord.importExternal": "",
   "dashboard.importRecord.importExternalLabel": "",
-  "dashboard.importRecord.useModel": "",
   "dashboard.labels.catalog": "Catalogus",
   "dashboard.labels.mySpace": "Mijn ruimte",
   "dashboard.records.all": "Catalogus",
@@ -216,6 +215,7 @@
   "editor.record.form.field.constraintsShortcuts": "",
   "editor.record.form.field.contacts.noContact": "",
   "editor.record.form.field.contactsForResource.noContact": "",
+  "editor.record.form.field.draft.only.disabled": "",
   "editor.record.form.field.keywords": "",
   "editor.record.form.field.legalConstraints": "",
   "editor.record.form.field.license": "",
diff --git a/translations/pt.json b/translations/pt.json
index 1144fb5dc4..95862d9370 100644
--- a/translations/pt.json
+++ b/translations/pt.json
@@ -26,7 +26,6 @@
   "dashboard.importRecord": "",
   "dashboard.importRecord.importExternal": "",
   "dashboard.importRecord.importExternalLabel": "",
-  "dashboard.importRecord.useModel": "",
   "dashboard.labels.catalog": "Catálogo",
   "dashboard.labels.mySpace": "Meu espaço",
   "dashboard.records.all": "Catálogo",
@@ -216,6 +215,7 @@
   "editor.record.form.field.constraintsShortcuts": "",
   "editor.record.form.field.contacts.noContact": "",
   "editor.record.form.field.contactsForResource.noContact": "",
+  "editor.record.form.field.draft.only.disabled": "",
   "editor.record.form.field.keywords": "",
   "editor.record.form.field.legalConstraints": "",
   "editor.record.form.field.license": "",
diff --git a/translations/sk.json b/translations/sk.json
index 3cfbb37587..d6d57f9d49 100644
--- a/translations/sk.json
+++ b/translations/sk.json
@@ -26,7 +26,6 @@
   "dashboard.importRecord": "",
   "dashboard.importRecord.importExternal": "",
   "dashboard.importRecord.importExternalLabel": "",
-  "dashboard.importRecord.useModel": "",
   "dashboard.labels.catalog": "Katalóg",
   "dashboard.labels.mySpace": "Môj priestor",
   "dashboard.records.all": "Katalóg",
@@ -216,6 +215,7 @@
   "editor.record.form.field.constraintsShortcuts": "",
   "editor.record.form.field.contacts.noContact": "",
   "editor.record.form.field.contactsForResource.noContact": "",
+  "editor.record.form.field.draft.only.disabled": "",
   "editor.record.form.field.keywords": "",
   "editor.record.form.field.legalConstraints": "",
   "editor.record.form.field.license": "Licencia",

From 1fcc068cebd1bf076bc710ad16b906268f507380 Mon Sep 17 00:00:00 2001
From: Angelika Kinas <angelika.kinas@camptocamp.com>
Date: Tue, 3 Dec 2024 13:17:09 +0100
Subject: [PATCH 4/9] chore(editor): change text size of banner in contacts
 form field

---
 .../form-field-contacts/form-field-contacts.component.html      | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libs/feature/editor/src/lib/components/record-form/form-field/form-field-contacts/form-field-contacts.component.html b/libs/feature/editor/src/lib/components/record-form/form-field/form-field-contacts/form-field-contacts.component.html
index 822ed4b9fb..11801f5ae8 100644
--- a/libs/feature/editor/src/lib/components/record-form/form-field/form-field-contacts/form-field-contacts.component.html
+++ b/libs/feature/editor/src/lib/components/record-form/form-field/form-field-contacts/form-field-contacts.component.html
@@ -32,7 +32,7 @@
 
 <ng-template #noContact>
   <div
-    class="p-4 border border-primary bg-primary-lightest rounded-lg"
+    class="p-4 text-sm border border-primary bg-primary-lightest rounded-lg"
     translate
   >
     editor.record.form.field.contacts.noContact

From 6a5ceac141081e967d678aaf9e1e7619475bfe87 Mon Sep 17 00:00:00 2001
From: Angelika Kinas <angelika.kinas@camptocamp.com>
Date: Tue, 3 Dec 2024 13:17:56 +0100
Subject: [PATCH 5/9] feat(metadata-editor-e2e): add test for disabled
 attachment upload to draft only

---
 .../src/e2e/record-actions.cy.ts              | 37 +++++++++++++++++++
 1 file changed, 37 insertions(+)

diff --git a/apps/metadata-editor-e2e/src/e2e/record-actions.cy.ts b/apps/metadata-editor-e2e/src/e2e/record-actions.cy.ts
index 6bbe256f0b..063e8849ef 100644
--- a/apps/metadata-editor-e2e/src/e2e/record-actions.cy.ts
+++ b/apps/metadata-editor-e2e/src/e2e/record-actions.cy.ts
@@ -114,6 +114,43 @@ describe('record-actions', () => {
         .should('contain.text', 'Next')
     })
 
+    it.only('the created record should not allow upload of resources and show info message as it was not saved yet', () => {
+      // first page
+      cy.get('gn-ui-form-field-overviews')
+        .find('gn-ui-image-input')
+        .find('input')
+        .should('be.disabled')
+      cy.get('gn-ui-form-field-overviews')
+        .children()
+        .find('div')
+        .should('contain.text', ' This field will be enabled once published ')
+
+      // second page
+      cy.get('[data-test="previousNextPageButtons"]')
+        .children()
+        .eq(1)
+        .should('contain.text', 'Next')
+        .click()
+      cy.get('gn-ui-form-field-online-resources')
+        .find('gn-ui-switch-toggle')
+        .find('mat-button-toggle-group')
+        .find('button')
+        .should('be.disabled')
+      cy.get('gn-ui-file-input').find('input').should('be.disabled')
+      cy.get('gn-ui-form-field-online-resources')
+        .children()
+        .find('div')
+        .should('contain.text', ' This field will be enabled once published ')
+
+      cy.get('gn-ui-form-field-online-link-resources')
+        .find('input')
+        .should('be.disabled')
+      cy.get('gn-ui-form-field-online-link-resources')
+        .children()
+        .find('div')
+        .should('contain.text', ' This field will be enabled once published ')
+    })
+
     it('back navigation should go to search after creating a record', () => {
       cy.go('back')
       cy.url().should('include', '/catalog/search')

From b7e25d39788c653a82fbf12b1d5140f80a22ea36 Mon Sep 17 00:00:00 2001
From: Angelika Kinas <angelika.kinas@camptocamp.com>
Date: Tue, 3 Dec 2024 13:40:25 +0100
Subject: [PATCH 6/9] chore: Remove only from e2e test

---
 apps/metadata-editor-e2e/src/e2e/record-actions.cy.ts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/apps/metadata-editor-e2e/src/e2e/record-actions.cy.ts b/apps/metadata-editor-e2e/src/e2e/record-actions.cy.ts
index 063e8849ef..94d6281f07 100644
--- a/apps/metadata-editor-e2e/src/e2e/record-actions.cy.ts
+++ b/apps/metadata-editor-e2e/src/e2e/record-actions.cy.ts
@@ -114,7 +114,7 @@ describe('record-actions', () => {
         .should('contain.text', 'Next')
     })
 
-    it.only('the created record should not allow upload of resources and show info message as it was not saved yet', () => {
+    it('the created record should not allow upload of resources and show info message as it was not saved yet', () => {
       // first page
       cy.get('gn-ui-form-field-overviews')
         .find('gn-ui-image-input')

From b7b4c35f89b8cde6bd82bef9cec9f6bc497eb226 Mon Sep 17 00:00:00 2001
From: Angelika Kinas <angelika.kinas@camptocamp.com>
Date: Tue, 3 Dec 2024 14:03:24 +0100
Subject: [PATCH 7/9] chore: Provide EditorFacadeMock to unit test

---
 .../form-field-online-link-resources.component.spec.ts     | 6 ++++++
 .../form-field-online-resources.component.spec.ts          | 7 ++++++-
 .../form-field-overviews.component.spec.ts                 | 6 ++++++
 3 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/libs/feature/editor/src/lib/components/record-form/form-field/form-field-online-link-resources/form-field-online-link-resources.component.spec.ts b/libs/feature/editor/src/lib/components/record-form/form-field/form-field-online-link-resources/form-field-online-link-resources.component.spec.ts
index ce65f266c4..353287971e 100644
--- a/libs/feature/editor/src/lib/components/record-form/form-field/form-field-online-link-resources/form-field-online-link-resources.component.spec.ts
+++ b/libs/feature/editor/src/lib/components/record-form/form-field/form-field-online-link-resources/form-field-online-link-resources.component.spec.ts
@@ -13,6 +13,7 @@ import { MatDialog, MatDialogRef } from '@angular/material/dialog'
 import { OnlineLinkResource } from '@geonetwork-ui/common/domain/model/record'
 import { ModalDialogComponent } from '@geonetwork-ui/ui/layout'
 import { ChangeDetectorRef } from '@angular/core'
+import { EditorFacade } from '../../../../+state/editor.facade'
 
 let uploadSubject: Subject<any>
 
@@ -38,6 +39,10 @@ export class MatDialogMock {
   }))
 }
 
+class EditorFacadeMock {
+  alreadySavedOnce$ = new BehaviorSubject(false)
+}
+
 describe('FormFieldOnlineLinkResourcesComponent', () => {
   let component: FormFieldOnlineLinkResourcesComponent
   let fixture: ComponentFixture<FormFieldOnlineLinkResourcesComponent>
@@ -65,6 +70,7 @@ describe('FormFieldOnlineLinkResourcesComponent', () => {
           detectChanges: jest.fn(),
         }),
         MockProvider(MatDialog, MatDialogMock, 'useClass'),
+        MockProvider(EditorFacade, EditorFacadeMock, 'useClass'),
       ],
     }).compileComponents()
 
diff --git a/libs/feature/editor/src/lib/components/record-form/form-field/form-field-online-resources/form-field-online-resources.component.spec.ts b/libs/feature/editor/src/lib/components/record-form/form-field/form-field-online-resources/form-field-online-resources.component.spec.ts
index 307a0d5a62..46d35577d5 100644
--- a/libs/feature/editor/src/lib/components/record-form/form-field/form-field-online-resources/form-field-online-resources.component.spec.ts
+++ b/libs/feature/editor/src/lib/components/record-form/form-field/form-field-online-resources/form-field-online-resources.component.spec.ts
@@ -2,10 +2,11 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'
 import { TranslateModule } from '@ngx-translate/core'
 import { FormFieldOnlineResourcesComponent } from './form-field-online-resources.component'
 import { MockBuilder, MockProvider } from 'ng-mocks'
-import { Subject } from 'rxjs'
+import { BehaviorSubject, Subject } from 'rxjs'
 import { PlatformServiceInterface } from '@geonetwork-ui/common/domain/platform.service.interface'
 import { NotificationsService } from '@geonetwork-ui/feature/notifications'
 import { MatDialog, MatDialogRef } from '@angular/material/dialog'
+import { EditorFacade } from '../../../../+state/editor.facade'
 
 let uploadSubject: Subject<any>
 class PlatformServiceInterfaceMock {
@@ -21,6 +22,9 @@ export class MatDialogMock {
     afterClosed: () => this._subject,
   }))
 }
+class EditorFacadeMock {
+  alreadySavedOnce$ = new BehaviorSubject(false)
+}
 
 describe('FormFieldOnlineResourcesComponent', () => {
   let component: FormFieldOnlineResourcesComponent
@@ -42,6 +46,7 @@ describe('FormFieldOnlineResourcesComponent', () => {
         MockProvider(NotificationsService),
         MockProvider(MatDialogRef),
         MockProvider(MatDialog, MatDialogMock, 'useClass'),
+        MockProvider(EditorFacade, EditorFacadeMock, 'useClass'),
       ],
     }).compileComponents()
 
diff --git a/libs/feature/editor/src/lib/components/record-form/form-field/form-field-overviews/form-field-overviews.component.spec.ts b/libs/feature/editor/src/lib/components/record-form/form-field/form-field-overviews/form-field-overviews.component.spec.ts
index a18dab7012..6412f56944 100644
--- a/libs/feature/editor/src/lib/components/record-form/form-field/form-field-overviews/form-field-overviews.component.spec.ts
+++ b/libs/feature/editor/src/lib/components/record-form/form-field/form-field-overviews/form-field-overviews.component.spec.ts
@@ -8,6 +8,7 @@ import {
   PlatformServiceInterface,
   RecordAttachment,
 } from '@geonetwork-ui/common/domain/platform.service.interface'
+import { EditorFacade } from '../../../../+state/editor.facade'
 
 let uploadSubject: Subject<any>
 
@@ -26,6 +27,10 @@ class PlatformServiceInterfaceMock {
   getRecordAttachments = jest.fn(() => recordAttachments)
 }
 
+class EditorFacadeMock {
+  alreadySavedOnce$ = new BehaviorSubject(false)
+}
+
 describe('FormFieldOverviewsComponent', () => {
   let component: FormFieldOverviewsComponent
   let fixture: ComponentFixture<FormFieldOverviewsComponent>
@@ -46,6 +51,7 @@ describe('FormFieldOverviewsComponent', () => {
           'useClass'
         ),
         MockProvider(NotificationsService),
+        MockProvider(EditorFacade, EditorFacadeMock, 'useClass'),
       ],
     }).compileComponents()
 

From daa822248fc78709734d0f9b4b00167038142467 Mon Sep 17 00:00:00 2001
From: Angelika Kinas <angelika.kinas@camptocamp.com>
Date: Thu, 12 Dec 2024 10:38:54 +0100
Subject: [PATCH 8/9] chore: fix translations

---
 translations/en.json | 2 +-
 translations/fr.json | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/translations/en.json b/translations/en.json
index 9f1e8218da..7af7b10f44 100644
--- a/translations/en.json
+++ b/translations/en.json
@@ -215,7 +215,7 @@
   "editor.record.form.field.constraintsShortcuts": "",
   "editor.record.form.field.contacts.noContact": "Please provide at least one point of contact.",
   "editor.record.form.field.contactsForResource.noContact": "Please provide at least one point of contact responsible for the data.",
-  "editor.record.form.field.draft.only.disabled": "This field will be enabled once published",
+  "editor.record.form.field.draft.only.disabled": "This field will be enabled once the data has been published",
   "editor.record.form.field.keywords": "Keywords",
   "editor.record.form.field.legalConstraints": "Legal constraint",
   "editor.record.form.field.license": "License",
diff --git a/translations/fr.json b/translations/fr.json
index 1aac8312ee..bfc7aa2320 100644
--- a/translations/fr.json
+++ b/translations/fr.json
@@ -215,7 +215,7 @@
   "editor.record.form.field.constraintsShortcuts": "",
   "editor.record.form.field.contacts.noContact": "Veuillez renseigner au moins un point de contact.",
   "editor.record.form.field.contactsForResource.noContact": "Veuillez renseigner au moins un point de contact responsable de la donnée.",
-  "editor.record.form.field.draft.only.disabled": "",
+  "editor.record.form.field.draft.only.disabled": "Ce champ sera activé une fois les données publiées",
   "editor.record.form.field.keywords": "Mots-clés",
   "editor.record.form.field.legalConstraints": "Contrainte légale",
   "editor.record.form.field.license": "Licence",

From 8827faa7a075583892b75fc7ba99160e94978119 Mon Sep 17 00:00:00 2001
From: Angelika Kinas <angelika.kinas@camptocamp.com>
Date: Thu, 12 Dec 2024 12:05:04 +0100
Subject: [PATCH 9/9] chore: fix e2e test

---
 .../src/e2e/record-actions.cy.ts                | 17 +++++++++++++----
 ...m-field-online-link-resources.component.html |  1 +
 .../form-field-online-resources.component.html  |  1 +
 .../form-field-overviews.component.html         |  1 +
 4 files changed, 16 insertions(+), 4 deletions(-)

diff --git a/apps/metadata-editor-e2e/src/e2e/record-actions.cy.ts b/apps/metadata-editor-e2e/src/e2e/record-actions.cy.ts
index 94d6281f07..76dd781865 100644
--- a/apps/metadata-editor-e2e/src/e2e/record-actions.cy.ts
+++ b/apps/metadata-editor-e2e/src/e2e/record-actions.cy.ts
@@ -122,8 +122,11 @@ describe('record-actions', () => {
         .should('be.disabled')
       cy.get('gn-ui-form-field-overviews')
         .children()
-        .find('div')
-        .should('contain.text', ' This field will be enabled once published ')
+        .find('[data-test="disabled-message"]')
+        .should(
+          'contain.text',
+          ' This field will be enabled once the data has been published '
+        )
 
       // second page
       cy.get('[data-test="previousNextPageButtons"]')
@@ -140,7 +143,10 @@ describe('record-actions', () => {
       cy.get('gn-ui-form-field-online-resources')
         .children()
         .find('div')
-        .should('contain.text', ' This field will be enabled once published ')
+        .should(
+          'contain.text',
+          ' This field will be enabled once the data has been published '
+        )
 
       cy.get('gn-ui-form-field-online-link-resources')
         .find('input')
@@ -148,7 +154,10 @@ describe('record-actions', () => {
       cy.get('gn-ui-form-field-online-link-resources')
         .children()
         .find('div')
-        .should('contain.text', ' This field will be enabled once published ')
+        .should(
+          'contain.text',
+          ' This field will be enabled once the data has been published '
+        )
     })
 
     it('back navigation should go to search after creating a record', () => {
diff --git a/libs/feature/editor/src/lib/components/record-form/form-field/form-field-online-link-resources/form-field-online-link-resources.component.html b/libs/feature/editor/src/lib/components/record-form/form-field/form-field-online-link-resources/form-field-online-link-resources.component.html
index e29bf0db6a..141c397bf1 100644
--- a/libs/feature/editor/src/lib/components/record-form/form-field/form-field-online-link-resources/form-field-online-link-resources.component.html
+++ b/libs/feature/editor/src/lib/components/record-form/form-field/form-field-online-link-resources/form-field-online-link-resources.component.html
@@ -51,6 +51,7 @@ <h3 class="text-[16px] font-bold text-main mb-[12px]" translate>
     *ngIf="disabled$ | async"
     class="p-4 text-sm border border-primary bg-primary-lightest rounded-lg"
     translate
+    data-testid="disabled-message"
   >
     editor.record.form.field.draft.only.disabled
   </div>
diff --git a/libs/feature/editor/src/lib/components/record-form/form-field/form-field-online-resources/form-field-online-resources.component.html b/libs/feature/editor/src/lib/components/record-form/form-field/form-field-online-resources/form-field-online-resources.component.html
index 5ba8d4c445..3d54511b29 100644
--- a/libs/feature/editor/src/lib/components/record-form/form-field/form-field-online-resources/form-field-online-resources.component.html
+++ b/libs/feature/editor/src/lib/components/record-form/form-field/form-field-online-resources/form-field-online-resources.component.html
@@ -81,6 +81,7 @@ <h3 class="text-[16px] font-bold text-main mb-[12px]" translate>
     *ngIf="disabled$ | async"
     class="p-4 text-sm border border-primary bg-primary-lightest rounded-lg"
     translate
+    data-test="disabled-message"
   >
     editor.record.form.field.draft.only.disabled
   </div>
diff --git a/libs/feature/editor/src/lib/components/record-form/form-field/form-field-overviews/form-field-overviews.component.html b/libs/feature/editor/src/lib/components/record-form/form-field/form-field-overviews/form-field-overviews.component.html
index 51ec69c759..6ed3d8e0eb 100644
--- a/libs/feature/editor/src/lib/components/record-form/form-field/form-field-overviews/form-field-overviews.component.html
+++ b/libs/feature/editor/src/lib/components/record-form/form-field/form-field-overviews/form-field-overviews.component.html
@@ -15,6 +15,7 @@
     *ngIf="disabled$ | async"
     class="p-4 text-sm border border-primary bg-primary-lightest rounded-lg"
     translate
+    data-test="disabled-message"
   >
     editor.record.form.field.draft.only.disabled
   </div>