diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..33f4c50 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,34 @@ +{ + // Use IntelliSense to find out which attributes exist for C# debugging + // Use hover for the description of the existing attributes + // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md + "version": "0.2.0", + "configurations": [ + { + "name": ".NET Core Launch (web)", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "build", + // If you have changed target frameworks, make sure to update the program path. + "program": "${workspaceFolder}/src/src/bin/Debug/netcoreapp2.0/src.dll", + "args": [], + "cwd": "${workspaceFolder}/src/src", + "stopAtEntry": false, + "launchBrowser": { + "enabled": true + }, + "env": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "sourceFileMap": { + "/Views": "${workspaceFolder}/Views" + } + }, + { + "name": ".NET Core Attach", + "type": "coreclr", + "request": "attach", + "processId": "${command:pickProcess}" + } + ] +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..84968ea --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,36 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "build", + "command": "dotnet", + "type": "process", + "args": [ + "build", + "${workspaceFolder}/src/src/src.csproj" + ], + "problemMatcher": "$tsc" + }, + { + "label": "publish", + "command": "dotnet", + "type": "process", + "args": [ + "publish", + "${workspaceFolder}/src/src/src.csproj" + ], + "problemMatcher": "$tsc" + }, + { + "label": "watch", + "command": "dotnet", + "type": "process", + "args": [ + "watch", + "run", + "${workspaceFolder}/src/src/src.csproj" + ], + "problemMatcher": "$tsc" + } + ] +} \ No newline at end of file diff --git a/src/src/Controllers/Api/TicketController.cs b/src/src/Controllers/Api/TicketController.cs index 3ee5de2..f2042ff 100644 --- a/src/src/Controllers/Api/TicketController.cs +++ b/src/src/Controllers/Api/TicketController.cs @@ -177,6 +177,46 @@ public async Task DeleteTicketCustomer([FromRoute] Guid id) } + [HttpPost("PostTicketComment")] + public async Task PostTicketComment([FromBody] TicketThread ticketThread) + { + if (!ModelState.IsValid) + { + return BadRequest(ModelState); + } + try + { + if(ticketThread.ticketId == Guid.Empty) + { + return NotFound(); + } + + if(ticketThread.ticketThreadId == Guid.Empty) + { + ticketThread.ticketThreadId = new Guid(); + _context.TicketThread.Add(ticketThread); + await _context.SaveChangesAsync(); + + return Json(new { success = true, message = "Add new data success." }); + } + + else + { + return Json(new { success = false, message = "Comment already exists" }); + } + } + catch (Exception ex) + { + return Json(new { success = false, message = ex.Message }); + } + } + + [HttpGet("ShowTicketComments/{ticketId}")] + public IActionResult ShowTicketComments([FromRoute]Guid ticketId) + { + return Json(new { data = _context.TicketThread.Where(x => x.ticketId.Equals(ticketId)).ToList() }); + } + private bool TicketExists(Guid id) { return _context.Ticket.Any(e => e.ticketId == id); diff --git a/src/src/Controllers/TicketController.cs b/src/src/Controllers/TicketController.cs index 40db0bc..2117bcc 100644 --- a/src/src/Controllers/TicketController.cs +++ b/src/src/Controllers/TicketController.cs @@ -49,6 +49,7 @@ public IActionResult AddEdit(Guid org, Guid id) if (id == Guid.Empty) { Ticket ticket = new Ticket(); + ticket.CreateBy = _userManager.GetUserName(User); ticket.organizationId = org; IList products = _context.Product.Where(x => x.organizationId.Equals(org)).ToList(); @@ -116,5 +117,46 @@ public IActionResult AddEditCustomerTicket(Guid cust, Guid id) } } + + public IActionResult Detail(Guid ticketId) + { + if(ticketId == Guid.Empty) + { + return NotFound(); + } + Ticket ticket = _context.Ticket.Where(x => x.ticketId.Equals(ticketId)).FirstOrDefault(); + Product product = _context.Product.Where(x => x.productId.Equals(ticket.productId)).FirstOrDefault(); + SupportAgent agent = _context.SupportAgent.Where(x => x.supportAgentId.Equals(ticket.supportAgentId)).FirstOrDefault(); + SupportEngineer engineer = _context.SupportEngineer.Where(x => x.supportEngineerId.Equals(ticket.supportEngineerId)).FirstOrDefault(); + Contact contact = _context.Contact.Where(x => x.contactId.Equals(ticket.contactId)).FirstOrDefault(); + ViewData["ticket"] = ticket.ticketId; + ViewBag.productName = product.productName; + ViewBag.supportAgentName = agent.supportAgentName; + ViewBag.supportEngineerName = engineer.supportEngineerName; + ViewBag.contactName = contact.contactName; + return View(ticket); + } + + public IActionResult AddComment(Guid ticketId) + { + if(ticketId == Guid.Empty) + { + return NotFound(); + } + TicketThread ticketThread = new TicketThread(); + ticketThread.ticketId = ticketId; + ticketThread.CreateBy = _userManager.GetUserName(User); + return View(ticketThread); + } + + public IActionResult ShowComments(Guid ticketId) + { + if(ticketId == Guid.Empty) + { + return NotFound(); + } + TicketThread ticketThread = _context.TicketThread.Where(x => x.ticketId.Equals(ticketId)).FirstOrDefault(); + return View(ticketThread); + } } } \ No newline at end of file diff --git a/src/src/Data/ApplicationDbContext.cs b/src/src/Data/ApplicationDbContext.cs index d86f2e1..03ed809 100644 --- a/src/src/Data/ApplicationDbContext.cs +++ b/src/src/Data/ApplicationDbContext.cs @@ -37,6 +37,8 @@ protected override void OnModelCreating(ModelBuilder builder) public DbSet Ticket { get; set; } + public DbSet TicketThread { get; set; } + public DbSet ApplicationUser { get; set; } } } diff --git a/src/src/Migrations/20190504103322_20190405113150_additionOfTicketThread.Designer.cs b/src/src/Migrations/20190504103322_20190405113150_additionOfTicketThread.Designer.cs new file mode 100644 index 0000000..70646d2 --- /dev/null +++ b/src/src/Migrations/20190504103322_20190405113150_additionOfTicketThread.Designer.cs @@ -0,0 +1,589 @@ +// +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.Storage.Internal; +using src.Data; +using src.Enum; +using System; + +namespace src.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20190504103322_20190405113150_additionOfTicketThread")] + partial class _20190405113150_additionOfTicketThread + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.0.2-rtm-10011") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken(); + + b.Property("Name") + .HasMaxLength(256); + + b.Property("NormalizedName") + .HasMaxLength(256); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasName("RoleNameIndex") + .HasFilter("[NormalizedName] IS NOT NULL"); + + b.ToTable("AspNetRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ClaimType"); + + b.Property("ClaimValue"); + + b.Property("RoleId") + .IsRequired(); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ClaimType"); + + b.Property("ClaimValue"); + + b.Property("UserId") + .IsRequired(); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider"); + + b.Property("ProviderKey"); + + b.Property("ProviderDisplayName"); + + b.Property("UserId") + .IsRequired(); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId"); + + b.Property("RoleId"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId"); + + b.Property("LoginProvider"); + + b.Property("Name"); + + b.Property("Value"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens"); + }); + + modelBuilder.Entity("src.Models.ApplicationUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AccessFailedCount"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken(); + + b.Property("Email") + .HasMaxLength(256); + + b.Property("EmailConfirmed"); + + b.Property("FullName") + .HasMaxLength(100); + + b.Property("IsCustomer"); + + b.Property("IsSuperAdmin"); + + b.Property("IsSupportAgent"); + + b.Property("IsSupportEngineer"); + + b.Property("LockoutEnabled"); + + b.Property("LockoutEnd"); + + b.Property("NormalizedEmail") + .HasMaxLength(256); + + b.Property("NormalizedUserName") + .HasMaxLength(256); + + b.Property("PasswordHash"); + + b.Property("PhoneNumber"); + + b.Property("PhoneNumberConfirmed"); + + b.Property("ProfilePictureUrl") + .HasMaxLength(250); + + b.Property("SecurityStamp"); + + b.Property("TwoFactorEnabled"); + + b.Property("UserName") + .HasMaxLength(256); + + b.Property("WallpaperPictureUrl") + .HasMaxLength(250); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasName("UserNameIndex") + .HasFilter("[NormalizedUserName] IS NOT NULL"); + + b.ToTable("AspNetUsers"); + }); + + modelBuilder.Entity("src.Models.Contact", b => + { + b.Property("contactId") + .ValueGeneratedOnAdd(); + + b.Property("CreateAt"); + + b.Property("CreateBy"); + + b.Property("applicationUserId"); + + b.Property("contactName") + .IsRequired() + .HasMaxLength(100); + + b.Property("customerId"); + + b.Property("description") + .HasMaxLength(200); + + b.Property("email") + .IsRequired() + .HasMaxLength(100); + + b.Property("linkedin") + .HasMaxLength(100); + + b.Property("phone") + .HasMaxLength(20); + + b.Property("secondaryEmail") + .HasMaxLength(100); + + b.Property("thumbUrl") + .HasMaxLength(255); + + b.Property("website") + .HasMaxLength(100); + + b.HasKey("contactId"); + + b.HasIndex("applicationUserId"); + + b.HasIndex("customerId"); + + b.ToTable("Contact"); + }); + + modelBuilder.Entity("src.Models.Customer", b => + { + b.Property("customerId") + .ValueGeneratedOnAdd(); + + b.Property("CreateAt"); + + b.Property("CreateBy"); + + b.Property("address") + .HasMaxLength(100); + + b.Property("customerName") + .IsRequired() + .HasMaxLength(100); + + b.Property("customerType"); + + b.Property("description") + .HasMaxLength(200); + + b.Property("email") + .HasMaxLength(100); + + b.Property("linkedin") + .HasMaxLength(100); + + b.Property("organizationId"); + + b.Property("phone") + .HasMaxLength(20); + + b.Property("thumbUrl") + .HasMaxLength(255); + + b.Property("website") + .HasMaxLength(100); + + b.HasKey("customerId"); + + b.HasIndex("organizationId"); + + b.ToTable("Customer"); + }); + + modelBuilder.Entity("src.Models.Organization", b => + { + b.Property("organizationId") + .ValueGeneratedOnAdd(); + + b.Property("CreateAt"); + + b.Property("CreateBy"); + + b.Property("description") + .HasMaxLength(200); + + b.Property("organizationName") + .IsRequired() + .HasMaxLength(100); + + b.Property("organizationOwnerId"); + + b.Property("thumbUrl") + .HasMaxLength(255); + + b.HasKey("organizationId"); + + b.ToTable("Organization"); + }); + + modelBuilder.Entity("src.Models.Product", b => + { + b.Property("productId") + .ValueGeneratedOnAdd(); + + b.Property("CreateAt"); + + b.Property("CreateBy"); + + b.Property("description") + .HasMaxLength(200); + + b.Property("organizationId"); + + b.Property("productCategory"); + + b.Property("productName") + .IsRequired() + .HasMaxLength(100); + + b.Property("thumbUrl") + .HasMaxLength(255); + + b.HasKey("productId"); + + b.HasIndex("organizationId"); + + b.ToTable("Product"); + }); + + modelBuilder.Entity("src.Models.SupportAgent", b => + { + b.Property("supportAgentId") + .ValueGeneratedOnAdd(); + + b.Property("CreateAt"); + + b.Property("CreateBy"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(100); + + b.Property("applicationUserId"); + + b.Property("organizationId"); + + b.Property("supportAgentName") + .IsRequired() + .HasMaxLength(100); + + b.HasKey("supportAgentId"); + + b.HasIndex("applicationUserId"); + + b.HasIndex("organizationId"); + + b.ToTable("SupportAgent"); + }); + + modelBuilder.Entity("src.Models.SupportEngineer", b => + { + b.Property("supportEngineerId") + .ValueGeneratedOnAdd(); + + b.Property("Email") + .IsRequired() + .HasMaxLength(100); + + b.Property("applicationUserId"); + + b.Property("organizationId"); + + b.Property("supportEngineerName") + .IsRequired() + .HasMaxLength(100); + + b.HasKey("supportEngineerId"); + + b.HasIndex("applicationUserId"); + + b.HasIndex("organizationId"); + + b.ToTable("SupportEngineer"); + }); + + modelBuilder.Entity("src.Models.Ticket", b => + { + b.Property("ticketId") + .ValueGeneratedOnAdd(); + + b.Property("CreateAt"); + + b.Property("CreateBy"); + + b.Property("contactId"); + + b.Property("customerId"); + + b.Property("description") + .IsRequired() + .HasMaxLength(200); + + b.Property("email") + .HasMaxLength(100); + + b.Property("organizationId"); + + b.Property("phone") + .HasMaxLength(20); + + b.Property("productId"); + + b.Property("supportAgentId"); + + b.Property("supportEngineerId"); + + b.Property("ticketChannel"); + + b.Property("ticketName") + .IsRequired() + .HasMaxLength(100); + + b.Property("ticketPriority"); + + b.Property("ticketStatus"); + + b.Property("ticketType"); + + b.HasKey("ticketId"); + + b.HasIndex("organizationId"); + + b.ToTable("Ticket"); + }); + + modelBuilder.Entity("src.Models.TicketThread", b => + { + b.Property("ticketThreadId") + .ValueGeneratedOnAdd(); + + b.Property("Comment") + .IsRequired() + .HasMaxLength(250); + + b.Property("ticketId"); + + b.HasKey("ticketThreadId"); + + b.HasIndex("ticketId"); + + b.ToTable("TicketThread"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("src.Models.ApplicationUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("src.Models.ApplicationUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("src.Models.ApplicationUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("src.Models.ApplicationUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("src.Models.Contact", b => + { + b.HasOne("src.Models.ApplicationUser", "applicationUser") + .WithMany() + .HasForeignKey("applicationUserId"); + + b.HasOne("src.Models.Customer", "customer") + .WithMany("contacts") + .HasForeignKey("customerId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("src.Models.Customer", b => + { + b.HasOne("src.Models.Organization", "organization") + .WithMany("customers") + .HasForeignKey("organizationId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("src.Models.Product", b => + { + b.HasOne("src.Models.Organization", "organization") + .WithMany("products") + .HasForeignKey("organizationId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("src.Models.SupportAgent", b => + { + b.HasOne("src.Models.ApplicationUser", "applicationUser") + .WithMany() + .HasForeignKey("applicationUserId"); + + b.HasOne("src.Models.Organization", "organization") + .WithMany("supportAgents") + .HasForeignKey("organizationId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("src.Models.SupportEngineer", b => + { + b.HasOne("src.Models.ApplicationUser", "applicationUser") + .WithMany() + .HasForeignKey("applicationUserId"); + + b.HasOne("src.Models.Organization", "organization") + .WithMany("supportEngineers") + .HasForeignKey("organizationId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("src.Models.Ticket", b => + { + b.HasOne("src.Models.Organization", "organization") + .WithMany("tickets") + .HasForeignKey("organizationId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("src.Models.TicketThread", b => + { + b.HasOne("src.Models.Ticket") + .WithMany("ticketThreads") + .HasForeignKey("ticketId") + .OnDelete(DeleteBehavior.Cascade); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/src/Migrations/20190504103322_20190405113150_additionOfTicketThread.cs b/src/src/Migrations/20190504103322_20190405113150_additionOfTicketThread.cs new file mode 100644 index 0000000..e6a8d24 --- /dev/null +++ b/src/src/Migrations/20190504103322_20190405113150_additionOfTicketThread.cs @@ -0,0 +1,42 @@ +using Microsoft.EntityFrameworkCore.Migrations; +using System; +using System.Collections.Generic; + +namespace src.Migrations +{ + public partial class _20190405113150_additionOfTicketThread : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "TicketThread", + columns: table => new + { + ticketThreadId = table.Column(nullable: false), + Comment = table.Column(maxLength: 250, nullable: false), + ticketId = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_TicketThread", x => x.ticketThreadId); + table.ForeignKey( + name: "FK_TicketThread_Ticket_ticketId", + column: x => x.ticketId, + principalTable: "Ticket", + principalColumn: "ticketId", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_TicketThread_ticketId", + table: "TicketThread", + column: "ticketId"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "TicketThread"); + } + } +} diff --git a/src/src/Migrations/20190504103613_20190405113556_additionOfTicketThread_extendBaseEntity.Designer.cs b/src/src/Migrations/20190504103613_20190405113556_additionOfTicketThread_extendBaseEntity.Designer.cs new file mode 100644 index 0000000..5e993fd --- /dev/null +++ b/src/src/Migrations/20190504103613_20190405113556_additionOfTicketThread_extendBaseEntity.Designer.cs @@ -0,0 +1,593 @@ +// +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.Storage.Internal; +using src.Data; +using src.Enum; +using System; + +namespace src.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20190504103613_20190405113556_additionOfTicketThread_extendBaseEntity")] + partial class _20190405113556_additionOfTicketThread_extendBaseEntity + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.0.2-rtm-10011") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken(); + + b.Property("Name") + .HasMaxLength(256); + + b.Property("NormalizedName") + .HasMaxLength(256); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasName("RoleNameIndex") + .HasFilter("[NormalizedName] IS NOT NULL"); + + b.ToTable("AspNetRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ClaimType"); + + b.Property("ClaimValue"); + + b.Property("RoleId") + .IsRequired(); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ClaimType"); + + b.Property("ClaimValue"); + + b.Property("UserId") + .IsRequired(); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider"); + + b.Property("ProviderKey"); + + b.Property("ProviderDisplayName"); + + b.Property("UserId") + .IsRequired(); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId"); + + b.Property("RoleId"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId"); + + b.Property("LoginProvider"); + + b.Property("Name"); + + b.Property("Value"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens"); + }); + + modelBuilder.Entity("src.Models.ApplicationUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AccessFailedCount"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken(); + + b.Property("Email") + .HasMaxLength(256); + + b.Property("EmailConfirmed"); + + b.Property("FullName") + .HasMaxLength(100); + + b.Property("IsCustomer"); + + b.Property("IsSuperAdmin"); + + b.Property("IsSupportAgent"); + + b.Property("IsSupportEngineer"); + + b.Property("LockoutEnabled"); + + b.Property("LockoutEnd"); + + b.Property("NormalizedEmail") + .HasMaxLength(256); + + b.Property("NormalizedUserName") + .HasMaxLength(256); + + b.Property("PasswordHash"); + + b.Property("PhoneNumber"); + + b.Property("PhoneNumberConfirmed"); + + b.Property("ProfilePictureUrl") + .HasMaxLength(250); + + b.Property("SecurityStamp"); + + b.Property("TwoFactorEnabled"); + + b.Property("UserName") + .HasMaxLength(256); + + b.Property("WallpaperPictureUrl") + .HasMaxLength(250); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasName("UserNameIndex") + .HasFilter("[NormalizedUserName] IS NOT NULL"); + + b.ToTable("AspNetUsers"); + }); + + modelBuilder.Entity("src.Models.Contact", b => + { + b.Property("contactId") + .ValueGeneratedOnAdd(); + + b.Property("CreateAt"); + + b.Property("CreateBy"); + + b.Property("applicationUserId"); + + b.Property("contactName") + .IsRequired() + .HasMaxLength(100); + + b.Property("customerId"); + + b.Property("description") + .HasMaxLength(200); + + b.Property("email") + .IsRequired() + .HasMaxLength(100); + + b.Property("linkedin") + .HasMaxLength(100); + + b.Property("phone") + .HasMaxLength(20); + + b.Property("secondaryEmail") + .HasMaxLength(100); + + b.Property("thumbUrl") + .HasMaxLength(255); + + b.Property("website") + .HasMaxLength(100); + + b.HasKey("contactId"); + + b.HasIndex("applicationUserId"); + + b.HasIndex("customerId"); + + b.ToTable("Contact"); + }); + + modelBuilder.Entity("src.Models.Customer", b => + { + b.Property("customerId") + .ValueGeneratedOnAdd(); + + b.Property("CreateAt"); + + b.Property("CreateBy"); + + b.Property("address") + .HasMaxLength(100); + + b.Property("customerName") + .IsRequired() + .HasMaxLength(100); + + b.Property("customerType"); + + b.Property("description") + .HasMaxLength(200); + + b.Property("email") + .HasMaxLength(100); + + b.Property("linkedin") + .HasMaxLength(100); + + b.Property("organizationId"); + + b.Property("phone") + .HasMaxLength(20); + + b.Property("thumbUrl") + .HasMaxLength(255); + + b.Property("website") + .HasMaxLength(100); + + b.HasKey("customerId"); + + b.HasIndex("organizationId"); + + b.ToTable("Customer"); + }); + + modelBuilder.Entity("src.Models.Organization", b => + { + b.Property("organizationId") + .ValueGeneratedOnAdd(); + + b.Property("CreateAt"); + + b.Property("CreateBy"); + + b.Property("description") + .HasMaxLength(200); + + b.Property("organizationName") + .IsRequired() + .HasMaxLength(100); + + b.Property("organizationOwnerId"); + + b.Property("thumbUrl") + .HasMaxLength(255); + + b.HasKey("organizationId"); + + b.ToTable("Organization"); + }); + + modelBuilder.Entity("src.Models.Product", b => + { + b.Property("productId") + .ValueGeneratedOnAdd(); + + b.Property("CreateAt"); + + b.Property("CreateBy"); + + b.Property("description") + .HasMaxLength(200); + + b.Property("organizationId"); + + b.Property("productCategory"); + + b.Property("productName") + .IsRequired() + .HasMaxLength(100); + + b.Property("thumbUrl") + .HasMaxLength(255); + + b.HasKey("productId"); + + b.HasIndex("organizationId"); + + b.ToTable("Product"); + }); + + modelBuilder.Entity("src.Models.SupportAgent", b => + { + b.Property("supportAgentId") + .ValueGeneratedOnAdd(); + + b.Property("CreateAt"); + + b.Property("CreateBy"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(100); + + b.Property("applicationUserId"); + + b.Property("organizationId"); + + b.Property("supportAgentName") + .IsRequired() + .HasMaxLength(100); + + b.HasKey("supportAgentId"); + + b.HasIndex("applicationUserId"); + + b.HasIndex("organizationId"); + + b.ToTable("SupportAgent"); + }); + + modelBuilder.Entity("src.Models.SupportEngineer", b => + { + b.Property("supportEngineerId") + .ValueGeneratedOnAdd(); + + b.Property("Email") + .IsRequired() + .HasMaxLength(100); + + b.Property("applicationUserId"); + + b.Property("organizationId"); + + b.Property("supportEngineerName") + .IsRequired() + .HasMaxLength(100); + + b.HasKey("supportEngineerId"); + + b.HasIndex("applicationUserId"); + + b.HasIndex("organizationId"); + + b.ToTable("SupportEngineer"); + }); + + modelBuilder.Entity("src.Models.Ticket", b => + { + b.Property("ticketId") + .ValueGeneratedOnAdd(); + + b.Property("CreateAt"); + + b.Property("CreateBy"); + + b.Property("contactId"); + + b.Property("customerId"); + + b.Property("description") + .IsRequired() + .HasMaxLength(200); + + b.Property("email") + .HasMaxLength(100); + + b.Property("organizationId"); + + b.Property("phone") + .HasMaxLength(20); + + b.Property("productId"); + + b.Property("supportAgentId"); + + b.Property("supportEngineerId"); + + b.Property("ticketChannel"); + + b.Property("ticketName") + .IsRequired() + .HasMaxLength(100); + + b.Property("ticketPriority"); + + b.Property("ticketStatus"); + + b.Property("ticketType"); + + b.HasKey("ticketId"); + + b.HasIndex("organizationId"); + + b.ToTable("Ticket"); + }); + + modelBuilder.Entity("src.Models.TicketThread", b => + { + b.Property("ticketThreadId") + .ValueGeneratedOnAdd(); + + b.Property("Comment") + .IsRequired() + .HasMaxLength(250); + + b.Property("CreateAt"); + + b.Property("CreateBy"); + + b.Property("ticketId"); + + b.HasKey("ticketThreadId"); + + b.HasIndex("ticketId"); + + b.ToTable("TicketThread"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("src.Models.ApplicationUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("src.Models.ApplicationUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("src.Models.ApplicationUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("src.Models.ApplicationUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("src.Models.Contact", b => + { + b.HasOne("src.Models.ApplicationUser", "applicationUser") + .WithMany() + .HasForeignKey("applicationUserId"); + + b.HasOne("src.Models.Customer", "customer") + .WithMany("contacts") + .HasForeignKey("customerId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("src.Models.Customer", b => + { + b.HasOne("src.Models.Organization", "organization") + .WithMany("customers") + .HasForeignKey("organizationId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("src.Models.Product", b => + { + b.HasOne("src.Models.Organization", "organization") + .WithMany("products") + .HasForeignKey("organizationId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("src.Models.SupportAgent", b => + { + b.HasOne("src.Models.ApplicationUser", "applicationUser") + .WithMany() + .HasForeignKey("applicationUserId"); + + b.HasOne("src.Models.Organization", "organization") + .WithMany("supportAgents") + .HasForeignKey("organizationId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("src.Models.SupportEngineer", b => + { + b.HasOne("src.Models.ApplicationUser", "applicationUser") + .WithMany() + .HasForeignKey("applicationUserId"); + + b.HasOne("src.Models.Organization", "organization") + .WithMany("supportEngineers") + .HasForeignKey("organizationId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("src.Models.Ticket", b => + { + b.HasOne("src.Models.Organization", "organization") + .WithMany("tickets") + .HasForeignKey("organizationId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("src.Models.TicketThread", b => + { + b.HasOne("src.Models.Ticket") + .WithMany("ticketThreads") + .HasForeignKey("ticketId") + .OnDelete(DeleteBehavior.Cascade); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/src/Migrations/20190504103613_20190405113556_additionOfTicketThread_extendBaseEntity.cs b/src/src/Migrations/20190504103613_20190405113556_additionOfTicketThread_extendBaseEntity.cs new file mode 100644 index 0000000..183df51 --- /dev/null +++ b/src/src/Migrations/20190504103613_20190405113556_additionOfTicketThread_extendBaseEntity.cs @@ -0,0 +1,34 @@ +using Microsoft.EntityFrameworkCore.Migrations; +using System; +using System.Collections.Generic; + +namespace src.Migrations +{ + public partial class _20190405113556_additionOfTicketThread_extendBaseEntity : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "CreateAt", + table: "TicketThread", + nullable: false, + defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified)); + + migrationBuilder.AddColumn( + name: "CreateBy", + table: "TicketThread", + nullable: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "CreateAt", + table: "TicketThread"); + + migrationBuilder.DropColumn( + name: "CreateBy", + table: "TicketThread"); + } + } +} diff --git a/src/src/Migrations/ApplicationDbContextModelSnapshot.cs b/src/src/Migrations/ApplicationDbContextModelSnapshot.cs index 6c8865e..d2598fe 100644 --- a/src/src/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/src/src/Migrations/ApplicationDbContextModelSnapshot.cs @@ -452,6 +452,28 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("Ticket"); }); + modelBuilder.Entity("src.Models.TicketThread", b => + { + b.Property("ticketThreadId") + .ValueGeneratedOnAdd(); + + b.Property("Comment") + .IsRequired() + .HasMaxLength(250); + + b.Property("CreateAt"); + + b.Property("CreateBy"); + + b.Property("ticketId"); + + b.HasKey("ticketThreadId"); + + b.HasIndex("ticketId"); + + b.ToTable("TicketThread"); + }); + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => { b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole") @@ -556,6 +578,14 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasForeignKey("organizationId") .OnDelete(DeleteBehavior.Cascade); }); + + modelBuilder.Entity("src.Models.TicketThread", b => + { + b.HasOne("src.Models.Ticket") + .WithMany("ticketThreads") + .HasForeignKey("ticketId") + .OnDelete(DeleteBehavior.Cascade); + }); #pragma warning restore 612, 618 } } diff --git a/src/src/Models/Ticket.cs b/src/src/Models/Ticket.cs index 9b20dd9..8dfbeec 100644 --- a/src/src/Models/Ticket.cs +++ b/src/src/Models/Ticket.cs @@ -60,5 +60,7 @@ public Ticket() public Guid organizationId { get; set; } public Organization organization { get; set; } + public ICollection ticketThreads { get; set; } + } } diff --git a/src/src/Models/TicketThread.cs b/src/src/Models/TicketThread.cs new file mode 100644 index 0000000..ff1dacc --- /dev/null +++ b/src/src/Models/TicketThread.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Threading.Tasks; + +namespace src.Models +{ + public class TicketThread : BaseEntity + { + public Guid ticketThreadId { get; set; } + [Required] + [StringLength(250)] + [Display(Name = "Comment")] + public string Comment { get; set; } + public Guid ticketId { get; set; } + } +} diff --git a/src/src/Services/Dotnetdesk.cs b/src/src/Services/Dotnetdesk.cs index 0961895..309a642 100644 --- a/src/src/Services/Dotnetdesk.cs +++ b/src/src/Services/Dotnetdesk.cs @@ -70,6 +70,31 @@ public async Task SendEmailByGmailAsync(string fromEmail, } + // for local dev purpose + // going to set email to deliver locally + public async Task SendEmailLocallyAsync(bool isBodyHtml + , string subject + , string body + , string toEmail + , string fromEmail + , string localDestination) + { + using (var smtp = new SmtpClient()){ + smtp.DeliveryMethod = SmtpDeliveryMethod.SpecifiedPickupDirectory; + smtp.PickupDirectoryLocation = localDestination; + + var message = new MailMessage{ + Body = body, + IsBodyHtml = isBodyHtml, + Subject = subject, + From = new MailAddress(fromEmail) + }; + + message.To.Add(toEmail); + await smtp.SendMailAsync(message); + } + } + public async Task IsAccountActivatedAsync(string email, UserManager userManager) { bool result = false; diff --git a/src/src/Services/EmailSender.cs b/src/src/Services/EmailSender.cs index 3be1f48..0493b39 100644 --- a/src/src/Services/EmailSender.cs +++ b/src/src/Services/EmailSender.cs @@ -14,24 +14,31 @@ public class EmailSender : IEmailSender public SendGridOptions _sendGridOptions { get; } public IDotnetdesk _dotnetdesk { get; } public SmtpOptions _smtpOptions { get; } + public SmtpLocalOptions _smtpLocalOptions { get; } public EmailSender(IOptions sendGridOptions, IDotnetdesk dotnetdesk, - IOptions smtpOptions) + IOptions smtpOptions, + IOptions smtpLocalOptions) { _sendGridOptions = sendGridOptions.Value; _dotnetdesk = dotnetdesk; _smtpOptions = smtpOptions.Value; + _smtpLocalOptions = smtpLocalOptions.Value; } public Task SendEmailAsync(string email, string subject, string message) { + _dotnetdesk.SendEmailLocallyAsync(true, subject, message, email, _smtpLocalOptions.fromEmail, _smtpLocalOptions.localDestination).Wait(); + + //send email using sendgrid via dotnetdesk - _dotnetdesk.SendEmailBySendGridAsync(_sendGridOptions.SendGridKey, - _sendGridOptions.FromEmail, - _sendGridOptions.FromFullName, - subject, - message, - email).Wait(); + // uncomment to use sendgrid via dotnetdesk + // _dotnetdesk.SendEmailBySendGridAsync(_sendGridOptions.SendGridKey, + // _sendGridOptions.FromEmail, + // _sendGridOptions.FromFullName, + // subject, + // message, + // email).Wait(); //send email using smtp via dotnetdesk. uncomment to use it /* diff --git a/src/src/Services/IDotnetdesk.cs b/src/src/Services/IDotnetdesk.cs index 0108e0a..0899167 100644 --- a/src/src/Services/IDotnetdesk.cs +++ b/src/src/Services/IDotnetdesk.cs @@ -28,6 +28,14 @@ Task SendEmailByGmailAsync(string fromEmail, int smtpPort, bool smtpSSL); + + Task SendEmailLocallyAsync( bool isBodyHtml + , string subject + , string body + , string toEmail + , string fromEmail + , string localDestination); + Task CreateDefaultOrganization(string applicationUserId, ApplicationDbContext context); diff --git a/src/src/Services/SmtpLocalOptions.cs b/src/src/Services/SmtpLocalOptions.cs new file mode 100644 index 0000000..cbff94a --- /dev/null +++ b/src/src/Services/SmtpLocalOptions.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace src.Services +{ + public class SmtpLocalOptions + { + public string localDestination {get; set;} + public string fromEmail { get; set; } + } +} diff --git a/src/src/Startup.cs b/src/src/Startup.cs index 1f296b0..04512cb 100644 --- a/src/src/Startup.cs +++ b/src/src/Startup.cs @@ -78,6 +78,9 @@ public void ConfigureServices(IServiceCollection services) // Get SMTP configuration options services.Configure(Configuration.GetSection("SmtpOptions")); + // Get SMTPLocal configuration options + services.Configure(Configuration.GetSection("SmtpLocal")); + services.AddMvc(); } diff --git a/src/src/Views/Shared/_LayoutAdminlte.cshtml b/src/src/Views/Shared/_LayoutAdminlte.cshtml index 9cd7316..c8c0c76 100644 --- a/src/src/Views/Shared/_LayoutAdminlte.cshtml +++ b/src/src/Views/Shared/_LayoutAdminlte.cshtml @@ -128,65 +128,65 @@ @if (appUser != null) { - } diff --git a/src/src/Views/Ticket/AddComment.cshtml b/src/src/Views/Ticket/AddComment.cshtml new file mode 100644 index 0000000..775474f --- /dev/null +++ b/src/src/Views/Ticket/AddComment.cshtml @@ -0,0 +1,37 @@ +@model src.Models.TicketThread +@{ + Layout = null; +} + + +
+
+
+ + +
+
+
+ + + +
+
+
+
+ + +
+ + + diff --git a/src/src/Views/Ticket/AddEdit.cshtml b/src/src/Views/Ticket/AddEdit.cshtml index f03c230..223ce67 100644 --- a/src/src/Views/Ticket/AddEdit.cshtml +++ b/src/src/Views/Ticket/AddEdit.cshtml @@ -13,6 +13,7 @@
+
diff --git a/src/src/Views/Ticket/Detail.cshtml b/src/src/Views/Ticket/Detail.cshtml new file mode 100644 index 0000000..1c4bc6c --- /dev/null +++ b/src/src/Views/Ticket/Detail.cshtml @@ -0,0 +1,137 @@ +@model src.Models.Ticket + +@{ + ViewData["Title"] = "Detail"; + Layout = "~/Views/Shared/_LayoutAdminlte.cshtml"; +} + + +
+
+
+
+
+ + + +
+
+
+ + +
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+ + +
+
+
+ + +
+
+
+ + +
+
+
+
+ +
+
+ +
+ + + + +@section Scripts{ + + @await Html.PartialAsync("_ValidationScriptsPartial") + + + +} + + diff --git a/src/src/Views/Ticket/Index.cshtml b/src/src/Views/Ticket/Index.cshtml index f0dbf92..7f0ac5a 100644 --- a/src/src/Views/Ticket/Index.cshtml +++ b/src/src/Views/Ticket/Index.cshtml @@ -17,8 +17,8 @@ - - + +
TicketTicket
diff --git a/src/src/Views/Ticket/ShowComments.cshtml b/src/src/Views/Ticket/ShowComments.cshtml new file mode 100644 index 0000000..b0ff55e --- /dev/null +++ b/src/src/Views/Ticket/ShowComments.cshtml @@ -0,0 +1,37 @@ +@model src.Models.TicketThread +@{ + Layout = null; +} + + +
+
+
+ + + + + + + + + +
CommentsAuthorTime
+
+
+
+ + + + + + diff --git a/src/src/appsettings.json b/src/src/appsettings.json index 3266480..9ee48e6 100644 --- a/src/src/appsettings.json +++ b/src/src/appsettings.json @@ -22,5 +22,9 @@ "smtpSSL": true, "fromEmail": "---your from email-------------------", "fromFullName": "---your from full name------------" + }, + "SmtpLocal":{ + "fromEmail": "info@dotnetdesk.com", + "localDestination": "C:\\Workspaces\\DotnetProjects\\maildump" } } diff --git a/src/src/wwwroot/js/views/ticket/detail.js b/src/src/wwwroot/js/views/ticket/detail.js new file mode 100644 index 0000000..9869aed --- /dev/null +++ b/src/src/wwwroot/js/views/ticket/detail.js @@ -0,0 +1,92 @@ +var popup, dataTable; +var entity = 'Ticket'; +var apiurl = '/api/' + entity; + +$(document).ready(function () { + var ticketId = $('#ticketId').val(); + dataTable = $('#grid').DataTable({ + "ajax": { + "url": apiurl + '/ShowTicketComments/' + ticketId, + "type": 'GET', + "datatype": 'json' + }, + "columns": [ + { "data": "comment"}, + { "data": "createBy" }, + { "data": "createAt" } + ], + "language": { + "emptyTable": "no data found." + }, + "lengthChange": false, + }); +}); + +function ShowPopup(url) { + var modalId = 'modalDefault'; + var modalPlaceholder = $('#' + modalId + ' .modal-dialog .modal-content'); + $.get(url) + .done(function (response) { + modalPlaceholder.html(response); + popup = $('#' + modalId + '').modal({ + keyboard: false, + backdrop: 'static' + }); + }); +} + + +function SubmitAddComment(form) { + $.validator.unobtrusive.parse(form); + if ($(form).valid()) { + var data = $(form).serializeJSON(); + data = JSON.stringify(data); + $.ajax({ + type: 'POST', + url: apiurl + '/PostTicketComment', + data: data, + contentType: 'application/json', + success: function (data) { + if (data.success) { + popup.modal('hide'); + ShowMessage(data.message); + dataTable.ajax.reload(); + } else { + ShowMessageError(data.message); + } + } + }); + + } + return false; +} + +function Delete(id) { + swal({ + title: "Are you sure want to Delete?", + text: "You will not be able to restore the data!", + type: "warning", + showCancelButton: true, + confirmButtonColor: "#dd4b39", + confirmButtonText: "Yes, delete it!", + closeOnConfirm: true + }, function () { + $.ajax({ + type: 'DELETE', + url: apiurl + '/' + id, + success: function (data) { + if (data.success) { + ShowMessage(data.message); + dataTable.ajax.reload(); + } else { + ShowMessageError(data.message); + } + } + }); + }); + + +} + + + diff --git a/src/src/wwwroot/js/views/ticket/index.js b/src/src/wwwroot/js/views/ticket/index.js index a9bf224..3a7125c 100644 --- a/src/src/wwwroot/js/views/ticket/index.js +++ b/src/src/wwwroot/js/views/ticket/index.js @@ -15,9 +15,10 @@ $(document).ready(function () { { "data": "ticketId", "render": function (data) { + var btnDetail = ""; var btnEdit = ""; var btnDelete = ""; - return btnEdit + btnDelete; + return btnDetail + btnEdit + btnDelete; } } ],