diff --git a/npm/ng-packs/guides/CMS_KIT_ANGULAR_STRUCTURE.md b/npm/ng-packs/guides/CMS_KIT_ANGULAR_STRUCTURE.md index 47b8b74375..478e01dd73 100644 --- a/npm/ng-packs/guides/CMS_KIT_ANGULAR_STRUCTURE.md +++ b/npm/ng-packs/guides/CMS_KIT_ANGULAR_STRUCTURE.md @@ -1175,31 +1175,31 @@ export enum eCmsKitAdminRouteNames { ### Phase 1: Foundation -- [ ] Create package structure (admin, public, proxy) -- [ ] Set up TypeScript configurations -- [ ] Set up ng-package.json files -- [ ] Create base models and enums -- [ ] Set up service base classes +- [x] Create package structure (admin, public, proxy) +- [x] Set up TypeScript configurations +- [x] Set up ng-package.json files +- [x] Create base models and enums +- [x] Set up service base classes ### Phase 2: Admin - Comments Feature -- [ ] Create CommentListComponent -- [ ] Create CommentApproveComponent -- [ ] Create CommentDetailsComponent -- [ ] Create default extension points -- [ ] Add routes and providers +- [x] Create CommentListComponent +- [x] Create CommentApproveComponent +- [x] Create CommentDetailsComponent +- [x] Create default extension points +- [x] Add routes and providers ### Phase 3: Admin - Tags Feature -- [ ] Create Tag components -- [ ] Create default extension points -- [ ] Add routes and providers +- [x] Create Tag components +- [x] Create default extension points +- [x] Add routes and providers ### Phase 4: Admin - Pages Feature -- [ ] Create Page components -- [ ] Create default extension points -- [ ] Add routes and providers +- [x] Create Page components +- [x] Create default extension points +- [x] Add routes and providers ### Phase 5: Admin - Blogs Feature diff --git a/npm/ng-packs/packages/cms-kit/admin/src/cms-kit-admin.routes.ts b/npm/ng-packs/packages/cms-kit/admin/src/cms-kit-admin.routes.ts index 842c0b67e1..7e175581ff 100644 --- a/npm/ng-packs/packages/cms-kit/admin/src/cms-kit-admin.routes.ts +++ b/npm/ng-packs/packages/cms-kit/admin/src/cms-kit-admin.routes.ts @@ -12,6 +12,8 @@ import { CommentApproveComponent, CommentDetailsComponent, TagListComponent, + PageListComponent, + PageFormComponent, } from './components'; import { CMS_KIT_ADMIN_ENTITY_ACTION_CONTRIBUTORS, @@ -91,6 +93,51 @@ export function createRoutes(config: CmsKitAdminConfigOptions = {}): Routes { }, title: 'CmsKit::Tags', }, + { + path: 'pages', + component: ReplaceableRouteContainerComponent, + resolve: { + extensions: cmsKitAdminExtensionsResolver, + }, + data: { + requiredPolicy: 'CmsKit.Pages', + replaceableComponent: { + key: eCmsKitAdminComponents.PageList, + defaultComponent: PageListComponent, + }, + }, + title: 'CmsKit::Pages', + }, + { + path: 'pages/create', + component: ReplaceableRouteContainerComponent, + resolve: { + extensions: cmsKitAdminExtensionsResolver, + }, + data: { + requiredPolicy: 'CmsKit.Pages.Create', + replaceableComponent: { + key: eCmsKitAdminComponents.PageCreate, + defaultComponent: PageFormComponent, + }, + }, + title: 'CmsKit::Pages', + }, + { + path: 'pages/update/:id', + component: ReplaceableRouteContainerComponent, + resolve: { + extensions: cmsKitAdminExtensionsResolver, + }, + data: { + requiredPolicy: 'CmsKit.Pages.Update', + replaceableComponent: { + key: eCmsKitAdminComponents.PageEdit, + defaultComponent: PageFormComponent, + }, + }, + title: 'CmsKit::Pages', + }, ], }, ]; diff --git a/npm/ng-packs/packages/cms-kit/admin/src/components/comments/comment-list/comment-list.component.ts b/npm/ng-packs/packages/cms-kit/admin/src/components/comments/comment-list/comment-list.component.ts index 3707ec306e..caceba65ee 100644 --- a/npm/ng-packs/packages/cms-kit/admin/src/components/comments/comment-list/comment-list.component.ts +++ b/npm/ng-packs/packages/cms-kit/admin/src/components/comments/comment-list/comment-list.component.ts @@ -18,7 +18,6 @@ import { CMS_KIT_COMMENTS_REQUIRE_APPROVEMENT } from '../constants'; @Component({ selector: 'abp-comment-list', - standalone: true, templateUrl: './comment-list.component.html', providers: [ ListService, diff --git a/npm/ng-packs/packages/cms-kit/admin/src/components/index.ts b/npm/ng-packs/packages/cms-kit/admin/src/components/index.ts index 6b7110fd21..72b16d664e 100644 --- a/npm/ng-packs/packages/cms-kit/admin/src/components/index.ts +++ b/npm/ng-packs/packages/cms-kit/admin/src/components/index.ts @@ -1,6 +1,6 @@ export * from './comments'; export * from './tags'; -// export * from './pages'; +export * from './pages'; // export * from './blogs'; // export * from './blog-posts'; // export * from './menus'; diff --git a/npm/ng-packs/packages/cms-kit/admin/src/components/pages/index.ts b/npm/ng-packs/packages/cms-kit/admin/src/components/pages/index.ts new file mode 100644 index 0000000000..c2665da015 --- /dev/null +++ b/npm/ng-packs/packages/cms-kit/admin/src/components/pages/index.ts @@ -0,0 +1,2 @@ +export * from './page-list/page-list.component'; +export * from './page-form/page-form.component'; diff --git a/npm/ng-packs/packages/cms-kit/admin/src/components/pages/page-form/page-form.component.html b/npm/ng-packs/packages/cms-kit/admin/src/components/pages/page-form/page-form.component.html new file mode 100644 index 0000000000..0dc5c4a296 --- /dev/null +++ b/npm/ng-packs/packages/cms-kit/admin/src/components/pages/page-form/page-form.component.html @@ -0,0 +1,57 @@ + + + + @if (form && (!isEditMode || page)) { + + + + + + + + {{ 'CmsKit::Content' | abpLocalization }} + + + + + + + + + {{ 'CmsKit::Script' | abpLocalization }} + + + + + + + + + {{ 'CmsKit::Style' | abpLocalization }} + + + + + + + + + + } @else { + + + + } + + + + diff --git a/npm/ng-packs/packages/cms-kit/admin/src/components/pages/page-form/page-form.component.ts b/npm/ng-packs/packages/cms-kit/admin/src/components/pages/page-form/page-form.component.ts new file mode 100644 index 0000000000..eeaa5a9411 --- /dev/null +++ b/npm/ng-packs/packages/cms-kit/admin/src/components/pages/page-form/page-form.component.ts @@ -0,0 +1,166 @@ +import { Component, OnInit, inject, Injector, DestroyRef } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; +import { CommonModule } from '@angular/common'; +import { ReactiveFormsModule, FormGroup, FormControl } from '@angular/forms'; +import { ActivatedRoute } from '@angular/router'; +import { NgbNavModule } from '@ng-bootstrap/ng-bootstrap'; +import { NgxValidateCoreModule } from '@ngx-validate/core'; +import { LocalizationPipe } from '@abp/ng.core'; +import { + ExtensibleFormComponent, + FormPropData, + generateFormFromProps, + EXTENSIONS_IDENTIFIER, +} from '@abp/ng.components/extensible'; +import { PageComponent } from '@abp/ng.components/page'; +import { ButtonComponent } from '@abp/ng.theme.shared'; +import { ToastuiEditorComponent, CodeMirrorEditorComponent } from '@abp/ng.cms-kit'; +import { PageAdminService, PageDto } from '@abp/ng.cms-kit/proxy'; +import { eCmsKitAdminComponents } from '../../../enums'; +import { PageFormService } from '../../../services'; + +@Component({ + selector: 'abp-page-form', + templateUrl: './page-form.component.html', + providers: [ + { + provide: EXTENSIONS_IDENTIFIER, + useFactory: (route: ActivatedRoute) => { + const id = route.snapshot.params['id']; + if (id) { + return eCmsKitAdminComponents.PageEdit; + } + return eCmsKitAdminComponents.PageCreate; + }, + deps: [ActivatedRoute], + }, + ], + imports: [ + ButtonComponent, + CodeMirrorEditorComponent, + ExtensibleFormComponent, + PageComponent, + ToastuiEditorComponent, + LocalizationPipe, + ReactiveFormsModule, + CommonModule, + NgxValidateCoreModule, + NgbNavModule, + ], +}) +export class PageFormComponent implements OnInit { + private pageService = inject(PageAdminService); + private injector = inject(Injector); + private pageFormService = inject(PageFormService); + private route = inject(ActivatedRoute); + private destroyRef = inject(DestroyRef); + + form: FormGroup; + page: PageDto | null = null; + pageId: string | null = null; + isEditMode = false; + + ngOnInit() { + const id = this.route.snapshot.params['id']; + if (id) { + this.isEditMode = true; + this.pageId = id; + this.loadPage(id); + } else { + this.isEditMode = false; + this.buildForm(); + } + } + + private loadPage(id: string) { + this.pageService.get(id).subscribe(page => { + this.page = page; + this.buildForm(); + }); + } + + private buildForm() { + const data = new FormPropData(this.injector, this.page || {}); + const baseForm = generateFormFromProps(data); + this.form = new FormGroup({ + ...baseForm.controls, + content: new FormControl(this.page?.content || ''), + script: new FormControl(this.page?.script || ''), + style: new FormControl(this.page?.style || ''), + }); + this.prepareSlug(); + } + + private executeSaveOperation(operation: 'save' | 'draft' | 'publish') { + if (this.isEditMode) { + if (!this.page || !this.pageId) { + return; + } + + switch (operation) { + case 'save': + this.pageFormService.update(this.pageId, this.form, this.page).subscribe(); + break; + case 'draft': + this.pageFormService.updateAsDraft(this.pageId, this.form, this.page).subscribe(); + break; + case 'publish': + this.pageFormService.updateAndPublish(this.pageId, this.form, this.page).subscribe(); + break; + } + return; + } + + switch (operation) { + case 'save': + this.pageFormService.create(this.form).subscribe(); + break; + case 'draft': + this.pageFormService.createAsDraft(this.form).subscribe(); + break; + case 'publish': + this.pageFormService.publish(this.form).subscribe(); + break; + } + } + + private dasharize(text: string): string { + return text + .trim() + .replace(/([a-z])([A-Z])/g, '$1-$2') + .replace(/([A-Z]+)([A-Z][a-z])/g, '$1-$2') + .replace(/[\s_]+/g, '-') + .replace(/[^\w\s-]/g, '') + .replace(/-+/g, '-') + .replace(/^-+|-+$/g, '') + .toLowerCase(); + } + + save() { + this.executeSaveOperation('save'); + } + + saveAsDraft() { + this.executeSaveOperation('draft'); + } + + publish() { + this.executeSaveOperation('publish'); + } + + prepareSlug() { + const titleControl = this.form.get('title'); + const slugControl = this.form.get('slug'); + if (titleControl && slugControl) { + titleControl.valueChanges.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(title => { + if (title && typeof title === 'string') { + const dasharized = this.dasharize(title); + const currentSlug = slugControl.value || ''; + if (dasharized !== currentSlug) { + slugControl.setValue(dasharized, { emitEvent: false }); + } + } + }); + } + } +} diff --git a/npm/ng-packs/packages/cms-kit/admin/src/components/pages/page-list/page-list.component.html b/npm/ng-packs/packages/cms-kit/admin/src/components/pages/page-list/page-list.component.html new file mode 100644 index 0000000000..3f87c51b2b --- /dev/null +++ b/npm/ng-packs/packages/cms-kit/admin/src/components/pages/page-list/page-list.component.html @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/npm/ng-packs/packages/cms-kit/admin/src/components/pages/page-list/page-list.component.ts b/npm/ng-packs/packages/cms-kit/admin/src/components/pages/page-list/page-list.component.ts new file mode 100644 index 0000000000..98ad14ec18 --- /dev/null +++ b/npm/ng-packs/packages/cms-kit/admin/src/components/pages/page-list/page-list.component.ts @@ -0,0 +1,56 @@ +import { Component, OnInit, inject } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { FormsModule } from '@angular/forms'; +import { ListService, PagedResultDto, LocalizationPipe } from '@abp/ng.core'; +import { ExtensibleTableComponent, EXTENSIONS_IDENTIFIER } from '@abp/ng.components/extensible'; +import { PageComponent } from '@abp/ng.components/page'; +import { PageAdminService, GetPagesInputDto, PageDto } from '@abp/ng.cms-kit/proxy'; +import { eCmsKitAdminComponents } from '../../../enums'; + +@Component({ + selector: 'abp-page-list', + templateUrl: './page-list.component.html', + providers: [ + ListService, + { + provide: EXTENSIONS_IDENTIFIER, + useValue: eCmsKitAdminComponents.PageList, + }, + ], + imports: [ExtensibleTableComponent, PageComponent, LocalizationPipe, FormsModule, CommonModule], +}) +export class PageListComponent implements OnInit { + data: PagedResultDto = { items: [], totalCount: 0 }; + + public readonly list = inject(ListService); + private pageService = inject(PageAdminService); + + filter = ''; + + ngOnInit() { + this.hookToQuery(); + } + + onSearch() { + this.list.filter = this.filter; + this.list.get(); + } + + private hookToQuery() { + this.list + .hookToQuery(query => { + let filters: Partial = {}; + if (this.list.filter) { + filters.filter = this.list.filter; + } + const input: GetPagesInputDto = { + ...query, + ...filters, + }; + return this.pageService.getList(input); + }) + .subscribe(res => { + this.data = res; + }); + } +} diff --git a/npm/ng-packs/packages/cms-kit/admin/src/defaults/index.ts b/npm/ng-packs/packages/cms-kit/admin/src/defaults/index.ts index 3438aaf406..6dd37dc974 100644 --- a/npm/ng-packs/packages/cms-kit/admin/src/defaults/index.ts +++ b/npm/ng-packs/packages/cms-kit/admin/src/defaults/index.ts @@ -1,2 +1,3 @@ export * from './comments'; export * from './tags'; +export * from './pages'; diff --git a/npm/ng-packs/packages/cms-kit/admin/src/defaults/pages/default-page-create-form-props.ts b/npm/ng-packs/packages/cms-kit/admin/src/defaults/pages/default-page-create-form-props.ts new file mode 100644 index 0000000000..a79f9dbec3 --- /dev/null +++ b/npm/ng-packs/packages/cms-kit/admin/src/defaults/pages/default-page-create-form-props.ts @@ -0,0 +1,52 @@ +import { Validators } from '@angular/forms'; +import { of } from 'rxjs'; +import { CreatePageInputDto, UpdatePageInputDto } from '@abp/ng.cms-kit/proxy'; +import { FormProp, ePropType } from '@abp/ng.components/extensible'; +import { pageStatusOptions } from '@abp/ng.cms-kit/proxy'; +import { LAYOUT_CONSTANTS } from './layout-constants'; + +export const DEFAULT_PAGE_CREATE_FORM_PROPS = FormProp.createMany([ + { + type: ePropType.String, + name: 'title', + displayName: 'CmsKit::Title', + id: 'title', + validators: () => [Validators.required], + }, + { + type: ePropType.String, + name: 'slug', + displayName: 'CmsKit::Slug', + id: 'slug', + validators: () => [Validators.required], + tooltip: { + text: 'CmsKit::PageSlugInformation', + localizationParams: [''], + }, + }, + { + type: ePropType.Enum, + name: 'layoutName', + displayName: 'CmsKit::SelectLayout', + id: 'layoutName', + options: () => + of( + Object.values(LAYOUT_CONSTANTS).map(layout => ({ + key: layout, + value: layout.toUpperCase(), + })), + ), + validators: () => [Validators.required], + }, + { + type: ePropType.Enum, + name: 'status', + displayName: 'CmsKit::Status', + id: 'status', + options: () => of(pageStatusOptions), + validators: () => [Validators.required], + }, +]); + +export const DEFAULT_PAGE_EDIT_FORM_PROPS: FormProp[] = + DEFAULT_PAGE_CREATE_FORM_PROPS; diff --git a/npm/ng-packs/packages/cms-kit/admin/src/defaults/pages/default-page-entity-actions.ts b/npm/ng-packs/packages/cms-kit/admin/src/defaults/pages/default-page-entity-actions.ts new file mode 100644 index 0000000000..a4a7e5a33c --- /dev/null +++ b/npm/ng-packs/packages/cms-kit/admin/src/defaults/pages/default-page-entity-actions.ts @@ -0,0 +1,56 @@ +import { Router } from '@angular/router'; +import { ListService } from '@abp/ng.core'; +import { EntityAction } from '@abp/ng.components/extensible'; +import { ConfirmationService, Confirmation, ToasterService } from '@abp/ng.theme.shared'; +import { PageAdminService, PageDto } from '@abp/ng.cms-kit/proxy'; + +export const DEFAULT_PAGE_ENTITY_ACTIONS = EntityAction.createMany([ + { + text: 'AbpUi::Edit', + action: data => { + const router = data.getInjected(Router); + router.navigate(['/cms/pages/update', data.record.id]); + }, + permission: 'CmsKit.Pages.Update', + }, + { + text: 'AbpUi::Delete', + action: data => { + const pageService = data.getInjected(PageAdminService); + const confirmationService = data.getInjected(ConfirmationService); + const list = data.getInjected(ListService); + + confirmationService + .warn('CmsKit::PageDeletionConfirmationMessage', 'AbpUi::AreYouSure', { + yesText: 'AbpUi::Yes', + cancelText: 'AbpUi::Cancel', + }) + .subscribe((status: Confirmation.Status) => { + if (status === Confirmation.Status.confirm) { + pageService.delete(data.record.id!).subscribe(() => { + list.get(); + }); + } + }); + }, + permission: 'CmsKit.Pages.Delete', + }, + { + text: 'CmsKit::SetAsHomePage', + action: data => { + const pageService = data.getInjected(PageAdminService); + const list = data.getInjected(ListService); + const toasterService = data.getInjected(ToasterService); + + pageService.setAsHomePage(data.record.id!).subscribe(() => { + list.get(); + if (data.record.isHomePage) { + toasterService.warn('CmsKit::RemovedSettingAsHomePage'); + } else { + toasterService.success('CmsKit::CompletedSettingAsHomePage'); + } + }); + }, + permission: 'CmsKit.Pages.SetAsHomePage', + }, +]); diff --git a/npm/ng-packs/packages/cms-kit/admin/src/defaults/pages/default-page-entity-props.ts b/npm/ng-packs/packages/cms-kit/admin/src/defaults/pages/default-page-entity-props.ts new file mode 100644 index 0000000000..9e875bc175 --- /dev/null +++ b/npm/ng-packs/packages/cms-kit/admin/src/defaults/pages/default-page-entity-props.ts @@ -0,0 +1,62 @@ +import { of } from 'rxjs'; +import { PageDto, PageStatus } from '@abp/ng.cms-kit/proxy'; +import { EntityProp, ePropType } from '@abp/ng.components/extensible'; +import { LocalizationService } from '@abp/ng.core'; + +export const DEFAULT_PAGE_ENTITY_PROPS = EntityProp.createMany([ + { + type: ePropType.String, + name: 'title', + displayName: 'CmsKit::Title', + sortable: true, + columnWidth: 200, + }, + { + type: ePropType.String, + name: 'slug', + displayName: 'CmsKit::Slug', + sortable: true, + columnWidth: 200, + }, + { + type: ePropType.String, + name: 'status', + displayName: 'CmsKit::Status', + sortable: true, + columnWidth: 120, + valueResolver: data => { + const localization = data.getInjected(LocalizationService); + let result = ''; + switch (data.record.status) { + case PageStatus.Draft: + result = localization.instant('CmsKit::Enum:PageStatus:0'); + break; + case PageStatus.Publish: + result = localization.instant('CmsKit::Enum:PageStatus:1'); + break; + } + return of(result); + }, + }, + { + type: ePropType.Boolean, + name: 'isHomePage', + displayName: 'CmsKit::IsHomePage', + sortable: true, + columnWidth: 120, + }, + { + type: ePropType.Date, + name: 'creationTime', + displayName: 'AbpIdentity::CreationTime', + sortable: true, + columnWidth: 200, + }, + { + type: ePropType.Date, + name: 'lastModificationTime', + displayName: 'AbpIdentity::LastModificationTime', + sortable: true, + columnWidth: 200, + }, +]); diff --git a/npm/ng-packs/packages/cms-kit/admin/src/defaults/pages/default-page-toolbar-actions.ts b/npm/ng-packs/packages/cms-kit/admin/src/defaults/pages/default-page-toolbar-actions.ts new file mode 100644 index 0000000000..378c62366f --- /dev/null +++ b/npm/ng-packs/packages/cms-kit/admin/src/defaults/pages/default-page-toolbar-actions.ts @@ -0,0 +1,15 @@ +import { Router } from '@angular/router'; +import { PageDto } from '@abp/ng.cms-kit/proxy'; +import { ToolbarAction } from '@abp/ng.components/extensible'; + +export const DEFAULT_PAGE_TOOLBAR_ACTIONS = ToolbarAction.createMany([ + { + text: 'CmsKit::NewPage', + action: data => { + const router = data.getInjected(Router); + router.navigate(['/cms/pages/create']); + }, + permission: 'CmsKit.Pages.Create', + icon: 'fa fa-plus', + }, +]); diff --git a/npm/ng-packs/packages/cms-kit/admin/src/defaults/pages/index.ts b/npm/ng-packs/packages/cms-kit/admin/src/defaults/pages/index.ts new file mode 100644 index 0000000000..255ba7e337 --- /dev/null +++ b/npm/ng-packs/packages/cms-kit/admin/src/defaults/pages/index.ts @@ -0,0 +1,5 @@ +export * from './default-page-entity-actions'; +export * from './default-page-entity-props'; +export * from './default-page-toolbar-actions'; +export * from './default-page-create-form-props'; +export * from './layout-constants'; diff --git a/npm/ng-packs/packages/cms-kit/admin/src/defaults/pages/layout-constants.ts b/npm/ng-packs/packages/cms-kit/admin/src/defaults/pages/layout-constants.ts new file mode 100644 index 0000000000..da7573afa9 --- /dev/null +++ b/npm/ng-packs/packages/cms-kit/admin/src/defaults/pages/layout-constants.ts @@ -0,0 +1,8 @@ +import { eLayoutType } from '@abp/ng.core'; + +export const LAYOUT_CONSTANTS = { + Account: eLayoutType.account, + Public: 'public', + Empty: eLayoutType.empty, + Application: eLayoutType.application, +} as const; diff --git a/npm/ng-packs/packages/cms-kit/admin/src/models/config-options.ts b/npm/ng-packs/packages/cms-kit/admin/src/models/config-options.ts index 3ce0bbeab8..c8f427479a 100644 --- a/npm/ng-packs/packages/cms-kit/admin/src/models/config-options.ts +++ b/npm/ng-packs/packages/cms-kit/admin/src/models/config-options.ts @@ -3,14 +3,17 @@ import { EntityActionContributorCallback, EntityPropContributorCallback, ToolbarActionContributorCallback, + CreateFormPropContributorCallback, + EditFormPropContributorCallback, } from '@abp/ng.components/extensible'; -import { CommentWithAuthorDto, TagDto } from '@abp/ng.cms-kit/proxy'; +import { CommentWithAuthorDto, TagDto, PageDto } from '@abp/ng.cms-kit/proxy'; export type CmsKitAdminEntityActionContributors = Partial<{ [eCmsKitAdminComponents.CommentList]: EntityActionContributorCallback[]; [eCmsKitAdminComponents.CommentApprove]: EntityActionContributorCallback[]; [eCmsKitAdminComponents.CommentDetails]: EntityActionContributorCallback[]; [eCmsKitAdminComponents.TagList]: EntityActionContributorCallback[]; + [eCmsKitAdminComponents.PageList]: EntityActionContributorCallback[]; }>; export type CmsKitAdminEntityPropContributors = Partial<{ @@ -18,15 +21,25 @@ export type CmsKitAdminEntityPropContributors = Partial<{ [eCmsKitAdminComponents.CommentApprove]: EntityPropContributorCallback[]; [eCmsKitAdminComponents.CommentDetails]: EntityPropContributorCallback[]; [eCmsKitAdminComponents.TagList]: EntityPropContributorCallback[]; + [eCmsKitAdminComponents.PageList]: EntityPropContributorCallback[]; }>; export type CmsKitAdminToolbarActionContributors = Partial<{ [eCmsKitAdminComponents.TagList]: ToolbarActionContributorCallback[]; + [eCmsKitAdminComponents.PageList]: ToolbarActionContributorCallback[]; }>; -export type CmsKitAdminCreateFormPropContributors = Partial<{}>; +export type CmsKitAdminCreateFormPropContributors = Partial<{ + [eCmsKitAdminComponents.TagList]: CreateFormPropContributorCallback[]; + [eCmsKitAdminComponents.PageList]: CreateFormPropContributorCallback[]; + [eCmsKitAdminComponents.PageCreate]: CreateFormPropContributorCallback[]; +}>; -export type CmsKitAdminEditFormPropContributors = Partial<{}>; +export type CmsKitAdminEditFormPropContributors = Partial<{ + [eCmsKitAdminComponents.TagList]: EditFormPropContributorCallback[]; + [eCmsKitAdminComponents.PageList]: EditFormPropContributorCallback[]; + [eCmsKitAdminComponents.PageEdit]: EditFormPropContributorCallback[]; +}>; export interface CmsKitAdminConfigOptions { entityActionContributors?: CmsKitAdminEntityActionContributors; diff --git a/npm/ng-packs/packages/cms-kit/admin/src/resolvers/extensions.resolver.ts b/npm/ng-packs/packages/cms-kit/admin/src/resolvers/extensions.resolver.ts index bc0056b85e..f5c91308bb 100644 --- a/npm/ng-packs/packages/cms-kit/admin/src/resolvers/extensions.resolver.ts +++ b/npm/ng-packs/packages/cms-kit/admin/src/resolvers/extensions.resolver.ts @@ -40,6 +40,9 @@ export const cmsKitAdminExtensionsResolver: ResolveFn = () => { [eCmsKitAdminComponents.CommentApprove]: entities.Comment, [eCmsKitAdminComponents.CommentDetails]: entities.Comment, [eCmsKitAdminComponents.TagList]: entities.Tag, + [eCmsKitAdminComponents.PageList]: entities.Page, + [eCmsKitAdminComponents.PageCreate]: entities.Page, + [eCmsKitAdminComponents.PageEdit]: entities.Page, })), mapEntitiesToContributors(injector, 'CmsKit'), tap(objectExtensionContributors => { diff --git a/npm/ng-packs/packages/cms-kit/admin/src/services/index.ts b/npm/ng-packs/packages/cms-kit/admin/src/services/index.ts index a607f1e450..1eecaecbc9 100644 --- a/npm/ng-packs/packages/cms-kit/admin/src/services/index.ts +++ b/npm/ng-packs/packages/cms-kit/admin/src/services/index.ts @@ -1,7 +1,7 @@ // Services will be exported here // export * from './comments'; // export * from './tags'; -// export * from './pages'; +export * from './page-form.service'; // export * from './blogs'; // export * from './blog-posts'; // export * from './menus'; diff --git a/npm/ng-packs/packages/cms-kit/admin/src/services/page-form.service.ts b/npm/ng-packs/packages/cms-kit/admin/src/services/page-form.service.ts new file mode 100644 index 0000000000..68b4aaef7c --- /dev/null +++ b/npm/ng-packs/packages/cms-kit/admin/src/services/page-form.service.ts @@ -0,0 +1,119 @@ +import { Injectable, inject } from '@angular/core'; +import { Router } from '@angular/router'; +import { FormGroup } from '@angular/forms'; +import { Observable } from 'rxjs'; +import { tap } from 'rxjs/operators'; +import { ToasterService } from '@abp/ng.theme.shared'; +import { + PageAdminService, + CreatePageInputDto, + UpdatePageInputDto, + PageDto, + PageStatus, +} from '@abp/ng.cms-kit/proxy'; + +@Injectable({ + providedIn: 'root', +}) +export class PageFormService { + private pageService = inject(PageAdminService); + private toasterService = inject(ToasterService); + private router = inject(Router); + + create(form: FormGroup): Observable { + if (!form.valid) { + throw new Error('Form is invalid'); + } + + return this.pageService.create(form.value as CreatePageInputDto).pipe( + tap(() => { + this.toasterService.success('AbpUi::SavedSuccessfully'); + this.router.navigate(['/cms/pages']); + }), + ); + } + + createAsDraft(form: FormGroup): Observable { + if (!form.valid) { + throw new Error('Form is invalid'); + } + + const formValue = { ...form.value, status: PageStatus.Draft } as CreatePageInputDto; + return this.pageService.create(formValue).pipe( + tap(() => { + this.toasterService.success('AbpUi::SavedSuccessfully'); + this.router.navigate(['/cms/pages']); + }), + ); + } + + publish(form: FormGroup): Observable { + if (!form.valid) { + throw new Error('Form is invalid'); + } + + const formValue = { ...form.value, status: PageStatus.Publish } as CreatePageInputDto; + return this.pageService.create(formValue).pipe( + tap(() => { + this.toasterService.success('AbpUi::SavedSuccessfully'); + this.router.navigate(['/cms/pages']); + }), + ); + } + + update(pageId: string, form: FormGroup, page: PageDto): Observable { + if (!form.valid || !page) { + throw new Error('Form is invalid or page is missing'); + } + + const formValue = { + ...page, + ...form.value, + } as UpdatePageInputDto; + + return this.pageService.update(pageId, formValue).pipe( + tap(() => { + this.toasterService.success('AbpUi::SavedSuccessfully'); + this.router.navigate(['/cms/pages']); + }), + ); + } + + updateAsDraft(pageId: string, form: FormGroup, page: PageDto): Observable { + if (!form.valid || !page) { + throw new Error('Form is invalid or page is missing'); + } + + const formValue = { + ...page, + ...form.value, + status: PageStatus.Draft, + } as UpdatePageInputDto; + + return this.pageService.update(pageId, formValue).pipe( + tap(() => { + this.toasterService.success('AbpUi::SavedSuccessfully'); + this.router.navigate(['/cms/pages']); + }), + ); + } + + updateAndPublish(pageId: string, form: FormGroup, page: PageDto): Observable { + if (!form.valid || !page) { + throw new Error('Form is invalid or page is missing'); + } + + const formValue = { + ...page, + ...form.value, + status: PageStatus.Publish, + } as UpdatePageInputDto; + + return this.pageService.update(pageId, formValue).pipe( + tap(() => { + this.toasterService.success('AbpUi::SavedSuccessfully'); + this.router.navigate(['/cms/pages']); + }), + ); + } +} diff --git a/npm/ng-packs/packages/cms-kit/admin/src/tokens/extensions.token.ts b/npm/ng-packs/packages/cms-kit/admin/src/tokens/extensions.token.ts index afd5db1b08..b63432544d 100644 --- a/npm/ng-packs/packages/cms-kit/admin/src/tokens/extensions.token.ts +++ b/npm/ng-packs/packages/cms-kit/admin/src/tokens/extensions.token.ts @@ -1,4 +1,4 @@ -import { CommentWithAuthorDto, TagDto } from '@abp/ng.cms-kit/proxy'; +import { CommentWithAuthorDto, TagDto, PageDto } from '@abp/ng.cms-kit/proxy'; import { EntityActionContributorCallback, EntityPropContributorCallback, @@ -16,6 +16,13 @@ import { DEFAULT_TAG_CREATE_FORM_PROPS, DEFAULT_TAG_EDIT_FORM_PROPS, } from '../defaults/tags'; +import { + DEFAULT_PAGE_ENTITY_ACTIONS, + DEFAULT_PAGE_ENTITY_PROPS, + DEFAULT_PAGE_TOOLBAR_ACTIONS, + DEFAULT_PAGE_CREATE_FORM_PROPS, + DEFAULT_PAGE_EDIT_FORM_PROPS, +} from '../defaults/pages'; import { eCmsKitAdminComponents } from '../enums'; export const DEFAULT_CMS_KIT_ADMIN_ENTITY_ACTIONS = { @@ -23,6 +30,7 @@ export const DEFAULT_CMS_KIT_ADMIN_ENTITY_ACTIONS = { [eCmsKitAdminComponents.CommentApprove]: DEFAULT_COMMENT_ENTITY_ACTIONS, [eCmsKitAdminComponents.CommentDetails]: DEFAULT_COMMENT_ENTITY_ACTIONS, [eCmsKitAdminComponents.TagList]: DEFAULT_TAG_ENTITY_ACTIONS, + [eCmsKitAdminComponents.PageList]: DEFAULT_PAGE_ENTITY_ACTIONS, }; export const DEFAULT_CMS_KIT_ADMIN_ENTITY_PROPS = { @@ -30,18 +38,24 @@ export const DEFAULT_CMS_KIT_ADMIN_ENTITY_PROPS = { [eCmsKitAdminComponents.CommentApprove]: DEFAULT_COMMENT_ENTITY_PROPS, [eCmsKitAdminComponents.CommentDetails]: DEFAULT_COMMENT_ENTITY_PROPS, [eCmsKitAdminComponents.TagList]: DEFAULT_TAG_ENTITY_PROPS, + [eCmsKitAdminComponents.PageList]: DEFAULT_PAGE_ENTITY_PROPS, }; export const DEFAULT_CMS_KIT_ADMIN_TOOLBAR_ACTIONS = { [eCmsKitAdminComponents.TagList]: DEFAULT_TAG_TOOLBAR_ACTIONS, + [eCmsKitAdminComponents.PageList]: DEFAULT_PAGE_TOOLBAR_ACTIONS, }; export const DEFAULT_CMS_KIT_ADMIN_CREATE_FORM_PROPS = { [eCmsKitAdminComponents.TagList]: DEFAULT_TAG_CREATE_FORM_PROPS, + [eCmsKitAdminComponents.PageList]: DEFAULT_PAGE_CREATE_FORM_PROPS, + [eCmsKitAdminComponents.PageCreate]: DEFAULT_PAGE_CREATE_FORM_PROPS, }; export const DEFAULT_CMS_KIT_ADMIN_EDIT_FORM_PROPS = { [eCmsKitAdminComponents.TagList]: DEFAULT_TAG_EDIT_FORM_PROPS, + [eCmsKitAdminComponents.PageList]: DEFAULT_PAGE_EDIT_FORM_PROPS, + [eCmsKitAdminComponents.PageEdit]: DEFAULT_PAGE_EDIT_FORM_PROPS, }; export const CMS_KIT_ADMIN_ENTITY_ACTION_CONTRIBUTORS = @@ -66,6 +80,7 @@ type EntityActionContributors = Partial<{ [eCmsKitAdminComponents.CommentApprove]: EntityActionContributorCallback[]; [eCmsKitAdminComponents.CommentDetails]: EntityActionContributorCallback[]; [eCmsKitAdminComponents.TagList]: EntityActionContributorCallback[]; + [eCmsKitAdminComponents.PageList]: EntityActionContributorCallback[]; }>; type EntityPropContributors = Partial<{ @@ -73,16 +88,20 @@ type EntityPropContributors = Partial<{ [eCmsKitAdminComponents.CommentApprove]: EntityPropContributorCallback[]; [eCmsKitAdminComponents.CommentDetails]: EntityPropContributorCallback[]; [eCmsKitAdminComponents.TagList]: EntityPropContributorCallback[]; + [eCmsKitAdminComponents.PageList]: EntityPropContributorCallback[]; }>; type ToolbarActionContributors = Partial<{ [eCmsKitAdminComponents.TagList]: ToolbarActionContributorCallback[]; + [eCmsKitAdminComponents.PageList]: ToolbarActionContributorCallback[]; }>; type CreateFormPropContributors = Partial<{ [eCmsKitAdminComponents.TagList]: CreateFormPropContributorCallback[]; + [eCmsKitAdminComponents.PageList]: CreateFormPropContributorCallback[]; }>; type EditFormPropContributors = Partial<{ [eCmsKitAdminComponents.TagList]: EditFormPropContributorCallback[]; + [eCmsKitAdminComponents.PageList]: EditFormPropContributorCallback[]; }>;