@dignite/ng.site 1.0.0 → 2.0.0
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.
- package/README.md +16 -2
- package/fesm2022/dignite-ng.site-config.mjs +10 -1
- package/fesm2022/dignite-ng.site-config.mjs.map +1 -1
- package/fesm2022/{dignite-ng.site-content-editor.component-iFWDeYJ9.mjs → dignite-ng.site-content-editor.component-DA6FaJSU.mjs} +2 -2
- package/fesm2022/{dignite-ng.site-content-editor.component-iFWDeYJ9.mjs.map → dignite-ng.site-content-editor.component-DA6FaJSU.mjs.map} +1 -1
- package/fesm2022/{dignite-ng.site-content-types.component-D2jMSSq6.mjs → dignite-ng.site-content-types.component-Dnqe8A4t.mjs} +27 -7
- package/fesm2022/dignite-ng.site-content-types.component-Dnqe8A4t.mjs.map +1 -0
- package/fesm2022/{dignite-ng.site-contents.component-DKuel8w-.mjs → dignite-ng.site-contents.component-Ch5GYIHE.mjs} +2 -2
- package/fesm2022/{dignite-ng.site-contents.component-DKuel8w-.mjs.map → dignite-ng.site-contents.component-Ch5GYIHE.mjs.map} +1 -1
- package/fesm2022/{dignite-ng.site-dignite-ng.site-CsKxqjY9.mjs → dignite-ng.site-dignite-ng.site-BMcNABSG.mjs} +283 -55
- package/fesm2022/dignite-ng.site-dignite-ng.site-BMcNABSG.mjs.map +1 -0
- package/fesm2022/{dignite-ng.site-fields.component-By_YyfIx.mjs → dignite-ng.site-fields.component-BaK27N9k.mjs} +5 -3
- package/fesm2022/dignite-ng.site-fields.component-BaK27N9k.mjs.map +1 -0
- package/fesm2022/{dignite-ng.site-pages.component-S9BEgC4W.mjs → dignite-ng.site-pages.component-BwGyK7jw.mjs} +28 -5
- package/fesm2022/dignite-ng.site-pages.component-BwGyK7jw.mjs.map +1 -0
- package/fesm2022/dignite-ng.site-setting-management.mjs +123 -0
- package/fesm2022/dignite-ng.site-setting-management.mjs.map +1 -0
- package/fesm2022/dignite-ng.site-theme-workbench.component-CA47DnTj.mjs +1206 -0
- package/fesm2022/dignite-ng.site-theme-workbench.component-CA47DnTj.mjs.map +1 -0
- package/fesm2022/dignite-ng.site.mjs +1 -1
- package/package.json +17 -1
- package/types/dignite-ng.site-config.d.ts +2 -1
- package/types/dignite-ng.site-setting-management.d.ts +41 -0
- package/types/dignite-ng.site.d.ts +386 -111
- package/fesm2022/dignite-ng.site-content-types.component-D2jMSSq6.mjs.map +0 -1
- package/fesm2022/dignite-ng.site-dignite-ng.site-CsKxqjY9.mjs.map +0 -1
- package/fesm2022/dignite-ng.site-fields.component-By_YyfIx.mjs.map +0 -1
- package/fesm2022/dignite-ng.site-pages.component-S9BEgC4W.mjs.map +0 -1
package/README.md
CHANGED
|
@@ -11,7 +11,7 @@ npm install @dignite/ng.site
|
|
|
11
11
|
```
|
|
12
12
|
|
|
13
13
|
(Pre-release builds are published to GitHub Packages as `@dignite-projects/ng.site`; see the root
|
|
14
|
-
[README](
|
|
14
|
+
[README](https://github.com/dignite-projects/site/blob/main/README.md) / `angular/.npmrc` for the registry setup, and alias the dependency:
|
|
15
15
|
`"@dignite/ng.site": "npm:@dignite-projects/ng.site@<version>"`.)
|
|
16
16
|
|
|
17
17
|
### CKEditor dependency and the file library
|
|
@@ -24,12 +24,19 @@ everything *it* needs (`@ckeditor/ckeditor5-angular`, `ckeditor5`, `marked`) as
|
|
|
24
24
|
rather than peers. `npm install @dignite/ng.site` (see "Installing" above) is the whole install; there's
|
|
25
25
|
nothing to add by hand.
|
|
26
26
|
|
|
27
|
+
Because `provideSite()` has to run at application-config level (`FieldTypeResolver` reads its registry
|
|
28
|
+
once, when it is first injected, so registering from the lazy-loaded `/site` routes would come too late),
|
|
29
|
+
everything it registers is in the host's **initial bundle**, CKEditor included: it is downloaded on first
|
|
30
|
+
paint, whether or not the host's content types use a rich-text field and whether or not anyone ever opens
|
|
31
|
+
`/site`. Registering Site adds roughly 950 KB (about 170 KB gzipped) to a production build of an ABP
|
|
32
|
+
admin app, so a host that enforces a bundle budget in `angular.json` may need to raise it.
|
|
33
|
+
|
|
27
34
|
The file picker, the file field type (registration key `FileExplorer`) and the SEO share-image picker
|
|
28
35
|
are this package's own (`src/lib/files`, `src/lib/field-types/file`) and talk to Site's admin API
|
|
29
36
|
(`apiName: 'SiteAdmin'`) - there is no separate file-picker package to install any more, and no extra
|
|
30
37
|
entry to keep in `environment.apis`. `provideSite()` also registers `SiteCKEditorUploadProvider` as the
|
|
31
38
|
`CKEDITOR_UPLOAD_PROVIDER` (which needs `@dignite/ng.flex-fields-ckeditor >= 10.0.0-rc.25`), so an image
|
|
32
|
-
inserted into a CKEditor field is uploaded into Site's file library. See
|
|
39
|
+
inserted into a CKEditor field is uploaded into Site's file library. See [Files](https://github.com/dignite-projects/site/blob/main/docs/en/files.md).
|
|
33
40
|
|
|
34
41
|
That `>= 10.0.0-rc.13` floor is load-bearing, not cosmetic. Below `rc.12` those packages were
|
|
35
42
|
the adapters' `peerDependencies`, and every ABP 10.7 + Angular 22 host installs with
|
|
@@ -45,6 +52,13 @@ the published package.json to the same alias form used for `@dignite/ng.site` it
|
|
|
45
52
|
step never covered `peerDependencies`, which is exactly why the old manual alias instruction lived
|
|
46
53
|
here.
|
|
47
54
|
|
|
55
|
+
### Code editor dependency (CodeMirror)
|
|
56
|
+
|
|
57
|
+
The Templates screen edits Scriban templates in CodeMirror 6 (`codemirror`, `@codemirror/lang-html`,
|
|
58
|
+
`@codemirror/state`, `@codemirror/view` - all MIT, all declared as this package's own `dependencies`, so
|
|
59
|
+
`npm install @dignite/ng.site` brings them). The screen is lazy-loaded with the `/site` routes, so the editor stays
|
|
60
|
+
out of the host's initial bundle. It needs no stylesheet from the host.
|
|
61
|
+
|
|
48
62
|
### Required global styles (ng-zorro-antd)
|
|
49
63
|
|
|
50
64
|
`@dignite/ng.site` builds several fields on `ng-zorro-antd` (`nz-tree`, `nz-tree-select`, `nz-select`,
|
|
@@ -18,7 +18,7 @@ function configureRoutes() {
|
|
|
18
18
|
iconClass: 'fas fa-globe',
|
|
19
19
|
layout: "application" /* eLayoutType.application */,
|
|
20
20
|
order: 3,
|
|
21
|
-
requiredPolicy: 'SiteAdmin.Pages || SiteAdmin.ContentTypes || SiteAdmin.Fields || SiteAdmin.Contents',
|
|
21
|
+
requiredPolicy: 'SiteAdmin.Pages || SiteAdmin.ContentTypes || SiteAdmin.Fields || SiteAdmin.Contents || SiteAdmin.Themes',
|
|
22
22
|
},
|
|
23
23
|
{
|
|
24
24
|
path: '/site/contents',
|
|
@@ -47,6 +47,15 @@ function configureRoutes() {
|
|
|
47
47
|
order: 3,
|
|
48
48
|
requiredPolicy: 'SiteAdmin.Fields',
|
|
49
49
|
},
|
|
50
|
+
{
|
|
51
|
+
path: '/site/theme',
|
|
52
|
+
name: "Site::Menu:Theme" /* eSiteRouteNames.Theme */,
|
|
53
|
+
parentName: "Site::Menu:Site" /* eSiteRouteNames.Site */,
|
|
54
|
+
iconClass: 'fas fa-code',
|
|
55
|
+
layout: "application" /* eLayoutType.application */,
|
|
56
|
+
order: 4,
|
|
57
|
+
requiredPolicy: 'SiteAdmin.Themes',
|
|
58
|
+
},
|
|
50
59
|
]);
|
|
51
60
|
// Content types have no menu entry: they belong to a page, and are reached from the Pages list.
|
|
52
61
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dignite-ng.site-config.mjs","sources":["../../../projects/site/config/src/providers/route.provider.ts","../../../projects/site/config/src/dignite-ng.site-config.ts"],"sourcesContent":["import { eLayoutType, RoutesService } from '@abp/ng.core';\nimport { provideFlexFields } from '@dignite/ng.flex-fields';\nimport {\n CKEDITOR_CONFIG_CONTRIBUTORS,\n CKEDITOR_DISPLAY_CONTRIBUTORS,\n CKEDITOR_UPLOAD_PROVIDER,\n provideCKEditorFieldType,\n} from '@dignite/ng.flex-fields-ckeditor';\nimport {\n CONTENT_FIELD_TYPE,\n FILE_FIELD_TYPE,\n SEO_FIELD_TYPE,\n SiteCKEditorUploadProvider,\n siteCKEditorConfigContributor,\n siteCKEditorDisplayContributor,\n} from '@dignite/ng.site';\nimport {\n EnvironmentProviders,\n inject,\n makeEnvironmentProviders,\n Provider,\n provideAppInitializer,\n} from '@angular/core';\nimport { eSiteRouteNames } from '../enums/route-names';\n\nexport const SITE_ROUTE_PROVIDERS = [\n provideAppInitializer(() => {\n configureRoutes();\n }),\n];\n\nexport function configureRoutes() {\n const routesService = inject(RoutesService);\n routesService.add([\n {\n path: '/site',\n name: eSiteRouteNames.Site,\n iconClass: 'fas fa-globe',\n layout: eLayoutType.application,\n order: 3,\n requiredPolicy:\n 'SiteAdmin.Pages || SiteAdmin.ContentTypes || SiteAdmin.Fields || SiteAdmin.Contents',\n },\n {\n path: '/site/contents',\n name: eSiteRouteNames.Contents,\n parentName: eSiteRouteNames.Site,\n iconClass: 'fas fa-file-lines',\n layout: eLayoutType.application,\n order: 1,\n requiredPolicy: 'SiteAdmin.Contents',\n },\n {\n path: '/site/pages',\n name: eSiteRouteNames.Pages,\n parentName: eSiteRouteNames.Site,\n iconClass: 'fas fa-file-code',\n layout: eLayoutType.application,\n order: 2,\n requiredPolicy: 'SiteAdmin.Pages',\n },\n {\n path: '/site/fields',\n name: eSiteRouteNames.Fields,\n parentName: eSiteRouteNames.Site,\n iconClass: 'fas fa-list-check',\n layout: eLayoutType.application,\n order: 3,\n requiredPolicy: 'SiteAdmin.Fields',\n },\n ]);\n\n // Content types have no menu entry: they belong to a page, and are reached from the Pages list.\n}\n\nconst SITE_PROVIDERS: (EnvironmentProviders | Provider)[] = [\n ...SITE_ROUTE_PROVIDERS,\n // The six built-ins (Matrix/Table among them as of flex-fields 10.0.0-rc.16, via\n // provideFlexFields()'s own BUILT_IN_FIELD_TYPES - they used to be Site's own MATRIX_FIELD_TYPE/\n // TABLE_FIELD_TYPE, registered explicitly here, until flex-fields shipped them as kernel built-ins)\n // plus Site's own `Seo`, `Content` and file (GitHub issue #42) types (GitHub issue #49). `FieldTypeResolver` is root-provided and reads the registry once when first\n // injected, so this has to happen at application-config level - registering from inside the\n // lazy-loaded Site routes would come too late for a resolver already constructed.\n provideFlexFields(SEO_FIELD_TYPE, CONTENT_FIELD_TYPE, FILE_FIELD_TYPE),\n // The CKEditor field type (GitHub issue #43). Unlike the server, where DependsOn plus DI discovery is\n // enough (总体设计 §8.2), the client has no equivalent - each field type's control/config/view trio has\n // to be registered explicitly or FieldTypeResolver.get(...) throws and the content editor breaks on\n // first use, the same failure mode SEO_FIELD_TYPE's own comment warns about.\n provideCKEditorFieldType(),\n // Inline images in a CKEditor field go into Site's file library (the field's CKEditor.ImagesContainerName,\n // normally images) and are embedded by their public address. Without a provider the editor shows\n // no upload button at all.\n { provide: CKEDITOR_UPLOAD_PROVIDER, useExisting: SiteCKEditorUploadProvider },\n // Those addresses are stored relative (/api/site-public/files/...); the editor shows them from the\n // SiteAdmin API's host, in its editing view only - getData(), and so what is saved, stays relative.\n { provide: CKEDITOR_CONFIG_CONTRIBUTORS, multi: true, useFactory: siteCKEditorConfigContributor },\n // The read-only view (ff-ckeditor-view: a content list cell) has no editor to convert in, so its HTML gets\n // the same host in front of those addresses before it is rendered; nothing is saved from there.\n { provide: CKEDITOR_DISPLAY_CONTRIBUTORS, multi: true, useFactory: siteCKEditorDisplayContributor },\n];\n\nexport function provideSite() {\n return makeEnvironmentProviders(SITE_PROVIDERS);\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":";;;;;;AAyBO,MAAM,oBAAoB,GAAG;IAClC,qBAAqB,CAAC,MAAK;AACzB,QAAA,eAAe,EAAE;AACnB,IAAA,CAAC,CAAC;;SAGY,eAAe,GAAA;AAC7B,IAAA,MAAM,aAAa,GAAG,MAAM,CAAC,aAAa,CAAC;IAC3C,aAAa,CAAC,GAAG,CAAC;AAChB,QAAA;AACE,YAAA,IAAI,EAAE,OAAO;AACb,YAAA,IAAI,EAAA,iBAAA;AACJ,YAAA,SAAS,EAAE,cAAc;AACzB,YAAA,MAAM,EAAA,aAAA;AACN,YAAA,KAAK,EAAE,CAAC;AACR,YAAA,cAAc,EACZ,
|
|
1
|
+
{"version":3,"file":"dignite-ng.site-config.mjs","sources":["../../../projects/site/config/src/providers/route.provider.ts","../../../projects/site/config/src/dignite-ng.site-config.ts"],"sourcesContent":["import { eLayoutType, RoutesService } from '@abp/ng.core';\nimport { provideFlexFields } from '@dignite/ng.flex-fields';\nimport {\n CKEDITOR_CONFIG_CONTRIBUTORS,\n CKEDITOR_DISPLAY_CONTRIBUTORS,\n CKEDITOR_UPLOAD_PROVIDER,\n provideCKEditorFieldType,\n} from '@dignite/ng.flex-fields-ckeditor';\nimport {\n CONTENT_FIELD_TYPE,\n FILE_FIELD_TYPE,\n SEO_FIELD_TYPE,\n SiteCKEditorUploadProvider,\n siteCKEditorConfigContributor,\n siteCKEditorDisplayContributor,\n} from '@dignite/ng.site';\nimport {\n EnvironmentProviders,\n inject,\n makeEnvironmentProviders,\n Provider,\n provideAppInitializer,\n} from '@angular/core';\nimport { eSiteRouteNames } from '../enums/route-names';\n\nexport const SITE_ROUTE_PROVIDERS = [\n provideAppInitializer(() => {\n configureRoutes();\n }),\n];\n\nexport function configureRoutes() {\n const routesService = inject(RoutesService);\n routesService.add([\n {\n path: '/site',\n name: eSiteRouteNames.Site,\n iconClass: 'fas fa-globe',\n layout: eLayoutType.application,\n order: 3,\n requiredPolicy:\n 'SiteAdmin.Pages || SiteAdmin.ContentTypes || SiteAdmin.Fields || SiteAdmin.Contents || SiteAdmin.Themes',\n },\n {\n path: '/site/contents',\n name: eSiteRouteNames.Contents,\n parentName: eSiteRouteNames.Site,\n iconClass: 'fas fa-file-lines',\n layout: eLayoutType.application,\n order: 1,\n requiredPolicy: 'SiteAdmin.Contents',\n },\n {\n path: '/site/pages',\n name: eSiteRouteNames.Pages,\n parentName: eSiteRouteNames.Site,\n iconClass: 'fas fa-file-code',\n layout: eLayoutType.application,\n order: 2,\n requiredPolicy: 'SiteAdmin.Pages',\n },\n {\n path: '/site/fields',\n name: eSiteRouteNames.Fields,\n parentName: eSiteRouteNames.Site,\n iconClass: 'fas fa-list-check',\n layout: eLayoutType.application,\n order: 3,\n requiredPolicy: 'SiteAdmin.Fields',\n },\n {\n path: '/site/theme',\n name: eSiteRouteNames.Theme,\n parentName: eSiteRouteNames.Site,\n iconClass: 'fas fa-code',\n layout: eLayoutType.application,\n order: 4,\n requiredPolicy: 'SiteAdmin.Themes',\n },\n ]);\n\n // Content types have no menu entry: they belong to a page, and are reached from the Pages list.\n}\n\nconst SITE_PROVIDERS: (EnvironmentProviders | Provider)[] = [\n ...SITE_ROUTE_PROVIDERS,\n // The six built-ins (Matrix/Table among them as of flex-fields 10.0.0-rc.16, via\n // provideFlexFields()'s own BUILT_IN_FIELD_TYPES - they used to be Site's own MATRIX_FIELD_TYPE/\n // TABLE_FIELD_TYPE, registered explicitly here, until flex-fields shipped them as kernel built-ins)\n // plus Site's own `Seo`, `Content` and file (GitHub issue #42) types (GitHub issue #49). `FieldTypeResolver` is root-provided and reads the registry once when first\n // injected, so this has to happen at application-config level - registering from inside the\n // lazy-loaded Site routes would come too late for a resolver already constructed.\n provideFlexFields(SEO_FIELD_TYPE, CONTENT_FIELD_TYPE, FILE_FIELD_TYPE),\n // The CKEditor field type (GitHub issue #43). Unlike the server, where DependsOn plus DI discovery is\n // enough (总体设计 §8.2), the client has no equivalent - each field type's control/config/view trio has\n // to be registered explicitly or FieldTypeResolver.get(...) throws and the content editor breaks on\n // first use, the same failure mode SEO_FIELD_TYPE's own comment warns about.\n provideCKEditorFieldType(),\n // Inline images in a CKEditor field go into Site's file library (the field's CKEditor.ImagesContainerName,\n // normally images) and are embedded by their public address. Without a provider the editor shows\n // no upload button at all.\n { provide: CKEDITOR_UPLOAD_PROVIDER, useExisting: SiteCKEditorUploadProvider },\n // Those addresses are stored relative (/api/site-public/files/...); the editor shows them from the\n // SiteAdmin API's host, in its editing view only - getData(), and so what is saved, stays relative.\n { provide: CKEDITOR_CONFIG_CONTRIBUTORS, multi: true, useFactory: siteCKEditorConfigContributor },\n // The read-only view (ff-ckeditor-view: a content list cell) has no editor to convert in, so its HTML gets\n // the same host in front of those addresses before it is rendered; nothing is saved from there.\n { provide: CKEDITOR_DISPLAY_CONTRIBUTORS, multi: true, useFactory: siteCKEditorDisplayContributor },\n];\n\nexport function provideSite() {\n return makeEnvironmentProviders(SITE_PROVIDERS);\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":";;;;;;AAyBO,MAAM,oBAAoB,GAAG;IAClC,qBAAqB,CAAC,MAAK;AACzB,QAAA,eAAe,EAAE;AACnB,IAAA,CAAC,CAAC;;SAGY,eAAe,GAAA;AAC7B,IAAA,MAAM,aAAa,GAAG,MAAM,CAAC,aAAa,CAAC;IAC3C,aAAa,CAAC,GAAG,CAAC;AAChB,QAAA;AACE,YAAA,IAAI,EAAE,OAAO;AACb,YAAA,IAAI,EAAA,iBAAA;AACJ,YAAA,SAAS,EAAE,cAAc;AACzB,YAAA,MAAM,EAAA,aAAA;AACN,YAAA,KAAK,EAAE,CAAC;AACR,YAAA,cAAc,EACZ,yGAAyG;AAC5G,SAAA;AACD,QAAA;AACE,YAAA,IAAI,EAAE,gBAAgB;AACtB,YAAA,IAAI,EAAA,qBAAA;AACJ,YAAA,UAAU,EAAA,iBAAA;AACV,YAAA,SAAS,EAAE,mBAAmB;AAC9B,YAAA,MAAM,EAAA,aAAA;AACN,YAAA,KAAK,EAAE,CAAC;AACR,YAAA,cAAc,EAAE,oBAAoB;AACrC,SAAA;AACD,QAAA;AACE,YAAA,IAAI,EAAE,aAAa;AACnB,YAAA,IAAI,EAAA,kBAAA;AACJ,YAAA,UAAU,EAAA,iBAAA;AACV,YAAA,SAAS,EAAE,kBAAkB;AAC7B,YAAA,MAAM,EAAA,aAAA;AACN,YAAA,KAAK,EAAE,CAAC;AACR,YAAA,cAAc,EAAE,iBAAiB;AAClC,SAAA;AACD,QAAA;AACE,YAAA,IAAI,EAAE,cAAc;AACpB,YAAA,IAAI,EAAA,mBAAA;AACJ,YAAA,UAAU,EAAA,iBAAA;AACV,YAAA,SAAS,EAAE,mBAAmB;AAC9B,YAAA,MAAM,EAAA,aAAA;AACN,YAAA,KAAK,EAAE,CAAC;AACR,YAAA,cAAc,EAAE,kBAAkB;AACnC,SAAA;AACD,QAAA;AACE,YAAA,IAAI,EAAE,aAAa;AACnB,YAAA,IAAI,EAAA,kBAAA;AACJ,YAAA,UAAU,EAAA,iBAAA;AACV,YAAA,SAAS,EAAE,aAAa;AACxB,YAAA,MAAM,EAAA,aAAA;AACN,YAAA,KAAK,EAAE,CAAC;AACR,YAAA,cAAc,EAAE,kBAAkB;AACnC,SAAA;AACF,KAAA,CAAC;;AAGJ;AAEA,MAAM,cAAc,GAAwC;AAC1D,IAAA,GAAG,oBAAoB;;;;;;;AAOvB,IAAA,iBAAiB,CAAC,cAAc,EAAE,kBAAkB,EAAE,eAAe,CAAC;;;;;AAKtE,IAAA,wBAAwB,EAAE;;;;AAI1B,IAAA,EAAE,OAAO,EAAE,wBAAwB,EAAE,WAAW,EAAE,0BAA0B,EAAE;;;IAG9E,EAAE,OAAO,EAAE,4BAA4B,EAAE,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,6BAA6B,EAAE;;;IAGjG,EAAE,OAAO,EAAE,6BAA6B,EAAE,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,8BAA8B,EAAE;CACpG;SAEe,WAAW,GAAA;AACzB,IAAA,OAAO,wBAAwB,CAAC,cAAc,CAAC;AACjD;;AChHA;;AAEG;;;;"}
|
|
@@ -9,7 +9,7 @@ import * as i2 from '@angular/router';
|
|
|
9
9
|
import { ActivatedRoute, Router, RouterLink } from '@angular/router';
|
|
10
10
|
import { FlexFieldControlComponent } from '@dignite/ng.flex-fields';
|
|
11
11
|
import { forkJoin, of, switchMap, catchError } from 'rxjs';
|
|
12
|
-
import { C as ContentAdminService, c as ContentTypeAdminService, P as PageAdminService, S as SiteReferenceDataService, d as ContentStatus } from './dignite-ng.site-dignite-ng.site-
|
|
12
|
+
import { C as ContentAdminService, c as ContentTypeAdminService, P as PageAdminService, S as SiteReferenceDataService, d as ContentStatus } from './dignite-ng.site-dignite-ng.site-BMcNABSG.mjs';
|
|
13
13
|
import * as i3 from '@ngx-validate/core';
|
|
14
14
|
|
|
15
15
|
/**
|
|
@@ -779,4 +779,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.2.2", ngImpor
|
|
|
779
779
|
}], ctorParameters: () => [] });
|
|
780
780
|
|
|
781
781
|
export { ContentEditorComponent };
|
|
782
|
-
//# sourceMappingURL=dignite-ng.site-content-editor.component-
|
|
782
|
+
//# sourceMappingURL=dignite-ng.site-content-editor.component-DA6FaJSU.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dignite-ng.site-content-editor.component-iFWDeYJ9.mjs","sources":["../../../projects/site/src/lib/field-types/flex-field-error-message.ts","../../../projects/site/src/lib/components/contents/content-editor.component.ts","../../../projects/site/src/lib/components/contents/content-editor.component.html"],"sourcesContent":["import { AbstractControl } from '@angular/forms';\nimport { LocalizationService } from '@abp/ng.core';\n\n/**\n * Maps a mounted flex field's own control errors to the same localized text, regardless of which\n * field type produced them or how deep the control is nested (top-level, a Table column, a Matrix\n * sub-field): every built-in field type only ever raises `required`/`min`/`max`/`maxlength`, since\n * that's the full set `NumberControlComponent`/`TextControlComponent`/etc. push in `@dignite/ng.flex-fields`.\n * Gated on `touched` so a fresh, still-empty required field doesn't show red before the user reaches it.\n */\nexport function flexFieldErrorMessage(\n control: AbstractControl | null | undefined,\n localization: LocalizationService,\n): string | null {\n const errors = control?.touched ? control.errors : null;\n if (!errors) {\n return null;\n }\n\n if (errors['required']) {\n return localization.instant('AbpValidation::ThisFieldIsRequired');\n }\n if (errors['min']) {\n return localization.instant('FlexFieldsSite::Validate:MinValue', String(errors['min'].min));\n }\n if (errors['max']) {\n return localization.instant('FlexFieldsSite::Validate:MaxValue', String(errors['max'].max));\n }\n if (errors['maxlength']) {\n return localization.instant('FlexFieldsSite::Validate:MaxLength', String(errors['maxlength'].requiredLength));\n }\n return null;\n}\n","import { CoreModule, LocalizationService } from '@abp/ng.core';\nimport { ThemeSharedModule, ToasterService } from '@abp/ng.theme.shared';\nimport { Component, inject, signal, ChangeDetectionStrategy } from '@angular/core';\nimport { FormBuilder, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';\nimport { ActivatedRoute, Router, RouterLink } from '@angular/router';\nimport { FlexFieldControlComponent } from '@dignite/ng.flex-fields';\nimport type { FlexFieldData, FlexFieldValue } from '@dignite/ng.flex-fields';\nimport { catchError, forkJoin, of, switchMap } from 'rxjs';\nimport { ContentAdminService } from '../../proxy/dignite/site/admin/contents/content-admin.service';\nimport { ContentTypeAdminService } from '../../proxy/dignite/site/admin/content-types/content-type-admin.service';\nimport { PageAdminService } from '../../proxy/dignite/site/admin/pages/page-admin.service';\nimport type { ContentTypeDto } from '../../proxy/dignite/site/content-types/models';\nimport type { ContentDto } from '../../proxy/dignite/site/contents/models';\nimport { ContentStatus } from '../../proxy/dignite/site/contents/content-status.enum';\nimport type { FieldDto } from '../../proxy/dignite/site/fields/models';\nimport type { PageDto } from '../../proxy/dignite/site/pages/models';\nimport { SiteReferenceDataService } from '../../services/site-reference-data.service';\nimport { flexFieldErrorMessage } from '../../field-types/flex-field-error-message';\nimport type { ArrangedField } from './arranged-field';\n\nconst MAX_SLUG_LENGTH = 256;\nconst OPTIONAL_SLUG_TOKEN = '{slug?}';\nconst REQUIRED_SLUG_TOKEN = '{slug}';\n\n/** Mirrors `SlugNormalizer.AllowedCharactersPattern` (`src/Dignite.Site.Domain.Shared/SlugNormalizer.cs`). */\nconst SLUG_PATTERN = /^[\\p{L}\\p{Nd}_-]*$/u;\n\n/** Mirrors `PageRoute.HasSlug`/`PageRoute.IsSlugOptional` (总体设计 §3.3) - see {@link ContentEditorComponent.slugState}. */\ntype SlugState = 'forbidden' | 'required' | 'optional';\n\n/**\n * Creating and editing one content, as a page of its own rather than a dialog.\n *\n * The two halves answer different questions and are sized accordingly: the left is the content itself -\n * however many fields its content type defines, which can be a long form - and the right is the handful\n * of system fields that place and schedule it. A dialog forced both into one scrolling column.\n *\n * Switching the content type rebuilds the left half, because the fields *are* the content type's\n * definition. Values already typed under fields the new type does not have are dropped, which is the\n * honest outcome: they have nowhere to be stored.\n *\n * **Deliberately no CKEditor theme bridge here.** This component used to carry a global\n * `::ng-deep :root` block remapping CKEditor 5's `--ck-color-base-*` tokens onto the host theme -\n * CKEditor ships one fixed light palette with no dark-mode switch, so the editor stayed light in a\n * dark-themed host. `@dignite/ng.flex-fields-ckeditor` >= 10.0.0-rc.13 ships that bridge itself, with\n * a longer fallback chain than this copy had (LeptonX token -> the Bootstrap 5.3 token every ABP\n * Angular theme defines -> CKEditor's own stock literal) plus fixes this copy never had. Re-adding a\n * copy here would not add anything and would fight it at equal `:root` specificity, decided by style\n * injection order alone.\n */\n@Component({\n selector: 'site-content-editor',\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './content-editor.component.html',\n imports: [CoreModule, ThemeSharedModule, ReactiveFormsModule, RouterLink, FlexFieldControlComponent],\n})\nexport class ContentEditorComponent {\n private readonly contentService = inject(ContentAdminService);\n private readonly contentTypeService = inject(ContentTypeAdminService);\n private readonly pageService = inject(PageAdminService);\n private readonly referenceData = inject(SiteReferenceDataService);\n private readonly route = inject(ActivatedRoute);\n private readonly router = inject(Router);\n private readonly fb = inject(FormBuilder);\n private readonly toaster = inject(ToasterService);\n private readonly localization = inject(LocalizationService);\n\n readonly ContentStatus = ContentStatus;\n readonly statuses = [ContentStatus.Draft, ContentStatus.Published, ContentStatus.Archived];\n\n readonly contentId: string | null = this.route.snapshot.paramMap.get('id');\n readonly isEdit = !!this.contentId;\n\n // State that changes in an HTTP callback is a signal, not a plain field: the host layout's ancestors\n // (`abp-router-outlet`, the LeptonX layouts) are OnPush, and a plain-field write in a response\n // callback never marks them for check, so the form would stay blank (or go stale) until some\n // unrelated event happened to.\n readonly page = signal<PageDto | undefined>(undefined);\n readonly contentTypes = signal<ContentTypeDto[]>([]);\n readonly languages = signal<string[]>([]);\n defaultLanguage = '';\n content?: ContentDto;\n\n /**\n * Whether the page's own address (an empty slug) is already taken by another content, for the\n * currently selected language - only meaningful, and only checked, when {@link slugState} is\n * `'optional'`. Read by the template to decide whether the \"use the page's own address\" checkbox is\n * offered at all.\n */\n readonly emptySlotTaken = signal(false);\n\n private fieldsById = new Map<string, FieldDto>();\n private arrangementByContentType = new Map<string, ArrangedField[]>();\n\n /**\n * The current content type's fields, as stable `FlexFieldValue`s. Rebuilt only when the content type\n * changes - `ff-flex-field-control` compares this input by object reference, and handing it a freshly\n * allocated array on every change-detection pass would make it tear down and recreate its dynamic\n * child forever (`NG0103`).\n */\n readonly fields = signal<FlexFieldValue[]>([]);\n\n form?: FormGroup;\n readonly isBusy = signal(false);\n readonly isLoading = signal(true);\n\n constructor() {\n const pageId = this.route.snapshot.queryParamMap.get('pageId');\n\n forkJoin({\n schema: this.referenceData.getSchema(),\n fieldsById: this.referenceData.getFieldsById(),\n content: this.contentId ? this.contentService.get(this.contentId) : of(undefined),\n })\n .pipe(\n switchMap(loaded => {\n const languages = loaded.schema.enabledLanguages ?? [];\n this.languages.set(languages);\n this.defaultLanguage = loaded.schema.defaultLanguage ?? languages[0] ?? '';\n this.fieldsById = loaded.fieldsById;\n this.content = loaded.content;\n\n const resolvedPageId = loaded.content?.pageId ?? pageId ?? '';\n\n return forkJoin({\n page: resolvedPageId ? this.pageService.get(resolvedPageId) : of(undefined),\n contentTypes: resolvedPageId\n ? this.contentTypeService.getListByPage(resolvedPageId)\n : of({ items: [] as ContentTypeDto[] }),\n });\n }),\n )\n .subscribe(({ page, contentTypes }) => {\n this.page.set(page);\n this.contentTypes.set(contentTypes.items ?? []);\n this.rebuildArrangements();\n this.form = this.buildForm();\n this.rebuildFields();\n this.isLoading.set(false);\n this.refreshEmptySlotAvailability();\n });\n }\n\n get hasMultipleContentTypes(): boolean {\n return this.contentTypes().length > 1;\n }\n\n /**\n * What this page's route (总体设计 §3.3) says about the slug beneath it - the front-end mirror of\n * `PageRoute.HasSlug`/`PageRoute.IsSlugOptional`. `'forbidden'`: no `{slug}`/`{slug?}` at all, so this\n * page has nothing beneath it but its own address. `'required'`: `{slug}` or `{slug:REGEX}`, so every\n * content needs one. `'optional'`: `{slug?}`, so an empty slug is also allowed, subject to\n * {@link emptySlotTaken}.\n */\n get slugState(): SlugState {\n const route = this.page()?.route ?? '';\n if (route.includes(OPTIONAL_SLUG_TOKEN)) {\n return 'optional';\n }\n return route.includes(REQUIRED_SLUG_TOKEN) || this.hasSlugWithRegex(route) ? 'required' : 'forbidden';\n }\n\n /**\n * Whether `route` carries `{slug:REGEX}` - a slug placeholder with a regex and no format, the one\n * decorated form `PageRoute.HasSlug` recognizes. Whether a given slug matches that regex is left to the\n * server (`PageRoute.IsSlugAllowed`): a .NET pattern does not always mean the same thing in JavaScript.\n */\n private hasSlugWithRegex(route: string): boolean {\n for (let i = route.indexOf('{'); i >= 0; i = route.indexOf('{', i + 1)) {\n const placeholder = this.readPlaceholder(route, i);\n if (placeholder && placeholder.name.toLowerCase() === 'slug' && placeholder.format === null) {\n return true;\n }\n if (placeholder) {\n i = placeholder.end - 1;\n }\n }\n return false;\n }\n\n get usePageOwnAddress(): boolean {\n return !!this.form?.get('usePageOwnAddress')?.value;\n }\n\n /**\n * The address this content will actually be served at, recomputed on every read so the template can\n * bind it directly and have it track the slug field as the user types. An approximation, not the\n * source of truth: {@link resolvePlaceholder} resolves every placeholder generically off the form and\n * the loaded content, falling back to the raw token when it cannot - `Page.BuildContentPath` on the\n * server is what actually decides the URL.\n *\n * The empty-slug branch mirrors `Page.BuildContentPath` itself, not a naming convention: an empty\n * slug is short-circuited to the page's own path there regardless of what the rest of the route\n * contains, so the preview has to do the same rather than run it through the placeholder replacement\n * below.\n */\n get slugPreview(): string {\n const route = this.page()?.route;\n if (!route) {\n return '';\n }\n\n const slug = (this.form?.get('slug')?.value ?? '').trim();\n const path = slug ? this.buildPreviewPath(route) : this.pageOwnPath(route);\n return this.applyCulturePrefix(path);\n }\n\n get isDraft(): boolean {\n return this.form?.getRawValue().status === ContentStatus.Draft;\n }\n\n statusKeyOf(status: ContentStatus): string {\n return `Site::Enum:ContentStatus:${ContentStatus[status]}`;\n }\n\n fieldErrorMessage(fieldValue: FlexFieldValue): string | null {\n return flexFieldErrorMessage(this.form?.get('flexFields')?.get(fieldValue.field.name), this.localization);\n }\n\n private rebuildArrangements(): void {\n this.arrangementByContentType = new Map(\n this.contentTypes().map(contentType => [\n contentType.id!,\n (contentType.fields ?? [])\n .map(entry => {\n const definition = entry.fieldId ? this.fieldsById.get(entry.fieldId) : undefined;\n if (!definition) {\n return undefined;\n }\n\n const fieldData: FlexFieldData = {\n id: definition.id!,\n name: definition.name!,\n displayName: entry.displayName || definition.displayName!,\n description: definition.description ?? undefined,\n fieldTypeName: definition.fieldTypeName!,\n configuration: (definition.configuration ?? {}) as Record<string, unknown>,\n };\n\n return {\n fieldId: definition.id!,\n name: definition.name!,\n displayName: fieldData.displayName,\n fieldTypeName: definition.fieldTypeName!,\n required: !!entry.required,\n searchable: !!entry.searchable,\n showInList: !!entry.showInList,\n order: entry.order ?? 0,\n fieldData,\n } satisfies ArrangedField;\n })\n .filter((field): field is ArrangedField => !!field)\n .sort((a, b) => a.order - b.order),\n ]),\n );\n }\n\n /** Called on load and whenever the content type changes. See {@link fields}. */\n private rebuildFields(): void {\n const contentTypeId = this.form?.get('contentTypeId')?.value as string | undefined;\n const arranged = this.arrangementByContentType.get(contentTypeId ?? '') ?? [];\n const values = this.content?.fieldValues ?? {};\n\n this.fields.set(\n arranged.map(field => ({\n field: field.fieldData,\n required: field.required,\n searchable: field.searchable,\n value: values[field.name],\n })),\n );\n }\n\n onContentTypeChange(): void {\n // The value bag is keyed by field name, so controls for the old type's fields have to go before the\n // new type's are registered - otherwise the payload carries both.\n this.form?.setControl('flexFields', this.fb.group({}));\n this.rebuildFields();\n }\n\n onStatusChange(): void {\n this.applyPublishTimeAvailability();\n }\n\n onCultureNameChange(): void {\n this.refreshEmptySlotAvailability();\n }\n\n onUsePageOwnAddressChange(): void {\n this.applySlugAvailability();\n }\n\n save(): void {\n if (!this.form || this.form.invalid || this.isBusy()) {\n return;\n }\n\n this.isBusy.set(true);\n const value = this.form.getRawValue();\n const fieldValues = (this.form.get('flexFields')?.getRawValue() ?? {}) as Record<string, object>;\n const slug = value.slug ?? '';\n\n const request$ = this.content\n ? this.contentService.update(this.content.id!, {\n contentTypeId: value.contentTypeId,\n slug,\n publishTime: value.publishTime,\n status: value.status,\n fieldValues,\n })\n : this.contentService.create({\n contentTypeId: value.contentTypeId,\n cultureName: value.cultureName,\n slug,\n publishTime: value.publishTime,\n status: value.status,\n fieldValues,\n });\n\n request$.subscribe({\n next: () => {\n this.isBusy.set(false);\n this.toaster.success('AbpUi::SavedSuccessfully');\n this.backToList();\n },\n error: () => this.isBusy.set(false),\n });\n }\n\n backToList(): void {\n this.router.navigate(['/site/contents']);\n }\n\n private buildForm(): FormGroup {\n const content = this.content;\n\n const form = this.fb.group({\n contentTypeId: [\n content?.contentTypeId ?? this.contentTypes()[0]?.id ?? '',\n Validators.required,\n ],\n cultureName: [\n {\n value:\n content?.cultureName ??\n this.route.snapshot.queryParamMap.get('cultureName') ??\n this.languages()[0] ??\n '',\n // Fixed after creation: the language is half the natural key that groups a content's\n // translations, so changing it would silently move the content to another translation set.\n disabled: !!content,\n },\n Validators.required,\n ],\n // Editing a content that is already the page's own (an empty slug) starts the checkbox checked -\n // otherwise applySlugAvailability would immediately overwrite its empty slug with a forced-required\n // value the moment the form builds.\n usePageOwnAddress: [!!content && !content.slug],\n slug: [content?.slug ?? '', [Validators.maxLength(MAX_SLUG_LENGTH), Validators.pattern(SLUG_PATTERN)]],\n publishTime: [this.toLocalDateTime(content?.publishTime), Validators.required],\n status: [content?.status ?? ContentStatus.Published],\n flexFields: this.fb.group({}),\n });\n\n this.form = form;\n this.applySlugAvailability();\n this.applyPublishTimeAvailability();\n\n return form;\n }\n\n /**\n * Enables/disables and (in)validates the `slug` control from {@link slugState} - and, in the\n * `'optional'` case, from whether the \"use the page's own address\" checkbox is ticked. The same\n * three-way split `ContentManager.CheckSlugRequirementAsync` enforces server-side; this only decides\n * what the form looks like before that ever runs.\n */\n private applySlugAvailability(): void {\n const slug = this.form?.get('slug');\n if (!slug) {\n return;\n }\n\n const forceOwnAddress = this.slugState === 'forbidden' ||\n (this.slugState === 'optional' && this.usePageOwnAddress);\n\n if (forceOwnAddress) {\n slug.setValue('');\n slug.clearValidators();\n slug.disable();\n } else {\n slug.enable();\n slug.setValidators([\n Validators.required,\n Validators.maxLength(MAX_SLUG_LENGTH),\n Validators.pattern(SLUG_PATTERN),\n ]);\n }\n\n slug.updateValueAndValidity();\n }\n\n /**\n * Looks up whether this page's own address (an empty slug) is already taken for the selected\n * language, so the \"use the page's own address\" option can be withheld before the editor ever submits\n * and hits `Site:040001`. A no-op outside the `'optional'` state, where the question does not arise.\n *\n * Goes through `getList` rather than the more direct `findBySlug`, which exists for exactly this\n * lookup - `IContentAdminAppService.FindBySlugAsync(pageId, cultureName, \"\")` is the same query\n * `SiteRouteResolver` uses to resolve a bare page match. But ABP's `RestService.getParams` silently\n * drops any query parameter whose value is an empty string, so a `slug` of `\"\"` never reaches the\n * request at all; the server then sees a *missing* parameter, not an intentionally empty one, and\n * rejects it exactly as `Should_Reject_A_Null_Slug` says it must. Listing this page's contents for the\n * language and filtering for an empty slug client-side sidesteps that without weakening the server's\n * null-vs-empty distinction.\n */\n private refreshEmptySlotAvailability(): void {\n const pageId = this.page()?.id;\n if (this.slugState !== 'optional' || !pageId) {\n this.emptySlotTaken.set(false);\n return;\n }\n\n const cultureName = this.form?.get('cultureName')?.value;\n if (!cultureName) {\n return;\n }\n\n this.contentService\n .getList({ pageId, cultureName, maxResultCount: 1000 })\n .pipe(catchError(() => of({ items: [] as ContentDto[], totalCount: 0 })))\n .subscribe(result => {\n const existing = (result.items ?? []).find(item => item.slug === '');\n const taken = !!existing && existing.id !== this.content?.id;\n this.emptySlotTaken.set(taken);\n\n // The slot this checkbox promised is gone (e.g. the language was switched to one where it is\n // already taken) - un-tick it rather than leave a checked box the next save would reject.\n if (taken && this.usePageOwnAddress) {\n this.form?.get('usePageOwnAddress')?.setValue(false);\n this.applySlugAvailability();\n }\n });\n }\n\n /**\n * A draft is never public, so a publish time on one is not a schedule anything acts on - the server\n * rejects the combination outright (`Site:040003`). Scheduling is Published plus a future time.\n */\n private applyPublishTimeAvailability(): void {\n const publishTime = this.form?.get('publishTime');\n const status = this.form?.get('status')?.value as ContentStatus | undefined;\n\n if (!publishTime) {\n return;\n }\n\n if (status === ContentStatus.Draft) {\n publishTime.setValue(this.toLocalDateTime());\n publishTime.disable();\n } else {\n publishTime.enable();\n }\n }\n\n /** `<input type=\"datetime-local\">` wants `yyyy-MM-ddTHH:mm`, not an ISO string with a zone. */\n private toLocalDateTime(value?: string): string {\n const date = value ? new Date(value) : new Date();\n const offset = date.getTimezoneOffset() * 60_000;\n return new Date(date.getTime() - offset).toISOString().slice(0, 16);\n }\n\n /**\n * Mirrors `SiteUrlContext.ApplyCulturePrefix` (总体设计 §5.5): every enabled language carries a\n * `/cultureName` prefix except the default one, which is served unprefixed. `cultureName` here is\n * already one of `languages` (or the loaded content's own, already-normalized value), so - unlike the\n * server, which normalizes through `CultureNameNormalizer` first - a plain equality check against\n * {@link defaultLanguage} is enough to tell the two apart.\n */\n private applyCulturePrefix(path: string): string {\n const cultureName = this.form?.get('cultureName')?.value;\n if (!cultureName || cultureName === this.defaultLanguage) {\n return path;\n }\n\n return path === '/' ? `/${cultureName}` : `/${cultureName}${path}`;\n }\n\n /** Mirrors `PageRoute.GetPath`: everything up to the segment that first carries a placeholder. */\n private pageOwnPath(route: string): string {\n const index = route.indexOf('{');\n if (index < 0) {\n return route;\n }\n\n const boundary = route.lastIndexOf('/', index);\n return boundary <= 0 ? '/' : route.slice(0, boundary);\n }\n\n /**\n * A rough, client-side mirror of `PageRoute.Build` - see {@link slugPreview}'s remarks. Every\n * placeholder, `{slug}` included, goes through the same generic {@link resolvePlaceholder} - no\n * per-name branch here, deliberately: the server does not have one either, it reflects over `Content`\n * (`Page.ResolveFieldValue`), and a name-by-name `if` ladder here would just be that same mistake\n * moved to TypeScript instead of removed.\n * <p>\n * Placeholders are located with {@link readPlaceholder}'s brace-depth-aware scan, not a single regex -\n * a `/\\{...\\}/` pattern cannot tell a placeholder's own closing brace apart from a balanced one inside\n * its `:REGEX` segment (a quantifier like `\\d{4}`, e.g. in `{publishTime:yyyy-MM:^\\d{4}-(0[1-9]|1[0-2])$}`),\n * the same reason `PageRoute.TryParseTemplate` on the server had to stop using ABP's own tokenizer.\n */\n private buildPreviewPath(route: string): string {\n const canonical = route.replace(OPTIONAL_SLUG_TOKEN, REQUIRED_SLUG_TOKEN);\n\n let result = '';\n let i = 0;\n\n while (i < canonical.length) {\n if (canonical[i] !== '{') {\n result += canonical[i];\n i++;\n continue;\n }\n\n const placeholder = this.readPlaceholder(canonical, i);\n if (!placeholder) {\n // Not a well-formed placeholder start - a route that reaches this component was already\n // validated by `PageRoute.IsValid` when it was saved, so this is only ever a defensive fallback:\n // treat '{' as a literal character rather than throwing out of what is meant to be a best-effort\n // preview.\n result += canonical[i];\n i++;\n continue;\n }\n\n result += this.resolvePlaceholder(placeholder.name, placeholder.format) ?? placeholder.token;\n i = placeholder.end;\n }\n\n return result;\n }\n\n /**\n * Reads one `{name}` / `{name:FORMAT}` / `{name:REGEX}` / `{name:FORMAT:REGEX}` placeholder starting at\n * `route[start]` (must be `'{'`), mirroring `PageRoute.TryParseTemplate`'s single-placeholder case\n * (`src/Dignite.Site.Domain.Shared/Pages/PageRoute.cs`): brace depth is tracked once inside the\n * `:`-segment so an embedded, balanced `{`/`}` does not get mistaken for the placeholder's own closing\n * brace, and a backslash escapes the next character so an explicitly-escaped `\\{`/`\\}` never perturbs\n * the count either. Returns `null` for anything that does not parse as a well-formed placeholder -\n * {@link buildPreviewPath} treats that as a literal `{` rather than failing the whole preview.\n * <p>\n * Only `name` and `format` are extracted, never the regex itself - a placeholder's regex constrains\n * what may be read back out of a request path, and has nothing to say about a value being written into\n * one, the same reason `PageRoute.Build` on the server discards it too (see that method's remarks).\n */\n private readPlaceholder(\n route: string,\n start: number,\n ): { token: string; end: number; name: string; format: string | null } | null {\n let i = start + 1; // consume '{'\n const nameStart = i;\n\n // Mirrors `PageRoute.IsNameStartChar`/`IsNameChar`: every `IdentifierName` a field can have, plus\n // uppercase for `Content`'s camel-cased system properties (`publishTime`).\n if (i >= route.length || !/[a-zA-Z0-9]/.test(route[i])) {\n return null;\n }\n i++;\n while (i < route.length && /[a-zA-Z0-9_-]/.test(route[i])) {\n i++;\n }\n const name = route.slice(nameStart, i);\n\n if (i >= route.length) {\n return null;\n }\n\n if (route[i] === '}') {\n return { token: route.slice(start, i + 1), end: i + 1, name, format: null };\n }\n\n if (route[i] !== ':') {\n return null;\n }\n\n i++; // consume ':'\n const innerStart = i;\n let depth = 0;\n let closed = false;\n\n while (i < route.length) {\n const c = route[i];\n if (c === '\\\\' && i + 1 < route.length) {\n i += 2;\n continue;\n }\n if (c === '{') {\n depth++;\n } else if (c === '}') {\n if (depth === 0) {\n closed = true;\n break;\n }\n depth--;\n }\n i++;\n }\n\n if (!closed) {\n return null;\n }\n\n const inner = route.slice(innerStart, i);\n const end = i + 1; // consume the closing '}'\n return { token: route.slice(start, end), end, name, format: this.disambiguateFormat(inner) };\n }\n\n /**\n * Mirrors `PageRoute.TryDisambiguate`, reduced to the half a preview needs: a placeholder's already\n * brace-depth-isolated inner text (everything after the first `:`) splits into a `:FORMAT` prefix plus a\n * regex remainder when the prefix is format-shaped (letters/digits/`.`/`_`/`-` only - a real format\n * string, by construction, can never also look like a regex worth compiling, which is what keeps every\n * `{name:FORMAT}` route classified exactly as it always was); otherwise the inner text is a bare format\n * on its own if it matches that shape whole, or else it is a regex with no format at all.\n */\n private disambiguateFormat(inner: string): string | null {\n const formatCharacters = /^[a-zA-Z0-9_.-]+$/;\n const colon = inner.indexOf(':');\n\n if (colon >= 0) {\n const candidate = inner.slice(0, colon);\n if (candidate && formatCharacters.test(candidate)) {\n return candidate;\n }\n }\n\n return formatCharacters.test(inner) ? inner : null;\n }\n\n /**\n * Resolves one placeholder's preview text purely from *where* `name` is actually found, never from\n * what it is called. Angular forms have no runtime type to reflect over the way `Content` does server\n * side - `ContentDto` is a TypeScript interface, erased at compile time - so the nearest equivalent is\n * a generic, case-insensitive walk of what is actually on the form and the loaded content, checked in\n * the same order the server would find them: a real property first, `FlexFields` second.\n * 1. A top-level form control - every system field the editor can change lives here (`cultureName`,\n * `status`, `publishTime`, `contentTypeId`, `slug`...), whatever it happens to be named.\n * 2. A control inside `flexFields` - a content type's own business fields.\n * 3. A property already on the loaded `this.content` DTO - covers the read-only audit trail\n * (`id`, `creationTime`, ...) `FullAuditedEntityDto` carries but no form control exists for.\n * Naturally empty until this content has actually been saved once - which is honest, since the\n * server has nothing to reflect there yet either.\n *\n * One deliberate, named exception to \"no name-based branching\": {@link usePageOwnAddress} is a UI-only\n * control with no server-side counterpart, and step 1 cannot tell that apart from a real field by\n * shape alone - a route that actually referenced `{usePageOwnAddress}` would resolve to \"true\"/\"false\"\n * here. Excluding it by name would be exactly the kind of branch this method exists to avoid, and the\n * failure mode is harmless: `Page.BuildContentPath` has no such property either, so a route that made\n * this mistake for real still fails loudly server-side the first time a URL is actually built from it.\n */\n private resolvePlaceholder(name: string, format: string | null): string | null {\n const raw = this.findValue(name);\n if (raw === null || raw === undefined || raw === '') {\n return null;\n }\n\n if (format) {\n const formatted = this.tryFormatByShape(raw, format);\n if (formatted !== null) {\n return formatted;\n }\n }\n\n return String(raw);\n }\n\n /**\n * Applies `format` to `raw` purely from what `raw` looks like, never from which placeholder produced\n * it - the same dispatch-by-shape rule {@link resolvePlaceholder} follows, extended to every shape\n * this preview knows how to format. Mirrors `Page.FormatFieldValue`'s `value is IFormattable` check,\n * just done by sniffing a form value's shape with a regex instead of asking the CLR for its runtime\n * type - there is no such type to ask here, `raw` is already unwrapped to a plain JS value by the time\n * it reaches this method.\n * <p>\n * Each shape is tried in turn; the first one whose regex matches `raw` owns the answer from there,\n * whether or not it actually recognizes `format` - a date-shaped value with a nonsense format is a\n * date that failed to format, not a number or a Guid that happened to also look like one. Recognizing\n * the shape but not the specific `format` asked of it (a Guid's `X`, a numeric format outside\n * {@link formatNumber}'s subset) returns null, same as a shape nothing here recognizes at all - both\n * fall back to the unformatted value in {@link resolvePlaceholder}, deliberately: this is a preview,\n * and a plausible but possibly-wrong guess at an unimplemented format would be worse than showing the\n * plain value.\n */\n private tryFormatByShape(raw: unknown, format: string): string | null {\n const date = this.tryParseDate(raw);\n if (date) {\n return this.formatDate(date, format);\n }\n\n const guid = this.tryParseGuid(raw);\n if (guid) {\n return this.formatGuid(guid, format);\n }\n\n const number = this.tryParseNumber(raw);\n if (number !== null) {\n return this.formatNumber(number, format);\n }\n\n return null;\n }\n\n private findValue(name: string): unknown {\n const lowerName = name.toLowerCase();\n\n const topLevelControls = this.form?.controls;\n const topLevelKey = topLevelControls && Object.keys(topLevelControls).find(key => key.toLowerCase() === lowerName);\n if (topLevelKey) {\n return this.form!.get(topLevelKey)!.value;\n }\n\n const flexFields = this.form?.get('flexFields');\n if (flexFields instanceof FormGroup) {\n const flexKey = Object.keys(flexFields.controls).find(key => key.toLowerCase() === lowerName);\n if (flexKey) {\n return flexFields.get(flexKey)!.value;\n }\n }\n\n if (this.content) {\n const contentRecord = this.content as unknown as Record<string, unknown>;\n const contentKey = Object.keys(contentRecord).find(key => key.toLowerCase() === lowerName);\n if (contentKey !== undefined) {\n return contentRecord[contentKey];\n }\n }\n\n return undefined;\n }\n\n /** Whether `value` is shaped like a `datetime-local` input's own output (`yyyy-MM-ddTHH:mm`). */\n private tryParseDate(value: unknown): Date | null {\n if (typeof value !== 'string' || !/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}/.test(value)) {\n return null;\n }\n\n const date = new Date(value);\n return isNaN(date.getTime()) ? null : date;\n }\n\n /** Only the three specifiers a `:FORMAT` suffix may actually contain (总体设计 §3.3) - no '/' among them. */\n private formatDate(date: Date, format: string): string {\n return format\n .replace(/yyyy/g, String(date.getFullYear()))\n .replace(/yy/g, String(date.getFullYear()).slice(-2))\n .replace(/MM/g, String(date.getMonth() + 1).padStart(2, '0'))\n .replace(/dd/g, String(date.getDate()).padStart(2, '0'));\n }\n\n /** Whether `value` is shaped like the canonical, hyphenated form of a Guid. */\n private tryParseGuid(value: unknown): string | null {\n return typeof value === 'string' &&\n /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value)\n ? value\n : null;\n }\n\n /**\n * `Guid.ToString(format)`'s four straightforward specifiers - N (no separators), D (hyphenated, the\n * shape already checked by {@link tryParseGuid}), B (braced) and P (parenthesized). `X` deliberately\n * not implemented: it renders as a C#-syntax initializer list, not a URL-shaped string, and nothing\n * about a route makes that a plausible thing to have ever asked for.\n */\n private formatGuid(guid: string, format: string): string | null {\n const digits = guid.replace(/-/g, '').toLowerCase();\n const dashed = `${digits.slice(0, 8)}-${digits.slice(8, 12)}-${digits.slice(12, 16)}-${digits.slice(16, 20)}-${digits.slice(20)}`;\n\n switch (format.toUpperCase()) {\n case 'N':\n return digits;\n case 'D':\n return dashed;\n case 'B':\n return `{${dashed}}`;\n case 'P':\n return `(${dashed})`;\n default:\n return null;\n }\n }\n\n /** Whether `value` is shaped like a plain, optionally negative, optionally decimal number. */\n private tryParseNumber(value: unknown): number | null {\n if (typeof value === 'number' && isFinite(value)) {\n return value;\n }\n\n return typeof value === 'string' && /^-?\\d+(\\.\\d+)?$/.test(value) ? Number(value) : null;\n }\n\n /**\n * A representative slice of .NET's numeric format strings - the ones a URL path segment plausibly\n * asks for. Custom zero-padding (`\"0000\"`, unchanged from before) plus four standard specifiers, each\n * with an optional 1-2 digit precision: `D` (zero-padded, integers only - the standard-format spelling\n * of the same thing `\"0000\"` does), `X`/`x` (hexadecimal, integers only, letter case controls digit\n * case, negative not attempted - see {@link formatHex}'s remarks), `F` (fixed-point) and `N`\n * (fixed-point with thousands grouping). Deliberately not `C`/`P` (currency/percent): both put a\n * character that means something else in a URL - a locale-dependent currency symbol, or `%`, the URL\n * escape character itself - into the path, which nothing about routing would ever actually want. Not\n * `E`/`G`/`R` either: those are about round-trip print fidelity for an arbitrary number, not a shape\n * any real route has a reason to ask for.\n */\n private formatNumber(value: number, format: string): string | null {\n if (/^0+$/.test(format)) {\n return Number.isInteger(value) ? this.padInteger(value, format.length) : null;\n }\n\n const standard = /^([DdXxFfNn])(\\d{0,2})$/.exec(format);\n if (!standard) {\n return null;\n }\n\n const [, specifier, precisionText] = standard;\n const precision = precisionText === '' ? null : Number(precisionText);\n\n switch (specifier.toUpperCase()) {\n case 'D':\n return Number.isInteger(value) ? this.padInteger(value, precision ?? 0) : null;\n case 'X':\n return Number.isInteger(value) && value >= 0 ? this.formatHex(value, precision ?? 0, specifier === 'X') : null;\n case 'F':\n return value.toFixed(precision ?? 2);\n case 'N':\n return this.groupThousands(value.toFixed(precision ?? 2));\n default:\n return null;\n }\n }\n\n private padInteger(value: number, width: number): string {\n const negative = value < 0;\n const padded = Math.abs(value).toString().padStart(width, '0');\n return negative ? `-${padded}` : padded;\n }\n\n /**\n * Negative values are rejected before this is ever called - .NET's `X` renders a negative signed\n * integer as its two's-complement bit pattern, which depends on the source type's own width (`int` vs\n * `long` vs `byte` produce different digits for the same value), information a form control's plain\n * number does not carry. Guessing a width would risk a preview that looks plausible and is wrong;\n * not attempting it is the same call already made for a Guid's `X` and for `C`/`P`/`E`/`G`/`R`.\n */\n private formatHex(value: number, width: number, uppercase: boolean): string {\n const hex = value.toString(16).padStart(width, '0');\n return uppercase ? hex.toUpperCase() : hex;\n }\n\n private groupThousands(fixedValue: string): string {\n const negative = fixedValue.startsWith('-');\n const [integerPart, fractionPart] = (negative ? fixedValue.slice(1) : fixedValue).split('.');\n const grouped = integerPart.replace(/\\B(?=(\\d{3})+(?!\\d))/g, ',');\n return `${negative ? '-' : ''}${grouped}${fractionPart ? '.' + fractionPart : ''}`;\n }\n}\n","@if (!isLoading() && form) {\n <form [formGroup]=\"form\" (submit)=\"save()\">\n <div class=\"d-flex justify-content-between align-items-center mb-3\">\n <div>\n <h5 class=\"mb-0\">\n {{ (isEdit ? 'Site::EditContent' : 'Site::NewContent') | abpLocalization }}\n </h5>\n @if (page(); as currentPage) {\n <small class=\"text-muted\">{{ currentPage.displayName }}</small>\n }\n </div>\n <div>\n <a class=\"btn btn-secondary me-2\" [routerLink]=\"['/site/contents']\">\n {{ 'AbpUi::Cancel' | abpLocalization }}\n </a>\n <!-- A plain submit button, not `abp-button`: that component declares its own `click` output,\n so `(click)` binds to an EventEmitter instead of the DOM event, and it takes `buttonType`\n rather than `type`. Both make it easy to end up with a button that quietly never submits.\n Inside a form on a page, the native element says what it does. -->\n <button type=\"submit\" class=\"btn btn-primary\" [disabled]=\"!form.valid || isBusy()\">\n @if (isBusy()) {\n <span class=\"spinner-border spinner-border-sm me-1\" role=\"status\"></span>\n } @else {\n <i class=\"fa fa-check me-1\"></i>\n }\n {{ 'AbpUi::Save' | abpLocalization }}\n </button>\n </div>\n </div>\n\n <div class=\"row g-3\">\n <!-- Left: the content itself - whatever fields its content type defines. -->\n <div class=\"col-lg-8\">\n <div class=\"card h-100\">\n <div class=\"card-body\">\n @if (hasMultipleContentTypes) {\n <div class=\"mb-3 pb-3 border-bottom\">\n <label class=\"form-label\">\n {{ 'Site::DisplayName:Content.ContentType' | abpLocalization }}\n </label>\n <select\n class=\"form-select\"\n formControlName=\"contentTypeId\"\n (change)=\"onContentTypeChange()\"\n >\n @for (contentType of contentTypes(); track contentType.id) {\n <option [value]=\"contentType.id\">{{ contentType.displayName }}</option>\n }\n </select>\n <small class=\"form-text text-muted\">\n {{ 'Site::ContentTypeSwitchHint' | abpLocalization }}\n </small>\n </div>\n }\n\n @if (fields().length > 0) {\n @for (fieldValue of fields(); track fieldValue.field.name) {\n <ff-flex-field-control\n [fields]=\"fieldValue\"\n [entity]=\"form\"\n parentFieldName=\"flexFields\"\n [selected]=\"fieldValue.value\"\n ></ff-flex-field-control>\n @if (fieldErrorMessage(fieldValue); as message) {\n <div class=\"invalid-feedback d-block mb-3\">{{ message }}</div>\n }\n }\n } @else {\n <p class=\"text-muted mb-0\">{{ 'Site::NoFieldsArranged' | abpLocalization }}</p>\n }\n </div>\n </div>\n </div>\n\n <!-- Right: the system fields that place and schedule the content. -->\n <div class=\"col-lg-4\">\n <div class=\"card\">\n <div class=\"card-body\">\n @if (!hasMultipleContentTypes && contentTypes().length === 1) {\n <div class=\"mb-3\">\n <label class=\"form-label\">\n {{ 'Site::DisplayName:Content.ContentType' | abpLocalization }}\n </label>\n <input type=\"text\" class=\"form-control\" [value]=\"contentTypes()[0].displayName\" disabled />\n </div>\n }\n\n <div class=\"mb-3\">\n <label class=\"form-label\">\n {{ 'Site::DisplayName:Content.CultureName' | abpLocalization }}\n </label>\n <select class=\"form-select\" formControlName=\"cultureName\" (change)=\"onCultureNameChange()\">\n @for (language of languages(); track language) {\n <option [value]=\"language\">{{ language }}</option>\n }\n </select>\n </div>\n\n <!-- The page's route (总体设计 §3.3) decides this, not the editor: no {slug}/{slug?} at all\n means nothing is shown here - there is nothing to choose. -->\n @if (slugState !== 'forbidden') {\n <div class=\"mb-3\">\n <label class=\"form-label\">{{ 'Site::DisplayName:Content.Slug' | abpLocalization }}</label>\n\n @if (slugState === 'optional' && !emptySlotTaken()) {\n <div class=\"form-check mb-2\">\n <input\n type=\"checkbox\"\n class=\"form-check-input\"\n id=\"site-use-page-own-address\"\n formControlName=\"usePageOwnAddress\"\n (change)=\"onUsePageOwnAddressChange()\"\n />\n <label class=\"form-check-label\" for=\"site-use-page-own-address\">\n {{ 'Site::UsePageOwnAddress' | abpLocalization }}\n </label>\n </div>\n }\n\n @if (!usePageOwnAddress) {\n <input type=\"text\" class=\"form-control\" formControlName=\"slug\" />\n <small class=\"form-text text-muted d-block mt-1\">\n {{ 'Site::Description:Content.Slug' | abpLocalization }}\n </small>\n }\n\n @if (slugState === 'optional' && emptySlotTaken()) {\n <small class=\"form-text text-muted d-block mt-1\">\n {{ 'Site::SlugSlotTaken' | abpLocalization }}\n </small>\n }\n\n <small class=\"form-text text-muted d-block mt-1\">\n {{ 'Site::SlugPreview' | abpLocalization: slugPreview }}\n </small>\n </div>\n }\n\n <div class=\"mb-3\">\n <label class=\"form-label\">{{ 'Site::DisplayName:Content.Status' | abpLocalization }}</label>\n <select class=\"form-select\" formControlName=\"status\" (change)=\"onStatusChange()\">\n @for (status of statuses; track status) {\n <option [ngValue]=\"status\">{{ statusKeyOf(status) | abpLocalization }}</option>\n }\n </select>\n </div>\n\n <div class=\"mb-0\">\n <label class=\"form-label\">\n {{ 'Site::DisplayName:Content.PublishTime' | abpLocalization }}\n </label>\n <input type=\"datetime-local\" class=\"form-control\" formControlName=\"publishTime\" />\n @if (isDraft) {\n <small class=\"form-text text-muted\">\n {{ 'Site::DraftPublishTimeDisabledHint' | abpLocalization }}\n </small>\n }\n </div>\n </div>\n </div>\n </div>\n </div>\n </form>\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"dignite-ng.site-content-editor.component-DA6FaJSU.mjs","sources":["../../../projects/site/src/lib/field-types/flex-field-error-message.ts","../../../projects/site/src/lib/components/contents/content-editor.component.ts","../../../projects/site/src/lib/components/contents/content-editor.component.html"],"sourcesContent":["import { AbstractControl } from '@angular/forms';\nimport { LocalizationService } from '@abp/ng.core';\n\n/**\n * Maps a mounted flex field's own control errors to the same localized text, regardless of which\n * field type produced them or how deep the control is nested (top-level, a Table column, a Matrix\n * sub-field): every built-in field type only ever raises `required`/`min`/`max`/`maxlength`, since\n * that's the full set `NumberControlComponent`/`TextControlComponent`/etc. push in `@dignite/ng.flex-fields`.\n * Gated on `touched` so a fresh, still-empty required field doesn't show red before the user reaches it.\n */\nexport function flexFieldErrorMessage(\n control: AbstractControl | null | undefined,\n localization: LocalizationService,\n): string | null {\n const errors = control?.touched ? control.errors : null;\n if (!errors) {\n return null;\n }\n\n if (errors['required']) {\n return localization.instant('AbpValidation::ThisFieldIsRequired');\n }\n if (errors['min']) {\n return localization.instant('FlexFieldsSite::Validate:MinValue', String(errors['min'].min));\n }\n if (errors['max']) {\n return localization.instant('FlexFieldsSite::Validate:MaxValue', String(errors['max'].max));\n }\n if (errors['maxlength']) {\n return localization.instant('FlexFieldsSite::Validate:MaxLength', String(errors['maxlength'].requiredLength));\n }\n return null;\n}\n","import { CoreModule, LocalizationService } from '@abp/ng.core';\nimport { ThemeSharedModule, ToasterService } from '@abp/ng.theme.shared';\nimport { Component, inject, signal, ChangeDetectionStrategy } from '@angular/core';\nimport { FormBuilder, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';\nimport { ActivatedRoute, Router, RouterLink } from '@angular/router';\nimport { FlexFieldControlComponent } from '@dignite/ng.flex-fields';\nimport type { FlexFieldData, FlexFieldValue } from '@dignite/ng.flex-fields';\nimport { catchError, forkJoin, of, switchMap } from 'rxjs';\nimport { ContentAdminService } from '../../proxy/dignite/site/admin/contents/content-admin.service';\nimport { ContentTypeAdminService } from '../../proxy/dignite/site/admin/content-types/content-type-admin.service';\nimport { PageAdminService } from '../../proxy/dignite/site/admin/pages/page-admin.service';\nimport type { ContentTypeDto } from '../../proxy/dignite/site/content-types/models';\nimport type { ContentDto } from '../../proxy/dignite/site/contents/models';\nimport { ContentStatus } from '../../proxy/dignite/site/contents/content-status.enum';\nimport type { FieldDto } from '../../proxy/dignite/site/fields/models';\nimport type { PageDto } from '../../proxy/dignite/site/pages/models';\nimport { SiteReferenceDataService } from '../../services/site-reference-data.service';\nimport { flexFieldErrorMessage } from '../../field-types/flex-field-error-message';\nimport type { ArrangedField } from './arranged-field';\n\nconst MAX_SLUG_LENGTH = 256;\nconst OPTIONAL_SLUG_TOKEN = '{slug?}';\nconst REQUIRED_SLUG_TOKEN = '{slug}';\n\n/** Mirrors `SlugNormalizer.AllowedCharactersPattern` (`src/Dignite.Site.Domain.Shared/SlugNormalizer.cs`). */\nconst SLUG_PATTERN = /^[\\p{L}\\p{Nd}_-]*$/u;\n\n/** Mirrors `PageRoute.HasSlug`/`PageRoute.IsSlugOptional` (总体设计 §3.3) - see {@link ContentEditorComponent.slugState}. */\ntype SlugState = 'forbidden' | 'required' | 'optional';\n\n/**\n * Creating and editing one content, as a page of its own rather than a dialog.\n *\n * The two halves answer different questions and are sized accordingly: the left is the content itself -\n * however many fields its content type defines, which can be a long form - and the right is the handful\n * of system fields that place and schedule it. A dialog forced both into one scrolling column.\n *\n * Switching the content type rebuilds the left half, because the fields *are* the content type's\n * definition. Values already typed under fields the new type does not have are dropped, which is the\n * honest outcome: they have nowhere to be stored.\n *\n * **Deliberately no CKEditor theme bridge here.** This component used to carry a global\n * `::ng-deep :root` block remapping CKEditor 5's `--ck-color-base-*` tokens onto the host theme -\n * CKEditor ships one fixed light palette with no dark-mode switch, so the editor stayed light in a\n * dark-themed host. `@dignite/ng.flex-fields-ckeditor` >= 10.0.0-rc.13 ships that bridge itself, with\n * a longer fallback chain than this copy had (LeptonX token -> the Bootstrap 5.3 token every ABP\n * Angular theme defines -> CKEditor's own stock literal) plus fixes this copy never had. Re-adding a\n * copy here would not add anything and would fight it at equal `:root` specificity, decided by style\n * injection order alone.\n */\n@Component({\n selector: 'site-content-editor',\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './content-editor.component.html',\n imports: [CoreModule, ThemeSharedModule, ReactiveFormsModule, RouterLink, FlexFieldControlComponent],\n})\nexport class ContentEditorComponent {\n private readonly contentService = inject(ContentAdminService);\n private readonly contentTypeService = inject(ContentTypeAdminService);\n private readonly pageService = inject(PageAdminService);\n private readonly referenceData = inject(SiteReferenceDataService);\n private readonly route = inject(ActivatedRoute);\n private readonly router = inject(Router);\n private readonly fb = inject(FormBuilder);\n private readonly toaster = inject(ToasterService);\n private readonly localization = inject(LocalizationService);\n\n readonly ContentStatus = ContentStatus;\n readonly statuses = [ContentStatus.Draft, ContentStatus.Published, ContentStatus.Archived];\n\n readonly contentId: string | null = this.route.snapshot.paramMap.get('id');\n readonly isEdit = !!this.contentId;\n\n // State that changes in an HTTP callback is a signal, not a plain field: the host layout's ancestors\n // (`abp-router-outlet`, the LeptonX layouts) are OnPush, and a plain-field write in a response\n // callback never marks them for check, so the form would stay blank (or go stale) until some\n // unrelated event happened to.\n readonly page = signal<PageDto | undefined>(undefined);\n readonly contentTypes = signal<ContentTypeDto[]>([]);\n readonly languages = signal<string[]>([]);\n defaultLanguage = '';\n content?: ContentDto;\n\n /**\n * Whether the page's own address (an empty slug) is already taken by another content, for the\n * currently selected language - only meaningful, and only checked, when {@link slugState} is\n * `'optional'`. Read by the template to decide whether the \"use the page's own address\" checkbox is\n * offered at all.\n */\n readonly emptySlotTaken = signal(false);\n\n private fieldsById = new Map<string, FieldDto>();\n private arrangementByContentType = new Map<string, ArrangedField[]>();\n\n /**\n * The current content type's fields, as stable `FlexFieldValue`s. Rebuilt only when the content type\n * changes - `ff-flex-field-control` compares this input by object reference, and handing it a freshly\n * allocated array on every change-detection pass would make it tear down and recreate its dynamic\n * child forever (`NG0103`).\n */\n readonly fields = signal<FlexFieldValue[]>([]);\n\n form?: FormGroup;\n readonly isBusy = signal(false);\n readonly isLoading = signal(true);\n\n constructor() {\n const pageId = this.route.snapshot.queryParamMap.get('pageId');\n\n forkJoin({\n schema: this.referenceData.getSchema(),\n fieldsById: this.referenceData.getFieldsById(),\n content: this.contentId ? this.contentService.get(this.contentId) : of(undefined),\n })\n .pipe(\n switchMap(loaded => {\n const languages = loaded.schema.enabledLanguages ?? [];\n this.languages.set(languages);\n this.defaultLanguage = loaded.schema.defaultLanguage ?? languages[0] ?? '';\n this.fieldsById = loaded.fieldsById;\n this.content = loaded.content;\n\n const resolvedPageId = loaded.content?.pageId ?? pageId ?? '';\n\n return forkJoin({\n page: resolvedPageId ? this.pageService.get(resolvedPageId) : of(undefined),\n contentTypes: resolvedPageId\n ? this.contentTypeService.getListByPage(resolvedPageId)\n : of({ items: [] as ContentTypeDto[] }),\n });\n }),\n )\n .subscribe(({ page, contentTypes }) => {\n this.page.set(page);\n this.contentTypes.set(contentTypes.items ?? []);\n this.rebuildArrangements();\n this.form = this.buildForm();\n this.rebuildFields();\n this.isLoading.set(false);\n this.refreshEmptySlotAvailability();\n });\n }\n\n get hasMultipleContentTypes(): boolean {\n return this.contentTypes().length > 1;\n }\n\n /**\n * What this page's route (总体设计 §3.3) says about the slug beneath it - the front-end mirror of\n * `PageRoute.HasSlug`/`PageRoute.IsSlugOptional`. `'forbidden'`: no `{slug}`/`{slug?}` at all, so this\n * page has nothing beneath it but its own address. `'required'`: `{slug}` or `{slug:REGEX}`, so every\n * content needs one. `'optional'`: `{slug?}`, so an empty slug is also allowed, subject to\n * {@link emptySlotTaken}.\n */\n get slugState(): SlugState {\n const route = this.page()?.route ?? '';\n if (route.includes(OPTIONAL_SLUG_TOKEN)) {\n return 'optional';\n }\n return route.includes(REQUIRED_SLUG_TOKEN) || this.hasSlugWithRegex(route) ? 'required' : 'forbidden';\n }\n\n /**\n * Whether `route` carries `{slug:REGEX}` - a slug placeholder with a regex and no format, the one\n * decorated form `PageRoute.HasSlug` recognizes. Whether a given slug matches that regex is left to the\n * server (`PageRoute.IsSlugAllowed`): a .NET pattern does not always mean the same thing in JavaScript.\n */\n private hasSlugWithRegex(route: string): boolean {\n for (let i = route.indexOf('{'); i >= 0; i = route.indexOf('{', i + 1)) {\n const placeholder = this.readPlaceholder(route, i);\n if (placeholder && placeholder.name.toLowerCase() === 'slug' && placeholder.format === null) {\n return true;\n }\n if (placeholder) {\n i = placeholder.end - 1;\n }\n }\n return false;\n }\n\n get usePageOwnAddress(): boolean {\n return !!this.form?.get('usePageOwnAddress')?.value;\n }\n\n /**\n * The address this content will actually be served at, recomputed on every read so the template can\n * bind it directly and have it track the slug field as the user types. An approximation, not the\n * source of truth: {@link resolvePlaceholder} resolves every placeholder generically off the form and\n * the loaded content, falling back to the raw token when it cannot - `Page.BuildContentPath` on the\n * server is what actually decides the URL.\n *\n * The empty-slug branch mirrors `Page.BuildContentPath` itself, not a naming convention: an empty\n * slug is short-circuited to the page's own path there regardless of what the rest of the route\n * contains, so the preview has to do the same rather than run it through the placeholder replacement\n * below.\n */\n get slugPreview(): string {\n const route = this.page()?.route;\n if (!route) {\n return '';\n }\n\n const slug = (this.form?.get('slug')?.value ?? '').trim();\n const path = slug ? this.buildPreviewPath(route) : this.pageOwnPath(route);\n return this.applyCulturePrefix(path);\n }\n\n get isDraft(): boolean {\n return this.form?.getRawValue().status === ContentStatus.Draft;\n }\n\n statusKeyOf(status: ContentStatus): string {\n return `Site::Enum:ContentStatus:${ContentStatus[status]}`;\n }\n\n fieldErrorMessage(fieldValue: FlexFieldValue): string | null {\n return flexFieldErrorMessage(this.form?.get('flexFields')?.get(fieldValue.field.name), this.localization);\n }\n\n private rebuildArrangements(): void {\n this.arrangementByContentType = new Map(\n this.contentTypes().map(contentType => [\n contentType.id!,\n (contentType.fields ?? [])\n .map(entry => {\n const definition = entry.fieldId ? this.fieldsById.get(entry.fieldId) : undefined;\n if (!definition) {\n return undefined;\n }\n\n const fieldData: FlexFieldData = {\n id: definition.id!,\n name: definition.name!,\n displayName: entry.displayName || definition.displayName!,\n description: definition.description ?? undefined,\n fieldTypeName: definition.fieldTypeName!,\n configuration: (definition.configuration ?? {}) as Record<string, unknown>,\n };\n\n return {\n fieldId: definition.id!,\n name: definition.name!,\n displayName: fieldData.displayName,\n fieldTypeName: definition.fieldTypeName!,\n required: !!entry.required,\n searchable: !!entry.searchable,\n showInList: !!entry.showInList,\n order: entry.order ?? 0,\n fieldData,\n } satisfies ArrangedField;\n })\n .filter((field): field is ArrangedField => !!field)\n .sort((a, b) => a.order - b.order),\n ]),\n );\n }\n\n /** Called on load and whenever the content type changes. See {@link fields}. */\n private rebuildFields(): void {\n const contentTypeId = this.form?.get('contentTypeId')?.value as string | undefined;\n const arranged = this.arrangementByContentType.get(contentTypeId ?? '') ?? [];\n const values = this.content?.fieldValues ?? {};\n\n this.fields.set(\n arranged.map(field => ({\n field: field.fieldData,\n required: field.required,\n searchable: field.searchable,\n value: values[field.name],\n })),\n );\n }\n\n onContentTypeChange(): void {\n // The value bag is keyed by field name, so controls for the old type's fields have to go before the\n // new type's are registered - otherwise the payload carries both.\n this.form?.setControl('flexFields', this.fb.group({}));\n this.rebuildFields();\n }\n\n onStatusChange(): void {\n this.applyPublishTimeAvailability();\n }\n\n onCultureNameChange(): void {\n this.refreshEmptySlotAvailability();\n }\n\n onUsePageOwnAddressChange(): void {\n this.applySlugAvailability();\n }\n\n save(): void {\n if (!this.form || this.form.invalid || this.isBusy()) {\n return;\n }\n\n this.isBusy.set(true);\n const value = this.form.getRawValue();\n const fieldValues = (this.form.get('flexFields')?.getRawValue() ?? {}) as Record<string, object>;\n const slug = value.slug ?? '';\n\n const request$ = this.content\n ? this.contentService.update(this.content.id!, {\n contentTypeId: value.contentTypeId,\n slug,\n publishTime: value.publishTime,\n status: value.status,\n fieldValues,\n })\n : this.contentService.create({\n contentTypeId: value.contentTypeId,\n cultureName: value.cultureName,\n slug,\n publishTime: value.publishTime,\n status: value.status,\n fieldValues,\n });\n\n request$.subscribe({\n next: () => {\n this.isBusy.set(false);\n this.toaster.success('AbpUi::SavedSuccessfully');\n this.backToList();\n },\n error: () => this.isBusy.set(false),\n });\n }\n\n backToList(): void {\n this.router.navigate(['/site/contents']);\n }\n\n private buildForm(): FormGroup {\n const content = this.content;\n\n const form = this.fb.group({\n contentTypeId: [\n content?.contentTypeId ?? this.contentTypes()[0]?.id ?? '',\n Validators.required,\n ],\n cultureName: [\n {\n value:\n content?.cultureName ??\n this.route.snapshot.queryParamMap.get('cultureName') ??\n this.languages()[0] ??\n '',\n // Fixed after creation: the language is half the natural key that groups a content's\n // translations, so changing it would silently move the content to another translation set.\n disabled: !!content,\n },\n Validators.required,\n ],\n // Editing a content that is already the page's own (an empty slug) starts the checkbox checked -\n // otherwise applySlugAvailability would immediately overwrite its empty slug with a forced-required\n // value the moment the form builds.\n usePageOwnAddress: [!!content && !content.slug],\n slug: [content?.slug ?? '', [Validators.maxLength(MAX_SLUG_LENGTH), Validators.pattern(SLUG_PATTERN)]],\n publishTime: [this.toLocalDateTime(content?.publishTime), Validators.required],\n status: [content?.status ?? ContentStatus.Published],\n flexFields: this.fb.group({}),\n });\n\n this.form = form;\n this.applySlugAvailability();\n this.applyPublishTimeAvailability();\n\n return form;\n }\n\n /**\n * Enables/disables and (in)validates the `slug` control from {@link slugState} - and, in the\n * `'optional'` case, from whether the \"use the page's own address\" checkbox is ticked. The same\n * three-way split `ContentManager.CheckSlugRequirementAsync` enforces server-side; this only decides\n * what the form looks like before that ever runs.\n */\n private applySlugAvailability(): void {\n const slug = this.form?.get('slug');\n if (!slug) {\n return;\n }\n\n const forceOwnAddress = this.slugState === 'forbidden' ||\n (this.slugState === 'optional' && this.usePageOwnAddress);\n\n if (forceOwnAddress) {\n slug.setValue('');\n slug.clearValidators();\n slug.disable();\n } else {\n slug.enable();\n slug.setValidators([\n Validators.required,\n Validators.maxLength(MAX_SLUG_LENGTH),\n Validators.pattern(SLUG_PATTERN),\n ]);\n }\n\n slug.updateValueAndValidity();\n }\n\n /**\n * Looks up whether this page's own address (an empty slug) is already taken for the selected\n * language, so the \"use the page's own address\" option can be withheld before the editor ever submits\n * and hits `Site:040001`. A no-op outside the `'optional'` state, where the question does not arise.\n *\n * Goes through `getList` rather than the more direct `findBySlug`, which exists for exactly this\n * lookup - `IContentAdminAppService.FindBySlugAsync(pageId, cultureName, \"\")` is the same query\n * `SiteRouteResolver` uses to resolve a bare page match. But ABP's `RestService.getParams` silently\n * drops any query parameter whose value is an empty string, so a `slug` of `\"\"` never reaches the\n * request at all; the server then sees a *missing* parameter, not an intentionally empty one, and\n * rejects it exactly as `Should_Reject_A_Null_Slug` says it must. Listing this page's contents for the\n * language and filtering for an empty slug client-side sidesteps that without weakening the server's\n * null-vs-empty distinction.\n */\n private refreshEmptySlotAvailability(): void {\n const pageId = this.page()?.id;\n if (this.slugState !== 'optional' || !pageId) {\n this.emptySlotTaken.set(false);\n return;\n }\n\n const cultureName = this.form?.get('cultureName')?.value;\n if (!cultureName) {\n return;\n }\n\n this.contentService\n .getList({ pageId, cultureName, maxResultCount: 1000 })\n .pipe(catchError(() => of({ items: [] as ContentDto[], totalCount: 0 })))\n .subscribe(result => {\n const existing = (result.items ?? []).find(item => item.slug === '');\n const taken = !!existing && existing.id !== this.content?.id;\n this.emptySlotTaken.set(taken);\n\n // The slot this checkbox promised is gone (e.g. the language was switched to one where it is\n // already taken) - un-tick it rather than leave a checked box the next save would reject.\n if (taken && this.usePageOwnAddress) {\n this.form?.get('usePageOwnAddress')?.setValue(false);\n this.applySlugAvailability();\n }\n });\n }\n\n /**\n * A draft is never public, so a publish time on one is not a schedule anything acts on - the server\n * rejects the combination outright (`Site:040003`). Scheduling is Published plus a future time.\n */\n private applyPublishTimeAvailability(): void {\n const publishTime = this.form?.get('publishTime');\n const status = this.form?.get('status')?.value as ContentStatus | undefined;\n\n if (!publishTime) {\n return;\n }\n\n if (status === ContentStatus.Draft) {\n publishTime.setValue(this.toLocalDateTime());\n publishTime.disable();\n } else {\n publishTime.enable();\n }\n }\n\n /** `<input type=\"datetime-local\">` wants `yyyy-MM-ddTHH:mm`, not an ISO string with a zone. */\n private toLocalDateTime(value?: string): string {\n const date = value ? new Date(value) : new Date();\n const offset = date.getTimezoneOffset() * 60_000;\n return new Date(date.getTime() - offset).toISOString().slice(0, 16);\n }\n\n /**\n * Mirrors `SiteUrlContext.ApplyCulturePrefix` (总体设计 §5.5): every enabled language carries a\n * `/cultureName` prefix except the default one, which is served unprefixed. `cultureName` here is\n * already one of `languages` (or the loaded content's own, already-normalized value), so - unlike the\n * server, which normalizes through `CultureNameNormalizer` first - a plain equality check against\n * {@link defaultLanguage} is enough to tell the two apart.\n */\n private applyCulturePrefix(path: string): string {\n const cultureName = this.form?.get('cultureName')?.value;\n if (!cultureName || cultureName === this.defaultLanguage) {\n return path;\n }\n\n return path === '/' ? `/${cultureName}` : `/${cultureName}${path}`;\n }\n\n /** Mirrors `PageRoute.GetPath`: everything up to the segment that first carries a placeholder. */\n private pageOwnPath(route: string): string {\n const index = route.indexOf('{');\n if (index < 0) {\n return route;\n }\n\n const boundary = route.lastIndexOf('/', index);\n return boundary <= 0 ? '/' : route.slice(0, boundary);\n }\n\n /**\n * A rough, client-side mirror of `PageRoute.Build` - see {@link slugPreview}'s remarks. Every\n * placeholder, `{slug}` included, goes through the same generic {@link resolvePlaceholder} - no\n * per-name branch here, deliberately: the server does not have one either, it reflects over `Content`\n * (`Page.ResolveFieldValue`), and a name-by-name `if` ladder here would just be that same mistake\n * moved to TypeScript instead of removed.\n * <p>\n * Placeholders are located with {@link readPlaceholder}'s brace-depth-aware scan, not a single regex -\n * a `/\\{...\\}/` pattern cannot tell a placeholder's own closing brace apart from a balanced one inside\n * its `:REGEX` segment (a quantifier like `\\d{4}`, e.g. in `{publishTime:yyyy-MM:^\\d{4}-(0[1-9]|1[0-2])$}`),\n * the same reason `PageRoute.TryParseTemplate` on the server had to stop using ABP's own tokenizer.\n */\n private buildPreviewPath(route: string): string {\n const canonical = route.replace(OPTIONAL_SLUG_TOKEN, REQUIRED_SLUG_TOKEN);\n\n let result = '';\n let i = 0;\n\n while (i < canonical.length) {\n if (canonical[i] !== '{') {\n result += canonical[i];\n i++;\n continue;\n }\n\n const placeholder = this.readPlaceholder(canonical, i);\n if (!placeholder) {\n // Not a well-formed placeholder start - a route that reaches this component was already\n // validated by `PageRoute.IsValid` when it was saved, so this is only ever a defensive fallback:\n // treat '{' as a literal character rather than throwing out of what is meant to be a best-effort\n // preview.\n result += canonical[i];\n i++;\n continue;\n }\n\n result += this.resolvePlaceholder(placeholder.name, placeholder.format) ?? placeholder.token;\n i = placeholder.end;\n }\n\n return result;\n }\n\n /**\n * Reads one `{name}` / `{name:FORMAT}` / `{name:REGEX}` / `{name:FORMAT:REGEX}` placeholder starting at\n * `route[start]` (must be `'{'`), mirroring `PageRoute.TryParseTemplate`'s single-placeholder case\n * (`src/Dignite.Site.Domain.Shared/Pages/PageRoute.cs`): brace depth is tracked once inside the\n * `:`-segment so an embedded, balanced `{`/`}` does not get mistaken for the placeholder's own closing\n * brace, and a backslash escapes the next character so an explicitly-escaped `\\{`/`\\}` never perturbs\n * the count either. Returns `null` for anything that does not parse as a well-formed placeholder -\n * {@link buildPreviewPath} treats that as a literal `{` rather than failing the whole preview.\n * <p>\n * Only `name` and `format` are extracted, never the regex itself - a placeholder's regex constrains\n * what may be read back out of a request path, and has nothing to say about a value being written into\n * one, the same reason `PageRoute.Build` on the server discards it too (see that method's remarks).\n */\n private readPlaceholder(\n route: string,\n start: number,\n ): { token: string; end: number; name: string; format: string | null } | null {\n let i = start + 1; // consume '{'\n const nameStart = i;\n\n // Mirrors `PageRoute.IsNameStartChar`/`IsNameChar`: every `IdentifierName` a field can have, plus\n // uppercase for `Content`'s camel-cased system properties (`publishTime`).\n if (i >= route.length || !/[a-zA-Z0-9]/.test(route[i])) {\n return null;\n }\n i++;\n while (i < route.length && /[a-zA-Z0-9_-]/.test(route[i])) {\n i++;\n }\n const name = route.slice(nameStart, i);\n\n if (i >= route.length) {\n return null;\n }\n\n if (route[i] === '}') {\n return { token: route.slice(start, i + 1), end: i + 1, name, format: null };\n }\n\n if (route[i] !== ':') {\n return null;\n }\n\n i++; // consume ':'\n const innerStart = i;\n let depth = 0;\n let closed = false;\n\n while (i < route.length) {\n const c = route[i];\n if (c === '\\\\' && i + 1 < route.length) {\n i += 2;\n continue;\n }\n if (c === '{') {\n depth++;\n } else if (c === '}') {\n if (depth === 0) {\n closed = true;\n break;\n }\n depth--;\n }\n i++;\n }\n\n if (!closed) {\n return null;\n }\n\n const inner = route.slice(innerStart, i);\n const end = i + 1; // consume the closing '}'\n return { token: route.slice(start, end), end, name, format: this.disambiguateFormat(inner) };\n }\n\n /**\n * Mirrors `PageRoute.TryDisambiguate`, reduced to the half a preview needs: a placeholder's already\n * brace-depth-isolated inner text (everything after the first `:`) splits into a `:FORMAT` prefix plus a\n * regex remainder when the prefix is format-shaped (letters/digits/`.`/`_`/`-` only - a real format\n * string, by construction, can never also look like a regex worth compiling, which is what keeps every\n * `{name:FORMAT}` route classified exactly as it always was); otherwise the inner text is a bare format\n * on its own if it matches that shape whole, or else it is a regex with no format at all.\n */\n private disambiguateFormat(inner: string): string | null {\n const formatCharacters = /^[a-zA-Z0-9_.-]+$/;\n const colon = inner.indexOf(':');\n\n if (colon >= 0) {\n const candidate = inner.slice(0, colon);\n if (candidate && formatCharacters.test(candidate)) {\n return candidate;\n }\n }\n\n return formatCharacters.test(inner) ? inner : null;\n }\n\n /**\n * Resolves one placeholder's preview text purely from *where* `name` is actually found, never from\n * what it is called. Angular forms have no runtime type to reflect over the way `Content` does server\n * side - `ContentDto` is a TypeScript interface, erased at compile time - so the nearest equivalent is\n * a generic, case-insensitive walk of what is actually on the form and the loaded content, checked in\n * the same order the server would find them: a real property first, `FlexFields` second.\n * 1. A top-level form control - every system field the editor can change lives here (`cultureName`,\n * `status`, `publishTime`, `contentTypeId`, `slug`...), whatever it happens to be named.\n * 2. A control inside `flexFields` - a content type's own business fields.\n * 3. A property already on the loaded `this.content` DTO - covers the read-only audit trail\n * (`id`, `creationTime`, ...) `FullAuditedEntityDto` carries but no form control exists for.\n * Naturally empty until this content has actually been saved once - which is honest, since the\n * server has nothing to reflect there yet either.\n *\n * One deliberate, named exception to \"no name-based branching\": {@link usePageOwnAddress} is a UI-only\n * control with no server-side counterpart, and step 1 cannot tell that apart from a real field by\n * shape alone - a route that actually referenced `{usePageOwnAddress}` would resolve to \"true\"/\"false\"\n * here. Excluding it by name would be exactly the kind of branch this method exists to avoid, and the\n * failure mode is harmless: `Page.BuildContentPath` has no such property either, so a route that made\n * this mistake for real still fails loudly server-side the first time a URL is actually built from it.\n */\n private resolvePlaceholder(name: string, format: string | null): string | null {\n const raw = this.findValue(name);\n if (raw === null || raw === undefined || raw === '') {\n return null;\n }\n\n if (format) {\n const formatted = this.tryFormatByShape(raw, format);\n if (formatted !== null) {\n return formatted;\n }\n }\n\n return String(raw);\n }\n\n /**\n * Applies `format` to `raw` purely from what `raw` looks like, never from which placeholder produced\n * it - the same dispatch-by-shape rule {@link resolvePlaceholder} follows, extended to every shape\n * this preview knows how to format. Mirrors `Page.FormatFieldValue`'s `value is IFormattable` check,\n * just done by sniffing a form value's shape with a regex instead of asking the CLR for its runtime\n * type - there is no such type to ask here, `raw` is already unwrapped to a plain JS value by the time\n * it reaches this method.\n * <p>\n * Each shape is tried in turn; the first one whose regex matches `raw` owns the answer from there,\n * whether or not it actually recognizes `format` - a date-shaped value with a nonsense format is a\n * date that failed to format, not a number or a Guid that happened to also look like one. Recognizing\n * the shape but not the specific `format` asked of it (a Guid's `X`, a numeric format outside\n * {@link formatNumber}'s subset) returns null, same as a shape nothing here recognizes at all - both\n * fall back to the unformatted value in {@link resolvePlaceholder}, deliberately: this is a preview,\n * and a plausible but possibly-wrong guess at an unimplemented format would be worse than showing the\n * plain value.\n */\n private tryFormatByShape(raw: unknown, format: string): string | null {\n const date = this.tryParseDate(raw);\n if (date) {\n return this.formatDate(date, format);\n }\n\n const guid = this.tryParseGuid(raw);\n if (guid) {\n return this.formatGuid(guid, format);\n }\n\n const number = this.tryParseNumber(raw);\n if (number !== null) {\n return this.formatNumber(number, format);\n }\n\n return null;\n }\n\n private findValue(name: string): unknown {\n const lowerName = name.toLowerCase();\n\n const topLevelControls = this.form?.controls;\n const topLevelKey = topLevelControls && Object.keys(topLevelControls).find(key => key.toLowerCase() === lowerName);\n if (topLevelKey) {\n return this.form!.get(topLevelKey)!.value;\n }\n\n const flexFields = this.form?.get('flexFields');\n if (flexFields instanceof FormGroup) {\n const flexKey = Object.keys(flexFields.controls).find(key => key.toLowerCase() === lowerName);\n if (flexKey) {\n return flexFields.get(flexKey)!.value;\n }\n }\n\n if (this.content) {\n const contentRecord = this.content as unknown as Record<string, unknown>;\n const contentKey = Object.keys(contentRecord).find(key => key.toLowerCase() === lowerName);\n if (contentKey !== undefined) {\n return contentRecord[contentKey];\n }\n }\n\n return undefined;\n }\n\n /** Whether `value` is shaped like a `datetime-local` input's own output (`yyyy-MM-ddTHH:mm`). */\n private tryParseDate(value: unknown): Date | null {\n if (typeof value !== 'string' || !/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}/.test(value)) {\n return null;\n }\n\n const date = new Date(value);\n return isNaN(date.getTime()) ? null : date;\n }\n\n /** Only the three specifiers a `:FORMAT` suffix may actually contain (总体设计 §3.3) - no '/' among them. */\n private formatDate(date: Date, format: string): string {\n return format\n .replace(/yyyy/g, String(date.getFullYear()))\n .replace(/yy/g, String(date.getFullYear()).slice(-2))\n .replace(/MM/g, String(date.getMonth() + 1).padStart(2, '0'))\n .replace(/dd/g, String(date.getDate()).padStart(2, '0'));\n }\n\n /** Whether `value` is shaped like the canonical, hyphenated form of a Guid. */\n private tryParseGuid(value: unknown): string | null {\n return typeof value === 'string' &&\n /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value)\n ? value\n : null;\n }\n\n /**\n * `Guid.ToString(format)`'s four straightforward specifiers - N (no separators), D (hyphenated, the\n * shape already checked by {@link tryParseGuid}), B (braced) and P (parenthesized). `X` deliberately\n * not implemented: it renders as a C#-syntax initializer list, not a URL-shaped string, and nothing\n * about a route makes that a plausible thing to have ever asked for.\n */\n private formatGuid(guid: string, format: string): string | null {\n const digits = guid.replace(/-/g, '').toLowerCase();\n const dashed = `${digits.slice(0, 8)}-${digits.slice(8, 12)}-${digits.slice(12, 16)}-${digits.slice(16, 20)}-${digits.slice(20)}`;\n\n switch (format.toUpperCase()) {\n case 'N':\n return digits;\n case 'D':\n return dashed;\n case 'B':\n return `{${dashed}}`;\n case 'P':\n return `(${dashed})`;\n default:\n return null;\n }\n }\n\n /** Whether `value` is shaped like a plain, optionally negative, optionally decimal number. */\n private tryParseNumber(value: unknown): number | null {\n if (typeof value === 'number' && isFinite(value)) {\n return value;\n }\n\n return typeof value === 'string' && /^-?\\d+(\\.\\d+)?$/.test(value) ? Number(value) : null;\n }\n\n /**\n * A representative slice of .NET's numeric format strings - the ones a URL path segment plausibly\n * asks for. Custom zero-padding (`\"0000\"`, unchanged from before) plus four standard specifiers, each\n * with an optional 1-2 digit precision: `D` (zero-padded, integers only - the standard-format spelling\n * of the same thing `\"0000\"` does), `X`/`x` (hexadecimal, integers only, letter case controls digit\n * case, negative not attempted - see {@link formatHex}'s remarks), `F` (fixed-point) and `N`\n * (fixed-point with thousands grouping). Deliberately not `C`/`P` (currency/percent): both put a\n * character that means something else in a URL - a locale-dependent currency symbol, or `%`, the URL\n * escape character itself - into the path, which nothing about routing would ever actually want. Not\n * `E`/`G`/`R` either: those are about round-trip print fidelity for an arbitrary number, not a shape\n * any real route has a reason to ask for.\n */\n private formatNumber(value: number, format: string): string | null {\n if (/^0+$/.test(format)) {\n return Number.isInteger(value) ? this.padInteger(value, format.length) : null;\n }\n\n const standard = /^([DdXxFfNn])(\\d{0,2})$/.exec(format);\n if (!standard) {\n return null;\n }\n\n const [, specifier, precisionText] = standard;\n const precision = precisionText === '' ? null : Number(precisionText);\n\n switch (specifier.toUpperCase()) {\n case 'D':\n return Number.isInteger(value) ? this.padInteger(value, precision ?? 0) : null;\n case 'X':\n return Number.isInteger(value) && value >= 0 ? this.formatHex(value, precision ?? 0, specifier === 'X') : null;\n case 'F':\n return value.toFixed(precision ?? 2);\n case 'N':\n return this.groupThousands(value.toFixed(precision ?? 2));\n default:\n return null;\n }\n }\n\n private padInteger(value: number, width: number): string {\n const negative = value < 0;\n const padded = Math.abs(value).toString().padStart(width, '0');\n return negative ? `-${padded}` : padded;\n }\n\n /**\n * Negative values are rejected before this is ever called - .NET's `X` renders a negative signed\n * integer as its two's-complement bit pattern, which depends on the source type's own width (`int` vs\n * `long` vs `byte` produce different digits for the same value), information a form control's plain\n * number does not carry. Guessing a width would risk a preview that looks plausible and is wrong;\n * not attempting it is the same call already made for a Guid's `X` and for `C`/`P`/`E`/`G`/`R`.\n */\n private formatHex(value: number, width: number, uppercase: boolean): string {\n const hex = value.toString(16).padStart(width, '0');\n return uppercase ? hex.toUpperCase() : hex;\n }\n\n private groupThousands(fixedValue: string): string {\n const negative = fixedValue.startsWith('-');\n const [integerPart, fractionPart] = (negative ? fixedValue.slice(1) : fixedValue).split('.');\n const grouped = integerPart.replace(/\\B(?=(\\d{3})+(?!\\d))/g, ',');\n return `${negative ? '-' : ''}${grouped}${fractionPart ? '.' + fractionPart : ''}`;\n }\n}\n","@if (!isLoading() && form) {\n <form [formGroup]=\"form\" (submit)=\"save()\">\n <div class=\"d-flex justify-content-between align-items-center mb-3\">\n <div>\n <h5 class=\"mb-0\">\n {{ (isEdit ? 'Site::EditContent' : 'Site::NewContent') | abpLocalization }}\n </h5>\n @if (page(); as currentPage) {\n <small class=\"text-muted\">{{ currentPage.displayName }}</small>\n }\n </div>\n <div>\n <a class=\"btn btn-secondary me-2\" [routerLink]=\"['/site/contents']\">\n {{ 'AbpUi::Cancel' | abpLocalization }}\n </a>\n <!-- A plain submit button, not `abp-button`: that component declares its own `click` output,\n so `(click)` binds to an EventEmitter instead of the DOM event, and it takes `buttonType`\n rather than `type`. Both make it easy to end up with a button that quietly never submits.\n Inside a form on a page, the native element says what it does. -->\n <button type=\"submit\" class=\"btn btn-primary\" [disabled]=\"!form.valid || isBusy()\">\n @if (isBusy()) {\n <span class=\"spinner-border spinner-border-sm me-1\" role=\"status\"></span>\n } @else {\n <i class=\"fa fa-check me-1\"></i>\n }\n {{ 'AbpUi::Save' | abpLocalization }}\n </button>\n </div>\n </div>\n\n <div class=\"row g-3\">\n <!-- Left: the content itself - whatever fields its content type defines. -->\n <div class=\"col-lg-8\">\n <div class=\"card h-100\">\n <div class=\"card-body\">\n @if (hasMultipleContentTypes) {\n <div class=\"mb-3 pb-3 border-bottom\">\n <label class=\"form-label\">\n {{ 'Site::DisplayName:Content.ContentType' | abpLocalization }}\n </label>\n <select\n class=\"form-select\"\n formControlName=\"contentTypeId\"\n (change)=\"onContentTypeChange()\"\n >\n @for (contentType of contentTypes(); track contentType.id) {\n <option [value]=\"contentType.id\">{{ contentType.displayName }}</option>\n }\n </select>\n <small class=\"form-text text-muted\">\n {{ 'Site::ContentTypeSwitchHint' | abpLocalization }}\n </small>\n </div>\n }\n\n @if (fields().length > 0) {\n @for (fieldValue of fields(); track fieldValue.field.name) {\n <ff-flex-field-control\n [fields]=\"fieldValue\"\n [entity]=\"form\"\n parentFieldName=\"flexFields\"\n [selected]=\"fieldValue.value\"\n ></ff-flex-field-control>\n @if (fieldErrorMessage(fieldValue); as message) {\n <div class=\"invalid-feedback d-block mb-3\">{{ message }}</div>\n }\n }\n } @else {\n <p class=\"text-muted mb-0\">{{ 'Site::NoFieldsArranged' | abpLocalization }}</p>\n }\n </div>\n </div>\n </div>\n\n <!-- Right: the system fields that place and schedule the content. -->\n <div class=\"col-lg-4\">\n <div class=\"card\">\n <div class=\"card-body\">\n @if (!hasMultipleContentTypes && contentTypes().length === 1) {\n <div class=\"mb-3\">\n <label class=\"form-label\">\n {{ 'Site::DisplayName:Content.ContentType' | abpLocalization }}\n </label>\n <input type=\"text\" class=\"form-control\" [value]=\"contentTypes()[0].displayName\" disabled />\n </div>\n }\n\n <div class=\"mb-3\">\n <label class=\"form-label\">\n {{ 'Site::DisplayName:Content.CultureName' | abpLocalization }}\n </label>\n <select class=\"form-select\" formControlName=\"cultureName\" (change)=\"onCultureNameChange()\">\n @for (language of languages(); track language) {\n <option [value]=\"language\">{{ language }}</option>\n }\n </select>\n </div>\n\n <!-- The page's route (总体设计 §3.3) decides this, not the editor: no {slug}/{slug?} at all\n means nothing is shown here - there is nothing to choose. -->\n @if (slugState !== 'forbidden') {\n <div class=\"mb-3\">\n <label class=\"form-label\">{{ 'Site::DisplayName:Content.Slug' | abpLocalization }}</label>\n\n @if (slugState === 'optional' && !emptySlotTaken()) {\n <div class=\"form-check mb-2\">\n <input\n type=\"checkbox\"\n class=\"form-check-input\"\n id=\"site-use-page-own-address\"\n formControlName=\"usePageOwnAddress\"\n (change)=\"onUsePageOwnAddressChange()\"\n />\n <label class=\"form-check-label\" for=\"site-use-page-own-address\">\n {{ 'Site::UsePageOwnAddress' | abpLocalization }}\n </label>\n </div>\n }\n\n @if (!usePageOwnAddress) {\n <input type=\"text\" class=\"form-control\" formControlName=\"slug\" />\n <small class=\"form-text text-muted d-block mt-1\">\n {{ 'Site::Description:Content.Slug' | abpLocalization }}\n </small>\n }\n\n @if (slugState === 'optional' && emptySlotTaken()) {\n <small class=\"form-text text-muted d-block mt-1\">\n {{ 'Site::SlugSlotTaken' | abpLocalization }}\n </small>\n }\n\n <small class=\"form-text text-muted d-block mt-1\">\n {{ 'Site::SlugPreview' | abpLocalization: slugPreview }}\n </small>\n </div>\n }\n\n <div class=\"mb-3\">\n <label class=\"form-label\">{{ 'Site::DisplayName:Content.Status' | abpLocalization }}</label>\n <select class=\"form-select\" formControlName=\"status\" (change)=\"onStatusChange()\">\n @for (status of statuses; track status) {\n <option [ngValue]=\"status\">{{ statusKeyOf(status) | abpLocalization }}</option>\n }\n </select>\n </div>\n\n <div class=\"mb-0\">\n <label class=\"form-label\">\n {{ 'Site::DisplayName:Content.PublishTime' | abpLocalization }}\n </label>\n <input type=\"datetime-local\" class=\"form-control\" formControlName=\"publishTime\" />\n @if (isDraft) {\n <small class=\"form-text text-muted\">\n {{ 'Site::DraftPublishTimeDisabledHint' | abpLocalization }}\n </small>\n }\n </div>\n </div>\n </div>\n </div>\n </div>\n </form>\n}\n"],"names":[],"mappings":"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"}
|