mirror of https://github.com/abpframework/abp.git
215 changed files with 5502 additions and 9725 deletions
@ -0,0 +1,288 @@ |
|||
# How Replaceable Components Work with Extensions |
|||
|
|||
Additional UI extensibility points ([Entity action extensions](https://docs.abp.io/en/abp/latest/UI/Angular/Entity-Action-Extensions), [data table column extensions](https://docs.abp.io/en/abp/latest/UI/Angular/Data-Table-Column-Extensions), [page toolbar extensions](https://docs.abp.io/en/abp/latest/UI/Angular/Page-Toolbar-Extensions) and others) are used in ABP pages to allow to control entity actions, table columns and page toolbar of a page. If you replace a page, you need to apply some configurations to be able to work extension components in your component. Let's see how to do this by replacing the roles page. |
|||
|
|||
Create a new module called `MyRolesModule`: |
|||
|
|||
```bash |
|||
yarn ng generate module my-roles --module app |
|||
``` |
|||
|
|||
Create a new component called `MyRolesComponent`: |
|||
|
|||
```bash |
|||
yarn ng generate component my-roles/my-roles --flat --export |
|||
``` |
|||
|
|||
Open the generated `src/app/my-roles/my-roles.component.ts` file and replace its content with the following: |
|||
|
|||
```js |
|||
import { ListService, PagedAndSortedResultRequestDto } from '@abp/ng.core'; |
|||
import { |
|||
CreateRole, |
|||
DeleteRole, |
|||
eIdentityComponents, |
|||
GetRoleById, |
|||
GetRoles, |
|||
IdentityRoleDto, |
|||
IdentityState, |
|||
RolesComponent, |
|||
UpdateRole, |
|||
} from '@abp/ng.identity'; |
|||
import { ePermissionManagementComponents } from '@abp/ng.permission-management'; |
|||
import { Confirmation, ConfirmationService } from '@abp/ng.theme.shared'; |
|||
import { |
|||
EXTENSIONS_IDENTIFIER, |
|||
FormPropData, |
|||
generateFormFromProps, |
|||
} from '@abp/ng.theme.shared/extensions'; |
|||
import { Component, Injector, OnInit } from '@angular/core'; |
|||
import { FormGroup } from '@angular/forms'; |
|||
import { Select, Store } from '@ngxs/store'; |
|||
import { Observable } from 'rxjs'; |
|||
import { finalize, pluck } from 'rxjs/operators'; |
|||
|
|||
@Component({ |
|||
selector: 'app-my-roles', |
|||
templateUrl: './my-roles.component.html', |
|||
providers: [ |
|||
ListService, |
|||
{ |
|||
provide: EXTENSIONS_IDENTIFIER, |
|||
useValue: eIdentityComponents.Roles, |
|||
}, |
|||
{ provide: RolesComponent, useExisting: MyRolesComponent }, |
|||
], |
|||
}) |
|||
export class MyRolesComponent implements OnInit { |
|||
@Select(IdentityState.getRoles) |
|||
data$: Observable<IdentityRoleDto[]>; |
|||
|
|||
@Select(IdentityState.getRolesTotalCount) |
|||
totalCount$: Observable<number>; |
|||
|
|||
form: FormGroup; |
|||
|
|||
selected: IdentityRoleDto; |
|||
|
|||
isModalVisible: boolean; |
|||
|
|||
visiblePermissions = false; |
|||
|
|||
providerKey: string; |
|||
|
|||
modalBusy = false; |
|||
|
|||
permissionManagementKey = ePermissionManagementComponents.PermissionManagement; |
|||
|
|||
onVisiblePermissionChange = event => { |
|||
this.visiblePermissions = event; |
|||
}; |
|||
|
|||
constructor( |
|||
public readonly list: ListService<PagedAndSortedResultRequestDto>, |
|||
protected confirmationService: ConfirmationService, |
|||
protected store: Store, |
|||
protected injector: Injector |
|||
) {} |
|||
|
|||
ngOnInit() { |
|||
this.hookToQuery(); |
|||
} |
|||
|
|||
buildForm() { |
|||
const data = new FormPropData(this.injector, this.selected); |
|||
this.form = generateFormFromProps(data); |
|||
} |
|||
|
|||
openModal() { |
|||
this.buildForm(); |
|||
this.isModalVisible = true; |
|||
} |
|||
|
|||
add() { |
|||
this.selected = {} as IdentityRoleDto; |
|||
this.openModal(); |
|||
} |
|||
|
|||
edit(id: string) { |
|||
this.store |
|||
.dispatch(new GetRoleById(id)) |
|||
.pipe(pluck('IdentityState', 'selectedRole')) |
|||
.subscribe(selectedRole => { |
|||
this.selected = selectedRole; |
|||
this.openModal(); |
|||
}); |
|||
} |
|||
|
|||
save() { |
|||
if (!this.form.valid) return; |
|||
this.modalBusy = true; |
|||
|
|||
this.store |
|||
.dispatch( |
|||
this.selected.id |
|||
? new UpdateRole({ ...this.selected, ...this.form.value, id: this.selected.id }) |
|||
: new CreateRole(this.form.value) |
|||
) |
|||
.pipe(finalize(() => (this.modalBusy = false))) |
|||
.subscribe(() => { |
|||
this.isModalVisible = false; |
|||
this.list.get(); |
|||
}); |
|||
} |
|||
|
|||
delete(id: string, name: string) { |
|||
this.confirmationService |
|||
.warn('AbpIdentity::RoleDeletionConfirmationMessage', 'AbpIdentity::AreYouSure', { |
|||
messageLocalizationParams: [name], |
|||
}) |
|||
.subscribe((status: Confirmation.Status) => { |
|||
if (status === Confirmation.Status.confirm) { |
|||
this.store.dispatch(new DeleteRole(id)).subscribe(() => this.list.get()); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
private hookToQuery() { |
|||
this.list.hookToQuery(query => this.store.dispatch(new GetRoles(query))).subscribe(); |
|||
} |
|||
|
|||
openPermissionsModal(providerKey: string) { |
|||
this.providerKey = providerKey; |
|||
setTimeout(() => { |
|||
this.visiblePermissions = true; |
|||
}, 0); |
|||
} |
|||
|
|||
sort(data) { |
|||
const { prop, dir } = data.sorts[0]; |
|||
this.list.sortKey = prop; |
|||
this.list.sortOrder = dir; |
|||
} |
|||
} |
|||
``` |
|||
|
|||
```js |
|||
{ |
|||
provide: EXTENSIONS_IDENTIFIER, |
|||
useValue: eIdentityComponents.Roles, |
|||
}, |
|||
{ |
|||
provide: RolesComponent, |
|||
useExisting: MyRolesComponent |
|||
} |
|||
``` |
|||
|
|||
The two providers we have defined in `MyRolesComponent` are required for the extension components to work correctly. |
|||
|
|||
* With the first provider, we defined the extension identifier for using `RolesComponent`'s extension actions in the `MyRolesComponent`. |
|||
* With the second provider, we have replaced the `RolesComponent` injection with the `MyRolesComponent`. Default extension actions of the `RolesComponent` try to get `RolesComponent` instance. However, the actions can get the `MyRolesComponent` instance after defining the second provider. |
|||
|
|||
Open the generated `src/app/my-role/my-role.component.html` file and replace its content with the following: |
|||
|
|||
```html |
|||
<div id="identity-roles-wrapper" class="card"> |
|||
<div class="card-header"> |
|||
<div class="row"> |
|||
<div class="col col-md-6"> |
|||
<h5 class="card-title">My Roles</h5> |
|||
</div> |
|||
<div class="text-right col col-md-6"> |
|||
<abp-page-toolbar [record]="data$ | async"></abp-page-toolbar> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="card-body"> |
|||
<abp-extensible-table |
|||
[data]="data$ | async" |
|||
[recordsTotal]="totalCount$ | async" |
|||
[list]="list" |
|||
></abp-extensible-table> |
|||
</div> |
|||
</div> |
|||
|
|||
<abp-modal size="md" [(visible)]="isModalVisible" [busy]="modalBusy"> |
|||
<ng-template #abpHeader> |
|||
<h3>{%{{{ (selected?.id ? 'AbpIdentity::Edit' : 'AbpIdentity::NewRole') | abpLocalization }}}%}</h3> |
|||
</ng-template> |
|||
|
|||
<ng-template #abpBody> |
|||
<form [formGroup]="form" (ngSubmit)="save()" validateOnSubmit> |
|||
<abp-extensible-form [selectedRecord]="selected"></abp-extensible-form> |
|||
</form> |
|||
</ng-template> |
|||
|
|||
<ng-template #abpFooter> |
|||
<button type="button" class="btn btn-secondary" #abpClose> |
|||
{%{{{ 'AbpIdentity::Cancel' | abpLocalization }}}%} |
|||
</button> |
|||
<abp-button iconClass="fa fa-check" [disabled]="form?.invalid" (click)="save()">{%{{{ |
|||
'AbpIdentity::Save' | abpLocalization |
|||
}}}%}</abp-button> |
|||
</ng-template> |
|||
</abp-modal> |
|||
|
|||
<abp-permission-management |
|||
#abpPermissionManagement="abpPermissionManagement" |
|||
*abpReplaceableTemplate=" |
|||
{ |
|||
inputs: { |
|||
providerName: { value: 'R' }, |
|||
providerKey: { value: providerKey }, |
|||
visible: { value: visiblePermissions, twoWay: true }, |
|||
hideBadges: { value: true } |
|||
}, |
|||
outputs: { visibleChange: onVisiblePermissionChange }, |
|||
componentKey: permissionManagementKey |
|||
}; |
|||
let init = initTemplate |
|||
" |
|||
(abpInit)="init(abpPermissionManagement)" |
|||
> |
|||
</abp-permission-management> |
|||
``` |
|||
|
|||
We have added the `abp-page-toolbar`, `abp-extensible-table`, and `abp-extensible-form` extension components to template of the `MyRolesComponent`. |
|||
|
|||
You should import the required modules for the `MyRolesComponent` to `MyRolesModule`. Open the `src/my-roles/my-roles.module.ts` file and replace the content with the following: |
|||
|
|||
```js |
|||
import { UiExtensionsModule } from '@abp/ng.theme.shared/extensions'; |
|||
import { NgModule } from '@angular/core'; |
|||
import { SharedModule } from '../shared/shared.module'; |
|||
import { MyRolesComponent } from './my-roles.component'; |
|||
import { PermissionManagementModule } from '@abp/ng.permission-management'; |
|||
|
|||
@NgModule({ |
|||
declarations: [MyRolesComponent], |
|||
imports: [SharedModule, UiExtensionsModule, PermissionManagementModule], |
|||
exports: [MyRolesComponent], |
|||
}) |
|||
export class MyRolesModule {} |
|||
``` |
|||
|
|||
- `UiExtensionsModule` imported to be able to use the extension components in your component. |
|||
- `PermissionManagementModule` imported to be able to use the `abp-permission-*management` in your component. |
|||
|
|||
As the last step, it is needs to be replaced the `RolesComponent` with the `MyRolesComponent`. Open the `app.component.ts` and modify its content as shown below: |
|||
|
|||
```js |
|||
import { ReplaceableComponentsService } from '@abp/ng.core'; |
|||
import { eIdentityComponents } from '@abp/ng.identity'; |
|||
import { MyRolesComponent } from './my-roles/my-roles.component'; |
|||
|
|||
@Component(/* component metadata */) |
|||
export class AppComponent { |
|||
constructor(private replaceableComponents: ReplaceableComponentsService) { |
|||
this.replaceableComponents.add({ component: MyRolesComponent, key: eIdentityComponents.Roles }); |
|||
} |
|||
} |
|||
``` |
|||
|
|||
After the steps above, the `RolesComponent` has been successfully replaced with the `MyRolesComponent`. When you navigate to the `/identity/roles` URL, you will see the `MyRolesComponent`'s template and see the extension components working correctly. |
|||
|
|||
 |
|||
|
|||
 |
|||
|
After Width: | Height: | Size: 56 KiB |
|
After Width: | Height: | Size: 59 KiB |
@ -1,65 +0,0 @@ |
|||
using System; |
|||
using System.IO; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.Cli.Args; |
|||
using Volo.Abp.Cli.Utils; |
|||
using Volo.Abp.DependencyInjection; |
|||
|
|||
namespace Volo.Abp.Cli.Commands |
|||
{ |
|||
public class CreateMigrationAndRunMigrator : IConsoleCommand, ITransientDependency |
|||
{ |
|||
public virtual async Task ExecuteAsync(CommandLineArgs commandLineArgs) |
|||
{ |
|||
if (commandLineArgs.Target.IsNullOrEmpty()) |
|||
{ |
|||
throw new CliUsageException( |
|||
"DbMigrations folder path is missing!" |
|||
); |
|||
} |
|||
|
|||
var dbMigratorProjectPath = GetDbMigratorProjectPath(commandLineArgs.Target); |
|||
|
|||
if (dbMigratorProjectPath == null) |
|||
{ |
|||
throw new Exception("DbMigrator is not found!"); |
|||
} |
|||
|
|||
var output = CmdHelper.RunCmdAndGetOutput($"cd \"{commandLineArgs.Target}\" && dotnet ef migrations add Initial -s \"{dbMigratorProjectPath}\""); |
|||
|
|||
if (output.Contains("Done.") && output.Contains("To undo this action") && output.Contains("ef migrations remove")) // Migration added successfully
|
|||
{ |
|||
CmdHelper.RunCmd("cd \"" + Path.GetDirectoryName(dbMigratorProjectPath) + "\" && dotnet run"); |
|||
} |
|||
else |
|||
{ |
|||
throw new Exception("Migrations failed: " + output); |
|||
} |
|||
} |
|||
|
|||
private string GetDbMigratorProjectPath(string dbMigrationsFolderPath) |
|||
{ |
|||
var srcFolder = Directory.GetParent(dbMigrationsFolderPath); |
|||
|
|||
var dbMigratorFolderPath = Directory.GetDirectories(srcFolder.FullName).FirstOrDefault(d => d.EndsWith(".DbMigrator")); |
|||
|
|||
if (dbMigratorFolderPath == null) |
|||
{ |
|||
return null; |
|||
} |
|||
|
|||
return Directory.GetFiles(dbMigratorFolderPath).FirstOrDefault(f => f.EndsWith(".csproj")); |
|||
} |
|||
|
|||
public string GetUsageInfo() |
|||
{ |
|||
return string.Empty; |
|||
} |
|||
|
|||
public string GetShortDescription() |
|||
{ |
|||
return string.Empty; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,98 @@ |
|||
using System; |
|||
using System.IO; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using Microsoft.Extensions.Logging; |
|||
using Microsoft.Extensions.Logging.Abstractions; |
|||
using Volo.Abp.Cli.Args; |
|||
using Volo.Abp.Cli.Utils; |
|||
using Volo.Abp.DependencyInjection; |
|||
|
|||
namespace Volo.Abp.Cli.Commands |
|||
{ |
|||
public class CreateMigrationAndRunMigratorCommand : IConsoleCommand, ITransientDependency |
|||
{ |
|||
public ILogger<CreateMigrationAndRunMigratorCommand> Logger { get; set; } |
|||
|
|||
public CreateMigrationAndRunMigratorCommand() |
|||
{ |
|||
Logger = NullLogger<CreateMigrationAndRunMigratorCommand>.Instance; |
|||
} |
|||
|
|||
public virtual async Task ExecuteAsync(CommandLineArgs commandLineArgs) |
|||
{ |
|||
if (commandLineArgs.Target.IsNullOrEmpty()) |
|||
{ |
|||
throw new CliUsageException("DbMigrations folder path is missing!"); |
|||
} |
|||
|
|||
var dbMigratorProjectPath = GetDbMigratorProjectPath(commandLineArgs.Target); |
|||
if (dbMigratorProjectPath == null) |
|||
{ |
|||
throw new Exception("DbMigrator is not found!"); |
|||
} |
|||
|
|||
if (!IsDotNetEfToolInstalled()) |
|||
{ |
|||
InstallDotnetEfTool(); |
|||
} |
|||
|
|||
var addMigrationCmd = $"cd \"{commandLineArgs.Target}\" && " + |
|||
$"dotnet ef migrations add Initial -s \"{dbMigratorProjectPath}\""; |
|||
|
|||
var output = CmdHelper.RunCmdAndGetOutput(addMigrationCmd); |
|||
if (output.Contains("Done.") && |
|||
output.Contains("To undo this action") && |
|||
output.Contains("ef migrations remove")) |
|||
{ |
|||
// Migration added successfully
|
|||
CmdHelper.RunCmd("cd \"" + Path.GetDirectoryName(dbMigratorProjectPath) + "\" && dotnet run"); |
|||
await Task.CompletedTask; |
|||
} |
|||
else |
|||
{ |
|||
var exceptionMsg = "Migrations failed! The following command didn't run successfully:" + |
|||
Environment.NewLine + |
|||
addMigrationCmd + |
|||
Environment.NewLine + output; |
|||
|
|||
Logger.LogError(exceptionMsg); |
|||
throw new Exception(exceptionMsg); |
|||
} |
|||
} |
|||
|
|||
private static bool IsDotNetEfToolInstalled() |
|||
{ |
|||
var output = CmdHelper.RunCmdAndGetOutput("dotnet tool list -g"); |
|||
return output.Contains("dotnet-ef"); |
|||
} |
|||
|
|||
private void InstallDotnetEfTool() |
|||
{ |
|||
Logger.LogInformation("Installing dotnet-ef tool..."); |
|||
CmdHelper.RunCmd("dotnet tool install --global dotnet-ef"); |
|||
Logger.LogInformation("dotnet-ef tool is installed."); |
|||
} |
|||
|
|||
private static string GetDbMigratorProjectPath(string dbMigrationsFolderPath) |
|||
{ |
|||
var srcFolder = Directory.GetParent(dbMigrationsFolderPath); |
|||
var dbMigratorDirectory = Directory.GetDirectories(srcFolder.FullName) |
|||
.FirstOrDefault(d => d.EndsWith(".DbMigrator")); |
|||
|
|||
return dbMigratorDirectory == null |
|||
? null |
|||
: Directory.GetFiles(dbMigratorDirectory).FirstOrDefault(f => f.EndsWith(".csproj")); |
|||
} |
|||
|
|||
public string GetUsageInfo() |
|||
{ |
|||
return string.Empty; |
|||
} |
|||
|
|||
public string GetShortDescription() |
|||
{ |
|||
return string.Empty; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,79 @@ |
|||
using System; |
|||
using System.Linq; |
|||
using System.Text; |
|||
using Microsoft.Extensions.Logging; |
|||
using Microsoft.Extensions.Logging.Abstractions; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.Cli.Args; |
|||
using Volo.Abp.Cli.ProjectBuilding; |
|||
using Volo.Abp.DependencyInjection; |
|||
|
|||
namespace Volo.Abp.Cli.Commands |
|||
{ |
|||
public class ListModulesCommand : IConsoleCommand, ITransientDependency |
|||
{ |
|||
public ModuleInfoProvider ModuleInfoProvider { get; } |
|||
public ILogger<ListModulesCommand> Logger { get; set; } |
|||
|
|||
|
|||
public ListModulesCommand(ModuleInfoProvider moduleInfoProvider) |
|||
{ |
|||
ModuleInfoProvider = moduleInfoProvider; |
|||
Logger = NullLogger<ListModulesCommand>.Instance; |
|||
} |
|||
|
|||
public async Task ExecuteAsync(CommandLineArgs commandLineArgs) |
|||
{ |
|||
var modules = await ModuleInfoProvider.GetModuleListAsync(); |
|||
var freeModules = modules.Where(m => !m.IsPro).ToList(); |
|||
var proModules = modules.Where(m => m.IsPro).ToList(); |
|||
|
|||
var output = new StringBuilder(Environment.NewLine); |
|||
output.AppendLine("Open Source Application Modules"); |
|||
output.AppendLine(); |
|||
|
|||
foreach (var module in freeModules) |
|||
{ |
|||
output.AppendLine($"> {module.DisplayName.PadRight(50)} ({module.Name})"); |
|||
} |
|||
|
|||
if (commandLineArgs.Options.ContainsKey("include-pro-modules")) |
|||
{ |
|||
output.AppendLine(); |
|||
output.AppendLine("Commercial (Pro) Application Modules"); |
|||
output.AppendLine(); |
|||
foreach (var module in proModules) |
|||
{ |
|||
output.AppendLine($"> {module.DisplayName.PadRight(50)} ({module.Name})"); |
|||
} |
|||
} |
|||
|
|||
Logger.LogInformation(output.ToString()); |
|||
} |
|||
|
|||
public string GetUsageInfo() |
|||
{ |
|||
var sb = new StringBuilder(); |
|||
|
|||
sb.AppendLine(""); |
|||
sb.AppendLine("'list-modules' command is used for listing open source application modules."); |
|||
sb.AppendLine(""); |
|||
sb.AppendLine("Usage:"); |
|||
sb.AppendLine(" abp list-modules"); |
|||
sb.AppendLine(" abp list-modules --include-pro-modules"); |
|||
sb.AppendLine(""); |
|||
sb.AppendLine("Options:"); |
|||
sb.AppendLine(" --include-pro-modules Includes commercial (pro) modules in the output."); |
|||
sb.AppendLine(""); |
|||
sb.AppendLine("See the documentation for more info: https://docs.abp.io/en/abp/latest/CLI"); |
|||
|
|||
return sb.ToString(); |
|||
} |
|||
|
|||
public string GetShortDescription() |
|||
{ |
|||
return "List open source application modules"; |
|||
} |
|||
|
|||
} |
|||
} |
|||
@ -1,26 +1,33 @@ |
|||
// using JetBrains.Annotations;
|
|||
// using Microsoft.EntityFrameworkCore;
|
|||
// using System;
|
|||
// using Oracle.EntityFrameworkCore.Infrastructure;
|
|||
// using Volo.Abp.EntityFrameworkCore.DependencyInjection;
|
|||
//
|
|||
// namespace Volo.Abp.EntityFrameworkCore
|
|||
// {
|
|||
// public static class AbpDbContextConfigurationContextOracleExtensions
|
|||
// {
|
|||
// public static DbContextOptionsBuilder UseOracle(
|
|||
// [NotNull] this AbpDbContextConfigurationContext context,
|
|||
// [CanBeNull] Action<OracleDbContextOptionsBuilder> oracleOptionsAction = null)
|
|||
// {
|
|||
// TODO: UseQuerySplittingBehavior(QuerySplittingBehavior.SplitQuery);
|
|||
// if (context.ExistingConnection != null)
|
|||
// {
|
|||
// return context.DbContextOptions.UseOracle(context.ExistingConnection, oracleOptionsAction);
|
|||
// }
|
|||
// else
|
|||
// {
|
|||
// return context.DbContextOptions.UseOracle(context.ConnectionString, oracleOptionsAction);
|
|||
// }
|
|||
// }
|
|||
// }
|
|||
// }
|
|||
using JetBrains.Annotations; |
|||
using Microsoft.EntityFrameworkCore; |
|||
using System; |
|||
using Oracle.EntityFrameworkCore.Infrastructure; |
|||
using Volo.Abp.EntityFrameworkCore.DependencyInjection; |
|||
|
|||
namespace Volo.Abp.EntityFrameworkCore |
|||
{ |
|||
public static class AbpDbContextConfigurationContextOracleExtensions |
|||
{ |
|||
public static DbContextOptionsBuilder UseOracle( |
|||
[NotNull] this AbpDbContextConfigurationContext context, |
|||
[CanBeNull] Action<OracleDbContextOptionsBuilder> oracleOptionsAction = null) |
|||
{ |
|||
if (context.ExistingConnection != null) |
|||
{ |
|||
return context.DbContextOptions.UseOracle(context.ExistingConnection, optionsBuilder => |
|||
{ |
|||
optionsBuilder.UseQuerySplittingBehavior(QuerySplittingBehavior.SplitQuery); |
|||
oracleOptionsAction?.Invoke(optionsBuilder); |
|||
}); |
|||
} |
|||
else |
|||
{ |
|||
return context.DbContextOptions.UseOracle(context.ConnectionString, optionsBuilder => |
|||
{ |
|||
optionsBuilder.UseQuerySplittingBehavior(QuerySplittingBehavior.SplitQuery); |
|||
oracleOptionsAction?.Invoke(optionsBuilder); |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -1,30 +1,30 @@ |
|||
// using JetBrains.Annotations;
|
|||
// using System;
|
|||
// using Oracle.EntityFrameworkCore.Infrastructure;
|
|||
//
|
|||
// namespace Volo.Abp.EntityFrameworkCore
|
|||
// {
|
|||
// public static class AbpDbContextOptionsOracleExtensions
|
|||
// {
|
|||
// public static void UseOracle(
|
|||
// [NotNull] this AbpDbContextOptions options,
|
|||
// [CanBeNull] Action<OracleDbContextOptionsBuilder> oracleOptionsAction = null)
|
|||
// {
|
|||
// options.Configure(context =>
|
|||
// {
|
|||
// context.UseOracle(oracleOptionsAction);
|
|||
// });
|
|||
// }
|
|||
//
|
|||
// public static void UseOracle<TDbContext>(
|
|||
// [NotNull] this AbpDbContextOptions options,
|
|||
// [CanBeNull] Action<OracleDbContextOptionsBuilder> oracleOptionsAction = null)
|
|||
// where TDbContext : AbpDbContext<TDbContext>
|
|||
// {
|
|||
// options.Configure<TDbContext>(context =>
|
|||
// {
|
|||
// context.UseOracle(oracleOptionsAction);
|
|||
// });
|
|||
// }
|
|||
// }
|
|||
// }
|
|||
using JetBrains.Annotations; |
|||
using System; |
|||
using Oracle.EntityFrameworkCore.Infrastructure; |
|||
|
|||
namespace Volo.Abp.EntityFrameworkCore |
|||
{ |
|||
public static class AbpDbContextOptionsOracleExtensions |
|||
{ |
|||
public static void UseOracle( |
|||
[NotNull] this AbpDbContextOptions options, |
|||
[CanBeNull] Action<OracleDbContextOptionsBuilder> oracleOptionsAction = null) |
|||
{ |
|||
options.Configure(context => |
|||
{ |
|||
context.UseOracle(oracleOptionsAction); |
|||
}); |
|||
} |
|||
|
|||
public static void UseOracle<TDbContext>( |
|||
[NotNull] this AbpDbContextOptions options, |
|||
[CanBeNull] Action<OracleDbContextOptionsBuilder> oracleOptionsAction = null) |
|||
where TDbContext : AbpDbContext<TDbContext> |
|||
{ |
|||
options.Configure<TDbContext>(context => |
|||
{ |
|||
context.UseOracle(oracleOptionsAction); |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -1,22 +1,20 @@ |
|||
// using Volo.Abp.Guids;
|
|||
// using Volo.Abp.Modularity;
|
|||
//
|
|||
// namespace Volo.Abp.EntityFrameworkCore.Oracle
|
|||
// {
|
|||
// [DependsOn(
|
|||
// typeof(AbpEntityFrameworkCoreModule)
|
|||
// )]
|
|||
// public class AbpEntityFrameworkCoreOracleModule : AbpModule
|
|||
// {
|
|||
// public override void ConfigureServices(ServiceConfigurationContext context)
|
|||
// {
|
|||
// Configure<AbpSequentialGuidGeneratorOptions>(options =>
|
|||
// {
|
|||
// if (options.DefaultSequentialGuidType == null)
|
|||
// {
|
|||
// options.DefaultSequentialGuidType = SequentialGuidType.SequentialAsBinary;
|
|||
// }
|
|||
// });
|
|||
// }
|
|||
// }
|
|||
// }
|
|||
using Volo.Abp.Guids; |
|||
using Volo.Abp.Modularity; |
|||
|
|||
namespace Volo.Abp.EntityFrameworkCore.Oracle |
|||
{ |
|||
[DependsOn(typeof(AbpEntityFrameworkCoreModule))] |
|||
public class AbpEntityFrameworkCoreOracleModule : AbpModule |
|||
{ |
|||
public override void ConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
Configure<AbpSequentialGuidGeneratorOptions>(options => |
|||
{ |
|||
if (options.DefaultSequentialGuidType == null) |
|||
{ |
|||
options.DefaultSequentialGuidType = SequentialGuidType.SequentialAsBinary; |
|||
} |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
|
|||
File diff suppressed because it is too large
File diff suppressed because it is too large
@ -1,46 +0,0 @@ |
|||
using System; |
|||
using Microsoft.EntityFrameworkCore.Migrations; |
|||
|
|||
namespace Volo.CmsKit.Migrations |
|||
{ |
|||
public partial class Added_Page : Migration |
|||
{ |
|||
protected override void Up(MigrationBuilder migrationBuilder) |
|||
{ |
|||
migrationBuilder.CreateTable( |
|||
name: "CmsPages", |
|||
columns: table => new |
|||
{ |
|||
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false), |
|||
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true), |
|||
Title = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: false), |
|||
Url = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: false), |
|||
Description = table.Column<string>(type: "nvarchar(515)", maxLength: 515, nullable: true), |
|||
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: true), |
|||
ConcurrencyStamp = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: true), |
|||
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false), |
|||
CreatorId = table.Column<Guid>(type: "uniqueidentifier", nullable: true), |
|||
LastModificationTime = table.Column<DateTime>(type: "datetime2", nullable: true), |
|||
LastModifierId = table.Column<Guid>(type: "uniqueidentifier", nullable: true), |
|||
IsDeleted = table.Column<bool>(type: "bit", nullable: false, defaultValue: false), |
|||
DeleterId = table.Column<Guid>(type: "uniqueidentifier", nullable: true), |
|||
DeletionTime = table.Column<DateTime>(type: "datetime2", nullable: true) |
|||
}, |
|||
constraints: table => |
|||
{ |
|||
table.PrimaryKey("PK_CmsPages", x => x.Id); |
|||
}); |
|||
|
|||
migrationBuilder.CreateIndex( |
|||
name: "IX_CmsPages_TenantId_Url", |
|||
table: "CmsPages", |
|||
columns: new[] { "TenantId", "Url" }); |
|||
} |
|||
|
|||
protected override void Down(MigrationBuilder migrationBuilder) |
|||
{ |
|||
migrationBuilder.DropTable( |
|||
name: "CmsPages"); |
|||
} |
|||
} |
|||
} |
|||
File diff suppressed because it is too large
@ -1,24 +0,0 @@ |
|||
using Microsoft.EntityFrameworkCore.Migrations; |
|||
|
|||
namespace Volo.CmsKit.Migrations |
|||
{ |
|||
public partial class Updated_Tag_Removed_HexColor : Migration |
|||
{ |
|||
protected override void Up(MigrationBuilder migrationBuilder) |
|||
{ |
|||
migrationBuilder.DropColumn( |
|||
name: "HexColor", |
|||
table: "CmsTags"); |
|||
} |
|||
|
|||
protected override void Down(MigrationBuilder migrationBuilder) |
|||
{ |
|||
migrationBuilder.AddColumn<string>( |
|||
name: "HexColor", |
|||
table: "CmsTags", |
|||
type: "nvarchar(6)", |
|||
maxLength: 6, |
|||
nullable: true); |
|||
} |
|||
} |
|||
} |
|||
File diff suppressed because it is too large
@ -1,95 +0,0 @@ |
|||
using System; |
|||
using Microsoft.EntityFrameworkCore.Migrations; |
|||
|
|||
namespace Volo.CmsKit.Migrations |
|||
{ |
|||
public partial class Added_Blob_Storing : Migration |
|||
{ |
|||
protected override void Up(MigrationBuilder migrationBuilder) |
|||
{ |
|||
migrationBuilder.AlterColumn<string>( |
|||
name: "Description", |
|||
table: "CmsPages", |
|||
type: "nvarchar(512)", |
|||
maxLength: 512, |
|||
nullable: true, |
|||
oldClrType: typeof(string), |
|||
oldType: "nvarchar(515)", |
|||
oldMaxLength: 515, |
|||
oldNullable: true); |
|||
|
|||
migrationBuilder.CreateTable( |
|||
name: "AbpBlobContainers", |
|||
columns: table => new |
|||
{ |
|||
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false), |
|||
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true), |
|||
Name = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: false), |
|||
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: true), |
|||
ConcurrencyStamp = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: true) |
|||
}, |
|||
constraints: table => |
|||
{ |
|||
table.PrimaryKey("PK_AbpBlobContainers", x => x.Id); |
|||
}); |
|||
|
|||
migrationBuilder.CreateTable( |
|||
name: "AbpBlobs", |
|||
columns: table => new |
|||
{ |
|||
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false), |
|||
ContainerId = table.Column<Guid>(type: "uniqueidentifier", nullable: false), |
|||
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true), |
|||
Name = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: false), |
|||
Content = table.Column<byte[]>(type: "varbinary(max)", maxLength: 2147483647, nullable: true), |
|||
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: true), |
|||
ConcurrencyStamp = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: true) |
|||
}, |
|||
constraints: table => |
|||
{ |
|||
table.PrimaryKey("PK_AbpBlobs", x => x.Id); |
|||
table.ForeignKey( |
|||
name: "FK_AbpBlobs_AbpBlobContainers_ContainerId", |
|||
column: x => x.ContainerId, |
|||
principalTable: "AbpBlobContainers", |
|||
principalColumn: "Id", |
|||
onDelete: ReferentialAction.Cascade); |
|||
}); |
|||
|
|||
migrationBuilder.CreateIndex( |
|||
name: "IX_AbpBlobContainers_TenantId_Name", |
|||
table: "AbpBlobContainers", |
|||
columns: new[] { "TenantId", "Name" }); |
|||
|
|||
migrationBuilder.CreateIndex( |
|||
name: "IX_AbpBlobs_ContainerId", |
|||
table: "AbpBlobs", |
|||
column: "ContainerId"); |
|||
|
|||
migrationBuilder.CreateIndex( |
|||
name: "IX_AbpBlobs_TenantId_ContainerId_Name", |
|||
table: "AbpBlobs", |
|||
columns: new[] { "TenantId", "ContainerId", "Name" }); |
|||
} |
|||
|
|||
protected override void Down(MigrationBuilder migrationBuilder) |
|||
{ |
|||
migrationBuilder.DropTable( |
|||
name: "AbpBlobs"); |
|||
|
|||
migrationBuilder.DropTable( |
|||
name: "AbpBlobContainers"); |
|||
|
|||
migrationBuilder.AlterColumn<string>( |
|||
name: "Description", |
|||
table: "CmsPages", |
|||
type: "nvarchar(515)", |
|||
maxLength: 515, |
|||
nullable: true, |
|||
oldClrType: typeof(string), |
|||
oldType: "nvarchar(512)", |
|||
oldMaxLength: 512, |
|||
oldNullable: true); |
|||
} |
|||
} |
|||
} |
|||
@ -1,106 +0,0 @@ |
|||
using System; |
|||
using Microsoft.EntityFrameworkCore.Migrations; |
|||
|
|||
namespace Volo.CmsKit.Migrations |
|||
{ |
|||
public partial class UrlSlugToSlug : Migration |
|||
{ |
|||
protected override void Up(MigrationBuilder migrationBuilder) |
|||
{ |
|||
migrationBuilder.CreateTable( |
|||
name: "CmsBlogPosts", |
|||
columns: table => new |
|||
{ |
|||
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false), |
|||
BlogId = table.Column<Guid>(type: "uniqueidentifier", nullable: false), |
|||
Title = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: false), |
|||
Slug = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: false), |
|||
ShortDescription = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true), |
|||
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true), |
|||
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: true), |
|||
ConcurrencyStamp = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: true), |
|||
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false), |
|||
CreatorId = table.Column<Guid>(type: "uniqueidentifier", nullable: true), |
|||
LastModificationTime = table.Column<DateTime>(type: "datetime2", nullable: true), |
|||
LastModifierId = table.Column<Guid>(type: "uniqueidentifier", nullable: true), |
|||
IsDeleted = table.Column<bool>(type: "bit", nullable: false, defaultValue: false), |
|||
DeleterId = table.Column<Guid>(type: "uniqueidentifier", nullable: true), |
|||
DeletionTime = table.Column<DateTime>(type: "datetime2", nullable: true) |
|||
}, |
|||
constraints: table => |
|||
{ |
|||
table.PrimaryKey("PK_CmsBlogPosts", x => x.Id); |
|||
table.ForeignKey( |
|||
name: "FK_CmsBlogPosts_CmsUsers_CreatorId", |
|||
column: x => x.CreatorId, |
|||
principalTable: "CmsUsers", |
|||
principalColumn: "Id", |
|||
onDelete: ReferentialAction.Restrict); |
|||
table.ForeignKey( |
|||
name: "FK_CmsBlogPosts_CmsUsers_DeleterId", |
|||
column: x => x.DeleterId, |
|||
principalTable: "CmsUsers", |
|||
principalColumn: "Id", |
|||
onDelete: ReferentialAction.Restrict); |
|||
table.ForeignKey( |
|||
name: "FK_CmsBlogPosts_CmsUsers_LastModifierId", |
|||
column: x => x.LastModifierId, |
|||
principalTable: "CmsUsers", |
|||
principalColumn: "Id", |
|||
onDelete: ReferentialAction.Restrict); |
|||
}); |
|||
|
|||
migrationBuilder.CreateTable( |
|||
name: "CmsBlogs", |
|||
columns: table => new |
|||
{ |
|||
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false), |
|||
Name = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: false), |
|||
Slug = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: false), |
|||
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true), |
|||
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: true), |
|||
ConcurrencyStamp = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: true), |
|||
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false), |
|||
CreatorId = table.Column<Guid>(type: "uniqueidentifier", nullable: true), |
|||
LastModificationTime = table.Column<DateTime>(type: "datetime2", nullable: true), |
|||
LastModifierId = table.Column<Guid>(type: "uniqueidentifier", nullable: true), |
|||
IsDeleted = table.Column<bool>(type: "bit", nullable: false, defaultValue: false), |
|||
DeleterId = table.Column<Guid>(type: "uniqueidentifier", nullable: true), |
|||
DeletionTime = table.Column<DateTime>(type: "datetime2", nullable: true) |
|||
}, |
|||
constraints: table => |
|||
{ |
|||
table.PrimaryKey("PK_CmsBlogs", x => x.Id); |
|||
}); |
|||
|
|||
migrationBuilder.CreateIndex( |
|||
name: "IX_CmsBlogPosts_CreatorId", |
|||
table: "CmsBlogPosts", |
|||
column: "CreatorId"); |
|||
|
|||
migrationBuilder.CreateIndex( |
|||
name: "IX_CmsBlogPosts_DeleterId", |
|||
table: "CmsBlogPosts", |
|||
column: "DeleterId"); |
|||
|
|||
migrationBuilder.CreateIndex( |
|||
name: "IX_CmsBlogPosts_LastModifierId", |
|||
table: "CmsBlogPosts", |
|||
column: "LastModifierId"); |
|||
|
|||
migrationBuilder.CreateIndex( |
|||
name: "IX_CmsBlogPosts_Slug_BlogId", |
|||
table: "CmsBlogPosts", |
|||
columns: new[] { "Slug", "BlogId" }); |
|||
} |
|||
|
|||
protected override void Down(MigrationBuilder migrationBuilder) |
|||
{ |
|||
migrationBuilder.DropTable( |
|||
name: "CmsBlogPosts"); |
|||
|
|||
migrationBuilder.DropTable( |
|||
name: "CmsBlogs"); |
|||
} |
|||
} |
|||
} |
|||
@ -1,73 +0,0 @@ |
|||
using System; |
|||
using Microsoft.EntityFrameworkCore.Migrations; |
|||
|
|||
namespace Volo.CmsKit.Migrations |
|||
{ |
|||
public partial class Added_Media : Migration |
|||
{ |
|||
protected override void Up(MigrationBuilder migrationBuilder) |
|||
{ |
|||
migrationBuilder.DropTable( |
|||
name: "CmsPages"); |
|||
|
|||
migrationBuilder.CreateTable( |
|||
name: "CmsMediaDescriptors", |
|||
columns: table => new |
|||
{ |
|||
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false), |
|||
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true), |
|||
Name = table.Column<string>(type: "nvarchar(255)", maxLength: 255, nullable: false), |
|||
MimeType = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: false), |
|||
Size = table.Column<long>(type: "bigint", maxLength: 2147483647, nullable: false), |
|||
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: true), |
|||
ConcurrencyStamp = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: true), |
|||
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false), |
|||
CreatorId = table.Column<Guid>(type: "uniqueidentifier", nullable: true), |
|||
LastModificationTime = table.Column<DateTime>(type: "datetime2", nullable: true), |
|||
LastModifierId = table.Column<Guid>(type: "uniqueidentifier", nullable: true), |
|||
IsDeleted = table.Column<bool>(type: "bit", nullable: false, defaultValue: false), |
|||
DeleterId = table.Column<Guid>(type: "uniqueidentifier", nullable: true), |
|||
DeletionTime = table.Column<DateTime>(type: "datetime2", nullable: true) |
|||
}, |
|||
constraints: table => |
|||
{ |
|||
table.PrimaryKey("PK_CmsMediaDescriptors", x => x.Id); |
|||
}); |
|||
} |
|||
|
|||
protected override void Down(MigrationBuilder migrationBuilder) |
|||
{ |
|||
migrationBuilder.DropTable( |
|||
name: "CmsMediaDescriptors"); |
|||
|
|||
migrationBuilder.CreateTable( |
|||
name: "CmsPages", |
|||
columns: table => new |
|||
{ |
|||
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false), |
|||
ConcurrencyStamp = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: true), |
|||
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false), |
|||
CreatorId = table.Column<Guid>(type: "uniqueidentifier", nullable: true), |
|||
DeleterId = table.Column<Guid>(type: "uniqueidentifier", nullable: true), |
|||
DeletionTime = table.Column<DateTime>(type: "datetime2", nullable: true), |
|||
Description = table.Column<string>(type: "nvarchar(512)", maxLength: 512, nullable: true), |
|||
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: true), |
|||
IsDeleted = table.Column<bool>(type: "bit", nullable: false, defaultValue: false), |
|||
LastModificationTime = table.Column<DateTime>(type: "datetime2", nullable: true), |
|||
LastModifierId = table.Column<Guid>(type: "uniqueidentifier", nullable: true), |
|||
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true), |
|||
Title = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: false), |
|||
Url = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: false) |
|||
}, |
|||
constraints: table => |
|||
{ |
|||
table.PrimaryKey("PK_CmsPages", x => x.Id); |
|||
}); |
|||
|
|||
migrationBuilder.CreateIndex( |
|||
name: "IX_CmsPages_TenantId_Url", |
|||
table: "CmsPages", |
|||
columns: new[] { "TenantId", "Url" }); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,23 @@ |
|||
using Microsoft.EntityFrameworkCore.Migrations; |
|||
|
|||
namespace Volo.CmsKit.Migrations |
|||
{ |
|||
public partial class BlogFeatureEnabledColumnRename : Migration |
|||
{ |
|||
protected override void Up(MigrationBuilder migrationBuilder) |
|||
{ |
|||
migrationBuilder.RenameColumn( |
|||
name: "Enabled", |
|||
table: "CmsBlogFeatures", |
|||
newName: "IsEnabled"); |
|||
} |
|||
|
|||
protected override void Down(MigrationBuilder migrationBuilder) |
|||
{ |
|||
migrationBuilder.RenameColumn( |
|||
name: "IsEnabled", |
|||
table: "CmsBlogFeatures", |
|||
newName: "Enabled"); |
|||
} |
|||
} |
|||
} |
|||
File diff suppressed because it is too large
@ -0,0 +1,11 @@ |
|||
using System.ComponentModel.DataAnnotations; |
|||
|
|||
namespace Volo.CmsKit.Admin.Blogs |
|||
{ |
|||
public class BlogFeatureInputDto |
|||
{ |
|||
[Required] |
|||
public string FeatureName { get; set; } |
|||
public bool IsEnabled { get; set; } |
|||
} |
|||
} |
|||
@ -1,10 +0,0 @@ |
|||
using System; |
|||
|
|||
namespace Volo.CmsKit.Admin.Blogs |
|||
{ |
|||
public class BlogLookupDto |
|||
{ |
|||
public Guid Id { get; set; } |
|||
public string Name { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,16 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Text; |
|||
using System.Threading.Tasks; |
|||
using Volo.CmsKit.Blogs; |
|||
|
|||
namespace Volo.CmsKit.Admin.Blogs |
|||
{ |
|||
public interface IBlogFeatureAdminAppService |
|||
{ |
|||
Task SetAsync(Guid blogId, BlogFeatureInputDto dto); |
|||
|
|||
Task<List<BlogFeatureDto>> GetListAsync(Guid blogId); |
|||
} |
|||
} |
|||
@ -0,0 +1,24 @@ |
|||
using System.ComponentModel.DataAnnotations; |
|||
using Volo.Abp.Validation; |
|||
using Volo.CmsKit.Blogs; |
|||
|
|||
namespace Volo.CmsKit.Admin.Blogs |
|||
{ |
|||
public class UpdateBlogPostDto |
|||
{ |
|||
[Required] |
|||
[DynamicMaxLength(typeof(BlogPostConsts), nameof(BlogPostConsts.MaxTitleLength))] |
|||
public string Title { get; set; } |
|||
|
|||
[Required] |
|||
[DynamicStringLength( |
|||
typeof(BlogPostConsts), |
|||
nameof(BlogPostConsts.MaxSlugLength), |
|||
nameof(BlogPostConsts.MinSlugLength))] |
|||
public string Slug { get; set; } |
|||
|
|||
[DynamicMaxLength(typeof(BlogPostConsts), nameof(BlogPostConsts.MaxShortDescriptionLength))] |
|||
public string ShortDescription { get; set; } |
|||
|
|||
} |
|||
} |
|||
@ -0,0 +1,15 @@ |
|||
using System; |
|||
|
|||
namespace Volo.CmsKit.Admin.Comments |
|||
{ |
|||
public class CmsUserDto |
|||
{ |
|||
public Guid Id { get; set; } |
|||
|
|||
public string UserName { get; set; } |
|||
|
|||
public string Name { get; set; } |
|||
|
|||
public string Surname { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,21 @@ |
|||
using System; |
|||
|
|||
namespace Volo.CmsKit.Admin.Comments |
|||
{ |
|||
public class CommentDto |
|||
{ |
|||
public Guid Id { get; set; } |
|||
|
|||
public string EntityType { get; set; } |
|||
|
|||
public string EntityId { get; set; } |
|||
|
|||
public string Text { get; set; } |
|||
|
|||
public Guid? RepliedCommentId { get; set; } |
|||
|
|||
public Guid CreatorId { get; set; } |
|||
|
|||
public DateTime CreationTime { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,22 @@ |
|||
using System; |
|||
using Volo.Abp.Application.Dtos; |
|||
|
|||
namespace Volo.CmsKit.Admin.Comments |
|||
{ |
|||
public class CommentGetListInput : PagedAndSortedResultRequestDto |
|||
{ |
|||
public string EntityType { get; set; } |
|||
|
|||
public string EntityId { get; set; } |
|||
|
|||
public string Text { get; set; } |
|||
|
|||
public Guid? RepliedCommentId { get; set; } |
|||
|
|||
public string Author { get; set; } |
|||
|
|||
public DateTime? CreationStartDate { get; set; } |
|||
|
|||
public DateTime? CreationEndDate { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,25 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using Volo.CmsKit.Users; |
|||
|
|||
namespace Volo.CmsKit.Admin.Comments |
|||
{ |
|||
public class CommentWithAuthorDto |
|||
{ |
|||
public Guid Id { get; set; } |
|||
|
|||
public string EntityType { get; set; } |
|||
|
|||
public string EntityId { get; set; } |
|||
|
|||
public string Text { get; set; } |
|||
|
|||
public Guid? RepliedCommentId { get; set; } |
|||
|
|||
public Guid CreatorId { get; set; } |
|||
|
|||
public DateTime CreationTime { get; set; } |
|||
|
|||
public CmsUserDto Author { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,16 @@ |
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.Application.Dtos; |
|||
using Volo.Abp.Application.Services; |
|||
|
|||
namespace Volo.CmsKit.Admin.Comments |
|||
{ |
|||
public interface ICommentAdminAppService : IApplicationService |
|||
{ |
|||
Task<PagedResultDto<CommentWithAuthorDto>> GetListAsync(CommentGetListInput input); |
|||
|
|||
Task<CommentWithAuthorDto> GetAsync(Guid id); |
|||
|
|||
Task DeleteAsync(Guid id); |
|||
} |
|||
} |
|||
@ -0,0 +1,49 @@ |
|||
using Microsoft.AspNetCore.Authorization; |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Text; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.EventBus.Distributed; |
|||
using Volo.Abp.GlobalFeatures; |
|||
using Volo.CmsKit.Admin.Blogs; |
|||
using Volo.CmsKit.Blogs; |
|||
using Volo.CmsKit.GlobalFeatures; |
|||
using Volo.CmsKit.Permissions; |
|||
|
|||
namespace Volo.CmsKit.Admin.Blogs |
|||
{ |
|||
[RequiresGlobalFeature(typeof(BlogsFeature))] |
|||
public class BlogFeatureAdminAppService : CmsKitAdminAppServiceBase, IBlogFeatureAdminAppService |
|||
{ |
|||
protected IBlogFeatureRepository BlogFeatureRepository { get; } |
|||
|
|||
protected IBlogFeatureManager BlogFeatureManager { get; } |
|||
|
|||
protected IDistributedEventBus EventBus { get; } |
|||
|
|||
public BlogFeatureAdminAppService( |
|||
IBlogFeatureRepository blogFeatureRepository, |
|||
IBlogFeatureManager blogFeatureManager, |
|||
IDistributedEventBus eventBus) |
|||
{ |
|||
BlogFeatureRepository = blogFeatureRepository; |
|||
BlogFeatureManager = blogFeatureManager; |
|||
EventBus = eventBus; |
|||
} |
|||
|
|||
[Authorize(CmsKitAdminPermissions.Blogs.Features)] |
|||
public async Task<List<BlogFeatureDto>> GetListAsync(Guid blogId) |
|||
{ |
|||
var blogFeatures = await BlogFeatureManager.GetListAsync(blogId); |
|||
|
|||
return ObjectMapper.Map<List<BlogFeature>, List<BlogFeatureDto>>(blogFeatures); |
|||
} |
|||
|
|||
[Authorize(CmsKitAdminPermissions.Blogs.Features)] |
|||
public Task SetAsync(Guid blogId, BlogFeatureInputDto dto) |
|||
{ |
|||
return BlogFeatureManager.SetAsync(blogId, dto.FeatureName, dto.IsEnabled); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,77 @@ |
|||
using System; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using Microsoft.AspNetCore.Authorization; |
|||
using Volo.Abp.Application.Dtos; |
|||
using Volo.Abp.GlobalFeatures; |
|||
using Volo.CmsKit.Comments; |
|||
using Volo.CmsKit.GlobalFeatures; |
|||
using Volo.CmsKit.Permissions; |
|||
using Volo.CmsKit.Users; |
|||
|
|||
namespace Volo.CmsKit.Admin.Comments |
|||
{ |
|||
[RequiresGlobalFeature(typeof(CommentsFeature))] |
|||
[Authorize(CmsKitAdminPermissions.Comments.Default)] |
|||
public class CommentAdminAppService : CmsKitAdminAppServiceBase, ICommentAdminAppService |
|||
{ |
|||
protected ICommentRepository CommentRepository { get; } |
|||
|
|||
public CommentAdminAppService(ICommentRepository commentRepository) |
|||
{ |
|||
CommentRepository = commentRepository; |
|||
} |
|||
|
|||
public virtual async Task<PagedResultDto<CommentWithAuthorDto>> GetListAsync(CommentGetListInput input) |
|||
{ |
|||
var totalCount = await CommentRepository.GetCountAsync( |
|||
input.Text, |
|||
input.EntityType, |
|||
input.EntityId, |
|||
input.RepliedCommentId, |
|||
input.Author, |
|||
input.CreationStartDate, |
|||
input.CreationEndDate); |
|||
|
|||
var comments = await CommentRepository.GetListAsync( |
|||
input.Text, |
|||
input.EntityType, |
|||
input.EntityId, |
|||
input.RepliedCommentId, |
|||
input.Author, |
|||
input.CreationStartDate, |
|||
input.CreationEndDate, |
|||
input.Sorting, |
|||
input.MaxResultCount, |
|||
input.SkipCount |
|||
); |
|||
|
|||
var dtos = comments.Select(queryResultItem => |
|||
{ |
|||
var dto = ObjectMapper.Map<Comment, CommentWithAuthorDto>(queryResultItem.Comment); |
|||
dto.Author = ObjectMapper.Map<CmsUser, CmsUserDto>(queryResultItem.Author); |
|||
|
|||
return dto; |
|||
}).ToList(); |
|||
|
|||
return new PagedResultDto<CommentWithAuthorDto>(totalCount, dtos); |
|||
} |
|||
|
|||
public virtual async Task<CommentWithAuthorDto> GetAsync(Guid id) |
|||
{ |
|||
var comment = await CommentRepository.GetWithAuthorAsync(id); |
|||
|
|||
var dto = ObjectMapper.Map<Comment, CommentWithAuthorDto>(comment.Comment); |
|||
dto.Author = ObjectMapper.Map<CmsUser, CmsUserDto>(comment.Author); |
|||
|
|||
return dto; |
|||
} |
|||
|
|||
[Authorize(CmsKitAdminPermissions.Comments.Delete)] |
|||
public virtual async Task DeleteAsync(Guid id) |
|||
{ |
|||
var comment = await CommentRepository.GetAsync(id); |
|||
await CommentRepository.DeleteWithRepliesAsync(comment); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,40 @@ |
|||
using Microsoft.AspNetCore.Authorization; |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp; |
|||
using Volo.Abp.GlobalFeatures; |
|||
using Volo.CmsKit.Blogs; |
|||
using Volo.CmsKit.GlobalFeatures; |
|||
using Volo.CmsKit.Permissions; |
|||
|
|||
namespace Volo.CmsKit.Admin.Blogs |
|||
{ |
|||
[RequiresGlobalFeature(typeof(BlogsFeature))] |
|||
[RemoteService(Name = CmsKitCommonRemoteServiceConsts.RemoteServiceName)] |
|||
[Area("cms-kit")] |
|||
[Authorize(CmsKitAdminPermissions.Blogs.Features)] |
|||
[Route("api/cms-kit-admin/blogs/{blogId}/features")] |
|||
public class BlogFeatureAdminController : CmsKitAdminController, IBlogFeatureAdminAppService |
|||
{ |
|||
protected IBlogFeatureAdminAppService BlogFeatureAdminAppService { get; } |
|||
|
|||
public BlogFeatureAdminController(IBlogFeatureAdminAppService blogFeatureAdminAppService) |
|||
{ |
|||
BlogFeatureAdminAppService = blogFeatureAdminAppService; |
|||
} |
|||
|
|||
[HttpGet] |
|||
public Task<List<BlogFeatureDto>> GetListAsync(Guid blogId) |
|||
{ |
|||
return BlogFeatureAdminAppService.GetListAsync(blogId); |
|||
} |
|||
|
|||
[HttpPut] |
|||
public Task SetAsync(Guid blogId, BlogFeatureInputDto dto) |
|||
{ |
|||
return BlogFeatureAdminAppService.SetAsync(blogId, dto); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,48 @@ |
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using Microsoft.AspNetCore.Authorization; |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using Volo.Abp; |
|||
using Volo.Abp.Application.Dtos; |
|||
using Volo.Abp.GlobalFeatures; |
|||
using Volo.CmsKit.GlobalFeatures; |
|||
using Volo.CmsKit.Permissions; |
|||
|
|||
namespace Volo.CmsKit.Admin.Comments |
|||
{ |
|||
[Authorize(CmsKitAdminPermissions.Comments.Default)] |
|||
[RequiresGlobalFeature(typeof(CommentsFeature))] |
|||
[RemoteService(Name = CmsKitCommonRemoteServiceConsts.RemoteServiceName)] |
|||
[Area("cms-kit")] |
|||
[Route("api/cms-kit-admin/comments")] |
|||
public class CommentAdminController : CmsKitAdminController, ICommentAdminAppService |
|||
{ |
|||
protected ICommentAdminAppService CommentAdminAppService { get; } |
|||
|
|||
public CommentAdminController(ICommentAdminAppService commentAdminAppService) |
|||
{ |
|||
CommentAdminAppService = commentAdminAppService; |
|||
} |
|||
|
|||
[HttpGet] |
|||
public virtual Task<PagedResultDto<CommentWithAuthorDto>> GetListAsync(CommentGetListInput input) |
|||
{ |
|||
return CommentAdminAppService.GetListAsync(input); |
|||
} |
|||
|
|||
[HttpGet] |
|||
[Route("{id}")] |
|||
public virtual Task<CommentWithAuthorDto> GetAsync(Guid id) |
|||
{ |
|||
return CommentAdminAppService.GetAsync(id); |
|||
} |
|||
|
|||
[HttpDelete] |
|||
[Route("{id}")] |
|||
[Authorize(CmsKitAdminPermissions.Comments.Delete)] |
|||
public virtual Task DeleteAsync(Guid id) |
|||
{ |
|||
return CommentAdminAppService.DeleteAsync(id); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,11 @@ |
|||
using System; |
|||
using Volo.Abp.Application.Dtos; |
|||
|
|||
namespace Volo.CmsKit.Blogs |
|||
{ |
|||
public class BlogFeatureDto : EntityDto<Guid> |
|||
{ |
|||
public string FeatureName { get; set; } |
|||
public bool IsEnabled { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,10 @@ |
|||
using System; |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace Volo.CmsKit.Blogs |
|||
{ |
|||
public interface IBlogFeatureAppService |
|||
{ |
|||
Task<BlogFeatureDto> GetOrDefaultAsync(Guid blogId, string featureName); |
|||
} |
|||
} |
|||
@ -0,0 +1,14 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Text; |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace Volo.CmsKit.Blogs |
|||
{ |
|||
public interface IBlogFeatureCacheManager |
|||
{ |
|||
Task<BlogFeatureDto> AddOrGetAsync(Guid blogId, string featureName, Func<Task<BlogFeatureDto>> factory); |
|||
Task ClearAsync(Guid blogId, string featureName); |
|||
} |
|||
} |
|||
@ -1,18 +1,19 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<Import Project="..\..\..\..\common.props" /> |
|||
<Import Project="..\..\..\..\configureawait.props" /> |
|||
<Import Project="..\..\..\..\common.props" /> |
|||
<Import Project="..\..\..\..\configureawait.props" /> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>netstandard2.0</TargetFramework> |
|||
<RootNamespace /> |
|||
</PropertyGroup> |
|||
<PropertyGroup> |
|||
<TargetFramework>netstandard2.0</TargetFramework> |
|||
<RootNamespace /> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.AutoMapper\Volo.Abp.AutoMapper.csproj" /> |
|||
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.Ddd.Application\Volo.Abp.Ddd.Application.csproj" /> |
|||
<ProjectReference Include="..\Volo.CmsKit.Common.Application.Contracts\Volo.CmsKit.Common.Application.Contracts.csproj" /> |
|||
<ProjectReference Include="..\Volo.CmsKit.Domain\Volo.CmsKit.Domain.csproj" /> |
|||
</ItemGroup> |
|||
<ItemGroup> |
|||
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.AutoMapper\Volo.Abp.AutoMapper.csproj" /> |
|||
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.Ddd.Application\Volo.Abp.Ddd.Application.csproj" /> |
|||
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.Caching\Volo.Abp.Caching.csproj" /> |
|||
<ProjectReference Include="..\Volo.CmsKit.Common.Application.Contracts\Volo.CmsKit.Common.Application.Contracts.csproj" /> |
|||
<ProjectReference Include="..\Volo.CmsKit.Domain\Volo.CmsKit.Domain.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
|
|||
@ -0,0 +1,41 @@ |
|||
using Microsoft.Extensions.Caching.Distributed; |
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.Caching; |
|||
using Volo.Abp.EventBus.Distributed; |
|||
|
|||
namespace Volo.CmsKit.Blogs |
|||
{ |
|||
public class BlogFeatureAppService : CmsKitAppServiceBase, IBlogFeatureAppService |
|||
{ |
|||
protected virtual IBlogFeatureRepository BlogFeatureRepository { get; } |
|||
|
|||
protected virtual IBlogFeatureCacheManager BlogFeatureCacheManager { get; } |
|||
|
|||
public BlogFeatureAppService( |
|||
IBlogFeatureRepository blogFeatureRepository, |
|||
IBlogFeatureCacheManager blogFeatureCacheManager) |
|||
{ |
|||
BlogFeatureRepository = blogFeatureRepository; |
|||
BlogFeatureCacheManager = blogFeatureCacheManager; |
|||
} |
|||
|
|||
public virtual Task<BlogFeatureDto> GetOrDefaultAsync(Guid blogId, string featureName) |
|||
{ |
|||
return BlogFeatureCacheManager |
|||
.AddOrGetAsync( |
|||
blogId, |
|||
featureName, |
|||
()=> GetOrDefaultFroRepositoryAsync(blogId, featureName) |
|||
); |
|||
} |
|||
|
|||
protected virtual async Task<BlogFeatureDto> GetOrDefaultFroRepositoryAsync(Guid blogId, string featureName) |
|||
{ |
|||
var feature = await BlogFeatureRepository.FindAsync(blogId, featureName); |
|||
var blogFeature = feature ?? new BlogFeature(blogId, featureName); |
|||
|
|||
return ObjectMapper.Map<BlogFeature, BlogFeatureDto>(blogFeature); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,46 @@ |
|||
using JetBrains.Annotations; |
|||
using Microsoft.Extensions.Caching.Distributed; |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Text; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp; |
|||
using Volo.Abp.Caching; |
|||
using Volo.Abp.DependencyInjection; |
|||
|
|||
namespace Volo.CmsKit.Blogs |
|||
{ |
|||
public class BlogFeatureCacheManager : IBlogFeatureCacheManager, ITransientDependency |
|||
{ |
|||
protected IDistributedCache<BlogFeatureDto> Cache { get; } |
|||
|
|||
public BlogFeatureCacheManager(IDistributedCache<BlogFeatureDto> cache) |
|||
{ |
|||
Cache = cache; |
|||
} |
|||
|
|||
public async Task<BlogFeatureDto> AddOrGetAsync(Guid blogId, string featureName, Func<Task<BlogFeatureDto>> factory) |
|||
{ |
|||
return await Cache.GetOrAddAsync( |
|||
GetCacheKey(blogId, featureName), |
|||
factory, |
|||
() => new DistributedCacheEntryOptions |
|||
{ |
|||
AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(1) |
|||
}); |
|||
} |
|||
|
|||
public Task ClearAsync(Guid blogId, string featureName) |
|||
{ |
|||
return Cache.RemoveAsync(GetCacheKey(blogId, featureName)); |
|||
} |
|||
|
|||
private string GetCacheKey(Guid blogId, [NotNull] string featureName) |
|||
{ |
|||
Check.NotNullOrWhiteSpace(featureName, nameof(featureName)); |
|||
|
|||
return $"{blogId}_{featureName}"; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,22 @@ |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.Caching; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.EventBus.Distributed; |
|||
|
|||
namespace Volo.CmsKit.Blogs |
|||
{ |
|||
public class BlogFeatureChangedHandler : IDistributedEventHandler<BlogFeatureChangedEto>, ITransientDependency |
|||
{ |
|||
protected IDistributedCache<BlogFeatureDto> Cache { get; } |
|||
|
|||
public BlogFeatureChangedHandler(IDistributedCache<BlogFeatureDto> cache) |
|||
{ |
|||
Cache = cache; |
|||
} |
|||
|
|||
public async Task HandleEventAsync(BlogFeatureChangedEto eventData) |
|||
{ |
|||
await Cache.RemoveAsync($"{eventData.BlogId}_{eventData.FeatureName}"); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,31 @@ |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp; |
|||
using Volo.Abp.GlobalFeatures; |
|||
using Volo.CmsKit.Blogs; |
|||
using Volo.CmsKit.GlobalFeatures; |
|||
|
|||
namespace Volo.CmsKit.Blogs |
|||
{ |
|||
[RequiresGlobalFeature(typeof(BlogsFeature))] |
|||
[RemoteService(Name = CmsKitCommonRemoteServiceConsts.RemoteServiceName)] |
|||
[Area("cms-kit")] |
|||
[Route("api/cms-kit/blogs/{blogId}/features")] |
|||
public class BlogFeatureController : CmsKitControllerBase, IBlogFeatureAppService |
|||
{ |
|||
protected IBlogFeatureAppService BlogFeatureAppService { get; } |
|||
|
|||
public BlogFeatureController(IBlogFeatureAppService blogFeatureAppService) |
|||
{ |
|||
BlogFeatureAppService = blogFeatureAppService; |
|||
} |
|||
|
|||
[HttpGet] |
|||
[Route("{featureName}")] |
|||
public Task<BlogFeatureDto> GetOrDefaultAsync(Guid blogId, string featureName) |
|||
{ |
|||
return BlogFeatureAppService.GetOrDefaultAsync(blogId, featureName); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,17 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Text; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.EventBus; |
|||
|
|||
namespace Volo.CmsKit.Blogs |
|||
{ |
|||
[EventName("CmsKit.Blogs.BlogFeature.Changed")] |
|||
public class BlogFeatureChangedEto |
|||
{ |
|||
public Guid BlogId { get; set; } |
|||
public string FeatureName { get; set; } |
|||
public bool IsEnabled { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,7 @@ |
|||
namespace Volo.CmsKit.Blogs |
|||
{ |
|||
public static class BlogFeatureConsts |
|||
{ |
|||
public const int MaxFeatureNameLenth = 64; |
|||
} |
|||
} |
|||
@ -0,0 +1,28 @@ |
|||
using JetBrains.Annotations; |
|||
using System; |
|||
using Volo.Abp; |
|||
using Volo.Abp.Domain.Entities.Auditing; |
|||
|
|||
namespace Volo.CmsKit.Blogs |
|||
{ |
|||
public class BlogFeature : FullAuditedAggregateRoot<Guid>, IEquatable<BlogFeature> |
|||
{ |
|||
public Guid BlogId { get; protected set; } |
|||
|
|||
public string FeatureName { get; protected set; } |
|||
|
|||
public bool IsEnabled { get; set; } = true; |
|||
|
|||
public BlogFeature(Guid blogId, [NotNull] string featureName, bool isEnabled = true) |
|||
{ |
|||
BlogId = blogId; |
|||
FeatureName = Check.NotNullOrWhiteSpace(featureName, nameof(featureName)); |
|||
IsEnabled = isEnabled; |
|||
} |
|||
|
|||
public bool Equals(BlogFeature other) |
|||
{ |
|||
return BlogId == other?.BlogId && FeatureName == other?.FeatureName; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,67 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.Domain.Services; |
|||
using Volo.Abp.EventBus.Distributed; |
|||
using Volo.Abp.Uow; |
|||
|
|||
namespace Volo.CmsKit.Blogs |
|||
{ |
|||
public class BlogFeatureManager : DomainService, IBlogFeatureManager |
|||
{ |
|||
protected IBlogFeatureRepository BlogFeatureRepository { get; } |
|||
|
|||
protected IDefaultBlogFeatureProvider DefaultBlogFeatureProvider { get; } |
|||
|
|||
protected IUnitOfWorkManager UnitOfWorkManager { get; } |
|||
|
|||
protected IDistributedEventBus EventBus { get; } |
|||
|
|||
public BlogFeatureManager( |
|||
IBlogFeatureRepository blogFeatureRepository, |
|||
IDefaultBlogFeatureProvider defaultBlogFeatureProvider, |
|||
IUnitOfWorkManager unitOfWorkManager, |
|||
IDistributedEventBus eventBus) |
|||
{ |
|||
BlogFeatureRepository = blogFeatureRepository; |
|||
DefaultBlogFeatureProvider = defaultBlogFeatureProvider; |
|||
UnitOfWorkManager = unitOfWorkManager; |
|||
EventBus = eventBus; |
|||
} |
|||
|
|||
public async Task<List<BlogFeature>> GetListAsync(Guid blogId) |
|||
{ |
|||
var blogFeatures = await BlogFeatureRepository.GetListAsync(blogId); |
|||
|
|||
var defaultFeatures = await DefaultBlogFeatureProvider.GetDefaultFeaturesAsync(blogId); |
|||
|
|||
defaultFeatures.ForEach(x => blogFeatures.AddIfNotContains(x)); |
|||
|
|||
return blogFeatures; |
|||
} |
|||
|
|||
public async Task SetAsync(Guid blogId, string featureName, bool isEnabled) |
|||
{ |
|||
var blogFeature = await BlogFeatureRepository.FindAsync(blogId, featureName); |
|||
if (blogFeature == null) |
|||
{ |
|||
var newBlogFeature = new BlogFeature(blogId, featureName, isEnabled); |
|||
await BlogFeatureRepository.InsertAsync(newBlogFeature); |
|||
} |
|||
else |
|||
{ |
|||
blogFeature.IsEnabled = isEnabled; |
|||
await BlogFeatureRepository.UpdateAsync(blogFeature); |
|||
} |
|||
|
|||
await UnitOfWorkManager.Current.SaveChangesAsync(); |
|||
|
|||
await EventBus.PublishAsync(new BlogFeatureChangedEto |
|||
{ |
|||
BlogId = blogId, |
|||
FeatureName = featureName, |
|||
IsEnabled = isEnabled |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue