@sumaris-net/ngx-components 18.6.10 → 18.6.11-alpha2

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.
@@ -1,6 +1,6 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { InjectionToken, Directive, Pipe, Injectable, EventEmitter, Output, Optional, Inject, inject, NgModule, forwardRef, Component, ChangeDetectionStrategy, Input, ViewChildren, HostBinding, HostListener, ElementRef, numberAttribute, booleanAttribute, ViewChild, ANIMATION_MODULE_TYPE, RendererStyleFlags2, CUSTOM_ELEMENTS_SCHEMA, ChangeDetectorRef, Self, ViewEncapsulation, APP_INITIALIZER, SecurityContext, viewChild, signal, input, model, computed, effect, untracked } from '@angular/core';
3
- import { firstValueFrom, shareReplay, tap, of, timer, Subject, merge, delay, isObservable, from, Subscription, BehaviorSubject, fromEvent, noop as noop$9, Observable, forkJoin, timeout, defer, debounceTime as debounceTime$1, distinctUntilChanged as distinctUntilChanged$1, interval, combineLatest, EMPTY, switchMap as switchMap$1 } from 'rxjs';
3
+ import { firstValueFrom, shareReplay, tap, of, timer, Subject, merge, delay, isObservable, from, Subscription, BehaviorSubject, fromEvent, noop as noop$9, Observable, forkJoin, timeout, defer, debounceTime as debounceTime$1, distinctUntilChanged as distinctUntilChanged$1, interval, mergeMap as mergeMap$1, combineLatest, EMPTY, switchMap as switchMap$1 } from 'rxjs';
4
4
  import { catchError, map, filter, takeUntil, first, switchMap, tap as tap$1, throttleTime, debounceTime, startWith, distinctUntilChanged, mergeMap, skip, finalize, bufferWhen, distinctUntilKeyChanged, take } from 'rxjs/operators';
5
5
  import * as i3 from '@angular/common';
6
6
  import { CommonModule, DOCUMENT, LocationStrategy, Location, AsyncPipe, JsonPipe } from '@angular/common';
@@ -16286,11 +16286,11 @@ class ModalToolbarComponent {
16286
16286
  this._subscription.unsubscribe();
16287
16287
  }
16288
16288
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ModalToolbarComponent, deps: [{ token: Hotkeys }], target: i0.ɵɵFactoryTarget.Component });
16289
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: ModalToolbarComponent, selector: "app-modal-toolbar", inputs: { modalName: "modalName", title: "title", color: "color", showSpinner: "showSpinner", canValidate: "canValidate", validateIcon: "validateIcon" }, outputs: { cancel: "cancel", validate: "validate" }, ngImport: i0, template: "<ion-header>\n <ion-toolbar [color]=\"color\">\n <ion-buttons slot=\"start\">\n <ion-button visible-xs visible-sm visible-mobile (click)=\"cancel.emit()\">\n <ion-icon slot=\"icon-only\" name=\"arrow-back\"></ion-icon>\n </ion-button>\n\n <ng-content select=\"[slot=start]\"></ng-content>\n </ion-buttons>\n\n <ion-title [innerHTML]=\"title\"></ion-title>\n\n <ng-content select=\"ion-title\"></ng-content>\n\n <ng-content select=\"ion-buttons[slot=end]\"></ng-content>\n\n <ion-buttons slot=\"end\">\n <ng-content select=\"ion-button[slot=end]\"></ng-content>\n\n <ion-spinner *ngIf=\"showSpinner\"></ion-spinner>\n\n <ion-button visible-xs visible-sm visible-mobile *ngIf=\"canValidate\" (click)=\"validate.emit($event)\">\n <ion-icon slot=\"icon-only\" *ngIf=\"validateIcon?.icon\" [name]=\"validateIcon.icon\"></ion-icon>\n <mat-icon slot=\"icon-only\" *ngIf=\"validateIcon?.matIcon\">{{ validateIcon.matIcon }}</mat-icon>\n </ion-button>\n </ion-buttons>\n </ion-toolbar>\n</ion-header>\n", styles: [""], dependencies: [{ kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i2$1.IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: i2$1.IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: i2$1.IonHeader, selector: "ion-header", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: i2$1.IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: i2$1.IonSpinner, selector: "ion-spinner", inputs: ["color", "duration", "name", "paused"] }, { kind: "component", type: i2$1.IonTitle, selector: "ion-title", inputs: ["color", "size"] }, { kind: "component", type: i2$1.IonToolbar, selector: "ion-toolbar", inputs: ["color", "mode"] }, { kind: "component", type: i6$2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
16289
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: ModalToolbarComponent, selector: "app-modal-toolbar", inputs: { modalName: "modalName", title: "title", color: "color", showSpinner: "showSpinner", canValidate: "canValidate", validateIcon: "validateIcon" }, outputs: { cancel: "cancel", validate: "validate" }, ngImport: i0, template: "<ion-header>\n <ion-toolbar [color]=\"color\">\n <ion-buttons slot=\"start\">\n @if (cancel.observed) {\n <ion-button visible-xs visible-sm visible-mobile (click)=\"cancel.emit()\">\n <ion-icon slot=\"icon-only\" name=\"arrow-back\"></ion-icon>\n </ion-button>\n }\n\n <ng-content select=\"[slot=start]\"></ng-content>\n </ion-buttons>\n\n <ion-title [innerHTML]=\"title\"></ion-title>\n\n <ng-content select=\"ion-title\"></ng-content>\n\n <ng-content select=\"ion-buttons[slot=end]\"></ng-content>\n\n <ion-buttons slot=\"end\">\n <ng-content select=\"ion-button[slot=end]\"></ng-content>\n\n <ion-spinner *ngIf=\"showSpinner\"></ion-spinner>\n\n <ion-button visible-xs visible-sm visible-mobile *ngIf=\"canValidate\" (click)=\"validate.emit($event)\">\n <ion-icon slot=\"icon-only\" *ngIf=\"validateIcon?.icon\" [name]=\"validateIcon.icon\"></ion-icon>\n <mat-icon slot=\"icon-only\" *ngIf=\"validateIcon?.matIcon\">{{ validateIcon.matIcon }}</mat-icon>\n </ion-button>\n </ion-buttons>\n </ion-toolbar>\n</ion-header>\n", styles: [""], dependencies: [{ kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i2$1.IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: i2$1.IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: i2$1.IonHeader, selector: "ion-header", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: i2$1.IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: i2$1.IonSpinner, selector: "ion-spinner", inputs: ["color", "duration", "name", "paused"] }, { kind: "component", type: i2$1.IonTitle, selector: "ion-title", inputs: ["color", "size"] }, { kind: "component", type: i2$1.IonToolbar, selector: "ion-toolbar", inputs: ["color", "mode"] }, { kind: "component", type: i6$2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
16290
16290
  }
16291
16291
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ModalToolbarComponent, decorators: [{
16292
16292
  type: Component,
16293
- args: [{ selector: 'app-modal-toolbar', changeDetection: ChangeDetectionStrategy.OnPush, template: "<ion-header>\n <ion-toolbar [color]=\"color\">\n <ion-buttons slot=\"start\">\n <ion-button visible-xs visible-sm visible-mobile (click)=\"cancel.emit()\">\n <ion-icon slot=\"icon-only\" name=\"arrow-back\"></ion-icon>\n </ion-button>\n\n <ng-content select=\"[slot=start]\"></ng-content>\n </ion-buttons>\n\n <ion-title [innerHTML]=\"title\"></ion-title>\n\n <ng-content select=\"ion-title\"></ng-content>\n\n <ng-content select=\"ion-buttons[slot=end]\"></ng-content>\n\n <ion-buttons slot=\"end\">\n <ng-content select=\"ion-button[slot=end]\"></ng-content>\n\n <ion-spinner *ngIf=\"showSpinner\"></ion-spinner>\n\n <ion-button visible-xs visible-sm visible-mobile *ngIf=\"canValidate\" (click)=\"validate.emit($event)\">\n <ion-icon slot=\"icon-only\" *ngIf=\"validateIcon?.icon\" [name]=\"validateIcon.icon\"></ion-icon>\n <mat-icon slot=\"icon-only\" *ngIf=\"validateIcon?.matIcon\">{{ validateIcon.matIcon }}</mat-icon>\n </ion-button>\n </ion-buttons>\n </ion-toolbar>\n</ion-header>\n" }]
16293
+ args: [{ selector: 'app-modal-toolbar', changeDetection: ChangeDetectionStrategy.OnPush, template: "<ion-header>\n <ion-toolbar [color]=\"color\">\n <ion-buttons slot=\"start\">\n @if (cancel.observed) {\n <ion-button visible-xs visible-sm visible-mobile (click)=\"cancel.emit()\">\n <ion-icon slot=\"icon-only\" name=\"arrow-back\"></ion-icon>\n </ion-button>\n }\n\n <ng-content select=\"[slot=start]\"></ng-content>\n </ion-buttons>\n\n <ion-title [innerHTML]=\"title\"></ion-title>\n\n <ng-content select=\"ion-title\"></ng-content>\n\n <ng-content select=\"ion-buttons[slot=end]\"></ng-content>\n\n <ion-buttons slot=\"end\">\n <ng-content select=\"ion-button[slot=end]\"></ng-content>\n\n <ion-spinner *ngIf=\"showSpinner\"></ion-spinner>\n\n <ion-button visible-xs visible-sm visible-mobile *ngIf=\"canValidate\" (click)=\"validate.emit($event)\">\n <ion-icon slot=\"icon-only\" *ngIf=\"validateIcon?.icon\" [name]=\"validateIcon.icon\"></ion-icon>\n <mat-icon slot=\"icon-only\" *ngIf=\"validateIcon?.matIcon\">{{ validateIcon.matIcon }}</mat-icon>\n </ion-button>\n </ion-buttons>\n </ion-toolbar>\n</ion-header>\n" }]
16294
16294
  }], ctorParameters: () => [{ type: Hotkeys }], propDecorators: { modalName: [{
16295
16295
  type: Input
16296
16296
  }], title: [{
@@ -27357,8 +27357,15 @@ class MarkdownUtils {
27357
27357
  return UrlUtils.normalizeUrl(UrlUtils.concat(baseUrl, relativePath));
27358
27358
  }
27359
27359
  static isGitlabUrl(url) {
27360
+ if (!url)
27361
+ return false;
27360
27362
  return url.startsWith('https://gitlab.') || url.includes('/-/raw/') || url.includes('/-/blob/');
27361
27363
  }
27364
+ static fixGitlabUrlToRaw(url) {
27365
+ if (!this.isGitlabUrl(url))
27366
+ return url;
27367
+ return url.replace('/-/blob/', '/-/raw/').replace('/-/tree/', '/-/raw/');
27368
+ }
27362
27369
  static getRootUrl(url) {
27363
27370
  if (this.isGitlabUrl(url)) {
27364
27371
  console.debug('[markdown] Gitlab URL detected: ' + url);
@@ -27477,10 +27484,11 @@ class MarkdownService {
27477
27484
  }
27478
27485
  async click(event, containerElement) {
27479
27486
  console.debug('[markdown-service] Processing click event...', event);
27480
- const element = event.target;
27481
- if (!(element instanceof HTMLAnchorElement)) {
27487
+ if (!(event.target instanceof HTMLAnchorElement) && !(event.target?.['tagName'] === 'A')) {
27488
+ console.warn('[markdown-service] Invalid click target. Should an anchor <a>');
27482
27489
  return;
27483
27490
  }
27491
+ const element = event.target;
27484
27492
  let href = element.getAttribute('href');
27485
27493
  const fragment = UrlUtils.getFragment(href);
27486
27494
  // Fragment
@@ -27595,18 +27603,266 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
27595
27603
  args: ['ready']
27596
27604
  }] } });
27597
27605
 
27606
+ const PRINT_LOADING_STORAGE_KEY_PREFIX = 'print-loading-';
27607
+ class PrintService {
27608
+ toastController;
27609
+ translate;
27610
+ storage;
27611
+ document;
27612
+ printId = 0;
27613
+ constructor(toastController, translate, storage, document) {
27614
+ this.toastController = toastController;
27615
+ this.translate = translate;
27616
+ this.storage = storage;
27617
+ this.document = document;
27618
+ }
27619
+ nextJobId() {
27620
+ return ++this.printId;
27621
+ }
27622
+ async printElement(element, opts) {
27623
+ if (!element)
27624
+ throw new Error("Missing required 'element' argument");
27625
+ return this.printHTML(element.innerHTML, opts);
27626
+ }
27627
+ async printHTML(html, opts) {
27628
+ if (!html)
27629
+ throw new Error("Missing required 'html' argument");
27630
+ // Create iframe
27631
+ const iframe = this.createPrintIframeByHtml(html, opts);
27632
+ return this.printIframe(iframe, opts);
27633
+ }
27634
+ async printUrl(url, opts) {
27635
+ if (!url)
27636
+ throw new Error("Missing required 'url' argument");
27637
+ // Create iframe
27638
+ const iframe = this.createPrintIframeByUrl(url);
27639
+ return this.printIframe(iframe, opts);
27640
+ }
27641
+ async printIframe(iframe, opts) {
27642
+ if (!iframe)
27643
+ throw new Error("Missing required 'iframe' argument");
27644
+ const printId = opts?.id ?? this.printId++;
27645
+ const toastId = `printing-${printId}`;
27646
+ const showLoadingToast = opts?.showToast !== false;
27647
+ if (showLoadingToast)
27648
+ await this.showToast({
27649
+ id: toastId,
27650
+ message: opts?.toastMessage || 'COMMON.PLEASE_WAIT',
27651
+ duration: 0,
27652
+ });
27653
+ try {
27654
+ // Wait end of iframe load
27655
+ await this.waitIdle(iframe, { id: printId });
27656
+ // Print (and wait end of print)
27657
+ await this.print(iframe);
27658
+ }
27659
+ catch (err) {
27660
+ console.error('[print-service] Failed to create hidden iframe', err);
27661
+ }
27662
+ finally {
27663
+ iframe.remove();
27664
+ if (showLoadingToast)
27665
+ await this.toastController.dismiss(null, null, toastId);
27666
+ }
27667
+ }
27668
+ async markAsLoading(id) {
27669
+ console.debug(`[print-service] Mark print job #${id} as loading`);
27670
+ await this.storage.set(PRINT_LOADING_STORAGE_KEY_PREFIX + id, '1');
27671
+ }
27672
+ async markAsLoaded(id) {
27673
+ console.debug(`[print-service] Mark print job #${id} as loaded`);
27674
+ await this.storage.remove(PRINT_LOADING_STORAGE_KEY_PREFIX + id);
27675
+ }
27676
+ async isLoaded(id) {
27677
+ const result = await this.storage.get(PRINT_LOADING_STORAGE_KEY_PREFIX + id);
27678
+ return isNil(result);
27679
+ }
27680
+ async isLoading(id) {
27681
+ return !(await this.isLoaded(id));
27682
+ }
27683
+ /* -- protected functions -- */
27684
+ createPrintIframeByUrl(url) {
27685
+ // Create a iframe with '?print-pdf'
27686
+ const iframe = this.document.createElement('iframe');
27687
+ iframe.classList.add('cdk-visually-hidden');
27688
+ iframe.style.width = '100%';
27689
+ iframe.style.height = '100%';
27690
+ this.document.body.appendChild(iframe);
27691
+ iframe.src = url;
27692
+ return iframe;
27693
+ }
27694
+ createPrintIframeByHtml(html, opts) {
27695
+ if (!html)
27696
+ throw new Error("Missing required 'html' argument");
27697
+ const lang = this.document.documentElement?.lang || 'en';
27698
+ // Create an empty iframe
27699
+ const iframe = this.document.createElement('iframe');
27700
+ iframe.classList.add('cdk-visually-hidden');
27701
+ iframe.style.width = '100%';
27702
+ iframe.style.height = '100%';
27703
+ this.document.body.appendChild(iframe);
27704
+ // Write iframe content
27705
+ const iframeDocument = iframe.contentDocument || iframe.contentWindow?.document;
27706
+ if (iframeDocument) {
27707
+ iframeDocument.open();
27708
+ iframeDocument.write(`
27709
+ <!DOCTYPE html>
27710
+ <html lang="${lang}" class="print-pdf">
27711
+ <head>
27712
+ <title>${opts?.title || ''}</title>
27713
+ <style>
27714
+ @media print {
27715
+ body {
27716
+ font-family: 'Roboto', Helvetica, Arial, sans-serif;
27717
+ margin: 0;
27718
+ padding: 0;
27719
+ overflow: hidden;
27720
+ }
27721
+ img {
27722
+ max-width: 100%;
27723
+ height: auto;
27724
+ page-break-inside: avoid;
27725
+ }
27726
+ }
27727
+ ${opts?.inlineStyle || ''}
27728
+ </style>
27729
+ </head>
27730
+ <body>
27731
+ ${html}
27732
+ </body>
27733
+ </html>
27734
+ `);
27735
+ iframeDocument.close();
27736
+ }
27737
+ // Set iframe style
27738
+ this.applyDocumentStyleToIframe(iframe);
27739
+ return iframe;
27740
+ }
27741
+ /**
27742
+ * Applies the styles from the provided document, including external stylesheets and inline styles,
27743
+ * to the specified iframe's document.
27744
+ *
27745
+ * @param {HTMLIFrameElement} iframe - The iframe to which the styles are applied.
27746
+ * @return {void} Does not return a value.
27747
+ */
27748
+ applyDocumentStyleToIframe(iframe) {
27749
+ // Ignore style injection, if not on Chrome
27750
+ // (There is bug on Firefox: nothing appear in the print dialog)
27751
+ // TODO: Should be tested on Safari
27752
+ if (!isChrome(window))
27753
+ return;
27754
+ const iframeDocument = iframe.contentDocument || iframe.contentWindow?.document;
27755
+ if (iframeDocument) {
27756
+ // Récupérer tous les styles (liens CSS)
27757
+ const links = Array.from(this.document.querySelectorAll('style,link[rel="stylesheet"]'));
27758
+ links.forEach((element) => {
27759
+ // Insert inline style
27760
+ if (element.tagName === 'STYLE') {
27761
+ const newStyle = iframeDocument.createElement('style');
27762
+ newStyle.innerHTML = element.innerHTML;
27763
+ iframeDocument.head.appendChild(newStyle);
27764
+ console.debug('[print-service] Add style to iframe', newStyle);
27765
+ }
27766
+ // Insert link to stylesheet file
27767
+ else if (element.tagName === 'LINK' && element.getAttribute('href')) {
27768
+ const newLink = iframeDocument.createElement('link');
27769
+ newLink.rel = 'stylesheet';
27770
+ newLink.href = element.getAttribute('href');
27771
+ iframeDocument.head.appendChild(newLink);
27772
+ console.debug('[print-service] Add stylesheet to iframe: ', newLink.href);
27773
+ }
27774
+ });
27775
+ }
27776
+ }
27777
+ async waitIdle(iframe, opts) {
27778
+ // Wait job finished
27779
+ const printId = opts?.id || this.printId;
27780
+ await waitForTrue(timer(500, 500).pipe(mergeMap$1(() => this.isLoaded(printId))), { timeout: opts?.timeout });
27781
+ // Wait end of iframe load
27782
+ await new Promise((resolve, reject) => {
27783
+ const iframeWindow = iframe.contentWindow?.window || iframe.contentWindow;
27784
+ if (iframeWindow.document.readyState === 'complete') {
27785
+ resolve();
27786
+ }
27787
+ else {
27788
+ // Stop if timeout reached
27789
+ if (opts?.timeout > 0) {
27790
+ setTimeout(() => reject('timeout'), opts.timeout);
27791
+ }
27792
+ const readyListener = () => {
27793
+ if (iframeWindow.document.readyState === 'complete') {
27794
+ resolve();
27795
+ iframeWindow.document.removeEventListener('readystatechange', readyListener);
27796
+ }
27797
+ };
27798
+ iframeWindow.document.addEventListener('readystatechange', readyListener);
27799
+ }
27800
+ });
27801
+ }
27802
+ /**
27803
+ * Triggers the print functionality of the given iframe and resolves or rejects based on the print completion or timeout.
27804
+ *
27805
+ * @param {HTMLIFrameElement} iframe - The iframe element to be printed.
27806
+ * @param {{timeout?: number}} [opts] - An optional configuration object.
27807
+ * @param {number} [opts.timeout] - The maximum time in milliseconds to wait for the print to complete before rejecting the promise.
27808
+ * @return {Promise<void>} A promise that resolves after the print is completed or rejects if a timeout occurs.
27809
+ */
27810
+ print(iframe, opts) {
27811
+ return new Promise((resolve, reject) => {
27812
+ const iframeWindow = iframe.contentWindow?.window || iframe.contentWindow;
27813
+ // Stop if timeout reached
27814
+ if (opts?.timeout > 0) {
27815
+ setTimeout(() => reject('timeout'), opts.timeout);
27816
+ }
27817
+ // On Chrome
27818
+ if (isChrome(window)) {
27819
+ // Wait after print event, to resolve the promise
27820
+ const afterPrintListener = () => {
27821
+ console.debug('[print-service] After print');
27822
+ resolve();
27823
+ // Remove the listener
27824
+ iframeWindow.removeEventListener('afterprint', afterPrintListener);
27825
+ };
27826
+ iframeWindow.addEventListener('afterprint', afterPrintListener);
27827
+ iframe.contentWindow.window.print();
27828
+ }
27829
+ // Otherwise (e.g. Firefox)
27830
+ else {
27831
+ iframe.contentWindow.window.print();
27832
+ resolve();
27833
+ }
27834
+ });
27835
+ }
27836
+ async showToast(opts) {
27837
+ if (!this.toastController)
27838
+ throw new Error("Missing toastController in component's constructor");
27839
+ return await Toasts.show(this.toastController, this.translate, opts);
27840
+ }
27841
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: PrintService, deps: [{ token: i2$1.ToastController }, { token: i1$1.TranslateService }, { token: StorageService }, { token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Injectable });
27842
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: PrintService, providedIn: 'root' });
27843
+ }
27844
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: PrintService, decorators: [{
27845
+ type: Injectable,
27846
+ args: [{ providedIn: 'root' }]
27847
+ }], ctorParameters: () => [{ type: i2$1.ToastController }, { type: i1$1.TranslateService }, { type: StorageService }, { type: Document, decorators: [{
27848
+ type: Inject,
27849
+ args: [DOCUMENT]
27850
+ }] }] });
27851
+
27598
27852
  class AppMarkdownContent {
27599
27853
  cd;
27600
27854
  element;
27601
27855
  _document;
27602
27856
  route;
27603
- _printIframe;
27857
+ _printId;
27604
27858
  _clickSubscription;
27605
27859
  navController = inject(NavController);
27606
27860
  settings = inject(LocalSettingsService);
27607
27861
  translate = inject(TranslateService);
27608
27862
  network = inject(NetworkService);
27609
27863
  markdownService = inject(MarkdownService);
27864
+ toastController = inject(ToastController);
27865
+ printService = inject(PrintService);
27610
27866
  loading = true;
27611
27867
  error = undefined;
27612
27868
  baseUrl;
@@ -27645,6 +27901,8 @@ class AppMarkdownContent {
27645
27901
  this.element = element;
27646
27902
  this._document = _document;
27647
27903
  this.route = route;
27904
+ this._printId = this.printService.nextJobId();
27905
+ this.markAsLoading({ emitEvent: false });
27648
27906
  // TODO: for DEV only
27649
27907
  //this.debug = !environment.production;
27650
27908
  }
@@ -27668,29 +27926,56 @@ class AppMarkdownContent {
27668
27926
  get canGoBack() {
27669
27927
  return isNotEmptyArray(this._navHistory);
27670
27928
  }
27671
- print(event) {
27672
- console.debug('[markdown] Print');
27929
+ async print() {
27930
+ if (this.loading)
27931
+ return; // skip
27932
+ console.debug('[markdown] Print...');
27673
27933
  if (!this.element) {
27674
- console.error('Erreur : Élément non trouvé.');
27934
+ console.error('Element to print not found. Please check the HTML template.');
27675
27935
  return;
27676
27936
  }
27677
- // Récupérer le contenu HTML depuis le composant
27678
- const content = this.element.nativeElement.innerHTML;
27679
- // Créer une iframe pour gérer l'impression
27680
- this._printIframe = this.createPrintHiddenIframe(content);
27681
- // Lancer l'impression après un court délai (le temps que l'iframe charge)
27682
- this._printIframe.contentWindow.addEventListener('load', () => {
27683
- this._printIframe.contentWindow?.window.print();
27684
- this._printIframe.remove();
27685
- });
27937
+ this.markAsLoading({ emitEvent: false });
27938
+ try {
27939
+ // Print
27940
+ await this.printService.printElement(this.element.nativeElement, {
27941
+ id: this._printId,
27942
+ // Print as portrait, by default
27943
+ style: `@media print {
27944
+ @page {
27945
+ size: portrait;
27946
+ margin: 1.1cm;
27947
+ }
27948
+ markdown hr {
27949
+ page-break-before: always;
27950
+ border: none;
27951
+ margin: 0;
27952
+ padding: 0;
27953
+ }
27954
+ markdown img {
27955
+ max-width: 100%;
27956
+ height: auto;
27957
+ page-break-inside: avoid;
27958
+ }
27959
+ }`,
27960
+ });
27961
+ }
27962
+ finally {
27963
+ this.markAsLoaded({ emitEvent: false });
27964
+ }
27686
27965
  }
27687
- markAsLoaded() {
27966
+ markAsLoaded(opts) {
27688
27967
  this.loading = false;
27689
- this.cd.markForCheck();
27968
+ if (opts?.emitEvent !== false) {
27969
+ this.printService.markAsLoaded(this._printId);
27970
+ this.cd.markForCheck();
27971
+ }
27690
27972
  }
27691
- markAsLoading() {
27973
+ markAsLoading(opts) {
27692
27974
  this.loading = true;
27693
- this.cd.markForCheck();
27975
+ if (opts?.emitEvent !== false) {
27976
+ this.printService.markAsLoading(this._printId);
27977
+ this.cd.markForCheck();
27978
+ }
27694
27979
  }
27695
27980
  setError(error) {
27696
27981
  this.error = error?.['message'] || error || null;
@@ -27701,66 +27986,6 @@ class AppMarkdownContent {
27701
27986
  this.cd.markForCheck();
27702
27987
  }
27703
27988
  /* -- protected functions -- */
27704
- createPrintHiddenIframe(html, style) {
27705
- // Create a iframe with '?print-pdf'
27706
- const iframe = this._document.createElement('iframe');
27707
- iframe.classList.add('cdk-visually-hidden');
27708
- iframe.style.width = '100%';
27709
- iframe.style.height = '100%';
27710
- this._document.body.appendChild(iframe);
27711
- // Charger le contenu HTML dans l'iframe
27712
- const iframeDocument = iframe.contentDocument || iframe.contentWindow?.document;
27713
- if (iframeDocument) {
27714
- iframeDocument.open();
27715
- iframeDocument.write(`
27716
- <html>
27717
- <head>
27718
- <title>${this._document.title}</title>
27719
- <style>
27720
- hr {
27721
- page-break-before: always;
27722
- border: 0 !important;
27723
- padding: 0 !important;
27724
- }
27725
- body {
27726
- font-family: 'Roboto', Helvetica, Arial, sans-serif;
27727
- margin: 0;
27728
- padding: 20px;
27729
- }
27730
- </style>
27731
- </head>
27732
- <body>
27733
- ${html}
27734
- </body>
27735
- </html>
27736
- `);
27737
- iframeDocument.close();
27738
- }
27739
- // Inject App style
27740
- this.injectAppStylesIntoIframe(iframe);
27741
- return iframe;
27742
- }
27743
- injectAppStylesIntoIframe(iframe) {
27744
- const iframeDocument = iframe.contentDocument || iframe.contentWindow?.document;
27745
- if (iframeDocument) {
27746
- // Récupérer tous les styles (liens CSS)
27747
- const links = Array.from(this._document.querySelectorAll('link[rel="stylesheet"]'));
27748
- links.forEach((link) => {
27749
- const newLink = iframeDocument.createElement('link');
27750
- newLink.rel = 'stylesheet';
27751
- newLink.href = link.getAttribute('href');
27752
- if (newLink.href)
27753
- iframeDocument.head.appendChild(newLink);
27754
- });
27755
- // Récupérer tous les `styles` en ligne
27756
- const inlineStyles = Array.from(this._document.querySelectorAll('style'));
27757
- inlineStyles.forEach((style) => {
27758
- const newStyle = iframeDocument.createElement('style');
27759
- newStyle.innerHTML = style.innerHTML;
27760
- iframeDocument.head.appendChild(newStyle);
27761
- });
27762
- }
27763
- }
27764
27989
  setData(value, opts) {
27765
27990
  const anchor = opts?.anchor || null;
27766
27991
  if (this._data !== value || this._anchor !== anchor) {
@@ -27792,7 +28017,9 @@ class AppMarkdownContent {
27792
28017
  // Clean URL (remove fragment and query)
27793
28018
  const anchor = opts?.anchor || UrlUtils.getFragment(src);
27794
28019
  src = UrlUtils.stripFragmentAndQuery(src);
28020
+ src = MarkdownUtils.isGitlabUrl(src) ? MarkdownUtils.fixGitlabUrlToRaw(src) : src;
27795
28021
  let fallbackSrc = opts?.fallbackSrc ? UrlUtils.stripFragmentAndQuery(opts.fallbackSrc) : null;
28022
+ fallbackSrc = MarkdownUtils.isGitlabUrl(fallbackSrc) ? MarkdownUtils.fixGitlabUrlToRaw(fallbackSrc) : fallbackSrc;
27796
28023
  if (this._src !== src || this._fallbackSrc !== fallbackSrc || this._anchor !== anchor) {
27797
28024
  const url = src ? src + (isNotNilOrBlank(anchor) ? `#${anchor}` : '') : null;
27798
28025
  if (url)
@@ -27886,11 +28113,11 @@ class AppMarkdownContent {
27886
28113
  }));
27887
28114
  }
27888
28115
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AppMarkdownContent, deps: [{ token: i0.ChangeDetectorRef }, { token: i0.ElementRef }, { token: DOCUMENT }, { token: i1$5.ActivatedRoute, optional: true }], target: i0.ɵɵFactoryTarget.Component });
27889
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: AppMarkdownContent, selector: "app-markdown-content", inputs: { data: "data", src: "src", anchor: "anchor", debug: ["debug", "debug", booleanAttribute], showError: ["showError", "showError", booleanAttribute], animated: ["animated", "animated", booleanAttribute], enableNavigationHistory: ["enableNavigationHistory", "enableNavigationHistory", booleanAttribute], updateRouteLocation: ["updateRouteLocation", "updateRouteLocation", booleanAttribute] }, outputs: { markdownUrlChange: "markdownUrlChange" }, ngImport: i0, template: "<app-debug *ngIf=\"debug\">\n <ion-grid class=\"ion-no-padding\">\n <ion-row>\n <ion-col>\n loading: {{ loading }}\n <br />\n error: {{ error }}\n <br />\n <br />\n baseUrl: {{ baseUrl }}\n <br />\n markdownUrl: {{ src }}\n <br />\n markdownFragment: {{ _anchor }}\n <br />\n markdownContent: {{ data }}\n <br />\n </ion-col>\n </ion-row>\n </ion-grid>\n</app-debug>\n\n<!-- error -->\n@if (showError && error; as error) {\n <ion-item lines=\"none\" @slideDownAnimation>\n <ion-icon color=\"danger\" slot=\"start\" name=\"alert-circle\"></ion-icon>\n <ion-label color=\"danger\" class=\"error\" [innerHTML]=\"error | translate\"></ion-label>\n </ion-item>\n} @else {\n @if (data) {\n <markdown [data]=\"data\" (ready)=\"onReady()\" emoji></markdown>\n } @else if (src) {\n <markdown [src]=\"src\" (error)=\"onLoadError($event)\" (ready)=\"onReady()\" emoji></markdown>\n }\n}\n\n<!-- loading spinner -->\n@if (loading) {\n <div class=\"loading-spinner\">\n <ng-container *ngTemplateOutlet=\"loadingParagraph\"></ng-container>\n <ng-container *ngTemplateOutlet=\"loadingParagraph\"></ng-container>\n <ng-container *ngTemplateOutlet=\"loadingParagraph\"></ng-container>\n </div>\n}\n\n<ng-template #loadingParagraph>\n <p>\n <ion-skeleton-text [animated]=\"animated\" style=\"width: 75%; margin-inline-start: 5%\"></ion-skeleton-text>\n <ion-skeleton-text [animated]=\"animated\" style=\"width: 80%\"></ion-skeleton-text>\n <ion-skeleton-text [animated]=\"animated\" style=\"width: 80%\"></ion-skeleton-text>\n <ion-skeleton-text [animated]=\"animated\" style=\"width: 80%\"></ion-skeleton-text>\n <ion-skeleton-text [animated]=\"animated\" style=\"width: 80%\"></ion-skeleton-text>\n <ion-skeleton-text [animated]=\"animated\" style=\"width: 80%\"></ion-skeleton-text>\n </p>\n</ng-template>\n", styles: [":host ::ng-deep markdown div.logo{display:none;visibility:hidden}:host ::ng-deep markdown hr{border-top:1px solid var(--ion-color-medium-tint, #dcdcde);margin:10px 0}:host ::ng-deep markdown blockquote{--block-margin: 16px 0;--block-padding: 4px 16px;--box-shadow: -4px 0px 0px rgba(var(--ion-text-color-rgb), .4);--ion-padding: 4px;display:block;position:relative;margin:var(--block-margin);padding:var(--block-padding);font-style:italic;background:var(--ion-color-light);box-shadow:var(--box-shadow)}:host ::ng-deep markdown code{color:rgba(var(--ion-text-color-rgb),.7);background:rgba(var(--ion-text-color-rgb),.03);font-size:.9rem;letter-spacing:-.5px}.loading-spinner ion-skeleton-text{width:100%;height:1.5em}.loading-spinner p{margin-top:var(ion-padding, 16px)}@media print{hr{page-break-before:always;border:none;margin:0}body{font-family:Roboto,Helvetica,Arial,sans-serif;margin:0;padding:20px}}\n"], dependencies: [{ kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i2$1.IonCol, selector: "ion-col", inputs: ["offset", "offsetLg", "offsetMd", "offsetSm", "offsetXl", "offsetXs", "pull", "pullLg", "pullMd", "pullSm", "pullXl", "pullXs", "push", "pushLg", "pushMd", "pushSm", "pushXl", "pushXs", "size", "sizeLg", "sizeMd", "sizeSm", "sizeXl", "sizeXs"] }, { kind: "component", type: i2$1.IonGrid, selector: "ion-grid", inputs: ["fixed"] }, { kind: "component", type: i2$1.IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: i2$1.IonItem, selector: "ion-item", inputs: ["button", "color", "counter", "counterFormatter", "detail", "detailIcon", "disabled", "download", "fill", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "shape", "target", "type"] }, { kind: "component", type: i2$1.IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: i2$1.IonRow, selector: "ion-row" }, { kind: "component", type: i2$1.IonSkeletonText, selector: "ion-skeleton-text", inputs: ["animated"] }, { kind: "component", type: i4$1.MarkdownComponent, selector: "markdown, [markdown]", inputs: ["data", "src", "disableSanitizer", "inline", "clipboard", "clipboardButtonComponent", "clipboardButtonTemplate", "emoji", "katex", "katexOptions", "mermaid", "mermaidOptions", "lineHighlight", "line", "lineOffset", "lineNumbers", "start", "commandLine", "filterOutput", "host", "prompt", "output", "user"], outputs: ["error", "load", "ready"] }, { kind: "component", type: DebugComponent, selector: "app-debug", inputs: ["titlePrefix", "title", "enable", "expanded"] }, { kind: "directive", type: MarkdownDirective, selector: "markdown,[markdown]" }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }], animations: [slideDownAnimation], changeDetection: i0.ChangeDetectionStrategy.OnPush });
28116
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: AppMarkdownContent, selector: "app-markdown-content", inputs: { data: "data", src: "src", anchor: "anchor", debug: ["debug", "debug", booleanAttribute], showError: ["showError", "showError", booleanAttribute], animated: ["animated", "animated", booleanAttribute], enableNavigationHistory: ["enableNavigationHistory", "enableNavigationHistory", booleanAttribute], updateRouteLocation: ["updateRouteLocation", "updateRouteLocation", booleanAttribute] }, outputs: { markdownUrlChange: "markdownUrlChange" }, ngImport: i0, template: "<app-debug *ngIf=\"debug\">\n <ion-grid class=\"ion-no-padding\">\n <ion-row>\n <ion-col>\n loading: {{ loading }}\n <br />\n error: {{ error }}\n <br />\n <br />\n baseUrl: {{ baseUrl }}\n <br />\n markdownUrl: {{ src }}\n <br />\n markdownFragment: {{ _anchor }}\n <br />\n markdownContent: {{ data }}\n <br />\n </ion-col>\n </ion-row>\n </ion-grid>\n</app-debug>\n\n<!-- error -->\n@if (showError && error; as error) {\n <ion-item lines=\"none\" @slideDownAnimation>\n <ion-icon color=\"danger\" slot=\"start\" name=\"alert-circle\"></ion-icon>\n <ion-label color=\"danger\" class=\"error\" [innerHTML]=\"error | translate\"></ion-label>\n </ion-item>\n} @else {\n @if (data) {\n <markdown [data]=\"data\" (ready)=\"onReady()\" emoji></markdown>\n } @else if (src) {\n <markdown [src]=\"src\" (error)=\"onLoadError($event)\" (ready)=\"onReady()\" emoji></markdown>\n }\n}\n\n<!-- loading spinner -->\n@if (loading) {\n <div class=\"loading-spinner\">\n <ng-container *ngTemplateOutlet=\"loadingParagraph\"></ng-container>\n <ng-container *ngTemplateOutlet=\"loadingParagraph\"></ng-container>\n <ng-container *ngTemplateOutlet=\"loadingParagraph\"></ng-container>\n </div>\n}\n\n<ng-template #loadingParagraph>\n <p>\n <ion-skeleton-text [animated]=\"animated\" style=\"width: 75%; margin-inline-start: 5%\"></ion-skeleton-text>\n <ion-skeleton-text [animated]=\"animated\" style=\"width: 80%\"></ion-skeleton-text>\n <ion-skeleton-text [animated]=\"animated\" style=\"width: 80%\"></ion-skeleton-text>\n <ion-skeleton-text [animated]=\"animated\" style=\"width: 80%\"></ion-skeleton-text>\n <ion-skeleton-text [animated]=\"animated\" style=\"width: 80%\"></ion-skeleton-text>\n <ion-skeleton-text [animated]=\"animated\" style=\"width: 80%\"></ion-skeleton-text>\n </p>\n</ng-template>\n", styles: [":host ::ng-deep markdown div.logo{display:none;visibility:hidden}:host ::ng-deep markdown hr{border-top:1px solid var(--ion-color-medium-tint, #dcdcde);margin:10px 0}:host ::ng-deep markdown blockquote{--block-margin: 16px 0;--block-padding: 4px 16px;--box-shadow: -4px 0px 0px rgba(var(--ion-text-color-rgb), .4);--ion-padding: 4px;display:block;position:relative;margin:var(--block-margin);padding:var(--block-padding);font-style:italic;background:var(--ion-color-light);box-shadow:var(--box-shadow)}:host ::ng-deep markdown code{color:rgba(var(--ion-text-color-rgb),.7);background:rgba(var(--ion-text-color-rgb),.03);font-size:.9rem;letter-spacing:-.5px}.loading-spinner ion-skeleton-text{width:100%;height:1.5em}.loading-spinner p{margin-top:var(ion-padding, 16px)}@media print{@page{size:portrait;margin:1.1cm}body{font-family:Roboto,Helvetica,Arial,sans-serif;margin:0;padding:0;overflow:hidden}markdown hr{page-break-before:always;border:none;margin:0;padding:0}markdown img{max-width:100%;height:auto;page-break-inside:avoid}}\n"], dependencies: [{ kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i2$1.IonCol, selector: "ion-col", inputs: ["offset", "offsetLg", "offsetMd", "offsetSm", "offsetXl", "offsetXs", "pull", "pullLg", "pullMd", "pullSm", "pullXl", "pullXs", "push", "pushLg", "pushMd", "pushSm", "pushXl", "pushXs", "size", "sizeLg", "sizeMd", "sizeSm", "sizeXl", "sizeXs"] }, { kind: "component", type: i2$1.IonGrid, selector: "ion-grid", inputs: ["fixed"] }, { kind: "component", type: i2$1.IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: i2$1.IonItem, selector: "ion-item", inputs: ["button", "color", "counter", "counterFormatter", "detail", "detailIcon", "disabled", "download", "fill", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "shape", "target", "type"] }, { kind: "component", type: i2$1.IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: i2$1.IonRow, selector: "ion-row" }, { kind: "component", type: i2$1.IonSkeletonText, selector: "ion-skeleton-text", inputs: ["animated"] }, { kind: "component", type: i4$1.MarkdownComponent, selector: "markdown, [markdown]", inputs: ["data", "src", "disableSanitizer", "inline", "clipboard", "clipboardButtonComponent", "clipboardButtonTemplate", "emoji", "katex", "katexOptions", "mermaid", "mermaidOptions", "lineHighlight", "line", "lineOffset", "lineNumbers", "start", "commandLine", "filterOutput", "host", "prompt", "output", "user"], outputs: ["error", "load", "ready"] }, { kind: "component", type: DebugComponent, selector: "app-debug", inputs: ["titlePrefix", "title", "enable", "expanded"] }, { kind: "directive", type: MarkdownDirective, selector: "markdown,[markdown]" }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }], animations: [slideDownAnimation], changeDetection: i0.ChangeDetectionStrategy.OnPush });
27890
28117
  }
27891
28118
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AppMarkdownContent, decorators: [{
27892
28119
  type: Component,
27893
- args: [{ selector: 'app-markdown-content', changeDetection: ChangeDetectionStrategy.OnPush, animations: [slideDownAnimation], template: "<app-debug *ngIf=\"debug\">\n <ion-grid class=\"ion-no-padding\">\n <ion-row>\n <ion-col>\n loading: {{ loading }}\n <br />\n error: {{ error }}\n <br />\n <br />\n baseUrl: {{ baseUrl }}\n <br />\n markdownUrl: {{ src }}\n <br />\n markdownFragment: {{ _anchor }}\n <br />\n markdownContent: {{ data }}\n <br />\n </ion-col>\n </ion-row>\n </ion-grid>\n</app-debug>\n\n<!-- error -->\n@if (showError && error; as error) {\n <ion-item lines=\"none\" @slideDownAnimation>\n <ion-icon color=\"danger\" slot=\"start\" name=\"alert-circle\"></ion-icon>\n <ion-label color=\"danger\" class=\"error\" [innerHTML]=\"error | translate\"></ion-label>\n </ion-item>\n} @else {\n @if (data) {\n <markdown [data]=\"data\" (ready)=\"onReady()\" emoji></markdown>\n } @else if (src) {\n <markdown [src]=\"src\" (error)=\"onLoadError($event)\" (ready)=\"onReady()\" emoji></markdown>\n }\n}\n\n<!-- loading spinner -->\n@if (loading) {\n <div class=\"loading-spinner\">\n <ng-container *ngTemplateOutlet=\"loadingParagraph\"></ng-container>\n <ng-container *ngTemplateOutlet=\"loadingParagraph\"></ng-container>\n <ng-container *ngTemplateOutlet=\"loadingParagraph\"></ng-container>\n </div>\n}\n\n<ng-template #loadingParagraph>\n <p>\n <ion-skeleton-text [animated]=\"animated\" style=\"width: 75%; margin-inline-start: 5%\"></ion-skeleton-text>\n <ion-skeleton-text [animated]=\"animated\" style=\"width: 80%\"></ion-skeleton-text>\n <ion-skeleton-text [animated]=\"animated\" style=\"width: 80%\"></ion-skeleton-text>\n <ion-skeleton-text [animated]=\"animated\" style=\"width: 80%\"></ion-skeleton-text>\n <ion-skeleton-text [animated]=\"animated\" style=\"width: 80%\"></ion-skeleton-text>\n <ion-skeleton-text [animated]=\"animated\" style=\"width: 80%\"></ion-skeleton-text>\n </p>\n</ng-template>\n", styles: [":host ::ng-deep markdown div.logo{display:none;visibility:hidden}:host ::ng-deep markdown hr{border-top:1px solid var(--ion-color-medium-tint, #dcdcde);margin:10px 0}:host ::ng-deep markdown blockquote{--block-margin: 16px 0;--block-padding: 4px 16px;--box-shadow: -4px 0px 0px rgba(var(--ion-text-color-rgb), .4);--ion-padding: 4px;display:block;position:relative;margin:var(--block-margin);padding:var(--block-padding);font-style:italic;background:var(--ion-color-light);box-shadow:var(--box-shadow)}:host ::ng-deep markdown code{color:rgba(var(--ion-text-color-rgb),.7);background:rgba(var(--ion-text-color-rgb),.03);font-size:.9rem;letter-spacing:-.5px}.loading-spinner ion-skeleton-text{width:100%;height:1.5em}.loading-spinner p{margin-top:var(ion-padding, 16px)}@media print{hr{page-break-before:always;border:none;margin:0}body{font-family:Roboto,Helvetica,Arial,sans-serif;margin:0;padding:20px}}\n"] }]
28120
+ args: [{ selector: 'app-markdown-content', changeDetection: ChangeDetectionStrategy.OnPush, animations: [slideDownAnimation], template: "<app-debug *ngIf=\"debug\">\n <ion-grid class=\"ion-no-padding\">\n <ion-row>\n <ion-col>\n loading: {{ loading }}\n <br />\n error: {{ error }}\n <br />\n <br />\n baseUrl: {{ baseUrl }}\n <br />\n markdownUrl: {{ src }}\n <br />\n markdownFragment: {{ _anchor }}\n <br />\n markdownContent: {{ data }}\n <br />\n </ion-col>\n </ion-row>\n </ion-grid>\n</app-debug>\n\n<!-- error -->\n@if (showError && error; as error) {\n <ion-item lines=\"none\" @slideDownAnimation>\n <ion-icon color=\"danger\" slot=\"start\" name=\"alert-circle\"></ion-icon>\n <ion-label color=\"danger\" class=\"error\" [innerHTML]=\"error | translate\"></ion-label>\n </ion-item>\n} @else {\n @if (data) {\n <markdown [data]=\"data\" (ready)=\"onReady()\" emoji></markdown>\n } @else if (src) {\n <markdown [src]=\"src\" (error)=\"onLoadError($event)\" (ready)=\"onReady()\" emoji></markdown>\n }\n}\n\n<!-- loading spinner -->\n@if (loading) {\n <div class=\"loading-spinner\">\n <ng-container *ngTemplateOutlet=\"loadingParagraph\"></ng-container>\n <ng-container *ngTemplateOutlet=\"loadingParagraph\"></ng-container>\n <ng-container *ngTemplateOutlet=\"loadingParagraph\"></ng-container>\n </div>\n}\n\n<ng-template #loadingParagraph>\n <p>\n <ion-skeleton-text [animated]=\"animated\" style=\"width: 75%; margin-inline-start: 5%\"></ion-skeleton-text>\n <ion-skeleton-text [animated]=\"animated\" style=\"width: 80%\"></ion-skeleton-text>\n <ion-skeleton-text [animated]=\"animated\" style=\"width: 80%\"></ion-skeleton-text>\n <ion-skeleton-text [animated]=\"animated\" style=\"width: 80%\"></ion-skeleton-text>\n <ion-skeleton-text [animated]=\"animated\" style=\"width: 80%\"></ion-skeleton-text>\n <ion-skeleton-text [animated]=\"animated\" style=\"width: 80%\"></ion-skeleton-text>\n </p>\n</ng-template>\n", styles: [":host ::ng-deep markdown div.logo{display:none;visibility:hidden}:host ::ng-deep markdown hr{border-top:1px solid var(--ion-color-medium-tint, #dcdcde);margin:10px 0}:host ::ng-deep markdown blockquote{--block-margin: 16px 0;--block-padding: 4px 16px;--box-shadow: -4px 0px 0px rgba(var(--ion-text-color-rgb), .4);--ion-padding: 4px;display:block;position:relative;margin:var(--block-margin);padding:var(--block-padding);font-style:italic;background:var(--ion-color-light);box-shadow:var(--box-shadow)}:host ::ng-deep markdown code{color:rgba(var(--ion-text-color-rgb),.7);background:rgba(var(--ion-text-color-rgb),.03);font-size:.9rem;letter-spacing:-.5px}.loading-spinner ion-skeleton-text{width:100%;height:1.5em}.loading-spinner p{margin-top:var(ion-padding, 16px)}@media print{@page{size:portrait;margin:1.1cm}body{font-family:Roboto,Helvetica,Arial,sans-serif;margin:0;padding:0;overflow:hidden}markdown hr{page-break-before:always;border:none;margin:0;padding:0}markdown img{max-width:100%;height:auto;page-break-inside:avoid}}\n"] }]
27894
28121
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: i0.ElementRef }, { type: Document, decorators: [{
27895
28122
  type: Inject,
27896
28123
  args: [DOCUMENT]
@@ -27929,12 +28156,13 @@ class AppMarkdownModal {
27929
28156
  translate;
27930
28157
  network;
27931
28158
  cd;
27932
- debug;
27933
28159
  title;
27934
28160
  showError = true;
27935
28161
  canPrint = false;
27936
28162
  data;
27937
28163
  src;
28164
+ enableNavigationHistory = true;
28165
+ debug;
27938
28166
  content;
27939
28167
  static async show(modalCtrl, options) {
27940
28168
  const modal = await modalCtrl.create({
@@ -27982,23 +28210,29 @@ class AppMarkdownModal {
27982
28210
  this.content?.resetError();
27983
28211
  }
27984
28212
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AppMarkdownModal, deps: [{ token: i0.Injector }, { token: i2$1.ModalController }, { token: PlatformService }, { token: LocalSettingsService }, { token: i1$1.TranslateService }, { token: NetworkService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
27985
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: AppMarkdownModal, selector: "app-markdown-modal", inputs: { debug: "debug", title: "title", showError: "showError", canPrint: "canPrint", data: "data", src: "src" }, viewQueries: [{ propertyName: "content", first: true, predicate: ["content"], descendants: true }], ngImport: i0, template: "@if (title || canPrint) {\n <app-modal-toolbar color=\"light\" [title]=\"title | translate\" (cancel)=\"close($event)\">\n @if (content.canGoBack) {\n <ion-button slot=\"start\" class=\"back-button\" (click)=\"goBack($event, content)\" routerDirection=\"back\">\n <ion-icon slot=\"icon-only\" name=\"arrow-back\"></ion-icon>\n </ion-button>\n }\n @if (canPrint) {\n <ion-button slot=\"end\" class=\"back-button\" (click)=\"content.print($event)\" routerDirection=\"back\">\n <ion-icon slot=\"icon-only\" name=\"print\"></ion-icon>\n </ion-button>\n }\n </app-modal-toolbar>\n}\n\n<ion-content class=\"ion-padding\">\n <app-markdown-content\n #content\n [src]=\"src\"\n [data]=\"data\"\n [showError]=\"showError\"\n [debug]=\"debug\"\n [updateRouteLocation]=\"false\"\n ></app-markdown-content>\n</ion-content>\n\n<ion-footer hidden-xs hidden-sm hidden-mobile>\n <ion-toolbar>\n <ion-row class=\"ion-no-padding\">\n <ion-col></ion-col>\n <ion-col size=\"auto\">\n <ion-button fill=\"solid\" color=\"tertiary\" (click)=\"close()\">{{ 'COMMON.BTN_CLOSE' | translate }}</ion-button>\n </ion-col>\n </ion-row>\n </ion-toolbar>\n</ion-footer>\n", dependencies: [{ kind: "component", type: i2$1.IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: i2$1.IonCol, selector: "ion-col", inputs: ["offset", "offsetLg", "offsetMd", "offsetSm", "offsetXl", "offsetXs", "pull", "pullLg", "pullMd", "pullSm", "pullXl", "pullXs", "push", "pushLg", "pushMd", "pushSm", "pushXl", "pushXs", "size", "sizeLg", "sizeMd", "sizeSm", "sizeXl", "sizeXs"] }, { kind: "component", type: i2$1.IonContent, selector: "ion-content", inputs: ["color", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: i2$1.IonFooter, selector: "ion-footer", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: i2$1.IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: i2$1.IonRow, selector: "ion-row" }, { kind: "component", type: i2$1.IonToolbar, selector: "ion-toolbar", inputs: ["color", "mode"] }, { kind: "component", type: ModalToolbarComponent, selector: "app-modal-toolbar", inputs: ["modalName", "title", "color", "showSpinner", "canValidate", "validateIcon"], outputs: ["cancel", "validate"] }, { kind: "component", type: AppMarkdownContent, selector: "app-markdown-content", inputs: ["data", "src", "anchor", "debug", "showError", "animated", "enableNavigationHistory", "updateRouteLocation"], outputs: ["markdownUrlChange"] }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
28213
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: AppMarkdownModal, selector: "app-markdown-modal", inputs: { title: "title", showError: ["showError", "showError", booleanAttribute], canPrint: ["canPrint", "canPrint", booleanAttribute], data: "data", src: "src", enableNavigationHistory: ["enableNavigationHistory", "enableNavigationHistory", booleanAttribute], debug: ["debug", "debug", booleanAttribute] }, viewQueries: [{ propertyName: "content", first: true, predicate: ["content"], descendants: true }], ngImport: i0, template: "<app-modal-toolbar color=\"light\" [title]=\"title | translate\">\n @if (content.canGoBack) {\n <ion-button slot=\"start\" class=\"back-button\" (click)=\"goBack($event, content)\" routerDirection=\"back\">\n <ion-icon slot=\"icon-only\" name=\"arrow-back\"></ion-icon>\n </ion-button>\n }\n\n <ion-buttons slot=\"end\">\n @if (canPrint) {\n <ion-button slot=\"end\" (click)=\"content.print()\">\n <ion-icon slot=\"icon-only\" name=\"print\"></ion-icon>\n </ion-button>\n }\n\n <ion-button (click)=\"close()\" visible-xs visible-sm visible-mobile>\n {{ 'COMMON.BTN_CLOSE' | translate }}\n </ion-button>\n </ion-buttons>\n</app-modal-toolbar>\n\n<ion-content class=\"ion-padding\">\n <app-markdown-content\n #content\n [src]=\"src\"\n [data]=\"data\"\n [showError]=\"showError\"\n [debug]=\"debug\"\n [enableNavigationHistory]=\"enableNavigationHistory\"\n [updateRouteLocation]=\"false\"\n ></app-markdown-content>\n</ion-content>\n\n<ion-footer hidden-xs hidden-sm hidden-mobile>\n <ion-toolbar>\n <ion-row class=\"ion-no-padding\">\n <ion-col></ion-col>\n <ion-col size=\"auto\">\n <ion-button fill=\"solid\" color=\"tertiary\" (click)=\"close()\">{{ 'COMMON.BTN_CLOSE' | translate }}</ion-button>\n </ion-col>\n </ion-row>\n </ion-toolbar>\n</ion-footer>\n", dependencies: [{ kind: "component", type: i2$1.IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: i2$1.IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: i2$1.IonCol, selector: "ion-col", inputs: ["offset", "offsetLg", "offsetMd", "offsetSm", "offsetXl", "offsetXs", "pull", "pullLg", "pullMd", "pullSm", "pullXl", "pullXs", "push", "pushLg", "pushMd", "pushSm", "pushXl", "pushXs", "size", "sizeLg", "sizeMd", "sizeSm", "sizeXl", "sizeXs"] }, { kind: "component", type: i2$1.IonContent, selector: "ion-content", inputs: ["color", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: i2$1.IonFooter, selector: "ion-footer", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: i2$1.IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: i2$1.IonRow, selector: "ion-row" }, { kind: "component", type: i2$1.IonToolbar, selector: "ion-toolbar", inputs: ["color", "mode"] }, { kind: "component", type: ModalToolbarComponent, selector: "app-modal-toolbar", inputs: ["modalName", "title", "color", "showSpinner", "canValidate", "validateIcon"], outputs: ["cancel", "validate"] }, { kind: "component", type: AppMarkdownContent, selector: "app-markdown-content", inputs: ["data", "src", "anchor", "debug", "showError", "animated", "enableNavigationHistory", "updateRouteLocation"], outputs: ["markdownUrlChange"] }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
27986
28214
  }
27987
28215
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AppMarkdownModal, decorators: [{
27988
28216
  type: Component,
27989
- args: [{ selector: 'app-markdown-modal', changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (title || canPrint) {\n <app-modal-toolbar color=\"light\" [title]=\"title | translate\" (cancel)=\"close($event)\">\n @if (content.canGoBack) {\n <ion-button slot=\"start\" class=\"back-button\" (click)=\"goBack($event, content)\" routerDirection=\"back\">\n <ion-icon slot=\"icon-only\" name=\"arrow-back\"></ion-icon>\n </ion-button>\n }\n @if (canPrint) {\n <ion-button slot=\"end\" class=\"back-button\" (click)=\"content.print($event)\" routerDirection=\"back\">\n <ion-icon slot=\"icon-only\" name=\"print\"></ion-icon>\n </ion-button>\n }\n </app-modal-toolbar>\n}\n\n<ion-content class=\"ion-padding\">\n <app-markdown-content\n #content\n [src]=\"src\"\n [data]=\"data\"\n [showError]=\"showError\"\n [debug]=\"debug\"\n [updateRouteLocation]=\"false\"\n ></app-markdown-content>\n</ion-content>\n\n<ion-footer hidden-xs hidden-sm hidden-mobile>\n <ion-toolbar>\n <ion-row class=\"ion-no-padding\">\n <ion-col></ion-col>\n <ion-col size=\"auto\">\n <ion-button fill=\"solid\" color=\"tertiary\" (click)=\"close()\">{{ 'COMMON.BTN_CLOSE' | translate }}</ion-button>\n </ion-col>\n </ion-row>\n </ion-toolbar>\n</ion-footer>\n" }]
27990
- }], ctorParameters: () => [{ type: i0.Injector }, { type: i2$1.ModalController }, { type: PlatformService }, { type: LocalSettingsService }, { type: i1$1.TranslateService }, { type: NetworkService }, { type: i0.ChangeDetectorRef }], propDecorators: { debug: [{
27991
- type: Input
27992
- }], title: [{
28217
+ args: [{ selector: 'app-markdown-modal', changeDetection: ChangeDetectionStrategy.OnPush, template: "<app-modal-toolbar color=\"light\" [title]=\"title | translate\">\n @if (content.canGoBack) {\n <ion-button slot=\"start\" class=\"back-button\" (click)=\"goBack($event, content)\" routerDirection=\"back\">\n <ion-icon slot=\"icon-only\" name=\"arrow-back\"></ion-icon>\n </ion-button>\n }\n\n <ion-buttons slot=\"end\">\n @if (canPrint) {\n <ion-button slot=\"end\" (click)=\"content.print()\">\n <ion-icon slot=\"icon-only\" name=\"print\"></ion-icon>\n </ion-button>\n }\n\n <ion-button (click)=\"close()\" visible-xs visible-sm visible-mobile>\n {{ 'COMMON.BTN_CLOSE' | translate }}\n </ion-button>\n </ion-buttons>\n</app-modal-toolbar>\n\n<ion-content class=\"ion-padding\">\n <app-markdown-content\n #content\n [src]=\"src\"\n [data]=\"data\"\n [showError]=\"showError\"\n [debug]=\"debug\"\n [enableNavigationHistory]=\"enableNavigationHistory\"\n [updateRouteLocation]=\"false\"\n ></app-markdown-content>\n</ion-content>\n\n<ion-footer hidden-xs hidden-sm hidden-mobile>\n <ion-toolbar>\n <ion-row class=\"ion-no-padding\">\n <ion-col></ion-col>\n <ion-col size=\"auto\">\n <ion-button fill=\"solid\" color=\"tertiary\" (click)=\"close()\">{{ 'COMMON.BTN_CLOSE' | translate }}</ion-button>\n </ion-col>\n </ion-row>\n </ion-toolbar>\n</ion-footer>\n" }]
28218
+ }], ctorParameters: () => [{ type: i0.Injector }, { type: i2$1.ModalController }, { type: PlatformService }, { type: LocalSettingsService }, { type: i1$1.TranslateService }, { type: NetworkService }, { type: i0.ChangeDetectorRef }], propDecorators: { title: [{
27993
28219
  type: Input
27994
28220
  }], showError: [{
27995
- type: Input
28221
+ type: Input,
28222
+ args: [{ transform: booleanAttribute }]
27996
28223
  }], canPrint: [{
27997
- type: Input
28224
+ type: Input,
28225
+ args: [{ transform: booleanAttribute }]
27998
28226
  }], data: [{
27999
28227
  type: Input
28000
28228
  }], src: [{
28001
28229
  type: Input
28230
+ }], enableNavigationHistory: [{
28231
+ type: Input,
28232
+ args: [{ transform: booleanAttribute }]
28233
+ }], debug: [{
28234
+ type: Input,
28235
+ args: [{ transform: booleanAttribute }]
28002
28236
  }], content: [{
28003
28237
  type: ViewChild,
28004
28238
  args: ['content']
@@ -31095,6 +31329,9 @@ class HomePage extends RxState {
31095
31329
  await AppMarkdownModal.show(this.modalCtrl, {
31096
31330
  title: this.translate.instant(item.title, item.titleArgs),
31097
31331
  src: url,
31332
+ enableNavigationHistory: false,
31333
+ // FIXME failed in chrome
31334
+ //canPrint: true,
31098
31335
  });
31099
31336
  }
31100
31337
  else {
@@ -45347,7 +45584,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
45347
45584
  class MarkdownTestPage {
45348
45585
  modalCtrl;
45349
45586
  cd;
45587
+ environment;
45350
45588
  markdownModalTitle = 'Markdown modal';
45589
+ debug;
45351
45590
  // URL from a starting markdown
45352
45591
  //protected markdownUrl = 'http://localhost:3000/user-manual/index.md';
45353
45592
  markdownUrl = 'https://gitlab.ifremer.fr/sih-public/sumaris/sumaris-doc/-/raw/master/projects/pifil/man/quick_start_guide_fr.md';
@@ -45356,9 +45595,11 @@ class MarkdownTestPage {
45356
45595
  //protected markdownUrl = 'https://gitlab.ifremer.fr/sih-public/sumaris/sumaris-doc/-/raw/master/model/administration/index.md';
45357
45596
  //protected markdownUrl ='https://gitlab.ifremer.fr/sih-public/sumaris/sumaris-doc/-/raw/master/projects/activity-calendar/spe/collecte_de_donnees.md';
45358
45597
  //protected markdownUrl ='https://gitlab.ifremer.fr/sih-public/sumaris/sumaris-app/-/raw/develop/doc/privacy_policy.md';
45359
- constructor(modalCtrl, cd) {
45598
+ constructor(modalCtrl, cd, environment) {
45360
45599
  this.modalCtrl = modalCtrl;
45361
45600
  this.cd = cd;
45601
+ this.environment = environment;
45602
+ this.debug = !environment.production;
45362
45603
  }
45363
45604
  onSubmit(event, newUrl) {
45364
45605
  this.markdownUrl = '' + newUrl;
@@ -45375,13 +45616,16 @@ class MarkdownTestPage {
45375
45616
  canPrint: true,
45376
45617
  });
45377
45618
  }
45378
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: MarkdownTestPage, deps: [{ token: i2$1.ModalController }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
45379
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: MarkdownTestPage, selector: "app-markdown-test", ngImport: i0, template: "<ion-header>\n <ion-toolbar color=\"primary\">\n <ion-buttons slot=\"start\">\n @if (content.canGoBack) {\n <ion-button class=\"back-button\" (click)=\"content.goBack($event)\" routerDirection=\"back\">\n <ion-icon slot=\"icon-only\" name=\"arrow-back\"></ion-icon>\n </ion-button>\n } @else {\n <ion-back-button></ion-back-button>\n }\n </ion-buttons>\n\n <ion-title>Markdown test page</ion-title>\n\n <ion-buttons slot=\"end\">\n <ion-button (click)=\"openHelpModal($event)\">Open in modal</ion-button>\n </ion-buttons>\n </ion-toolbar>\n</ion-header>\n\n<ion-content class=\"ion-padding\">\n <ion-input\n #input\n fill=\"outline\"\n [ngModel]=\"markdownUrl\"\n placeholder=\"Markdown URL\"\n label=\"URL: \"\n (keyup.enter)=\"onSubmit($event, input.value)\"\n >\n <ion-button\n slot=\"end\"\n [fill]=\"markdownUrl !== input.value ? 'solid' : 'clear'\"\n (click)=\"onSubmit($event, input.value)\"\n >\n {{ 'COMMON.BTN_OK' | translate }}\n </ion-button>\n </ion-input>\n\n <app-markdown-content\n #content\n [src]=\"markdownUrl\"\n enableNavigationHistory=\"true\"\n debug=\"true\"\n (markdownUrlChange)=\"updateInputUrl($event)\"\n ></app-markdown-content>\n</ion-content>\n", dependencies: [{ kind: "component", type: i2$1.IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: i2$1.IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: i2$1.IonContent, selector: "ion-content", inputs: ["color", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: i2$1.IonHeader, selector: "ion-header", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: i2$1.IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: i2$1.IonInput, selector: "ion-input", inputs: ["accept", "autocapitalize", "autocomplete", "autocorrect", "autofocus", "clearInput", "clearOnEdit", "color", "counter", "counterFormatter", "debounce", "disabled", "enterkeyhint", "errorText", "fill", "helperText", "inputmode", "label", "labelPlacement", "legacy", "max", "maxlength", "min", "minlength", "mode", "multiple", "name", "pattern", "placeholder", "readonly", "required", "shape", "size", "spellcheck", "step", "type", "value"] }, { kind: "component", type: i2$1.IonTitle, selector: "ion-title", inputs: ["color", "size"] }, { kind: "component", type: i2$1.IonToolbar, selector: "ion-toolbar", inputs: ["color", "mode"] }, { kind: "directive", type: i2$1.TextValueAccessor, selector: "ion-input:not([type=number]),ion-textarea,ion-searchbar,ion-range" }, { kind: "component", type: i2$1.IonBackButton, selector: "ion-back-button" }, { kind: "directive", type: i1$3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: AppMarkdownContent, selector: "app-markdown-content", inputs: ["data", "src", "anchor", "debug", "showError", "animated", "enableNavigationHistory", "updateRouteLocation"], outputs: ["markdownUrlChange"] }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
45619
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: MarkdownTestPage, deps: [{ token: i2$1.ModalController }, { token: i0.ChangeDetectorRef }, { token: ENVIRONMENT }], target: i0.ɵɵFactoryTarget.Component });
45620
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: MarkdownTestPage, selector: "app-markdown-test", ngImport: i0, template: "<ion-header>\n <ion-toolbar color=\"primary\">\n <ion-buttons slot=\"start\">\n @if (content.canGoBack) {\n <ion-button class=\"back-button\" (click)=\"content.goBack($event)\" routerDirection=\"back\">\n <ion-icon slot=\"icon-only\" name=\"arrow-back\"></ion-icon>\n </ion-button>\n } @else {\n <ion-back-button></ion-back-button>\n }\n </ion-buttons>\n\n <ion-title>Markdown test page</ion-title>\n\n <ion-buttons slot=\"end\">\n <ion-button slot=\"end\" (click)=\"content.print()\">\n <ion-icon slot=\"icon-only\" name=\"print\"></ion-icon>\n </ion-button>\n\n <ion-button (click)=\"openHelpModal($event)\">Open in modal</ion-button>\n </ion-buttons>\n </ion-toolbar>\n</ion-header>\n\n<ion-content class=\"ion-padding\">\n <ion-input\n #input\n fill=\"outline\"\n [ngModel]=\"markdownUrl\"\n placeholder=\"Markdown URL\"\n label=\"URL: \"\n (keyup.enter)=\"onSubmit($event, input.value)\"\n >\n <ion-button\n slot=\"end\"\n [fill]=\"markdownUrl !== input.value ? 'solid' : 'clear'\"\n (click)=\"onSubmit($event, input.value)\"\n >\n {{ 'COMMON.BTN_OK' | translate }}\n </ion-button>\n </ion-input>\n\n <app-markdown-content\n #content\n [src]=\"markdownUrl\"\n enableNavigationHistory=\"true\"\n [debug]=\"debug\"\n (markdownUrlChange)=\"updateInputUrl($event)\"\n ></app-markdown-content>\n</ion-content>\n", dependencies: [{ kind: "component", type: i2$1.IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: i2$1.IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: i2$1.IonContent, selector: "ion-content", inputs: ["color", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: i2$1.IonHeader, selector: "ion-header", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: i2$1.IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: i2$1.IonInput, selector: "ion-input", inputs: ["accept", "autocapitalize", "autocomplete", "autocorrect", "autofocus", "clearInput", "clearOnEdit", "color", "counter", "counterFormatter", "debounce", "disabled", "enterkeyhint", "errorText", "fill", "helperText", "inputmode", "label", "labelPlacement", "legacy", "max", "maxlength", "min", "minlength", "mode", "multiple", "name", "pattern", "placeholder", "readonly", "required", "shape", "size", "spellcheck", "step", "type", "value"] }, { kind: "component", type: i2$1.IonTitle, selector: "ion-title", inputs: ["color", "size"] }, { kind: "component", type: i2$1.IonToolbar, selector: "ion-toolbar", inputs: ["color", "mode"] }, { kind: "directive", type: i2$1.TextValueAccessor, selector: "ion-input:not([type=number]),ion-textarea,ion-searchbar,ion-range" }, { kind: "component", type: i2$1.IonBackButton, selector: "ion-back-button" }, { kind: "directive", type: i1$3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: AppMarkdownContent, selector: "app-markdown-content", inputs: ["data", "src", "anchor", "debug", "showError", "animated", "enableNavigationHistory", "updateRouteLocation"], outputs: ["markdownUrlChange"] }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
45380
45621
  }
45381
45622
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: MarkdownTestPage, decorators: [{
45382
45623
  type: Component,
45383
- args: [{ selector: 'app-markdown-test', changeDetection: ChangeDetectionStrategy.OnPush, template: "<ion-header>\n <ion-toolbar color=\"primary\">\n <ion-buttons slot=\"start\">\n @if (content.canGoBack) {\n <ion-button class=\"back-button\" (click)=\"content.goBack($event)\" routerDirection=\"back\">\n <ion-icon slot=\"icon-only\" name=\"arrow-back\"></ion-icon>\n </ion-button>\n } @else {\n <ion-back-button></ion-back-button>\n }\n </ion-buttons>\n\n <ion-title>Markdown test page</ion-title>\n\n <ion-buttons slot=\"end\">\n <ion-button (click)=\"openHelpModal($event)\">Open in modal</ion-button>\n </ion-buttons>\n </ion-toolbar>\n</ion-header>\n\n<ion-content class=\"ion-padding\">\n <ion-input\n #input\n fill=\"outline\"\n [ngModel]=\"markdownUrl\"\n placeholder=\"Markdown URL\"\n label=\"URL: \"\n (keyup.enter)=\"onSubmit($event, input.value)\"\n >\n <ion-button\n slot=\"end\"\n [fill]=\"markdownUrl !== input.value ? 'solid' : 'clear'\"\n (click)=\"onSubmit($event, input.value)\"\n >\n {{ 'COMMON.BTN_OK' | translate }}\n </ion-button>\n </ion-input>\n\n <app-markdown-content\n #content\n [src]=\"markdownUrl\"\n enableNavigationHistory=\"true\"\n debug=\"true\"\n (markdownUrlChange)=\"updateInputUrl($event)\"\n ></app-markdown-content>\n</ion-content>\n" }]
45384
- }], ctorParameters: () => [{ type: i2$1.ModalController }, { type: i0.ChangeDetectorRef }] });
45624
+ args: [{ selector: 'app-markdown-test', changeDetection: ChangeDetectionStrategy.OnPush, template: "<ion-header>\n <ion-toolbar color=\"primary\">\n <ion-buttons slot=\"start\">\n @if (content.canGoBack) {\n <ion-button class=\"back-button\" (click)=\"content.goBack($event)\" routerDirection=\"back\">\n <ion-icon slot=\"icon-only\" name=\"arrow-back\"></ion-icon>\n </ion-button>\n } @else {\n <ion-back-button></ion-back-button>\n }\n </ion-buttons>\n\n <ion-title>Markdown test page</ion-title>\n\n <ion-buttons slot=\"end\">\n <ion-button slot=\"end\" (click)=\"content.print()\">\n <ion-icon slot=\"icon-only\" name=\"print\"></ion-icon>\n </ion-button>\n\n <ion-button (click)=\"openHelpModal($event)\">Open in modal</ion-button>\n </ion-buttons>\n </ion-toolbar>\n</ion-header>\n\n<ion-content class=\"ion-padding\">\n <ion-input\n #input\n fill=\"outline\"\n [ngModel]=\"markdownUrl\"\n placeholder=\"Markdown URL\"\n label=\"URL: \"\n (keyup.enter)=\"onSubmit($event, input.value)\"\n >\n <ion-button\n slot=\"end\"\n [fill]=\"markdownUrl !== input.value ? 'solid' : 'clear'\"\n (click)=\"onSubmit($event, input.value)\"\n >\n {{ 'COMMON.BTN_OK' | translate }}\n </ion-button>\n </ion-input>\n\n <app-markdown-content\n #content\n [src]=\"markdownUrl\"\n enableNavigationHistory=\"true\"\n [debug]=\"debug\"\n (markdownUrlChange)=\"updateInputUrl($event)\"\n ></app-markdown-content>\n</ion-content>\n" }]
45625
+ }], ctorParameters: () => [{ type: i2$1.ModalController }, { type: i0.ChangeDetectorRef }, { type: Environment, decorators: [{
45626
+ type: Inject,
45627
+ args: [ENVIRONMENT]
45628
+ }] }] });
45385
45629
 
45386
45630
  const routes$4 = [
45387
45631
  {
@@ -47123,5 +47367,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
47123
47367
  * Generated bundle index. Do not edit.
47124
47368
  */
47125
47369
 
47126
- export { APP_ABOUT_DEVELOPERS, APP_ABOUT_PARTNERS, APP_CONFIG_OPTIONS, APP_DEBUG_DATA_SERVICE, APP_FORM_ERROR_I18N_KEYS, APP_GRAPHQL_FRAGMENTS, APP_GRAPHQL_TYPE_POLICIES, APP_HOME_BUTTONS, APP_HOTKEYS_CONFIG, APP_JOB_PROGRESSION_SERVICE, APP_LOCALES, APP_LOCAL_SETTINGS, APP_LOCAL_SETTINGS_OPTIONS, APP_LOCAL_STORAGE_TYPE_POLICIES, APP_LOGGING_SERVICE, APP_MENU_ITEMS, APP_MENU_OPTIONS, APP_NAMED_FILTER_SERVICE, APP_PROGRESS_BAR_SERVICE, APP_SETTINGS_MENU_ITEMS, APP_STORAGE, APP_STORAGE_EXPLORER_PROTECTED_KEYS, APP_TESTING_PAGES, APP_USER_EVENT_LIST_INFINITE_SCROLL_THRESHOLD, APP_USER_EVENT_SERVICE, APP_USER_SETTINGS_OPTIONS, APP_USER_TOKEN_SCOPES, AboutModal, AbstractNamedFilterService, AbstractSelectionModelPipe, AbstractTableSelectionPipe, AbstractUserEventService, Account, AccountPage, AccountService, AccountToStringPipe, AccountUtils, ActionsColumnComponent, AdminModule, AdminRoutingModule, AdminUsersModule, Alerts, AndroidOsEnvironment, AppAboutModalModule, AppAccountModule, AppAsyncTable, AppAuthForm, AppAuthModal, AppAuthModule, AppChangePasswordModule, AppChangePasswordPage, AppEditor, AppEditorOptions, AppEntityEditor, AppEntityEditorModal, AppEntityEditorModalOptions, AppEntityFormModule, AppForm, AppFormArray, AppFormButtonsBarModule, AppFormContainer, AppFormField, AppFormModule, AppFormProvider, AppFormUtils, AppGestureConfig, AppGraphQLModule, AppHomePageModule, AppIconComponent, AppIconModule, AppImageGalleryComponent, AppInMemoryTable, AppInstallUpgradeCard, AppInstallUpgradeCardModule, AppListForm, AppListFormModule, AppLoadingSpinner, AppMarkdownContent, AppMarkdownModal, AppMenuModule, AppNullForm, AppPropertiesForm, AppPropertiesFormModule, AppPropertiesTable, AppPropertiesUtils, AppPropertyUtils, AppRegisterModule, AppResetPasswordModal, AppRowField, AppSelectPeerModule, AppSettingsPageModule, AppTabEditor, AppTabEditorOptions, AppTable, AppTableModule, AppTableUtils, AppTextPopoverModule, AppUpdateOfflineModeCard, AppUpdateOfflineModeCardModule, AppValidatorService, ArrayFilterPipe, ArrayFirstPipe, ArrayFormTestPage, ArrayIncludesPipe, ArrayJoinPipe, ArrayLastPipe, ArrayLengthPipe, ArrayPluckPipe, AsAnyPipe, AsArrayPipe, AsBooleanPipe, AsFloatLabelTypePipe, AsObservablePipe, AudioProvider, AudioTestingModule, AudioTestingPage, AuthGuardService, AutoTitleDirective, AutocompleteTestPage, AutofocusDirective, BadgeDirective, BadgeNumberPipe, Base58, BaseEntityService, BaseGraphqlService, BaseGraphqlServiceOptions, BaseReferential, Beans, BooleanFormatPipe, BooleanTestPage, CORE_CONFIG_OPTIONS, CORE_TESTING_PAGES, CapitalizePipe, CellValueChangeListener, ChangePasswordForm, ChipsTestPage, Color, ColorScale, ComponentDirtyGuard, ConfigFragments, ConfigService, Configuration, CoreModule, CorePipesModule, CoreTestingModule, CryptoService, CsvUtils, DATE_ISO_PATTERN, DATE_MATCH_REGEXP, DATE_PATTERN, DATE_UNIX_MS_TIMESTAMP, DATE_UNIX_TIMESTAMP, DEFAULT_JOIN_ARRAY_VALUES_SEPARATOR, DEFAULT_JOIN_PROPERTIES_SEPARATOR, DEFAULT_MENU_SHOW_WHEN, DEFAULT_PAGE_SIZE, DEFAULT_PAGE_SIZE_OPTIONS, DEFAULT_PLACEHOLDER_CHAR, DEFAULT_REQUIRED_COLUMNS, DateDiffDurationPipe, DateFormatPipe, DateFormatService, DateFromNowPipe, DateShortTestPage, DateTestPage, DateTimeTestPage, DateUtils, DebugComponent, Department, DepartmentToStringPipe, DisplayWithPipe, DragAndDropDirective, DurationPipe, DurationTestPage, ED25519_SEED_LENGTH, EMPTY_PLACEHOLDER_CHAR, EMPTY_PLACEHOLDER_CHAR_REGEXP_GLOBAL, ENTITIES_STORAGE_KEY_PREFIX, ENVIRONMENT, EmptyArrayPipe, EntitiesAsyncTableDataSource, EntitiesStorage, EntitiesTableDataSource, Entity, EntityClass, EntityClasses, EntityFilter, EntityFilterUtils, EntityMetadataComponent, EntityStore, EntityUtils, Environment, EnvironmentHttpLoader, EnvironmentLoader, ErrorCodes, EvenPipe, FileResponse, FileService, FileSizePipe, FilesUtils, FormArrayHelper, FormArrayTestModule, FormButtonsBarComponent, FormButtonsBarToken, FormErrorPipe, FormErrorTranslatePipe, FormErrorTranslator, FormFieldDefinitionUtils, FormFieldValuesHolder, FormGetArrayPipe, FormGetControlPipe, FormGetGroupPipe, FormGetPipe, FormGetValuePipe, GalleryTestPage, GeolocationUtils, GraphqlService, HAMMER_PRESS_TIME, HAMMER_TAP_TIME, HighlightPipe, HomePage, Hotkeys, HotkeysDialogComponent, IMAGE_DEFAULTS, IPosition, ImageAttachment, ImageAttachmentFilter, ImageAttachmentService, ImageGalleryModule, ImageGalleryTestingModule, ImageModule, ImageService, ImagesUtils, InMemoryEntitiesService, IsAllSelectedPipe, IsEmptySelectionPipe, IsLoginAccountPipe, IsMultipleSelectionPipe, IsNilOrBlankPipe, IsNilOrNaNPipe, IsNilPipe, IsNotAllSelectedPipe, IsNotEmptySelectionPipe, IsNotNilOrBlankPipe, IsNotNilOrNaNPipe, IsNotNilPipe, IsOnDeskPipe, IsOnFieldPipe, IsSelectedPipe, IsSingleSelectionPipe, IsValidDatePipe, JobModule, JobProgression, JobProgressionComponent, JobProgressionIcon, JobProgressionList, JobProgressionService, JobProgressionTestService, JobProgressionTestingPage, JobTestingModule, JobUtils, JsonUtils, KEYBOARD_HIDE_DELAY_MS, LAT_LONG_PATTERNS, LAT_LONG_PATTERN_MAX_DECIMALS, LAT_LONG_VALUE_MAX_DECIMALS, LatLongFormatPipe, LatLongTestPage, LatitudeFormatPipe, LocalSettingsService, LogLevel, LogUtils, Logger, LoggingService, LoggingServiceModule, LongitudeFormatPipe, MASKS, MASK_RANGES, MAT_FORM_FIELD_DEFAULT_APPEARANCE, MAT_FORM_FIELD_DEFAULT_SUBSCRIPT_SIZING, MINIFY_ENTITY_FOR_LOCAL_STORAGE, MINIFY_ENTITY_FOR_POD, MOMENT_NO_TIME_PROPERTY, MapGetPipe, MapKeysPipe, MapValuesPipe, MarkdownDirective, MarkdownService, MarkdownTestPage, MarkdownTestingModule, MarkdownUtils, MaskitoPlaceholderPipe, MaskitoTestPage, MatAutocompleteConfigHolder, MatAutocompleteField, MatAutocompleteFieldUtils, MatBadgeTestPage, MatBooleanField, MatChipsField, MatColorPipe, MatCommonTestPage, MatDate, MatDateShort, MatDateTime, MatDuration, MatLatLongField, MatLatLongFieldInput, MatPaginatorI18n, MatStepperI18n, MatSwipeField, MaterialTestingModule, MathAbsPipe, MenuComponent, MenuItem, MenuItems, MenuOptions, MenuService, MenuTestingModule, MenuTestingPage, Message, MessageFilter, MessageForm, MessageModal, MessageModule, MessageService, MessageTypeList, MessageTypes, MimeTypes, ModalToolbarComponent, NETWORK_DEFAULT_CONNECTION_TIMEOUT, NamedFilter, NamedFilterFilter, NamedFilterSelector, NamedFilterSelectorTestingModule, NamedFilterSelectorTestingPage, NavActionsColumnComponent, NetworkService, NetworkUtils, NewTokenForm, NewTokenModal, NgInitDirective, NgVarDirective, NoHtmlPipe, NotEmptyArrayPipe, NumberFormatPipe, ObservableTestPage, OddPipe, OtherMenuTestingPage, PEER_URL_REGEXP, PLUS_PLACEHOLDER_CHAR_REGEXP_GLOBAL, PRIORITIZED_AUTHORITIES, PUBKEY_REGEXP, Peer, Person, PersonFilter, PersonFragments, PersonService, PersonToStringPipe, PersonUtils, PersonValidatorService, PlatformService, ProgressBarService, ProgressInterceptor, PropertiesFormTestPage, PropertiesFormTestingModule, PropertyEntity, PropertyEntityFilter, PropertyEntityValidator, PropertyFormatPipe, PropertyGetPipe, RESERVED_END_COLUMNS, RESERVED_START_COLUMNS, Referential, ReferentialFilter, ReferentialRef, ReferentialToStringPipe, ReferentialUtils, ReferentialValidatorService, RegExpUtils, RegisterConfirmPage, RegisterForm, RegisterModal, ResizableComponent, ResizableDirective, ResizableModule, RxStateModule, RxStateProperty, RxStateRegister, RxStateSelect, SCRYPT_PARAMS, SETTINGS_DISPLAY_COLUMNS, SETTINGS_FILTER, SETTINGS_PAGE_SIZE, SETTINGS_SORTED_COLUMN, SETTINGS_STORAGE_KEY, SETTINGS_TRANSIENT_PROPERTIES, SHARED_MATERIAL_TESTING_PAGES, SHARED_STORAGE_TESTING_PAGES, SHARED_TESTING_PAGES, SOCIAL_TESTING_PAGES, SPACE_PLACEHOLDER_CHAR, SPACE_PLACEHOLDER_CHAR_REGEXP_GLOBAL, SafeHtmlPipe, SelectPeerModal, SelectionLengthPipe, ServerErrorCodes, SettingsPage, SharedAsyncValidators, SharedBadgeModule, SharedDebugModule, SharedDirectivesModule, SharedFormArrayValidators, SharedFormGroupValidators, SharedHotkeysModule, SharedMarkdownModule, SharedMatAutocompleteModule, SharedMatBooleanModule, SharedMatChipsModule, SharedMatDateTimeModule, SharedMatDurationModule, SharedMatLatLongModule, SharedMatSwipeModule, SharedMaterialModule, SharedModule, SharedNamedFilterModule, SharedPipesModule, SharedRoutingModule, SharedTestingModule, SharedTestsPage, SharedTextFormModule, SharedToolbarModule, SharedValidators, SocialErrorCodes, SocialModule, SocialModuleOptionsToken, SocialTestingModule, Software, StartableService, StatusById, StatusIds, StatusList, StorageDrivers, StorageExplorerComponent, StorageExplorerModule, StorageExplorerTestingModule, StorageExplorerTestingRoutingModule, StorageService, StrIncludesPipe, StrLengthPipe, StrReplacePipe, SubMenuTabDirective, SwipeTestPage, Table2TestPage, TableSelectColumnsComponent, TableTestPage, TableTestingModule, TableValidatorService, TextForm, TextFormTestingPage, TextPopover, TextPopoverTestingModule, TextPopoverTestingPage, ThrottledClickDirective, ToStringPipe, ToastTestingModule, ToastTestingPage, Toasts, TokenScope, ToolbarComponent, ToolbarToken, TranslatablePipe, TranslateContextPipe, TranslateContextService, TreeItemEntityUtils, UploadFile, UploadFileComponent, UploadFilePopover, UploadFileTestingModule, UploadFileTestingPage, UriUtils, UrlUtils, UserEventModule, UserEventNotificationIcon, UserEventNotificationList, UserEventTestService, UserEventTestingModule, UserEventTestingPage, UserSettings, UserToken, UserTokenTable, UsersPage, ValueFormatPipe, VersionUtils, accountToString, adaptValueToControl, addValueInArray, arrayDistinct, arrayResize, arraySize, asInputElement, booleanToString, canHaveFocus, capitalizeFirstLetter, chainPromises, changeCaseToUnderscore, clearValueInArray, collectByProperty, compareVersionNumbers, computeDecimalDegrees, computeDecimalPart, copyEntity2Form, createPromiseEvent, createPromiseEventEmitter, departmentToString, departmentsToString, disableAndClearControl, disableAndClearControls, disableControl, disableControls, emitPromiseEvent, enableControl, enableControls, enableRxStateProduction, entityToString, equals, equalsOrNil, escapeRegExp, fadeInAnimation, fadeInOutAnimation, fadeInSlowAnimation, filterFalse, filterFormErrors, filterFormErrorsByPath, filterFormErrorsByPrefix, filterNotNil, filterNumberInput, filterTrue, findParentWithClass, firstArrayValue, firstFalse, firstFalsePromise, firstNotNil, firstNotNilPromise, firstTrue, firstTruePromise, focusInput, focusNextInput, focusPreviousInput, formatLatLong, formatLatitude, formatLongitude, fromDateISOString, fromScrollEndEvent, fromUnixMsTimestamp, fromUnixTimestamp, getCaretPosition, getColorContrast, getColorShade, getColorTint, getControlFromPath, getFocusableInputElements, getFormErrors, getFormValueFromEntity, getInputRangeFromCaretIndex, getInputSelectionRangesFromMask, getProperty, getPropertyByPath, getPropertyByPathAsString, getRandomImage, getRandomImageWithCredit, getUserAgent, hexToRgb, hexToRgbArray, initArrayControlsFromValues, intersectArrays, isAndroid, isBlankString, isCapacitor, isChrome, isControlHasInput, isEdge, isEmptyArray, isFirefox, isIOS, isInputElement, isInstanceOf, isInt, isIpad, isMacOS, isMobile, isNil, isNilOrBlank, isNilOrNaN, isNotEmptyArray, isNotNil, isNotNilBoolean, isNotNilObject, isNotNilOrBlank, isNotNilOrNaN, isNotNilString, isNumber, isNumberRange, isOnFieldMode, isProgressEvent, isPromise, isResponseEvent, isSafari, isSameVersion, isStartableService, isTouchUi, isVersionCompatible, isWindows, joinProperties, joinPropertiesPath, lastArrayValue, logFormErrors, markAllAsTouched, markAsUntouched, markControlAsTouched, markFormGroupAsTouched, maskitoAutoSelectByMaskPattern, maskitoPrefixPlugin, matchMedia, matchUpperCase, mergeLoadResult, mixHex, moveInputCaretToSeparator, newArray, noHtml, noTrailingSlash, notNilOrDefault, nullIfNilOrBlank, nullIfUndefined, parseLatitudeOrLongitude, propertiesPathComparator, propertyComparator, propertyPathComparator, referentialToString, referentialsToString, remove, removeAll, removeDiacritics, removeDuplicatesFromArray, removeEnd, removeValueInArray, replaceAll, resetCalculatedValue, resizeArray, rgbArrayToHex, rgbToHex, round, scrollFactory, selectInputContent, selectInputContentFromEvent, selectInputRange, setCalculatedValue, setControlEnabled, setControlsEnabled, setPropertyByPath, setTabIndex, sleep, slideDownAnimation, slideInAnimation, slideInOutAnimation, slideUpDownAnimation, sort, splitById, splitByProperty, splitDegreesToDDArray, splitDegreesToDDMMArray, splitDegreesToDDMMSSArray, startsWithUpperCase, suggestFromArray, suggestFromStringArray, tabindexComparator, testUserAgent, toBoolean, toDateISOString, toDuration, toFloat, toInt, toNotNil, toNumber, trimEmptyToNull, uncapitalizeFirstLetter, undefinedIfNull, underscoreToChangeCase, updateValueAndValidity, waitFor, waitForFalse, waitForTrue, waitIdle, waitWhilePending };
47370
+ export { APP_ABOUT_DEVELOPERS, APP_ABOUT_PARTNERS, APP_CONFIG_OPTIONS, APP_DEBUG_DATA_SERVICE, APP_FORM_ERROR_I18N_KEYS, APP_GRAPHQL_FRAGMENTS, APP_GRAPHQL_TYPE_POLICIES, APP_HOME_BUTTONS, APP_HOTKEYS_CONFIG, APP_JOB_PROGRESSION_SERVICE, APP_LOCALES, APP_LOCAL_SETTINGS, APP_LOCAL_SETTINGS_OPTIONS, APP_LOCAL_STORAGE_TYPE_POLICIES, APP_LOGGING_SERVICE, APP_MENU_ITEMS, APP_MENU_OPTIONS, APP_NAMED_FILTER_SERVICE, APP_PROGRESS_BAR_SERVICE, APP_SETTINGS_MENU_ITEMS, APP_STORAGE, APP_STORAGE_EXPLORER_PROTECTED_KEYS, APP_TESTING_PAGES, APP_USER_EVENT_LIST_INFINITE_SCROLL_THRESHOLD, APP_USER_EVENT_SERVICE, APP_USER_SETTINGS_OPTIONS, APP_USER_TOKEN_SCOPES, AboutModal, AbstractNamedFilterService, AbstractSelectionModelPipe, AbstractTableSelectionPipe, AbstractUserEventService, Account, AccountPage, AccountService, AccountToStringPipe, AccountUtils, ActionsColumnComponent, AdminModule, AdminRoutingModule, AdminUsersModule, Alerts, AndroidOsEnvironment, AppAboutModalModule, AppAccountModule, AppAsyncTable, AppAuthForm, AppAuthModal, AppAuthModule, AppChangePasswordModule, AppChangePasswordPage, AppEditor, AppEditorOptions, AppEntityEditor, AppEntityEditorModal, AppEntityEditorModalOptions, AppEntityFormModule, AppForm, AppFormArray, AppFormButtonsBarModule, AppFormContainer, AppFormField, AppFormModule, AppFormProvider, AppFormUtils, AppGestureConfig, AppGraphQLModule, AppHomePageModule, AppIconComponent, AppIconModule, AppImageGalleryComponent, AppInMemoryTable, AppInstallUpgradeCard, AppInstallUpgradeCardModule, AppListForm, AppListFormModule, AppLoadingSpinner, AppMarkdownContent, AppMarkdownModal, AppMenuModule, AppNullForm, AppPropertiesForm, AppPropertiesFormModule, AppPropertiesTable, AppPropertiesUtils, AppPropertyUtils, AppRegisterModule, AppResetPasswordModal, AppRowField, AppSelectPeerModule, AppSettingsPageModule, AppTabEditor, AppTabEditorOptions, AppTable, AppTableModule, AppTableUtils, AppTextPopoverModule, AppUpdateOfflineModeCard, AppUpdateOfflineModeCardModule, AppValidatorService, ArrayFilterPipe, ArrayFirstPipe, ArrayFormTestPage, ArrayIncludesPipe, ArrayJoinPipe, ArrayLastPipe, ArrayLengthPipe, ArrayPluckPipe, AsAnyPipe, AsArrayPipe, AsBooleanPipe, AsFloatLabelTypePipe, AsObservablePipe, AudioProvider, AudioTestingModule, AudioTestingPage, AuthGuardService, AutoTitleDirective, AutocompleteTestPage, AutofocusDirective, BadgeDirective, BadgeNumberPipe, Base58, BaseEntityService, BaseGraphqlService, BaseGraphqlServiceOptions, BaseReferential, Beans, BooleanFormatPipe, BooleanTestPage, CORE_CONFIG_OPTIONS, CORE_TESTING_PAGES, CapitalizePipe, CellValueChangeListener, ChangePasswordForm, ChipsTestPage, Color, ColorScale, ComponentDirtyGuard, ConfigFragments, ConfigService, Configuration, CoreModule, CorePipesModule, CoreTestingModule, CryptoService, CsvUtils, DATE_ISO_PATTERN, DATE_MATCH_REGEXP, DATE_PATTERN, DATE_UNIX_MS_TIMESTAMP, DATE_UNIX_TIMESTAMP, DEFAULT_JOIN_ARRAY_VALUES_SEPARATOR, DEFAULT_JOIN_PROPERTIES_SEPARATOR, DEFAULT_MENU_SHOW_WHEN, DEFAULT_PAGE_SIZE, DEFAULT_PAGE_SIZE_OPTIONS, DEFAULT_PLACEHOLDER_CHAR, DEFAULT_REQUIRED_COLUMNS, DateDiffDurationPipe, DateFormatPipe, DateFormatService, DateFromNowPipe, DateShortTestPage, DateTestPage, DateTimeTestPage, DateUtils, DebugComponent, Department, DepartmentToStringPipe, DisplayWithPipe, DragAndDropDirective, DurationPipe, DurationTestPage, ED25519_SEED_LENGTH, EMPTY_PLACEHOLDER_CHAR, EMPTY_PLACEHOLDER_CHAR_REGEXP_GLOBAL, ENTITIES_STORAGE_KEY_PREFIX, ENVIRONMENT, EmptyArrayPipe, EntitiesAsyncTableDataSource, EntitiesStorage, EntitiesTableDataSource, Entity, EntityClass, EntityClasses, EntityFilter, EntityFilterUtils, EntityMetadataComponent, EntityStore, EntityUtils, Environment, EnvironmentHttpLoader, EnvironmentLoader, ErrorCodes, EvenPipe, FileResponse, FileService, FileSizePipe, FilesUtils, FormArrayHelper, FormArrayTestModule, FormButtonsBarComponent, FormButtonsBarToken, FormErrorPipe, FormErrorTranslatePipe, FormErrorTranslator, FormFieldDefinitionUtils, FormFieldValuesHolder, FormGetArrayPipe, FormGetControlPipe, FormGetGroupPipe, FormGetPipe, FormGetValuePipe, GalleryTestPage, GeolocationUtils, GraphqlService, HAMMER_PRESS_TIME, HAMMER_TAP_TIME, HighlightPipe, HomePage, Hotkeys, HotkeysDialogComponent, IMAGE_DEFAULTS, IPosition, ImageAttachment, ImageAttachmentFilter, ImageAttachmentService, ImageGalleryModule, ImageGalleryTestingModule, ImageModule, ImageService, ImagesUtils, InMemoryEntitiesService, IsAllSelectedPipe, IsEmptySelectionPipe, IsLoginAccountPipe, IsMultipleSelectionPipe, IsNilOrBlankPipe, IsNilOrNaNPipe, IsNilPipe, IsNotAllSelectedPipe, IsNotEmptySelectionPipe, IsNotNilOrBlankPipe, IsNotNilOrNaNPipe, IsNotNilPipe, IsOnDeskPipe, IsOnFieldPipe, IsSelectedPipe, IsSingleSelectionPipe, IsValidDatePipe, JobModule, JobProgression, JobProgressionComponent, JobProgressionIcon, JobProgressionList, JobProgressionService, JobProgressionTestService, JobProgressionTestingPage, JobTestingModule, JobUtils, JsonUtils, KEYBOARD_HIDE_DELAY_MS, LAT_LONG_PATTERNS, LAT_LONG_PATTERN_MAX_DECIMALS, LAT_LONG_VALUE_MAX_DECIMALS, LatLongFormatPipe, LatLongTestPage, LatitudeFormatPipe, LocalSettingsService, LogLevel, LogUtils, Logger, LoggingService, LoggingServiceModule, LongitudeFormatPipe, MASKS, MASK_RANGES, MAT_FORM_FIELD_DEFAULT_APPEARANCE, MAT_FORM_FIELD_DEFAULT_SUBSCRIPT_SIZING, MINIFY_ENTITY_FOR_LOCAL_STORAGE, MINIFY_ENTITY_FOR_POD, MOMENT_NO_TIME_PROPERTY, MapGetPipe, MapKeysPipe, MapValuesPipe, MarkdownDirective, MarkdownService, MarkdownTestPage, MarkdownTestingModule, MarkdownUtils, MaskitoPlaceholderPipe, MaskitoTestPage, MatAutocompleteConfigHolder, MatAutocompleteField, MatAutocompleteFieldUtils, MatBadgeTestPage, MatBooleanField, MatChipsField, MatColorPipe, MatCommonTestPage, MatDate, MatDateShort, MatDateTime, MatDuration, MatLatLongField, MatLatLongFieldInput, MatPaginatorI18n, MatStepperI18n, MatSwipeField, MaterialTestingModule, MathAbsPipe, MenuComponent, MenuItem, MenuItems, MenuOptions, MenuService, MenuTestingModule, MenuTestingPage, Message, MessageFilter, MessageForm, MessageModal, MessageModule, MessageService, MessageTypeList, MessageTypes, MimeTypes, ModalToolbarComponent, NETWORK_DEFAULT_CONNECTION_TIMEOUT, NamedFilter, NamedFilterFilter, NamedFilterSelector, NamedFilterSelectorTestingModule, NamedFilterSelectorTestingPage, NavActionsColumnComponent, NetworkService, NetworkUtils, NewTokenForm, NewTokenModal, NgInitDirective, NgVarDirective, NoHtmlPipe, NotEmptyArrayPipe, NumberFormatPipe, ObservableTestPage, OddPipe, OtherMenuTestingPage, PEER_URL_REGEXP, PLUS_PLACEHOLDER_CHAR_REGEXP_GLOBAL, PRINT_LOADING_STORAGE_KEY_PREFIX, PRIORITIZED_AUTHORITIES, PUBKEY_REGEXP, Peer, Person, PersonFilter, PersonFragments, PersonService, PersonToStringPipe, PersonUtils, PersonValidatorService, PlatformService, PrintService, ProgressBarService, ProgressInterceptor, PropertiesFormTestPage, PropertiesFormTestingModule, PropertyEntity, PropertyEntityFilter, PropertyEntityValidator, PropertyFormatPipe, PropertyGetPipe, RESERVED_END_COLUMNS, RESERVED_START_COLUMNS, Referential, ReferentialFilter, ReferentialRef, ReferentialToStringPipe, ReferentialUtils, ReferentialValidatorService, RegExpUtils, RegisterConfirmPage, RegisterForm, RegisterModal, ResizableComponent, ResizableDirective, ResizableModule, RxStateModule, RxStateProperty, RxStateRegister, RxStateSelect, SCRYPT_PARAMS, SETTINGS_DISPLAY_COLUMNS, SETTINGS_FILTER, SETTINGS_PAGE_SIZE, SETTINGS_SORTED_COLUMN, SETTINGS_STORAGE_KEY, SETTINGS_TRANSIENT_PROPERTIES, SHARED_MATERIAL_TESTING_PAGES, SHARED_STORAGE_TESTING_PAGES, SHARED_TESTING_PAGES, SOCIAL_TESTING_PAGES, SPACE_PLACEHOLDER_CHAR, SPACE_PLACEHOLDER_CHAR_REGEXP_GLOBAL, SafeHtmlPipe, SelectPeerModal, SelectionLengthPipe, ServerErrorCodes, SettingsPage, SharedAsyncValidators, SharedBadgeModule, SharedDebugModule, SharedDirectivesModule, SharedFormArrayValidators, SharedFormGroupValidators, SharedHotkeysModule, SharedMarkdownModule, SharedMatAutocompleteModule, SharedMatBooleanModule, SharedMatChipsModule, SharedMatDateTimeModule, SharedMatDurationModule, SharedMatLatLongModule, SharedMatSwipeModule, SharedMaterialModule, SharedModule, SharedNamedFilterModule, SharedPipesModule, SharedRoutingModule, SharedTestingModule, SharedTestsPage, SharedTextFormModule, SharedToolbarModule, SharedValidators, SocialErrorCodes, SocialModule, SocialModuleOptionsToken, SocialTestingModule, Software, StartableService, StatusById, StatusIds, StatusList, StorageDrivers, StorageExplorerComponent, StorageExplorerModule, StorageExplorerTestingModule, StorageExplorerTestingRoutingModule, StorageService, StrIncludesPipe, StrLengthPipe, StrReplacePipe, SubMenuTabDirective, SwipeTestPage, Table2TestPage, TableSelectColumnsComponent, TableTestPage, TableTestingModule, TableValidatorService, TextForm, TextFormTestingPage, TextPopover, TextPopoverTestingModule, TextPopoverTestingPage, ThrottledClickDirective, ToStringPipe, ToastTestingModule, ToastTestingPage, Toasts, TokenScope, ToolbarComponent, ToolbarToken, TranslatablePipe, TranslateContextPipe, TranslateContextService, TreeItemEntityUtils, UploadFile, UploadFileComponent, UploadFilePopover, UploadFileTestingModule, UploadFileTestingPage, UriUtils, UrlUtils, UserEventModule, UserEventNotificationIcon, UserEventNotificationList, UserEventTestService, UserEventTestingModule, UserEventTestingPage, UserSettings, UserToken, UserTokenTable, UsersPage, ValueFormatPipe, VersionUtils, accountToString, adaptValueToControl, addValueInArray, arrayDistinct, arrayResize, arraySize, asInputElement, booleanToString, canHaveFocus, capitalizeFirstLetter, chainPromises, changeCaseToUnderscore, clearValueInArray, collectByProperty, compareVersionNumbers, computeDecimalDegrees, computeDecimalPart, copyEntity2Form, createPromiseEvent, createPromiseEventEmitter, departmentToString, departmentsToString, disableAndClearControl, disableAndClearControls, disableControl, disableControls, emitPromiseEvent, enableControl, enableControls, enableRxStateProduction, entityToString, equals, equalsOrNil, escapeRegExp, fadeInAnimation, fadeInOutAnimation, fadeInSlowAnimation, filterFalse, filterFormErrors, filterFormErrorsByPath, filterFormErrorsByPrefix, filterNotNil, filterNumberInput, filterTrue, findParentWithClass, firstArrayValue, firstFalse, firstFalsePromise, firstNotNil, firstNotNilPromise, firstTrue, firstTruePromise, focusInput, focusNextInput, focusPreviousInput, formatLatLong, formatLatitude, formatLongitude, fromDateISOString, fromScrollEndEvent, fromUnixMsTimestamp, fromUnixTimestamp, getCaretPosition, getColorContrast, getColorShade, getColorTint, getControlFromPath, getFocusableInputElements, getFormErrors, getFormValueFromEntity, getInputRangeFromCaretIndex, getInputSelectionRangesFromMask, getProperty, getPropertyByPath, getPropertyByPathAsString, getRandomImage, getRandomImageWithCredit, getUserAgent, hexToRgb, hexToRgbArray, initArrayControlsFromValues, intersectArrays, isAndroid, isBlankString, isCapacitor, isChrome, isControlHasInput, isEdge, isEmptyArray, isFirefox, isIOS, isInputElement, isInstanceOf, isInt, isIpad, isMacOS, isMobile, isNil, isNilOrBlank, isNilOrNaN, isNotEmptyArray, isNotNil, isNotNilBoolean, isNotNilObject, isNotNilOrBlank, isNotNilOrNaN, isNotNilString, isNumber, isNumberRange, isOnFieldMode, isProgressEvent, isPromise, isResponseEvent, isSafari, isSameVersion, isStartableService, isTouchUi, isVersionCompatible, isWindows, joinProperties, joinPropertiesPath, lastArrayValue, logFormErrors, markAllAsTouched, markAsUntouched, markControlAsTouched, markFormGroupAsTouched, maskitoAutoSelectByMaskPattern, maskitoPrefixPlugin, matchMedia, matchUpperCase, mergeLoadResult, mixHex, moveInputCaretToSeparator, newArray, noHtml, noTrailingSlash, notNilOrDefault, nullIfNilOrBlank, nullIfUndefined, parseLatitudeOrLongitude, propertiesPathComparator, propertyComparator, propertyPathComparator, referentialToString, referentialsToString, remove, removeAll, removeDiacritics, removeDuplicatesFromArray, removeEnd, removeValueInArray, replaceAll, resetCalculatedValue, resizeArray, rgbArrayToHex, rgbToHex, round, scrollFactory, selectInputContent, selectInputContentFromEvent, selectInputRange, setCalculatedValue, setControlEnabled, setControlsEnabled, setPropertyByPath, setTabIndex, sleep, slideDownAnimation, slideInAnimation, slideInOutAnimation, slideUpDownAnimation, sort, splitById, splitByProperty, splitDegreesToDDArray, splitDegreesToDDMMArray, splitDegreesToDDMMSSArray, startsWithUpperCase, suggestFromArray, suggestFromStringArray, tabindexComparator, testUserAgent, toBoolean, toDateISOString, toDuration, toFloat, toInt, toNotNil, toNumber, trimEmptyToNull, uncapitalizeFirstLetter, undefinedIfNull, underscoreToChangeCase, updateValueAndValidity, waitFor, waitForFalse, waitForTrue, waitIdle, waitWhilePending };
47127
47371
  //# sourceMappingURL=sumaris-net.ngx-components.mjs.map