@dignite/ng.site 0.0.0-stage → 1.0.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,235 @@
1
+ import * as i4 from '@abp/ng.core';
2
+ import { PermissionService, CoreModule, PermissionDirective } from '@abp/ng.core';
3
+ import * as i2$1 from '@abp/ng.theme.shared';
4
+ import { ConfirmationService, ToasterService, Confirmation, ThemeSharedModule } from '@abp/ng.theme.shared';
5
+ import * as i6 from '@swimlane/ngx-datatable';
6
+ import { NgxDatatableModule } from '@swimlane/ngx-datatable';
7
+ import * as i0 from '@angular/core';
8
+ import { inject, signal, ViewChild, ChangeDetectionStrategy, Component } from '@angular/core';
9
+ import * as i1$1 from '@angular/forms';
10
+ import { FormBuilder, Validators, ReactiveFormsModule } from '@angular/forms';
11
+ import * as i2 from '@angular/router';
12
+ import { Router, RouterLink } from '@angular/router';
13
+ import * as i8 from 'ng-zorro-antd/tree-select';
14
+ import { NzTreeSelectModule } from 'ng-zorro-antd/tree-select';
15
+ import { P as PageAdminService, e as eSitePolicyNames } from './dignite-ng.site-dignite-ng.site-CsKxqjY9.mjs';
16
+ import * as i1 from '@angular/common';
17
+ import * as i3 from '@ngx-validate/core';
18
+
19
+ /** Max lengths mirror `PageConsts` (`src/Dignite.Site.Domain.Shared/Pages/PageConsts.cs`). */
20
+ const PAGE_CONSTS = {
21
+ maxNameLength: 64,
22
+ maxDisplayNameLength: 128,
23
+ maxRouteLength: 512,
24
+ maxTemplateLength: 256,
25
+ };
26
+ /** Mirrors `IdentifierName.Pattern` (`src/Dignite.Site.Domain.Shared/IdentifierName.cs`). */
27
+ const NAME_PATTERN = /^[a-z0-9][a-z0-9_-]*$/;
28
+ /** Mirrors `PageConsts.RoutePattern`. */
29
+ const ROUTE_PATTERN = /^\S+$/;
30
+ /** Mirrors `PageConsts.TemplatePattern`. Required - at least one character - since `template` is required. */
31
+ const TEMPLATE_PATTERN = /^\/?[A-Za-z0-9_][A-Za-z0-9_/-]*$/;
32
+ class PagesComponent {
33
+ constructor() {
34
+ this.pageService = inject(PageAdminService);
35
+ this.fb = inject(FormBuilder);
36
+ this.confirmation = inject(ConfirmationService);
37
+ this.toaster = inject(ToasterService);
38
+ this.router = inject(Router);
39
+ this.permission = inject(PermissionService);
40
+ this.policies = eSitePolicyNames;
41
+ /**
42
+ * The whole (filtered) result set, unpaged - the datatable paginates it client-side.
43
+ *
44
+ * State that changes in an HTTP callback (this, and the modal flags below) is a signal, not a plain
45
+ * field: the host layout's ancestors (`abp-router-outlet`, the LeptonX layouts) are OnPush, and a
46
+ * plain-field write in a response callback never marks them for check, so the list would stay empty
47
+ * until some unrelated event happened to.
48
+ */
49
+ this.data = signal({ items: [] }, /* @ts-ignore */
50
+ ...(ngDevMode ? [{ debugName: "data" }] : /* istanbul ignore next */ []));
51
+ this.filters = {};
52
+ this.isModalOpen = signal(false, /* @ts-ignore */
53
+ ...(ngDevMode ? [{ debugName: "isModalOpen" }] : /* istanbul ignore next */ []));
54
+ this.isModalBusy = signal(false, /* @ts-ignore */
55
+ ...(ngDevMode ? [{ debugName: "isModalBusy" }] : /* istanbul ignore next */ []));
56
+ this.applyFilters();
57
+ }
58
+ /** Whether the tree-toggle template should render a toggle for this row at all. */
59
+ hasChildren(row) {
60
+ return this.data().items.some(page => page.parentId === row.id);
61
+ }
62
+ applyFilters() {
63
+ this.pageService.getList(this.filters).subscribe(result => {
64
+ // A page's parentId can point at a page the current filter excludes (isActive/filter are
65
+ // backend params, so a match can survive while its parent does not). Rather than let such a
66
+ // row vanish from the tree, it renders at the root - normalized here once so every reader of
67
+ // `data().items` (the datatable's tree grouping, the tree-select's candidate list) sees a
68
+ // consistent, dangling-free parentId.
69
+ const ids = new Set(result.items.map(page => page.id));
70
+ this.data.set({
71
+ items: result.items.map(page => ({
72
+ ...page,
73
+ parentId: page.parentId && ids.has(page.parentId) ? page.parentId : null,
74
+ treeStatus: 'expanded',
75
+ })),
76
+ });
77
+ });
78
+ }
79
+ clearFilters() {
80
+ this.filters = {};
81
+ this.applyFilters();
82
+ }
83
+ /** Toggles one row's branch. `ngx-datatable` reads `treeStatus` off the row it is given back. */
84
+ onTreeAction(event) {
85
+ event.row.treeStatus = event.row.treeStatus === 'collapsed' ? 'expanded' : 'collapsed';
86
+ this.data.set({ items: [...this.data().items] });
87
+ }
88
+ openCreate() {
89
+ this.editingPage = undefined;
90
+ this.form = this.buildForm();
91
+ this.isModalOpen.set(true);
92
+ }
93
+ openEdit(page) {
94
+ this.editingPage = page;
95
+ this.form = this.buildForm(page);
96
+ this.isModalOpen.set(true);
97
+ }
98
+ closeModal() {
99
+ this.isModalOpen.set(false);
100
+ this.form = undefined;
101
+ this.editingPage = undefined;
102
+ }
103
+ save() {
104
+ if (!this.form || this.form.invalid || this.isModalBusy()) {
105
+ return;
106
+ }
107
+ this.isModalBusy.set(true);
108
+ const value = this.form.getRawValue();
109
+ const isCreating = !this.editingPage;
110
+ const request$ = this.editingPage
111
+ ? this.pageService.update(this.editingPage.id, value)
112
+ : this.pageService.create(value);
113
+ request$.subscribe({
114
+ next: page => {
115
+ this.isModalBusy.set(false);
116
+ this.closeModal();
117
+ this.toaster.success('AbpUi::SavedSuccessfully');
118
+ // A fresh page always has exactly one auto-created content type
119
+ // (PageAdminAppService.CreateDefaultContentTypeAsync) still waiting for its fields - go straight
120
+ // there instead of leaving the user to find the sitemap icon themselves.
121
+ if (isCreating && this.permission.getGrantedPolicy(this.policies.ContentTypes)) {
122
+ this.router.navigate(['/site/pages', page.id, 'content-types']);
123
+ return;
124
+ }
125
+ this.applyFilters();
126
+ },
127
+ error: () => this.isModalBusy.set(false),
128
+ });
129
+ }
130
+ delete(page) {
131
+ this.confirmation
132
+ .warn('AbpUi::ItemWillBeDeletedMessage', 'AbpUi::AreYouSure', {
133
+ messageLocalizationParams: [page.displayName ?? ''],
134
+ })
135
+ .subscribe((status) => {
136
+ if (status === Confirmation.Status.confirm) {
137
+ this.pageService.delete(page.id).subscribe(() => {
138
+ this.applyFilters();
139
+ this.toaster.success('AbpUi::SuccessfullyDeleted');
140
+ });
141
+ }
142
+ });
143
+ }
144
+ /**
145
+ * The "Parent page" picker's candidates: every page except the one being edited and its own
146
+ * subtree - offering either as a choice would only trade a clean rejection in the picker for a
147
+ * `PageParentCycleException` from the server.
148
+ *
149
+ * Cached against a cheap key, not recomputed every read, for the same reason
150
+ * `field-arrangement.component.ts`'s `addableFieldOptions` is: `nz-tree-select` expects a stable
151
+ * array reference, and a plain rebuild here would hand it a fresh one on every change-detection
152
+ * cycle, including the ones firing while its dropdown is open.
153
+ */
154
+ get parentTreeNodes() {
155
+ const editingId = this.editingPage?.id;
156
+ const items = this.data().items;
157
+ if (this.parentTreeNodesCache?.items !== items ||
158
+ this.parentTreeNodesCache?.editingId !== editingId) {
159
+ const excluded = editingId ? this.subtreeIds(editingId) : new Set();
160
+ this.parentTreeNodesCache = {
161
+ items,
162
+ editingId,
163
+ nodes: this.buildTreeNodes(null, excluded),
164
+ };
165
+ }
166
+ return this.parentTreeNodesCache.nodes;
167
+ }
168
+ /** `rootId` and everything beneath it, found by repeatedly sweeping for newly-matched children. */
169
+ subtreeIds(rootId) {
170
+ const ids = new Set([rootId]);
171
+ for (let grew = true; grew;) {
172
+ grew = false;
173
+ for (const page of this.data().items) {
174
+ if (page.parentId && ids.has(page.parentId) && !ids.has(page.id)) {
175
+ ids.add(page.id);
176
+ grew = true;
177
+ }
178
+ }
179
+ }
180
+ return ids;
181
+ }
182
+ buildTreeNodes(parentId, excluded) {
183
+ const items = this.data().items;
184
+ return items
185
+ .filter(page => (page.parentId ?? null) === parentId && !excluded.has(page.id))
186
+ .map(page => ({
187
+ key: page.id,
188
+ title: page.displayName || page.name || '',
189
+ children: this.buildTreeNodes(page.id, excluded),
190
+ isLeaf: !items.some(child => child.parentId === page.id),
191
+ }));
192
+ }
193
+ buildForm(page) {
194
+ return this.fb.group({
195
+ name: [
196
+ page?.name ?? '',
197
+ [Validators.required, Validators.maxLength(PAGE_CONSTS.maxNameLength), Validators.pattern(NAME_PATTERN)],
198
+ ],
199
+ displayName: [
200
+ page?.displayName ?? '',
201
+ [Validators.required, Validators.maxLength(PAGE_CONSTS.maxDisplayNameLength)],
202
+ ],
203
+ route: [
204
+ page?.route ?? '',
205
+ [Validators.required, Validators.maxLength(PAGE_CONSTS.maxRouteLength), Validators.pattern(ROUTE_PATTERN)],
206
+ ],
207
+ template: [
208
+ page?.template ?? '',
209
+ [Validators.required, Validators.maxLength(PAGE_CONSTS.maxTemplateLength), Validators.pattern(TEMPLATE_PATTERN)],
210
+ ],
211
+ parentId: [page?.parentId ?? null],
212
+ isActive: [page?.isActive ?? true],
213
+ });
214
+ }
215
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.2.2", ngImport: i0, type: PagesComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
216
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.2.2", type: PagesComponent, isStandalone: true, selector: "site-pages", viewQueries: [{ propertyName: "submitButton", first: true, predicate: ["submitButton"], descendants: true }], ngImport: i0, template: "<div class=\"card mb-3\">\n <div class=\"card-body\">\n <div class=\"row align-items-end g-2\">\n <div class=\"col-md-3\">\n <label class=\"form-label\">{{ 'Site::DisplayName:Page.IsActive' | abpLocalization }}</label>\n <select class=\"form-select\" [(ngModel)]=\"filters.isActive\" (change)=\"applyFilters()\">\n <option [ngValue]=\"undefined\">--</option>\n <option [ngValue]=\"true\">{{ 'AbpUi::Yes' | abpLocalization }}</option>\n <option [ngValue]=\"false\">{{ 'AbpUi::No' | abpLocalization }}</option>\n </select>\n </div>\n <div class=\"col-md-5\">\n <label class=\"form-label\">{{ 'AbpUi::Search' | abpLocalization }}</label>\n <input\n type=\"text\"\n class=\"form-control\"\n [(ngModel)]=\"filters.filter\"\n (keyup.enter)=\"applyFilters()\"\n [placeholder]=\"'AbpUi::Search' | abpLocalization\"\n />\n </div>\n <div class=\"col-md-4\">\n <button type=\"button\" class=\"btn btn-primary me-2\" (click)=\"applyFilters()\">\n <i class=\"fa fa-search me-1\"></i>{{ 'AbpUi::Search' | abpLocalization }}\n </button>\n <button type=\"button\" class=\"btn btn-outline-secondary\" (click)=\"clearFilters()\">\n {{ 'AbpUi::Clear' | abpLocalization }}\n </button>\n </div>\n </div>\n </div>\n</div>\n\n<div class=\"card\">\n <div class=\"card-body\">\n <div class=\"d-flex justify-content-between align-items-center mb-3\">\n <h5 class=\"mb-0\">{{ 'Site::Pages' | abpLocalization }}</h5>\n <button\n *abpPermission=\"policies.PagesCreate\"\n type=\"button\"\n class=\"btn btn-primary\"\n (click)=\"openCreate()\"\n >\n <i class=\"fa fa-plus me-1\"></i>{{ 'Site::NewPage' | abpLocalization }}\n </button>\n </div>\n\n <ngx-datatable\n class=\"material\"\n [rows]=\"data().items\"\n columnMode=\"flex\"\n [headerHeight]=\"42\"\n [footerHeight]=\"42\"\n rowHeight=\"auto\"\n treeFromRelation=\"parentId\"\n treeToRelation=\"id\"\n (treeAction)=\"onTreeAction($event)\"\n >\n <ngx-datatable-column\n prop=\"displayName\"\n [flexGrow]=\"2\"\n [isTreeColumn]=\"true\"\n [treeLevelIndent]=\"20\"\n [name]=\"'Site::DisplayName:Page.DisplayName' | abpLocalization\"\n >\n <ng-template\n let-row=\"row\"\n let-treeStatus=\"treeStatus\"\n let-onTreeAction=\"onTreeAction\"\n ngx-datatable-cell-template\n >\n @if (hasChildren(row)) {\n <button type=\"button\" class=\"page-tree-toggle\" (click)=\"onTreeAction()\">\n <i\n class=\"fa\"\n [ngClass]=\"treeStatus === 'collapsed' ? 'fa-caret-right' : 'fa-caret-down'\"\n ></i>\n </button>\n }\n {{ row.displayName }}\n </ng-template>\n </ngx-datatable-column>\n <ngx-datatable-column\n prop=\"name\"\n [flexGrow]=\"2\"\n [name]=\"'Site::DisplayName:Page.Name' | abpLocalization\"\n ></ngx-datatable-column>\n <ngx-datatable-column\n prop=\"route\"\n [flexGrow]=\"2\"\n [name]=\"'Site::DisplayName:Page.Route' | abpLocalization\"\n ></ngx-datatable-column>\n <ngx-datatable-column\n [flexGrow]=\"1\"\n [name]=\"'Site::DisplayName:Page.IsActive' | abpLocalization\"\n [sortable]=\"false\"\n >\n <ng-template let-row=\"row\" ngx-datatable-cell-template>\n <i class=\"fa\" [ngClass]=\"row.isActive ? 'fa-check text-success' : 'fa-times text-muted'\"></i>\n </ng-template>\n </ngx-datatable-column>\n <ngx-datatable-column [flexGrow]=\"2\" [sortable]=\"false\" [name]=\"'AbpUi::Actions' | abpLocalization\">\n <ng-template let-row=\"row\" ngx-datatable-cell-template>\n <a\n *abpPermission=\"policies.ContentTypes\"\n class=\"btn btn-sm btn-light me-1\"\n [routerLink]=\"['/site/pages', row.id, 'content-types']\"\n [title]=\"'Site::ContentTypes' | abpLocalization\"\n >\n <i class=\"fa fa-sitemap\"></i>\n </a>\n <button\n *abpPermission=\"policies.PagesUpdate\"\n type=\"button\"\n class=\"btn btn-sm btn-light me-1\"\n (click)=\"openEdit(row)\"\n [title]=\"'AbpUi::Edit' | abpLocalization\"\n >\n <i class=\"fa fa-pencil\"></i>\n </button>\n <button\n *abpPermission=\"policies.PagesDelete\"\n type=\"button\"\n class=\"btn btn-sm btn-light\"\n (click)=\"delete(row)\"\n [title]=\"'AbpUi::Delete' | abpLocalization\"\n >\n <i class=\"fa fa-trash text-danger\"></i>\n </button>\n </ng-template>\n </ngx-datatable-column>\n </ngx-datatable>\n </div>\n</div>\n\n<abp-modal [(visible)]=\"isModalOpen\" [busy]=\"isModalBusy()\" (disappear)=\"closeModal()\">\n <ng-template #abpHeader>\n <h3>{{ (editingPage ? 'Site::EditPage' : 'Site::NewPage') | abpLocalization }}</h3>\n </ng-template>\n <ng-template #abpBody>\n @if (form) {\n <form [formGroup]=\"form\" (submit)=\"save()\">\n <button type=\"submit\" #submitButton style=\"display: none\"></button>\n\n <div class=\"mb-3\">\n <label class=\"form-label\">{{ 'Site::DisplayName:Page.DisplayName' | abpLocalization }}</label>\n <input type=\"text\" class=\"form-control\" formControlName=\"displayName\" />\n </div>\n <div class=\"mb-3\">\n <label class=\"form-label\">{{ 'Site::DisplayName:Page.Name' | abpLocalization }}</label>\n <input type=\"text\" class=\"form-control\" formControlName=\"name\" />\n <small class=\"form-text text-muted\">\n {{ 'Site::Description:Page.Name' | abpLocalization }}\n </small>\n </div>\n <div class=\"mb-3\">\n <label class=\"form-label\">{{ 'Site::DisplayName:Page.Route' | abpLocalization }}</label>\n <input type=\"text\" class=\"form-control\" formControlName=\"route\" />\n <small class=\"form-text text-muted\">\n {{ 'Site::Description:Page.Route' | abpLocalization }}\n </small>\n </div>\n <div class=\"mb-3\">\n <label class=\"form-label\">{{ 'Site::DisplayName:Page.Template' | abpLocalization }}</label>\n <input type=\"text\" class=\"form-control\" formControlName=\"template\" />\n <small class=\"form-text text-muted\">\n {{ 'Site::Description:Page.Template' | abpLocalization }}\n </small>\n </div>\n <div class=\"mb-3\">\n <label class=\"form-label\">{{ 'Site::DisplayName:Page.ParentId' | abpLocalization }}</label>\n <nz-tree-select\n class=\"form-select parent-picker-select\"\n formControlName=\"parentId\"\n [nzNodes]=\"parentTreeNodes\"\n nzAllowClear\n nzShowSearch\n nzDefaultExpandAll\n nzDropdownClassName=\"parent-picker-dropdown\"\n [nzPlaceHolder]=\"'Site::DisplayName:Page.ParentId' | abpLocalization\"\n ></nz-tree-select>\n <small class=\"form-text text-muted\">\n {{ 'Site::Description:Page.ParentId' | abpLocalization }}\n </small>\n </div>\n <div class=\"form-check\">\n <input\n type=\"checkbox\"\n class=\"form-check-input\"\n id=\"site-page-is-active\"\n formControlName=\"isActive\"\n />\n <label class=\"form-check-label\" for=\"site-page-is-active\">\n {{ 'Site::DisplayName:Page.IsActive' | abpLocalization }}\n </label>\n </div>\n </form>\n }\n </ng-template>\n <ng-template #abpFooter>\n <button type=\"button\" class=\"btn btn-secondary\" abpClose>\n {{ 'AbpUi::Cancel' | abpLocalization }}\n </button>\n <abp-button\n iconClass=\"fa fa-check\"\n [disabled]=\"!form?.valid\"\n [loading]=\"isModalBusy()\"\n (click)=\"submitButton?.nativeElement?.click()\"\n >\n {{ 'AbpUi::Save' | abpLocalization }}\n </abp-button>\n </ng-template>\n</abp-modal>\n", styles: [":host ::ng-deep .datatable-tree-button{display:none}.page-tree-toggle{border:none;background:transparent;padding:0;width:16px;cursor:pointer;color:inherit}::ng-deep .parent-picker-select{width:100%}::ng-deep .parent-picker-select.ant-select{color:inherit!important;height:unset!important;font-size:unset!important;--bs-form-select-bg-img: unset !important}::ng-deep .parent-picker-select .ant-select-selector{background:transparent!important;border:none!important;padding:.475rem 1.25rem!important;box-shadow:none!important;height:auto!important}::ng-deep .parent-picker-select .ant-select-selection-placeholder{color:inherit!important}::ng-deep .parent-picker-select.form-select{padding:0!important}::ng-deep .parent-picker-dropdown.ant-select-dropdown{background:var(--lpx-content-bg, var(--bs-secondary-bg, #fff))!important}::ng-deep .parent-picker-dropdown .ant-select-tree-node-content-wrapper:hover{background-color:var(--bs-primary)!important;color:var(--bs-white)!important}::ng-deep .parent-picker-dropdown .ant-select-tree-node-content-wrapper.ant-select-tree-node-selected{background-color:var(--lpx-brand)!important;color:var(--bs-white)!important}::ng-deep .parent-picker-dropdown .ant-select-tree{color:var(--bs-body-color)!important;background-color:transparent!important}\n"], dependencies: [{ kind: "ngmodule", type: CoreModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { 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]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.CheckboxControlValueAccessor, selector: "input[type=checkbox]:not([ngNoCva])[formControlName],input[type=checkbox]:not([ngNoCva])[formControl],input[type=checkbox]:not([ngNoCva])[ngModel]" }, { kind: "directive", type: i1$1.SelectControlValueAccessor, selector: "select:not([multiple]):not([ngNoCva])[formControlName],select:not([multiple]):not([ngNoCva])[formControl],select:not([multiple]):not([ngNoCva])[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.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { 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: i2.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "browserUrl", "routerLink"] }, { kind: "directive", type: i3.ValidationGroupDirective, selector: "[formGroup],[formGroupName]", exportAs: ["validationGroup"] }, { kind: "directive", type: i3.ValidationDirective, selector: "[formControl],[formControlName]", exportAs: ["validationDirective"] }, { kind: "directive", type: i4.PermissionDirective, selector: "[abpPermission]", inputs: ["abpPermission", "abpPermissionRunChangeDetection"] }, { kind: "ngmodule", type: ThemeSharedModule }, { kind: "component", type: i2$1.ButtonComponent, selector: "abp-button", inputs: ["buttonId", "buttonClass", "buttonType", "formName", "iconClass", "loading", "disabled", "attributes"], outputs: ["click", "focus", "blur", "abpClick", "abpFocus", "abpBlur"] }, { kind: "component", type: i2$1.ModalComponent, selector: "abp-modal", inputs: ["visible", "busy", "options", "suppressUnsavedChangesWarning"], outputs: ["visibleChange", "init", "appear", "disappear"] }, { kind: "directive", type: i2$1.ModalCloseDirective, selector: "[abpClose]" }, { kind: "component", type: i6.DatatableComponent, selector: "ngx-datatable", inputs: ["targetMarkerTemplate", "rows", "groupRowsBy", "groupedRows", "columns", "selected", "scrollbarV", "scrollbarVDynamic", "scrollbarH", "rowHeight", "columnMode", "headerHeight", "footerHeight", "externalPaging", "externalSorting", "limit", "count", "offset", "loadingIndicator", "ghostLoadingIndicator", "selectionType", "reorderable", "swapColumns", "sortType", "sorts", "cssClasses", "messages", "rowClass", "selectCheck", "displayCheck", "groupExpansionDefault", "trackByProp", "selectAllRowsOnPage", "virtualization", "treeFromRelation", "treeToRelation", "summaryRow", "summaryHeight", "summaryPosition", "disableRowCheck", "rowDraggable", "enableClearingSortState", "rowIdentity"], outputs: ["scroll", "activate", "select", "sort", "page", "reorder", "resize", "tableContextmenu", "treeAction", "rowDragEvents"] }, { kind: "directive", type: i6.DataTableColumnDirective, selector: "ngx-datatable-column", inputs: ["name", "prop", "bindAsUnsafeHtml", "frozenLeft", "frozenRight", "flexGrow", "resizeable", "comparator", "pipe", "sortable", "draggable", "canAutoResize", "minWidth", "width", "maxWidth", "checkboxable", "headerCheckboxable", "headerClass", "cellClass", "isTreeColumn", "treeLevelIndent", "summaryFunc", "summaryTemplate", "cellTemplate", "headerTemplate", "treeToggleTemplate", "ghostCellTemplate"] }, { kind: "directive", type: i6.DataTableColumnCellDirective, selector: "[ngx-datatable-cell-template]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "ngmodule", type: NgxDatatableModule }, { kind: "ngmodule", type: NzTreeSelectModule }, { kind: "component", type: i8.NzTreeSelectComponent, selector: "nz-tree-select", inputs: ["nzId", "nzAllowClear", "nzShowExpand", "nzShowLine", "nzDropdownMatchSelectWidth", "nzCheckable", "nzHideUnMatched", "nzShowIcon", "nzShowSearch", "nzDisabled", "nzAsyncData", "nzMultiple", "nzDefaultExpandAll", "nzCheckStrictly", "nzVirtualItemSize", "nzVirtualMaxBufferPx", "nzVirtualMinBufferPx", "nzVirtualHeight", "nzExpandedIcon", "nzNotFoundContent", "nzNodes", "nzOpen", "nzSize", "nzVariant", "nzPlaceHolder", "nzDropdownStyle", "nzDropdownClassName", "nzBackdrop", "nzStatus", "nzPlacement", "nzExpandedKeys", "nzPrefix", "nzSuffixIcon", "nzDisplayWith", "nzMaxTagCount", "nzMaxTagPlaceholder", "nzTreeTemplate"], outputs: ["nzOpenChange", "nzCleared", "nzRemoved", "nzExpandChange", "nzTreeClick", "nzTreeCheckboxChange"], exportAs: ["nzTreeSelect"] }, { kind: "pipe", type: i4.LocalizationPipe, name: "abpLocalization" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
217
+ }
218
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.2.2", ngImport: i0, type: PagesComponent, decorators: [{
219
+ type: Component,
220
+ args: [{ selector: 'site-pages', changeDetection: ChangeDetectionStrategy.OnPush, imports: [
221
+ CoreModule,
222
+ ThemeSharedModule,
223
+ ReactiveFormsModule,
224
+ NgxDatatableModule,
225
+ NzTreeSelectModule,
226
+ PermissionDirective,
227
+ RouterLink,
228
+ ], template: "<div class=\"card mb-3\">\n <div class=\"card-body\">\n <div class=\"row align-items-end g-2\">\n <div class=\"col-md-3\">\n <label class=\"form-label\">{{ 'Site::DisplayName:Page.IsActive' | abpLocalization }}</label>\n <select class=\"form-select\" [(ngModel)]=\"filters.isActive\" (change)=\"applyFilters()\">\n <option [ngValue]=\"undefined\">--</option>\n <option [ngValue]=\"true\">{{ 'AbpUi::Yes' | abpLocalization }}</option>\n <option [ngValue]=\"false\">{{ 'AbpUi::No' | abpLocalization }}</option>\n </select>\n </div>\n <div class=\"col-md-5\">\n <label class=\"form-label\">{{ 'AbpUi::Search' | abpLocalization }}</label>\n <input\n type=\"text\"\n class=\"form-control\"\n [(ngModel)]=\"filters.filter\"\n (keyup.enter)=\"applyFilters()\"\n [placeholder]=\"'AbpUi::Search' | abpLocalization\"\n />\n </div>\n <div class=\"col-md-4\">\n <button type=\"button\" class=\"btn btn-primary me-2\" (click)=\"applyFilters()\">\n <i class=\"fa fa-search me-1\"></i>{{ 'AbpUi::Search' | abpLocalization }}\n </button>\n <button type=\"button\" class=\"btn btn-outline-secondary\" (click)=\"clearFilters()\">\n {{ 'AbpUi::Clear' | abpLocalization }}\n </button>\n </div>\n </div>\n </div>\n</div>\n\n<div class=\"card\">\n <div class=\"card-body\">\n <div class=\"d-flex justify-content-between align-items-center mb-3\">\n <h5 class=\"mb-0\">{{ 'Site::Pages' | abpLocalization }}</h5>\n <button\n *abpPermission=\"policies.PagesCreate\"\n type=\"button\"\n class=\"btn btn-primary\"\n (click)=\"openCreate()\"\n >\n <i class=\"fa fa-plus me-1\"></i>{{ 'Site::NewPage' | abpLocalization }}\n </button>\n </div>\n\n <ngx-datatable\n class=\"material\"\n [rows]=\"data().items\"\n columnMode=\"flex\"\n [headerHeight]=\"42\"\n [footerHeight]=\"42\"\n rowHeight=\"auto\"\n treeFromRelation=\"parentId\"\n treeToRelation=\"id\"\n (treeAction)=\"onTreeAction($event)\"\n >\n <ngx-datatable-column\n prop=\"displayName\"\n [flexGrow]=\"2\"\n [isTreeColumn]=\"true\"\n [treeLevelIndent]=\"20\"\n [name]=\"'Site::DisplayName:Page.DisplayName' | abpLocalization\"\n >\n <ng-template\n let-row=\"row\"\n let-treeStatus=\"treeStatus\"\n let-onTreeAction=\"onTreeAction\"\n ngx-datatable-cell-template\n >\n @if (hasChildren(row)) {\n <button type=\"button\" class=\"page-tree-toggle\" (click)=\"onTreeAction()\">\n <i\n class=\"fa\"\n [ngClass]=\"treeStatus === 'collapsed' ? 'fa-caret-right' : 'fa-caret-down'\"\n ></i>\n </button>\n }\n {{ row.displayName }}\n </ng-template>\n </ngx-datatable-column>\n <ngx-datatable-column\n prop=\"name\"\n [flexGrow]=\"2\"\n [name]=\"'Site::DisplayName:Page.Name' | abpLocalization\"\n ></ngx-datatable-column>\n <ngx-datatable-column\n prop=\"route\"\n [flexGrow]=\"2\"\n [name]=\"'Site::DisplayName:Page.Route' | abpLocalization\"\n ></ngx-datatable-column>\n <ngx-datatable-column\n [flexGrow]=\"1\"\n [name]=\"'Site::DisplayName:Page.IsActive' | abpLocalization\"\n [sortable]=\"false\"\n >\n <ng-template let-row=\"row\" ngx-datatable-cell-template>\n <i class=\"fa\" [ngClass]=\"row.isActive ? 'fa-check text-success' : 'fa-times text-muted'\"></i>\n </ng-template>\n </ngx-datatable-column>\n <ngx-datatable-column [flexGrow]=\"2\" [sortable]=\"false\" [name]=\"'AbpUi::Actions' | abpLocalization\">\n <ng-template let-row=\"row\" ngx-datatable-cell-template>\n <a\n *abpPermission=\"policies.ContentTypes\"\n class=\"btn btn-sm btn-light me-1\"\n [routerLink]=\"['/site/pages', row.id, 'content-types']\"\n [title]=\"'Site::ContentTypes' | abpLocalization\"\n >\n <i class=\"fa fa-sitemap\"></i>\n </a>\n <button\n *abpPermission=\"policies.PagesUpdate\"\n type=\"button\"\n class=\"btn btn-sm btn-light me-1\"\n (click)=\"openEdit(row)\"\n [title]=\"'AbpUi::Edit' | abpLocalization\"\n >\n <i class=\"fa fa-pencil\"></i>\n </button>\n <button\n *abpPermission=\"policies.PagesDelete\"\n type=\"button\"\n class=\"btn btn-sm btn-light\"\n (click)=\"delete(row)\"\n [title]=\"'AbpUi::Delete' | abpLocalization\"\n >\n <i class=\"fa fa-trash text-danger\"></i>\n </button>\n </ng-template>\n </ngx-datatable-column>\n </ngx-datatable>\n </div>\n</div>\n\n<abp-modal [(visible)]=\"isModalOpen\" [busy]=\"isModalBusy()\" (disappear)=\"closeModal()\">\n <ng-template #abpHeader>\n <h3>{{ (editingPage ? 'Site::EditPage' : 'Site::NewPage') | abpLocalization }}</h3>\n </ng-template>\n <ng-template #abpBody>\n @if (form) {\n <form [formGroup]=\"form\" (submit)=\"save()\">\n <button type=\"submit\" #submitButton style=\"display: none\"></button>\n\n <div class=\"mb-3\">\n <label class=\"form-label\">{{ 'Site::DisplayName:Page.DisplayName' | abpLocalization }}</label>\n <input type=\"text\" class=\"form-control\" formControlName=\"displayName\" />\n </div>\n <div class=\"mb-3\">\n <label class=\"form-label\">{{ 'Site::DisplayName:Page.Name' | abpLocalization }}</label>\n <input type=\"text\" class=\"form-control\" formControlName=\"name\" />\n <small class=\"form-text text-muted\">\n {{ 'Site::Description:Page.Name' | abpLocalization }}\n </small>\n </div>\n <div class=\"mb-3\">\n <label class=\"form-label\">{{ 'Site::DisplayName:Page.Route' | abpLocalization }}</label>\n <input type=\"text\" class=\"form-control\" formControlName=\"route\" />\n <small class=\"form-text text-muted\">\n {{ 'Site::Description:Page.Route' | abpLocalization }}\n </small>\n </div>\n <div class=\"mb-3\">\n <label class=\"form-label\">{{ 'Site::DisplayName:Page.Template' | abpLocalization }}</label>\n <input type=\"text\" class=\"form-control\" formControlName=\"template\" />\n <small class=\"form-text text-muted\">\n {{ 'Site::Description:Page.Template' | abpLocalization }}\n </small>\n </div>\n <div class=\"mb-3\">\n <label class=\"form-label\">{{ 'Site::DisplayName:Page.ParentId' | abpLocalization }}</label>\n <nz-tree-select\n class=\"form-select parent-picker-select\"\n formControlName=\"parentId\"\n [nzNodes]=\"parentTreeNodes\"\n nzAllowClear\n nzShowSearch\n nzDefaultExpandAll\n nzDropdownClassName=\"parent-picker-dropdown\"\n [nzPlaceHolder]=\"'Site::DisplayName:Page.ParentId' | abpLocalization\"\n ></nz-tree-select>\n <small class=\"form-text text-muted\">\n {{ 'Site::Description:Page.ParentId' | abpLocalization }}\n </small>\n </div>\n <div class=\"form-check\">\n <input\n type=\"checkbox\"\n class=\"form-check-input\"\n id=\"site-page-is-active\"\n formControlName=\"isActive\"\n />\n <label class=\"form-check-label\" for=\"site-page-is-active\">\n {{ 'Site::DisplayName:Page.IsActive' | abpLocalization }}\n </label>\n </div>\n </form>\n }\n </ng-template>\n <ng-template #abpFooter>\n <button type=\"button\" class=\"btn btn-secondary\" abpClose>\n {{ 'AbpUi::Cancel' | abpLocalization }}\n </button>\n <abp-button\n iconClass=\"fa fa-check\"\n [disabled]=\"!form?.valid\"\n [loading]=\"isModalBusy()\"\n (click)=\"submitButton?.nativeElement?.click()\"\n >\n {{ 'AbpUi::Save' | abpLocalization }}\n </abp-button>\n </ng-template>\n</abp-modal>\n", styles: [":host ::ng-deep .datatable-tree-button{display:none}.page-tree-toggle{border:none;background:transparent;padding:0;width:16px;cursor:pointer;color:inherit}::ng-deep .parent-picker-select{width:100%}::ng-deep .parent-picker-select.ant-select{color:inherit!important;height:unset!important;font-size:unset!important;--bs-form-select-bg-img: unset !important}::ng-deep .parent-picker-select .ant-select-selector{background:transparent!important;border:none!important;padding:.475rem 1.25rem!important;box-shadow:none!important;height:auto!important}::ng-deep .parent-picker-select .ant-select-selection-placeholder{color:inherit!important}::ng-deep .parent-picker-select.form-select{padding:0!important}::ng-deep .parent-picker-dropdown.ant-select-dropdown{background:var(--lpx-content-bg, var(--bs-secondary-bg, #fff))!important}::ng-deep .parent-picker-dropdown .ant-select-tree-node-content-wrapper:hover{background-color:var(--bs-primary)!important;color:var(--bs-white)!important}::ng-deep .parent-picker-dropdown .ant-select-tree-node-content-wrapper.ant-select-tree-node-selected{background-color:var(--lpx-brand)!important;color:var(--bs-white)!important}::ng-deep .parent-picker-dropdown .ant-select-tree{color:var(--bs-body-color)!important;background-color:transparent!important}\n"] }]
229
+ }], ctorParameters: () => [], propDecorators: { submitButton: [{
230
+ type: ViewChild,
231
+ args: ['submitButton']
232
+ }] } });
233
+
234
+ export { PagesComponent };
235
+ //# sourceMappingURL=dignite-ng.site-pages.component-S9BEgC4W.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dignite-ng.site-pages.component-S9BEgC4W.mjs","sources":["../../../projects/site/src/lib/components/pages/pages.component.ts","../../../projects/site/src/lib/components/pages/pages.component.html"],"sourcesContent":["import { CoreModule, ListResultDto, PermissionDirective, PermissionService } from '@abp/ng.core';\nimport {\n Confirmation,\n ConfirmationService,\n ThemeSharedModule,\n ToasterService,\n} from '@abp/ng.theme.shared';\nimport { NgxDatatableModule } from '@swimlane/ngx-datatable';\nimport type { TreeStatus } from '@swimlane/ngx-datatable';\nimport {\n Component,\n ElementRef,\n ViewChild,\n inject,\n signal,\n ChangeDetectionStrategy,\n} from '@angular/core';\nimport { FormBuilder, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';\nimport { Router, RouterLink } from '@angular/router';\nimport { NzTreeSelectModule } from 'ng-zorro-antd/tree-select';\nimport type { NzTreeNodeOptions } from 'ng-zorro-antd/tree';\nimport { PageAdminService } from '../../proxy/dignite/site/admin/pages/page-admin.service';\nimport type { GetPageListInput } from '../../proxy/dignite/site/admin/pages/models';\nimport type { PageDto } from '../../proxy/dignite/site/pages/models';\nimport { eSitePolicyNames } from '../../enums/policy-names';\n\n/** Max lengths mirror `PageConsts` (`src/Dignite.Site.Domain.Shared/Pages/PageConsts.cs`). */\nconst PAGE_CONSTS = {\n maxNameLength: 64,\n maxDisplayNameLength: 128,\n maxRouteLength: 512,\n maxTemplateLength: 256,\n} as const;\n\n/** Mirrors `IdentifierName.Pattern` (`src/Dignite.Site.Domain.Shared/IdentifierName.cs`). */\nconst NAME_PATTERN = /^[a-z0-9][a-z0-9_-]*$/;\n\n/** Mirrors `PageConsts.RoutePattern`. */\nconst ROUTE_PATTERN = /^\\S+$/;\n\n/** Mirrors `PageConsts.TemplatePattern`. Required - at least one character - since `template` is required. */\nconst TEMPLATE_PATTERN = /^\\/?[A-Za-z0-9_][A-Za-z0-9_/-]*$/;\n\n/** A page, plus the expand/collapse state `ngx-datatable`'s tree mode keeps on each row. */\ntype PageRow = PageDto & { treeStatus?: TreeStatus };\n\n@Component({\n selector: 'site-pages',\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './pages.component.html',\n imports: [\n CoreModule,\n ThemeSharedModule,\n ReactiveFormsModule,\n NgxDatatableModule,\n NzTreeSelectModule,\n PermissionDirective,\n RouterLink,\n ],\n styles: `\n /* ngx-datatable always renders its own .datatable-tree-button for every row in the tree column,\n with no chrome reset (bare native <button>) and no way to suppress it for a childless row -\n [treeToggleTemplate] is documented to override it but does not take effect in this library\n version (tried both content-projection via ngx-datatable-tree-toggle and a direct\n [treeToggleTemplate] binding; neither replaced the default). Hidden here instead, with our own\n toggle built into the column's ngx-datatable-cell-template - see pages.component.html - which\n only renders one when hasChildren() says there is something to expand. */\n :host ::ng-deep .datatable-tree-button {\n display: none;\n }\n\n .page-tree-toggle {\n border: none;\n background: transparent;\n padding: 0;\n width: 16px;\n cursor: pointer;\n color: inherit;\n }\n\n /* Dresses nz-tree-select up as a Bootstrap .form-select, matching field-arrangement.component.ts's\n .field-picker-select for the same reason: ng-zorro's own look does not match the plain\n .form-control/.form-select styling of every other field in this form.\n\n Plain ::ng-deep, not :host ::ng-deep - this form lives inside abp-modal, which ng-bootstrap\n renders as an NgbModalWindow appended straight to <body>, outside <site-pages>'s own DOM\n subtree. A :host-scoped rule compiles to an attribute-selector prefix scoped to this\n component's own host element, which can only ever match a descendant of that element - never\n true here, so the rule silently never applied and the select fell back to ng-zorro's raw\n styling (a barely 8px-tall selector box, nothing like the surrounding .form-control fields).\n The .parent-picker-dropdown rules below already got this right; these four did not. */\n ::ng-deep .parent-picker-select {\n width: 100%;\n }\n ::ng-deep .parent-picker-select.ant-select {\n color: inherit !important;\n height:unset !important;\n font-size: unset !important;\n --bs-form-select-bg-img: unset !important;\n }\n ::ng-deep .parent-picker-select .ant-select-selector {\n background: transparent !important;\n border: none !important;\n padding: 0.475rem 1.25rem !important;\n box-shadow: none !important;\n height: auto !important;\n }\n ::ng-deep .parent-picker-select .ant-select-selection-placeholder {\n color: inherit !important;\n }\n ::ng-deep .parent-picker-select.form-select {\n padding: 0 !important;\n }\n /* Compound, not descendant - nz-tree-select builds one class STRING (\"ant-select-dropdown\n ant-select-tree-dropdown parent-picker-dropdown\") and binds it with [class] on a single <div>\n (see NzTreeSelectComponent's dropdownClassName/ngOnChanges in ng-zorro-antd-tree-select.mjs),\n unlike nz-select, which puts nzDropdownClassName on the ancestor .cdk-overlay-pane via\n [cdkConnectedOverlayPanelClass] (see field-arrangement.component.ts's identically-shaped rule,\n which is a real ancestor-descendant match). \".parent-picker-dropdown .ant-select-dropdown\"\n (with a space) asks for .ant-select-dropdown *inside* .parent-picker-dropdown, but they're the\n same element here, so that never matched anything and this panel stayed on ant-design's own\n white default no matter what the nested rules below did. */\n /* --lpx-content-bg is a FULL LeptonX token (@volosoft/ngx-lepton-x: #f0f4f7 light, #121212 dark).\n LeptonX *Lite* - @volo/ngx-lepton-x.lite, what @abp/ng.theme.lepton-x wraps, and what this app\n actually runs - never defines it: it ships 11 --lpx-* tokens and this is not one of them. The\n chain therefore fell straight through to the literal #fff and this panel stayed white in every\n theme, while .ant-select-item/-tree below kept following --bs-body-color into light-grey-on-\n white. --bs-secondary-bg is the Bootstrap 5.3 \"one step off the body surface\" token, defined at\n :root by every Bootstrap-based theme and redefined under [data-bs-theme=dark] (#e9ecef ->\n #343a40 in Lite), so it flips with the host. Light mode moves from pure white to #e9ecef. */\n ::ng-deep .parent-picker-dropdown.ant-select-dropdown {\n background: var(--lpx-content-bg, var(--bs-secondary-bg, #fff)) !important;\n }\n /* nz-tree's per-node classes drop the \"select-\" infix outside of a select's dropdown\n (NzTreeNodeComponent's host bindings key every tree class off selectMode - see\n ng-zorro-antd-tree.mjs) - nz-tree-select's own embedded tree always runs in select mode, so\n its nodes carry ant-select-tree-node-content-wrapper/-selected, never the plain\n ant-tree-node-* classes a standalone <nz-tree> would use. The un-prefixed selectors here\n matched nothing, silently leaving every node on ant-design's own default colors. */\n ::ng-deep .parent-picker-dropdown .ant-select-tree-node-content-wrapper:hover {\n background-color: var(--bs-primary) !important;\n color: var(--bs-white) !important;\n }\n ::ng-deep .parent-picker-dropdown .ant-select-tree-node-content-wrapper.ant-select-tree-node-selected {\n background-color: var(--lpx-brand) !important;\n color: var(--bs-white) !important;\n }\n /* !important, matching every other rule in this block - ant-design's own .ant-select-tree rule\n (background: #fff, color: rgba(0,0,0,.85)) carries the same one-class specificity as this\n override, and its stylesheet is injected lazily when nz-tree-select first opens, i.e. after\n this component's styles - a same-specificity tie that source order was resolving in its\n favor, keeping idle (non-hover, non-selected) nodes on ant-design's white/dark-gray default. */\n ::ng-deep .parent-picker-dropdown .ant-select-tree {\n color: var(--bs-body-color) !important;\n background-color: transparent !important;\n }\n `,\n})\nexport class PagesComponent {\n private readonly pageService = inject(PageAdminService);\n private readonly fb = inject(FormBuilder);\n private readonly confirmation = inject(ConfirmationService);\n private readonly toaster = inject(ToasterService);\n private readonly router = inject(Router);\n private readonly permission = inject(PermissionService);\n\n readonly policies = eSitePolicyNames;\n\n /**\n * The whole (filtered) result set, unpaged - the datatable paginates it client-side.\n *\n * State that changes in an HTTP callback (this, and the modal flags below) is a signal, not a plain\n * field: the host layout's ancestors (`abp-router-outlet`, the LeptonX layouts) are OnPush, and a\n * plain-field write in a response callback never marks them for check, so the list would stay empty\n * until some unrelated event happened to.\n */\n readonly data = signal<ListResultDto<PageRow>>({ items: [] });\n filters = {} as GetPageListInput;\n\n readonly isModalOpen = signal(false);\n readonly isModalBusy = signal(false);\n editingPage?: PageDto;\n form?: FormGroup;\n\n @ViewChild('submitButton') submitButton?: ElementRef<HTMLButtonElement>;\n\n constructor() {\n this.applyFilters();\n }\n\n /** Whether the tree-toggle template should render a toggle for this row at all. */\n hasChildren(row: PageRow): boolean {\n return this.data().items.some(page => page.parentId === row.id);\n }\n\n applyFilters(): void {\n this.pageService.getList(this.filters).subscribe(result => {\n // A page's parentId can point at a page the current filter excludes (isActive/filter are\n // backend params, so a match can survive while its parent does not). Rather than let such a\n // row vanish from the tree, it renders at the root - normalized here once so every reader of\n // `data().items` (the datatable's tree grouping, the tree-select's candidate list) sees a\n // consistent, dangling-free parentId.\n const ids = new Set(result.items.map(page => page.id));\n\n this.data.set({\n items: result.items.map(page => ({\n ...page,\n parentId: page.parentId && ids.has(page.parentId) ? page.parentId : null,\n treeStatus: 'expanded' as TreeStatus,\n })),\n });\n });\n }\n\n clearFilters(): void {\n this.filters = {} as GetPageListInput;\n this.applyFilters();\n }\n\n /** Toggles one row's branch. `ngx-datatable` reads `treeStatus` off the row it is given back. */\n onTreeAction(event: { row: PageRow }): void {\n event.row.treeStatus = event.row.treeStatus === 'collapsed' ? 'expanded' : 'collapsed';\n this.data.set({ items: [...this.data().items] });\n }\n\n openCreate(): void {\n this.editingPage = undefined;\n this.form = this.buildForm();\n this.isModalOpen.set(true);\n }\n\n openEdit(page: PageDto): void {\n this.editingPage = page;\n this.form = this.buildForm(page);\n this.isModalOpen.set(true);\n }\n\n closeModal(): void {\n this.isModalOpen.set(false);\n this.form = undefined;\n this.editingPage = undefined;\n }\n\n save(): void {\n if (!this.form || this.form.invalid || this.isModalBusy()) {\n return;\n }\n\n this.isModalBusy.set(true);\n const value = this.form.getRawValue();\n const isCreating = !this.editingPage;\n\n const request$ = this.editingPage\n ? this.pageService.update(this.editingPage.id!, value)\n : this.pageService.create(value);\n\n request$.subscribe({\n next: page => {\n this.isModalBusy.set(false);\n this.closeModal();\n this.toaster.success('AbpUi::SavedSuccessfully');\n\n // A fresh page always has exactly one auto-created content type\n // (PageAdminAppService.CreateDefaultContentTypeAsync) still waiting for its fields - go straight\n // there instead of leaving the user to find the sitemap icon themselves.\n if (isCreating && this.permission.getGrantedPolicy(this.policies.ContentTypes)) {\n this.router.navigate(['/site/pages', page.id, 'content-types']);\n return;\n }\n\n this.applyFilters();\n },\n error: () => this.isModalBusy.set(false),\n });\n }\n\n delete(page: PageDto): void {\n this.confirmation\n .warn('AbpUi::ItemWillBeDeletedMessage', 'AbpUi::AreYouSure', {\n messageLocalizationParams: [page.displayName ?? ''],\n })\n .subscribe((status: Confirmation.Status) => {\n if (status === Confirmation.Status.confirm) {\n this.pageService.delete(page.id!).subscribe(() => {\n this.applyFilters();\n this.toaster.success('AbpUi::SuccessfullyDeleted');\n });\n }\n });\n }\n\n private parentTreeNodesCache?: {\n items: PageRow[];\n editingId: string | undefined;\n nodes: NzTreeNodeOptions[];\n };\n\n /**\n * The \"Parent page\" picker's candidates: every page except the one being edited and its own\n * subtree - offering either as a choice would only trade a clean rejection in the picker for a\n * `PageParentCycleException` from the server.\n *\n * Cached against a cheap key, not recomputed every read, for the same reason\n * `field-arrangement.component.ts`'s `addableFieldOptions` is: `nz-tree-select` expects a stable\n * array reference, and a plain rebuild here would hand it a fresh one on every change-detection\n * cycle, including the ones firing while its dropdown is open.\n */\n get parentTreeNodes(): NzTreeNodeOptions[] {\n const editingId = this.editingPage?.id;\n const items = this.data().items;\n\n if (\n this.parentTreeNodesCache?.items !== items ||\n this.parentTreeNodesCache?.editingId !== editingId\n ) {\n const excluded = editingId ? this.subtreeIds(editingId) : new Set<string>();\n this.parentTreeNodesCache = {\n items,\n editingId,\n nodes: this.buildTreeNodes(null, excluded),\n };\n }\n\n return this.parentTreeNodesCache.nodes;\n }\n\n /** `rootId` and everything beneath it, found by repeatedly sweeping for newly-matched children. */\n private subtreeIds(rootId: string): Set<string> {\n const ids = new Set<string>([rootId]);\n\n for (let grew = true; grew; ) {\n grew = false;\n for (const page of this.data().items) {\n if (page.parentId && ids.has(page.parentId) && !ids.has(page.id!)) {\n ids.add(page.id!);\n grew = true;\n }\n }\n }\n\n return ids;\n }\n\n private buildTreeNodes(parentId: string | null, excluded: Set<string>): NzTreeNodeOptions[] {\n const items = this.data().items;\n\n return items\n .filter(page => (page.parentId ?? null) === parentId && !excluded.has(page.id!))\n .map(page => ({\n key: page.id!,\n title: page.displayName || page.name || '',\n children: this.buildTreeNodes(page.id!, excluded),\n isLeaf: !items.some(child => child.parentId === page.id),\n }));\n }\n\n private buildForm(page?: PageDto): FormGroup {\n return this.fb.group({\n name: [\n page?.name ?? '',\n [Validators.required, Validators.maxLength(PAGE_CONSTS.maxNameLength), Validators.pattern(NAME_PATTERN)],\n ],\n displayName: [\n page?.displayName ?? '',\n [Validators.required, Validators.maxLength(PAGE_CONSTS.maxDisplayNameLength)],\n ],\n route: [\n page?.route ?? '',\n [Validators.required, Validators.maxLength(PAGE_CONSTS.maxRouteLength), Validators.pattern(ROUTE_PATTERN)],\n ],\n template: [\n page?.template ?? '',\n [Validators.required, Validators.maxLength(PAGE_CONSTS.maxTemplateLength), Validators.pattern(TEMPLATE_PATTERN)],\n ],\n parentId: [page?.parentId ?? null],\n isActive: [page?.isActive ?? true],\n });\n }\n}\n","<div class=\"card mb-3\">\n <div class=\"card-body\">\n <div class=\"row align-items-end g-2\">\n <div class=\"col-md-3\">\n <label class=\"form-label\">{{ 'Site::DisplayName:Page.IsActive' | abpLocalization }}</label>\n <select class=\"form-select\" [(ngModel)]=\"filters.isActive\" (change)=\"applyFilters()\">\n <option [ngValue]=\"undefined\">--</option>\n <option [ngValue]=\"true\">{{ 'AbpUi::Yes' | abpLocalization }}</option>\n <option [ngValue]=\"false\">{{ 'AbpUi::No' | abpLocalization }}</option>\n </select>\n </div>\n <div class=\"col-md-5\">\n <label class=\"form-label\">{{ 'AbpUi::Search' | abpLocalization }}</label>\n <input\n type=\"text\"\n class=\"form-control\"\n [(ngModel)]=\"filters.filter\"\n (keyup.enter)=\"applyFilters()\"\n [placeholder]=\"'AbpUi::Search' | abpLocalization\"\n />\n </div>\n <div class=\"col-md-4\">\n <button type=\"button\" class=\"btn btn-primary me-2\" (click)=\"applyFilters()\">\n <i class=\"fa fa-search me-1\"></i>{{ 'AbpUi::Search' | abpLocalization }}\n </button>\n <button type=\"button\" class=\"btn btn-outline-secondary\" (click)=\"clearFilters()\">\n {{ 'AbpUi::Clear' | abpLocalization }}\n </button>\n </div>\n </div>\n </div>\n</div>\n\n<div class=\"card\">\n <div class=\"card-body\">\n <div class=\"d-flex justify-content-between align-items-center mb-3\">\n <h5 class=\"mb-0\">{{ 'Site::Pages' | abpLocalization }}</h5>\n <button\n *abpPermission=\"policies.PagesCreate\"\n type=\"button\"\n class=\"btn btn-primary\"\n (click)=\"openCreate()\"\n >\n <i class=\"fa fa-plus me-1\"></i>{{ 'Site::NewPage' | abpLocalization }}\n </button>\n </div>\n\n <ngx-datatable\n class=\"material\"\n [rows]=\"data().items\"\n columnMode=\"flex\"\n [headerHeight]=\"42\"\n [footerHeight]=\"42\"\n rowHeight=\"auto\"\n treeFromRelation=\"parentId\"\n treeToRelation=\"id\"\n (treeAction)=\"onTreeAction($event)\"\n >\n <ngx-datatable-column\n prop=\"displayName\"\n [flexGrow]=\"2\"\n [isTreeColumn]=\"true\"\n [treeLevelIndent]=\"20\"\n [name]=\"'Site::DisplayName:Page.DisplayName' | abpLocalization\"\n >\n <ng-template\n let-row=\"row\"\n let-treeStatus=\"treeStatus\"\n let-onTreeAction=\"onTreeAction\"\n ngx-datatable-cell-template\n >\n @if (hasChildren(row)) {\n <button type=\"button\" class=\"page-tree-toggle\" (click)=\"onTreeAction()\">\n <i\n class=\"fa\"\n [ngClass]=\"treeStatus === 'collapsed' ? 'fa-caret-right' : 'fa-caret-down'\"\n ></i>\n </button>\n }\n {{ row.displayName }}\n </ng-template>\n </ngx-datatable-column>\n <ngx-datatable-column\n prop=\"name\"\n [flexGrow]=\"2\"\n [name]=\"'Site::DisplayName:Page.Name' | abpLocalization\"\n ></ngx-datatable-column>\n <ngx-datatable-column\n prop=\"route\"\n [flexGrow]=\"2\"\n [name]=\"'Site::DisplayName:Page.Route' | abpLocalization\"\n ></ngx-datatable-column>\n <ngx-datatable-column\n [flexGrow]=\"1\"\n [name]=\"'Site::DisplayName:Page.IsActive' | abpLocalization\"\n [sortable]=\"false\"\n >\n <ng-template let-row=\"row\" ngx-datatable-cell-template>\n <i class=\"fa\" [ngClass]=\"row.isActive ? 'fa-check text-success' : 'fa-times text-muted'\"></i>\n </ng-template>\n </ngx-datatable-column>\n <ngx-datatable-column [flexGrow]=\"2\" [sortable]=\"false\" [name]=\"'AbpUi::Actions' | abpLocalization\">\n <ng-template let-row=\"row\" ngx-datatable-cell-template>\n <a\n *abpPermission=\"policies.ContentTypes\"\n class=\"btn btn-sm btn-light me-1\"\n [routerLink]=\"['/site/pages', row.id, 'content-types']\"\n [title]=\"'Site::ContentTypes' | abpLocalization\"\n >\n <i class=\"fa fa-sitemap\"></i>\n </a>\n <button\n *abpPermission=\"policies.PagesUpdate\"\n type=\"button\"\n class=\"btn btn-sm btn-light me-1\"\n (click)=\"openEdit(row)\"\n [title]=\"'AbpUi::Edit' | abpLocalization\"\n >\n <i class=\"fa fa-pencil\"></i>\n </button>\n <button\n *abpPermission=\"policies.PagesDelete\"\n type=\"button\"\n class=\"btn btn-sm btn-light\"\n (click)=\"delete(row)\"\n [title]=\"'AbpUi::Delete' | abpLocalization\"\n >\n <i class=\"fa fa-trash text-danger\"></i>\n </button>\n </ng-template>\n </ngx-datatable-column>\n </ngx-datatable>\n </div>\n</div>\n\n<abp-modal [(visible)]=\"isModalOpen\" [busy]=\"isModalBusy()\" (disappear)=\"closeModal()\">\n <ng-template #abpHeader>\n <h3>{{ (editingPage ? 'Site::EditPage' : 'Site::NewPage') | abpLocalization }}</h3>\n </ng-template>\n <ng-template #abpBody>\n @if (form) {\n <form [formGroup]=\"form\" (submit)=\"save()\">\n <button type=\"submit\" #submitButton style=\"display: none\"></button>\n\n <div class=\"mb-3\">\n <label class=\"form-label\">{{ 'Site::DisplayName:Page.DisplayName' | abpLocalization }}</label>\n <input type=\"text\" class=\"form-control\" formControlName=\"displayName\" />\n </div>\n <div class=\"mb-3\">\n <label class=\"form-label\">{{ 'Site::DisplayName:Page.Name' | abpLocalization }}</label>\n <input type=\"text\" class=\"form-control\" formControlName=\"name\" />\n <small class=\"form-text text-muted\">\n {{ 'Site::Description:Page.Name' | abpLocalization }}\n </small>\n </div>\n <div class=\"mb-3\">\n <label class=\"form-label\">{{ 'Site::DisplayName:Page.Route' | abpLocalization }}</label>\n <input type=\"text\" class=\"form-control\" formControlName=\"route\" />\n <small class=\"form-text text-muted\">\n {{ 'Site::Description:Page.Route' | abpLocalization }}\n </small>\n </div>\n <div class=\"mb-3\">\n <label class=\"form-label\">{{ 'Site::DisplayName:Page.Template' | abpLocalization }}</label>\n <input type=\"text\" class=\"form-control\" formControlName=\"template\" />\n <small class=\"form-text text-muted\">\n {{ 'Site::Description:Page.Template' | abpLocalization }}\n </small>\n </div>\n <div class=\"mb-3\">\n <label class=\"form-label\">{{ 'Site::DisplayName:Page.ParentId' | abpLocalization }}</label>\n <nz-tree-select\n class=\"form-select parent-picker-select\"\n formControlName=\"parentId\"\n [nzNodes]=\"parentTreeNodes\"\n nzAllowClear\n nzShowSearch\n nzDefaultExpandAll\n nzDropdownClassName=\"parent-picker-dropdown\"\n [nzPlaceHolder]=\"'Site::DisplayName:Page.ParentId' | abpLocalization\"\n ></nz-tree-select>\n <small class=\"form-text text-muted\">\n {{ 'Site::Description:Page.ParentId' | abpLocalization }}\n </small>\n </div>\n <div class=\"form-check\">\n <input\n type=\"checkbox\"\n class=\"form-check-input\"\n id=\"site-page-is-active\"\n formControlName=\"isActive\"\n />\n <label class=\"form-check-label\" for=\"site-page-is-active\">\n {{ 'Site::DisplayName:Page.IsActive' | abpLocalization }}\n </label>\n </div>\n </form>\n }\n </ng-template>\n <ng-template #abpFooter>\n <button type=\"button\" class=\"btn btn-secondary\" abpClose>\n {{ 'AbpUi::Cancel' | abpLocalization }}\n </button>\n <abp-button\n iconClass=\"fa fa-check\"\n [disabled]=\"!form?.valid\"\n [loading]=\"isModalBusy()\"\n (click)=\"submitButton?.nativeElement?.click()\"\n >\n {{ 'AbpUi::Save' | abpLocalization }}\n </abp-button>\n </ng-template>\n</abp-modal>\n"],"names":["i2","i3","i4","i5","i6","i7"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export { h as CONTENT_FIELD_TYPE, i as CONTENT_FIELD_TYPE_NAME, j as ContentConfigComponent, k as ContentConfiguration, l as ContentControlComponent, b as ContentListStateService, a as ContentQueryService, m as ContentViewComponent, n as Dignite, o as FILE_FIELD_CONFIGURATION_NAMES, p as FILE_FIELD_TYPE, q as FILE_FIELD_TYPE_NAME, r as FileConfigComponent, s as FileControlComponent, t as FileDirectoryTreeComponent, u as FileFieldConfiguration, v as FileModalComponent, w as FilePickerComponent, x as FilePreviewComponent, y as FileUploadComponent, z as FileViewComponent, A as FormatFileSizePipe, I as IMAGE_TYPE_OPTIONS, M as MY_FILES_NODE_KEY, O as ObjectUrlService, B as SEO_FIELD_TYPE, D as SEO_FIELD_TYPE_NAME, E as SITE_FILE_CONTAINER_NAMES, G as SITE_FILE_PATH, H as SITE_IMAGES_CONTAINER_NAME, J as SITE_ROUTES, K as SeoConfigComponent, L as SeoConfiguration, N as SeoControlComponent, Q as SeoViewComponent, R as SiteCKEditorUploadProvider, T as SiteFileUrlService, S as SiteReferenceDataService, V as ValidatorsService, U as Volo, W as absoluteFileUrl, e as eSitePolicyNames, X as isMyFilesNode, Y as isSiteFileUrl, Z as siteCKEditorConfigContributor, _ as siteCKEditorDisplayContributor, $ as sizedFileUrl, a0 as toContentListParams } from './dignite-ng.site-dignite-ng.site-CsKxqjY9.mjs';
2
+ //# sourceMappingURL=dignite-ng.site.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dignite-ng.site.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":""}
package/package.json CHANGED
@@ -1,6 +1,51 @@
1
1
  {
2
2
  "name": "@dignite/ng.site",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "1.0.1",
4
+ "homepage": "https://github.com/dignite-projects/site",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "git+https://github.com/dignite-projects/site.git",
8
+ "directory": "angular/projects/site"
9
+ },
10
+ "license": "MIT",
11
+ "publishConfig": {
12
+ "access": "public"
13
+ },
14
+ "dependencies": {
15
+ "@abp/ng.components": "~10.7.0",
16
+ "@angular/cdk": "~21.2.0",
17
+ "@dignite/ng.flex-fields": "^10.7.0",
18
+ "@dignite/ng.flex-fields-ckeditor": "^10.7.0",
19
+ "ng-zorro-antd": "~21.3.1",
20
+ "tslib": "^2.1.0"
21
+ },
22
+ "peerDependencies": {
23
+ "@abp/ng.core": "~10.7.0",
24
+ "@abp/ng.theme.shared": "~10.7.0",
25
+ "@angular/common": "^22.0.0",
26
+ "@angular/core": "^22.0.0",
27
+ "@angular/forms": "^22.0.0",
28
+ "@angular/platform-browser": "^22.0.0",
29
+ "@angular/router": "^22.0.0",
30
+ "@ngx-validate/core": "^0.2.0",
31
+ "@swimlane/ngx-datatable": "~22.0.0",
32
+ "rxjs": "~7.8.0"
33
+ },
34
+ "module": "fesm2022/dignite-ng.site.mjs",
35
+ "typings": "types/dignite-ng.site.d.ts",
36
+ "exports": {
37
+ "./package.json": {
38
+ "default": "./package.json"
39
+ },
40
+ ".": {
41
+ "types": "./types/dignite-ng.site.d.ts",
42
+ "default": "./fesm2022/dignite-ng.site.mjs"
43
+ },
44
+ "./config": {
45
+ "types": "./types/dignite-ng.site-config.d.ts",
46
+ "default": "./fesm2022/dignite-ng.site-config.mjs"
47
+ }
48
+ },
49
+ "sideEffects": false,
50
+ "type": "module"
6
51
  }
@@ -0,0 +1,14 @@
1
+ import { EnvironmentProviders } from '@angular/core';
2
+
3
+ declare const enum eSiteRouteNames {
4
+ Site = "Site::Menu:Site",
5
+ Contents = "Site::Menu:Contents",
6
+ Pages = "Site::Menu:Pages",
7
+ Fields = "Site::Menu:Fields"
8
+ }
9
+
10
+ declare const SITE_ROUTE_PROVIDERS: EnvironmentProviders[];
11
+ declare function configureRoutes(): void;
12
+ declare function provideSite(): EnvironmentProviders;
13
+
14
+ export { SITE_ROUTE_PROVIDERS, configureRoutes, eSiteRouteNames, provideSite };