@dignite/ng.site 0.0.0-stage → 1.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 CHANGED
@@ -1,3 +1,124 @@
1
- # Temporary Holding Version
1
+ # @dignite/ng.site
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ The Angular library for Dignite Site's admin UI: routes, components, and services under `src/`
4
+ (imported as `@dignite/ng.site`), plus `provideSite()` and friends under `config/`
5
+ (imported as `@dignite/ng.site/config`).
6
+
7
+ ## Installing
8
+
9
+ ```bash
10
+ npm install @dignite/ng.site
11
+ ```
12
+
13
+ (Pre-release builds are published to GitHub Packages as `@dignite-projects/ng.site`; see the root
14
+ [README](../../README.md) / `angular/.npmrc` for the registry setup, and alias the dependency:
15
+ `"@dignite/ng.site": "npm:@dignite-projects/ng.site@<version>"`.)
16
+
17
+ ### CKEditor dependency and the file library
18
+
19
+ `provideSite()` (from `@dignite/ng.site/config`) unconditionally registers the CKEditor field type and
20
+ Site's own field types - it's not optional, skipping one makes `FieldTypeResolver.get(...)` throw and the
21
+ content editor fails to render entirely. So this package declares `@dignite/ng.flex-fields-ckeditor` as
22
+ its own `dependency`, not a `peerDependency` - and from `10.0.0-rc.13` that adapter in turn declares
23
+ everything *it* needs (`@ckeditor/ckeditor5-angular`, `ckeditor5`, `marked`) as its own dependencies
24
+ rather than peers. `npm install @dignite/ng.site` (see "Installing" above) is the whole install; there's
25
+ nothing to add by hand.
26
+
27
+ The file picker, the file field type (registration key `FileExplorer`) and the SEO share-image picker
28
+ are this package's own (`src/lib/files`, `src/lib/field-types/file`) and talk to Site's admin API
29
+ (`apiName: 'SiteAdmin'`) - there is no separate file-picker package to install any more, and no extra
30
+ entry to keep in `environment.apis`. `provideSite()` also registers `SiteCKEditorUploadProvider` as the
31
+ `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 `docs/site-files.md`.
33
+
34
+ That `>= 10.0.0-rc.13` floor is load-bearing, not cosmetic. Below `rc.12` those packages were
35
+ the adapters' `peerDependencies`, and every ABP 10.7 + Angular 22 host installs with
36
+ `--legacy-peer-deps` (`@abp/ng.theme.shared` pins `@swimlane/ngx-datatable@~22`, whose own Angular
37
+ peer range stops at 20), under which npm does not install peers at all. Loosening the floor back
38
+ below `rc.12` would silently reintroduce four unresolvable imports - discovered at the consuming
39
+ app's build, with nothing in `npm install` to warn about them.
40
+
41
+ During the pre-release (GitHub Packages) channel you do not need to separately alias the
42
+ `@dignite/*` packages this one depends on (`@dignite/ng.flex-fields` and the adapter above) -
43
+ the release workflow's scope-swap step rewrites every `@dignite/*` entry under `dependencies` in
44
+ the published package.json to the same alias form used for `@dignite/ng.site` itself above. That
45
+ step never covered `peerDependencies`, which is exactly why the old manual alias instruction lived
46
+ here.
47
+
48
+ ### Required global styles (ng-zorro-antd)
49
+
50
+ `@dignite/ng.site` builds several fields on `ng-zorro-antd` (`nz-tree`, `nz-tree-select`, `nz-select`,
51
+ `nz-autocomplete` - pulled in directly or via the `@dignite/ng.flex-fields` dependency). These
52
+ components render their dropdown/panel content through Angular CDK's overlay, which attaches
53
+ directly to `<body>` outside this library's view tree - so they can only be styled with global CSS,
54
+ never with the scoped component styles an Angular library ships to consumers.
55
+
56
+ That makes this a hard limitation, not an oversight: ng-packagr has no mechanism to add entries to
57
+ a *consuming application's* `angular.json` (or global style bundle), so every app that installs
58
+ `@dignite/ng.site` has to register these stylesheets itself. Skipping this doesn't break the
59
+ build - it silently leaves the affected controls unstyled (e.g. a tree-select panel with no
60
+ background or positioning). This has already caught out two separate hosts (this repo's own `Host`
61
+ app and the `cloud` project both needed the identical fix) - budget for it on every new one.
62
+
63
+ Add to the host app's `angular.json`, in `projects.<app>.architect.build.options.styles`:
64
+
65
+ ```jsonc
66
+ { "input": "node_modules/ng-zorro-antd/tree/style/index.min.css", "inject": false, "bundleName": "ng-zorro-antd-tree" },
67
+ { "input": "node_modules/ng-zorro-antd/tree-select/style/index.min.css", "inject": true, "bundleName": "ng-zorro-antd-tree-select" },
68
+ { "input": "node_modules/ng-zorro-antd/select/style/index.min.css", "inject": false, "bundleName": "ng-zorro-antd-select" },
69
+ { "input": "node_modules/ng-zorro-antd/auto-complete/style/index.min.css", "inject": true, "bundleName": "ng-zorro-antd-auto-complete" },
70
+ { "input": "node_modules/ckeditor5/dist/ckeditor5.css", "inject": false, "bundleName": "ckeditor5" }
71
+ ```
72
+
73
+ The three `inject: false` entries are fetched at runtime by fixed file name - `ng-zorro-antd-tree.css`
74
+ by ABP's `<abp-tree>` (which flex-fields' `Tree` field types and this library's content-list page
75
+ filter render; this is the entry ABP's own 7.0 migration guide prescribes), `ng-zorro-antd-select.css`
76
+ by `@dignite/ng.flex-fields`' `Select`
77
+ controls and by this library's field arrangement picker, and `ckeditor5.css` by
78
+ `@dignite/ng.flex-fields-ckeditor`, which `@dignite/ng.site/config` always registers.
79
+ `inject: false` is what keeps those names literal: under the production `outputHashing: "all"` an
80
+ injected entry is emitted under a content hash, so the fetch 404s. For the two flex-fields bundles
81
+ that costs a console error - and for `ckeditor5`, an editor that renders as blank space. For
82
+ `ng-zorro-antd-tree` it is worse: `abp-tree` loads with no retry limit, and ABP's `LazyLoadService`
83
+ removes and re-inserts the failed `<link>` on every attempt, so an injected tree entry turns into an
84
+ unbroken stream of 404 requests for as long as a tree is on screen. See the "Styles" section of the
85
+ `@dignite/ng.flex-fields` and `@dignite/ng.flex-fields-ckeditor` READMEs (>= 10.0.0-rc.17).
86
+
87
+ If the host doesn't wire global styles through `angular.json`, `@import` the two injected paths
88
+ from its root stylesheet instead; the three fetched by name still need their `angular.json` entries.
89
+
90
+ `ng-zorro-antd` itself is declared as a direct `dependency` of `@dignite/ng.site` (not a peer), the
91
+ same way `@angular/cdk` is: every consumer needs it unconditionally, there's no opt-out the way
92
+ there is for the CKEditor/File Explorer field types, so there's no reason to push the install step
93
+ onto the host. Both stay on their 21 line on an Angular 22 host, because that is what ABP 10.7 brings:
94
+ `@abp/ng.components` 10.7.0 depends on `ng-zorro-antd` `~21.3.1`, and `ng-zorro-antd` 21.3 depends on
95
+ `@angular/cdk` `^21`. They are declared as `~21.3.1` and `~21.2.0` so a host that declares the same ranges
96
+ gets one copy of each; a range the ABP copy does not satisfy (`ng-zorro-antd` 22 or `@angular/cdk` 22) is
97
+ installed beside it, giving two module-scoped `NZ_CONFIG` / `NzConfigService` tokens.
98
+ `@swimlane/ngx-datatable` is different - it's a `peerDependency` here because
99
+ `@abp/ng.theme.shared` already guarantees every ABP host has it.
100
+
101
+ This list only covers what `@dignite/ng.site` and `@dignite/ng.flex-fields` import as of this writing.
102
+ Re-derive it before trusting it on a new `ng-zorro-antd` version, or after either package adds a new
103
+ field type:
104
+
105
+ ```bash
106
+ grep -rohE "ng-zorro-antd/[a-z-]+" node_modules/@dignite/ng.site node_modules/@dignite/ng.flex-fields | sort -u
107
+ ```
108
+
109
+ ## Code scaffolding
110
+
111
+ Run `ng generate component component-name --project site` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module --project site`.
112
+ > Note: Don't forget to add `--project site` or else it will be added to the default project in your `angular.json` file.
113
+
114
+ ## Build
115
+
116
+ Run `ng build site` to build the project. The build artifacts will be stored in the `dist/` directory.
117
+
118
+ ## Running unit tests
119
+
120
+ Run `ng test site` to execute the unit tests via [Vitest](https://vitest.dev).
121
+
122
+ ## Further help
123
+
124
+ To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.io/cli) page.
@@ -0,0 +1,87 @@
1
+ import { RoutesService } from '@abp/ng.core';
2
+ import { provideFlexFields } from '@dignite/ng.flex-fields';
3
+ import { CKEDITOR_UPLOAD_PROVIDER, CKEDITOR_CONFIG_CONTRIBUTORS, CKEDITOR_DISPLAY_CONTRIBUTORS, provideCKEditorFieldType } from '@dignite/ng.flex-fields-ckeditor';
4
+ import { SiteCKEditorUploadProvider, siteCKEditorConfigContributor, siteCKEditorDisplayContributor, SEO_FIELD_TYPE, CONTENT_FIELD_TYPE, FILE_FIELD_TYPE } from '@dignite/ng.site';
5
+ import { provideAppInitializer, inject, makeEnvironmentProviders } from '@angular/core';
6
+
7
+ const SITE_ROUTE_PROVIDERS = [
8
+ provideAppInitializer(() => {
9
+ configureRoutes();
10
+ }),
11
+ ];
12
+ function configureRoutes() {
13
+ const routesService = inject(RoutesService);
14
+ routesService.add([
15
+ {
16
+ path: '/site',
17
+ name: "Site::Menu:Site" /* eSiteRouteNames.Site */,
18
+ iconClass: 'fas fa-globe',
19
+ layout: "application" /* eLayoutType.application */,
20
+ order: 3,
21
+ requiredPolicy: 'SiteAdmin.Pages || SiteAdmin.ContentTypes || SiteAdmin.Fields || SiteAdmin.Contents',
22
+ },
23
+ {
24
+ path: '/site/contents',
25
+ name: "Site::Menu:Contents" /* eSiteRouteNames.Contents */,
26
+ parentName: "Site::Menu:Site" /* eSiteRouteNames.Site */,
27
+ iconClass: 'fas fa-file-lines',
28
+ layout: "application" /* eLayoutType.application */,
29
+ order: 1,
30
+ requiredPolicy: 'SiteAdmin.Contents',
31
+ },
32
+ {
33
+ path: '/site/pages',
34
+ name: "Site::Menu:Pages" /* eSiteRouteNames.Pages */,
35
+ parentName: "Site::Menu:Site" /* eSiteRouteNames.Site */,
36
+ iconClass: 'fas fa-file-code',
37
+ layout: "application" /* eLayoutType.application */,
38
+ order: 2,
39
+ requiredPolicy: 'SiteAdmin.Pages',
40
+ },
41
+ {
42
+ path: '/site/fields',
43
+ name: "Site::Menu:Fields" /* eSiteRouteNames.Fields */,
44
+ parentName: "Site::Menu:Site" /* eSiteRouteNames.Site */,
45
+ iconClass: 'fas fa-list-check',
46
+ layout: "application" /* eLayoutType.application */,
47
+ order: 3,
48
+ requiredPolicy: 'SiteAdmin.Fields',
49
+ },
50
+ ]);
51
+ // Content types have no menu entry: they belong to a page, and are reached from the Pages list.
52
+ }
53
+ const SITE_PROVIDERS = [
54
+ ...SITE_ROUTE_PROVIDERS,
55
+ // The six built-ins (Matrix/Table among them as of flex-fields 10.0.0-rc.16, via
56
+ // provideFlexFields()'s own BUILT_IN_FIELD_TYPES - they used to be Site's own MATRIX_FIELD_TYPE/
57
+ // TABLE_FIELD_TYPE, registered explicitly here, until flex-fields shipped them as kernel built-ins)
58
+ // 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
59
+ // injected, so this has to happen at application-config level - registering from inside the
60
+ // lazy-loaded Site routes would come too late for a resolver already constructed.
61
+ provideFlexFields(SEO_FIELD_TYPE, CONTENT_FIELD_TYPE, FILE_FIELD_TYPE),
62
+ // The CKEditor field type (GitHub issue #43). Unlike the server, where DependsOn plus DI discovery is
63
+ // enough (总体设计 §8.2), the client has no equivalent - each field type's control/config/view trio has
64
+ // to be registered explicitly or FieldTypeResolver.get(...) throws and the content editor breaks on
65
+ // first use, the same failure mode SEO_FIELD_TYPE's own comment warns about.
66
+ provideCKEditorFieldType(),
67
+ // Inline images in a CKEditor field go into Site's file library (the field's CKEditor.ImagesContainerName,
68
+ // normally images) and are embedded by their public address. Without a provider the editor shows
69
+ // no upload button at all.
70
+ { provide: CKEDITOR_UPLOAD_PROVIDER, useExisting: SiteCKEditorUploadProvider },
71
+ // Those addresses are stored relative (/api/site-public/files/...); the editor shows them from the
72
+ // SiteAdmin API's host, in its editing view only - getData(), and so what is saved, stays relative.
73
+ { provide: CKEDITOR_CONFIG_CONTRIBUTORS, multi: true, useFactory: siteCKEditorConfigContributor },
74
+ // The read-only view (ff-ckeditor-view: a content list cell) has no editor to convert in, so its HTML gets
75
+ // the same host in front of those addresses before it is rendered; nothing is saved from there.
76
+ { provide: CKEDITOR_DISPLAY_CONTRIBUTORS, multi: true, useFactory: siteCKEditorDisplayContributor },
77
+ ];
78
+ function provideSite() {
79
+ return makeEnvironmentProviders(SITE_PROVIDERS);
80
+ }
81
+
82
+ /**
83
+ * Generated bundle index. Do not edit.
84
+ */
85
+
86
+ export { SITE_ROUTE_PROVIDERS, configureRoutes, provideSite };
87
+ //# sourceMappingURL=dignite-ng.site-config.mjs.map
@@ -0,0 +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,qFAAqF;AACxF,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;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;;ACvGA;;AAEG;;;;"}