сделал, хз, может не работать

This commit is contained in:
antoc0der 2024-05-21 20:37:40 +04:00
parent 417b42d187
commit 7885582b9f
22 changed files with 861 additions and 75 deletions

View File

@ -74,7 +74,38 @@ namespace FlowerShopBusinessLogic.MailWorker
_messageInfoLogic.Create(mail);
}
}
protected abstract Task SendMailAsync(MailSendInfoBindingModel info);
public async void MailSendReplyAsync(MailReplySendInfoBindingModel info)
{
if (string.IsNullOrEmpty(_mailLogin) || string.IsNullOrEmpty(_mailPassword))
return;
if (string.IsNullOrEmpty(_smtpClientHost) || _smtpClientPort == 0)
return;
if (string.IsNullOrEmpty(info.MailAddress) || string.IsNullOrEmpty(info.Subject) || string.IsNullOrEmpty(info.Text) || string.IsNullOrEmpty(info.ParentMessageId))
return;
_logger.LogDebug("Send Mail as reply: {To}, {Subject}, {parentId}", info.MailAddress, info.Subject, info.ParentMessageId);
string? messageId = await SendMailAsync(info);
if (string.IsNullOrEmpty(messageId))
throw new InvalidOperationException("Непредвиденная ошибка при отправке сообщения в ответ");
if (_messageInfoLogic.Create(new MessageInfoBindingModel
{
MessageId = messageId,
DateDelivery = DateTime.Now,
SenderName = _mailLogin,
IsReply = true,
Subject = info.Subject,
Body = info.Text,
}))
{
_messageInfoLogic.Update(new MessageInfoBindingModel()
{
MessageId = info.ParentMessageId,
ReplyMessageId = messageId,
IsReaded = true
});
}
}
protected abstract Task<string?> SendMailAsync(MailSendInfoBindingModel info);
protected abstract Task<List<MessageInfoBindingModel>>
ReceiveMailAsync();
}

View File

@ -17,32 +17,34 @@ namespace FlowerShopBusinessLogic.MailWorker
{
public MailKitWorker(ILogger<MailKitWorker> logger, IMessageInfoLogic
messageInfoLogic) : base(logger, messageInfoLogic) { }
protected override async Task SendMailAsync(MailSendInfoBindingModel
info)
protected override async Task<string?> SendMailAsync(MailSendInfoBindingModel info)
{
string? resount = null;
using var objMailMessage = new MailMessage();
using var objSmtpClient = new SmtpClient(_smtpClientHost,_smtpClientPort);
using var objSmtpClient = new SmtpClient(_smtpClientHost, _smtpClientPort);
try
{
objMailMessage.From = new MailAddress(_mailLogin);
objMailMessage.To.Add(new MailAddress(info.MailAddress));
objMailMessage.Subject = info.Subject;
objMailMessage.Body = info.Text;
objMailMessage.SubjectEncoding = Encoding.UTF8;
objMailMessage.BodyEncoding = Encoding.UTF8;
objSmtpClient.UseDefaultCredentials = false;
objSmtpClient.EnableSsl = true;
objSmtpClient.DeliveryMethod = SmtpDeliveryMethod.Network;
objSmtpClient.Credentials = new NetworkCredential(_mailLogin,_mailPassword);
ConfigurateSmtpClient(objSmtpClient);
CreateMessage(objMailMessage, info);
if (info is MailReplySendInfoBindingModel replyInfo)
{
objMailMessage.Headers.Add("In-Reply-To", replyInfo.ParentMessageId);
objMailMessage.Headers.Add("References", replyInfo.ParentMessageId);
string messageGuid = Guid.NewGuid().ToString();
objMailMessage.Headers.Add("Message-Id", messageGuid);
resount = messageGuid;
}
await Task.Run(() => objSmtpClient.Send(objMailMessage));
}
catch (Exception)
{
throw;
}
return resount;
}
protected override async Task<List<MessageInfoBindingModel>>
ReceiveMailAsync()
protected override async Task<List<MessageInfoBindingModel>> ReceiveMailAsync()
{
var list = new List<MessageInfoBindingModel>();
using var client = new Pop3Client();
@ -78,5 +80,21 @@ namespace FlowerShopBusinessLogic.MailWorker
});
return list;
}
private void CreateMessage(MailMessage objMailMessage, MailSendInfoBindingModel info)
{
objMailMessage.From = new MailAddress(_mailLogin);
objMailMessage.To.Add(new MailAddress(info.MailAddress));
objMailMessage.Subject = info.Subject;
objMailMessage.Body = info.Text;
objMailMessage.SubjectEncoding = Encoding.UTF8;
objMailMessage.BodyEncoding = Encoding.UTF8;
}
private void ConfigurateSmtpClient(SmtpClient objSmtpClient)
{
objSmtpClient.UseDefaultCredentials = false;
objSmtpClient.EnableSsl = true;
objSmtpClient.DeliveryMethod = SmtpDeliveryMethod.Network;
objSmtpClient.Credentials = new NetworkCredential(_mailLogin, _mailPassword);
}
}
}

View File

@ -222,7 +222,7 @@ namespace FlowerShopBusinessLogic.BusinessLogic
return false;
}
}
private bool SendOrderStatusMail(int clientId, string subject, string text)
{
var client = _clientLogic.ReadElement(new() { Id = clientId });

View File

@ -9,7 +9,9 @@ namespace FlowerShopClientApp
{
private static readonly HttpClient _client = new();
public static ClientViewModel? Client { get; set; } = null;
public static void Connect(IConfiguration configuration)
public static int MailPage { get; set; } = 1;
public static void Connect(IConfiguration configuration)
{
_client.BaseAddress = new Uri(configuration["IPAddress"]);
_client.DefaultRequestHeaders.Accept.Clear();

View File

@ -26,14 +26,14 @@ namespace FlowerShopClientApp.Controllers
}
[HttpGet]
public IActionResult Mails()
public IActionResult Mails(int page = 1)
{
if (APIClient.Client == null)
{
return Redirect("~/Home/Enter");
}
return
View(APIClient.GetRequest<List<MessageInfoViewModel>>($"api/client/getmessages?clientId={APIClient.Client.Id}"));
page = Math.Max(page, 1);
return View(APIClient.GetRequest<List<MessageInfoViewModel>>($"api/client/getmessages?clientId={APIClient.Client.Id}&page={page}"));
}
[HttpGet]

View File

@ -1,7 +1,7 @@
@using FlowerShopContracts.ViewModels
@model List<MessageInfoViewModel>
@Url.ActionContext.RouteData.Values["page"]
@{
ViewData["Title"] = "Mails";
}
@ -50,5 +50,22 @@
}
</tbody>
</table>
<div class="d-flex justify-content-center align-items-center">
@{
int page = int.Parse(Context.Request.Query["page"]);
<div class="m-1">
<input type="number" class="form-control" min="1" step="1" asp-action="Mails" name="page" value="@(page)" readonly>
</div>
if (page > 1)
{
<a name="page" class="btn btn-primary" type="button" asp-action="Mails" asp-route-page="@(page-1)">&lt;-</a>
}
else
{
<p class="btn btn-primary my-auto">&lt;-</p>
}
<a name="" id="" class="btn btn-primary" type="button" asp-action="Mails" asp-route-page="@(page+1)">-&gt;</a>
}
</div>
}
</div>

View File

@ -24,7 +24,9 @@ namespace FlowerShopDatabaseImplement.Models
public string Password { get; set; } = string.Empty;
[ForeignKey("ClientId")]
public virtual List<Order> Orders { get; set; } = new();
public static Client? Create(ClientBindingModel model)
[ForeignKey("ClientId")]
public virtual List<MessageInfo> MessageInfos { get; set; } = new();
public static Client? Create(ClientBindingModel model)
{
if (model == null)
{

View File

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
@ -27,6 +28,13 @@ namespace FlowerShopDatabaseImplement.Models
public string Body { get; private set; } = string.Empty;
public Client? Client { get; private set; }
[Required]
public bool IsReaded { get; set; }
public string? ReplyMessageId { get; set; }
[ForeignKey("ReplyMessageId")]
public virtual MessageInfo? Reply { get; set; }
[Required]
public bool IsReply { get; set; }
public static MessageInfo? Create(FlowerShopDataBase context, MessageInfoBindingModel model)
{
@ -43,9 +51,24 @@ namespace FlowerShopDatabaseImplement.Models
MessageId = model.MessageId,
SenderName = model.SenderName,
DateDelivery = model.DateDelivery,
IsReaded = model.IsReaded,
ReplyMessageId = model.ReplyMessageId,
IsReply = model.IsReply
};
}
public void Update(FlowerShopDataBase context, MessageInfoBindingModel model)
{
if (model == null)
{
return;
}
IsReaded = model.IsReaded;
ReplyMessageId = model.ReplyMessageId;
if (!string.IsNullOrEmpty(ReplyMessageId))
{
Reply = context.Messages.First(x => x.MessageId == ReplyMessageId);
}
}
public MessageInfoViewModel GetViewModel => new()
{
Body = Body,
@ -54,6 +77,10 @@ namespace FlowerShopDatabaseImplement.Models
MessageId = MessageId,
SenderName = SenderName,
DateDelivery = DateDelivery,
IsReaded = IsReaded,
ReplyMessageId = ReplyMessageId,
Reply = Reply,
IsReply = IsReply
};
}
}

View File

@ -26,9 +26,24 @@ namespace FlowerShopDatabaseImplement.Implements
public List<MessageInfoViewModel> GetFilteredList(MessageInfoSearchModel model)
{
if (!model.ClientId.HasValue && !model.PageLength.HasValue && !model.PageIndex.HasValue)
{
return new();
}
using var context = new FlowerShopDataBase();
return context.Messages
.Where(x => x.ClientId == model.ClientId)
var request = context.Messages
.Where(x => !x.IsReply);
if (model.ClientId.HasValue)
request = request
.Where(x => x.ClientId.HasValue && x.ClientId == model.ClientId);
if (model.PageLength.HasValue)
{
int skipRows = model.PageIndex.HasValue ? (model.PageIndex.Value - 1) * model.PageLength.Value : 0;
request = request
.Skip(skipRows)
.Take(model.PageLength.Value);
}
return request
.Select(x => x.GetViewModel)
.ToList();
}
@ -53,5 +68,17 @@ namespace FlowerShopDatabaseImplement.Implements
context.SaveChanges();
return newMessage.GetViewModel;
}
public MessageInfoViewModel? Update(MessageInfoBindingModel model)
{
using var context = new FlowerShopDataBase();
var message = context.Messages.FirstOrDefault(x => x.MessageId == model.MessageId);
if (message == null)
{
return null;
}
message.Update(context, model);
context.SaveChanges();
return message.GetViewModel;
}
}
}

View File

@ -15,13 +15,11 @@ internal class DataFileSingleton
public List<Component> Components { get; private set; }
private readonly string ImplementerFileName = "Implementer.xml";
private readonly string MessageInfoFileName = "MessageInfo.xml";
public List<Component> Components { get; private set; }
public List<Order> Orders { get; private set; }
public List<Flower> Flowers { get; private set; }
public List<Client> Clients { get; private set; }
public List<Implementer> Implementers { get; private set; }
public List<MessageInfo> Messages { get; private set; }
public List<Shop> Shops { get; private set; }
public static DataFileSingleton GetInstance()
{
@ -42,7 +40,7 @@ internal class DataFileSingleton
public void SaveClients() => SaveData(Clients, ClientFileName, "Clients", x => x.GetXElement);
public void SaveShops() => SaveData(Shops, ShopFileName,
"Shops", x => x.GetXElement);
private DataFileSingleton()
public void SaveMessages() => SaveData(Orders, ImplementerFileName, "Messages", x => x.GetXElement);
private DataFileSingleton()
{

View File

@ -23,6 +23,9 @@ namespace FlowerShopFileImplement.Models
public string Subject { get; private set; } = string.Empty;
public string Body { get; private set; } = string.Empty;
public bool IsReaded { get; private set; }
public bool IsReply { get; private set; }
public string? ReplyMessageId { get; private set; } = string.Empty;
public static MessageInfo? Create(MessageInfoBindingModel model)
{
@ -38,6 +41,9 @@ namespace FlowerShopFileImplement.Models
MessageId = model.MessageId,
SenderName = model.SenderName,
DateDelivery = model.DateDelivery,
IsReply = model.IsReply,
IsReaded = model.IsReaded,
ReplyMessageId = model.ReplyMessageId,
};
}
@ -55,8 +61,20 @@ namespace FlowerShopFileImplement.Models
MessageId = element.Attribute("MessageId")!.Value,
SenderName = element.Attribute("SenderName")!.Value,
DateDelivery = Convert.ToDateTime(element.Attribute("DateDelivery")!.Value),
IsReply = Convert.ToBoolean(element.Attribute("IsReply")!.Value),
IsReaded = Convert.ToBoolean(element.Attribute("HasRead")!.Value),
ReplyMessageId = element.Attribute("ReplyMessageId")!.Value,
};
}
public void Update(MessageInfoBindingModel model)
{
if (model == null)
{
return;
}
IsReply = model.IsReply;
IsReaded = model.IsReaded;
}
public MessageInfoViewModel GetViewModel => new()
{
@ -66,6 +84,9 @@ namespace FlowerShopFileImplement.Models
MessageId = MessageId,
SenderName = SenderName,
DateDelivery = DateDelivery,
IsReply = IsReply,
IsReaded = IsReaded,
ReplyMessageId = ReplyMessageId,
};
public XElement GetXElement => new("MessageInfo",
@ -74,7 +95,10 @@ namespace FlowerShopFileImplement.Models
new XAttribute("ClientId", ClientId),
new XAttribute("MessageId", MessageId),
new XAttribute("SenderName", SenderName),
new XAttribute("DateDelivery", DateDelivery)
new XAttribute("DateDelivery", DateDelivery),
new XAttribute("IsReply", IsReply),
new XAttribute("IsReaded", IsReaded),
new XAttribute("ReplyMessageId", ReplyMessageId ?? "")
);
}
}

View File

@ -30,9 +30,16 @@ namespace FlowerShopFileImplement.Implements
public List<MessageInfoViewModel> GetFilteredList(MessageInfoSearchModel model)
{
return _source.Messages
.Where(x => x.ClientId == model.ClientId)
.Select(x => x.GetViewModel)
var res = _source.Messages
.Where(x => !model.ClientId.HasValue || x.ClientId == model.ClientId)
.Select(x => x.GetViewModel);
if (!(model.PageIndex.HasValue && model.PageLength.HasValue))
{
return res.ToList();
}
return res
.Skip((model.PageIndex.Value - 1) * model.PageLength.Value)
.Take(model.PageLength.Value)
.ToList();
}
@ -54,5 +61,15 @@ namespace FlowerShopFileImplement.Implements
_source.SaveMessages();
return newMessage.GetViewModel;
}
public MessageInfoViewModel? Update(MessageInfoBindingModel model)
{
var res = _source.Messages.FirstOrDefault(x => x.MessageId.Equals(model.MessageId));
if (res != null)
{
res.Update(model);
_source.SaveMessages();
}
return res?.GetViewModel;
}
}
}

View File

@ -22,6 +22,9 @@ namespace FlowerShopListImplement.Models
public string Subject { get; private set; } = string.Empty;
public string Body { get; private set; } = string.Empty;
public bool IsReaded { get; private set; }
public bool IsReply { get; private set; }
public string? ReplyMessageId { get; private set; }
public static MessageInfo? Create(MessageInfoBindingModel model)
{
@ -37,8 +40,20 @@ namespace FlowerShopListImplement.Models
MessageId = model.MessageId,
SenderName = model.SenderName,
DateDelivery = model.DateDelivery,
IsReply = model.IsReply,
IsReaded = model.IsReaded,
ReplyMessageId = model.ReplyMessageId,
};
}
public void Update(MessageInfoBindingModel model)
{
if (model == null)
{
return;
}
IsReply = model.IsReply;
IsReaded = model.IsReaded;
}
public MessageInfoViewModel GetViewModel => new()
{
@ -48,6 +63,9 @@ namespace FlowerShopListImplement.Models
MessageId = MessageId,
SenderName = SenderName,
DateDelivery = DateDelivery,
IsReply = IsReply,
IsReaded = IsReaded,
ReplyMessageId = ReplyMessageId,
};
}

View File

@ -40,7 +40,20 @@ namespace FlowerShopListImplement.Implements
result.Add(item.GetViewModel);
}
}
return result;
if (!(model.PageIndex.HasValue && model.PageLength.HasValue))
{
return result;
}
if (model.PageIndex * model.PageLength >= result.Count)
{
return new();
}
List<MessageInfoViewModel> filteredResult = new();
for (var i = (model.PageIndex.Value - 1) * model.PageLength.Value; i < model.PageIndex.Value * model.PageLength.Value; i++)
{
filteredResult.Add(result[i]);
}
return filteredResult;
}
public List<MessageInfoViewModel> GetFullList()
@ -63,5 +76,17 @@ namespace FlowerShopListImplement.Implements
_source.Messages.Add(newMessage);
return newMessage.GetViewModel;
}
public MessageInfoViewModel? Update(MessageInfoBindingModel model)
{
foreach (var message in _source.Messages)
{
if (message.MessageId.Equals(model.MessageId))
{
message.Update(model);
return message.GetViewModel;
}
}
return null;
}
}
}

View File

@ -20,13 +20,15 @@ namespace FlowerShopRestApi.Controllers
_mailLogic = mailLogic;
}
[HttpGet]
public List<MessageInfoViewModel>? GetMessages(int clientId)
public List<MessageInfoViewModel>? GetMessages(int clientId, int page, int pagesize = 1)
{
try
{
return _mailLogic.ReadList(new MessageInfoSearchModel
{
ClientId = clientId
ClientId = clientId,
PageLength = pagesize,
PageIndex = page
});
}
catch (Exception ex)

189
ProjectFlowerShop/FormLetter.Designer.cs generated Normal file
View File

@ -0,0 +1,189 @@
namespace ProjectFlowerShop
{
partial class FormLetter
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
textBoxEmail = new TextBox();
labelAdress = new Label();
labelSubject = new Label();
textBoxSubject = new TextBox();
labelBody = new Label();
textBoxBody = new TextBox();
buttonClose = new Button();
buttonReply = new Button();
labelDate = new Label();
textBoxDate = new TextBox();
buttonSend = new Button();
SuspendLayout();
//
// textBoxEmail
//
textBoxEmail.Location = new Point(63, 4);
textBoxEmail.Margin = new Padding(3, 2, 3, 2);
textBoxEmail.Name = "textBoxEmail";
textBoxEmail.ReadOnly = true;
textBoxEmail.Size = new Size(163, 23);
textBoxEmail.TabIndex = 0;
//
// labelAdress
//
labelAdress.AutoSize = true;
labelAdress.Location = new Point(10, 7);
labelAdress.Name = "labelAdress";
labelAdress.Size = new Size(43, 15);
labelAdress.TabIndex = 1;
labelAdress.Text = "Адрес:";
//
// labelSubject
//
labelSubject.AutoSize = true;
labelSubject.Location = new Point(10, 41);
labelSubject.Name = "labelSubject";
labelSubject.Size = new Size(37, 15);
labelSubject.TabIndex = 2;
labelSubject.Text = "Тема:";
//
// textBoxSubject
//
textBoxSubject.Location = new Point(63, 39);
textBoxSubject.Margin = new Padding(3, 2, 3, 2);
textBoxSubject.Name = "textBoxSubject";
textBoxSubject.ReadOnly = true;
textBoxSubject.Size = new Size(484, 23);
textBoxSubject.TabIndex = 3;
//
// labelBody
//
labelBody.AutoSize = true;
labelBody.Location = new Point(10, 72);
labelBody.Name = "labelBody";
labelBody.Size = new Size(83, 15);
labelBody.TabIndex = 4;
labelBody.Text = "Текст письма:";
//
// textBoxBody
//
textBoxBody.Location = new Point(10, 89);
textBoxBody.Margin = new Padding(3, 2, 3, 2);
textBoxBody.Multiline = true;
textBoxBody.Name = "textBoxBody";
textBoxBody.ReadOnly = true;
textBoxBody.Size = new Size(536, 140);
textBoxBody.TabIndex = 5;
//
// buttonClose
//
buttonClose.Location = new Point(430, 244);
buttonClose.Margin = new Padding(3, 2, 3, 2);
buttonClose.Name = "buttonClose";
buttonClose.Size = new Size(97, 29);
buttonClose.TabIndex = 6;
buttonClose.Text = "Закрыть";
buttonClose.UseVisualStyleBackColor = true;
buttonClose.Click += buttonClose_Click;
//
// buttonReply
//
buttonReply.Location = new Point(327, 244);
buttonReply.Margin = new Padding(3, 2, 3, 2);
buttonReply.Name = "buttonReply";
buttonReply.Size = new Size(97, 29);
buttonReply.TabIndex = 7;
buttonReply.Text = "Ответить";
buttonReply.UseVisualStyleBackColor = true;
buttonReply.Click += buttonReply_Click;
//
// labelDate
//
labelDate.AutoSize = true;
labelDate.Location = new Point(243, 7);
labelDate.Name = "labelDate";
labelDate.Size = new Size(101, 15);
labelDate.TabIndex = 8;
labelDate.Text = "Дата получения: ";
//
// textBoxDate
//
textBoxDate.Location = new Point(360, 4);
textBoxDate.Margin = new Padding(3, 2, 3, 2);
textBoxDate.Name = "textBoxDate";
textBoxDate.ReadOnly = true;
textBoxDate.Size = new Size(187, 23);
textBoxDate.TabIndex = 9;
//
// buttonSend
//
buttonSend.Location = new Point(224, 244);
buttonSend.Margin = new Padding(3, 2, 3, 2);
buttonSend.Name = "buttonSend";
buttonSend.Size = new Size(97, 29);
buttonSend.TabIndex = 10;
buttonSend.Text = "Отправить";
buttonSend.UseVisualStyleBackColor = true;
buttonSend.Visible = false;
buttonSend.Click += buttonSend_Click;
//
// FormLetter
//
AutoScaleDimensions = new SizeF(7F, 15F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(556, 283);
Controls.Add(buttonSend);
Controls.Add(textBoxDate);
Controls.Add(labelDate);
Controls.Add(buttonReply);
Controls.Add(buttonClose);
Controls.Add(textBoxBody);
Controls.Add(labelBody);
Controls.Add(textBoxSubject);
Controls.Add(labelSubject);
Controls.Add(labelAdress);
Controls.Add(textBoxEmail);
Margin = new Padding(3, 2, 3, 2);
Name = "FormLetter";
Text = "Письмо";
Load += FormLetter_Load;
ResumeLayout(false);
PerformLayout();
}
#endregion
private TextBox textBoxEmail;
private Label labelAdress;
private Label labelSubject;
private TextBox textBoxSubject;
private Label labelBody;
private TextBox textBoxBody;
private Button buttonClose;
private Button buttonReply;
private Label labelDate;
private TextBox textBoxDate;
private Button buttonSend;
}
}

View File

@ -0,0 +1,141 @@
using FlowerShopBusinessLogic.MailWorker;
using FlowerShopContracts.BindingModels;
using FlowerShopContracts.BusinessLogicsContracts;
using FlowerShopContracts.SearchModels;
using FlowerShopContracts.ViewModels;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Windows.Forms.VisualStyles;
namespace ProjectFlowerShop
{
public partial class FormLetter : Form
{
private readonly ILogger _logger;
private readonly IMessageInfoLogic _logic;
private readonly AbstractMailWorker _worker;
public MessageInfoViewModel? model;
public string? messageId;
public FormLetter(ILogger<FormLetter> logger, IMessageInfoLogic logic, AbstractMailWorker worker)
{
InitializeComponent();
_logger = logger;
_logic = logic;
_worker = worker;
}
private void FormLetter_Load(object sender, EventArgs e)
{
if (!string.IsNullOrEmpty(messageId))
{
ReloadLetter();
return;
}
else if (model != null)
{
ConfigurateToCreateAnsver();
return;
}
_logger.LogError("Для формы не переданно сведений о письме, на которое отвечаем!");
DialogResult = DialogResult.Abort;
Close();
return;
}
private void ReloadLetter()
{
_logger.LogInformation("Загрузка существующего письма с id:{}", messageId);
model = _logic.ReadElement(new MessageInfoSearchModel
{
MessageId = messageId
});
if (model != null)
{
_logger.LogInformation("Письмо найдено");
textBoxEmail.Text = model.SenderName;
textBoxDate.Text = model.DateDelivery.ToString();
textBoxSubject.Text = model.Subject;
textBoxBody.Text = model.Body;
if (model.IsReply)
{
_logger.LogInformation("Письмо само и есть ответ");
buttonReply.Visible = false;
}
else
{
if (!string.IsNullOrEmpty(model.ReplyMessageId))
{
_logger.LogInformation("У письма есть ответ.");
buttonReply.Text = "Прочитать ответ";
}
}
return;
}
_logger.LogWarning("Письмо с таким id не удалось найти");
DialogResult = DialogResult.Abort;
Close();
return;
}
private void ConfigurateToCreateAnsver()
{
textBoxEmail.Text = model.SenderName;
labelDate.Visible = false;
textBoxDate.Visible = false;
textBoxSubject.Text = $"re: {model.Subject}";
textBoxBody.ReadOnly = false;
buttonReply.Visible = false;
buttonSend.Visible = true;
_logger.LogInformation("Запущена форма создания нового письма - ответа");
}
private void buttonClose_Click(object sender, EventArgs e)
{
DialogResult = DialogResult.Cancel;
Close();
}
private void buttonReply_Click(object sender, EventArgs e)
{
var service = Program.ServiceProvider?.GetService(typeof(FormLetter));
if (service is FormLetter form)
{
if (!string.IsNullOrEmpty(model.ReplyMessageId))
{
form.messageId = model.ReplyMessageId;
}
else
{
form.model = model;
}
if (form.ShowDialog() != DialogResult.Cancel)
{
buttonReply.Visible = false;
}
}
}
private void buttonSend_Click(object sender, EventArgs e)
{
if (model == null)
{
return;
}
string subject = textBoxSubject.Text;
string text = textBoxBody.Text;
Task.Run(() => _worker.MailSendReplyAsync(new MailReplySendInfoBindingModel
{
MailAddress = model.SenderName,
Subject = subject,
Text = text,
ParentMessageId = model.MessageId,
}));
DialogResult = DialogResult.OK;
Close();
}
}
}

View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -28,35 +28,108 @@
/// </summary>
private void InitializeComponent()
{
panel1 = new Panel();
dataGridView = new DataGridView();
buttonOpen = new Button();
numericUpDownPage = new NumericUpDown();
buttonPreveous = new Button();
buttonNext = new Button();
panel1.SuspendLayout();
((System.ComponentModel.ISupportInitialize)dataGridView).BeginInit();
((System.ComponentModel.ISupportInitialize)numericUpDownPage).BeginInit();
SuspendLayout();
//
// panel1
//
panel1.Controls.Add(dataGridView);
panel1.Location = new Point(3, 1);
panel1.Name = "panel1";
panel1.Size = new Size(696, 323);
panel1.TabIndex = 0;
//
// dataGridView
//
dataGridView.AllowUserToAddRows = false;
dataGridView.AllowUserToDeleteRows = false;
dataGridView.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize;
dataGridView.Location = new Point(12, 12);
dataGridView.Dock = DockStyle.Fill;
dataGridView.Location = new Point(0, 0);
dataGridView.Margin = new Padding(3, 2, 3, 2);
dataGridView.Name = "dataGridView";
dataGridView.ReadOnly = true;
dataGridView.RowHeadersWidth = 51;
dataGridView.RowTemplate.Height = 29;
dataGridView.Size = new Size(776, 426);
dataGridView.TabIndex = 0;
dataGridView.Size = new Size(696, 323);
dataGridView.TabIndex = 2;
//
// buttonOpen
//
buttonOpen.Location = new Point(722, 187);
buttonOpen.Name = "buttonOpen";
buttonOpen.Size = new Size(74, 23);
buttonOpen.TabIndex = 1;
buttonOpen.Text = "Прочитать";
buttonOpen.UseVisualStyleBackColor = true;
buttonOpen.Click += buttonOpen_Click;
//
// numericUpDownPage
//
numericUpDownPage.Location = new Point(722, 215);
numericUpDownPage.Margin = new Padding(3, 2, 3, 2);
numericUpDownPage.Name = "numericUpDownPage";
numericUpDownPage.Size = new Size(74, 23);
numericUpDownPage.TabIndex = 4;
numericUpDownPage.ValueChanged += numericUpDownPage_ValueChanged;
//
// buttonPreveous
//
buttonPreveous.Location = new Point(722, 242);
buttonPreveous.Margin = new Padding(3, 2, 3, 2);
buttonPreveous.Name = "buttonPreveous";
buttonPreveous.Size = new Size(34, 22);
buttonPreveous.TabIndex = 5;
buttonPreveous.Text = "<-";
buttonPreveous.UseVisualStyleBackColor = true;
buttonPreveous.Click += buttonPreveous_Click;
//
// buttonNext
//
buttonNext.Location = new Point(763, 242);
buttonNext.Margin = new Padding(3, 2, 3, 2);
buttonNext.Name = "buttonNext";
buttonNext.Size = new Size(34, 22);
buttonNext.TabIndex = 6;
buttonNext.Text = "->";
buttonNext.UseVisualStyleBackColor = true;
buttonNext.Click += buttonNext_Click;
//
// ViewMailForm
//
AutoScaleDimensions = new SizeF(8F, 20F);
AutoScaleDimensions = new SizeF(7F, 15F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(800, 450);
Controls.Add(dataGridView);
ClientSize = new Size(809, 321);
Controls.Add(buttonNext);
Controls.Add(buttonPreveous);
Controls.Add(numericUpDownPage);
Controls.Add(buttonOpen);
Controls.Add(panel1);
Margin = new Padding(3, 2, 3, 2);
Name = "ViewMailForm";
Text = "ViewMailForm";
Text = "Письма";
Load += ViewMailForm_Load;
panel1.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)dataGridView).EndInit();
((System.ComponentModel.ISupportInitialize)numericUpDownPage).EndInit();
ResumeLayout(false);
}
#endregion
private Panel panel1;
private DataGridView dataGridView;
private Button buttonOpen;
private NumericUpDown numericUpDownPage;
private Button buttonPreveous;
private Button buttonNext;
}
}

View File

@ -1,4 +1,6 @@
using FlowerShopContracts.BusinessLogicsContracts;
using FlowerShopContracts.BindingModels;
using FlowerShopContracts.BusinessLogicsContracts;
using FlowerShopContracts.SearchModels;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
@ -6,6 +8,7 @@ using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
@ -16,23 +19,36 @@ namespace ProjectFlowerShop
{
private readonly ILogger _logger;
private readonly IMessageInfoLogic _logic;
private int currentPage = 1;
private int pageLength = 2;
public FormViewMail(ILogger<FormViewMail> logger, IMessageInfoLogic logic)
{
InitializeComponent();
_logger = logger;
_logic = logic;
}
private void ViewMailForm_Load(object sender, EventArgs e)
{
LoadData();
numericUpDownPage.Value = pageLength;
}
private void LoadData()
{
try
{
var list = _logic.ReadList(null);
var list = _logic.ReadList(new MessageInfoSearchModel()
{
PageLength = pageLength,
PageIndex = currentPage
});
if (list != null)
{
dataGridView.DataSource = list;
dataGridView.Columns["ClientId"].Visible = false;
dataGridView.Columns["MessageId"].Visible = false;
dataGridView.Columns["ReplyMessageId"].Visible = false;
dataGridView.Columns["Reply"].Visible = false;
dataGridView.Columns["IsReply"].Visible = false;
dataGridView.Columns["Body"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
}
_logger.LogInformation("Загрузка списка писем");
@ -44,5 +60,49 @@ namespace ProjectFlowerShop
MessageBoxIcon.Error);
}
}
private void buttonOpen_Click(object sender, EventArgs e)
{
if (dataGridView.SelectedRows.Count <= 0)
return;
var service = Program.ServiceProvider?.GetService(typeof(FormLetter));
if (service is FormLetter form)
{
string? messageId = dataGridView.SelectedRows[0].Cells["MessageId"].Value.ToString();
if (messageId == null) return;
form.messageId = messageId;
if (!Convert.ToBoolean(dataGridView.SelectedRows[0].Cells["IsReaded"].Value))
{
_logic.Update(new MessageInfoBindingModel
{
MessageId = messageId,
IsReaded = true,
ReplyMessageId = dataGridView.SelectedRows[0].Cells["ReplyMessageId"].Value?.ToString()
});
}
form.ShowDialog();
LoadData();
}
}
private void buttonPreveous_Click(object sender, EventArgs e)
{
currentPage = Math.Max(1, currentPage - 1);
LoadData();
}
private void buttonNext_Click(object sender, EventArgs e)
{
currentPage++;
LoadData();
}
private void numericUpDownPage_ValueChanged(object sender, EventArgs e)
{
pageLength = Math.Max(1, (int)numericUpDownPage.Value);
LoadData();
}
}
}

View File

@ -37,7 +37,8 @@
поставкиToolStripMenuItem = new ToolStripMenuItem();
продажиToolStripMenuItem = new ToolStripMenuItem();
исполнителиToolStripMenuItem = new ToolStripMenuItem();
начатьРаботуToolStripMenuItem = new ToolStripMenuItem();
стартРаботToolStripMenuItem = new ToolStripMenuItem();
почтаToolStripMenuItem = new ToolStripMenuItem();
отчетыToolStripMenuItem = new ToolStripMenuItem();
списокКомпонентовToolStripMenuItem = new ToolStripMenuItem();
компонентыToolStripMenuItem = new ToolStripMenuItem();
@ -51,7 +52,6 @@
ReadyButton = new Button();
IssuedButton = new Button();
RefreshButton = new Button();
почтаToolStripMenuItem = new ToolStripMenuItem();
menuStrip1.SuspendLayout();
((System.ComponentModel.ISupportInitialize)DataGridView).BeginInit();
SuspendLayout();
@ -68,8 +68,7 @@
//
// ToolStripMenu
//
ToolStripMenu.DropDownItems.AddRange(new ToolStripItem[] { клиентыToolStripMenuItem, КомпонентыStripMenuItem, ЦветыStripMenuItem, магазиныToolStripMenuItem, поставкиToolStripMenuItem, продажиToolStripMenuItem, исполнителиToolStripMenuItem, начатьРаботуToolStripMenuItem, почтаToolStripMenuItem });
ToolStripMenu.DropDownItems.AddRange(new ToolStripItem[] { КомпонентыStripMenuItem, ЦветыStripMenuItem, клиентыToolStripMenuItem, исполнителиToolStripMenuItem, стартРаботToolStripMenuItem, });
ToolStripMenu.DropDownItems.AddRange(new ToolStripItem[] { магазиныToolStripMenuItem, поставкиToolStripMenuItem, продажиToolStripMenuItem, почтаToolStripMenuItem, КомпонентыStripMenuItem, ЦветыStripMenuItem, клиентыToolStripMenuItem, исполнителиToolStripMenuItem, стартРаботToolStripMenuItem });
ToolStripMenu.Name = "ToolStripMenu";
ToolStripMenu.Size = new Size(117, 24);
ToolStripMenu.Text = "Справочники";
@ -77,46 +76,42 @@
// клиентыToolStripMenuItem
//
клиентыToolStripMenuItem.Name = "клиентыToolStripMenuItem";
клиентыToolStripMenuItem.Size = new Size(193, 26);
клиентыToolStripMenuItem.Size = new Size(224, 26);
клиентыToolStripMenuItem.Text = "Клиенты";
клиентыToolStripMenuItem.Click += клиентыToolStripMenuItem_Click;
//
// КомпонентыStripMenuItem
//
КомпонентыStripMenuItem.Name = "КомпонентыStripMenuItem";
КомпонентыStripMenuItem.Size = new Size(185, 26);
КомпонентыStripMenuItem.Size = new Size(224, 26);
КомпонентыStripMenuItem.Text = "Компоненты";
КомпонентыStripMenuItem.Click += КомпонентыStripMenuItem_Click;
//
// ЦветыStripMenuItem
//
ЦветыStripMenuItem.Name = "ЦветыStripMenuItem";
ЦветыStripMenuItem.Size = new Size(185, 26);
ЦветыStripMenuItem.Size = new Size(224, 26);
ЦветыStripMenuItem.Text = "Цветы";
ЦветыStripMenuItem.Click += ЦветыStripMenuItem_Click;
//
// магазиныToolStripMenuItem
//
магазиныToolStripMenuItem.Name = агазиныToolStripMenuItem";
магазиныToolStripMenuItem.Size = new Size(193, 26);
магазиныToolStripMenuItem.Size = new Size(224, 26);
магазиныToolStripMenuItem.Text = "Магазины";
магазиныToolStripMenuItem.Click += магазиныToolStripMenuItem_Click;
клиентыToolStripMenuItem.Name = "клиентыToolStripMenuItem";
клиентыToolStripMenuItem.Size = new Size(224, 26);
клиентыToolStripMenuItem.Text = "Клиенты";
клиентыToolStripMenuItem.Click += клиентыToolStripMenuItem_Click;
//
// поставкиToolStripMenuItem
//
поставкиToolStripMenuItem.Name = "поставкиToolStripMenuItem";
поставкиToolStripMenuItem.Size = new Size(193, 26);
поставкиToolStripMenuItem.Size = new Size(224, 26);
поставкиToolStripMenuItem.Text = "Поставки";
поставкиToolStripMenuItem.Click += поставкиToolStripMenuItem_Click;
//
// продажиToolStripMenuItem
//
продажиToolStripMenuItem.Name = "продажиToolStripMenuItem";
продажиToolStripMenuItem.Size = new Size(193, 26);
продажиToolStripMenuItem.Size = new Size(224, 26);
продажиToolStripMenuItem.Text = "Продажи";
продажиToolStripMenuItem.Click += продажиToolStripMenuItem_Click;
//
@ -127,13 +122,20 @@
исполнителиToolStripMenuItem.Text = "Исполнители";
исполнителиToolStripMenuItem.Click += исполнителиToolStripMenuItem_Click;
//
// начатьРаботуToolStripMenuItem
// стартРаботToolStripMenuItem
//
стартРаботToolStripMenuItem.Name = "стартРаботToolStripMenuItem";
стартРаботToolStripMenuItem.Size = new Size(224, 26);
стартРаботToolStripMenuItem.Text = "Старт работ";
стартРаботToolStripMenuItem.Click += стартРаботToolStripMenuItem_Click;
//
// почтаToolStripMenuItem
//
почтаToolStripMenuItem.Name = "почтаToolStripMenuItem";
почтаToolStripMenuItem.Size = new Size(224, 26);
почтаToolStripMenuItem.Text = "Почта";
почтаToolStripMenuItem.Click += почтаToolStripMenuItem_Click;
//
// отчетыToolStripMenuItem
//
отчетыToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { списокКомпонентовToolStripMenuItem, компонентыToolStripMenuItem, списокЗаказовToolStripMenuItem, списокМагазиновToolStripMenuItem, цветыПоМагазинамToolStripMenuItem, заказыПоДатамToolStripMenuItem });
@ -242,13 +244,6 @@
RefreshButton.UseVisualStyleBackColor = true;
RefreshButton.Click += RefreshButton_Click;
//
// почтаToolStripMenuItem
//
почтаToolStripMenuItem.Name = "почтаToolStripMenuItem";
почтаToolStripMenuItem.Size = new Size(224, 26);
почтаToolStripMenuItem.Text = "Почта";
почтаToolStripMenuItem.Click += почтаToolStripMenuItem_Click;
//
// MainForm
//
AutoScaleDimensions = new SizeF(8F, 20F);

View File

@ -297,13 +297,6 @@ namespace ProjectFlowerShop
}
}
private void начатьРаботуToolStripMenuItem_Click(object sender, EventArgs e)
{
_workProcess.DoWork((Program.ServiceProvider?.GetService(typeof(IImplementerLogic)) as IImplementerLogic)!, _orderLogic);
MessageBox.Show("Процесс обработки запущен", "Сообщение",
MessageBoxButtons.OK, MessageBoxIcon.Information);
}
private void почтаToolStripMenuItem_Click(object sender, EventArgs e)
{
var service = Program.ServiceProvider?.GetService(typeof(FormViewMail));
@ -312,5 +305,12 @@ namespace ProjectFlowerShop
form.ShowDialog();
}
}
private void стартРаботToolStripMenuItem_Click(object sender, EventArgs e)
{
_workProcess.DoWork((Program.ServiceProvider?.GetService(typeof(IImplementerLogic)) as IImplementerLogic)!, _orderLogic);
MessageBox.Show("Процесс обработки запущен", "Сообщение",
MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
}