@firestitch/content 18.0.4 → 18.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,136 +1,214 @@
1
1
  import * as i0 from '@angular/core';
2
- import { InjectionToken, inject, ChangeDetectorRef, Component, ChangeDetectionStrategy, ViewChildren, Input, EventEmitter, Output, ViewChild, NgModule, ElementRef } from '@angular/core';
2
+ import { inject, ElementRef, Component, ChangeDetectionStrategy, ViewChild, Input, InjectionToken, ChangeDetectorRef, NgModule, EventEmitter, Output, ViewChildren } from '@angular/core';
3
+ import { DomSanitizer, Title } from '@angular/platform-browser';
4
+ import { Router, NavigationEnd, RouterLink } from '@angular/router';
5
+ import { HtmlRenderer } from '@firestitch/html';
6
+ import { Subject, of, throwError, fromEvent } from 'rxjs';
7
+ import { filter, takeUntil, tap, switchMap, finalize, map } from 'rxjs/operators';
8
+ import { MatButtonToggleGroup, MatButtonToggle } from '@angular/material/button-toggle';
3
9
  import * as i4 from '@angular/material/dialog';
4
10
  import { MAT_DIALOG_DATA, MatDialogRef, MatDialogTitle, MatDialogContent, MatDialogActions, MatDialog } from '@angular/material/dialog';
5
11
  import { FsMessage } from '@firestitch/message';
6
- import * as i2$1 from '@firestitch/text-editor';
7
- import { FsTextEditorComponent, FsTextEditorModule } from '@firestitch/text-editor';
8
- import { Subject, of, throwError, fromEvent } from 'rxjs';
9
- import { tap, switchMap, takeUntil, filter, finalize, map } from 'rxjs/operators';
10
- import * as i1 from '@firestitch/skeleton';
11
- import { FsSkeletonModule } from '@firestitch/skeleton';
12
- import * as i2 from '@angular/forms';
12
+ import { FsPrompt } from '@firestitch/prompt';
13
+ import * as i2 from '@firestitch/text-editor';
14
+ import { FsTextEditorModule, FsTextEditorComponent } from '@firestitch/text-editor';
15
+ import * as i1 from 'angular-split';
16
+ import { AngularSplitModule } from 'angular-split';
17
+ import { NgClass, NgTemplateOutlet } from '@angular/common';
18
+ import * as i2$1 from '@angular/forms';
13
19
  import { FormsModule } from '@angular/forms';
14
20
  import * as i3 from '@firestitch/form';
15
21
  import { FsFormModule, FsFormDirective } from '@firestitch/form';
16
- import * as i5 from '@firestitch/dialog';
22
+ import * as i5 from '@firestitch/common';
23
+ import { FsCommonModule, index } from '@firestitch/common';
24
+ import * as i1$1 from '@firestitch/skeleton';
25
+ import { FsSkeletonModule } from '@firestitch/skeleton';
26
+ import * as i5$1 from '@firestitch/dialog';
17
27
  import { FsDialogModule } from '@firestitch/dialog';
18
28
  import { CdkScrollable } from '@angular/cdk/scrolling';
19
29
  import { MatFormField, MatLabel } from '@angular/material/form-field';
20
- import { MatSelect } from '@angular/material/select';
21
- import { MatOption } from '@angular/material/core';
22
30
  import { MatInput } from '@angular/material/input';
23
- import { MatButtonToggleGroup, MatButtonToggle } from '@angular/material/button-toggle';
24
- import { FsPrompt } from '@firestitch/prompt';
25
- import * as i1$1 from 'angular-split';
26
- import { AngularSplitModule } from 'angular-split';
27
- import { NgClass, NgTemplateOutlet } from '@angular/common';
28
- import * as i5$1 from '@firestitch/common';
29
- import { FsCommonModule, index } from '@firestitch/common';
30
31
  import { MatIconAnchor, MatButton, MatAnchor } from '@angular/material/button';
31
32
  import { MatIcon } from '@angular/material/icon';
32
33
  import { MatTooltip } from '@angular/material/tooltip';
33
- import { RouterLink, Router, NavigationEnd } from '@angular/router';
34
34
  import { ItemType } from '@firestitch/filter';
35
35
  import * as i1$2 from '@firestitch/list';
36
36
  import { FsListComponent, FsListModule } from '@firestitch/list';
37
37
  import * as i2$2 from '@firestitch/date';
38
38
  import { FsDateModule } from '@firestitch/date';
39
- import { DomSanitizer, Title } from '@angular/platform-browser';
40
- import { HtmlRenderer } from '@firestitch/html';
41
-
42
- var EditorType;
43
- (function (EditorType) {
44
- EditorType["Js"] = "js";
45
- EditorType["Html"] = "html";
46
- EditorType["Scss"] = "scss";
47
- EditorType["GlobalScss"] = "globalScss";
48
- })(EditorType || (EditorType = {}));
49
-
50
- var PageType;
51
- (function (PageType) {
52
- PageType["StandardPage"] = "standardPage";
53
- PageType["BlogPost"] = "blogPost";
54
- PageType["HomePage"] = "homePage";
55
- PageType["NotFoundPage"] = "notFoundPage";
56
- })(PageType || (PageType = {}));
39
+ import { MatSelect } from '@angular/material/select';
40
+ import { MatOption } from '@angular/material/core';
57
41
 
58
- const PageTypes = [
59
- { name: 'Page', value: PageType.StandardPage },
60
- { name: 'Page (Not Found)', value: PageType.NotFoundPage },
61
- ];
42
+ class ContentRendererComponent {
43
+ _sanitizer = inject(DomSanitizer);
44
+ _router = inject(Router);
45
+ _el = inject(ElementRef);
46
+ _htmlRenderer = inject(HtmlRenderer);
47
+ script;
48
+ contentPage;
49
+ content;
50
+ _destroy$ = new Subject();
51
+ ngOnChanges(changes) {
52
+ if (changes.contentPage.currentValue) {
53
+ this._htmlRenderer.addStyle(this.contentPage.styles, { id: 'contentPageStyles' });
54
+ this.content = this._sanitizer.bypassSecurityTrustHtml(this.contentPage.content);
55
+ }
56
+ }
57
+ ngAfterViewChecked() {
58
+ this.registerHrefs();
59
+ if (this.contentPage.js) {
60
+ const script = document.createElement('script');
61
+ script.text = this.contentPage.js;
62
+ this.script.nativeElement.after(script);
63
+ }
64
+ }
65
+ registerHrefs() {
66
+ Array.from(this.el.querySelectorAll('a[href]'))
67
+ .filter((el) => {
68
+ return el.getAttribute('href').match(/^\//);
69
+ })
70
+ .forEach((el) => {
71
+ el.addEventListener('click', (event) => {
72
+ if (!event.shiftKey && !event.ctrlKey) {
73
+ event.preventDefault();
74
+ const href = el.getAttribute('href');
75
+ this._router.navigateByUrl(href);
76
+ }
77
+ });
78
+ });
79
+ }
80
+ get el() {
81
+ return this._el.nativeElement;
82
+ }
83
+ ngOnDestroy() {
84
+ this.removeStyles();
85
+ this._destroy$.next(null);
86
+ this._destroy$.complete();
87
+ }
88
+ removeStyles() {
89
+ const el = document.querySelector('#contentPageStyles');
90
+ if (el) {
91
+ el.remove();
92
+ }
93
+ }
94
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: ContentRendererComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
95
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.7", type: ContentRendererComponent, isStandalone: true, selector: "fs-content-renderer", inputs: { contentPage: "contentPage" }, viewQueries: [{ propertyName: "script", first: true, predicate: ["script"], descendants: true, read: ElementRef }], usesOnChanges: true, ngImport: i0, template: "@if (content) {\n <div [innerHTML]=\"content\"></div>\n}\n<span #script></span>", styles: [""], changeDetection: i0.ChangeDetectionStrategy.OnPush });
96
+ }
97
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: ContentRendererComponent, decorators: [{
98
+ type: Component,
99
+ args: [{ selector: 'fs-content-renderer', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, template: "@if (content) {\n <div [innerHTML]=\"content\"></div>\n}\n<span #script></span>" }]
100
+ }], propDecorators: { script: [{
101
+ type: ViewChild,
102
+ args: ['script', { read: ElementRef }]
103
+ }], contentPage: [{
104
+ type: Input
105
+ }] } });
62
106
 
63
107
  const FS_CONTENT_CONFIG = new InjectionToken('fs-content-config');
64
108
 
65
- class ContentPageComponent {
109
+ class FsContentComponent {
66
110
  _config = inject(FS_CONTENT_CONFIG);
67
- _data = inject(MAT_DIALOG_DATA);
68
- _dialogRef = inject(MatDialogRef);
69
- _message = inject(FsMessage);
111
+ _title = inject(Title);
70
112
  _cdRef = inject(ChangeDetectorRef);
71
- textEditors;
72
- contentPage = null;
73
- PageTypes = PageTypes;
74
- contentLayouts;
75
- editors = { content: true, styles: true };
113
+ _router = inject(Router);
114
+ _el = inject(ElementRef);
115
+ _htmlRenderer = inject(HtmlRenderer);
116
+ contentPage;
76
117
  _destroy$ = new Subject();
77
118
  ngOnInit() {
78
- this._dialogRef.updateSize('600px');
79
- this._fetchData();
119
+ this._initContent();
120
+ this._initStyles();
121
+ }
122
+ get el() {
123
+ return this._el.nativeElement;
80
124
  }
81
125
  ngOnDestroy() {
82
126
  this._destroy$.next(null);
83
127
  this._destroy$.complete();
128
+ this._title.setTitle('');
129
+ document.querySelector('#content-style')?.remove();
84
130
  }
85
- save = () => {
86
- return this._config.saveContentPage(this.contentPage)
87
- .pipe(tap((contentPage) => {
88
- this._message.success('Saved Changes');
89
- this._dialogRef.close(contentPage);
90
- }));
91
- };
92
- _fetchData() {
93
- this._config.loadContentLayouts()
94
- .subscribe((contentLayouts) => {
95
- this.contentLayouts = contentLayouts;
96
- this._cdRef.markForCheck();
131
+ _initStyles() {
132
+ if (this._config.loadContentStyleCss) {
133
+ this._config.loadContentStyleCss()
134
+ .subscribe((styles) => {
135
+ this._htmlRenderer.addStyle(styles, { id: 'content-style' });
136
+ });
137
+ }
138
+ }
139
+ _initContent() {
140
+ this._loadContent();
141
+ this._router.events
142
+ .pipe(filter((e) => e instanceof NavigationEnd), takeUntil(this._destroy$))
143
+ .subscribe((e) => {
144
+ this._loadContent();
97
145
  });
98
- of(this._data.contentPage)
99
- .pipe(switchMap((contentPage) => {
100
- return of(contentPage);
101
- }), takeUntil(this._destroy$))
146
+ }
147
+ _loadContent() {
148
+ const path = window.location.pathname;
149
+ this._config.loadContent(path)
102
150
  .subscribe((contentPage) => {
103
- this.contentPage = {
104
- ...contentPage,
105
- path: contentPage.path || '/',
106
- };
151
+ if (contentPage.title) {
152
+ this._title.setTitle(contentPage.title);
153
+ let ogTitleEl = document.querySelector('head meta[property="og:title"]');
154
+ if (!ogTitleEl) {
155
+ ogTitleEl = document.createElement('meta');
156
+ ogTitleEl.setAttribute('property', 'og:title');
157
+ document.getElementsByTagName('head')[0].appendChild(ogTitleEl);
158
+ }
159
+ ogTitleEl.setAttribute('content', contentPage.title);
160
+ }
161
+ this.contentPage = contentPage;
107
162
  this._cdRef.markForCheck();
108
163
  });
109
164
  }
110
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: ContentPageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
111
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.7", type: ContentPageComponent, isStandalone: true, selector: "ng-component", viewQueries: [{ propertyName: "textEditors", predicate: FsTextEditorComponent, descendants: true }], ngImport: i0, template: "<form fsForm [submit]=\"save\" *fsSkeletonForm=\"contentPage\">\n <fs-dialog>\n <h1 mat-dialog-title>{{contentPage.id ? 'Page' : 'Create Page'}}</h1>\n <div mat-dialog-content>\n <div class=\"fs-column\">\n <mat-form-field>\n <mat-label>Type</mat-label>\n <mat-select\n [(ngModel)]=\"contentPage.type\"\n name=\"type\"\n required>\n @for (item of PageTypes; track item) {\n <mat-option\n [value]=\"item.value\">\n {{ item.name }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n @if (contentLayouts) {\n <mat-form-field>\n <mat-label>Layout</mat-label>\n <mat-select\n [(ngModel)]=\"contentPage.contentLayoutId\"\n required\n name=\"contentLayoutId\">\n @for (item of contentLayouts; track item) {\n <mat-option\n [value]=\"item.id\">\n {{ item.name }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n }\n <mat-form-field>\n <mat-label>Name</mat-label>\n <input\n matInput\n [(ngModel)]=\"contentPage.name\"\n name=\"name\"\n required>\n </mat-form-field>\n <mat-form-field>\n <mat-label>Path</mat-label>\n <input\n matInput\n [(ngModel)]=\"contentPage.path\"\n name=\"path\"\n required>\n </mat-form-field>\n <mat-form-field>\n <mat-label>Title</mat-label>\n <input\n matInput\n [(ngModel)]=\"contentPage.title\"\n name=\"title\">\n </mat-form-field>\n </div>\n </div>\n\n <div mat-dialog-actions>\n <fs-form-dialog-actions>\n </fs-form-dialog-actions>\n </div>\n </fs-dialog>\n</form>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: FsSkeletonModule }, { kind: "directive", type: i1.FsSkeletonFormDirective, selector: "[fsSkeletonForm]", inputs: ["fsSkeletonForm", "fsSkeletonFormLines"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i2.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: FsFormModule }, { kind: "directive", type: i3.FsFormDirective, selector: "[fsForm]", inputs: ["wrapperSelector", "messageSelector", "hintSelector", "labelSelector", "autocomplete", "shortcuts", "confirm", "confirmDialog", "confirmDrawer", "confirmBrowser", "confirmTabs", "dirtySubmitButton", "submit", "successDelay", "errorDelay", "tabGroup", "deactivationGuard"], outputs: ["fsForm", "invalid", "valid", "submitted", "reseted", "cleared"], exportAs: ["fsForm"] }, { kind: "directive", type: i3.FsFormRequiredDirective, selector: "[fsFormRequired],[ngModel][required]", inputs: ["fsFormRequired", "required", "fsFormRequiredMessage"] }, { kind: "component", type: i3.FsFormDialogActionsComponent, selector: "fs-form-dialog-actions", inputs: ["save", "create", "close", "done", "closeData", "name"] }, { kind: "directive", type: i3.FsFormNoFsValidatorsDirective, selector: "[ngModel]:not([required]):not([fsFormRequired]):not([fsFormCompare]):not([fsFormDateRange]):not([fsFormEmail]):not([fsFormEmails]):not([fsFormFunction]):not([fsFormGreater]):not([fsFormGreaterEqual]):not([fsFormInteger]):not([fsFormLesser]):not([fsFormMax]):not([fsFormMaxLength]):not([fsFormMin]):not([fsFormMinLength]):not([fsFormNumeric]):not([fsFormPattern]):not([fsFormPhone]):not([fsFormUrl]):not([validate])" }, { kind: "ngmodule", type: FsDialogModule }, { kind: "directive", type: i4.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i4.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i4.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "component", type: i5.FsDialogComponent, selector: "fs-dialog", inputs: ["mobileMode", "mobileButtonPlacement", "mobileWidth", "mode", "buttonLayout", "dock", "dockable", "fullscreenPercent"] }, { kind: "component", type: MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: MatLabel, selector: "mat-label" }, { kind: "component", type: MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "directive", type: MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
165
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: FsContentComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
166
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.7", type: FsContentComponent, isStandalone: true, selector: "fs-content", ngImport: i0, template: "@if (contentPage) {\n <fs-content-renderer [contentPage]=\"contentPage\"></fs-content-renderer>\n}", styles: [""], dependencies: [{ kind: "component", type: ContentRendererComponent, selector: "fs-content-renderer", inputs: ["contentPage"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
112
167
  }
113
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: ContentPageComponent, decorators: [{
168
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: FsContentComponent, decorators: [{
114
169
  type: Component,
115
- args: [{ changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [
116
- FsSkeletonModule,
117
- FormsModule,
118
- FsFormModule,
119
- FsDialogModule,
120
- MatDialogTitle,
121
- CdkScrollable,
122
- MatDialogContent,
123
- MatFormField,
124
- MatLabel,
125
- MatSelect,
126
- MatOption,
127
- MatInput,
128
- MatDialogActions,
129
- ], template: "<form fsForm [submit]=\"save\" *fsSkeletonForm=\"contentPage\">\n <fs-dialog>\n <h1 mat-dialog-title>{{contentPage.id ? 'Page' : 'Create Page'}}</h1>\n <div mat-dialog-content>\n <div class=\"fs-column\">\n <mat-form-field>\n <mat-label>Type</mat-label>\n <mat-select\n [(ngModel)]=\"contentPage.type\"\n name=\"type\"\n required>\n @for (item of PageTypes; track item) {\n <mat-option\n [value]=\"item.value\">\n {{ item.name }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n @if (contentLayouts) {\n <mat-form-field>\n <mat-label>Layout</mat-label>\n <mat-select\n [(ngModel)]=\"contentPage.contentLayoutId\"\n required\n name=\"contentLayoutId\">\n @for (item of contentLayouts; track item) {\n <mat-option\n [value]=\"item.id\">\n {{ item.name }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n }\n <mat-form-field>\n <mat-label>Name</mat-label>\n <input\n matInput\n [(ngModel)]=\"contentPage.name\"\n name=\"name\"\n required>\n </mat-form-field>\n <mat-form-field>\n <mat-label>Path</mat-label>\n <input\n matInput\n [(ngModel)]=\"contentPage.path\"\n name=\"path\"\n required>\n </mat-form-field>\n <mat-form-field>\n <mat-label>Title</mat-label>\n <input\n matInput\n [(ngModel)]=\"contentPage.title\"\n name=\"title\">\n </mat-form-field>\n </div>\n </div>\n\n <div mat-dialog-actions>\n <fs-form-dialog-actions>\n </fs-form-dialog-actions>\n </div>\n </fs-dialog>\n</form>\n" }]
130
- }], propDecorators: { textEditors: [{
131
- type: ViewChildren,
132
- args: [FsTextEditorComponent]
133
- }] } });
170
+ args: [{ selector: 'fs-content', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [ContentRendererComponent], template: "@if (contentPage) {\n <fs-content-renderer [contentPage]=\"contentPage\"></fs-content-renderer>\n}" }]
171
+ }] });
172
+
173
+ class FsContentModule {
174
+ static forRoot() {
175
+ return {
176
+ ngModule: FsContentModule,
177
+ };
178
+ }
179
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: FsContentModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
180
+ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.7", ngImport: i0, type: FsContentModule, imports: [FsContentComponent,
181
+ ContentRendererComponent], exports: [FsContentComponent] });
182
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: FsContentModule });
183
+ }
184
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: FsContentModule, decorators: [{
185
+ type: NgModule,
186
+ args: [{
187
+ imports: [
188
+ FsContentComponent,
189
+ ContentRendererComponent,
190
+ ],
191
+ exports: [
192
+ FsContentComponent,
193
+ ],
194
+ }]
195
+ }] });
196
+
197
+ var EditorType;
198
+ (function (EditorType) {
199
+ EditorType["Js"] = "js";
200
+ EditorType["Html"] = "html";
201
+ EditorType["Scss"] = "scss";
202
+ EditorType["GlobalScss"] = "globalScss";
203
+ })(EditorType || (EditorType = {}));
204
+
205
+ var PageType;
206
+ (function (PageType) {
207
+ PageType["StandardPage"] = "standardPage";
208
+ PageType["BlogPost"] = "blogPost";
209
+ PageType["HomePage"] = "homePage";
210
+ PageType["NotFoundPage"] = "notFoundPage";
211
+ })(PageType || (PageType = {}));
134
212
 
135
213
  class EditorLabelComponent {
136
214
  changed;
@@ -257,7 +335,7 @@ class EditorComponent {
257
335
  this.focused.emit(type);
258
336
  }
259
337
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: EditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
260
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.7", type: EditorComponent, isStandalone: true, selector: "app-editor", inputs: { showHtml: "showHtml", showScss: "showScss", showJs: "showJs", showGlobalScss: "showGlobalScss", html: "html", scss: "scss", js: "js", contentConfig: "contentConfig" }, outputs: { changed: "changed", focused: "focused", blured: "blured" }, ngImport: i0, template: "<as-split [unit]=\"'percent'\" [gutterSize]=\"25\"> \n <as-split-area [size]=\"70\" [visible]=\"showHtml\" [order]=\"1\">\n <div class=\"editor-container\">\n <app-editor-label\n [changed]=\"changes.html !== undefined\"\n [focused]=\"focusedArea === 'html'\">\n HTML\n </app-editor-label>\n <fs-text-editor \n [(ngModel)]=\"html\" \n name=\"html\"\n [fsModelChangeOptions]=\"{ debounce: 0 }\"\n (fsModelChange)=\"change(EditorType.Html, $event)\"\n [config]=\"htmlConfig\">\n </fs-text-editor> \n </div>\n </as-split-area>\n <as-split-area [size]=\"30\" [visible]=\"showScss\" [order]=\"2\">\n <div class=\"editor-container\">\n <app-editor-label\n [changed]=\"changes.scss !== undefined\"\n [focused]=\"focusedArea === 'scss'\">\n SCSS\n </app-editor-label>\n <fs-text-editor \n [(ngModel)]=\"scss\" \n name=\"scss\"\n [fsModelChangeOptions]=\"{ debounce: 0 }\"\n (fsModelChange)=\"change(EditorType.Scss, $event)\"\n [config]=\"scssConfig\">\n </fs-text-editor> \n </div>\n </as-split-area>\n <as-split-area [size]=\"30\" [visible]=\"showJs\" [order]=\"3\">\n <div class=\"editor-container\">\n <app-editor-label\n [changed]=\"changes.js !== undefined\"\n [focused]=\"focusedArea === 'js'\">\n JS\n </app-editor-label>\n <fs-text-editor \n [(ngModel)]=\"js\" \n name=\"js\"\n [fsModelChangeOptions]=\"{ debounce: 0 }\"\n (fsModelChange)=\"change(EditorType.Js, $event)\"\n [config]=\"jsConfig\">\n </fs-text-editor> \n </div>\n </as-split-area>\n <as-split-area [size]=\"30\" [visible]=\"showGlobalScss\" [order]=\"4\">\n <div class=\"editor-container\">\n <app-editor-label\n [changed]=\"changes.globalScss !== undefined\"\n [focused]=\"focusedArea === 'globalScss'\">\n Global SCSS\n </app-editor-label>\n <ng-container *fsSkeleton=\"contentStyle\">\n <fs-text-editor \n [(ngModel)]=\"contentStyle.scss\" \n name=\"globalScss\"\n [fsModelChangeOptions]=\"{ debounce: 300 }\"\n (fsModelChange)=\"change(EditorType.GlobalScss, $event)\"\n [config]=\"globalScssConfig\">\n </fs-text-editor> \n </ng-container> \n </div>\n </as-split-area>\n</as-split>\n", styles: [":host ::ng-deep .as-split-gutter{background-color:unset!important}.editor-container{height:100%;border-radius:5px;display:flex;flex-direction:column}.editor-container fs-text-editor{flex:1}\n"], dependencies: [{ kind: "ngmodule", type: AngularSplitModule }, { kind: "component", type: i1$1.SplitComponent, selector: "as-split", inputs: ["direction", "unit", "gutterSize", "gutterStep", "restrictMove", "useTransition", "disabled", "dir", "gutterDblClickDuration", "gutterClickDeltaPx", "gutterAriaLabel"], outputs: ["transitionEnd", "dragStart", "dragEnd", "gutterClick", "gutterDblClick"], exportAs: ["asSplit"] }, { kind: "directive", type: i1$1.SplitAreaDirective, selector: "as-split-area, [as-split-area]", inputs: ["order", "size", "minSize", "maxSize", "lockSize", "visible"], exportAs: ["asSplitArea"] }, { kind: "component", type: EditorLabelComponent, selector: "app-editor-label", inputs: ["changed", "focused"] }, { kind: "ngmodule", type: FsTextEditorModule }, { kind: "component", type: i2$1.FsTextEditorComponent, selector: "fs-text-editor", inputs: ["config", "scrollable"], outputs: ["ready", "blur"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: FsFormModule }, { kind: "directive", type: i3.FsFormNoFsValidatorsDirective, selector: "[ngModel]:not([required]):not([fsFormRequired]):not([fsFormCompare]):not([fsFormDateRange]):not([fsFormEmail]):not([fsFormEmails]):not([fsFormFunction]):not([fsFormGreater]):not([fsFormGreaterEqual]):not([fsFormInteger]):not([fsFormLesser]):not([fsFormMax]):not([fsFormMaxLength]):not([fsFormMin]):not([fsFormMinLength]):not([fsFormNumeric]):not([fsFormPattern]):not([fsFormPhone]):not([fsFormUrl]):not([validate])" }, { kind: "ngmodule", type: FsCommonModule }, { kind: "directive", type: i5$1.FsModelChangeDirective, selector: "[fsModelChange]", inputs: ["fsModelChangeOptions"], outputs: ["fsModelChange"] }, { kind: "ngmodule", type: FsSkeletonModule }, { kind: "directive", type: i1.FsSkeletonContentDirective, selector: "[fsSkeleton]", inputs: ["fsSkeleton", "fsSkeletonPattern"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
338
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.7", type: EditorComponent, isStandalone: true, selector: "app-editor", inputs: { showHtml: "showHtml", showScss: "showScss", showJs: "showJs", showGlobalScss: "showGlobalScss", html: "html", scss: "scss", js: "js", contentConfig: "contentConfig" }, outputs: { changed: "changed", focused: "focused", blured: "blured" }, ngImport: i0, template: "<as-split [unit]=\"'percent'\" [gutterSize]=\"25\"> \n <as-split-area [size]=\"70\" [visible]=\"showHtml\" [order]=\"1\">\n <div class=\"editor-container\">\n <app-editor-label\n [changed]=\"changes.html !== undefined\"\n [focused]=\"focusedArea === 'html'\">\n HTML\n </app-editor-label>\n <fs-text-editor \n [(ngModel)]=\"html\" \n name=\"html\"\n [fsModelChangeOptions]=\"{ debounce: 0 }\"\n (fsModelChange)=\"change(EditorType.Html, $event)\"\n [config]=\"htmlConfig\">\n </fs-text-editor> \n </div>\n </as-split-area>\n <as-split-area [size]=\"30\" [visible]=\"showScss\" [order]=\"2\">\n <div class=\"editor-container\">\n <app-editor-label\n [changed]=\"changes.scss !== undefined\"\n [focused]=\"focusedArea === 'scss'\">\n SCSS\n </app-editor-label>\n <fs-text-editor \n [(ngModel)]=\"scss\" \n name=\"scss\"\n [fsModelChangeOptions]=\"{ debounce: 0 }\"\n (fsModelChange)=\"change(EditorType.Scss, $event)\"\n [config]=\"scssConfig\">\n </fs-text-editor> \n </div>\n </as-split-area>\n <as-split-area [size]=\"30\" [visible]=\"showJs\" [order]=\"3\">\n <div class=\"editor-container\">\n <app-editor-label\n [changed]=\"changes.js !== undefined\"\n [focused]=\"focusedArea === 'js'\">\n JS\n </app-editor-label>\n <fs-text-editor \n [(ngModel)]=\"js\" \n name=\"js\"\n [fsModelChangeOptions]=\"{ debounce: 0 }\"\n (fsModelChange)=\"change(EditorType.Js, $event)\"\n [config]=\"jsConfig\">\n </fs-text-editor> \n </div>\n </as-split-area>\n <as-split-area [size]=\"30\" [visible]=\"showGlobalScss\" [order]=\"4\">\n <div class=\"editor-container\">\n <app-editor-label\n [changed]=\"changes.globalScss !== undefined\"\n [focused]=\"focusedArea === 'globalScss'\">\n Global SCSS\n </app-editor-label>\n <ng-container *fsSkeleton=\"contentStyle\">\n <fs-text-editor \n [(ngModel)]=\"contentStyle.scss\" \n name=\"globalScss\"\n [fsModelChangeOptions]=\"{ debounce: 300 }\"\n (fsModelChange)=\"change(EditorType.GlobalScss, $event)\"\n [config]=\"globalScssConfig\">\n </fs-text-editor> \n </ng-container> \n </div>\n </as-split-area>\n</as-split>\n", styles: [":host ::ng-deep .as-split-gutter{background-color:unset!important}.editor-container{height:100%;border-radius:5px;display:flex;flex-direction:column}.editor-container fs-text-editor{flex:1}\n"], dependencies: [{ kind: "ngmodule", type: AngularSplitModule }, { kind: "component", type: i1.SplitComponent, selector: "as-split", inputs: ["direction", "unit", "gutterSize", "gutterStep", "restrictMove", "useTransition", "disabled", "dir", "gutterDblClickDuration", "gutterClickDeltaPx", "gutterAriaLabel"], outputs: ["transitionEnd", "dragStart", "dragEnd", "gutterClick", "gutterDblClick"], exportAs: ["asSplit"] }, { kind: "directive", type: i1.SplitAreaDirective, selector: "as-split-area, [as-split-area]", inputs: ["order", "size", "minSize", "maxSize", "lockSize", "visible"], exportAs: ["asSplitArea"] }, { kind: "component", type: EditorLabelComponent, selector: "app-editor-label", inputs: ["changed", "focused"] }, { kind: "ngmodule", type: FsTextEditorModule }, { kind: "component", type: i2.FsTextEditorComponent, selector: "fs-text-editor", inputs: ["config", "scrollable"], outputs: ["ready", "blur"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: FsFormModule }, { kind: "directive", type: i3.FsFormNoFsValidatorsDirective, selector: "[ngModel]:not([required]):not([fsFormRequired]):not([fsFormCompare]):not([fsFormDateRange]):not([fsFormEmail]):not([fsFormEmails]):not([fsFormFunction]):not([fsFormGreater]):not([fsFormGreaterEqual]):not([fsFormInteger]):not([fsFormLesser]):not([fsFormMax]):not([fsFormMaxLength]):not([fsFormMin]):not([fsFormMinLength]):not([fsFormNumeric]):not([fsFormPattern]):not([fsFormPhone]):not([fsFormUrl]):not([validate])" }, { kind: "ngmodule", type: FsCommonModule }, { kind: "directive", type: i5.FsModelChangeDirective, selector: "[fsModelChange]", inputs: ["fsModelChangeOptions"], outputs: ["fsModelChange"] }, { kind: "ngmodule", type: FsSkeletonModule }, { kind: "directive", type: i1$1.FsSkeletonContentDirective, selector: "[fsSkeleton]", inputs: ["fsSkeleton", "fsSkeletonPattern"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
261
339
  }
262
340
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: EditorComponent, decorators: [{
263
341
  type: Component,
@@ -294,7 +372,64 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImpor
294
372
  type: Output
295
373
  }] } });
296
374
 
297
- class ContentPageEditorComponent {
375
+ class ContentLayoutComponent {
376
+ _config = inject(FS_CONTENT_CONFIG);
377
+ _data = inject(MAT_DIALOG_DATA);
378
+ _dialogRef = inject(MatDialogRef);
379
+ _message = inject(FsMessage);
380
+ _cdRef = inject(ChangeDetectorRef);
381
+ textEditors;
382
+ contentLayout = null;
383
+ editors = { content: true, styles: true };
384
+ _destroy$ = new Subject();
385
+ ngOnInit() {
386
+ this._fetchData();
387
+ }
388
+ ngOnDestroy() {
389
+ this._destroy$.next(null);
390
+ this._destroy$.complete();
391
+ }
392
+ save = () => {
393
+ return this._config.saveContentLayout(this.contentLayout)
394
+ .pipe(tap((contentLayout) => {
395
+ this._message.success('Saved Changes');
396
+ this._dialogRef.close(contentLayout);
397
+ }));
398
+ };
399
+ _fetchData() {
400
+ of(this._data.contentLayout)
401
+ .pipe(switchMap((contentLayout) => {
402
+ return of(contentLayout);
403
+ }), takeUntil(this._destroy$))
404
+ .subscribe((contentLayout) => {
405
+ this.contentLayout = { ...contentLayout };
406
+ this._cdRef.markForCheck();
407
+ });
408
+ }
409
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: ContentLayoutComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
410
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.7", type: ContentLayoutComponent, isStandalone: true, selector: "ng-component", viewQueries: [{ propertyName: "textEditors", predicate: FsTextEditorComponent, descendants: true }], ngImport: i0, template: "<form fsForm [submit]=\"save\" *fsSkeletonForm=\"contentLayout\">\n <fs-dialog>\n <h1 mat-dialog-title>{{contentLayout.id ? 'Layout' : 'Layout Page'}}</h1>\n <div mat-dialog-content>\n <div class=\"fs-column\">\n <mat-form-field>\n <mat-label>Name</mat-label>\n <input\n matInput\n [(ngModel)]=\"contentLayout.name\"\n name=\"name\"\n required>\n </mat-form-field>\n <mat-form-field>\n <mat-label>Tag</mat-label>\n <input\n matInput\n [(ngModel)]=\"contentLayout.tag\"\n name=\"tag\">\n </mat-form-field>\n </div>\n </div>\n\n <div mat-dialog-actions>\n <fs-form-dialog-actions>\n </fs-form-dialog-actions>\n </div>\n </fs-dialog>\n</form>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: FsSkeletonModule }, { kind: "directive", type: i1$1.FsSkeletonFormDirective, selector: "[fsSkeletonForm]", inputs: ["fsSkeletonForm", "fsSkeletonFormLines"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2$1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i2$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i2$1.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: FsFormModule }, { kind: "directive", type: i3.FsFormDirective, selector: "[fsForm]", inputs: ["wrapperSelector", "messageSelector", "hintSelector", "labelSelector", "autocomplete", "shortcuts", "confirm", "confirmDialog", "confirmDrawer", "confirmBrowser", "confirmTabs", "dirtySubmitButton", "submit", "successDelay", "errorDelay", "tabGroup", "deactivationGuard"], outputs: ["fsForm", "invalid", "valid", "submitted", "reseted", "cleared"], exportAs: ["fsForm"] }, { kind: "directive", type: i3.FsFormRequiredDirective, selector: "[fsFormRequired],[ngModel][required]", inputs: ["fsFormRequired", "required", "fsFormRequiredMessage"] }, { kind: "component", type: i3.FsFormDialogActionsComponent, selector: "fs-form-dialog-actions", inputs: ["save", "create", "close", "done", "closeData", "name"] }, { kind: "directive", type: i3.FsFormNoFsValidatorsDirective, selector: "[ngModel]:not([required]):not([fsFormRequired]):not([fsFormCompare]):not([fsFormDateRange]):not([fsFormEmail]):not([fsFormEmails]):not([fsFormFunction]):not([fsFormGreater]):not([fsFormGreaterEqual]):not([fsFormInteger]):not([fsFormLesser]):not([fsFormMax]):not([fsFormMaxLength]):not([fsFormMin]):not([fsFormMinLength]):not([fsFormNumeric]):not([fsFormPattern]):not([fsFormPhone]):not([fsFormUrl]):not([validate])" }, { kind: "ngmodule", type: FsDialogModule }, { kind: "directive", type: i4.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i4.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i4.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "component", type: i5$1.FsDialogComponent, selector: "fs-dialog", inputs: ["mobileMode", "mobileButtonPlacement", "mobileWidth", "mode", "buttonLayout", "dock", "dockable", "fullscreenPercent"] }, { kind: "component", type: MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: MatLabel, selector: "mat-label" }, { kind: "directive", type: MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
411
+ }
412
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: ContentLayoutComponent, decorators: [{
413
+ type: Component,
414
+ args: [{ changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [
415
+ FsSkeletonModule,
416
+ FormsModule,
417
+ FsFormModule,
418
+ FsDialogModule,
419
+ MatDialogTitle,
420
+ CdkScrollable,
421
+ MatDialogContent,
422
+ MatFormField,
423
+ MatLabel,
424
+ MatInput,
425
+ MatDialogActions,
426
+ ], template: "<form fsForm [submit]=\"save\" *fsSkeletonForm=\"contentLayout\">\n <fs-dialog>\n <h1 mat-dialog-title>{{contentLayout.id ? 'Layout' : 'Layout Page'}}</h1>\n <div mat-dialog-content>\n <div class=\"fs-column\">\n <mat-form-field>\n <mat-label>Name</mat-label>\n <input\n matInput\n [(ngModel)]=\"contentLayout.name\"\n name=\"name\"\n required>\n </mat-form-field>\n <mat-form-field>\n <mat-label>Tag</mat-label>\n <input\n matInput\n [(ngModel)]=\"contentLayout.tag\"\n name=\"tag\">\n </mat-form-field>\n </div>\n </div>\n\n <div mat-dialog-actions>\n <fs-form-dialog-actions>\n </fs-form-dialog-actions>\n </div>\n </fs-dialog>\n</form>\n" }]
427
+ }], propDecorators: { textEditors: [{
428
+ type: ViewChildren,
429
+ args: [FsTextEditorComponent]
430
+ }] } });
431
+
432
+ class ContentLayoutEditorComponent {
298
433
  _data = inject(MAT_DIALOG_DATA);
299
434
  _dialogRef = inject(MatDialogRef);
300
435
  _message = inject(FsMessage);
@@ -302,27 +437,26 @@ class ContentPageEditorComponent {
302
437
  _cdRef = inject(ChangeDetectorRef);
303
438
  _prompt = inject(FsPrompt);
304
439
  editor;
305
- contentPage;
306
- focused = null;
440
+ contentLayout;
441
+ get isMac() {
442
+ return navigator.platform.toUpperCase().indexOf('MAC') >= 0;
443
+ }
444
+ submitting;
307
445
  config;
308
- resizing = false;
446
+ EditorType = EditorType;
447
+ focused = null;
309
448
  title;
310
449
  editors = {
311
450
  [EditorType.Html]: true,
312
451
  [EditorType.Scss]: true,
313
- [EditorType.Js]: false,
314
452
  [EditorType.GlobalScss]: false,
315
453
  };
316
- get isMac() {
317
- return navigator.platform.toUpperCase().indexOf('MAC') >= 0;
318
- }
319
- submitting;
320
454
  _destroy$ = new Subject();
321
455
  ngOnInit() {
322
456
  this._dialogRef.addPanelClass('fs-content-editor-overlay-pane');
323
457
  this._dialogRef.disableClose = true;
324
458
  this.config = this._data.contentConfig;
325
- this._initContentPage(this._data.contentPage);
459
+ this._initContentLayout(this._data.contentLayout);
326
460
  this._initEscape();
327
461
  }
328
462
  editorToggleChange(event) {
@@ -332,10 +466,10 @@ class ContentPageEditorComponent {
332
466
  this._destroy$.next(null);
333
467
  this._destroy$.complete();
334
468
  }
335
- _initContentPage(contentPage) {
336
- this.config.loadContentPage(contentPage.id)
469
+ _initContentLayout(contentLayout) {
470
+ this.config.loadContentLayout(contentLayout.id)
337
471
  .subscribe((data) => {
338
- this.contentPage = data;
472
+ this.contentLayout = data;
339
473
  this._cdRef.markForCheck();
340
474
  });
341
475
  }
@@ -351,7 +485,6 @@ class ContentPageEditorComponent {
351
485
  return of(null)
352
486
  .pipe(filter(() => this.focused), switchMap(() => {
353
487
  switch (this.focused) {
354
- case EditorType.Js:
355
488
  case EditorType.Html:
356
489
  case EditorType.Scss:
357
490
  return this.saveContentPage();
@@ -365,21 +498,19 @@ class ContentPageEditorComponent {
365
498
  }), finalize(() => {
366
499
  this.submitting = false;
367
500
  this._cdRef.markForCheck();
368
- }))
369
- .pipe(takeUntil(this._destroy$));
501
+ }));
370
502
  };
371
503
  saveContentPage() {
372
504
  const names = {
373
- [EditorType.Js]: 'js',
374
505
  [EditorType.Scss]: 'styles',
375
506
  [EditorType.Html]: 'content',
376
507
  };
377
508
  const data = {
378
- id: this.contentPage.id,
509
+ id: this.contentLayout.id,
379
510
  [names[this.focused]]: this.editor.changes[this.focused],
380
511
  };
381
- return this.config.saveContentPage({
382
- id: this.contentPage.id,
512
+ return this.config.saveContentLayout({
513
+ id: this.contentLayout.id,
383
514
  ...data,
384
515
  })
385
516
  .pipe(tap(() => {
@@ -415,17 +546,17 @@ class ContentPageEditorComponent {
415
546
  });
416
547
  }
417
548
  openSettings() {
418
- this._dialog.open(ContentPageComponent, {
549
+ this._dialog.open(ContentLayoutComponent, {
419
550
  data: {
420
- contentPage: this.contentPage,
551
+ contentLayout: this.contentLayout,
421
552
  },
422
553
  })
423
554
  .afterClosed()
424
555
  .pipe(takeUntil(this._destroy$))
425
- .subscribe((contentPage) => {
426
- this.contentPage = {
427
- ...this.contentPage,
428
- ...contentPage,
556
+ .subscribe((contentLayout) => {
557
+ this.contentLayout = {
558
+ ...this.contentLayout,
559
+ ...contentLayout,
429
560
  };
430
561
  this._cdRef.markForCheck();
431
562
  });
@@ -439,10 +570,10 @@ class ContentPageEditorComponent {
439
570
  }
440
571
  });
441
572
  }
442
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: ContentPageEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
443
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.7", type: ContentPageEditorComponent, isStandalone: true, selector: "ng-component", viewQueries: [{ propertyName: "editor", first: true, predicate: EditorComponent, descendants: true }], ngImport: i0, template: "<form fsForm [submit]=\"submitted\" [dirtySubmitButton]=\"false\" [confirm]=\"false\">\n <fs-dialog *fsSkeletonForm=\"contentPage\">\n <h1 mat-dialog-title>\n <div class=\"title-container\">\n <div class=\"title\">\n Page Editor\n <div class=\"small\">{{contentPage.name}}</div> \n </div>\n <a\n (click)=\"openSettings()\"\n mat-icon-button>\n <mat-icon>settings</mat-icon>\n </a>\n\n <div class=\"toggles\">\n <mat-button-toggle-group multiple>\n <mat-button-toggle value=\"html\" [checked]=\"editors.html\" (change)=\"editorToggleChange($event)\">HTML</mat-button-toggle>\n <mat-button-toggle value=\"scss\" [checked]=\"editors.scss\" (change)=\"editorToggleChange($event)\">SCSS</mat-button-toggle>\n <mat-button-toggle value=\"js\" [checked]=\"editors.js\" (change)=\"editorToggleChange($event)\">JS</mat-button-toggle>\n <mat-button-toggle value=\"globalScss\" [checked]=\"editors.globalScss\" (change)=\"editorToggleChange($event)\">Global SCSS</mat-button-toggle>\n </mat-button-toggle-group> \n </div>\n\n <div class=\"actions\">\n <button\n #submit\n mat-stroked-button\n color=\"primary\"\n [disabled]=\"!editor?.hasChanges || submitting\"\n [matTooltip]=\"isMac ? 'cmd+s' : 'ctrl+s'\"\n type=\"button\"\n (click)=\"save()\"> \n Save\n </button>\n\n <a \n mat-stroked-button\n target=\"_blank\"\n [routerLink]=\"contentPage.path\"\n type=\"button\"> \n Preview\n </a>\n\n <button \n mat-stroked-button\n (click)=\"close()\"\n type=\"button\"> \n Done\n </button>\n </div>\n </div>\n </h1>\n <div mat-dialog-content>\n <app-editor\n [contentConfig]=\"config\"\n [showHtml]=\"editors.html\"\n [showJs]=\"editors.js\"\n [showScss]=\"editors.scss\"\n [showGlobalScss]=\"editors.globalScss\"\n [html]=\"contentPage.content\"\n [scss]=\"contentPage.styles\"\n [js]=\"contentPage.js\"\n (focused)=\"editorFocused($event)\">\n </app-editor>\n </div>\n </fs-dialog>\n</form>\n", styles: ["::ng-deep .fs-content-editor-overlay-pane .mat-dialog-container{border-radius:0}form{height:100%}fs-dialog{display:flex;height:100%;flex-direction:column}fs-dialog ::ng-deep .mat-dialog-content{max-height:none;flex:1;overflow:hidden}fs-dialog ::ng-deep .mat-button-toggle-label-content{line-height:36px}h1 .toggles{display:flex;justify-content:flex-end;justify-self:baseline;font-size:13px}h1 .actions{margin-left:30px}h1 .actions .mdc-button{margin-left:5px}.title-container{display:flex;align-items:center}.title-container .title{flex:1}.title-container .title .small{line-height:normal}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: FsFormModule }, { kind: "directive", type: i3.FsFormDirective, selector: "[fsForm]", inputs: ["wrapperSelector", "messageSelector", "hintSelector", "labelSelector", "autocomplete", "shortcuts", "confirm", "confirmDialog", "confirmDrawer", "confirmBrowser", "confirmTabs", "dirtySubmitButton", "submit", "successDelay", "errorDelay", "tabGroup", "deactivationGuard"], outputs: ["fsForm", "invalid", "valid", "submitted", "reseted", "cleared"], exportAs: ["fsForm"] }, { kind: "directive", type: i3.FsButtonDirective, selector: "[mat-raised-button]:not([fsFormButtonStandalone]),[mat-button]:not([fsFormButtonStandalone]),[mat-flat-button]:not([fsFormButtonStandalone]),[mat-stroked-button]:not([fsFormButtonStandalone])", inputs: ["name", "dirtySubmit", "form"] }, { kind: "ngmodule", type: FsSkeletonModule }, { kind: "directive", type: i1.FsSkeletonFormDirective, selector: "[fsSkeletonForm]", inputs: ["fsSkeletonForm", "fsSkeletonFormLines"] }, { kind: "ngmodule", type: FsDialogModule }, { kind: "directive", type: i4.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i4.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "component", type: i5.FsDialogComponent, selector: "fs-dialog", inputs: ["mobileMode", "mobileButtonPlacement", "mobileWidth", "mode", "buttonLayout", "dock", "dockable", "fullscreenPercent"] }, { kind: "component", type: MatIconAnchor, selector: "a[mat-icon-button]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: MatButtonToggleGroup, selector: "mat-button-toggle-group", inputs: ["appearance", "name", "vertical", "value", "multiple", "disabled", "disabledInteractive", "hideSingleSelectionIndicator", "hideMultipleSelectionIndicator"], outputs: ["valueChange", "change"], exportAs: ["matButtonToggleGroup"] }, { kind: "component", type: MatButtonToggle, selector: "mat-button-toggle", inputs: ["aria-label", "aria-labelledby", "id", "name", "value", "tabIndex", "disableRipple", "appearance", "checked", "disabled", "disabledInteractive"], outputs: ["change"], exportAs: ["matButtonToggle"] }, { kind: "component", type: MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: MatAnchor, selector: "a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button]", exportAs: ["matButton", "matAnchor"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: EditorComponent, selector: "app-editor", inputs: ["showHtml", "showScss", "showJs", "showGlobalScss", "html", "scss", "js", "contentConfig"], outputs: ["changed", "focused", "blured"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
573
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: ContentLayoutEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
574
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.7", type: ContentLayoutEditorComponent, isStandalone: true, selector: "ng-component", viewQueries: [{ propertyName: "editor", first: true, predicate: EditorComponent, descendants: true }], ngImport: i0, template: "<form fsForm [submit]=\"submitted\" [dirtySubmitButton]=\"false\" [confirm]=\"false\">\n <fs-dialog *fsSkeletonForm=\"contentLayout\">\n <h1 mat-dialog-title>\n <div class=\"title-container\">\n <div class=\"title\">\n Layout Editor\n <div class=\"small\">{{contentLayout.name}}</div> \n </div>\n <a\n (click)=\"openSettings()\"\n mat-icon-button>\n <mat-icon>settings</mat-icon>\n </a>\n\n <div class=\"toggles\">\n <mat-button-toggle-group multiple>\n <mat-button-toggle value=\"html\" [checked]=\"editors.html\" (change)=\"editorToggleChange($event)\">HTML</mat-button-toggle>\n <mat-button-toggle value=\"scss\" [checked]=\"editors.scss\" (change)=\"editorToggleChange($event)\">SCSS</mat-button-toggle>\n <!-- <mat-button-toggle value=\"js\" [checked]=\"editors.js\" (change)=\"editorToggleChange($event)\">JS</mat-button-toggle> -->\n <mat-button-toggle value=\"globalScss\" [checked]=\"editors.globalScss\" (change)=\"editorToggleChange($event)\">Global SCSS</mat-button-toggle>\n </mat-button-toggle-group> \n </div>\n\n <div class=\"actions\">\n <button\n #submit\n mat-stroked-button\n color=\"primary\"\n [disabled]=\"!editor?.hasChanges || submitting\"\n [matTooltip]=\"isMac ? 'cmd+s' : 'ctrl+s'\"\n type=\"button\"\n (click)=\"save()\"> \n Save\n </button>\n\n <button \n mat-stroked-button\n (click)=\"close()\"\n type=\"button\"> \n Done\n </button>\n </div>\n </div>\n </h1>\n <div mat-dialog-content>\n <app-editor\n [contentConfig]=\"config\"\n [showHtml]=\"editors.html\"\n [showScss]=\"editors.scss\"\n [showGlobalScss]=\"editors.globalScss\"\n [html]=\"contentLayout.content\"\n [scss]=\"contentLayout.styles\"\n (focused)=\"editorFocused($event)\">\n </app-editor>\n </div>\n\n <!-- <div mat-dialog-actions>\n <button \n mat-button\n color=\"primary\"\n (click)=\"close()\"\n type=\"button\"> \n Done \n </button>\n <div class=\"toggles\">\n <mat-button-toggle-group multiple>\n <mat-button-toggle value=\"html\" [checked]=\"editors.html\" (change)=\"editorToggleChange($event)\">HTML</mat-button-toggle>\n <mat-button-toggle value=\"scss\" [checked]=\"editors.scss\" (change)=\"editorToggleChange($event)\">SCSS</mat-button-toggle>\n <mat-button-toggle value=\"globalScss\" [checked]=\"editors.globalScss\" (change)=\"editorToggleChange($event)\">Global SCSS</mat-button-toggle>\n </mat-button-toggle-group> \n </div>\n </div> -->\n </fs-dialog>\n</form>", styles: ["::ng-deep .fs-content-editor-overlay-pane .mat-dialog-container{border-radius:0}form{height:100%}fs-dialog{display:flex;height:100%;flex-direction:column}fs-dialog ::ng-deep .mat-dialog-content{max-height:none;flex:1;overflow:hidden}fs-dialog ::ng-deep .mat-button-toggle-label-content{line-height:36px}h1 .toggles{display:flex;justify-content:flex-end;justify-self:baseline;font-size:13px}h1 .actions{margin-left:30px}h1 .actions .mdc-button{margin-left:5px}.title-container{display:flex;align-items:center}.title-container .title{flex:1}.title-container .title .small{line-height:normal}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2$1.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: FsFormModule }, { kind: "directive", type: i3.FsFormDirective, selector: "[fsForm]", inputs: ["wrapperSelector", "messageSelector", "hintSelector", "labelSelector", "autocomplete", "shortcuts", "confirm", "confirmDialog", "confirmDrawer", "confirmBrowser", "confirmTabs", "dirtySubmitButton", "submit", "successDelay", "errorDelay", "tabGroup", "deactivationGuard"], outputs: ["fsForm", "invalid", "valid", "submitted", "reseted", "cleared"], exportAs: ["fsForm"] }, { kind: "directive", type: i3.FsButtonDirective, selector: "[mat-raised-button]:not([fsFormButtonStandalone]),[mat-button]:not([fsFormButtonStandalone]),[mat-flat-button]:not([fsFormButtonStandalone]),[mat-stroked-button]:not([fsFormButtonStandalone])", inputs: ["name", "dirtySubmit", "form"] }, { kind: "ngmodule", type: FsSkeletonModule }, { kind: "directive", type: i1$1.FsSkeletonFormDirective, selector: "[fsSkeletonForm]", inputs: ["fsSkeletonForm", "fsSkeletonFormLines"] }, { kind: "ngmodule", type: FsDialogModule }, { kind: "directive", type: i4.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i4.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "component", type: i5$1.FsDialogComponent, selector: "fs-dialog", inputs: ["mobileMode", "mobileButtonPlacement", "mobileWidth", "mode", "buttonLayout", "dock", "dockable", "fullscreenPercent"] }, { kind: "component", type: MatIconAnchor, selector: "a[mat-icon-button]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: MatButtonToggleGroup, selector: "mat-button-toggle-group", inputs: ["appearance", "name", "vertical", "value", "multiple", "disabled", "disabledInteractive", "hideSingleSelectionIndicator", "hideMultipleSelectionIndicator"], outputs: ["valueChange", "change"], exportAs: ["matButtonToggleGroup"] }, { kind: "component", type: MatButtonToggle, selector: "mat-button-toggle", inputs: ["aria-label", "aria-labelledby", "id", "name", "value", "tabIndex", "disableRipple", "appearance", "checked", "disabled", "disabledInteractive"], outputs: ["change"], exportAs: ["matButtonToggle"] }, { kind: "component", type: MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: EditorComponent, selector: "app-editor", inputs: ["showHtml", "showScss", "showJs", "showGlobalScss", "html", "scss", "js", "contentConfig"], outputs: ["changed", "focused", "blured"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
444
575
  }
445
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: ContentPageEditorComponent, decorators: [{
576
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: ContentLayoutEditorComponent, decorators: [{
446
577
  type: Component,
447
578
  args: [{ changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [
448
579
  FormsModule,
@@ -456,39 +587,33 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImpor
456
587
  MatButtonToggle,
457
588
  MatButton,
458
589
  MatTooltip,
459
- MatAnchor,
460
- RouterLink,
461
590
  CdkScrollable,
462
591
  MatDialogContent,
463
592
  EditorComponent,
464
- ], template: "<form fsForm [submit]=\"submitted\" [dirtySubmitButton]=\"false\" [confirm]=\"false\">\n <fs-dialog *fsSkeletonForm=\"contentPage\">\n <h1 mat-dialog-title>\n <div class=\"title-container\">\n <div class=\"title\">\n Page Editor\n <div class=\"small\">{{contentPage.name}}</div> \n </div>\n <a\n (click)=\"openSettings()\"\n mat-icon-button>\n <mat-icon>settings</mat-icon>\n </a>\n\n <div class=\"toggles\">\n <mat-button-toggle-group multiple>\n <mat-button-toggle value=\"html\" [checked]=\"editors.html\" (change)=\"editorToggleChange($event)\">HTML</mat-button-toggle>\n <mat-button-toggle value=\"scss\" [checked]=\"editors.scss\" (change)=\"editorToggleChange($event)\">SCSS</mat-button-toggle>\n <mat-button-toggle value=\"js\" [checked]=\"editors.js\" (change)=\"editorToggleChange($event)\">JS</mat-button-toggle>\n <mat-button-toggle value=\"globalScss\" [checked]=\"editors.globalScss\" (change)=\"editorToggleChange($event)\">Global SCSS</mat-button-toggle>\n </mat-button-toggle-group> \n </div>\n\n <div class=\"actions\">\n <button\n #submit\n mat-stroked-button\n color=\"primary\"\n [disabled]=\"!editor?.hasChanges || submitting\"\n [matTooltip]=\"isMac ? 'cmd+s' : 'ctrl+s'\"\n type=\"button\"\n (click)=\"save()\"> \n Save\n </button>\n\n <a \n mat-stroked-button\n target=\"_blank\"\n [routerLink]=\"contentPage.path\"\n type=\"button\"> \n Preview\n </a>\n\n <button \n mat-stroked-button\n (click)=\"close()\"\n type=\"button\"> \n Done\n </button>\n </div>\n </div>\n </h1>\n <div mat-dialog-content>\n <app-editor\n [contentConfig]=\"config\"\n [showHtml]=\"editors.html\"\n [showJs]=\"editors.js\"\n [showScss]=\"editors.scss\"\n [showGlobalScss]=\"editors.globalScss\"\n [html]=\"contentPage.content\"\n [scss]=\"contentPage.styles\"\n [js]=\"contentPage.js\"\n (focused)=\"editorFocused($event)\">\n </app-editor>\n </div>\n </fs-dialog>\n</form>\n", styles: ["::ng-deep .fs-content-editor-overlay-pane .mat-dialog-container{border-radius:0}form{height:100%}fs-dialog{display:flex;height:100%;flex-direction:column}fs-dialog ::ng-deep .mat-dialog-content{max-height:none;flex:1;overflow:hidden}fs-dialog ::ng-deep .mat-button-toggle-label-content{line-height:36px}h1 .toggles{display:flex;justify-content:flex-end;justify-self:baseline;font-size:13px}h1 .actions{margin-left:30px}h1 .actions .mdc-button{margin-left:5px}.title-container{display:flex;align-items:center}.title-container .title{flex:1}.title-container .title .small{line-height:normal}\n"] }]
593
+ ], template: "<form fsForm [submit]=\"submitted\" [dirtySubmitButton]=\"false\" [confirm]=\"false\">\n <fs-dialog *fsSkeletonForm=\"contentLayout\">\n <h1 mat-dialog-title>\n <div class=\"title-container\">\n <div class=\"title\">\n Layout Editor\n <div class=\"small\">{{contentLayout.name}}</div> \n </div>\n <a\n (click)=\"openSettings()\"\n mat-icon-button>\n <mat-icon>settings</mat-icon>\n </a>\n\n <div class=\"toggles\">\n <mat-button-toggle-group multiple>\n <mat-button-toggle value=\"html\" [checked]=\"editors.html\" (change)=\"editorToggleChange($event)\">HTML</mat-button-toggle>\n <mat-button-toggle value=\"scss\" [checked]=\"editors.scss\" (change)=\"editorToggleChange($event)\">SCSS</mat-button-toggle>\n <!-- <mat-button-toggle value=\"js\" [checked]=\"editors.js\" (change)=\"editorToggleChange($event)\">JS</mat-button-toggle> -->\n <mat-button-toggle value=\"globalScss\" [checked]=\"editors.globalScss\" (change)=\"editorToggleChange($event)\">Global SCSS</mat-button-toggle>\n </mat-button-toggle-group> \n </div>\n\n <div class=\"actions\">\n <button\n #submit\n mat-stroked-button\n color=\"primary\"\n [disabled]=\"!editor?.hasChanges || submitting\"\n [matTooltip]=\"isMac ? 'cmd+s' : 'ctrl+s'\"\n type=\"button\"\n (click)=\"save()\"> \n Save\n </button>\n\n <button \n mat-stroked-button\n (click)=\"close()\"\n type=\"button\"> \n Done\n </button>\n </div>\n </div>\n </h1>\n <div mat-dialog-content>\n <app-editor\n [contentConfig]=\"config\"\n [showHtml]=\"editors.html\"\n [showScss]=\"editors.scss\"\n [showGlobalScss]=\"editors.globalScss\"\n [html]=\"contentLayout.content\"\n [scss]=\"contentLayout.styles\"\n (focused)=\"editorFocused($event)\">\n </app-editor>\n </div>\n\n <!-- <div mat-dialog-actions>\n <button \n mat-button\n color=\"primary\"\n (click)=\"close()\"\n type=\"button\"> \n Done \n </button>\n <div class=\"toggles\">\n <mat-button-toggle-group multiple>\n <mat-button-toggle value=\"html\" [checked]=\"editors.html\" (change)=\"editorToggleChange($event)\">HTML</mat-button-toggle>\n <mat-button-toggle value=\"scss\" [checked]=\"editors.scss\" (change)=\"editorToggleChange($event)\">SCSS</mat-button-toggle>\n <mat-button-toggle value=\"globalScss\" [checked]=\"editors.globalScss\" (change)=\"editorToggleChange($event)\">Global SCSS</mat-button-toggle>\n </mat-button-toggle-group> \n </div>\n </div> -->\n </fs-dialog>\n</form>", styles: ["::ng-deep .fs-content-editor-overlay-pane .mat-dialog-container{border-radius:0}form{height:100%}fs-dialog{display:flex;height:100%;flex-direction:column}fs-dialog ::ng-deep .mat-dialog-content{max-height:none;flex:1;overflow:hidden}fs-dialog ::ng-deep .mat-button-toggle-label-content{line-height:36px}h1 .toggles{display:flex;justify-content:flex-end;justify-self:baseline;font-size:13px}h1 .actions{margin-left:30px}h1 .actions .mdc-button{margin-left:5px}.title-container{display:flex;align-items:center}.title-container .title{flex:1}.title-container .title .small{line-height:normal}\n"] }]
465
594
  }], propDecorators: { editor: [{
466
595
  type: ViewChild,
467
596
  args: [EditorComponent]
468
597
  }] } });
469
598
 
470
- class FsContentPagesComponent {
599
+ class FsContentLayoutsComponent {
471
600
  _config = inject(FS_CONTENT_CONFIG);
472
601
  _dialog = inject(MatDialog);
473
- htmlEditorConfig;
474
602
  listComponent;
475
603
  listConfig;
476
- pageTypes = index(PageTypes, 'value', 'name');
477
604
  _destroy$ = new Subject();
478
605
  ngOnInit() {
479
606
  this._initListConfig();
480
607
  }
481
- openEditor(contentPage) {
482
- this._dialog.open(ContentPageEditorComponent, {
483
- data: {
484
- contentPage,
485
- config: this._config,
486
- contentConfig: this._config,
487
- },
608
+ openEditor(contentLayout) {
609
+ this._dialog.open(ContentLayoutEditorComponent, {
488
610
  maxWidth: '100vw',
489
611
  width: '100%',
490
612
  height: '100%',
491
- autoFocus: false,
613
+ data: {
614
+ contentLayout,
615
+ contentConfig: this._config,
616
+ },
492
617
  })
493
618
  .afterClosed()
494
619
  .pipe(takeUntil(this._destroy$))
@@ -496,17 +621,19 @@ class FsContentPagesComponent {
496
621
  this.listComponent.reload();
497
622
  });
498
623
  }
624
+ openLayout(contentLayout) {
625
+ return this._dialog.open(ContentLayoutComponent, {
626
+ data: {
627
+ contentLayout,
628
+ },
629
+ })
630
+ .afterClosed()
631
+ .pipe(filter((_contentLayout) => !!_contentLayout), takeUntil(this._destroy$));
632
+ }
499
633
  ngOnDestroy() {
500
634
  this._destroy$.next(null);
501
635
  this._destroy$.complete();
502
636
  }
503
- openContentPage(contentPage) {
504
- return this._dialog.open(ContentPageComponent, {
505
- data: { contentPage },
506
- })
507
- .afterClosed()
508
- .pipe(takeUntil(this._destroy$));
509
- }
510
637
  _initListConfig() {
511
638
  this.listConfig = {
512
639
  filters: [
@@ -520,12 +647,8 @@ class FsContentPagesComponent {
520
647
  {
521
648
  label: 'Create',
522
649
  click: () => {
523
- this.openContentPage({
524
- type: PageType.StandardPage,
525
- })
526
- .pipe(filter((contentPage) => !!contentPage))
527
- .subscribe((contentPage) => {
528
- this.openEditor(contentPage);
650
+ this.openLayout({})
651
+ .subscribe(() => {
529
652
  this.listComponent.reload();
530
653
  });
531
654
  },
@@ -534,7 +657,7 @@ class FsContentPagesComponent {
534
657
  rowActions: [
535
658
  {
536
659
  click: (data) => {
537
- return this._config.deleteContentPage(data);
660
+ return this._config.deleteContentLayout(data);
538
661
  },
539
662
  remove: {
540
663
  title: 'Confirm',
@@ -545,13 +668,9 @@ class FsContentPagesComponent {
545
668
  },
546
669
  ],
547
670
  fetch: (query) => {
548
- query = {
549
- contentLayouts: true,
550
- ...query,
551
- };
552
- return this._config.loadContentPages(query)
671
+ return this._config.loadContentLayouts(query)
553
672
  .pipe(map((response) => {
554
- return { data: response.contentPages, paging: response.paging };
673
+ return { data: response.contentLayouts, paging: response.paging };
555
674
  }));
556
675
  },
557
676
  restore: {
@@ -560,67 +679,73 @@ class FsContentPagesComponent {
560
679
  menuLabel: 'Restore',
561
680
  reload: true,
562
681
  click: (row) => {
563
- return this._config.saveContentPage({ id: row.id, state: 'active' });
682
+ return this._config.saveContentLayout({ id: row.id, state: 'active' });
564
683
  },
565
684
  },
566
685
  };
567
686
  }
568
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: FsContentPagesComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
569
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.7", type: FsContentPagesComponent, isStandalone: true, selector: "fs-content-pages", inputs: { htmlEditorConfig: "htmlEditorConfig" }, viewQueries: [{ propertyName: "listComponent", first: true, predicate: FsListComponent, descendants: true }], ngImport: i0, template: "<fs-list [config]=\"listConfig\">\n <fs-list-column name=\"name\" title=\"Name\" [sortable]=\"true\">\n <ng-template fs-list-cell let-row=\"row\">\n @if (row.state !== 'deleted') {\n <a (click)=\"openEditor(row)\">\n <ng-container [ngTemplateOutlet]=\"name\"></ng-container>\n </a>\n } @else {\n {{row.name}}\n }\n <ng-template #name>{{row.name}}</ng-template>\n </ng-template>\n </fs-list-column>\n <fs-list-column name=\"path\" title=\"Path\" [sortable]=\"true\">\n <ng-template fs-list-cell let-row=\"row\">\n @if (row.state !== 'deleted') {\n <a [href]=\"'/' + row.path\" target=\"_black\">\n <ng-container [ngTemplateOutlet]=\"path\"></ng-container>\n </a>\n } @else {\n /{{row.path}}\n }\n <ng-template #path>/{{row.path}}</ng-template>\n </ng-template>\n </fs-list-column>\n <fs-list-column name=\"layout\" title=\"Layout\">\n <ng-template fs-list-cell let-row=\"row\">\n {{row.contentLayout?.name}}\n </ng-template>\n </fs-list-column>\n <fs-list-column name=\"type\" title=\"Type\" [sortable]=\"true\">\n <ng-template fs-list-cell let-row=\"row\">\n {{pageTypes[row.type]}}\n </ng-template>\n </fs-list-column>\n <fs-list-column name=\"modify_date\" title=\"Modified\" [sortable]=\"true\">\n <ng-template fs-list-cell let-row=\"row\">\n {{row.modifyDate | fsDate: 'date-time-yearless'}}\n </ng-template>\n </fs-list-column>\n</fs-list>\n", styles: [":host ::ng-deep .modified,:host ::ng-deep .name{width:1%;white-space:nowrap}:host ::ng-deep .preview-content img{display:none}.preview-content{position:relative;max-height:100px;max-width:100%;overflow:hidden;-webkit-mask-image:-webkit-gradient(linear,left 60%,left bottom,from(rgb(0,0,0)),to(rgba(0,0,0,0)))}\n"], dependencies: [{ kind: "ngmodule", type: FsListModule }, { kind: "component", type: i1$2.FsListComponent, selector: "fs-list", inputs: ["config", "loaderLines"], outputs: ["filtersReady"] }, { kind: "directive", type: i1$2.FsListColumnDirective, selector: "fs-list-column", inputs: ["show", "title", "name", "customize", "sortable", "sortableDefault", "sortableDirection", "direction", "align", "width", "class"] }, { kind: "directive", type: i1$2.FsListCellDirective, selector: "[fs-list-cell]", inputs: ["colspan", "align", "class"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: FsDateModule }, { kind: "pipe", type: i2$2.FsDatePipe, name: "fsDate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
687
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: FsContentLayoutsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
688
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.7", type: FsContentLayoutsComponent, isStandalone: true, selector: "fs-content-layouts", viewQueries: [{ propertyName: "listComponent", first: true, predicate: FsListComponent, descendants: true }], ngImport: i0, template: "<fs-list [config]=\"listConfig\">\n <fs-list-column name=\"name\" title=\"Name\" [sortable]=\"true\">\n <ng-template fs-list-cell let-row=\"row\">\n @if (row.state !== 'deleted') {\n <a (click)=\"openEditor(row)\">\n <ng-container [ngTemplateOutlet]=\"name\"></ng-container>\n </a>\n } @else {\n {{row.name}}\n }\n\n <ng-template #name>{{row.name}}</ng-template>\n </ng-template>\n </fs-list-column>\n <fs-list-column name=\"modify_date\" title=\"Modified\" [sortable]=\"true\">\n <ng-template fs-list-cell let-row=\"row\">\n {{row.modifyDate | fsDate: 'date-time-yearless'}}\n </ng-template>\n </fs-list-column>\n</fs-list>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: FsListModule }, { kind: "component", type: i1$2.FsListComponent, selector: "fs-list", inputs: ["config", "loaderLines"], outputs: ["filtersReady"] }, { kind: "directive", type: i1$2.FsListColumnDirective, selector: "fs-list-column", inputs: ["show", "title", "name", "customize", "sortable", "sortableDefault", "sortableDirection", "direction", "align", "width", "class"] }, { kind: "directive", type: i1$2.FsListCellDirective, selector: "[fs-list-cell]", inputs: ["colspan", "align", "class"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: FsDateModule }, { kind: "pipe", type: i2$2.FsDatePipe, name: "fsDate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
570
689
  }
571
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: FsContentPagesComponent, decorators: [{
690
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: FsContentLayoutsComponent, decorators: [{
572
691
  type: Component,
573
- args: [{ selector: 'fs-content-pages', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [
692
+ args: [{ selector: 'fs-content-layouts', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [
574
693
  FsListModule,
575
694
  NgTemplateOutlet,
576
695
  FsDateModule,
577
- ], template: "<fs-list [config]=\"listConfig\">\n <fs-list-column name=\"name\" title=\"Name\" [sortable]=\"true\">\n <ng-template fs-list-cell let-row=\"row\">\n @if (row.state !== 'deleted') {\n <a (click)=\"openEditor(row)\">\n <ng-container [ngTemplateOutlet]=\"name\"></ng-container>\n </a>\n } @else {\n {{row.name}}\n }\n <ng-template #name>{{row.name}}</ng-template>\n </ng-template>\n </fs-list-column>\n <fs-list-column name=\"path\" title=\"Path\" [sortable]=\"true\">\n <ng-template fs-list-cell let-row=\"row\">\n @if (row.state !== 'deleted') {\n <a [href]=\"'/' + row.path\" target=\"_black\">\n <ng-container [ngTemplateOutlet]=\"path\"></ng-container>\n </a>\n } @else {\n /{{row.path}}\n }\n <ng-template #path>/{{row.path}}</ng-template>\n </ng-template>\n </fs-list-column>\n <fs-list-column name=\"layout\" title=\"Layout\">\n <ng-template fs-list-cell let-row=\"row\">\n {{row.contentLayout?.name}}\n </ng-template>\n </fs-list-column>\n <fs-list-column name=\"type\" title=\"Type\" [sortable]=\"true\">\n <ng-template fs-list-cell let-row=\"row\">\n {{pageTypes[row.type]}}\n </ng-template>\n </fs-list-column>\n <fs-list-column name=\"modify_date\" title=\"Modified\" [sortable]=\"true\">\n <ng-template fs-list-cell let-row=\"row\">\n {{row.modifyDate | fsDate: 'date-time-yearless'}}\n </ng-template>\n </fs-list-column>\n</fs-list>\n", styles: [":host ::ng-deep .modified,:host ::ng-deep .name{width:1%;white-space:nowrap}:host ::ng-deep .preview-content img{display:none}.preview-content{position:relative;max-height:100px;max-width:100%;overflow:hidden;-webkit-mask-image:-webkit-gradient(linear,left 60%,left bottom,from(rgb(0,0,0)),to(rgba(0,0,0,0)))}\n"] }]
578
- }], propDecorators: { htmlEditorConfig: [{
579
- type: Input
580
- }], listComponent: [{
696
+ ], template: "<fs-list [config]=\"listConfig\">\n <fs-list-column name=\"name\" title=\"Name\" [sortable]=\"true\">\n <ng-template fs-list-cell let-row=\"row\">\n @if (row.state !== 'deleted') {\n <a (click)=\"openEditor(row)\">\n <ng-container [ngTemplateOutlet]=\"name\"></ng-container>\n </a>\n } @else {\n {{row.name}}\n }\n\n <ng-template #name>{{row.name}}</ng-template>\n </ng-template>\n </fs-list-column>\n <fs-list-column name=\"modify_date\" title=\"Modified\" [sortable]=\"true\">\n <ng-template fs-list-cell let-row=\"row\">\n {{row.modifyDate | fsDate: 'date-time-yearless'}}\n </ng-template>\n </fs-list-column>\n</fs-list>\n" }]
697
+ }], propDecorators: { listComponent: [{
581
698
  type: ViewChild,
582
699
  args: [FsListComponent]
583
700
  }] } });
584
701
 
585
- class FsContentPagesModule {
702
+ class FsContentLayoutsModule {
586
703
  static forRoot() {
587
704
  return {
588
- ngModule: FsContentPagesModule,
705
+ ngModule: FsContentLayoutsModule,
589
706
  };
590
707
  }
591
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: FsContentPagesModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
592
- static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.7", ngImport: i0, type: FsContentPagesModule, imports: [FsContentPagesComponent,
593
- ContentPageComponent,
594
- ContentPageEditorComponent], exports: [FsContentPagesComponent] });
595
- static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: FsContentPagesModule, imports: [FsContentPagesComponent,
596
- ContentPageComponent,
597
- ContentPageEditorComponent] });
708
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: FsContentLayoutsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
709
+ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.7", ngImport: i0, type: FsContentLayoutsModule, imports: [FsContentLayoutsComponent,
710
+ ContentLayoutComponent,
711
+ ContentLayoutEditorComponent], exports: [FsContentLayoutsComponent] });
712
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: FsContentLayoutsModule, imports: [FsContentLayoutsComponent,
713
+ ContentLayoutComponent,
714
+ ContentLayoutEditorComponent] });
598
715
  }
599
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: FsContentPagesModule, decorators: [{
716
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: FsContentLayoutsModule, decorators: [{
600
717
  type: NgModule,
601
718
  args: [{
602
719
  imports: [
603
- FsContentPagesComponent,
604
- ContentPageComponent,
605
- ContentPageEditorComponent,
720
+ FsContentLayoutsComponent,
721
+ ContentLayoutComponent,
722
+ ContentLayoutEditorComponent,
606
723
  ],
607
724
  exports: [
608
- FsContentPagesComponent,
725
+ FsContentLayoutsComponent,
609
726
  ],
610
727
  }]
611
728
  }] });
612
729
 
613
- class ContentLayoutComponent {
730
+ const PageTypes = [
731
+ { name: 'Page', value: PageType.StandardPage },
732
+ { name: 'Page (Not Found)', value: PageType.NotFoundPage },
733
+ ];
734
+
735
+ class ContentPageComponent {
614
736
  _config = inject(FS_CONTENT_CONFIG);
615
737
  _data = inject(MAT_DIALOG_DATA);
616
738
  _dialogRef = inject(MatDialogRef);
617
739
  _message = inject(FsMessage);
618
740
  _cdRef = inject(ChangeDetectorRef);
619
741
  textEditors;
620
- contentLayout = null;
742
+ contentPage = null;
743
+ PageTypes = PageTypes;
744
+ contentLayouts;
621
745
  editors = { content: true, styles: true };
622
746
  _destroy$ = new Subject();
623
747
  ngOnInit() {
748
+ this._dialogRef.updateSize('600px');
624
749
  this._fetchData();
625
750
  }
626
751
  ngOnDestroy() {
@@ -628,26 +753,34 @@ class ContentLayoutComponent {
628
753
  this._destroy$.complete();
629
754
  }
630
755
  save = () => {
631
- return this._config.saveContentLayout(this.contentLayout)
632
- .pipe(tap((contentLayout) => {
756
+ return this._config.saveContentPage(this.contentPage)
757
+ .pipe(tap((contentPage) => {
633
758
  this._message.success('Saved Changes');
634
- this._dialogRef.close(contentLayout);
759
+ this._dialogRef.close(contentPage);
635
760
  }));
636
761
  };
637
762
  _fetchData() {
638
- of(this._data.contentLayout)
639
- .pipe(switchMap((contentLayout) => {
640
- return of(contentLayout);
763
+ this._config.loadContentLayouts()
764
+ .subscribe((contentLayouts) => {
765
+ this.contentLayouts = contentLayouts;
766
+ this._cdRef.markForCheck();
767
+ });
768
+ of(this._data.contentPage)
769
+ .pipe(switchMap((contentPage) => {
770
+ return of(contentPage);
641
771
  }), takeUntil(this._destroy$))
642
- .subscribe((contentLayout) => {
643
- this.contentLayout = { ...contentLayout };
772
+ .subscribe((contentPage) => {
773
+ this.contentPage = {
774
+ ...contentPage,
775
+ path: contentPage.path || '/',
776
+ };
644
777
  this._cdRef.markForCheck();
645
778
  });
646
779
  }
647
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: ContentLayoutComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
648
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.7", type: ContentLayoutComponent, isStandalone: true, selector: "ng-component", viewQueries: [{ propertyName: "textEditors", predicate: FsTextEditorComponent, descendants: true }], ngImport: i0, template: "<form fsForm [submit]=\"save\" *fsSkeletonForm=\"contentLayout\">\n <fs-dialog>\n <h1 mat-dialog-title>{{contentLayout.id ? 'Layout' : 'Layout Page'}}</h1>\n <div mat-dialog-content>\n <div class=\"fs-column\">\n <mat-form-field>\n <mat-label>Name</mat-label>\n <input\n matInput\n [(ngModel)]=\"contentLayout.name\"\n name=\"name\"\n required>\n </mat-form-field>\n <mat-form-field>\n <mat-label>Tag</mat-label>\n <input\n matInput\n [(ngModel)]=\"contentLayout.tag\"\n name=\"tag\">\n </mat-form-field>\n </div>\n </div>\n\n <div mat-dialog-actions>\n <fs-form-dialog-actions>\n </fs-form-dialog-actions>\n </div>\n </fs-dialog>\n</form>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: FsSkeletonModule }, { kind: "directive", type: i1.FsSkeletonFormDirective, selector: "[fsSkeletonForm]", inputs: ["fsSkeletonForm", "fsSkeletonFormLines"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i2.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: FsFormModule }, { kind: "directive", type: i3.FsFormDirective, selector: "[fsForm]", inputs: ["wrapperSelector", "messageSelector", "hintSelector", "labelSelector", "autocomplete", "shortcuts", "confirm", "confirmDialog", "confirmDrawer", "confirmBrowser", "confirmTabs", "dirtySubmitButton", "submit", "successDelay", "errorDelay", "tabGroup", "deactivationGuard"], outputs: ["fsForm", "invalid", "valid", "submitted", "reseted", "cleared"], exportAs: ["fsForm"] }, { kind: "directive", type: i3.FsFormRequiredDirective, selector: "[fsFormRequired],[ngModel][required]", inputs: ["fsFormRequired", "required", "fsFormRequiredMessage"] }, { kind: "component", type: i3.FsFormDialogActionsComponent, selector: "fs-form-dialog-actions", inputs: ["save", "create", "close", "done", "closeData", "name"] }, { kind: "directive", type: i3.FsFormNoFsValidatorsDirective, selector: "[ngModel]:not([required]):not([fsFormRequired]):not([fsFormCompare]):not([fsFormDateRange]):not([fsFormEmail]):not([fsFormEmails]):not([fsFormFunction]):not([fsFormGreater]):not([fsFormGreaterEqual]):not([fsFormInteger]):not([fsFormLesser]):not([fsFormMax]):not([fsFormMaxLength]):not([fsFormMin]):not([fsFormMinLength]):not([fsFormNumeric]):not([fsFormPattern]):not([fsFormPhone]):not([fsFormUrl]):not([validate])" }, { kind: "ngmodule", type: FsDialogModule }, { kind: "directive", type: i4.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i4.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i4.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "component", type: i5.FsDialogComponent, selector: "fs-dialog", inputs: ["mobileMode", "mobileButtonPlacement", "mobileWidth", "mode", "buttonLayout", "dock", "dockable", "fullscreenPercent"] }, { kind: "component", type: MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: MatLabel, selector: "mat-label" }, { kind: "directive", type: MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
780
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: ContentPageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
781
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.7", type: ContentPageComponent, isStandalone: true, selector: "ng-component", viewQueries: [{ propertyName: "textEditors", predicate: FsTextEditorComponent, descendants: true }], ngImport: i0, template: "<form fsForm [submit]=\"save\" *fsSkeletonForm=\"contentPage\">\n <fs-dialog>\n <h1 mat-dialog-title>{{contentPage.id ? 'Page' : 'Create Page'}}</h1>\n <div mat-dialog-content>\n <div class=\"fs-column\">\n <mat-form-field>\n <mat-label>Type</mat-label>\n <mat-select\n [(ngModel)]=\"contentPage.type\"\n name=\"type\"\n required>\n @for (item of PageTypes; track item) {\n <mat-option\n [value]=\"item.value\">\n {{ item.name }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n @if (contentLayouts) {\n <mat-form-field>\n <mat-label>Layout</mat-label>\n <mat-select\n [(ngModel)]=\"contentPage.contentLayoutId\"\n required\n name=\"contentLayoutId\">\n @for (item of contentLayouts; track item) {\n <mat-option\n [value]=\"item.id\">\n {{ item.name }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n }\n <mat-form-field>\n <mat-label>Name</mat-label>\n <input\n matInput\n [(ngModel)]=\"contentPage.name\"\n name=\"name\"\n required>\n </mat-form-field>\n <mat-form-field>\n <mat-label>Path</mat-label>\n <input\n matInput\n [(ngModel)]=\"contentPage.path\"\n name=\"path\"\n required>\n </mat-form-field>\n <mat-form-field>\n <mat-label>Title</mat-label>\n <input\n matInput\n [(ngModel)]=\"contentPage.title\"\n name=\"title\">\n </mat-form-field>\n </div>\n </div>\n\n <div mat-dialog-actions>\n <fs-form-dialog-actions>\n </fs-form-dialog-actions>\n </div>\n </fs-dialog>\n</form>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: FsSkeletonModule }, { kind: "directive", type: i1$1.FsSkeletonFormDirective, selector: "[fsSkeletonForm]", inputs: ["fsSkeletonForm", "fsSkeletonFormLines"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2$1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i2$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i2$1.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: FsFormModule }, { kind: "directive", type: i3.FsFormDirective, selector: "[fsForm]", inputs: ["wrapperSelector", "messageSelector", "hintSelector", "labelSelector", "autocomplete", "shortcuts", "confirm", "confirmDialog", "confirmDrawer", "confirmBrowser", "confirmTabs", "dirtySubmitButton", "submit", "successDelay", "errorDelay", "tabGroup", "deactivationGuard"], outputs: ["fsForm", "invalid", "valid", "submitted", "reseted", "cleared"], exportAs: ["fsForm"] }, { kind: "directive", type: i3.FsFormRequiredDirective, selector: "[fsFormRequired],[ngModel][required]", inputs: ["fsFormRequired", "required", "fsFormRequiredMessage"] }, { kind: "component", type: i3.FsFormDialogActionsComponent, selector: "fs-form-dialog-actions", inputs: ["save", "create", "close", "done", "closeData", "name"] }, { kind: "directive", type: i3.FsFormNoFsValidatorsDirective, selector: "[ngModel]:not([required]):not([fsFormRequired]):not([fsFormCompare]):not([fsFormDateRange]):not([fsFormEmail]):not([fsFormEmails]):not([fsFormFunction]):not([fsFormGreater]):not([fsFormGreaterEqual]):not([fsFormInteger]):not([fsFormLesser]):not([fsFormMax]):not([fsFormMaxLength]):not([fsFormMin]):not([fsFormMinLength]):not([fsFormNumeric]):not([fsFormPattern]):not([fsFormPhone]):not([fsFormUrl]):not([validate])" }, { kind: "ngmodule", type: FsDialogModule }, { kind: "directive", type: i4.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i4.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i4.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "component", type: i5$1.FsDialogComponent, selector: "fs-dialog", inputs: ["mobileMode", "mobileButtonPlacement", "mobileWidth", "mode", "buttonLayout", "dock", "dockable", "fullscreenPercent"] }, { kind: "component", type: MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: MatLabel, selector: "mat-label" }, { kind: "component", type: MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "directive", type: MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
649
782
  }
650
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: ContentLayoutComponent, decorators: [{
783
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: ContentPageComponent, decorators: [{
651
784
  type: Component,
652
785
  args: [{ changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [
653
786
  FsSkeletonModule,
@@ -659,15 +792,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImpor
659
792
  MatDialogContent,
660
793
  MatFormField,
661
794
  MatLabel,
795
+ MatSelect,
796
+ MatOption,
662
797
  MatInput,
663
798
  MatDialogActions,
664
- ], template: "<form fsForm [submit]=\"save\" *fsSkeletonForm=\"contentLayout\">\n <fs-dialog>\n <h1 mat-dialog-title>{{contentLayout.id ? 'Layout' : 'Layout Page'}}</h1>\n <div mat-dialog-content>\n <div class=\"fs-column\">\n <mat-form-field>\n <mat-label>Name</mat-label>\n <input\n matInput\n [(ngModel)]=\"contentLayout.name\"\n name=\"name\"\n required>\n </mat-form-field>\n <mat-form-field>\n <mat-label>Tag</mat-label>\n <input\n matInput\n [(ngModel)]=\"contentLayout.tag\"\n name=\"tag\">\n </mat-form-field>\n </div>\n </div>\n\n <div mat-dialog-actions>\n <fs-form-dialog-actions>\n </fs-form-dialog-actions>\n </div>\n </fs-dialog>\n</form>\n" }]
799
+ ], template: "<form fsForm [submit]=\"save\" *fsSkeletonForm=\"contentPage\">\n <fs-dialog>\n <h1 mat-dialog-title>{{contentPage.id ? 'Page' : 'Create Page'}}</h1>\n <div mat-dialog-content>\n <div class=\"fs-column\">\n <mat-form-field>\n <mat-label>Type</mat-label>\n <mat-select\n [(ngModel)]=\"contentPage.type\"\n name=\"type\"\n required>\n @for (item of PageTypes; track item) {\n <mat-option\n [value]=\"item.value\">\n {{ item.name }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n @if (contentLayouts) {\n <mat-form-field>\n <mat-label>Layout</mat-label>\n <mat-select\n [(ngModel)]=\"contentPage.contentLayoutId\"\n required\n name=\"contentLayoutId\">\n @for (item of contentLayouts; track item) {\n <mat-option\n [value]=\"item.id\">\n {{ item.name }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n }\n <mat-form-field>\n <mat-label>Name</mat-label>\n <input\n matInput\n [(ngModel)]=\"contentPage.name\"\n name=\"name\"\n required>\n </mat-form-field>\n <mat-form-field>\n <mat-label>Path</mat-label>\n <input\n matInput\n [(ngModel)]=\"contentPage.path\"\n name=\"path\"\n required>\n </mat-form-field>\n <mat-form-field>\n <mat-label>Title</mat-label>\n <input\n matInput\n [(ngModel)]=\"contentPage.title\"\n name=\"title\">\n </mat-form-field>\n </div>\n </div>\n\n <div mat-dialog-actions>\n <fs-form-dialog-actions>\n </fs-form-dialog-actions>\n </div>\n </fs-dialog>\n</form>\n" }]
665
800
  }], propDecorators: { textEditors: [{
666
801
  type: ViewChildren,
667
802
  args: [FsTextEditorComponent]
668
803
  }] } });
669
804
 
670
- class ContentLayoutEditorComponent {
805
+ class ContentPageEditorComponent {
671
806
  _data = inject(MAT_DIALOG_DATA);
672
807
  _dialogRef = inject(MatDialogRef);
673
808
  _message = inject(FsMessage);
@@ -675,26 +810,27 @@ class ContentLayoutEditorComponent {
675
810
  _cdRef = inject(ChangeDetectorRef);
676
811
  _prompt = inject(FsPrompt);
677
812
  editor;
678
- contentLayout;
679
- get isMac() {
680
- return navigator.platform.toUpperCase().indexOf('MAC') >= 0;
681
- }
682
- submitting;
683
- config;
684
- EditorType = EditorType;
813
+ contentPage;
685
814
  focused = null;
815
+ config;
816
+ resizing = false;
686
817
  title;
687
818
  editors = {
688
819
  [EditorType.Html]: true,
689
820
  [EditorType.Scss]: true,
821
+ [EditorType.Js]: false,
690
822
  [EditorType.GlobalScss]: false,
691
823
  };
824
+ get isMac() {
825
+ return navigator.platform.toUpperCase().indexOf('MAC') >= 0;
826
+ }
827
+ submitting;
692
828
  _destroy$ = new Subject();
693
829
  ngOnInit() {
694
830
  this._dialogRef.addPanelClass('fs-content-editor-overlay-pane');
695
831
  this._dialogRef.disableClose = true;
696
832
  this.config = this._data.contentConfig;
697
- this._initContentLayout(this._data.contentLayout);
833
+ this._initContentPage(this._data.contentPage);
698
834
  this._initEscape();
699
835
  }
700
836
  editorToggleChange(event) {
@@ -704,10 +840,10 @@ class ContentLayoutEditorComponent {
704
840
  this._destroy$.next(null);
705
841
  this._destroy$.complete();
706
842
  }
707
- _initContentLayout(contentLayout) {
708
- this.config.loadContentLayout(contentLayout.id)
843
+ _initContentPage(contentPage) {
844
+ this.config.loadContentPage(contentPage.id)
709
845
  .subscribe((data) => {
710
- this.contentLayout = data;
846
+ this.contentPage = data;
711
847
  this._cdRef.markForCheck();
712
848
  });
713
849
  }
@@ -723,6 +859,7 @@ class ContentLayoutEditorComponent {
723
859
  return of(null)
724
860
  .pipe(filter(() => this.focused), switchMap(() => {
725
861
  switch (this.focused) {
862
+ case EditorType.Js:
726
863
  case EditorType.Html:
727
864
  case EditorType.Scss:
728
865
  return this.saveContentPage();
@@ -736,19 +873,21 @@ class ContentLayoutEditorComponent {
736
873
  }), finalize(() => {
737
874
  this.submitting = false;
738
875
  this._cdRef.markForCheck();
739
- }));
876
+ }))
877
+ .pipe(takeUntil(this._destroy$));
740
878
  };
741
879
  saveContentPage() {
742
880
  const names = {
881
+ [EditorType.Js]: 'js',
743
882
  [EditorType.Scss]: 'styles',
744
883
  [EditorType.Html]: 'content',
745
884
  };
746
885
  const data = {
747
- id: this.contentLayout.id,
886
+ id: this.contentPage.id,
748
887
  [names[this.focused]]: this.editor.changes[this.focused],
749
888
  };
750
- return this.config.saveContentLayout({
751
- id: this.contentLayout.id,
889
+ return this.config.saveContentPage({
890
+ id: this.contentPage.id,
752
891
  ...data,
753
892
  })
754
893
  .pipe(tap(() => {
@@ -784,17 +923,17 @@ class ContentLayoutEditorComponent {
784
923
  });
785
924
  }
786
925
  openSettings() {
787
- this._dialog.open(ContentLayoutComponent, {
926
+ this._dialog.open(ContentPageComponent, {
788
927
  data: {
789
- contentLayout: this.contentLayout,
928
+ contentPage: this.contentPage,
790
929
  },
791
930
  })
792
931
  .afterClosed()
793
932
  .pipe(takeUntil(this._destroy$))
794
- .subscribe((contentLayout) => {
795
- this.contentLayout = {
796
- ...this.contentLayout,
797
- ...contentLayout,
933
+ .subscribe((contentPage) => {
934
+ this.contentPage = {
935
+ ...this.contentPage,
936
+ ...contentPage,
798
937
  };
799
938
  this._cdRef.markForCheck();
800
939
  });
@@ -808,10 +947,10 @@ class ContentLayoutEditorComponent {
808
947
  }
809
948
  });
810
949
  }
811
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: ContentLayoutEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
812
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.7", type: ContentLayoutEditorComponent, isStandalone: true, selector: "ng-component", viewQueries: [{ propertyName: "editor", first: true, predicate: EditorComponent, descendants: true }], ngImport: i0, template: "<form fsForm [submit]=\"submitted\" [dirtySubmitButton]=\"false\" [confirm]=\"false\">\n <fs-dialog *fsSkeletonForm=\"contentLayout\">\n <h1 mat-dialog-title>\n <div class=\"title-container\">\n <div class=\"title\">\n Layout Editor\n <div class=\"small\">{{contentLayout.name}}</div> \n </div>\n <a\n (click)=\"openSettings()\"\n mat-icon-button>\n <mat-icon>settings</mat-icon>\n </a>\n\n <div class=\"toggles\">\n <mat-button-toggle-group multiple>\n <mat-button-toggle value=\"html\" [checked]=\"editors.html\" (change)=\"editorToggleChange($event)\">HTML</mat-button-toggle>\n <mat-button-toggle value=\"scss\" [checked]=\"editors.scss\" (change)=\"editorToggleChange($event)\">SCSS</mat-button-toggle>\n <!-- <mat-button-toggle value=\"js\" [checked]=\"editors.js\" (change)=\"editorToggleChange($event)\">JS</mat-button-toggle> -->\n <mat-button-toggle value=\"globalScss\" [checked]=\"editors.globalScss\" (change)=\"editorToggleChange($event)\">Global SCSS</mat-button-toggle>\n </mat-button-toggle-group> \n </div>\n\n <div class=\"actions\">\n <button\n #submit\n mat-stroked-button\n color=\"primary\"\n [disabled]=\"!editor?.hasChanges || submitting\"\n [matTooltip]=\"isMac ? 'cmd+s' : 'ctrl+s'\"\n type=\"button\"\n (click)=\"save()\"> \n Save\n </button>\n\n <button \n mat-stroked-button\n (click)=\"close()\"\n type=\"button\"> \n Done\n </button>\n </div>\n </div>\n </h1>\n <div mat-dialog-content>\n <app-editor\n [contentConfig]=\"config\"\n [showHtml]=\"editors.html\"\n [showScss]=\"editors.scss\"\n [showGlobalScss]=\"editors.globalScss\"\n [html]=\"contentLayout.content\"\n [scss]=\"contentLayout.styles\"\n (focused)=\"editorFocused($event)\">\n </app-editor>\n </div>\n\n <!-- <div mat-dialog-actions>\n <button \n mat-button\n color=\"primary\"\n (click)=\"close()\"\n type=\"button\"> \n Done \n </button>\n <div class=\"toggles\">\n <mat-button-toggle-group multiple>\n <mat-button-toggle value=\"html\" [checked]=\"editors.html\" (change)=\"editorToggleChange($event)\">HTML</mat-button-toggle>\n <mat-button-toggle value=\"scss\" [checked]=\"editors.scss\" (change)=\"editorToggleChange($event)\">SCSS</mat-button-toggle>\n <mat-button-toggle value=\"globalScss\" [checked]=\"editors.globalScss\" (change)=\"editorToggleChange($event)\">Global SCSS</mat-button-toggle>\n </mat-button-toggle-group> \n </div>\n </div> -->\n </fs-dialog>\n</form>", styles: ["::ng-deep .fs-content-editor-overlay-pane .mat-dialog-container{border-radius:0}form{height:100%}fs-dialog{display:flex;height:100%;flex-direction:column}fs-dialog ::ng-deep .mat-dialog-content{max-height:none;flex:1;overflow:hidden}fs-dialog ::ng-deep .mat-button-toggle-label-content{line-height:36px}h1 .toggles{display:flex;justify-content:flex-end;justify-self:baseline;font-size:13px}h1 .actions{margin-left:30px}h1 .actions .mdc-button{margin-left:5px}.title-container{display:flex;align-items:center}.title-container .title{flex:1}.title-container .title .small{line-height:normal}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: FsFormModule }, { kind: "directive", type: i3.FsFormDirective, selector: "[fsForm]", inputs: ["wrapperSelector", "messageSelector", "hintSelector", "labelSelector", "autocomplete", "shortcuts", "confirm", "confirmDialog", "confirmDrawer", "confirmBrowser", "confirmTabs", "dirtySubmitButton", "submit", "successDelay", "errorDelay", "tabGroup", "deactivationGuard"], outputs: ["fsForm", "invalid", "valid", "submitted", "reseted", "cleared"], exportAs: ["fsForm"] }, { kind: "directive", type: i3.FsButtonDirective, selector: "[mat-raised-button]:not([fsFormButtonStandalone]),[mat-button]:not([fsFormButtonStandalone]),[mat-flat-button]:not([fsFormButtonStandalone]),[mat-stroked-button]:not([fsFormButtonStandalone])", inputs: ["name", "dirtySubmit", "form"] }, { kind: "ngmodule", type: FsSkeletonModule }, { kind: "directive", type: i1.FsSkeletonFormDirective, selector: "[fsSkeletonForm]", inputs: ["fsSkeletonForm", "fsSkeletonFormLines"] }, { kind: "ngmodule", type: FsDialogModule }, { kind: "directive", type: i4.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i4.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "component", type: i5.FsDialogComponent, selector: "fs-dialog", inputs: ["mobileMode", "mobileButtonPlacement", "mobileWidth", "mode", "buttonLayout", "dock", "dockable", "fullscreenPercent"] }, { kind: "component", type: MatIconAnchor, selector: "a[mat-icon-button]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: MatButtonToggleGroup, selector: "mat-button-toggle-group", inputs: ["appearance", "name", "vertical", "value", "multiple", "disabled", "disabledInteractive", "hideSingleSelectionIndicator", "hideMultipleSelectionIndicator"], outputs: ["valueChange", "change"], exportAs: ["matButtonToggleGroup"] }, { kind: "component", type: MatButtonToggle, selector: "mat-button-toggle", inputs: ["aria-label", "aria-labelledby", "id", "name", "value", "tabIndex", "disableRipple", "appearance", "checked", "disabled", "disabledInteractive"], outputs: ["change"], exportAs: ["matButtonToggle"] }, { kind: "component", type: MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: EditorComponent, selector: "app-editor", inputs: ["showHtml", "showScss", "showJs", "showGlobalScss", "html", "scss", "js", "contentConfig"], outputs: ["changed", "focused", "blured"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
950
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: ContentPageEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
951
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.7", type: ContentPageEditorComponent, isStandalone: true, selector: "ng-component", viewQueries: [{ propertyName: "editor", first: true, predicate: EditorComponent, descendants: true }], ngImport: i0, template: "<form fsForm [submit]=\"submitted\" [dirtySubmitButton]=\"false\" [confirm]=\"false\">\n <fs-dialog *fsSkeletonForm=\"contentPage\">\n <h1 mat-dialog-title>\n <div class=\"title-container\">\n <div class=\"title\">\n Page Editor\n <div class=\"small\">{{contentPage.name}}</div> \n </div>\n <a\n (click)=\"openSettings()\"\n mat-icon-button>\n <mat-icon>settings</mat-icon>\n </a>\n\n <div class=\"toggles\">\n <mat-button-toggle-group multiple>\n <mat-button-toggle value=\"html\" [checked]=\"editors.html\" (change)=\"editorToggleChange($event)\">HTML</mat-button-toggle>\n <mat-button-toggle value=\"scss\" [checked]=\"editors.scss\" (change)=\"editorToggleChange($event)\">SCSS</mat-button-toggle>\n <mat-button-toggle value=\"js\" [checked]=\"editors.js\" (change)=\"editorToggleChange($event)\">JS</mat-button-toggle>\n <mat-button-toggle value=\"globalScss\" [checked]=\"editors.globalScss\" (change)=\"editorToggleChange($event)\">Global SCSS</mat-button-toggle>\n </mat-button-toggle-group> \n </div>\n\n <div class=\"actions\">\n <button\n #submit\n mat-stroked-button\n color=\"primary\"\n [disabled]=\"!editor?.hasChanges || submitting\"\n [matTooltip]=\"isMac ? 'cmd+s' : 'ctrl+s'\"\n type=\"button\"\n (click)=\"save()\"> \n Save\n </button>\n\n <a \n mat-stroked-button\n target=\"_blank\"\n [routerLink]=\"contentPage.path\"\n type=\"button\"> \n Preview\n </a>\n\n <button \n mat-stroked-button\n (click)=\"close()\"\n type=\"button\"> \n Done\n </button>\n </div>\n </div>\n </h1>\n <div mat-dialog-content>\n <app-editor\n [contentConfig]=\"config\"\n [showHtml]=\"editors.html\"\n [showJs]=\"editors.js\"\n [showScss]=\"editors.scss\"\n [showGlobalScss]=\"editors.globalScss\"\n [html]=\"contentPage.content\"\n [scss]=\"contentPage.styles\"\n [js]=\"contentPage.js\"\n (focused)=\"editorFocused($event)\">\n </app-editor>\n </div>\n </fs-dialog>\n</form>\n", styles: ["::ng-deep .fs-content-editor-overlay-pane .mat-dialog-container{border-radius:0}form{height:100%}fs-dialog{display:flex;height:100%;flex-direction:column}fs-dialog ::ng-deep .mat-dialog-content{max-height:none;flex:1;overflow:hidden}fs-dialog ::ng-deep .mat-button-toggle-label-content{line-height:36px}h1 .toggles{display:flex;justify-content:flex-end;justify-self:baseline;font-size:13px}h1 .actions{margin-left:30px}h1 .actions .mdc-button{margin-left:5px}.title-container{display:flex;align-items:center}.title-container .title{flex:1}.title-container .title .small{line-height:normal}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2$1.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: FsFormModule }, { kind: "directive", type: i3.FsFormDirective, selector: "[fsForm]", inputs: ["wrapperSelector", "messageSelector", "hintSelector", "labelSelector", "autocomplete", "shortcuts", "confirm", "confirmDialog", "confirmDrawer", "confirmBrowser", "confirmTabs", "dirtySubmitButton", "submit", "successDelay", "errorDelay", "tabGroup", "deactivationGuard"], outputs: ["fsForm", "invalid", "valid", "submitted", "reseted", "cleared"], exportAs: ["fsForm"] }, { kind: "directive", type: i3.FsButtonDirective, selector: "[mat-raised-button]:not([fsFormButtonStandalone]),[mat-button]:not([fsFormButtonStandalone]),[mat-flat-button]:not([fsFormButtonStandalone]),[mat-stroked-button]:not([fsFormButtonStandalone])", inputs: ["name", "dirtySubmit", "form"] }, { kind: "ngmodule", type: FsSkeletonModule }, { kind: "directive", type: i1$1.FsSkeletonFormDirective, selector: "[fsSkeletonForm]", inputs: ["fsSkeletonForm", "fsSkeletonFormLines"] }, { kind: "ngmodule", type: FsDialogModule }, { kind: "directive", type: i4.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i4.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "component", type: i5$1.FsDialogComponent, selector: "fs-dialog", inputs: ["mobileMode", "mobileButtonPlacement", "mobileWidth", "mode", "buttonLayout", "dock", "dockable", "fullscreenPercent"] }, { kind: "component", type: MatIconAnchor, selector: "a[mat-icon-button]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: MatButtonToggleGroup, selector: "mat-button-toggle-group", inputs: ["appearance", "name", "vertical", "value", "multiple", "disabled", "disabledInteractive", "hideSingleSelectionIndicator", "hideMultipleSelectionIndicator"], outputs: ["valueChange", "change"], exportAs: ["matButtonToggleGroup"] }, { kind: "component", type: MatButtonToggle, selector: "mat-button-toggle", inputs: ["aria-label", "aria-labelledby", "id", "name", "value", "tabIndex", "disableRipple", "appearance", "checked", "disabled", "disabledInteractive"], outputs: ["change"], exportAs: ["matButtonToggle"] }, { kind: "component", type: MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: MatAnchor, selector: "a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button]", exportAs: ["matButton", "matAnchor"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: EditorComponent, selector: "app-editor", inputs: ["showHtml", "showScss", "showJs", "showGlobalScss", "html", "scss", "js", "contentConfig"], outputs: ["changed", "focused", "blured"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
813
952
  }
814
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: ContentLayoutEditorComponent, decorators: [{
953
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: ContentPageEditorComponent, decorators: [{
815
954
  type: Component,
816
955
  args: [{ changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [
817
956
  FormsModule,
@@ -825,33 +964,39 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImpor
825
964
  MatButtonToggle,
826
965
  MatButton,
827
966
  MatTooltip,
967
+ MatAnchor,
968
+ RouterLink,
828
969
  CdkScrollable,
829
970
  MatDialogContent,
830
971
  EditorComponent,
831
- ], template: "<form fsForm [submit]=\"submitted\" [dirtySubmitButton]=\"false\" [confirm]=\"false\">\n <fs-dialog *fsSkeletonForm=\"contentLayout\">\n <h1 mat-dialog-title>\n <div class=\"title-container\">\n <div class=\"title\">\n Layout Editor\n <div class=\"small\">{{contentLayout.name}}</div> \n </div>\n <a\n (click)=\"openSettings()\"\n mat-icon-button>\n <mat-icon>settings</mat-icon>\n </a>\n\n <div class=\"toggles\">\n <mat-button-toggle-group multiple>\n <mat-button-toggle value=\"html\" [checked]=\"editors.html\" (change)=\"editorToggleChange($event)\">HTML</mat-button-toggle>\n <mat-button-toggle value=\"scss\" [checked]=\"editors.scss\" (change)=\"editorToggleChange($event)\">SCSS</mat-button-toggle>\n <!-- <mat-button-toggle value=\"js\" [checked]=\"editors.js\" (change)=\"editorToggleChange($event)\">JS</mat-button-toggle> -->\n <mat-button-toggle value=\"globalScss\" [checked]=\"editors.globalScss\" (change)=\"editorToggleChange($event)\">Global SCSS</mat-button-toggle>\n </mat-button-toggle-group> \n </div>\n\n <div class=\"actions\">\n <button\n #submit\n mat-stroked-button\n color=\"primary\"\n [disabled]=\"!editor?.hasChanges || submitting\"\n [matTooltip]=\"isMac ? 'cmd+s' : 'ctrl+s'\"\n type=\"button\"\n (click)=\"save()\"> \n Save\n </button>\n\n <button \n mat-stroked-button\n (click)=\"close()\"\n type=\"button\"> \n Done\n </button>\n </div>\n </div>\n </h1>\n <div mat-dialog-content>\n <app-editor\n [contentConfig]=\"config\"\n [showHtml]=\"editors.html\"\n [showScss]=\"editors.scss\"\n [showGlobalScss]=\"editors.globalScss\"\n [html]=\"contentLayout.content\"\n [scss]=\"contentLayout.styles\"\n (focused)=\"editorFocused($event)\">\n </app-editor>\n </div>\n\n <!-- <div mat-dialog-actions>\n <button \n mat-button\n color=\"primary\"\n (click)=\"close()\"\n type=\"button\"> \n Done \n </button>\n <div class=\"toggles\">\n <mat-button-toggle-group multiple>\n <mat-button-toggle value=\"html\" [checked]=\"editors.html\" (change)=\"editorToggleChange($event)\">HTML</mat-button-toggle>\n <mat-button-toggle value=\"scss\" [checked]=\"editors.scss\" (change)=\"editorToggleChange($event)\">SCSS</mat-button-toggle>\n <mat-button-toggle value=\"globalScss\" [checked]=\"editors.globalScss\" (change)=\"editorToggleChange($event)\">Global SCSS</mat-button-toggle>\n </mat-button-toggle-group> \n </div>\n </div> -->\n </fs-dialog>\n</form>", styles: ["::ng-deep .fs-content-editor-overlay-pane .mat-dialog-container{border-radius:0}form{height:100%}fs-dialog{display:flex;height:100%;flex-direction:column}fs-dialog ::ng-deep .mat-dialog-content{max-height:none;flex:1;overflow:hidden}fs-dialog ::ng-deep .mat-button-toggle-label-content{line-height:36px}h1 .toggles{display:flex;justify-content:flex-end;justify-self:baseline;font-size:13px}h1 .actions{margin-left:30px}h1 .actions .mdc-button{margin-left:5px}.title-container{display:flex;align-items:center}.title-container .title{flex:1}.title-container .title .small{line-height:normal}\n"] }]
972
+ ], template: "<form fsForm [submit]=\"submitted\" [dirtySubmitButton]=\"false\" [confirm]=\"false\">\n <fs-dialog *fsSkeletonForm=\"contentPage\">\n <h1 mat-dialog-title>\n <div class=\"title-container\">\n <div class=\"title\">\n Page Editor\n <div class=\"small\">{{contentPage.name}}</div> \n </div>\n <a\n (click)=\"openSettings()\"\n mat-icon-button>\n <mat-icon>settings</mat-icon>\n </a>\n\n <div class=\"toggles\">\n <mat-button-toggle-group multiple>\n <mat-button-toggle value=\"html\" [checked]=\"editors.html\" (change)=\"editorToggleChange($event)\">HTML</mat-button-toggle>\n <mat-button-toggle value=\"scss\" [checked]=\"editors.scss\" (change)=\"editorToggleChange($event)\">SCSS</mat-button-toggle>\n <mat-button-toggle value=\"js\" [checked]=\"editors.js\" (change)=\"editorToggleChange($event)\">JS</mat-button-toggle>\n <mat-button-toggle value=\"globalScss\" [checked]=\"editors.globalScss\" (change)=\"editorToggleChange($event)\">Global SCSS</mat-button-toggle>\n </mat-button-toggle-group> \n </div>\n\n <div class=\"actions\">\n <button\n #submit\n mat-stroked-button\n color=\"primary\"\n [disabled]=\"!editor?.hasChanges || submitting\"\n [matTooltip]=\"isMac ? 'cmd+s' : 'ctrl+s'\"\n type=\"button\"\n (click)=\"save()\"> \n Save\n </button>\n\n <a \n mat-stroked-button\n target=\"_blank\"\n [routerLink]=\"contentPage.path\"\n type=\"button\"> \n Preview\n </a>\n\n <button \n mat-stroked-button\n (click)=\"close()\"\n type=\"button\"> \n Done\n </button>\n </div>\n </div>\n </h1>\n <div mat-dialog-content>\n <app-editor\n [contentConfig]=\"config\"\n [showHtml]=\"editors.html\"\n [showJs]=\"editors.js\"\n [showScss]=\"editors.scss\"\n [showGlobalScss]=\"editors.globalScss\"\n [html]=\"contentPage.content\"\n [scss]=\"contentPage.styles\"\n [js]=\"contentPage.js\"\n (focused)=\"editorFocused($event)\">\n </app-editor>\n </div>\n </fs-dialog>\n</form>\n", styles: ["::ng-deep .fs-content-editor-overlay-pane .mat-dialog-container{border-radius:0}form{height:100%}fs-dialog{display:flex;height:100%;flex-direction:column}fs-dialog ::ng-deep .mat-dialog-content{max-height:none;flex:1;overflow:hidden}fs-dialog ::ng-deep .mat-button-toggle-label-content{line-height:36px}h1 .toggles{display:flex;justify-content:flex-end;justify-self:baseline;font-size:13px}h1 .actions{margin-left:30px}h1 .actions .mdc-button{margin-left:5px}.title-container{display:flex;align-items:center}.title-container .title{flex:1}.title-container .title .small{line-height:normal}\n"] }]
832
973
  }], propDecorators: { editor: [{
833
974
  type: ViewChild,
834
975
  args: [EditorComponent]
835
976
  }] } });
836
977
 
837
- class FsContentLayoutsComponent {
978
+ class FsContentPagesComponent {
838
979
  _config = inject(FS_CONTENT_CONFIG);
839
980
  _dialog = inject(MatDialog);
981
+ htmlEditorConfig;
840
982
  listComponent;
841
983
  listConfig;
984
+ pageTypes = index(PageTypes, 'value', 'name');
842
985
  _destroy$ = new Subject();
843
986
  ngOnInit() {
844
987
  this._initListConfig();
845
988
  }
846
- openEditor(contentLayout) {
847
- this._dialog.open(ContentLayoutEditorComponent, {
848
- maxWidth: '100vw',
849
- width: '100%',
850
- height: '100%',
989
+ openEditor(contentPage) {
990
+ this._dialog.open(ContentPageEditorComponent, {
851
991
  data: {
852
- contentLayout,
992
+ contentPage,
993
+ config: this._config,
853
994
  contentConfig: this._config,
854
995
  },
996
+ maxWidth: '100vw',
997
+ width: '100%',
998
+ height: '100%',
999
+ autoFocus: false,
855
1000
  })
856
1001
  .afterClosed()
857
1002
  .pipe(takeUntil(this._destroy$))
@@ -859,19 +1004,17 @@ class FsContentLayoutsComponent {
859
1004
  this.listComponent.reload();
860
1005
  });
861
1006
  }
862
- openLayout(contentLayout) {
863
- return this._dialog.open(ContentLayoutComponent, {
864
- data: {
865
- contentLayout,
866
- },
867
- })
868
- .afterClosed()
869
- .pipe(filter((_contentLayout) => !!_contentLayout), takeUntil(this._destroy$));
870
- }
871
1007
  ngOnDestroy() {
872
1008
  this._destroy$.next(null);
873
1009
  this._destroy$.complete();
874
1010
  }
1011
+ openContentPage(contentPage) {
1012
+ return this._dialog.open(ContentPageComponent, {
1013
+ data: { contentPage },
1014
+ })
1015
+ .afterClosed()
1016
+ .pipe(takeUntil(this._destroy$));
1017
+ }
875
1018
  _initListConfig() {
876
1019
  this.listConfig = {
877
1020
  filters: [
@@ -885,8 +1028,12 @@ class FsContentLayoutsComponent {
885
1028
  {
886
1029
  label: 'Create',
887
1030
  click: () => {
888
- this.openLayout({})
889
- .subscribe(() => {
1031
+ this.openContentPage({
1032
+ type: PageType.StandardPage,
1033
+ })
1034
+ .pipe(filter((contentPage) => !!contentPage))
1035
+ .subscribe((contentPage) => {
1036
+ this.openEditor(contentPage);
890
1037
  this.listComponent.reload();
891
1038
  });
892
1039
  },
@@ -895,7 +1042,7 @@ class FsContentLayoutsComponent {
895
1042
  rowActions: [
896
1043
  {
897
1044
  click: (data) => {
898
- return this._config.deleteContentLayout(data);
1045
+ return this._config.deleteContentPage(data);
899
1046
  },
900
1047
  remove: {
901
1048
  title: 'Confirm',
@@ -906,9 +1053,13 @@ class FsContentLayoutsComponent {
906
1053
  },
907
1054
  ],
908
1055
  fetch: (query) => {
909
- return this._config.loadContentLayouts(query)
1056
+ query = {
1057
+ contentLayouts: true,
1058
+ ...query,
1059
+ };
1060
+ return this._config.loadContentPages(query)
910
1061
  .pipe(map((response) => {
911
- return { data: response.contentLayouts, paging: response.paging };
1062
+ return { data: response.contentPages, paging: response.paging };
912
1063
  }));
913
1064
  },
914
1065
  restore: {
@@ -917,26 +1068,56 @@ class FsContentLayoutsComponent {
917
1068
  menuLabel: 'Restore',
918
1069
  reload: true,
919
1070
  click: (row) => {
920
- return this._config.saveContentLayout({ id: row.id, state: 'active' });
1071
+ return this._config.saveContentPage({ id: row.id, state: 'active' });
921
1072
  },
922
1073
  },
923
1074
  };
924
1075
  }
925
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: FsContentLayoutsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
926
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.7", type: FsContentLayoutsComponent, isStandalone: true, selector: "fs-content-layouts", viewQueries: [{ propertyName: "listComponent", first: true, predicate: FsListComponent, descendants: true }], ngImport: i0, template: "<fs-list [config]=\"listConfig\">\n <fs-list-column name=\"name\" title=\"Name\" [sortable]=\"true\">\n <ng-template fs-list-cell let-row=\"row\">\n @if (row.state !== 'deleted') {\n <a (click)=\"openEditor(row)\">\n <ng-container [ngTemplateOutlet]=\"name\"></ng-container>\n </a>\n } @else {\n {{row.name}}\n }\n\n <ng-template #name>{{row.name}}</ng-template>\n </ng-template>\n </fs-list-column>\n <fs-list-column name=\"modify_date\" title=\"Modified\" [sortable]=\"true\">\n <ng-template fs-list-cell let-row=\"row\">\n {{row.modifyDate | fsDate: 'date-time-yearless'}}\n </ng-template>\n </fs-list-column>\n</fs-list>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: FsListModule }, { kind: "component", type: i1$2.FsListComponent, selector: "fs-list", inputs: ["config", "loaderLines"], outputs: ["filtersReady"] }, { kind: "directive", type: i1$2.FsListColumnDirective, selector: "fs-list-column", inputs: ["show", "title", "name", "customize", "sortable", "sortableDefault", "sortableDirection", "direction", "align", "width", "class"] }, { kind: "directive", type: i1$2.FsListCellDirective, selector: "[fs-list-cell]", inputs: ["colspan", "align", "class"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: FsDateModule }, { kind: "pipe", type: i2$2.FsDatePipe, name: "fsDate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1076
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: FsContentPagesComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1077
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.7", type: FsContentPagesComponent, isStandalone: true, selector: "fs-content-pages", inputs: { htmlEditorConfig: "htmlEditorConfig" }, viewQueries: [{ propertyName: "listComponent", first: true, predicate: FsListComponent, descendants: true }], ngImport: i0, template: "<fs-list [config]=\"listConfig\">\n <fs-list-column name=\"name\" title=\"Name\" [sortable]=\"true\">\n <ng-template fs-list-cell let-row=\"row\">\n @if (row.state !== 'deleted') {\n <a (click)=\"openEditor(row)\">\n <ng-container [ngTemplateOutlet]=\"name\"></ng-container>\n </a>\n } @else {\n {{row.name}}\n }\n <ng-template #name>{{row.name}}</ng-template>\n </ng-template>\n </fs-list-column>\n <fs-list-column name=\"path\" title=\"Path\" [sortable]=\"true\">\n <ng-template fs-list-cell let-row=\"row\">\n @if (row.state !== 'deleted') {\n <a [href]=\"'/' + row.path\" target=\"_black\">\n <ng-container [ngTemplateOutlet]=\"path\"></ng-container>\n </a>\n } @else {\n /{{row.path}}\n }\n <ng-template #path>/{{row.path}}</ng-template>\n </ng-template>\n </fs-list-column>\n <fs-list-column name=\"layout\" title=\"Layout\">\n <ng-template fs-list-cell let-row=\"row\">\n {{row.contentLayout?.name}}\n </ng-template>\n </fs-list-column>\n <fs-list-column name=\"type\" title=\"Type\" [sortable]=\"true\">\n <ng-template fs-list-cell let-row=\"row\">\n {{pageTypes[row.type]}}\n </ng-template>\n </fs-list-column>\n <fs-list-column name=\"modify_date\" title=\"Modified\" [sortable]=\"true\">\n <ng-template fs-list-cell let-row=\"row\">\n {{row.modifyDate | fsDate: 'date-time-yearless'}}\n </ng-template>\n </fs-list-column>\n</fs-list>\n", styles: [":host ::ng-deep .modified,:host ::ng-deep .name{width:1%;white-space:nowrap}:host ::ng-deep .preview-content img{display:none}.preview-content{position:relative;max-height:100px;max-width:100%;overflow:hidden;-webkit-mask-image:-webkit-gradient(linear,left 60%,left bottom,from(rgb(0,0,0)),to(rgba(0,0,0,0)))}\n"], dependencies: [{ kind: "ngmodule", type: FsListModule }, { kind: "component", type: i1$2.FsListComponent, selector: "fs-list", inputs: ["config", "loaderLines"], outputs: ["filtersReady"] }, { kind: "directive", type: i1$2.FsListColumnDirective, selector: "fs-list-column", inputs: ["show", "title", "name", "customize", "sortable", "sortableDefault", "sortableDirection", "direction", "align", "width", "class"] }, { kind: "directive", type: i1$2.FsListCellDirective, selector: "[fs-list-cell]", inputs: ["colspan", "align", "class"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: FsDateModule }, { kind: "pipe", type: i2$2.FsDatePipe, name: "fsDate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
927
1078
  }
928
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: FsContentLayoutsComponent, decorators: [{
1079
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: FsContentPagesComponent, decorators: [{
929
1080
  type: Component,
930
- args: [{ selector: 'fs-content-layouts', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [
1081
+ args: [{ selector: 'fs-content-pages', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [
931
1082
  FsListModule,
932
1083
  NgTemplateOutlet,
933
1084
  FsDateModule,
934
- ], template: "<fs-list [config]=\"listConfig\">\n <fs-list-column name=\"name\" title=\"Name\" [sortable]=\"true\">\n <ng-template fs-list-cell let-row=\"row\">\n @if (row.state !== 'deleted') {\n <a (click)=\"openEditor(row)\">\n <ng-container [ngTemplateOutlet]=\"name\"></ng-container>\n </a>\n } @else {\n {{row.name}}\n }\n\n <ng-template #name>{{row.name}}</ng-template>\n </ng-template>\n </fs-list-column>\n <fs-list-column name=\"modify_date\" title=\"Modified\" [sortable]=\"true\">\n <ng-template fs-list-cell let-row=\"row\">\n {{row.modifyDate | fsDate: 'date-time-yearless'}}\n </ng-template>\n </fs-list-column>\n</fs-list>\n" }]
935
- }], propDecorators: { listComponent: [{
1085
+ ], template: "<fs-list [config]=\"listConfig\">\n <fs-list-column name=\"name\" title=\"Name\" [sortable]=\"true\">\n <ng-template fs-list-cell let-row=\"row\">\n @if (row.state !== 'deleted') {\n <a (click)=\"openEditor(row)\">\n <ng-container [ngTemplateOutlet]=\"name\"></ng-container>\n </a>\n } @else {\n {{row.name}}\n }\n <ng-template #name>{{row.name}}</ng-template>\n </ng-template>\n </fs-list-column>\n <fs-list-column name=\"path\" title=\"Path\" [sortable]=\"true\">\n <ng-template fs-list-cell let-row=\"row\">\n @if (row.state !== 'deleted') {\n <a [href]=\"'/' + row.path\" target=\"_black\">\n <ng-container [ngTemplateOutlet]=\"path\"></ng-container>\n </a>\n } @else {\n /{{row.path}}\n }\n <ng-template #path>/{{row.path}}</ng-template>\n </ng-template>\n </fs-list-column>\n <fs-list-column name=\"layout\" title=\"Layout\">\n <ng-template fs-list-cell let-row=\"row\">\n {{row.contentLayout?.name}}\n </ng-template>\n </fs-list-column>\n <fs-list-column name=\"type\" title=\"Type\" [sortable]=\"true\">\n <ng-template fs-list-cell let-row=\"row\">\n {{pageTypes[row.type]}}\n </ng-template>\n </fs-list-column>\n <fs-list-column name=\"modify_date\" title=\"Modified\" [sortable]=\"true\">\n <ng-template fs-list-cell let-row=\"row\">\n {{row.modifyDate | fsDate: 'date-time-yearless'}}\n </ng-template>\n </fs-list-column>\n</fs-list>\n", styles: [":host ::ng-deep .modified,:host ::ng-deep .name{width:1%;white-space:nowrap}:host ::ng-deep .preview-content img{display:none}.preview-content{position:relative;max-height:100px;max-width:100%;overflow:hidden;-webkit-mask-image:-webkit-gradient(linear,left 60%,left bottom,from(rgb(0,0,0)),to(rgba(0,0,0,0)))}\n"] }]
1086
+ }], propDecorators: { htmlEditorConfig: [{
1087
+ type: Input
1088
+ }], listComponent: [{
936
1089
  type: ViewChild,
937
1090
  args: [FsListComponent]
938
1091
  }] } });
939
1092
 
1093
+ class FsContentPagesModule {
1094
+ static forRoot() {
1095
+ return {
1096
+ ngModule: FsContentPagesModule,
1097
+ };
1098
+ }
1099
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: FsContentPagesModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1100
+ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.7", ngImport: i0, type: FsContentPagesModule, imports: [FsContentPagesComponent,
1101
+ ContentPageComponent,
1102
+ ContentPageEditorComponent], exports: [FsContentPagesComponent] });
1103
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: FsContentPagesModule, imports: [FsContentPagesComponent,
1104
+ ContentPageComponent,
1105
+ ContentPageEditorComponent] });
1106
+ }
1107
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: FsContentPagesModule, decorators: [{
1108
+ type: NgModule,
1109
+ args: [{
1110
+ imports: [
1111
+ FsContentPagesComponent,
1112
+ ContentPageComponent,
1113
+ ContentPageEditorComponent,
1114
+ ],
1115
+ exports: [
1116
+ FsContentPagesComponent,
1117
+ ],
1118
+ }]
1119
+ }] });
1120
+
940
1121
  class ContentStyleComponent {
941
1122
  _config = inject(FS_CONTENT_CONFIG);
942
1123
  _message = inject(FsMessage);
@@ -975,7 +1156,7 @@ class ContentStyleComponent {
975
1156
  })).subscribe();
976
1157
  }
977
1158
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: ContentStyleComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
978
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.7", type: ContentStyleComponent, isStandalone: true, selector: "fs-content-style", inputs: { height: "height" }, viewQueries: [{ propertyName: "textEditors", first: true, predicate: FsTextEditorComponent, descendants: true }, { propertyName: "form", first: true, predicate: FsFormDirective, descendants: true }], ngImport: i0, template: "<ng-container *fsSkeletonForm=\"contentStyle\">\n <fs-text-editor \n [(ngModel)]=\"contentStyle.scss\" \n name=\"contentStyle\"\n [fsModelChangeOptions]=\"{ debounce: 300 }\"\n (fsModelChange)=\"save()\"\n [config]=\"styleConfig\">\n </fs-text-editor> \n</ng-container>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: FsSkeletonModule }, { kind: "directive", type: i1.FsSkeletonFormDirective, selector: "[fsSkeletonForm]", inputs: ["fsSkeletonForm", "fsSkeletonFormLines"] }, { kind: "ngmodule", type: FsTextEditorModule }, { kind: "component", type: i2$1.FsTextEditorComponent, selector: "fs-text-editor", inputs: ["config", "scrollable"], outputs: ["ready", "blur"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: FsCommonModule }, { kind: "directive", type: i5$1.FsModelChangeDirective, selector: "[fsModelChange]", inputs: ["fsModelChangeOptions"], outputs: ["fsModelChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1159
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.7", type: ContentStyleComponent, isStandalone: true, selector: "fs-content-style", inputs: { height: "height" }, viewQueries: [{ propertyName: "textEditors", first: true, predicate: FsTextEditorComponent, descendants: true }, { propertyName: "form", first: true, predicate: FsFormDirective, descendants: true }], ngImport: i0, template: "<ng-container *fsSkeletonForm=\"contentStyle\">\n <fs-text-editor \n [(ngModel)]=\"contentStyle.scss\" \n name=\"contentStyle\"\n [fsModelChangeOptions]=\"{ debounce: 300 }\"\n (fsModelChange)=\"save()\"\n [config]=\"styleConfig\">\n </fs-text-editor> \n</ng-container>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: FsSkeletonModule }, { kind: "directive", type: i1$1.FsSkeletonFormDirective, selector: "[fsSkeletonForm]", inputs: ["fsSkeletonForm", "fsSkeletonFormLines"] }, { kind: "ngmodule", type: FsTextEditorModule }, { kind: "component", type: i2.FsTextEditorComponent, selector: "fs-text-editor", inputs: ["config", "scrollable"], outputs: ["ready", "blur"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: FsCommonModule }, { kind: "directive", type: i5.FsModelChangeDirective, selector: "[fsModelChange]", inputs: ["fsModelChangeOptions"], outputs: ["fsModelChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
979
1160
  }
980
1161
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: ContentStyleComponent, decorators: [{
981
1162
  type: Component,
@@ -995,138 +1176,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImpor
995
1176
  type: Input
996
1177
  }] } });
997
1178
 
998
- class ContentRendererComponent {
999
- _sanitizer = inject(DomSanitizer);
1000
- _router = inject(Router);
1001
- _el = inject(ElementRef);
1002
- _htmlRenderer = inject(HtmlRenderer);
1003
- script;
1004
- contentPage;
1005
- content;
1006
- _destroy$ = new Subject();
1007
- ngOnChanges(changes) {
1008
- if (changes.contentPage.currentValue) {
1009
- this._htmlRenderer.addStyle(this.contentPage.styles, { id: 'contentPageStyles' });
1010
- this.content = this._sanitizer.bypassSecurityTrustHtml(this.contentPage.content);
1011
- }
1012
- }
1013
- ngAfterViewChecked() {
1014
- this.registerHrefs();
1015
- if (this.contentPage.js) {
1016
- const script = document.createElement('script');
1017
- script.text = this.contentPage.js;
1018
- this.script.nativeElement.after(script);
1019
- }
1020
- }
1021
- registerHrefs() {
1022
- Array.from(this.el.querySelectorAll('a[href]'))
1023
- .filter((el) => {
1024
- return el.getAttribute('href').match(/^\//);
1025
- })
1026
- .forEach((el) => {
1027
- el.addEventListener('click', (event) => {
1028
- if (!event.shiftKey && !event.ctrlKey) {
1029
- event.preventDefault();
1030
- const href = el.getAttribute('href');
1031
- this._router.navigateByUrl(href);
1032
- }
1033
- });
1034
- });
1035
- }
1036
- get el() {
1037
- return this._el.nativeElement;
1038
- }
1039
- ngOnDestroy() {
1040
- this.removeStyles();
1041
- this._destroy$.next(null);
1042
- this._destroy$.complete();
1043
- }
1044
- removeStyles() {
1045
- const el = document.querySelector('#contentPageStyles');
1046
- if (el) {
1047
- el.remove();
1048
- }
1049
- }
1050
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: ContentRendererComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1051
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.7", type: ContentRendererComponent, isStandalone: true, selector: "fs-content-renderer", inputs: { contentPage: "contentPage" }, viewQueries: [{ propertyName: "script", first: true, predicate: ["script"], descendants: true, read: ElementRef }], usesOnChanges: true, ngImport: i0, template: "@if (content) {\n <div [innerHTML]=\"content\"></div>\n}\n<span #script></span>", styles: [""], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1052
- }
1053
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: ContentRendererComponent, decorators: [{
1054
- type: Component,
1055
- args: [{ selector: 'fs-content-renderer', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, template: "@if (content) {\n <div [innerHTML]=\"content\"></div>\n}\n<span #script></span>" }]
1056
- }], propDecorators: { script: [{
1057
- type: ViewChild,
1058
- args: ['script', { read: ElementRef }]
1059
- }], contentPage: [{
1060
- type: Input
1061
- }] } });
1062
-
1063
- class FsContentComponent {
1064
- _config = inject(FS_CONTENT_CONFIG);
1065
- _title = inject(Title);
1066
- _cdRef = inject(ChangeDetectorRef);
1067
- _router = inject(Router);
1068
- _el = inject(ElementRef);
1069
- _htmlRenderer = inject(HtmlRenderer);
1070
- contentPage;
1071
- _destroy$ = new Subject();
1072
- ngOnInit() {
1073
- this._initContent();
1074
- this._initStyles();
1075
- }
1076
- get el() {
1077
- return this._el.nativeElement;
1078
- }
1079
- ngOnDestroy() {
1080
- this._destroy$.next(null);
1081
- this._destroy$.complete();
1082
- this._title.setTitle('');
1083
- document.querySelector('#content-style')?.remove();
1084
- }
1085
- _initStyles() {
1086
- if (this._config.loadContentStyleCss) {
1087
- this._config.loadContentStyleCss()
1088
- .subscribe((styles) => {
1089
- this._htmlRenderer.addStyle(styles, { id: 'content-style' });
1090
- });
1091
- }
1092
- }
1093
- _initContent() {
1094
- this._loadContent();
1095
- this._router.events
1096
- .pipe(filter((e) => e instanceof NavigationEnd), takeUntil(this._destroy$))
1097
- .subscribe((e) => {
1098
- this._loadContent();
1099
- });
1100
- }
1101
- _loadContent() {
1102
- const path = window.location.pathname;
1103
- this._config.loadContent(path)
1104
- .subscribe((contentPage) => {
1105
- if (contentPage.title) {
1106
- this._title.setTitle(contentPage.title);
1107
- let ogTitleEl = document.querySelector('head meta[property="og:title"]');
1108
- if (!ogTitleEl) {
1109
- ogTitleEl = document.createElement('meta');
1110
- ogTitleEl.setAttribute('property', 'og:title');
1111
- document.getElementsByTagName('head')[0].appendChild(ogTitleEl);
1112
- }
1113
- ogTitleEl.setAttribute('content', contentPage.title);
1114
- }
1115
- this.contentPage = contentPage;
1116
- this._cdRef.markForCheck();
1117
- });
1118
- }
1119
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: FsContentComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1120
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.7", type: FsContentComponent, isStandalone: true, selector: "fs-content", ngImport: i0, template: "@if (contentPage) {\n <fs-content-renderer [contentPage]=\"contentPage\"></fs-content-renderer>\n}", styles: [""], dependencies: [{ kind: "component", type: ContentRendererComponent, selector: "fs-content-renderer", inputs: ["contentPage"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1121
- }
1122
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: FsContentComponent, decorators: [{
1123
- type: Component,
1124
- args: [{ selector: 'fs-content', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [ContentRendererComponent], template: "@if (contentPage) {\n <fs-content-renderer [contentPage]=\"contentPage\"></fs-content-renderer>\n}" }]
1125
- }] });
1126
-
1127
1179
  /**
1128
1180
  * Generated bundle index. Do not edit.
1129
1181
  */
1130
1182
 
1131
- export { ContentStyleComponent, FS_CONTENT_CONFIG, FsContentComponent, FsContentLayoutsComponent, FsContentPagesComponent, FsContentPagesModule };
1183
+ export { ContentStyleComponent, FS_CONTENT_CONFIG, FsContentComponent, FsContentLayoutsComponent, FsContentLayoutsModule, FsContentModule, FsContentPagesComponent, FsContentPagesModule };
1132
1184
  //# sourceMappingURL=firestitch-content.mjs.map