mirror of https://github.com/abpframework/abp.git
23 changed files with 1051 additions and 31 deletions
@ -0,0 +1,72 @@ |
|||
<abp-page [title]="'CmsKit::Comments' | abpLocalization"> |
|||
<div class="card mb-4"> |
|||
<div class="card-body"> |
|||
<form [formGroup]="filterForm" (ngSubmit)="onFilter()"> |
|||
<div class="row align-items-end"> |
|||
<div class="col-lg-4 col-md-12"> |
|||
<div class="row"> |
|||
<div class="col-lg-6 col-md-6"> |
|||
<div class="mb-3"> |
|||
<label class="form-label" for="creationStartDate"> |
|||
{{ 'CmsKit::StartDate' | abpLocalization }} |
|||
</label> |
|||
<input |
|||
id="creationStartDate" |
|||
formControlName="creationStartDate" |
|||
class="form-control" |
|||
ngbDatepicker |
|||
#startDatePicker="ngbDatepicker" |
|||
(click)="startDatePicker.toggle()" |
|||
readonly |
|||
/> |
|||
</div> |
|||
</div> |
|||
<div class="col-lg-6 col-md-6"> |
|||
<div class="mb-3"> |
|||
<label class="form-label" for="creationEndDate"> |
|||
{{ 'CmsKit::EndDate' | abpLocalization }} |
|||
</label> |
|||
<input |
|||
id="creationEndDate" |
|||
formControlName="creationEndDate" |
|||
class="form-control" |
|||
ngbDatepicker |
|||
#endDatePicker="ngbDatepicker" |
|||
(click)="endDatePicker.toggle()" |
|||
readonly |
|||
/> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="col-lg-3 col-md-6"> |
|||
<abp-form-input |
|||
formControlName="author" |
|||
[label]="'CmsKit::Username' | abpLocalization" |
|||
type="text" |
|||
/> |
|||
</div> |
|||
|
|||
<div class="col-lg-3 col-md-6"> |
|||
<abp-form-input |
|||
formControlName="entityType" |
|||
[label]="'CmsKit::EntityType' | abpLocalization" |
|||
type="text" |
|||
/> |
|||
</div> |
|||
|
|||
<div class="col-lg-2 col-md-6"> |
|||
<abp-button class="w-100 mb-3" buttonType="Primary" type="submit"> |
|||
<i class="fa fa-search" aria-hidden="true"></i> |
|||
</abp-button> |
|||
</div> |
|||
</div> |
|||
</form> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="card"> |
|||
<abp-extensible-table [data]="data.items" [recordsTotal]="data.totalCount" [list]="list" /> |
|||
</div> |
|||
</abp-page> |
|||
@ -0,0 +1,122 @@ |
|||
import { Component, OnInit, inject, LOCALE_ID } from '@angular/core'; |
|||
import { CommonModule, formatDate } from '@angular/common'; |
|||
import { FormBuilder, FormGroup, ReactiveFormsModule } from '@angular/forms'; |
|||
import { NgbDatepickerModule } from '@ng-bootstrap/ng-bootstrap'; |
|||
import { ListService, LocalizationPipe, PagedResultDto } from '@abp/ng.core'; |
|||
import { ExtensibleTableComponent, EXTENSIONS_IDENTIFIER } from '@abp/ng.components/extensible'; |
|||
import { PageComponent } from '@abp/ng.components/page'; |
|||
import { ButtonComponent, FormInputComponent } from '@abp/ng.theme.shared'; |
|||
import { |
|||
CommentAdminService, |
|||
CommentGetListInput, |
|||
CommentWithAuthorDto, |
|||
CommentApproveState, |
|||
} from '@abp/ng.cms-kit/proxy'; |
|||
import { eCmsKitAdminComponents } from '../../../enums'; |
|||
|
|||
@Component({ |
|||
selector: 'abp-comment-approve', |
|||
templateUrl: './comment-approve.component.html', |
|||
providers: [ |
|||
ListService, |
|||
{ |
|||
provide: EXTENSIONS_IDENTIFIER, |
|||
useValue: eCmsKitAdminComponents.CommentApprove, |
|||
}, |
|||
], |
|||
imports: [ |
|||
ReactiveFormsModule, |
|||
NgbDatepickerModule, |
|||
CommonModule, |
|||
PageComponent, |
|||
ButtonComponent, |
|||
FormInputComponent, |
|||
LocalizationPipe, |
|||
ExtensibleTableComponent, |
|||
], |
|||
}) |
|||
export class CommentApproveComponent implements OnInit { |
|||
data: PagedResultDto<CommentWithAuthorDto> = { items: [], totalCount: 0 }; |
|||
|
|||
public readonly list = inject(ListService<CommentGetListInput>); |
|||
private commentService = inject(CommentAdminService); |
|||
private fb = inject(FormBuilder); |
|||
private locale = inject(LOCALE_ID); |
|||
|
|||
filterForm!: FormGroup; |
|||
|
|||
ngOnInit() { |
|||
this.createFilterForm(); |
|||
this.hookToQuery(); |
|||
} |
|||
|
|||
private createFilterForm() { |
|||
this.filterForm = this.fb.group({ |
|||
creationStartDate: [null], |
|||
creationEndDate: [null], |
|||
author: [''], |
|||
entityType: [''], |
|||
}); |
|||
} |
|||
|
|||
onFilter() { |
|||
const formValue = this.filterForm.value; |
|||
const filters: Partial<CommentGetListInput> = { |
|||
author: formValue.author || undefined, |
|||
entityType: formValue.entityType || undefined, |
|||
commentApproveState: CommentApproveState.Waiting, |
|||
}; |
|||
|
|||
if (formValue.creationStartDate) { |
|||
filters.creationStartDate = this.formatDateForApi(formValue.creationStartDate); |
|||
} |
|||
|
|||
if (formValue.creationEndDate) { |
|||
filters.creationEndDate = this.formatDateForApi(formValue.creationEndDate); |
|||
} |
|||
|
|||
this.list.filter = JSON.stringify(filters); |
|||
this.list.get(); |
|||
} |
|||
|
|||
private formatDateForApi(date: any): string { |
|||
if (!date) { |
|||
return ''; |
|||
} |
|||
|
|||
if (typeof date === 'string') { |
|||
return date; |
|||
} |
|||
|
|||
if (date.year && date.month && date.day) { |
|||
const jsDate = new Date(date.year, date.month - 1, date.day); |
|||
return formatDate(jsDate, 'yyyy-MM-dd', this.locale); |
|||
} |
|||
|
|||
return ''; |
|||
} |
|||
|
|||
private hookToQuery() { |
|||
this.list |
|||
.hookToQuery(query => { |
|||
let filters: Partial<CommentGetListInput> = { |
|||
commentApproveState: CommentApproveState.Waiting, |
|||
}; |
|||
if (this.list.filter) { |
|||
try { |
|||
filters = { ...filters, ...JSON.parse(this.list.filter) }; |
|||
} catch { |
|||
// Ignore parse errors, use default filters
|
|||
} |
|||
} |
|||
const input: CommentGetListInput = { |
|||
...query, |
|||
...filters, |
|||
}; |
|||
return this.commentService.getList(input); |
|||
}) |
|||
.subscribe(res => { |
|||
this.data = res; |
|||
}); |
|||
} |
|||
} |
|||
@ -0,0 +1 @@ |
|||
export * from './comment-approve.component'; |
|||
@ -0,0 +1,147 @@ |
|||
<abp-page [title]="'CmsKit::Comments' | abpLocalization"> |
|||
@if (comment) { |
|||
<div class="card mb-4"> |
|||
<div class="card-body"> |
|||
<table class="table"> |
|||
<tr> |
|||
<td width="10%"> |
|||
<b>{{ 'CmsKit::EntityType' | abpLocalization }}</b |
|||
>: |
|||
</td> |
|||
<td>{{ comment.entityType }}</td> |
|||
</tr> |
|||
<tr> |
|||
<td> |
|||
<b>{{ 'CmsKit::EntityId' | abpLocalization }}</b |
|||
>: |
|||
</td> |
|||
<td>{{ comment.entityId }}</td> |
|||
</tr> |
|||
<tr> |
|||
<td> |
|||
<b>{{ 'AbpIdentity::CreationTime' | abpLocalization }}</b |
|||
>: |
|||
</td> |
|||
<td>{{ comment.creationTime | date }}</td> |
|||
</tr> |
|||
<tr> |
|||
<td> |
|||
<b>{{ 'CmsKit::Username' | abpLocalization }}</b |
|||
>: |
|||
</td> |
|||
<td>{{ comment.author?.name }}</td> |
|||
</tr> |
|||
@if (comment.repliedCommentId) { |
|||
<tr> |
|||
<td> |
|||
<b>{{ 'CmsKit::ReplyTo' | abpLocalization }}</b |
|||
>: |
|||
</td> |
|||
<td> |
|||
<a (click)="navigateToReply(comment.repliedCommentId!)" style="cursor: pointer"> |
|||
{{ comment.repliedCommentId }} |
|||
</a> |
|||
</td> |
|||
</tr> |
|||
} |
|||
<tr> |
|||
<td class="align-text-top"> |
|||
<b>{{ 'CmsKit::Text' | abpLocalization }}</b |
|||
>: |
|||
</td> |
|||
<td>{{ comment.text }}</td> |
|||
</tr> |
|||
</table> |
|||
</div> |
|||
</div> |
|||
} |
|||
|
|||
<div class="card mb-4"> |
|||
<div class="card-body"> |
|||
<form [formGroup]="filterForm" (ngSubmit)="onFilter()"> |
|||
<input type="hidden" [value]="commentId" /> |
|||
<div class="row"> |
|||
<div class="col-lg-4 col-md-12"> |
|||
<div class="row"> |
|||
<div class="col-lg-6 col-md-6"> |
|||
<div class="mb-3"> |
|||
<label class="form-label" for="creationStartDate"> |
|||
{{ 'CmsKit::StartDate' | abpLocalization }} |
|||
</label> |
|||
<input |
|||
id="creationStartDate" |
|||
formControlName="creationStartDate" |
|||
class="form-control" |
|||
ngbDatepicker |
|||
#startDatePicker="ngbDatepicker" |
|||
(click)="startDatePicker.toggle()" |
|||
readonly |
|||
/> |
|||
</div> |
|||
</div> |
|||
<div class="col-lg-6 col-md-6"> |
|||
<div class="mb-3"> |
|||
<label class="form-label" for="creationEndDate"> |
|||
{{ 'CmsKit::EndDate' | abpLocalization }} |
|||
</label> |
|||
<input |
|||
id="creationEndDate" |
|||
formControlName="creationEndDate" |
|||
class="form-control" |
|||
ngbDatepicker |
|||
#endDatePicker="ngbDatepicker" |
|||
(click)="endDatePicker.toggle()" |
|||
readonly |
|||
/> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="col-lg-4 col-md-12"> |
|||
<abp-form-input |
|||
formControlName="author" |
|||
[label]="'CmsKit::Username' | abpLocalization" |
|||
type="text" |
|||
/> |
|||
</div> |
|||
|
|||
@if (requireApprovement) { |
|||
<div class="col-lg-2 col-md-12"> |
|||
<div class="mb-3"> |
|||
<label class="mb-1 form-label" for="commentApproveState"> |
|||
{{ 'CmsKit::CommentFilter:ApproveState' | abpLocalization }} |
|||
</label> |
|||
<select |
|||
id="commentApproveState" |
|||
formControlName="commentApproveState" |
|||
class="form-control" |
|||
> |
|||
@for (option of commentApproveStateOptions; track option.value) { |
|||
<option [value]="option.value"> |
|||
{{ 'CmsKit::CommentFilter:' + option.value | abpLocalization }} |
|||
</option> |
|||
} |
|||
</select> |
|||
</div> |
|||
</div> |
|||
} |
|||
|
|||
<div class="col-lg-2 col-md-12"> |
|||
<div class="d-grid gap-2"> |
|||
<abp-button class="mt-md-4" buttonType="Primary" type="submit"> |
|||
<i class="fa fa-search" aria-hidden="true"></i> |
|||
</abp-button> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</form> |
|||
</div> |
|||
</div> |
|||
|
|||
<h3>{{ 'CmsKit::RepliesToThisComment' | abpLocalization }}</h3> |
|||
|
|||
<div class="card"> |
|||
<abp-extensible-table [data]="data.items" [recordsTotal]="data.totalCount" [list]="list" /> |
|||
</div> |
|||
</abp-page> |
|||
@ -0,0 +1,152 @@ |
|||
import { Component, OnInit, inject, LOCALE_ID } from '@angular/core'; |
|||
import { CommonModule, DatePipe, formatDate } from '@angular/common'; |
|||
import { FormBuilder, FormGroup, ReactiveFormsModule } from '@angular/forms'; |
|||
import { ActivatedRoute, Router } from '@angular/router'; |
|||
import { NgbDatepickerModule } from '@ng-bootstrap/ng-bootstrap'; |
|||
import { ListService, LocalizationPipe, PagedResultDto, ConfigStateService } from '@abp/ng.core'; |
|||
import { PageComponent } from '@abp/ng.components/page'; |
|||
import { ExtensibleTableComponent, EXTENSIONS_IDENTIFIER } from '@abp/ng.components/extensible'; |
|||
import { ButtonComponent, FormInputComponent } from '@abp/ng.theme.shared'; |
|||
import { |
|||
CommentAdminService, |
|||
CommentGetListInput, |
|||
CommentWithAuthorDto, |
|||
CommentApproveState, |
|||
commentApproveStateOptions, |
|||
} from '@abp/ng.cms-kit/proxy'; |
|||
import { eCmsKitAdminComponents } from '../../../enums'; |
|||
import { CMS_KIT_COMMENTS_REQUIRE_APPROVEMENT } from '../comment-list'; |
|||
|
|||
@Component({ |
|||
selector: 'abp-comment-details', |
|||
templateUrl: './comment-details.component.html', |
|||
providers: [ |
|||
ListService, |
|||
{ |
|||
provide: EXTENSIONS_IDENTIFIER, |
|||
useValue: eCmsKitAdminComponents.CommentDetails, |
|||
}, |
|||
], |
|||
imports: [ |
|||
ExtensibleTableComponent, |
|||
PageComponent, |
|||
LocalizationPipe, |
|||
ReactiveFormsModule, |
|||
NgbDatepickerModule, |
|||
CommonModule, |
|||
DatePipe, |
|||
FormInputComponent, |
|||
ButtonComponent, |
|||
], |
|||
}) |
|||
export class CommentDetailsComponent implements OnInit { |
|||
comment: CommentWithAuthorDto | null = null; |
|||
data: PagedResultDto<CommentWithAuthorDto> = { items: [], totalCount: 0 }; |
|||
|
|||
public readonly list = inject(ListService<CommentGetListInput>); |
|||
private commentService = inject(CommentAdminService); |
|||
private route = inject(ActivatedRoute); |
|||
private router = inject(Router); |
|||
private fb = inject(FormBuilder); |
|||
private configState = inject(ConfigStateService); |
|||
private locale = inject(LOCALE_ID); |
|||
|
|||
filterForm!: FormGroup; |
|||
commentApproveStateOptions = commentApproveStateOptions; |
|||
requireApprovement = false; |
|||
commentId!: string; |
|||
|
|||
ngOnInit() { |
|||
this.requireApprovement = |
|||
this.configState.getSetting(CMS_KIT_COMMENTS_REQUIRE_APPROVEMENT) === 'true'; |
|||
this.route.params.subscribe(params => { |
|||
const id = params['id']; |
|||
if (id) { |
|||
this.commentId = id; |
|||
this.loadComment(id); |
|||
this.createFilterForm(); |
|||
this.hookToQuery(); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
private createFilterForm() { |
|||
this.filterForm = this.fb.group({ |
|||
creationStartDate: [null], |
|||
creationEndDate: [null], |
|||
author: [''], |
|||
commentApproveState: [CommentApproveState.All], |
|||
}); |
|||
} |
|||
|
|||
private loadComment(id: string) { |
|||
this.commentService.get(id).subscribe(comment => { |
|||
this.comment = comment; |
|||
}); |
|||
} |
|||
|
|||
onFilter() { |
|||
const formValue = this.filterForm.value; |
|||
const filters: Partial<CommentGetListInput> = { |
|||
author: formValue.author || undefined, |
|||
commentApproveState: formValue.commentApproveState, |
|||
repliedCommentId: this.commentId, |
|||
}; |
|||
|
|||
if (formValue.creationStartDate) { |
|||
filters.creationStartDate = this.formatDateForApi(formValue.creationStartDate); |
|||
} |
|||
|
|||
if (formValue.creationEndDate) { |
|||
filters.creationEndDate = this.formatDateForApi(formValue.creationEndDate); |
|||
} |
|||
|
|||
this.list.filter = JSON.stringify(filters); |
|||
this.list.get(); |
|||
} |
|||
|
|||
private formatDateForApi(date: any): string { |
|||
if (!date) { |
|||
return ''; |
|||
} |
|||
|
|||
if (typeof date === 'string') { |
|||
return date; |
|||
} |
|||
|
|||
if (date.year && date.month && date.day) { |
|||
const jsDate = new Date(date.year, date.month - 1, date.day); |
|||
return formatDate(jsDate, 'yyyy-MM-dd', this.locale); |
|||
} |
|||
|
|||
return ''; |
|||
} |
|||
|
|||
private hookToQuery() { |
|||
this.list |
|||
.hookToQuery(query => { |
|||
let filters: Partial<CommentGetListInput> = { |
|||
repliedCommentId: this.commentId, |
|||
}; |
|||
if (this.list.filter) { |
|||
try { |
|||
filters = { ...filters, ...JSON.parse(this.list.filter) }; |
|||
} catch { |
|||
// Ignore parse errors, use default filters
|
|||
} |
|||
} |
|||
const input: CommentGetListInput = { |
|||
...query, |
|||
...filters, |
|||
}; |
|||
return this.commentService.getList(input); |
|||
}) |
|||
.subscribe(res => { |
|||
this.data = res; |
|||
}); |
|||
} |
|||
|
|||
navigateToReply(id: string) { |
|||
this.router.navigate(['/cms/comments', id]); |
|||
} |
|||
} |
|||
@ -0,0 +1 @@ |
|||
export * from './comment-details.component'; |
|||
@ -0,0 +1,91 @@ |
|||
<abp-page [title]="'CmsKit::Comments' | abpLocalization"> |
|||
<div class="card mb-4"> |
|||
<div class="card-body"> |
|||
<form [formGroup]="filterForm" (ngSubmit)="onFilter()"> |
|||
<div class="row align-items-end"> |
|||
<div class="col-lg-4 col-md-12"> |
|||
<div class="row"> |
|||
<div class="col-lg-6 col-md-6"> |
|||
<div class="mb-3"> |
|||
<label class="form-label" for="creationStartDate"> |
|||
{{ 'CmsKit::StartDate' | abpLocalization }} |
|||
</label> |
|||
<input |
|||
id="creationStartDate" |
|||
formControlName="creationStartDate" |
|||
class="form-control" |
|||
ngbDatepicker |
|||
#startDatePicker="ngbDatepicker" |
|||
(click)="startDatePicker.toggle()" |
|||
readonly |
|||
/> |
|||
</div> |
|||
</div> |
|||
<div class="col-lg-6 col-md-6"> |
|||
<div class="mb-3"> |
|||
<label class="form-label" for="creationEndDate"> |
|||
{{ 'CmsKit::EndDate' | abpLocalization }} |
|||
</label> |
|||
<input |
|||
id="creationEndDate" |
|||
formControlName="creationEndDate" |
|||
class="form-control" |
|||
ngbDatepicker |
|||
#endDatePicker="ngbDatepicker" |
|||
(click)="endDatePicker.toggle()" |
|||
readonly |
|||
/> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="col-lg-2 col-md-6"> |
|||
<abp-form-input |
|||
formControlName="author" |
|||
[label]="'CmsKit::Username' | abpLocalization" |
|||
type="text" |
|||
/> |
|||
</div> |
|||
|
|||
<div class="col-lg-2 col-md-6"> |
|||
<abp-form-input |
|||
formControlName="entityType" |
|||
[label]="'CmsKit::EntityType' | abpLocalization" |
|||
type="text" |
|||
/> |
|||
</div> |
|||
@if (requireApprovement) { |
|||
<div class="col-lg-2 col-md-6"> |
|||
<div class="mb-3"> |
|||
<label class="mb-1 form-label" for="commentApproveState"> |
|||
{{ 'CmsKit::CommentFilter:ApproveState' | abpLocalization }} |
|||
</label> |
|||
<select |
|||
id="commentApproveState" |
|||
formControlName="commentApproveState" |
|||
class="form-control" |
|||
> |
|||
@for (option of commentApproveStateOptions; track option.value) { |
|||
<option [value]="option.value"> |
|||
{{ 'CmsKit::CommentFilter:' + option.value | abpLocalization }} |
|||
</option> |
|||
} |
|||
</select> |
|||
</div> |
|||
</div> |
|||
} |
|||
<div class="col-lg-2 col-md-6"> |
|||
<abp-button class="w-100 mb-3" buttonType="Primary" type="submit"> |
|||
<i class="fa fa-search" aria-hidden="true"></i> |
|||
</abp-button> |
|||
</div> |
|||
</div> |
|||
</form> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="card"> |
|||
<abp-extensible-table [data]="data.items" [recordsTotal]="data.totalCount" [list]="list" /> |
|||
</div> |
|||
</abp-page> |
|||
@ -0,0 +1,128 @@ |
|||
import { Component, OnInit, inject, LOCALE_ID } from '@angular/core'; |
|||
import { CommonModule, formatDate } from '@angular/common'; |
|||
import { FormBuilder, FormGroup, ReactiveFormsModule } from '@angular/forms'; |
|||
import { NgbDatepickerModule } from '@ng-bootstrap/ng-bootstrap'; |
|||
import { ListService, PagedResultDto, ConfigStateService, LocalizationPipe } from '@abp/ng.core'; |
|||
import { ExtensibleModule, EXTENSIONS_IDENTIFIER } from '@abp/ng.components/extensible'; |
|||
import { PageModule } from '@abp/ng.components/page'; |
|||
import { ButtonComponent, FormInputComponent } from '@abp/ng.theme.shared'; |
|||
import { |
|||
CommentAdminService, |
|||
CommentGetListInput, |
|||
CommentWithAuthorDto, |
|||
CommentApproveState, |
|||
commentApproveStateOptions, |
|||
} from '@abp/ng.cms-kit/proxy'; |
|||
import { eCmsKitAdminComponents } from '../../../enums'; |
|||
|
|||
export const CMS_KIT_COMMENTS_REQUIRE_APPROVEMENT = 'CmsKit.Comments.RequireApprovement'; |
|||
|
|||
@Component({ |
|||
selector: 'abp-comment-list', |
|||
standalone: true, |
|||
templateUrl: './comment-list.component.html', |
|||
providers: [ |
|||
ListService, |
|||
{ |
|||
provide: EXTENSIONS_IDENTIFIER, |
|||
useValue: eCmsKitAdminComponents.CommentList, |
|||
}, |
|||
], |
|||
imports: [ |
|||
ExtensibleModule, |
|||
PageModule, |
|||
ReactiveFormsModule, |
|||
NgbDatepickerModule, |
|||
CommonModule, |
|||
LocalizationPipe, |
|||
FormInputComponent, |
|||
ButtonComponent, |
|||
], |
|||
}) |
|||
export class CommentListComponent implements OnInit { |
|||
data: PagedResultDto<CommentWithAuthorDto> = { items: [], totalCount: 0 }; |
|||
|
|||
public readonly list = inject(ListService<CommentGetListInput>); |
|||
private commentService = inject(CommentAdminService); |
|||
private fb = inject(FormBuilder); |
|||
private configState = inject(ConfigStateService); |
|||
private locale = inject(LOCALE_ID); |
|||
|
|||
filterForm!: FormGroup; |
|||
commentApproveStateOptions = commentApproveStateOptions; |
|||
requireApprovement = false; |
|||
|
|||
ngOnInit() { |
|||
this.requireApprovement = |
|||
this.configState.getSetting(CMS_KIT_COMMENTS_REQUIRE_APPROVEMENT) === 'true'; |
|||
this.createFilterForm(); |
|||
this.hookToQuery(); |
|||
} |
|||
|
|||
private createFilterForm() { |
|||
this.filterForm = this.fb.group({ |
|||
creationStartDate: [null], |
|||
creationEndDate: [null], |
|||
author: [''], |
|||
entityType: [''], |
|||
commentApproveState: [CommentApproveState.All], |
|||
}); |
|||
} |
|||
|
|||
onFilter() { |
|||
const formValue = this.filterForm.value; |
|||
const filters: Partial<CommentGetListInput> = { |
|||
author: formValue.author || undefined, |
|||
entityType: formValue.entityType || undefined, |
|||
commentApproveState: formValue.commentApproveState, |
|||
}; |
|||
|
|||
if (formValue.creationStartDate) { |
|||
filters.creationStartDate = this.formatDateForApi(formValue.creationStartDate); |
|||
} |
|||
|
|||
if (formValue.creationEndDate) { |
|||
filters.creationEndDate = this.formatDateForApi(formValue.creationEndDate); |
|||
} |
|||
|
|||
this.list.filter = JSON.stringify(filters); |
|||
this.list.get(); |
|||
} |
|||
|
|||
private formatDateForApi(date: any): string { |
|||
if (!date) { |
|||
return ''; |
|||
} |
|||
|
|||
if (typeof date === 'string') { |
|||
return date; |
|||
} |
|||
|
|||
if (date.year && date.month && date.day) { |
|||
const jsDate = new Date(date.year, date.month - 1, date.day); |
|||
return formatDate(jsDate, 'yyyy-MM-dd', this.locale); |
|||
} |
|||
|
|||
return ''; |
|||
} |
|||
|
|||
private hookToQuery() { |
|||
this.list |
|||
.hookToQuery(query => { |
|||
let filters: Partial<CommentGetListInput> = {}; |
|||
if (this.list.filter) { |
|||
try { |
|||
filters = JSON.parse(this.list.filter); |
|||
} catch { |
|||
// Ignore parse errors, use empty filters
|
|||
} |
|||
} |
|||
const input: CommentGetListInput = { |
|||
...query, |
|||
...filters, |
|||
}; |
|||
return this.commentService.getList(input); |
|||
}) |
|||
.subscribe(res => (this.data = res)); |
|||
} |
|||
} |
|||
@ -0,0 +1 @@ |
|||
export * from './comment-list.component'; |
|||
@ -0,0 +1,3 @@ |
|||
export * from './comment-list'; |
|||
export * from './comment-approve'; |
|||
export * from './comment-details'; |
|||
@ -0,0 +1,62 @@ |
|||
import { CommentWithAuthorDto } from '@abp/ng.cms-kit/proxy'; |
|||
import { EntityAction } from '@abp/ng.components/extensible'; |
|||
import { Router } from '@angular/router'; |
|||
import { CommentAdminService } from '@abp/ng.cms-kit/proxy'; |
|||
import { ConfirmationService, Confirmation } from '@abp/ng.theme.shared'; |
|||
import { ConfigStateService, ListService } from '@abp/ng.core'; |
|||
|
|||
export const DEFAULT_COMMENT_ENTITY_ACTIONS = EntityAction.createMany<CommentWithAuthorDto>([ |
|||
{ |
|||
text: 'CmsKit::Details', |
|||
action: data => { |
|||
const router = data.getInjected(Router); |
|||
router.navigate(['/cms/comments', data.record.id]); |
|||
}, |
|||
}, |
|||
{ |
|||
text: 'CmsKit::Delete', |
|||
action: data => { |
|||
const commentService = data.getInjected(CommentAdminService); |
|||
const confirmation = data.getInjected(ConfirmationService); |
|||
const list = data.getInjected(ListService); |
|||
|
|||
confirmation |
|||
.warn('CmsKit::CommentDeletionConfirmationMessage', 'AbpUi::AreYouSure', { |
|||
yesText: 'AbpUi::Yes', |
|||
cancelText: 'AbpUi::Cancel', |
|||
}) |
|||
.subscribe(status => { |
|||
if (status === Confirmation.Status.confirm) { |
|||
commentService.delete(data.record.id!).subscribe(() => { |
|||
list.get(); |
|||
}); |
|||
} |
|||
}); |
|||
}, |
|||
permission: 'CmsKit.Comments.Delete', |
|||
}, |
|||
{ |
|||
// text: data => {
|
|||
// return data.record.isApproved ? 'CmsKit::Disapproved' : 'CmsKit::Approve';
|
|||
// },
|
|||
// TODO: Add a resolver for the text
|
|||
text: 'CmsKit::Approve', |
|||
action: data => { |
|||
const commentService = data.getInjected(CommentAdminService); |
|||
const list = data.getInjected(ListService); |
|||
const newApprovalStatus = !data.record.isApproved; |
|||
|
|||
commentService |
|||
.updateApprovalStatus(data.record.id!, { isApproved: newApprovalStatus }) |
|||
.subscribe(() => { |
|||
list.get(); |
|||
}); |
|||
}, |
|||
visible: data => { |
|||
const configState = data.getInjected(ConfigStateService); |
|||
const requireApprovement = |
|||
configState.getSetting('CmsKit.Comments.RequireApprovement') === 'true'; |
|||
return requireApprovement; |
|||
}, |
|||
}, |
|||
]); |
|||
@ -0,0 +1,78 @@ |
|||
import { CommentWithAuthorDto } from '@abp/ng.cms-kit/proxy'; |
|||
import { EntityProp, ePropType } from '@abp/ng.components/extensible'; |
|||
import { ConfigStateService } from '@abp/ng.core'; |
|||
import { of } from 'rxjs'; |
|||
|
|||
export const DEFAULT_COMMENT_ENTITY_PROPS = EntityProp.createMany<CommentWithAuthorDto>([ |
|||
{ |
|||
type: ePropType.String, |
|||
name: 'author.userName', |
|||
displayName: 'CmsKit::Username', |
|||
sortable: false, |
|||
columnWidth: 150, |
|||
}, |
|||
{ |
|||
type: ePropType.String, |
|||
name: 'entityType', |
|||
displayName: 'CmsKit::EntityType', |
|||
sortable: false, |
|||
columnWidth: 200, |
|||
}, |
|||
{ |
|||
type: ePropType.String, |
|||
name: 'url', |
|||
displayName: 'CmsKit::URL', |
|||
sortable: false, |
|||
valueResolver: data => { |
|||
const url = data.record.url; |
|||
if (url) { |
|||
return of( |
|||
`<a href="${url}#comment-${data.record.id}" target="_blank"><i class="fa fa-location-arrow"></i></a>`, |
|||
); |
|||
} |
|||
return of(''); |
|||
}, |
|||
}, |
|||
{ |
|||
type: ePropType.String, |
|||
name: 'text', |
|||
displayName: 'CmsKit::Text', |
|||
sortable: false, |
|||
valueResolver: data => { |
|||
const text = data.record.text || ''; |
|||
const maxChars = 64; |
|||
if (text.length > maxChars) { |
|||
return of(text.substring(0, maxChars) + '...'); |
|||
} |
|||
return of(text); |
|||
}, |
|||
}, |
|||
{ |
|||
type: ePropType.Boolean, |
|||
name: 'isApproved', |
|||
displayName: 'CmsKit::ApproveState', |
|||
sortable: false, |
|||
columnWidth: 100, |
|||
columnVisible: getInjected => { |
|||
const configState = getInjected(ConfigStateService); |
|||
return configState.getSetting('CmsKit.Comments.RequireApprovement') === 'true'; |
|||
}, |
|||
valueResolver: data => { |
|||
const isApproved = data.record.isApproved; |
|||
if (isApproved === null || isApproved === undefined) { |
|||
return of('<i class="fa-solid fa-hourglass-half text-muted"></i>'); |
|||
} else if (isApproved === true) { |
|||
return of('<i class="fa-solid fa-check text-success"></i>'); |
|||
} else { |
|||
return of('<i class="fa-solid fa-x text-danger"></i>'); |
|||
} |
|||
}, |
|||
}, |
|||
{ |
|||
type: ePropType.Date, |
|||
name: 'creationTime', |
|||
displayName: 'AbpIdentity::CreationTime', |
|||
sortable: true, |
|||
columnWidth: 200, |
|||
}, |
|||
]); |
|||
@ -0,0 +1,2 @@ |
|||
export * from './default-comment-entity-actions'; |
|||
export * from './default-comment-entity-props'; |
|||
@ -0,0 +1 @@ |
|||
export * from './comments'; |
|||
@ -1,3 +1,29 @@ |
|||
import { eCmsKitAdminComponents } from '../enums'; |
|||
import { |
|||
EntityActionContributorCallback, |
|||
EntityPropContributorCallback, |
|||
} from '@abp/ng.components/extensible'; |
|||
import { CommentWithAuthorDto } from '@abp/ng.cms-kit/proxy'; |
|||
|
|||
export type CmsKitAdminEntityActionContributors = Partial<{ |
|||
[eCmsKitAdminComponents.CommentList]: EntityActionContributorCallback<CommentWithAuthorDto>[]; |
|||
[eCmsKitAdminComponents.CommentApprove]: EntityActionContributorCallback<CommentWithAuthorDto>[]; |
|||
[eCmsKitAdminComponents.CommentDetails]: EntityActionContributorCallback<CommentWithAuthorDto>[]; |
|||
}>; |
|||
|
|||
export type CmsKitAdminEntityPropContributors = Partial<{ |
|||
[eCmsKitAdminComponents.CommentList]: EntityPropContributorCallback<CommentWithAuthorDto>[]; |
|||
[eCmsKitAdminComponents.CommentApprove]: EntityPropContributorCallback<CommentWithAuthorDto>[]; |
|||
[eCmsKitAdminComponents.CommentDetails]: EntityPropContributorCallback<CommentWithAuthorDto>[]; |
|||
}>; |
|||
|
|||
export type CmsKitAdminCreateFormPropContributors = Partial<{}>; |
|||
|
|||
export type CmsKitAdminEditFormPropContributors = Partial<{}>; |
|||
|
|||
export interface CmsKitAdminConfigOptions { |
|||
// Extension point contributors will be added here
|
|||
entityActionContributors?: CmsKitAdminEntityActionContributors; |
|||
entityPropContributors?: CmsKitAdminEntityPropContributors; |
|||
createFormPropContributors?: CmsKitAdminCreateFormPropContributors; |
|||
editFormPropContributors?: CmsKitAdminEditFormPropContributors; |
|||
} |
|||
|
|||
@ -1,8 +1,6 @@ |
|||
// export * from './components';
|
|||
// export * from './defaults';
|
|||
export * from './components'; |
|||
export * from './defaults'; |
|||
export * from './enums'; |
|||
// export * from './models';
|
|||
export * from './resolvers'; |
|||
// export * from './services';
|
|||
export * from './tokens'; |
|||
export * from './cms-kit-admin.routes'; |
|||
|
|||
@ -1,8 +1,49 @@ |
|||
import { |
|||
ExtensionsService, |
|||
getObjectExtensionEntitiesFromStore, |
|||
mapEntitiesToContributors, |
|||
mergeWithDefaultActions, |
|||
mergeWithDefaultProps, |
|||
} from '@abp/ng.components/extensible'; |
|||
import { inject, Injector } from '@angular/core'; |
|||
import { ResolveFn } from '@angular/router'; |
|||
import { map, tap } from 'rxjs'; |
|||
import { eCmsKitAdminComponents } from '../enums'; |
|||
import { |
|||
CMS_KIT_ADMIN_ENTITY_ACTION_CONTRIBUTORS, |
|||
CMS_KIT_ADMIN_ENTITY_PROP_CONTRIBUTORS, |
|||
DEFAULT_CMS_KIT_ADMIN_ENTITY_ACTIONS, |
|||
DEFAULT_CMS_KIT_ADMIN_ENTITY_PROPS, |
|||
} from '../tokens'; |
|||
|
|||
// Resolvers will be defined here
|
|||
// Example:
|
|||
// export const cmsKitAdminResolver: ResolveFn<any> = (route, state) => {
|
|||
// // Resolver implementation
|
|||
// return null;
|
|||
// };
|
|||
export const cmsKitAdminExtensionsResolver: ResolveFn<any> = () => { |
|||
const injector = inject(Injector); |
|||
const extensions = inject(ExtensionsService); |
|||
|
|||
const config = { optional: true }; |
|||
|
|||
const actionContributors = inject(CMS_KIT_ADMIN_ENTITY_ACTION_CONTRIBUTORS, config) || {}; |
|||
const propContributors = inject(CMS_KIT_ADMIN_ENTITY_PROP_CONTRIBUTORS, config) || {}; |
|||
|
|||
return getObjectExtensionEntitiesFromStore(injector, 'CmsKit').pipe( |
|||
map(entities => ({ |
|||
[eCmsKitAdminComponents.CommentList]: entities.Comment, |
|||
[eCmsKitAdminComponents.CommentApprove]: entities.Comment, |
|||
[eCmsKitAdminComponents.CommentDetails]: entities.Comment, |
|||
})), |
|||
mapEntitiesToContributors(injector, 'CmsKit'), |
|||
tap(objectExtensionContributors => { |
|||
mergeWithDefaultActions( |
|||
extensions.entityActions, |
|||
DEFAULT_CMS_KIT_ADMIN_ENTITY_ACTIONS, |
|||
actionContributors, |
|||
); |
|||
mergeWithDefaultProps( |
|||
extensions.entityProps, |
|||
DEFAULT_CMS_KIT_ADMIN_ENTITY_PROPS, |
|||
objectExtensionContributors.prop, |
|||
propContributors, |
|||
); |
|||
}), |
|||
); |
|||
}; |
|||
|
|||
@ -1,4 +1,41 @@ |
|||
import { CommentWithAuthorDto } from '@abp/ng.cms-kit/proxy'; |
|||
import { |
|||
EntityActionContributorCallback, |
|||
EntityPropContributorCallback, |
|||
} from '@abp/ng.components/extensible'; |
|||
import { InjectionToken } from '@angular/core'; |
|||
import { DEFAULT_COMMENT_ENTITY_ACTIONS } from '../defaults/comments/default-comment-entity-actions'; |
|||
import { DEFAULT_COMMENT_ENTITY_PROPS } from '../defaults/comments/default-comment-entity-props'; |
|||
import { eCmsKitAdminComponents } from '../enums'; |
|||
|
|||
// Extension tokens will be defined here
|
|||
export const EXTENSIONS_IDENTIFIER = new InjectionToken<string>('EXTENSIONS_IDENTIFIER'); |
|||
export const DEFAULT_CMS_KIT_ADMIN_ENTITY_ACTIONS = { |
|||
[eCmsKitAdminComponents.CommentList]: DEFAULT_COMMENT_ENTITY_ACTIONS, |
|||
[eCmsKitAdminComponents.CommentApprove]: DEFAULT_COMMENT_ENTITY_ACTIONS, |
|||
[eCmsKitAdminComponents.CommentDetails]: DEFAULT_COMMENT_ENTITY_ACTIONS, |
|||
}; |
|||
|
|||
export const DEFAULT_CMS_KIT_ADMIN_ENTITY_PROPS = { |
|||
[eCmsKitAdminComponents.CommentList]: DEFAULT_COMMENT_ENTITY_PROPS, |
|||
[eCmsKitAdminComponents.CommentApprove]: DEFAULT_COMMENT_ENTITY_PROPS, |
|||
[eCmsKitAdminComponents.CommentDetails]: DEFAULT_COMMENT_ENTITY_PROPS, |
|||
}; |
|||
|
|||
export const CMS_KIT_ADMIN_ENTITY_ACTION_CONTRIBUTORS = |
|||
new InjectionToken<EntityActionContributors>('CMS_KIT_ADMIN_ENTITY_ACTION_CONTRIBUTORS'); |
|||
|
|||
export const CMS_KIT_ADMIN_ENTITY_PROP_CONTRIBUTORS = new InjectionToken<EntityPropContributors>( |
|||
'CMS_KIT_ADMIN_ENTITY_PROP_CONTRIBUTORS', |
|||
); |
|||
|
|||
// Fix for TS4023 -> https://github.com/microsoft/TypeScript/issues/9944#issuecomment-254693497
|
|||
type EntityActionContributors = Partial<{ |
|||
[eCmsKitAdminComponents.CommentList]: EntityActionContributorCallback<CommentWithAuthorDto>[]; |
|||
[eCmsKitAdminComponents.CommentApprove]: EntityActionContributorCallback<CommentWithAuthorDto>[]; |
|||
[eCmsKitAdminComponents.CommentDetails]: EntityActionContributorCallback<CommentWithAuthorDto>[]; |
|||
}>; |
|||
|
|||
type EntityPropContributors = Partial<{ |
|||
[eCmsKitAdminComponents.CommentList]: EntityPropContributorCallback<CommentWithAuthorDto>[]; |
|||
[eCmsKitAdminComponents.CommentApprove]: EntityPropContributorCallback<CommentWithAuthorDto>[]; |
|||
[eCmsKitAdminComponents.CommentDetails]: EntityPropContributorCallback<CommentWithAuthorDto>[]; |
|||
}>; |
|||
|
|||
Loading…
Reference in new issue