@abp/ng.cms-kit 10.2.0-rc.1

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.
@@ -0,0 +1,2826 @@
1
+ import * as i0 from '@angular/core';
2
+ import { inject, Injectable, Component, Injector, input, output, DestroyRef, ChangeDetectionStrategy, InjectionToken } from '@angular/core';
3
+ import * as i3$1 from '@angular/common';
4
+ import { CommonModule, DatePipe } from '@angular/common';
5
+ import * as i1$1 from '@angular/forms';
6
+ import { FormBuilder, ReactiveFormsModule, FormsModule, FormGroup, FormControl, Validators } from '@angular/forms';
7
+ import * as i3 from '@ng-bootstrap/ng-bootstrap';
8
+ import { NgbDateAdapter, NgbDatepickerModule, NgbNavModule, NgbDropdownModule, NgbNav, NgbNavItem, NgbNavItemRole, NgbNavLink, NgbNavLinkBase, NgbNavContent, NgbNavOutlet } from '@ng-bootstrap/ng-bootstrap';
9
+ import { ConfigStateService, ListService, LocalizationPipe, RestService, PermissionDirective, LocalizationService, ReplaceableRouteContainerComponent, authGuard, permissionGuard, RouterOutletComponent } from '@abp/ng.core';
10
+ import * as i1 from '@abp/ng.components/extensible';
11
+ import { ExtensibleModule, EXTENSIONS_IDENTIFIER, ExtensibleTableComponent, FormPropData, generateFormFromProps, ExtensibleFormComponent, EntityAction, EntityProp, ToolbarAction, FormProp, ExtensionsService, getObjectExtensionEntitiesFromStore, mapEntitiesToContributors, mergeWithDefaultActions, mergeWithDefaultProps } from '@abp/ng.components/extensible';
12
+ import * as i2 from '@abp/ng.components/page';
13
+ import { PageModule, PageComponent } from '@abp/ng.components/page';
14
+ import { ToasterService, ConfirmationService, Confirmation, DateTimeAdapter, FormInputComponent, ButtonComponent, ModalComponent, ModalCloseDirective } from '@abp/ng.theme.shared';
15
+ import { PageAdminService, PageStatus, BlogPostAdminService, CommentAdminService, commentApproveStateOptions, CommentApproveState, TagAdminService, BlogAdminService, BlogFeatureAdminService, BlogPostStatus, MediaDescriptorAdminService, EntityTagAdminService, MenuItemAdminService, GlobalResourceAdminService, pageStatusOptions } from '@abp/ng.cms-kit/proxy';
16
+ import { Router, ActivatedRoute } from '@angular/router';
17
+ import { tap, switchMap, debounceTime, distinctUntilChanged, finalize, map } from 'rxjs/operators';
18
+ import * as i2$1 from '@ngx-validate/core';
19
+ import { NgxValidateCoreModule } from '@ngx-validate/core';
20
+ import { prepareSlugFromControl, CodeMirrorEditorComponent, ToastuiEditorComponent, dasharize } from '@abp/ng.cms-kit';
21
+ import { forkJoin, of, Subject, map as map$1, tap as tap$1 } from 'rxjs';
22
+ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
23
+ import { TreeComponent } from '@abp/ng.components/tree';
24
+
25
+ var eCmsKitAdminComponents;
26
+ (function (eCmsKitAdminComponents) {
27
+ eCmsKitAdminComponents["CommentList"] = "CmsKit.Admin.CommentList";
28
+ eCmsKitAdminComponents["CommentDetails"] = "CmsKit.Admin.CommentDetails";
29
+ eCmsKitAdminComponents["Tags"] = "CmsKit.Admin.Tags";
30
+ eCmsKitAdminComponents["Pages"] = "CmsKit.Admin.Pages";
31
+ eCmsKitAdminComponents["PageForm"] = "CmsKit.Admin.PageForm";
32
+ eCmsKitAdminComponents["Blogs"] = "CmsKit.Admin.Blogs";
33
+ eCmsKitAdminComponents["BlogPosts"] = "CmsKit.Admin.BlogPosts";
34
+ eCmsKitAdminComponents["BlogPostForm"] = "CmsKit.Admin.BlogPostForm";
35
+ eCmsKitAdminComponents["Menus"] = "CmsKit.Admin.Menus";
36
+ eCmsKitAdminComponents["GlobalResources"] = "CmsKit.Admin.GlobalResources";
37
+ })(eCmsKitAdminComponents || (eCmsKitAdminComponents = {}));
38
+
39
+ class PageFormService {
40
+ constructor() {
41
+ this.pageService = inject(PageAdminService);
42
+ this.toasterService = inject(ToasterService);
43
+ this.router = inject(Router);
44
+ }
45
+ create(form) {
46
+ if (!form.valid) {
47
+ throw new Error('Form is invalid');
48
+ }
49
+ return this.pageService.create(form.value).pipe(tap(() => {
50
+ this.toasterService.success('AbpUi::SavedSuccessfully');
51
+ this.router.navigate(['/cms/pages']);
52
+ }));
53
+ }
54
+ createAsDraft(form) {
55
+ if (!form.valid) {
56
+ throw new Error('Form is invalid');
57
+ }
58
+ const formValue = { ...form.value, status: PageStatus.Draft };
59
+ return this.pageService.create(formValue).pipe(tap(() => {
60
+ this.toasterService.success('AbpUi::SavedSuccessfully');
61
+ this.router.navigate(['/cms/pages']);
62
+ }));
63
+ }
64
+ publish(form) {
65
+ if (!form.valid) {
66
+ throw new Error('Form is invalid');
67
+ }
68
+ const formValue = { ...form.value, status: PageStatus.Publish };
69
+ return this.pageService.create(formValue).pipe(tap(() => {
70
+ this.toasterService.success('AbpUi::SavedSuccessfully');
71
+ this.router.navigate(['/cms/pages']);
72
+ }));
73
+ }
74
+ update(pageId, form, page) {
75
+ if (!form.valid || !page) {
76
+ throw new Error('Form is invalid or page is missing');
77
+ }
78
+ const formValue = {
79
+ ...page,
80
+ ...form.value,
81
+ };
82
+ return this.pageService.update(pageId, formValue).pipe(tap(() => {
83
+ this.toasterService.success('AbpUi::SavedSuccessfully');
84
+ this.router.navigate(['/cms/pages']);
85
+ }));
86
+ }
87
+ updateAsDraft(pageId, form, page) {
88
+ if (!form.valid || !page) {
89
+ throw new Error('Form is invalid or page is missing');
90
+ }
91
+ const formValue = {
92
+ ...page,
93
+ ...form.value,
94
+ status: PageStatus.Draft,
95
+ };
96
+ return this.pageService.update(pageId, formValue).pipe(tap(() => {
97
+ this.toasterService.success('AbpUi::SavedSuccessfully');
98
+ this.router.navigate(['/cms/pages']);
99
+ }));
100
+ }
101
+ updateAndPublish(pageId, form, page) {
102
+ if (!form.valid || !page) {
103
+ throw new Error('Form is invalid or page is missing');
104
+ }
105
+ const formValue = {
106
+ ...page,
107
+ ...form.value,
108
+ status: PageStatus.Publish,
109
+ };
110
+ return this.pageService.update(pageId, formValue).pipe(tap(() => {
111
+ this.toasterService.success('AbpUi::SavedSuccessfully');
112
+ this.router.navigate(['/cms/pages']);
113
+ }));
114
+ }
115
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: PageFormService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
116
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: PageFormService, providedIn: 'root' }); }
117
+ }
118
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: PageFormService, decorators: [{
119
+ type: Injectable,
120
+ args: [{
121
+ providedIn: 'root',
122
+ }]
123
+ }] });
124
+
125
+ class BlogPostFormService {
126
+ constructor() {
127
+ this.blogPostService = inject(BlogPostAdminService);
128
+ this.toasterService = inject(ToasterService);
129
+ this.router = inject(Router);
130
+ }
131
+ create(form) {
132
+ if (!form.valid) {
133
+ throw new Error('Form is invalid');
134
+ }
135
+ return this.blogPostService.create(form.value).pipe(tap(() => {
136
+ this.toasterService.success('AbpUi::SavedSuccessfully');
137
+ this.router.navigate(['/cms/blog-posts']);
138
+ }));
139
+ }
140
+ createAsDraft(form) {
141
+ if (!form.valid) {
142
+ throw new Error('Form is invalid');
143
+ }
144
+ return this.blogPostService.create(form.value).pipe(tap(() => {
145
+ this.toasterService.success('AbpUi::SavedSuccessfully');
146
+ this.router.navigate(['/cms/blog-posts']);
147
+ }));
148
+ }
149
+ createAndPublish(form) {
150
+ if (!form.valid) {
151
+ throw new Error('Form is invalid');
152
+ }
153
+ return this.blogPostService.createAndPublish(form.value).pipe(tap(() => {
154
+ this.toasterService.success('AbpUi::SavedSuccessfully');
155
+ this.router.navigate(['/cms/blog-posts']);
156
+ }));
157
+ }
158
+ createAndSendToReview(form) {
159
+ if (!form.valid) {
160
+ throw new Error('Form is invalid');
161
+ }
162
+ return this.blogPostService.createAndSendToReview(form.value).pipe(tap(() => {
163
+ this.toasterService.success('AbpUi::SavedSuccessfully');
164
+ this.router.navigate(['/cms/blog-posts']);
165
+ }));
166
+ }
167
+ update(blogPostId, form, blogPost) {
168
+ if (!form.valid || !blogPost) {
169
+ throw new Error('Form is invalid or blog post is missing');
170
+ }
171
+ const formValue = {
172
+ ...blogPost,
173
+ ...form.value,
174
+ };
175
+ return this.blogPostService.update(blogPostId, formValue).pipe(tap(() => {
176
+ this.toasterService.success('AbpUi::SavedSuccessfully');
177
+ this.router.navigate(['/cms/blog-posts']);
178
+ }));
179
+ }
180
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: BlogPostFormService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
181
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: BlogPostFormService, providedIn: 'root' }); }
182
+ }
183
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: BlogPostFormService, decorators: [{
184
+ type: Injectable,
185
+ args: [{
186
+ providedIn: 'root',
187
+ }]
188
+ }] });
189
+
190
+ class CommentEntityService {
191
+ constructor() {
192
+ this.commentService = inject(CommentAdminService);
193
+ this.toasterService = inject(ToasterService);
194
+ this.confirmation = inject(ConfirmationService);
195
+ this.configState = inject(ConfigStateService);
196
+ this.router = inject(Router);
197
+ }
198
+ get requireApprovement() {
199
+ return (this.configState.getSetting(CMS_KIT_COMMENTS_REQUIRE_APPROVEMENT).toLowerCase() === 'true');
200
+ }
201
+ isCommentReply(commentId) {
202
+ if (!commentId) {
203
+ return false;
204
+ }
205
+ const id = this.router.url.split('/').pop();
206
+ return id === commentId;
207
+ }
208
+ updateApprovalStatus(id, isApproved, list) {
209
+ this.commentService
210
+ .updateApprovalStatus(id, { isApproved: isApproved })
211
+ .pipe(tap(() => list.get()))
212
+ .subscribe(() => isApproved
213
+ ? this.toasterService.success('CmsKit::ApprovedSuccessfully')
214
+ : this.toasterService.success('CmsKit::ApprovalRevokedSuccessfully'));
215
+ }
216
+ delete(id, list) {
217
+ this.confirmation
218
+ .warn('CmsKit::CommentDeletionConfirmationMessage', 'AbpUi::AreYouSure', {
219
+ yesText: 'AbpUi::Yes',
220
+ cancelText: 'AbpUi::Cancel',
221
+ })
222
+ .subscribe(status => {
223
+ if (status === Confirmation.Status.confirm) {
224
+ this.commentService.delete(id).subscribe(() => {
225
+ list.get();
226
+ });
227
+ }
228
+ });
229
+ }
230
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: CommentEntityService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
231
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: CommentEntityService, providedIn: 'root' }); }
232
+ }
233
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: CommentEntityService, decorators: [{
234
+ type: Injectable,
235
+ args: [{
236
+ providedIn: 'root',
237
+ }]
238
+ }] });
239
+
240
+ class CommentListComponent {
241
+ constructor() {
242
+ this.data = { items: [], totalCount: 0 };
243
+ this.list = inject((ListService));
244
+ this.commentEntityService = inject(CommentEntityService);
245
+ this.commentService = inject(CommentAdminService);
246
+ this.fb = inject(FormBuilder);
247
+ this.commentApproveStateOptions = commentApproveStateOptions;
248
+ }
249
+ ngOnInit() {
250
+ this.createFilterForm();
251
+ this.hookToQuery();
252
+ this.requireApprovement = this.commentEntityService.requireApprovement;
253
+ }
254
+ createFilterForm() {
255
+ this.filterForm = this.fb.group({
256
+ creationStartDate: [null],
257
+ creationEndDate: [null],
258
+ author: [''],
259
+ entityType: [''],
260
+ commentApproveState: [CommentApproveState.All],
261
+ });
262
+ }
263
+ onFilter() {
264
+ const formValue = this.filterForm.value;
265
+ const filters = {
266
+ author: formValue.author || undefined,
267
+ entityType: formValue.entityType || undefined,
268
+ commentApproveState: formValue.commentApproveState,
269
+ creationStartDate: formValue.creationStartDate || undefined,
270
+ creationEndDate: formValue.creationEndDate || undefined,
271
+ };
272
+ this.list.filter = filters;
273
+ this.list.get();
274
+ }
275
+ hookToQuery() {
276
+ this.list
277
+ .hookToQuery(query => {
278
+ const filters = this.list.filter || {};
279
+ const input = {
280
+ ...query,
281
+ ...filters,
282
+ };
283
+ return this.commentService.getList(input);
284
+ })
285
+ .subscribe(res => (this.data = res));
286
+ }
287
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: CommentListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
288
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.9", type: CommentListComponent, isStandalone: true, selector: "abp-comment-list", providers: [
289
+ ListService,
290
+ {
291
+ provide: EXTENSIONS_IDENTIFIER,
292
+ useValue: eCmsKitAdminComponents.CommentList,
293
+ },
294
+ ], ngImport: i0, template: "<abp-page [title]=\"'CmsKit::Comments' | abpLocalization\">\r\n <div class=\"card mb-4\">\r\n <div class=\"card-body\">\r\n <form [formGroup]=\"filterForm\" (ngSubmit)=\"onFilter()\">\r\n <div class=\"row align-items-end\">\r\n <div class=\"col-lg-4 col-md-12\">\r\n <div class=\"row\">\r\n <div class=\"col-lg-6 col-md-6\">\r\n <div class=\"mb-3\">\r\n <label class=\"form-label\" for=\"creationStartDate\">\r\n {{ 'CmsKit::StartDate' | abpLocalization }}\r\n </label>\r\n <input\r\n id=\"creationStartDate\"\r\n formControlName=\"creationStartDate\"\r\n (click)=\"startDatePicker.open()\"\r\n (keyup.space)=\"startDatePicker.open()\"\r\n ngbDatepicker\r\n #startDatePicker=\"ngbDatepicker\"\r\n type=\"text\"\r\n class=\"form-control\"\r\n />\r\n </div>\r\n </div>\r\n <div class=\"col-lg-6 col-md-6\">\r\n <div class=\"mb-3\">\r\n <label class=\"form-label\" for=\"creationEndDate\">\r\n {{ 'CmsKit::EndDate' | abpLocalization }}\r\n </label>\r\n <input\r\n id=\"creationEndDate\"\r\n formControlName=\"creationEndDate\"\r\n class=\"form-control\"\r\n ngbDatepicker\r\n #endDatePicker=\"ngbDatepicker\"\r\n (click)=\"endDatePicker.toggle()\"\r\n readonly\r\n />\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"col-lg-2 col-md-6\">\r\n <abp-form-input\r\n formControlName=\"author\"\r\n [label]=\"'CmsKit::Username' | abpLocalization\"\r\n type=\"text\"\r\n />\r\n </div>\r\n\r\n <div class=\"col-lg-2 col-md-6\">\r\n <abp-form-input\r\n formControlName=\"entityType\"\r\n [label]=\"'CmsKit::EntityType' | abpLocalization\"\r\n type=\"text\"\r\n />\r\n </div>\r\n @if (requireApprovement) {\r\n <div class=\"col-lg-2 col-md-6\">\r\n <div class=\"mb-3\">\r\n <label class=\"mb-1 form-label\" for=\"commentApproveState\">\r\n {{ 'CmsKit::CommentFilter:ApproveState' | abpLocalization }}\r\n </label>\r\n <select\r\n id=\"commentApproveState\"\r\n formControlName=\"commentApproveState\"\r\n class=\"form-control\"\r\n >\r\n @for (option of commentApproveStateOptions; track option.value) {\r\n <option [value]=\"option.value\">\r\n {{ 'CmsKit::CommentFilter:' + option.value | abpLocalization }}\r\n </option>\r\n }\r\n </select>\r\n </div>\r\n </div>\r\n }\r\n <div class=\"col-lg-2 col-md-6\">\r\n <abp-button class=\"w-100 mb-3\" buttonType=\"Primary\" type=\"submit\">\r\n <i class=\"fa fa-search\" aria-hidden=\"true\"></i>\r\n </abp-button>\r\n </div>\r\n </div>\r\n </form>\r\n </div>\r\n </div>\r\n\r\n <div class=\"card\">\r\n <abp-extensible-table [data]=\"data.items\" [recordsTotal]=\"data.totalCount\" [list]=\"list\" />\r\n </div>\r\n</abp-page>\r\n", dependencies: [{ kind: "ngmodule", type: ExtensibleModule }, { kind: "component", type: i1.ExtensibleTableComponent, selector: "abp-extensible-table", inputs: ["actionsText", "data", "list", "recordsTotal", "actionsColumnWidth", "actionsTemplate", "selectable", "selectionType", "selected", "infiniteScroll", "isLoading", "scrollThreshold", "tableHeight", "rowDetailTemplate", "rowDetailHeight"], outputs: ["tableActivate", "selectionChange", "loadMore", "rowDetailToggle"], exportAs: ["abpExtensibleTable"] }, { kind: "ngmodule", type: PageModule }, { kind: "component", type: i2.PageComponent, selector: "abp-page", inputs: ["title", "toolbar", "breadcrumb"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$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: i1$1.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: NgbDatepickerModule }, { kind: "directive", type: i3.NgbInputDatepicker, selector: "input[ngbDatepicker]", inputs: ["autoClose", "contentTemplate", "datepickerClass", "dayTemplate", "dayTemplateData", "displayMonths", "firstDayOfWeek", "footerTemplate", "markDisabled", "minDate", "maxDate", "navigation", "outsideDays", "placement", "popperOptions", "restoreFocus", "showWeekNumbers", "startDate", "container", "positionTarget", "weekdays", "disabled"], outputs: ["dateSelect", "navigate", "closed"], exportAs: ["ngbDatepicker"] }, { kind: "ngmodule", type: CommonModule }, { kind: "component", type: FormInputComponent, selector: "abp-form-input", inputs: ["inputId", "inputReadonly", "label", "labelClass", "inputPlaceholder", "inputStyle", "inputClass"], outputs: ["formBlur", "formFocus"] }, { kind: "component", type: ButtonComponent, selector: "abp-button", inputs: ["buttonId", "buttonClass", "buttonType", "formName", "iconClass", "loading", "disabled", "attributes"], outputs: ["click", "focus", "blur", "abpClick", "abpFocus", "abpBlur"] }, { kind: "pipe", type: LocalizationPipe, name: "abpLocalization" }], viewProviders: [
295
+ {
296
+ provide: NgbDateAdapter,
297
+ useClass: DateTimeAdapter,
298
+ },
299
+ ] }); }
300
+ }
301
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: CommentListComponent, decorators: [{
302
+ type: Component,
303
+ args: [{ selector: 'abp-comment-list', providers: [
304
+ ListService,
305
+ {
306
+ provide: EXTENSIONS_IDENTIFIER,
307
+ useValue: eCmsKitAdminComponents.CommentList,
308
+ },
309
+ ], viewProviders: [
310
+ {
311
+ provide: NgbDateAdapter,
312
+ useClass: DateTimeAdapter,
313
+ },
314
+ ], imports: [
315
+ ExtensibleModule,
316
+ PageModule,
317
+ ReactiveFormsModule,
318
+ NgbDatepickerModule,
319
+ CommonModule,
320
+ LocalizationPipe,
321
+ FormInputComponent,
322
+ ButtonComponent,
323
+ ], template: "<abp-page [title]=\"'CmsKit::Comments' | abpLocalization\">\r\n <div class=\"card mb-4\">\r\n <div class=\"card-body\">\r\n <form [formGroup]=\"filterForm\" (ngSubmit)=\"onFilter()\">\r\n <div class=\"row align-items-end\">\r\n <div class=\"col-lg-4 col-md-12\">\r\n <div class=\"row\">\r\n <div class=\"col-lg-6 col-md-6\">\r\n <div class=\"mb-3\">\r\n <label class=\"form-label\" for=\"creationStartDate\">\r\n {{ 'CmsKit::StartDate' | abpLocalization }}\r\n </label>\r\n <input\r\n id=\"creationStartDate\"\r\n formControlName=\"creationStartDate\"\r\n (click)=\"startDatePicker.open()\"\r\n (keyup.space)=\"startDatePicker.open()\"\r\n ngbDatepicker\r\n #startDatePicker=\"ngbDatepicker\"\r\n type=\"text\"\r\n class=\"form-control\"\r\n />\r\n </div>\r\n </div>\r\n <div class=\"col-lg-6 col-md-6\">\r\n <div class=\"mb-3\">\r\n <label class=\"form-label\" for=\"creationEndDate\">\r\n {{ 'CmsKit::EndDate' | abpLocalization }}\r\n </label>\r\n <input\r\n id=\"creationEndDate\"\r\n formControlName=\"creationEndDate\"\r\n class=\"form-control\"\r\n ngbDatepicker\r\n #endDatePicker=\"ngbDatepicker\"\r\n (click)=\"endDatePicker.toggle()\"\r\n readonly\r\n />\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"col-lg-2 col-md-6\">\r\n <abp-form-input\r\n formControlName=\"author\"\r\n [label]=\"'CmsKit::Username' | abpLocalization\"\r\n type=\"text\"\r\n />\r\n </div>\r\n\r\n <div class=\"col-lg-2 col-md-6\">\r\n <abp-form-input\r\n formControlName=\"entityType\"\r\n [label]=\"'CmsKit::EntityType' | abpLocalization\"\r\n type=\"text\"\r\n />\r\n </div>\r\n @if (requireApprovement) {\r\n <div class=\"col-lg-2 col-md-6\">\r\n <div class=\"mb-3\">\r\n <label class=\"mb-1 form-label\" for=\"commentApproveState\">\r\n {{ 'CmsKit::CommentFilter:ApproveState' | abpLocalization }}\r\n </label>\r\n <select\r\n id=\"commentApproveState\"\r\n formControlName=\"commentApproveState\"\r\n class=\"form-control\"\r\n >\r\n @for (option of commentApproveStateOptions; track option.value) {\r\n <option [value]=\"option.value\">\r\n {{ 'CmsKit::CommentFilter:' + option.value | abpLocalization }}\r\n </option>\r\n }\r\n </select>\r\n </div>\r\n </div>\r\n }\r\n <div class=\"col-lg-2 col-md-6\">\r\n <abp-button class=\"w-100 mb-3\" buttonType=\"Primary\" type=\"submit\">\r\n <i class=\"fa fa-search\" aria-hidden=\"true\"></i>\r\n </abp-button>\r\n </div>\r\n </div>\r\n </form>\r\n </div>\r\n </div>\r\n\r\n <div class=\"card\">\r\n <abp-extensible-table [data]=\"data.items\" [recordsTotal]=\"data.totalCount\" [list]=\"list\" />\r\n </div>\r\n</abp-page>\r\n" }]
324
+ }] });
325
+
326
+ class CommentDetailsComponent {
327
+ constructor() {
328
+ this.comment = null;
329
+ this.data = { items: [], totalCount: 0 };
330
+ this.list = inject((ListService));
331
+ this.commentEntityService = inject(CommentEntityService);
332
+ this.commentService = inject(CommentAdminService);
333
+ this.route = inject(ActivatedRoute);
334
+ this.router = inject(Router);
335
+ this.fb = inject(FormBuilder);
336
+ this.commentApproveStateOptions = commentApproveStateOptions;
337
+ }
338
+ ngOnInit() {
339
+ this.route.params.subscribe(params => {
340
+ const id = params['id'];
341
+ if (id) {
342
+ this.commentId = id;
343
+ this.loadComment(id);
344
+ this.createFilterForm();
345
+ this.hookToQuery();
346
+ }
347
+ });
348
+ this.requireApprovement = this.commentEntityService.requireApprovement;
349
+ }
350
+ createFilterForm() {
351
+ this.filterForm = this.fb.group({
352
+ creationStartDate: [null],
353
+ creationEndDate: [null],
354
+ author: [''],
355
+ commentApproveState: [CommentApproveState.All],
356
+ });
357
+ }
358
+ loadComment(id) {
359
+ this.commentService.get(id).subscribe(comment => {
360
+ this.comment = comment;
361
+ });
362
+ }
363
+ onFilter() {
364
+ const formValue = this.filterForm.value;
365
+ const filters = {
366
+ author: formValue.author || undefined,
367
+ commentApproveState: formValue.commentApproveState,
368
+ repliedCommentId: this.commentId,
369
+ creationStartDate: formValue.creationStartDate || undefined,
370
+ creationEndDate: formValue.creationEndDate || undefined,
371
+ };
372
+ this.list.filter = filters;
373
+ this.list.get();
374
+ }
375
+ hookToQuery() {
376
+ this.list
377
+ .hookToQuery(query => {
378
+ const filters = this.list.filter || {};
379
+ const input = {
380
+ repliedCommentId: this.commentId,
381
+ ...query,
382
+ ...filters,
383
+ };
384
+ return this.commentService.getList(input);
385
+ })
386
+ .subscribe(res => (this.data = res));
387
+ }
388
+ navigateToReply(id) {
389
+ this.router.navigate(['/cms/comments', id]);
390
+ }
391
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: CommentDetailsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
392
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.9", type: CommentDetailsComponent, isStandalone: true, selector: "abp-comment-details", providers: [
393
+ ListService,
394
+ {
395
+ provide: EXTENSIONS_IDENTIFIER,
396
+ useValue: eCmsKitAdminComponents.CommentDetails,
397
+ },
398
+ ], ngImport: i0, template: "<abp-page [title]=\"'CmsKit::Comments' | abpLocalization\">\r\n @if (comment) {\r\n <div class=\"card mb-4\">\r\n <div class=\"card-body\">\r\n <table class=\"table\">\r\n <tr>\r\n <td width=\"10%\">\r\n <b>{{ 'CmsKit::EntityType' | abpLocalization }}</b\r\n >:\r\n </td>\r\n <td>{{ comment.entityType }}</td>\r\n </tr>\r\n <tr>\r\n <td>\r\n <b>{{ 'CmsKit::EntityId' | abpLocalization }}</b\r\n >:\r\n </td>\r\n <td>{{ comment.entityId }}</td>\r\n </tr>\r\n <tr>\r\n <td>\r\n <b>{{ 'AbpIdentity::CreationTime' | abpLocalization }}</b\r\n >:\r\n </td>\r\n <td>{{ comment.creationTime | date }}</td>\r\n </tr>\r\n <tr>\r\n <td>\r\n <b>{{ 'CmsKit::Username' | abpLocalization }}</b\r\n >:\r\n </td>\r\n <td>{{ comment.author?.name }}</td>\r\n </tr>\r\n @if (comment.repliedCommentId) {\r\n <tr>\r\n <td>\r\n <b>{{ 'CmsKit::ReplyTo' | abpLocalization }}</b\r\n >:\r\n </td>\r\n <td>\r\n <a (click)=\"navigateToReply(comment.repliedCommentId!)\" style=\"cursor: pointer\">\r\n {{ comment.repliedCommentId }}\r\n </a>\r\n </td>\r\n </tr>\r\n }\r\n <tr>\r\n <td class=\"align-text-top\">\r\n <b>{{ 'CmsKit::Text' | abpLocalization }}</b\r\n >:\r\n </td>\r\n <td>{{ comment.text }}</td>\r\n </tr>\r\n </table>\r\n </div>\r\n </div>\r\n }\r\n\r\n <div class=\"card mb-4\">\r\n <div class=\"card-body\">\r\n <form [formGroup]=\"filterForm\" (ngSubmit)=\"onFilter()\">\r\n <input type=\"hidden\" [value]=\"commentId\" />\r\n <div class=\"row\">\r\n <div class=\"col-lg-4 col-md-12\">\r\n <div class=\"row\">\r\n <div class=\"col-lg-6 col-md-6\">\r\n <div class=\"mb-3\">\r\n <label class=\"form-label\" for=\"creationStartDate\">\r\n {{ 'CmsKit::StartDate' | abpLocalization }}\r\n </label>\r\n <input\r\n id=\"creationStartDate\"\r\n formControlName=\"creationStartDate\"\r\n (click)=\"startDatePicker.open()\"\r\n (keyup.space)=\"startDatePicker.open()\"\r\n ngbDatepicker\r\n #startDatePicker=\"ngbDatepicker\"\r\n type=\"text\"\r\n class=\"form-control\"\r\n />\r\n </div>\r\n </div>\r\n <div class=\"col-lg-6 col-md-6\">\r\n <div class=\"mb-3\">\r\n <label class=\"form-label\" for=\"creationEndDate\">\r\n {{ 'CmsKit::EndDate' | abpLocalization }}\r\n </label>\r\n <input\r\n id=\"creationEndDate\"\r\n formControlName=\"creationEndDate\"\r\n class=\"form-control\"\r\n ngbDatepicker\r\n #endDatePicker=\"ngbDatepicker\"\r\n (click)=\"endDatePicker.toggle()\"\r\n readonly\r\n />\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"col-lg-4 col-md-12\">\r\n <abp-form-input\r\n formControlName=\"author\"\r\n [label]=\"'CmsKit::Username' | abpLocalization\"\r\n type=\"text\"\r\n />\r\n </div>\r\n @if (requireApprovement) {\r\n <div class=\"col-lg-2 col-md-12\">\r\n <div class=\"mb-3\">\r\n <label class=\"mb-1 form-label\" for=\"commentApproveState\">\r\n {{ 'CmsKit::CommentFilter:ApproveState' | abpLocalization }}\r\n </label>\r\n <select\r\n id=\"commentApproveState\"\r\n formControlName=\"commentApproveState\"\r\n class=\"form-control\"\r\n >\r\n @for (option of commentApproveStateOptions; track option.value) {\r\n <option [value]=\"option.value\">\r\n {{ 'CmsKit::CommentFilter:' + option.value | abpLocalization }}\r\n </option>\r\n }\r\n </select>\r\n </div>\r\n </div>\r\n }\r\n\r\n <div class=\"col-lg-2 col-md-12\">\r\n <div class=\"d-grid gap-2\">\r\n <abp-button class=\"mt-md-4\" buttonType=\"Primary\" type=\"submit\">\r\n <i class=\"fa fa-search\" aria-hidden=\"true\"></i>\r\n </abp-button>\r\n </div>\r\n </div>\r\n </div>\r\n </form>\r\n </div>\r\n </div>\r\n\r\n <h3>{{ 'CmsKit::RepliesToThisComment' | abpLocalization }}</h3>\r\n\r\n <div class=\"card\">\r\n <abp-extensible-table [data]=\"data.items\" [recordsTotal]=\"data.totalCount\" [list]=\"list\" />\r\n </div>\r\n</abp-page>\r\n", dependencies: [{ kind: "component", type: ExtensibleTableComponent, selector: "abp-extensible-table", inputs: ["actionsText", "data", "list", "recordsTotal", "actionsColumnWidth", "actionsTemplate", "selectable", "selectionType", "selected", "infiniteScroll", "isLoading", "scrollThreshold", "tableHeight", "rowDetailTemplate", "rowDetailHeight"], outputs: ["tableActivate", "selectionChange", "loadMore", "rowDetailToggle"], exportAs: ["abpExtensibleTable"] }, { kind: "component", type: PageComponent, selector: "abp-page", inputs: ["title", "toolbar", "breadcrumb"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$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: i1$1.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: NgbDatepickerModule }, { kind: "directive", type: i3.NgbInputDatepicker, selector: "input[ngbDatepicker]", inputs: ["autoClose", "contentTemplate", "datepickerClass", "dayTemplate", "dayTemplateData", "displayMonths", "firstDayOfWeek", "footerTemplate", "markDisabled", "minDate", "maxDate", "navigation", "outsideDays", "placement", "popperOptions", "restoreFocus", "showWeekNumbers", "startDate", "container", "positionTarget", "weekdays", "disabled"], outputs: ["dateSelect", "navigate", "closed"], exportAs: ["ngbDatepicker"] }, { kind: "ngmodule", type: CommonModule }, { kind: "component", type: FormInputComponent, selector: "abp-form-input", inputs: ["inputId", "inputReadonly", "label", "labelClass", "inputPlaceholder", "inputStyle", "inputClass"], outputs: ["formBlur", "formFocus"] }, { kind: "component", type: ButtonComponent, selector: "abp-button", inputs: ["buttonId", "buttonClass", "buttonType", "formName", "iconClass", "loading", "disabled", "attributes"], outputs: ["click", "focus", "blur", "abpClick", "abpFocus", "abpBlur"] }, { kind: "pipe", type: LocalizationPipe, name: "abpLocalization" }, { kind: "pipe", type: i3$1.DatePipe, name: "date" }], viewProviders: [
399
+ {
400
+ provide: NgbDateAdapter,
401
+ useClass: DateTimeAdapter,
402
+ },
403
+ ] }); }
404
+ }
405
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: CommentDetailsComponent, decorators: [{
406
+ type: Component,
407
+ args: [{ selector: 'abp-comment-details', providers: [
408
+ ListService,
409
+ {
410
+ provide: EXTENSIONS_IDENTIFIER,
411
+ useValue: eCmsKitAdminComponents.CommentDetails,
412
+ },
413
+ ], viewProviders: [
414
+ {
415
+ provide: NgbDateAdapter,
416
+ useClass: DateTimeAdapter,
417
+ },
418
+ ], imports: [
419
+ ExtensibleTableComponent,
420
+ PageComponent,
421
+ LocalizationPipe,
422
+ ReactiveFormsModule,
423
+ NgbDatepickerModule,
424
+ CommonModule,
425
+ DatePipe,
426
+ FormInputComponent,
427
+ ButtonComponent,
428
+ ], template: "<abp-page [title]=\"'CmsKit::Comments' | abpLocalization\">\r\n @if (comment) {\r\n <div class=\"card mb-4\">\r\n <div class=\"card-body\">\r\n <table class=\"table\">\r\n <tr>\r\n <td width=\"10%\">\r\n <b>{{ 'CmsKit::EntityType' | abpLocalization }}</b\r\n >:\r\n </td>\r\n <td>{{ comment.entityType }}</td>\r\n </tr>\r\n <tr>\r\n <td>\r\n <b>{{ 'CmsKit::EntityId' | abpLocalization }}</b\r\n >:\r\n </td>\r\n <td>{{ comment.entityId }}</td>\r\n </tr>\r\n <tr>\r\n <td>\r\n <b>{{ 'AbpIdentity::CreationTime' | abpLocalization }}</b\r\n >:\r\n </td>\r\n <td>{{ comment.creationTime | date }}</td>\r\n </tr>\r\n <tr>\r\n <td>\r\n <b>{{ 'CmsKit::Username' | abpLocalization }}</b\r\n >:\r\n </td>\r\n <td>{{ comment.author?.name }}</td>\r\n </tr>\r\n @if (comment.repliedCommentId) {\r\n <tr>\r\n <td>\r\n <b>{{ 'CmsKit::ReplyTo' | abpLocalization }}</b\r\n >:\r\n </td>\r\n <td>\r\n <a (click)=\"navigateToReply(comment.repliedCommentId!)\" style=\"cursor: pointer\">\r\n {{ comment.repliedCommentId }}\r\n </a>\r\n </td>\r\n </tr>\r\n }\r\n <tr>\r\n <td class=\"align-text-top\">\r\n <b>{{ 'CmsKit::Text' | abpLocalization }}</b\r\n >:\r\n </td>\r\n <td>{{ comment.text }}</td>\r\n </tr>\r\n </table>\r\n </div>\r\n </div>\r\n }\r\n\r\n <div class=\"card mb-4\">\r\n <div class=\"card-body\">\r\n <form [formGroup]=\"filterForm\" (ngSubmit)=\"onFilter()\">\r\n <input type=\"hidden\" [value]=\"commentId\" />\r\n <div class=\"row\">\r\n <div class=\"col-lg-4 col-md-12\">\r\n <div class=\"row\">\r\n <div class=\"col-lg-6 col-md-6\">\r\n <div class=\"mb-3\">\r\n <label class=\"form-label\" for=\"creationStartDate\">\r\n {{ 'CmsKit::StartDate' | abpLocalization }}\r\n </label>\r\n <input\r\n id=\"creationStartDate\"\r\n formControlName=\"creationStartDate\"\r\n (click)=\"startDatePicker.open()\"\r\n (keyup.space)=\"startDatePicker.open()\"\r\n ngbDatepicker\r\n #startDatePicker=\"ngbDatepicker\"\r\n type=\"text\"\r\n class=\"form-control\"\r\n />\r\n </div>\r\n </div>\r\n <div class=\"col-lg-6 col-md-6\">\r\n <div class=\"mb-3\">\r\n <label class=\"form-label\" for=\"creationEndDate\">\r\n {{ 'CmsKit::EndDate' | abpLocalization }}\r\n </label>\r\n <input\r\n id=\"creationEndDate\"\r\n formControlName=\"creationEndDate\"\r\n class=\"form-control\"\r\n ngbDatepicker\r\n #endDatePicker=\"ngbDatepicker\"\r\n (click)=\"endDatePicker.toggle()\"\r\n readonly\r\n />\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"col-lg-4 col-md-12\">\r\n <abp-form-input\r\n formControlName=\"author\"\r\n [label]=\"'CmsKit::Username' | abpLocalization\"\r\n type=\"text\"\r\n />\r\n </div>\r\n @if (requireApprovement) {\r\n <div class=\"col-lg-2 col-md-12\">\r\n <div class=\"mb-3\">\r\n <label class=\"mb-1 form-label\" for=\"commentApproveState\">\r\n {{ 'CmsKit::CommentFilter:ApproveState' | abpLocalization }}\r\n </label>\r\n <select\r\n id=\"commentApproveState\"\r\n formControlName=\"commentApproveState\"\r\n class=\"form-control\"\r\n >\r\n @for (option of commentApproveStateOptions; track option.value) {\r\n <option [value]=\"option.value\">\r\n {{ 'CmsKit::CommentFilter:' + option.value | abpLocalization }}\r\n </option>\r\n }\r\n </select>\r\n </div>\r\n </div>\r\n }\r\n\r\n <div class=\"col-lg-2 col-md-12\">\r\n <div class=\"d-grid gap-2\">\r\n <abp-button class=\"mt-md-4\" buttonType=\"Primary\" type=\"submit\">\r\n <i class=\"fa fa-search\" aria-hidden=\"true\"></i>\r\n </abp-button>\r\n </div>\r\n </div>\r\n </div>\r\n </form>\r\n </div>\r\n </div>\r\n\r\n <h3>{{ 'CmsKit::RepliesToThisComment' | abpLocalization }}</h3>\r\n\r\n <div class=\"card\">\r\n <abp-extensible-table [data]=\"data.items\" [recordsTotal]=\"data.totalCount\" [list]=\"list\" />\r\n </div>\r\n</abp-page>\r\n" }]
429
+ }] });
430
+
431
+ const CMS_KIT_COMMENTS_REQUIRE_APPROVEMENT = 'CmsKit.Comments.RequireApprovement';
432
+
433
+ class TagModalComponent {
434
+ constructor() {
435
+ this.tagService = inject(TagAdminService);
436
+ this.injector = inject(Injector);
437
+ this.toasterService = inject(ToasterService);
438
+ this.selected = input(...(ngDevMode ? [undefined, { debugName: "selected" }] : []));
439
+ this.sectionId = input(...(ngDevMode ? [undefined, { debugName: "sectionId" }] : []));
440
+ this.visibleChange = output();
441
+ }
442
+ ngOnInit() {
443
+ this.buildForm();
444
+ }
445
+ buildForm() {
446
+ const data = new FormPropData(this.injector, this.selected());
447
+ this.form = generateFormFromProps(data);
448
+ }
449
+ onVisibleChange(visible, refresh = false) {
450
+ this.visibleChange.emit({ visible, refresh });
451
+ }
452
+ save() {
453
+ if (!this.form.valid) {
454
+ return;
455
+ }
456
+ let observable$ = this.tagService.create(this.form.value);
457
+ const selectedTag = this.selected();
458
+ const { id } = selectedTag || {};
459
+ if (id) {
460
+ observable$ = this.tagService.update(id, {
461
+ ...selectedTag,
462
+ ...this.form.value,
463
+ });
464
+ }
465
+ observable$.subscribe(() => {
466
+ this.onVisibleChange(false, true);
467
+ this.toasterService.success('AbpUi::SavedSuccessfully');
468
+ });
469
+ }
470
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: TagModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
471
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.9", type: TagModalComponent, isStandalone: true, selector: "abp-tag-modal", inputs: { selected: { classPropertyName: "selected", publicName: "selected", isSignal: true, isRequired: false, transformFunction: null }, sectionId: { classPropertyName: "sectionId", publicName: "sectionId", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { visibleChange: "visibleChange" }, ngImport: i0, template: "<abp-modal [visible]=\"true\" (visibleChange)=\"onVisibleChange($event)\">\r\n <ng-template #abpHeader>\r\n <h3>\r\n {{ (selected()?.id ? 'AbpUi::Edit' : 'AbpUi::New') | abpLocalization }}\r\n </h3>\r\n </ng-template>\r\n\r\n <ng-template #abpBody>\r\n @if (form) {\r\n <form [formGroup]=\"form\" (ngSubmit)=\"save()\" validateOnSubmit>\r\n <abp-extensible-form [selectedRecord]=\"selected()\" />\r\n </form>\r\n } @else {\r\n <div class=\"text-center\">\r\n <i class=\"fa fa-pulse fa-spinner\" aria-hidden=\"true\"></i>\r\n </div>\r\n }\r\n </ng-template>\r\n\r\n <ng-template #abpFooter>\r\n <button type=\"button\" class=\"btn btn-outline-primary\" abpClose>\r\n {{ 'AbpUi::Cancel' | abpLocalization }}\r\n </button>\r\n <abp-button iconClass=\"fa fa-check\" [disabled]=\"form?.invalid\" (click)=\"save()\">\r\n {{ 'AbpUi::Save' | abpLocalization }}\r\n </abp-button>\r\n </ng-template>\r\n</abp-modal>\r\n", dependencies: [{ kind: "component", type: ExtensibleFormComponent, selector: "abp-extensible-form", inputs: ["selectedRecord"], exportAs: ["abpExtensibleForm"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: NgxValidateCoreModule }, { kind: "directive", type: i2$1.ValidationGroupDirective, selector: "[formGroup],[formGroupName]", exportAs: ["validationGroup"] }, { kind: "component", type: ModalComponent, selector: "abp-modal", inputs: ["visible", "busy", "options", "suppressUnsavedChangesWarning"], outputs: ["visibleChange", "init", "appear", "disappear"] }, { kind: "directive", type: ModalCloseDirective, selector: "[abpClose]" }, { kind: "component", type: ButtonComponent, selector: "abp-button", inputs: ["buttonId", "buttonClass", "buttonType", "formName", "iconClass", "loading", "disabled", "attributes"], outputs: ["click", "focus", "blur", "abpClick", "abpFocus", "abpBlur"] }, { kind: "pipe", type: LocalizationPipe, name: "abpLocalization" }] }); }
472
+ }
473
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: TagModalComponent, decorators: [{
474
+ type: Component,
475
+ args: [{ selector: 'abp-tag-modal', imports: [
476
+ ExtensibleFormComponent,
477
+ LocalizationPipe,
478
+ ReactiveFormsModule,
479
+ CommonModule,
480
+ NgxValidateCoreModule,
481
+ ModalComponent,
482
+ ModalCloseDirective,
483
+ ButtonComponent,
484
+ ], template: "<abp-modal [visible]=\"true\" (visibleChange)=\"onVisibleChange($event)\">\r\n <ng-template #abpHeader>\r\n <h3>\r\n {{ (selected()?.id ? 'AbpUi::Edit' : 'AbpUi::New') | abpLocalization }}\r\n </h3>\r\n </ng-template>\r\n\r\n <ng-template #abpBody>\r\n @if (form) {\r\n <form [formGroup]=\"form\" (ngSubmit)=\"save()\" validateOnSubmit>\r\n <abp-extensible-form [selectedRecord]=\"selected()\" />\r\n </form>\r\n } @else {\r\n <div class=\"text-center\">\r\n <i class=\"fa fa-pulse fa-spinner\" aria-hidden=\"true\"></i>\r\n </div>\r\n }\r\n </ng-template>\r\n\r\n <ng-template #abpFooter>\r\n <button type=\"button\" class=\"btn btn-outline-primary\" abpClose>\r\n {{ 'AbpUi::Cancel' | abpLocalization }}\r\n </button>\r\n <abp-button iconClass=\"fa fa-check\" [disabled]=\"form?.invalid\" (click)=\"save()\">\r\n {{ 'AbpUi::Save' | abpLocalization }}\r\n </abp-button>\r\n </ng-template>\r\n</abp-modal>\r\n" }]
485
+ }], propDecorators: { selected: [{ type: i0.Input, args: [{ isSignal: true, alias: "selected", required: false }] }], sectionId: [{ type: i0.Input, args: [{ isSignal: true, alias: "sectionId", required: false }] }], visibleChange: [{ type: i0.Output, args: ["visibleChange"] }] } });
486
+
487
+ class TagListComponent {
488
+ constructor() {
489
+ this.data = { items: [], totalCount: 0 };
490
+ this.list = inject((ListService));
491
+ this.tagService = inject(TagAdminService);
492
+ this.confirmationService = inject(ConfirmationService);
493
+ this.filter = '';
494
+ this.isModalVisible = false;
495
+ this.tagDefinitions = [];
496
+ }
497
+ ngOnInit() {
498
+ this.loadTagDefinitions();
499
+ this.hookToQuery();
500
+ }
501
+ loadTagDefinitions() {
502
+ this.tagService.getTagDefinitions().subscribe(definitions => {
503
+ this.tagDefinitions = definitions;
504
+ });
505
+ }
506
+ onSearch() {
507
+ this.list.filter = this.filter;
508
+ this.list.get();
509
+ }
510
+ add() {
511
+ this.selected = {};
512
+ this.isModalVisible = true;
513
+ }
514
+ edit(id) {
515
+ this.tagService.get(id).subscribe(tag => {
516
+ this.selected = tag;
517
+ this.isModalVisible = true;
518
+ });
519
+ }
520
+ hookToQuery() {
521
+ this.list
522
+ .hookToQuery(query => {
523
+ let filters = {};
524
+ if (this.list.filter) {
525
+ filters.filter = this.list.filter;
526
+ }
527
+ const input = {
528
+ ...query,
529
+ ...filters,
530
+ };
531
+ return this.tagService.getList(input);
532
+ })
533
+ .subscribe(res => {
534
+ this.data = res;
535
+ });
536
+ }
537
+ onVisibleModalChange(visibilityChange) {
538
+ if (visibilityChange.visible) {
539
+ return;
540
+ }
541
+ if (visibilityChange.refresh) {
542
+ this.list.get();
543
+ }
544
+ this.selected = null;
545
+ this.isModalVisible = false;
546
+ }
547
+ delete(id, name) {
548
+ this.confirmationService
549
+ .warn('CmsKit::TagDeletionConfirmationMessage', 'AbpUi::AreYouSure', {
550
+ messageLocalizationParams: [name],
551
+ })
552
+ .subscribe((status) => {
553
+ if (status === Confirmation.Status.confirm) {
554
+ this.tagService.delete(id).subscribe(() => {
555
+ this.list.get();
556
+ });
557
+ }
558
+ });
559
+ }
560
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: TagListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
561
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.9", type: TagListComponent, isStandalone: true, selector: "abp-tag-list", providers: [
562
+ ListService,
563
+ {
564
+ provide: EXTENSIONS_IDENTIFIER,
565
+ useValue: eCmsKitAdminComponents.Tags,
566
+ },
567
+ ], ngImport: i0, template: "<abp-page [title]=\"'CmsKit::Tags' | abpLocalization\" [toolbar]=\"data.items\">\r\n <div class=\"card mb-4\">\r\n <div class=\"card-body\">\r\n <div class=\"row\">\r\n <div class=\"col-12\">\r\n <div class=\"input-group\">\r\n <input\r\n type=\"search\"\r\n class=\"form-control\"\r\n [placeholder]=\"'AbpUi::PagerSearch' | abpLocalization\"\r\n [(ngModel)]=\"filter\"\r\n (keyup.enter)=\"onSearch()\"\r\n />\r\n <button class=\"btn btn-primary\" type=\"button\" (click)=\"onSearch()\">\r\n <i class=\"fa fa-search\" aria-hidden=\"true\"></i>\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"card\">\r\n <abp-extensible-table [data]=\"data.items\" [recordsTotal]=\"data.totalCount\" [list]=\"list\" />\r\n </div>\r\n\r\n @if (isModalVisible) {\r\n <abp-tag-modal [selected]=\"selected\" (visibleChange)=\"onVisibleModalChange($event)\" />\r\n }\r\n</abp-page>\r\n", dependencies: [{ kind: "component", type: ExtensibleTableComponent, selector: "abp-extensible-table", inputs: ["actionsText", "data", "list", "recordsTotal", "actionsColumnWidth", "actionsTemplate", "selectable", "selectionType", "selected", "infiniteScroll", "isLoading", "scrollThreshold", "tableHeight", "rowDetailTemplate", "rowDetailHeight"], outputs: ["tableActivate", "selectionChange", "loadMore", "rowDetailToggle"], exportAs: ["abpExtensibleTable"] }, { kind: "component", type: PageComponent, selector: "abp-page", inputs: ["title", "toolbar", "breadcrumb"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$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: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: CommonModule }, { kind: "component", type: TagModalComponent, selector: "abp-tag-modal", inputs: ["selected", "sectionId"], outputs: ["visibleChange"] }, { kind: "pipe", type: LocalizationPipe, name: "abpLocalization" }] }); }
568
+ }
569
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: TagListComponent, decorators: [{
570
+ type: Component,
571
+ args: [{ selector: 'abp-tag-list', providers: [
572
+ ListService,
573
+ {
574
+ provide: EXTENSIONS_IDENTIFIER,
575
+ useValue: eCmsKitAdminComponents.Tags,
576
+ },
577
+ ], imports: [
578
+ ExtensibleTableComponent,
579
+ PageComponent,
580
+ LocalizationPipe,
581
+ FormsModule,
582
+ CommonModule,
583
+ TagModalComponent,
584
+ ], template: "<abp-page [title]=\"'CmsKit::Tags' | abpLocalization\" [toolbar]=\"data.items\">\r\n <div class=\"card mb-4\">\r\n <div class=\"card-body\">\r\n <div class=\"row\">\r\n <div class=\"col-12\">\r\n <div class=\"input-group\">\r\n <input\r\n type=\"search\"\r\n class=\"form-control\"\r\n [placeholder]=\"'AbpUi::PagerSearch' | abpLocalization\"\r\n [(ngModel)]=\"filter\"\r\n (keyup.enter)=\"onSearch()\"\r\n />\r\n <button class=\"btn btn-primary\" type=\"button\" (click)=\"onSearch()\">\r\n <i class=\"fa fa-search\" aria-hidden=\"true\"></i>\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"card\">\r\n <abp-extensible-table [data]=\"data.items\" [recordsTotal]=\"data.totalCount\" [list]=\"list\" />\r\n </div>\r\n\r\n @if (isModalVisible) {\r\n <abp-tag-modal [selected]=\"selected\" (visibleChange)=\"onVisibleModalChange($event)\" />\r\n }\r\n</abp-page>\r\n" }]
585
+ }] });
586
+
587
+ class PageListComponent {
588
+ constructor() {
589
+ this.data = { items: [], totalCount: 0 };
590
+ this.list = inject((ListService));
591
+ this.pageService = inject(PageAdminService);
592
+ this.confirmationService = inject(ConfirmationService);
593
+ this.toasterService = inject(ToasterService);
594
+ this.filter = '';
595
+ }
596
+ ngOnInit() {
597
+ this.hookToQuery();
598
+ }
599
+ onSearch() {
600
+ this.list.filter = this.filter;
601
+ this.list.get();
602
+ }
603
+ hookToQuery() {
604
+ this.list
605
+ .hookToQuery(query => {
606
+ let filters = {};
607
+ if (this.list.filter) {
608
+ filters.filter = this.list.filter;
609
+ }
610
+ const input = {
611
+ ...query,
612
+ ...filters,
613
+ };
614
+ return this.pageService.getList(input);
615
+ })
616
+ .subscribe(res => {
617
+ this.data = res;
618
+ });
619
+ }
620
+ delete(id) {
621
+ this.confirmationService
622
+ .warn('CmsKit::PageDeletionConfirmationMessage', 'AbpUi::AreYouSure', {
623
+ yesText: 'AbpUi::Yes',
624
+ cancelText: 'AbpUi::Cancel',
625
+ })
626
+ .subscribe((status) => {
627
+ if (status === Confirmation.Status.confirm) {
628
+ this.pageService.delete(id).subscribe(() => {
629
+ this.list.get();
630
+ });
631
+ }
632
+ });
633
+ }
634
+ setAsHomePage(id, isHomePage) {
635
+ this.pageService.setAsHomePage(id).subscribe(() => {
636
+ this.list.get();
637
+ if (isHomePage) {
638
+ this.toasterService.warn('CmsKit::RemovedSettingAsHomePage');
639
+ }
640
+ else {
641
+ this.toasterService.success('CmsKit::CompletedSettingAsHomePage');
642
+ }
643
+ });
644
+ }
645
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: PageListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
646
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.9", type: PageListComponent, isStandalone: true, selector: "abp-page-list", providers: [
647
+ ListService,
648
+ {
649
+ provide: EXTENSIONS_IDENTIFIER,
650
+ useValue: eCmsKitAdminComponents.Pages,
651
+ },
652
+ ], ngImport: i0, template: "<abp-page [title]=\"'CmsKit::Pages' | abpLocalization\" [toolbar]=\"data.items\">\r\n <div class=\"card mb-4\">\r\n <div class=\"card-body\">\r\n <div class=\"row\">\r\n <div class=\"col-12\">\r\n <div class=\"input-group\">\r\n <input\r\n type=\"search\"\r\n class=\"form-control\"\r\n [placeholder]=\"'AbpUi::PagerSearch' | abpLocalization\"\r\n [(ngModel)]=\"filter\"\r\n (keyup.enter)=\"onSearch()\"\r\n />\r\n <button class=\"btn btn-primary\" type=\"button\" (click)=\"onSearch()\">\r\n <i class=\"fa fa-search\" aria-hidden=\"true\"></i>\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"card\">\r\n <abp-extensible-table [data]=\"data.items\" [recordsTotal]=\"data.totalCount\" [list]=\"list\" />\r\n </div>\r\n</abp-page>\r\n", dependencies: [{ kind: "component", type: ExtensibleTableComponent, selector: "abp-extensible-table", inputs: ["actionsText", "data", "list", "recordsTotal", "actionsColumnWidth", "actionsTemplate", "selectable", "selectionType", "selected", "infiniteScroll", "isLoading", "scrollThreshold", "tableHeight", "rowDetailTemplate", "rowDetailHeight"], outputs: ["tableActivate", "selectionChange", "loadMore", "rowDetailToggle"], exportAs: ["abpExtensibleTable"] }, { kind: "component", type: PageComponent, selector: "abp-page", inputs: ["title", "toolbar", "breadcrumb"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$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: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: CommonModule }, { kind: "pipe", type: LocalizationPipe, name: "abpLocalization" }] }); }
653
+ }
654
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: PageListComponent, decorators: [{
655
+ type: Component,
656
+ args: [{ selector: 'abp-page-list', providers: [
657
+ ListService,
658
+ {
659
+ provide: EXTENSIONS_IDENTIFIER,
660
+ useValue: eCmsKitAdminComponents.Pages,
661
+ },
662
+ ], imports: [ExtensibleTableComponent, PageComponent, LocalizationPipe, FormsModule, CommonModule], template: "<abp-page [title]=\"'CmsKit::Pages' | abpLocalization\" [toolbar]=\"data.items\">\r\n <div class=\"card mb-4\">\r\n <div class=\"card-body\">\r\n <div class=\"row\">\r\n <div class=\"col-12\">\r\n <div class=\"input-group\">\r\n <input\r\n type=\"search\"\r\n class=\"form-control\"\r\n [placeholder]=\"'AbpUi::PagerSearch' | abpLocalization\"\r\n [(ngModel)]=\"filter\"\r\n (keyup.enter)=\"onSearch()\"\r\n />\r\n <button class=\"btn btn-primary\" type=\"button\" (click)=\"onSearch()\">\r\n <i class=\"fa fa-search\" aria-hidden=\"true\"></i>\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"card\">\r\n <abp-extensible-table [data]=\"data.items\" [recordsTotal]=\"data.totalCount\" [list]=\"list\" />\r\n </div>\r\n</abp-page>\r\n" }]
663
+ }] });
664
+
665
+ class PageFormComponent {
666
+ constructor() {
667
+ this.pageService = inject(PageAdminService);
668
+ this.injector = inject(Injector);
669
+ this.pageFormService = inject(PageFormService);
670
+ this.route = inject(ActivatedRoute);
671
+ this.destroyRef = inject(DestroyRef);
672
+ this.page = null;
673
+ this.pageId = null;
674
+ this.isEditMode = false;
675
+ }
676
+ ngOnInit() {
677
+ const id = this.route.snapshot.params['id'];
678
+ if (id) {
679
+ this.isEditMode = true;
680
+ this.pageId = id;
681
+ this.loadPage(id);
682
+ }
683
+ else {
684
+ this.isEditMode = false;
685
+ this.buildForm();
686
+ }
687
+ }
688
+ loadPage(id) {
689
+ this.pageService.get(id).subscribe(page => {
690
+ this.page = page;
691
+ this.buildForm();
692
+ });
693
+ }
694
+ buildForm() {
695
+ const data = new FormPropData(this.injector, this.page || {});
696
+ const baseForm = generateFormFromProps(data);
697
+ this.form = new FormGroup({
698
+ ...baseForm.controls,
699
+ content: new FormControl(this.page?.content || ''),
700
+ script: new FormControl(this.page?.script || ''),
701
+ style: new FormControl(this.page?.style || ''),
702
+ });
703
+ prepareSlugFromControl(this.form, 'title', 'slug', this.destroyRef);
704
+ }
705
+ executeSaveOperation(operation) {
706
+ if (this.isEditMode) {
707
+ if (!this.page || !this.pageId) {
708
+ return;
709
+ }
710
+ switch (operation) {
711
+ case 'save':
712
+ this.pageFormService.update(this.pageId, this.form, this.page).subscribe();
713
+ break;
714
+ case 'draft':
715
+ this.pageFormService.updateAsDraft(this.pageId, this.form, this.page).subscribe();
716
+ break;
717
+ case 'publish':
718
+ this.pageFormService.updateAndPublish(this.pageId, this.form, this.page).subscribe();
719
+ break;
720
+ }
721
+ return;
722
+ }
723
+ switch (operation) {
724
+ case 'save':
725
+ this.pageFormService.create(this.form).subscribe();
726
+ break;
727
+ case 'draft':
728
+ this.pageFormService.createAsDraft(this.form).subscribe();
729
+ break;
730
+ case 'publish':
731
+ this.pageFormService.publish(this.form).subscribe();
732
+ break;
733
+ }
734
+ }
735
+ save() {
736
+ this.executeSaveOperation('save');
737
+ }
738
+ saveAsDraft() {
739
+ this.executeSaveOperation('draft');
740
+ }
741
+ publish() {
742
+ this.executeSaveOperation('publish');
743
+ }
744
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: PageFormComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
745
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.9", type: PageFormComponent, isStandalone: true, selector: "abp-page-form", providers: [
746
+ {
747
+ provide: EXTENSIONS_IDENTIFIER,
748
+ useValue: eCmsKitAdminComponents.PageForm,
749
+ },
750
+ ], ngImport: i0, template: "<abp-page [title]=\"'CmsKit::Pages' | abpLocalization\">\r\n <div class=\"card\">\r\n <div class=\"card-body\">\r\n @if (form && (!isEditMode || page)) {\r\n <form [formGroup]=\"form\" (ngSubmit)=\"save()\" validateOnSubmit>\r\n <!-- Basic fields outside tabs -->\r\n <abp-extensible-form [selectedRecord]=\"page || {}\" />\r\n\r\n <!-- Tabs for Content, Script, and Style -->\r\n <ul ngbNav #nav=\"ngbNav\" class=\"nav-tabs mt-3\">\r\n <li ngbNavItem>\r\n <a ngbNavLink>{{ 'CmsKit::Content' | abpLocalization }}</a>\r\n <ng-template ngbNavContent>\r\n <div class=\"mt-3\">\r\n <abp-toastui-editor formControlName=\"content\" />\r\n </div>\r\n </ng-template>\r\n </li>\r\n\r\n <li ngbNavItem>\r\n <a ngbNavLink>{{ 'CmsKit::Script' | abpLocalization }}</a>\r\n <ng-template ngbNavContent>\r\n <div class=\"mt-3\">\r\n <abp-codemirror-editor formControlName=\"script\" />\r\n </div>\r\n </ng-template>\r\n </li>\r\n\r\n <li ngbNavItem>\r\n <a ngbNavLink>{{ 'CmsKit::Style' | abpLocalization }}</a>\r\n <ng-template ngbNavContent>\r\n <div class=\"mt-3\">\r\n <abp-codemirror-editor formControlName=\"style\" />\r\n </div>\r\n </ng-template>\r\n </li>\r\n </ul>\r\n <div class=\"mt-2 fade-in-top\" [ngbNavOutlet]=\"nav\"></div>\r\n </form>\r\n } @else {\r\n <div class=\"text-center\">\r\n <i class=\"fa fa-pulse fa-spinner\" aria-hidden=\"true\"></i>\r\n </div>\r\n }\r\n </div>\r\n <div class=\"card-footer\">\r\n <div class=\"d-flex justify-content-start gap-2\">\r\n <button class=\"btn btn-secondary\" (click)=\"saveAsDraft()\" [disabled]=\"form?.invalid\">\r\n {{ 'CmsKit::SaveAsDraft' | abpLocalization }}\r\n </button>\r\n <abp-button (click)=\"publish()\" [disabled]=\"form?.invalid\">\r\n {{ 'CmsKit::Publish' | abpLocalization }}\r\n </abp-button>\r\n </div>\r\n </div>\r\n </div>\r\n</abp-page>\r\n", dependencies: [{ kind: "component", type: ButtonComponent, selector: "abp-button", inputs: ["buttonId", "buttonClass", "buttonType", "formName", "iconClass", "loading", "disabled", "attributes"], outputs: ["click", "focus", "blur", "abpClick", "abpFocus", "abpBlur"] }, { kind: "component", type: CodeMirrorEditorComponent, selector: "abp-codemirror-editor" }, { kind: "component", type: ExtensibleFormComponent, selector: "abp-extensible-form", inputs: ["selectedRecord"], exportAs: ["abpExtensibleForm"] }, { kind: "component", type: PageComponent, selector: "abp-page", inputs: ["title", "toolbar", "breadcrumb"] }, { kind: "component", type: ToastuiEditorComponent, selector: "abp-toastui-editor" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: NgxValidateCoreModule }, { kind: "directive", type: i2$1.ValidationGroupDirective, selector: "[formGroup],[formGroupName]", exportAs: ["validationGroup"] }, { kind: "directive", type: i2$1.ValidationDirective, selector: "[formControl],[formControlName]", exportAs: ["validationDirective"] }, { kind: "ngmodule", type: NgbNavModule }, { kind: "directive", type: i3.NgbNavContent, selector: "ng-template[ngbNavContent]" }, { kind: "directive", type: i3.NgbNav, selector: "[ngbNav]", inputs: ["activeId", "animation", "destroyOnHide", "orientation", "roles", "keyboard"], outputs: ["activeIdChange", "shown", "hidden", "navChange"], exportAs: ["ngbNav"] }, { kind: "directive", type: i3.NgbNavItem, selector: "[ngbNavItem]", inputs: ["destroyOnHide", "disabled", "domId", "ngbNavItem"], outputs: ["shown", "hidden"], exportAs: ["ngbNavItem"] }, { kind: "directive", type: i3.NgbNavItemRole, selector: "[ngbNavItem]:not(ng-container)" }, { kind: "directive", type: i3.NgbNavLink, selector: "a[ngbNavLink]" }, { kind: "directive", type: i3.NgbNavLinkBase, selector: "[ngbNavLink]" }, { kind: "component", type: i3.NgbNavOutlet, selector: "[ngbNavOutlet]", inputs: ["paneRole", "ngbNavOutlet"] }, { kind: "pipe", type: LocalizationPipe, name: "abpLocalization" }] }); }
751
+ }
752
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: PageFormComponent, decorators: [{
753
+ type: Component,
754
+ args: [{ selector: 'abp-page-form', providers: [
755
+ {
756
+ provide: EXTENSIONS_IDENTIFIER,
757
+ useValue: eCmsKitAdminComponents.PageForm,
758
+ },
759
+ ], imports: [
760
+ ButtonComponent,
761
+ CodeMirrorEditorComponent,
762
+ ExtensibleFormComponent,
763
+ PageComponent,
764
+ ToastuiEditorComponent,
765
+ LocalizationPipe,
766
+ ReactiveFormsModule,
767
+ CommonModule,
768
+ NgxValidateCoreModule,
769
+ NgbNavModule,
770
+ ], template: "<abp-page [title]=\"'CmsKit::Pages' | abpLocalization\">\r\n <div class=\"card\">\r\n <div class=\"card-body\">\r\n @if (form && (!isEditMode || page)) {\r\n <form [formGroup]=\"form\" (ngSubmit)=\"save()\" validateOnSubmit>\r\n <!-- Basic fields outside tabs -->\r\n <abp-extensible-form [selectedRecord]=\"page || {}\" />\r\n\r\n <!-- Tabs for Content, Script, and Style -->\r\n <ul ngbNav #nav=\"ngbNav\" class=\"nav-tabs mt-3\">\r\n <li ngbNavItem>\r\n <a ngbNavLink>{{ 'CmsKit::Content' | abpLocalization }}</a>\r\n <ng-template ngbNavContent>\r\n <div class=\"mt-3\">\r\n <abp-toastui-editor formControlName=\"content\" />\r\n </div>\r\n </ng-template>\r\n </li>\r\n\r\n <li ngbNavItem>\r\n <a ngbNavLink>{{ 'CmsKit::Script' | abpLocalization }}</a>\r\n <ng-template ngbNavContent>\r\n <div class=\"mt-3\">\r\n <abp-codemirror-editor formControlName=\"script\" />\r\n </div>\r\n </ng-template>\r\n </li>\r\n\r\n <li ngbNavItem>\r\n <a ngbNavLink>{{ 'CmsKit::Style' | abpLocalization }}</a>\r\n <ng-template ngbNavContent>\r\n <div class=\"mt-3\">\r\n <abp-codemirror-editor formControlName=\"style\" />\r\n </div>\r\n </ng-template>\r\n </li>\r\n </ul>\r\n <div class=\"mt-2 fade-in-top\" [ngbNavOutlet]=\"nav\"></div>\r\n </form>\r\n } @else {\r\n <div class=\"text-center\">\r\n <i class=\"fa fa-pulse fa-spinner\" aria-hidden=\"true\"></i>\r\n </div>\r\n }\r\n </div>\r\n <div class=\"card-footer\">\r\n <div class=\"d-flex justify-content-start gap-2\">\r\n <button class=\"btn btn-secondary\" (click)=\"saveAsDraft()\" [disabled]=\"form?.invalid\">\r\n {{ 'CmsKit::SaveAsDraft' | abpLocalization }}\r\n </button>\r\n <abp-button (click)=\"publish()\" [disabled]=\"form?.invalid\">\r\n {{ 'CmsKit::Publish' | abpLocalization }}\r\n </abp-button>\r\n </div>\r\n </div>\r\n </div>\r\n</abp-page>\r\n" }]
771
+ }] });
772
+
773
+ class BlogModalComponent {
774
+ constructor() {
775
+ this.blogService = inject(BlogAdminService);
776
+ this.injector = inject(Injector);
777
+ this.toasterService = inject(ToasterService);
778
+ this.destroyRef = inject(DestroyRef);
779
+ this.selected = input(...(ngDevMode ? [undefined, { debugName: "selected" }] : []));
780
+ this.visibleChange = output();
781
+ }
782
+ ngOnInit() {
783
+ this.buildForm();
784
+ }
785
+ buildForm() {
786
+ const data = new FormPropData(this.injector, this.selected());
787
+ this.form = generateFormFromProps(data);
788
+ prepareSlugFromControl(this.form, 'name', 'slug', this.destroyRef);
789
+ }
790
+ onVisibleChange(visible, refresh = false) {
791
+ this.visibleChange.emit({ visible, refresh });
792
+ }
793
+ save() {
794
+ if (!this.form.valid) {
795
+ return;
796
+ }
797
+ let observable$ = this.blogService.create(this.form.value);
798
+ const selectedBlog = this.selected();
799
+ const { id } = selectedBlog || {};
800
+ if (id) {
801
+ observable$ = this.blogService.update(id, {
802
+ ...selectedBlog,
803
+ ...this.form.value,
804
+ });
805
+ }
806
+ observable$.subscribe(() => {
807
+ this.onVisibleChange(false, true);
808
+ this.toasterService.success('AbpUi::SavedSuccessfully');
809
+ });
810
+ }
811
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: BlogModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
812
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.9", type: BlogModalComponent, isStandalone: true, selector: "abp-blog-modal", inputs: { selected: { classPropertyName: "selected", publicName: "selected", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { visibleChange: "visibleChange" }, ngImport: i0, template: "<abp-modal [visible]=\"true\" (visibleChange)=\"onVisibleChange($event)\">\r\n <ng-template #abpHeader>\r\n <h3>\r\n {{ (selected()?.id ? 'AbpUi::Edit' : 'AbpUi::New') | abpLocalization }}\r\n </h3>\r\n </ng-template>\r\n\r\n <ng-template #abpBody>\r\n @if (form) {\r\n <form [formGroup]=\"form\" (ngSubmit)=\"save()\" validateOnSubmit>\r\n <abp-extensible-form [selectedRecord]=\"selected()\" />\r\n </form>\r\n } @else {\r\n <div class=\"text-center\">\r\n <i class=\"fa fa-pulse fa-spinner\" aria-hidden=\"true\"></i>\r\n </div>\r\n }\r\n </ng-template>\r\n\r\n <ng-template #abpFooter>\r\n <button type=\"button\" class=\"btn btn-outline-primary\" abpClose>\r\n {{ 'AbpUi::Cancel' | abpLocalization }}\r\n </button>\r\n <abp-button iconClass=\"fa fa-check\" [disabled]=\"form?.invalid\" (click)=\"save()\">\r\n {{ 'AbpUi::Save' | abpLocalization }}\r\n </abp-button>\r\n </ng-template>\r\n</abp-modal>\r\n", dependencies: [{ kind: "component", type: ExtensibleFormComponent, selector: "abp-extensible-form", inputs: ["selectedRecord"], exportAs: ["abpExtensibleForm"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: NgxValidateCoreModule }, { kind: "directive", type: i2$1.ValidationGroupDirective, selector: "[formGroup],[formGroupName]", exportAs: ["validationGroup"] }, { kind: "component", type: ModalComponent, selector: "abp-modal", inputs: ["visible", "busy", "options", "suppressUnsavedChangesWarning"], outputs: ["visibleChange", "init", "appear", "disappear"] }, { kind: "directive", type: ModalCloseDirective, selector: "[abpClose]" }, { kind: "component", type: ButtonComponent, selector: "abp-button", inputs: ["buttonId", "buttonClass", "buttonType", "formName", "iconClass", "loading", "disabled", "attributes"], outputs: ["click", "focus", "blur", "abpClick", "abpFocus", "abpBlur"] }, { kind: "pipe", type: LocalizationPipe, name: "abpLocalization" }] }); }
813
+ }
814
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: BlogModalComponent, decorators: [{
815
+ type: Component,
816
+ args: [{ selector: 'abp-blog-modal', imports: [
817
+ ExtensibleFormComponent,
818
+ LocalizationPipe,
819
+ ReactiveFormsModule,
820
+ CommonModule,
821
+ NgxValidateCoreModule,
822
+ ModalComponent,
823
+ ModalCloseDirective,
824
+ ButtonComponent,
825
+ ], template: "<abp-modal [visible]=\"true\" (visibleChange)=\"onVisibleChange($event)\">\r\n <ng-template #abpHeader>\r\n <h3>\r\n {{ (selected()?.id ? 'AbpUi::Edit' : 'AbpUi::New') | abpLocalization }}\r\n </h3>\r\n </ng-template>\r\n\r\n <ng-template #abpBody>\r\n @if (form) {\r\n <form [formGroup]=\"form\" (ngSubmit)=\"save()\" validateOnSubmit>\r\n <abp-extensible-form [selectedRecord]=\"selected()\" />\r\n </form>\r\n } @else {\r\n <div class=\"text-center\">\r\n <i class=\"fa fa-pulse fa-spinner\" aria-hidden=\"true\"></i>\r\n </div>\r\n }\r\n </ng-template>\r\n\r\n <ng-template #abpFooter>\r\n <button type=\"button\" class=\"btn btn-outline-primary\" abpClose>\r\n {{ 'AbpUi::Cancel' | abpLocalization }}\r\n </button>\r\n <abp-button iconClass=\"fa fa-check\" [disabled]=\"form?.invalid\" (click)=\"save()\">\r\n {{ 'AbpUi::Save' | abpLocalization }}\r\n </abp-button>\r\n </ng-template>\r\n</abp-modal>\r\n" }]
826
+ }], propDecorators: { selected: [{ type: i0.Input, args: [{ isSignal: true, alias: "selected", required: false }] }], visibleChange: [{ type: i0.Output, args: ["visibleChange"] }] } });
827
+
828
+ class BlogFeaturesModalComponent {
829
+ constructor() {
830
+ this.blogFeatureService = inject(BlogFeatureAdminService);
831
+ this.fb = inject(FormBuilder);
832
+ this.toasterService = inject(ToasterService);
833
+ this.blogId = input(...(ngDevMode ? [undefined, { debugName: "blogId" }] : []));
834
+ this.visibleChange = output();
835
+ this.features = [];
836
+ this.initialFeatureStates = new Map();
837
+ }
838
+ ngOnInit() {
839
+ if (this.blogId()) {
840
+ this.loadFeatures();
841
+ }
842
+ }
843
+ loadFeatures() {
844
+ this.blogFeatureService.getList(this.blogId()).subscribe(features => {
845
+ this.features = features.sort((a, b) => (a.featureName || '').localeCompare(b.featureName || ''));
846
+ // Store initial states
847
+ this.initialFeatureStates = new Map(this.features.map(f => [f.featureName || '', f.isEnabled || false]));
848
+ this.buildForm();
849
+ });
850
+ }
851
+ buildForm() {
852
+ const featureControls = this.features.map(feature => this.fb.group({
853
+ featureName: [feature.featureName],
854
+ isEnabled: [feature.isEnabled],
855
+ isAvailable: [feature.isAvailable ?? true],
856
+ }));
857
+ this.form = this.fb.group({
858
+ features: this.fb.array(featureControls),
859
+ });
860
+ }
861
+ get featuresFormArray() {
862
+ return this.form.get('features');
863
+ }
864
+ onVisibleChange(visible, refresh = false) {
865
+ this.visibleChange.emit({ visible, refresh });
866
+ }
867
+ save() {
868
+ if (!this.form.valid || !this.blogId()) {
869
+ return;
870
+ }
871
+ const featuresArray = this.form.get('features');
872
+ // Only save features that have changed
873
+ const changedFeatures = featuresArray.controls
874
+ .map(control => {
875
+ const featureName = control.get('featureName')?.value;
876
+ const isEnabled = control.get('isEnabled')?.value;
877
+ const initialIsEnabled = this.initialFeatureStates.get(featureName);
878
+ // Only include if the value has changed
879
+ if (featureName && initialIsEnabled !== isEnabled) {
880
+ return {
881
+ featureName,
882
+ isEnabled,
883
+ };
884
+ }
885
+ return null;
886
+ })
887
+ .filter((input) => input !== null);
888
+ // If no features changed, just close the modal
889
+ if (changedFeatures.length === 0) {
890
+ this.onVisibleChange(false, false);
891
+ return;
892
+ }
893
+ // Save only changed features
894
+ const saveObservables = changedFeatures.map(input => this.blogFeatureService.set(this.blogId(), input));
895
+ // Use forkJoin to save all changed features at once
896
+ forkJoin(saveObservables).subscribe({
897
+ next: () => {
898
+ this.onVisibleChange(false, true);
899
+ this.toasterService.success('AbpUi::SavedSuccessfully');
900
+ },
901
+ });
902
+ }
903
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: BlogFeaturesModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
904
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.9", type: BlogFeaturesModalComponent, isStandalone: true, selector: "abp-blog-features-modal", inputs: { blogId: { classPropertyName: "blogId", publicName: "blogId", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { visibleChange: "visibleChange" }, ngImport: i0, template: "<abp-modal [visible]=\"true\" (visibleChange)=\"onVisibleChange($event)\">\r\n <ng-template #abpHeader>\r\n <h3>{{ 'CmsKit::Features' | abpLocalization }}</h3>\r\n </ng-template>\r\n\r\n <ng-template #abpBody>\r\n @if (form) {\r\n <form [formGroup]=\"form\" (ngSubmit)=\"save()\" validateOnSubmit>\r\n <div formArrayName=\"features\">\r\n @for (featureControl of featuresFormArray.controls; track $index; let i = $index) {\r\n <div class=\"mb-3\" [formGroupName]=\"i\">\r\n @let isAvailable = featureControl.get('isAvailable')?.value;\r\n @if (isAvailable) {\r\n <div class=\"form-check\">\r\n <input\r\n type=\"checkbox\"\r\n class=\"form-check-input\"\r\n id=\"feature-{{ i }}\"\r\n formControlName=\"isEnabled\"\r\n />\r\n <label class=\"form-check-label\" for=\"feature-{{ i }}\">\r\n {{ 'CmsKit::' + features[i]?.featureName | abpLocalization }}\r\n </label>\r\n </div>\r\n } @else {\r\n <div\r\n data-toggle=\"tooltip\"\r\n [title]=\"'CmsKit::BlogFeatureNotAvailable' | abpLocalization\"\r\n >\r\n <div class=\"form-check\">\r\n <input\r\n type=\"checkbox\"\r\n class=\"form-check-input\"\r\n id=\"feature-{{ i }}\"\r\n formControlName=\"isEnabled\"\r\n disabled\r\n />\r\n <label class=\"form-check-label\" for=\"feature-{{ i }}\">\r\n {{ 'CmsKit::' + features[i]?.featureName | abpLocalization }}\r\n </label>\r\n </div>\r\n </div>\r\n }\r\n <input type=\"hidden\" formControlName=\"featureName\" />\r\n <input type=\"hidden\" formControlName=\"isAvailable\" />\r\n </div>\r\n }\r\n </div>\r\n </form>\r\n } @else {\r\n <div class=\"text-center\">\r\n <i class=\"fa fa-pulse fa-spinner\" aria-hidden=\"true\"></i>\r\n </div>\r\n }\r\n </ng-template>\r\n\r\n <ng-template #abpFooter>\r\n <button type=\"button\" class=\"btn btn-outline-primary\" abpClose>\r\n {{ 'AbpUi::Cancel' | abpLocalization }}\r\n </button>\r\n <abp-button iconClass=\"fa fa-check\" [disabled]=\"form?.invalid\" (click)=\"save()\">\r\n {{ 'AbpUi::Save' | abpLocalization }}\r\n </abp-button>\r\n </ng-template>\r\n</abp-modal>\r\n", dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$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: i1$1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1$1.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "directive", type: i1$1.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: NgxValidateCoreModule }, { kind: "directive", type: i2$1.ValidationGroupDirective, selector: "[formGroup],[formGroupName]", exportAs: ["validationGroup"] }, { kind: "directive", type: i2$1.ValidationDirective, selector: "[formControl],[formControlName]", exportAs: ["validationDirective"] }, { kind: "component", type: ModalComponent, selector: "abp-modal", inputs: ["visible", "busy", "options", "suppressUnsavedChangesWarning"], outputs: ["visibleChange", "init", "appear", "disappear"] }, { kind: "directive", type: ModalCloseDirective, selector: "[abpClose]" }, { kind: "component", type: ButtonComponent, selector: "abp-button", inputs: ["buttonId", "buttonClass", "buttonType", "formName", "iconClass", "loading", "disabled", "attributes"], outputs: ["click", "focus", "blur", "abpClick", "abpFocus", "abpBlur"] }, { kind: "pipe", type: LocalizationPipe, name: "abpLocalization" }] }); }
905
+ }
906
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: BlogFeaturesModalComponent, decorators: [{
907
+ type: Component,
908
+ args: [{ selector: 'abp-blog-features-modal', imports: [
909
+ LocalizationPipe,
910
+ ReactiveFormsModule,
911
+ CommonModule,
912
+ NgxValidateCoreModule,
913
+ ModalComponent,
914
+ ModalCloseDirective,
915
+ ButtonComponent,
916
+ ], template: "<abp-modal [visible]=\"true\" (visibleChange)=\"onVisibleChange($event)\">\r\n <ng-template #abpHeader>\r\n <h3>{{ 'CmsKit::Features' | abpLocalization }}</h3>\r\n </ng-template>\r\n\r\n <ng-template #abpBody>\r\n @if (form) {\r\n <form [formGroup]=\"form\" (ngSubmit)=\"save()\" validateOnSubmit>\r\n <div formArrayName=\"features\">\r\n @for (featureControl of featuresFormArray.controls; track $index; let i = $index) {\r\n <div class=\"mb-3\" [formGroupName]=\"i\">\r\n @let isAvailable = featureControl.get('isAvailable')?.value;\r\n @if (isAvailable) {\r\n <div class=\"form-check\">\r\n <input\r\n type=\"checkbox\"\r\n class=\"form-check-input\"\r\n id=\"feature-{{ i }}\"\r\n formControlName=\"isEnabled\"\r\n />\r\n <label class=\"form-check-label\" for=\"feature-{{ i }}\">\r\n {{ 'CmsKit::' + features[i]?.featureName | abpLocalization }}\r\n </label>\r\n </div>\r\n } @else {\r\n <div\r\n data-toggle=\"tooltip\"\r\n [title]=\"'CmsKit::BlogFeatureNotAvailable' | abpLocalization\"\r\n >\r\n <div class=\"form-check\">\r\n <input\r\n type=\"checkbox\"\r\n class=\"form-check-input\"\r\n id=\"feature-{{ i }}\"\r\n formControlName=\"isEnabled\"\r\n disabled\r\n />\r\n <label class=\"form-check-label\" for=\"feature-{{ i }}\">\r\n {{ 'CmsKit::' + features[i]?.featureName | abpLocalization }}\r\n </label>\r\n </div>\r\n </div>\r\n }\r\n <input type=\"hidden\" formControlName=\"featureName\" />\r\n <input type=\"hidden\" formControlName=\"isAvailable\" />\r\n </div>\r\n }\r\n </div>\r\n </form>\r\n } @else {\r\n <div class=\"text-center\">\r\n <i class=\"fa fa-pulse fa-spinner\" aria-hidden=\"true\"></i>\r\n </div>\r\n }\r\n </ng-template>\r\n\r\n <ng-template #abpFooter>\r\n <button type=\"button\" class=\"btn btn-outline-primary\" abpClose>\r\n {{ 'AbpUi::Cancel' | abpLocalization }}\r\n </button>\r\n <abp-button iconClass=\"fa fa-check\" [disabled]=\"form?.invalid\" (click)=\"save()\">\r\n {{ 'AbpUi::Save' | abpLocalization }}\r\n </abp-button>\r\n </ng-template>\r\n</abp-modal>\r\n" }]
917
+ }], propDecorators: { blogId: [{ type: i0.Input, args: [{ isSignal: true, alias: "blogId", required: false }] }], visibleChange: [{ type: i0.Output, args: ["visibleChange"] }] } });
918
+
919
+ class BlogListComponent {
920
+ constructor() {
921
+ this.data = { items: [], totalCount: 0 };
922
+ this.list = inject((ListService));
923
+ this.blogService = inject(BlogAdminService);
924
+ this.confirmationService = inject(ConfirmationService);
925
+ this.filter = '';
926
+ this.isModalVisible = false;
927
+ this.isFeaturesModalVisible = false;
928
+ }
929
+ ngOnInit() {
930
+ this.hookToQuery();
931
+ }
932
+ onSearch() {
933
+ this.list.filter = this.filter;
934
+ this.list.get();
935
+ }
936
+ add() {
937
+ this.selected = {};
938
+ this.isModalVisible = true;
939
+ }
940
+ edit(id) {
941
+ this.blogService.get(id).subscribe(blog => {
942
+ this.selected = blog;
943
+ this.isModalVisible = true;
944
+ });
945
+ }
946
+ delete(id, name) {
947
+ this.confirmationService
948
+ .warn('CmsKit::BlogDeletionConfirmationMessage', 'AbpUi::AreYouSure', {
949
+ messageLocalizationParams: [name],
950
+ })
951
+ .subscribe((status) => {
952
+ if (status === Confirmation.Status.confirm) {
953
+ this.blogService.delete(id).subscribe(() => {
954
+ this.list.get();
955
+ });
956
+ }
957
+ });
958
+ }
959
+ openFeatures(id) {
960
+ this.selectedBlogId = id;
961
+ this.isFeaturesModalVisible = true;
962
+ }
963
+ hookToQuery() {
964
+ this.list
965
+ .hookToQuery(query => {
966
+ let filters = {};
967
+ if (this.list.filter) {
968
+ filters.filter = this.list.filter;
969
+ }
970
+ const input = {
971
+ ...query,
972
+ ...filters,
973
+ };
974
+ return this.blogService.getList(input);
975
+ })
976
+ .subscribe(res => {
977
+ this.data = res;
978
+ });
979
+ }
980
+ onVisibleModalChange(visibilityChange) {
981
+ if (visibilityChange.visible) {
982
+ return;
983
+ }
984
+ if (visibilityChange.refresh) {
985
+ this.list.get();
986
+ }
987
+ this.selected = null;
988
+ this.isModalVisible = false;
989
+ }
990
+ onFeaturesModalChange(visibilityChange) {
991
+ if (visibilityChange.visible) {
992
+ return;
993
+ }
994
+ if (visibilityChange.refresh) {
995
+ this.list.get();
996
+ }
997
+ this.selectedBlogId = null;
998
+ this.isFeaturesModalVisible = false;
999
+ }
1000
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: BlogListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1001
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.9", type: BlogListComponent, isStandalone: true, selector: "abp-blog-list", providers: [
1002
+ ListService,
1003
+ {
1004
+ provide: EXTENSIONS_IDENTIFIER,
1005
+ useValue: eCmsKitAdminComponents.Blogs,
1006
+ },
1007
+ ], ngImport: i0, template: "<abp-page [title]=\"'CmsKit::Blogs' | abpLocalization\" [toolbar]=\"data.items\">\r\n <div class=\"card\">\r\n <abp-extensible-table [data]=\"data.items\" [recordsTotal]=\"data.totalCount\" [list]=\"list\" />\r\n </div>\r\n\r\n @if (isModalVisible) {\r\n <abp-blog-modal [selected]=\"selected\" (visibleChange)=\"onVisibleModalChange($event)\" />\r\n }\r\n\r\n @if (isFeaturesModalVisible) {\r\n <abp-blog-features-modal\r\n [blogId]=\"selectedBlogId\"\r\n (visibleChange)=\"onFeaturesModalChange($event)\"\r\n />\r\n }\r\n</abp-page>\r\n", dependencies: [{ kind: "component", type: ExtensibleTableComponent, selector: "abp-extensible-table", inputs: ["actionsText", "data", "list", "recordsTotal", "actionsColumnWidth", "actionsTemplate", "selectable", "selectionType", "selected", "infiniteScroll", "isLoading", "scrollThreshold", "tableHeight", "rowDetailTemplate", "rowDetailHeight"], outputs: ["tableActivate", "selectionChange", "loadMore", "rowDetailToggle"], exportAs: ["abpExtensibleTable"] }, { kind: "component", type: PageComponent, selector: "abp-page", inputs: ["title", "toolbar", "breadcrumb"] }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: CommonModule }, { kind: "component", type: BlogModalComponent, selector: "abp-blog-modal", inputs: ["selected"], outputs: ["visibleChange"] }, { kind: "component", type: BlogFeaturesModalComponent, selector: "abp-blog-features-modal", inputs: ["blogId"], outputs: ["visibleChange"] }, { kind: "pipe", type: LocalizationPipe, name: "abpLocalization" }] }); }
1008
+ }
1009
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: BlogListComponent, decorators: [{
1010
+ type: Component,
1011
+ args: [{ selector: 'abp-blog-list', providers: [
1012
+ ListService,
1013
+ {
1014
+ provide: EXTENSIONS_IDENTIFIER,
1015
+ useValue: eCmsKitAdminComponents.Blogs,
1016
+ },
1017
+ ], imports: [
1018
+ ExtensibleTableComponent,
1019
+ PageComponent,
1020
+ LocalizationPipe,
1021
+ FormsModule,
1022
+ CommonModule,
1023
+ BlogModalComponent,
1024
+ BlogFeaturesModalComponent,
1025
+ ], template: "<abp-page [title]=\"'CmsKit::Blogs' | abpLocalization\" [toolbar]=\"data.items\">\r\n <div class=\"card\">\r\n <abp-extensible-table [data]=\"data.items\" [recordsTotal]=\"data.totalCount\" [list]=\"list\" />\r\n </div>\r\n\r\n @if (isModalVisible) {\r\n <abp-blog-modal [selected]=\"selected\" (visibleChange)=\"onVisibleModalChange($event)\" />\r\n }\r\n\r\n @if (isFeaturesModalVisible) {\r\n <abp-blog-features-modal\r\n [blogId]=\"selectedBlogId\"\r\n (visibleChange)=\"onFeaturesModalChange($event)\"\r\n />\r\n }\r\n</abp-page>\r\n" }]
1026
+ }] });
1027
+
1028
+ class BlogPostListComponent {
1029
+ constructor() {
1030
+ this.data = { items: [], totalCount: 0 };
1031
+ this.list = inject((ListService));
1032
+ this.blogPostService = inject(BlogPostAdminService);
1033
+ this.confirmationService = inject(ConfirmationService);
1034
+ this.filter = '';
1035
+ this.statusFilter = null;
1036
+ this.BlogPostStatus = BlogPostStatus;
1037
+ }
1038
+ ngOnInit() {
1039
+ this.hookToQuery();
1040
+ }
1041
+ onSearch() {
1042
+ this.list.filter = this.filter;
1043
+ this.list.get();
1044
+ }
1045
+ onStatusChange() {
1046
+ this.list.get();
1047
+ }
1048
+ hookToQuery() {
1049
+ this.list
1050
+ .hookToQuery(query => {
1051
+ let filters = {};
1052
+ if (this.list.filter) {
1053
+ filters.filter = this.list.filter;
1054
+ }
1055
+ if (this.statusFilter !== null) {
1056
+ filters.status = this.statusFilter;
1057
+ }
1058
+ const input = {
1059
+ ...query,
1060
+ ...filters,
1061
+ };
1062
+ return this.blogPostService.getList(input);
1063
+ })
1064
+ .subscribe(res => (this.data = res));
1065
+ }
1066
+ delete(id, title) {
1067
+ this.confirmationService
1068
+ .warn('CmsKit::BlogPostDeletionConfirmationMessage', 'AbpUi::AreYouSure', {
1069
+ yesText: 'AbpUi::Yes',
1070
+ cancelText: 'AbpUi::Cancel',
1071
+ messageLocalizationParams: [title],
1072
+ })
1073
+ .subscribe((status) => {
1074
+ if (status === Confirmation.Status.confirm) {
1075
+ this.blogPostService.delete(id).subscribe(() => {
1076
+ this.list.get();
1077
+ });
1078
+ }
1079
+ });
1080
+ }
1081
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: BlogPostListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1082
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.9", type: BlogPostListComponent, isStandalone: true, selector: "abp-blog-post-list", providers: [
1083
+ ListService,
1084
+ {
1085
+ provide: EXTENSIONS_IDENTIFIER,
1086
+ useValue: eCmsKitAdminComponents.BlogPosts,
1087
+ },
1088
+ ], ngImport: i0, template: "<abp-page [title]=\"'CmsKit::BlogPosts' | abpLocalization\" [toolbar]=\"data.items\">\r\n <div class=\"card mb-4\">\r\n <div class=\"card-body\">\r\n <div class=\"row\">\r\n <div class=\"col-2\">\r\n <select class=\"form-select\" [(ngModel)]=\"statusFilter\" (change)=\"onStatusChange()\">\r\n <option [ngValue]=\"null\">{{ 'CmsKit::AllPosts' | abpLocalization }}</option>\r\n <option [ngValue]=\"BlogPostStatus.Draft\">\r\n {{ 'CmsKit::' + 'CmsKit.BlogPost.Status.0' | abpLocalization }}\r\n </option>\r\n <option [ngValue]=\"BlogPostStatus.Published\">\r\n {{ 'CmsKit::' + 'CmsKit.BlogPost.Status.1' | abpLocalization }}\r\n </option>\r\n <option [ngValue]=\"BlogPostStatus.WaitingForReview\">\r\n {{ 'CmsKit::' + 'CmsKit.BlogPost.Status.2' | abpLocalization }}\r\n </option>\r\n </select>\r\n </div>\r\n <div class=\"col-10\">\r\n <div class=\"input-group\">\r\n <input\r\n type=\"search\"\r\n class=\"form-control\"\r\n [placeholder]=\"'AbpUi::PagerSearch' | abpLocalization\"\r\n [(ngModel)]=\"filter\"\r\n (keyup.enter)=\"onSearch()\"\r\n />\r\n <button class=\"btn btn-primary\" type=\"button\" (click)=\"onSearch()\">\r\n <i class=\"fa fa-search\" aria-hidden=\"true\"></i>\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"card\">\r\n <abp-extensible-table [data]=\"data.items\" [recordsTotal]=\"data.totalCount\" [list]=\"list\" />\r\n </div>\r\n</abp-page>\r\n", dependencies: [{ kind: "component", type: ExtensibleTableComponent, selector: "abp-extensible-table", inputs: ["actionsText", "data", "list", "recordsTotal", "actionsColumnWidth", "actionsTemplate", "selectable", "selectionType", "selected", "infiniteScroll", "isLoading", "scrollThreshold", "tableHeight", "rowDetailTemplate", "rowDetailHeight"], outputs: ["tableActivate", "selectionChange", "loadMore", "rowDetailToggle"], exportAs: ["abpExtensibleTable"] }, { kind: "component", type: PageComponent, selector: "abp-page", inputs: ["title", "toolbar", "breadcrumb"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$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: i1$1.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: CommonModule }, { kind: "pipe", type: LocalizationPipe, name: "abpLocalization" }] }); }
1089
+ }
1090
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: BlogPostListComponent, decorators: [{
1091
+ type: Component,
1092
+ args: [{ selector: 'abp-blog-post-list', providers: [
1093
+ ListService,
1094
+ {
1095
+ provide: EXTENSIONS_IDENTIFIER,
1096
+ useValue: eCmsKitAdminComponents.BlogPosts,
1097
+ },
1098
+ ], imports: [ExtensibleTableComponent, PageComponent, LocalizationPipe, FormsModule, CommonModule], template: "<abp-page [title]=\"'CmsKit::BlogPosts' | abpLocalization\" [toolbar]=\"data.items\">\r\n <div class=\"card mb-4\">\r\n <div class=\"card-body\">\r\n <div class=\"row\">\r\n <div class=\"col-2\">\r\n <select class=\"form-select\" [(ngModel)]=\"statusFilter\" (change)=\"onStatusChange()\">\r\n <option [ngValue]=\"null\">{{ 'CmsKit::AllPosts' | abpLocalization }}</option>\r\n <option [ngValue]=\"BlogPostStatus.Draft\">\r\n {{ 'CmsKit::' + 'CmsKit.BlogPost.Status.0' | abpLocalization }}\r\n </option>\r\n <option [ngValue]=\"BlogPostStatus.Published\">\r\n {{ 'CmsKit::' + 'CmsKit.BlogPost.Status.1' | abpLocalization }}\r\n </option>\r\n <option [ngValue]=\"BlogPostStatus.WaitingForReview\">\r\n {{ 'CmsKit::' + 'CmsKit.BlogPost.Status.2' | abpLocalization }}\r\n </option>\r\n </select>\r\n </div>\r\n <div class=\"col-10\">\r\n <div class=\"input-group\">\r\n <input\r\n type=\"search\"\r\n class=\"form-control\"\r\n [placeholder]=\"'AbpUi::PagerSearch' | abpLocalization\"\r\n [(ngModel)]=\"filter\"\r\n (keyup.enter)=\"onSearch()\"\r\n />\r\n <button class=\"btn btn-primary\" type=\"button\" (click)=\"onSearch()\">\r\n <i class=\"fa fa-search\" aria-hidden=\"true\"></i>\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"card\">\r\n <abp-extensible-table [data]=\"data.items\" [recordsTotal]=\"data.totalCount\" [list]=\"list\" />\r\n </div>\r\n</abp-page>\r\n" }]
1099
+ }] });
1100
+
1101
+ class BlogPostFormComponent {
1102
+ constructor() {
1103
+ this.blogPostService = inject(BlogPostAdminService);
1104
+ this.mediaService = inject(MediaDescriptorAdminService);
1105
+ this.entityTagService = inject(EntityTagAdminService);
1106
+ this.restService = inject(RestService);
1107
+ this.injector = inject(Injector);
1108
+ this.blogPostFormService = inject(BlogPostFormService);
1109
+ this.route = inject(ActivatedRoute);
1110
+ this.destroyRef = inject(DestroyRef);
1111
+ this.blogPost = null;
1112
+ this.blogPostId = null;
1113
+ this.isEditMode = false;
1114
+ this.coverImageFile = null;
1115
+ this.coverImagePreview = null;
1116
+ this.tags = '';
1117
+ this.isTagsEnabled = true;
1118
+ this.BLOG_POST_ENTITY_TYPE = 'BlogPost';
1119
+ }
1120
+ ngOnInit() {
1121
+ const id = this.route.snapshot.params['id'];
1122
+ if (id) {
1123
+ this.isEditMode = true;
1124
+ this.blogPostId = id;
1125
+ this.loadBlogPost(id);
1126
+ }
1127
+ else {
1128
+ this.isEditMode = false;
1129
+ this.buildForm();
1130
+ }
1131
+ }
1132
+ loadBlogPost(id) {
1133
+ this.blogPostService.get(id).subscribe(blogPost => {
1134
+ this.blogPost = blogPost;
1135
+ if (blogPost.coverImageMediaId) {
1136
+ this.coverImagePreview = `/api/cms-kit/media/${blogPost.coverImageMediaId}`;
1137
+ }
1138
+ this.buildForm();
1139
+ this.loadTags(id);
1140
+ });
1141
+ }
1142
+ loadTags(blogPostId) {
1143
+ // TODO: use the public service to load the tags
1144
+ this.restService
1145
+ .request({
1146
+ method: 'GET',
1147
+ url: `/api/cms-kit-public/tags/${this.BLOG_POST_ENTITY_TYPE}/${blogPostId}`,
1148
+ })
1149
+ .subscribe(tags => {
1150
+ if (tags && tags.length > 0) {
1151
+ this.tags = tags.map(t => t.name || '').join(', ');
1152
+ }
1153
+ });
1154
+ }
1155
+ buildForm() {
1156
+ const data = new FormPropData(this.injector, this.blogPost || {});
1157
+ const baseForm = generateFormFromProps(data);
1158
+ this.form = new FormGroup({
1159
+ ...baseForm.controls,
1160
+ content: new FormControl(this.blogPost?.content || ''),
1161
+ coverImageMediaId: new FormControl(this.blogPost?.coverImageMediaId || null),
1162
+ });
1163
+ prepareSlugFromControl(this.form, 'title', 'slug', this.destroyRef);
1164
+ // Check if tags feature is enabled for the blog
1165
+ const blogId = this.form.get('blogId')?.value || this.blogPost?.blogId;
1166
+ if (blogId) {
1167
+ this.checkTagsFeature(blogId);
1168
+ }
1169
+ // Listen for blog selection changes
1170
+ this.form
1171
+ .get('blogId')
1172
+ ?.valueChanges.pipe(takeUntilDestroyed(this.destroyRef))
1173
+ .subscribe(blogId => {
1174
+ if (blogId) {
1175
+ this.checkTagsFeature(blogId);
1176
+ }
1177
+ });
1178
+ }
1179
+ checkTagsFeature(blogId) {
1180
+ this.restService
1181
+ .request({
1182
+ method: 'GET',
1183
+ url: `/api/cms-kit/blogs/${blogId}/features/CmsKit.Tags`,
1184
+ })
1185
+ .subscribe(feature => {
1186
+ const { isEnabled } = feature || {};
1187
+ this.isTagsEnabled = isEnabled;
1188
+ });
1189
+ }
1190
+ onCoverImageChange(event) {
1191
+ const input = event.target;
1192
+ if (input.files && input.files[0]) {
1193
+ this.coverImageFile = input.files[0];
1194
+ const reader = new FileReader();
1195
+ reader.onload = (e) => {
1196
+ this.coverImagePreview = e.target.result;
1197
+ };
1198
+ reader.readAsDataURL(this.coverImageFile);
1199
+ }
1200
+ }
1201
+ removeCoverImage() {
1202
+ this.coverImageFile = null;
1203
+ this.coverImagePreview = null;
1204
+ this.form.patchValue({ coverImageMediaId: null });
1205
+ }
1206
+ uploadCoverImage() {
1207
+ if (!this.coverImageFile) {
1208
+ return of(this.form.value.coverImageMediaId || null);
1209
+ }
1210
+ const input = {
1211
+ name: this.coverImageFile.name,
1212
+ file: this.coverImageFile,
1213
+ };
1214
+ return this.mediaService.create('blogpost', input).pipe(tap(result => {
1215
+ this.form.patchValue({ coverImageMediaId: result.id });
1216
+ }), switchMap(result => of(result.id || null)));
1217
+ }
1218
+ setTags(blogPostId) {
1219
+ if (!this.tags || !this.tags.trim()) {
1220
+ return of(null);
1221
+ }
1222
+ const tagArray = this.tags
1223
+ .split(',')
1224
+ .map(t => t.trim())
1225
+ .filter(t => t.length > 0);
1226
+ if (tagArray.length === 0) {
1227
+ return of(null);
1228
+ }
1229
+ return this.entityTagService.setEntityTags({
1230
+ entityType: this.BLOG_POST_ENTITY_TYPE,
1231
+ entityId: blogPostId,
1232
+ tags: tagArray,
1233
+ });
1234
+ }
1235
+ executeSaveOperation(operation) {
1236
+ // First upload cover image if selected
1237
+ this.uploadCoverImage()
1238
+ .pipe(tap(coverImageMediaId => {
1239
+ if (coverImageMediaId) {
1240
+ this.form.patchValue({ coverImageMediaId });
1241
+ }
1242
+ }), switchMap(() => {
1243
+ if (this.isEditMode) {
1244
+ if (!this.blogPost || !this.blogPostId) {
1245
+ return of(null);
1246
+ }
1247
+ return this.blogPostFormService.update(this.blogPostId, this.form, this.blogPost);
1248
+ }
1249
+ switch (operation) {
1250
+ case 'save':
1251
+ case 'draft':
1252
+ return this.blogPostFormService.createAsDraft(this.form);
1253
+ case 'publish':
1254
+ return this.blogPostFormService.createAndPublish(this.form);
1255
+ case 'sendToReview':
1256
+ return this.blogPostFormService.createAndSendToReview(this.form);
1257
+ default:
1258
+ return of(null);
1259
+ }
1260
+ }), switchMap(result => {
1261
+ if (!result || !result.id) {
1262
+ return of(null);
1263
+ }
1264
+ // Set tags after blog post is created/updated
1265
+ return forkJoin([of(result), this.setTags(result.id)]);
1266
+ }))
1267
+ .subscribe();
1268
+ }
1269
+ saveAsDraft() {
1270
+ this.executeSaveOperation('draft');
1271
+ }
1272
+ publish() {
1273
+ this.executeSaveOperation('publish');
1274
+ }
1275
+ sendToReview() {
1276
+ this.executeSaveOperation('sendToReview');
1277
+ }
1278
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: BlogPostFormComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1279
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.9", type: BlogPostFormComponent, isStandalone: true, selector: "abp-blog-post-form", providers: [
1280
+ {
1281
+ provide: EXTENSIONS_IDENTIFIER,
1282
+ useValue: eCmsKitAdminComponents.BlogPostForm,
1283
+ },
1284
+ ], ngImport: i0, template: "<abp-page [title]=\"'CmsKit::BlogPosts' | abpLocalization\">\r\n <div class=\"card\">\r\n <div class=\"card-body\">\r\n @if (form && (!isEditMode || blogPost)) {\r\n <form [formGroup]=\"form\" (ngSubmit)=\"saveAsDraft()\" validateOnSubmit>\r\n <!-- Cover Image -->\r\n <div class=\"mb-3\">\r\n @if (coverImagePreview) {\r\n <div class=\"mb-2\">\r\n <img [src]=\"coverImagePreview\" height=\"120\" alt=\"Cover Image\" />\r\n <br />\r\n <button type=\"button\" class=\"btn btn-link p-0\" (click)=\"removeCoverImage()\">\r\n {{ 'CmsKit::RemoveCoverImage' | abpLocalization }}\r\n </button>\r\n <br />\r\n </div>\r\n }\r\n <label class=\"form-label\"\r\n >{{ 'CmsKit::CoverImage' | abpLocalization }}\r\n <span class=\"badge text-bg-light\">16:9</span></label\r\n >\r\n <input\r\n type=\"file\"\r\n class=\"form-control\"\r\n accept=\"image/*\"\r\n (change)=\"onCoverImageChange($event)\"\r\n />\r\n </div>\r\n\r\n <!-- Basic fields -->\r\n <abp-extensible-form [selectedRecord]=\"blogPost || {}\" />\r\n\r\n <!-- Content editor -->\r\n <div class=\"mt-3\">\r\n <label class=\"form-label\">{{ 'CmsKit::Content' | abpLocalization }}</label>\r\n <abp-toastui-editor formControlName=\"content\" />\r\n </div>\r\n </form>\r\n\r\n <!-- Tags Editor -->\r\n @if (isTagsEnabled) {\r\n <hr />\r\n <div class=\"mb-3\">\r\n <label class=\"form-label\">{{ 'CmsKit::Tags' | abpLocalization }}</label>\r\n <input\r\n type=\"text\"\r\n class=\"form-control\"\r\n [(ngModel)]=\"tags\"\r\n [ngModelOptions]=\"{ standalone: true }\"\r\n [placeholder]=\"'CmsKit::TagsHelpText' | abpLocalization\"\r\n />\r\n <div class=\"form-text\">{{ 'CmsKit::TagsHelpText' | abpLocalization }}</div>\r\n </div>\r\n }\r\n } @else {\r\n <div class=\"text-center\">\r\n <i class=\"fa fa-pulse fa-spinner\" aria-hidden=\"true\"></i>\r\n </div>\r\n }\r\n </div>\r\n <div class=\"card-footer\">\r\n <div class=\"d-flex justify-content-start gap-2\">\r\n <button class=\"btn btn-secondary\" (click)=\"saveAsDraft()\" [disabled]=\"form?.invalid\">\r\n {{ 'CmsKit::SaveAsDraft' | abpLocalization }}\r\n </button>\r\n @if (isEditMode) {\r\n <abp-button (click)=\"publish()\" [disabled]=\"form?.invalid\">\r\n {{ 'CmsKit::Publish' | abpLocalization }}\r\n </abp-button>\r\n } @else {\r\n <abp-button (click)=\"publish()\" [disabled]=\"form?.invalid\">\r\n {{ 'CmsKit::Publish' | abpLocalization }}\r\n </abp-button>\r\n <abp-button (click)=\"sendToReview()\" [disabled]=\"form?.invalid\">\r\n {{ 'CmsKit::SendToReviewToPublish' | abpLocalization }}\r\n </abp-button>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n</abp-page>\r\n", dependencies: [{ kind: "component", type: ButtonComponent, selector: "abp-button", inputs: ["buttonId", "buttonClass", "buttonType", "formName", "iconClass", "loading", "disabled", "attributes"], outputs: ["click", "focus", "blur", "abpClick", "abpFocus", "abpBlur"] }, { kind: "component", type: ExtensibleFormComponent, selector: "abp-extensible-form", inputs: ["selectedRecord"], exportAs: ["abpExtensibleForm"] }, { kind: "component", type: PageComponent, selector: "abp-page", inputs: ["title", "toolbar", "breadcrumb"] }, { kind: "component", type: ToastuiEditorComponent, selector: "abp-toastui-editor" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$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: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: NgxValidateCoreModule }, { kind: "directive", type: i2$1.ValidationGroupDirective, selector: "[formGroup],[formGroupName]", exportAs: ["validationGroup"] }, { kind: "directive", type: i2$1.ValidationDirective, selector: "[formControl],[formControlName]", exportAs: ["validationDirective"] }, { kind: "pipe", type: LocalizationPipe, name: "abpLocalization" }] }); }
1285
+ }
1286
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: BlogPostFormComponent, decorators: [{
1287
+ type: Component,
1288
+ args: [{ selector: 'abp-blog-post-form', providers: [
1289
+ {
1290
+ provide: EXTENSIONS_IDENTIFIER,
1291
+ useValue: eCmsKitAdminComponents.BlogPostForm,
1292
+ },
1293
+ ], imports: [
1294
+ ButtonComponent,
1295
+ ExtensibleFormComponent,
1296
+ PageComponent,
1297
+ ToastuiEditorComponent,
1298
+ LocalizationPipe,
1299
+ ReactiveFormsModule,
1300
+ FormsModule,
1301
+ CommonModule,
1302
+ NgxValidateCoreModule,
1303
+ ], template: "<abp-page [title]=\"'CmsKit::BlogPosts' | abpLocalization\">\r\n <div class=\"card\">\r\n <div class=\"card-body\">\r\n @if (form && (!isEditMode || blogPost)) {\r\n <form [formGroup]=\"form\" (ngSubmit)=\"saveAsDraft()\" validateOnSubmit>\r\n <!-- Cover Image -->\r\n <div class=\"mb-3\">\r\n @if (coverImagePreview) {\r\n <div class=\"mb-2\">\r\n <img [src]=\"coverImagePreview\" height=\"120\" alt=\"Cover Image\" />\r\n <br />\r\n <button type=\"button\" class=\"btn btn-link p-0\" (click)=\"removeCoverImage()\">\r\n {{ 'CmsKit::RemoveCoverImage' | abpLocalization }}\r\n </button>\r\n <br />\r\n </div>\r\n }\r\n <label class=\"form-label\"\r\n >{{ 'CmsKit::CoverImage' | abpLocalization }}\r\n <span class=\"badge text-bg-light\">16:9</span></label\r\n >\r\n <input\r\n type=\"file\"\r\n class=\"form-control\"\r\n accept=\"image/*\"\r\n (change)=\"onCoverImageChange($event)\"\r\n />\r\n </div>\r\n\r\n <!-- Basic fields -->\r\n <abp-extensible-form [selectedRecord]=\"blogPost || {}\" />\r\n\r\n <!-- Content editor -->\r\n <div class=\"mt-3\">\r\n <label class=\"form-label\">{{ 'CmsKit::Content' | abpLocalization }}</label>\r\n <abp-toastui-editor formControlName=\"content\" />\r\n </div>\r\n </form>\r\n\r\n <!-- Tags Editor -->\r\n @if (isTagsEnabled) {\r\n <hr />\r\n <div class=\"mb-3\">\r\n <label class=\"form-label\">{{ 'CmsKit::Tags' | abpLocalization }}</label>\r\n <input\r\n type=\"text\"\r\n class=\"form-control\"\r\n [(ngModel)]=\"tags\"\r\n [ngModelOptions]=\"{ standalone: true }\"\r\n [placeholder]=\"'CmsKit::TagsHelpText' | abpLocalization\"\r\n />\r\n <div class=\"form-text\">{{ 'CmsKit::TagsHelpText' | abpLocalization }}</div>\r\n </div>\r\n }\r\n } @else {\r\n <div class=\"text-center\">\r\n <i class=\"fa fa-pulse fa-spinner\" aria-hidden=\"true\"></i>\r\n </div>\r\n }\r\n </div>\r\n <div class=\"card-footer\">\r\n <div class=\"d-flex justify-content-start gap-2\">\r\n <button class=\"btn btn-secondary\" (click)=\"saveAsDraft()\" [disabled]=\"form?.invalid\">\r\n {{ 'CmsKit::SaveAsDraft' | abpLocalization }}\r\n </button>\r\n @if (isEditMode) {\r\n <abp-button (click)=\"publish()\" [disabled]=\"form?.invalid\">\r\n {{ 'CmsKit::Publish' | abpLocalization }}\r\n </abp-button>\r\n } @else {\r\n <abp-button (click)=\"publish()\" [disabled]=\"form?.invalid\">\r\n {{ 'CmsKit::Publish' | abpLocalization }}\r\n </abp-button>\r\n <abp-button (click)=\"sendToReview()\" [disabled]=\"form?.invalid\">\r\n {{ 'CmsKit::SendToReviewToPublish' | abpLocalization }}\r\n </abp-button>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n</abp-page>\r\n" }]
1304
+ }] });
1305
+
1306
+ // Constants
1307
+ const PAGE_LOOKUP_MAX_RESULT = 1000;
1308
+ const PAGE_SEARCH_MAX_RESULT = 100;
1309
+ const PAGE_SEARCH_DEBOUNCE_MS = 300;
1310
+ const TABS = {
1311
+ URL: 'url',
1312
+ PAGE: 'page',
1313
+ };
1314
+ class MenuItemModalComponent {
1315
+ constructor() {
1316
+ // Injected services
1317
+ this.menuItemService = inject(MenuItemAdminService);
1318
+ this.injector = inject(Injector);
1319
+ this.toasterService = inject(ToasterService);
1320
+ this.destroyRef = inject(DestroyRef);
1321
+ // Inputs/Outputs
1322
+ this.selected = input(...(ngDevMode ? [undefined, { debugName: "selected" }] : []));
1323
+ this.parentId = input(...(ngDevMode ? [undefined, { debugName: "parentId" }] : []));
1324
+ this.visible = input(true, ...(ngDevMode ? [{ debugName: "visible" }] : []));
1325
+ this.visibleChange = output();
1326
+ this.activeTab = TABS.URL;
1327
+ // Page selection state
1328
+ this.pages = [];
1329
+ this.selectedPage = null;
1330
+ this.pageSearchText = '';
1331
+ this.filteredPages = [];
1332
+ // Search subject for debouncing
1333
+ this.pageSearchSubject = new Subject();
1334
+ }
1335
+ get isPageSelected() {
1336
+ return !!this.form?.get('pageId')?.value;
1337
+ }
1338
+ ngOnInit() {
1339
+ this.setupPageSearch();
1340
+ this.initializeComponent();
1341
+ }
1342
+ /**
1343
+ * Sets up debounced page search functionality
1344
+ */
1345
+ setupPageSearch() {
1346
+ this.pageSearchSubject
1347
+ .pipe(debounceTime(PAGE_SEARCH_DEBOUNCE_MS), distinctUntilChanged(), switchMap(searchText => {
1348
+ if (!searchText?.trim()) {
1349
+ // Show all pages when search is cleared
1350
+ return this.menuItemService.getPageLookup({ maxResultCount: PAGE_LOOKUP_MAX_RESULT });
1351
+ }
1352
+ return this.menuItemService.getPageLookup({
1353
+ filter: searchText.trim(),
1354
+ maxResultCount: PAGE_SEARCH_MAX_RESULT,
1355
+ });
1356
+ }), takeUntilDestroyed(this.destroyRef))
1357
+ .subscribe({
1358
+ next: result => {
1359
+ this.filteredPages = result.items || [];
1360
+ },
1361
+ error: () => {
1362
+ this.filteredPages = [];
1363
+ },
1364
+ });
1365
+ }
1366
+ /**
1367
+ * Initializes the component based on create or edit mode
1368
+ */
1369
+ initializeComponent() {
1370
+ const selectedItem = this.selected();
1371
+ if (selectedItem?.id) {
1372
+ this.loadMenuItemForEdit(selectedItem.id);
1373
+ }
1374
+ else {
1375
+ this.loadPagesForCreate();
1376
+ this.buildForm();
1377
+ }
1378
+ }
1379
+ /**
1380
+ * Loads menu item data and pages for edit mode
1381
+ */
1382
+ loadMenuItemForEdit(menuItemId) {
1383
+ forkJoin({
1384
+ menuItem: this.menuItemService.get(menuItemId),
1385
+ pages: this.menuItemService.getPageLookup({ maxResultCount: PAGE_LOOKUP_MAX_RESULT }),
1386
+ })
1387
+ .pipe(takeUntilDestroyed(this.destroyRef))
1388
+ .subscribe({
1389
+ next: ({ menuItem, pages }) => {
1390
+ this.pages = pages.items || [];
1391
+ this.filteredPages = this.pages;
1392
+ this.buildForm(menuItem);
1393
+ this.initializePageSelection(menuItem);
1394
+ },
1395
+ error: () => {
1396
+ this.toasterService.error('AbpUi::ErrorMessage');
1397
+ },
1398
+ });
1399
+ }
1400
+ /**
1401
+ * Loads pages for create mode
1402
+ */
1403
+ loadPagesForCreate() {
1404
+ this.menuItemService
1405
+ .getPageLookup({ maxResultCount: PAGE_LOOKUP_MAX_RESULT })
1406
+ .pipe(takeUntilDestroyed(this.destroyRef))
1407
+ .subscribe({
1408
+ next: result => {
1409
+ this.pages = result.items || [];
1410
+ this.filteredPages = this.pages;
1411
+ },
1412
+ error: () => {
1413
+ this.toasterService.error('AbpUi::ErrorMessage');
1414
+ },
1415
+ });
1416
+ }
1417
+ /**
1418
+ * Initializes page selection when editing a menu item with a page
1419
+ */
1420
+ initializePageSelection(menuItem) {
1421
+ if (menuItem.pageId) {
1422
+ this.activeTab = TABS.PAGE;
1423
+ this.selectedPage = this.pages.find(p => p.id === menuItem.pageId) || null;
1424
+ const url = this.selectedPage
1425
+ ? this.generateUrlFromPage(this.selectedPage)
1426
+ : menuItem.url || '';
1427
+ this.form.patchValue({ pageId: menuItem.pageId, url }, { emitEvent: false });
1428
+ this.pageSearchText = this.selectedPage?.title || '';
1429
+ }
1430
+ else if (menuItem.url) {
1431
+ this.activeTab = TABS.URL;
1432
+ this.form.patchValue({ url: menuItem.url, pageId: null }, { emitEvent: false });
1433
+ }
1434
+ }
1435
+ /**
1436
+ * Generates a URL from a page's slug or title
1437
+ */
1438
+ generateUrlFromPage(page) {
1439
+ if (!page)
1440
+ return '';
1441
+ const source = page.slug || page.title;
1442
+ if (!source)
1443
+ return '';
1444
+ return '/' + dasharize(source);
1445
+ }
1446
+ /**
1447
+ * Handles page search input changes
1448
+ */
1449
+ onPageSearchChange(searchText) {
1450
+ this.pageSearchText = searchText;
1451
+ if (!searchText?.trim()) {
1452
+ this.filteredPages = this.pages;
1453
+ return;
1454
+ }
1455
+ this.pageSearchSubject.next(searchText);
1456
+ }
1457
+ /**
1458
+ * Handles dropdown open event
1459
+ */
1460
+ onDropdownOpen() {
1461
+ if (!this.pageSearchText?.trim()) {
1462
+ this.filteredPages = this.pages;
1463
+ }
1464
+ }
1465
+ /**
1466
+ * Handles page selection from dropdown
1467
+ */
1468
+ selectPage(page) {
1469
+ if (!page)
1470
+ return;
1471
+ this.selectedPage = page;
1472
+ const url = this.generateUrlFromPage(page);
1473
+ this.form.patchValue({ pageId: page.id, url }, { emitEvent: false });
1474
+ this.pageSearchText = page.title || '';
1475
+ }
1476
+ /**
1477
+ * Clears the selected page
1478
+ */
1479
+ clearPageSelection() {
1480
+ this.form.patchValue({ pageId: null }, { emitEvent: false });
1481
+ this.selectedPage = null;
1482
+ this.pageSearchText = '';
1483
+ this.filteredPages = this.pages;
1484
+ }
1485
+ /**
1486
+ * Builds the reactive form for menu item creation/editing
1487
+ */
1488
+ buildForm(menuItem) {
1489
+ const data = new FormPropData(this.injector, menuItem || {});
1490
+ const baseForm = generateFormFromProps(data);
1491
+ const parentId = this.parentId() || menuItem?.parentId || null;
1492
+ this.form = new FormGroup({
1493
+ ...baseForm.controls,
1494
+ url: new FormControl(menuItem?.url || ''),
1495
+ pageId: new FormControl(menuItem?.pageId || null),
1496
+ parentId: new FormControl(parentId),
1497
+ });
1498
+ this.loadAvailableOrder(parentId, menuItem?.id);
1499
+ }
1500
+ /**
1501
+ * Loads the available menu order for new menu items
1502
+ */
1503
+ loadAvailableOrder(parentId, menuItemId) {
1504
+ if (menuItemId)
1505
+ return; // Only needed for new items
1506
+ const order$ = parentId
1507
+ ? this.menuItemService.getAvailableMenuOrder(parentId)
1508
+ : this.menuItemService.getAvailableMenuOrder();
1509
+ order$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe({
1510
+ next: order => {
1511
+ this.form.patchValue({ order });
1512
+ },
1513
+ });
1514
+ }
1515
+ /**
1516
+ * Handles modal visibility changes
1517
+ */
1518
+ onVisibleChange(visible, refresh = false) {
1519
+ this.visibleChange.emit({ visible, refresh });
1520
+ }
1521
+ /**
1522
+ * Handles tab changes
1523
+ */
1524
+ onTabChange(activeId) {
1525
+ this.activeTab = activeId;
1526
+ }
1527
+ /**
1528
+ * Handles URL input changes - clears page selection if URL is manually entered
1529
+ */
1530
+ onUrlInput() {
1531
+ const urlValue = this.form.get('url')?.value;
1532
+ if (urlValue && this.form.get('pageId')?.value) {
1533
+ this.clearPageSelection();
1534
+ if (this.activeTab === TABS.PAGE) {
1535
+ this.activeTab = TABS.URL;
1536
+ }
1537
+ }
1538
+ }
1539
+ /**
1540
+ * Saves the menu item (create or update)
1541
+ */
1542
+ save() {
1543
+ if (!this.form.valid) {
1544
+ return;
1545
+ }
1546
+ const formValue = this.prepareFormValue();
1547
+ const selectedItem = this.selected();
1548
+ const isEditMode = !!selectedItem?.id;
1549
+ const observable$ = isEditMode
1550
+ ? this.updateMenuItem(selectedItem.id, formValue, selectedItem)
1551
+ : this.createMenuItem(formValue);
1552
+ observable$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe({
1553
+ next: () => {
1554
+ this.onVisibleChange(false, true);
1555
+ this.toasterService.success('AbpUi::SavedSuccessfully');
1556
+ },
1557
+ error: () => {
1558
+ this.toasterService.error('AbpUi::ErrorMessage');
1559
+ },
1560
+ });
1561
+ }
1562
+ /**
1563
+ * Prepares form value ensuring mutual exclusivity between pageId and url
1564
+ */
1565
+ prepareFormValue() {
1566
+ const formValue = { ...this.form.value };
1567
+ if (formValue.pageId) {
1568
+ // If pageId is set, generate URL from the page
1569
+ const selectedPage = this.pages.find(p => p.id === formValue.pageId);
1570
+ if (selectedPage) {
1571
+ formValue.url = this.generateUrlFromPage(selectedPage);
1572
+ }
1573
+ }
1574
+ else if (formValue.url) {
1575
+ // If URL is manually entered, ensure pageId is cleared
1576
+ formValue.pageId = null;
1577
+ }
1578
+ // Clean up undefined values
1579
+ return {
1580
+ ...formValue,
1581
+ url: formValue.url || undefined,
1582
+ pageId: formValue.pageId || undefined,
1583
+ };
1584
+ }
1585
+ /**
1586
+ * Creates a new menu item
1587
+ */
1588
+ createMenuItem(formValue) {
1589
+ const createInput = formValue;
1590
+ return this.menuItemService.create(createInput);
1591
+ }
1592
+ /**
1593
+ * Updates an existing menu item
1594
+ */
1595
+ updateMenuItem(id, formValue, selectedItem) {
1596
+ const updateInput = {
1597
+ ...formValue,
1598
+ concurrencyStamp: selectedItem.concurrencyStamp,
1599
+ };
1600
+ return this.menuItemService.update(id, updateInput);
1601
+ }
1602
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: MenuItemModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1603
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.9", type: MenuItemModalComponent, isStandalone: true, selector: "abp-menu-item-modal", inputs: { selected: { classPropertyName: "selected", publicName: "selected", isSignal: true, isRequired: false, transformFunction: null }, parentId: { classPropertyName: "parentId", publicName: "parentId", isSignal: true, isRequired: false, transformFunction: null }, visible: { classPropertyName: "visible", publicName: "visible", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { visibleChange: "visibleChange" }, ngImport: i0, template: "<abp-modal [visible]=\"visible()\" (visibleChange)=\"onVisibleChange($event)\">\r\n <ng-template #abpHeader>\r\n <h3>\r\n @if (selected()?.id) {\r\n {{ 'AbpUi::Edit' | abpLocalization }}\r\n } @else {\r\n {{ 'AbpUi::New' | abpLocalization }}\r\n }\r\n </h3>\r\n </ng-template>\r\n\r\n <ng-template #abpBody>\r\n @if (form) {\r\n <form [formGroup]=\"form\" (ngSubmit)=\"save()\" validateOnSubmit>\r\n <ul\r\n ngbNav\r\n #nav=\"ngbNav\"\r\n class=\"nav-tabs\"\r\n [(activeId)]=\"activeTab\"\r\n (activeIdChange)=\"onTabChange($event)\"\r\n >\r\n <li ngbNavItem=\"url\">\r\n <a ngbNavLink>{{ 'CmsKit::Url' | abpLocalization }}</a>\r\n <ng-template ngbNavContent>\r\n <div class=\"mt-3\">\r\n <label class=\"form-label\">{{ 'CmsKit::Url' | abpLocalization }}</label>\r\n <input\r\n type=\"text\"\r\n class=\"form-control\"\r\n formControlName=\"url\"\r\n [disabled]=\"isPageSelected\"\r\n (input)=\"onUrlInput()\"\r\n />\r\n </div>\r\n </ng-template>\r\n </li>\r\n <li ngbNavItem=\"page\">\r\n <a ngbNavLink>{{ 'CmsKit::Page' | abpLocalization }}</a>\r\n <ng-template ngbNavContent>\r\n <div class=\"mt-3\">\r\n <label class=\"form-label\">{{ 'CmsKit::Page' | abpLocalization }}</label>\r\n <div\r\n class=\"position-relative\"\r\n ngbDropdown\r\n #pageDropdown=\"ngbDropdown\"\r\n display=\"static\"\r\n (openChange)=\"onDropdownOpen()\"\r\n >\r\n <button\r\n class=\"form-select form-control text-start d-flex align-items-center justify-content-between\"\r\n type=\"button\"\r\n id=\"pageSelectDropdown\"\r\n ngbDropdownToggle\r\n [class.text-muted]=\"!selectedPage\"\r\n >\r\n <span>{{ selectedPage?.title || ('CmsKit::Page' | abpLocalization) }}</span>\r\n </button>\r\n <div\r\n class=\"dropdown-menu w-100\"\r\n ngbDropdownMenu\r\n aria-labelledby=\"pageSelectDropdown\"\r\n style=\"max-height: 300px; overflow-y: auto\"\r\n >\r\n <div class=\"p-2 border-bottom\">\r\n <input\r\n type=\"text\"\r\n class=\"form-control form-control-sm\"\r\n [(ngModel)]=\"pageSearchText\"\r\n [ngModelOptions]=\"{ standalone: true }\"\r\n (input)=\"onPageSearchChange($any($event.target).value)\"\r\n (click)=\"$event.stopPropagation()\"\r\n placeholder=\"{{ 'AbpUi::Search' | abpLocalization }}\"\r\n autocomplete=\"off\"\r\n />\r\n </div>\r\n @if (filteredPages.length > 0) {\r\n @for (page of filteredPages; track page.id) {\r\n <button\r\n type=\"button\"\r\n class=\"dropdown-item\"\r\n (click)=\"selectPage(page); pageDropdown.close()\"\r\n >\r\n {{ page.title }}\r\n </button>\r\n }\r\n } @else if (pageSearchText && pageSearchText.length > 0) {\r\n <div class=\"dropdown-item text-muted\">\r\n {{ 'No results found' }}\r\n </div>\r\n } @else if (pages.length === 0) {\r\n <div class=\"dropdown-item text-muted\">\r\n {{ 'No pages found' }}\r\n </div>\r\n }\r\n @if (selectedPage) {\r\n <div class=\"dropdown-divider\"></div>\r\n <button\r\n type=\"button\"\r\n class=\"dropdown-item text-danger\"\r\n (click)=\"clearPageSelection(); pageDropdown.close()\"\r\n >\r\n {{ 'AbpUi::Clear' | abpLocalization }}\r\n </button>\r\n }\r\n </div>\r\n <input [formControlName]=\"'pageId'\" type=\"hidden\" />\r\n </div>\r\n </div>\r\n </ng-template>\r\n </li>\r\n </ul>\r\n <div class=\"mt-2 fade-in-top\" [ngbNavOutlet]=\"nav\"></div>\r\n <hr />\r\n <abp-extensible-form [selectedRecord]=\"selected() || {}\" />\r\n </form>\r\n }\r\n </ng-template>\r\n\r\n <ng-template #abpFooter>\r\n <button type=\"button\" class=\"btn btn-outline-primary\" abpClose>\r\n {{ 'AbpUi::Cancel' | abpLocalization }}\r\n </button>\r\n <abp-button (click)=\"save()\" [disabled]=\"form?.invalid\">\r\n {{ 'AbpUi::Save' | abpLocalization }}\r\n </abp-button>\r\n </ng-template>\r\n</abp-modal>\r\n", styles: [".dropdown-toggle:after{display:none!important}\n"], dependencies: [{ kind: "component", type: ExtensibleFormComponent, selector: "abp-extensible-form", inputs: ["selectedRecord"], exportAs: ["abpExtensibleForm"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$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: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: NgxValidateCoreModule }, { kind: "directive", type: i2$1.ValidationGroupDirective, selector: "[formGroup],[formGroupName]", exportAs: ["validationGroup"] }, { kind: "directive", type: i2$1.ValidationDirective, selector: "[formControl],[formControlName]", exportAs: ["validationDirective"] }, { kind: "component", type: ModalComponent, selector: "abp-modal", inputs: ["visible", "busy", "options", "suppressUnsavedChangesWarning"], outputs: ["visibleChange", "init", "appear", "disappear"] }, { kind: "directive", type: ModalCloseDirective, selector: "[abpClose]" }, { kind: "component", type: ButtonComponent, selector: "abp-button", inputs: ["buttonId", "buttonClass", "buttonType", "formName", "iconClass", "loading", "disabled", "attributes"], outputs: ["click", "focus", "blur", "abpClick", "abpFocus", "abpBlur"] }, { kind: "ngmodule", type: NgbNavModule }, { kind: "directive", type: i3.NgbNavContent, selector: "ng-template[ngbNavContent]" }, { kind: "directive", type: i3.NgbNav, selector: "[ngbNav]", inputs: ["activeId", "animation", "destroyOnHide", "orientation", "roles", "keyboard"], outputs: ["activeIdChange", "shown", "hidden", "navChange"], exportAs: ["ngbNav"] }, { kind: "directive", type: i3.NgbNavItem, selector: "[ngbNavItem]", inputs: ["destroyOnHide", "disabled", "domId", "ngbNavItem"], outputs: ["shown", "hidden"], exportAs: ["ngbNavItem"] }, { kind: "directive", type: i3.NgbNavItemRole, selector: "[ngbNavItem]:not(ng-container)" }, { kind: "directive", type: i3.NgbNavLink, selector: "a[ngbNavLink]" }, { kind: "directive", type: i3.NgbNavLinkBase, selector: "[ngbNavLink]" }, { kind: "component", type: i3.NgbNavOutlet, selector: "[ngbNavOutlet]", inputs: ["paneRole", "ngbNavOutlet"] }, { kind: "ngmodule", type: NgbDropdownModule }, { kind: "directive", type: i3.NgbDropdown, selector: "[ngbDropdown]", inputs: ["autoClose", "dropdownClass", "open", "placement", "popperOptions", "container", "display"], outputs: ["openChange"], exportAs: ["ngbDropdown"] }, { kind: "directive", type: i3.NgbDropdownToggle, selector: "[ngbDropdownToggle]" }, { kind: "directive", type: i3.NgbDropdownMenu, selector: "[ngbDropdownMenu]" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "pipe", type: LocalizationPipe, name: "abpLocalization" }] }); }
1604
+ }
1605
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: MenuItemModalComponent, decorators: [{
1606
+ type: Component,
1607
+ args: [{ selector: 'abp-menu-item-modal', imports: [
1608
+ ExtensibleFormComponent,
1609
+ LocalizationPipe,
1610
+ ReactiveFormsModule,
1611
+ CommonModule,
1612
+ NgxValidateCoreModule,
1613
+ ModalComponent,
1614
+ ModalCloseDirective,
1615
+ ButtonComponent,
1616
+ NgbNavModule,
1617
+ NgbDropdownModule,
1618
+ FormsModule,
1619
+ ], template: "<abp-modal [visible]=\"visible()\" (visibleChange)=\"onVisibleChange($event)\">\r\n <ng-template #abpHeader>\r\n <h3>\r\n @if (selected()?.id) {\r\n {{ 'AbpUi::Edit' | abpLocalization }}\r\n } @else {\r\n {{ 'AbpUi::New' | abpLocalization }}\r\n }\r\n </h3>\r\n </ng-template>\r\n\r\n <ng-template #abpBody>\r\n @if (form) {\r\n <form [formGroup]=\"form\" (ngSubmit)=\"save()\" validateOnSubmit>\r\n <ul\r\n ngbNav\r\n #nav=\"ngbNav\"\r\n class=\"nav-tabs\"\r\n [(activeId)]=\"activeTab\"\r\n (activeIdChange)=\"onTabChange($event)\"\r\n >\r\n <li ngbNavItem=\"url\">\r\n <a ngbNavLink>{{ 'CmsKit::Url' | abpLocalization }}</a>\r\n <ng-template ngbNavContent>\r\n <div class=\"mt-3\">\r\n <label class=\"form-label\">{{ 'CmsKit::Url' | abpLocalization }}</label>\r\n <input\r\n type=\"text\"\r\n class=\"form-control\"\r\n formControlName=\"url\"\r\n [disabled]=\"isPageSelected\"\r\n (input)=\"onUrlInput()\"\r\n />\r\n </div>\r\n </ng-template>\r\n </li>\r\n <li ngbNavItem=\"page\">\r\n <a ngbNavLink>{{ 'CmsKit::Page' | abpLocalization }}</a>\r\n <ng-template ngbNavContent>\r\n <div class=\"mt-3\">\r\n <label class=\"form-label\">{{ 'CmsKit::Page' | abpLocalization }}</label>\r\n <div\r\n class=\"position-relative\"\r\n ngbDropdown\r\n #pageDropdown=\"ngbDropdown\"\r\n display=\"static\"\r\n (openChange)=\"onDropdownOpen()\"\r\n >\r\n <button\r\n class=\"form-select form-control text-start d-flex align-items-center justify-content-between\"\r\n type=\"button\"\r\n id=\"pageSelectDropdown\"\r\n ngbDropdownToggle\r\n [class.text-muted]=\"!selectedPage\"\r\n >\r\n <span>{{ selectedPage?.title || ('CmsKit::Page' | abpLocalization) }}</span>\r\n </button>\r\n <div\r\n class=\"dropdown-menu w-100\"\r\n ngbDropdownMenu\r\n aria-labelledby=\"pageSelectDropdown\"\r\n style=\"max-height: 300px; overflow-y: auto\"\r\n >\r\n <div class=\"p-2 border-bottom\">\r\n <input\r\n type=\"text\"\r\n class=\"form-control form-control-sm\"\r\n [(ngModel)]=\"pageSearchText\"\r\n [ngModelOptions]=\"{ standalone: true }\"\r\n (input)=\"onPageSearchChange($any($event.target).value)\"\r\n (click)=\"$event.stopPropagation()\"\r\n placeholder=\"{{ 'AbpUi::Search' | abpLocalization }}\"\r\n autocomplete=\"off\"\r\n />\r\n </div>\r\n @if (filteredPages.length > 0) {\r\n @for (page of filteredPages; track page.id) {\r\n <button\r\n type=\"button\"\r\n class=\"dropdown-item\"\r\n (click)=\"selectPage(page); pageDropdown.close()\"\r\n >\r\n {{ page.title }}\r\n </button>\r\n }\r\n } @else if (pageSearchText && pageSearchText.length > 0) {\r\n <div class=\"dropdown-item text-muted\">\r\n {{ 'No results found' }}\r\n </div>\r\n } @else if (pages.length === 0) {\r\n <div class=\"dropdown-item text-muted\">\r\n {{ 'No pages found' }}\r\n </div>\r\n }\r\n @if (selectedPage) {\r\n <div class=\"dropdown-divider\"></div>\r\n <button\r\n type=\"button\"\r\n class=\"dropdown-item text-danger\"\r\n (click)=\"clearPageSelection(); pageDropdown.close()\"\r\n >\r\n {{ 'AbpUi::Clear' | abpLocalization }}\r\n </button>\r\n }\r\n </div>\r\n <input [formControlName]=\"'pageId'\" type=\"hidden\" />\r\n </div>\r\n </div>\r\n </ng-template>\r\n </li>\r\n </ul>\r\n <div class=\"mt-2 fade-in-top\" [ngbNavOutlet]=\"nav\"></div>\r\n <hr />\r\n <abp-extensible-form [selectedRecord]=\"selected() || {}\" />\r\n </form>\r\n }\r\n </ng-template>\r\n\r\n <ng-template #abpFooter>\r\n <button type=\"button\" class=\"btn btn-outline-primary\" abpClose>\r\n {{ 'AbpUi::Cancel' | abpLocalization }}\r\n </button>\r\n <abp-button (click)=\"save()\" [disabled]=\"form?.invalid\">\r\n {{ 'AbpUi::Save' | abpLocalization }}\r\n </abp-button>\r\n </ng-template>\r\n</abp-modal>\r\n", styles: [".dropdown-toggle:after{display:none!important}\n"] }]
1620
+ }], propDecorators: { selected: [{ type: i0.Input, args: [{ isSignal: true, alias: "selected", required: false }] }], parentId: [{ type: i0.Input, args: [{ isSignal: true, alias: "parentId", required: false }] }], visible: [{ type: i0.Input, args: [{ isSignal: true, alias: "visible", required: false }] }], visibleChange: [{ type: i0.Output, args: ["visibleChange"] }] } });
1621
+
1622
+ class MenuItemListComponent {
1623
+ constructor() {
1624
+ this.menuItemService = inject(MenuItemAdminService);
1625
+ this.confirmationService = inject(ConfirmationService);
1626
+ this.nodes = [];
1627
+ this.selectedNode = null;
1628
+ this.expandedKeys = [];
1629
+ this.draggable = true;
1630
+ this.isModalVisible = false;
1631
+ this.selectedMenuItem = null;
1632
+ this.parentId = null;
1633
+ this.beforeDrop = (event) => {
1634
+ return of(true);
1635
+ };
1636
+ }
1637
+ ngOnInit() {
1638
+ this.loadMenuItems();
1639
+ }
1640
+ loadMenuItems() {
1641
+ this.menuItemService.getList().subscribe(result => {
1642
+ if (result.items && result.items.length > 0) {
1643
+ this.nodes = this.buildTreeNodes(result.items);
1644
+ // Expand all nodes by default
1645
+ this.expandedKeys = this.nodes.map(n => n.key);
1646
+ }
1647
+ else {
1648
+ this.nodes = [];
1649
+ }
1650
+ });
1651
+ }
1652
+ buildTreeNodes(items) {
1653
+ const nodeMap = new Map();
1654
+ const rootNodes = [];
1655
+ // First pass: create all nodes
1656
+ items.forEach(item => {
1657
+ const node = {
1658
+ key: item.id,
1659
+ title: item.displayName || '',
1660
+ entity: item,
1661
+ children: [],
1662
+ isLeaf: false,
1663
+ };
1664
+ nodeMap.set(item.id, node);
1665
+ });
1666
+ // Second pass: build tree structure
1667
+ items.forEach(item => {
1668
+ const node = nodeMap.get(item.id);
1669
+ if (item.parentId) {
1670
+ const parent = nodeMap.get(item.parentId);
1671
+ if (parent) {
1672
+ parent.children.push(node);
1673
+ parent.isLeaf = false;
1674
+ }
1675
+ else {
1676
+ rootNodes.push(node);
1677
+ }
1678
+ }
1679
+ else {
1680
+ rootNodes.push(node);
1681
+ }
1682
+ });
1683
+ // Sort by order
1684
+ const sortByOrder = (nodes) => {
1685
+ nodes.sort((a, b) => (a.entity.order || 0) - (b.entity.order || 0));
1686
+ nodes.forEach(node => {
1687
+ if (node.children && node.children.length > 0) {
1688
+ sortByOrder(node.children);
1689
+ }
1690
+ });
1691
+ };
1692
+ sortByOrder(rootNodes);
1693
+ return rootNodes;
1694
+ }
1695
+ onSelectedNodeChange(node) {
1696
+ this.selectedNode = node?.entity || null;
1697
+ }
1698
+ onDrop(event) {
1699
+ const node = event.dragNode?.origin?.entity;
1700
+ if (!node) {
1701
+ return;
1702
+ }
1703
+ const newParentId = event.dragNode?.parent?.key === '0' ? null : event.dragNode?.parent?.key;
1704
+ const position = event.dragNode?.pos || 0;
1705
+ const parentNodeName = !newParentId || newParentId === '0'
1706
+ ? 'Root'
1707
+ : event.dragNode?.parent?.origin?.entity?.displayName || 'Root';
1708
+ this.confirmationService
1709
+ .warn('CmsKit::MenuItemMoveConfirmMessage', 'AbpUi::AreYouSure', {
1710
+ messageLocalizationParams: [node.displayName || '', parentNodeName],
1711
+ yesText: 'AbpUi::Yes',
1712
+ cancelText: 'AbpUi::Cancel',
1713
+ })
1714
+ .subscribe((status) => {
1715
+ if (status === Confirmation.Status.confirm) {
1716
+ const input = {
1717
+ newParentId: newParentId === '0' ? null : newParentId,
1718
+ position: position,
1719
+ };
1720
+ this.menuItemService.moveMenuItem(node.id, input).subscribe({
1721
+ next: () => {
1722
+ this.loadMenuItems();
1723
+ },
1724
+ error: () => {
1725
+ // Reload to rollback
1726
+ this.loadMenuItems();
1727
+ },
1728
+ });
1729
+ }
1730
+ else {
1731
+ // Reload to rollback
1732
+ this.loadMenuItems();
1733
+ }
1734
+ });
1735
+ }
1736
+ add() {
1737
+ this.selectedMenuItem = null;
1738
+ this.parentId = null;
1739
+ this.isModalVisible = true;
1740
+ }
1741
+ addSubMenuItem(parentId) {
1742
+ this.selectedMenuItem = null;
1743
+ this.parentId = parentId || null;
1744
+ this.isModalVisible = true;
1745
+ }
1746
+ edit(id) {
1747
+ this.menuItemService.get(id).subscribe(menuItem => {
1748
+ this.selectedMenuItem = menuItem;
1749
+ this.parentId = null;
1750
+ this.isModalVisible = true;
1751
+ });
1752
+ }
1753
+ onVisibleModalChange(visibilityChange) {
1754
+ if (visibilityChange.visible) {
1755
+ return;
1756
+ }
1757
+ if (visibilityChange.refresh) {
1758
+ this.loadMenuItems();
1759
+ }
1760
+ this.selectedMenuItem = null;
1761
+ this.parentId = null;
1762
+ this.isModalVisible = false;
1763
+ }
1764
+ delete(id, displayName) {
1765
+ this.confirmationService
1766
+ .warn('CmsKit::MenuItemDeletionConfirmationMessage', 'AbpUi::AreYouSure', {
1767
+ messageLocalizationParams: [displayName || ''],
1768
+ yesText: 'AbpUi::Yes',
1769
+ cancelText: 'AbpUi::Cancel',
1770
+ })
1771
+ .subscribe((status) => {
1772
+ if (status === Confirmation.Status.confirm) {
1773
+ this.menuItemService.delete(id).subscribe({
1774
+ next: () => {
1775
+ this.loadMenuItems();
1776
+ },
1777
+ });
1778
+ }
1779
+ });
1780
+ }
1781
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: MenuItemListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1782
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.9", type: MenuItemListComponent, isStandalone: true, selector: "abp-menu-item-list", providers: [
1783
+ ListService,
1784
+ {
1785
+ provide: EXTENSIONS_IDENTIFIER,
1786
+ useValue: eCmsKitAdminComponents.Menus,
1787
+ },
1788
+ ], ngImport: i0, template: "<abp-page [title]=\"'CmsKit::MenuItems' | abpLocalization\" [toolbar]=\"nodes\">\r\n <div class=\"card\">\r\n <div class=\"card-body\">\r\n @if (nodes.length > 0) {\r\n <abp-tree\r\n [nodes]=\"nodes\"\r\n [draggable]=\"draggable\"\r\n [expandedKeys]=\"expandedKeys\"\r\n [selectedNode]=\"selectedNode\"\r\n (selectedNodeChange)=\"onSelectedNodeChange($event)\"\r\n [beforeDrop]=\"beforeDrop\"\r\n (dropOver)=\"onDrop($event)\"\r\n >\r\n <ng-template #menu let-node>\r\n <button\r\n class=\"dropdown-item\"\r\n (click)=\"edit(node.key)\"\r\n *abpPermission=\"'CmsKit.Menus.Update'\"\r\n >\r\n <i class=\"fa fa-pencil me-2\"></i>\r\n {{ 'AbpUi::Edit' | abpLocalization }}\r\n </button>\r\n <button\r\n class=\"dropdown-item\"\r\n (click)=\"addSubMenuItem(node.key)\"\r\n *abpPermission=\"'CmsKit.Menus.Create'\"\r\n >\r\n <i class=\"fa fa-plus me-2\"></i>\r\n {{ 'CmsKit::AddSubMenuItem' | abpLocalization }}\r\n </button>\r\n <button\r\n class=\"dropdown-item\"\r\n (click)=\"delete(node.key, node.title)\"\r\n *abpPermission=\"'CmsKit.Menus.Delete'\"\r\n >\r\n <i class=\"fa fa-remove me-2\"></i>\r\n {{ 'AbpUi::Delete' | abpLocalization }}\r\n </button>\r\n </ng-template>\r\n </abp-tree>\r\n } @else {\r\n <div class=\"text-muted text-center\">\r\n {{ 'CmsKit::NoMenuItems' | abpLocalization }}\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n</abp-page>\r\n\r\n@if (isModalVisible) {\r\n <abp-menu-item-modal\r\n [selected]=\"selectedMenuItem || undefined\"\r\n [parentId]=\"parentId\"\r\n (visibleChange)=\"onVisibleModalChange($event)\"\r\n />\r\n}\r\n", dependencies: [{ kind: "component", type: PageComponent, selector: "abp-page", inputs: ["title", "toolbar", "breadcrumb"] }, { kind: "component", type: TreeComponent, selector: "abp-tree", inputs: ["noAnimation", "draggable", "checkable", "checkStrictly", "checkedKeys", "nodes", "expandedKeys", "selectedNode", "changeCheckboxWithNode", "isNodeSelected", "beforeDrop"], outputs: ["checkedKeysChange", "expandedKeysChange", "selectedNodeChange", "dropOver", "nzExpandChange"] }, { kind: "ngmodule", type: CommonModule }, { kind: "component", type: MenuItemModalComponent, selector: "abp-menu-item-modal", inputs: ["selected", "parentId", "visible"], outputs: ["visibleChange"] }, { kind: "directive", type: PermissionDirective, selector: "[abpPermission]", inputs: ["abpPermission", "abpPermissionRunChangeDetection"] }, { kind: "pipe", type: LocalizationPipe, name: "abpLocalization" }] }); }
1789
+ }
1790
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: MenuItemListComponent, decorators: [{
1791
+ type: Component,
1792
+ args: [{ selector: 'abp-menu-item-list', imports: [
1793
+ PageComponent,
1794
+ TreeComponent,
1795
+ LocalizationPipe,
1796
+ CommonModule,
1797
+ MenuItemModalComponent,
1798
+ PermissionDirective,
1799
+ ], providers: [
1800
+ ListService,
1801
+ {
1802
+ provide: EXTENSIONS_IDENTIFIER,
1803
+ useValue: eCmsKitAdminComponents.Menus,
1804
+ },
1805
+ ], template: "<abp-page [title]=\"'CmsKit::MenuItems' | abpLocalization\" [toolbar]=\"nodes\">\r\n <div class=\"card\">\r\n <div class=\"card-body\">\r\n @if (nodes.length > 0) {\r\n <abp-tree\r\n [nodes]=\"nodes\"\r\n [draggable]=\"draggable\"\r\n [expandedKeys]=\"expandedKeys\"\r\n [selectedNode]=\"selectedNode\"\r\n (selectedNodeChange)=\"onSelectedNodeChange($event)\"\r\n [beforeDrop]=\"beforeDrop\"\r\n (dropOver)=\"onDrop($event)\"\r\n >\r\n <ng-template #menu let-node>\r\n <button\r\n class=\"dropdown-item\"\r\n (click)=\"edit(node.key)\"\r\n *abpPermission=\"'CmsKit.Menus.Update'\"\r\n >\r\n <i class=\"fa fa-pencil me-2\"></i>\r\n {{ 'AbpUi::Edit' | abpLocalization }}\r\n </button>\r\n <button\r\n class=\"dropdown-item\"\r\n (click)=\"addSubMenuItem(node.key)\"\r\n *abpPermission=\"'CmsKit.Menus.Create'\"\r\n >\r\n <i class=\"fa fa-plus me-2\"></i>\r\n {{ 'CmsKit::AddSubMenuItem' | abpLocalization }}\r\n </button>\r\n <button\r\n class=\"dropdown-item\"\r\n (click)=\"delete(node.key, node.title)\"\r\n *abpPermission=\"'CmsKit.Menus.Delete'\"\r\n >\r\n <i class=\"fa fa-remove me-2\"></i>\r\n {{ 'AbpUi::Delete' | abpLocalization }}\r\n </button>\r\n </ng-template>\r\n </abp-tree>\r\n } @else {\r\n <div class=\"text-muted text-center\">\r\n {{ 'CmsKit::NoMenuItems' | abpLocalization }}\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n</abp-page>\r\n\r\n@if (isModalVisible) {\r\n <abp-menu-item-modal\r\n [selected]=\"selectedMenuItem || undefined\"\r\n [parentId]=\"parentId\"\r\n (visibleChange)=\"onVisibleModalChange($event)\"\r\n />\r\n}\r\n" }]
1806
+ }] });
1807
+
1808
+ class CmsSettingsComponent {
1809
+ constructor() {
1810
+ this.commentAdminService = inject(CommentAdminService);
1811
+ this.configState = inject(ConfigStateService);
1812
+ this.toaster = inject(ToasterService);
1813
+ this.commentApprovalControl = new FormControl(false);
1814
+ }
1815
+ ngOnInit() {
1816
+ const isCommentApprovalEnabled = this.configState.getSetting(CMS_KIT_COMMENTS_REQUIRE_APPROVEMENT).toLowerCase() === 'true';
1817
+ this.commentApprovalControl.setValue(isCommentApprovalEnabled);
1818
+ }
1819
+ submit() {
1820
+ this.commentAdminService
1821
+ .updateSettings({ commentRequireApprovement: this.commentApprovalControl.value })
1822
+ .pipe(finalize(() => {
1823
+ this.configState.refreshAppState().subscribe();
1824
+ }))
1825
+ .subscribe(() => this.toaster.success('AbpUi::SavedSuccessfully', null));
1826
+ }
1827
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: CmsSettingsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1828
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.9", type: CmsSettingsComponent, isStandalone: true, selector: "abp-cms-settings", ngImport: i0, template: "<div id=\"CmsSettingsForm\" class=\"row\">\r\n <div class=\"col-md-12\">\r\n <ul ngbNav #nav=\"ngbNav\" class=\"nav-tabs\">\r\n <!-- Comments -->\r\n <li ngbNavItem>\r\n <a ngbNavLink>{{ 'CmsKit::CmsKit:Comment' | abpLocalization }}</a>\r\n <ng-template ngbNavContent>\r\n <div class=\"abp-md-form\">\r\n <div (keyup.enter)=\"submit()\">\r\n <div class=\"mt-3\">\r\n <div class=\"form-check mb-2\">\r\n <input\r\n class=\"form-check-input\"\r\n [formControl]=\"commentApprovalControl\"\r\n type=\"checkbox\"\r\n id=\"EnableCommentApproval\"\r\n [checked]=\"commentApprovalControl.value\"\r\n (input)=\"commentApprovalControl.setValue($event.target.checked)\"\r\n />\r\n <label class=\"form-check-label\" for=\"EnableCommentApproval\">\r\n {{ 'CmsKit::CmsKitCommentOptions:RequireApprovement' | abpLocalization }}\r\n </label>\r\n <br />\r\n <small class=\"form-text text-muted\">{{\r\n 'CmsKit::CmsKitCommentOptions:RequireApprovementDescription' | abpLocalization\r\n }}</small>\r\n </div>\r\n </div>\r\n <hr class=\"my-3\" />\r\n <div>\r\n <abp-button (click)=\"submit()\" iconClass=\"fa fa-save\" [loading]=\"loading\">\r\n {{ 'AbpAccount::Save' | abpLocalization }}\r\n </abp-button>\r\n </div>\r\n </div>\r\n </div>\r\n </ng-template>\r\n </li>\r\n </ul>\r\n <div [ngbNavOutlet]=\"nav\"></div>\r\n </div>\r\n</div>\r\n", dependencies: [{ kind: "directive", type: NgbNav, selector: "[ngbNav]", inputs: ["activeId", "animation", "destroyOnHide", "orientation", "roles", "keyboard"], outputs: ["activeIdChange", "shown", "hidden", "navChange"], exportAs: ["ngbNav"] }, { kind: "directive", type: NgbNavItem, selector: "[ngbNavItem]", inputs: ["destroyOnHide", "disabled", "domId", "ngbNavItem"], outputs: ["shown", "hidden"], exportAs: ["ngbNavItem"] }, { kind: "directive", type: NgbNavItemRole, selector: "[ngbNavItem]:not(ng-container)" }, { kind: "directive", type: NgbNavLink, selector: "a[ngbNavLink]" }, { kind: "directive", type: NgbNavLinkBase, selector: "[ngbNavLink]" }, { kind: "directive", type: NgbNavContent, selector: "ng-template[ngbNavContent]" }, { kind: "component", type: NgbNavOutlet, selector: "[ngbNavOutlet]", inputs: ["paneRole", "ngbNavOutlet"] }, { kind: "component", type: ButtonComponent, selector: "abp-button", inputs: ["buttonId", "buttonClass", "buttonType", "formName", "iconClass", "loading", "disabled", "attributes"], outputs: ["click", "focus", "blur", "abpClick", "abpFocus", "abpBlur"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "pipe", type: LocalizationPipe, name: "abpLocalization" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1829
+ }
1830
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: CmsSettingsComponent, decorators: [{
1831
+ type: Component,
1832
+ args: [{ selector: 'abp-cms-settings', changeDetection: ChangeDetectionStrategy.OnPush, imports: [
1833
+ NgbNav,
1834
+ NgbNavItem,
1835
+ NgbNavItemRole,
1836
+ NgbNavLink,
1837
+ NgbNavLinkBase,
1838
+ NgbNavContent,
1839
+ NgbNavOutlet,
1840
+ LocalizationPipe,
1841
+ ButtonComponent,
1842
+ ReactiveFormsModule,
1843
+ ], template: "<div id=\"CmsSettingsForm\" class=\"row\">\r\n <div class=\"col-md-12\">\r\n <ul ngbNav #nav=\"ngbNav\" class=\"nav-tabs\">\r\n <!-- Comments -->\r\n <li ngbNavItem>\r\n <a ngbNavLink>{{ 'CmsKit::CmsKit:Comment' | abpLocalization }}</a>\r\n <ng-template ngbNavContent>\r\n <div class=\"abp-md-form\">\r\n <div (keyup.enter)=\"submit()\">\r\n <div class=\"mt-3\">\r\n <div class=\"form-check mb-2\">\r\n <input\r\n class=\"form-check-input\"\r\n [formControl]=\"commentApprovalControl\"\r\n type=\"checkbox\"\r\n id=\"EnableCommentApproval\"\r\n [checked]=\"commentApprovalControl.value\"\r\n (input)=\"commentApprovalControl.setValue($event.target.checked)\"\r\n />\r\n <label class=\"form-check-label\" for=\"EnableCommentApproval\">\r\n {{ 'CmsKit::CmsKitCommentOptions:RequireApprovement' | abpLocalization }}\r\n </label>\r\n <br />\r\n <small class=\"form-text text-muted\">{{\r\n 'CmsKit::CmsKitCommentOptions:RequireApprovementDescription' | abpLocalization\r\n }}</small>\r\n </div>\r\n </div>\r\n <hr class=\"my-3\" />\r\n <div>\r\n <abp-button (click)=\"submit()\" iconClass=\"fa fa-save\" [loading]=\"loading\">\r\n {{ 'AbpAccount::Save' | abpLocalization }}\r\n </abp-button>\r\n </div>\r\n </div>\r\n </div>\r\n </ng-template>\r\n </li>\r\n </ul>\r\n <div [ngbNavOutlet]=\"nav\"></div>\r\n </div>\r\n</div>\r\n" }]
1844
+ }] });
1845
+
1846
+ class GlobalResourcesComponent {
1847
+ constructor() {
1848
+ this.globalResourceService = inject(GlobalResourceAdminService);
1849
+ this.toasterService = inject(ToasterService);
1850
+ this.destroyRef = inject(DestroyRef);
1851
+ this.activeTab = 'script';
1852
+ }
1853
+ ngOnInit() {
1854
+ this.buildForm();
1855
+ this.loadGlobalResources();
1856
+ }
1857
+ buildForm() {
1858
+ this.form = new FormGroup({
1859
+ script: new FormControl(''),
1860
+ style: new FormControl(''),
1861
+ });
1862
+ }
1863
+ loadGlobalResources() {
1864
+ this.globalResourceService
1865
+ .get()
1866
+ .pipe(takeUntilDestroyed(this.destroyRef))
1867
+ .subscribe({
1868
+ next: (result) => {
1869
+ this.form.patchValue({
1870
+ script: result.scriptContent || '',
1871
+ style: result.styleContent || '',
1872
+ });
1873
+ },
1874
+ error: () => {
1875
+ this.toasterService.error('AbpUi::ErrorMessage');
1876
+ },
1877
+ });
1878
+ }
1879
+ onTabChange(activeId) {
1880
+ this.activeTab = activeId;
1881
+ }
1882
+ save() {
1883
+ if (!this.form.valid) {
1884
+ return;
1885
+ }
1886
+ const formValue = this.form.value;
1887
+ const input = {
1888
+ script: formValue.script || '',
1889
+ style: formValue.style || '',
1890
+ };
1891
+ this.globalResourceService
1892
+ .setGlobalResources(input)
1893
+ .pipe(takeUntilDestroyed(this.destroyRef))
1894
+ .subscribe({
1895
+ next: () => {
1896
+ this.toasterService.success('AbpUi::SavedSuccessfully');
1897
+ },
1898
+ error: () => {
1899
+ this.toasterService.error('AbpUi::ErrorMessage');
1900
+ },
1901
+ });
1902
+ }
1903
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: GlobalResourcesComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1904
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.9", type: GlobalResourcesComponent, isStandalone: true, selector: "abp-global-resources", ngImport: i0, template: "<abp-page [title]=\"'CmsKit::GlobalResources' | abpLocalization\">\r\n <form [formGroup]=\"form\" (ngSubmit)=\"save()\" validateOnSubmit>\r\n <div class=\"card\">\r\n <div class=\"card-body\">\r\n <ul\r\n ngbNav\r\n #nav=\"ngbNav\"\r\n class=\"nav-tabs\"\r\n [(activeId)]=\"activeTab\"\r\n (activeIdChange)=\"onTabChange($event)\"\r\n >\r\n <li ngbNavItem=\"script\">\r\n <a ngbNavLink>{{ 'CmsKit::Script' | abpLocalization }}</a>\r\n <ng-template ngbNavContent>\r\n <div class=\"mt-3\">\r\n <abp-codemirror-editor formControlName=\"script\" />\r\n </div>\r\n </ng-template>\r\n </li>\r\n <li ngbNavItem=\"style\">\r\n <a ngbNavLink>{{ 'CmsKit::Style' | abpLocalization }}</a>\r\n <ng-template ngbNavContent>\r\n <div class=\"mt-3\">\r\n <abp-codemirror-editor formControlName=\"style\" />\r\n </div>\r\n </ng-template>\r\n </li>\r\n </ul>\r\n <div class=\"mt-2 fade-in-top\" [ngbNavOutlet]=\"nav\"></div>\r\n </div>\r\n <div class=\"card-footer\">\r\n <!-- *abpPermission=\"'CmsKit.GlobalResources.Update'\" -->\r\n <abp-button type=\"submit\" [disabled]=\"form?.invalid\" (click)=\"save()\">\r\n {{ 'AbpUi::Save' | abpLocalization }}\r\n </abp-button>\r\n </div>\r\n </div>\r\n </form>\r\n</abp-page>\r\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: NgxValidateCoreModule }, { kind: "directive", type: i2$1.ValidationGroupDirective, selector: "[formGroup],[formGroupName]", exportAs: ["validationGroup"] }, { kind: "directive", type: i2$1.ValidationDirective, selector: "[formControl],[formControlName]", exportAs: ["validationDirective"] }, { kind: "ngmodule", type: NgbNavModule }, { kind: "directive", type: i3.NgbNavContent, selector: "ng-template[ngbNavContent]" }, { kind: "directive", type: i3.NgbNav, selector: "[ngbNav]", inputs: ["activeId", "animation", "destroyOnHide", "orientation", "roles", "keyboard"], outputs: ["activeIdChange", "shown", "hidden", "navChange"], exportAs: ["ngbNav"] }, { kind: "directive", type: i3.NgbNavItem, selector: "[ngbNavItem]", inputs: ["destroyOnHide", "disabled", "domId", "ngbNavItem"], outputs: ["shown", "hidden"], exportAs: ["ngbNavItem"] }, { kind: "directive", type: i3.NgbNavItemRole, selector: "[ngbNavItem]:not(ng-container)" }, { kind: "directive", type: i3.NgbNavLink, selector: "a[ngbNavLink]" }, { kind: "directive", type: i3.NgbNavLinkBase, selector: "[ngbNavLink]" }, { kind: "component", type: i3.NgbNavOutlet, selector: "[ngbNavOutlet]", inputs: ["paneRole", "ngbNavOutlet"] }, { kind: "component", type: CodeMirrorEditorComponent, selector: "abp-codemirror-editor" }, { kind: "component", type: PageComponent, selector: "abp-page", inputs: ["title", "toolbar", "breadcrumb"] }, { kind: "component", type: ButtonComponent, selector: "abp-button", inputs: ["buttonId", "buttonClass", "buttonType", "formName", "iconClass", "loading", "disabled", "attributes"], outputs: ["click", "focus", "blur", "abpClick", "abpFocus", "abpBlur"] }, { kind: "pipe", type: LocalizationPipe, name: "abpLocalization" }] }); }
1905
+ }
1906
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: GlobalResourcesComponent, decorators: [{
1907
+ type: Component,
1908
+ args: [{ selector: 'abp-global-resources', imports: [
1909
+ CommonModule,
1910
+ ReactiveFormsModule,
1911
+ NgxValidateCoreModule,
1912
+ NgbNavModule,
1913
+ CodeMirrorEditorComponent,
1914
+ LocalizationPipe,
1915
+ PageComponent,
1916
+ ButtonComponent,
1917
+ ], template: "<abp-page [title]=\"'CmsKit::GlobalResources' | abpLocalization\">\r\n <form [formGroup]=\"form\" (ngSubmit)=\"save()\" validateOnSubmit>\r\n <div class=\"card\">\r\n <div class=\"card-body\">\r\n <ul\r\n ngbNav\r\n #nav=\"ngbNav\"\r\n class=\"nav-tabs\"\r\n [(activeId)]=\"activeTab\"\r\n (activeIdChange)=\"onTabChange($event)\"\r\n >\r\n <li ngbNavItem=\"script\">\r\n <a ngbNavLink>{{ 'CmsKit::Script' | abpLocalization }}</a>\r\n <ng-template ngbNavContent>\r\n <div class=\"mt-3\">\r\n <abp-codemirror-editor formControlName=\"script\" />\r\n </div>\r\n </ng-template>\r\n </li>\r\n <li ngbNavItem=\"style\">\r\n <a ngbNavLink>{{ 'CmsKit::Style' | abpLocalization }}</a>\r\n <ng-template ngbNavContent>\r\n <div class=\"mt-3\">\r\n <abp-codemirror-editor formControlName=\"style\" />\r\n </div>\r\n </ng-template>\r\n </li>\r\n </ul>\r\n <div class=\"mt-2 fade-in-top\" [ngbNavOutlet]=\"nav\"></div>\r\n </div>\r\n <div class=\"card-footer\">\r\n <!-- *abpPermission=\"'CmsKit.GlobalResources.Update'\" -->\r\n <abp-button type=\"submit\" [disabled]=\"form?.invalid\" (click)=\"save()\">\r\n {{ 'AbpUi::Save' | abpLocalization }}\r\n </abp-button>\r\n </div>\r\n </div>\r\n </form>\r\n</abp-page>\r\n" }]
1918
+ }] });
1919
+
1920
+ const DEFAULT_COMMENT_ENTITY_ACTIONS = EntityAction.createMany([
1921
+ {
1922
+ text: 'CmsKit::Details',
1923
+ action: data => {
1924
+ const router = data.getInjected(Router);
1925
+ router.navigate(['/cms/comments', data.record.id]);
1926
+ },
1927
+ },
1928
+ {
1929
+ text: 'CmsKit::Delete',
1930
+ action: data => {
1931
+ const commentEntityService = data.getInjected(CommentEntityService);
1932
+ const list = data.getInjected((ListService));
1933
+ commentEntityService.delete(data.record.id, list);
1934
+ },
1935
+ permission: 'CmsKit.Comments.Delete',
1936
+ },
1937
+ {
1938
+ text: 'CmsKit::Approve',
1939
+ action: data => {
1940
+ const commentEntityService = data.getInjected(CommentEntityService);
1941
+ const list = data.getInjected((ListService));
1942
+ commentEntityService.updateApprovalStatus(data.record.id, true, list);
1943
+ },
1944
+ visible: data => {
1945
+ const commentEntityService = data.getInjected(CommentEntityService);
1946
+ return commentEntityService.requireApprovement && data.record.isApproved === false;
1947
+ },
1948
+ },
1949
+ {
1950
+ text: 'CmsKit::Disapproved',
1951
+ action: data => {
1952
+ const commentEntityService = data.getInjected(CommentEntityService);
1953
+ const list = data.getInjected((ListService));
1954
+ commentEntityService.updateApprovalStatus(data.record.id, false, list);
1955
+ },
1956
+ visible: data => {
1957
+ const commentEntityService = data.getInjected(CommentEntityService);
1958
+ return (commentEntityService.requireApprovement &&
1959
+ (data.record.isApproved || data.record.isApproved === null));
1960
+ },
1961
+ },
1962
+ ]);
1963
+
1964
+ const DEFAULT_COMMENT_ENTITY_PROPS = EntityProp.createMany([
1965
+ {
1966
+ type: "string" /* ePropType.String */,
1967
+ name: 'userName',
1968
+ displayName: 'CmsKit::Username',
1969
+ sortable: false,
1970
+ columnWidth: 150,
1971
+ valueResolver: data => {
1972
+ const userName = data.record.author.userName;
1973
+ return of(userName);
1974
+ },
1975
+ },
1976
+ {
1977
+ type: "string" /* ePropType.String */,
1978
+ name: 'entityType',
1979
+ displayName: 'CmsKit::EntityType',
1980
+ sortable: false,
1981
+ columnWidth: 200,
1982
+ },
1983
+ {
1984
+ type: "string" /* ePropType.String */,
1985
+ name: 'url',
1986
+ displayName: 'CmsKit::URL',
1987
+ sortable: false,
1988
+ valueResolver: data => {
1989
+ const url = data.record.url;
1990
+ if (url) {
1991
+ return of(`<a href="${url}#comment-${data.record.id}" target="_blank"><i class="fa fa-location-arrow"></i></a>`);
1992
+ }
1993
+ return of('');
1994
+ },
1995
+ },
1996
+ {
1997
+ type: "string" /* ePropType.String */,
1998
+ name: 'text',
1999
+ displayName: 'CmsKit::Text',
2000
+ sortable: false,
2001
+ valueResolver: data => {
2002
+ const text = data.record.text || '';
2003
+ const maxChars = 64;
2004
+ if (text.length > maxChars) {
2005
+ return of(text.substring(0, maxChars) + '...');
2006
+ }
2007
+ return of(text);
2008
+ },
2009
+ },
2010
+ {
2011
+ type: "string" /* ePropType.String */,
2012
+ name: 'isApproved',
2013
+ displayName: 'CmsKit::ApproveState',
2014
+ sortable: false,
2015
+ columnWidth: 100,
2016
+ columnVisible: getInjected => {
2017
+ const commentEntityService = getInjected(CommentEntityService);
2018
+ return commentEntityService.requireApprovement;
2019
+ },
2020
+ valueResolver: data => {
2021
+ const isApproved = data.record.isApproved;
2022
+ if (isApproved || isApproved === null) {
2023
+ return of('<div class="text-success"><i class="fa fa-check" aria-hidden="true"></i></div>');
2024
+ }
2025
+ return of('<div class="text-danger"><i class="fa fa-times" aria-hidden="true"></i></div>');
2026
+ },
2027
+ },
2028
+ {
2029
+ type: "date" /* ePropType.Date */,
2030
+ name: 'creationTime',
2031
+ displayName: 'CmsKit::CreationTime',
2032
+ sortable: true,
2033
+ columnWidth: 200,
2034
+ },
2035
+ ]);
2036
+
2037
+ const DEFAULT_TAG_ENTITY_ACTIONS = EntityAction.createMany([
2038
+ {
2039
+ text: 'AbpUi::Edit',
2040
+ action: data => {
2041
+ const component = data.getInjected(TagListComponent);
2042
+ component.edit(data.record.id);
2043
+ },
2044
+ permission: 'CmsKit.Tags.Update',
2045
+ },
2046
+ {
2047
+ text: 'AbpUi::Delete',
2048
+ action: data => {
2049
+ const component = data.getInjected(TagListComponent);
2050
+ const { id, name } = data.record;
2051
+ component.delete(id, name);
2052
+ },
2053
+ permission: 'CmsKit.Tags.Delete',
2054
+ },
2055
+ ]);
2056
+
2057
+ const DEFAULT_TAG_ENTITY_PROPS = EntityProp.createMany([
2058
+ {
2059
+ type: "string" /* ePropType.String */,
2060
+ name: 'entityType',
2061
+ displayName: 'CmsKit::EntityType',
2062
+ sortable: true,
2063
+ columnWidth: 200,
2064
+ },
2065
+ {
2066
+ type: "string" /* ePropType.String */,
2067
+ name: 'name',
2068
+ displayName: 'CmsKit::Name',
2069
+ sortable: true,
2070
+ columnWidth: 250,
2071
+ },
2072
+ ]);
2073
+
2074
+ const DEFAULT_TAG_TOOLBAR_ACTIONS = ToolbarAction.createMany([
2075
+ {
2076
+ text: 'CmsKit::NewTag',
2077
+ action: data => {
2078
+ const component = data.getInjected(TagListComponent);
2079
+ component.add();
2080
+ },
2081
+ permission: 'CmsKit.Tags.Create',
2082
+ icon: 'fa fa-plus',
2083
+ },
2084
+ ]);
2085
+
2086
+ const DEFAULT_TAG_CREATE_FORM_PROPS = FormProp.createMany([
2087
+ {
2088
+ type: "enum" /* ePropType.Enum */,
2089
+ name: 'entityType',
2090
+ displayName: 'CmsKit::EntityType',
2091
+ id: 'entityType',
2092
+ validators: () => [Validators.required],
2093
+ options: data => {
2094
+ const tagService = data.getInjected(TagAdminService);
2095
+ return tagService.getTagDefinitions().pipe(map((definitions) => definitions.map(def => ({
2096
+ key: def.displayName || def.entityType || '',
2097
+ value: def.entityType || '',
2098
+ }))));
2099
+ },
2100
+ },
2101
+ {
2102
+ type: "string" /* ePropType.String */,
2103
+ name: 'name',
2104
+ displayName: 'CmsKit::Name',
2105
+ id: 'name',
2106
+ validators: () => [Validators.required],
2107
+ },
2108
+ ]);
2109
+ const DEFAULT_TAG_EDIT_FORM_PROPS = DEFAULT_TAG_CREATE_FORM_PROPS.filter(prop => prop.name !== 'entityType');
2110
+
2111
+ const DEFAULT_PAGE_ENTITY_ACTIONS = EntityAction.createMany([
2112
+ {
2113
+ text: 'AbpUi::Edit',
2114
+ action: data => {
2115
+ const router = data.getInjected(Router);
2116
+ router.navigate(['/cms/pages/update', data.record.id]);
2117
+ },
2118
+ permission: 'CmsKit.Pages.Update',
2119
+ },
2120
+ {
2121
+ text: 'AbpUi::Delete',
2122
+ action: data => {
2123
+ const component = data.getInjected(PageListComponent);
2124
+ component.delete(data.record.id);
2125
+ },
2126
+ permission: 'CmsKit.Pages.Delete',
2127
+ },
2128
+ {
2129
+ text: 'CmsKit::SetAsHomePage',
2130
+ action: data => {
2131
+ const component = data.getInjected(PageListComponent);
2132
+ const { id, isHomePage } = data.record;
2133
+ component.setAsHomePage(id, isHomePage);
2134
+ },
2135
+ permission: 'CmsKit.Pages.SetAsHomePage',
2136
+ },
2137
+ ]);
2138
+
2139
+ const DEFAULT_PAGE_ENTITY_PROPS = EntityProp.createMany([
2140
+ {
2141
+ type: "string" /* ePropType.String */,
2142
+ name: 'title',
2143
+ displayName: 'CmsKit::Title',
2144
+ sortable: true,
2145
+ columnWidth: 200,
2146
+ },
2147
+ {
2148
+ type: "string" /* ePropType.String */,
2149
+ name: 'slug',
2150
+ displayName: 'CmsKit::Slug',
2151
+ sortable: true,
2152
+ columnWidth: 200,
2153
+ },
2154
+ {
2155
+ type: "string" /* ePropType.String */,
2156
+ name: 'status',
2157
+ displayName: 'CmsKit::Status',
2158
+ sortable: true,
2159
+ columnWidth: 120,
2160
+ valueResolver: data => {
2161
+ const localization = data.getInjected(LocalizationService);
2162
+ let result = '';
2163
+ switch (data.record.status) {
2164
+ case PageStatus.Draft:
2165
+ result = localization.instant('CmsKit::Enum:PageStatus:0');
2166
+ break;
2167
+ case PageStatus.Publish:
2168
+ result = localization.instant('CmsKit::Enum:PageStatus:1');
2169
+ break;
2170
+ }
2171
+ return of(result);
2172
+ },
2173
+ },
2174
+ {
2175
+ type: "boolean" /* ePropType.Boolean */,
2176
+ name: 'isHomePage',
2177
+ displayName: 'CmsKit::IsHomePage',
2178
+ sortable: true,
2179
+ columnWidth: 120,
2180
+ },
2181
+ {
2182
+ type: "date" /* ePropType.Date */,
2183
+ name: 'creationTime',
2184
+ displayName: 'AbpIdentity::CreationTime',
2185
+ sortable: true,
2186
+ columnWidth: 200,
2187
+ },
2188
+ {
2189
+ type: "date" /* ePropType.Date */,
2190
+ name: 'lastModificationTime',
2191
+ displayName: 'AbpIdentity::LastModificationTime',
2192
+ sortable: true,
2193
+ columnWidth: 200,
2194
+ },
2195
+ ]);
2196
+
2197
+ const DEFAULT_PAGE_TOOLBAR_ACTIONS = ToolbarAction.createMany([
2198
+ {
2199
+ text: 'CmsKit::NewPage',
2200
+ action: data => {
2201
+ const router = data.getInjected(Router);
2202
+ router.navigate(['/cms/pages/create']);
2203
+ },
2204
+ permission: 'CmsKit.Pages.Create',
2205
+ icon: 'fa fa-plus',
2206
+ },
2207
+ ]);
2208
+
2209
+ const LAYOUT_CONSTANTS = {
2210
+ Account: "account" /* eLayoutType.account */,
2211
+ Public: 'public',
2212
+ Empty: "empty" /* eLayoutType.empty */,
2213
+ Application: "application" /* eLayoutType.application */,
2214
+ };
2215
+
2216
+ const DEFAULT_PAGE_CREATE_FORM_PROPS = FormProp.createMany([
2217
+ {
2218
+ type: "string" /* ePropType.String */,
2219
+ name: 'title',
2220
+ displayName: 'CmsKit::Title',
2221
+ id: 'title',
2222
+ validators: () => [Validators.required],
2223
+ },
2224
+ {
2225
+ type: "string" /* ePropType.String */,
2226
+ name: 'slug',
2227
+ displayName: 'CmsKit::Slug',
2228
+ id: 'slug',
2229
+ validators: () => [Validators.required],
2230
+ tooltip: {
2231
+ text: 'CmsKit::PageSlugInformation',
2232
+ },
2233
+ },
2234
+ {
2235
+ type: "enum" /* ePropType.Enum */,
2236
+ name: 'layoutName',
2237
+ displayName: 'CmsKit::SelectLayout',
2238
+ id: 'layoutName',
2239
+ options: () => of(Object.values(LAYOUT_CONSTANTS).map(layout => ({
2240
+ key: layout,
2241
+ value: layout.toUpperCase(),
2242
+ }))),
2243
+ validators: () => [Validators.required],
2244
+ },
2245
+ {
2246
+ type: "enum" /* ePropType.Enum */,
2247
+ name: 'status',
2248
+ displayName: 'CmsKit::Status',
2249
+ id: 'status',
2250
+ options: () => of(pageStatusOptions),
2251
+ validators: () => [Validators.required],
2252
+ },
2253
+ ]);
2254
+ const DEFAULT_PAGE_EDIT_FORM_PROPS = DEFAULT_PAGE_CREATE_FORM_PROPS;
2255
+
2256
+ const DEFAULT_BLOG_ENTITY_ACTIONS = EntityAction.createMany([
2257
+ {
2258
+ text: 'CmsKit::Features',
2259
+ action: data => {
2260
+ const component = data.getInjected(BlogListComponent);
2261
+ component.openFeatures(data.record.id);
2262
+ },
2263
+ permission: 'CmsKit.Blogs.Features',
2264
+ },
2265
+ {
2266
+ text: 'AbpUi::Edit',
2267
+ action: data => {
2268
+ const component = data.getInjected(BlogListComponent);
2269
+ component.edit(data.record.id);
2270
+ },
2271
+ permission: 'CmsKit.Blogs.Update',
2272
+ },
2273
+ {
2274
+ text: 'AbpUi::Delete',
2275
+ action: data => {
2276
+ const component = data.getInjected(BlogListComponent);
2277
+ component.delete(data.record.id, data.record.name);
2278
+ },
2279
+ permission: 'CmsKit.Blogs.Delete',
2280
+ },
2281
+ ]);
2282
+
2283
+ const DEFAULT_BLOG_ENTITY_PROPS = EntityProp.createMany([
2284
+ {
2285
+ type: "string" /* ePropType.String */,
2286
+ name: 'name',
2287
+ displayName: 'CmsKit::Name',
2288
+ sortable: true,
2289
+ columnWidth: 250,
2290
+ },
2291
+ {
2292
+ type: "string" /* ePropType.String */,
2293
+ name: 'slug',
2294
+ displayName: 'CmsKit::Slug',
2295
+ sortable: true,
2296
+ columnWidth: 250,
2297
+ },
2298
+ ]);
2299
+
2300
+ const DEFAULT_BLOG_TOOLBAR_ACTIONS = ToolbarAction.createMany([
2301
+ {
2302
+ text: 'CmsKit::NewBlog',
2303
+ action: data => {
2304
+ const component = data.getInjected(BlogListComponent);
2305
+ component.add();
2306
+ },
2307
+ permission: 'CmsKit.Blogs.Create',
2308
+ icon: 'fa fa-plus',
2309
+ },
2310
+ ]);
2311
+
2312
+ const DEFAULT_BLOG_CREATE_FORM_PROPS = FormProp.createMany([
2313
+ {
2314
+ type: "string" /* ePropType.String */,
2315
+ name: 'name',
2316
+ displayName: 'CmsKit::Name',
2317
+ id: 'name',
2318
+ validators: () => [Validators.required],
2319
+ },
2320
+ {
2321
+ type: "string" /* ePropType.String */,
2322
+ name: 'slug',
2323
+ displayName: 'CmsKit::Slug',
2324
+ id: 'slug',
2325
+ validators: () => [Validators.required],
2326
+ tooltip: {
2327
+ text: 'CmsKit::BlogSlugInformation',
2328
+ // params: ['blogs'],
2329
+ },
2330
+ },
2331
+ ]);
2332
+ const DEFAULT_BLOG_EDIT_FORM_PROPS = DEFAULT_BLOG_CREATE_FORM_PROPS;
2333
+
2334
+ const DEFAULT_BLOG_POST_ENTITY_ACTIONS = EntityAction.createMany([
2335
+ {
2336
+ text: 'AbpUi::Edit',
2337
+ action: data => {
2338
+ const router = data.getInjected(Router);
2339
+ router.navigate(['/cms/blog-posts/update', data.record.id]);
2340
+ },
2341
+ permission: 'CmsKit.BlogPosts.Update',
2342
+ },
2343
+ {
2344
+ text: 'AbpUi::Delete',
2345
+ action: data => {
2346
+ const component = data.getInjected(BlogPostListComponent);
2347
+ component.delete(data.record.id, data.record.title);
2348
+ },
2349
+ permission: 'CmsKit.BlogPosts.Delete',
2350
+ },
2351
+ ]);
2352
+
2353
+ const DEFAULT_BLOG_POST_ENTITY_PROPS = EntityProp.createMany([
2354
+ {
2355
+ type: "string" /* ePropType.String */,
2356
+ name: 'blogName',
2357
+ displayName: 'CmsKit::Blog',
2358
+ sortable: true,
2359
+ columnWidth: 150,
2360
+ },
2361
+ {
2362
+ type: "string" /* ePropType.String */,
2363
+ name: 'title',
2364
+ displayName: 'CmsKit::Title',
2365
+ sortable: true,
2366
+ columnWidth: 200,
2367
+ },
2368
+ {
2369
+ type: "string" /* ePropType.String */,
2370
+ name: 'slug',
2371
+ displayName: 'CmsKit::Slug',
2372
+ sortable: true,
2373
+ columnWidth: 200,
2374
+ },
2375
+ {
2376
+ type: "string" /* ePropType.String */,
2377
+ name: 'status',
2378
+ displayName: 'CmsKit::Status',
2379
+ sortable: true,
2380
+ columnWidth: 120,
2381
+ valueResolver: data => {
2382
+ const localization = data.getInjected(LocalizationService);
2383
+ let result = '';
2384
+ switch (data.record.status) {
2385
+ case BlogPostStatus.Draft:
2386
+ result = localization.instant('CmsKit::CmsKit.BlogPost.Status.0');
2387
+ break;
2388
+ case BlogPostStatus.Published:
2389
+ result = localization.instant('CmsKit::CmsKit.BlogPost.Status.1');
2390
+ break;
2391
+ case BlogPostStatus.WaitingForReview:
2392
+ result = localization.instant('CmsKit::CmsKit.BlogPost.Status.2');
2393
+ break;
2394
+ }
2395
+ return of(result);
2396
+ },
2397
+ },
2398
+ {
2399
+ type: "date" /* ePropType.Date */,
2400
+ name: 'creationTime',
2401
+ displayName: 'AbpIdentity::CreationTime',
2402
+ sortable: true,
2403
+ columnWidth: 200,
2404
+ },
2405
+ {
2406
+ type: "date" /* ePropType.Date */,
2407
+ name: 'lastModificationTime',
2408
+ displayName: 'AbpIdentity::LastModificationTime',
2409
+ sortable: true,
2410
+ columnWidth: 200,
2411
+ },
2412
+ ]);
2413
+
2414
+ const DEFAULT_BLOG_POST_TOOLBAR_ACTIONS = ToolbarAction.createMany([
2415
+ {
2416
+ text: 'CmsKit::NewBlogPost',
2417
+ action: data => {
2418
+ const router = data.getInjected(Router);
2419
+ router.navigate(['/cms/blog-posts/create']);
2420
+ },
2421
+ permission: 'CmsKit.BlogPosts.Create',
2422
+ icon: 'fa fa-plus',
2423
+ },
2424
+ ]);
2425
+
2426
+ const DEFAULT_BLOG_POST_CREATE_FORM_PROPS = FormProp.createMany([
2427
+ {
2428
+ type: "enum" /* ePropType.Enum */,
2429
+ name: 'blogId',
2430
+ displayName: 'CmsKit::Blog',
2431
+ id: 'blogId',
2432
+ options: data => {
2433
+ const blogService = data.getInjected(BlogAdminService);
2434
+ return blogService.getList({ maxResultCount: 1000 }).pipe(map(result => result.items.map(blog => ({
2435
+ key: blog.name || '',
2436
+ value: blog.id || '',
2437
+ }))));
2438
+ },
2439
+ validators: () => [Validators.required],
2440
+ },
2441
+ {
2442
+ type: "string" /* ePropType.String */,
2443
+ name: 'title',
2444
+ displayName: 'CmsKit::Title',
2445
+ id: 'title',
2446
+ validators: () => [Validators.required],
2447
+ },
2448
+ {
2449
+ type: "string" /* ePropType.String */,
2450
+ name: 'slug',
2451
+ displayName: 'CmsKit::Slug',
2452
+ id: 'slug',
2453
+ validators: () => [Validators.required],
2454
+ tooltip: {
2455
+ text: 'CmsKit::BlogPostSlugInformation',
2456
+ },
2457
+ },
2458
+ {
2459
+ type: "string" /* ePropType.String */,
2460
+ name: 'shortDescription',
2461
+ displayName: 'CmsKit::ShortDescription',
2462
+ id: 'shortDescription',
2463
+ },
2464
+ ]);
2465
+ const DEFAULT_BLOG_POST_EDIT_FORM_PROPS = DEFAULT_BLOG_POST_CREATE_FORM_PROPS;
2466
+
2467
+ const DEFAULT_MENU_ITEM_CREATE_FORM_PROPS = FormProp.createMany([
2468
+ {
2469
+ type: "string" /* ePropType.String */,
2470
+ name: 'displayName',
2471
+ displayName: 'CmsKit::DisplayName',
2472
+ id: 'displayName',
2473
+ validators: () => [Validators.required],
2474
+ },
2475
+ {
2476
+ type: "boolean" /* ePropType.Boolean */,
2477
+ name: 'isActive',
2478
+ displayName: 'CmsKit::IsActive',
2479
+ id: 'isActive',
2480
+ defaultValue: true,
2481
+ },
2482
+ {
2483
+ type: "string" /* ePropType.String */,
2484
+ name: 'icon',
2485
+ displayName: 'CmsKit::Icon',
2486
+ id: 'icon',
2487
+ },
2488
+ {
2489
+ type: "string" /* ePropType.String */,
2490
+ name: 'target',
2491
+ displayName: 'CmsKit::Target',
2492
+ id: 'target',
2493
+ },
2494
+ {
2495
+ type: "string" /* ePropType.String */,
2496
+ name: 'elementId',
2497
+ displayName: 'CmsKit::ElementId',
2498
+ id: 'elementId',
2499
+ },
2500
+ {
2501
+ type: "string" /* ePropType.String */,
2502
+ name: 'cssClass',
2503
+ displayName: 'CmsKit::CssClass',
2504
+ id: 'cssClass',
2505
+ },
2506
+ {
2507
+ type: "enum" /* ePropType.Enum */,
2508
+ name: 'requiredPermissionName',
2509
+ displayName: 'CmsKit::RequiredPermissionName',
2510
+ id: 'requiredPermissionName',
2511
+ options: data => {
2512
+ const menuItemService = data.getInjected(MenuItemAdminService);
2513
+ return menuItemService
2514
+ .getPermissionLookup({
2515
+ filter: '',
2516
+ })
2517
+ .pipe(map((result) => result.items.map(permission => ({
2518
+ key: permission.displayName || permission.name || '',
2519
+ value: permission.name || '',
2520
+ }))));
2521
+ },
2522
+ },
2523
+ ]);
2524
+ const DEFAULT_MENU_ITEM_EDIT_FORM_PROPS = DEFAULT_MENU_ITEM_CREATE_FORM_PROPS;
2525
+
2526
+ const DEFAULT_MENU_ITEM_TOOLBAR_ACTIONS = ToolbarAction.createMany([
2527
+ {
2528
+ text: 'CmsKit::NewMenuItem',
2529
+ action: data => {
2530
+ const component = data.getInjected(MenuItemListComponent);
2531
+ component.add();
2532
+ },
2533
+ permission: 'CmsKit.Menus.Create',
2534
+ icon: 'fa fa-plus',
2535
+ },
2536
+ ]);
2537
+
2538
+ const DEFAULT_CMS_KIT_ADMIN_ENTITY_ACTIONS = {
2539
+ [eCmsKitAdminComponents.CommentList]: DEFAULT_COMMENT_ENTITY_ACTIONS,
2540
+ [eCmsKitAdminComponents.CommentDetails]: DEFAULT_COMMENT_ENTITY_ACTIONS,
2541
+ [eCmsKitAdminComponents.Tags]: DEFAULT_TAG_ENTITY_ACTIONS,
2542
+ [eCmsKitAdminComponents.Pages]: DEFAULT_PAGE_ENTITY_ACTIONS,
2543
+ [eCmsKitAdminComponents.Blogs]: DEFAULT_BLOG_ENTITY_ACTIONS,
2544
+ [eCmsKitAdminComponents.BlogPosts]: DEFAULT_BLOG_POST_ENTITY_ACTIONS,
2545
+ };
2546
+ const DEFAULT_CMS_KIT_ADMIN_ENTITY_PROPS = {
2547
+ [eCmsKitAdminComponents.CommentList]: DEFAULT_COMMENT_ENTITY_PROPS,
2548
+ [eCmsKitAdminComponents.CommentDetails]: DEFAULT_COMMENT_ENTITY_PROPS,
2549
+ [eCmsKitAdminComponents.Tags]: DEFAULT_TAG_ENTITY_PROPS,
2550
+ [eCmsKitAdminComponents.Pages]: DEFAULT_PAGE_ENTITY_PROPS,
2551
+ [eCmsKitAdminComponents.Blogs]: DEFAULT_BLOG_ENTITY_PROPS,
2552
+ [eCmsKitAdminComponents.BlogPosts]: DEFAULT_BLOG_POST_ENTITY_PROPS,
2553
+ };
2554
+ const DEFAULT_CMS_KIT_ADMIN_TOOLBAR_ACTIONS = {
2555
+ [eCmsKitAdminComponents.Tags]: DEFAULT_TAG_TOOLBAR_ACTIONS,
2556
+ [eCmsKitAdminComponents.Pages]: DEFAULT_PAGE_TOOLBAR_ACTIONS,
2557
+ [eCmsKitAdminComponents.Blogs]: DEFAULT_BLOG_TOOLBAR_ACTIONS,
2558
+ [eCmsKitAdminComponents.BlogPosts]: DEFAULT_BLOG_POST_TOOLBAR_ACTIONS,
2559
+ [eCmsKitAdminComponents.Menus]: DEFAULT_MENU_ITEM_TOOLBAR_ACTIONS,
2560
+ };
2561
+ const DEFAULT_CMS_KIT_ADMIN_CREATE_FORM_PROPS = {
2562
+ [eCmsKitAdminComponents.Tags]: DEFAULT_TAG_CREATE_FORM_PROPS,
2563
+ [eCmsKitAdminComponents.Pages]: DEFAULT_PAGE_CREATE_FORM_PROPS,
2564
+ [eCmsKitAdminComponents.Blogs]: DEFAULT_BLOG_CREATE_FORM_PROPS,
2565
+ [eCmsKitAdminComponents.PageForm]: DEFAULT_PAGE_CREATE_FORM_PROPS,
2566
+ [eCmsKitAdminComponents.BlogPostForm]: DEFAULT_BLOG_POST_CREATE_FORM_PROPS,
2567
+ [eCmsKitAdminComponents.Menus]: DEFAULT_MENU_ITEM_CREATE_FORM_PROPS,
2568
+ };
2569
+ const DEFAULT_CMS_KIT_ADMIN_EDIT_FORM_PROPS = {
2570
+ [eCmsKitAdminComponents.Tags]: DEFAULT_TAG_EDIT_FORM_PROPS,
2571
+ [eCmsKitAdminComponents.Pages]: DEFAULT_PAGE_EDIT_FORM_PROPS,
2572
+ [eCmsKitAdminComponents.Blogs]: DEFAULT_BLOG_EDIT_FORM_PROPS,
2573
+ [eCmsKitAdminComponents.PageForm]: DEFAULT_PAGE_EDIT_FORM_PROPS,
2574
+ [eCmsKitAdminComponents.BlogPostForm]: DEFAULT_BLOG_POST_EDIT_FORM_PROPS,
2575
+ [eCmsKitAdminComponents.Menus]: DEFAULT_MENU_ITEM_EDIT_FORM_PROPS,
2576
+ };
2577
+ const CMS_KIT_ADMIN_ENTITY_ACTION_CONTRIBUTORS = new InjectionToken('CMS_KIT_ADMIN_ENTITY_ACTION_CONTRIBUTORS');
2578
+ const CMS_KIT_ADMIN_ENTITY_PROP_CONTRIBUTORS = new InjectionToken('CMS_KIT_ADMIN_ENTITY_PROP_CONTRIBUTORS');
2579
+ const CMS_KIT_ADMIN_TOOLBAR_ACTION_CONTRIBUTORS = new InjectionToken('CMS_KIT_ADMIN_TOOLBAR_ACTION_CONTRIBUTORS');
2580
+ const CMS_KIT_ADMIN_CREATE_FORM_PROP_CONTRIBUTORS = new InjectionToken('CMS_KIT_ADMIN_CREATE_FORM_PROP_CONTRIBUTORS');
2581
+ const CMS_KIT_ADMIN_EDIT_FORM_PROP_CONTRIBUTORS = new InjectionToken('CMS_KIT_ADMIN_EDIT_FORM_PROP_CONTRIBUTORS');
2582
+
2583
+ const cmsKitAdminExtensionsResolver = () => {
2584
+ const injector = inject(Injector);
2585
+ const extensions = inject(ExtensionsService);
2586
+ const config = { optional: true };
2587
+ const actionContributors = inject(CMS_KIT_ADMIN_ENTITY_ACTION_CONTRIBUTORS, config) || {};
2588
+ const toolbarContributors = inject(CMS_KIT_ADMIN_TOOLBAR_ACTION_CONTRIBUTORS, config) || {};
2589
+ const propContributors = inject(CMS_KIT_ADMIN_ENTITY_PROP_CONTRIBUTORS, config) || {};
2590
+ const createFormContributors = inject(CMS_KIT_ADMIN_CREATE_FORM_PROP_CONTRIBUTORS, config) || {};
2591
+ const editFormContributors = inject(CMS_KIT_ADMIN_EDIT_FORM_PROP_CONTRIBUTORS, config) || {};
2592
+ return getObjectExtensionEntitiesFromStore(injector, 'CmsKit').pipe(map$1(entities => ({
2593
+ [eCmsKitAdminComponents.CommentList]: entities.Comment,
2594
+ [eCmsKitAdminComponents.CommentDetails]: entities.Comment,
2595
+ [eCmsKitAdminComponents.Tags]: entities.Tag,
2596
+ [eCmsKitAdminComponents.Pages]: entities.Page,
2597
+ [eCmsKitAdminComponents.PageForm]: entities.Page,
2598
+ [eCmsKitAdminComponents.Blogs]: entities.Blog,
2599
+ [eCmsKitAdminComponents.BlogPosts]: entities.BlogPost,
2600
+ [eCmsKitAdminComponents.BlogPostForm]: entities.BlogPost,
2601
+ [eCmsKitAdminComponents.Menus]: entities.MenuItem,
2602
+ })), mapEntitiesToContributors(injector, 'CmsKit'), tap$1(objectExtensionContributors => {
2603
+ mergeWithDefaultActions(extensions.entityActions, DEFAULT_CMS_KIT_ADMIN_ENTITY_ACTIONS, actionContributors);
2604
+ mergeWithDefaultActions(extensions.toolbarActions, DEFAULT_CMS_KIT_ADMIN_TOOLBAR_ACTIONS, toolbarContributors);
2605
+ mergeWithDefaultProps(extensions.entityProps, DEFAULT_CMS_KIT_ADMIN_ENTITY_PROPS, objectExtensionContributors.prop, propContributors);
2606
+ mergeWithDefaultProps(extensions.createFormProps, DEFAULT_CMS_KIT_ADMIN_CREATE_FORM_PROPS, objectExtensionContributors.createForm, createFormContributors);
2607
+ mergeWithDefaultProps(extensions.editFormProps, DEFAULT_CMS_KIT_ADMIN_EDIT_FORM_PROPS, objectExtensionContributors.editForm, editFormContributors);
2608
+ }));
2609
+ };
2610
+
2611
+ function createRoutes(config = {}) {
2612
+ return [
2613
+ {
2614
+ path: '',
2615
+ component: RouterOutletComponent,
2616
+ providers: provideCmsKitAdminContributors(config),
2617
+ canActivate: [authGuard, permissionGuard],
2618
+ children: [
2619
+ {
2620
+ path: 'comments',
2621
+ component: ReplaceableRouteContainerComponent,
2622
+ resolve: {
2623
+ extensions: cmsKitAdminExtensionsResolver,
2624
+ },
2625
+ data: {
2626
+ requiredPolicy: 'CmsKit.Comments',
2627
+ replaceableComponent: {
2628
+ key: eCmsKitAdminComponents.CommentList,
2629
+ defaultComponent: CommentListComponent,
2630
+ },
2631
+ },
2632
+ title: 'CmsKit::Comments',
2633
+ },
2634
+ {
2635
+ path: 'comments/:id',
2636
+ component: ReplaceableRouteContainerComponent,
2637
+ resolve: {
2638
+ extensions: cmsKitAdminExtensionsResolver,
2639
+ },
2640
+ data: {
2641
+ requiredPolicy: 'CmsKit.Comments',
2642
+ replaceableComponent: {
2643
+ key: eCmsKitAdminComponents.CommentDetails,
2644
+ defaultComponent: CommentDetailsComponent,
2645
+ },
2646
+ },
2647
+ title: 'CmsKit::Comments',
2648
+ },
2649
+ {
2650
+ path: 'tags',
2651
+ component: ReplaceableRouteContainerComponent,
2652
+ resolve: {
2653
+ extensions: cmsKitAdminExtensionsResolver,
2654
+ },
2655
+ data: {
2656
+ requiredPolicy: 'CmsKit.Tags',
2657
+ replaceableComponent: {
2658
+ key: eCmsKitAdminComponents.Tags,
2659
+ defaultComponent: TagListComponent,
2660
+ },
2661
+ },
2662
+ title: 'CmsKit::Tags',
2663
+ },
2664
+ {
2665
+ path: 'pages',
2666
+ component: ReplaceableRouteContainerComponent,
2667
+ resolve: {
2668
+ extensions: cmsKitAdminExtensionsResolver,
2669
+ },
2670
+ data: {
2671
+ requiredPolicy: 'CmsKit.Pages',
2672
+ replaceableComponent: {
2673
+ key: eCmsKitAdminComponents.Pages,
2674
+ defaultComponent: PageListComponent,
2675
+ },
2676
+ },
2677
+ title: 'CmsKit::Pages',
2678
+ },
2679
+ {
2680
+ path: 'pages/create',
2681
+ component: ReplaceableRouteContainerComponent,
2682
+ resolve: {
2683
+ extensions: cmsKitAdminExtensionsResolver,
2684
+ },
2685
+ data: {
2686
+ requiredPolicy: 'CmsKit.Pages.Create',
2687
+ replaceableComponent: {
2688
+ key: eCmsKitAdminComponents.PageForm,
2689
+ defaultComponent: PageFormComponent,
2690
+ },
2691
+ },
2692
+ title: 'CmsKit::Pages',
2693
+ },
2694
+ {
2695
+ path: 'pages/update/:id',
2696
+ component: ReplaceableRouteContainerComponent,
2697
+ resolve: {
2698
+ extensions: cmsKitAdminExtensionsResolver,
2699
+ },
2700
+ data: {
2701
+ requiredPolicy: 'CmsKit.Pages.Update',
2702
+ replaceableComponent: {
2703
+ key: eCmsKitAdminComponents.PageForm,
2704
+ defaultComponent: PageFormComponent,
2705
+ },
2706
+ },
2707
+ title: 'CmsKit::Pages',
2708
+ },
2709
+ {
2710
+ path: 'blogs',
2711
+ component: ReplaceableRouteContainerComponent,
2712
+ resolve: {
2713
+ extensions: cmsKitAdminExtensionsResolver,
2714
+ },
2715
+ data: {
2716
+ requiredPolicy: 'CmsKit.Blogs',
2717
+ replaceableComponent: {
2718
+ key: eCmsKitAdminComponents.Blogs,
2719
+ defaultComponent: BlogListComponent,
2720
+ },
2721
+ },
2722
+ title: 'CmsKit::Blogs',
2723
+ },
2724
+ {
2725
+ path: 'blog-posts',
2726
+ component: ReplaceableRouteContainerComponent,
2727
+ resolve: {
2728
+ extensions: cmsKitAdminExtensionsResolver,
2729
+ },
2730
+ data: {
2731
+ requiredPolicy: 'CmsKit.BlogPosts',
2732
+ replaceableComponent: {
2733
+ key: eCmsKitAdminComponents.BlogPosts,
2734
+ defaultComponent: BlogPostListComponent,
2735
+ },
2736
+ },
2737
+ title: 'CmsKit::BlogPosts',
2738
+ },
2739
+ {
2740
+ path: 'blog-posts/create',
2741
+ component: ReplaceableRouteContainerComponent,
2742
+ resolve: {
2743
+ extensions: cmsKitAdminExtensionsResolver,
2744
+ },
2745
+ data: {
2746
+ requiredPolicy: 'CmsKit.BlogPosts.Create',
2747
+ replaceableComponent: {
2748
+ key: eCmsKitAdminComponents.BlogPostForm,
2749
+ defaultComponent: BlogPostFormComponent,
2750
+ },
2751
+ },
2752
+ title: 'CmsKit::BlogPosts',
2753
+ },
2754
+ {
2755
+ path: 'blog-posts/update/:id',
2756
+ component: ReplaceableRouteContainerComponent,
2757
+ resolve: {
2758
+ extensions: cmsKitAdminExtensionsResolver,
2759
+ },
2760
+ data: {
2761
+ requiredPolicy: 'CmsKit.BlogPosts.Update',
2762
+ replaceableComponent: {
2763
+ key: eCmsKitAdminComponents.BlogPostForm,
2764
+ defaultComponent: BlogPostFormComponent,
2765
+ },
2766
+ },
2767
+ title: 'CmsKit::BlogPosts',
2768
+ },
2769
+ {
2770
+ path: 'menus',
2771
+ component: ReplaceableRouteContainerComponent,
2772
+ resolve: {
2773
+ extensions: cmsKitAdminExtensionsResolver,
2774
+ },
2775
+ data: {
2776
+ requiredPolicy: 'CmsKit.Menus',
2777
+ replaceableComponent: {
2778
+ key: eCmsKitAdminComponents.Menus,
2779
+ defaultComponent: MenuItemListComponent,
2780
+ },
2781
+ },
2782
+ title: 'CmsKit::MenuItems',
2783
+ },
2784
+ {
2785
+ path: 'global-resources',
2786
+ component: GlobalResourcesComponent,
2787
+ data: {
2788
+ requiredPolicy: 'CmsKit.GlobalResources',
2789
+ },
2790
+ title: 'CmsKit::GlobalResources',
2791
+ },
2792
+ ],
2793
+ },
2794
+ ];
2795
+ }
2796
+ function provideCmsKitAdminContributors(options = {}) {
2797
+ return [
2798
+ {
2799
+ provide: CMS_KIT_ADMIN_ENTITY_ACTION_CONTRIBUTORS,
2800
+ useValue: options.entityActionContributors,
2801
+ },
2802
+ {
2803
+ provide: CMS_KIT_ADMIN_ENTITY_PROP_CONTRIBUTORS,
2804
+ useValue: options.entityPropContributors,
2805
+ },
2806
+ {
2807
+ provide: CMS_KIT_ADMIN_TOOLBAR_ACTION_CONTRIBUTORS,
2808
+ useValue: options.toolbarActionContributors,
2809
+ },
2810
+ {
2811
+ provide: CMS_KIT_ADMIN_CREATE_FORM_PROP_CONTRIBUTORS,
2812
+ useValue: options.createFormPropContributors,
2813
+ },
2814
+ {
2815
+ provide: CMS_KIT_ADMIN_EDIT_FORM_PROP_CONTRIBUTORS,
2816
+ useValue: options.editFormPropContributors,
2817
+ },
2818
+ ];
2819
+ }
2820
+
2821
+ /**
2822
+ * Generated bundle index. Do not edit.
2823
+ */
2824
+
2825
+ export { BlogFeaturesModalComponent, BlogListComponent, BlogModalComponent, BlogPostFormComponent, BlogPostListComponent, CMS_KIT_ADMIN_CREATE_FORM_PROP_CONTRIBUTORS, CMS_KIT_ADMIN_EDIT_FORM_PROP_CONTRIBUTORS, CMS_KIT_ADMIN_ENTITY_ACTION_CONTRIBUTORS, CMS_KIT_ADMIN_ENTITY_PROP_CONTRIBUTORS, CMS_KIT_ADMIN_TOOLBAR_ACTION_CONTRIBUTORS, CMS_KIT_COMMENTS_REQUIRE_APPROVEMENT, CmsSettingsComponent, CommentDetailsComponent, CommentListComponent, DEFAULT_BLOG_CREATE_FORM_PROPS, DEFAULT_BLOG_EDIT_FORM_PROPS, DEFAULT_BLOG_ENTITY_ACTIONS, DEFAULT_BLOG_ENTITY_PROPS, DEFAULT_BLOG_POST_CREATE_FORM_PROPS, DEFAULT_BLOG_POST_EDIT_FORM_PROPS, DEFAULT_BLOG_POST_ENTITY_ACTIONS, DEFAULT_BLOG_POST_ENTITY_PROPS, DEFAULT_BLOG_POST_TOOLBAR_ACTIONS, DEFAULT_BLOG_TOOLBAR_ACTIONS, DEFAULT_CMS_KIT_ADMIN_CREATE_FORM_PROPS, DEFAULT_CMS_KIT_ADMIN_EDIT_FORM_PROPS, DEFAULT_CMS_KIT_ADMIN_ENTITY_ACTIONS, DEFAULT_CMS_KIT_ADMIN_ENTITY_PROPS, DEFAULT_CMS_KIT_ADMIN_TOOLBAR_ACTIONS, DEFAULT_COMMENT_ENTITY_ACTIONS, DEFAULT_COMMENT_ENTITY_PROPS, DEFAULT_MENU_ITEM_CREATE_FORM_PROPS, DEFAULT_MENU_ITEM_EDIT_FORM_PROPS, DEFAULT_MENU_ITEM_TOOLBAR_ACTIONS, DEFAULT_PAGE_CREATE_FORM_PROPS, DEFAULT_PAGE_EDIT_FORM_PROPS, DEFAULT_PAGE_ENTITY_ACTIONS, DEFAULT_PAGE_ENTITY_PROPS, DEFAULT_PAGE_TOOLBAR_ACTIONS, DEFAULT_TAG_CREATE_FORM_PROPS, DEFAULT_TAG_EDIT_FORM_PROPS, DEFAULT_TAG_ENTITY_ACTIONS, DEFAULT_TAG_ENTITY_PROPS, DEFAULT_TAG_TOOLBAR_ACTIONS, GlobalResourcesComponent, LAYOUT_CONSTANTS, MenuItemListComponent, MenuItemModalComponent, PageFormComponent, PageListComponent, TagListComponent, TagModalComponent, cmsKitAdminExtensionsResolver, createRoutes, eCmsKitAdminComponents };
2826
+ //# sourceMappingURL=abp-ng.cms-kit-admin.mjs.map