@dflat-core/web 1.7.2076 → 1.7.2077

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.
@@ -580,6 +580,28 @@ i0.ɵɵngDeclareClassMetadata({
580
580
  }
581
581
  });
582
582
  var PresentationProfileEditorComponent = class PresentationProfileEditorComponent extends BaseEntityEditor {
583
+ get visibleTabs() {
584
+ return [
585
+ ...this.showProperties ? [0] : [],
586
+ 1,
587
+ 2,
588
+ ...this.isDefaultView ? [] : [3],
589
+ ...this.cardTemplate ? [4] : []
590
+ ];
591
+ }
592
+ selectTab(index) {
593
+ this.activeTab = this.visibleTabs[index] ?? 1;
594
+ }
595
+ get shownTab() {
596
+ return this.visibleTabs.includes(this.activeTab) ? this.activeTab : 1;
597
+ }
598
+ set showProperties(value) {
599
+ this._showProperties = value !== false;
600
+ if (!this._showProperties && this.activeTab === 0) this.activeTab = 1;
601
+ }
602
+ get showProperties() {
603
+ return this._showProperties;
604
+ }
583
605
  static {
584
606
  this.frozenFields = [
585
607
  "MetaEntityKey",
@@ -605,6 +627,10 @@ var PresentationProfileEditorComponent = class PresentationProfileEditorComponen
605
627
  get selectedCount() {
606
628
  return this.orderedSelection.length;
607
629
  }
630
+ get isDefaultView() {
631
+ const scope = this.current?.PresentationProfileScope;
632
+ return scope === void 0 || scope === null || scope === PresentationProfileScopes.Default;
633
+ }
608
634
  get current() {
609
635
  if (!this.entity) return void 0;
610
636
  return this.facade?.change.getModified(this.entity.Id) ?? this.entity;
@@ -614,6 +640,9 @@ var PresentationProfileEditorComponent = class PresentationProfileEditorComponen
614
640
  this.itemData = itemData;
615
641
  this.modalService = modalService;
616
642
  this.activeTab = 0;
643
+ this.cardTemplate = null;
644
+ this.panelFields = [];
645
+ this._showProperties = true;
617
646
  this.viewSort = [];
618
647
  this.viewFilter = {
619
648
  Logic: "and",
@@ -747,7 +776,9 @@ var PresentationProfileEditorComponent = class PresentationProfileEditorComponen
747
776
  Groups: []
748
777
  };
749
778
  this.viewFilter.Groups = this.viewFilter.Groups ?? [];
750
- this.publishedQueries = JSON.stringify(this.currentQueries());
779
+ const loaded = this.currentQueries();
780
+ if (this.isDefaultView) delete loaded.FilterQuery;
781
+ this.publishedQueries = JSON.stringify(loaded);
751
782
  }
752
783
  currentQueries() {
753
784
  const sort = this.viewSort.filter((s) => !!s.property);
@@ -759,6 +790,7 @@ var PresentationProfileEditorComponent = class PresentationProfileEditorComponen
759
790
  ngDoCheck() {
760
791
  if (!this.loadedEntity || this.readonly) return;
761
792
  const queries = this.currentQueries();
793
+ if (this.isDefaultView) delete queries.FilterQuery;
762
794
  const json = JSON.stringify(queries);
763
795
  if (json === this.publishedQueries) return;
764
796
  this.publishedQueries = json;
@@ -890,9 +922,14 @@ var PresentationProfileEditorComponent = class PresentationProfileEditorComponen
890
922
  type: PresentationProfileEditorComponent,
891
923
  isStandalone: false,
892
924
  selector: "alg-presentation-profile-editor",
925
+ inputs: {
926
+ cardTemplate: "cardTemplate",
927
+ panelFields: "panelFields",
928
+ showProperties: "showProperties"
929
+ },
893
930
  usesInheritance: true,
894
931
  ngImport: i0,
895
- template: "<div class=\"pp-editor\">\r\n @if (entity) {\r\n <alg-tabset [showNavs]=\"true\" [pills]=\"false\" (onSelect)=\"activeTab = $event\">\r\n\r\n <!--Propriétés : table, libellé, finalité et portée du profil, avec les composants des formulaires-->\r\n <alg-tab title=\"Propriétés\" [active]=\"activeTab === 0\" [class.pp-editor-tab]=\"activeTab === 0\">\r\n <div class=\"property-container pp-editor-properties\">\r\n @for (section of sections; track section.Name) {\r\n <div class=\"property-section-container\">\r\n <div class=\"property-section-title\">{{ section.Name }}</div>\r\n <div class=\"property-section-content\">\r\n @for (field of section.FieldViewModels; track field.PropertyName) {\r\n <div class=\"property-row\" [hidden]=\"isFieldHidden(field)\">\r\n <alg-field [field]=\"field\" [form]=\"form\" [readonly]=\"isFieldReadonly(field)\"\r\n (propertyChanged)=\"onPropertyChanged($event)\">\r\n </alg-field>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n </alg-tab>\r\n\r\n <!--Colonnes : colonnes affichées par la grille, leur ordre et leurs libellés-->\r\n <alg-tab title=\"Colonnes\" [active]=\"activeTab === 1\" [class.pp-editor-tab]=\"activeTab === 1\">\r\n <div class=\"gcc pp-editor-columns\">\r\n <div *ngIf=\"isLoading\" class=\"gcc__loading\">\r\n <span class=\"gcc__spinner-icon fa fa-circle-o-notch fa-spin\"></span>\r\n Chargement des colonnes…\r\n </div>\r\n <div *ngIf=\"!isLoading && allItems.length === 0 && orderedSelection.length === 0\" class=\"gcc__hint\">\r\n Choisissez la table du profil dans l'onglet « Propriétés ».\r\n </div>\r\n <ng-container *ngIf=\"!isLoading && (allItems.length > 0 || orderedSelection.length > 0)\">\r\n <div class=\"gcc__panels\">\r\n\r\n <!-- ── Colonnes disponibles : celles de la table qui ne sont pas affichées ── -->\r\n <div class=\"gcc__browse\">\r\n <div class=\"gcc__panel-hd\">\r\n <span class=\"gcc__panel-label\">Colonnes disponibles</span>\r\n <span class=\"gcc__badge\">{{ filteredItems.length }}</span>\r\n <input class=\"gcc__search\" type=\"text\" placeholder=\"Rechercher…\"\r\n [(ngModel)]=\"searchText\" (ngModelChange)=\"onSearch()\">\r\n <button *ngIf=\"!readonly\" class=\"pp-editor-add-all\" type=\"button\" [disabled]=\"filteredItems.length === 0\"\r\n (click)=\"addAll()\" title=\"Afficher toutes les colonnes listées\">Tout ajouter</button>\r\n </div>\r\n\r\n <div class=\"gcc__table-wrap\">\r\n <table class=\"gcc__browse-table\">\r\n <tbody>\r\n <tr *ngFor=\"let item of filteredItems\"\r\n class=\"gcc__browse-row\"\r\n [class.gcc__browse-row--custom]=\"item.ColumnSourceType === 2\"\r\n title=\"Afficher cette colonne\"\r\n (click)=\"addItem(item)\">\r\n <td class=\"gcc__col-name\">\r\n <div class=\"gcc__col-key\">{{ item.ColumnKey }}</div>\r\n <div *ngIf=\"item.Label && item.Label !== item.ColumnKey\" class=\"gcc__sub\">{{ item.Label }}</div>\r\n </td>\r\n <td class=\"pp-editor-add\"><i *ngIf=\"!readonly\" class=\"fa fa-plus\"></i></td>\r\n </tr>\r\n <tr *ngIf=\"filteredItems.length === 0\">\r\n <td colspan=\"2\" class=\"gcc__browse-empty\">\r\n {{ searchText ? 'Aucune colonne trouvée' : 'Toutes les colonnes sont affichées' }}\r\n </td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n </div>\r\n </div>\r\n\r\n <!-- ── Panel 4: Ordered selection with admin flags ────────────── -->\r\n <div class=\"gcc__selection\">\r\n <div class=\"gcc__panel-hd\">\r\n <span class=\"gcc__panel-label\">Colonnes affichées</span>\r\n <span *ngIf=\"selectedCount > 0\" class=\"gcc__badge gcc__badge--primary\">{{ selectedCount }}</span>\r\n </div>\r\n\r\n <div *ngIf=\"orderedSelection.length > 0\" class=\"gcc__sel-legend\">\r\n <span class=\"gcc__sel-legend__drag\"></span>\r\n <span class=\"gcc__sel-legend__pos\">#</span>\r\n <span class=\"gcc__sel-legend__code\">Colonne</span>\r\n <span class=\"gcc__sel-legend__label\">Étiquette</span>\r\n <span class=\"gcc__sel-legend__display\">Affichage</span>\r\n <ng-container *ngIf=\"isPerimeter\">\r\n <span class=\"gcc__sel-legend__flag\">Aut.</span>\r\n </ng-container>\r\n <span class=\"gcc__sel-legend__flag\">Ver.</span>\r\n <span class=\"gcc__sel-legend__remove\"></span>\r\n </div>\r\n\r\n <div *ngIf=\"orderedSelection.length === 0\" class=\"gcc__sel-empty\">\r\n <span class=\"fa fa-columns gcc__sel-empty__icon\"></span>\r\n <p>Choisissez des colonnes parmi les colonnes disponibles</p>\r\n </div>\r\n\r\n <div *ngIf=\"orderedSelection.length > 0\"\r\n class=\"gcc__sel-list\"\r\n cdkDropList\r\n [cdkDropListData]=\"orderedSelection\"\r\n (cdkDropListDropped)=\"onDrop($event)\">\r\n\r\n <div *ngFor=\"let item of orderedSelection; let i = index\"\r\n class=\"gcc__sel-item\"\r\n cdkDrag [cdkDragDisabled]=\"readonly\"\r\n [cdkDragData]=\"item\">\r\n\r\n <div class=\"gcc__sel-item__placeholder\" *cdkDragPlaceholder></div>\r\n\r\n <span class=\"gcc__sel-item__drag\" cdkDragHandle>\r\n <i class=\"fa fa-bars\"></i>\r\n </span>\r\n\r\n <span class=\"gcc__sel-item__pos\">{{ i + 1 }}</span>\r\n\r\n <span class=\"gcc__sel-item__code\"\r\n [class.gcc__sel-item__code--cf]=\"item.ColumnSourceType === 2\"\r\n [title]=\"item.ColumnKey\">\r\n <span class=\"gcc__sel-item__name\">{{ item.ColumnKey }}</span>\r\n <span *ngIf=\"getCatalogLabel(item) !== item.ColumnKey\" class=\"gcc__sub\">{{ getCatalogLabel(item) }}</span>\r\n </span>\r\n\r\n <input class=\"gcc__sel-item__label\" type=\"text\"\r\n [placeholder]=\"getCatalogLabel(item)\"\r\n [(ngModel)]=\"item.Label\" (ngModelChange)=\"onColumnsChanged()\" [disabled]=\"readonly\"\r\n (click)=\"$event.stopPropagation()\"\r\n title=\"Étiquette personnalisée\">\r\n\r\n <!-- Affichage : indicateur du type, ouvre la fenêtre d'édition de la colonne -->\r\n <span class=\"pp-display\" (click)=\"$event.stopPropagation()\">\r\n <button type=\"button\" class=\"pp-display__badge\"\r\n [class.pp-display__badge--default]=\"!getDisplayType(item)\"\r\n [title]=\"describeDisplay(item)\"\r\n (click)=\"openColumn(item)\">\r\n <i class=\"fa fa-{{ getDisplayType(item)?.icon ?? 'magic' }}\"></i>\r\n <span class=\"pp-display__text\">{{ getDisplayType(item)?.short ?? 'Auto' }}</span>\r\n </button>\r\n <button type=\"button\" class=\"pp-display__edit\" title=\"Modifier la colonne (libellé, affichage...)\" (click)=\"openColumn(item)\">\r\n <i class=\"fa fa-sliders\"></i>\r\n </button>\r\n </span>\r\n\r\n <!-- Perimeter scope: allowed flag -->\r\n <ng-container *ngIf=\"isPerimeter\">\r\n <label class=\"gcc__flag\" (click)=\"$event.stopPropagation()\">\r\n <input type=\"checkbox\" [(ngModel)]=\"item.IsAllowed\" (ngModelChange)=\"onColumnsChanged()\" [disabled]=\"readonly\" title=\"Autorisé\">\r\n </label>\r\n </ng-container>\r\n\r\n <!-- Always: locked flag -->\r\n <label class=\"gcc__flag\" (click)=\"$event.stopPropagation()\">\r\n <input type=\"checkbox\" [(ngModel)]=\"item.IsLocked\" (ngModelChange)=\"onColumnsChanged()\" [disabled]=\"readonly\" title=\"Verrouillé\">\r\n </label>\r\n\r\n <button class=\"gcc__sel-item__remove\" type=\"button\"\r\n (click)=\"removeFromSelection(item); $event.stopPropagation()\"\r\n title=\"Retirer\">&#x2715;</button>\r\n </div>\r\n\r\n </div>\r\n\r\n <!-- Pied de la sélection -->\r\n <div class=\"gcc__sel-footer\">\r\n <span class=\"gcc__sel-footer__info\">\r\n <ng-container *ngIf=\"selectedCount > 0\">\r\n {{ selectedCount }} colonne(s) — glissez pour réordonner\r\n </ng-container>\r\n </span>\r\n </div>\r\n </div>\r\n\r\n </div><!-- /.gcc__panels -->\r\n </ng-container>\r\n </div>\r\n </alg-tab>\r\n\r\n <!--Tri : tri enregistré dans la vue, appliqué à la grille quand elle affiche la vue-->\r\n <alg-tab title=\"Tri\" [active]=\"activeTab === 2\" [class.pp-editor-tab]=\"activeTab === 2\">\r\n <div class=\"pp-editor-queries\">\r\n <alg-filter-editor [embedded]=\"true\" section=\"sort\" [columns]=\"filterColumns\" [sort]=\"viewSort\"\r\n [filter]=\"viewFilter\" [class.pp-editor-readonly]=\"readonly\"></alg-filter-editor>\r\n </div>\r\n </alg-tab>\r\n\r\n <!--Filtres : filtre enregistré dans la vue (groupes ET / OU), ajouté aux filtres de la grille-->\r\n <alg-tab title=\"Filtres\" [active]=\"activeTab === 3\" [class.pp-editor-tab]=\"activeTab === 3\">\r\n <div class=\"pp-editor-queries\">\r\n <alg-filter-editor [embedded]=\"true\" section=\"filters\" [columns]=\"filterColumns\" [sort]=\"viewSort\"\r\n [filter]=\"viewFilter\" [class.pp-editor-readonly]=\"readonly\"></alg-filter-editor>\r\n </div>\r\n </alg-tab>\r\n </alg-tabset>\r\n }\r\n</div>\r\n",
932
+ template: "<div class=\"pp-editor\">\r\n @if (entity) {\r\n <alg-tabset [showNavs]=\"true\" [pills]=\"false\" (onSelect)=\"selectTab($event)\">\r\n\r\n <!--Propriétés : table, libellé, finalité et portée du profil, avec les composants des formulaires\r\n (masqué dans la fenêtre des vues d'une grille : la vue y est choisie à gauche)-->\r\n @if (showProperties) {\r\n <alg-tab title=\"Propriétés\" [active]=\"shownTab === 0\" [class.pp-editor-tab]=\"shownTab === 0\">\r\n <div class=\"property-container pp-editor-properties\">\r\n @for (section of sections; track section.Name) {\r\n <div class=\"property-section-container\">\r\n <div class=\"property-section-title\">{{ section.Name }}</div>\r\n <div class=\"property-section-content\">\r\n @for (field of section.FieldViewModels; track field.PropertyName) {\r\n <div class=\"property-row\" [hidden]=\"isFieldHidden(field)\">\r\n <alg-field [field]=\"field\" [form]=\"form\" [readonly]=\"isFieldReadonly(field)\"\r\n (propertyChanged)=\"onPropertyChanged($event)\">\r\n </alg-field>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n </alg-tab>\r\n }\r\n\r\n <!--Colonnes : colonnes affichées par la grille, leur ordre et leurs libellés-->\r\n <alg-tab title=\"Colonnes\" [active]=\"shownTab === 1\" [class.pp-editor-tab]=\"shownTab === 1\">\r\n <div class=\"gcc pp-editor-columns\">\r\n <div *ngIf=\"isLoading\" class=\"gcc__loading\">\r\n <span class=\"gcc__spinner-icon fa fa-circle-o-notch fa-spin\"></span>\r\n Chargement des colonnes…\r\n </div>\r\n <div *ngIf=\"!isLoading && allItems.length === 0 && orderedSelection.length === 0\" class=\"gcc__hint\">\r\n Choisissez la table du profil dans l'onglet « Propriétés ».\r\n </div>\r\n <ng-container *ngIf=\"!isLoading && (allItems.length > 0 || orderedSelection.length > 0)\">\r\n <div class=\"gcc__panels\">\r\n\r\n <!-- ── Colonnes disponibles : celles de la table qui ne sont pas affichées ── -->\r\n <div class=\"gcc__browse\">\r\n <div class=\"gcc__panel-hd\">\r\n <span class=\"gcc__panel-label\">Colonnes disponibles</span>\r\n <span class=\"gcc__badge\">{{ filteredItems.length }}</span>\r\n <input class=\"gcc__search\" type=\"text\" placeholder=\"Rechercher…\"\r\n [(ngModel)]=\"searchText\" (ngModelChange)=\"onSearch()\">\r\n <button *ngIf=\"!readonly\" class=\"pp-editor-add-all\" type=\"button\" [disabled]=\"filteredItems.length === 0\"\r\n (click)=\"addAll()\" title=\"Afficher toutes les colonnes listées\">Tout ajouter</button>\r\n </div>\r\n\r\n <div class=\"gcc__table-wrap\">\r\n <table class=\"gcc__browse-table\">\r\n <tbody>\r\n <tr *ngFor=\"let item of filteredItems\"\r\n class=\"gcc__browse-row\"\r\n [class.gcc__browse-row--custom]=\"item.ColumnSourceType === 2\"\r\n title=\"Afficher cette colonne\"\r\n (click)=\"addItem(item)\">\r\n <td class=\"gcc__col-name\">\r\n <div class=\"gcc__col-key\">{{ item.ColumnKey }}</div>\r\n <div *ngIf=\"item.Label && item.Label !== item.ColumnKey\" class=\"gcc__sub\">{{ item.Label }}</div>\r\n </td>\r\n <td class=\"pp-editor-add\"><i *ngIf=\"!readonly\" class=\"fa fa-plus\"></i></td>\r\n </tr>\r\n <tr *ngIf=\"filteredItems.length === 0\">\r\n <td colspan=\"2\" class=\"gcc__browse-empty\">\r\n {{ searchText ? 'Aucune colonne trouvée' : 'Toutes les colonnes sont affichées' }}\r\n </td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n </div>\r\n </div>\r\n\r\n <!-- ── Panel 4: Ordered selection with admin flags ────────────── -->\r\n <div class=\"gcc__selection\">\r\n <div class=\"gcc__panel-hd\">\r\n <span class=\"gcc__panel-label\">Colonnes affichées</span>\r\n <span *ngIf=\"selectedCount > 0\" class=\"gcc__badge gcc__badge--primary\">{{ selectedCount }}</span>\r\n </div>\r\n\r\n <div *ngIf=\"orderedSelection.length > 0\" class=\"gcc__sel-legend\">\r\n <span class=\"gcc__sel-legend__drag\"></span>\r\n <span class=\"gcc__sel-legend__pos\">#</span>\r\n <span class=\"gcc__sel-legend__code\">Colonne</span>\r\n <span class=\"gcc__sel-legend__label\">Étiquette</span>\r\n <span class=\"gcc__sel-legend__display\">Affichage</span>\r\n <ng-container *ngIf=\"isPerimeter\">\r\n <span class=\"gcc__sel-legend__flag\">Aut.</span>\r\n </ng-container>\r\n <span class=\"gcc__sel-legend__flag\">Ver.</span>\r\n <span class=\"gcc__sel-legend__remove\"></span>\r\n </div>\r\n\r\n <div *ngIf=\"orderedSelection.length === 0\" class=\"gcc__sel-empty\">\r\n <span class=\"fa fa-columns gcc__sel-empty__icon\"></span>\r\n <p>Choisissez des colonnes parmi les colonnes disponibles</p>\r\n </div>\r\n\r\n <div *ngIf=\"orderedSelection.length > 0\"\r\n class=\"gcc__sel-list\"\r\n cdkDropList\r\n [cdkDropListData]=\"orderedSelection\"\r\n (cdkDropListDropped)=\"onDrop($event)\">\r\n\r\n <div *ngFor=\"let item of orderedSelection; let i = index\"\r\n class=\"gcc__sel-item\"\r\n cdkDrag [cdkDragDisabled]=\"readonly\"\r\n [cdkDragData]=\"item\">\r\n\r\n <div class=\"gcc__sel-item__placeholder\" *cdkDragPlaceholder></div>\r\n\r\n <span class=\"gcc__sel-item__drag\" cdkDragHandle>\r\n <i class=\"fa fa-bars\"></i>\r\n </span>\r\n\r\n <span class=\"gcc__sel-item__pos\">{{ i + 1 }}</span>\r\n\r\n <span class=\"gcc__sel-item__code\"\r\n [class.gcc__sel-item__code--cf]=\"item.ColumnSourceType === 2\"\r\n [title]=\"item.ColumnKey\">\r\n <span class=\"gcc__sel-item__name\">{{ item.ColumnKey }}</span>\r\n <span *ngIf=\"getCatalogLabel(item) !== item.ColumnKey\" class=\"gcc__sub\">{{ getCatalogLabel(item) }}</span>\r\n </span>\r\n\r\n <input class=\"gcc__sel-item__label\" type=\"text\"\r\n [placeholder]=\"getCatalogLabel(item)\"\r\n [(ngModel)]=\"item.Label\" (ngModelChange)=\"onColumnsChanged()\" [disabled]=\"readonly\"\r\n (click)=\"$event.stopPropagation()\"\r\n title=\"Étiquette personnalisée\">\r\n\r\n <!-- Affichage : indicateur du type, ouvre la fenêtre d'édition de la colonne -->\r\n <span class=\"pp-display\" (click)=\"$event.stopPropagation()\">\r\n <button type=\"button\" class=\"pp-display__badge\"\r\n [class.pp-display__badge--default]=\"!getDisplayType(item)\"\r\n [title]=\"describeDisplay(item)\"\r\n (click)=\"openColumn(item)\">\r\n <i class=\"fa fa-{{ getDisplayType(item)?.icon ?? 'magic' }}\"></i>\r\n <span class=\"pp-display__text\">{{ getDisplayType(item)?.short ?? 'Auto' }}</span>\r\n </button>\r\n <button type=\"button\" class=\"pp-display__edit\" title=\"Modifier la colonne (libellé, affichage...)\" (click)=\"openColumn(item)\">\r\n <i class=\"fa fa-sliders\"></i>\r\n </button>\r\n </span>\r\n\r\n <!-- Perimeter scope: allowed flag -->\r\n <ng-container *ngIf=\"isPerimeter\">\r\n <label class=\"gcc__flag\" (click)=\"$event.stopPropagation()\">\r\n <input type=\"checkbox\" [(ngModel)]=\"item.IsAllowed\" (ngModelChange)=\"onColumnsChanged()\" [disabled]=\"readonly\" title=\"Autorisé\">\r\n </label>\r\n </ng-container>\r\n\r\n <!-- Always: locked flag -->\r\n <label class=\"gcc__flag\" (click)=\"$event.stopPropagation()\">\r\n <input type=\"checkbox\" [(ngModel)]=\"item.IsLocked\" (ngModelChange)=\"onColumnsChanged()\" [disabled]=\"readonly\" title=\"Verrouillé\">\r\n </label>\r\n\r\n <button class=\"gcc__sel-item__remove\" type=\"button\"\r\n (click)=\"removeFromSelection(item); $event.stopPropagation()\"\r\n title=\"Retirer\">&#x2715;</button>\r\n </div>\r\n\r\n </div>\r\n\r\n <!-- Pied de la sélection -->\r\n <div class=\"gcc__sel-footer\">\r\n <span class=\"gcc__sel-footer__info\">\r\n <ng-container *ngIf=\"selectedCount > 0\">\r\n {{ selectedCount }} colonne(s) — glissez pour réordonner\r\n </ng-container>\r\n </span>\r\n </div>\r\n </div>\r\n\r\n </div><!-- /.gcc__panels -->\r\n </ng-container>\r\n </div>\r\n </alg-tab>\r\n\r\n <!--Tri : tri enregistré dans la vue, appliqué à la grille quand elle affiche la vue-->\r\n <alg-tab title=\"Tri\" [active]=\"shownTab === 2\" [class.pp-editor-tab]=\"shownTab === 2\">\r\n <div class=\"pp-editor-queries\">\r\n <alg-filter-editor [embedded]=\"true\" section=\"sort\" [columns]=\"filterColumns\" [sort]=\"viewSort\"\r\n [filter]=\"viewFilter\" [class.pp-editor-readonly]=\"readonly\"></alg-filter-editor>\r\n </div>\r\n </alg-tab>\r\n\r\n <!--Filtres : filtre enregistré dans la vue (groupes ET / OU, valeurs du FilterPanel), ajouté aux filtres\r\n de la grille ; pas sur une vue par défaut, qui s'applique à tous les utilisateurs (lignes masquées pour tous)-->\r\n @if (!isDefaultView) {\r\n <alg-tab title=\"Filtres\" [active]=\"shownTab === 3\" [class.pp-editor-tab]=\"shownTab === 3\">\r\n <div class=\"pp-editor-queries\">\r\n <alg-filter-editor [embedded]=\"true\" section=\"filters\" [columns]=\"filterColumns\" [sort]=\"viewSort\"\r\n [filter]=\"viewFilter\" [panelFields]=\"panelFields\" [class.pp-editor-readonly]=\"readonly\"></alg-filter-editor>\r\n </div>\r\n </alg-tab>\r\n }\r\n\r\n <!--Carte : carte de la vue Grille (fenêtre des vues d'une grille), à défaut la carte par défaut-->\r\n @if (cardTemplate) {\r\n <alg-tab title=\"Carte\" [active]=\"shownTab === 4\" [class.pp-editor-tab]=\"shownTab === 4\">\r\n <ng-container [ngTemplateOutlet]=\"cardTemplate\"></ng-container>\r\n </alg-tab>\r\n }\r\n </alg-tabset>\r\n }\r\n</div>\r\n",
896
933
  styles: ["alg-pp-column{display:block;height:100%}.gcc{display:flex;flex-direction:column;height:100%;overflow:hidden;padding:10px;box-sizing:border-box}.gcc__form{flex:1;min-height:0;display:flex;flex-direction:column;background:#fff}.gcc__tabs{display:block;flex:none}.gcc__tabs .tabset-content{display:none}.gcc__tabs .nav-tabs-custom{margin-bottom:0;box-shadow:none}.gcc__content{flex:1;min-height:0;display:flex;flex-direction:column;gap:.75rem;padding:15px;overflow:hidden}.gcc__buttons{flex:none;margin-right:0;padding-bottom:0}.gcc__buttons .btn{margin-left:8px}.gcc__toolbar{display:flex;flex-wrap:wrap;align-items:flex-end;gap:.75rem;flex-shrink:0}.gcc__field{display:flex;flex-direction:column;gap:.25rem}.gcc__field label{font-size:.75rem;font-weight:600;color:#6c757d}.gcc__field input,.gcc__field select{min-width:9rem;padding:.35rem .5rem;border:1px solid #ced4da;border-radius:.25rem;font-size:.85rem}.gcc__message{padding:.5rem .75rem;background:#eef3f8;border-left:3px solid #4465C9;border-radius:.25rem;font-size:.85rem;flex-shrink:0}.gcc__body{flex:1;display:flex;gap:0;overflow:hidden;min-height:0;border:1px solid #e9ecef;border-radius:.25rem;background:#fff}.gcc__panel-hd{display:flex;align-items:center;justify-content:space-between;padding:.4rem .75rem;background:#f8f9fa;border-bottom:1px solid #e9ecef;flex-shrink:0}.gcc__panel-title{font-size:.8rem;font-weight:600;display:flex;align-items:center;gap:6px}.gcc__panel-label{font-size:.75rem;font-weight:600;color:#495057}.gcc__count{display:inline-flex;align-items:center;justify-content:center;min-width:20px;height:16px;padding:0 5px;background:#4465c91f;color:#4465c9;border-radius:20px;font-size:10px;font-weight:700}.gcc__badge{display:inline-flex;align-items:center;justify-content:center;min-width:18px;height:16px;padding:0 5px;background:#4465c91a;color:#4465c9;border-radius:20px;font-size:10px;font-weight:700}.gcc__badge--primary{background:#4465c9;color:#fff}.gcc__muted{color:#6c757d;font-size:.8rem}.gcc__fw-normal{font-weight:400}.gcc__configs{display:flex;flex-direction:column;flex:0 0 220px;border-right:1px solid #e9ecef;overflow:hidden}.gcc__list-scroll{flex:1;overflow:auto}.gcc__table{width:100%;border-collapse:collapse}.gcc__table th,.gcc__table td{padding:.35rem .6rem;border-bottom:1px solid #e9ecef;text-align:left;font-size:.78rem}.gcc__table th{font-weight:600;color:#495057;background:#f8f9fa;position:sticky;top:0;z-index:1}.gcc__config-row{cursor:pointer;transition:background .1s}.gcc__config-row:hover{background:#4465c90a}.gcc__config-row--selected{background:#4465c914;border-left:3px solid #4465C9}.gcc__config-row--selected td:first-child{padding-left:calc(.6rem - 3px)}.gcc__key{font-family:monospace;font-weight:600;color:#4465c9;font-size:.78rem}.gcc__sub{font-size:.7rem;font-weight:400;color:#6c757d;line-height:1.2;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.gcc__scope-badge{display:inline-block;padding:1px 5px;border-radius:20px;background:#4465c91a;color:#4465c9;font-size:9px;font-weight:700;text-transform:uppercase}.gcc__actions-cell{text-align:right;width:28px}.gcc__del-btn{background:none;border:none;color:#adb5bd;cursor:pointer;padding:2px 4px;border-radius:3px;font-size:.72rem;transition:color .1s}.gcc__del-btn:hover{color:#dc3545}.gcc__spinner{display:flex;align-items:center;gap:8px;padding:1rem .75rem;color:#6c757d;font-size:.8rem}.gcc__empty{padding:1.25rem .75rem;color:#6c757d;font-style:italic;font-size:.8rem}.gcc__editor{flex:1;display:flex;flex-direction:column;overflow:hidden;min-width:0}.gcc__editor-hd{display:flex;align-items:center;padding:.4rem .75rem;background:#f8f9fa;border-bottom:1px solid #e9ecef;flex-shrink:0}.gcc__loading{display:flex;align-items:center;gap:8px;padding:1.5rem 1rem;color:#6c757d;font-size:.85rem;flex-shrink:0}.gcc__spinner-icon{font-size:1rem}.gcc__panels{flex:1;display:flex;overflow:hidden;min-height:0}.gcc__groups{display:flex;flex-direction:column;flex:0 0 160px;border-right:1px solid #e9ecef;overflow:hidden}.gcc__group-list{list-style:none;margin:0;padding:0;flex:1;overflow-y:auto}.gcc__group-item{display:flex;align-items:center;justify-content:space-between;padding:.4rem .6rem;cursor:pointer;font-size:.78rem;border-bottom:1px solid #e9ecef;transition:background .1s}.gcc__group-item:hover{background:#4465c90a}.gcc__group-item--active{background:#4465c914;font-weight:600;color:#4465c9}.gcc__group-item--standard .gcc__group-item__name{color:#4465c9}.gcc__group-item--custom .gcc__group-item__name{color:#6b7fd4}.gcc__group-item__name{flex:1}.gcc__group-meta{display:flex;align-items:center;gap:3px}.gcc__browse{display:flex;flex-direction:column;flex:1;border-right:1px solid #e9ecef;overflow:hidden;min-width:0}.gcc__search{height:26px;padding:0 .5rem;border:1px solid #ced4da;border-radius:.2rem;font-size:.78rem;width:140px}.gcc__table-wrap{flex:1;overflow:auto}.gcc__table-wrap::-webkit-scrollbar{width:5px}.gcc__table-wrap::-webkit-scrollbar-track{background:transparent}.gcc__table-wrap::-webkit-scrollbar-thumb{background:#e9ecef;border-radius:3px}.gcc__browse-table{width:100%;border-collapse:collapse}.gcc__browse-table th,.gcc__browse-table td{padding:.3rem .5rem;border-bottom:1px solid #e9ecef;text-align:left;font-size:.78rem}.gcc__browse-table th{font-weight:600;color:#495057;background:#f8f9fa;position:sticky;top:0;z-index:1}.gcc__browse-row{cursor:pointer;transition:background .1s}.gcc__browse-row:hover{background:#4465c90a}.gcc__browse-row--selected{background:#4465c914}.gcc__browse-row--custom .gcc__col-key{color:#6b7fd4}.gcc__col-check{width:28px;text-align:center}.gcc__col-key{font-family:monospace;font-size:11px;font-weight:600;color:#4465c9}.gcc__browse-empty{padding:1rem .75rem;color:#6c757d;font-style:italic;font-size:.78rem}.gcc__selection{display:flex;flex-direction:column;flex:0 0 380px;overflow:hidden}.gcc__sel-legend{display:flex;align-items:center;padding:3px .5rem;background:#f8f9fa;border-bottom:1px solid #e9ecef;font-size:9px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:#6c757d;flex-shrink:0;gap:0}.gcc__sel-legend__drag{width:20px;flex-shrink:0}.gcc__sel-legend__pos{width:22px;flex-shrink:0;text-align:center}.gcc__sel-legend__code{width:150px;flex-shrink:0;padding-left:2px}.gcc__sel-legend__label{flex:1;min-width:0}.gcc__sel-legend__flag{width:36px;text-align:center;flex-shrink:0}.gcc__sel-legend__width{width:50px;flex-shrink:0;padding-left:2px}.gcc__sel-legend__remove{width:22px;flex-shrink:0}.gcc__sel-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;flex:1;color:#6c757d;gap:.5rem;font-size:.8rem}.gcc__sel-empty__icon{font-size:2rem;opacity:.3}.gcc__sel-empty p{margin:0}.gcc__sel-list{flex:1;overflow-y:auto}.gcc__sel-list::-webkit-scrollbar{width:4px}.gcc__sel-list::-webkit-scrollbar-track{background:transparent}.gcc__sel-list::-webkit-scrollbar-thumb{background:#e9ecef;border-radius:3px}.gcc__sel-item{display:flex;align-items:center;padding:4px .5rem;border-bottom:1px solid #e9ecef;background:#fff;-webkit-user-select:none;user-select:none;gap:0;transition:background .1s}.gcc__sel-item:hover{background:#4465c908}.gcc__sel-item.cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}.gcc__sel-item__placeholder{height:32px;background:#4465c90f;border:1px dashed #4465C9;border-radius:2px;flex:1}.gcc__sel-item__drag{width:20px;flex-shrink:0;color:#ced4da;cursor:grab;font-size:11px;display:flex;align-items:center;justify-content:center}.gcc__sel-item__drag:hover{color:#4465c9}.gcc__sel-item__drag:active{cursor:grabbing}.gcc__sel-item__pos{width:22px;flex-shrink:0;font-size:9px;color:#6c757d;text-align:center}.gcc__sel-item__code{width:150px;flex-shrink:0;display:flex;flex-direction:column;overflow:hidden;padding-left:2px}.gcc__sel-item__code--cf .gcc__sel-item__name{color:#6b7fd4}.gcc__sel-item__name{font-family:monospace;font-size:10px;font-weight:600;color:#4465c9;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.gcc__sel-item__label{flex:1;min-width:0;height:22px;padding:0 4px;border:1px solid transparent;border-radius:3px;font-size:11px;color:#343a40;background:transparent;outline:none;transition:border-color .1s,background .1s}.gcc__sel-item__label::placeholder{color:#6c757d;font-style:italic}.gcc__sel-item__label:hover{border-color:#d1d8de;background:#f8f9fa}.gcc__sel-item__label:focus{border-color:#4465c9;background:#fff}.gcc__sel-item__remove{width:22px;flex-shrink:0;background:none;border:none;color:#adb5bd;cursor:pointer;font-size:11px;padding:0;text-align:center;transition:color .1s}.gcc__sel-item__remove:hover{color:#dc3545}.gcc__sel-list.cdk-drop-list-dragging .gcc__sel-item:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}.gcc__flag{width:36px;flex-shrink:0;display:flex;align-items:center;justify-content:center;cursor:pointer;margin:0}.gcc__flag input[type=checkbox]{cursor:pointer}.gcc__item-width{width:46px;flex-shrink:0;padding:1px 3px;border:1px solid #ced4da;border-radius:3px;font-size:10px;text-align:right}.gcc__sel-footer{display:flex;align-items:center;justify-content:space-between;padding:.4rem .75rem;background:#f8f9fa;border-top:1px solid #e9ecef;flex-shrink:0}.gcc__sel-footer__info{font-size:.75rem;color:#6c757d;font-style:italic}.gcc__hint{display:flex;align-items:center;justify-content:center;flex:1;color:#6c757d;font-style:italic;font-size:.85rem}\n", ".home-page{font-family:Open sans,sans-serif;background:#fff;-webkit-font-smoothing:antialiased;height:100%;width:100%;padding:16px}.main-container{margin:0 50px}.main-container-modal{width:calc(100% - 50px);margin:10px 25px 0}.moyen-titre{font-weight:700;font-size:24px;color:#4d5a81;margin:8px 0;border-bottom:solid 1px #DBE4FF}.grand-titre{font-weight:700;font-size:28px;color:#4d5a81;margin:0 0 8px}.petit-titre{font-weight:700;font-size:16px;color:#4d5a81;margin:0 0 8px}.petit-titre.underlined{border-bottom:solid 1px #4D5A81}.paragraph{padding:0 15px}.paragraph-highlight{padding:5px 15px 0 12px;border-left:5px solid #8EA7F8;border-bottom:1px solid #DBE4FF;border-top:1px solid #DBE4FF;border-right:1px solid #DBE4FF;background-color:#f7faff}.highlight{background-color:#f7faff;border:1px solid #DBE4FF;border-radius:5px;padding:15px;color:#3c5dc4;margin:0 0 16px}.highlight p{margin-bottom:0}.highlight:before{position:relative;display:block;float:left;width:24px;height:24px;content:\" \";background-size:24px 24px;-webkit-background-size:24px 24px;background-image:url('data:image/svg+xml,<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"53.294\" height=\"50.629\" viewBox=\"0 0 53.294 50.629\">%0D%0A <path id=\"allerg\\e8ne\" d=\"M830.494,25.793l-5.814,6.783.727,8.963-8.721,1.938-4.6,7.752L803.847,47.6l-8.236,3.634-4.6-7.51-8.721-1.938.727-8.963L777.2,26.035l5.814-6.783-.727-8.963,8.721-1.938L795.61.6l8.236,3.634L812.083.6l4.6,7.752,8.721,1.938-.727,8.963Zm-24.467,2.422V13.681h-4.845V28.216Zm0,9.69V33.06h-4.845v4.845Z\" transform=\"translate(-777.2 -0.6)\"/>%0D%0A</svg>%0D%0A');background-repeat:no-repeat;margin:0 8px 24px 0;filter:invert(31%) sepia(51%) saturate(1323%) hue-rotate(199deg) brightness(99%) contrast(94%)}.notification{background-color:#dbe4ff;border:1px solid #C4D0F9;border-radius:5px;color:#4d5a81;margin:16px;padding:5px 15px;text-align:justify}.notification:before{position:relative;display:block;float:left;width:24px;height:24px;content:\" \";background-size:24px 24px;-webkit-background-size:24px 24px;background-image:url('data:image/svg+xml,<svg aria-hidden=\"true\" focusable=\"false\" data-prefix=\"fas\" data-icon=\"info-circle\" class=\"svg-inline--fa fa-info-circle fa-w-16\" role=\"img\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\"><path fill=\"currentColor\" d=\"M256 8C119.043 8 8 119.083 8 256c0 136.997 111.043 248 248 248s248-111.003 248-248C504 119.083 392.957 8 256 8zm0 110c23.196 0 42 18.804 42 42s-18.804 42-42 42-42-18.804-42-42 18.804-42 42-42zm56 254c0 6.627-5.373 12-12 12h-88c-6.627 0-12-5.373-12-12v-24c0-6.627 5.373-12 12-12h12v-64h-12c-6.627 0-12-5.373-12-12v-24c0-6.627 5.373-12 12-12h64c6.627 0 12 5.373 12 12v100h12c6.627 0 12 5.373 12 12v24z\"></path></svg>');background-repeat:no-repeat;margin:0 8px 0 0;filter:invert(31%) sepia(8%) saturate(2329%) hue-rotate(188deg) brightness(103%) contrast(85%)}.notification-text{padding:0 15px 0 30px;font-size:16px}.propertyGridform{height:100%;width:100%}.property-grid-tabset{height:100%}.property-grid-tab{height:100%;width:100%;padding:5px}.property-row-center{padding-top:21px}.property-section-content{display:grid;grid-template-columns:repeat(auto-fit,minmax(225px,1fr));align-items:flex-start;align-content:flex-start;gap:10px;margin:0 10px}.property-section-container{display:flex;flex-direction:column;background:#f7faff;border-radius:5px;border:1px solid #C1D0FD;padding-bottom:10px}.property-section-title{display:block;font-size:14px;background:#f7faff;border-bottom:none;padding:2px 0;margin:10px;line-height:24px;font-weight:700;border-bottom:solid 1px #C1D0FD;color:#4d5a81}.property-container{display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));gap:10px;padding:5px;height:100%;overflow:auto}.property-row{display:flex;flex-wrap:wrap;align-items:center;flex:25%;gap:10px}.property-label{color:#4465c9}.property-label span{padding-top:5px;display:inline-block;margin-right:5px}.property-label.invalid{color:red}.property-input{flex:2;min-width:200px}.checkbox-container{display:flex;align-items:center;gap:5px}.validation-error{color:red;font-size:.9rem}alg-presentation-profile-editor{display:block;height:100%}.pp-editor{height:100%}.pp-editor alg-tabset{display:block;height:100%}.pp-editor-tab{display:block;height:100%}.pp-editor-properties{height:100%;overflow:auto}.pp-editor-columns.gcc{padding:10px}.pp-editor-columns.gcc .gcc__panels{flex:1;min-height:0;border:1px solid #e9ecef}.pp-editor-columns.gcc{container-type:inline-size}.pp-editor-columns.gcc .gcc__browse,.pp-editor-columns.gcc .gcc__selection{flex:1 1 0;min-width:0;min-height:0}.pp-editor-columns.gcc .gcc__browse-row{cursor:pointer}@container (max-width: 700px){.pp-editor-columns .gcc__panels{flex-direction:column}.pp-editor-columns .gcc__browse{border-right:none;border-bottom:1px solid #e9ecef}}.pp-editor-add{width:28px;text-align:center;color:#999}.pp-editor-add-all{flex:none;margin-left:8px;padding:2px 8px;border:1px solid #ced4da;border-radius:3px;background:#fff;font-size:11px;cursor:pointer}.pp-editor-add-all:disabled{opacity:.5;cursor:default}.gcc__sel-legend__display{flex:none;width:112px;margin:0 4px;text-align:center}.pp-display{flex:none;display:inline-flex;align-items:center;gap:2px;width:112px;margin:0 4px}.pp-display__badge{flex:1;min-width:0;display:inline-flex;align-items:center;gap:4px;padding:1px 6px;border:1px solid #c5d3f0;border-radius:10px;background:#eef3fc;color:#35a;font-size:11px;white-space:nowrap;cursor:pointer}.pp-display__badge .fa{width:12px;text-align:center}.pp-display__badge--default{border-style:dashed;background:transparent;color:#999}.pp-display__text{overflow:hidden;text-overflow:ellipsis}.pp-display__edit{flex:none;width:22px;height:22px;padding:0;border:none;border-radius:3px;background:transparent;color:#777;cursor:pointer}.pp-display__edit:hover{background:#e9ecef;color:#333}.pp-editor-queries{padding:8px 12px;overflow:auto}.pp-editor-readonly{pointer-events:none;opacity:.7}\n"],
897
934
  dependencies: [
898
935
  {
@@ -982,6 +1019,16 @@ var PresentationProfileEditorComponent = class PresentationProfileEditorComponen
982
1019
  "ngIfElse"
983
1020
  ]
984
1021
  },
1022
+ {
1023
+ kind: "directive",
1024
+ type: i4$2.NgTemplateOutlet,
1025
+ selector: "[ngTemplateOutlet]",
1026
+ inputs: [
1027
+ "ngTemplateOutletContext",
1028
+ "ngTemplateOutlet",
1029
+ "ngTemplateOutletInjector"
1030
+ ]
1031
+ },
985
1032
  {
986
1033
  kind: "directive",
987
1034
  type: i1$3.DefaultValueAccessor,
@@ -1056,7 +1103,8 @@ var PresentationProfileEditorComponent = class PresentationProfileEditorComponen
1056
1103
  "filter",
1057
1104
  "sort",
1058
1105
  "embedded",
1059
- "section"
1106
+ "section",
1107
+ "panelFields"
1060
1108
  ]
1061
1109
  }
1062
1110
  ],
@@ -1077,7 +1125,7 @@ i0.ɵɵngDeclareClassMetadata({
1077
1125
  encapsulation: ViewEncapsulation.None,
1078
1126
  changeDetection: ChangeDetectionStrategy.Eager,
1079
1127
  standalone: false,
1080
- template: "<div class=\"pp-editor\">\r\n @if (entity) {\r\n <alg-tabset [showNavs]=\"true\" [pills]=\"false\" (onSelect)=\"activeTab = $event\">\r\n\r\n <!--Propriétés : table, libellé, finalité et portée du profil, avec les composants des formulaires-->\r\n <alg-tab title=\"Propriétés\" [active]=\"activeTab === 0\" [class.pp-editor-tab]=\"activeTab === 0\">\r\n <div class=\"property-container pp-editor-properties\">\r\n @for (section of sections; track section.Name) {\r\n <div class=\"property-section-container\">\r\n <div class=\"property-section-title\">{{ section.Name }}</div>\r\n <div class=\"property-section-content\">\r\n @for (field of section.FieldViewModels; track field.PropertyName) {\r\n <div class=\"property-row\" [hidden]=\"isFieldHidden(field)\">\r\n <alg-field [field]=\"field\" [form]=\"form\" [readonly]=\"isFieldReadonly(field)\"\r\n (propertyChanged)=\"onPropertyChanged($event)\">\r\n </alg-field>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n </alg-tab>\r\n\r\n <!--Colonnes : colonnes affichées par la grille, leur ordre et leurs libellés-->\r\n <alg-tab title=\"Colonnes\" [active]=\"activeTab === 1\" [class.pp-editor-tab]=\"activeTab === 1\">\r\n <div class=\"gcc pp-editor-columns\">\r\n <div *ngIf=\"isLoading\" class=\"gcc__loading\">\r\n <span class=\"gcc__spinner-icon fa fa-circle-o-notch fa-spin\"></span>\r\n Chargement des colonnes…\r\n </div>\r\n <div *ngIf=\"!isLoading && allItems.length === 0 && orderedSelection.length === 0\" class=\"gcc__hint\">\r\n Choisissez la table du profil dans l'onglet « Propriétés ».\r\n </div>\r\n <ng-container *ngIf=\"!isLoading && (allItems.length > 0 || orderedSelection.length > 0)\">\r\n <div class=\"gcc__panels\">\r\n\r\n <!-- ── Colonnes disponibles : celles de la table qui ne sont pas affichées ── -->\r\n <div class=\"gcc__browse\">\r\n <div class=\"gcc__panel-hd\">\r\n <span class=\"gcc__panel-label\">Colonnes disponibles</span>\r\n <span class=\"gcc__badge\">{{ filteredItems.length }}</span>\r\n <input class=\"gcc__search\" type=\"text\" placeholder=\"Rechercher…\"\r\n [(ngModel)]=\"searchText\" (ngModelChange)=\"onSearch()\">\r\n <button *ngIf=\"!readonly\" class=\"pp-editor-add-all\" type=\"button\" [disabled]=\"filteredItems.length === 0\"\r\n (click)=\"addAll()\" title=\"Afficher toutes les colonnes listées\">Tout ajouter</button>\r\n </div>\r\n\r\n <div class=\"gcc__table-wrap\">\r\n <table class=\"gcc__browse-table\">\r\n <tbody>\r\n <tr *ngFor=\"let item of filteredItems\"\r\n class=\"gcc__browse-row\"\r\n [class.gcc__browse-row--custom]=\"item.ColumnSourceType === 2\"\r\n title=\"Afficher cette colonne\"\r\n (click)=\"addItem(item)\">\r\n <td class=\"gcc__col-name\">\r\n <div class=\"gcc__col-key\">{{ item.ColumnKey }}</div>\r\n <div *ngIf=\"item.Label && item.Label !== item.ColumnKey\" class=\"gcc__sub\">{{ item.Label }}</div>\r\n </td>\r\n <td class=\"pp-editor-add\"><i *ngIf=\"!readonly\" class=\"fa fa-plus\"></i></td>\r\n </tr>\r\n <tr *ngIf=\"filteredItems.length === 0\">\r\n <td colspan=\"2\" class=\"gcc__browse-empty\">\r\n {{ searchText ? 'Aucune colonne trouvée' : 'Toutes les colonnes sont affichées' }}\r\n </td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n </div>\r\n </div>\r\n\r\n <!-- ── Panel 4: Ordered selection with admin flags ────────────── -->\r\n <div class=\"gcc__selection\">\r\n <div class=\"gcc__panel-hd\">\r\n <span class=\"gcc__panel-label\">Colonnes affichées</span>\r\n <span *ngIf=\"selectedCount > 0\" class=\"gcc__badge gcc__badge--primary\">{{ selectedCount }}</span>\r\n </div>\r\n\r\n <div *ngIf=\"orderedSelection.length > 0\" class=\"gcc__sel-legend\">\r\n <span class=\"gcc__sel-legend__drag\"></span>\r\n <span class=\"gcc__sel-legend__pos\">#</span>\r\n <span class=\"gcc__sel-legend__code\">Colonne</span>\r\n <span class=\"gcc__sel-legend__label\">Étiquette</span>\r\n <span class=\"gcc__sel-legend__display\">Affichage</span>\r\n <ng-container *ngIf=\"isPerimeter\">\r\n <span class=\"gcc__sel-legend__flag\">Aut.</span>\r\n </ng-container>\r\n <span class=\"gcc__sel-legend__flag\">Ver.</span>\r\n <span class=\"gcc__sel-legend__remove\"></span>\r\n </div>\r\n\r\n <div *ngIf=\"orderedSelection.length === 0\" class=\"gcc__sel-empty\">\r\n <span class=\"fa fa-columns gcc__sel-empty__icon\"></span>\r\n <p>Choisissez des colonnes parmi les colonnes disponibles</p>\r\n </div>\r\n\r\n <div *ngIf=\"orderedSelection.length > 0\"\r\n class=\"gcc__sel-list\"\r\n cdkDropList\r\n [cdkDropListData]=\"orderedSelection\"\r\n (cdkDropListDropped)=\"onDrop($event)\">\r\n\r\n <div *ngFor=\"let item of orderedSelection; let i = index\"\r\n class=\"gcc__sel-item\"\r\n cdkDrag [cdkDragDisabled]=\"readonly\"\r\n [cdkDragData]=\"item\">\r\n\r\n <div class=\"gcc__sel-item__placeholder\" *cdkDragPlaceholder></div>\r\n\r\n <span class=\"gcc__sel-item__drag\" cdkDragHandle>\r\n <i class=\"fa fa-bars\"></i>\r\n </span>\r\n\r\n <span class=\"gcc__sel-item__pos\">{{ i + 1 }}</span>\r\n\r\n <span class=\"gcc__sel-item__code\"\r\n [class.gcc__sel-item__code--cf]=\"item.ColumnSourceType === 2\"\r\n [title]=\"item.ColumnKey\">\r\n <span class=\"gcc__sel-item__name\">{{ item.ColumnKey }}</span>\r\n <span *ngIf=\"getCatalogLabel(item) !== item.ColumnKey\" class=\"gcc__sub\">{{ getCatalogLabel(item) }}</span>\r\n </span>\r\n\r\n <input class=\"gcc__sel-item__label\" type=\"text\"\r\n [placeholder]=\"getCatalogLabel(item)\"\r\n [(ngModel)]=\"item.Label\" (ngModelChange)=\"onColumnsChanged()\" [disabled]=\"readonly\"\r\n (click)=\"$event.stopPropagation()\"\r\n title=\"Étiquette personnalisée\">\r\n\r\n <!-- Affichage : indicateur du type, ouvre la fenêtre d'édition de la colonne -->\r\n <span class=\"pp-display\" (click)=\"$event.stopPropagation()\">\r\n <button type=\"button\" class=\"pp-display__badge\"\r\n [class.pp-display__badge--default]=\"!getDisplayType(item)\"\r\n [title]=\"describeDisplay(item)\"\r\n (click)=\"openColumn(item)\">\r\n <i class=\"fa fa-{{ getDisplayType(item)?.icon ?? 'magic' }}\"></i>\r\n <span class=\"pp-display__text\">{{ getDisplayType(item)?.short ?? 'Auto' }}</span>\r\n </button>\r\n <button type=\"button\" class=\"pp-display__edit\" title=\"Modifier la colonne (libellé, affichage...)\" (click)=\"openColumn(item)\">\r\n <i class=\"fa fa-sliders\"></i>\r\n </button>\r\n </span>\r\n\r\n <!-- Perimeter scope: allowed flag -->\r\n <ng-container *ngIf=\"isPerimeter\">\r\n <label class=\"gcc__flag\" (click)=\"$event.stopPropagation()\">\r\n <input type=\"checkbox\" [(ngModel)]=\"item.IsAllowed\" (ngModelChange)=\"onColumnsChanged()\" [disabled]=\"readonly\" title=\"Autorisé\">\r\n </label>\r\n </ng-container>\r\n\r\n <!-- Always: locked flag -->\r\n <label class=\"gcc__flag\" (click)=\"$event.stopPropagation()\">\r\n <input type=\"checkbox\" [(ngModel)]=\"item.IsLocked\" (ngModelChange)=\"onColumnsChanged()\" [disabled]=\"readonly\" title=\"Verrouillé\">\r\n </label>\r\n\r\n <button class=\"gcc__sel-item__remove\" type=\"button\"\r\n (click)=\"removeFromSelection(item); $event.stopPropagation()\"\r\n title=\"Retirer\">&#x2715;</button>\r\n </div>\r\n\r\n </div>\r\n\r\n <!-- Pied de la sélection -->\r\n <div class=\"gcc__sel-footer\">\r\n <span class=\"gcc__sel-footer__info\">\r\n <ng-container *ngIf=\"selectedCount > 0\">\r\n {{ selectedCount }} colonne(s) — glissez pour réordonner\r\n </ng-container>\r\n </span>\r\n </div>\r\n </div>\r\n\r\n </div><!-- /.gcc__panels -->\r\n </ng-container>\r\n </div>\r\n </alg-tab>\r\n\r\n <!--Tri : tri enregistré dans la vue, appliqué à la grille quand elle affiche la vue-->\r\n <alg-tab title=\"Tri\" [active]=\"activeTab === 2\" [class.pp-editor-tab]=\"activeTab === 2\">\r\n <div class=\"pp-editor-queries\">\r\n <alg-filter-editor [embedded]=\"true\" section=\"sort\" [columns]=\"filterColumns\" [sort]=\"viewSort\"\r\n [filter]=\"viewFilter\" [class.pp-editor-readonly]=\"readonly\"></alg-filter-editor>\r\n </div>\r\n </alg-tab>\r\n\r\n <!--Filtres : filtre enregistré dans la vue (groupes ET / OU), ajouté aux filtres de la grille-->\r\n <alg-tab title=\"Filtres\" [active]=\"activeTab === 3\" [class.pp-editor-tab]=\"activeTab === 3\">\r\n <div class=\"pp-editor-queries\">\r\n <alg-filter-editor [embedded]=\"true\" section=\"filters\" [columns]=\"filterColumns\" [sort]=\"viewSort\"\r\n [filter]=\"viewFilter\" [class.pp-editor-readonly]=\"readonly\"></alg-filter-editor>\r\n </div>\r\n </alg-tab>\r\n </alg-tabset>\r\n }\r\n</div>\r\n",
1128
+ template: "<div class=\"pp-editor\">\r\n @if (entity) {\r\n <alg-tabset [showNavs]=\"true\" [pills]=\"false\" (onSelect)=\"selectTab($event)\">\r\n\r\n <!--Propriétés : table, libellé, finalité et portée du profil, avec les composants des formulaires\r\n (masqué dans la fenêtre des vues d'une grille : la vue y est choisie à gauche)-->\r\n @if (showProperties) {\r\n <alg-tab title=\"Propriétés\" [active]=\"shownTab === 0\" [class.pp-editor-tab]=\"shownTab === 0\">\r\n <div class=\"property-container pp-editor-properties\">\r\n @for (section of sections; track section.Name) {\r\n <div class=\"property-section-container\">\r\n <div class=\"property-section-title\">{{ section.Name }}</div>\r\n <div class=\"property-section-content\">\r\n @for (field of section.FieldViewModels; track field.PropertyName) {\r\n <div class=\"property-row\" [hidden]=\"isFieldHidden(field)\">\r\n <alg-field [field]=\"field\" [form]=\"form\" [readonly]=\"isFieldReadonly(field)\"\r\n (propertyChanged)=\"onPropertyChanged($event)\">\r\n </alg-field>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n </alg-tab>\r\n }\r\n\r\n <!--Colonnes : colonnes affichées par la grille, leur ordre et leurs libellés-->\r\n <alg-tab title=\"Colonnes\" [active]=\"shownTab === 1\" [class.pp-editor-tab]=\"shownTab === 1\">\r\n <div class=\"gcc pp-editor-columns\">\r\n <div *ngIf=\"isLoading\" class=\"gcc__loading\">\r\n <span class=\"gcc__spinner-icon fa fa-circle-o-notch fa-spin\"></span>\r\n Chargement des colonnes…\r\n </div>\r\n <div *ngIf=\"!isLoading && allItems.length === 0 && orderedSelection.length === 0\" class=\"gcc__hint\">\r\n Choisissez la table du profil dans l'onglet « Propriétés ».\r\n </div>\r\n <ng-container *ngIf=\"!isLoading && (allItems.length > 0 || orderedSelection.length > 0)\">\r\n <div class=\"gcc__panels\">\r\n\r\n <!-- ── Colonnes disponibles : celles de la table qui ne sont pas affichées ── -->\r\n <div class=\"gcc__browse\">\r\n <div class=\"gcc__panel-hd\">\r\n <span class=\"gcc__panel-label\">Colonnes disponibles</span>\r\n <span class=\"gcc__badge\">{{ filteredItems.length }}</span>\r\n <input class=\"gcc__search\" type=\"text\" placeholder=\"Rechercher…\"\r\n [(ngModel)]=\"searchText\" (ngModelChange)=\"onSearch()\">\r\n <button *ngIf=\"!readonly\" class=\"pp-editor-add-all\" type=\"button\" [disabled]=\"filteredItems.length === 0\"\r\n (click)=\"addAll()\" title=\"Afficher toutes les colonnes listées\">Tout ajouter</button>\r\n </div>\r\n\r\n <div class=\"gcc__table-wrap\">\r\n <table class=\"gcc__browse-table\">\r\n <tbody>\r\n <tr *ngFor=\"let item of filteredItems\"\r\n class=\"gcc__browse-row\"\r\n [class.gcc__browse-row--custom]=\"item.ColumnSourceType === 2\"\r\n title=\"Afficher cette colonne\"\r\n (click)=\"addItem(item)\">\r\n <td class=\"gcc__col-name\">\r\n <div class=\"gcc__col-key\">{{ item.ColumnKey }}</div>\r\n <div *ngIf=\"item.Label && item.Label !== item.ColumnKey\" class=\"gcc__sub\">{{ item.Label }}</div>\r\n </td>\r\n <td class=\"pp-editor-add\"><i *ngIf=\"!readonly\" class=\"fa fa-plus\"></i></td>\r\n </tr>\r\n <tr *ngIf=\"filteredItems.length === 0\">\r\n <td colspan=\"2\" class=\"gcc__browse-empty\">\r\n {{ searchText ? 'Aucune colonne trouvée' : 'Toutes les colonnes sont affichées' }}\r\n </td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n </div>\r\n </div>\r\n\r\n <!-- ── Panel 4: Ordered selection with admin flags ────────────── -->\r\n <div class=\"gcc__selection\">\r\n <div class=\"gcc__panel-hd\">\r\n <span class=\"gcc__panel-label\">Colonnes affichées</span>\r\n <span *ngIf=\"selectedCount > 0\" class=\"gcc__badge gcc__badge--primary\">{{ selectedCount }}</span>\r\n </div>\r\n\r\n <div *ngIf=\"orderedSelection.length > 0\" class=\"gcc__sel-legend\">\r\n <span class=\"gcc__sel-legend__drag\"></span>\r\n <span class=\"gcc__sel-legend__pos\">#</span>\r\n <span class=\"gcc__sel-legend__code\">Colonne</span>\r\n <span class=\"gcc__sel-legend__label\">Étiquette</span>\r\n <span class=\"gcc__sel-legend__display\">Affichage</span>\r\n <ng-container *ngIf=\"isPerimeter\">\r\n <span class=\"gcc__sel-legend__flag\">Aut.</span>\r\n </ng-container>\r\n <span class=\"gcc__sel-legend__flag\">Ver.</span>\r\n <span class=\"gcc__sel-legend__remove\"></span>\r\n </div>\r\n\r\n <div *ngIf=\"orderedSelection.length === 0\" class=\"gcc__sel-empty\">\r\n <span class=\"fa fa-columns gcc__sel-empty__icon\"></span>\r\n <p>Choisissez des colonnes parmi les colonnes disponibles</p>\r\n </div>\r\n\r\n <div *ngIf=\"orderedSelection.length > 0\"\r\n class=\"gcc__sel-list\"\r\n cdkDropList\r\n [cdkDropListData]=\"orderedSelection\"\r\n (cdkDropListDropped)=\"onDrop($event)\">\r\n\r\n <div *ngFor=\"let item of orderedSelection; let i = index\"\r\n class=\"gcc__sel-item\"\r\n cdkDrag [cdkDragDisabled]=\"readonly\"\r\n [cdkDragData]=\"item\">\r\n\r\n <div class=\"gcc__sel-item__placeholder\" *cdkDragPlaceholder></div>\r\n\r\n <span class=\"gcc__sel-item__drag\" cdkDragHandle>\r\n <i class=\"fa fa-bars\"></i>\r\n </span>\r\n\r\n <span class=\"gcc__sel-item__pos\">{{ i + 1 }}</span>\r\n\r\n <span class=\"gcc__sel-item__code\"\r\n [class.gcc__sel-item__code--cf]=\"item.ColumnSourceType === 2\"\r\n [title]=\"item.ColumnKey\">\r\n <span class=\"gcc__sel-item__name\">{{ item.ColumnKey }}</span>\r\n <span *ngIf=\"getCatalogLabel(item) !== item.ColumnKey\" class=\"gcc__sub\">{{ getCatalogLabel(item) }}</span>\r\n </span>\r\n\r\n <input class=\"gcc__sel-item__label\" type=\"text\"\r\n [placeholder]=\"getCatalogLabel(item)\"\r\n [(ngModel)]=\"item.Label\" (ngModelChange)=\"onColumnsChanged()\" [disabled]=\"readonly\"\r\n (click)=\"$event.stopPropagation()\"\r\n title=\"Étiquette personnalisée\">\r\n\r\n <!-- Affichage : indicateur du type, ouvre la fenêtre d'édition de la colonne -->\r\n <span class=\"pp-display\" (click)=\"$event.stopPropagation()\">\r\n <button type=\"button\" class=\"pp-display__badge\"\r\n [class.pp-display__badge--default]=\"!getDisplayType(item)\"\r\n [title]=\"describeDisplay(item)\"\r\n (click)=\"openColumn(item)\">\r\n <i class=\"fa fa-{{ getDisplayType(item)?.icon ?? 'magic' }}\"></i>\r\n <span class=\"pp-display__text\">{{ getDisplayType(item)?.short ?? 'Auto' }}</span>\r\n </button>\r\n <button type=\"button\" class=\"pp-display__edit\" title=\"Modifier la colonne (libellé, affichage...)\" (click)=\"openColumn(item)\">\r\n <i class=\"fa fa-sliders\"></i>\r\n </button>\r\n </span>\r\n\r\n <!-- Perimeter scope: allowed flag -->\r\n <ng-container *ngIf=\"isPerimeter\">\r\n <label class=\"gcc__flag\" (click)=\"$event.stopPropagation()\">\r\n <input type=\"checkbox\" [(ngModel)]=\"item.IsAllowed\" (ngModelChange)=\"onColumnsChanged()\" [disabled]=\"readonly\" title=\"Autorisé\">\r\n </label>\r\n </ng-container>\r\n\r\n <!-- Always: locked flag -->\r\n <label class=\"gcc__flag\" (click)=\"$event.stopPropagation()\">\r\n <input type=\"checkbox\" [(ngModel)]=\"item.IsLocked\" (ngModelChange)=\"onColumnsChanged()\" [disabled]=\"readonly\" title=\"Verrouillé\">\r\n </label>\r\n\r\n <button class=\"gcc__sel-item__remove\" type=\"button\"\r\n (click)=\"removeFromSelection(item); $event.stopPropagation()\"\r\n title=\"Retirer\">&#x2715;</button>\r\n </div>\r\n\r\n </div>\r\n\r\n <!-- Pied de la sélection -->\r\n <div class=\"gcc__sel-footer\">\r\n <span class=\"gcc__sel-footer__info\">\r\n <ng-container *ngIf=\"selectedCount > 0\">\r\n {{ selectedCount }} colonne(s) — glissez pour réordonner\r\n </ng-container>\r\n </span>\r\n </div>\r\n </div>\r\n\r\n </div><!-- /.gcc__panels -->\r\n </ng-container>\r\n </div>\r\n </alg-tab>\r\n\r\n <!--Tri : tri enregistré dans la vue, appliqué à la grille quand elle affiche la vue-->\r\n <alg-tab title=\"Tri\" [active]=\"shownTab === 2\" [class.pp-editor-tab]=\"shownTab === 2\">\r\n <div class=\"pp-editor-queries\">\r\n <alg-filter-editor [embedded]=\"true\" section=\"sort\" [columns]=\"filterColumns\" [sort]=\"viewSort\"\r\n [filter]=\"viewFilter\" [class.pp-editor-readonly]=\"readonly\"></alg-filter-editor>\r\n </div>\r\n </alg-tab>\r\n\r\n <!--Filtres : filtre enregistré dans la vue (groupes ET / OU, valeurs du FilterPanel), ajouté aux filtres\r\n de la grille ; pas sur une vue par défaut, qui s'applique à tous les utilisateurs (lignes masquées pour tous)-->\r\n @if (!isDefaultView) {\r\n <alg-tab title=\"Filtres\" [active]=\"shownTab === 3\" [class.pp-editor-tab]=\"shownTab === 3\">\r\n <div class=\"pp-editor-queries\">\r\n <alg-filter-editor [embedded]=\"true\" section=\"filters\" [columns]=\"filterColumns\" [sort]=\"viewSort\"\r\n [filter]=\"viewFilter\" [panelFields]=\"panelFields\" [class.pp-editor-readonly]=\"readonly\"></alg-filter-editor>\r\n </div>\r\n </alg-tab>\r\n }\r\n\r\n <!--Carte : carte de la vue Grille (fenêtre des vues d'une grille), à défaut la carte par défaut-->\r\n @if (cardTemplate) {\r\n <alg-tab title=\"Carte\" [active]=\"shownTab === 4\" [class.pp-editor-tab]=\"shownTab === 4\">\r\n <ng-container [ngTemplateOutlet]=\"cardTemplate\"></ng-container>\r\n </alg-tab>\r\n }\r\n </alg-tabset>\r\n }\r\n</div>\r\n",
1081
1129
  styles: ["alg-pp-column{display:block;height:100%}.gcc{display:flex;flex-direction:column;height:100%;overflow:hidden;padding:10px;box-sizing:border-box}.gcc__form{flex:1;min-height:0;display:flex;flex-direction:column;background:#fff}.gcc__tabs{display:block;flex:none}.gcc__tabs .tabset-content{display:none}.gcc__tabs .nav-tabs-custom{margin-bottom:0;box-shadow:none}.gcc__content{flex:1;min-height:0;display:flex;flex-direction:column;gap:.75rem;padding:15px;overflow:hidden}.gcc__buttons{flex:none;margin-right:0;padding-bottom:0}.gcc__buttons .btn{margin-left:8px}.gcc__toolbar{display:flex;flex-wrap:wrap;align-items:flex-end;gap:.75rem;flex-shrink:0}.gcc__field{display:flex;flex-direction:column;gap:.25rem}.gcc__field label{font-size:.75rem;font-weight:600;color:#6c757d}.gcc__field input,.gcc__field select{min-width:9rem;padding:.35rem .5rem;border:1px solid #ced4da;border-radius:.25rem;font-size:.85rem}.gcc__message{padding:.5rem .75rem;background:#eef3f8;border-left:3px solid #4465C9;border-radius:.25rem;font-size:.85rem;flex-shrink:0}.gcc__body{flex:1;display:flex;gap:0;overflow:hidden;min-height:0;border:1px solid #e9ecef;border-radius:.25rem;background:#fff}.gcc__panel-hd{display:flex;align-items:center;justify-content:space-between;padding:.4rem .75rem;background:#f8f9fa;border-bottom:1px solid #e9ecef;flex-shrink:0}.gcc__panel-title{font-size:.8rem;font-weight:600;display:flex;align-items:center;gap:6px}.gcc__panel-label{font-size:.75rem;font-weight:600;color:#495057}.gcc__count{display:inline-flex;align-items:center;justify-content:center;min-width:20px;height:16px;padding:0 5px;background:#4465c91f;color:#4465c9;border-radius:20px;font-size:10px;font-weight:700}.gcc__badge{display:inline-flex;align-items:center;justify-content:center;min-width:18px;height:16px;padding:0 5px;background:#4465c91a;color:#4465c9;border-radius:20px;font-size:10px;font-weight:700}.gcc__badge--primary{background:#4465c9;color:#fff}.gcc__muted{color:#6c757d;font-size:.8rem}.gcc__fw-normal{font-weight:400}.gcc__configs{display:flex;flex-direction:column;flex:0 0 220px;border-right:1px solid #e9ecef;overflow:hidden}.gcc__list-scroll{flex:1;overflow:auto}.gcc__table{width:100%;border-collapse:collapse}.gcc__table th,.gcc__table td{padding:.35rem .6rem;border-bottom:1px solid #e9ecef;text-align:left;font-size:.78rem}.gcc__table th{font-weight:600;color:#495057;background:#f8f9fa;position:sticky;top:0;z-index:1}.gcc__config-row{cursor:pointer;transition:background .1s}.gcc__config-row:hover{background:#4465c90a}.gcc__config-row--selected{background:#4465c914;border-left:3px solid #4465C9}.gcc__config-row--selected td:first-child{padding-left:calc(.6rem - 3px)}.gcc__key{font-family:monospace;font-weight:600;color:#4465c9;font-size:.78rem}.gcc__sub{font-size:.7rem;font-weight:400;color:#6c757d;line-height:1.2;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.gcc__scope-badge{display:inline-block;padding:1px 5px;border-radius:20px;background:#4465c91a;color:#4465c9;font-size:9px;font-weight:700;text-transform:uppercase}.gcc__actions-cell{text-align:right;width:28px}.gcc__del-btn{background:none;border:none;color:#adb5bd;cursor:pointer;padding:2px 4px;border-radius:3px;font-size:.72rem;transition:color .1s}.gcc__del-btn:hover{color:#dc3545}.gcc__spinner{display:flex;align-items:center;gap:8px;padding:1rem .75rem;color:#6c757d;font-size:.8rem}.gcc__empty{padding:1.25rem .75rem;color:#6c757d;font-style:italic;font-size:.8rem}.gcc__editor{flex:1;display:flex;flex-direction:column;overflow:hidden;min-width:0}.gcc__editor-hd{display:flex;align-items:center;padding:.4rem .75rem;background:#f8f9fa;border-bottom:1px solid #e9ecef;flex-shrink:0}.gcc__loading{display:flex;align-items:center;gap:8px;padding:1.5rem 1rem;color:#6c757d;font-size:.85rem;flex-shrink:0}.gcc__spinner-icon{font-size:1rem}.gcc__panels{flex:1;display:flex;overflow:hidden;min-height:0}.gcc__groups{display:flex;flex-direction:column;flex:0 0 160px;border-right:1px solid #e9ecef;overflow:hidden}.gcc__group-list{list-style:none;margin:0;padding:0;flex:1;overflow-y:auto}.gcc__group-item{display:flex;align-items:center;justify-content:space-between;padding:.4rem .6rem;cursor:pointer;font-size:.78rem;border-bottom:1px solid #e9ecef;transition:background .1s}.gcc__group-item:hover{background:#4465c90a}.gcc__group-item--active{background:#4465c914;font-weight:600;color:#4465c9}.gcc__group-item--standard .gcc__group-item__name{color:#4465c9}.gcc__group-item--custom .gcc__group-item__name{color:#6b7fd4}.gcc__group-item__name{flex:1}.gcc__group-meta{display:flex;align-items:center;gap:3px}.gcc__browse{display:flex;flex-direction:column;flex:1;border-right:1px solid #e9ecef;overflow:hidden;min-width:0}.gcc__search{height:26px;padding:0 .5rem;border:1px solid #ced4da;border-radius:.2rem;font-size:.78rem;width:140px}.gcc__table-wrap{flex:1;overflow:auto}.gcc__table-wrap::-webkit-scrollbar{width:5px}.gcc__table-wrap::-webkit-scrollbar-track{background:transparent}.gcc__table-wrap::-webkit-scrollbar-thumb{background:#e9ecef;border-radius:3px}.gcc__browse-table{width:100%;border-collapse:collapse}.gcc__browse-table th,.gcc__browse-table td{padding:.3rem .5rem;border-bottom:1px solid #e9ecef;text-align:left;font-size:.78rem}.gcc__browse-table th{font-weight:600;color:#495057;background:#f8f9fa;position:sticky;top:0;z-index:1}.gcc__browse-row{cursor:pointer;transition:background .1s}.gcc__browse-row:hover{background:#4465c90a}.gcc__browse-row--selected{background:#4465c914}.gcc__browse-row--custom .gcc__col-key{color:#6b7fd4}.gcc__col-check{width:28px;text-align:center}.gcc__col-key{font-family:monospace;font-size:11px;font-weight:600;color:#4465c9}.gcc__browse-empty{padding:1rem .75rem;color:#6c757d;font-style:italic;font-size:.78rem}.gcc__selection{display:flex;flex-direction:column;flex:0 0 380px;overflow:hidden}.gcc__sel-legend{display:flex;align-items:center;padding:3px .5rem;background:#f8f9fa;border-bottom:1px solid #e9ecef;font-size:9px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:#6c757d;flex-shrink:0;gap:0}.gcc__sel-legend__drag{width:20px;flex-shrink:0}.gcc__sel-legend__pos{width:22px;flex-shrink:0;text-align:center}.gcc__sel-legend__code{width:150px;flex-shrink:0;padding-left:2px}.gcc__sel-legend__label{flex:1;min-width:0}.gcc__sel-legend__flag{width:36px;text-align:center;flex-shrink:0}.gcc__sel-legend__width{width:50px;flex-shrink:0;padding-left:2px}.gcc__sel-legend__remove{width:22px;flex-shrink:0}.gcc__sel-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;flex:1;color:#6c757d;gap:.5rem;font-size:.8rem}.gcc__sel-empty__icon{font-size:2rem;opacity:.3}.gcc__sel-empty p{margin:0}.gcc__sel-list{flex:1;overflow-y:auto}.gcc__sel-list::-webkit-scrollbar{width:4px}.gcc__sel-list::-webkit-scrollbar-track{background:transparent}.gcc__sel-list::-webkit-scrollbar-thumb{background:#e9ecef;border-radius:3px}.gcc__sel-item{display:flex;align-items:center;padding:4px .5rem;border-bottom:1px solid #e9ecef;background:#fff;-webkit-user-select:none;user-select:none;gap:0;transition:background .1s}.gcc__sel-item:hover{background:#4465c908}.gcc__sel-item.cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}.gcc__sel-item__placeholder{height:32px;background:#4465c90f;border:1px dashed #4465C9;border-radius:2px;flex:1}.gcc__sel-item__drag{width:20px;flex-shrink:0;color:#ced4da;cursor:grab;font-size:11px;display:flex;align-items:center;justify-content:center}.gcc__sel-item__drag:hover{color:#4465c9}.gcc__sel-item__drag:active{cursor:grabbing}.gcc__sel-item__pos{width:22px;flex-shrink:0;font-size:9px;color:#6c757d;text-align:center}.gcc__sel-item__code{width:150px;flex-shrink:0;display:flex;flex-direction:column;overflow:hidden;padding-left:2px}.gcc__sel-item__code--cf .gcc__sel-item__name{color:#6b7fd4}.gcc__sel-item__name{font-family:monospace;font-size:10px;font-weight:600;color:#4465c9;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.gcc__sel-item__label{flex:1;min-width:0;height:22px;padding:0 4px;border:1px solid transparent;border-radius:3px;font-size:11px;color:#343a40;background:transparent;outline:none;transition:border-color .1s,background .1s}.gcc__sel-item__label::placeholder{color:#6c757d;font-style:italic}.gcc__sel-item__label:hover{border-color:#d1d8de;background:#f8f9fa}.gcc__sel-item__label:focus{border-color:#4465c9;background:#fff}.gcc__sel-item__remove{width:22px;flex-shrink:0;background:none;border:none;color:#adb5bd;cursor:pointer;font-size:11px;padding:0;text-align:center;transition:color .1s}.gcc__sel-item__remove:hover{color:#dc3545}.gcc__sel-list.cdk-drop-list-dragging .gcc__sel-item:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}.gcc__flag{width:36px;flex-shrink:0;display:flex;align-items:center;justify-content:center;cursor:pointer;margin:0}.gcc__flag input[type=checkbox]{cursor:pointer}.gcc__item-width{width:46px;flex-shrink:0;padding:1px 3px;border:1px solid #ced4da;border-radius:3px;font-size:10px;text-align:right}.gcc__sel-footer{display:flex;align-items:center;justify-content:space-between;padding:.4rem .75rem;background:#f8f9fa;border-top:1px solid #e9ecef;flex-shrink:0}.gcc__sel-footer__info{font-size:.75rem;color:#6c757d;font-style:italic}.gcc__hint{display:flex;align-items:center;justify-content:center;flex:1;color:#6c757d;font-style:italic;font-size:.85rem}\n", ".home-page{font-family:Open sans,sans-serif;background:#fff;-webkit-font-smoothing:antialiased;height:100%;width:100%;padding:16px}.main-container{margin:0 50px}.main-container-modal{width:calc(100% - 50px);margin:10px 25px 0}.moyen-titre{font-weight:700;font-size:24px;color:#4d5a81;margin:8px 0;border-bottom:solid 1px #DBE4FF}.grand-titre{font-weight:700;font-size:28px;color:#4d5a81;margin:0 0 8px}.petit-titre{font-weight:700;font-size:16px;color:#4d5a81;margin:0 0 8px}.petit-titre.underlined{border-bottom:solid 1px #4D5A81}.paragraph{padding:0 15px}.paragraph-highlight{padding:5px 15px 0 12px;border-left:5px solid #8EA7F8;border-bottom:1px solid #DBE4FF;border-top:1px solid #DBE4FF;border-right:1px solid #DBE4FF;background-color:#f7faff}.highlight{background-color:#f7faff;border:1px solid #DBE4FF;border-radius:5px;padding:15px;color:#3c5dc4;margin:0 0 16px}.highlight p{margin-bottom:0}.highlight:before{position:relative;display:block;float:left;width:24px;height:24px;content:\" \";background-size:24px 24px;-webkit-background-size:24px 24px;background-image:url('data:image/svg+xml,<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"53.294\" height=\"50.629\" viewBox=\"0 0 53.294 50.629\">%0D%0A <path id=\"allerg\\e8ne\" d=\"M830.494,25.793l-5.814,6.783.727,8.963-8.721,1.938-4.6,7.752L803.847,47.6l-8.236,3.634-4.6-7.51-8.721-1.938.727-8.963L777.2,26.035l5.814-6.783-.727-8.963,8.721-1.938L795.61.6l8.236,3.634L812.083.6l4.6,7.752,8.721,1.938-.727,8.963Zm-24.467,2.422V13.681h-4.845V28.216Zm0,9.69V33.06h-4.845v4.845Z\" transform=\"translate(-777.2 -0.6)\"/>%0D%0A</svg>%0D%0A');background-repeat:no-repeat;margin:0 8px 24px 0;filter:invert(31%) sepia(51%) saturate(1323%) hue-rotate(199deg) brightness(99%) contrast(94%)}.notification{background-color:#dbe4ff;border:1px solid #C4D0F9;border-radius:5px;color:#4d5a81;margin:16px;padding:5px 15px;text-align:justify}.notification:before{position:relative;display:block;float:left;width:24px;height:24px;content:\" \";background-size:24px 24px;-webkit-background-size:24px 24px;background-image:url('data:image/svg+xml,<svg aria-hidden=\"true\" focusable=\"false\" data-prefix=\"fas\" data-icon=\"info-circle\" class=\"svg-inline--fa fa-info-circle fa-w-16\" role=\"img\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\"><path fill=\"currentColor\" d=\"M256 8C119.043 8 8 119.083 8 256c0 136.997 111.043 248 248 248s248-111.003 248-248C504 119.083 392.957 8 256 8zm0 110c23.196 0 42 18.804 42 42s-18.804 42-42 42-42-18.804-42-42 18.804-42 42-42zm56 254c0 6.627-5.373 12-12 12h-88c-6.627 0-12-5.373-12-12v-24c0-6.627 5.373-12 12-12h12v-64h-12c-6.627 0-12-5.373-12-12v-24c0-6.627 5.373-12 12-12h64c6.627 0 12 5.373 12 12v100h12c6.627 0 12 5.373 12 12v24z\"></path></svg>');background-repeat:no-repeat;margin:0 8px 0 0;filter:invert(31%) sepia(8%) saturate(2329%) hue-rotate(188deg) brightness(103%) contrast(85%)}.notification-text{padding:0 15px 0 30px;font-size:16px}.propertyGridform{height:100%;width:100%}.property-grid-tabset{height:100%}.property-grid-tab{height:100%;width:100%;padding:5px}.property-row-center{padding-top:21px}.property-section-content{display:grid;grid-template-columns:repeat(auto-fit,minmax(225px,1fr));align-items:flex-start;align-content:flex-start;gap:10px;margin:0 10px}.property-section-container{display:flex;flex-direction:column;background:#f7faff;border-radius:5px;border:1px solid #C1D0FD;padding-bottom:10px}.property-section-title{display:block;font-size:14px;background:#f7faff;border-bottom:none;padding:2px 0;margin:10px;line-height:24px;font-weight:700;border-bottom:solid 1px #C1D0FD;color:#4d5a81}.property-container{display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));gap:10px;padding:5px;height:100%;overflow:auto}.property-row{display:flex;flex-wrap:wrap;align-items:center;flex:25%;gap:10px}.property-label{color:#4465c9}.property-label span{padding-top:5px;display:inline-block;margin-right:5px}.property-label.invalid{color:red}.property-input{flex:2;min-width:200px}.checkbox-container{display:flex;align-items:center;gap:5px}.validation-error{color:red;font-size:.9rem}alg-presentation-profile-editor{display:block;height:100%}.pp-editor{height:100%}.pp-editor alg-tabset{display:block;height:100%}.pp-editor-tab{display:block;height:100%}.pp-editor-properties{height:100%;overflow:auto}.pp-editor-columns.gcc{padding:10px}.pp-editor-columns.gcc .gcc__panels{flex:1;min-height:0;border:1px solid #e9ecef}.pp-editor-columns.gcc{container-type:inline-size}.pp-editor-columns.gcc .gcc__browse,.pp-editor-columns.gcc .gcc__selection{flex:1 1 0;min-width:0;min-height:0}.pp-editor-columns.gcc .gcc__browse-row{cursor:pointer}@container (max-width: 700px){.pp-editor-columns .gcc__panels{flex-direction:column}.pp-editor-columns .gcc__browse{border-right:none;border-bottom:1px solid #e9ecef}}.pp-editor-add{width:28px;text-align:center;color:#999}.pp-editor-add-all{flex:none;margin-left:8px;padding:2px 8px;border:1px solid #ced4da;border-radius:3px;background:#fff;font-size:11px;cursor:pointer}.pp-editor-add-all:disabled{opacity:.5;cursor:default}.gcc__sel-legend__display{flex:none;width:112px;margin:0 4px;text-align:center}.pp-display{flex:none;display:inline-flex;align-items:center;gap:2px;width:112px;margin:0 4px}.pp-display__badge{flex:1;min-width:0;display:inline-flex;align-items:center;gap:4px;padding:1px 6px;border:1px solid #c5d3f0;border-radius:10px;background:#eef3fc;color:#35a;font-size:11px;white-space:nowrap;cursor:pointer}.pp-display__badge .fa{width:12px;text-align:center}.pp-display__badge--default{border-style:dashed;background:transparent;color:#999}.pp-display__text{overflow:hidden;text-overflow:ellipsis}.pp-display__edit{flex:none;width:22px;height:22px;padding:0;border:none;border-radius:3px;background:transparent;color:#777;cursor:pointer}.pp-display__edit:hover{background:#e9ecef;color:#333}.pp-editor-queries{padding:8px 12px;overflow:auto}.pp-editor-readonly{pointer-events:none;opacity:.7}\n"]
1082
1130
  }]
1083
1131
  }],
@@ -1086,8 +1134,21 @@ i0.ɵɵngDeclareClassMetadata({
1086
1134
  { type: i1$2.ValidationService },
1087
1135
  { type: i2$2.PresentationProfileItemDataService },
1088
1136
  { type: i1$2.DflatModalService }
1089
- ]
1137
+ ],
1138
+ propDecorators: {
1139
+ cardTemplate: [{ type: Input }],
1140
+ panelFields: [{ type: Input }],
1141
+ showProperties: [{ type: Input }]
1142
+ }
1090
1143
  });
1144
+ const CardSlotNames = [
1145
+ "title",
1146
+ "text",
1147
+ "detail",
1148
+ "badge",
1149
+ "image"
1150
+ ];
1151
+ const EntityImageKey = "@EntityImage";
1091
1152
  var PresentationProfileResolver = class PresentationProfileResolver {
1092
1153
  constructor(itemData) {
1093
1154
  this.itemData = itemData;
@@ -1179,6 +1240,34 @@ var PresentationProfileService = class PresentationProfileService {
1179
1240
  sort: "",
1180
1241
  filter: ""
1181
1242
  };
1243
+ this.cardSlotList = [
1244
+ {
1245
+ name: "title",
1246
+ label: "Titre"
1247
+ },
1248
+ {
1249
+ name: "text",
1250
+ label: "Texte"
1251
+ },
1252
+ {
1253
+ name: "detail",
1254
+ label: "Détail"
1255
+ },
1256
+ {
1257
+ name: "badge",
1258
+ label: "Badge"
1259
+ },
1260
+ {
1261
+ name: "image",
1262
+ label: "Image"
1263
+ }
1264
+ ];
1265
+ this.cardOptions = [];
1266
+ this.cardImageOptions = [];
1267
+ this.cardSlots = PresentationProfileService.emptySlots();
1268
+ this.loadedCardSlots = "";
1269
+ this.usesDefaultCard = true;
1270
+ this.cardLabel = "";
1182
1271
  this.confirmed$ = new Subject();
1183
1272
  this.cancelled$ = new Subject();
1184
1273
  this.destroy$ = new Subject();
@@ -1224,6 +1313,100 @@ var PresentationProfileService = class PresentationProfileService {
1224
1313
  type: typeOf(i.ColumnDisplayType)
1225
1314
  }).sort((a, b) => a.label.localeCompare(b.label, "fr", { sensitivity: "base" }));
1226
1315
  }
1316
+ get hasCardChanges() {
1317
+ return JSON.stringify(this.cardSlots) !== this.loadedCardSlots;
1318
+ }
1319
+ static emptySlots() {
1320
+ return {
1321
+ title: "",
1322
+ text: "",
1323
+ detail: "",
1324
+ badge: "",
1325
+ image: ""
1326
+ };
1327
+ }
1328
+ buildCardOptions(catalog) {
1329
+ const byLabel = (a, b) => a.label.localeCompare(b.label, "fr", { sensitivity: "base" });
1330
+ const optionLabel = (i) => i.Label && i.Label !== i.ColumnKey ? `${i.Label} (${i.ColumnKey})` : i.ColumnKey;
1331
+ this.cardOptions = catalog.map((i) => ({
1332
+ key: i.ColumnKey,
1333
+ label: optionLabel(i)
1334
+ })).sort(byLabel);
1335
+ const imageTypes = [
1336
+ 7,
1337
+ 8,
1338
+ 9,
1339
+ 10
1340
+ ];
1341
+ this.cardImageOptions = [{
1342
+ key: EntityImageKey,
1343
+ label: "Image de l'élément"
1344
+ }, ...catalog.filter((i) => imageTypes.includes(i.ColumnDisplayType ?? -1)).map((i) => ({
1345
+ key: i.ColumnKey,
1346
+ label: optionLabel(i)
1347
+ })).sort(byLabel)];
1348
+ }
1349
+ loadCard(view) {
1350
+ this.cardSlots = PresentationProfileService.emptySlots();
1351
+ this.loadedCardSlots = JSON.stringify(this.cardSlots);
1352
+ this.usesDefaultCard = true;
1353
+ this.cardLabel = "";
1354
+ if (this.purpose !== PresentationProfilePurposes.Grid) return;
1355
+ this.data.getCardView({
1356
+ MetaEntityKey: this.config.metaEntityKey,
1357
+ PresentationProfileId: view.id
1358
+ }).pipe(catchError(() => of(null)), takeUntil$1(this.destroy$)).subscribe((result) => {
1359
+ if (this.selectedView?.id !== view.id) return;
1360
+ const card = result?.Card;
1361
+ const slots = PresentationProfileService.emptySlots();
1362
+ for (const item of card?.Items ?? []) {
1363
+ const slot = CardSlotNames[item.CardSlot ?? -1];
1364
+ if (slot) slots[slot] = item.ColumnSourceType === 3 ? EntityImageKey : item.ColumnKey ?? "";
1365
+ }
1366
+ this.cardSlots = slots;
1367
+ this.loadedCardSlots = JSON.stringify(slots);
1368
+ this.usesDefaultCard = !card || card.PresentationProfileScope === PresentationProfileScopes.Default;
1369
+ this.cardLabel = card?.Label ?? "";
1370
+ });
1371
+ }
1372
+ resetCard() {
1373
+ this.cardSlots = PresentationProfileService.emptySlots();
1374
+ }
1375
+ cardItems() {
1376
+ const byKey = new Map(this.allColumns.map((i) => [i.ColumnKey, i]));
1377
+ const items = [];
1378
+ CardSlotNames.forEach((slot, index) => {
1379
+ const key = this.cardSlots[slot];
1380
+ if (!key) return;
1381
+ if (key === "@EntityImage") items.push({
1382
+ ColumnKey: EntityImageKey,
1383
+ Label: "Image de l'élément",
1384
+ ColumnSourceType: 3,
1385
+ CardSlot: index
1386
+ });
1387
+ else if (byKey.has(key)) items.push({
1388
+ ...byKey.get(key),
1389
+ Id: void 0,
1390
+ PresentationProfileId: void 0,
1391
+ CardSlot: index
1392
+ });
1393
+ });
1394
+ return items;
1395
+ }
1396
+ saveCard(gridViewId) {
1397
+ if (gridViewId == null || !this.hasCardChanges || this.purpose !== PresentationProfilePurposes.Grid) return of(gridViewId);
1398
+ return this.data.saveGridCard({
1399
+ GridViewId: gridViewId,
1400
+ Profile: {
1401
+ MetaEntityKey: this.config.metaEntityKey,
1402
+ PresentationProfilePurpose: PresentationProfilePurposes.Card,
1403
+ Items: this.cardItems()
1404
+ }
1405
+ }).pipe(map$1((res) => {
1406
+ if (res?.Success === false) throw new Error(res.ErrorMessage ?? "L'enregistrement de la carte a échoué");
1407
+ return res?.Id ?? gridViewId;
1408
+ }));
1409
+ }
1227
1410
  get purpose() {
1228
1411
  return this.config?.purpose ?? PresentationProfilePurposes.Grid;
1229
1412
  }
@@ -1278,6 +1461,7 @@ var PresentationProfileService = class PresentationProfileService {
1278
1461
  this.naturalLabelByKey = new Map(catalog.map((i) => [i.ColumnKey, i.Label ?? i.ColumnKey]));
1279
1462
  this.allColumns = catalog;
1280
1463
  this.buildFilterColumns(catalog);
1464
+ this.buildCardOptions(catalog);
1281
1465
  this.applyViews(views);
1282
1466
  this.applyFilter();
1283
1467
  const current = this.views.find((v) => v.id === this.config.viewId) ?? this.views.find((v) => v.isCurrent) ?? this.views[0] ?? null;
@@ -1318,6 +1502,7 @@ var PresentationProfileService = class PresentationProfileService {
1318
1502
  this.message = null;
1319
1503
  this.isLoading = true;
1320
1504
  this.loadQueries(view);
1505
+ this.loadCard(view);
1321
1506
  this.itemData.getPresentationProfileItems(view.id).pipe(map$1((items) => items ?? []), catchError(() => of([])), takeUntil$1(this.destroy$)).subscribe((items) => {
1322
1507
  const catalogByKey = new Map(this.allColumns.map((i) => [i.ColumnKey, i]));
1323
1508
  const columns = [...items].filter((i) => !!i.ColumnKey && catalogByKey.has(i.ColumnKey)).sort((a, b) => (a.DisplayOrder ?? 0) - (b.DisplayOrder ?? 0)).map((i) => ({
@@ -1333,6 +1518,22 @@ var PresentationProfileService = class PresentationProfileService {
1333
1518
  this.selectedIds = new Set(cols.map((c) => c.ColumnKey ?? ""));
1334
1519
  this.loadedItemIds = loadedIds;
1335
1520
  }
1521
+ createView() {
1522
+ const source = this.selectedView ?? this.views.find((v) => v.isDefault) ?? null;
1523
+ if (!source) return;
1524
+ const queries = source.isCurrent ? this.config.gridQueries : void 0;
1525
+ this.runViewAction(this.data.duplicateView({
1526
+ PresentationProfileId: source.id,
1527
+ Label: PresentationProfileService.NewViewLabel,
1528
+ ...queries ? {
1529
+ SortQuery: queries.sortQuery,
1530
+ FilterQuery: queries.filterQuery
1531
+ } : {}
1532
+ }), (id) => id);
1533
+ }
1534
+ static {
1535
+ this.NewViewLabel = "Nouvelle vue";
1536
+ }
1336
1537
  duplicateView(view) {
1337
1538
  this.runViewAction(this.data.duplicateView({ PresentationProfileId: view.id }), (id) => id);
1338
1539
  }
@@ -1464,15 +1665,18 @@ var PresentationProfileService = class PresentationProfileService {
1464
1665
  };
1465
1666
  this.isSaving = true;
1466
1667
  this.message = null;
1467
- const done = (id) => {
1468
- this.isSaving = false;
1469
- result.profileId = id;
1470
- this.confirmed$.next(result);
1471
- };
1472
1668
  const failed = (message) => {
1473
1669
  this.isSaving = false;
1474
1670
  this.message = message ?? "L'enregistrement de la vue a échoué";
1475
1671
  };
1672
+ const done = (id) => this.saveCard(id).subscribe({
1673
+ next: (gridId) => {
1674
+ this.isSaving = false;
1675
+ result.profileId = gridId;
1676
+ this.confirmed$.next(result);
1677
+ },
1678
+ error: (err) => failed(err?.message)
1679
+ });
1476
1680
  if (view && !this.hasChanges) {
1477
1681
  this.data.selectView({
1478
1682
  MetaEntityKey: this.config.metaEntityKey,
@@ -1566,6 +1770,9 @@ var PresentationProfileComponent = class PresentationProfileComponent {
1566
1770
  this.editor = this.editorHost.createComponent(PresentationProfileEditorComponent);
1567
1771
  this.editor.setInput("entityKey", SystemEntityKeys.PresentationProfile);
1568
1772
  this.editor.setInput("guid", this.guid);
1773
+ this.editor.setInput("showProperties", false);
1774
+ if ((this.config?.purpose ?? PresentationProfilePurposes.Grid) === PresentationProfilePurposes.Grid) this.editor.setInput("cardTemplate", this.cardTab);
1775
+ this.editor.setInput("panelFields", this.config?.panelFields ?? []);
1569
1776
  }
1570
1777
  ngDoCheck() {
1571
1778
  const view = this.svc.selectedView;
@@ -1618,10 +1825,16 @@ var PresentationProfileComponent = class PresentationProfileComponent {
1618
1825
  descendants: true,
1619
1826
  read: ViewContainerRef,
1620
1827
  static: true
1828
+ }, {
1829
+ propertyName: "cardTab",
1830
+ first: true,
1831
+ predicate: ["cardTab"],
1832
+ descendants: true,
1833
+ static: true
1621
1834
  }],
1622
1835
  ngImport: i0,
1623
- template: "<!-- ── Header ─────────────────────────────────────────────────────────────── -->\r\n<div class=\"csl-header\">\r\n <div class=\"csl-header__left\">\r\n <h4 class=\"csl-title\">{{ svc.config?.title || 'Sélection des colonnes' }}</h4>\r\n </div>\r\n @if (!svc.isEmbedded) {\r\n <button class=\"csl-icon-btn\" type=\"button\" (click)=\"svc.cancel()\" aria-label=\"Fermer\">&#x2715;</button>\r\n }\r\n</div>\r\n\r\n<!-- ── Body : vues à gauche, éditeur standard de la vue choisie à droite ── -->\r\n<div class=\"csl-body\">\r\n <div class=\"csl-panels\">\r\n\r\n <!-- ── GAUCHE : vues personnalisées ─────────────────────────────────── -->\r\n <div class=\"csl-panel csl-panel--groups\">\r\n <div class=\"csl-panel__header\">\r\n <span class=\"csl-panel__label\">Vues personnalisées</span>\r\n <span class=\"csl-badge\">{{ svc.views.length }}</span>\r\n </div>\r\n <ul class=\"csl-group-list csl-scroll\">\r\n @for (view of svc.views; track view.id) {\r\n <li class=\"csl-group-item csl-view-item\"\r\n [class.csl-group-item--active]=\"svc.selectedView?.id === view.id\"\r\n [class.csl-group-item--standard]=\"view.isDefault\"\r\n [class.csl-group-item--profile]=\"!view.isDefault\"\r\n (click)=\"svc.selectView(view)\">\r\n @if (svc.renamingId === view.id) {\r\n <input class=\"gps-rename-input\" type=\"text\" maxlength=\"100\"\r\n [(ngModel)]=\"svc.renameLabel\"\r\n (click)=\"$event.stopPropagation()\"\r\n (keydown.enter)=\"svc.confirmRename(view)\"\r\n (keydown.escape)=\"svc.cancelRename()\">\r\n <div class=\"gps-rename-actions\" (click)=\"$event.stopPropagation()\">\r\n <button class=\"gps-rename-btn gps-rename-btn--ok\" type=\"button\" title=\"Renommer\" (click)=\"svc.confirmRename(view)\">\r\n <i class=\"fa fa-check\"></i>\r\n </button>\r\n <button class=\"gps-rename-btn gps-rename-btn--cancel\" type=\"button\" title=\"Annuler\" (click)=\"svc.cancelRename()\">\r\n <i class=\"fa fa-times\"></i>\r\n </button>\r\n </div>\r\n } @else {\r\n <span class=\"csl-group-item__name\" [title]=\"view.label\">\r\n @if (view.isDefault) { <i class=\"fa fa-lock csl-view-icon\" title=\"Vue par défaut\"></i> }\r\n {{ view.label }}\r\n </span>\r\n <div class=\"csl-group-item__meta\">\r\n @if (view.isCurrent) {\r\n <span class=\"csl-badge csl-badge--primary csl-badge--sm\" title=\"Vue affichée par la grille\">\r\n <i class=\"fa fa-eye\"></i>\r\n </span>\r\n }\r\n <div class=\"gps-profile-actions\" (click)=\"$event.stopPropagation()\">\r\n @if (svc.canEdit(view)) {\r\n <button class=\"gps-profile-btn\" type=\"button\" title=\"Renommer\" (click)=\"svc.startRename(view)\">\r\n <i class=\"fa fa-pencil\"></i>\r\n </button>\r\n }\r\n <button class=\"gps-profile-btn\" type=\"button\" title=\"Dupliquer\" (click)=\"svc.duplicateView(view)\">\r\n <i class=\"fa fa-files-o\"></i>\r\n </button>\r\n @if (!view.isDefault) {\r\n <button class=\"gps-profile-btn gps-profile-btn--danger\" type=\"button\" title=\"Supprimer\" (click)=\"svc.deleteView(view)\">\r\n <i class=\"fa fa-trash-o\"></i>\r\n </button>\r\n }\r\n </div>\r\n </div>\r\n }\r\n </li>\r\n }\r\n @empty {\r\n <li class=\"csl-group-section-label\">Aucune vue enregistrée</li>\r\n }\r\n </ul>\r\n @if (svc.isReadOnly) {\r\n <div class=\"csl-view-note\">\r\n <i class=\"fa fa-info-circle\"></i>\r\n Vue par défaut en lecture seule : « Appliquer » crée une nouvelle vue personnelle.\r\n </div>\r\n }\r\n </div>\r\n\r\n <!-- ── DROITE : éditeur standard de la vue choisie (Propriétés, Colonnes, Tri, Filtres) ── -->\r\n <div class=\"csl-tabbed csl-editor\">\r\n <ng-container #editorHost></ng-container>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<!-- ── Footer ─────────────────────────────────────────────────────────────── -->\r\n<div class=\"csl-footer\">\r\n <span class=\"csl-footer__count\">\r\n @if (svc.message) {\r\n <span class=\"csl-footer__error\">{{ svc.message }}</span>\r\n } @else if (svc.selectedView) {\r\n Vue « {{ svc.selectedView.label }} » — « Appliquer » l'enregistre et l'affiche dans la grille\r\n }\r\n </span>\r\n <div class=\"csl-footer__actions\">\r\n @if (!svc.isEmbedded) {\r\n <button class=\"csl-btn csl-btn--secondary\" type=\"button\" (click)=\"svc.cancel()\">Annuler</button>\r\n }\r\n <button class=\"csl-btn csl-btn--primary\" type=\"button\"\r\n (click)=\"apply()\" [disabled]=\"!svc.selectedView || svc.isSaving || svc.isLoading\">\r\n @if (svc.isSaving) {\r\n <span class=\"csl-spinner csl-spinner--sm csl-spinner--light\"></span>&nbsp;\r\n }\r\n Appliquer\r\n </button>\r\n </div>\r\n</div>\r\n",
1624
- styles: [".home-page{font-family:Open sans,sans-serif;background:#fff;-webkit-font-smoothing:antialiased;height:100%;width:100%;padding:16px}.main-container{margin:0 50px}.main-container-modal{width:calc(100% - 50px);margin:10px 25px 0}.moyen-titre{font-weight:700;font-size:24px;color:#4d5a81;margin:8px 0;border-bottom:solid 1px #DBE4FF}.grand-titre{font-weight:700;font-size:28px;color:#4d5a81;margin:0 0 8px}.petit-titre{font-weight:700;font-size:16px;color:#4d5a81;margin:0 0 8px}.petit-titre.underlined{border-bottom:solid 1px #4D5A81}.paragraph{padding:0 15px}.paragraph-highlight{padding:5px 15px 0 12px;border-left:5px solid #8EA7F8;border-bottom:1px solid #DBE4FF;border-top:1px solid #DBE4FF;border-right:1px solid #DBE4FF;background-color:#f7faff}.highlight{background-color:#f7faff;border:1px solid #DBE4FF;border-radius:5px;padding:15px;color:#3c5dc4;margin:0 0 16px}.highlight p{margin-bottom:0}.highlight:before{position:relative;display:block;float:left;width:24px;height:24px;content:\" \";background-size:24px 24px;-webkit-background-size:24px 24px;background-image:url('data:image/svg+xml,<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"53.294\" height=\"50.629\" viewBox=\"0 0 53.294 50.629\">%0D%0A <path id=\"allerg\\e8ne\" d=\"M830.494,25.793l-5.814,6.783.727,8.963-8.721,1.938-4.6,7.752L803.847,47.6l-8.236,3.634-4.6-7.51-8.721-1.938.727-8.963L777.2,26.035l5.814-6.783-.727-8.963,8.721-1.938L795.61.6l8.236,3.634L812.083.6l4.6,7.752,8.721,1.938-.727,8.963Zm-24.467,2.422V13.681h-4.845V28.216Zm0,9.69V33.06h-4.845v4.845Z\" transform=\"translate(-777.2 -0.6)\"/>%0D%0A</svg>%0D%0A');background-repeat:no-repeat;margin:0 8px 24px 0;filter:invert(31%) sepia(51%) saturate(1323%) hue-rotate(199deg) brightness(99%) contrast(94%)}.notification{background-color:#dbe4ff;border:1px solid #C4D0F9;border-radius:5px;color:#4d5a81;margin:16px;padding:5px 15px;text-align:justify}.notification:before{position:relative;display:block;float:left;width:24px;height:24px;content:\" \";background-size:24px 24px;-webkit-background-size:24px 24px;background-image:url('data:image/svg+xml,<svg aria-hidden=\"true\" focusable=\"false\" data-prefix=\"fas\" data-icon=\"info-circle\" class=\"svg-inline--fa fa-info-circle fa-w-16\" role=\"img\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\"><path fill=\"currentColor\" d=\"M256 8C119.043 8 8 119.083 8 256c0 136.997 111.043 248 248 248s248-111.003 248-248C504 119.083 392.957 8 256 8zm0 110c23.196 0 42 18.804 42 42s-18.804 42-42 42-42-18.804-42-42 18.804-42 42-42zm56 254c0 6.627-5.373 12-12 12h-88c-6.627 0-12-5.373-12-12v-24c0-6.627 5.373-12 12-12h12v-64h-12c-6.627 0-12-5.373-12-12v-24c0-6.627 5.373-12 12-12h64c6.627 0 12 5.373 12 12v100h12c6.627 0 12 5.373 12 12v24z\"></path></svg>');background-repeat:no-repeat;margin:0 8px 0 0;filter:invert(31%) sepia(8%) saturate(2329%) hue-rotate(188deg) brightness(103%) contrast(85%)}.notification-text{padding:0 15px 0 30px;font-size:16px}:host{display:flex;flex-direction:column;height:100%}.csl-header{display:flex;align-items:center;justify-content:space-between;padding:6px 8px 6px 16px;background:#5272d3;border-bottom:1px solid #3C5DC4;flex-shrink:0}.csl-header__left{display:flex;flex-direction:column}.csl-title{font-size:15px;font-weight:600;color:#fff;letter-spacing:-.2px;line-height:1.4;margin:0}.csl-icon-btn{display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;border-radius:50%;border:none;background:transparent;color:#fffc;font-size:14px;cursor:pointer;flex-shrink:0;margin-left:16px;transition:background .1s ease}.csl-icon-btn:hover{background:#ffffff26;color:#fff}.gps-tabs{display:flex;gap:2px}.gps-tab{display:inline-flex;align-items:center;gap:5px;padding:7px 18px;border:none;background:#ffffff1f;color:#ffffffb8;font-size:13px;font-weight:500;cursor:pointer;border-radius:6px 6px 0 0;transition:background .1s ease,color .1s ease}.gps-tab:hover:not(.gps-tab--active){background:#fff3;color:#fff}.gps-tab--active{background:#fff;color:#4465c9;font-weight:600}.csl-body{flex:1;overflow:hidden;padding:16px 20px}.csl-loading{display:flex;align-items:center;justify-content:center;gap:10px;min-height:200px;color:#535353;font-size:13px}.csl-panels{display:grid;grid-template-columns:240px 1fr 320px;grid-template-rows:minmax(0,1fr);gap:12px;height:calc(70vh - 160px);min-height:380px;overflow:hidden}.csl-panel{min-height:0}.csl-scroll{flex:1 1 auto;min-height:0;overflow-y:auto}.csl-view-icon{margin-right:4px;font-size:11px;color:#888}.csl-view-note{flex-shrink:0;padding:8px 12px;border-top:1px solid #C4D0F9;font-size:11.5px;color:#535353;background:#f5f5f5}.csl-view-note .fa{color:#4465c9;margin-right:4px}.csl-attribute-tag{display:inline-block;margin-left:6px;padding:0 6px;border-radius:8px;font-size:10px;font-weight:600;color:#fff;background:#6b7fd4;vertical-align:middle}.csl-group-item--active .gps-profile-actions{opacity:1}.csl-footer__error{color:#dc3545}.csl-panel{display:flex;flex-direction:column;border:1px solid #C4D0F9;border-radius:10px;overflow:hidden;background:#fff}.csl-panel__header{display:flex;align-items:center;justify-content:space-between;padding:10px 13px;border-bottom:1px solid #C4D0F9;background:#f5f5f5;flex-shrink:0;gap:8px}.csl-panel__label{font-size:10.5px;font-weight:600;text-transform:uppercase;letter-spacing:.9px;color:#535353;flex-shrink:0}.csl-group-list{list-style:none;margin:0;padding:6px;overflow-y:auto;flex:1}.csl-group-item{display:flex;align-items:center;justify-content:space-between;padding:7px 8px;border-radius:6px;cursor:pointer;transition:background .1s ease;min-height:34px}.csl-group-item:hover{background:#f7faff}.csl-group-item:hover .gps-profile-actions{opacity:1}.csl-group-item--active{background:#ebf0ff}.csl-group-item--active .csl-group-item__name{color:#4465c9;font-weight:600}.csl-group-item--standard{border-left:3px solid #4465C9;padding-left:5px}.csl-group-item--model{border-left:3px solid #6B7FD4;padding-left:5px}.csl-group-item--profile{border-left:3px solid #4465C9;padding-left:5px}.csl-group-item__name{font-size:12.5px;color:#272c5d;flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;margin-right:4px}.csl-group-item__meta{display:flex;align-items:center;gap:4px;flex-shrink:0}.gps-profile-actions{display:flex;align-items:center;gap:2px;flex-shrink:0;opacity:0;transition:opacity .1s ease}.gps-profile-btn{display:inline-flex;align-items:center;justify-content:center;width:22px;height:22px;border:none;background:none;border-radius:4px;font-size:11px;color:#888;cursor:pointer;padding:0;transition:background .1s,color .1s}.gps-profile-btn:hover{background:#00000014;color:#4465c9}.gps-profile-btn--danger:hover{background:#dc35451a;color:#dc3545}.gps-rename-input{flex:1;height:24px;border:1px solid #4465C9;border-radius:4px;padding:0 6px;font-size:12px;color:#272c5d;background:#fff;outline:none;min-width:0;margin-right:4px}.gps-rename-actions{display:flex;align-items:center;gap:2px;flex-shrink:0}.gps-rename-btn{display:inline-flex;align-items:center;justify-content:center;width:22px;height:22px;border:none;border-radius:4px;font-size:11px;cursor:pointer;padding:0}.gps-rename-btn--ok{background:#4465c9;color:#fff}.gps-rename-btn--ok:hover{background:#3c5dc4}.gps-rename-btn--cancel{background:#00000014;color:#535353}.gps-rename-btn--cancel:hover{background:#00000026}.gps-new-profile{color:#4465c9;font-size:12px;font-weight:500;opacity:.75;justify-content:flex-start;gap:4px}.gps-new-profile:hover{opacity:1;background:#ebf0ff}.csl-group-section-label{padding:8px 8px 4px;font-size:9.5px;font-weight:700;text-transform:uppercase;letter-spacing:.8px;color:#888;list-style:none}.csl-group-divider{height:1px;background:#c4d0f9;margin:6px 8px;list-style:none}.csl-badge{display:inline-flex;align-items:center;justify-content:center;min-width:20px;height:18px;padding:0 5px;border-radius:9px;background:#00000012;color:#535353;font-size:10px;font-weight:600}.csl-badge--primary{background:#4465c9;color:#fff}.csl-badge--sm{height:16px;min-width:16px;font-size:9px;padding:0 4px}.csl-search{flex:1;height:28px;border:1px solid #C4D0F9;border-radius:6px;padding:0 8px;font-size:12px;color:#272c5d;background:#fff;outline:none;transition:border-color .1s ease}.csl-search:focus{border-color:#6684e0}.csl-table-wrap{overflow-y:auto;flex:1}.csl-table{width:100%;border-collapse:collapse;font-size:12.5px}.csl-table thead tr{position:sticky;top:0;z-index:1;background:#f5f5f5}.csl-table thead tr th{padding:8px 10px;text-align:left;font-size:10px;font-weight:600;color:#888;text-transform:uppercase;letter-spacing:.6px;border-bottom:1px solid #C4D0F9;white-space:nowrap}.csl-table tbody tr{border-bottom:1px solid rgba(0,0,0,.04);cursor:pointer;transition:background .1s ease}.csl-table tbody tr:hover{background:#f7faff}.csl-table tbody tr:last-child{border-bottom:none}.csl-table tbody tr td{padding:9px 10px;color:#272c5d}.csl-col-check{width:36px;text-align:center;padding:0 8px!important}.csl-col-check input[type=checkbox]{cursor:pointer;accent-color:#4465C9;width:14px;height:14px}.csl-col-key{font-family:monospace;font-size:11.5px;color:#535353;width:130px}.csl-col-name{font-weight:500}.csl-row--selected{background:#ebf0ff!important}.csl-row--custom-field .csl-col-key{color:#6b7fd4}.csl-empty{text-align:center;padding:32px 16px!important;color:#888;font-size:12.5px}.csl-panel--selected{overflow:hidden}.csl-ordered-list{flex:1;overflow-y:auto;padding:7px}.csl-ordered-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;flex:1;gap:8px;padding:20px;text-align:center}.csl-ordered-empty__icon{font-size:28px;color:#888;opacity:.35}.csl-ordered-empty p{font-size:12px;color:#535353;margin:0;line-height:1.5}.csl-ordered-item{display:flex;align-items:center;gap:5px;padding:6px 8px 6px 4px;margin-bottom:4px;border:1px solid #C4D0F9;border-radius:6px;background:#fff;transition:border-color .14s ease,background .14s ease}.csl-ordered-item:last-child{margin-bottom:0}.csl-ordered-item:hover{border-color:#8ea7f8;background:#f7faff}.csl-ordered-item__drag{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;width:20px;color:#888;font-size:11px;cursor:grab;padding:0 2px;-webkit-user-select:none;user-select:none}.csl-ordered-item__drag:active{cursor:grabbing}.csl-ordered-item__position{flex-shrink:0;width:19px;height:19px;border-radius:50%;background:#ebf0ff;color:#4465c9;font-size:10px;font-weight:700;display:flex;align-items:center;justify-content:center}.csl-ordered-item__code{flex-shrink:0;width:90px;font-family:monospace;font-size:11px;font-weight:600;color:#535353;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.csl-ordered-item__code--cf{color:#6b7fd4}.csl-ordered-item__desc{flex:1;height:24px;min-width:0;padding:0 6px;border:1px solid transparent;border-radius:4px;font-size:12px;color:#272c5d;background:transparent;transition:border-color .1s,background .1s}.csl-ordered-item__desc::placeholder{color:#888;font-style:italic}.csl-ordered-item__desc:hover{border-color:#c4d0f9;background:#fff}.csl-ordered-item__desc:focus{border-color:#4465c9;background:#fff;outline:none}.csl-ordered-item__remove{flex-shrink:0;background:none;border:none;padding:0 3px;font-size:12px;color:#888;cursor:pointer;line-height:1}.csl-ordered-item__remove:hover{color:#f78383}.csl-ordered-item.cdk-drag-animating{transition:transform .2s cubic-bezier(.25,.8,.25,1)}.csl-ordered-item__placeholder{width:100%;height:38px;border:2px dashed #C4D0F9;border-radius:6px;background:#f7faff}.cdk-drop-list-dragging .csl-ordered-item:not(.cdk-drag-placeholder){transition:transform .2s cubic-bezier(.25,.8,.25,1)}.cdk-drag-preview{display:flex;align-items:center;gap:6px;padding:8px 8px 8px 4px;border-radius:6px;background:#fff;box-shadow:0 4px 16px #4465c92e,0 1px 4px #0000001a;font-size:12px;font-weight:500;color:#272c5d;min-width:180px}.csl-footer{display:flex;align-items:center;justify-content:space-between;padding:13px 22px 16px;border-top:1px solid #C4D0F9;flex-shrink:0}.csl-footer__count{font-size:12px;color:#888;min-width:180px}.csl-footer__actions{display:flex;gap:10px}.csl-btn{display:inline-flex;align-items:center;gap:7px;padding:7px 18px;font-size:13px;font-weight:500;border-radius:6px;cursor:pointer;transition:background .12s ease,opacity .12s ease}.csl-btn--secondary{background:transparent;border:1px solid rgba(0,0,0,.16);color:#535353}.csl-btn--secondary:hover{background:#0000000a}.csl-btn--primary{background:#4465c9;border:1px solid transparent;color:#fff;min-width:130px;justify-content:center}.csl-btn--primary:hover:not([disabled]){background:#3c5dc4}.csl-btn--primary[disabled]{opacity:.42;cursor:not-allowed}.csl-save-prompt{display:flex;align-items:center;gap:10px;width:100%;flex-wrap:wrap}.csl-save-prompt__label{font-size:12.5px;font-weight:500;color:#272c5d;white-space:nowrap}.csl-save-prompt__input{flex:1;min-width:160px;height:32px;padding:0 10px;border:1px solid #C4D0F9;border-radius:6px;font-size:12px;color:#272c5d;background:#fff;outline:none;transition:border-color .1s}.csl-save-prompt__input:focus{border-color:#4465c9}.csl-save-prompt__input[disabled]{opacity:.5}.csl-save-prompt__actions{display:flex;gap:8px;flex-shrink:0}.csl-spinner{display:inline-block;width:14px;height:14px;border:2px solid #DBE4FF;border-top-color:#4465c9;border-radius:50%;animation:gps-spin .65s linear infinite}.csl-spinner--sm{width:11px;height:11px;border-width:2px}.csl-spinner--light{border-color:#ffffff59;border-top-color:#fff}@keyframes gps-spin{to{transform:rotate(360deg)}}.csl-tabbed{flex:2 1 0;min-width:0;display:flex;flex-direction:column;gap:8px}.csl-tabs{display:flex;gap:4px;border-bottom:1px solid #3C5DC4}.csl-tab{position:relative;flex:1 1 0;text-align:center;padding:6px 14px;border:none;border-bottom:2px solid transparent;background:none;color:#6b7591;font:inherit;font-weight:700;cursor:pointer}.csl-tab--active{color:#5272d3;border-bottom-color:#5272d3}.csl-tab-dot{display:inline-block;width:7px;height:7px;margin-left:6px;border-radius:50%;background:var(--orange-algorima, #f59d0f);vertical-align:middle}.csl-panels--inner{flex:1 1 auto;min-height:0}.csl-panel--filters{flex:1 1 auto;min-height:0;overflow:auto}.csl-editor{overflow:auto;min-height:0}\n"],
1836
+ template: "<!-- ── Header ─────────────────────────────────────────────────────────────── -->\r\n<div class=\"csl-header\">\r\n <div class=\"csl-header__left\">\r\n <h4 class=\"csl-title\">{{ svc.config?.title || 'Sélection des colonnes' }}</h4>\r\n </div>\r\n @if (!svc.isEmbedded) {\r\n <button class=\"csl-icon-btn\" type=\"button\" (click)=\"svc.cancel()\" aria-label=\"Fermer\">&#x2715;</button>\r\n }\r\n</div>\r\n\r\n<!-- ── Body : vues à gauche, éditeur standard de la vue choisie à droite ── -->\r\n<div class=\"csl-body\">\r\n <div class=\"csl-panels\">\r\n\r\n <!-- ── GAUCHE : vues personnalisées ─────────────────────────────────── -->\r\n <div class=\"csl-panel csl-panel--groups\">\r\n <div class=\"csl-panel__header\">\r\n <span class=\"csl-panel__label\">Vues personnalisées</span>\r\n <span class=\"csl-badge\">{{ svc.views.length }}</span>\r\n <button class=\"gps-profile-btn csl-add-view\" type=\"button\" title=\"Nouvelle vue (copie de la vue choisie)\"\r\n [disabled]=\"svc.isLoading || svc.isSaving\" (click)=\"svc.createView()\">\r\n <i class=\"fa fa-plus\"></i>\r\n </button>\r\n </div>\r\n <ul class=\"csl-group-list csl-scroll\">\r\n @for (view of svc.views; track view.id) {\r\n <li class=\"csl-group-item csl-view-item\"\r\n [class.csl-group-item--active]=\"svc.selectedView?.id === view.id\"\r\n [class.csl-group-item--standard]=\"view.isDefault\"\r\n [class.csl-group-item--profile]=\"!view.isDefault\"\r\n (click)=\"svc.selectView(view)\">\r\n @if (svc.renamingId === view.id) {\r\n <input class=\"gps-rename-input\" type=\"text\" maxlength=\"100\"\r\n [(ngModel)]=\"svc.renameLabel\"\r\n (click)=\"$event.stopPropagation()\"\r\n (keydown.enter)=\"svc.confirmRename(view)\"\r\n (keydown.escape)=\"svc.cancelRename()\">\r\n <div class=\"gps-rename-actions\" (click)=\"$event.stopPropagation()\">\r\n <button class=\"gps-rename-btn gps-rename-btn--ok\" type=\"button\" title=\"Renommer\" (click)=\"svc.confirmRename(view)\">\r\n <i class=\"fa fa-check\"></i>\r\n </button>\r\n <button class=\"gps-rename-btn gps-rename-btn--cancel\" type=\"button\" title=\"Annuler\" (click)=\"svc.cancelRename()\">\r\n <i class=\"fa fa-times\"></i>\r\n </button>\r\n </div>\r\n } @else {\r\n <span class=\"csl-group-item__name\" [title]=\"view.label\">\r\n @if (view.isDefault) { <i class=\"fa fa-lock csl-view-icon\" title=\"Vue par défaut\"></i> }\r\n {{ view.label }}\r\n </span>\r\n <div class=\"csl-group-item__meta\">\r\n @if (view.isCurrent) {\r\n <span class=\"csl-badge csl-badge--primary csl-badge--sm\" title=\"Vue affichée par la grille\">\r\n <i class=\"fa fa-eye\"></i>\r\n </span>\r\n }\r\n <div class=\"gps-profile-actions\" (click)=\"$event.stopPropagation()\">\r\n @if (svc.canEdit(view)) {\r\n <button class=\"gps-profile-btn\" type=\"button\" title=\"Renommer\" (click)=\"svc.startRename(view)\">\r\n <i class=\"fa fa-pencil\"></i>\r\n </button>\r\n }\r\n <button class=\"gps-profile-btn\" type=\"button\" title=\"Dupliquer\" (click)=\"svc.duplicateView(view)\">\r\n <i class=\"fa fa-files-o\"></i>\r\n </button>\r\n @if (!view.isDefault) {\r\n <button class=\"gps-profile-btn gps-profile-btn--danger\" type=\"button\" title=\"Supprimer\" (click)=\"svc.deleteView(view)\">\r\n <i class=\"fa fa-trash-o\"></i>\r\n </button>\r\n }\r\n </div>\r\n </div>\r\n }\r\n </li>\r\n }\r\n @empty {\r\n <li class=\"csl-group-section-label\">Aucune vue enregistrée</li>\r\n }\r\n </ul>\r\n @if (svc.isReadOnly) {\r\n <div class=\"csl-view-note\">\r\n <i class=\"fa fa-info-circle\"></i>\r\n Vue par défaut en lecture seule : « Appliquer » crée une nouvelle vue personnelle.\r\n </div>\r\n }\r\n </div>\r\n\r\n <!-- ── DROITE : éditeur standard de la vue choisie (Colonnes, Tri, Filtres, Carte) ── -->\r\n <div class=\"csl-tabbed csl-editor\">\r\n <ng-container #editorHost></ng-container>\r\n </div>\r\n\r\n <!-- Onglet « Carte » de l'éditeur : carte de la vue choisie, à défaut la carte par défaut de la table -->\r\n <ng-template #cardTab>\r\n <div class=\"csl-card\">\r\n <p class=\"csl-card__hint\">\r\n @if (svc.usesDefaultCard) {\r\n Cette vue affiche la carte par défaut de la table : vos choix lui donnent sa propre carte.\r\n } @else {\r\n Carte propre à la vue « {{ svc.selectedView?.label }} ».\r\n }\r\n </p>\r\n @for (slot of svc.cardSlotList; track slot.name) {\r\n <label class=\"csl-card__slot\">\r\n <span>{{ slot.label }}</span>\r\n <select class=\"form-control\" [id]=\"'card-slot-' + slot.name\" [(ngModel)]=\"svc.cardSlots[slot.name]\">\r\n <option value=\"\">{{ slot.name === 'image' ? 'Aucune' : 'Aucun' }}</option>\r\n @for (option of (slot.name === 'image' ? svc.cardImageOptions : svc.cardOptions); track option.key) {\r\n <option [value]=\"option.key\">{{ option.label }}</option>\r\n }\r\n </select>\r\n </label>\r\n }\r\n @if (!svc.usesDefaultCard && !(svc.selectedView?.isDefault)) {\r\n <div class=\"csl-card__actions\">\r\n <button class=\"csl-btn csl-btn--secondary\" type=\"button\" (click)=\"svc.resetCard()\"\r\n title=\"La vue n'a plus de carte propre : elle affiche la carte par défaut de la table\">\r\n Revenir à la carte par défaut\r\n </button>\r\n </div>\r\n }\r\n </div>\r\n </ng-template>\r\n </div>\r\n</div>\r\n\r\n<!-- ── Footer ─────────────────────────────────────────────────────────────── -->\r\n<div class=\"csl-footer\">\r\n <span class=\"csl-footer__count\">\r\n @if (svc.message) {\r\n <span class=\"csl-footer__error\">{{ svc.message }}</span>\r\n } @else if (svc.selectedView) {\r\n Vue « {{ svc.selectedView.label }} » — « Appliquer » l'enregistre et l'affiche dans la grille\r\n }\r\n </span>\r\n <div class=\"csl-footer__actions\">\r\n @if (!svc.isEmbedded) {\r\n <button class=\"csl-btn csl-btn--secondary\" type=\"button\" (click)=\"svc.cancel()\">Annuler</button>\r\n }\r\n <button class=\"csl-btn csl-btn--primary\" type=\"button\"\r\n (click)=\"apply()\" [disabled]=\"!svc.selectedView || svc.isSaving || svc.isLoading\">\r\n @if (svc.isSaving) {\r\n <span class=\"csl-spinner csl-spinner--sm csl-spinner--light\"></span>&nbsp;\r\n }\r\n Appliquer\r\n </button>\r\n </div>\r\n</div>\r\n",
1837
+ styles: [".home-page{font-family:Open sans,sans-serif;background:#fff;-webkit-font-smoothing:antialiased;height:100%;width:100%;padding:16px}.main-container{margin:0 50px}.main-container-modal{width:calc(100% - 50px);margin:10px 25px 0}.moyen-titre{font-weight:700;font-size:24px;color:#4d5a81;margin:8px 0;border-bottom:solid 1px #DBE4FF}.grand-titre{font-weight:700;font-size:28px;color:#4d5a81;margin:0 0 8px}.petit-titre{font-weight:700;font-size:16px;color:#4d5a81;margin:0 0 8px}.petit-titre.underlined{border-bottom:solid 1px #4D5A81}.paragraph{padding:0 15px}.paragraph-highlight{padding:5px 15px 0 12px;border-left:5px solid #8EA7F8;border-bottom:1px solid #DBE4FF;border-top:1px solid #DBE4FF;border-right:1px solid #DBE4FF;background-color:#f7faff}.highlight{background-color:#f7faff;border:1px solid #DBE4FF;border-radius:5px;padding:15px;color:#3c5dc4;margin:0 0 16px}.highlight p{margin-bottom:0}.highlight:before{position:relative;display:block;float:left;width:24px;height:24px;content:\" \";background-size:24px 24px;-webkit-background-size:24px 24px;background-image:url('data:image/svg+xml,<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"53.294\" height=\"50.629\" viewBox=\"0 0 53.294 50.629\">%0D%0A <path id=\"allerg\\e8ne\" d=\"M830.494,25.793l-5.814,6.783.727,8.963-8.721,1.938-4.6,7.752L803.847,47.6l-8.236,3.634-4.6-7.51-8.721-1.938.727-8.963L777.2,26.035l5.814-6.783-.727-8.963,8.721-1.938L795.61.6l8.236,3.634L812.083.6l4.6,7.752,8.721,1.938-.727,8.963Zm-24.467,2.422V13.681h-4.845V28.216Zm0,9.69V33.06h-4.845v4.845Z\" transform=\"translate(-777.2 -0.6)\"/>%0D%0A</svg>%0D%0A');background-repeat:no-repeat;margin:0 8px 24px 0;filter:invert(31%) sepia(51%) saturate(1323%) hue-rotate(199deg) brightness(99%) contrast(94%)}.notification{background-color:#dbe4ff;border:1px solid #C4D0F9;border-radius:5px;color:#4d5a81;margin:16px;padding:5px 15px;text-align:justify}.notification:before{position:relative;display:block;float:left;width:24px;height:24px;content:\" \";background-size:24px 24px;-webkit-background-size:24px 24px;background-image:url('data:image/svg+xml,<svg aria-hidden=\"true\" focusable=\"false\" data-prefix=\"fas\" data-icon=\"info-circle\" class=\"svg-inline--fa fa-info-circle fa-w-16\" role=\"img\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\"><path fill=\"currentColor\" d=\"M256 8C119.043 8 8 119.083 8 256c0 136.997 111.043 248 248 248s248-111.003 248-248C504 119.083 392.957 8 256 8zm0 110c23.196 0 42 18.804 42 42s-18.804 42-42 42-42-18.804-42-42 18.804-42 42-42zm56 254c0 6.627-5.373 12-12 12h-88c-6.627 0-12-5.373-12-12v-24c0-6.627 5.373-12 12-12h12v-64h-12c-6.627 0-12-5.373-12-12v-24c0-6.627 5.373-12 12-12h64c6.627 0 12 5.373 12 12v100h12c6.627 0 12 5.373 12 12v24z\"></path></svg>');background-repeat:no-repeat;margin:0 8px 0 0;filter:invert(31%) sepia(8%) saturate(2329%) hue-rotate(188deg) brightness(103%) contrast(85%)}.notification-text{padding:0 15px 0 30px;font-size:16px}:host{display:flex;flex-direction:column;height:100%}.csl-header{display:flex;align-items:center;justify-content:space-between;padding:6px 8px 6px 16px;background:#5272d3;border-bottom:1px solid #3C5DC4;flex-shrink:0}.csl-header__left{display:flex;flex-direction:column}.csl-title{font-size:15px;font-weight:600;color:#fff;letter-spacing:-.2px;line-height:1.4;margin:0}.csl-icon-btn{display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;border-radius:50%;border:none;background:transparent;color:#fffc;font-size:14px;cursor:pointer;flex-shrink:0;margin-left:16px;transition:background .1s ease}.csl-icon-btn:hover{background:#ffffff26;color:#fff}.gps-tabs{display:flex;gap:2px}.gps-tab{display:inline-flex;align-items:center;gap:5px;padding:7px 18px;border:none;background:#ffffff1f;color:#ffffffb8;font-size:13px;font-weight:500;cursor:pointer;border-radius:6px 6px 0 0;transition:background .1s ease,color .1s ease}.gps-tab:hover:not(.gps-tab--active){background:#fff3;color:#fff}.gps-tab--active{background:#fff;color:#4465c9;font-weight:600}.csl-body{flex:1;overflow:hidden;padding:16px 20px}.csl-loading{display:flex;align-items:center;justify-content:center;gap:10px;min-height:200px;color:#535353;font-size:13px}.csl-panel--groups .csl-panel__header{justify-content:flex-start}.csl-panel--groups .csl-panel__header .csl-panel__label{margin-right:auto}.csl-card{padding:12px 16px;display:flex;flex-direction:column;gap:8px;max-width:560px}.csl-card__hint{margin:0 0 4px;font-size:12px;opacity:.8}.csl-card__slot{display:grid;grid-template-columns:80px minmax(0,1fr);align-items:center;gap:10px;margin:0;font-weight:400}.csl-card__slot span{font-weight:600}.csl-card__actions{margin-top:4px}.csl-panels{display:grid;grid-template-columns:240px minmax(0,1fr);grid-template-rows:minmax(0,1fr);gap:12px;height:calc(70vh - 160px);min-height:380px;overflow:hidden}.csl-panel{min-height:0}.csl-scroll{flex:1 1 auto;min-height:0;overflow-y:auto}.csl-view-icon{margin-right:4px;font-size:11px;color:#888}.csl-view-note{flex-shrink:0;padding:8px 12px;border-top:1px solid #C4D0F9;font-size:11.5px;color:#535353;background:#f5f5f5}.csl-view-note .fa{color:#4465c9;margin-right:4px}.csl-attribute-tag{display:inline-block;margin-left:6px;padding:0 6px;border-radius:8px;font-size:10px;font-weight:600;color:#fff;background:#6b7fd4;vertical-align:middle}.csl-group-item--active .gps-profile-actions{opacity:1}.csl-footer__error{color:#dc3545}.csl-panel{display:flex;flex-direction:column;border:1px solid #C4D0F9;border-radius:10px;overflow:hidden;background:#fff}.csl-panel__header{display:flex;align-items:center;justify-content:space-between;padding:10px 13px;border-bottom:1px solid #C4D0F9;background:#f5f5f5;flex-shrink:0;gap:8px}.csl-panel__label{font-size:10.5px;font-weight:600;text-transform:uppercase;letter-spacing:.9px;color:#535353;flex-shrink:0}.csl-group-list{list-style:none;margin:0;padding:6px;overflow-y:auto;flex:1}.csl-group-item{display:flex;align-items:center;justify-content:space-between;padding:7px 8px;border-radius:0 6px 6px 0;cursor:pointer;transition:background .1s ease;min-height:34px}.csl-group-item:hover{background:#f7faff}.csl-group-item:hover .gps-profile-actions{opacity:1}.csl-group-item--active{background:#ebf0ff}.csl-group-item--active .csl-group-item__name{color:#4465c9;font-weight:600}.csl-group-item--standard{border-left:3px solid #4465C9;padding-left:5px}.csl-group-item--model{border-left:3px solid #6B7FD4;padding-left:5px}.csl-group-item--profile{border-left:3px solid #4465C9;padding-left:5px}.csl-group-item__name{font-size:12.5px;color:#272c5d;flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;margin-right:4px}.csl-group-item__meta{display:flex;align-items:center;gap:4px;flex-shrink:0}.gps-profile-actions{display:flex;align-items:center;gap:2px;flex-shrink:0;opacity:0;transition:opacity .1s ease}.gps-profile-btn{display:inline-flex;align-items:center;justify-content:center;width:22px;height:22px;border:none;background:none;border-radius:4px;font-size:11px;color:#888;cursor:pointer;padding:0;transition:background .1s,color .1s}.gps-profile-btn:hover{background:#00000014;color:#4465c9}.gps-profile-btn--danger:hover{background:#dc35451a;color:#dc3545}.gps-rename-input{flex:1;height:24px;border:1px solid #4465C9;border-radius:4px;padding:0 6px;font-size:12px;color:#272c5d;background:#fff;outline:none;min-width:0;margin-right:4px}.gps-rename-actions{display:flex;align-items:center;gap:2px;flex-shrink:0}.gps-rename-btn{display:inline-flex;align-items:center;justify-content:center;width:22px;height:22px;border:none;border-radius:4px;font-size:11px;cursor:pointer;padding:0}.gps-rename-btn--ok{background:#4465c9;color:#fff}.gps-rename-btn--ok:hover{background:#3c5dc4}.gps-rename-btn--cancel{background:#00000014;color:#535353}.gps-rename-btn--cancel:hover{background:#00000026}.gps-new-profile{color:#4465c9;font-size:12px;font-weight:500;opacity:.75;justify-content:flex-start;gap:4px}.gps-new-profile:hover{opacity:1;background:#ebf0ff}.csl-group-section-label{padding:8px 8px 4px;font-size:9.5px;font-weight:700;text-transform:uppercase;letter-spacing:.8px;color:#888;list-style:none}.csl-group-divider{height:1px;background:#c4d0f9;margin:6px 8px;list-style:none}.csl-badge{display:inline-flex;align-items:center;justify-content:center;min-width:20px;height:18px;padding:0 5px;border-radius:9px;background:#00000012;color:#535353;font-size:10px;font-weight:600}.csl-badge--primary{background:#4465c9;color:#fff}.csl-badge--sm{height:16px;min-width:16px;font-size:9px;padding:0 4px}.csl-search{flex:1;height:28px;border:1px solid #C4D0F9;border-radius:6px;padding:0 8px;font-size:12px;color:#272c5d;background:#fff;outline:none;transition:border-color .1s ease}.csl-search:focus{border-color:#6684e0}.csl-table-wrap{overflow-y:auto;flex:1}.csl-table{width:100%;border-collapse:collapse;font-size:12.5px}.csl-table thead tr{position:sticky;top:0;z-index:1;background:#f5f5f5}.csl-table thead tr th{padding:8px 10px;text-align:left;font-size:10px;font-weight:600;color:#888;text-transform:uppercase;letter-spacing:.6px;border-bottom:1px solid #C4D0F9;white-space:nowrap}.csl-table tbody tr{border-bottom:1px solid rgba(0,0,0,.04);cursor:pointer;transition:background .1s ease}.csl-table tbody tr:hover{background:#f7faff}.csl-table tbody tr:last-child{border-bottom:none}.csl-table tbody tr td{padding:9px 10px;color:#272c5d}.csl-col-check{width:36px;text-align:center;padding:0 8px!important}.csl-col-check input[type=checkbox]{cursor:pointer;accent-color:#4465C9;width:14px;height:14px}.csl-col-key{font-family:monospace;font-size:11.5px;color:#535353;width:130px}.csl-col-name{font-weight:500}.csl-row--selected{background:#ebf0ff!important}.csl-row--custom-field .csl-col-key{color:#6b7fd4}.csl-empty{text-align:center;padding:32px 16px!important;color:#888;font-size:12.5px}.csl-panel--selected{overflow:hidden}.csl-ordered-list{flex:1;overflow-y:auto;padding:7px}.csl-ordered-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;flex:1;gap:8px;padding:20px;text-align:center}.csl-ordered-empty__icon{font-size:28px;color:#888;opacity:.35}.csl-ordered-empty p{font-size:12px;color:#535353;margin:0;line-height:1.5}.csl-ordered-item{display:flex;align-items:center;gap:5px;padding:6px 8px 6px 4px;margin-bottom:4px;border:1px solid #C4D0F9;border-radius:6px;background:#fff;transition:border-color .14s ease,background .14s ease}.csl-ordered-item:last-child{margin-bottom:0}.csl-ordered-item:hover{border-color:#8ea7f8;background:#f7faff}.csl-ordered-item__drag{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;width:20px;color:#888;font-size:11px;cursor:grab;padding:0 2px;-webkit-user-select:none;user-select:none}.csl-ordered-item__drag:active{cursor:grabbing}.csl-ordered-item__position{flex-shrink:0;width:19px;height:19px;border-radius:50%;background:#ebf0ff;color:#4465c9;font-size:10px;font-weight:700;display:flex;align-items:center;justify-content:center}.csl-ordered-item__code{flex-shrink:0;width:90px;font-family:monospace;font-size:11px;font-weight:600;color:#535353;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.csl-ordered-item__code--cf{color:#6b7fd4}.csl-ordered-item__desc{flex:1;height:24px;min-width:0;padding:0 6px;border:1px solid transparent;border-radius:4px;font-size:12px;color:#272c5d;background:transparent;transition:border-color .1s,background .1s}.csl-ordered-item__desc::placeholder{color:#888;font-style:italic}.csl-ordered-item__desc:hover{border-color:#c4d0f9;background:#fff}.csl-ordered-item__desc:focus{border-color:#4465c9;background:#fff;outline:none}.csl-ordered-item__remove{flex-shrink:0;background:none;border:none;padding:0 3px;font-size:12px;color:#888;cursor:pointer;line-height:1}.csl-ordered-item__remove:hover{color:#f78383}.csl-ordered-item.cdk-drag-animating{transition:transform .2s cubic-bezier(.25,.8,.25,1)}.csl-ordered-item__placeholder{width:100%;height:38px;border:2px dashed #C4D0F9;border-radius:6px;background:#f7faff}.cdk-drop-list-dragging .csl-ordered-item:not(.cdk-drag-placeholder){transition:transform .2s cubic-bezier(.25,.8,.25,1)}.cdk-drag-preview{display:flex;align-items:center;gap:6px;padding:8px 8px 8px 4px;border-radius:6px;background:#fff;box-shadow:0 4px 16px #4465c92e,0 1px 4px #0000001a;font-size:12px;font-weight:500;color:#272c5d;min-width:180px}.csl-footer{display:flex;align-items:center;justify-content:space-between;padding:13px 22px 16px;border-top:1px solid #C4D0F9;flex-shrink:0}.csl-footer__count{font-size:12px;color:#888;min-width:180px}.csl-footer__actions{display:flex;gap:10px}.csl-btn{display:inline-flex;align-items:center;gap:7px;padding:7px 18px;font-size:13px;font-weight:500;border-radius:6px;cursor:pointer;transition:background .12s ease,opacity .12s ease}.csl-btn--secondary{background:transparent;border:1px solid rgba(0,0,0,.16);color:#535353}.csl-btn--secondary:hover{background:#0000000a}.csl-btn--primary{background:#4465c9;border:1px solid transparent;color:#fff;min-width:130px;justify-content:center}.csl-btn--primary:hover:not([disabled]){background:#3c5dc4}.csl-btn--primary[disabled]{opacity:.42;cursor:not-allowed}.csl-save-prompt{display:flex;align-items:center;gap:10px;width:100%;flex-wrap:wrap}.csl-save-prompt__label{font-size:12.5px;font-weight:500;color:#272c5d;white-space:nowrap}.csl-save-prompt__input{flex:1;min-width:160px;height:32px;padding:0 10px;border:1px solid #C4D0F9;border-radius:6px;font-size:12px;color:#272c5d;background:#fff;outline:none;transition:border-color .1s}.csl-save-prompt__input:focus{border-color:#4465c9}.csl-save-prompt__input[disabled]{opacity:.5}.csl-save-prompt__actions{display:flex;gap:8px;flex-shrink:0}.csl-spinner{display:inline-block;width:14px;height:14px;border:2px solid #DBE4FF;border-top-color:#4465c9;border-radius:50%;animation:gps-spin .65s linear infinite}.csl-spinner--sm{width:11px;height:11px;border-width:2px}.csl-spinner--light{border-color:#ffffff59;border-top-color:#fff}@keyframes gps-spin{to{transform:rotate(360deg)}}.csl-tabbed{flex:2 1 0;min-width:0;display:flex;flex-direction:column;gap:8px}.csl-tabs{display:flex;gap:4px;border-bottom:1px solid #3C5DC4}.csl-tab{position:relative;flex:1 1 0;text-align:center;padding:6px 14px;border:none;border-bottom:2px solid transparent;background:none;color:#6b7591;font:inherit;font-weight:700;cursor:pointer}.csl-tab--active{color:#5272d3;border-bottom-color:#5272d3}.csl-tab-dot{display:inline-block;width:7px;height:7px;margin-left:6px;border-radius:50%;background:var(--orange-algorima, #f59d0f);vertical-align:middle}.csl-panels--inner{flex:1 1 auto;min-height:0}.csl-panel--filters{flex:1 1 auto;min-height:0;overflow:auto}.csl-editor{overflow:auto;min-height:0}.csl-editor ::ng-deep>alg-presentation-profile-editor{display:block;width:100%;height:100%}\n"],
1625
1838
  dependencies: [
1626
1839
  {
1627
1840
  kind: "ngmodule",
@@ -1631,11 +1844,29 @@ var PresentationProfileComponent = class PresentationProfileComponent {
1631
1844
  kind: "ngmodule",
1632
1845
  type: FormsModule
1633
1846
  },
1847
+ {
1848
+ kind: "directive",
1849
+ type: i1$3.NgSelectOption,
1850
+ selector: "option",
1851
+ inputs: ["ngValue", "value"]
1852
+ },
1853
+ {
1854
+ kind: "directive",
1855
+ type: i1$3.ɵNgSelectMultipleOption,
1856
+ selector: "option",
1857
+ inputs: ["ngValue", "value"]
1858
+ },
1634
1859
  {
1635
1860
  kind: "directive",
1636
1861
  type: i1$3.DefaultValueAccessor,
1637
1862
  selector: "input:not([type=checkbox]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[ngModel],[ngDefaultControl]"
1638
1863
  },
1864
+ {
1865
+ kind: "directive",
1866
+ type: i1$3.SelectControlValueAccessor,
1867
+ selector: "select:not([multiple]):not([ngNoCva])[formControlName],select:not([multiple]):not([ngNoCva])[formControl],select:not([multiple]):not([ngNoCva])[ngModel]",
1868
+ inputs: ["compareWith"]
1869
+ },
1639
1870
  {
1640
1871
  kind: "directive",
1641
1872
  type: i1$3.NgControlStatus,
@@ -1686,8 +1917,8 @@ i0.ɵɵngDeclareClassMetadata({
1686
1917
  ],
1687
1918
  providers: [PresentationProfileService],
1688
1919
  changeDetection: ChangeDetectionStrategy.Eager,
1689
- template: "<!-- ── Header ─────────────────────────────────────────────────────────────── -->\r\n<div class=\"csl-header\">\r\n <div class=\"csl-header__left\">\r\n <h4 class=\"csl-title\">{{ svc.config?.title || 'Sélection des colonnes' }}</h4>\r\n </div>\r\n @if (!svc.isEmbedded) {\r\n <button class=\"csl-icon-btn\" type=\"button\" (click)=\"svc.cancel()\" aria-label=\"Fermer\">&#x2715;</button>\r\n }\r\n</div>\r\n\r\n<!-- ── Body : vues à gauche, éditeur standard de la vue choisie à droite ── -->\r\n<div class=\"csl-body\">\r\n <div class=\"csl-panels\">\r\n\r\n <!-- ── GAUCHE : vues personnalisées ─────────────────────────────────── -->\r\n <div class=\"csl-panel csl-panel--groups\">\r\n <div class=\"csl-panel__header\">\r\n <span class=\"csl-panel__label\">Vues personnalisées</span>\r\n <span class=\"csl-badge\">{{ svc.views.length }}</span>\r\n </div>\r\n <ul class=\"csl-group-list csl-scroll\">\r\n @for (view of svc.views; track view.id) {\r\n <li class=\"csl-group-item csl-view-item\"\r\n [class.csl-group-item--active]=\"svc.selectedView?.id === view.id\"\r\n [class.csl-group-item--standard]=\"view.isDefault\"\r\n [class.csl-group-item--profile]=\"!view.isDefault\"\r\n (click)=\"svc.selectView(view)\">\r\n @if (svc.renamingId === view.id) {\r\n <input class=\"gps-rename-input\" type=\"text\" maxlength=\"100\"\r\n [(ngModel)]=\"svc.renameLabel\"\r\n (click)=\"$event.stopPropagation()\"\r\n (keydown.enter)=\"svc.confirmRename(view)\"\r\n (keydown.escape)=\"svc.cancelRename()\">\r\n <div class=\"gps-rename-actions\" (click)=\"$event.stopPropagation()\">\r\n <button class=\"gps-rename-btn gps-rename-btn--ok\" type=\"button\" title=\"Renommer\" (click)=\"svc.confirmRename(view)\">\r\n <i class=\"fa fa-check\"></i>\r\n </button>\r\n <button class=\"gps-rename-btn gps-rename-btn--cancel\" type=\"button\" title=\"Annuler\" (click)=\"svc.cancelRename()\">\r\n <i class=\"fa fa-times\"></i>\r\n </button>\r\n </div>\r\n } @else {\r\n <span class=\"csl-group-item__name\" [title]=\"view.label\">\r\n @if (view.isDefault) { <i class=\"fa fa-lock csl-view-icon\" title=\"Vue par défaut\"></i> }\r\n {{ view.label }}\r\n </span>\r\n <div class=\"csl-group-item__meta\">\r\n @if (view.isCurrent) {\r\n <span class=\"csl-badge csl-badge--primary csl-badge--sm\" title=\"Vue affichée par la grille\">\r\n <i class=\"fa fa-eye\"></i>\r\n </span>\r\n }\r\n <div class=\"gps-profile-actions\" (click)=\"$event.stopPropagation()\">\r\n @if (svc.canEdit(view)) {\r\n <button class=\"gps-profile-btn\" type=\"button\" title=\"Renommer\" (click)=\"svc.startRename(view)\">\r\n <i class=\"fa fa-pencil\"></i>\r\n </button>\r\n }\r\n <button class=\"gps-profile-btn\" type=\"button\" title=\"Dupliquer\" (click)=\"svc.duplicateView(view)\">\r\n <i class=\"fa fa-files-o\"></i>\r\n </button>\r\n @if (!view.isDefault) {\r\n <button class=\"gps-profile-btn gps-profile-btn--danger\" type=\"button\" title=\"Supprimer\" (click)=\"svc.deleteView(view)\">\r\n <i class=\"fa fa-trash-o\"></i>\r\n </button>\r\n }\r\n </div>\r\n </div>\r\n }\r\n </li>\r\n }\r\n @empty {\r\n <li class=\"csl-group-section-label\">Aucune vue enregistrée</li>\r\n }\r\n </ul>\r\n @if (svc.isReadOnly) {\r\n <div class=\"csl-view-note\">\r\n <i class=\"fa fa-info-circle\"></i>\r\n Vue par défaut en lecture seule : « Appliquer » crée une nouvelle vue personnelle.\r\n </div>\r\n }\r\n </div>\r\n\r\n <!-- ── DROITE : éditeur standard de la vue choisie (Propriétés, Colonnes, Tri, Filtres) ── -->\r\n <div class=\"csl-tabbed csl-editor\">\r\n <ng-container #editorHost></ng-container>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<!-- ── Footer ─────────────────────────────────────────────────────────────── -->\r\n<div class=\"csl-footer\">\r\n <span class=\"csl-footer__count\">\r\n @if (svc.message) {\r\n <span class=\"csl-footer__error\">{{ svc.message }}</span>\r\n } @else if (svc.selectedView) {\r\n Vue « {{ svc.selectedView.label }} » — « Appliquer » l'enregistre et l'affiche dans la grille\r\n }\r\n </span>\r\n <div class=\"csl-footer__actions\">\r\n @if (!svc.isEmbedded) {\r\n <button class=\"csl-btn csl-btn--secondary\" type=\"button\" (click)=\"svc.cancel()\">Annuler</button>\r\n }\r\n <button class=\"csl-btn csl-btn--primary\" type=\"button\"\r\n (click)=\"apply()\" [disabled]=\"!svc.selectedView || svc.isSaving || svc.isLoading\">\r\n @if (svc.isSaving) {\r\n <span class=\"csl-spinner csl-spinner--sm csl-spinner--light\"></span>&nbsp;\r\n }\r\n Appliquer\r\n </button>\r\n </div>\r\n</div>\r\n",
1690
- styles: [".home-page{font-family:Open sans,sans-serif;background:#fff;-webkit-font-smoothing:antialiased;height:100%;width:100%;padding:16px}.main-container{margin:0 50px}.main-container-modal{width:calc(100% - 50px);margin:10px 25px 0}.moyen-titre{font-weight:700;font-size:24px;color:#4d5a81;margin:8px 0;border-bottom:solid 1px #DBE4FF}.grand-titre{font-weight:700;font-size:28px;color:#4d5a81;margin:0 0 8px}.petit-titre{font-weight:700;font-size:16px;color:#4d5a81;margin:0 0 8px}.petit-titre.underlined{border-bottom:solid 1px #4D5A81}.paragraph{padding:0 15px}.paragraph-highlight{padding:5px 15px 0 12px;border-left:5px solid #8EA7F8;border-bottom:1px solid #DBE4FF;border-top:1px solid #DBE4FF;border-right:1px solid #DBE4FF;background-color:#f7faff}.highlight{background-color:#f7faff;border:1px solid #DBE4FF;border-radius:5px;padding:15px;color:#3c5dc4;margin:0 0 16px}.highlight p{margin-bottom:0}.highlight:before{position:relative;display:block;float:left;width:24px;height:24px;content:\" \";background-size:24px 24px;-webkit-background-size:24px 24px;background-image:url('data:image/svg+xml,<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"53.294\" height=\"50.629\" viewBox=\"0 0 53.294 50.629\">%0D%0A <path id=\"allerg\\e8ne\" d=\"M830.494,25.793l-5.814,6.783.727,8.963-8.721,1.938-4.6,7.752L803.847,47.6l-8.236,3.634-4.6-7.51-8.721-1.938.727-8.963L777.2,26.035l5.814-6.783-.727-8.963,8.721-1.938L795.61.6l8.236,3.634L812.083.6l4.6,7.752,8.721,1.938-.727,8.963Zm-24.467,2.422V13.681h-4.845V28.216Zm0,9.69V33.06h-4.845v4.845Z\" transform=\"translate(-777.2 -0.6)\"/>%0D%0A</svg>%0D%0A');background-repeat:no-repeat;margin:0 8px 24px 0;filter:invert(31%) sepia(51%) saturate(1323%) hue-rotate(199deg) brightness(99%) contrast(94%)}.notification{background-color:#dbe4ff;border:1px solid #C4D0F9;border-radius:5px;color:#4d5a81;margin:16px;padding:5px 15px;text-align:justify}.notification:before{position:relative;display:block;float:left;width:24px;height:24px;content:\" \";background-size:24px 24px;-webkit-background-size:24px 24px;background-image:url('data:image/svg+xml,<svg aria-hidden=\"true\" focusable=\"false\" data-prefix=\"fas\" data-icon=\"info-circle\" class=\"svg-inline--fa fa-info-circle fa-w-16\" role=\"img\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\"><path fill=\"currentColor\" d=\"M256 8C119.043 8 8 119.083 8 256c0 136.997 111.043 248 248 248s248-111.003 248-248C504 119.083 392.957 8 256 8zm0 110c23.196 0 42 18.804 42 42s-18.804 42-42 42-42-18.804-42-42 18.804-42 42-42zm56 254c0 6.627-5.373 12-12 12h-88c-6.627 0-12-5.373-12-12v-24c0-6.627 5.373-12 12-12h12v-64h-12c-6.627 0-12-5.373-12-12v-24c0-6.627 5.373-12 12-12h64c6.627 0 12 5.373 12 12v100h12c6.627 0 12 5.373 12 12v24z\"></path></svg>');background-repeat:no-repeat;margin:0 8px 0 0;filter:invert(31%) sepia(8%) saturate(2329%) hue-rotate(188deg) brightness(103%) contrast(85%)}.notification-text{padding:0 15px 0 30px;font-size:16px}:host{display:flex;flex-direction:column;height:100%}.csl-header{display:flex;align-items:center;justify-content:space-between;padding:6px 8px 6px 16px;background:#5272d3;border-bottom:1px solid #3C5DC4;flex-shrink:0}.csl-header__left{display:flex;flex-direction:column}.csl-title{font-size:15px;font-weight:600;color:#fff;letter-spacing:-.2px;line-height:1.4;margin:0}.csl-icon-btn{display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;border-radius:50%;border:none;background:transparent;color:#fffc;font-size:14px;cursor:pointer;flex-shrink:0;margin-left:16px;transition:background .1s ease}.csl-icon-btn:hover{background:#ffffff26;color:#fff}.gps-tabs{display:flex;gap:2px}.gps-tab{display:inline-flex;align-items:center;gap:5px;padding:7px 18px;border:none;background:#ffffff1f;color:#ffffffb8;font-size:13px;font-weight:500;cursor:pointer;border-radius:6px 6px 0 0;transition:background .1s ease,color .1s ease}.gps-tab:hover:not(.gps-tab--active){background:#fff3;color:#fff}.gps-tab--active{background:#fff;color:#4465c9;font-weight:600}.csl-body{flex:1;overflow:hidden;padding:16px 20px}.csl-loading{display:flex;align-items:center;justify-content:center;gap:10px;min-height:200px;color:#535353;font-size:13px}.csl-panels{display:grid;grid-template-columns:240px 1fr 320px;grid-template-rows:minmax(0,1fr);gap:12px;height:calc(70vh - 160px);min-height:380px;overflow:hidden}.csl-panel{min-height:0}.csl-scroll{flex:1 1 auto;min-height:0;overflow-y:auto}.csl-view-icon{margin-right:4px;font-size:11px;color:#888}.csl-view-note{flex-shrink:0;padding:8px 12px;border-top:1px solid #C4D0F9;font-size:11.5px;color:#535353;background:#f5f5f5}.csl-view-note .fa{color:#4465c9;margin-right:4px}.csl-attribute-tag{display:inline-block;margin-left:6px;padding:0 6px;border-radius:8px;font-size:10px;font-weight:600;color:#fff;background:#6b7fd4;vertical-align:middle}.csl-group-item--active .gps-profile-actions{opacity:1}.csl-footer__error{color:#dc3545}.csl-panel{display:flex;flex-direction:column;border:1px solid #C4D0F9;border-radius:10px;overflow:hidden;background:#fff}.csl-panel__header{display:flex;align-items:center;justify-content:space-between;padding:10px 13px;border-bottom:1px solid #C4D0F9;background:#f5f5f5;flex-shrink:0;gap:8px}.csl-panel__label{font-size:10.5px;font-weight:600;text-transform:uppercase;letter-spacing:.9px;color:#535353;flex-shrink:0}.csl-group-list{list-style:none;margin:0;padding:6px;overflow-y:auto;flex:1}.csl-group-item{display:flex;align-items:center;justify-content:space-between;padding:7px 8px;border-radius:6px;cursor:pointer;transition:background .1s ease;min-height:34px}.csl-group-item:hover{background:#f7faff}.csl-group-item:hover .gps-profile-actions{opacity:1}.csl-group-item--active{background:#ebf0ff}.csl-group-item--active .csl-group-item__name{color:#4465c9;font-weight:600}.csl-group-item--standard{border-left:3px solid #4465C9;padding-left:5px}.csl-group-item--model{border-left:3px solid #6B7FD4;padding-left:5px}.csl-group-item--profile{border-left:3px solid #4465C9;padding-left:5px}.csl-group-item__name{font-size:12.5px;color:#272c5d;flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;margin-right:4px}.csl-group-item__meta{display:flex;align-items:center;gap:4px;flex-shrink:0}.gps-profile-actions{display:flex;align-items:center;gap:2px;flex-shrink:0;opacity:0;transition:opacity .1s ease}.gps-profile-btn{display:inline-flex;align-items:center;justify-content:center;width:22px;height:22px;border:none;background:none;border-radius:4px;font-size:11px;color:#888;cursor:pointer;padding:0;transition:background .1s,color .1s}.gps-profile-btn:hover{background:#00000014;color:#4465c9}.gps-profile-btn--danger:hover{background:#dc35451a;color:#dc3545}.gps-rename-input{flex:1;height:24px;border:1px solid #4465C9;border-radius:4px;padding:0 6px;font-size:12px;color:#272c5d;background:#fff;outline:none;min-width:0;margin-right:4px}.gps-rename-actions{display:flex;align-items:center;gap:2px;flex-shrink:0}.gps-rename-btn{display:inline-flex;align-items:center;justify-content:center;width:22px;height:22px;border:none;border-radius:4px;font-size:11px;cursor:pointer;padding:0}.gps-rename-btn--ok{background:#4465c9;color:#fff}.gps-rename-btn--ok:hover{background:#3c5dc4}.gps-rename-btn--cancel{background:#00000014;color:#535353}.gps-rename-btn--cancel:hover{background:#00000026}.gps-new-profile{color:#4465c9;font-size:12px;font-weight:500;opacity:.75;justify-content:flex-start;gap:4px}.gps-new-profile:hover{opacity:1;background:#ebf0ff}.csl-group-section-label{padding:8px 8px 4px;font-size:9.5px;font-weight:700;text-transform:uppercase;letter-spacing:.8px;color:#888;list-style:none}.csl-group-divider{height:1px;background:#c4d0f9;margin:6px 8px;list-style:none}.csl-badge{display:inline-flex;align-items:center;justify-content:center;min-width:20px;height:18px;padding:0 5px;border-radius:9px;background:#00000012;color:#535353;font-size:10px;font-weight:600}.csl-badge--primary{background:#4465c9;color:#fff}.csl-badge--sm{height:16px;min-width:16px;font-size:9px;padding:0 4px}.csl-search{flex:1;height:28px;border:1px solid #C4D0F9;border-radius:6px;padding:0 8px;font-size:12px;color:#272c5d;background:#fff;outline:none;transition:border-color .1s ease}.csl-search:focus{border-color:#6684e0}.csl-table-wrap{overflow-y:auto;flex:1}.csl-table{width:100%;border-collapse:collapse;font-size:12.5px}.csl-table thead tr{position:sticky;top:0;z-index:1;background:#f5f5f5}.csl-table thead tr th{padding:8px 10px;text-align:left;font-size:10px;font-weight:600;color:#888;text-transform:uppercase;letter-spacing:.6px;border-bottom:1px solid #C4D0F9;white-space:nowrap}.csl-table tbody tr{border-bottom:1px solid rgba(0,0,0,.04);cursor:pointer;transition:background .1s ease}.csl-table tbody tr:hover{background:#f7faff}.csl-table tbody tr:last-child{border-bottom:none}.csl-table tbody tr td{padding:9px 10px;color:#272c5d}.csl-col-check{width:36px;text-align:center;padding:0 8px!important}.csl-col-check input[type=checkbox]{cursor:pointer;accent-color:#4465C9;width:14px;height:14px}.csl-col-key{font-family:monospace;font-size:11.5px;color:#535353;width:130px}.csl-col-name{font-weight:500}.csl-row--selected{background:#ebf0ff!important}.csl-row--custom-field .csl-col-key{color:#6b7fd4}.csl-empty{text-align:center;padding:32px 16px!important;color:#888;font-size:12.5px}.csl-panel--selected{overflow:hidden}.csl-ordered-list{flex:1;overflow-y:auto;padding:7px}.csl-ordered-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;flex:1;gap:8px;padding:20px;text-align:center}.csl-ordered-empty__icon{font-size:28px;color:#888;opacity:.35}.csl-ordered-empty p{font-size:12px;color:#535353;margin:0;line-height:1.5}.csl-ordered-item{display:flex;align-items:center;gap:5px;padding:6px 8px 6px 4px;margin-bottom:4px;border:1px solid #C4D0F9;border-radius:6px;background:#fff;transition:border-color .14s ease,background .14s ease}.csl-ordered-item:last-child{margin-bottom:0}.csl-ordered-item:hover{border-color:#8ea7f8;background:#f7faff}.csl-ordered-item__drag{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;width:20px;color:#888;font-size:11px;cursor:grab;padding:0 2px;-webkit-user-select:none;user-select:none}.csl-ordered-item__drag:active{cursor:grabbing}.csl-ordered-item__position{flex-shrink:0;width:19px;height:19px;border-radius:50%;background:#ebf0ff;color:#4465c9;font-size:10px;font-weight:700;display:flex;align-items:center;justify-content:center}.csl-ordered-item__code{flex-shrink:0;width:90px;font-family:monospace;font-size:11px;font-weight:600;color:#535353;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.csl-ordered-item__code--cf{color:#6b7fd4}.csl-ordered-item__desc{flex:1;height:24px;min-width:0;padding:0 6px;border:1px solid transparent;border-radius:4px;font-size:12px;color:#272c5d;background:transparent;transition:border-color .1s,background .1s}.csl-ordered-item__desc::placeholder{color:#888;font-style:italic}.csl-ordered-item__desc:hover{border-color:#c4d0f9;background:#fff}.csl-ordered-item__desc:focus{border-color:#4465c9;background:#fff;outline:none}.csl-ordered-item__remove{flex-shrink:0;background:none;border:none;padding:0 3px;font-size:12px;color:#888;cursor:pointer;line-height:1}.csl-ordered-item__remove:hover{color:#f78383}.csl-ordered-item.cdk-drag-animating{transition:transform .2s cubic-bezier(.25,.8,.25,1)}.csl-ordered-item__placeholder{width:100%;height:38px;border:2px dashed #C4D0F9;border-radius:6px;background:#f7faff}.cdk-drop-list-dragging .csl-ordered-item:not(.cdk-drag-placeholder){transition:transform .2s cubic-bezier(.25,.8,.25,1)}.cdk-drag-preview{display:flex;align-items:center;gap:6px;padding:8px 8px 8px 4px;border-radius:6px;background:#fff;box-shadow:0 4px 16px #4465c92e,0 1px 4px #0000001a;font-size:12px;font-weight:500;color:#272c5d;min-width:180px}.csl-footer{display:flex;align-items:center;justify-content:space-between;padding:13px 22px 16px;border-top:1px solid #C4D0F9;flex-shrink:0}.csl-footer__count{font-size:12px;color:#888;min-width:180px}.csl-footer__actions{display:flex;gap:10px}.csl-btn{display:inline-flex;align-items:center;gap:7px;padding:7px 18px;font-size:13px;font-weight:500;border-radius:6px;cursor:pointer;transition:background .12s ease,opacity .12s ease}.csl-btn--secondary{background:transparent;border:1px solid rgba(0,0,0,.16);color:#535353}.csl-btn--secondary:hover{background:#0000000a}.csl-btn--primary{background:#4465c9;border:1px solid transparent;color:#fff;min-width:130px;justify-content:center}.csl-btn--primary:hover:not([disabled]){background:#3c5dc4}.csl-btn--primary[disabled]{opacity:.42;cursor:not-allowed}.csl-save-prompt{display:flex;align-items:center;gap:10px;width:100%;flex-wrap:wrap}.csl-save-prompt__label{font-size:12.5px;font-weight:500;color:#272c5d;white-space:nowrap}.csl-save-prompt__input{flex:1;min-width:160px;height:32px;padding:0 10px;border:1px solid #C4D0F9;border-radius:6px;font-size:12px;color:#272c5d;background:#fff;outline:none;transition:border-color .1s}.csl-save-prompt__input:focus{border-color:#4465c9}.csl-save-prompt__input[disabled]{opacity:.5}.csl-save-prompt__actions{display:flex;gap:8px;flex-shrink:0}.csl-spinner{display:inline-block;width:14px;height:14px;border:2px solid #DBE4FF;border-top-color:#4465c9;border-radius:50%;animation:gps-spin .65s linear infinite}.csl-spinner--sm{width:11px;height:11px;border-width:2px}.csl-spinner--light{border-color:#ffffff59;border-top-color:#fff}@keyframes gps-spin{to{transform:rotate(360deg)}}.csl-tabbed{flex:2 1 0;min-width:0;display:flex;flex-direction:column;gap:8px}.csl-tabs{display:flex;gap:4px;border-bottom:1px solid #3C5DC4}.csl-tab{position:relative;flex:1 1 0;text-align:center;padding:6px 14px;border:none;border-bottom:2px solid transparent;background:none;color:#6b7591;font:inherit;font-weight:700;cursor:pointer}.csl-tab--active{color:#5272d3;border-bottom-color:#5272d3}.csl-tab-dot{display:inline-block;width:7px;height:7px;margin-left:6px;border-radius:50%;background:var(--orange-algorima, #f59d0f);vertical-align:middle}.csl-panels--inner{flex:1 1 auto;min-height:0}.csl-panel--filters{flex:1 1 auto;min-height:0;overflow:auto}.csl-editor{overflow:auto;min-height:0}\n"]
1920
+ template: "<!-- ── Header ─────────────────────────────────────────────────────────────── -->\r\n<div class=\"csl-header\">\r\n <div class=\"csl-header__left\">\r\n <h4 class=\"csl-title\">{{ svc.config?.title || 'Sélection des colonnes' }}</h4>\r\n </div>\r\n @if (!svc.isEmbedded) {\r\n <button class=\"csl-icon-btn\" type=\"button\" (click)=\"svc.cancel()\" aria-label=\"Fermer\">&#x2715;</button>\r\n }\r\n</div>\r\n\r\n<!-- ── Body : vues à gauche, éditeur standard de la vue choisie à droite ── -->\r\n<div class=\"csl-body\">\r\n <div class=\"csl-panels\">\r\n\r\n <!-- ── GAUCHE : vues personnalisées ─────────────────────────────────── -->\r\n <div class=\"csl-panel csl-panel--groups\">\r\n <div class=\"csl-panel__header\">\r\n <span class=\"csl-panel__label\">Vues personnalisées</span>\r\n <span class=\"csl-badge\">{{ svc.views.length }}</span>\r\n <button class=\"gps-profile-btn csl-add-view\" type=\"button\" title=\"Nouvelle vue (copie de la vue choisie)\"\r\n [disabled]=\"svc.isLoading || svc.isSaving\" (click)=\"svc.createView()\">\r\n <i class=\"fa fa-plus\"></i>\r\n </button>\r\n </div>\r\n <ul class=\"csl-group-list csl-scroll\">\r\n @for (view of svc.views; track view.id) {\r\n <li class=\"csl-group-item csl-view-item\"\r\n [class.csl-group-item--active]=\"svc.selectedView?.id === view.id\"\r\n [class.csl-group-item--standard]=\"view.isDefault\"\r\n [class.csl-group-item--profile]=\"!view.isDefault\"\r\n (click)=\"svc.selectView(view)\">\r\n @if (svc.renamingId === view.id) {\r\n <input class=\"gps-rename-input\" type=\"text\" maxlength=\"100\"\r\n [(ngModel)]=\"svc.renameLabel\"\r\n (click)=\"$event.stopPropagation()\"\r\n (keydown.enter)=\"svc.confirmRename(view)\"\r\n (keydown.escape)=\"svc.cancelRename()\">\r\n <div class=\"gps-rename-actions\" (click)=\"$event.stopPropagation()\">\r\n <button class=\"gps-rename-btn gps-rename-btn--ok\" type=\"button\" title=\"Renommer\" (click)=\"svc.confirmRename(view)\">\r\n <i class=\"fa fa-check\"></i>\r\n </button>\r\n <button class=\"gps-rename-btn gps-rename-btn--cancel\" type=\"button\" title=\"Annuler\" (click)=\"svc.cancelRename()\">\r\n <i class=\"fa fa-times\"></i>\r\n </button>\r\n </div>\r\n } @else {\r\n <span class=\"csl-group-item__name\" [title]=\"view.label\">\r\n @if (view.isDefault) { <i class=\"fa fa-lock csl-view-icon\" title=\"Vue par défaut\"></i> }\r\n {{ view.label }}\r\n </span>\r\n <div class=\"csl-group-item__meta\">\r\n @if (view.isCurrent) {\r\n <span class=\"csl-badge csl-badge--primary csl-badge--sm\" title=\"Vue affichée par la grille\">\r\n <i class=\"fa fa-eye\"></i>\r\n </span>\r\n }\r\n <div class=\"gps-profile-actions\" (click)=\"$event.stopPropagation()\">\r\n @if (svc.canEdit(view)) {\r\n <button class=\"gps-profile-btn\" type=\"button\" title=\"Renommer\" (click)=\"svc.startRename(view)\">\r\n <i class=\"fa fa-pencil\"></i>\r\n </button>\r\n }\r\n <button class=\"gps-profile-btn\" type=\"button\" title=\"Dupliquer\" (click)=\"svc.duplicateView(view)\">\r\n <i class=\"fa fa-files-o\"></i>\r\n </button>\r\n @if (!view.isDefault) {\r\n <button class=\"gps-profile-btn gps-profile-btn--danger\" type=\"button\" title=\"Supprimer\" (click)=\"svc.deleteView(view)\">\r\n <i class=\"fa fa-trash-o\"></i>\r\n </button>\r\n }\r\n </div>\r\n </div>\r\n }\r\n </li>\r\n }\r\n @empty {\r\n <li class=\"csl-group-section-label\">Aucune vue enregistrée</li>\r\n }\r\n </ul>\r\n @if (svc.isReadOnly) {\r\n <div class=\"csl-view-note\">\r\n <i class=\"fa fa-info-circle\"></i>\r\n Vue par défaut en lecture seule : « Appliquer » crée une nouvelle vue personnelle.\r\n </div>\r\n }\r\n </div>\r\n\r\n <!-- ── DROITE : éditeur standard de la vue choisie (Colonnes, Tri, Filtres, Carte) ── -->\r\n <div class=\"csl-tabbed csl-editor\">\r\n <ng-container #editorHost></ng-container>\r\n </div>\r\n\r\n <!-- Onglet « Carte » de l'éditeur : carte de la vue choisie, à défaut la carte par défaut de la table -->\r\n <ng-template #cardTab>\r\n <div class=\"csl-card\">\r\n <p class=\"csl-card__hint\">\r\n @if (svc.usesDefaultCard) {\r\n Cette vue affiche la carte par défaut de la table : vos choix lui donnent sa propre carte.\r\n } @else {\r\n Carte propre à la vue « {{ svc.selectedView?.label }} ».\r\n }\r\n </p>\r\n @for (slot of svc.cardSlotList; track slot.name) {\r\n <label class=\"csl-card__slot\">\r\n <span>{{ slot.label }}</span>\r\n <select class=\"form-control\" [id]=\"'card-slot-' + slot.name\" [(ngModel)]=\"svc.cardSlots[slot.name]\">\r\n <option value=\"\">{{ slot.name === 'image' ? 'Aucune' : 'Aucun' }}</option>\r\n @for (option of (slot.name === 'image' ? svc.cardImageOptions : svc.cardOptions); track option.key) {\r\n <option [value]=\"option.key\">{{ option.label }}</option>\r\n }\r\n </select>\r\n </label>\r\n }\r\n @if (!svc.usesDefaultCard && !(svc.selectedView?.isDefault)) {\r\n <div class=\"csl-card__actions\">\r\n <button class=\"csl-btn csl-btn--secondary\" type=\"button\" (click)=\"svc.resetCard()\"\r\n title=\"La vue n'a plus de carte propre : elle affiche la carte par défaut de la table\">\r\n Revenir à la carte par défaut\r\n </button>\r\n </div>\r\n }\r\n </div>\r\n </ng-template>\r\n </div>\r\n</div>\r\n\r\n<!-- ── Footer ─────────────────────────────────────────────────────────────── -->\r\n<div class=\"csl-footer\">\r\n <span class=\"csl-footer__count\">\r\n @if (svc.message) {\r\n <span class=\"csl-footer__error\">{{ svc.message }}</span>\r\n } @else if (svc.selectedView) {\r\n Vue « {{ svc.selectedView.label }} » — « Appliquer » l'enregistre et l'affiche dans la grille\r\n }\r\n </span>\r\n <div class=\"csl-footer__actions\">\r\n @if (!svc.isEmbedded) {\r\n <button class=\"csl-btn csl-btn--secondary\" type=\"button\" (click)=\"svc.cancel()\">Annuler</button>\r\n }\r\n <button class=\"csl-btn csl-btn--primary\" type=\"button\"\r\n (click)=\"apply()\" [disabled]=\"!svc.selectedView || svc.isSaving || svc.isLoading\">\r\n @if (svc.isSaving) {\r\n <span class=\"csl-spinner csl-spinner--sm csl-spinner--light\"></span>&nbsp;\r\n }\r\n Appliquer\r\n </button>\r\n </div>\r\n</div>\r\n",
1921
+ styles: [".home-page{font-family:Open sans,sans-serif;background:#fff;-webkit-font-smoothing:antialiased;height:100%;width:100%;padding:16px}.main-container{margin:0 50px}.main-container-modal{width:calc(100% - 50px);margin:10px 25px 0}.moyen-titre{font-weight:700;font-size:24px;color:#4d5a81;margin:8px 0;border-bottom:solid 1px #DBE4FF}.grand-titre{font-weight:700;font-size:28px;color:#4d5a81;margin:0 0 8px}.petit-titre{font-weight:700;font-size:16px;color:#4d5a81;margin:0 0 8px}.petit-titre.underlined{border-bottom:solid 1px #4D5A81}.paragraph{padding:0 15px}.paragraph-highlight{padding:5px 15px 0 12px;border-left:5px solid #8EA7F8;border-bottom:1px solid #DBE4FF;border-top:1px solid #DBE4FF;border-right:1px solid #DBE4FF;background-color:#f7faff}.highlight{background-color:#f7faff;border:1px solid #DBE4FF;border-radius:5px;padding:15px;color:#3c5dc4;margin:0 0 16px}.highlight p{margin-bottom:0}.highlight:before{position:relative;display:block;float:left;width:24px;height:24px;content:\" \";background-size:24px 24px;-webkit-background-size:24px 24px;background-image:url('data:image/svg+xml,<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"53.294\" height=\"50.629\" viewBox=\"0 0 53.294 50.629\">%0D%0A <path id=\"allerg\\e8ne\" d=\"M830.494,25.793l-5.814,6.783.727,8.963-8.721,1.938-4.6,7.752L803.847,47.6l-8.236,3.634-4.6-7.51-8.721-1.938.727-8.963L777.2,26.035l5.814-6.783-.727-8.963,8.721-1.938L795.61.6l8.236,3.634L812.083.6l4.6,7.752,8.721,1.938-.727,8.963Zm-24.467,2.422V13.681h-4.845V28.216Zm0,9.69V33.06h-4.845v4.845Z\" transform=\"translate(-777.2 -0.6)\"/>%0D%0A</svg>%0D%0A');background-repeat:no-repeat;margin:0 8px 24px 0;filter:invert(31%) sepia(51%) saturate(1323%) hue-rotate(199deg) brightness(99%) contrast(94%)}.notification{background-color:#dbe4ff;border:1px solid #C4D0F9;border-radius:5px;color:#4d5a81;margin:16px;padding:5px 15px;text-align:justify}.notification:before{position:relative;display:block;float:left;width:24px;height:24px;content:\" \";background-size:24px 24px;-webkit-background-size:24px 24px;background-image:url('data:image/svg+xml,<svg aria-hidden=\"true\" focusable=\"false\" data-prefix=\"fas\" data-icon=\"info-circle\" class=\"svg-inline--fa fa-info-circle fa-w-16\" role=\"img\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\"><path fill=\"currentColor\" d=\"M256 8C119.043 8 8 119.083 8 256c0 136.997 111.043 248 248 248s248-111.003 248-248C504 119.083 392.957 8 256 8zm0 110c23.196 0 42 18.804 42 42s-18.804 42-42 42-42-18.804-42-42 18.804-42 42-42zm56 254c0 6.627-5.373 12-12 12h-88c-6.627 0-12-5.373-12-12v-24c0-6.627 5.373-12 12-12h12v-64h-12c-6.627 0-12-5.373-12-12v-24c0-6.627 5.373-12 12-12h64c6.627 0 12 5.373 12 12v100h12c6.627 0 12 5.373 12 12v24z\"></path></svg>');background-repeat:no-repeat;margin:0 8px 0 0;filter:invert(31%) sepia(8%) saturate(2329%) hue-rotate(188deg) brightness(103%) contrast(85%)}.notification-text{padding:0 15px 0 30px;font-size:16px}:host{display:flex;flex-direction:column;height:100%}.csl-header{display:flex;align-items:center;justify-content:space-between;padding:6px 8px 6px 16px;background:#5272d3;border-bottom:1px solid #3C5DC4;flex-shrink:0}.csl-header__left{display:flex;flex-direction:column}.csl-title{font-size:15px;font-weight:600;color:#fff;letter-spacing:-.2px;line-height:1.4;margin:0}.csl-icon-btn{display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;border-radius:50%;border:none;background:transparent;color:#fffc;font-size:14px;cursor:pointer;flex-shrink:0;margin-left:16px;transition:background .1s ease}.csl-icon-btn:hover{background:#ffffff26;color:#fff}.gps-tabs{display:flex;gap:2px}.gps-tab{display:inline-flex;align-items:center;gap:5px;padding:7px 18px;border:none;background:#ffffff1f;color:#ffffffb8;font-size:13px;font-weight:500;cursor:pointer;border-radius:6px 6px 0 0;transition:background .1s ease,color .1s ease}.gps-tab:hover:not(.gps-tab--active){background:#fff3;color:#fff}.gps-tab--active{background:#fff;color:#4465c9;font-weight:600}.csl-body{flex:1;overflow:hidden;padding:16px 20px}.csl-loading{display:flex;align-items:center;justify-content:center;gap:10px;min-height:200px;color:#535353;font-size:13px}.csl-panel--groups .csl-panel__header{justify-content:flex-start}.csl-panel--groups .csl-panel__header .csl-panel__label{margin-right:auto}.csl-card{padding:12px 16px;display:flex;flex-direction:column;gap:8px;max-width:560px}.csl-card__hint{margin:0 0 4px;font-size:12px;opacity:.8}.csl-card__slot{display:grid;grid-template-columns:80px minmax(0,1fr);align-items:center;gap:10px;margin:0;font-weight:400}.csl-card__slot span{font-weight:600}.csl-card__actions{margin-top:4px}.csl-panels{display:grid;grid-template-columns:240px minmax(0,1fr);grid-template-rows:minmax(0,1fr);gap:12px;height:calc(70vh - 160px);min-height:380px;overflow:hidden}.csl-panel{min-height:0}.csl-scroll{flex:1 1 auto;min-height:0;overflow-y:auto}.csl-view-icon{margin-right:4px;font-size:11px;color:#888}.csl-view-note{flex-shrink:0;padding:8px 12px;border-top:1px solid #C4D0F9;font-size:11.5px;color:#535353;background:#f5f5f5}.csl-view-note .fa{color:#4465c9;margin-right:4px}.csl-attribute-tag{display:inline-block;margin-left:6px;padding:0 6px;border-radius:8px;font-size:10px;font-weight:600;color:#fff;background:#6b7fd4;vertical-align:middle}.csl-group-item--active .gps-profile-actions{opacity:1}.csl-footer__error{color:#dc3545}.csl-panel{display:flex;flex-direction:column;border:1px solid #C4D0F9;border-radius:10px;overflow:hidden;background:#fff}.csl-panel__header{display:flex;align-items:center;justify-content:space-between;padding:10px 13px;border-bottom:1px solid #C4D0F9;background:#f5f5f5;flex-shrink:0;gap:8px}.csl-panel__label{font-size:10.5px;font-weight:600;text-transform:uppercase;letter-spacing:.9px;color:#535353;flex-shrink:0}.csl-group-list{list-style:none;margin:0;padding:6px;overflow-y:auto;flex:1}.csl-group-item{display:flex;align-items:center;justify-content:space-between;padding:7px 8px;border-radius:0 6px 6px 0;cursor:pointer;transition:background .1s ease;min-height:34px}.csl-group-item:hover{background:#f7faff}.csl-group-item:hover .gps-profile-actions{opacity:1}.csl-group-item--active{background:#ebf0ff}.csl-group-item--active .csl-group-item__name{color:#4465c9;font-weight:600}.csl-group-item--standard{border-left:3px solid #4465C9;padding-left:5px}.csl-group-item--model{border-left:3px solid #6B7FD4;padding-left:5px}.csl-group-item--profile{border-left:3px solid #4465C9;padding-left:5px}.csl-group-item__name{font-size:12.5px;color:#272c5d;flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;margin-right:4px}.csl-group-item__meta{display:flex;align-items:center;gap:4px;flex-shrink:0}.gps-profile-actions{display:flex;align-items:center;gap:2px;flex-shrink:0;opacity:0;transition:opacity .1s ease}.gps-profile-btn{display:inline-flex;align-items:center;justify-content:center;width:22px;height:22px;border:none;background:none;border-radius:4px;font-size:11px;color:#888;cursor:pointer;padding:0;transition:background .1s,color .1s}.gps-profile-btn:hover{background:#00000014;color:#4465c9}.gps-profile-btn--danger:hover{background:#dc35451a;color:#dc3545}.gps-rename-input{flex:1;height:24px;border:1px solid #4465C9;border-radius:4px;padding:0 6px;font-size:12px;color:#272c5d;background:#fff;outline:none;min-width:0;margin-right:4px}.gps-rename-actions{display:flex;align-items:center;gap:2px;flex-shrink:0}.gps-rename-btn{display:inline-flex;align-items:center;justify-content:center;width:22px;height:22px;border:none;border-radius:4px;font-size:11px;cursor:pointer;padding:0}.gps-rename-btn--ok{background:#4465c9;color:#fff}.gps-rename-btn--ok:hover{background:#3c5dc4}.gps-rename-btn--cancel{background:#00000014;color:#535353}.gps-rename-btn--cancel:hover{background:#00000026}.gps-new-profile{color:#4465c9;font-size:12px;font-weight:500;opacity:.75;justify-content:flex-start;gap:4px}.gps-new-profile:hover{opacity:1;background:#ebf0ff}.csl-group-section-label{padding:8px 8px 4px;font-size:9.5px;font-weight:700;text-transform:uppercase;letter-spacing:.8px;color:#888;list-style:none}.csl-group-divider{height:1px;background:#c4d0f9;margin:6px 8px;list-style:none}.csl-badge{display:inline-flex;align-items:center;justify-content:center;min-width:20px;height:18px;padding:0 5px;border-radius:9px;background:#00000012;color:#535353;font-size:10px;font-weight:600}.csl-badge--primary{background:#4465c9;color:#fff}.csl-badge--sm{height:16px;min-width:16px;font-size:9px;padding:0 4px}.csl-search{flex:1;height:28px;border:1px solid #C4D0F9;border-radius:6px;padding:0 8px;font-size:12px;color:#272c5d;background:#fff;outline:none;transition:border-color .1s ease}.csl-search:focus{border-color:#6684e0}.csl-table-wrap{overflow-y:auto;flex:1}.csl-table{width:100%;border-collapse:collapse;font-size:12.5px}.csl-table thead tr{position:sticky;top:0;z-index:1;background:#f5f5f5}.csl-table thead tr th{padding:8px 10px;text-align:left;font-size:10px;font-weight:600;color:#888;text-transform:uppercase;letter-spacing:.6px;border-bottom:1px solid #C4D0F9;white-space:nowrap}.csl-table tbody tr{border-bottom:1px solid rgba(0,0,0,.04);cursor:pointer;transition:background .1s ease}.csl-table tbody tr:hover{background:#f7faff}.csl-table tbody tr:last-child{border-bottom:none}.csl-table tbody tr td{padding:9px 10px;color:#272c5d}.csl-col-check{width:36px;text-align:center;padding:0 8px!important}.csl-col-check input[type=checkbox]{cursor:pointer;accent-color:#4465C9;width:14px;height:14px}.csl-col-key{font-family:monospace;font-size:11.5px;color:#535353;width:130px}.csl-col-name{font-weight:500}.csl-row--selected{background:#ebf0ff!important}.csl-row--custom-field .csl-col-key{color:#6b7fd4}.csl-empty{text-align:center;padding:32px 16px!important;color:#888;font-size:12.5px}.csl-panel--selected{overflow:hidden}.csl-ordered-list{flex:1;overflow-y:auto;padding:7px}.csl-ordered-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;flex:1;gap:8px;padding:20px;text-align:center}.csl-ordered-empty__icon{font-size:28px;color:#888;opacity:.35}.csl-ordered-empty p{font-size:12px;color:#535353;margin:0;line-height:1.5}.csl-ordered-item{display:flex;align-items:center;gap:5px;padding:6px 8px 6px 4px;margin-bottom:4px;border:1px solid #C4D0F9;border-radius:6px;background:#fff;transition:border-color .14s ease,background .14s ease}.csl-ordered-item:last-child{margin-bottom:0}.csl-ordered-item:hover{border-color:#8ea7f8;background:#f7faff}.csl-ordered-item__drag{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;width:20px;color:#888;font-size:11px;cursor:grab;padding:0 2px;-webkit-user-select:none;user-select:none}.csl-ordered-item__drag:active{cursor:grabbing}.csl-ordered-item__position{flex-shrink:0;width:19px;height:19px;border-radius:50%;background:#ebf0ff;color:#4465c9;font-size:10px;font-weight:700;display:flex;align-items:center;justify-content:center}.csl-ordered-item__code{flex-shrink:0;width:90px;font-family:monospace;font-size:11px;font-weight:600;color:#535353;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.csl-ordered-item__code--cf{color:#6b7fd4}.csl-ordered-item__desc{flex:1;height:24px;min-width:0;padding:0 6px;border:1px solid transparent;border-radius:4px;font-size:12px;color:#272c5d;background:transparent;transition:border-color .1s,background .1s}.csl-ordered-item__desc::placeholder{color:#888;font-style:italic}.csl-ordered-item__desc:hover{border-color:#c4d0f9;background:#fff}.csl-ordered-item__desc:focus{border-color:#4465c9;background:#fff;outline:none}.csl-ordered-item__remove{flex-shrink:0;background:none;border:none;padding:0 3px;font-size:12px;color:#888;cursor:pointer;line-height:1}.csl-ordered-item__remove:hover{color:#f78383}.csl-ordered-item.cdk-drag-animating{transition:transform .2s cubic-bezier(.25,.8,.25,1)}.csl-ordered-item__placeholder{width:100%;height:38px;border:2px dashed #C4D0F9;border-radius:6px;background:#f7faff}.cdk-drop-list-dragging .csl-ordered-item:not(.cdk-drag-placeholder){transition:transform .2s cubic-bezier(.25,.8,.25,1)}.cdk-drag-preview{display:flex;align-items:center;gap:6px;padding:8px 8px 8px 4px;border-radius:6px;background:#fff;box-shadow:0 4px 16px #4465c92e,0 1px 4px #0000001a;font-size:12px;font-weight:500;color:#272c5d;min-width:180px}.csl-footer{display:flex;align-items:center;justify-content:space-between;padding:13px 22px 16px;border-top:1px solid #C4D0F9;flex-shrink:0}.csl-footer__count{font-size:12px;color:#888;min-width:180px}.csl-footer__actions{display:flex;gap:10px}.csl-btn{display:inline-flex;align-items:center;gap:7px;padding:7px 18px;font-size:13px;font-weight:500;border-radius:6px;cursor:pointer;transition:background .12s ease,opacity .12s ease}.csl-btn--secondary{background:transparent;border:1px solid rgba(0,0,0,.16);color:#535353}.csl-btn--secondary:hover{background:#0000000a}.csl-btn--primary{background:#4465c9;border:1px solid transparent;color:#fff;min-width:130px;justify-content:center}.csl-btn--primary:hover:not([disabled]){background:#3c5dc4}.csl-btn--primary[disabled]{opacity:.42;cursor:not-allowed}.csl-save-prompt{display:flex;align-items:center;gap:10px;width:100%;flex-wrap:wrap}.csl-save-prompt__label{font-size:12.5px;font-weight:500;color:#272c5d;white-space:nowrap}.csl-save-prompt__input{flex:1;min-width:160px;height:32px;padding:0 10px;border:1px solid #C4D0F9;border-radius:6px;font-size:12px;color:#272c5d;background:#fff;outline:none;transition:border-color .1s}.csl-save-prompt__input:focus{border-color:#4465c9}.csl-save-prompt__input[disabled]{opacity:.5}.csl-save-prompt__actions{display:flex;gap:8px;flex-shrink:0}.csl-spinner{display:inline-block;width:14px;height:14px;border:2px solid #DBE4FF;border-top-color:#4465c9;border-radius:50%;animation:gps-spin .65s linear infinite}.csl-spinner--sm{width:11px;height:11px;border-width:2px}.csl-spinner--light{border-color:#ffffff59;border-top-color:#fff}@keyframes gps-spin{to{transform:rotate(360deg)}}.csl-tabbed{flex:2 1 0;min-width:0;display:flex;flex-direction:column;gap:8px}.csl-tabs{display:flex;gap:4px;border-bottom:1px solid #3C5DC4}.csl-tab{position:relative;flex:1 1 0;text-align:center;padding:6px 14px;border:none;border-bottom:2px solid transparent;background:none;color:#6b7591;font:inherit;font-weight:700;cursor:pointer}.csl-tab--active{color:#5272d3;border-bottom-color:#5272d3}.csl-tab-dot{display:inline-block;width:7px;height:7px;margin-left:6px;border-radius:50%;background:var(--orange-algorima, #f59d0f);vertical-align:middle}.csl-panels--inner{flex:1 1 auto;min-height:0}.csl-panel--filters{flex:1 1 auto;min-height:0;overflow:auto}.csl-editor{overflow:auto;min-height:0}.csl-editor ::ng-deep>alg-presentation-profile-editor{display:block;width:100%;height:100%}\n"]
1691
1922
  }]
1692
1923
  }],
1693
1924
  ctorParameters: () => [{ type: PresentationProfileService }, { type: i1$2.ApplicationService }],
@@ -1701,6 +1932,10 @@ i0.ɵɵngDeclareClassMetadata({
1701
1932
  read: ViewContainerRef,
1702
1933
  static: true
1703
1934
  }]
1935
+ }],
1936
+ cardTab: [{
1937
+ type: ViewChild,
1938
+ args: ["cardTab", { static: true }]
1704
1939
  }]
1705
1940
  }
1706
1941
  });
@@ -6581,6 +6816,9 @@ var BaseSubcompanyComponent = class BaseSubcompanyComponent extends BaseComponen
6581
6816
  get PermissionKey() {
6582
6817
  return SystemPermissions.SYSTEM_SUBCOMPANY;
6583
6818
  }
6819
+ getPpMetaEntityKey() {
6820
+ return "CPYV";
6821
+ }
6584
6822
  constructor(app, route) {
6585
6823
  super(app, route);
6586
6824
  this.route = route;
@@ -22882,187 +23120,6 @@ i0.ɵɵngDeclareClassMetadata({
22882
23120
  }],
22883
23121
  ctorParameters: () => [{ type: i1$2.ApplicationService }, { type: i2$1.ActivatedRoute }]
22884
23122
  });
22885
- const CardSlotNames = [
22886
- "title",
22887
- "text",
22888
- "detail",
22889
- "badge",
22890
- "image"
22891
- ];
22892
- const EntityImageKey = "@EntityImage";
22893
- var CardEditorComponent = class CardEditorComponent {
22894
- constructor() {
22895
- this.cardLabel = "";
22896
- this.isNewCard = true;
22897
- this.options = [];
22898
- this.imageOptions = [];
22899
- this.slots = {
22900
- title: "",
22901
- text: "",
22902
- detail: "",
22903
- badge: "",
22904
- image: ""
22905
- };
22906
- this.slotList = [
22907
- {
22908
- name: "title",
22909
- label: "Titre"
22910
- },
22911
- {
22912
- name: "text",
22913
- label: "Texte"
22914
- },
22915
- {
22916
- name: "detail",
22917
- label: "Détail"
22918
- },
22919
- {
22920
- name: "badge",
22921
- label: "Badge"
22922
- },
22923
- {
22924
- name: "image",
22925
- label: "Image"
22926
- }
22927
- ];
22928
- }
22929
- get result() {
22930
- return { slots: { ...this.slots } };
22931
- }
22932
- static {
22933
- this.ɵfac = i0.ɵɵngDeclareFactory({
22934
- minVersion: "12.0.0",
22935
- version: "22.2.1",
22936
- ngImport: i0,
22937
- type: CardEditorComponent,
22938
- deps: [],
22939
- target: i0.ɵɵFactoryTarget.Component
22940
- });
22941
- }
22942
- static {
22943
- this.ɵcmp = i0.ɵɵngDeclareComponent({
22944
- minVersion: "14.0.0",
22945
- version: "22.2.1",
22946
- type: CardEditorComponent,
22947
- isStandalone: true,
22948
- selector: "alg-card-editor",
22949
- ngImport: i0,
22950
- template: `
22951
- <div class="card-editor">
22952
- <p class="card-editor-hint" *ngIf="isNewCard">
22953
- La carte « {{ cardLabel }} » est en lecture seule : vos choix sont enregistrés dans une nouvelle carte, liée à la vue affichée.
22954
- </p>
22955
- <label class="card-editor-slot" *ngFor="let slot of slotList">
22956
- <span>{{ slot.label }}</span>
22957
- <select class="form-control" [id]="'card-slot-' + slot.name" [(ngModel)]="slots[slot.name]">
22958
- <option value="">{{ slot.name === 'image' ? 'Aucune' : 'Aucun' }}</option>
22959
- <option *ngFor="let option of (slot.name === 'image' ? imageOptions : options)" [value]="option.key">{{ option.label }}</option>
22960
- </select>
22961
- </label>
22962
- </div>
22963
- `,
22964
- isInline: true,
22965
- styles: [".card-editor{padding:12px 16px 4px;display:flex;flex-direction:column;gap:8px}.card-editor-hint{margin:0 0 4px;font-size:12px;opacity:.8}.card-editor-slot{display:grid;grid-template-columns:80px minmax(0,1fr);align-items:center;gap:10px;margin:0;font-weight:400}.card-editor-slot span{font-weight:600}\n"],
22966
- dependencies: [
22967
- {
22968
- kind: "ngmodule",
22969
- type: CommonModule
22970
- },
22971
- {
22972
- kind: "directive",
22973
- type: i4$2.NgForOf,
22974
- selector: "[ngFor][ngForOf]",
22975
- inputs: [
22976
- "ngForOf",
22977
- "ngForTrackBy",
22978
- "ngForTemplate"
22979
- ]
22980
- },
22981
- {
22982
- kind: "directive",
22983
- type: i4$2.NgIf,
22984
- selector: "[ngIf]",
22985
- inputs: [
22986
- "ngIf",
22987
- "ngIfThen",
22988
- "ngIfElse"
22989
- ]
22990
- },
22991
- {
22992
- kind: "ngmodule",
22993
- type: FormsModule
22994
- },
22995
- {
22996
- kind: "directive",
22997
- type: i1$3.NgSelectOption,
22998
- selector: "option",
22999
- inputs: ["ngValue", "value"]
23000
- },
23001
- {
23002
- kind: "directive",
23003
- type: i1$3.ɵNgSelectMultipleOption,
23004
- selector: "option",
23005
- inputs: ["ngValue", "value"]
23006
- },
23007
- {
23008
- kind: "directive",
23009
- type: i1$3.SelectControlValueAccessor,
23010
- selector: "select:not([multiple]):not([ngNoCva])[formControlName],select:not([multiple]):not([ngNoCva])[formControl],select:not([multiple]):not([ngNoCva])[ngModel]",
23011
- inputs: ["compareWith"]
23012
- },
23013
- {
23014
- kind: "directive",
23015
- type: i1$3.NgControlStatus,
23016
- selector: "[formControlName],[ngModel],[formControl]"
23017
- },
23018
- {
23019
- kind: "directive",
23020
- type: i1$3.NgModel,
23021
- selector: "[ngModel]:not([formControlName]):not([formControl])",
23022
- inputs: [
23023
- "name",
23024
- "disabled",
23025
- "ngModel",
23026
- "ngModelOptions"
23027
- ],
23028
- outputs: ["ngModelChange"],
23029
- exportAs: ["ngModel"]
23030
- }
23031
- ],
23032
- changeDetection: i0.ChangeDetectionStrategy.Eager
23033
- });
23034
- }
23035
- };
23036
- i0.ɵɵngDeclareClassMetadata({
23037
- minVersion: "12.0.0",
23038
- version: "22.2.1",
23039
- ngImport: i0,
23040
- type: CardEditorComponent,
23041
- decorators: [{
23042
- type: Component,
23043
- args: [{
23044
- selector: "alg-card-editor",
23045
- standalone: true,
23046
- imports: [CommonModule, FormsModule],
23047
- changeDetection: ChangeDetectionStrategy.Eager,
23048
- template: `
23049
- <div class="card-editor">
23050
- <p class="card-editor-hint" *ngIf="isNewCard">
23051
- La carte « {{ cardLabel }} » est en lecture seule : vos choix sont enregistrés dans une nouvelle carte, liée à la vue affichée.
23052
- </p>
23053
- <label class="card-editor-slot" *ngFor="let slot of slotList">
23054
- <span>{{ slot.label }}</span>
23055
- <select class="form-control" [id]="'card-slot-' + slot.name" [(ngModel)]="slots[slot.name]">
23056
- <option value="">{{ slot.name === 'image' ? 'Aucune' : 'Aucun' }}</option>
23057
- <option *ngFor="let option of (slot.name === 'image' ? imageOptions : options)" [value]="option.key">{{ option.label }}</option>
23058
- </select>
23059
- </label>
23060
- </div>
23061
- `,
23062
- styles: [".card-editor{padding:12px 16px 4px;display:flex;flex-direction:column;gap:8px}.card-editor-hint{margin:0 0 4px;font-size:12px;opacity:.8}.card-editor-slot{display:grid;grid-template-columns:80px minmax(0,1fr);align-items:center;gap:10px;margin:0;font-weight:400}.card-editor-slot span{font-weight:600}\n"]
23063
- }]
23064
- }]
23065
- });
23066
23123
  var SaveViewPromptComponent = class SaveViewPromptComponent {
23067
23124
  constructor() {
23068
23125
  this.title = "";
@@ -23278,6 +23335,42 @@ var PpFacadeService = class PpFacadeService {
23278
23335
  });
23279
23336
  });
23280
23337
  }
23338
+ confirmLeaveView(config, columnOrder, queries) {
23339
+ if (!config?.metaEntityKey || !columnOrder?.length) return of(true);
23340
+ return this.loadViews(config).pipe(take(1), switchMap((list) => {
23341
+ const selected = list.views.find((v) => v.id === list.selectedId);
23342
+ const ownView = selected && !selected.isDefault ? selected : null;
23343
+ return this.askSaveView(config.title, !ownView, ownView?.label ?? "", false).pipe(switchMap((answer) => !answer.save ? of(true) : this.writeColumnOrder(config, columnOrder, ownView?.id ?? null, ownView ? null : answer.label, queries).pipe(map$1(() => false))));
23344
+ }), catchError(() => of(true)));
23345
+ }
23346
+ saveViewFilter(config, columnOrder, queries) {
23347
+ if (!config?.metaEntityKey || !columnOrder?.length) return of(false);
23348
+ return this.loadViews(config).pipe(take(1), switchMap((list) => {
23349
+ const selected = list.views.find((v) => v.id === list.selectedId) ?? list.views.find((v) => v.isDefault);
23350
+ if (!selected) return of(false);
23351
+ if (!selected.isDefault) return this.writeColumnOrder(config, columnOrder, selected.id, null, queries);
23352
+ if (!list.canEditDefault) return of(false);
23353
+ return this.resolver.loadContext({
23354
+ ...config,
23355
+ purpose: PresentationProfilePurposes.Grid
23356
+ }).pipe(take(1), switchMap((ctx) => {
23357
+ const resolved = new Map((ctx?.Resolved ?? []).map((i) => [i.ColumnKey, i]));
23358
+ const catalog = new Map((ctx?.Catalog ?? []).map((i) => [i.ColumnKey, i]));
23359
+ const items = columnOrder.map((key) => resolved.get(key) ?? catalog.get(key)).filter((i) => !!i);
23360
+ if (!items.length) return of(false);
23361
+ const request = PresentationProfileTransformer.toAdminConfigContext(items, {
23362
+ Id: selected.id,
23363
+ Label: selected.label,
23364
+ MetaEntityKey: config.metaEntityKey,
23365
+ PresentationProfilePurpose: PresentationProfilePurposes.Grid,
23366
+ PresentationProfileScope: PresentationProfileScopes.Default,
23367
+ SortQuery: queries.sortQuery,
23368
+ FilterQuery: queries.filterQuery
23369
+ });
23370
+ return this.profileData.savePresentationProfile(request).pipe(map$1((result) => !!result && result.Success !== false));
23371
+ }));
23372
+ }), catchError(() => of(false)));
23373
+ }
23281
23374
  saveCurrentColumnOrder(config, columnOrder, queries) {
23282
23375
  if (!config?.metaEntityKey || !columnOrder?.length) return of(false);
23283
23376
  return this.loadViews(config).pipe(take(1), switchMap((list) => {
@@ -23320,14 +23413,18 @@ var PpFacadeService = class PpFacadeService {
23320
23413
  label: String(label).trim() || "Ma vue"
23321
23414
  }));
23322
23415
  }
23323
- createView(config) {
23416
+ createView(config, queries) {
23324
23417
  if (!config?.metaEntityKey) return of(false);
23325
23418
  return this.loadViews(config).pipe(take(1), switchMap((list) => {
23326
23419
  const sourceId = list.selectedId ?? list.views.find((v) => v.isDefault)?.id ?? null;
23327
23420
  if (sourceId == null) return of(false);
23328
23421
  return this.profileData.duplicateView({
23329
23422
  PresentationProfileId: sourceId,
23330
- Label: PpFacadeService.NewViewLabel
23423
+ Label: PpFacadeService.NewViewLabel,
23424
+ ...queries ? {
23425
+ SortQuery: queries.sortQuery,
23426
+ FilterQuery: queries.filterQuery
23427
+ } : {}
23331
23428
  }).pipe(switchMap((result) => result?.Success === false || result?.Id == null ? of(false) : this.selectView(config, result.Id).pipe(map$1(() => true))));
23332
23429
  }), catchError(() => of(false)));
23333
23430
  }
@@ -23343,126 +23440,6 @@ var PpFacadeService = class PpFacadeService {
23343
23440
  }))
23344
23441
  }), catchError(() => of(null)));
23345
23442
  }
23346
- loadCardViews(config) {
23347
- const empty = {
23348
- cards: [],
23349
- linkedId: null,
23350
- canLink: false
23351
- };
23352
- if (!config?.metaEntityKey) return of(empty);
23353
- return this.profileData.getCardView({ MetaEntityKey: config.metaEntityKey }).pipe(map$1((result) => ({
23354
- cards: (result?.Cards ?? []).filter((c) => c.Id != null).map((c) => ({
23355
- id: c.Id,
23356
- label: c.Label ?? "",
23357
- isDefault: c.PresentationProfileScope === PresentationProfileScopes.Default
23358
- })),
23359
- linkedId: result?.Card?.Id ?? null,
23360
- canLink: !!result?.CanLink
23361
- })), catchError(() => of(empty)));
23362
- }
23363
- linkCardView(config, cardId) {
23364
- if (!config?.metaEntityKey) return of(false);
23365
- return this.profileData.linkCardView({
23366
- MetaEntityKey: config.metaEntityKey,
23367
- PresentationProfileId: cardId ?? void 0
23368
- }).pipe(map$1((result) => result?.Success !== false), catchError(() => of(false)));
23369
- }
23370
- editCardView(config) {
23371
- if (!config?.metaEntityKey) return of(false);
23372
- return forkJoin({
23373
- view: this.profileData.getCardView({ MetaEntityKey: config.metaEntityKey }).pipe(take(1)),
23374
- ctx: this.resolver.loadContext({
23375
- ...config,
23376
- purpose: PresentationProfilePurposes.Grid
23377
- }).pipe(take(1))
23378
- }).pipe(switchMap(({ view, ctx }) => {
23379
- const card = view?.Card;
23380
- const ownCard = !!card && card.PresentationProfileScope === PresentationProfileScopes.User;
23381
- const catalog = (ctx?.Catalog ?? []).filter((i) => !!i.ColumnKey);
23382
- const byLabel = (a, b) => a.label.localeCompare(b.label, "fr", { sensitivity: "base" });
23383
- const options = catalog.map((i) => ({
23384
- key: i.ColumnKey,
23385
- label: i.Label || i.ColumnKey
23386
- })).sort(byLabel);
23387
- const imageTypes = [
23388
- 7,
23389
- 8,
23390
- 9,
23391
- 10
23392
- ];
23393
- const imageOptions = [{
23394
- key: EntityImageKey,
23395
- label: "Image de l'élément"
23396
- }, ...catalog.filter((i) => imageTypes.includes(i.ColumnDisplayType ?? -1)).map((i) => ({
23397
- key: i.ColumnKey,
23398
- label: i.Label || i.ColumnKey
23399
- })).sort(byLabel)];
23400
- const slots = {
23401
- title: "",
23402
- text: "",
23403
- detail: "",
23404
- badge: "",
23405
- image: ""
23406
- };
23407
- for (const item of card?.Items ?? []) {
23408
- const slot = CardSlotNames[item.CardSlot ?? -1];
23409
- if (slot) slots[slot] = item.ColumnSourceType === 3 ? EntityImageKey : item.ColumnKey ?? "";
23410
- }
23411
- const state = new DialogComponentParameter();
23412
- state.showButtons = true;
23413
- state.dialogOptions = {
23414
- title: `Carte — ${config.title}`,
23415
- childComponentType: CardEditorComponent,
23416
- initialViewModel: {
23417
- cardLabel: card?.Label ?? "",
23418
- isNewCard: !ownCard,
23419
- options,
23420
- imageOptions,
23421
- slots
23422
- },
23423
- propertyCallback: "result",
23424
- okLabel: "Enregistrer",
23425
- cancelLabel: "Annuler",
23426
- enableDirtyCheck: false
23427
- };
23428
- const dialog = this.modalService.show(DialogComponent, {
23429
- class: "modal-md",
23430
- initialState: state
23431
- }).content;
23432
- if (!dialog) return of(false);
23433
- return dialog.onClose.pipe(take(1), switchMap((answer) => {
23434
- if (!answer?.slots) return of(false);
23435
- const byKey = new Map(catalog.map((i) => [i.ColumnKey, i]));
23436
- const items = [];
23437
- CardSlotNames.forEach((slot, index) => {
23438
- const key = answer.slots[slot];
23439
- if (!key) return;
23440
- if (key === "@EntityImage") items.push({
23441
- ColumnKey: EntityImageKey,
23442
- Label: "Image de l'élément",
23443
- ColumnSourceType: 3,
23444
- CardSlot: index
23445
- });
23446
- else if (byKey.has(key)) items.push({
23447
- ...byKey.get(key),
23448
- CardSlot: index
23449
- });
23450
- });
23451
- if (!items.length) return of(false);
23452
- const request = PresentationProfileTransformer.toUserPreferenceContext(items, config.metaEntityKey, PresentationProfilePurposes.Card, ownCard ? null : PpFacadeService.NewCardLabel, ownCard ? {
23453
- Id: card.Id,
23454
- Label: card.Label
23455
- } : null);
23456
- return this.profileData.savePresentationProfile(request).pipe(switchMap((result) => {
23457
- if (!result || result.Success === false) return of(false);
23458
- return ownCard || !view?.CanLink ? of(true) : this.linkCardView(config, result.Id ?? null);
23459
- }));
23460
- }));
23461
- }), catchError(() => of(false)));
23462
- }
23463
- static {
23464
- this.NewCardLabel = "Ma carte";
23465
- }
23466
23443
  loadViewColumns(config) {
23467
23444
  if (!config?.metaEntityKey) return of([]);
23468
23445
  return this.resolver.loadContext({