geonetwork-ui 2.9.0-dev.53585ee9e → 2.9.0-dev.5b71064ef

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.
@@ -41,7 +41,7 @@ import * as TOML from '@ltd/j-toml';
41
41
  import { Style, Stroke, Fill, Circle } from 'ol/style.js';
42
42
  import CircleStyle from 'ol/style/Circle.js';
43
43
  import EmblaCarousel from 'embla-carousel';
44
- import { iconoirNavArrowLeft, iconoirNavArrowRight, iconoirLongArrowDownLeft, iconoirSearch, iconoirCalendar, iconoirArrowUp, iconoirLink, iconoirFramePlusIn, iconoirCloudUpload, iconoirReduce, iconoirNavArrowUp, iconoirNavArrowDown, iconoirExpand, iconoirSettings, iconoirDownload, iconoirPlus, iconoirBin, iconoirMediaImageXmark, iconoirMediaImage, iconoirAppWindow, iconoirCode, iconoirDatabase, iconoirAppleWallet, iconoirBank, iconoirList, iconoirTranslate, iconoirLock, iconoirUser, iconoirArrowLeft, iconoirLightBulbOn, iconoirImport, iconoirAttachment, iconoirRefresh, iconoirCircle, iconoirCheckCircle, iconoirBadgeCheck, iconoirSystemShut } from '@ng-icons/iconoir';
44
+ import { iconoirNavArrowLeft, iconoirNavArrowRight, iconoirLongArrowDownLeft, iconoirSearch, iconoirCalendar, iconoirArrowUp, iconoirLink, iconoirFramePlusIn, iconoirCloudUpload, iconoirReduce, iconoirNavArrowUp, iconoirNavArrowDown, iconoirExpand, iconoirSettings, iconoirDownload, iconoirPlus, iconoirBin, iconoirMediaImageXmark, iconoirMediaImage, iconoirAppWindow, iconoirCode, iconoirDatabase, iconoirAppleWallet, iconoirBank, iconoirList, iconoirTranslate, iconoirLock, iconoirUser, iconoirArrowLeft, iconoirLightBulbOn, iconoirImport, iconoirBadgeCheck, iconoirSystemShut, iconoirCircle, iconoirCheckCircle, iconoirAttachment, iconoirRefresh } from '@ng-icons/iconoir';
45
45
  import { MatButtonModule } from '@angular/material/button';
46
46
  import * as i1$8 from '@angular/cdk/overlay';
47
47
  import { OverlayContainer, ScrollStrategyOptions, OverlayModule, CdkConnectedOverlay, ScrollDispatcher, Overlay, CdkOverlayOrigin } from '@angular/cdk/overlay';
@@ -25519,7 +25519,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
25519
25519
  }] } });
25520
25520
 
25521
25521
  var name = "geonetwork-ui";
25522
- var version = "2.9.0-dev.53585ee9e";
25522
+ var version = "2.9.0-dev.5b71064ef";
25523
25523
  var engines = {
25524
25524
  node: ">=20"
25525
25525
  };
@@ -41121,6 +41121,7 @@ const saveRecordSuccess = createAction('[Editor] Save record success');
41121
41121
  const saveRecordFailure = createAction('[Editor] Save record failure', props());
41122
41122
  const draftSaveSuccess = createAction('[Editor] Draft save success');
41123
41123
  const undoRecordDraft = createAction('[Editor] Undo record draft');
41124
+ const setEditorConfiguration = createAction('[Editor] Set editor configuration', props());
41124
41125
  const setCurrentPage = createAction('[Editor] Set current page', props());
41125
41126
  const setFieldVisibility = createAction('[Editor] Set field visibility', props());
41126
41127
  const hasRecordChangedSinceDraft = createAction('[Editor] Has Record Changed Since Draft', props());
@@ -41543,6 +41544,9 @@ const reducer = createReducer(initialEditorState, on(openRecord, (state, { recor
41543
41544
  })), on(markRecordAsChanged, (state) => ({
41544
41545
  ...state,
41545
41546
  changedSinceSave: true,
41547
+ })), on(setEditorConfiguration, (state, { configuration }) => ({
41548
+ ...state,
41549
+ editorConfig: configuration,
41546
41550
  })), on(setCurrentPage, (state, { page }) => ({
41547
41551
  ...state,
41548
41552
  currentPage: page,
@@ -41645,6 +41649,9 @@ class EditorFacade {
41645
41649
  updateRecordLanguages(defaultLanguage, otherLanguages) {
41646
41650
  this.store.dispatch(updateRecordLanguages({ defaultLanguage, otherLanguages }));
41647
41651
  }
41652
+ setConfiguration(configuration) {
41653
+ this.store.dispatch(setEditorConfiguration({ configuration }));
41654
+ }
41648
41655
  setCurrentPage(page) {
41649
41656
  this.store.dispatch(setCurrentPage({ page }));
41650
41657
  }
@@ -41667,149 +41674,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
41667
41674
  type: Injectable
41668
41675
  }] });
41669
41676
 
41670
- function evaluate(expression) {
41671
- if (expression.match(/^\${.*}$/)) {
41672
- return evaluate(expression.slice(2, -1));
41673
- }
41674
- const operator = expression.split('(')[0];
41675
- switch (operator) {
41676
- case 'dateNow':
41677
- return () => new Date();
41678
- default:
41679
- throw new Error(`Unknown operator: ${operator}`);
41680
- }
41681
- }
41682
-
41683
- class EditorService {
41684
- constructor() {
41685
- this.recordsRepository = inject(RecordsRepositoryInterface);
41686
- }
41687
- // returns the record as it was when saved, alongside its source
41688
- saveRecord(record, recordSource, fieldsConfig) {
41689
- const savedRecord = { ...record };
41690
- const fields = fieldsConfig.pages.flatMap((page) => page.sections.flatMap((section) => section.fields));
41691
- // run onSave processes
41692
- for (const field of fields) {
41693
- if (field.onSaveProcess && field.model) {
41694
- const evaluator = evaluate(field.onSaveProcess);
41695
- savedRecord[field.model] = evaluator({
41696
- model: field.model,
41697
- value: record[field.model],
41698
- });
41699
- }
41700
- }
41701
- let publishToAll = true;
41702
- // if the record is new, generate a new unique identifier and pass publishToAll as false
41703
- if (!record.uniqueIdentifier) {
41704
- savedRecord.uniqueIdentifier = null;
41705
- publishToAll = false;
41706
- }
41707
- return this.recordsRepository
41708
- .saveRecord(savedRecord, recordSource, publishToAll)
41709
- .pipe(switchMap((uniqueIdentifier) => this.recordsRepository.openRecordForEdition(uniqueIdentifier)), tap$1(() => {
41710
- // if saving was successful, the original draft can be discarded
41711
- this.recordsRepository.clearRecordDraft(record.uniqueIdentifier);
41712
- }), map$1(([record, recordSource]) => [record, recordSource]));
41713
- }
41714
- // emits and completes once saving is done
41715
- // note: onSave processes are not run for drafts
41716
- saveRecordAsDraft(record, recordSource) {
41717
- record.recordUpdated = new Date();
41718
- return this.recordsRepository
41719
- .saveRecordAsDraft(record, recordSource)
41720
- .pipe(map$1(() => undefined));
41721
- }
41722
- undoRecordDraft(record) {
41723
- this.recordsRepository.clearRecordDraft(record.uniqueIdentifier);
41724
- return this.recordsRepository.openRecordForEdition(record.uniqueIdentifier);
41725
- }
41726
- hasRecordChangedSinceDraft(localRecord) {
41727
- return this.recordsRepository.hasRecordChangedSinceDraft(localRecord);
41728
- }
41729
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: EditorService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
41730
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: EditorService, providedIn: 'root' }); }
41731
- }
41732
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: EditorService, decorators: [{
41733
- type: Injectable,
41734
- args: [{
41735
- providedIn: 'root',
41736
- }]
41737
- }] });
41738
-
41739
- class EditorEffects {
41740
- constructor() {
41741
- this.actions$ = inject(Actions);
41742
- this.editorService = inject(EditorService);
41743
- this.recordsRepository = inject(RecordsRepositoryInterface);
41744
- this.plateformService = inject(PlatformServiceInterface);
41745
- this.store = inject(Store);
41746
- this.saveRecord$ = createEffect(() => this.actions$.pipe(ofType(saveRecord), withLatestFrom$1(this.store.select(selectRecord), this.store.select(selectRecordSource), this.store.select(selectEditorConfig)), switchMap$1(([, record, recordSource, fieldsConfig]) => this.editorService.saveRecord(record, recordSource, fieldsConfig).pipe(switchMap$1(([savedRecord, savedRecordSource]) => {
41747
- const actions = [saveRecordSuccess()];
41748
- if (!record?.uniqueIdentifier) {
41749
- actions.push(openRecord({
41750
- record: savedRecord,
41751
- recordSource: savedRecordSource,
41752
- }));
41753
- }
41754
- return of(...actions);
41755
- }), catchError((error) => of(saveRecordFailure({
41756
- error,
41757
- })))))));
41758
- this.cleanRecordAttachments$ = createEffect(() => this.actions$.pipe(ofType(saveRecordSuccess), withLatestFrom$1(this.store.select(selectRecord)), switchMap$1(([_, record]) => {
41759
- if (record.uniqueIdentifier !== null) {
41760
- this.plateformService.cleanRecordAttachments(record).subscribe({
41761
- next: (_) => undefined,
41762
- error: (err) => {
41763
- console.error(err);
41764
- },
41765
- });
41766
- }
41767
- return EMPTY;
41768
- }), catchError((error) => {
41769
- console.error(error);
41770
- return EMPTY;
41771
- })), { dispatch: false });
41772
- this.markAsChanged$ = createEffect(() => this.actions$.pipe(ofType(updateRecordField, updateRecordLanguages), map$1(() => markRecordAsChanged())));
41773
- this.saveRecordDraft$ = createEffect(() => this.actions$.pipe(ofType(updateRecordField, updateRecordLanguages), debounceTime$1(1000), withLatestFrom$1(this.store.select(selectRecord), this.store.select(selectRecordSource)), switchMap$1(([, record, recordSource]) => this.editorService.saveRecordAsDraft(record, recordSource)), map$1(() => draftSaveSuccess())));
41774
- this.undoRecordDraft$ = createEffect(() => this.actions$.pipe(ofType(undoRecordDraft), withLatestFrom$1(this.store.select(selectRecord)), switchMap$1(([, record]) => this.editorService.undoRecordDraft(record)), map$1(([record, recordSource]) => openRecord({
41775
- record,
41776
- recordSource,
41777
- }))));
41778
- this.checkHasChangesOnOpen$ = createEffect(() => this.actions$.pipe(ofType(openRecord), map$1(({ record }) => this.recordsRepository.recordHasDraft(record.uniqueIdentifier)), filter((hasDraft) => hasDraft), map$1(() => markRecordAsChanged())));
41779
- this.hasRecordChangedSinceDraft$ = createEffect(() => this.actions$.pipe(ofType(hasRecordChangedSinceDraft), switchMap$1(({ record }) => this.editorService
41780
- .hasRecordChangedSinceDraft(record)
41781
- .pipe(map$1((changes) => hasRecordChangedSinceDraftSuccess({ changes }))))));
41782
- this.checkIsRecordPublished$ = createEffect(() => this.actions$.pipe(ofType(openRecord), map$1(({ record }) => record.uniqueIdentifier), switchMap$1((uniqueIdentifier) => this.recordsRepository.getRecordPublicationStatus(uniqueIdentifier)), map$1((isPublished$1) => isPublished({
41783
- isPublished: isPublished$1,
41784
- }))));
41785
- this.checkCanEditRecord$ = createEffect(() => this.actions$.pipe(ofType(openRecord), map$1(({ record }) => record.uniqueIdentifier), switchMap$1((uniqueIdentifier) => this.recordsRepository.canEditRecord(uniqueIdentifier)), map$1((canEditRecord$1) => canEditRecord({
41786
- canEditRecord: canEditRecord$1,
41787
- }))));
41788
- }
41789
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: EditorEffects, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
41790
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: EditorEffects }); }
41791
- }
41792
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: EditorEffects, decorators: [{
41793
- type: Injectable
41794
- }] });
41795
-
41796
- class FeatureEditorModule {
41797
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: FeatureEditorModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
41798
- static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.15", ngImport: i0, type: FeatureEditorModule, imports: [i1.StoreFeatureModule, i2$2.EffectsFeatureModule] }); }
41799
- static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: FeatureEditorModule, providers: [EditorFacade, provideHttpClient()], imports: [StoreModule.forFeature(EDITOR_FEATURE_KEY, editorReducer),
41800
- EffectsModule.forFeature([EditorEffects])] }); }
41801
- }
41802
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: FeatureEditorModule, decorators: [{
41803
- type: NgModule,
41804
- args: [{
41805
- imports: [
41806
- StoreModule.forFeature(EDITOR_FEATURE_KEY, editorReducer),
41807
- EffectsModule.forFeature([EditorEffects]),
41808
- ],
41809
- providers: [EditorFacade, provideHttpClient()],
41810
- }]
41811
- }] });
41812
-
41813
41677
  class ImportRecordComponent {
41814
41678
  constructor() {
41815
41679
  this.router = inject(Router);
@@ -41905,6 +41769,328 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
41905
41769
  type: Output
41906
41770
  }] } });
41907
41771
 
41772
+ //forced translations that are not available in fields.config.ts
41773
+ marker('editor.record.form.field.keywords');
41774
+ marker('editor.record.form.field.topics');
41775
+ marker('editor.record.form.field.contacts');
41776
+ marker('editor.record.form.field.organisation');
41777
+ class MetadataQualityPanelComponent {
41778
+ constructor() {
41779
+ this.propsToValidate = getAllKeysValidator();
41780
+ this.propertiesByPage = [];
41781
+ }
41782
+ ngOnChanges() {
41783
+ if (this.editorConfig && this.record) {
41784
+ const fieldsByPage = this.editorConfig.pages.map((page) => page.sections.flatMap((section) => section.fields
41785
+ .filter((field) => this.propsToValidate.includes(field.model))
41786
+ .map((field) => field.model)));
41787
+ // FIXME: temporarily add topics and organisation to the first and third page
41788
+ // as long as they are not handled by the editor
41789
+ if (fieldsByPage.length > 0) {
41790
+ fieldsByPage[0].includes('topics') || fieldsByPage[0].push('topics');
41791
+ fieldsByPage[2].includes('organisation') ||
41792
+ fieldsByPage[2].push('organisation');
41793
+ }
41794
+ this.propertiesByPage = fieldsByPage
41795
+ .map((fields) => getQualityValidators(this.record, fields).map(({ name, validator }) => ({
41796
+ label: `editor.record.form.field.${name}`, // use same translations as in fields.config.ts
41797
+ value: validator(),
41798
+ })))
41799
+ .filter((arr) => arr.length > 0);
41800
+ }
41801
+ }
41802
+ getExtraClass(checked) {
41803
+ const baseClasses = 'flex flex-row justify-between rounded mb-1 h-[34px] w-full focus:ring-0 hover:border-none border-none hover:text-black text-black cursor-default';
41804
+ return checked
41805
+ ? `${baseClasses} bg-neutral-100 hover:bg-neutral-100`
41806
+ : `${baseClasses} bg-transparent hover:bg-transparent`;
41807
+ }
41808
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: MetadataQualityPanelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
41809
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: MetadataQualityPanelComponent, isStandalone: true, selector: "gn-ui-metadata-quality-panel", inputs: { editorConfig: "editorConfig", record: "record" }, providers: [
41810
+ provideIcons({
41811
+ iconoirSystemShut,
41812
+ iconoirBadgeCheck,
41813
+ }),
41814
+ provideNgIconsConfig({
41815
+ size: '1.25em',
41816
+ }),
41817
+ ], usesOnChanges: true, ngImport: i0, template: "<div\n class=\"flex flex-col h-full w-[302px] border-l border-gray-300 py-8 px-3 gap-3 overflow-auto\"\n style=\"background-color: #fafaf9\"\n>\n <div class=\"flex flex-row px-2 justify-between\">\n <span class=\"text-3xl font-title text-black/80\" translate\n >editor.record.form.metadataQuality.title</span\n >\n </div>\n @for (properties of propertiesByPage; track properties; let i = $index) {\n <div class=\"flex flex-col gap-2\">\n @for (property of properties; track property) {\n <gn-ui-button\n [extraClass]=\"getExtraClass(property.value)\"\n type=\"outline\"\n attr.data-cy=\"md-quality-btn-{{ property.label }}\"\n >\n <span>{{ property.label | translate }}</span>\n <div class=\"flex flex-row gap-2 items-center\">\n @if (property.value) {\n <ng-icon class=\"text-primary\" name=\"iconoirBadgeCheck\"></ng-icon>\n } @else {\n <ng-icon\n class=\"text-neutral-300\"\n name=\"iconoirSystemShut\"\n ></ng-icon>\n }\n </div>\n </gn-ui-button>\n }\n @if (i !== propertiesByPage.length - 1) {\n <hr class=\"border-gray-300 w-11/12 mx-auto\" />\n }\n </div>\n }\n</div>\n", styles: [""], dependencies: [{ kind: "directive", type: TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }, { kind: "component", type: ButtonComponent, selector: "gn-ui-button", inputs: ["type", "disabled", "extraClass"], outputs: ["buttonClick"] }, { kind: "component", type: NgIconComponent, selector: "ng-icon", inputs: ["name", "svg", "size", "strokeWidth", "color"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
41818
+ }
41819
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: MetadataQualityPanelComponent, decorators: [{
41820
+ type: Component,
41821
+ args: [{ selector: 'gn-ui-metadata-quality-panel', standalone: true, imports: [
41822
+ TranslateDirective,
41823
+ TranslatePipe,
41824
+ ButtonComponent,
41825
+ NgIconComponent,
41826
+ ], providers: [
41827
+ provideIcons({
41828
+ iconoirSystemShut,
41829
+ iconoirBadgeCheck,
41830
+ }),
41831
+ provideNgIconsConfig({
41832
+ size: '1.25em',
41833
+ }),
41834
+ ], template: "<div\n class=\"flex flex-col h-full w-[302px] border-l border-gray-300 py-8 px-3 gap-3 overflow-auto\"\n style=\"background-color: #fafaf9\"\n>\n <div class=\"flex flex-row px-2 justify-between\">\n <span class=\"text-3xl font-title text-black/80\" translate\n >editor.record.form.metadataQuality.title</span\n >\n </div>\n @for (properties of propertiesByPage; track properties; let i = $index) {\n <div class=\"flex flex-col gap-2\">\n @for (property of properties; track property) {\n <gn-ui-button\n [extraClass]=\"getExtraClass(property.value)\"\n type=\"outline\"\n attr.data-cy=\"md-quality-btn-{{ property.label }}\"\n >\n <span>{{ property.label | translate }}</span>\n <div class=\"flex flex-row gap-2 items-center\">\n @if (property.value) {\n <ng-icon class=\"text-primary\" name=\"iconoirBadgeCheck\"></ng-icon>\n } @else {\n <ng-icon\n class=\"text-neutral-300\"\n name=\"iconoirSystemShut\"\n ></ng-icon>\n }\n </div>\n </gn-ui-button>\n }\n @if (i !== propertiesByPage.length - 1) {\n <hr class=\"border-gray-300 w-11/12 mx-auto\" />\n }\n </div>\n }\n</div>\n" }]
41835
+ }], propDecorators: { editorConfig: [{
41836
+ type: Input
41837
+ }], record: [{
41838
+ type: Input
41839
+ }] } });
41840
+
41841
+ const extraFlagMap = {
41842
+ ar: 'arab',
41843
+ en: 'gb',
41844
+ ko: 'kr',
41845
+ cs: 'cz',
41846
+ zh: 'cn',
41847
+ ca: 'es-ct',
41848
+ rm: 'ch',
41849
+ da: 'dk',
41850
+ sv: 'se',
41851
+ cy: 'gb-wls',
41852
+ hy: 'am',
41853
+ ka: 'ge',
41854
+ uk: 'ua',
41855
+ };
41856
+ class MultilingualPanelComponent {
41857
+ constructor() {
41858
+ this.facade = inject(EditorFacade);
41859
+ this.dialog = inject(MatDialog);
41860
+ this.translateService = inject(TranslateService);
41861
+ this.recordsRepository = inject(RecordsRepositoryInterface);
41862
+ this.overlay = inject(Overlay);
41863
+ this.viewContainerRef = inject(ViewContainerRef);
41864
+ this.cdr = inject(ChangeDetectorRef);
41865
+ this.selectedLanguages = [];
41866
+ this.recordLanguages = [];
41867
+ this.formLanguage = '';
41868
+ this.isActionMenuOpen = false;
41869
+ this.subscription = new Subscription();
41870
+ this.supportedLanguages$ = this.recordsRepository
41871
+ .getApplicationLanguages()
41872
+ .pipe(map$2((languages) => this.sortLanguages(languages)));
41873
+ }
41874
+ set record(value) {
41875
+ this._record = value;
41876
+ this.isMultilingual = value.otherLanguages.length > 0;
41877
+ this.editTranslations = false;
41878
+ this.recordLanguages = [...value.otherLanguages, value.defaultLanguage];
41879
+ this.selectedLanguages = this.recordLanguages;
41880
+ this.formLanguage = value.defaultLanguage;
41881
+ }
41882
+ ngOnDestroy() {
41883
+ this.subscription.unsubscribe();
41884
+ }
41885
+ sortLanguages(languages) {
41886
+ return languages
41887
+ .map((lang) => {
41888
+ const label = this.translateService.instant('language.' + lang);
41889
+ const isTranslated = label !== 'language.' + lang;
41890
+ return {
41891
+ lang,
41892
+ label,
41893
+ isTranslated,
41894
+ };
41895
+ })
41896
+ .sort((a, b) => {
41897
+ if (a.isTranslated && !b.isTranslated)
41898
+ return -1;
41899
+ if (!a.isTranslated && b.isTranslated)
41900
+ return 1;
41901
+ return a.label.localeCompare(b.label);
41902
+ })
41903
+ .map((item) => item.lang);
41904
+ }
41905
+ toggleLanguageSelection() {
41906
+ this.editTranslations = !this.editTranslations;
41907
+ }
41908
+ getIconClass(lang) {
41909
+ return extraFlagMap[lang]
41910
+ ? `fi fi-${extraFlagMap[lang]} w-4 h-3`
41911
+ : `fi fi-${lang} w-4 h-3`;
41912
+ }
41913
+ switchMultilingual() {
41914
+ if (this.isMultilingual && this.selectedLanguages.length > 1) {
41915
+ this.confirmDeleteAction();
41916
+ }
41917
+ else {
41918
+ this.isMultilingual = true;
41919
+ this.editTranslations = true;
41920
+ }
41921
+ }
41922
+ getExtraClass(lang) {
41923
+ const baseClass = 'h-[34px] w-full font-bold justify-start hover:bg-white';
41924
+ if (this.selectedLanguages.includes(lang)) {
41925
+ return `${baseClass} bg-white border border-black`;
41926
+ }
41927
+ return baseClass;
41928
+ }
41929
+ toggleLanguage(lang) {
41930
+ if (this.selectedLanguages.includes(lang)) {
41931
+ this.removeSelectedLanguage(lang);
41932
+ }
41933
+ else {
41934
+ this.selectedLanguages.push(lang);
41935
+ }
41936
+ }
41937
+ removeSelectedLanguage(lang) {
41938
+ this.selectedLanguages = this.selectedLanguages.filter((language) => language !== lang);
41939
+ }
41940
+ validateTranslations() {
41941
+ const equalLength = this.selectedLanguages.length === this.recordLanguages.length;
41942
+ if (this.selectedLanguages.length < this.recordLanguages.length ||
41943
+ (equalLength && this.selectedLanguages !== this.recordLanguages)) {
41944
+ this.confirmDeleteAction(this.selectedLanguages);
41945
+ }
41946
+ else {
41947
+ this.updateTranslations();
41948
+ }
41949
+ }
41950
+ updateTranslations() {
41951
+ const newLanguageSelection = this.selectedLanguages.filter((lang) => lang !== this.formLanguage);
41952
+ this.facade.updateRecordLanguages(this.formLanguage, newLanguageSelection);
41953
+ this.recordLanguages = newLanguageSelection;
41954
+ this.editTranslations = false;
41955
+ }
41956
+ switchFormLang(lang) {
41957
+ // TO IMPLEMENT FURTHER
41958
+ }
41959
+ switchDefaultLang(lang) {
41960
+ this.formLanguage = lang;
41961
+ this.facade.updateRecordLanguages(lang, this.selectedLanguages.filter((lang) => lang !== this.formLanguage));
41962
+ this.closeActionMenu();
41963
+ }
41964
+ confirmDeleteAction(lang) {
41965
+ const dialogRef = this.dialog.open(ConfirmationDialogComponent, {
41966
+ data: {
41967
+ title: this.translateService.instant('editor.record.multilingual.confirmation.title'),
41968
+ message: this.translateService.instant('editor.record.multilingual.confirmation.message'),
41969
+ confirmText: this.translateService.instant('editor.record.multilingual.confirmation.confirmText'),
41970
+ cancelText: this.translateService.instant('editor.record.multilingual.confirmation.cancelText'),
41971
+ focusCancel: true,
41972
+ },
41973
+ restoreFocus: true,
41974
+ });
41975
+ this.subscription.add(dialogRef.afterClosed().subscribe((confirmed) => {
41976
+ if (confirmed) {
41977
+ if (lang) {
41978
+ if (!Array.isArray(lang)) {
41979
+ this.removeSelectedLanguage(lang);
41980
+ this.closeActionMenu();
41981
+ }
41982
+ this.updateTranslations();
41983
+ }
41984
+ else {
41985
+ this.facade.updateRecordLanguages(this.formLanguage, []);
41986
+ this.isMultilingual = false;
41987
+ this.selectedLanguages = [];
41988
+ }
41989
+ }
41990
+ else {
41991
+ this.isMultilingual = true;
41992
+ this.selectedLanguages = this.recordLanguages;
41993
+ }
41994
+ this.editTranslations = false;
41995
+ }));
41996
+ }
41997
+ isFirstUnsupported(index) {
41998
+ const langs = this.sortLanguages(this.recordLanguages);
41999
+ return (langs[index].length === 3 &&
42000
+ langs.slice(0, index).every((lang) => lang.length !== 3));
42001
+ }
42002
+ isLangSupported(lang) {
42003
+ return lang.length === 2;
42004
+ }
42005
+ getToggleTitle(lang) {
42006
+ if (lang === this._record.defaultLanguage) {
42007
+ return this.translateService.instant('editor.record.form.multilingual.forbidden');
42008
+ }
42009
+ return '';
42010
+ }
42011
+ openActionMenu(item, template) {
42012
+ this.isActionMenuOpen = true;
42013
+ const index = this.sortLanguages(this.selectedLanguages).indexOf(item);
42014
+ const buttonElement = this.actionMenuButtons.toArray()[index];
42015
+ const positionStrategy = this.overlay
42016
+ .position()
42017
+ .flexibleConnectedTo(buttonElement)
42018
+ .withFlexibleDimensions(true)
42019
+ .withPush(true)
42020
+ .withPositions([
42021
+ {
42022
+ originX: 'end',
42023
+ originY: 'bottom',
42024
+ overlayX: 'end',
42025
+ overlayY: 'top',
42026
+ },
42027
+ {
42028
+ originX: 'end',
42029
+ originY: 'top',
42030
+ overlayX: 'end',
42031
+ overlayY: 'bottom',
42032
+ },
42033
+ ]);
42034
+ this.overlayRef = this.overlay.create({
42035
+ hasBackdrop: true,
42036
+ backdropClass: 'cdk-overlay-transparent-backdrop',
42037
+ positionStrategy: positionStrategy,
42038
+ scrollStrategy: this.overlay.scrollStrategies.reposition(),
42039
+ });
42040
+ const portal = new TemplatePortal(template, this.viewContainerRef);
42041
+ this.overlayRef.attach(portal);
42042
+ this.subscription.add(this.overlayRef.backdropClick().subscribe(() => {
42043
+ this.closeActionMenu();
42044
+ }));
42045
+ }
42046
+ closeActionMenu() {
42047
+ if (this.overlayRef) {
42048
+ this.isActionMenuOpen = false;
42049
+ this.overlayRef.dispose();
42050
+ this.cdr.markForCheck();
42051
+ }
42052
+ }
42053
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: MultilingualPanelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
42054
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: MultilingualPanelComponent, isStandalone: true, selector: "gn-ui-multilingual-panel", inputs: { record: "record" }, providers: [
42055
+ provideIcons({
42056
+ iconoirSettings,
42057
+ matMoreHorizOutline,
42058
+ iconoirCheckCircle,
42059
+ iconoirCircle,
42060
+ }),
42061
+ provideNgIconsConfig({
42062
+ size: '1.25em',
42063
+ }),
42064
+ ], viewQueries: [{ propertyName: "actionMenuButtons", predicate: ["actionMenuButton"], descendants: true, read: ElementRef }], ngImport: i0, template: "<div\n class=\"flex flex-col h-full w-[302px] border-l border-gray-300 py-8 px-3 gap-6 overflow-auto\"\n style=\"background-color: #fafaf9\"\n>\n <div class=\"flex flex-row px-2 justify-between\">\n <span class=\"text-3xl font-title text-black/80\" translate\n >editor.record.form.multilingual.title</span\n >\n @if (isMultilingual) {\n <button\n [title]=\"'editor.record.form.multilingual.open' | translate\"\n (click)=\"toggleLanguageSelection()\"\n data-test=\"activateSelection\"\n >\n <ng-icon class=\"mt-1\" name=\"iconoirSettings\"></ng-icon>\n </button>\n }\n </div>\n @if (editTranslations || !isMultilingual) {\n <div class=\"flex flex-col gap-2\">\n <gn-ui-check-toggle\n class=\"p-2\"\n [label]=\"'editor.record.form.multilingual.enable' | translate\"\n [color]=\"'primary'\"\n [(value)]=\"isMultilingual\"\n (toggled)=\"switchMultilingual($event)\"\n ></gn-ui-check-toggle>\n @if (isMultilingual) {\n <div class=\"flex flex-col gap-2\">\n <div\n class=\"flex flex-row justify-between border-t border-gray-300 p-3\"\n >\n <span class=\"mt-2 text-sm text-gray-600\" translate\n >editor.record.form.multilingual.activate</span\n >\n <gn-ui-button\n extraClass=\"w-16 h-8 font-bold\"\n type=\"gray\"\n (buttonClick)=\"validateTranslations()\"\n data-test=\"validateSelection\"\n >{{ 'editor.record.form.multilingual.validate' | translate }}\n </gn-ui-button>\n </div>\n @if (supportedLanguages$ | async; as languages) {\n @for (lang of languages; track lang) {\n <div\n class=\"flex flex-col gap-2 w-full px-2\"\n data-test=\"langAvailable\"\n [attr.data-test-lang]=\"lang\"\n >\n <gn-ui-button\n [extraClass]=\"getExtraClass(lang)\"\n type=\"gray\"\n (buttonClick)=\"toggleLanguage(lang)\"\n [disabled]=\"lang === _record.defaultLanguage\"\n [title]=\"getToggleTitle(lang)\"\n >\n <span [class]=\"getIconClass(lang)\"></span>\n <span class=\"ml-2\">{{ 'language.' + lang | translate }}</span>\n </gn-ui-button>\n </div>\n }\n }\n </div>\n }\n </div>\n }\n @if (!editTranslations && isMultilingual) {\n <div class=\"flex flex-col gap-2\">\n @for (\n recordLang of sortLanguages(recordLanguages);\n track recordLang;\n let i = $index\n ) {\n <gn-ui-button\n extraClass=\"flex flex-row justify-between bg-white border border-white rounded mb-1 h-[34px] w-full\"\n [ngClass]=\"{\n 'mt-8': isFirstUnsupported(i),\n '': true,\n }\"\n (buttonClick)=\"switchFormLang(recordLang)\"\n type=\"outline\"\n data-test=\"langSwitch\"\n >\n <div class=\"flex flex-row gap-2 items-center\">\n @if (recordLang === formLanguage) {\n <ng-icon\n class=\"text-primary mt-1\"\n name=\"iconoirCheckCircle\"\n ></ng-icon>\n }\n @if (recordLang !== formLanguage) {\n <ng-icon\n class=\"text-gray-800 mt-1\"\n name=\"iconoirCircle\"\n ></ng-icon>\n }\n @if (recordLang.length === 2) {\n <span [class]=\"getIconClass(recordLang) + 'mt-1'\"></span>\n }\n <span [ngClass]=\"recordLang === formLanguage ? 'text-black' : ''\">{{\n isLangSupported(recordLang)\n ? ('language.' + recordLang | translate)\n : recordLang.toUpperCase()\n }}</span>\n </div>\n <div class=\"flex flex-row gap-2 items-center\">\n @if (recordLang === formLanguage) {\n <span class=\"text-xs text-base\" translate\n >editor.record.form.multilingual.default</span\n >\n }\n <button\n (click)=\"\n openActionMenu(recordLang, template); $event.stopPropagation()\n \"\n cdkOverlayOrigin\n #actionMenuButton\n >\n <ng-icon class=\"pb-5\" name=\"matMoreHorizOutline\"></ng-icon>\n </button>\n <ng-template #template>\n <gn-ui-action-menu\n [canDelete]=\"recordLang !== _record.defaultLanguage\"\n page=\"record\"\n (delete)=\"confirmDeleteAction(recordLang)\"\n (closeActionMenu)=\"closeActionMenu()\"\n (switch)=\"switchDefaultLang(recordLang)\"\n >\n </gn-ui-action-menu>\n </ng-template>\n </div>\n </gn-ui-button>\n }\n </div>\n }\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: CheckToggleComponent, selector: "gn-ui-check-toggle", inputs: ["title", "label", "value", "color"], outputs: ["toggled"] }, { kind: "directive", type: TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }, { kind: "component", type: ButtonComponent, selector: "gn-ui-button", inputs: ["type", "disabled", "extraClass"], outputs: ["buttonClick"] }, { kind: "component", type: NgIconComponent, selector: "ng-icon", inputs: ["name", "svg", "size", "strokeWidth", "color"] }, { kind: "component", type: ActionMenuComponent, selector: "gn-ui-action-menu", inputs: ["canDuplicate", "isDuplicating", "canDelete", "page"], outputs: ["duplicate", "delete", "closeActionMenu", "rollback", "switch"] }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
42065
+ }
42066
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: MultilingualPanelComponent, decorators: [{
42067
+ type: Component,
42068
+ args: [{ selector: 'gn-ui-multilingual-panel', standalone: true, imports: [
42069
+ CommonModule,
42070
+ CheckToggleComponent,
42071
+ TranslateDirective,
42072
+ TranslatePipe,
42073
+ ButtonComponent,
42074
+ NgIconComponent,
42075
+ ActionMenuComponent,
42076
+ ], providers: [
42077
+ provideIcons({
42078
+ iconoirSettings,
42079
+ matMoreHorizOutline,
42080
+ iconoirCheckCircle,
42081
+ iconoirCircle,
42082
+ }),
42083
+ provideNgIconsConfig({
42084
+ size: '1.25em',
42085
+ }),
42086
+ ], template: "<div\n class=\"flex flex-col h-full w-[302px] border-l border-gray-300 py-8 px-3 gap-6 overflow-auto\"\n style=\"background-color: #fafaf9\"\n>\n <div class=\"flex flex-row px-2 justify-between\">\n <span class=\"text-3xl font-title text-black/80\" translate\n >editor.record.form.multilingual.title</span\n >\n @if (isMultilingual) {\n <button\n [title]=\"'editor.record.form.multilingual.open' | translate\"\n (click)=\"toggleLanguageSelection()\"\n data-test=\"activateSelection\"\n >\n <ng-icon class=\"mt-1\" name=\"iconoirSettings\"></ng-icon>\n </button>\n }\n </div>\n @if (editTranslations || !isMultilingual) {\n <div class=\"flex flex-col gap-2\">\n <gn-ui-check-toggle\n class=\"p-2\"\n [label]=\"'editor.record.form.multilingual.enable' | translate\"\n [color]=\"'primary'\"\n [(value)]=\"isMultilingual\"\n (toggled)=\"switchMultilingual($event)\"\n ></gn-ui-check-toggle>\n @if (isMultilingual) {\n <div class=\"flex flex-col gap-2\">\n <div\n class=\"flex flex-row justify-between border-t border-gray-300 p-3\"\n >\n <span class=\"mt-2 text-sm text-gray-600\" translate\n >editor.record.form.multilingual.activate</span\n >\n <gn-ui-button\n extraClass=\"w-16 h-8 font-bold\"\n type=\"gray\"\n (buttonClick)=\"validateTranslations()\"\n data-test=\"validateSelection\"\n >{{ 'editor.record.form.multilingual.validate' | translate }}\n </gn-ui-button>\n </div>\n @if (supportedLanguages$ | async; as languages) {\n @for (lang of languages; track lang) {\n <div\n class=\"flex flex-col gap-2 w-full px-2\"\n data-test=\"langAvailable\"\n [attr.data-test-lang]=\"lang\"\n >\n <gn-ui-button\n [extraClass]=\"getExtraClass(lang)\"\n type=\"gray\"\n (buttonClick)=\"toggleLanguage(lang)\"\n [disabled]=\"lang === _record.defaultLanguage\"\n [title]=\"getToggleTitle(lang)\"\n >\n <span [class]=\"getIconClass(lang)\"></span>\n <span class=\"ml-2\">{{ 'language.' + lang | translate }}</span>\n </gn-ui-button>\n </div>\n }\n }\n </div>\n }\n </div>\n }\n @if (!editTranslations && isMultilingual) {\n <div class=\"flex flex-col gap-2\">\n @for (\n recordLang of sortLanguages(recordLanguages);\n track recordLang;\n let i = $index\n ) {\n <gn-ui-button\n extraClass=\"flex flex-row justify-between bg-white border border-white rounded mb-1 h-[34px] w-full\"\n [ngClass]=\"{\n 'mt-8': isFirstUnsupported(i),\n '': true,\n }\"\n (buttonClick)=\"switchFormLang(recordLang)\"\n type=\"outline\"\n data-test=\"langSwitch\"\n >\n <div class=\"flex flex-row gap-2 items-center\">\n @if (recordLang === formLanguage) {\n <ng-icon\n class=\"text-primary mt-1\"\n name=\"iconoirCheckCircle\"\n ></ng-icon>\n }\n @if (recordLang !== formLanguage) {\n <ng-icon\n class=\"text-gray-800 mt-1\"\n name=\"iconoirCircle\"\n ></ng-icon>\n }\n @if (recordLang.length === 2) {\n <span [class]=\"getIconClass(recordLang) + 'mt-1'\"></span>\n }\n <span [ngClass]=\"recordLang === formLanguage ? 'text-black' : ''\">{{\n isLangSupported(recordLang)\n ? ('language.' + recordLang | translate)\n : recordLang.toUpperCase()\n }}</span>\n </div>\n <div class=\"flex flex-row gap-2 items-center\">\n @if (recordLang === formLanguage) {\n <span class=\"text-xs text-base\" translate\n >editor.record.form.multilingual.default</span\n >\n }\n <button\n (click)=\"\n openActionMenu(recordLang, template); $event.stopPropagation()\n \"\n cdkOverlayOrigin\n #actionMenuButton\n >\n <ng-icon class=\"pb-5\" name=\"matMoreHorizOutline\"></ng-icon>\n </button>\n <ng-template #template>\n <gn-ui-action-menu\n [canDelete]=\"recordLang !== _record.defaultLanguage\"\n page=\"record\"\n (delete)=\"confirmDeleteAction(recordLang)\"\n (closeActionMenu)=\"closeActionMenu()\"\n (switch)=\"switchDefaultLang(recordLang)\"\n >\n </gn-ui-action-menu>\n </ng-template>\n </div>\n </gn-ui-button>\n }\n </div>\n }\n</div>\n" }]
42087
+ }], propDecorators: { record: [{
42088
+ type: Input
42089
+ }], actionMenuButtons: [{
42090
+ type: ViewChildren,
42091
+ args: ['actionMenuButton', { read: ElementRef }]
42092
+ }] } });
42093
+
41908
42094
  class GenericKeywordsComponent {
41909
42095
  constructor() {
41910
42096
  this.platformService = inject(PlatformServiceInterface);
@@ -43783,327 +43969,148 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
43783
43969
  args: [{ selector: 'gn-ui-record-form', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [CommonModule, FormFieldComponent, TranslateDirective], template: "<div class=\"flex flex-col gap-6\">\n @for (\n section of facade.currentSections$ | async;\n track sectionTracker($index, section)\n ) {\n @if (!section.hidden) {\n <div class=\"flex flex-col gap-6 border p-8 rounded-[8px] shadow\">\n <div class=\"flex flex-col gap-2\">\n @if (section.labelKey) {\n <div class=\"text-2xl font-title text-black\" translate>\n {{ section.labelKey }}\n </div>\n }\n @if (section.descriptionKey) {\n <div class=\"text-gray-800 text-sm\" translate>\n {{ section.descriptionKey }}\n </div>\n }\n </div>\n <div class=\"grid auto-rows-auto grid-cols-2 gap-[32px]\">\n @for (\n field of section.fieldsWithValues;\n track fieldTracker($index, field)\n ) {\n @if (!field.config.hidden) {\n <gn-ui-form-field\n [ngClass]=\"\n field.config.gridColumnSpan === 1\n ? 'col-span-1'\n : 'col-span-2'\n \"\n [uniqueIdentifier]=\"recordUniqueIdentifier$ | async\"\n [model]=\"field.config.model!\"\n [modelSpecifier]=\"field.config.modelSpecifier!\"\n [config]=\"field.config.formFieldConfig\"\n [value]=\"field.value\"\n [componentName]=\"field.config.componentName\"\n (valueChange)=\"\n handleFieldValueChange(field.config.model!, $event)\n \"\n ></gn-ui-form-field>\n }\n }\n </div>\n </div>\n }\n }\n</div>\n" }]
43784
43970
  }] });
43785
43971
 
43786
- const extraFlagMap = {
43787
- ar: 'arab',
43788
- en: 'gb',
43789
- ko: 'kr',
43790
- cs: 'cz',
43791
- zh: 'cn',
43792
- ca: 'es-ct',
43793
- rm: 'ch',
43794
- da: 'dk',
43795
- sv: 'se',
43796
- cy: 'gb-wls',
43797
- hy: 'am',
43798
- ka: 'ge',
43799
- uk: 'ua',
43800
- };
43801
- class MultilingualPanelComponent {
43802
- constructor() {
43803
- this.facade = inject(EditorFacade);
43804
- this.dialog = inject(MatDialog);
43805
- this.translateService = inject(TranslateService);
43806
- this.recordsRepository = inject(RecordsRepositoryInterface);
43807
- this.overlay = inject(Overlay);
43808
- this.viewContainerRef = inject(ViewContainerRef);
43809
- this.cdr = inject(ChangeDetectorRef);
43810
- this.selectedLanguages = [];
43811
- this.recordLanguages = [];
43812
- this.formLanguage = '';
43813
- this.isActionMenuOpen = false;
43814
- this.subscription = new Subscription();
43815
- this.supportedLanguages$ = this.recordsRepository
43816
- .getApplicationLanguages()
43817
- .pipe(map$2((languages) => this.sortLanguages(languages)));
43818
- }
43819
- set record(value) {
43820
- this._record = value;
43821
- this.isMultilingual = value.otherLanguages.length > 0;
43822
- this.editTranslations = false;
43823
- this.recordLanguages = [...value.otherLanguages, value.defaultLanguage];
43824
- this.selectedLanguages = this.recordLanguages;
43825
- this.formLanguage = value.defaultLanguage;
43826
- }
43827
- ngOnDestroy() {
43828
- this.subscription.unsubscribe();
43829
- }
43830
- sortLanguages(languages) {
43831
- return languages
43832
- .map((lang) => {
43833
- const label = this.translateService.instant('language.' + lang);
43834
- const isTranslated = label !== 'language.' + lang;
43835
- return {
43836
- lang,
43837
- label,
43838
- isTranslated,
43839
- };
43840
- })
43841
- .sort((a, b) => {
43842
- if (a.isTranslated && !b.isTranslated)
43843
- return -1;
43844
- if (!a.isTranslated && b.isTranslated)
43845
- return 1;
43846
- return a.label.localeCompare(b.label);
43847
- })
43848
- .map((item) => item.lang);
43849
- }
43850
- toggleLanguageSelection() {
43851
- this.editTranslations = !this.editTranslations;
43852
- }
43853
- getIconClass(lang) {
43854
- return extraFlagMap[lang]
43855
- ? `fi fi-${extraFlagMap[lang]} w-4 h-3`
43856
- : `fi fi-${lang} w-4 h-3`;
43857
- }
43858
- switchMultilingual() {
43859
- if (this.isMultilingual && this.selectedLanguages.length > 1) {
43860
- this.confirmDeleteAction();
43861
- }
43862
- else {
43863
- this.isMultilingual = true;
43864
- this.editTranslations = true;
43865
- }
43866
- }
43867
- getExtraClass(lang) {
43868
- const baseClass = 'h-[34px] w-full font-bold justify-start hover:bg-white';
43869
- if (this.selectedLanguages.includes(lang)) {
43870
- return `${baseClass} bg-white border border-black`;
43871
- }
43872
- return baseClass;
43972
+ function evaluate(expression) {
43973
+ if (expression.match(/^\${.*}$/)) {
43974
+ return evaluate(expression.slice(2, -1));
43873
43975
  }
43874
- toggleLanguage(lang) {
43875
- if (this.selectedLanguages.includes(lang)) {
43876
- this.removeSelectedLanguage(lang);
43877
- }
43878
- else {
43879
- this.selectedLanguages.push(lang);
43880
- }
43976
+ const operator = expression.split('(')[0];
43977
+ switch (operator) {
43978
+ case 'dateNow':
43979
+ return () => new Date();
43980
+ default:
43981
+ throw new Error(`Unknown operator: ${operator}`);
43881
43982
  }
43882
- removeSelectedLanguage(lang) {
43883
- this.selectedLanguages = this.selectedLanguages.filter((language) => language !== lang);
43983
+ }
43984
+
43985
+ class EditorService {
43986
+ constructor() {
43987
+ this.recordsRepository = inject(RecordsRepositoryInterface);
43884
43988
  }
43885
- validateTranslations() {
43886
- const equalLength = this.selectedLanguages.length === this.recordLanguages.length;
43887
- if (this.selectedLanguages.length < this.recordLanguages.length ||
43888
- (equalLength && this.selectedLanguages !== this.recordLanguages)) {
43889
- this.confirmDeleteAction(this.selectedLanguages);
43989
+ // returns the record as it was when saved, alongside its source
43990
+ saveRecord(record, recordSource, fieldsConfig) {
43991
+ const savedRecord = { ...record };
43992
+ const fields = fieldsConfig.pages.flatMap((page) => page.sections.flatMap((section) => section.fields));
43993
+ // run onSave processes
43994
+ for (const field of fields) {
43995
+ if (field.onSaveProcess && field.model) {
43996
+ const evaluator = evaluate(field.onSaveProcess);
43997
+ savedRecord[field.model] = evaluator({
43998
+ model: field.model,
43999
+ value: record[field.model],
44000
+ });
44001
+ }
43890
44002
  }
43891
- else {
43892
- this.updateTranslations();
44003
+ let publishToAll = true;
44004
+ // if the record is new, generate a new unique identifier and pass publishToAll as false
44005
+ if (!record.uniqueIdentifier) {
44006
+ savedRecord.uniqueIdentifier = null;
44007
+ publishToAll = false;
43893
44008
  }
44009
+ return this.recordsRepository
44010
+ .saveRecord(savedRecord, recordSource, publishToAll)
44011
+ .pipe(switchMap((uniqueIdentifier) => this.recordsRepository.openRecordForEdition(uniqueIdentifier)), tap$1(() => {
44012
+ // if saving was successful, the original draft can be discarded
44013
+ this.recordsRepository.clearRecordDraft(record.uniqueIdentifier);
44014
+ }), map$1(([record, recordSource]) => [record, recordSource]));
43894
44015
  }
43895
- updateTranslations() {
43896
- const newLanguageSelection = this.selectedLanguages.filter((lang) => lang !== this.formLanguage);
43897
- this.facade.updateRecordLanguages(this.formLanguage, newLanguageSelection);
43898
- this.recordLanguages = newLanguageSelection;
43899
- this.editTranslations = false;
43900
- }
43901
- switchFormLang(lang) {
43902
- // TO IMPLEMENT FURTHER
43903
- }
43904
- switchDefaultLang(lang) {
43905
- this.formLanguage = lang;
43906
- this.facade.updateRecordLanguages(lang, this.selectedLanguages.filter((lang) => lang !== this.formLanguage));
43907
- this.closeActionMenu();
43908
- }
43909
- confirmDeleteAction(lang) {
43910
- const dialogRef = this.dialog.open(ConfirmationDialogComponent, {
43911
- data: {
43912
- title: this.translateService.instant('editor.record.multilingual.confirmation.title'),
43913
- message: this.translateService.instant('editor.record.multilingual.confirmation.message'),
43914
- confirmText: this.translateService.instant('editor.record.multilingual.confirmation.confirmText'),
43915
- cancelText: this.translateService.instant('editor.record.multilingual.confirmation.cancelText'),
43916
- focusCancel: true,
43917
- },
43918
- restoreFocus: true,
43919
- });
43920
- this.subscription.add(dialogRef.afterClosed().subscribe((confirmed) => {
43921
- if (confirmed) {
43922
- if (lang) {
43923
- if (!Array.isArray(lang)) {
43924
- this.removeSelectedLanguage(lang);
43925
- this.closeActionMenu();
43926
- }
43927
- this.updateTranslations();
43928
- }
43929
- else {
43930
- this.facade.updateRecordLanguages(this.formLanguage, []);
43931
- this.isMultilingual = false;
43932
- this.selectedLanguages = [];
43933
- }
43934
- }
43935
- else {
43936
- this.isMultilingual = true;
43937
- this.selectedLanguages = this.recordLanguages;
43938
- }
43939
- this.editTranslations = false;
43940
- }));
43941
- }
43942
- isFirstUnsupported(index) {
43943
- const langs = this.sortLanguages(this.recordLanguages);
43944
- return (langs[index].length === 3 &&
43945
- langs.slice(0, index).every((lang) => lang.length !== 3));
43946
- }
43947
- isLangSupported(lang) {
43948
- return lang.length === 2;
43949
- }
43950
- getToggleTitle(lang) {
43951
- if (lang === this._record.defaultLanguage) {
43952
- return this.translateService.instant('editor.record.form.multilingual.forbidden');
43953
- }
43954
- return '';
44016
+ // emits and completes once saving is done
44017
+ // note: onSave processes are not run for drafts
44018
+ saveRecordAsDraft(record, recordSource) {
44019
+ record.recordUpdated = new Date();
44020
+ return this.recordsRepository
44021
+ .saveRecordAsDraft(record, recordSource)
44022
+ .pipe(map$1(() => undefined));
43955
44023
  }
43956
- openActionMenu(item, template) {
43957
- this.isActionMenuOpen = true;
43958
- const index = this.sortLanguages(this.selectedLanguages).indexOf(item);
43959
- const buttonElement = this.actionMenuButtons.toArray()[index];
43960
- const positionStrategy = this.overlay
43961
- .position()
43962
- .flexibleConnectedTo(buttonElement)
43963
- .withFlexibleDimensions(true)
43964
- .withPush(true)
43965
- .withPositions([
43966
- {
43967
- originX: 'end',
43968
- originY: 'bottom',
43969
- overlayX: 'end',
43970
- overlayY: 'top',
43971
- },
43972
- {
43973
- originX: 'end',
43974
- originY: 'top',
43975
- overlayX: 'end',
43976
- overlayY: 'bottom',
43977
- },
43978
- ]);
43979
- this.overlayRef = this.overlay.create({
43980
- hasBackdrop: true,
43981
- backdropClass: 'cdk-overlay-transparent-backdrop',
43982
- positionStrategy: positionStrategy,
43983
- scrollStrategy: this.overlay.scrollStrategies.reposition(),
43984
- });
43985
- const portal = new TemplatePortal(template, this.viewContainerRef);
43986
- this.overlayRef.attach(portal);
43987
- this.subscription.add(this.overlayRef.backdropClick().subscribe(() => {
43988
- this.closeActionMenu();
43989
- }));
44024
+ undoRecordDraft(record) {
44025
+ this.recordsRepository.clearRecordDraft(record.uniqueIdentifier);
44026
+ return this.recordsRepository.openRecordForEdition(record.uniqueIdentifier);
43990
44027
  }
43991
- closeActionMenu() {
43992
- if (this.overlayRef) {
43993
- this.isActionMenuOpen = false;
43994
- this.overlayRef.dispose();
43995
- this.cdr.markForCheck();
43996
- }
44028
+ hasRecordChangedSinceDraft(localRecord) {
44029
+ return this.recordsRepository.hasRecordChangedSinceDraft(localRecord);
43997
44030
  }
43998
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: MultilingualPanelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
43999
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: MultilingualPanelComponent, isStandalone: true, selector: "gn-ui-multilingual-panel", inputs: { record: "record" }, providers: [
44000
- provideIcons({
44001
- iconoirSettings,
44002
- matMoreHorizOutline,
44003
- iconoirCheckCircle,
44004
- iconoirCircle,
44005
- }),
44006
- provideNgIconsConfig({
44007
- size: '1.25em',
44008
- }),
44009
- ], viewQueries: [{ propertyName: "actionMenuButtons", predicate: ["actionMenuButton"], descendants: true, read: ElementRef }], ngImport: i0, template: "<div\n class=\"flex flex-col h-full w-[302px] border-l border-gray-300 py-8 px-3 gap-6 overflow-auto\"\n style=\"background-color: #fafaf9\"\n>\n <div class=\"flex flex-row px-2 justify-between\">\n <span class=\"text-3xl font-title text-black/80\" translate\n >editor.record.form.multilingual.title</span\n >\n @if (isMultilingual) {\n <button\n [title]=\"'editor.record.form.multilingual.open' | translate\"\n (click)=\"toggleLanguageSelection()\"\n data-test=\"activateSelection\"\n >\n <ng-icon class=\"mt-1\" name=\"iconoirSettings\"></ng-icon>\n </button>\n }\n </div>\n @if (editTranslations || !isMultilingual) {\n <div class=\"flex flex-col gap-2\">\n <gn-ui-check-toggle\n class=\"p-2\"\n [label]=\"'editor.record.form.multilingual.enable' | translate\"\n [color]=\"'primary'\"\n [(value)]=\"isMultilingual\"\n (toggled)=\"switchMultilingual($event)\"\n ></gn-ui-check-toggle>\n @if (isMultilingual) {\n <div class=\"flex flex-col gap-2\">\n <div\n class=\"flex flex-row justify-between border-t border-gray-300 p-3\"\n >\n <span class=\"mt-2 text-sm text-gray-600\" translate\n >editor.record.form.multilingual.activate</span\n >\n <gn-ui-button\n extraClass=\"w-16 h-8 font-bold\"\n type=\"gray\"\n (buttonClick)=\"validateTranslations()\"\n data-test=\"validateSelection\"\n >{{ 'editor.record.form.multilingual.validate' | translate }}\n </gn-ui-button>\n </div>\n @if (supportedLanguages$ | async; as languages) {\n @for (lang of languages; track lang) {\n <div\n class=\"flex flex-col gap-2 w-full px-2\"\n data-test=\"langAvailable\"\n [attr.data-test-lang]=\"lang\"\n >\n <gn-ui-button\n [extraClass]=\"getExtraClass(lang)\"\n type=\"gray\"\n (buttonClick)=\"toggleLanguage(lang)\"\n [disabled]=\"lang === _record.defaultLanguage\"\n [title]=\"getToggleTitle(lang)\"\n >\n <span [class]=\"getIconClass(lang)\"></span>\n <span class=\"ml-2\">{{ 'language.' + lang | translate }}</span>\n </gn-ui-button>\n </div>\n }\n }\n </div>\n }\n </div>\n }\n @if (!editTranslations && isMultilingual) {\n <div class=\"flex flex-col gap-2\">\n @for (\n recordLang of sortLanguages(recordLanguages);\n track recordLang;\n let i = $index\n ) {\n <gn-ui-button\n extraClass=\"flex flex-row justify-between bg-white border border-white rounded mb-1 h-[34px] w-full\"\n [ngClass]=\"{\n 'mt-8': isFirstUnsupported(i),\n '': true,\n }\"\n (buttonClick)=\"switchFormLang(recordLang)\"\n type=\"outline\"\n data-test=\"langSwitch\"\n >\n <div class=\"flex flex-row gap-2 items-center\">\n @if (recordLang === formLanguage) {\n <ng-icon\n class=\"text-primary mt-1\"\n name=\"iconoirCheckCircle\"\n ></ng-icon>\n }\n @if (recordLang !== formLanguage) {\n <ng-icon\n class=\"text-gray-800 mt-1\"\n name=\"iconoirCircle\"\n ></ng-icon>\n }\n @if (recordLang.length === 2) {\n <span [class]=\"getIconClass(recordLang) + 'mt-1'\"></span>\n }\n <span [ngClass]=\"recordLang === formLanguage ? 'text-black' : ''\">{{\n isLangSupported(recordLang)\n ? ('language.' + recordLang | translate)\n : recordLang.toUpperCase()\n }}</span>\n </div>\n <div class=\"flex flex-row gap-2 items-center\">\n @if (recordLang === formLanguage) {\n <span class=\"text-xs text-base\" translate\n >editor.record.form.multilingual.default</span\n >\n }\n <button\n (click)=\"\n openActionMenu(recordLang, template); $event.stopPropagation()\n \"\n cdkOverlayOrigin\n #actionMenuButton\n >\n <ng-icon class=\"pb-5\" name=\"matMoreHorizOutline\"></ng-icon>\n </button>\n <ng-template #template>\n <gn-ui-action-menu\n [canDelete]=\"recordLang !== _record.defaultLanguage\"\n page=\"record\"\n (delete)=\"confirmDeleteAction(recordLang)\"\n (closeActionMenu)=\"closeActionMenu()\"\n (switch)=\"switchDefaultLang(recordLang)\"\n >\n </gn-ui-action-menu>\n </ng-template>\n </div>\n </gn-ui-button>\n }\n </div>\n }\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: CheckToggleComponent, selector: "gn-ui-check-toggle", inputs: ["title", "label", "value", "color"], outputs: ["toggled"] }, { kind: "directive", type: TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }, { kind: "component", type: ButtonComponent, selector: "gn-ui-button", inputs: ["type", "disabled", "extraClass"], outputs: ["buttonClick"] }, { kind: "component", type: NgIconComponent, selector: "ng-icon", inputs: ["name", "svg", "size", "strokeWidth", "color"] }, { kind: "component", type: ActionMenuComponent, selector: "gn-ui-action-menu", inputs: ["canDuplicate", "isDuplicating", "canDelete", "page"], outputs: ["duplicate", "delete", "closeActionMenu", "rollback", "switch"] }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
44031
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: EditorService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
44032
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: EditorService, providedIn: 'root' }); }
44010
44033
  }
44011
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: MultilingualPanelComponent, decorators: [{
44012
- type: Component,
44013
- args: [{ selector: 'gn-ui-multilingual-panel', standalone: true, imports: [
44014
- CommonModule,
44015
- CheckToggleComponent,
44016
- TranslateDirective,
44017
- TranslatePipe,
44018
- ButtonComponent,
44019
- NgIconComponent,
44020
- ActionMenuComponent,
44021
- ], providers: [
44022
- provideIcons({
44023
- iconoirSettings,
44024
- matMoreHorizOutline,
44025
- iconoirCheckCircle,
44026
- iconoirCircle,
44027
- }),
44028
- provideNgIconsConfig({
44029
- size: '1.25em',
44030
- }),
44031
- ], template: "<div\n class=\"flex flex-col h-full w-[302px] border-l border-gray-300 py-8 px-3 gap-6 overflow-auto\"\n style=\"background-color: #fafaf9\"\n>\n <div class=\"flex flex-row px-2 justify-between\">\n <span class=\"text-3xl font-title text-black/80\" translate\n >editor.record.form.multilingual.title</span\n >\n @if (isMultilingual) {\n <button\n [title]=\"'editor.record.form.multilingual.open' | translate\"\n (click)=\"toggleLanguageSelection()\"\n data-test=\"activateSelection\"\n >\n <ng-icon class=\"mt-1\" name=\"iconoirSettings\"></ng-icon>\n </button>\n }\n </div>\n @if (editTranslations || !isMultilingual) {\n <div class=\"flex flex-col gap-2\">\n <gn-ui-check-toggle\n class=\"p-2\"\n [label]=\"'editor.record.form.multilingual.enable' | translate\"\n [color]=\"'primary'\"\n [(value)]=\"isMultilingual\"\n (toggled)=\"switchMultilingual($event)\"\n ></gn-ui-check-toggle>\n @if (isMultilingual) {\n <div class=\"flex flex-col gap-2\">\n <div\n class=\"flex flex-row justify-between border-t border-gray-300 p-3\"\n >\n <span class=\"mt-2 text-sm text-gray-600\" translate\n >editor.record.form.multilingual.activate</span\n >\n <gn-ui-button\n extraClass=\"w-16 h-8 font-bold\"\n type=\"gray\"\n (buttonClick)=\"validateTranslations()\"\n data-test=\"validateSelection\"\n >{{ 'editor.record.form.multilingual.validate' | translate }}\n </gn-ui-button>\n </div>\n @if (supportedLanguages$ | async; as languages) {\n @for (lang of languages; track lang) {\n <div\n class=\"flex flex-col gap-2 w-full px-2\"\n data-test=\"langAvailable\"\n [attr.data-test-lang]=\"lang\"\n >\n <gn-ui-button\n [extraClass]=\"getExtraClass(lang)\"\n type=\"gray\"\n (buttonClick)=\"toggleLanguage(lang)\"\n [disabled]=\"lang === _record.defaultLanguage\"\n [title]=\"getToggleTitle(lang)\"\n >\n <span [class]=\"getIconClass(lang)\"></span>\n <span class=\"ml-2\">{{ 'language.' + lang | translate }}</span>\n </gn-ui-button>\n </div>\n }\n }\n </div>\n }\n </div>\n }\n @if (!editTranslations && isMultilingual) {\n <div class=\"flex flex-col gap-2\">\n @for (\n recordLang of sortLanguages(recordLanguages);\n track recordLang;\n let i = $index\n ) {\n <gn-ui-button\n extraClass=\"flex flex-row justify-between bg-white border border-white rounded mb-1 h-[34px] w-full\"\n [ngClass]=\"{\n 'mt-8': isFirstUnsupported(i),\n '': true,\n }\"\n (buttonClick)=\"switchFormLang(recordLang)\"\n type=\"outline\"\n data-test=\"langSwitch\"\n >\n <div class=\"flex flex-row gap-2 items-center\">\n @if (recordLang === formLanguage) {\n <ng-icon\n class=\"text-primary mt-1\"\n name=\"iconoirCheckCircle\"\n ></ng-icon>\n }\n @if (recordLang !== formLanguage) {\n <ng-icon\n class=\"text-gray-800 mt-1\"\n name=\"iconoirCircle\"\n ></ng-icon>\n }\n @if (recordLang.length === 2) {\n <span [class]=\"getIconClass(recordLang) + 'mt-1'\"></span>\n }\n <span [ngClass]=\"recordLang === formLanguage ? 'text-black' : ''\">{{\n isLangSupported(recordLang)\n ? ('language.' + recordLang | translate)\n : recordLang.toUpperCase()\n }}</span>\n </div>\n <div class=\"flex flex-row gap-2 items-center\">\n @if (recordLang === formLanguage) {\n <span class=\"text-xs text-base\" translate\n >editor.record.form.multilingual.default</span\n >\n }\n <button\n (click)=\"\n openActionMenu(recordLang, template); $event.stopPropagation()\n \"\n cdkOverlayOrigin\n #actionMenuButton\n >\n <ng-icon class=\"pb-5\" name=\"matMoreHorizOutline\"></ng-icon>\n </button>\n <ng-template #template>\n <gn-ui-action-menu\n [canDelete]=\"recordLang !== _record.defaultLanguage\"\n page=\"record\"\n (delete)=\"confirmDeleteAction(recordLang)\"\n (closeActionMenu)=\"closeActionMenu()\"\n (switch)=\"switchDefaultLang(recordLang)\"\n >\n </gn-ui-action-menu>\n </ng-template>\n </div>\n </gn-ui-button>\n }\n </div>\n }\n</div>\n" }]
44032
- }], propDecorators: { record: [{
44033
- type: Input
44034
- }], actionMenuButtons: [{
44035
- type: ViewChildren,
44036
- args: ['actionMenuButton', { read: ElementRef }]
44037
- }] } });
44034
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: EditorService, decorators: [{
44035
+ type: Injectable,
44036
+ args: [{
44037
+ providedIn: 'root',
44038
+ }]
44039
+ }] });
44038
44040
 
44039
- //forced translations that are not available in fields.config.ts
44040
- marker('editor.record.form.field.keywords');
44041
- marker('editor.record.form.field.topics');
44042
- marker('editor.record.form.field.contacts');
44043
- marker('editor.record.form.field.organisation');
44044
- class MetadataQualityPanelComponent {
44041
+ class EditorEffects {
44045
44042
  constructor() {
44046
- this.propsToValidate = getAllKeysValidator();
44047
- this.propertiesByPage = [];
44048
- }
44049
- ngOnChanges() {
44050
- if (this.editorConfig && this.record) {
44051
- const fieldsByPage = this.editorConfig.pages.map((page) => page.sections.flatMap((section) => section.fields
44052
- .filter((field) => this.propsToValidate.includes(field.model))
44053
- .map((field) => field.model)));
44054
- // FIXME: temporarily add topics and organisation to the first and third page
44055
- // as long as they are not handled by the editor
44056
- if (fieldsByPage.length > 0) {
44057
- fieldsByPage[0].includes('topics') || fieldsByPage[0].push('topics');
44058
- fieldsByPage[2].includes('organisation') ||
44059
- fieldsByPage[2].push('organisation');
44043
+ this.actions$ = inject(Actions);
44044
+ this.editorService = inject(EditorService);
44045
+ this.recordsRepository = inject(RecordsRepositoryInterface);
44046
+ this.plateformService = inject(PlatformServiceInterface);
44047
+ this.store = inject(Store);
44048
+ this.saveRecord$ = createEffect(() => this.actions$.pipe(ofType(saveRecord), withLatestFrom$1(this.store.select(selectRecord), this.store.select(selectRecordSource), this.store.select(selectEditorConfig)), switchMap$1(([, record, recordSource, fieldsConfig]) => this.editorService.saveRecord(record, recordSource, fieldsConfig).pipe(switchMap$1(([savedRecord, savedRecordSource]) => {
44049
+ const actions = [saveRecordSuccess()];
44050
+ if (!record?.uniqueIdentifier) {
44051
+ actions.push(openRecord({
44052
+ record: savedRecord,
44053
+ recordSource: savedRecordSource,
44054
+ }));
44060
44055
  }
44061
- this.propertiesByPage = fieldsByPage
44062
- .map((fields) => getQualityValidators(this.record, fields).map(({ name, validator }) => ({
44063
- label: `editor.record.form.field.${name}`, // use same translations as in fields.config.ts
44064
- value: validator(),
44065
- })))
44066
- .filter((arr) => arr.length > 0);
44067
- }
44068
- }
44069
- getExtraClass(checked) {
44070
- const baseClasses = 'flex flex-row justify-between rounded mb-1 h-[34px] w-full focus:ring-0 hover:border-none border-none hover:text-black text-black cursor-default';
44071
- return checked
44072
- ? `${baseClasses} bg-neutral-100 hover:bg-neutral-100`
44073
- : `${baseClasses} bg-transparent hover:bg-transparent`;
44056
+ return of(...actions);
44057
+ }), catchError((error) => of(saveRecordFailure({
44058
+ error,
44059
+ })))))));
44060
+ this.cleanRecordAttachments$ = createEffect(() => this.actions$.pipe(ofType(saveRecordSuccess), withLatestFrom$1(this.store.select(selectRecord)), switchMap$1(([_, record]) => {
44061
+ if (record.uniqueIdentifier !== null) {
44062
+ this.plateformService.cleanRecordAttachments(record).subscribe({
44063
+ next: (_) => undefined,
44064
+ error: (err) => {
44065
+ console.error(err);
44066
+ },
44067
+ });
44068
+ }
44069
+ return EMPTY;
44070
+ }), catchError((error) => {
44071
+ console.error(error);
44072
+ return EMPTY;
44073
+ })), { dispatch: false });
44074
+ this.markAsChanged$ = createEffect(() => this.actions$.pipe(ofType(updateRecordField, updateRecordLanguages), map$1(() => markRecordAsChanged())));
44075
+ this.saveRecordDraft$ = createEffect(() => this.actions$.pipe(ofType(updateRecordField, updateRecordLanguages), debounceTime$1(1000), withLatestFrom$1(this.store.select(selectRecord), this.store.select(selectRecordSource)), switchMap$1(([, record, recordSource]) => this.editorService.saveRecordAsDraft(record, recordSource)), map$1(() => draftSaveSuccess())));
44076
+ this.undoRecordDraft$ = createEffect(() => this.actions$.pipe(ofType(undoRecordDraft), withLatestFrom$1(this.store.select(selectRecord)), switchMap$1(([, record]) => this.editorService.undoRecordDraft(record)), map$1(([record, recordSource]) => openRecord({
44077
+ record,
44078
+ recordSource,
44079
+ }))));
44080
+ this.checkHasChangesOnOpen$ = createEffect(() => this.actions$.pipe(ofType(openRecord), map$1(({ record }) => this.recordsRepository.recordHasDraft(record.uniqueIdentifier)), filter((hasDraft) => hasDraft), map$1(() => markRecordAsChanged())));
44081
+ this.hasRecordChangedSinceDraft$ = createEffect(() => this.actions$.pipe(ofType(hasRecordChangedSinceDraft), switchMap$1(({ record }) => this.editorService
44082
+ .hasRecordChangedSinceDraft(record)
44083
+ .pipe(map$1((changes) => hasRecordChangedSinceDraftSuccess({ changes }))))));
44084
+ this.checkIsRecordPublished$ = createEffect(() => this.actions$.pipe(ofType(openRecord), map$1(({ record }) => record.uniqueIdentifier), switchMap$1((uniqueIdentifier) => this.recordsRepository.getRecordPublicationStatus(uniqueIdentifier)), map$1((isPublished$1) => isPublished({
44085
+ isPublished: isPublished$1,
44086
+ }))));
44087
+ this.checkCanEditRecord$ = createEffect(() => this.actions$.pipe(ofType(openRecord), map$1(({ record }) => record.uniqueIdentifier), switchMap$1((uniqueIdentifier) => this.recordsRepository.canEditRecord(uniqueIdentifier)), map$1((canEditRecord$1) => canEditRecord({
44088
+ canEditRecord: canEditRecord$1,
44089
+ }))));
44074
44090
  }
44075
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: MetadataQualityPanelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
44076
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: MetadataQualityPanelComponent, isStandalone: true, selector: "gn-ui-metadata-quality-panel", inputs: { editorConfig: "editorConfig", record: "record" }, providers: [
44077
- provideIcons({
44078
- iconoirSystemShut,
44079
- iconoirBadgeCheck,
44080
- }),
44081
- provideNgIconsConfig({
44082
- size: '1.25em',
44083
- }),
44084
- ], usesOnChanges: true, ngImport: i0, template: "<div\n class=\"flex flex-col h-full w-[302px] border-l border-gray-300 py-8 px-3 gap-3 overflow-auto\"\n style=\"background-color: #fafaf9\"\n>\n <div class=\"flex flex-row px-2 justify-between\">\n <span class=\"text-3xl font-title text-black/80\" translate\n >editor.record.form.metadataQuality.title</span\n >\n </div>\n @for (properties of propertiesByPage; track properties; let i = $index) {\n <div class=\"flex flex-col gap-2\">\n @for (property of properties; track property) {\n <gn-ui-button\n [extraClass]=\"getExtraClass(property.value)\"\n type=\"outline\"\n attr.data-cy=\"md-quality-btn-{{ property.label }}\"\n >\n <span>{{ property.label | translate }}</span>\n <div class=\"flex flex-row gap-2 items-center\">\n @if (property.value) {\n <ng-icon class=\"text-primary\" name=\"iconoirBadgeCheck\"></ng-icon>\n } @else {\n <ng-icon\n class=\"text-neutral-300\"\n name=\"iconoirSystemShut\"\n ></ng-icon>\n }\n </div>\n </gn-ui-button>\n }\n @if (i !== propertiesByPage.length - 1) {\n <hr class=\"border-gray-300 w-11/12 mx-auto\" />\n }\n </div>\n }\n</div>\n", styles: [""], dependencies: [{ kind: "directive", type: TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }, { kind: "component", type: ButtonComponent, selector: "gn-ui-button", inputs: ["type", "disabled", "extraClass"], outputs: ["buttonClick"] }, { kind: "component", type: NgIconComponent, selector: "ng-icon", inputs: ["name", "svg", "size", "strokeWidth", "color"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
44091
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: EditorEffects, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
44092
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: EditorEffects }); }
44085
44093
  }
44086
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: MetadataQualityPanelComponent, decorators: [{
44087
- type: Component,
44088
- args: [{ selector: 'gn-ui-metadata-quality-panel', standalone: true, imports: [
44089
- TranslateDirective,
44090
- TranslatePipe,
44091
- ButtonComponent,
44092
- NgIconComponent,
44093
- ], providers: [
44094
- provideIcons({
44095
- iconoirSystemShut,
44096
- iconoirBadgeCheck,
44097
- }),
44098
- provideNgIconsConfig({
44099
- size: '1.25em',
44100
- }),
44101
- ], template: "<div\n class=\"flex flex-col h-full w-[302px] border-l border-gray-300 py-8 px-3 gap-3 overflow-auto\"\n style=\"background-color: #fafaf9\"\n>\n <div class=\"flex flex-row px-2 justify-between\">\n <span class=\"text-3xl font-title text-black/80\" translate\n >editor.record.form.metadataQuality.title</span\n >\n </div>\n @for (properties of propertiesByPage; track properties; let i = $index) {\n <div class=\"flex flex-col gap-2\">\n @for (property of properties; track property) {\n <gn-ui-button\n [extraClass]=\"getExtraClass(property.value)\"\n type=\"outline\"\n attr.data-cy=\"md-quality-btn-{{ property.label }}\"\n >\n <span>{{ property.label | translate }}</span>\n <div class=\"flex flex-row gap-2 items-center\">\n @if (property.value) {\n <ng-icon class=\"text-primary\" name=\"iconoirBadgeCheck\"></ng-icon>\n } @else {\n <ng-icon\n class=\"text-neutral-300\"\n name=\"iconoirSystemShut\"\n ></ng-icon>\n }\n </div>\n </gn-ui-button>\n }\n @if (i !== propertiesByPage.length - 1) {\n <hr class=\"border-gray-300 w-11/12 mx-auto\" />\n }\n </div>\n }\n</div>\n" }]
44102
- }], propDecorators: { editorConfig: [{
44103
- type: Input
44104
- }], record: [{
44105
- type: Input
44106
- }] } });
44094
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: EditorEffects, decorators: [{
44095
+ type: Injectable
44096
+ }] });
44097
+
44098
+ class FeatureEditorModule {
44099
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: FeatureEditorModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
44100
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.15", ngImport: i0, type: FeatureEditorModule, imports: [i1.StoreFeatureModule, i2$2.EffectsFeatureModule] }); }
44101
+ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: FeatureEditorModule, providers: [EditorFacade, provideHttpClient()], imports: [StoreModule.forFeature(EDITOR_FEATURE_KEY, editorReducer),
44102
+ EffectsModule.forFeature([EditorEffects])] }); }
44103
+ }
44104
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: FeatureEditorModule, decorators: [{
44105
+ type: NgModule,
44106
+ args: [{
44107
+ imports: [
44108
+ StoreModule.forFeature(EDITOR_FEATURE_KEY, editorReducer),
44109
+ EffectsModule.forFeature([EditorEffects]),
44110
+ ],
44111
+ providers: [EditorFacade, provideHttpClient()],
44112
+ }]
44113
+ }] });
44107
44114
 
44108
44115
  const ROUTER_STATE_KEY = 'router';
44109
44116
  const ROUTER_ROUTE_SEARCH = 'search';
@@ -44546,5 +44553,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
44546
44553
  * Generated bundle index. Do not edit.
44547
44554
  */
44548
44555
 
44549
- export { ADD_RESULTS, ADD_SEARCH, AbstractAction, AbstractSearchField, ActionMenuComponent, AddLayerFromCatalogComponent, AddLayerRecordPreviewComponent, AddResults, AddSearch, AnchorLinkDirective, ApiCardComponent, ApplicationBannerComponent, AuthService, AutocompleteComponent, AvailableServicesField, AvatarComponent, AvatarServiceInterface, BASEMAP_LAYERS, BadgeComponent, BaseConverter, BaseFileReader, BaseReader, BlockListComponent, ButtonComponent, CLEAR_ERROR, CLEAR_RESULTS, CarouselComponent, CatalogTitleComponent, CellPopinComponent, ChartComponent, ChartViewComponent, CheckToggleComponent, CheckboxComponent, ClearError, ClearResults, ColorScaleComponent, ConfirmationDialogComponent, ContentGhostComponent, CopyTextButtonComponent, DEFAULT_GN4_LOGIN_URL, DEFAULT_GN4_LOGOUT_URL, DEFAULT_GN4_SETTINGS_URL, DEFAULT_LANG, DEFAULT_PAGE_SIZE, DEFAULT_RESULTS_LAYOUT_CONFIG, DEFAULT_SEARCH_KEY, DISABLE_AUTH, DO_NOT_USE_DEFAULT_BASEMAP, DataService, DataTableComponent, DataViewComponent, DataViewPermalinkComponent, DataViewShareComponent, DataViewWebComponentComponent, DatePickerComponent, DateRangeDropdownComponent, DateRangeInputsComponent, DateRangePickerComponent, DateRangeSearchField, DateService, DcatApConverter, DefaultRouterModule, DownloadItemComponent, DownloadsListComponent, DragAndDropFileInputComponent, DropdownMultiselectComponent, DropdownSelectorComponent, EDITOR_FEATURE_KEY, ES_QUERY_FIELDS_PRIORITY, ES_RESOURCES_VALUES, ES_SOURCE_SUMMARY, EXTERNAL_VIEWER_OPEN_NEW_TAB, EXTERNAL_VIEWER_URL_TEMPLATE, EditableLabelDirective, EditorFacade, EditorService, ElasticsearchService, EmbeddedTranslateLoader, ErrorComponent, ErrorType, ExpandablePanelButtonComponent, ExpandablePanelComponent, ExternalLinkCardComponent, ExternalViewerButtonComponent, FIELDS_BRIEF, FIELDS_SUMMARY, FILTER_GEOMETRY, FILTER_SUMMARY_IGNORE_LIST, FORMATS, FacetBlockComponent, FacetItemComponent, FacetListComponent, FacetsContainerComponent, FavoriteStarComponent, FavoritesService, FeatureCatalogListComponent, FeatureDetailComponent, FeatureEditorModule, FeatureMapModule, FeatureRecordModule, FeatureSearchModule, FetchError, FieldsService, FigureComponent, FigureContainerComponent, FileInputComponent, FileTranslateLoader, FilesDropDirective, FilterDropdownComponent, FormFieldArrayComponent, FormFieldComponent, FormFieldDateComponent, FormFieldFileComponent, FormFieldKeywordsComponent, FormFieldLicenseComponent, FormFieldObjectComponent, FormFieldRichComponent, FormFieldSimpleComponent, FormFieldSpatialExtentComponent, FormFieldTemporalExtentsComponent, FormFieldTopicsComponent, FormFieldWrapperComponent, FullTextSearchField, FuzzySearchComponent, GEONETWORK_UI_TAG_NAME, GEONETWORK_UI_VERSION, GeoDataBadgeComponent, GeoTableViewComponent, GeocodingComponent, GeojsonReader, Gn4Converter, Gn4PlatformMapper, Gn4PlatformService, Gn4Repository, Gn4SettingsService, GnUiHumanizeDateDirective, GpfApiDlComponent, GravatarService, HttpLoaderFactory, I18nInterceptor, ImageFallbackDirective, ImageInputComponent, ImageOverlayPreviewComponent, ImportRecordComponent, InlineFilterComponent, InteractiveTableColumnComponent, InteractiveTableComponent, InternalLinkCardComponent, IsSpatialSearchField, Iso191153Converter, Iso19139Converter, KindBadgeComponent, LANGUAGES_LIST, LANGUAGE_NAMES, LANGUAGE_STORAGE_KEY, LANG_2_TO_3_MAPPER, LOGIN_URL, LOGOUT_URL, LONLAT_CRS_CODES, LanguageSwitcherComponent, LayersPanelComponent, LicenseSearchField, LinkClassifierService, LinkUsage, LoadingMaskComponent, LogService, MAP_FEATURE_KEY, MAP_VIEW_CONSTRAINTS, METADATA_LANGUAGE, MapContainerComponent, MapFacade, MapLegendComponent, MapStateContainerComponent, MapStyleService, MapUtilsService, MapViewComponent, MarkdownEditorComponent, MarkdownParserComponent, MaxLinesComponent, mdview_actions as MdViewActions, MdViewFacade, MetadataCatalogComponent, MetadataContactComponent, MetadataDoiComponent, MetadataInfoComponent, MetadataLinkType, MetadataMapperContext, MetadataQualityComponent, MetadataQualityItemComponent, MetadataQualityPanelComponent, ModalDialogComponent, MultilingualPanelComponent, MultilingualSearchField, MyOrgService, NAMESPACES, NOT_APPLICABLE_CONSTRAINT, NOT_KNOWN_CONSTRAINT, NotificationComponent, NotificationsContainerComponent, NotificationsService, ORGANIZATIONS_STRATEGY, ORGANIZATION_PAGE_URL_TOKEN, ORGANIZATION_URL_TOKEN, OrganisationPreviewComponent, OrganisationsComponent, OrganisationsFilterComponent, OrganisationsResultComponent, OrganizationSearchField, OrganizationsFromGroupsService, OrganizationsFromMetadataService, OrganizationsServiceInterface, OwnerSearchField, PAGINATE, PARSE_DELIMITER, PATCH_RESULTS_AGGREGATIONS, PROXY_PATH, Paginate, PaginationButtonsComponent, PaginationComponent, PaginationDotsComponent, PatchResultsAggregations, PlatformServiceInterface, PopoverComponent, PopupAlertComponent, PossibleResourceTypes, PossibleResourceTypesDefinition, PreviousNextButtonsComponent, ProgressBarComponent, ProxyService, QUERY_FIELDS, RECORD_DATASET_URL_TOKEN, RECORD_REUSE_URL_TOKEN, RECORD_SERVICE_URL_TOKEN, REQUEST_MORE_ON_AGGREGATION, REQUEST_MORE_RESULTS, REQUEST_NEW_RESULTS, RESULTS_LAYOUT_CONFIG, ROUTER_CONFIG, ROUTER_ROUTE_DATASET, ROUTER_ROUTE_ORGANIZATION, ROUTER_ROUTE_REUSE, ROUTER_ROUTE_SEARCH, ROUTER_ROUTE_SERVICE, ROUTER_STATE_KEY, ROUTE_PARAMS, RecordApiFormComponent, RecordFormComponent, RecordKindField, RecordMetaComponent, RecordMetricComponent, RecordPreviewCardComponent, RecordPreviewComponent, RecordPreviewFeedComponent, RecordPreviewListComponent, RecordPreviewRowComponent, RecordPreviewTextComponent, RecordPreviewTitleComponent, RecordsMetricsComponent, RecordsRepositoryInterface, RecordsService, RequestMoreOnAggregation, RequestMoreResults, RequestNewResults, ResourceTypeLegacyField, ResultsHitsContainerComponent, ResultsHitsNumberComponent, ResultsHitsSearchKindComponent, ResultsLayoutComponent, ResultsLayoutConfigItem, ResultsListComponent, ResultsListContainerComponent, ResultsListItemComponent, ResultsTableComponent, ResultsTableContainerComponent, ReusePresentationForms, RouterEffects, RouterFacade, RouterService, SEARCH_FEATURE_KEY, SETTINGS_URL, SET_CONFIG_AGGREGATIONS, SET_CONFIG_FILTERS, SET_CONFIG_REQUEST_FIELDS, SET_ERROR, SET_FAVORITES_ONLY, SET_FILTERS, SET_INCLUDE_ON_AGGREGATION, SET_PAGE_SIZE, SET_RESULTS_AGGREGATIONS, SET_RESULTS_HITS, SET_RESULTS_LAYOUT, SET_SEARCH, SET_SORT_BY, SET_SPATIAL_FILTER_ENABLED, SearchEffects, SearchFacade, SearchFeatureCatalogComponent, SearchFiltersSummaryComponent, SearchFiltersSummaryItemComponent, SearchInputComponent, SearchRouterContainerDirective, SearchService, SearchStateContainerDirective, SelectionService, ServiceCapabilitiesComponent, SetConfigAggregations, SetConfigFilters, SetConfigRequestFields, SetError, SetFavoritesOnly, SetFilters, SetIncludeOnAggregation, SetPageSize, SetResultsAggregations, SetResultsHits, SetResultsLayout, SetSearch, SetSortBy, SetSpatialFilterEnabled, SimpleSearchField, SiteTitleComponent, SortByComponent, SortableListComponent, SourceLabelComponent, SourcesService, SpatialExtentComponent, SpinningLoaderComponent, StacItemsResultGridComponent, StacViewComponent, StarToggleComponent, StickyHeaderComponent, SupportedTypes, SwitchToggleComponent, THUMBNAIL_PLACEHOLDER, TRANSLATE_DEBUG_CONFIG, TRANSLATE_DEFAULT_CONFIG, TRANSLATE_WITH_OVERRIDES_CONFIG, TableViewComponent, TextAreaComponent, TextInputComponent, ThemeService, ThumbnailComponent, TranslatedSearchField, TruncatedTextComponent, UPDATE_CONFIG_AGGREGATIONS, UPDATE_FILTERS, UPDATE_REQUEST_AGGREGATION_TERM, UpdateConfigAggregations, UpdateFilters, UrlInputComponent, UserFeedbackItemComponent, UserPreviewComponent, UserSearchField, VECTOR_STYLE_DEFAULT, ViewportIntersectorComponent, WEB_COMPONENT_EMBEDDER_URL, XmlParseError, _reset, allChildrenElement, appConfigWithTranslationFixture, appendChildTree, appendChildren, assertValidXml, blockModelFixture, bytesToMegabytes, canEditRecord, checkFileFormat, clearSelectedFeatures, createChild, createDocument, createElement, createFuzzyFilter, createNestedChild, createNestedElement, currentPage, defaultMapStyleFixture, defaultMapStyleHlFixture, downgradeImage, downsizeImage, draftSaveSuccess, dragPanCondition, dropEmptyTranslations, editorReducer, emptyBlockModelFixture, findChildElement, findChildOrCreate, findChildrenElement, findConverterForDocument, findNestedChildOrCreate, findNestedElement, findNestedElements, findParent, firstChildElement, formatDate, formatUserInfo, getAllKeysValidator, getArrayItem, getAsArray, getAsUrl, getBadgeColor, getCustomTranslations, getError, getFavoritesOnly, getFileFormat, getFileFormatFromServiceOutput, getFirstValue, getFormatPriority, getGeometryBoundingBox, getGeometryFromGeoJSON, getGlobalConfig, getIsMobile, getJsonDataItemsProxy, getLayers, getLinkId, getLinkLabel, getLinkPriority, getMapContext, getMapContextLayerFromConfig, getMapState, getMetadataQualityConfig, getMimeTypeForFormat, getNamespace, getOptionalMapConfig, getOptionalSearchConfig, getPageSize, getQualityValidators, getResourceType, getReusePresentationForm, getReuseType, getRootElement, getSearchConfigAggregations, getSearchFilters, getSearchResults, getSearchResultsAggregations, getSearchResultsHits, getSearchResultsLayout, getSearchResultsLoading, getSearchSortBy, getSearchState, getSearchStateSearch, getSelectedFeatures, getSpatialFilterEnabled, getTemporalRangeUnion, getThemeConfig, handleScrollOnNavigation, hasRecordChangedSinceDraft, hasRecordChangedSinceDraftSuccess, initSearch, initialEditorState, initialMapState, initialState, isConfigLoaded, isDateRange, isFormatInQueryParam, isPublished, itemModelFixture, kindToCodeListValue, loadAppConfig, malformedConfigFixture, mapConfigFixture, mapContact, mapKeywords, mapLogo, mapOrganization, mapReducer, markRecordAsChanged, matchesNoApplicableConstraint, matchesNoKnownConstraint, megabytesToBytes, mimeTypeToFormat, minimalAppConfigFixture, missingMandatoryConfigFixture, mouseWheelZoomCondition, noDuplicateFileName, okAppConfigFixture, openDataset, openRecord, organizationsServiceFactory, parse, parseXmlString, placeholder, prioritizePageScroll, propagateToDocumentOnly, provideGn4, provideI18n, provideRepositoryUrl, readAttribute, readDataset, readDatasetHeaders, readText, reducer$2 as reducer, reducerSearch, removeAllChildren, removeChildren, removeChildrenByName, removeSearchParams, removeWhitespace, renameElements, saveRecord, saveRecordFailure, saveRecordSuccess, selectCanEditRecord, selectCurrentPage, selectEditorConfig, selectEditorState, selectFallback, selectFallbackFields, selectField, selectHasRecordChanged, selectIsPublished, selectRecord, selectRecordChangedSinceSave, selectRecordSaveError, selectRecordSaving, selectRecordSections, selectRecordSource, selectTranslatedField, selectTranslatedValue, setContext, setCurrentPage, setFieldVisibility, setSelectedFeatures, setTextContent, someHabTableItemFixture, sortByFromString, sortByToString, sortByToStrings, stripHtml, stripNamespace, tableItemsFixture, toDate, toLang2, toLang3, totalPages, undoRecordDraft, unrecognizedKeysConfigFixture, updateLanguages, updateRecordField, updateRecordLanguages, wmsLayerFlatten, writeAttribute, wrongLanguageCodeConfigFixture, xmlToString };
44556
+ export { ABOUT_SECTION, ADD_RESULTS, ADD_SEARCH, ANNEXES_SECTION, ASSOCIATED_RESOURCES_SECTION, AVAILABLE_LICENSES, AbstractAction, AbstractSearchField, ActionMenuComponent, AddLayerFromCatalogComponent, AddLayerRecordPreviewComponent, AddResults, AddSearch, AnchorLinkDirective, ApiCardComponent, ApplicationBannerComponent, AuthService, AutocompleteComponent, AvailableServicesField, AvatarComponent, AvatarServiceInterface, BASEMAP_LAYERS, BadgeComponent, BaseConverter, BaseFileReader, BaseReader, BlockListComponent, ButtonComponent, CLASSIFICATION_SECTION, CLEAR_ERROR, CLEAR_RESULTS, CONSTRAINTS_SHORTCUTS, CONTACTS, CONTACTS_FOR_RESOURCE_FIELD, CarouselComponent, CatalogTitleComponent, CellPopinComponent, ChartComponent, ChartViewComponent, CheckToggleComponent, CheckboxComponent, ClearError, ClearResults, ColorScaleComponent, ConfirmationDialogComponent, ContentGhostComponent, CopyTextButtonComponent, DATA_MANAGERS_SECTION, DEFAULT_CONFIGURATION, DEFAULT_GN4_LOGIN_URL, DEFAULT_GN4_LOGOUT_URL, DEFAULT_GN4_SETTINGS_URL, DEFAULT_LANG, DEFAULT_PAGE_SIZE, DEFAULT_RESULTS_LAYOUT_CONFIG, DEFAULT_SEARCH_KEY, DISABLE_AUTH, DO_NOT_USE_DEFAULT_BASEMAP, DataService, DataTableComponent, DataViewComponent, DataViewPermalinkComponent, DataViewShareComponent, DataViewWebComponentComponent, DatePickerComponent, DateRangeDropdownComponent, DateRangeInputsComponent, DateRangePickerComponent, DateRangeSearchField, DateService, DcatApConverter, DefaultRouterModule, DownloadItemComponent, DownloadsListComponent, DragAndDropFileInputComponent, DropdownMultiselectComponent, DropdownSelectorComponent, EDITOR_FEATURE_KEY, ES_QUERY_FIELDS_PRIORITY, ES_RESOURCES_VALUES, ES_SOURCE_SUMMARY, EXTERNAL_VIEWER_OPEN_NEW_TAB, EXTERNAL_VIEWER_URL_TEMPLATE, EditableLabelDirective, EditorFacade, EditorService, ElasticsearchService, EmbeddedTranslateLoader, ErrorComponent, ErrorType, ExpandablePanelButtonComponent, ExpandablePanelComponent, ExternalLinkCardComponent, ExternalViewerButtonComponent, FIELDS_BRIEF, FIELDS_SUMMARY, FILTER_GEOMETRY, FILTER_SUMMARY_IGNORE_LIST, FORMATS, FacetBlockComponent, FacetItemComponent, FacetListComponent, FacetsContainerComponent, FavoriteStarComponent, FavoritesService, FeatureCatalogListComponent, FeatureDetailComponent, FeatureEditorModule, FeatureMapModule, FeatureRecordModule, FeatureSearchModule, FetchError, FieldsService, FigureComponent, FigureContainerComponent, FileInputComponent, FileTranslateLoader, FilesDropDirective, FilterDropdownComponent, FormFieldArrayComponent, FormFieldComponent, FormFieldDateComponent, FormFieldFileComponent, FormFieldKeywordsComponent, FormFieldLicenseComponent, FormFieldObjectComponent, FormFieldRichComponent, FormFieldSimpleComponent, FormFieldSpatialExtentComponent, FormFieldTemporalExtentsComponent, FormFieldTopicsComponent, FormFieldWrapperComponent, FullTextSearchField, FuzzySearchComponent, GEOGRAPHICAL_COVERAGE_SECTION, GEONETWORK_UI_TAG_NAME, GEONETWORK_UI_VERSION, GeoDataBadgeComponent, GeoTableViewComponent, GeocodingComponent, GeojsonReader, Gn4Converter, Gn4PlatformMapper, Gn4PlatformService, Gn4Repository, Gn4SettingsService, GnUiHumanizeDateDirective, GpfApiDlComponent, GravatarService, HttpLoaderFactory, I18nInterceptor, INSPIRE_TOPICS, ImageFallbackDirective, ImageInputComponent, ImageOverlayPreviewComponent, ImportRecordComponent, InlineFilterComponent, InteractiveTableColumnComponent, InteractiveTableComponent, InternalLinkCardComponent, IsSpatialSearchField, Iso191153Converter, Iso19139Converter, KindBadgeComponent, LANGUAGES_LIST, LANGUAGE_NAMES, LANGUAGE_STORAGE_KEY, LANG_2_TO_3_MAPPER, LEGAL_CONSTRAINTS_FIELD, LOGIN_URL, LOGOUT_URL, LONLAT_CRS_CODES, LanguageSwitcherComponent, LayersPanelComponent, LicenseSearchField, LinkClassifierService, LinkUsage, LoadingMaskComponent, LogService, MAP_FEATURE_KEY, MAP_VIEW_CONSTRAINTS, MAX_UPLOAD_SIZE_MB, METADATA_LANGUAGE, METADATA_POINT_OF_CONTACT_SECTION, MapContainerComponent, MapFacade, MapLegendComponent, MapStateContainerComponent, MapStyleService, MapUtilsService, MapViewComponent, MarkdownEditorComponent, MarkdownParserComponent, MaxLinesComponent, mdview_actions as MdViewActions, MdViewFacade, MetadataCatalogComponent, MetadataContactComponent, MetadataDoiComponent, MetadataInfoComponent, MetadataLinkType, MetadataMapperContext, MetadataQualityComponent, MetadataQualityItemComponent, MetadataQualityPanelComponent, ModalDialogComponent, MultilingualPanelComponent, MultilingualSearchField, MyOrgService, NAMESPACES, NOT_APPLICABLE_CONSTRAINT, NOT_KNOWN_CONSTRAINT, NotificationComponent, NotificationsContainerComponent, NotificationsService, OPEN_DATA_LICENSE, ORGANIZATIONS_STRATEGY, ORGANIZATION_PAGE_URL_TOKEN, ORGANIZATION_URL_TOKEN, OTHER_CONSTRAINTS_FIELD, OrganisationPreviewComponent, OrganisationsComponent, OrganisationsFilterComponent, OrganisationsResultComponent, OrganizationSearchField, OrganizationsFromGroupsService, OrganizationsFromMetadataService, OrganizationsServiceInterface, OwnerSearchField, PAGINATE, PARSE_DELIMITER, PATCH_RESULTS_AGGREGATIONS, PROXY_PATH, Paginate, PaginationButtonsComponent, PaginationComponent, PaginationDotsComponent, PatchResultsAggregations, PlatformServiceInterface, PopoverComponent, PopupAlertComponent, PossibleResourceTypes, PossibleResourceTypesDefinition, PreviousNextButtonsComponent, ProgressBarComponent, ProxyService, QUERY_FIELDS, RECORD_ABSTRACT_FIELD, RECORD_DATASET_URL_TOKEN, RECORD_GRAPHICAL_OVERVIEW_FIELD, RECORD_KEYWORDS_FIELD, RECORD_LICENSE_FIELD, RECORD_ONLINE_LINK_RESOURCES, RECORD_ONLINE_RESOURCES, RECORD_RESOURCE_CREATED_FIELD, RECORD_RESOURCE_UPDATED_FIELD, RECORD_REUSE_URL_TOKEN, RECORD_SERVICE_URL_TOKEN, RECORD_SPATIAL_EXTENTS_FIELD, RECORD_SPATIAL_TOGGLE_FIELD, RECORD_TEMPORAL_EXTENTS_FIELD, RECORD_TITLE_FIELD, RECORD_TOPICS_FIELD, RECORD_UNIQUE_IDENTIFIER_FIELD, RECORD_UPDATED_FIELD, RECORD_UPDATE_FREQUENCY_FIELD, REQUEST_MORE_ON_AGGREGATION, REQUEST_MORE_RESULTS, REQUEST_NEW_RESULTS, RESOURCE_IDENTIFIER_FIELD, RESULTS_LAYOUT_CONFIG, ROUTER_CONFIG, ROUTER_ROUTE_DATASET, ROUTER_ROUTE_ORGANIZATION, ROUTER_ROUTE_REUSE, ROUTER_ROUTE_SEARCH, ROUTER_ROUTE_SERVICE, ROUTER_STATE_KEY, ROUTE_PARAMS, RecordApiFormComponent, RecordFormComponent, RecordKindField, RecordMetaComponent, RecordMetricComponent, RecordPreviewCardComponent, RecordPreviewComponent, RecordPreviewFeedComponent, RecordPreviewListComponent, RecordPreviewRowComponent, RecordPreviewTextComponent, RecordPreviewTitleComponent, RecordsMetricsComponent, RecordsRepositoryInterface, RecordsService, RequestMoreOnAggregation, RequestMoreResults, RequestNewResults, ResourceTypeLegacyField, ResultsHitsContainerComponent, ResultsHitsNumberComponent, ResultsHitsSearchKindComponent, ResultsLayoutComponent, ResultsLayoutConfigItem, ResultsListComponent, ResultsListContainerComponent, ResultsListItemComponent, ResultsTableComponent, ResultsTableContainerComponent, ReusePresentationForms, RouterEffects, RouterFacade, RouterService, SEARCH_FEATURE_KEY, SECURITY_CONSTRAINTS_FIELD, SETTINGS_URL, SET_CONFIG_AGGREGATIONS, SET_CONFIG_FILTERS, SET_CONFIG_REQUEST_FIELDS, SET_ERROR, SET_FAVORITES_ONLY, SET_FILTERS, SET_INCLUDE_ON_AGGREGATION, SET_PAGE_SIZE, SET_RESULTS_AGGREGATIONS, SET_RESULTS_HITS, SET_RESULTS_LAYOUT, SET_SEARCH, SET_SORT_BY, SET_SPATIAL_FILTER_ENABLED, SPATIAL_SCOPES, SearchEffects, SearchFacade, SearchFeatureCatalogComponent, SearchFiltersSummaryComponent, SearchFiltersSummaryItemComponent, SearchInputComponent, SearchRouterContainerDirective, SearchService, SearchStateContainerDirective, SelectionService, ServiceCapabilitiesComponent, SetConfigAggregations, SetConfigFilters, SetConfigRequestFields, SetError, SetFavoritesOnly, SetFilters, SetIncludeOnAggregation, SetPageSize, SetResultsAggregations, SetResultsHits, SetResultsLayout, SetSearch, SetSortBy, SetSpatialFilterEnabled, SimpleSearchField, SiteTitleComponent, SortByComponent, SortableListComponent, SourceLabelComponent, SourcesService, SpatialExtentComponent, SpinningLoaderComponent, StacItemsResultGridComponent, StacViewComponent, StarToggleComponent, StickyHeaderComponent, SupportedTypes, SwitchToggleComponent, THUMBNAIL_PLACEHOLDER, TITLE_SECTION, TOPICS_SECTION, TRANSLATE_DEBUG_CONFIG, TRANSLATE_DEFAULT_CONFIG, TRANSLATE_WITH_OVERRIDES_CONFIG, TableViewComponent, TextAreaComponent, TextInputComponent, ThemeService, ThumbnailComponent, TranslatedSearchField, TruncatedTextComponent, UPDATE_CONFIG_AGGREGATIONS, UPDATE_FILTERS, UPDATE_REQUEST_AGGREGATION_TERM, USE_AND_ACCESS_CONDITIONS_SECTION, UpdateConfigAggregations, UpdateFilters, UrlInputComponent, UserFeedbackItemComponent, UserPreviewComponent, UserSearchField, VECTOR_STYLE_DEFAULT, ViewportIntersectorComponent, WEB_COMPONENT_EMBEDDER_URL, XmlParseError, _reset, allChildrenElement, appConfigWithTranslationFixture, appendChildTree, appendChildren, assertValidXml, blockModelFixture, bytesToMegabytes, canEditRecord, checkFileFormat, clearSelectedFeatures, createChild, createDocument, createElement, createFuzzyFilter, createNestedChild, createNestedElement, currentPage, defaultMapStyleFixture, defaultMapStyleHlFixture, downgradeImage, downsizeImage, draftSaveSuccess, dragPanCondition, dropEmptyTranslations, editorReducer, emptyBlockModelFixture, findChildElement, findChildOrCreate, findChildrenElement, findConverterForDocument, findNestedChildOrCreate, findNestedElement, findNestedElements, findParent, firstChildElement, formatDate, formatUserInfo, getAllKeysValidator, getArrayItem, getAsArray, getAsUrl, getBadgeColor, getCustomTranslations, getError, getFavoritesOnly, getFileFormat, getFileFormatFromServiceOutput, getFirstValue, getFormatPriority, getGeometryBoundingBox, getGeometryFromGeoJSON, getGlobalConfig, getIsMobile, getJsonDataItemsProxy, getLayers, getLinkId, getLinkLabel, getLinkPriority, getMapContext, getMapContextLayerFromConfig, getMapState, getMetadataQualityConfig, getMimeTypeForFormat, getNamespace, getOptionalMapConfig, getOptionalSearchConfig, getPageSize, getQualityValidators, getResourceType, getReusePresentationForm, getReuseType, getRootElement, getSearchConfigAggregations, getSearchFilters, getSearchResults, getSearchResultsAggregations, getSearchResultsHits, getSearchResultsLayout, getSearchResultsLoading, getSearchSortBy, getSearchState, getSearchStateSearch, getSelectedFeatures, getSpatialFilterEnabled, getTemporalRangeUnion, getThemeConfig, handleScrollOnNavigation, hasRecordChangedSinceDraft, hasRecordChangedSinceDraftSuccess, initSearch, initialEditorState, initialMapState, initialState, isConfigLoaded, isDateRange, isFormatInQueryParam, isPublished, itemModelFixture, kindToCodeListValue, loadAppConfig, malformedConfigFixture, mapConfigFixture, mapContact, mapKeywords, mapLogo, mapOrganization, mapReducer, markRecordAsChanged, matchesNoApplicableConstraint, matchesNoKnownConstraint, megabytesToBytes, mimeTypeToFormat, minimalAppConfigFixture, missingMandatoryConfigFixture, mouseWheelZoomCondition, noDuplicateFileName, okAppConfigFixture, openDataset, openRecord, organizationsServiceFactory, parse, parseXmlString, placeholder, prioritizePageScroll, propagateToDocumentOnly, provideGn4, provideI18n, provideRepositoryUrl, readAttribute, readDataset, readDatasetHeaders, readText, reducer$2 as reducer, reducerSearch, removeAllChildren, removeChildren, removeChildrenByName, removeSearchParams, removeWhitespace, renameElements, saveRecord, saveRecordFailure, saveRecordSuccess, selectCanEditRecord, selectCurrentPage, selectEditorConfig, selectEditorState, selectFallback, selectFallbackFields, selectField, selectHasRecordChanged, selectIsPublished, selectRecord, selectRecordChangedSinceSave, selectRecordSaveError, selectRecordSaving, selectRecordSections, selectRecordSource, selectTranslatedField, selectTranslatedValue, setContext, setCurrentPage, setEditorConfiguration, setFieldVisibility, setSelectedFeatures, setTextContent, someHabTableItemFixture, sortByFromString, sortByToString, sortByToStrings, stripHtml, stripNamespace, tableItemsFixture, toDate, toLang2, toLang3, totalPages, undoRecordDraft, unrecognizedKeysConfigFixture, updateLanguages, updateRecordField, updateRecordLanguages, wmsLayerFlatten, writeAttribute, wrongLanguageCodeConfigFixture, xmlToString };
44550
44557
  //# sourceMappingURL=geonetwork-ui.mjs.map