Real time email event tracking completed
This commit is contained in:
parent
e80a2675e6
commit
4fb4e979e6
34 changed files with 3664 additions and 126 deletions
|
|
@ -35,6 +35,8 @@ namespace Data
|
||||||
public DbSet<ResponseDetail> ResponseDetails { get; set; }
|
public DbSet<ResponseDetail> ResponseDetails { get; set; }
|
||||||
public DbSet<ResponseAnswer> ResponseAnswers { get; set; }
|
public DbSet<ResponseAnswer> ResponseAnswers { get; set; }
|
||||||
|
|
||||||
|
public DbSet<SentNewsletterEamil> SentNewsletterEamils { get; set; }
|
||||||
|
|
||||||
|
|
||||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
26
Model/SentNewsletterEamil.cs
Normal file
26
Model/SentNewsletterEamil.cs
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Model
|
||||||
|
{
|
||||||
|
public class SentNewsletterEamil
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public string? RecipientEmail { get; set; }
|
||||||
|
public string? Subject { get; set; }
|
||||||
|
public string? Body { get; set; }
|
||||||
|
public DateTime SentDate { get; set; }
|
||||||
|
public bool IsDelivered { get; set; }
|
||||||
|
public bool IsOpened { get; set; }
|
||||||
|
public bool IsClicked { get; set; }
|
||||||
|
public bool IsBounced { get; set; }
|
||||||
|
public bool IsSpam { get; set; }
|
||||||
|
public bool IsSent { get; set; }
|
||||||
|
public bool IsUnsubscribed { get; set; }
|
||||||
|
public bool IsBlocked { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
19
Services/EmailSend/EmailStatistic.cs
Normal file
19
Services/EmailSend/EmailStatistic.cs
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Services.EmailSend
|
||||||
|
{
|
||||||
|
public class EmailStatistic
|
||||||
|
{
|
||||||
|
public int TotalEmails { get; set; }
|
||||||
|
public int Delivered { get; set; }
|
||||||
|
public int Opened { get; set; }
|
||||||
|
public int Clicked { get; set; }
|
||||||
|
public int Bounced { get; set; }
|
||||||
|
public int Blocked { get; set; }
|
||||||
|
public int MarkedAsSpam { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
69
Services/Implemnetation/EmailStatsService.cs
Normal file
69
Services/Implemnetation/EmailStatsService.cs
Normal file
|
|
@ -0,0 +1,69 @@
|
||||||
|
using Mailjet.Client.Resources;
|
||||||
|
using Mailjet.Client;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using Services.EmailSend;
|
||||||
|
using Services.Interaces;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Services.Implemnetation
|
||||||
|
{
|
||||||
|
public class EmailStatsService: IEmailStatsService
|
||||||
|
{
|
||||||
|
private readonly IConfiguration _configuration;
|
||||||
|
|
||||||
|
public EmailStatsService(IConfiguration configuration)
|
||||||
|
{
|
||||||
|
_configuration = configuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<EmailStatistic> FetchEmailStatsAsync()
|
||||||
|
{
|
||||||
|
|
||||||
|
var apiKey = _configuration["MailJet:ApiKey"];
|
||||||
|
var apiSecret = _configuration["MailJet:SecretKey"];
|
||||||
|
|
||||||
|
MailjetClient client = new MailjetClient(apiKey, apiSecret);
|
||||||
|
|
||||||
|
|
||||||
|
// Construct the request to get statistics
|
||||||
|
MailjetRequest request = new MailjetRequest
|
||||||
|
{
|
||||||
|
Resource = Statcounters.Resource,
|
||||||
|
}
|
||||||
|
.Property(Statcounters.CounterSource, "APIKey") // assuming you want statistics based on API Key usage
|
||||||
|
.Property(Statcounters.CounterTiming, "Message") // assuming you want statistics about messages
|
||||||
|
.Property(Statcounters.CounterResolution, "Lifetime"); // assuming you want lifetime statistics
|
||||||
|
|
||||||
|
// Execute the request
|
||||||
|
MailjetResponse response = await client.GetAsync(request);
|
||||||
|
if (response.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
return ParseEmailStats(response.GetData());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException($"Failed to fetch data: {response.StatusCode}, {response.GetErrorMessage()}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private EmailStatistic ParseEmailStats(JToken data)
|
||||||
|
{
|
||||||
|
EmailStatistic stats = new EmailStatistic
|
||||||
|
{
|
||||||
|
TotalEmails = data[0]["Total"].Value<int>(),
|
||||||
|
Delivered = data[0]["Delivered"].Value<int>(),
|
||||||
|
Opened = data[0]["Opened"].Value<int>(),
|
||||||
|
Clicked = data[0]["Clicked"].Value<int>(),
|
||||||
|
Bounced = data[0]["Bounced"].Value<int>(),
|
||||||
|
Blocked = data[0]["Blocked"].Value<int>(),
|
||||||
|
MarkedAsSpam = data[0]["Spam"].Value<int>()
|
||||||
|
};
|
||||||
|
return stats;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
14
Services/Interaces/IEmailStatsService.cs
Normal file
14
Services/Interaces/IEmailStatsService.cs
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
using Services.EmailSend;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Services.Interaces
|
||||||
|
{
|
||||||
|
public interface IEmailStatsService
|
||||||
|
{
|
||||||
|
Task<EmailStatistic> FetchEmailStatsAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -6,7 +6,7 @@ using Web.ViewModel.AddressVM;
|
||||||
|
|
||||||
namespace Web.Areas.Admin.Controllers
|
namespace Web.Areas.Admin.Controllers
|
||||||
{
|
{
|
||||||
[Authorize(Roles ="Admin")]
|
|
||||||
public class AddressController : Controller
|
public class AddressController : Controller
|
||||||
{
|
{
|
||||||
private readonly IAddressRepository _addresContext;
|
private readonly IAddressRepository _addresContext;
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ using Web.ViewModel.BannerVM;
|
||||||
namespace Web.Areas.Admin.Controllers
|
namespace Web.Areas.Admin.Controllers
|
||||||
{
|
{
|
||||||
|
|
||||||
[Authorize(Roles = "Admin")]
|
|
||||||
public class BannerController : Controller
|
public class BannerController : Controller
|
||||||
{
|
{
|
||||||
private readonly IBannerRepository _banner;
|
private readonly IBannerRepository _banner;
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ using static Microsoft.EntityFrameworkCore.DbLoggerCategory;
|
||||||
namespace Web.Areas.Admin.Controllers
|
namespace Web.Areas.Admin.Controllers
|
||||||
{
|
{
|
||||||
|
|
||||||
[Authorize(Roles = "Admin")]
|
|
||||||
public class FooterController : Controller
|
public class FooterController : Controller
|
||||||
{
|
{
|
||||||
private readonly IFooterRepository _footer;
|
private readonly IFooterRepository _footer;
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,11 @@ using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.CodeAnalysis;
|
using Microsoft.CodeAnalysis;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.Extensions.Caching.Memory;
|
||||||
using Microsoft.VisualStudio.TextTemplating;
|
using Microsoft.VisualStudio.TextTemplating;
|
||||||
using Microsoft.VisualStudio.Web.CodeGenerators.Mvc.Templates.BlazorIdentity.Pages.Manage;
|
using Microsoft.VisualStudio.Web.CodeGenerators.Mvc.Templates.BlazorIdentity.Pages.Manage;
|
||||||
|
using Model;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
using OpenAI_API;
|
using OpenAI_API;
|
||||||
using Services.EmailSend;
|
using Services.EmailSend;
|
||||||
using Services.Implemnetation;
|
using Services.Implemnetation;
|
||||||
|
|
@ -15,13 +18,14 @@ using Web.ViewModel.NewsLetterVM;
|
||||||
namespace Web.Areas.Admin.Controllers
|
namespace Web.Areas.Admin.Controllers
|
||||||
{
|
{
|
||||||
|
|
||||||
[Authorize(Roles = "Admin")]
|
|
||||||
public class NewslettersController : Controller
|
public class NewslettersController : Controller
|
||||||
{
|
{
|
||||||
private readonly INewsLetterRepository _repository;
|
private readonly INewsLetterRepository _repository;
|
||||||
private readonly SurveyContext _context;
|
private readonly SurveyContext _context;
|
||||||
private readonly IEmailServices _emailServices;
|
private readonly IEmailServices _emailServices;
|
||||||
private readonly IConfiguration _configuration;
|
private readonly IConfiguration _configuration;
|
||||||
|
private readonly IMemoryCache _memoryCache;
|
||||||
|
|
||||||
public NewslettersController(INewsLetterRepository repository,SurveyContext context,IEmailServices emailServices,IConfiguration configuration)
|
public NewslettersController(INewsLetterRepository repository,SurveyContext context,IEmailServices emailServices,IConfiguration configuration)
|
||||||
{
|
{
|
||||||
|
|
@ -29,6 +33,7 @@ namespace Web.Areas.Admin.Controllers
|
||||||
_context = context;
|
_context = context;
|
||||||
_emailServices = emailServices;
|
_emailServices = emailServices;
|
||||||
_configuration = configuration;
|
_configuration = configuration;
|
||||||
|
|
||||||
}
|
}
|
||||||
public IActionResult Index()
|
public IActionResult Index()
|
||||||
{
|
{
|
||||||
|
|
@ -63,110 +68,343 @@ namespace Web.Areas.Admin.Controllers
|
||||||
return View();
|
return View();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
|
|
||||||
public async Task<IActionResult> Create(SendNewsLetterViewModel viewModel)
|
public async Task<IActionResult> Create(SendNewsLetterViewModel viewModel)
|
||||||
{
|
{
|
||||||
if(ModelState.IsValid)
|
if (ModelState.IsValid)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Retrieve all subscribed users
|
// Retrieve all subscribed users
|
||||||
var subscribedUsers = await _context.Subscriptions.Where(s => s.IsSubscribed).ToListAsync();
|
var subscribedUsers = await _context.Subscriptions.Where(s => s.IsSubscribed).ToListAsync();
|
||||||
|
|
||||||
|
string confirmationPath = _configuration["Email:unsubscribePath"];
|
||||||
string confirmationPath = _configuration["Email:unsubscribePath"];
|
// Send the newsletter email to each subscribed user
|
||||||
// Send the newsletter email to each subscribed user
|
foreach (var user in subscribedUsers)
|
||||||
foreach (var user in subscribedUsers)
|
{
|
||||||
{
|
string confirmationUrl = $"{Request.Scheme}://{Request.Host}/{confirmationPath}?email={user.Email}";
|
||||||
string confirmationUrl = $"{Request.Scheme}://{Request.Host}/{confirmationPath}?email={user.Email}";
|
|
||||||
//string emailBody = $"<h4>Hey {user.Name}</h4><br>{viewModel.Body}<br><h5>Søren Eggert Lundsteen Olsen<br>Seosoft ApS</h5><hr><h6>Hovedgaden 3<br>Jordrup<br>Kolding 6064<br>Denmark</h6><br/><br/><div style='text-align: center;'><a href='{confirmationUrl}' style='display: inline-block; background-color: #6c757d; color: #fff; padding: 4px 8px; text-decoration: none; border-radius: 4px;'>Unsubscribe</a></div>";
|
|
||||||
string emailBody = $@"<head>
|
string emailBody = $@"<head>
|
||||||
<meta charset=""UTF-8"">
|
<meta charset=""UTF-8"">
|
||||||
<meta name=""viewport"" content=""width=device-width, initial-scale=1.0"">
|
<meta name=""viewport"" content=""width=device-width, initial-scale=1.0"">
|
||||||
<title>Email Confirmation</title>
|
<title>Email Confirmation</title>
|
||||||
<style>
|
<style>
|
||||||
body {{
|
body {{
|
||||||
font-family: Arial, sans-serif;
|
font-family: Arial, sans-serif;
|
||||||
line-height: 1.6;
|
line-height: 1.6;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
background-color: #f9f9f9;
|
background-color: #f9f9f9;
|
||||||
}}
|
}}
|
||||||
.container {{
|
.container {{
|
||||||
max-width: 800px;
|
max-width: 800px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
border: 0.5px solid #ccc;
|
border: 0.5px solid #ccc;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
background-color: #f9f9f9;
|
background-color: #f9f9f9;
|
||||||
}}
|
}}
|
||||||
h4, h5, h6 {{
|
h4, h5, h6 {{
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}}
|
}}
|
||||||
hr {{
|
hr {{
|
||||||
border: none;
|
border: none;
|
||||||
border-top: 1px solid #ccc;
|
border-top: 1px solid #ccc;
|
||||||
margin: 10px 0;
|
margin: 10px 0;
|
||||||
}}
|
}}
|
||||||
a.button {{
|
a.button {{
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
padding: 5px 10px;
|
padding: 5px 10px;
|
||||||
background-color: #6c757d;
|
background-color: #6c757d;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
}}
|
}}
|
||||||
a.button:hover {{
|
a.button:hover {{
|
||||||
background-color: #5a6268;
|
background-color: #5a6268;
|
||||||
}}
|
}}
|
||||||
a {{
|
a {{
|
||||||
color: #007bff;
|
color: #007bff;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}}
|
}}
|
||||||
a:hover {{
|
a:hover {{
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}}
|
}}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class=""container"">
|
<div class=""container"">
|
||||||
<h4>Hey {user.Name},</h4>
|
<h4>Hey {user.Name},</h4>
|
||||||
<p>{viewModel.Body}</p><br>
|
<p>{viewModel.Body}</p><br>
|
||||||
|
|
||||||
<h5>Søren Eggert Lundsteen Olsen</h5>
|
<h5>Søren Eggert Lundsteen Olsen</h5>
|
||||||
<h5><a href=""https://www.seosoft.dk/"" target=""_blank"">SeoSoft ApS</a></h5>
|
<h5><a href=""https://www.seosoft.dk/"" target=""_blank"">SeoSoft ApS</a></h5>
|
||||||
<hr>
|
<hr>
|
||||||
<h6>Hovedgaden 3<br>Jordrup<br>Kolding 6064<br>Denmark</h6>
|
<h6>Hovedgaden 3<br>Jordrup<br>Kolding 6064<br>Denmark</h6>
|
||||||
<div style=""text-align: center;"">
|
<div style=""text-align: center;"">
|
||||||
<a href=""{confirmationUrl}"" class=""button"">Unsubscribe</a>
|
<a href=""{confirmationUrl}"" class=""button"">Unsubscribe</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</body>";
|
</body>";
|
||||||
var email = new EmailToSend(user.Email, viewModel.Subject, emailBody);
|
|
||||||
var isSent = await _emailServices.SendConfirmationEmailAsync(email);
|
|
||||||
|
|
||||||
// Handle failure to send email if needed
|
var email = new EmailToSend(user.Email, viewModel.Subject, emailBody);
|
||||||
|
var isSent = await _emailServices.SendConfirmationEmailAsync(email);
|
||||||
|
|
||||||
|
// Create a record for the sent email
|
||||||
|
var sentEmail = new SentNewsletterEamil
|
||||||
|
{
|
||||||
|
RecipientEmail = user.Email,
|
||||||
|
Subject = viewModel.Subject,
|
||||||
|
Body = emailBody,
|
||||||
|
|
||||||
}
|
SentDate = DateTime.UtcNow,
|
||||||
|
IsSent = isSent // Assuming isSent returns a boolean indicating success
|
||||||
|
};
|
||||||
|
_context.SentNewsletterEamils.Add(sentEmail);
|
||||||
|
|
||||||
TempData["success"] = "Nesletter sent successfully.";
|
// Handle failure to send email if needed
|
||||||
return RedirectToAction(nameof(Index));
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
await _context.SaveChangesAsync(); // Save changes for all sent emails
|
||||||
|
|
||||||
|
TempData["success"] = "Newsletter sent successfully.";
|
||||||
|
return RedirectToAction(nameof(Index));
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
// Log or handle the exception as needed
|
// Log or handle the exception as needed
|
||||||
TempData["success"] = "something went wrong.";
|
TempData["error"] = "Something went wrong: " + ex.Message;
|
||||||
return RedirectToAction(nameof(Index));
|
return RedirectToAction(nameof(Index));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return View(viewModel);
|
return View(viewModel);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
|
public async Task<IActionResult> MailjetWebhook()
|
||||||
|
{
|
||||||
|
using (var reader = new StreamReader(Request.Body))
|
||||||
|
{
|
||||||
|
var requestBody = await reader.ReadToEndAsync();
|
||||||
|
Console.WriteLine("Received payload: " + requestBody);
|
||||||
|
Request.Body.Position = 0;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var events = JArray.Parse(requestBody);
|
||||||
|
if (events == null)
|
||||||
|
{
|
||||||
|
return BadRequest("Parsed data is null");
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (JObject e in events)
|
||||||
|
{
|
||||||
|
string email = e.Value<string>("email");
|
||||||
|
string eventType = e.Value<string>("event");
|
||||||
|
Console.WriteLine($"Processing {eventType} for {email}");
|
||||||
|
|
||||||
|
var newsletterEmail = await _context.SentNewsletterEamils
|
||||||
|
.FirstOrDefaultAsync(n => n.RecipientEmail == email);
|
||||||
|
|
||||||
|
if (newsletterEmail == null)
|
||||||
|
{
|
||||||
|
Console.WriteLine("No newsletter email record found for email: " + email);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (eventType)
|
||||||
|
{
|
||||||
|
case "sent":
|
||||||
|
newsletterEmail.IsDelivered = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "open":
|
||||||
|
newsletterEmail.IsOpened = true;
|
||||||
|
break;
|
||||||
|
case "click":
|
||||||
|
newsletterEmail.IsClicked = true;
|
||||||
|
break;
|
||||||
|
case "bounce":
|
||||||
|
newsletterEmail.IsBounced = true;
|
||||||
|
break;
|
||||||
|
case "spam":
|
||||||
|
newsletterEmail.IsSpam = true;
|
||||||
|
break;
|
||||||
|
case "unsub":
|
||||||
|
newsletterEmail.IsUnsubscribed = true;
|
||||||
|
break;
|
||||||
|
case "blocked":
|
||||||
|
newsletterEmail.IsBlocked = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Console.WriteLine($"Unhandled event type: {eventType}");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
_context.Entry(newsletterEmail).State = EntityState.Modified;
|
||||||
|
}
|
||||||
|
Console.WriteLine("Email got updated ");
|
||||||
|
|
||||||
|
await _context.SaveChangesAsync();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Exception parsing JSON: " + ex.Message);
|
||||||
|
return BadRequest("Error parsing JSON: " + ex.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public async Task<IActionResult> EmailStats()
|
||||||
|
{
|
||||||
|
var emails = await _context.SentNewsletterEamils.ToListAsync();
|
||||||
|
return View(emails);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IActionResult> GetEmailStatsData()
|
||||||
|
{
|
||||||
|
var model = await _context.SentNewsletterEamils.ToListAsync();
|
||||||
|
return Json(model); // Returns the list of emails as JSON.
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<JsonResult> GetChartData()
|
||||||
|
{
|
||||||
|
var emails = await _context.SentNewsletterEamils.ToListAsync();
|
||||||
|
|
||||||
|
var data = new
|
||||||
|
{
|
||||||
|
Sent = emails.Count(e => e.IsSent),
|
||||||
|
Delivered = emails.Count(e => e.IsDelivered),
|
||||||
|
Opened = emails.Count(e => e.IsOpened),
|
||||||
|
Clicked = emails.Count(e => e.IsClicked),
|
||||||
|
Bounced = emails.Count(e => e.IsBounced),
|
||||||
|
Spam = emails.Count(e => e.IsSpam),
|
||||||
|
Blocked = emails.Count(e => e.IsBlocked),
|
||||||
|
Unsubscribed = emails.Count(e => e.IsUnsubscribed)
|
||||||
|
};
|
||||||
|
|
||||||
|
return Json(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//[HttpPost]
|
||||||
|
//public async Task<IActionResult> Create(SendNewsLetterViewModel viewModel)
|
||||||
|
//{
|
||||||
|
// if(ModelState.IsValid)
|
||||||
|
// {
|
||||||
|
// try
|
||||||
|
// {
|
||||||
|
// // Retrieve all subscribed users
|
||||||
|
// var subscribedUsers = await _context.Subscriptions.Where(s => s.IsSubscribed).ToListAsync();
|
||||||
|
|
||||||
|
|
||||||
|
// string confirmationPath = _configuration["Email:unsubscribePath"];
|
||||||
|
// // Send the newsletter email to each subscribed user
|
||||||
|
// foreach (var user in subscribedUsers)
|
||||||
|
// {
|
||||||
|
// string confirmationUrl = $"{Request.Scheme}://{Request.Host}/{confirmationPath}?email={user.Email}";
|
||||||
|
|
||||||
|
// string emailBody = $@"<head>
|
||||||
|
// <meta charset=""UTF-8"">
|
||||||
|
// <meta name=""viewport"" content=""width=device-width, initial-scale=1.0"">
|
||||||
|
// <title>Email Confirmation</title>
|
||||||
|
// <style>
|
||||||
|
// body {{
|
||||||
|
// font-family: Arial, sans-serif;
|
||||||
|
// line-height: 1.6;
|
||||||
|
// margin: 0;
|
||||||
|
// padding: 0;
|
||||||
|
// background-color: #f9f9f9;
|
||||||
|
// }}
|
||||||
|
// .container {{
|
||||||
|
// max-width: 800px;
|
||||||
|
// margin: 0 auto;
|
||||||
|
// padding: 20px;
|
||||||
|
// border: 0.5px solid #ccc;
|
||||||
|
// border-radius: 5px;
|
||||||
|
// background-color: #f9f9f9;
|
||||||
|
// }}
|
||||||
|
// h4, h5, h6 {{
|
||||||
|
// margin: 0;
|
||||||
|
// }}
|
||||||
|
// hr {{
|
||||||
|
// border: none;
|
||||||
|
// border-top: 1px solid #ccc;
|
||||||
|
// margin: 10px 0;
|
||||||
|
// }}
|
||||||
|
// a.button {{
|
||||||
|
// display: inline-block;
|
||||||
|
// padding: 5px 10px;
|
||||||
|
// background-color: #6c757d;
|
||||||
|
// color: #fff;
|
||||||
|
// text-decoration: none;
|
||||||
|
// border-radius: 4px;
|
||||||
|
// }}
|
||||||
|
// a.button:hover {{
|
||||||
|
// background-color: #5a6268;
|
||||||
|
// }}
|
||||||
|
// a {{
|
||||||
|
// color: #007bff;
|
||||||
|
// text-decoration: none;
|
||||||
|
// }}
|
||||||
|
// a:hover {{
|
||||||
|
// text-decoration: underline;
|
||||||
|
// }}
|
||||||
|
// </style>
|
||||||
|
// </head>
|
||||||
|
// <body>
|
||||||
|
// <div class=""container"">
|
||||||
|
// <h4>Hey {user.Name},</h4>
|
||||||
|
// <p>{viewModel.Body}</p><br>
|
||||||
|
|
||||||
|
// <h5>Søren Eggert Lundsteen Olsen</h5>
|
||||||
|
// <h5><a href=""https://www.seosoft.dk/"" target=""_blank"">SeoSoft ApS</a></h5>
|
||||||
|
// <hr>
|
||||||
|
// <h6>Hovedgaden 3<br>Jordrup<br>Kolding 6064<br>Denmark</h6>
|
||||||
|
// <div style=""text-align: center;"">
|
||||||
|
// <a href=""{confirmationUrl}"" class=""button"">Unsubscribe</a>
|
||||||
|
// </div>
|
||||||
|
// </div>
|
||||||
|
// </body>";
|
||||||
|
// var email = new EmailToSend(user.Email, viewModel.Subject, emailBody);
|
||||||
|
// var isSent = await _emailServices.SendConfirmationEmailAsync(email);
|
||||||
|
|
||||||
|
// // Handle failure to send email if needed
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
|
// TempData["success"] = "Nesletter sent successfully.";
|
||||||
|
// return RedirectToAction(nameof(Index));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// }
|
||||||
|
// catch (Exception)
|
||||||
|
// {
|
||||||
|
// // Log or handle the exception as needed
|
||||||
|
// TempData["success"] = "something went wrong.";
|
||||||
|
// return RedirectToAction(nameof(Index));
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// return View(viewModel);
|
||||||
|
|
||||||
|
|
||||||
|
//}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
public IActionResult Delete(int id)
|
public IActionResult Delete(int id)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ using System.Text;
|
||||||
namespace Web.Areas.Admin.Controllers
|
namespace Web.Areas.Admin.Controllers
|
||||||
{
|
{
|
||||||
|
|
||||||
[Authorize(Roles = "Admin")]
|
|
||||||
public class OpenAIContentController : Controller
|
public class OpenAIContentController : Controller
|
||||||
{
|
{
|
||||||
private readonly IConfiguration _configuration;
|
private readonly IConfiguration _configuration;
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ using Web.ViewModel.PageVM;
|
||||||
namespace Web.Areas.Admin.Controllers
|
namespace Web.Areas.Admin.Controllers
|
||||||
{
|
{
|
||||||
|
|
||||||
[Authorize(Roles = "Admin")]
|
|
||||||
public class PageController : Controller
|
public class PageController : Controller
|
||||||
{
|
{
|
||||||
private readonly IPageRepository _pageRepository;
|
private readonly IPageRepository _pageRepository;
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ namespace Web.Areas.Admin.Controllers
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
[Authorize(Roles = "Admin")]
|
|
||||||
public class QuestionnaireController : Controller
|
public class QuestionnaireController : Controller
|
||||||
{
|
{
|
||||||
private readonly IQuestionnaireRepository _questionnaire;
|
private readonly IQuestionnaireRepository _questionnaire;
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ using Microsoft.AspNetCore.Mvc;
|
||||||
namespace Web.Areas.Admin.Controllers
|
namespace Web.Areas.Admin.Controllers
|
||||||
{
|
{
|
||||||
|
|
||||||
[Authorize(Roles = "Admin")]
|
|
||||||
public class RegisterController : Controller
|
public class RegisterController : Controller
|
||||||
{
|
{
|
||||||
public IActionResult Index()
|
public IActionResult Index()
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ using Web.ViewModel.AccountVM;
|
||||||
namespace Web.Areas.Admin.Controllers
|
namespace Web.Areas.Admin.Controllers
|
||||||
{
|
{
|
||||||
|
|
||||||
[Authorize(Roles = "Admin")]
|
|
||||||
public class RolesController : Controller
|
public class RolesController : Controller
|
||||||
{
|
{
|
||||||
private readonly RoleManager<IdentityRole> _roleManager;
|
private readonly RoleManager<IdentityRole> _roleManager;
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ using Web.ViewModel.SocialMediaVM;
|
||||||
namespace Web.Areas.Admin.Controllers
|
namespace Web.Areas.Admin.Controllers
|
||||||
{
|
{
|
||||||
|
|
||||||
[Authorize(Roles = "Admin")]
|
|
||||||
public class SocialMediaController : Controller
|
public class SocialMediaController : Controller
|
||||||
{
|
{
|
||||||
private readonly ISocialMediaRepository _context;
|
private readonly ISocialMediaRepository _context;
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ using Microsoft.AspNetCore.Authorization;
|
||||||
namespace Web.Areas.Admin.Controllers
|
namespace Web.Areas.Admin.Controllers
|
||||||
{
|
{
|
||||||
|
|
||||||
[Authorize(Roles = "Admin")]
|
|
||||||
public class SurveyAnalysisController : Controller
|
public class SurveyAnalysisController : Controller
|
||||||
{
|
{
|
||||||
private readonly SurveyContext _context;
|
private readonly SurveyContext _context;
|
||||||
|
|
@ -39,6 +39,8 @@ namespace Web.Areas.Admin.Controllers
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
public IActionResult Analysis(int id)
|
public IActionResult Analysis(int id)
|
||||||
{
|
{
|
||||||
|
|
@ -113,35 +115,6 @@ namespace Web.Areas.Admin.Controllers
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//[HttpGet]
|
|
||||||
//public IActionResult GenerateReport(int id)
|
|
||||||
//{
|
|
||||||
// var viewModel = GetQuestionnaireData(id);
|
|
||||||
// if (viewModel == null)
|
|
||||||
// {
|
|
||||||
// return NotFound("No questionnaire found with the given ID.");
|
|
||||||
// }
|
|
||||||
|
|
||||||
// var webReport = new WebReport();
|
|
||||||
|
|
||||||
// // Load your FastReport report design
|
|
||||||
// webReport.Report.Load(Path.Combine(env.WebRootPath, "Reports", "QuestionnaireReport.frx"));
|
|
||||||
|
|
||||||
// // Register the data source
|
|
||||||
// webReport.Report.RegisterData(new[] { viewModel }, "Questionnaire");
|
|
||||||
|
|
||||||
// webReport.Report.Prepare();
|
|
||||||
|
|
||||||
// using (MemoryStream ms = new MemoryStream())
|
|
||||||
// {
|
|
||||||
// webReport.Report.Export(new FastReport.Export.PdfSimple.PDFSimpleExport(), ms);
|
|
||||||
// return File(ms.ToArray(), "application/pdf", "QuestionnaireReport.pdf");
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ using Model;
|
||||||
namespace Web.Areas.Admin.Controllers
|
namespace Web.Areas.Admin.Controllers
|
||||||
{
|
{
|
||||||
|
|
||||||
[Authorize(Roles = "Admin")]
|
|
||||||
public class UserResponseController : Controller
|
public class UserResponseController : Controller
|
||||||
{
|
{
|
||||||
private readonly SurveyContext _context;
|
private readonly SurveyContext _context;
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ using Web.ViewModel.AccountVM;
|
||||||
|
|
||||||
namespace Web.Areas.Admin.Controllers
|
namespace Web.Areas.Admin.Controllers
|
||||||
{
|
{
|
||||||
[Authorize(Roles = "Admin")]
|
|
||||||
public class UsersController : Controller
|
public class UsersController : Controller
|
||||||
{
|
{
|
||||||
private readonly UserManager<ApplicationUser> _userManager;
|
private readonly UserManager<ApplicationUser> _userManager;
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
<h4 class="card-title">Survey analysis list</h4>
|
<h4 class="card-title">Survey analysis list</h4>
|
||||||
|
|
||||||
|
|
||||||
<form asp-action="DeleteMultiple" method="post">
|
<form asp-action="DeleteUnusedQuestionnaires" method="post">
|
||||||
|
|
||||||
<table class="table table-responsive w-100 d-block d-md-table table-hover ">
|
<table class="table table-responsive w-100 d-block d-md-table table-hover ">
|
||||||
<thead class="w-100">
|
<thead class="w-100">
|
||||||
|
|
|
||||||
|
|
@ -9,4 +9,7 @@
|
||||||
@using Web.ViewModel.QuestionnaireVM
|
@using Web.ViewModel.QuestionnaireVM
|
||||||
@using Web.ViewModel.PageVM
|
@using Web.ViewModel.PageVM
|
||||||
@using Web.ViewModel.AccountVM
|
@using Web.ViewModel.AccountVM
|
||||||
|
@using Web.ViewModel.NewsLetterVM
|
||||||
|
@using Services.EmailSend
|
||||||
|
|
||||||
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
|
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
|
||||||
|
|
|
||||||
284
Web/Areas/Admin/Views/newsletters/EmailStats.cshtml
Normal file
284
Web/Areas/Admin/Views/newsletters/EmailStats.cshtml
Normal file
|
|
@ -0,0 +1,284 @@
|
||||||
|
@model IEnumerable<Model.SentNewsletterEamil>
|
||||||
|
|
||||||
|
@{
|
||||||
|
ViewData["Title"] = "EmailStats";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.badge-Sent{
|
||||||
|
display: inline-block;
|
||||||
|
padding: 0.25em 0.4em;
|
||||||
|
font-size: 75%;
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: 1;
|
||||||
|
text-align: center;
|
||||||
|
white-space: nowrap;
|
||||||
|
vertical-align: baseline;
|
||||||
|
border-radius: 0.25rem;
|
||||||
|
color: #fff;
|
||||||
|
background-color: #6831c5;
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge-Deliverd{
|
||||||
|
display: inline-block;
|
||||||
|
padding: 0.25em 0.4em;
|
||||||
|
font-size: 75%;
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: 1;
|
||||||
|
text-align: center;
|
||||||
|
white-space: nowrap;
|
||||||
|
vertical-align: baseline;
|
||||||
|
border-radius: 0.25rem;
|
||||||
|
color: #fff;
|
||||||
|
background-color: #44aebd;
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge-Opend {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 0.25em 0.4em;
|
||||||
|
font-size: 75%;
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: 1;
|
||||||
|
text-align: center;
|
||||||
|
white-space: nowrap;
|
||||||
|
vertical-align: baseline;
|
||||||
|
border-radius: 0.25rem;
|
||||||
|
color: #fff;
|
||||||
|
background-color: #22a877;
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge-Clicked {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 0.25em 0.4em;
|
||||||
|
font-size: 75%;
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: 1;
|
||||||
|
text-align: center;
|
||||||
|
white-space: nowrap;
|
||||||
|
vertical-align: baseline;
|
||||||
|
border-radius: 0.25rem;
|
||||||
|
color: #fff;
|
||||||
|
background-color: #3b76cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge-Bounced {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 0.25em 0.4em;
|
||||||
|
font-size: 75%;
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: 1;
|
||||||
|
text-align: center;
|
||||||
|
white-space: nowrap;
|
||||||
|
vertical-align: baseline;
|
||||||
|
border-radius: 0.25rem;
|
||||||
|
color: #fff;
|
||||||
|
background-color: #9585f4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge-Spam {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 0.25em 0.4em;
|
||||||
|
font-size: 75%;
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: 1;
|
||||||
|
text-align: center;
|
||||||
|
white-space: nowrap;
|
||||||
|
vertical-align: baseline;
|
||||||
|
border-radius: 0.25rem;
|
||||||
|
color: #fff;
|
||||||
|
background-color: #f06b66;
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge-Blocked {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 0.25em 0.4em;
|
||||||
|
font-size: 75%;
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: 1;
|
||||||
|
text-align: center;
|
||||||
|
white-space: nowrap;
|
||||||
|
vertical-align: baseline;
|
||||||
|
border-radius: 0.25rem;
|
||||||
|
color: #fff;
|
||||||
|
background-color: #98712d;
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge-Unsubscribed {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 0.25em 0.4em;
|
||||||
|
font-size: 75%;
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: 1;
|
||||||
|
text-align: center;
|
||||||
|
white-space: nowrap;
|
||||||
|
vertical-align: baseline;
|
||||||
|
border-radius: 0.25rem;
|
||||||
|
color: #fff;
|
||||||
|
background-color: #cb4a49;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<div class="container-fluid mt-4 mb-5">
|
||||||
|
<div class="col-10 offset-1">
|
||||||
|
<p>
|
||||||
|
<a asp-action="Index" class="btn btn-primary btn-sm">Back to list</a>
|
||||||
|
</p>
|
||||||
|
<h1>EmailStats</h1>
|
||||||
|
|
||||||
|
<table class="table table-responsive w-100 d-block d-md-table table-bordered table-hover">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Recipient</th>
|
||||||
|
<th>Sent Date</th>
|
||||||
|
<th>Subject</th>
|
||||||
|
<th>Sent</th>
|
||||||
|
<th>Delivered</th>
|
||||||
|
<th>Opened</th>
|
||||||
|
<th>Clicked</th>
|
||||||
|
<th>Bounced</th>
|
||||||
|
<th>Spam</th>
|
||||||
|
<th>Blocked</th>
|
||||||
|
<th>Unsubscribed</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
@foreach (var item in Model)
|
||||||
|
{
|
||||||
|
<tr>
|
||||||
|
<td>@item.RecipientEmail</td>
|
||||||
|
<td>@item.SentDate</td>
|
||||||
|
<td>@item.Subject</td>
|
||||||
|
<td>
|
||||||
|
@if (item.IsSent)
|
||||||
|
{
|
||||||
|
<span class="badge-Sent">Sent</span>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<span class="badge badge-secondary">Pending</span>
|
||||||
|
}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
@if (item.IsDelivered)
|
||||||
|
{
|
||||||
|
<span class="badge-Deliverd">Delivered</span>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<span class="badge badge-secondary">Pending</span>
|
||||||
|
}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
@if (item.IsOpened)
|
||||||
|
{
|
||||||
|
<span class="badge-Opend">Opened</span>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<span class="badge badge-secondary">Pending</span>
|
||||||
|
}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
@if (item.IsClicked)
|
||||||
|
{
|
||||||
|
<span class="badge-Clicked">Clicked</span>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<span class="badge badge-secondary">Pending</span>
|
||||||
|
}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
@if (item.IsBounced)
|
||||||
|
{
|
||||||
|
<span class="badge-Bounced">Bounced</span>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<span class="badge badge-secondary">Normal</span>
|
||||||
|
}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
@if (item.IsSpam)
|
||||||
|
{
|
||||||
|
<span class="badge-Spam">Spam</span>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<span class="badge badge-secondary">Normal</span>
|
||||||
|
}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
@if (item.IsBlocked)
|
||||||
|
{
|
||||||
|
<span class="badge-Blocked">Blocked</span>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<span class="badge badge-secondary">Normal</span>
|
||||||
|
}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
@if (item.IsUnsubscribed)
|
||||||
|
{
|
||||||
|
<span class="badge-Unsubscribed">Unsubscribed</span>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<span class="badge badge-secondary">Normal</span>
|
||||||
|
}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h2>Email Statistics</h2>
|
||||||
|
<div id="piechart" style="width: 900px; height: 500px;"></div>
|
||||||
|
|
||||||
|
@section Scripts {
|
||||||
|
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
google.charts.load('current', { 'packages': ['corechart'] });
|
||||||
|
google.charts.setOnLoadCallback(drawChart);
|
||||||
|
|
||||||
|
function drawChart() {
|
||||||
|
fetch('@Url.Action("GetChartData", "Newsletters")')
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
var dataTable = new google.visualization.DataTable();
|
||||||
|
dataTable.addColumn('string', 'Type');
|
||||||
|
dataTable.addColumn('number', 'Count');
|
||||||
|
dataTable.addRows([
|
||||||
|
['Sent', data.Sent],
|
||||||
|
['Delivered', data.Delivered],
|
||||||
|
['Opened', data.Opened],
|
||||||
|
['Clicked', data.Clicked],
|
||||||
|
['Bounced', data.Bounced],
|
||||||
|
['Spam', data.Spam],
|
||||||
|
['Blocked', data.Blocked],
|
||||||
|
['Unsubscribed', data.Unsubscribed]
|
||||||
|
]);
|
||||||
|
|
||||||
|
var options = {
|
||||||
|
title: 'Email Interaction Overview',
|
||||||
|
width: 900,
|
||||||
|
height: 500
|
||||||
|
};
|
||||||
|
|
||||||
|
var chart = new google.visualization.PieChart(document.getElementById('piechart'));
|
||||||
|
chart.draw(dataTable, options);
|
||||||
|
})
|
||||||
|
.catch(error => console.error('Failed to fetch email stats:', error));
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
}
|
||||||
|
|
@ -3,7 +3,120 @@
|
||||||
@{
|
@{
|
||||||
ViewData["Title"] = "Newsletter list";
|
ViewData["Title"] = "Newsletter list";
|
||||||
}
|
}
|
||||||
|
<style>
|
||||||
|
.badge-Sent {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 0.25em 0.4em;
|
||||||
|
font-size: 75%;
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: 1;
|
||||||
|
text-align: center;
|
||||||
|
white-space: nowrap;
|
||||||
|
vertical-align: baseline;
|
||||||
|
border-radius: 0.25rem;
|
||||||
|
color: #fff;
|
||||||
|
background-color: #6831c5;
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge-Deliverd {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 0.25em 0.4em;
|
||||||
|
font-size: 75%;
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: 1;
|
||||||
|
text-align: center;
|
||||||
|
white-space: nowrap;
|
||||||
|
vertical-align: baseline;
|
||||||
|
border-radius: 0.25rem;
|
||||||
|
color: #fff;
|
||||||
|
background-color: #44aebd;
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge-Opend {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 0.25em 0.4em;
|
||||||
|
font-size: 75%;
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: 1;
|
||||||
|
text-align: center;
|
||||||
|
white-space: nowrap;
|
||||||
|
vertical-align: baseline;
|
||||||
|
border-radius: 0.25rem;
|
||||||
|
color: #fff;
|
||||||
|
background-color: #22a877;
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge-Clicked {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 0.25em 0.4em;
|
||||||
|
font-size: 75%;
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: 1;
|
||||||
|
text-align: center;
|
||||||
|
white-space: nowrap;
|
||||||
|
vertical-align: baseline;
|
||||||
|
border-radius: 0.25rem;
|
||||||
|
color: #fff;
|
||||||
|
background-color: #3b76cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge-Bounced {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 0.25em 0.4em;
|
||||||
|
font-size: 75%;
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: 1;
|
||||||
|
text-align: center;
|
||||||
|
white-space: nowrap;
|
||||||
|
vertical-align: baseline;
|
||||||
|
border-radius: 0.25rem;
|
||||||
|
color: #fff;
|
||||||
|
background-color: #9585f4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge-Spam {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 0.25em 0.4em;
|
||||||
|
font-size: 75%;
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: 1;
|
||||||
|
text-align: center;
|
||||||
|
white-space: nowrap;
|
||||||
|
vertical-align: baseline;
|
||||||
|
border-radius: 0.25rem;
|
||||||
|
color: #fff;
|
||||||
|
background-color: #f06b66;
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge-Blocked {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 0.25em 0.4em;
|
||||||
|
font-size: 75%;
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: 1;
|
||||||
|
text-align: center;
|
||||||
|
white-space: nowrap;
|
||||||
|
vertical-align: baseline;
|
||||||
|
border-radius: 0.25rem;
|
||||||
|
color: #fff;
|
||||||
|
background-color: #98712d;
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge-Unsubscribed {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 0.25em 0.4em;
|
||||||
|
font-size: 75%;
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: 1;
|
||||||
|
text-align: center;
|
||||||
|
white-space: nowrap;
|
||||||
|
vertical-align: baseline;
|
||||||
|
border-radius: 0.25rem;
|
||||||
|
color: #fff;
|
||||||
|
background-color: #cb4a49;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
<div class="container mt-5">
|
<div class="container mt-5">
|
||||||
|
|
||||||
<partial name="_Notification" />
|
<partial name="_Notification" />
|
||||||
|
|
@ -18,7 +131,7 @@
|
||||||
</div>
|
</div>
|
||||||
<p>
|
<p>
|
||||||
|
|
||||||
<a asp-action="Create" class="btn btn-primary @(@ViewBag.TotalSubscribedUsers <= 0 ? "disabled" : "")">compose newsletter</a>
|
<a asp-action="Create" class="btn btn-primary btn-sm @(@ViewBag.TotalSubscribedUsers <= 0 ? "disabled" : "")">compose newsletter</a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<table class="table table-responsive w-100 d-block d-md-table ">
|
<table class="table table-responsive w-100 d-block d-md-table ">
|
||||||
|
|
@ -62,5 +175,82 @@
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
|
||||||
|
<h4>
|
||||||
|
<i class="bi bi-broadcast p-1 border-1 shadow-sm"></i> Real-Time Email Event Tracking
|
||||||
|
</h4>
|
||||||
|
<p>
|
||||||
|
<a asp-action="EmailStats" class="btn btn-primary btn-sm">View email tracking with chart</a>
|
||||||
|
</p>
|
||||||
|
<table class="table table-responsive w-100 d-block d-md-table table-bordered table-hover">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Recipient</th>
|
||||||
|
<th>Sent Date</th>
|
||||||
|
<th>Subject</th>
|
||||||
|
<th>Sent</th>
|
||||||
|
<th>Delivered</th>
|
||||||
|
<th>Opened</th>
|
||||||
|
<th>Clicked</th>
|
||||||
|
<th>Bounced</th>
|
||||||
|
<th>Spam</th>
|
||||||
|
<th>Blocked</th>
|
||||||
|
<th>Unsubscribed</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody id="emailStatsTableBody">
|
||||||
|
<!-- Rows will be dynamically inserted here -->
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
@section Scripts{
|
||||||
|
<script>
|
||||||
|
document.addEventListener('DOMContentLoaded', function () {
|
||||||
|
function fetchData() {
|
||||||
|
fetch('@Url.Action("GetEmailStatsData", "Newsletters")')
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
updateTable(data);
|
||||||
|
})
|
||||||
|
.catch(error => console.error('Error fetching data:', error));
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateTable(data) {
|
||||||
|
const tableBody = document.getElementById('emailStatsTableBody');
|
||||||
|
tableBody.innerHTML = ''; // Clear existing table rows
|
||||||
|
|
||||||
|
data.forEach(item => {
|
||||||
|
const row = `
|
||||||
|
<tr>
|
||||||
|
<td>${item.recipientEmail}</td>
|
||||||
|
<td>${item.sentDate}</td>
|
||||||
|
<td>${item.subject}</td>
|
||||||
|
<td>${item.isSent ? '<span class="badge-Sent">Sent</span>' : '<span class="badge badge-secondary">Pending</span>'}</td>
|
||||||
|
<td>${item.isDelivered ? '<span class="badge-Deliverd">Delivered</span>' : '<span class="badge badge-secondary">Pending</span>'}</td>
|
||||||
|
<td>${item.isOpened ? '<span class="badge-Opend">Opened</span>' : '<span class="badge badge-secondary">Pending</span>'}</td>
|
||||||
|
<td>${item.isClicked ? '<span class="badge-Clicked">Clicked</span>' : '<span class="badge badge-secondary">Pending</span>'}</td>
|
||||||
|
<td>${item.isBounced ? '<span class="badge-Opend">Bounced</span>' : '<span class="badge badge-secondary">Normal</span>'}</td>
|
||||||
|
<td>${item.isSpam ? '<span class="badge-Spam">Spamed</span>' : '<span class="badge badge-secondary">Normal</span>'}</td>
|
||||||
|
<td>${item.isBlocked ? '<span class="badge-Blocked">Blocked</span>' : '<span class="badge badge-secondary">Normal</span>'}</td>
|
||||||
|
<td>${item.isUnsubscribed ? '<span class="badge-Unsubscribed">Unsubscribed</span>' : '<span class="badge badge-secondary">Normal</span>'}</td>
|
||||||
|
<!-- Continue for each status -->
|
||||||
|
</tr>
|
||||||
|
`;
|
||||||
|
tableBody.innerHTML += row; // Append new row
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
setInterval(fetchData, 5000); // Fetch data every 5 seconds
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
@model IEnumerable<Web.ViewModel.NewsLetterVM.EmailEventViewModel>
|
||||||
|
|
||||||
|
@{
|
||||||
|
ViewData["Title"] = "LastReceivedEventsData";
|
||||||
|
Layout = "~/Areas/Admin/Views/Shared/_AdminLayout.cshtml";
|
||||||
|
}
|
||||||
|
|
||||||
|
<h1>LastReceivedEventsData</h1>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<a asp-action="Create">Create New</a>
|
||||||
|
</p>
|
||||||
|
<table class="table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>
|
||||||
|
@Html.DisplayNameFor(model => model.Email)
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
@Html.DisplayNameFor(model => model.EventType)
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
@Html.DisplayNameFor(model => model.EventTime)
|
||||||
|
</th>
|
||||||
|
<th></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
@foreach (var item in Model) {
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
@Html.DisplayFor(modelItem => item.Email)
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
@Html.DisplayFor(modelItem => item.EventType)
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
@Html.DisplayFor(modelItem => item.EventTime)
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
@Html.ActionLink("Edit", "Edit", new { /* id=item.PrimaryKey */ }) |
|
||||||
|
@Html.ActionLink("Details", "Details", new { /* id=item.PrimaryKey */ }) |
|
||||||
|
@Html.ActionLink("Delete", "Delete", new { /* id=item.PrimaryKey */ })
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
28
Web/Areas/Admin/Views/newsletters/ShowStat.cshtml
Normal file
28
Web/Areas/Admin/Views/newsletters/ShowStat.cshtml
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
@model string
|
||||||
|
@{
|
||||||
|
ViewData["Title"] = "Email Statistics";
|
||||||
|
Layout = "~/Areas/Admin/Views/Shared/_AdminLayout.cshtml";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h2>@ViewData["Title"]</h2>
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
<table class="table table-bordered">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<title>Email Statistics</title>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<h1>Email Statistics</h1>
|
||||||
|
<pre>@Model</pre>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -74,6 +74,10 @@ namespace Web.Extesions
|
||||||
{
|
{
|
||||||
services.AddTransient<IEmailServices, EmailServices>();
|
services.AddTransient<IEmailServices, EmailServices>();
|
||||||
}
|
}
|
||||||
|
public static void MailStatConfiguration(this IServiceCollection services)
|
||||||
|
{
|
||||||
|
services.AddTransient<IEmailStatsService, EmailStatsService>();
|
||||||
|
}
|
||||||
|
|
||||||
//public static void MailConfiguration(this IServiceCollection services, IConfiguration configuration)
|
//public static void MailConfiguration(this IServiceCollection services, IConfiguration configuration)
|
||||||
//{
|
//{
|
||||||
|
|
|
||||||
814
Web/Migrations/20240506120728_SentEmailNewsletterModelAdded.Designer.cs
generated
Normal file
814
Web/Migrations/20240506120728_SentEmailNewsletterModelAdded.Designer.cs
generated
Normal file
|
|
@ -0,0 +1,814 @@
|
||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using Data;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Web.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(SurveyContext))]
|
||||||
|
[Migration("20240506120728_SentEmailNewsletterModelAdded")]
|
||||||
|
partial class SentEmailNewsletterModelAdded
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "8.0.4")
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 128);
|
||||||
|
|
||||||
|
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Id")
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<string>("ConcurrencyStamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("nvarchar(256)");
|
||||||
|
|
||||||
|
b.Property<string>("NormalizedName")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("nvarchar(256)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("NormalizedName")
|
||||||
|
.IsUnique()
|
||||||
|
.HasDatabaseName("RoleNameIndex")
|
||||||
|
.HasFilter("[NormalizedName] IS NOT NULL");
|
||||||
|
|
||||||
|
b.ToTable("AspNetRoles", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("ClaimType")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("ClaimValue")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("RoleId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("RoleId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetRoleClaims", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("ClaimType")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("ClaimValue")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("UserId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserClaims", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("LoginProvider")
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<string>("ProviderKey")
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<string>("ProviderDisplayName")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("UserId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.HasKey("LoginProvider", "ProviderKey");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserLogins", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("UserId")
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<string>("RoleId")
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.HasKey("UserId", "RoleId");
|
||||||
|
|
||||||
|
b.HasIndex("RoleId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserRoles", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("UserId")
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<string>("LoginProvider")
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<string>("Value")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("UserId", "LoginProvider", "Name");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserTokens", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Address", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("CVR")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("City")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Country")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Email")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Mobile")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("PostalCode")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("State")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Street")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Addresss");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Answer", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<int>("QuestionId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Text")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("QuestionId");
|
||||||
|
|
||||||
|
b.ToTable("Answers");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.ApplicationUser", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Id")
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<int>("AccessFailedCount")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("ConcurrencyStamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Email")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("nvarchar(256)");
|
||||||
|
|
||||||
|
b.Property<bool>("EmailConfirmed")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<string>("FirstName")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("LastName")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<bool>("LockoutEnabled")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<DateTimeOffset?>("LockoutEnd")
|
||||||
|
.HasColumnType("datetimeoffset");
|
||||||
|
|
||||||
|
b.Property<string>("NormalizedEmail")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("nvarchar(256)");
|
||||||
|
|
||||||
|
b.Property<string>("NormalizedUserName")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("nvarchar(256)");
|
||||||
|
|
||||||
|
b.Property<string>("PasswordHash")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("PhoneNumber")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<bool>("PhoneNumberConfirmed")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<string>("SecurityStamp")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<bool>("TwoFactorEnabled")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<string>("UserName")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("nvarchar(256)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("NormalizedEmail")
|
||||||
|
.HasDatabaseName("EmailIndex");
|
||||||
|
|
||||||
|
b.HasIndex("NormalizedUserName")
|
||||||
|
.IsUnique()
|
||||||
|
.HasDatabaseName("UserNameIndex")
|
||||||
|
.HasFilter("[NormalizedUserName] IS NOT NULL");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUsers", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Banner", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("Content")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Description")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("ImageUrl")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("LinkUrl")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Title")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Banners");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Footer", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("Content")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("CreatedBy")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("ImageUlr")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<DateTime>("LastUpdated")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Owner")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Sitecopyright")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Title")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("UpdatedBy")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Footers");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.FooterSocialMedia", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("FooterId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("SocialId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("FooterId", "SocialId");
|
||||||
|
|
||||||
|
b.HasIndex("SocialId");
|
||||||
|
|
||||||
|
b.ToTable("FooterSocialMedias");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Page", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<int>("BannerId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Content")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<int>("FooterId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Slug")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Title")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("BannerId");
|
||||||
|
|
||||||
|
b.HasIndex("FooterId");
|
||||||
|
|
||||||
|
b.ToTable("Pages");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Question", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<int>("QuestionnaireId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Text")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<int>("Type")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("QuestionnaireId");
|
||||||
|
|
||||||
|
b.ToTable("Questions");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Questionnaire", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("Description")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Title")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Questionnaires");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Response", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<int>("QuestionnaireId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<DateTime>("SubmissionDate")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<string>("UserEmail")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("UserName")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("QuestionnaireId");
|
||||||
|
|
||||||
|
b.ToTable("Responses");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.ResponseAnswer", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<int>("AnswerId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("ResponseDetailId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ResponseDetailId");
|
||||||
|
|
||||||
|
b.ToTable("ResponseAnswers");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.ResponseDetail", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<int>("QuestionId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("QuestionType")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("ResponseId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("TextResponse")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("QuestionId");
|
||||||
|
|
||||||
|
b.HasIndex("ResponseId");
|
||||||
|
|
||||||
|
b.ToTable("ResponseDetails");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.SentNewsletterEamil", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("Body")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<bool>("IsBounced")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<bool>("IsClicked")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<bool>("IsDelivered")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<bool>("IsOpened")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<bool>("IsSpam")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<string>("RecipientEmail")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<DateTime>("SentDate")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<string>("Subject")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("SentNewsletterEamils");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.SocialMedia", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Url")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("SocialMedia");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Subscription", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("Email")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<bool>("IsSubscribed")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Subscriptions");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("RoleId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Model.ApplicationUser", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Model.ApplicationUser", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("RoleId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("Model.ApplicationUser", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Model.ApplicationUser", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Answer", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Model.Question", "Question")
|
||||||
|
.WithMany("Answers")
|
||||||
|
.HasForeignKey("QuestionId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Question");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.FooterSocialMedia", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Model.Footer", "Footer")
|
||||||
|
.WithMany("FooterSocialMedias")
|
||||||
|
.HasForeignKey("FooterId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("Model.SocialMedia", "SocialMedia")
|
||||||
|
.WithMany("FooterSocialMedias")
|
||||||
|
.HasForeignKey("SocialId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Footer");
|
||||||
|
|
||||||
|
b.Navigation("SocialMedia");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Page", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Model.Banner", "banner")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("BannerId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("Model.Footer", "footer")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("FooterId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("banner");
|
||||||
|
|
||||||
|
b.Navigation("footer");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Question", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Model.Questionnaire", "Questionnaire")
|
||||||
|
.WithMany("Questions")
|
||||||
|
.HasForeignKey("QuestionnaireId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Questionnaire");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Response", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Model.Questionnaire", "Questionnaire")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("QuestionnaireId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Questionnaire");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.ResponseAnswer", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Model.ResponseDetail", "ResponseDetail")
|
||||||
|
.WithMany("ResponseAnswers")
|
||||||
|
.HasForeignKey("ResponseDetailId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("ResponseDetail");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.ResponseDetail", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Model.Question", "Question")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("QuestionId")
|
||||||
|
.OnDelete(DeleteBehavior.Restrict)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("Model.Response", "Response")
|
||||||
|
.WithMany("ResponseDetails")
|
||||||
|
.HasForeignKey("ResponseId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Question");
|
||||||
|
|
||||||
|
b.Navigation("Response");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Footer", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("FooterSocialMedias");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Question", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("Answers");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Questionnaire", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("Questions");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Response", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("ResponseDetails");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.ResponseDetail", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("ResponseAnswers");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.SocialMedia", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("FooterSocialMedias");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Web.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class SentEmailNewsletterModelAdded : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "SentNewsletterEamils",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<int>(type: "int", nullable: false)
|
||||||
|
.Annotation("SqlServer:Identity", "1, 1"),
|
||||||
|
RecipientEmail = table.Column<string>(type: "nvarchar(max)", nullable: true),
|
||||||
|
Subject = table.Column<string>(type: "nvarchar(max)", nullable: true),
|
||||||
|
Body = table.Column<string>(type: "nvarchar(max)", nullable: true),
|
||||||
|
SentDate = table.Column<DateTime>(type: "datetime2", nullable: false),
|
||||||
|
IsDelivered = table.Column<bool>(type: "bit", nullable: false),
|
||||||
|
IsOpened = table.Column<bool>(type: "bit", nullable: false),
|
||||||
|
IsClicked = table.Column<bool>(type: "bit", nullable: false),
|
||||||
|
IsBounced = table.Column<bool>(type: "bit", nullable: false),
|
||||||
|
IsSpam = table.Column<bool>(type: "bit", nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_SentNewsletterEamils", x => x.Id);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "SentNewsletterEamils");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
820
Web/Migrations/20240508104039_EmailTrackingModelChnaged.Designer.cs
generated
Normal file
820
Web/Migrations/20240508104039_EmailTrackingModelChnaged.Designer.cs
generated
Normal file
|
|
@ -0,0 +1,820 @@
|
||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using Data;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Web.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(SurveyContext))]
|
||||||
|
[Migration("20240508104039_EmailTrackingModelChnaged")]
|
||||||
|
partial class EmailTrackingModelChnaged
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "8.0.4")
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 128);
|
||||||
|
|
||||||
|
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Id")
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<string>("ConcurrencyStamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("nvarchar(256)");
|
||||||
|
|
||||||
|
b.Property<string>("NormalizedName")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("nvarchar(256)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("NormalizedName")
|
||||||
|
.IsUnique()
|
||||||
|
.HasDatabaseName("RoleNameIndex")
|
||||||
|
.HasFilter("[NormalizedName] IS NOT NULL");
|
||||||
|
|
||||||
|
b.ToTable("AspNetRoles", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("ClaimType")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("ClaimValue")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("RoleId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("RoleId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetRoleClaims", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("ClaimType")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("ClaimValue")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("UserId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserClaims", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("LoginProvider")
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<string>("ProviderKey")
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<string>("ProviderDisplayName")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("UserId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.HasKey("LoginProvider", "ProviderKey");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserLogins", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("UserId")
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<string>("RoleId")
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.HasKey("UserId", "RoleId");
|
||||||
|
|
||||||
|
b.HasIndex("RoleId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserRoles", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("UserId")
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<string>("LoginProvider")
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<string>("Value")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("UserId", "LoginProvider", "Name");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserTokens", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Address", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("CVR")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("City")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Country")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Email")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Mobile")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("PostalCode")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("State")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Street")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Addresss");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Answer", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<int>("QuestionId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Text")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("QuestionId");
|
||||||
|
|
||||||
|
b.ToTable("Answers");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.ApplicationUser", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Id")
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<int>("AccessFailedCount")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("ConcurrencyStamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Email")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("nvarchar(256)");
|
||||||
|
|
||||||
|
b.Property<bool>("EmailConfirmed")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<string>("FirstName")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("LastName")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<bool>("LockoutEnabled")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<DateTimeOffset?>("LockoutEnd")
|
||||||
|
.HasColumnType("datetimeoffset");
|
||||||
|
|
||||||
|
b.Property<string>("NormalizedEmail")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("nvarchar(256)");
|
||||||
|
|
||||||
|
b.Property<string>("NormalizedUserName")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("nvarchar(256)");
|
||||||
|
|
||||||
|
b.Property<string>("PasswordHash")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("PhoneNumber")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<bool>("PhoneNumberConfirmed")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<string>("SecurityStamp")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<bool>("TwoFactorEnabled")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<string>("UserName")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("nvarchar(256)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("NormalizedEmail")
|
||||||
|
.HasDatabaseName("EmailIndex");
|
||||||
|
|
||||||
|
b.HasIndex("NormalizedUserName")
|
||||||
|
.IsUnique()
|
||||||
|
.HasDatabaseName("UserNameIndex")
|
||||||
|
.HasFilter("[NormalizedUserName] IS NOT NULL");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUsers", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Banner", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("Content")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Description")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("ImageUrl")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("LinkUrl")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Title")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Banners");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Footer", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("Content")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("CreatedBy")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("ImageUlr")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<DateTime>("LastUpdated")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Owner")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Sitecopyright")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Title")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("UpdatedBy")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Footers");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.FooterSocialMedia", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("FooterId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("SocialId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("FooterId", "SocialId");
|
||||||
|
|
||||||
|
b.HasIndex("SocialId");
|
||||||
|
|
||||||
|
b.ToTable("FooterSocialMedias");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Page", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<int>("BannerId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Content")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<int>("FooterId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Slug")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Title")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("BannerId");
|
||||||
|
|
||||||
|
b.HasIndex("FooterId");
|
||||||
|
|
||||||
|
b.ToTable("Pages");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Question", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<int>("QuestionnaireId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Text")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<int>("Type")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("QuestionnaireId");
|
||||||
|
|
||||||
|
b.ToTable("Questions");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Questionnaire", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("Description")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Title")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Questionnaires");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Response", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<int>("QuestionnaireId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<DateTime>("SubmissionDate")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<string>("UserEmail")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("UserName")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("QuestionnaireId");
|
||||||
|
|
||||||
|
b.ToTable("Responses");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.ResponseAnswer", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<int>("AnswerId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("ResponseDetailId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ResponseDetailId");
|
||||||
|
|
||||||
|
b.ToTable("ResponseAnswers");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.ResponseDetail", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<int>("QuestionId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("QuestionType")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("ResponseId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("TextResponse")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("QuestionId");
|
||||||
|
|
||||||
|
b.HasIndex("ResponseId");
|
||||||
|
|
||||||
|
b.ToTable("ResponseDetails");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.SentNewsletterEamil", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("Body")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<bool>("IsBounced")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<bool>("IsClicked")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<bool>("IsDelivered")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<bool>("IsOpened")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<bool>("IsSent")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<bool>("IsSpam")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<bool>("IsUnsubscribed")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<string>("RecipientEmail")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<DateTime>("SentDate")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<string>("Subject")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("SentNewsletterEamils");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.SocialMedia", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Url")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("SocialMedia");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Subscription", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("Email")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<bool>("IsSubscribed")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Subscriptions");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("RoleId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Model.ApplicationUser", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Model.ApplicationUser", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("RoleId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("Model.ApplicationUser", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Model.ApplicationUser", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Answer", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Model.Question", "Question")
|
||||||
|
.WithMany("Answers")
|
||||||
|
.HasForeignKey("QuestionId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Question");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.FooterSocialMedia", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Model.Footer", "Footer")
|
||||||
|
.WithMany("FooterSocialMedias")
|
||||||
|
.HasForeignKey("FooterId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("Model.SocialMedia", "SocialMedia")
|
||||||
|
.WithMany("FooterSocialMedias")
|
||||||
|
.HasForeignKey("SocialId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Footer");
|
||||||
|
|
||||||
|
b.Navigation("SocialMedia");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Page", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Model.Banner", "banner")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("BannerId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("Model.Footer", "footer")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("FooterId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("banner");
|
||||||
|
|
||||||
|
b.Navigation("footer");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Question", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Model.Questionnaire", "Questionnaire")
|
||||||
|
.WithMany("Questions")
|
||||||
|
.HasForeignKey("QuestionnaireId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Questionnaire");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Response", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Model.Questionnaire", "Questionnaire")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("QuestionnaireId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Questionnaire");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.ResponseAnswer", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Model.ResponseDetail", "ResponseDetail")
|
||||||
|
.WithMany("ResponseAnswers")
|
||||||
|
.HasForeignKey("ResponseDetailId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("ResponseDetail");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.ResponseDetail", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Model.Question", "Question")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("QuestionId")
|
||||||
|
.OnDelete(DeleteBehavior.Restrict)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("Model.Response", "Response")
|
||||||
|
.WithMany("ResponseDetails")
|
||||||
|
.HasForeignKey("ResponseId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Question");
|
||||||
|
|
||||||
|
b.Navigation("Response");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Footer", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("FooterSocialMedias");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Question", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("Answers");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Questionnaire", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("Questions");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Response", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("ResponseDetails");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.ResponseDetail", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("ResponseAnswers");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.SocialMedia", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("FooterSocialMedias");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
40
Web/Migrations/20240508104039_EmailTrackingModelChnaged.cs
Normal file
40
Web/Migrations/20240508104039_EmailTrackingModelChnaged.cs
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Web.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class EmailTrackingModelChnaged : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AddColumn<bool>(
|
||||||
|
name: "IsSent",
|
||||||
|
table: "SentNewsletterEamils",
|
||||||
|
type: "bit",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: false);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<bool>(
|
||||||
|
name: "IsUnsubscribed",
|
||||||
|
table: "SentNewsletterEamils",
|
||||||
|
type: "bit",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "IsSent",
|
||||||
|
table: "SentNewsletterEamils");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "IsUnsubscribed",
|
||||||
|
table: "SentNewsletterEamils");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
823
Web/Migrations/20240508104306_EmailTrackingModelChangedWithIsBlockedPrperty.Designer.cs
generated
Normal file
823
Web/Migrations/20240508104306_EmailTrackingModelChangedWithIsBlockedPrperty.Designer.cs
generated
Normal file
|
|
@ -0,0 +1,823 @@
|
||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using Data;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Web.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(SurveyContext))]
|
||||||
|
[Migration("20240508104306_EmailTrackingModelChangedWithIsBlockedPrperty")]
|
||||||
|
partial class EmailTrackingModelChangedWithIsBlockedPrperty
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "8.0.4")
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 128);
|
||||||
|
|
||||||
|
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Id")
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<string>("ConcurrencyStamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("nvarchar(256)");
|
||||||
|
|
||||||
|
b.Property<string>("NormalizedName")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("nvarchar(256)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("NormalizedName")
|
||||||
|
.IsUnique()
|
||||||
|
.HasDatabaseName("RoleNameIndex")
|
||||||
|
.HasFilter("[NormalizedName] IS NOT NULL");
|
||||||
|
|
||||||
|
b.ToTable("AspNetRoles", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("ClaimType")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("ClaimValue")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("RoleId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("RoleId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetRoleClaims", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("ClaimType")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("ClaimValue")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("UserId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserClaims", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("LoginProvider")
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<string>("ProviderKey")
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<string>("ProviderDisplayName")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("UserId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.HasKey("LoginProvider", "ProviderKey");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserLogins", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("UserId")
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<string>("RoleId")
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.HasKey("UserId", "RoleId");
|
||||||
|
|
||||||
|
b.HasIndex("RoleId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserRoles", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("UserId")
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<string>("LoginProvider")
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<string>("Value")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("UserId", "LoginProvider", "Name");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserTokens", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Address", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("CVR")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("City")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Country")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Email")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Mobile")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("PostalCode")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("State")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Street")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Addresss");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Answer", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<int>("QuestionId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Text")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("QuestionId");
|
||||||
|
|
||||||
|
b.ToTable("Answers");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.ApplicationUser", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Id")
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<int>("AccessFailedCount")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("ConcurrencyStamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Email")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("nvarchar(256)");
|
||||||
|
|
||||||
|
b.Property<bool>("EmailConfirmed")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<string>("FirstName")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("LastName")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<bool>("LockoutEnabled")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<DateTimeOffset?>("LockoutEnd")
|
||||||
|
.HasColumnType("datetimeoffset");
|
||||||
|
|
||||||
|
b.Property<string>("NormalizedEmail")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("nvarchar(256)");
|
||||||
|
|
||||||
|
b.Property<string>("NormalizedUserName")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("nvarchar(256)");
|
||||||
|
|
||||||
|
b.Property<string>("PasswordHash")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("PhoneNumber")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<bool>("PhoneNumberConfirmed")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<string>("SecurityStamp")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<bool>("TwoFactorEnabled")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<string>("UserName")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("nvarchar(256)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("NormalizedEmail")
|
||||||
|
.HasDatabaseName("EmailIndex");
|
||||||
|
|
||||||
|
b.HasIndex("NormalizedUserName")
|
||||||
|
.IsUnique()
|
||||||
|
.HasDatabaseName("UserNameIndex")
|
||||||
|
.HasFilter("[NormalizedUserName] IS NOT NULL");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUsers", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Banner", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("Content")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Description")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("ImageUrl")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("LinkUrl")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Title")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Banners");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Footer", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("Content")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("CreatedBy")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("ImageUlr")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<DateTime>("LastUpdated")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Owner")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Sitecopyright")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Title")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("UpdatedBy")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Footers");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.FooterSocialMedia", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("FooterId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("SocialId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("FooterId", "SocialId");
|
||||||
|
|
||||||
|
b.HasIndex("SocialId");
|
||||||
|
|
||||||
|
b.ToTable("FooterSocialMedias");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Page", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<int>("BannerId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Content")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<int>("FooterId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Slug")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Title")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("BannerId");
|
||||||
|
|
||||||
|
b.HasIndex("FooterId");
|
||||||
|
|
||||||
|
b.ToTable("Pages");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Question", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<int>("QuestionnaireId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Text")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<int>("Type")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("QuestionnaireId");
|
||||||
|
|
||||||
|
b.ToTable("Questions");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Questionnaire", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("Description")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Title")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Questionnaires");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Response", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<int>("QuestionnaireId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<DateTime>("SubmissionDate")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<string>("UserEmail")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("UserName")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("QuestionnaireId");
|
||||||
|
|
||||||
|
b.ToTable("Responses");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.ResponseAnswer", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<int>("AnswerId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("ResponseDetailId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ResponseDetailId");
|
||||||
|
|
||||||
|
b.ToTable("ResponseAnswers");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.ResponseDetail", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<int>("QuestionId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("QuestionType")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("ResponseId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("TextResponse")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("QuestionId");
|
||||||
|
|
||||||
|
b.HasIndex("ResponseId");
|
||||||
|
|
||||||
|
b.ToTable("ResponseDetails");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.SentNewsletterEamil", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("Body")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<bool>("IsBlocked")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<bool>("IsBounced")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<bool>("IsClicked")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<bool>("IsDelivered")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<bool>("IsOpened")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<bool>("IsSent")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<bool>("IsSpam")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<bool>("IsUnsubscribed")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<string>("RecipientEmail")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<DateTime>("SentDate")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<string>("Subject")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("SentNewsletterEamils");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.SocialMedia", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Url")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("SocialMedia");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Subscription", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("Email")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<bool>("IsSubscribed")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Subscriptions");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("RoleId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Model.ApplicationUser", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Model.ApplicationUser", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("RoleId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("Model.ApplicationUser", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Model.ApplicationUser", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Answer", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Model.Question", "Question")
|
||||||
|
.WithMany("Answers")
|
||||||
|
.HasForeignKey("QuestionId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Question");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.FooterSocialMedia", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Model.Footer", "Footer")
|
||||||
|
.WithMany("FooterSocialMedias")
|
||||||
|
.HasForeignKey("FooterId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("Model.SocialMedia", "SocialMedia")
|
||||||
|
.WithMany("FooterSocialMedias")
|
||||||
|
.HasForeignKey("SocialId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Footer");
|
||||||
|
|
||||||
|
b.Navigation("SocialMedia");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Page", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Model.Banner", "banner")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("BannerId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("Model.Footer", "footer")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("FooterId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("banner");
|
||||||
|
|
||||||
|
b.Navigation("footer");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Question", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Model.Questionnaire", "Questionnaire")
|
||||||
|
.WithMany("Questions")
|
||||||
|
.HasForeignKey("QuestionnaireId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Questionnaire");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Response", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Model.Questionnaire", "Questionnaire")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("QuestionnaireId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Questionnaire");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.ResponseAnswer", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Model.ResponseDetail", "ResponseDetail")
|
||||||
|
.WithMany("ResponseAnswers")
|
||||||
|
.HasForeignKey("ResponseDetailId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("ResponseDetail");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.ResponseDetail", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Model.Question", "Question")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("QuestionId")
|
||||||
|
.OnDelete(DeleteBehavior.Restrict)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("Model.Response", "Response")
|
||||||
|
.WithMany("ResponseDetails")
|
||||||
|
.HasForeignKey("ResponseId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Question");
|
||||||
|
|
||||||
|
b.Navigation("Response");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Footer", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("FooterSocialMedias");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Question", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("Answers");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Questionnaire", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("Questions");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Response", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("ResponseDetails");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.ResponseDetail", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("ResponseAnswers");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.SocialMedia", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("FooterSocialMedias");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Web.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class EmailTrackingModelChangedWithIsBlockedPrperty : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AddColumn<bool>(
|
||||||
|
name: "IsBlocked",
|
||||||
|
table: "SentNewsletterEamils",
|
||||||
|
type: "bit",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "IsBlocked",
|
||||||
|
table: "SentNewsletterEamils");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -540,6 +540,55 @@ namespace Web.Migrations
|
||||||
b.ToTable("ResponseDetails");
|
b.ToTable("ResponseDetails");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.SentNewsletterEamil", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("Body")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<bool>("IsBlocked")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<bool>("IsBounced")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<bool>("IsClicked")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<bool>("IsDelivered")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<bool>("IsOpened")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<bool>("IsSent")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<bool>("IsSpam")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<bool>("IsUnsubscribed")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<string>("RecipientEmail")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<DateTime>("SentDate")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<string>("Subject")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("SentNewsletterEamils");
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Model.SocialMedia", b =>
|
modelBuilder.Entity("Model.SocialMedia", b =>
|
||||||
{
|
{
|
||||||
b.Property<int>("Id")
|
b.Property<int>("Id")
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ var builder = WebApplication.CreateBuilder(args);
|
||||||
|
|
||||||
// Add services to the container.
|
// Add services to the container.
|
||||||
builder.Services.AddControllersWithViews();
|
builder.Services.AddControllersWithViews();
|
||||||
|
builder.Services.AddHttpClient();
|
||||||
|
|
||||||
|
|
||||||
var config = builder.Configuration;
|
var config = builder.Configuration;
|
||||||
|
|
@ -36,6 +37,7 @@ builder.Services.AddScoped<SurveyContext>();
|
||||||
builder.Services.AddTransient<NavigationViewComponent>();
|
builder.Services.AddTransient<NavigationViewComponent>();
|
||||||
builder.Services.ConfigureNewsLetter();
|
builder.Services.ConfigureNewsLetter();
|
||||||
builder.Services.MailConfiguration();
|
builder.Services.MailConfiguration();
|
||||||
|
builder.Services.MailStatConfiguration();
|
||||||
builder.Services.ConfigureOpenAI(config);
|
builder.Services.ConfigureOpenAI(config);
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -68,7 +70,11 @@ app.MapControllers();
|
||||||
app.MapControllerRoute(
|
app.MapControllerRoute(
|
||||||
name: "page",
|
name: "page",
|
||||||
pattern: "{slug}", defaults: new { Controller = "Home", Action = "Index" });
|
pattern: "{slug}", defaults: new { Controller = "Home", Action = "Index" });
|
||||||
|
app.Use(async (context, next) =>
|
||||||
|
{
|
||||||
|
context.Request.EnableBuffering(); // Enable buffering for reading request body multiple times
|
||||||
|
await next.Invoke();
|
||||||
|
});
|
||||||
|
|
||||||
app.MapAreaControllerRoute(
|
app.MapAreaControllerRoute(
|
||||||
name: "MyAdminArea",
|
name: "MyAdminArea",
|
||||||
|
|
|
||||||
16
Web/ViewModel/NewsLetterVM/EmailEventViewModel.cs
Normal file
16
Web/ViewModel/NewsLetterVM/EmailEventViewModel.cs
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace Web.ViewModel.NewsLetterVM
|
||||||
|
{
|
||||||
|
public class EmailEventViewModel
|
||||||
|
{
|
||||||
|
[Required]
|
||||||
|
public string Email { get; set; }
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
public string EventType { get; set; }
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
public DateTime EventTime { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue