diff --git a/src/hosts/CRMCore.DBMigration.Console/Data/Migrations/CRMCore/20171216094333_InitDatabase.Designer.cs b/src/hosts/CRMCore.DBMigration.Console/Data/Migrations/CRMCore/20180112095254_InitDatabase.Designer.cs similarity index 95% rename from src/hosts/CRMCore.DBMigration.Console/Data/Migrations/CRMCore/20171216094333_InitDatabase.Designer.cs rename to src/hosts/CRMCore.DBMigration.Console/Data/Migrations/CRMCore/20180112095254_InitDatabase.Designer.cs index 43db0ea..41416bb 100644 --- a/src/hosts/CRMCore.DBMigration.Console/Data/Migrations/CRMCore/20171216094333_InitDatabase.Designer.cs +++ b/src/hosts/CRMCore.DBMigration.Console/Data/Migrations/CRMCore/20180112095254_InitDatabase.Designer.cs @@ -12,7 +12,7 @@ namespace CRMCore.DBMigration.Console.Data.Migrations.CRMCore { [DbContext(typeof(ApplicationDbContext))] - [Migration("20171216094333_InitDatabase")] + [Migration("20180112095254_InitDatabase")] partial class InitDatabase { protected override void BuildTargetModel(ModelBuilder modelBuilder) @@ -22,6 +22,24 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) .HasAnnotation("ProductVersion", "2.0.1-rtm-125") .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + modelBuilder.Entity("CRMCore.Module.CustomCollection.Entity.Morphism", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ContentStr"); + + b.Property("Created"); + + b.Property("SchemaStr"); + + b.Property("Updated"); + + b.HasKey("Id"); + + b.ToTable("crm_Morphisms"); + }); + modelBuilder.Entity("CRMCore.Module.Entities.Identity.ApplicationRole", b => { b.Property("Id") @@ -101,24 +119,6 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.ToTable("AspNetUsers"); }); - modelBuilder.Entity("CRMCore.Module.CustomCollection.Entity.Morphism", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ContentStr"); - - b.Property("Created"); - - b.Property("SchemaStr"); - - b.Property("Updated"); - - b.HasKey("Id"); - - b.ToTable("crm_Morphisms"); - }); - modelBuilder.Entity("CRMCore.Module.Task.Domain.Task", b => { b.Property("Id") @@ -133,12 +133,18 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Property("Name") .IsRequired(); + b.Property("ParentId"); + + b.Property("TaskId"); + b.Property("TaskStatus"); b.Property("Updated"); b.HasKey("Id"); + b.HasIndex("TaskId"); + b.ToTable("crm_Tasks"); }); @@ -223,6 +229,13 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.ToTable("AspNetUserTokens"); }); + modelBuilder.Entity("CRMCore.Module.Task.Domain.Task", b => + { + b.HasOne("CRMCore.Module.Task.Domain.Task") + .WithMany("SubTasks") + .HasForeignKey("TaskId"); + }); + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => { b.HasOne("CRMCore.Module.Entities.Identity.ApplicationRole") diff --git a/src/hosts/CRMCore.DBMigration.Console/Data/Migrations/CRMCore/20171216094333_InitDatabase.cs b/src/hosts/CRMCore.DBMigration.Console/Data/Migrations/CRMCore/20180112095254_InitDatabase.cs similarity index 94% rename from src/hosts/CRMCore.DBMigration.Console/Data/Migrations/CRMCore/20171216094333_InitDatabase.cs rename to src/hosts/CRMCore.DBMigration.Console/Data/Migrations/CRMCore/20180112095254_InitDatabase.cs index 43b43ea..b8c075d 100644 --- a/src/hosts/CRMCore.DBMigration.Console/Data/Migrations/CRMCore/20171216094333_InitDatabase.cs +++ b/src/hosts/CRMCore.DBMigration.Console/Data/Migrations/CRMCore/20180112095254_InitDatabase.cs @@ -74,12 +74,20 @@ protected override void Up(MigrationBuilder migrationBuilder) CategoryType = table.Column(nullable: false), Created = table.Column(nullable: false), Name = table.Column(nullable: false), + ParentId = table.Column(nullable: true), + TaskId = table.Column(nullable: true), TaskStatus = table.Column(nullable: false), Updated = table.Column(nullable: false) }, constraints: table => { table.PrimaryKey("PK_crm_Tasks", x => x.Id); + table.ForeignKey( + name: "FK_crm_Tasks_crm_Tasks_TaskId", + column: x => x.TaskId, + principalTable: "crm_Tasks", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); }); migrationBuilder.CreateTable( @@ -226,6 +234,11 @@ protected override void Up(MigrationBuilder migrationBuilder) column: "NormalizedUserName", unique: true, filter: "[NormalizedUserName] IS NOT NULL"); + + migrationBuilder.CreateIndex( + name: "IX_crm_Tasks_TaskId", + table: "crm_Tasks", + column: "TaskId"); } protected override void Down(MigrationBuilder migrationBuilder) diff --git a/src/hosts/CRMCore.DBMigration.Console/Data/Migrations/CRMCore/ApplicationDbContextModelSnapshot.cs b/src/hosts/CRMCore.DBMigration.Console/Data/Migrations/CRMCore/ApplicationDbContextModelSnapshot.cs index c234636..ab52427 100644 --- a/src/hosts/CRMCore.DBMigration.Console/Data/Migrations/CRMCore/ApplicationDbContextModelSnapshot.cs +++ b/src/hosts/CRMCore.DBMigration.Console/Data/Migrations/CRMCore/ApplicationDbContextModelSnapshot.cs @@ -21,6 +21,24 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasAnnotation("ProductVersion", "2.0.1-rtm-125") .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + modelBuilder.Entity("CRMCore.Module.CustomCollection.Entity.Morphism", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ContentStr"); + + b.Property("Created"); + + b.Property("SchemaStr"); + + b.Property("Updated"); + + b.HasKey("Id"); + + b.ToTable("crm_Morphisms"); + }); + modelBuilder.Entity("CRMCore.Module.Entities.Identity.ApplicationRole", b => { b.Property("Id") @@ -100,24 +118,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("AspNetUsers"); }); - modelBuilder.Entity("CRMCore.Module.CustomCollection.Entity.Morphism", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ContentStr"); - - b.Property("Created"); - - b.Property("SchemaStr"); - - b.Property("Updated"); - - b.HasKey("Id"); - - b.ToTable("crm_Morphisms"); - }); - modelBuilder.Entity("CRMCore.Module.Task.Domain.Task", b => { b.Property("Id") @@ -132,12 +132,18 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("Name") .IsRequired(); + b.Property("ParentId"); + + b.Property("TaskId"); + b.Property("TaskStatus"); b.Property("Updated"); b.HasKey("Id"); + b.HasIndex("TaskId"); + b.ToTable("crm_Tasks"); }); @@ -222,6 +228,13 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("AspNetUserTokens"); }); + modelBuilder.Entity("CRMCore.Module.Task.Domain.Task", b => + { + b.HasOne("CRMCore.Module.Task.Domain.Task") + .WithMany("SubTasks") + .HasForeignKey("TaskId"); + }); + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => { b.HasOne("CRMCore.Module.Entities.Identity.ApplicationRole") diff --git a/src/modules/Base/CRMCore.Module.MvcCore/Extensions/ExtensionInfo.cs b/src/modules/Base/CRMCore.Module.MvcCore/Extensions/ExtensionInfo.cs index fb31bda..a8eca78 100644 --- a/src/modules/Base/CRMCore.Module.MvcCore/Extensions/ExtensionInfo.cs +++ b/src/modules/Base/CRMCore.Module.MvcCore/Extensions/ExtensionInfo.cs @@ -1,5 +1,4 @@ -using System; -using Microsoft.Extensions.FileProviders; +using Microsoft.Extensions.FileProviders; namespace CRMCore.Module.MvcCore.Extensions { diff --git a/src/modules/Base/CRMCore.Module.MvcCore/Extensions/IExtensionManager.cs b/src/modules/Base/CRMCore.Module.MvcCore/Extensions/IExtensionManager.cs index 9ec17e5..b388de8 100644 --- a/src/modules/Base/CRMCore.Module.MvcCore/Extensions/IExtensionManager.cs +++ b/src/modules/Base/CRMCore.Module.MvcCore/Extensions/IExtensionManager.cs @@ -1,5 +1,4 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; namespace CRMCore.Module.MvcCore.Extensions { diff --git a/src/modules/Base/CRMCore.Module.MvcCore/Extensions/ModularServiceCollectionExtensions.cs b/src/modules/Base/CRMCore.Module.MvcCore/Extensions/ModularServiceCollectionExtensions.cs index 2f73c17..faf49bd 100644 --- a/src/modules/Base/CRMCore.Module.MvcCore/Extensions/ModularServiceCollectionExtensions.cs +++ b/src/modules/Base/CRMCore.Module.MvcCore/Extensions/ModularServiceCollectionExtensions.cs @@ -29,7 +29,6 @@ public static IServiceCollection AddMvcModules(this IServiceCollection services) internal static void AddMvcModuleCoreServices(this IServiceCollection services) { services.AddSingleton(); - services.Replace(ServiceDescriptor.Scoped()); services.AddScoped(); services.AddScoped(); diff --git a/src/modules/Base/CRMCore.Module.MvcCore/IModularTenantRouteBuilder.cs b/src/modules/Base/CRMCore.Module.MvcCore/IModularTenantRouteBuilder.cs index c0a28d6..908022c 100644 --- a/src/modules/Base/CRMCore.Module.MvcCore/IModularTenantRouteBuilder.cs +++ b/src/modules/Base/CRMCore.Module.MvcCore/IModularTenantRouteBuilder.cs @@ -5,7 +5,6 @@ namespace CRMCore.Module.MvcCore public interface IModularTenantRouteBuilder { IRouteBuilder Build(); - void Configure(IRouteBuilder builder); } } diff --git a/src/modules/Base/CRMCore.Module.MvcCore/LocationExpander/DefaultViewLocationExpanderProvider.cs b/src/modules/Base/CRMCore.Module.MvcCore/LocationExpander/DefaultViewLocationExpanderProvider.cs index 7b8f8bc..73f89fe 100644 --- a/src/modules/Base/CRMCore.Module.MvcCore/LocationExpander/DefaultViewLocationExpanderProvider.cs +++ b/src/modules/Base/CRMCore.Module.MvcCore/LocationExpander/DefaultViewLocationExpanderProvider.cs @@ -14,7 +14,6 @@ public IEnumerable ExpandViewLocations(ViewLocationExpanderContext conte public void PopulateValues(ViewLocationExpanderContext context) { - } } } diff --git a/src/modules/Base/CRMCore.Module.MvcCore/Middlewares/ModularTenantRouterMiddleware.cs b/src/modules/Base/CRMCore.Module.MvcCore/Middlewares/ModularTenantRouterMiddleware.cs index e0efc42..26d3f9d 100644 --- a/src/modules/Base/CRMCore.Module.MvcCore/Middlewares/ModularTenantRouterMiddleware.cs +++ b/src/modules/Base/CRMCore.Module.MvcCore/Middlewares/ModularTenantRouterMiddleware.cs @@ -71,7 +71,6 @@ public RequestDelegate BuildTenantPipeline(IServiceProvider serviceProvider) startup.Configure(appBuilder, routeBuilder, serviceProvider); } - tenantRouteBuilder.Configure(routeBuilder); var router = routeBuilder.Build(); diff --git a/src/modules/Base/CRMCore.Module.MvcCore/RazorPages/DefaultModularPageRouteModelConvention.cs b/src/modules/Base/CRMCore.Module.MvcCore/RazorPages/DefaultModularPageRouteModelConvention.cs index 58fe5b6..204ac38 100644 --- a/src/modules/Base/CRMCore.Module.MvcCore/RazorPages/DefaultModularPageRouteModelConvention.cs +++ b/src/modules/Base/CRMCore.Module.MvcCore/RazorPages/DefaultModularPageRouteModelConvention.cs @@ -1,9 +1,8 @@ -using System; -using Microsoft.AspNetCore.Mvc.ApplicationModels; +using Microsoft.AspNetCore.Mvc.ApplicationModels; namespace CRMCore.Module.MvcCore.RazorPages { - public class DefaultModularPageRouteModelConvention: IPageRouteModelConvention + public class DefaultModularPageRouteModelConvention : IPageRouteModelConvention { public void Apply(PageRouteModel model) { @@ -16,7 +15,8 @@ public void Apply(PageRouteModel model) var pageIndex = template.LastIndexOf("/Pages/"); var moduleFolder = template.Substring(0, pageIndex); var moduleId = moduleFolder.Substring(moduleFolder.LastIndexOf("/") + 1); - //convert module format CRMCore.module.ModuleName to ModuleName + + //convert module format CRMCore..ModuleName to ModuleName moduleId = moduleId.Substring(moduleId.LastIndexOf(".") + 1); template = moduleId + template.Replace("/Pages/", "/").Substring(pageIndex); diff --git a/src/modules/Base/CRMCore.Module.MvcCore/RazorPages/ModularPageMvcCoreBuilderExtensions.cs b/src/modules/Base/CRMCore.Module.MvcCore/RazorPages/ModularPageMvcCoreBuilderExtensions.cs index f553700..ed1805a 100644 --- a/src/modules/Base/CRMCore.Module.MvcCore/RazorPages/ModularPageMvcCoreBuilderExtensions.cs +++ b/src/modules/Base/CRMCore.Module.MvcCore/RazorPages/ModularPageMvcCoreBuilderExtensions.cs @@ -1,5 +1,4 @@ -using System; -using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection; namespace CRMCore.Module.MvcCore.RazorPages { @@ -11,7 +10,7 @@ public static IMvcBuilder AddModularRazorPages(this IMvcBuilder builder) { options.RootDirectory = "/"; options.Conventions.Add(new DefaultModularPageRouteModelConvention()); - }); + }); return builder; } diff --git a/src/modules/Core/CRMCore.Module.Data/Extensions/OrderByExtension.cs b/src/modules/Core/CRMCore.Module.Data/Extensions/OrderByExtension.cs index 14979da..2c0a05e 100644 --- a/src/modules/Core/CRMCore.Module.Data/Extensions/OrderByExtension.cs +++ b/src/modules/Core/CRMCore.Module.Data/Extensions/OrderByExtension.cs @@ -38,6 +38,7 @@ public static IQueryable OrderByPropertyName(this IQueryable)result; } } diff --git a/src/modules/crm/CRMCore.Module.GraphQL/DbContextExtensions.cs b/src/modules/crm/CRMCore.Module.GraphQL/DbContextExtensions.cs index 7d90443..cc5a410 100644 --- a/src/modules/crm/CRMCore.Module.GraphQL/DbContextExtensions.cs +++ b/src/modules/crm/CRMCore.Module.GraphQL/DbContextExtensions.cs @@ -1,18 +1,77 @@ using Microsoft.EntityFrameworkCore; using System; using System.Linq; +using System.Linq.Expressions; using System.Reflection; namespace CRMCore.Module.GraphQL { public static class DbContextExtensions { - public static IQueryable Query(this DbContext context, string entityName) => - context.Query(context.Model.FindEntityType(entityName).ClrType); + public static IQueryable Query( + this DbContext context, + string entityName) => + context.Query(context.Model.FindEntityType(entityName).ClrType); - static readonly MethodInfo SetMethod = typeof(DbContext).GetMethod(nameof(DbContext.Set)); + public static IQueryable Query( + this DbContext context, + Type entityType) => + (IQueryable)SetMethod.MakeGenericMethod(entityType).Invoke(context, null); + + public static IQueryable Query( + this DbContext context, + string entityName, + string[] includes) + { + return context.DbSetQuery( + context.Model.FindEntityType(entityName).ClrType, + includes); + } + + public static IQueryable DbSetQuery( + this DbContext context, + Type entityType, + string[] includes) + { + return context.Set(entityType, includes); + } + + public static IQueryable Set(this DbContext context, + Type T, + string[] includes) + { + // Get the generic type definition + MethodInfo method = typeof(DbContext).GetMethod(nameof(DbContext.Set), BindingFlags.Public | BindingFlags.Instance); + + // Build a method with the specific type argument you're interested in + method = method.MakeGenericMethod(T); + + var dbSet = method.Invoke(context, null); - public static IQueryable Query(this DbContext context, Type entityType) => - (IQueryable)SetMethod.MakeGenericMethod(entityType).Invoke(context, null); + if (includes != null && includes.Count() > 0) + { + // https://stackoverflow.com/questions/38312437/can-a-string-based-include-alternative-be-created-in-entity-framework-core + MethodInfo includeMethodInfo = typeof(EntityFrameworkQueryableExtensions) + .GetTypeInfo() + .GetDeclaredMethods( + nameof(EntityFrameworkQueryableExtensions.Include)) + .FirstOrDefault(mi => mi.GetParameters().Any(pi => pi.Name == "navigationPropertyPath")); + + foreach (var include in includes) + { + var parameter = Expression.Parameter(T, "e"); + var property = Expression.PropertyOrField(parameter, include); + includeMethodInfo = includeMethodInfo.MakeGenericMethod(T, property.Type); + + dbSet = includeMethodInfo.Invoke( + null, + new object[] { dbSet, Expression.Lambda(property, new[] { parameter }) }); + } + } + + return dbSet as IQueryable; + } + + static readonly MethodInfo SetMethod = typeof(DbContext).GetMethod(nameof(DbContext.Set)); } } diff --git a/src/modules/crm/CRMCore.Module.GraphQL/GraphQLController.cs b/src/modules/crm/CRMCore.Module.GraphQL/GraphQLController.cs index c6ce3f6..945d7f4 100644 --- a/src/modules/crm/CRMCore.Module.GraphQL/GraphQLController.cs +++ b/src/modules/crm/CRMCore.Module.GraphQL/GraphQLController.cs @@ -32,7 +32,7 @@ public async Task Get([FromQuery] string query = "{ crm_Tasks_list(offse new ExecutionOptions() { Schema = graphQLSchema, - Query = query + Query = query } ).ConfigureAwait(false); diff --git a/src/modules/crm/CRMCore.Module.GraphQL/Models/DatabaseMetadata.cs b/src/modules/crm/CRMCore.Module.GraphQL/Models/DatabaseMetadata.cs index 1e58cd5..7c05fa6 100644 --- a/src/modules/crm/CRMCore.Module.GraphQL/Models/DatabaseMetadata.cs +++ b/src/modules/crm/CRMCore.Module.GraphQL/Models/DatabaseMetadata.cs @@ -59,7 +59,7 @@ private IReadOnlyList FetchTableMetaData() _tableNameLookup.InsertKeyName(tableName); } - + return metaTables; } @@ -77,6 +77,16 @@ private IReadOnlyList GetColumnsMetadata(IEntityType entityType) }); } + var navigations = entityType.GetNavigations(); + foreach (var nav in navigations) + { + tableColumns.Add(new ColumnMetadata + { + ColumnName = nav.Name, + DataType = nav.DeclaringEntityType.Name + }); + } + return tableColumns; } } diff --git a/src/modules/crm/CRMCore.Module.GraphQL/Resolvers/MyFieldResolver.cs b/src/modules/crm/CRMCore.Module.GraphQL/Resolvers/MyFieldResolver.cs index d68dc25..d4fc95c 100644 --- a/src/modules/crm/CRMCore.Module.GraphQL/Resolvers/MyFieldResolver.cs +++ b/src/modules/crm/CRMCore.Module.GraphQL/Resolvers/MyFieldResolver.cs @@ -21,7 +21,18 @@ public MyFieldResolver(TableMetadata tableMetadata, DbContext dbContext) public object Resolve(ResolveFieldContext context) { - var queryable = _dbContext.Query(_tableMetadata.AssemblyFullName); + var includes = context.Arguments["includes"] != null ? + context.GetArgument("includes").Split(',') : null; + + IQueryable queryable = null; + if (includes != null) + { + queryable = _dbContext.Query(_tableMetadata.AssemblyFullName, includes); + } else + { + queryable = _dbContext.Query(_tableMetadata.AssemblyFullName); + } + if (context.FieldName.Contains("_list")) { @@ -41,7 +52,8 @@ public object Resolve(ResolveFieldContext context) else { var id = context.GetArgument("id"); - return queryable.FirstOrDefault($"Id == @0", id); + return queryable + .FirstOrDefault($"Id == @0", id); } } } diff --git a/src/modules/crm/CRMCore.Module.GraphQL/Resolvers/NameFieldResolver.cs b/src/modules/crm/CRMCore.Module.GraphQL/Resolvers/NameFieldResolver.cs index 1b346be..0cc486e 100644 --- a/src/modules/crm/CRMCore.Module.GraphQL/Resolvers/NameFieldResolver.cs +++ b/src/modules/crm/CRMCore.Module.GraphQL/Resolvers/NameFieldResolver.cs @@ -18,10 +18,12 @@ public object Resolve(ResolveFieldContext context) var name = Char.ToUpperInvariant(context.FieldAst.Name[0]) + context.FieldAst.Name.Substring(1); var value = GetPropValue(source, name); - if (value == null) + value = value != null ? value : string.Empty; + + /*if (value == null) { throw new InvalidOperationException($"Expected to find property {context.FieldAst.Name} on {context.Source.GetType().Name} but it does not exist."); - } + } */ return value; } diff --git a/src/modules/crm/CRMCore.Module.GraphQL/Types/TableType.cs b/src/modules/crm/CRMCore.Module.GraphQL/Types/TableType.cs index 223e551..bf7dc6f 100644 --- a/src/modules/crm/CRMCore.Module.GraphQL/Types/TableType.cs +++ b/src/modules/crm/CRMCore.Module.GraphQL/Types/TableType.cs @@ -9,6 +9,20 @@ namespace CRMCore.Module.GraphQL.Types { public class TableType : ObjectGraphType { + public TableType(TableMetadata tableMetadata) + { + Name = tableMetadata.TableName; + foreach (var tableColumn in tableMetadata.Columns) + { + InitGraphTableColumn(tableColumn); + } + + TableArgs.Add(new QueryArgument { Name = "id" }); + TableArgs.Add(new QueryArgument { Name = "first" }); + TableArgs.Add(new QueryArgument { Name = "offset" }); + TableArgs.Add(new QueryArgument { Name = "includes" }); + } + public QueryArguments TableArgs { get; set; @@ -34,15 +48,6 @@ protected IDictionary DatabaseTypeToSystemType } } - public TableType(TableMetadata tableMetadata) - { - Name = tableMetadata.TableName; - foreach (var tableColumn in tableMetadata.Columns) - { - InitGraphTableColumn(tableColumn); - } - } - private void InitGraphTableColumn(ColumnMetadata columnMetadata) { var graphQLType = (ResolveColumnMetaType(columnMetadata.DataType)).GetGraphTypeFromType(true); @@ -70,10 +75,6 @@ private void FillArgs(string columnName) { TableArgs.Add(new QueryArgument { Name = columnName }); } - - TableArgs.Add(new QueryArgument { Name = "id" }); - TableArgs.Add(new QueryArgument { Name = "first" }); - TableArgs.Add(new QueryArgument { Name = "offset" }); } private Type ResolveColumnMetaType(string dbType) diff --git a/src/modules/crm/CRMCore.Module.Migration/Seeder/ApplicationDbContextSeed.cs b/src/modules/crm/CRMCore.Module.Migration/Seeder/ApplicationDbContextSeed.cs index 14e5d0c..05728d4 100644 --- a/src/modules/crm/CRMCore.Module.Migration/Seeder/ApplicationDbContextSeed.cs +++ b/src/modules/crm/CRMCore.Module.Migration/Seeder/ApplicationDbContextSeed.cs @@ -175,10 +175,19 @@ private IEnumerable GetDefaultMorphisms() IdHelper.GenerateId("0fd266b3-4376-4fa3-9a35-aabe1d08043e"))); } + var task1 = CrmTask.Domain.Task + .CreateInstance( + "Implementing Repository in Task module.", + IdHelper.GenerateId("0fd266b3-4376-4fa3-9a35-aabe1d08043e")) + .AddSubTask(CrmTask.Domain.Task.CreateInstance( + "This is a sub task one.", + IdHelper.GenerateId("0fd266b3-4376-4fa3-9a35-aabe1d08043e"))) + .AddSubTask(CrmTask.Domain.Task.CreateInstance( + "This is a sub task two.", + IdHelper.GenerateId("0fd266b3-4376-4fa3-9a35-aabe1d08043e"))); + results.AddRange(new[] { - CrmTask.Domain.Task.CreateInstance( - "Implementing Repository in Task module.", - IdHelper.GenerateId("0fd266b3-4376-4fa3-9a35-aabe1d08043e")), + task1, CrmTask.Domain.Task.CreateInstance( "Implementing Controller in Task module.", IdHelper.GenerateId("0fd266b3-4376-4fa3-9a35-aabe1d08043e")), diff --git a/src/modules/crm/CRMCore.Module.Task/Domain/Task.cs b/src/modules/crm/CRMCore.Module.Task/Domain/Task.cs index 7b12c4a..7d1d1dc 100644 --- a/src/modules/crm/CRMCore.Module.Task/Domain/Task.cs +++ b/src/modules/crm/CRMCore.Module.Task/Domain/Task.cs @@ -1,6 +1,7 @@ using CRMCore.Module.Entities; using CRMCore.Module.Entities.Helpers; using System; +using System.Collections.Generic; using System.ComponentModel.DataAnnotations; namespace CRMCore.Module.Task.Domain @@ -20,6 +21,8 @@ internal Task(Guid id, string name, Guid assignedTo) Name = name; AssignedTo = assignedTo; TaskStatus = TaskStatus.NotStarted; + ParentId = null; // is a root node + SubTasks = new List(); } public static Task CreateInstance(Guid id, string name, Guid assignedTo) @@ -29,7 +32,7 @@ public static Task CreateInstance(Guid id, string name, Guid assignedTo) public static Task CreateInstance(string name, Guid assignedTo) { - return Task.CreateInstance(IdHelper.GenerateId(), name, assignedTo); + return CreateInstance(IdHelper.GenerateId(), name, assignedTo); } public Task ChangeName(string name) @@ -38,6 +41,7 @@ public Task ChangeName(string name) { Name = name; } + return this; } @@ -47,6 +51,7 @@ public Task ChangeAssignedTo(Guid id) { AssignedTo = id; } + return this; } @@ -56,6 +61,7 @@ public Task ChangeCategoryType(CategoryType categoryType) { CategoryType = categoryType; } + return this; } @@ -65,6 +71,39 @@ public Task ChangeTaskStatus(TaskStatus status) { TaskStatus = status; } + + return this; + } + + public Task AddSubTask(Task task) + { + task.ParentId = Id; + SubTasks.Add(task); + + return this; + } + + public Task RemoveSubTask(Task task) + { + SubTasks.Remove(task); + + return this; + } + + public Task UpdateSubTask(Task task) + { + SubTasks.Remove(task); + + task.ParentId = Id; + SubTasks.Add(task); + + return this; + } + + public Task RemoveAllSubTasks() + { + SubTasks.Clear(); + return this; } @@ -79,5 +118,9 @@ public Task ChangeTaskStatus(TaskStatus status) [Required] public TaskStatus TaskStatus { get; private set; } + + public Guid? ParentId { get; private set; } + + public ICollection SubTasks { get; private set; } } } diff --git a/src/modules/crm/CRMCore.Module.Task/Features/GetTasks/Impl/GetTasksService.cs b/src/modules/crm/CRMCore.Module.Task/Features/GetTasks/Impl/GetTasksService.cs index fb691a4..ec202d1 100644 --- a/src/modules/crm/CRMCore.Module.Task/Features/GetTasks/Impl/GetTasksService.cs +++ b/src/modules/crm/CRMCore.Module.Task/Features/GetTasks/Impl/GetTasksService.cs @@ -1,14 +1,13 @@ using CRMCore.Module.Data; -using System.Linq; using CRMCore.Module.Entities; using CRMCore.Module.Task.Features.GetTask; using Microsoft.Extensions.Options; -using System.Linq.Expressions; using System; +using System.Linq; +using System.Linq.Expressions; namespace CRMCore.Module.Task.Features.GetTasks.Impl { - public class GetTasksService : QueryServiceBase, IGetTasksService { private readonly IEfQueryRepository _taskRepo; diff --git a/src/modules/crm/CRMCore.Module.Task/StartUp.cs b/src/modules/crm/CRMCore.Module.Task/StartUp.cs index 62634b4..4227cf9 100644 --- a/src/modules/crm/CRMCore.Module.Task/StartUp.cs +++ b/src/modules/crm/CRMCore.Module.Task/StartUp.cs @@ -8,7 +8,7 @@ namespace CRMCore.Module.Task { - public class StartUp : StartupBase + public class Startup : StartupBase { public override void ConfigureServices(IServiceCollection services) {