16 Commits
lab4 ... lab7

Author SHA1 Message Date
7f5911ffaf ready 2024-06-21 21:27:01 +04:00
37140ad273 ready 2024-06-21 21:03:33 +04:00
34004cd13f работает 2024-06-21 20:59:30 +04:00
8d048df15b отображение колонок 2024-06-19 14:38:52 +04:00
9cfd6b1b6f 7 готовая 2024-06-16 14:32:38 +04:00
ac51c61cf0 поменяла емайл и пароль 2024-06-14 18:38:41 +04:00
1cde2587b2 в abstractMailWorker mainLogin и password пустые( 2024-05-15 00:53:41 +04:00
596f77bcb9 готово 2024-05-14 19:05:59 +04:00
c8f16f65fe утро вечера мудренее 2024-05-13 23:46:59 +04:00
113baf20a0 да 2024-05-13 22:15:56 +04:00
23ff91c1e5 добавлен исполнитель, всё прописано 2024-05-12 19:24:51 +04:00
f0a6b9d5c7 точно всё 2024-05-12 13:02:16 +04:00
c3238fa244 готово!!! 2024-05-12 12:56:51 +04:00
9255552c85 основа есть, надо отшлифовать 2024-05-06 22:32:01 +04:00
864ba4c58a настроить clientAPI 2024-04-17 12:51:33 +04:00
d4aa1e4805 начата лаб5 2024-04-17 11:28:47 +04:00
177 changed files with 79523 additions and 284 deletions

11
FishFactory/App.config Normal file
View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="SmtpClientHost" value="smtp.yandex.ru" />
<add key="SmtpClientPort" value="587" />
<add key="PopHost" value="pop.yandex.ru" />
<add key="PopPort" value="995" />
<add key="MailLogin" value="iskander044ya@yandex.ru" />
<add key="MailPassword" value="aakjmhccsmlkkisn" />
</appSettings>
</configuration>

View File

@@ -2,7 +2,7 @@
<PropertyGroup> <PropertyGroup>
<OutputType>WinExe</OutputType> <OutputType>WinExe</OutputType>
<TargetFramework>net6.0-windows</TargetFramework> <TargetFramework>net8.0-windows7.0</TargetFramework>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<UseWindowsForms>true</UseWindowsForms> <UseWindowsForms>true</UseWindowsForms>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
@@ -42,6 +42,12 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Update="App.config">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="nlog.config">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="ReportOrders.rdlc"> <None Update="ReportOrders.rdlc">
<CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None> </None>

View File

@@ -13,9 +13,13 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FishFactoryDataModel", "..\
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FishFactoryListImplement", "..\FishFactoryListImplement\FishFactoryListImplement.csproj", "{A507DACE-7D8D-4C0F-AB5D-764FE1A61EDC}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FishFactoryListImplement", "..\FishFactoryListImplement\FishFactoryListImplement.csproj", "{A507DACE-7D8D-4C0F-AB5D-764FE1A61EDC}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FishFactoryFileImplement", "..\FishFactoryFileImplement\FishFactoryFileImplement.csproj", "{4EB943AB-67A8-4386-8874-FA0E3E98159C}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FishFactoryFileImplement", "..\FishFactoryFileImplement\FishFactoryFileImplement.csproj", "{4EB943AB-67A8-4386-8874-FA0E3E98159C}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FishFactoryDatabaseImplement", "..\FishFactoryDatabaseImplement\FishFactoryDatabaseImplement.csproj", "{5744376D-B7D8-4FFD-B6D9-F53C169B056C}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FishFactoryDatabaseImplement", "..\FishFactoryDatabaseImplement\FishFactoryDatabaseImplement.csproj", "{5744376D-B7D8-4FFD-B6D9-F53C169B056C}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FishFactoryRestApi", "..\FishFactoryRestApi\FishFactoryRestApi.csproj", "{AB6068FA-9FA7-40E9-9A2F-2BF7B97AD621}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FishFactoryClientApp", "..\FishFactoryClientApp\FishFactoryClientApp.csproj", "{76A3D175-F30D-46ED-94C7-7D4272D5E97D}"
EndProject EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -81,6 +85,22 @@ Global
{5744376D-B7D8-4FFD-B6D9-F53C169B056C}.Release|Any CPU.Build.0 = Release|Any CPU {5744376D-B7D8-4FFD-B6D9-F53C169B056C}.Release|Any CPU.Build.0 = Release|Any CPU
{5744376D-B7D8-4FFD-B6D9-F53C169B056C}.Release|x86.ActiveCfg = Release|Any CPU {5744376D-B7D8-4FFD-B6D9-F53C169B056C}.Release|x86.ActiveCfg = Release|Any CPU
{5744376D-B7D8-4FFD-B6D9-F53C169B056C}.Release|x86.Build.0 = Release|Any CPU {5744376D-B7D8-4FFD-B6D9-F53C169B056C}.Release|x86.Build.0 = Release|Any CPU
{AB6068FA-9FA7-40E9-9A2F-2BF7B97AD621}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AB6068FA-9FA7-40E9-9A2F-2BF7B97AD621}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AB6068FA-9FA7-40E9-9A2F-2BF7B97AD621}.Debug|x86.ActiveCfg = Debug|Any CPU
{AB6068FA-9FA7-40E9-9A2F-2BF7B97AD621}.Debug|x86.Build.0 = Debug|Any CPU
{AB6068FA-9FA7-40E9-9A2F-2BF7B97AD621}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AB6068FA-9FA7-40E9-9A2F-2BF7B97AD621}.Release|Any CPU.Build.0 = Release|Any CPU
{AB6068FA-9FA7-40E9-9A2F-2BF7B97AD621}.Release|x86.ActiveCfg = Release|Any CPU
{AB6068FA-9FA7-40E9-9A2F-2BF7B97AD621}.Release|x86.Build.0 = Release|Any CPU
{76A3D175-F30D-46ED-94C7-7D4272D5E97D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{76A3D175-F30D-46ED-94C7-7D4272D5E97D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{76A3D175-F30D-46ED-94C7-7D4272D5E97D}.Debug|x86.ActiveCfg = Debug|Any CPU
{76A3D175-F30D-46ED-94C7-7D4272D5E97D}.Debug|x86.Build.0 = Debug|Any CPU
{76A3D175-F30D-46ED-94C7-7D4272D5E97D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{76A3D175-F30D-46ED-94C7-7D4272D5E97D}.Release|Any CPU.Build.0 = Release|Any CPU
{76A3D175-F30D-46ED-94C7-7D4272D5E97D}.Release|x86.ActiveCfg = Release|Any CPU
{76A3D175-F30D-46ED-94C7-7D4272D5E97D}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE

View File

@@ -0,0 +1,93 @@
namespace FishFactory.Forms
{
partial class FormClients
{
/// <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()
{
dataGridView = new DataGridView();
buttonRefresh = new Button();
buttonDel = new Button();
((System.ComponentModel.ISupportInitialize)dataGridView).BeginInit();
SuspendLayout();
//
// dataGridView
//
dataGridView.AllowUserToAddRows = false;
dataGridView.AllowUserToDeleteRows = false;
dataGridView.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
dataGridView.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize;
dataGridView.Location = new Point(0, -3);
dataGridView.Name = "dataGridView";
dataGridView.ReadOnly = true;
dataGridView.RowHeadersWidth = 48;
dataGridView.Size = new Size(660, 441);
dataGridView.TabIndex = 0;
//
// buttonRefresh
//
buttonRefresh.Anchor = AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
buttonRefresh.Location = new Point(352, 470);
buttonRefresh.Name = "buttonRefresh";
buttonRefresh.Size = new Size(118, 28);
buttonRefresh.TabIndex = 1;
buttonRefresh.Text = "Обновить";
buttonRefresh.UseVisualStyleBackColor = true;
buttonRefresh.Click += buttonRefresh_Click;
//
// buttonDel
//
buttonDel.Anchor = AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
buttonDel.Location = new Point(188, 471);
buttonDel.Name = "buttonDel";
buttonDel.Size = new Size(118, 27);
buttonDel.TabIndex = 2;
buttonDel.Text = "Удалить";
buttonDel.UseVisualStyleBackColor = true;
buttonDel.Click += buttonDel_Click;
//
// FormClients
//
AutoScaleDimensions = new SizeF(8F, 19F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(660, 531);
Controls.Add(buttonDel);
Controls.Add(buttonRefresh);
Controls.Add(dataGridView);
Name = "FormClients";
Text = "FormClients";
Load += FormClients_Load;
((System.ComponentModel.ISupportInitialize)dataGridView).EndInit();
ResumeLayout(false);
}
#endregion
private DataGridView dataGridView;
private Button buttonRefresh;
private Button buttonDel;
}
}

View File

@@ -0,0 +1,77 @@
using FishFactoryContracts.BindingModels;
using FishFactoryContracts.BusinessLogicsContracts;
using Microsoft.Extensions.Logging;
namespace FishFactory.Forms
{
public partial class FormClients : Form
{
private readonly ILogger _logger;
private readonly IClientLogic _logic;
public FormClients(ILogger<FormClients> logger, IClientLogic logic)
{
InitializeComponent();
_logger = logger;
_logic = logic;
}
private void FormClients_Load(object sender, EventArgs e)
{
LoadData();
}
private void LoadData()
{
try
{
var list = _logic.ReadList(null);
if (list != null)
{
dataGridView.DataSource = list;
dataGridView.Columns["Id"].Visible = false;
dataGridView.Columns["ClientFIO"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
dataGridView.Columns["Email"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
dataGridView.Columns["Password"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
}
_logger.LogInformation("Загрузка клиентов");
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка загрузки клиентов");
MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void buttonRefresh_Click(object sender, EventArgs e)
{
LoadData();
}
private void buttonDel_Click(object sender, EventArgs e)
{
if (dataGridView.SelectedRows.Count == 1)
{
if (MessageBox.Show("Удалить пользователя?", "Удаление", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
{
int id = Convert.ToInt32(dataGridView.SelectedRows[0].Cells["Id"].Value);
try
{
if (!_logic.Delete(new ClientBindingModel { Id = id }))
{
throw new Exception("Ошибка при удалении. Дополнительная информация в логах.");
}
_logger.LogInformation("Удаление клиента");
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка удаления клиента");
MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
LoadData();
}
}
}
}
}

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

@@ -36,69 +36,71 @@
textBoxSum = new TextBox(); textBoxSum = new TextBox();
buttonSave = new Button(); buttonSave = new Button();
buttonCancel = new Button(); buttonCancel = new Button();
label4 = new Label();
comboBoxClient = new ComboBox();
SuspendLayout(); SuspendLayout();
// //
// label1 // label1
// //
label1.AutoSize = true; label1.AutoSize = true;
label1.Location = new Point(22, 16); label1.Location = new Point(23, 58);
label1.Name = "label1"; label1.Name = "label1";
label1.Size = new Size(71, 20); label1.Size = new Size(65, 19);
label1.TabIndex = 0; label1.TabIndex = 0;
label1.Text = "Изделие:"; label1.Text = "Изделие:";
// //
// label2 // label2
// //
label2.AutoSize = true; label2.AutoSize = true;
label2.Location = new Point(22, 58); label2.Location = new Point(23, 97);
label2.Name = "label2"; label2.Name = "label2";
label2.Size = new Size(93, 20); label2.Size = new Size(85, 19);
label2.TabIndex = 1; label2.TabIndex = 1;
label2.Text = "Количество:"; label2.Text = "Количество:";
// //
// label3 // label3
// //
label3.AutoSize = true; label3.AutoSize = true;
label3.Location = new Point(22, 94); label3.Location = new Point(23, 135);
label3.Name = "label3"; label3.Name = "label3";
label3.Size = new Size(58, 20); label3.Size = new Size(55, 19);
label3.TabIndex = 2; label3.TabIndex = 2;
label3.Text = "Сумма:"; label3.Text = "Сумма:";
// //
// textBoxCount // textBoxCount
// //
textBoxCount.Location = new Point(118, 55); textBoxCount.Location = new Point(119, 94);
textBoxCount.Margin = new Padding(3, 4, 3, 4); textBoxCount.Margin = new Padding(3, 4, 3, 4);
textBoxCount.Name = "textBoxCount"; textBoxCount.Name = "textBoxCount";
textBoxCount.Size = new Size(280, 27); textBoxCount.Size = new Size(280, 26);
textBoxCount.TabIndex = 3; textBoxCount.TabIndex = 3;
textBoxCount.TextChanged += textBoxCount_TextChanged; textBoxCount.TextChanged += textBoxCount_TextChanged;
// //
// comboBoxCanned // comboBoxCanned
// //
comboBoxCanned.FormattingEnabled = true; comboBoxCanned.FormattingEnabled = true;
comboBoxCanned.Location = new Point(118, 14); comboBoxCanned.Location = new Point(119, 55);
comboBoxCanned.Margin = new Padding(3, 4, 3, 4); comboBoxCanned.Margin = new Padding(3, 4, 3, 4);
comboBoxCanned.Name = "comboBoxCanned"; comboBoxCanned.Name = "comboBoxCanned";
comboBoxCanned.Size = new Size(280, 28); comboBoxCanned.Size = new Size(280, 27);
comboBoxCanned.TabIndex = 4; comboBoxCanned.TabIndex = 4;
comboBoxCanned.SelectedIndexChanged += ComboBoxCanned_SelectedIndexChanged; comboBoxCanned.SelectedIndexChanged += ComboBoxCanned_SelectedIndexChanged;
// //
// textBoxSum // textBoxSum
// //
textBoxSum.Location = new Point(118, 94); textBoxSum.Location = new Point(119, 132);
textBoxSum.Margin = new Padding(3, 4, 3, 4); textBoxSum.Margin = new Padding(3, 4, 3, 4);
textBoxSum.Name = "textBoxSum"; textBoxSum.Name = "textBoxSum";
textBoxSum.ReadOnly = true; textBoxSum.ReadOnly = true;
textBoxSum.Size = new Size(280, 27); textBoxSum.Size = new Size(280, 26);
textBoxSum.TabIndex = 5; textBoxSum.TabIndex = 5;
// //
// buttonSave // buttonSave
// //
buttonSave.Location = new Point(172, 135); buttonSave.Location = new Point(177, 176);
buttonSave.Margin = new Padding(3, 4, 3, 4); buttonSave.Margin = new Padding(3, 4, 3, 4);
buttonSave.Name = "buttonSave"; buttonSave.Name = "buttonSave";
buttonSave.Size = new Size(107, 35); buttonSave.Size = new Size(107, 33);
buttonSave.TabIndex = 6; buttonSave.TabIndex = 6;
buttonSave.Text = "Сохранить"; buttonSave.Text = "Сохранить";
buttonSave.UseVisualStyleBackColor = true; buttonSave.UseVisualStyleBackColor = true;
@@ -106,20 +108,39 @@
// //
// buttonCancel // buttonCancel
// //
buttonCancel.Location = new Point(285, 135); buttonCancel.Location = new Point(290, 176);
buttonCancel.Margin = new Padding(3, 4, 3, 4); buttonCancel.Margin = new Padding(3, 4, 3, 4);
buttonCancel.Name = "buttonCancel"; buttonCancel.Name = "buttonCancel";
buttonCancel.Size = new Size(107, 35); buttonCancel.Size = new Size(107, 33);
buttonCancel.TabIndex = 7; buttonCancel.TabIndex = 7;
buttonCancel.Text = "Отмена"; buttonCancel.Text = "Отмена";
buttonCancel.UseVisualStyleBackColor = true; buttonCancel.UseVisualStyleBackColor = true;
buttonCancel.Click += buttonCancel_Click; buttonCancel.Click += buttonCancel_Click;
// //
// label4
//
label4.AutoSize = true;
label4.Location = new Point(23, 18);
label4.Name = "label4";
label4.Size = new Size(56, 19);
label4.TabIndex = 8;
label4.Text = "Клиент:";
//
// comboBoxClient
//
comboBoxClient.FormattingEnabled = true;
comboBoxClient.Location = new Point(119, 15);
comboBoxClient.Name = "comboBoxClient";
comboBoxClient.Size = new Size(280, 27);
comboBoxClient.TabIndex = 9;
//
// FormCreateOrder // FormCreateOrder
// //
AutoScaleDimensions = new SizeF(8F, 20F); AutoScaleDimensions = new SizeF(8F, 19F);
AutoScaleMode = AutoScaleMode.Font; AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(428, 182); ClientSize = new Size(428, 222);
Controls.Add(comboBoxClient);
Controls.Add(label4);
Controls.Add(buttonCancel); Controls.Add(buttonCancel);
Controls.Add(buttonSave); Controls.Add(buttonSave);
Controls.Add(textBoxSum); Controls.Add(textBoxSum);
@@ -131,7 +152,7 @@
Margin = new Padding(3, 4, 3, 4); Margin = new Padding(3, 4, 3, 4);
Name = "FormCreateOrder"; Name = "FormCreateOrder";
Text = "Заказ"; Text = "Заказ";
Load += new System.EventHandler(this.FormCreateOrder_Load); Load += FormCreateOrder_Load;
ResumeLayout(false); ResumeLayout(false);
PerformLayout(); PerformLayout();
} }
@@ -146,5 +167,7 @@
private TextBox textBoxSum; private TextBox textBoxSum;
private Button buttonSave; private Button buttonSave;
private Button buttonCancel; private Button buttonCancel;
private Label label4;
private ComboBox comboBoxClient;
} }
} }

View File

@@ -2,15 +2,6 @@
using FishFactoryContracts.BusinessLogicsContracts; using FishFactoryContracts.BusinessLogicsContracts;
using FishFactoryContracts.SearchModels; using FishFactoryContracts.SearchModels;
using Microsoft.Extensions.Logging; 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;
namespace FishFactory.Forms namespace FishFactory.Forms
{ {
@@ -19,12 +10,14 @@ namespace FishFactory.Forms
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly ICannedLogic _logicP; private readonly ICannedLogic _logicP;
private readonly IOrderLogic _logicO; private readonly IOrderLogic _logicO;
public FormCreateOrder(ILogger<FormCreateOrder> logger, ICannedLogic logicP, IOrderLogic logicO) private readonly IClientLogic _logicC;
public FormCreateOrder(ILogger<FormCreateOrder> logger, ICannedLogic logicP, IOrderLogic logicO, IClientLogic logicC)
{ {
InitializeComponent(); InitializeComponent();
_logger = logger; _logger = logger;
_logicP = logicP; _logicP = logicP;
_logicO = logicO; _logicO = logicO;
_logicC = logicC;
} }
private void FormCreateOrder_Load(object sender, EventArgs e) private void FormCreateOrder_Load(object sender, EventArgs e)
@@ -40,10 +33,19 @@ namespace FishFactory.Forms
comboBoxCanned.SelectedItem = null; comboBoxCanned.SelectedItem = null;
_logger.LogInformation("Загрузка изделий для заказа"); _logger.LogInformation("Загрузка изделий для заказа");
} }
var listC = _logicC.ReadList(null);
if (listC != null)
{
comboBoxClient.DisplayMember = "ClientFIO";
comboBoxClient.ValueMember = "Id";
comboBoxClient.DataSource = listC;
comboBoxClient.SelectedItem = null;
_logger.LogInformation("Загрузка клинтов для заказа");
}
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex, "Ошибка загрузки списка изделий"); _logger.LogError(ex, "Ошибка загрузки списка изделий и списка клиентов");
} }
} }
private void CalcSum() private void CalcSum()
@@ -80,9 +82,9 @@ namespace FishFactory.Forms
private void buttonSave_Click(object sender, EventArgs e) private void buttonSave_Click(object sender, EventArgs e)
{ {
if (string.IsNullOrEmpty(textBoxCount.Text)) if (comboBoxClient.SelectedValue == null)
{ {
MessageBox.Show("Заполните поле Количество", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error); MessageBox.Show("Выберите клиента", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
return; return;
} }
if (comboBoxCanned.SelectedValue == null) if (comboBoxCanned.SelectedValue == null)
@@ -90,6 +92,11 @@ namespace FishFactory.Forms
MessageBox.Show("Выберите изделие", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error); MessageBox.Show("Выберите изделие", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
return; return;
} }
if (string.IsNullOrEmpty(textBoxCount.Text))
{
MessageBox.Show("Заполните поле Количество", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
_logger.LogInformation("Создание заказа"); _logger.LogInformation("Создание заказа");
try try
{ {
@@ -97,7 +104,8 @@ namespace FishFactory.Forms
{ {
CannedId = Convert.ToInt32(comboBoxCanned.SelectedValue), CannedId = Convert.ToInt32(comboBoxCanned.SelectedValue),
Count = Convert.ToInt32(textBoxCount.Text), Count = Convert.ToInt32(textBoxCount.Text),
Sum = Convert.ToDouble(textBoxSum.Text) Sum = Convert.ToDouble(textBoxSum.Text),
ClientId = Convert.ToInt32(comboBoxClient.SelectedValue)
}); });
if (!operationResult) if (!operationResult)
{ {

View File

@@ -0,0 +1,168 @@
namespace FishFactory.Forms
{
partial class FormImplementer
{
/// <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()
{
textBoxWorkExperience = new TextBox();
textBoxFIO = new TextBox();
label2 = new Label();
label1 = new Label();
buttonCancel = new Button();
buttonSave = new Button();
textBoxQualification = new TextBox();
label3 = new Label();
textBoxPassword = new TextBox();
label4 = new Label();
SuspendLayout();
//
// textBoxWorkExperience
//
textBoxWorkExperience.Location = new Point(189, 97);
textBoxWorkExperience.Margin = new Padding(3, 4, 3, 4);
textBoxWorkExperience.Name = "textBoxWorkExperience";
textBoxWorkExperience.Size = new Size(305, 26);
textBoxWorkExperience.TabIndex = 11;
//
// textBoxFIO
//
textBoxFIO.Location = new Point(189, 27);
textBoxFIO.Margin = new Padding(3, 4, 3, 4);
textBoxFIO.Name = "textBoxFIO";
textBoxFIO.Size = new Size(305, 26);
textBoxFIO.TabIndex = 10;
//
// label2
//
label2.AutoSize = true;
label2.Location = new Point(43, 100);
label2.Name = "label2";
label2.Size = new Size(95, 19);
label2.TabIndex = 9;
label2.Text = "Стаж работы:";
//
// label1
//
label1.AutoSize = true;
label1.Location = new Point(43, 29);
label1.Name = "label1";
label1.Size = new Size(127, 19);
label1.TabIndex = 8;
label1.Text = "ФИО исполнителя:";
//
// buttonCancel
//
buttonCancel.Location = new Point(400, 191);
buttonCancel.Margin = new Padding(3, 4, 3, 4);
buttonCancel.Name = "buttonCancel";
buttonCancel.Size = new Size(98, 32);
buttonCancel.TabIndex = 7;
buttonCancel.Text = "Отмена";
buttonCancel.UseVisualStyleBackColor = true;
buttonCancel.Click += buttonCancel_Click;
//
// buttonSave
//
buttonSave.Location = new Point(292, 191);
buttonSave.Margin = new Padding(3, 4, 3, 4);
buttonSave.Name = "buttonSave";
buttonSave.Size = new Size(98, 32);
buttonSave.TabIndex = 6;
buttonSave.Text = "Сохранить";
buttonSave.UseVisualStyleBackColor = true;
buttonSave.Click += buttonSave_Click;
//
// textBoxQualification
//
textBoxQualification.Location = new Point(189, 131);
textBoxQualification.Margin = new Padding(3, 4, 3, 4);
textBoxQualification.Name = "textBoxQualification";
textBoxQualification.Size = new Size(305, 26);
textBoxQualification.TabIndex = 13;
//
// label3
//
label3.AutoSize = true;
label3.Location = new Point(43, 134);
label3.Name = "label3";
label3.Size = new Size(104, 19);
label3.TabIndex = 12;
label3.Text = "Квалификация:";
//
// textBoxPassword
//
textBoxPassword.Location = new Point(189, 63);
textBoxPassword.Margin = new Padding(3, 4, 3, 4);
textBoxPassword.Name = "textBoxPassword";
textBoxPassword.Size = new Size(305, 26);
textBoxPassword.TabIndex = 15;
//
// label4
//
label4.AutoSize = true;
label4.Location = new Point(43, 65);
label4.Name = "label4";
label4.Size = new Size(59, 19);
label4.TabIndex = 14;
label4.Text = "Пароль:";
//
// FormImplementer
//
AutoScaleDimensions = new SizeF(8F, 19F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(536, 238);
Controls.Add(textBoxPassword);
Controls.Add(label4);
Controls.Add(textBoxQualification);
Controls.Add(label3);
Controls.Add(textBoxWorkExperience);
Controls.Add(textBoxFIO);
Controls.Add(label2);
Controls.Add(label1);
Controls.Add(buttonCancel);
Controls.Add(buttonSave);
Name = "FormImplementer";
Text = "FormImplementer";
Load += FormImplementer_Load;
ResumeLayout(false);
PerformLayout();
}
#endregion
private TextBox textBoxWorkExperience;
private TextBox textBoxFIO;
private Label label2;
private Label label1;
private Button buttonCancel;
private Button buttonSave;
private TextBox textBoxQualification;
private Label label3;
private TextBox textBoxPassword;
private Label label4;
}
}

View File

@@ -0,0 +1,95 @@
using FishFactoryContracts.BindingModels;
using FishFactoryContracts.BusinessLogicsContracts;
using FishFactoryContracts.SearchModels;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
namespace FishFactory.Forms
{
public partial class FormImplementer : Form
{
private readonly ILogger _logger;
private readonly IImplementerLogic _logic;
private int? _id;
public int Id {set { _id = value; }}
public FormImplementer(ILogger<FormImplementer> logger, IImplementerLogic logic)
{
InitializeComponent();
_logger = logger;
_logic = logic;
}
private void FormImplementer_Load(object sender, EventArgs e)
{
if (_id.HasValue)
{
try
{
_logger.LogInformation("Получение исполнителя");
var view = _logic.ReadElement(new ImplementerSearchModel
{
Id = _id.Value
});
if (view != null)
{
textBoxFIO.Text = view.ImplementerFIO;
textBoxPassword.Text = view.Password;
textBoxWorkExperience.Text = view.WorkExperience.ToString();
textBoxQualification.Text = view.Qualification.ToString();
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка получения исполнителя");
MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
private void buttonSave_Click(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(textBoxFIO.Text))
{
MessageBox.Show("Заполните ФИО", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
if (string.IsNullOrEmpty(textBoxPassword.Text))
{
MessageBox.Show("Заполните пароль", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
_logger.LogInformation("Сохранение исполнителя");
try
{
var model = new ImplementerBindingModel
{
Id = _id ?? 0,
ImplementerFIO = textBoxFIO.Text,
Password = textBoxPassword.Text,
WorkExperience = Convert.ToInt32(textBoxWorkExperience.Text),
Qualification = Convert.ToInt32(textBoxQualification.Text)
};
var operationResult = _id.HasValue ? _logic.Update(model) : _logic.Create(model);
if (!operationResult)
{
throw new Exception("Ошибка при создании или обновлении. Дополнительная информация в логах.");
}
MessageBox.Show("Сохранение прошло успешно", "Сообщение", MessageBoxButtons.OK, MessageBoxIcon.Information);
DialogResult = DialogResult.OK;
Close();
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка сохранения исполнителя");
MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void buttonCancel_Click(object sender, EventArgs e)
{
DialogResult = DialogResult.Cancel;
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

@@ -0,0 +1,125 @@
namespace FishFactory.Forms
{
partial class FormImplementers
{
/// <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()
{
buttonRef = new Button();
buttonDel = new Button();
buttonUpd = new Button();
buttonAdd = new Button();
dataGridView = new DataGridView();
((System.ComponentModel.ISupportInitialize)dataGridView).BeginInit();
SuspendLayout();
//
// buttonRef
//
buttonRef.Anchor = AnchorStyles.Top | AnchorStyles.Right;
buttonRef.Location = new Point(622, 175);
buttonRef.Margin = new Padding(3, 4, 3, 4);
buttonRef.Name = "buttonRef";
buttonRef.Size = new Size(125, 33);
buttonRef.TabIndex = 9;
buttonRef.Text = "Обновить";
buttonRef.UseVisualStyleBackColor = true;
buttonRef.Click += buttonRef_Click;
//
// buttonDel
//
buttonDel.Anchor = AnchorStyles.Top | AnchorStyles.Right;
buttonDel.Location = new Point(622, 126);
buttonDel.Margin = new Padding(3, 4, 3, 4);
buttonDel.Name = "buttonDel";
buttonDel.Size = new Size(125, 33);
buttonDel.TabIndex = 8;
buttonDel.Text = "Удалить";
buttonDel.UseVisualStyleBackColor = true;
buttonDel.Click += buttonDel_Click;
//
// buttonUpd
//
buttonUpd.Anchor = AnchorStyles.Top | AnchorStyles.Right;
buttonUpd.Location = new Point(622, 77);
buttonUpd.Margin = new Padding(3, 4, 3, 4);
buttonUpd.Name = "buttonUpd";
buttonUpd.Size = new Size(125, 33);
buttonUpd.TabIndex = 7;
buttonUpd.Text = "Изменить";
buttonUpd.UseVisualStyleBackColor = true;
buttonUpd.Click += buttonUpd_Click;
//
// buttonAdd
//
buttonAdd.Anchor = AnchorStyles.Top | AnchorStyles.Right;
buttonAdd.Location = new Point(622, 30);
buttonAdd.Margin = new Padding(3, 4, 3, 4);
buttonAdd.Name = "buttonAdd";
buttonAdd.Size = new Size(125, 33);
buttonAdd.TabIndex = 6;
buttonAdd.Text = "Добавить";
buttonAdd.UseVisualStyleBackColor = true;
buttonAdd.Click += buttonAdd_Click;
//
// dataGridView
//
dataGridView.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
dataGridView.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize;
dataGridView.Location = new Point(-2, -2);
dataGridView.Margin = new Padding(3, 4, 3, 4);
dataGridView.Name = "dataGridView";
dataGridView.ReadOnly = true;
dataGridView.RowHeadersWidth = 51;
dataGridView.RowTemplate.Height = 24;
dataGridView.Size = new Size(587, 549);
dataGridView.TabIndex = 5;
//
// FormImplementers
//
AutoScaleDimensions = new SizeF(8F, 19F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(775, 546);
Controls.Add(buttonRef);
Controls.Add(buttonDel);
Controls.Add(buttonUpd);
Controls.Add(buttonAdd);
Controls.Add(dataGridView);
Name = "FormImplementers";
Text = "FormImplementers";
Load += FormImplementers_Load;
((System.ComponentModel.ISupportInitialize)dataGridView).EndInit();
ResumeLayout(false);
}
#endregion
private Button buttonRef;
private Button buttonDel;
private Button buttonUpd;
private Button buttonAdd;
private DataGridView dataGridView;
}
}

View File

@@ -0,0 +1,104 @@
using FishFactoryContracts.BindingModels;
using FishFactoryContracts.BusinessLogicsContracts;
using Microsoft.Extensions.Logging;
namespace FishFactory.Forms
{
public partial class FormImplementers : Form
{
private readonly ILogger _logger;
private readonly IImplementerLogic _logic;
public FormImplementers(ILogger<FormImplementers> logger, IImplementerLogic implementerLogic)
{
InitializeComponent();
_logger = logger;
_logic = implementerLogic;
}
private void FormImplementers_Load(object sender, EventArgs e)
{
LoadData();
}
private void LoadData()
{
try
{
var list = _logic.ReadList(null);
if (list != null)
{
dataGridView.DataSource = list;
dataGridView.Columns["Id"].Visible = false;
dataGridView.Columns["ImplementerFIO"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
}
_logger.LogInformation("Загрузка исполнителей");
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка загрузки исполнителей");
MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void buttonAdd_Click(object sender, EventArgs e)
{
var service = Program.ServiceProvider?.GetService(typeof(FormImplementer));
if (service is FormImplementer form)
{
if (form.ShowDialog() == DialogResult.OK)
{
LoadData();
}
}
}
private void buttonUpd_Click(object sender, EventArgs e)
{
if (dataGridView.SelectedRows.Count == 1)
{
var service = Program.ServiceProvider?.GetService(typeof(FormImplementer));
if (service is FormImplementer form)
{
form.Id = Convert.ToInt32(dataGridView.SelectedRows[0].Cells["Id"].Value);
if (form.ShowDialog() == DialogResult.OK)
{
LoadData();
}
}
}
}
private void buttonDel_Click(object sender, EventArgs e)
{
if (dataGridView.SelectedRows.Count == 1)
{
if (MessageBox.Show("Удалить исполнителя?", "Удаление", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
{
int id = Convert.ToInt32(dataGridView.SelectedRows[0].Cells["Id"].Value);
_logger.LogInformation("Удаление исполнителя");
try
{
if (!_logic.Delete(new ImplementerBindingModel
{
Id = id
}))
{
throw new Exception("Ошибка при удалении исполнителя. Дополнительная информация в логах.");
}
LoadData();
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка удаления исполнителя"); MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
}
private void buttonRef_Click(object sender, EventArgs e)
{
LoadData();
}
}
}

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>

78
FishFactory/Forms/FormMails.Designer.cs generated Normal file
View File

@@ -0,0 +1,78 @@
namespace FishFactory.Forms
{
partial class FormMails
{
/// <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()
{
dataGridView = new DataGridView();
buttonRef = new Button();
((System.ComponentModel.ISupportInitialize)dataGridView).BeginInit();
SuspendLayout();
//
// dataGridView
//
dataGridView.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
dataGridView.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize;
dataGridView.Location = new Point(-2, -1);
dataGridView.Margin = new Padding(3, 4, 3, 4);
dataGridView.Name = "dataGridView";
dataGridView.ReadOnly = true;
dataGridView.RowHeadersWidth = 51;
dataGridView.RowTemplate.Height = 24;
dataGridView.Size = new Size(962, 517);
dataGridView.TabIndex = 10;
//
// buttonRef
//
buttonRef.Anchor = AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
buttonRef.Location = new Point(966, 233);
buttonRef.Name = "buttonRef";
buttonRef.Size = new Size(118, 28);
buttonRef.TabIndex = 11;
buttonRef.Text = "Обновить";
buttonRef.UseVisualStyleBackColor = true;
buttonRef.Click += buttonRef_Click;
//
// FormMails
//
AutoScaleDimensions = new SizeF(8F, 19F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(1084, 515);
Controls.Add(buttonRef);
Controls.Add(dataGridView);
Name = "FormMails";
Text = "FormMails";
Load += FormMail_Load;
((System.ComponentModel.ISupportInitialize)dataGridView).EndInit();
ResumeLayout(false);
}
#endregion
private DataGridView dataGridView;
private Button buttonRef;
}
}

View File

@@ -0,0 +1,58 @@
using FishFactoryContracts.BusinessLogicsContracts;
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;
namespace FishFactory.Forms
{
public partial class FormMails : Form
{
private readonly ILogger _logger;
private readonly IMessageInfoLogic _logic;
public FormMails(ILogger<FormMails> logger, IMessageInfoLogic logic)
{
InitializeComponent();
_logger = logger;
_logic = logic;
}
private void LoadData()
{
try
{
var list = _logic.ReadList(null);
if (list != null)
{
dataGridView.DataSource = list;
dataGridView.Columns["MessageId"].Visible = false;
dataGridView.Columns["ClientId"].Visible = false;
dataGridView.Columns["Body"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
}
_logger.LogInformation("Загрузка почтовых собщений");
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка загрузки почтовых сообщений");
MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void FormMail_Load(object sender, EventArgs e)
{
LoadData();
}
private void buttonRef_Click(object sender, EventArgs e)
{
LoadData();
}
}
}

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

@@ -33,16 +33,18 @@
toolStripDropDownButton1 = new ToolStripDropDownButton(); toolStripDropDownButton1 = new ToolStripDropDownButton();
компонентыToolStripMenuItem = new ToolStripMenuItem(); компонентыToolStripMenuItem = new ToolStripMenuItem();
консервыToolStripMenuItem = new ToolStripMenuItem(); консервыToolStripMenuItem = new ToolStripMenuItem();
клиентыToolStripMenuItem = new ToolStripMenuItem();
исполнителиToolStripMenuItem = new ToolStripMenuItem();
toolStripDropDownButton2 = new ToolStripDropDownButton(); toolStripDropDownButton2 = new ToolStripDropDownButton();
списокКомпонентовToolStripMenuItem = new ToolStripMenuItem(); списокКомпонентовToolStripMenuItem = new ToolStripMenuItem();
компонентыПоКонсервамToolStripMenuItem = new ToolStripMenuItem(); компонентыПоКонсервамToolStripMenuItem = new ToolStripMenuItem();
списокЗаказовToolStripMenuItem = new ToolStripMenuItem(); списокЗаказовToolStripMenuItem = new ToolStripMenuItem();
ЗапускРаботToolStripLabel = new ToolStripLabel();
buttonCreateOrder = new Button(); buttonCreateOrder = new Button();
buttonTakeOrderInWork = new Button();
buttonOrderReady = new Button();
buttonIssuedOrder = new Button(); buttonIssuedOrder = new Button();
buttonRef = new Button(); buttonRef = new Button();
dataGridView = new DataGridView(); dataGridView = new DataGridView();
ПисьмаtoolStripLabel = new ToolStripLabel();
toolStrip1.SuspendLayout(); toolStrip1.SuspendLayout();
((System.ComponentModel.ISupportInitialize)dataGridView).BeginInit(); ((System.ComponentModel.ISupportInitialize)dataGridView).BeginInit();
SuspendLayout(); SuspendLayout();
@@ -50,37 +52,51 @@
// toolStrip1 // toolStrip1
// //
toolStrip1.ImageScalingSize = new Size(20, 20); toolStrip1.ImageScalingSize = new Size(20, 20);
toolStrip1.Items.AddRange(new ToolStripItem[] { toolStripDropDownButton1, toolStripDropDownButton2 }); toolStrip1.Items.AddRange(new ToolStripItem[] { toolStripDropDownButton1, toolStripDropDownButton2, ЗапускРаботToolStripLabel, ПисьмаtoolStripLabel });
toolStrip1.Location = new Point(0, 0); toolStrip1.Location = new Point(0, 0);
toolStrip1.Name = "toolStrip1"; toolStrip1.Name = "toolStrip1";
toolStrip1.Size = new Size(969, 25); toolStrip1.Size = new Size(1265, 26);
toolStrip1.TabIndex = 0; toolStrip1.TabIndex = 0;
toolStrip1.Text = "toolStrip1"; toolStrip1.Text = "toolStrip1";
// //
// toolStripDropDownButton1 // toolStripDropDownButton1
// //
toolStripDropDownButton1.DisplayStyle = ToolStripItemDisplayStyle.Text; toolStripDropDownButton1.DisplayStyle = ToolStripItemDisplayStyle.Text;
toolStripDropDownButton1.DropDownItems.AddRange(new ToolStripItem[] { компонентыToolStripMenuItem, консервыToolStripMenuItem }); toolStripDropDownButton1.DropDownItems.AddRange(new ToolStripItem[] { компонентыToolStripMenuItem, консервыToolStripMenuItem, клиентыToolStripMenuItem, исполнителиToolStripMenuItem });
toolStripDropDownButton1.Image = (Image)resources.GetObject("toolStripDropDownButton1.Image"); toolStripDropDownButton1.Image = (Image)resources.GetObject("toolStripDropDownButton1.Image");
toolStripDropDownButton1.ImageTransparentColor = Color.Magenta; toolStripDropDownButton1.ImageTransparentColor = Color.Magenta;
toolStripDropDownButton1.Name = "toolStripDropDownButton1"; toolStripDropDownButton1.Name = "toolStripDropDownButton1";
toolStripDropDownButton1.Size = new Size(88, 22); toolStripDropDownButton1.Size = new Size(101, 23);
toolStripDropDownButton1.Text = "Справочник"; toolStripDropDownButton1.Text = "Справочник";
// //
// компонентыToolStripMenuItem // компонентыToolStripMenuItem
// //
компонентыToolStripMenuItem.Name = омпонентыToolStripMenuItem"; компонентыToolStripMenuItem.Name = омпонентыToolStripMenuItem";
компонентыToolStripMenuItem.Size = new Size(145, 22); компонентыToolStripMenuItem.Size = new Size(171, 26);
компонентыToolStripMenuItem.Text = "Компоненты"; компонентыToolStripMenuItem.Text = "Компоненты";
компонентыToolStripMenuItem.Click += компонентыToolStripMenuItem_Click; компонентыToolStripMenuItem.Click += компонентыToolStripMenuItem_Click;
// //
// консервыToolStripMenuItem // консервыToolStripMenuItem
// //
консервыToolStripMenuItem.Name = онсервыToolStripMenuItem"; консервыToolStripMenuItem.Name = онсервыToolStripMenuItem";
консервыToolStripMenuItem.Size = new Size(145, 22); консервыToolStripMenuItem.Size = new Size(171, 26);
консервыToolStripMenuItem.Text = "Консервы"; консервыToolStripMenuItem.Text = "Консервы";
консервыToolStripMenuItem.Click += консервыToolStripMenuItem_Click; консервыToolStripMenuItem.Click += консервыToolStripMenuItem_Click;
// //
// клиентыToolStripMenuItem
//
клиентыToolStripMenuItem.Name = "клиентыToolStripMenuItem";
клиентыToolStripMenuItem.Size = new Size(171, 26);
клиентыToolStripMenuItem.Text = "Клиенты";
клиентыToolStripMenuItem.Click += клиентыToolStripMenuItem_Click;
//
// исполнителиToolStripMenuItem
//
исполнителиToolStripMenuItem.Name = сполнителиToolStripMenuItem";
исполнителиToolStripMenuItem.Size = new Size(171, 26);
исполнителиToolStripMenuItem.Text = "Исполнители";
исполнителиToolStripMenuItem.Click += исполнителиToolStripMenuItem_Click;
//
// toolStripDropDownButton2 // toolStripDropDownButton2
// //
toolStripDropDownButton2.DisplayStyle = ToolStripItemDisplayStyle.Text; toolStripDropDownButton2.DisplayStyle = ToolStripItemDisplayStyle.Text;
@@ -88,69 +104,56 @@
toolStripDropDownButton2.Image = (Image)resources.GetObject("toolStripDropDownButton2.Image"); toolStripDropDownButton2.Image = (Image)resources.GetObject("toolStripDropDownButton2.Image");
toolStripDropDownButton2.ImageTransparentColor = Color.Magenta; toolStripDropDownButton2.ImageTransparentColor = Color.Magenta;
toolStripDropDownButton2.Name = "toolStripDropDownButton2"; toolStripDropDownButton2.Name = "toolStripDropDownButton2";
toolStripDropDownButton2.Size = new Size(61, 22); toolStripDropDownButton2.Size = new Size(71, 23);
toolStripDropDownButton2.Text = "Отчёты"; toolStripDropDownButton2.Text = "Отчёты";
// //
// списокКомпонентовToolStripMenuItem // списокКомпонентовToolStripMenuItem
// //
списокКомпонентовToolStripMenuItem.Name = "списокКомпонентовToolStripMenuItem"; списокКомпонентовToolStripMenuItem.Name = "списокКомпонентовToolStripMenuItem";
списокКомпонентовToolStripMenuItem.Size = new Size(225, 22); списокКомпонентовToolStripMenuItem.Size = new Size(261, 26);
списокКомпонентовToolStripMenuItem.Text = "Список консерв"; списокКомпонентовToolStripMenuItem.Text = "Список консерв";
списокКомпонентовToolStripMenuItem.Click += списокКомпонентовToolStripMenuItem_Click; списокКомпонентовToolStripMenuItem.Click += списокКомпонентовToolStripMenuItem_Click;
// //
// компонентыПоКонсервамToolStripMenuItem // компонентыПоКонсервамToolStripMenuItem
// //
компонентыПоКонсервамToolStripMenuItem.Name = омпонентыПоКонсервамToolStripMenuItem"; компонентыПоКонсервамToolStripMenuItem.Name = омпонентыПоКонсервамToolStripMenuItem";
компонентыПоКонсервамToolStripMenuItem.Size = new Size(225, 22); компонентыПоКонсервамToolStripMenuItem.Size = new Size(261, 26);
компонентыПоКонсервамToolStripMenuItem.Text = "Компоненты по консервам"; компонентыПоКонсервамToolStripMenuItem.Text = "Компоненты по консервам";
компонентыПоКонсервамToolStripMenuItem.Click += компонентыПоИзделиямToolStripMenuItem_Click; компонентыПоКонсервамToolStripMenuItem.Click += компонентыПоИзделиямToolStripMenuItem_Click;
// //
// списокЗаказовToolStripMenuItem // списокЗаказовToolStripMenuItem
// //
списокЗаказовToolStripMenuItem.Name = "списокЗаказовToolStripMenuItem"; списокЗаказовToolStripMenuItem.Name = "списокЗаказовToolStripMenuItem";
списокЗаказовToolStripMenuItem.Size = new Size(225, 22); списокЗаказовToolStripMenuItem.Size = new Size(261, 26);
списокЗаказовToolStripMenuItem.Text = "Список заказов"; списокЗаказовToolStripMenuItem.Text = "Список заказов";
списокЗаказовToolStripMenuItem.Click += списокЗаказовToolStripMenuItem_Click; списокЗаказовToolStripMenuItem.Click += списокЗаказовToolStripMenuItem_Click;
// //
// ЗапускРаботToolStripLabel
//
ЗапускРаботToolStripLabel.Name = "ЗапускРаботToolStripLabel";
ЗапускРаботToolStripLabel.Size = new Size(93, 23);
ЗапускРаботToolStripLabel.Text = "Запуск работ";
ЗапускРаботToolStripLabel.Click += ЗапускРаботToolStripLabel_Click;
//
// buttonCreateOrder // buttonCreateOrder
// //
buttonCreateOrder.Anchor = AnchorStyles.Top | AnchorStyles.Right; buttonCreateOrder.Anchor = AnchorStyles.Top | AnchorStyles.Right;
buttonCreateOrder.Location = new Point(800, 56); buttonCreateOrder.Location = new Point(1078, 71);
buttonCreateOrder.Margin = new Padding(3, 4, 3, 4);
buttonCreateOrder.Name = "buttonCreateOrder"; buttonCreateOrder.Name = "buttonCreateOrder";
buttonCreateOrder.Size = new Size(141, 24); buttonCreateOrder.Size = new Size(161, 30);
buttonCreateOrder.TabIndex = 1; buttonCreateOrder.TabIndex = 1;
buttonCreateOrder.Text = "Создать заказ"; buttonCreateOrder.Text = "Создать заказ";
buttonCreateOrder.UseVisualStyleBackColor = true; buttonCreateOrder.UseVisualStyleBackColor = true;
buttonCreateOrder.Click += buttonCreateOrder_Click; buttonCreateOrder.Click += buttonCreateOrder_Click;
// //
// buttonTakeOrderInWork
//
buttonTakeOrderInWork.Anchor = AnchorStyles.Top | AnchorStyles.Right;
buttonTakeOrderInWork.Location = new Point(800, 100);
buttonTakeOrderInWork.Name = "buttonTakeOrderInWork";
buttonTakeOrderInWork.Size = new Size(141, 24);
buttonTakeOrderInWork.TabIndex = 2;
buttonTakeOrderInWork.Text = "Отдать на выполнение";
buttonTakeOrderInWork.UseVisualStyleBackColor = true;
buttonTakeOrderInWork.Click += buttonTakeOrderInWork_Click;
//
// buttonOrderReady
//
buttonOrderReady.Anchor = AnchorStyles.Top | AnchorStyles.Right;
buttonOrderReady.Location = new Point(800, 142);
buttonOrderReady.Name = "buttonOrderReady";
buttonOrderReady.Size = new Size(141, 24);
buttonOrderReady.TabIndex = 3;
buttonOrderReady.Text = "Заказ готов";
buttonOrderReady.UseVisualStyleBackColor = true;
buttonOrderReady.Click += buttonOrderReady_Click;
//
// buttonIssuedOrder // buttonIssuedOrder
// //
buttonIssuedOrder.Anchor = AnchorStyles.Top | AnchorStyles.Right; buttonIssuedOrder.Anchor = AnchorStyles.Top | AnchorStyles.Right;
buttonIssuedOrder.Location = new Point(800, 181); buttonIssuedOrder.Location = new Point(1078, 125);
buttonIssuedOrder.Margin = new Padding(3, 4, 3, 4);
buttonIssuedOrder.Name = "buttonIssuedOrder"; buttonIssuedOrder.Name = "buttonIssuedOrder";
buttonIssuedOrder.Size = new Size(141, 24); buttonIssuedOrder.Size = new Size(161, 30);
buttonIssuedOrder.TabIndex = 4; buttonIssuedOrder.TabIndex = 4;
buttonIssuedOrder.Text = "Заказ выдан"; buttonIssuedOrder.Text = "Заказ выдан";
buttonIssuedOrder.UseVisualStyleBackColor = true; buttonIssuedOrder.UseVisualStyleBackColor = true;
@@ -159,9 +162,10 @@
// buttonRef // buttonRef
// //
buttonRef.Anchor = AnchorStyles.Top | AnchorStyles.Right; buttonRef.Anchor = AnchorStyles.Top | AnchorStyles.Right;
buttonRef.Location = new Point(800, 222); buttonRef.Location = new Point(1078, 177);
buttonRef.Margin = new Padding(3, 4, 3, 4);
buttonRef.Name = "buttonRef"; buttonRef.Name = "buttonRef";
buttonRef.Size = new Size(141, 24); buttonRef.Size = new Size(161, 30);
buttonRef.TabIndex = 5; buttonRef.TabIndex = 5;
buttonRef.Text = "Обновить список"; buttonRef.Text = "Обновить список";
buttonRef.UseVisualStyleBackColor = true; buttonRef.UseVisualStyleBackColor = true;
@@ -169,28 +173,36 @@
// //
// dataGridView // dataGridView
// //
dataGridView.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
dataGridView.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize; dataGridView.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize;
dataGridView.Location = new Point(0, 20); dataGridView.Location = new Point(0, 25);
dataGridView.Margin = new Padding(3, 4, 3, 4);
dataGridView.Name = "dataGridView"; dataGridView.Name = "dataGridView";
dataGridView.ReadOnly = true; dataGridView.ReadOnly = true;
dataGridView.RowHeadersWidth = 51; dataGridView.RowHeadersWidth = 51;
dataGridView.RowTemplate.Height = 24; dataGridView.RowTemplate.Height = 24;
dataGridView.SelectionMode = DataGridViewSelectionMode.FullRowSelect; dataGridView.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
dataGridView.Size = new Size(763, 441); dataGridView.Size = new Size(1054, 559);
dataGridView.TabIndex = 6; dataGridView.TabIndex = 6;
// //
// ПисьмаtoolStripLabel
//
ПисьмаtoolStripLabel.Name = "ПисьмаtoolStripLabel";
ПисьмаtoolStripLabel.Size = new Size(128, 23);
ПисьмаtoolStripLabel.Text = "Письма (призрака)";
ПисьмаtoolStripLabel.Click += ПисьмаtoolStripLabel_Click;
//
// FormMain // FormMain
// //
AutoScaleDimensions = new SizeF(7F, 15F); AutoScaleDimensions = new SizeF(8F, 19F);
AutoScaleMode = AutoScaleMode.Font; AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(969, 461); ClientSize = new Size(1265, 584);
Controls.Add(dataGridView); Controls.Add(dataGridView);
Controls.Add(buttonRef); Controls.Add(buttonRef);
Controls.Add(buttonIssuedOrder); Controls.Add(buttonIssuedOrder);
Controls.Add(buttonOrderReady);
Controls.Add(buttonTakeOrderInWork);
Controls.Add(buttonCreateOrder); Controls.Add(buttonCreateOrder);
Controls.Add(toolStrip1); Controls.Add(toolStrip1);
Margin = new Padding(3, 4, 3, 4);
Name = "FormMain"; Name = "FormMain";
Text = "Рыбный завод"; Text = "Рыбный завод";
Load += FormMain_Load; Load += FormMain_Load;
@@ -205,8 +217,6 @@
private ToolStrip toolStrip1; private ToolStrip toolStrip1;
private Button buttonCreateOrder; private Button buttonCreateOrder;
private Button buttonTakeOrderInWork;
private Button buttonOrderReady;
private Button buttonIssuedOrder; private Button buttonIssuedOrder;
private Button buttonRef; private Button buttonRef;
private DataGridView dataGridView; private DataGridView dataGridView;
@@ -217,5 +227,9 @@
private ToolStripMenuItem списокКомпонентовToolStripMenuItem; private ToolStripMenuItem списокКомпонентовToolStripMenuItem;
private ToolStripMenuItem компонентыПоКонсервамToolStripMenuItem; private ToolStripMenuItem компонентыПоКонсервамToolStripMenuItem;
private ToolStripMenuItem списокЗаказовToolStripMenuItem; private ToolStripMenuItem списокЗаказовToolStripMenuItem;
private ToolStripMenuItem клиентыToolStripMenuItem;
private ToolStripLabel ЗапускРаботToolStripLabel;
private ToolStripMenuItem исполнителиToolStripMenuItem;
private ToolStripLabel ПисьмаtoolStripLabel;
} }
} }

View File

@@ -1,5 +1,4 @@
using FishFactoryBusinessLogic.BusinessLogic; using FishFactoryContracts.BindingModels;
using FishFactoryContracts.BindingModels;
using FishFactoryContracts.BusinessLogicsContracts; using FishFactoryContracts.BusinessLogicsContracts;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
@@ -10,13 +9,16 @@ namespace FishFactory.Forms
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly IOrderLogic _orderLogic; private readonly IOrderLogic _orderLogic;
private readonly IReportLogic _reportLogic; private readonly IReportLogic _reportLogic;
public FormMain(ILogger<FormMain> logger, IOrderLogic orderLogic, IReportLogic reportLogic) private readonly IWorkProcess _workProcess;
public FormMain(ILogger<FormMain> logger, IOrderLogic orderLogic, IReportLogic reportLogic, IWorkProcess workProcess)
{ {
InitializeComponent(); InitializeComponent();
_logger = logger; _logger = logger;
_orderLogic = orderLogic; _orderLogic = orderLogic;
_reportLogic = reportLogic; _reportLogic = reportLogic;
} _workProcess = workProcess;
}
private void FormMain_Load(object sender, EventArgs e) private void FormMain_Load(object sender, EventArgs e)
{ {
LoadData(); LoadData();
@@ -33,6 +35,10 @@ namespace FishFactory.Forms
dataGridView.DataSource = list; dataGridView.DataSource = list;
dataGridView.Columns["CannedId"].Visible = false; dataGridView.Columns["CannedId"].Visible = false;
dataGridView.Columns["CannedName"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill; dataGridView.Columns["CannedName"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
dataGridView.Columns["ClientId"].Visible = false;
dataGridView.Columns["ClientFIO"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
dataGridView.Columns["ImplementerId"].Visible = false;
dataGridView.Columns["ImplementerFIO"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
} }
_logger.LogInformation("Загрузка заказов"); _logger.LogInformation("Загрузка заказов");
@@ -59,6 +65,26 @@ namespace FishFactory.Forms
form.ShowDialog(); form.ShowDialog();
} }
} }
private void клиентыToolStripMenuItem_Click(object sender, EventArgs e)
{
var service = Program.ServiceProvider?.GetService(typeof(FormClients));
if (service is FormClients form)
{
form.ShowDialog();
}
}
private void исполнителиToolStripMenuItem_Click(object sender, EventArgs e)
{
var service = Program.ServiceProvider?.GetService(typeof(FormImplementers));
if (service is FormImplementers form)
{
form.ShowDialog();
}
}
private void buttonCreateOrder_Click(object sender, EventArgs e) private void buttonCreateOrder_Click(object sender, EventArgs e)
{ {
var service = Program.ServiceProvider?.GetService(typeof(FormCreateOrder)); var service = Program.ServiceProvider?.GetService(typeof(FormCreateOrder));
@@ -68,54 +94,7 @@ namespace FishFactory.Forms
LoadData(); LoadData();
} }
} }
private void buttonTakeOrderInWork_Click(object sender, EventArgs e)
{
if (dataGridView.SelectedRows.Count == 1)
{
int id = Convert.ToInt32(dataGridView.SelectedRows[0].Cells["Id"].Value);
_logger.LogInformation("Заказ №{id}. Меняется статус на 'В работе'", id);
try
{
var operationResult = _orderLogic.TakeOrderInWork(new OrderBindingModel
{
Id = id,
});
if (!operationResult)
{
throw new Exception("Ошибка при сохранении. Дополнительная информация в логах.");
}
LoadData();
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка передачи заказа в работу");
MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
private void buttonOrderReady_Click(object sender, EventArgs e)
{
if (dataGridView.SelectedRows.Count == 1)
{
int id =
Convert.ToInt32(dataGridView.SelectedRows[0].Cells["Id"].Value);
_logger.LogInformation("Заказ №{id}. Меняется статус на 'Готов'", id);
try
{
var operationResult = _orderLogic.FinishOrder(new OrderBindingModel { Id = id });
if (!operationResult)
{
throw new Exception("Ошибка при сохранении. Дополнительная информация в логах.");
}
LoadData();
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка отметки о готовности заказа");
MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
private void buttonIssuedOrder_Click(object sender, EventArgs e) private void buttonIssuedOrder_Click(object sender, EventArgs e)
{ {
if (dataGridView.SelectedRows.Count == 1) if (dataGridView.SelectedRows.Count == 1)
@@ -178,5 +157,20 @@ namespace FishFactory.Forms
form.ShowDialog(); form.ShowDialog();
} }
} }
private void ЗапускРаботToolStripLabel_Click(object sender, EventArgs e)
{
_workProcess.DoWork((Program.ServiceProvider?.GetService(typeof(IImplementerLogic)) as IImplementerLogic)!, _orderLogic);
MessageBox.Show("Процесс обработки запущен", "Сообщение", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
private void ПисьмаtoolStripLabel_Click(object sender, EventArgs e)
{
var service = Program.ServiceProvider?.GetService(typeof(FormMails));
if (service is FormMails form)
{
form.ShowDialog();
}
}
} }
} }

View File

@@ -124,7 +124,7 @@
<data name="toolStripDropDownButton1.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="toolStripDropDownButton1.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG YQUAAAAJcEhZcwAAEWAAABFgAVshLGQAAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG
YKxG6WBogkMZKgPNCEVJFBGdGETEvgwyO9DJE5syZw3PIlPEE9pgBCLZ5XvdMB8Ew8gXbl54nuf63dd9 YKxG6WBogkMZKgPNCEVJFBGdGETEvgwyO9DJE5syZw3PIlPEE9pgBCLZ5XvdMB8Ew8gXbl54nuf63dd9
0OGSnwCahxbPRNPAPMw9Xpg6ZmF46kZZ0xSKzJPIrhpDWsVnpBhGkKx3nAX8Pv7z1zg8OoY/cITdn4fw 0OGSnwCahxbPRNPAPMw9Xpg6ZmF46kZZ0xSKzJPIrhpDWsVnpBhGkKx3nAX8Pv7z1zg8OoY/cITdn4fw
bf/C0kYAN3Ma/w3gWfZL5kzTKBxjWyK2DftwI9tyMYCZKXbNHaD91bLYJrDXsYbrWfUKwJrPE9M2M1Oc bf/C0kYAN3Ma/w3gWfZL5kzTKBxjWyK2DftwI9tyMYCZKXbNHaD91bLYJrDXsYbrWfUKwJrPE9M2M1Oc
@@ -139,7 +139,7 @@
<data name="toolStripDropDownButton2.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="toolStripDropDownButton2.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAEKSURBVEhL3ZG9DsFQHMXvczDZvIOtXsHObuhqkViI3Quw YQUAAAAJcEhZcwAAEWAAABFgAVshLGQAAAEKSURBVEhL3ZG9DsFQHMXvczDZvIOtXsHObuhqkViI3Quw
6CYmNoMYJJ0NBiFFIoIytOuf0+TeXP3yde+iyS+3OcP53Z4y3/dJJ4HAsiwyTVMp6BQCBIZhKAWdEcHV 6CYmNoMYJJ0NBiFFIoIytOuf0+TeXP3yde+iyS+3OcP53Z4y3/dJJ4HAsiwyTVMp6BQCBIZhKAWdEcHV
vSlBmeB82NFy1KLluEWOPRC5MoHdMWhazwi4RJlALgf4EuT6BI+5kCsTrGddUY658E+QvyXYHq9UnRyC vSlBmeB82NFy1KLluEWOPRC5MoHdMWhazwi4RJlALgf4EuT6BI+5kCsTrGddUY658E+QvyXYHq9UnRyC
U87f4aUApcXhnrI9Jzg/laQKFntXlHM+lSQK5psL5fvbp/JvJLGCQqmSWM5JkiCT84igXGtSrruKLQ0T U87f4aUApcXhnrI9Jzg/laQKFntXlHM+lSQK5psL5fvbp/JvJLGCQqmSWM5JkiCT84igXGtSrruKLQ0T

View File

@@ -2,12 +2,14 @@ using FishFactory.Forms;
using FishFactoryContracts.BusinessLogicsContracts; using FishFactoryContracts.BusinessLogicsContracts;
using FishFactoryBusinessLogic.BusinessLogic; using FishFactoryBusinessLogic.BusinessLogic;
using FishFactoryContracts.StoragesContracts; using FishFactoryContracts.StoragesContracts;
using FishFactoryFileImplement.Implements; using FishFactoryDatabaseImplement.Implements;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using NLog.Extensions.Logging; using NLog.Extensions.Logging;
using FishFactoryBusinessLogic.OfficePackage; using FishFactoryBusinessLogic.OfficePackage;
using FishFactoryBusinessLogic.OfficePackage.Implements; using FishFactoryBusinessLogic.OfficePackage.Implements;
using FishFactoryBusinessLogic.MailWorker;
using FishFactoryContracts.BindingModels;
namespace FishFactory namespace FishFactory
{ {
@@ -28,6 +30,27 @@ namespace FishFactory
ConfigureServices(services); ConfigureServices(services);
_serviceProvider = services.BuildServiceProvider(); _serviceProvider = services.BuildServiceProvider();
var mailSender = _serviceProvider.GetService<AbstractMailWorker>();
try
{
mailSender?.MailConfig(new MailConfigBindingModel
{
MailLogin = System.Configuration.ConfigurationManager.AppSettings["MailLogin"] ?? string.Empty,
MailPassword = System.Configuration.ConfigurationManager.AppSettings["MailPassword"] ?? string.Empty,
SmtpClientHost = System.Configuration.ConfigurationManager.AppSettings["SmtpClientHost"] ?? string.Empty,
SmtpClientPort = Convert.ToInt32(System.Configuration.ConfigurationManager.AppSettings["SmtpClientPort"]),
PopHost = System.Configuration.ConfigurationManager.AppSettings["PopHost"] ?? string.Empty,
PopPort = Convert.ToInt32(System.Configuration.ConfigurationManager.AppSettings["PopPort"])
});
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
var timer = new System.Threading.Timer(new TimerCallback(MailCheck!), null, 0, 100000);
}
catch (Exception ex)
{
var logger = _serviceProvider.GetService<ILogger>();
logger?.LogError(ex, "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>");
}
Application.Run(_serviceProvider.GetRequiredService<FormMain>()); Application.Run(_serviceProvider.GetRequiredService<FormMain>());
} }
private static void ConfigureServices(ServiceCollection services) private static void ConfigureServices(ServiceCollection services)
@@ -40,22 +63,41 @@ namespace FishFactory
services.AddTransient<IComponentStorage, ComponentStorage>(); services.AddTransient<IComponentStorage, ComponentStorage>();
services.AddTransient<IOrderStorage, OrderStorage>(); services.AddTransient<IOrderStorage, OrderStorage>();
services.AddTransient<ICannedStorage, CannedStorage>(); services.AddTransient<ICannedStorage, CannedStorage>();
services.AddTransient<IClientStorage, ClientStorage>();
services.AddTransient<IImplementerStorage, ImplementerStorage>();
services.AddTransient<IMessageInfoStorage, MessageInfoStorage>();
services.AddTransient<IComponentLogic, ComponentLogic>(); services.AddTransient<IComponentLogic, ComponentLogic>();
services.AddTransient<IOrderLogic, OrderLogic>(); services.AddTransient<IOrderLogic, OrderLogic>();
services.AddTransient<ICannedLogic, CannedLogic>(); services.AddTransient<ICannedLogic, CannedLogic>();
services.AddTransient<IClientLogic, ClientLogic>();
services.AddTransient<IImplementerLogic, ImplementerLogic>();
services.AddTransient<IMessageInfoLogic, MessageInfoLogic>();
services.AddTransient<IReportLogic, ReportLogic>(); services.AddTransient<IReportLogic, ReportLogic>();
services.AddTransient<IWorkProcess, WorkModeling>();
services.AddSingleton<AbstractMailWorker, MailKitWorker>();
services.AddTransient<AbstractSaveToWord, SaveToWord>(); services.AddTransient<AbstractSaveToWord, SaveToWord>();
services.AddTransient<AbstractSaveToExcel, SaveToExcel>(); services.AddTransient<AbstractSaveToExcel, SaveToExcel>();
services.AddTransient<AbstractSaveToPdf, SaveToPdf>(); services.AddTransient<AbstractSaveToPdf, SaveToPdf>();
services.AddTransient<FormMain>(); services.AddTransient<FormMain>();
services.AddTransient<FormComponent>();
services.AddTransient<FormComponents>();
services.AddTransient<FormCreateOrder>();
services.AddTransient<FormCanned>();
services.AddTransient<FormCannedComponent>();
services.AddTransient<FormCanneds>(); services.AddTransient<FormCanneds>();
services.AddTransient<FormComponents>();
services.AddTransient<FormClients>();
services.AddTransient<FormImplementers>();
services.AddTransient<FormMails>();
services.AddTransient<FormCanned>();
services.AddTransient<FormComponent>();
services.AddTransient<FormImplementer>();
services.AddTransient<FormCreateOrder>();
services.AddTransient<FormCannedComponent>();
services.AddTransient<FormReportOrders>(); services.AddTransient<FormReportOrders>();
services.AddTransient<FormReportCannedComponents>(); services.AddTransient<FormReportCannedComponents>();
} }
private static void MailCheck(object obj) => ServiceProvider?.GetService<AbstractMailWorker>()?.MailCheck();
} }
} }

View File

@@ -0,0 +1,119 @@

using FishFactoryContracts.BindingModels;
using FishFactoryContracts.BusinessLogicsContracts;
using FishFactoryContracts.SearchModels;
using FishFactoryContracts.StoragesContracts;
using FishFactoryContracts.ViewModels;
using Microsoft.Extensions.Logging;
using System.Text.RegularExpressions;
namespace FishFactoryBusinessLogic.BusinessLogic
{
public class ClientLogic : IClientLogic
{
private readonly ILogger _logger;
private readonly IClientStorage _ClientStorage;
public ClientLogic(ILogger<ClientLogic> logger, IClientStorage
ClientStorage)
{
_logger = logger;
_ClientStorage = ClientStorage;
}
public List<ClientViewModel>? ReadList(ClientSearchModel? model)
{
_logger.LogInformation("ReadList. Email:{Email}.Id:{Id}", model?.Email, model?.Id);
var list = model == null ? _ClientStorage.GetFullList() : _ClientStorage.GetFilteredList(model);
if (list == null)
{
_logger.LogWarning("ReadList return null list");
return null;
}
_logger.LogInformation("ReadList. Count:{Count}", list.Count);
return list;
}
public ClientViewModel? ReadElement(ClientSearchModel model)
{
if (model == null)
{
throw new ArgumentNullException(nameof(model));
}
_logger.LogInformation("ReadElement. Id:{ Id} email:{ email} password:{ password}.", model.Id, model.Email, model.Password);
var element = _ClientStorage.GetElement(model);
if (element == null)
{
_logger.LogWarning("ReadElement element not found");
return null;
}
_logger.LogInformation("ReadElement find. Id:{Id}", element.Id);
return element;
}
public bool Create(ClientBindingModel model)
{
CheckModel(model);
if (_ClientStorage.Insert(model) == null)
{
_logger.LogWarning("Insert operation failed");
return false;
}
return true;
}
public bool Update(ClientBindingModel model)
{
CheckModel(model);
if (_ClientStorage.Update(model) == null)
{
_logger.LogWarning("Update operation failed");
return false;
}
return true;
}
public bool Delete(ClientBindingModel model)
{
CheckModel(model, false);
_logger.LogInformation("Delete. Id:{Id}", model.Id);
if (_ClientStorage.Delete(model) == null)
{
_logger.LogWarning("Delete operation failed");
return false;
}
return true;
}
private void CheckModel(ClientBindingModel model, bool withParams = true)
{
if (model == null)
{
throw new ArgumentNullException(nameof(model));
}
if (!withParams)
{
return;
}
if (string.IsNullOrEmpty(model.ClientFIO))
{
throw new ArgumentNullException("Нет ФИО пользователя", nameof(model.ClientFIO));
}
if (string.IsNullOrEmpty(model.Email) || !Regex.IsMatch(model.Email, @"^[a-z0-9._%+-]+\@([a-z0-9-]+\.)+[a-z]{2,4}$"))
{
throw new ArgumentException("Почта не соответствует требованиям", nameof(model.Email));
}
if (string.IsNullOrEmpty(model.Password) || !Regex.IsMatch(model.Password, @"^(?=.*[A-Za-z])(?=.*\d)(?=.*[^A-Za-z0-9\n]).{10,50}$"))
{
throw new ArgumentNullException("Пароль не соответствует требованиям", nameof(model.Password));
}
_logger.LogInformation("Client. ClientFIO:{ClientFIO}. Email:{Email}. Id:{Id}", model.ClientFIO, model.Email, model.Id);
var element = _ClientStorage.GetElement(new ClientSearchModel
{
Email = model.Email
});
if (element != null && element.Id != model.Id)
{
throw new InvalidOperationException("Пользователь с таким логином уже есть");
}
}
}
}

View File

@@ -0,0 +1,115 @@
using FishFactoryContracts.BindingModels;
using FishFactoryContracts.BusinessLogicsContracts;
using FishFactoryContracts.SearchModels;
using FishFactoryContracts.StoragesContracts;
using FishFactoryContracts.ViewModels;
using Microsoft.Extensions.Logging;
namespace FishFactoryBusinessLogic.BusinessLogic
{
public class ImplementerLogic : IImplementerLogic
{
private readonly ILogger _logger;
private readonly IImplementerStorage _implementerStorage;
public ImplementerLogic(ILogger<ImplementerLogic> logger, IImplementerStorage implementerStorage)
{
_logger = logger;
_implementerStorage = implementerStorage;
}
public List<ImplementerViewModel>? ReadList(ImplementerSearchModel? model)
{
_logger.LogInformation("ReadList. ImplementerFIO:{ImplementerFIO}. Id:{ Id}", model?.ImplementerFIO, model?.Id);
var list = model == null ? _implementerStorage.GetFullList() : _implementerStorage.GetFilteredList(model);
if (list == null)
{
_logger.LogWarning("ReadList return null list");
return null;
}
_logger.LogInformation("ReadList. Count:{Count}", list.Count);
return list;
}
public ImplementerViewModel? ReadElement(ImplementerSearchModel model)
{
if (model == null)
{
throw new ArgumentNullException(nameof(model));
}
_logger.LogInformation("ReadElement. ImplementerFIO:{ImplementerFIO}.Id:{ Id}", model.ImplementerFIO, model.Id);
var element = _implementerStorage.GetElement(model);
if (element == null)
{
_logger.LogWarning("ReadElement element not found");
return null;
}
_logger.LogInformation("ReadElement find. Id:{Id}", element.Id);
return element;
}
public bool Create(ImplementerBindingModel model)
{
CheckModel(model);
if (_implementerStorage.Insert(model) == null)
{
_logger.LogWarning("Insert operation failed");
return false;
}
return true;
}
public bool Update(ImplementerBindingModel model)
{
CheckModel(model);
if (_implementerStorage.Update(model) == null)
{
_logger.LogWarning("Update operation failed");
return false;
}
return true;
}
public bool Delete(ImplementerBindingModel model)
{
CheckModel(model, false);
_logger.LogInformation("Delete. Id:{Id}", model.Id);
if (_implementerStorage.Delete(model) == null)
{
_logger.LogWarning("Delete operation failed");
return false;
}
return true;
}
private void CheckModel(ImplementerBindingModel model, bool withParams = true)
{
if (model == null)
{
throw new ArgumentNullException(nameof(model));
}
if (!withParams)
{
return;
}
if (string.IsNullOrEmpty(model.ImplementerFIO))
{
throw new ArgumentNullException("Нет ФИО исполнителя", nameof(model.ImplementerFIO));
}
if (string.IsNullOrEmpty(model.Password))
{
throw new ArgumentNullException("Нет пароля исполнителя", nameof(model.Password));
}
if (model.WorkExperience < 0)
{
throw new ArgumentNullException("Стаж меньше 0", nameof(model.WorkExperience));
}
if (model.Qualification < 0)
{
throw new ArgumentException("Квалификация меньше 0", nameof(model.Qualification));
}
_logger.LogInformation("Implementer. ImplementerFIO:{ImplementerFIO}." + "Password:{ Password}. WorkExperience:{ WorkExperience}. Qualification:{ Qualification}. Id: { Id} ", model.ImplementerFIO, model.Password, model.WorkExperience, model.Qualification, model.Id);
var element = _implementerStorage.GetElement(new ImplementerSearchModel
{
ImplementerFIO = model.ImplementerFIO,
});
if (element != null && element.Id != model.Id)
{
throw new InvalidOperationException("Исполнитель с таким ФИО уже есть");
}
}
}
}

View File

@@ -0,0 +1,85 @@
using FishFactoryContracts.BindingModels;
using FishFactoryContracts.BusinessLogicsContracts;
using FishFactoryContracts.SearchModels;
using FishFactoryContracts.StoragesContracts;
using FishFactoryContracts.ViewModels;
using Microsoft.Extensions.Logging;
namespace FishFactoryBusinessLogic.BusinessLogic
{
public class MessageInfoLogic : IMessageInfoLogic
{
private readonly ILogger _logger;
private readonly IMessageInfoStorage _messageInfoStorage;
private readonly IClientStorage _clientStorage;
public MessageInfoLogic(ILogger<MessageInfoLogic> logger, IMessageInfoStorage messageInfoStorage, IClientStorage clientStorage)
{
_logger = logger;
_messageInfoStorage = messageInfoStorage;
_clientStorage = clientStorage;
}
public List<MessageInfoViewModel>? ReadList(MessageInfoSearchModel? model)
{
_logger.LogInformation("ReadList. MessageId:{MessageId}.ClientId:{ClientId}", model?.MessageId, model?.ClientId);
var list = model == null ? _messageInfoStorage.GetFullList() : _messageInfoStorage.GetFilteredList(model);
if (list == null)
{
_logger.LogWarning("ReadList return null list");
return null;
}
_logger.LogInformation("ReadList. Count:{Count}", list.Count);
return list;
}
public bool Create(MessageInfoBindingModel model)
{
CheckModel(model);
if (_messageInfoStorage.Insert(model) == null)
{
_logger.LogWarning("Insert operation failed");
return false;
}
return true;
}
private void CheckModel(MessageInfoBindingModel model, bool withParams = true)
{
if (model == null)
{
throw new ArgumentNullException(nameof(model));
}
if (!withParams)
{
return;
}
if (string.IsNullOrEmpty(model.MessageId))
{
throw new ArgumentNullException("Не указан id сообщения", nameof(model.MessageId));
}
if (string.IsNullOrEmpty(model.SenderName))
{
throw new ArgumentNullException("Не указана почта", nameof(model.SenderName));
}
if (string.IsNullOrEmpty(model.Subject))
{
throw new ArgumentNullException("Не указана тема", nameof(model.Subject));
}
if (string.IsNullOrEmpty(model.Body))
{
throw new ArgumentNullException("Не указан текст сообщения", nameof(model.Subject));
}
_logger.LogInformation("MessageInfo. MessageId:{MessageId}.SenderName:{SenderName}.Subject:{Subject}.Body:{Body}", model.MessageId, model.SenderName, model.Subject, model.Body);
var element = _clientStorage.GetElement(new ClientSearchModel
{
Email = model.SenderName
});
if (element == null)
{
_logger.LogWarning("Не удалоссь найти клиента, отправившего письмо с адреса:{Email}", model.SenderName);
}
else
{
model.ClientId = element.Id;
}
}
}
}

View File

@@ -1,31 +1,25 @@
using FishFactoryContracts.BindingModels; using FishFactoryBusinessLogic.MailWorker;
using FishFactoryContracts.BindingModels;
using FishFactoryContracts.BusinessLogicsContracts; using FishFactoryContracts.BusinessLogicsContracts;
using FishFactoryContracts.SearchModels; using FishFactoryContracts.SearchModels;
using FishFactoryContracts.StoragesContracts; using FishFactoryContracts.StoragesContracts;
using FishFactoryContracts.ViewModels; using FishFactoryContracts.ViewModels;
using FishFactoryDataModel.Enums; using FishFactoryDataModel.Enums;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FishFactoryBusinessLogic.BusinessLogic namespace FishFactoryBusinessLogic.BusinessLogic
{ {
public class OrderLogic : IOrderLogic public class OrderLogic : IOrderLogic
{ {
//Класс с логикой для заказов будет отвечать за получение списка заказов,
//создания заказа и смены его статусов. Следует учитывать, что у заказа можно
//менять статус на новый, если его текущий статус предшествует новому
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly IOrderStorage _orderStorage; private readonly IOrderStorage _orderStorage;
private readonly AbstractMailWorker _mailWorker;
public OrderLogic(ILogger<OrderLogic> logger, IOrderStorage orderStorage) public OrderLogic(ILogger<OrderLogic> logger, IOrderStorage orderStorage, AbstractMailWorker mailWorker)
{ {
_logger = logger; _logger = logger;
_orderStorage = orderStorage; _orderStorage = orderStorage;
_mailWorker = mailWorker;
} }
public List<OrderViewModel>? ReadList(OrderSearchModel? model) public List<OrderViewModel>? ReadList(OrderSearchModel? model)
@@ -41,27 +35,54 @@ namespace FishFactoryBusinessLogic.BusinessLogic
return list; return list;
} }
public OrderViewModel? ReadElement(OrderSearchModel model)
{
if (model == null)
{
throw new ArgumentNullException(nameof(model));
}
_logger.LogInformation("ReadElement. ClientId:{ClientId}.Status:{Status}.ImplementerId:{ImplementerId}.DateFrom:{DateFrom}.DateTo:{DateTo}OrderId:{Id}", model.ClientId, model.Status, model.ImplementerId, model.DateFrom, model.DateTo, model.Id);
var element = _orderStorage.GetElement(model);
if (element == null)
{
_logger.LogWarning("ReadElement element not found");
return null;
}
_logger.LogInformation("ReadElement find. Id:{Id}", element.Id);
return element;
}
public bool CreateOrder(OrderBindingModel model) public bool CreateOrder(OrderBindingModel model)
{ {
CheckModel(model); CheckModel(model);
if (model.Status != OrderStatus.Неизвестен) if (model.Status != OrderStatus.Неизвестен)
return false; return false;
model.Status = OrderStatus.Принят; model.Status = OrderStatus.Принят;
if (_orderStorage.Insert(model) == null) var order = _orderStorage.Insert(model);
if (order == null)
{
_logger.LogWarning("Insert operation failed");
return false;
}
Task.Run(() => _mailWorker.MailSendAsync(new MailSendInfoBindingModel
{ {
model.Status = OrderStatus.Неизвестен; MailAddress = order.ClientEmail,
_logger.LogWarning("Insert operation failed"); Subject = $"Новый заказ создан. Номер заказа - {order.Id}",
return false; Text = $"Ваш заказ номер {order.Id} на консерву {order.CannedName} от {order.DateCreate} на сумму {order.Sum} принят."
} }));
return true; return true;
} }
public bool TakeOrderInWork(OrderBindingModel model) public bool TakeOrderInWork(OrderBindingModel model)
{ {
return ToNextStatus(model, OrderStatus.Выполняется); return ToNextStatus(model, OrderStatus.Выполняется);
} }
public bool FinishOrder(OrderBindingModel model) public bool FinishOrder(OrderBindingModel model)
{ {
@@ -85,21 +106,28 @@ namespace FishFactoryBusinessLogic.BusinessLogic
throw new ArgumentNullException(nameof(element)); throw new ArgumentNullException(nameof(element));
} }
model.CannedId = element.CannedId; if (element.ImplementerId != null && model.ImplementerId != null && model.ImplementerId != element.ImplementerId)
{
throw new InvalidOperationException(nameof(model.ImplementerId));
}
model.CannedId = element.CannedId;
model.ClientId = element.ClientId;
model.DateCreate = element.DateCreate; model.DateCreate = element.DateCreate;
model.DateImplement = element.DateImplement; model.DateImplement = element.DateImplement;
model.Status = element.Status; model.Status = element.Status;
model.Count = element.Count; model.Count = element.Count;
model.Sum = element.Sum; model.Sum = element.Sum;
model.ImplementerId = element.ImplementerId.HasValue ? element.ImplementerId : model.ImplementerId;
if (model.Status != orderStatus - 1) if (model.Status != orderStatus - 1)
{ {
_logger.LogWarning("Status update to " + orderStatus + " operation failed"); _logger.LogWarning("Status update to " + orderStatus + " operation failed");
return false; return false;
} }
model.Status = orderStatus; model.Status = orderStatus;
if (model.Status == OrderStatus.Выдан) if (model.Status == OrderStatus.Готов)
{ {
model.DateImplement = DateTime.Now; model.DateImplement = DateTime.Now;
} }
@@ -110,6 +138,14 @@ namespace FishFactoryBusinessLogic.BusinessLogic
_logger.LogWarning("Changing status operation faled"); _logger.LogWarning("Changing status operation faled");
return false; return false;
} }
Task.Run(() => _mailWorker.MailSendAsync(new MailSendInfoBindingModel
{
MailAddress = element.ClientEmail,
Subject = $"Изменение статуса заказа номер {element.Id}",
Text = $"У заказа номер {element.Id} изменен статус на {orderStatus}"
}));
return true; return true;
} }

View File

@@ -0,0 +1,141 @@
using FishFactoryContracts.BindingModels;
using FishFactoryContracts.BusinessLogicsContracts;
using FishFactoryContracts.SearchModels;
using FishFactoryContracts.ViewModels;
using FishFactoryDataModel.Enums;
using Microsoft.Extensions.Logging;
namespace FishFactoryBusinessLogic.BusinessLogic
{
public class WorkModeling : IWorkProcess
{
private readonly ILogger _logger;
private readonly Random _rnd;
private IOrderLogic? _orderLogic;
public WorkModeling(ILogger<WorkModeling> logger)
{
_logger = logger;
_rnd = new Random(1000);
}
public void DoWork(IImplementerLogic implementerLogic, IOrderLogic orderLogic)
{
_orderLogic = orderLogic;
var implementers = implementerLogic.ReadList(null);
if (implementers == null)
{
_logger.LogWarning("DoWork. Implementers is null");
return;
}
var orders = _orderLogic.ReadList(new OrderSearchModel { Status = OrderStatus.Принят });
if (orders == null || orders.Count == 0)
{
_logger.LogWarning("DoWork. Orders is null or empty");
return;
}
_logger.LogDebug("DoWork for {Count} orders", orders.Count);
foreach (var implementer in implementers)
{
Task.Run(() => WorkerWorkAsync(implementer, orders));
}
}
private async Task WorkerWorkAsync(ImplementerViewModel implementer, List<OrderViewModel> orders)
{
if (_orderLogic == null || implementer == null)
{
return;
}
await RunOrderInWork(implementer);
await Task.Run(() =>
{
foreach (var order in orders)
{
try
{
_logger.LogDebug("DoWork. Worker {Id} try get order {Order}", implementer.Id, order.Id);
// пытаемся назначить заказ на исполнителя
bool result = _orderLogic.TakeOrderInWork(new OrderBindingModel
{
Id = order.Id,
ImplementerId = implementer.Id
});
if (!result)
{
_logger.LogDebug("WorkerWorkAsync. Worker {Id} tried to get order {Order} but it's already acquired by other worker", implementer.Id, order.Id);
continue;
}
// делаем работу
Thread.Sleep(implementer.WorkExperience * _rnd.Next(100, 1000) * order.Count);
_logger.LogDebug("DoWork. Worker {Id} finish order {Order}", implementer.Id, order.Id);
_orderLogic.FinishOrder(new OrderBindingModel
{
Id = order.Id
});
Thread.Sleep(implementer.Qualification * _rnd.Next(10, 100));
}
// кто-то мог уже перехватить заказ, игнорируем ошибку
catch (InvalidOperationException ex)
{
_logger.LogWarning(ex, "Error try get work");
}
// заканчиваем выполнение имитации в случае иной ошибки
catch (Exception ex)
{
_logger.LogError(ex, "Error while do work");
throw;
}
// отдыхаем
}
});
}
private async Task RunOrderInWork(ImplementerViewModel implementer)
{
if (_orderLogic == null || implementer == null)
{
return;
}
try
{
var runOrder = await Task.Run(() => _orderLogic.ReadElement(new()
{
ImplementerId = implementer.Id,
Status = OrderStatus.Выполняется
}));
if (runOrder == null)
{
return;
}
_logger.LogDebug("DoWork. Worker {Id} back to order {Order}", implementer.Id, runOrder.Id);
// доделываем работу
Thread.Sleep(implementer.WorkExperience * _rnd.Next(100, 300) * runOrder.Count);
_logger.LogDebug("DoWork. Worker {Id} finish order {Order}", implementer.Id, runOrder.Id);
_orderLogic.FinishOrder(new OrderBindingModel
{
Id = runOrder.Id
});
// отдыхаем
Thread.Sleep(implementer.Qualification * _rnd.Next(10, 100));
}
// заказа может не быть, просто игнорируем ошибку
catch (InvalidOperationException ex)
{
_logger.LogWarning(ex, "Error try get work");
}
// а может возникнуть иная ошибка, тогда просто заканчиваем выполнение имитации
catch (Exception ex)
{
_logger.LogError(ex, "Error while do work");
throw;
}
}
}
}

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net6.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<Platforms>AnyCPU;x86</Platforms> <Platforms>AnyCPU;x86</Platforms>
@@ -9,6 +9,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="DocumentFormat.OpenXml" Version="2.19.0" /> <PackageReference Include="DocumentFormat.OpenXml" Version="2.19.0" />
<PackageReference Include="MailKit" Version="4.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="8.0.0" />

View File

@@ -0,0 +1,81 @@
using FishFactoryBusinessLogic.BusinessLogic;
using FishFactoryContracts.BindingModels;
using FishFactoryContracts.BusinessLogicsContracts;
using Microsoft.Extensions.Logging;
namespace FishFactoryBusinessLogic.MailWorker
{
public abstract class AbstractMailWorker
{
protected string _mailLogin = string.Empty;
protected string _mailPassword = string.Empty;
protected string _smtpClientHost = string.Empty;
protected int _smtpClientPort;
protected string _popHost = string.Empty;
protected int _popPort;
private readonly IMessageInfoLogic _messageInfoLogic;
private readonly ILogger _logger;
public AbstractMailWorker(ILogger<AbstractMailWorker> logger, IMessageInfoLogic messageInfoLogic)
{
_logger = logger;
_messageInfoLogic = messageInfoLogic;
}
public void MailConfig(MailConfigBindingModel config)
{
_mailLogin = config.MailLogin;
_mailPassword = config.MailPassword;
_smtpClientHost = config.SmtpClientHost;
_smtpClientPort = config.SmtpClientPort;
_popHost = config.PopHost;
_popPort = config.PopPort;
_logger.LogDebug("Config: {login}, {password}, {clientHost}, { clientPOrt}, { popHost}, { popPort}", _mailLogin, _mailPassword, _smtpClientHost, _smtpClientPort, _popHost, _popPort);
}
public async void MailSendAsync(MailSendInfoBindingModel 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))
{
return;
}
_logger.LogDebug("Send Mail: {To}, {Subject}", info.MailAddress,
info.Subject);
await SendMailAsync(info);
}
public async void MailCheck()
{
if (string.IsNullOrEmpty(_mailLogin) ||
string.IsNullOrEmpty(_mailPassword))
{
return;
}
if (string.IsNullOrEmpty(_popHost) || _popPort == 0)
{
return;
}
if (_messageInfoLogic == null)
{
return;
}
var list = await ReceiveMailAsync();
_logger.LogDebug("Check Mail: {Count} new mails", list.Count);
foreach (var mail in list)
{
_messageInfoLogic.Create(mail);
}
}
protected abstract Task SendMailAsync(MailSendInfoBindingModel info);
protected abstract Task<List<MessageInfoBindingModel>> ReceiveMailAsync();
}
}

View File

@@ -0,0 +1,77 @@
using FishFactoryContracts.BindingModels;
using FishFactoryContracts.BusinessLogicsContracts;
using System.Net.Mail;
using System.Net;
using System.Text;
using MailKit.Net.Pop3;
using MailKit.Security;
using Microsoft.Extensions.Logging;
namespace FishFactoryBusinessLogic.MailWorker
{
public class MailKitWorker : AbstractMailWorker
{
public MailKitWorker(ILogger<MailKitWorker> logger, IMessageInfoLogic messageInfoLogic) : base(logger, messageInfoLogic) { }
//отправка письма
protected override async Task SendMailAsync(MailSendInfoBindingModel info)
{
using var objMailMessage = new MailMessage();
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);
await Task.Run(() => objSmtpClient.Send(objMailMessage));
}
catch (Exception)
{
throw;
}
}
//получение письма
protected override async Task<List<MessageInfoBindingModel>> ReceiveMailAsync()
{
var list = new List<MessageInfoBindingModel>();
using var client = new Pop3Client();
await Task.Run(() =>
{
try
{
client.Connect(_popHost, _popPort, SecureSocketOptions.SslOnConnect);
client.Authenticate(_mailLogin, _mailPassword);
for (int i = 0; i < client.Count; i++)
{
var message = client.GetMessage(i);
foreach (var mail in message.From.Mailboxes)
{
list.Add(new MessageInfoBindingModel
{
DateDelivery = message.Date.DateTime,
MessageId = message.MessageId,
SenderName = mail.Address,
Subject = message.Subject,
Body = message.TextBody
});
}
}
}
catch (MailKit.Security.AuthenticationException) { }
finally
{
client.Disconnect(true);
}
});
return list;
}
}
}

View File

@@ -0,0 +1,44 @@
using FishFactoryContracts.ViewModels;
using Newtonsoft.Json;
using System.Net.Http.Headers;
using System.Text;
namespace FishFactoryClientApp
{
public static class APIClient
{
private static readonly HttpClient _client = new();
public static ClientViewModel? Client { get; set; } = null;
public static void Connect(IConfiguration configuration)
{
_client.BaseAddress = new Uri(configuration["IPAddress"]);
_client.DefaultRequestHeaders.Accept.Clear();
_client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
}
public static T? GetRequest<T>(string requestUrl)
{
var response = _client.GetAsync(requestUrl);
var result = response.Result.Content.ReadAsStringAsync().Result;
if (response.Result.IsSuccessStatusCode)
{
return JsonConvert.DeserializeObject<T>(result);
}
else
{
throw new Exception(result);
}
}
public static void PostRequest<T>(string requestUrl, T model)
{
var json = JsonConvert.SerializeObject(model);
var data = new StringContent(json, Encoding.UTF8, "application/json");
var response = _client.PostAsync(requestUrl, data);
var result = response.Result.Content.ReadAsStringAsync().Result;
if (!response.Result.IsSuccessStatusCode)
{
throw new Exception(result);
}
}
}
}

View File

@@ -0,0 +1,82 @@
using FishFactoryContracts.BindingModels;
using FishFactoryContracts.BusinessLogicsContracts;
using FishFactoryContracts.SearchModels;
using FishFactoryContracts.ViewModels;
using Microsoft.AspNetCore.Mvc;
namespace FishFactoryClientApp.Controllers
{
[Route("api/[controller]/[action]")]
[ApiController]
public class ClientController : Controller
{
private readonly ILogger _logger;
private readonly IClientLogic _logic;
private readonly IMessageInfoLogic _mailLogic;
public ClientController(IClientLogic logic, IMessageInfoLogic mailLogic, ILogger<ClientController> logger)
{
_logger = logger;
_logic = logic;
_mailLogic = mailLogic;
}
[HttpGet]
public ClientViewModel? Login(string login, string password)
{
try
{
return _logic.ReadElement(new ClientSearchModel
{
Email = login,
Password = password
});
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка входа в систему");
throw;
}
}
[HttpPost]
public void Register(ClientBindingModel model)
{
try
{
_logic.Create(model);
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка регистрации");
throw;
}
}
[HttpPost]
public void UpdateData(ClientBindingModel model)
{
try
{
_logic.Update(model);
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка обновления данных");
throw;
}
}
[HttpGet]
public List<MessageInfoViewModel>? GetMessages(int clientId)
{
try
{
return _mailLogic.ReadList(new MessageInfoSearchModel
{
ClientId = clientId
});
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка получения писем клиента");
throw;
}
}
}
}

View File

@@ -0,0 +1,144 @@
using FishFactoryContracts.BindingModels;
using FishFactoryContracts.ViewModels;
using FishFactoryClientApp.Models;
using FishFactoryClientApp;
using Microsoft.AspNetCore.Mvc;
using System.Diagnostics;
namespace AbstractShowClientApp.Controllers
{
public class HomeController : Controller
{
private readonly ILogger<HomeController> _logger;
public HomeController(ILogger<HomeController> logger)
{
_logger = logger;
}
public IActionResult Index()
{
if (APIClient.Client == null)
{
return Redirect("~/Home/Enter");
}
return View(APIClient.GetRequest<List<OrderViewModel>>($"api/main/getorders?clientId={APIClient.Client.Id}"));
}
[HttpGet]
public IActionResult Privacy()
{
if (APIClient.Client == null)
{
return Redirect("~/Home/Enter");
}
return View(APIClient.Client);
}
[HttpPost]
public void Privacy(string login, string password, string fio)
{
if (APIClient.Client == null)
{
throw new Exception("Вы как суда попали? Суда вход только авторизованным");
}
if (string.IsNullOrEmpty(login) || string.IsNullOrEmpty(password) || string.IsNullOrEmpty(fio))
{
throw new Exception("Введите логин, пароль и ФИО");
}
APIClient.PostRequest("api/client/updatedata", new ClientBindingModel
{
Id = APIClient.Client.Id,
ClientFIO = fio,
Email = login,
Password = password
});
APIClient.Client.ClientFIO = fio;
APIClient.Client.Email = login;
APIClient.Client.Password = password;
Response.Redirect("Index");
}
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public IActionResult Error()
{
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
}
[HttpGet]
public IActionResult Enter()
{
return View();
}
[HttpPost]
public void Enter(string login, string password)
{
if (string.IsNullOrEmpty(login) || string.IsNullOrEmpty(password))
{
throw new Exception("Введите логин и пароль");
}
APIClient.Client = APIClient.GetRequest<ClientViewModel>($"api/client/login?login={login}&password={password}");
if (APIClient.Client == null)
{
throw new Exception("Неверный логин/пароль");
}
Response.Redirect("Index");
}
[HttpGet]
public IActionResult Register()
{
return View();
}
[HttpPost]
public void Register(string login, string password, string fio)
{
if (string.IsNullOrEmpty(login) || string.IsNullOrEmpty(password) || string.IsNullOrEmpty(fio))
{
throw new Exception("Введите логин, пароль и ФИО");
}
APIClient.PostRequest("api/client/register", new ClientBindingModel
{
ClientFIO = fio,
Email = login,
Password = password
});
Response.Redirect("Enter");
return;
}
[HttpGet]
public IActionResult Create()
{
ViewBag.Canneds = APIClient.GetRequest<List<CannedViewModel>>("api/main/getcannedlist");
return View();
}
[HttpPost]
public void Create(int canned, int count)
{
if (APIClient.Client == null)
{
throw new Exception("Вы как суда попали? Суда вход только авторизованным");
}
if (count <= 0)
{
throw new Exception("Количество и сумма должны быть больше 0");
}
APIClient.PostRequest("api/main/createorder", new OrderBindingModel
{
ClientId = APIClient.Client.Id,
CannedId = canned,
Count = count,
Sum = Calc(count, canned)
});
Response.Redirect("Index");
}
[HttpPost]
public double Calc(int count, int canned)
{
var prod = APIClient.GetRequest<CannedViewModel>($"api/main/getcanned?cannedId={canned}");
return count * (prod?.Price ?? 1);
}
[HttpGet]
public IActionResult Mails()
{
if (APIClient.Client == null)
{
return Redirect("~/Home/Enter");
}
return View(APIClient.GetRequest<List<MessageInfoViewModel>>($"api/client/getmessages?clientId={APIClient.Client.Id}"));
}
}
}

View File

@@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="7.0.17" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\FishFactoryBusinessLogic\FishFactoryBusinessLogic.csproj" />
<ProjectReference Include="..\FishFactoryDatabaseImplement\FishFactoryDatabaseImplement.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,9 @@
namespace FishFactoryClientApp.Models
{
public class ErrorViewModel
{
public string? RequestId { get; set; }
public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
}
}

View File

@@ -0,0 +1,22 @@
using FishFactoryClientApp;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllersWithViews();
var app = builder.Build();
APIClient.Connect(builder.Configuration);
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.Run();

View File

@@ -0,0 +1,38 @@
{
"$schema": "https://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:37816",
"sslPort": 44335
}
},
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "http://localhost:5220",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "https://localhost:7232;http://localhost:5220",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}

View File

@@ -0,0 +1,48 @@
@{
ViewData["Title"] = "Create";
}
<div class="text-center">
<h2 class="display-4">Создание заказа</h2>
</div>
<form method="post">
<div class="row">
<div class="col-4">Изделие:</div>
<div class="col-8">
<select id="canned" name="canned" class="form-control" asp-items="@(new SelectList(@ViewBag.Canneds,"Id", "CannedName"))"></select>
</div>
</div>
<div class="row">
<div class="col-4">Количество:</div>
<div class="col-8"><input type="text" name="count" id="count" /></div>
</div>
<div class="row">
<div class="col-4">Сумма:</div>
<div class="col-8"><input type="text" id="sum" name="sum" readonly /></div>
</div>
<div class="row">
<div class="col-8"></div>
<div class="col-4"><input type="submit" value="Создать" class="btn btn-primary" /></div>
</div>
</form>
<script>
$('#canned').on('change', function () {
check();
});
$('#count').on('change', function () {
check();
});
function check() {
var count = $('#count').val();
var canned = $('#canned').val();
if (count && canned) {
$.ajax({
method: "POST",
url: "/Home/Calc",
data: { count: count, canned: canned },
success: function (result) {
$("#sum").val(result);
}
});
};
}
</script>

View File

@@ -0,0 +1,22 @@
@{
ViewData["Title"] = "Enter";
}
<div class="text-center">
<h2 class="display-4">Вход в приложение</h2>
</div>
<form method="post">
<div class="row">
<div class="col-4">Логин:</div>
<div class="col-8"><input type="text" name="login" /></div>
</div>
<div class="row">
<div class="col-4">Пароль:</div>
<div class="col-8"><input type="password" name="password" /></div>
</div>
<div class="row">
<div class="col-8"></div>
<div class="col-4"><input type="submit" value="Вход" class="btn btn-primary" /></div>
</div>
<div class="row">
<div class="col-8">Или <a link="Register.cshtml">зарегистрируйтесь</a></div>
</form>

View File

@@ -0,0 +1,69 @@
@using FishFactoryContracts.ViewModels
@model List<OrderViewModel>
@{
ViewData["Title"] = "Home Page";
}
<div class="text-center">
<h1 class="display-4">Заказы</h1>
</div>
<div class="text-center">
@{
if (Model == null)
{
<h3 class="display-4">Авторизируйтесь</h3>
return;
}
<p>
<a asp-action="Create">Создать заказ</a>
</p>
<table class="table">
<thead>
<tr>
<th>
Номер
</th>
<th>
Изделие
</th>
<th>
Дата создания
</th>
<th>
Количество
</th>
<th>
Сумма
</th>
<th>
Статус
</th>
</tr>
</thead>
<tbody>
@foreach (var item in Model)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.Id)
</td>
<td>
@Html.DisplayFor(modelItem => item.CannedName)
</td>
<td>
@Html.DisplayFor(modelItem => item.DateCreate)
</td>
<td>
@Html.DisplayFor(modelItem => item.Count)
</td>
<td>
@Html.DisplayFor(modelItem => item.Sum)
</td>
<td>
@Html.DisplayFor(modelItem => item.Status)
</td>
</tr>
}
</tbody>
</table>
}
</div>

View File

@@ -0,0 +1,48 @@
@using FishFactoryContracts.ViewModels
@model List<MessageInfoViewModel>
@{
ViewData["Title"] = "Mails";
}
<div class="text-center">
<h1 class="display-4">Заказы</h1>
</div>
<div class="text-center">
@{
if (Model == null)
{
<h3 class="display-4">Авторизируйтесь</h3>
return;
}
<table class="table">
<thead>
<tr>
<th>
Дата письма
</th>
<th>
Заголовок
</th>
<th>
Текст
</th>
</tr>
</thead>
<tbody>
@foreach (var item in Model)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.DateDelivery)
</td>
<td>
@Html.DisplayFor(modelItem => item.Subject)
</td>
<td>
@Html.DisplayFor(modelItem => item.Body)
</td>
</tr>
}
</tbody>
</table>
}
</div>

View File

@@ -0,0 +1,26 @@
@using FishFactoryContracts.ViewModels
@model ClientViewModel
@{
ViewData["Title"] = "Privacy Policy";
}
<div class="text-center">
<h2 class="display-4">Личные данные</h2>
</div>
<form method="post">
<div class="row">
<div class="col-4">Логин:</div>
<div class="col-8"><input type="text" name="login" value="@Model.Email" /></div>
</div>
<div class="row">
<div class="col-4">Пароль:</div>
<div class="col-8"><input type="password" name="password" value="@Model.Password" /></div>
</div>
<div class="row">
<div class="col-4">ФИО:</div>
<div class="col-8"><input type="text" name="fio" value="@Model.ClientFIO" /></div>
</div>
<div class="row">
<div class="col-8"></div>
<div class="col-4"><input type="submit" value="Сохранить" class="btn btn-primary" /></div>
</div>
</form>

View File

@@ -0,0 +1,24 @@
@{
ViewData["Title"] = "Register";
}
<div class="text-center">
<h2 class="display-4">Регистрация</h2>
</div>
<form method="post">
<div class="row">
<div class="col-4">Логин:</div>
<div class="col-8"><input type="text" name="login" /></div>
</div>
<div class="row">
<div class="col-4">Пароль:</div>
<div class="col-8"><input type="password" name="password" /></div>
</div>
<div class="row">
<div class="col-4">ФИО:</div>
<div class="col-8"><input type="text" name="fio" /></div>
</div>
<div class="row">
<div class="col-8"></div>
<div class="col-4"><input type="submit" value="Регистрация" class="btn btn-primary" /></div>
</div>
</form>

View File

@@ -0,0 +1,25 @@
@model ErrorViewModel
@{
ViewData["Title"] = "Error";
}
<h1 class="text-danger">Error.</h1>
<h2 class="text-danger">An error occurred while processing your request.</h2>
@if (Model.ShowRequestId)
{
<p>
<strong>Request ID:</strong> <code>@Model.RequestId</code>
</p>
}
<h3>Development Mode</h3>
<p>
Swapping to <strong>Development</strong> environment will display more detailed information about the error that occurred.
</p>
<p>
<strong>The Development environment shouldn't be enabled for deployed applications.</strong>
It can result in displaying sensitive information from exceptions to end users.
For local debugging, enable the <strong>Development</strong> environment by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>
and restarting the app.
</p>

View File

@@ -0,0 +1,56 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - AbstractShowClientApp</title>
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
<link rel="stylesheet" href="~/css/site.css" />
<script src="~/lib/jquery/dist/jquery.min.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
</head>
<body>
<header>
<nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
<div class="container">
<a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index">Рыбный завод</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target=".navbar-collapse" aria-controls="navbarSupportedContent"
aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">
<ul class="navbar-nav flex-grow-1">
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Index">Заказы</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Privacy">Личные данные</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Mails">Письма</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Enter">Вход</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Register">Регистрация</a>
</li>
</ul>
</div>
</div>
</nav>
</header>
<div class="container">
<main role="main" class="pb-3">
@RenderBody()
</main>
</div>
<footer class="border-top footer text-muted">
<div class="container">
&copy; 2024 - Рыбный завод - <a asp-area="" asp-controller="Home" asp-action="Privacy">Личные данные</a>
</div>
</footer>
<script src="~/js/site.js" asp-append-version="true"></script>
@RenderSection("Scripts", required: false)
</body>
</html>

View File

@@ -0,0 +1,5 @@
@*
For more information on enabling MVC for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860
*@
@{
}

View File

@@ -0,0 +1,3 @@
@using FishFactoryClientApp
@using FishFactoryClientApp.Models
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

View File

@@ -0,0 +1,3 @@
@{
Layout = "_Layout";
}

View File

@@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}

View File

@@ -0,0 +1,10 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"IPAddress": "http://localhost:5284/"
}

View File

@@ -0,0 +1,22 @@
The MIT License (MIT)
Copyright (c) 2011-2021 Twitter, Inc.
Copyright (c) 2011-2021 The Bootstrap Authors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,427 @@
/*!
* Bootstrap Reboot v5.1.0 (https://getbootstrap.com/)
* Copyright 2011-2021 The Bootstrap Authors
* Copyright 2011-2021 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
*/
*,
*::before,
*::after {
box-sizing: border-box;
}
@media (prefers-reduced-motion: no-preference) {
:root {
scroll-behavior: smooth;
}
}
body {
margin: 0;
font-family: var(--bs-body-font-family);
font-size: var(--bs-body-font-size);
font-weight: var(--bs-body-font-weight);
line-height: var(--bs-body-line-height);
color: var(--bs-body-color);
text-align: var(--bs-body-text-align);
background-color: var(--bs-body-bg);
-webkit-text-size-adjust: 100%;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
hr {
margin: 1rem 0;
color: inherit;
background-color: currentColor;
border: 0;
opacity: 0.25;
}
hr:not([size]) {
height: 1px;
}
h6, h5, h4, h3, h2, h1 {
margin-top: 0;
margin-bottom: 0.5rem;
font-weight: 500;
line-height: 1.2;
}
h1 {
font-size: calc(1.375rem + 1.5vw);
}
@media (min-width: 1200px) {
h1 {
font-size: 2.5rem;
}
}
h2 {
font-size: calc(1.325rem + 0.9vw);
}
@media (min-width: 1200px) {
h2 {
font-size: 2rem;
}
}
h3 {
font-size: calc(1.3rem + 0.6vw);
}
@media (min-width: 1200px) {
h3 {
font-size: 1.75rem;
}
}
h4 {
font-size: calc(1.275rem + 0.3vw);
}
@media (min-width: 1200px) {
h4 {
font-size: 1.5rem;
}
}
h5 {
font-size: 1.25rem;
}
h6 {
font-size: 1rem;
}
p {
margin-top: 0;
margin-bottom: 1rem;
}
abbr[title],
abbr[data-bs-original-title] {
-webkit-text-decoration: underline dotted;
text-decoration: underline dotted;
cursor: help;
-webkit-text-decoration-skip-ink: none;
text-decoration-skip-ink: none;
}
address {
margin-bottom: 1rem;
font-style: normal;
line-height: inherit;
}
ol,
ul {
padding-left: 2rem;
}
ol,
ul,
dl {
margin-top: 0;
margin-bottom: 1rem;
}
ol ol,
ul ul,
ol ul,
ul ol {
margin-bottom: 0;
}
dt {
font-weight: 700;
}
dd {
margin-bottom: 0.5rem;
margin-left: 0;
}
blockquote {
margin: 0 0 1rem;
}
b,
strong {
font-weight: bolder;
}
small {
font-size: 0.875em;
}
mark {
padding: 0.2em;
background-color: #fcf8e3;
}
sub,
sup {
position: relative;
font-size: 0.75em;
line-height: 0;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
a {
color: #0d6efd;
text-decoration: underline;
}
a:hover {
color: #0a58ca;
}
a:not([href]):not([class]), a:not([href]):not([class]):hover {
color: inherit;
text-decoration: none;
}
pre,
code,
kbd,
samp {
font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
font-size: 1em;
direction: ltr /* rtl:ignore */;
unicode-bidi: bidi-override;
}
pre {
display: block;
margin-top: 0;
margin-bottom: 1rem;
overflow: auto;
font-size: 0.875em;
}
pre code {
font-size: inherit;
color: inherit;
word-break: normal;
}
code {
font-size: 0.875em;
color: #d63384;
word-wrap: break-word;
}
a > code {
color: inherit;
}
kbd {
padding: 0.2rem 0.4rem;
font-size: 0.875em;
color: #fff;
background-color: #212529;
border-radius: 0.2rem;
}
kbd kbd {
padding: 0;
font-size: 1em;
font-weight: 700;
}
figure {
margin: 0 0 1rem;
}
img,
svg {
vertical-align: middle;
}
table {
caption-side: bottom;
border-collapse: collapse;
}
caption {
padding-top: 0.5rem;
padding-bottom: 0.5rem;
color: #6c757d;
text-align: left;
}
th {
text-align: inherit;
text-align: -webkit-match-parent;
}
thead,
tbody,
tfoot,
tr,
td,
th {
border-color: inherit;
border-style: solid;
border-width: 0;
}
label {
display: inline-block;
}
button {
border-radius: 0;
}
button:focus:not(:focus-visible) {
outline: 0;
}
input,
button,
select,
optgroup,
textarea {
margin: 0;
font-family: inherit;
font-size: inherit;
line-height: inherit;
}
button,
select {
text-transform: none;
}
[role=button] {
cursor: pointer;
}
select {
word-wrap: normal;
}
select:disabled {
opacity: 1;
}
[list]::-webkit-calendar-picker-indicator {
display: none;
}
button,
[type=button],
[type=reset],
[type=submit] {
-webkit-appearance: button;
}
button:not(:disabled),
[type=button]:not(:disabled),
[type=reset]:not(:disabled),
[type=submit]:not(:disabled) {
cursor: pointer;
}
::-moz-focus-inner {
padding: 0;
border-style: none;
}
textarea {
resize: vertical;
}
fieldset {
min-width: 0;
padding: 0;
margin: 0;
border: 0;
}
legend {
float: left;
width: 100%;
padding: 0;
margin-bottom: 0.5rem;
font-size: calc(1.275rem + 0.3vw);
line-height: inherit;
}
@media (min-width: 1200px) {
legend {
font-size: 1.5rem;
}
}
legend + * {
clear: left;
}
::-webkit-datetime-edit-fields-wrapper,
::-webkit-datetime-edit-text,
::-webkit-datetime-edit-minute,
::-webkit-datetime-edit-hour-field,
::-webkit-datetime-edit-day-field,
::-webkit-datetime-edit-month-field,
::-webkit-datetime-edit-year-field {
padding: 0;
}
::-webkit-inner-spin-button {
height: auto;
}
[type=search] {
outline-offset: -2px;
-webkit-appearance: textfield;
}
/* rtl:raw:
[type="tel"],
[type="url"],
[type="email"],
[type="number"] {
direction: ltr;
}
*/
::-webkit-search-decoration {
-webkit-appearance: none;
}
::-webkit-color-swatch-wrapper {
padding: 0;
}
::file-selector-button {
font: inherit;
}
::-webkit-file-upload-button {
font: inherit;
-webkit-appearance: button;
}
output {
display: inline-block;
}
iframe {
border: 0;
}
summary {
display: list-item;
cursor: pointer;
}
progress {
vertical-align: baseline;
}
[hidden] {
display: none !important;
}
/*# sourceMappingURL=bootstrap-reboot.css.map */

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,8 @@
/*!
* Bootstrap Reboot v5.1.0 (https://getbootstrap.com/)
* Copyright 2011-2021 The Bootstrap Authors
* Copyright 2011-2021 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
*/*,::after,::before{box-sizing:border-box}@media (prefers-reduced-motion:no-preference){:root{scroll-behavior:smooth}}body{margin:0;font-family:var(--bs-body-font-family);font-size:var(--bs-body-font-size);font-weight:var(--bs-body-font-weight);line-height:var(--bs-body-line-height);color:var(--bs-body-color);text-align:var(--bs-body-text-align);background-color:var(--bs-body-bg);-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}hr{margin:1rem 0;color:inherit;background-color:currentColor;border:0;opacity:.25}hr:not([size]){height:1px}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem;font-weight:500;line-height:1.2}h1{font-size:calc(1.375rem + 1.5vw)}@media (min-width:1200px){h1{font-size:2.5rem}}h2{font-size:calc(1.325rem + .9vw)}@media (min-width:1200px){h2{font-size:2rem}}h3{font-size:calc(1.3rem + .6vw)}@media (min-width:1200px){h3{font-size:1.75rem}}h4{font-size:calc(1.275rem + .3vw)}@media (min-width:1200px){h4{font-size:1.5rem}}h5{font-size:1.25rem}h6{font-size:1rem}p{margin-top:0;margin-bottom:1rem}abbr[data-bs-original-title],abbr[title]{-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}ol,ul{padding-left:2rem}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:.875em}mark{padding:.2em;background-color:#fcf8e3}sub,sup{position:relative;font-size:.75em;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#0d6efd;text-decoration:underline}a:hover{color:#0a58ca}a:not([href]):not([class]),a:not([href]):not([class]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em;direction:ltr;unicode-bidi:bidi-override}pre{display:block;margin-top:0;margin-bottom:1rem;overflow:auto;font-size:.875em}pre code{font-size:inherit;color:inherit;word-break:normal}code{font-size:.875em;color:#d63384;word-wrap:break-word}a>code{color:inherit}kbd{padding:.2rem .4rem;font-size:.875em;color:#fff;background-color:#212529;border-radius:.2rem}kbd kbd{padding:0;font-size:1em;font-weight:700}figure{margin:0 0 1rem}img,svg{vertical-align:middle}table{caption-side:bottom;border-collapse:collapse}caption{padding-top:.5rem;padding-bottom:.5rem;color:#6c757d;text-align:left}th{text-align:inherit;text-align:-webkit-match-parent}tbody,td,tfoot,th,thead,tr{border-color:inherit;border-style:solid;border-width:0}label{display:inline-block}button{border-radius:0}button:focus:not(:focus-visible){outline:0}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}select:disabled{opacity:1}[list]::-webkit-calendar-picker-indicator{display:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}::-moz-focus-inner{padding:0;border-style:none}textarea{resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{float:left;width:100%;padding:0;margin-bottom:.5rem;font-size:calc(1.275rem + .3vw);line-height:inherit}@media (min-width:1200px){legend{font-size:1.5rem}}legend+*{clear:left}::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-fields-wrapper,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-minute,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-text,::-webkit-datetime-edit-year-field{padding:0}::-webkit-inner-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:textfield}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-color-swatch-wrapper{padding:0}::file-selector-button{font:inherit}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}iframe{border:0}summary{display:list-item;cursor:pointer}progress{vertical-align:baseline}[hidden]{display:none!important}
/*# sourceMappingURL=bootstrap-reboot.min.css.map */

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,424 @@
/*!
* Bootstrap Reboot v5.1.0 (https://getbootstrap.com/)
* Copyright 2011-2021 The Bootstrap Authors
* Copyright 2011-2021 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
*/
*,
*::before,
*::after {
box-sizing: border-box;
}
@media (prefers-reduced-motion: no-preference) {
:root {
scroll-behavior: smooth;
}
}
body {
margin: 0;
font-family: var(--bs-body-font-family);
font-size: var(--bs-body-font-size);
font-weight: var(--bs-body-font-weight);
line-height: var(--bs-body-line-height);
color: var(--bs-body-color);
text-align: var(--bs-body-text-align);
background-color: var(--bs-body-bg);
-webkit-text-size-adjust: 100%;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
hr {
margin: 1rem 0;
color: inherit;
background-color: currentColor;
border: 0;
opacity: 0.25;
}
hr:not([size]) {
height: 1px;
}
h6, h5, h4, h3, h2, h1 {
margin-top: 0;
margin-bottom: 0.5rem;
font-weight: 500;
line-height: 1.2;
}
h1 {
font-size: calc(1.375rem + 1.5vw);
}
@media (min-width: 1200px) {
h1 {
font-size: 2.5rem;
}
}
h2 {
font-size: calc(1.325rem + 0.9vw);
}
@media (min-width: 1200px) {
h2 {
font-size: 2rem;
}
}
h3 {
font-size: calc(1.3rem + 0.6vw);
}
@media (min-width: 1200px) {
h3 {
font-size: 1.75rem;
}
}
h4 {
font-size: calc(1.275rem + 0.3vw);
}
@media (min-width: 1200px) {
h4 {
font-size: 1.5rem;
}
}
h5 {
font-size: 1.25rem;
}
h6 {
font-size: 1rem;
}
p {
margin-top: 0;
margin-bottom: 1rem;
}
abbr[title],
abbr[data-bs-original-title] {
-webkit-text-decoration: underline dotted;
text-decoration: underline dotted;
cursor: help;
-webkit-text-decoration-skip-ink: none;
text-decoration-skip-ink: none;
}
address {
margin-bottom: 1rem;
font-style: normal;
line-height: inherit;
}
ol,
ul {
padding-right: 2rem;
}
ol,
ul,
dl {
margin-top: 0;
margin-bottom: 1rem;
}
ol ol,
ul ul,
ol ul,
ul ol {
margin-bottom: 0;
}
dt {
font-weight: 700;
}
dd {
margin-bottom: 0.5rem;
margin-right: 0;
}
blockquote {
margin: 0 0 1rem;
}
b,
strong {
font-weight: bolder;
}
small {
font-size: 0.875em;
}
mark {
padding: 0.2em;
background-color: #fcf8e3;
}
sub,
sup {
position: relative;
font-size: 0.75em;
line-height: 0;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
a {
color: #0d6efd;
text-decoration: underline;
}
a:hover {
color: #0a58ca;
}
a:not([href]):not([class]), a:not([href]):not([class]):hover {
color: inherit;
text-decoration: none;
}
pre,
code,
kbd,
samp {
font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
font-size: 1em;
direction: ltr ;
unicode-bidi: bidi-override;
}
pre {
display: block;
margin-top: 0;
margin-bottom: 1rem;
overflow: auto;
font-size: 0.875em;
}
pre code {
font-size: inherit;
color: inherit;
word-break: normal;
}
code {
font-size: 0.875em;
color: #d63384;
word-wrap: break-word;
}
a > code {
color: inherit;
}
kbd {
padding: 0.2rem 0.4rem;
font-size: 0.875em;
color: #fff;
background-color: #212529;
border-radius: 0.2rem;
}
kbd kbd {
padding: 0;
font-size: 1em;
font-weight: 700;
}
figure {
margin: 0 0 1rem;
}
img,
svg {
vertical-align: middle;
}
table {
caption-side: bottom;
border-collapse: collapse;
}
caption {
padding-top: 0.5rem;
padding-bottom: 0.5rem;
color: #6c757d;
text-align: right;
}
th {
text-align: inherit;
text-align: -webkit-match-parent;
}
thead,
tbody,
tfoot,
tr,
td,
th {
border-color: inherit;
border-style: solid;
border-width: 0;
}
label {
display: inline-block;
}
button {
border-radius: 0;
}
button:focus:not(:focus-visible) {
outline: 0;
}
input,
button,
select,
optgroup,
textarea {
margin: 0;
font-family: inherit;
font-size: inherit;
line-height: inherit;
}
button,
select {
text-transform: none;
}
[role=button] {
cursor: pointer;
}
select {
word-wrap: normal;
}
select:disabled {
opacity: 1;
}
[list]::-webkit-calendar-picker-indicator {
display: none;
}
button,
[type=button],
[type=reset],
[type=submit] {
-webkit-appearance: button;
}
button:not(:disabled),
[type=button]:not(:disabled),
[type=reset]:not(:disabled),
[type=submit]:not(:disabled) {
cursor: pointer;
}
::-moz-focus-inner {
padding: 0;
border-style: none;
}
textarea {
resize: vertical;
}
fieldset {
min-width: 0;
padding: 0;
margin: 0;
border: 0;
}
legend {
float: right;
width: 100%;
padding: 0;
margin-bottom: 0.5rem;
font-size: calc(1.275rem + 0.3vw);
line-height: inherit;
}
@media (min-width: 1200px) {
legend {
font-size: 1.5rem;
}
}
legend + * {
clear: right;
}
::-webkit-datetime-edit-fields-wrapper,
::-webkit-datetime-edit-text,
::-webkit-datetime-edit-minute,
::-webkit-datetime-edit-hour-field,
::-webkit-datetime-edit-day-field,
::-webkit-datetime-edit-month-field,
::-webkit-datetime-edit-year-field {
padding: 0;
}
::-webkit-inner-spin-button {
height: auto;
}
[type=search] {
outline-offset: -2px;
-webkit-appearance: textfield;
}
[type="tel"],
[type="url"],
[type="email"],
[type="number"] {
direction: ltr;
}
::-webkit-search-decoration {
-webkit-appearance: none;
}
::-webkit-color-swatch-wrapper {
padding: 0;
}
::file-selector-button {
font: inherit;
}
::-webkit-file-upload-button {
font: inherit;
-webkit-appearance: button;
}
output {
display: inline-block;
}
iframe {
border: 0;
}
summary {
display: list-item;
cursor: pointer;
}
progress {
vertical-align: baseline;
}
[hidden] {
display: none !important;
}
/*# sourceMappingURL=bootstrap-reboot.rtl.css.map */

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,8 @@
/*!
* Bootstrap Reboot v5.1.0 (https://getbootstrap.com/)
* Copyright 2011-2021 The Bootstrap Authors
* Copyright 2011-2021 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
*/*,::after,::before{box-sizing:border-box}@media (prefers-reduced-motion:no-preference){:root{scroll-behavior:smooth}}body{margin:0;font-family:var(--bs-body-font-family);font-size:var(--bs-body-font-size);font-weight:var(--bs-body-font-weight);line-height:var(--bs-body-line-height);color:var(--bs-body-color);text-align:var(--bs-body-text-align);background-color:var(--bs-body-bg);-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}hr{margin:1rem 0;color:inherit;background-color:currentColor;border:0;opacity:.25}hr:not([size]){height:1px}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem;font-weight:500;line-height:1.2}h1{font-size:calc(1.375rem + 1.5vw)}@media (min-width:1200px){h1{font-size:2.5rem}}h2{font-size:calc(1.325rem + .9vw)}@media (min-width:1200px){h2{font-size:2rem}}h3{font-size:calc(1.3rem + .6vw)}@media (min-width:1200px){h3{font-size:1.75rem}}h4{font-size:calc(1.275rem + .3vw)}@media (min-width:1200px){h4{font-size:1.5rem}}h5{font-size:1.25rem}h6{font-size:1rem}p{margin-top:0;margin-bottom:1rem}abbr[data-bs-original-title],abbr[title]{-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}ol,ul{padding-right:2rem}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-right:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:.875em}mark{padding:.2em;background-color:#fcf8e3}sub,sup{position:relative;font-size:.75em;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#0d6efd;text-decoration:underline}a:hover{color:#0a58ca}a:not([href]):not([class]),a:not([href]):not([class]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em;direction:ltr;unicode-bidi:bidi-override}pre{display:block;margin-top:0;margin-bottom:1rem;overflow:auto;font-size:.875em}pre code{font-size:inherit;color:inherit;word-break:normal}code{font-size:.875em;color:#d63384;word-wrap:break-word}a>code{color:inherit}kbd{padding:.2rem .4rem;font-size:.875em;color:#fff;background-color:#212529;border-radius:.2rem}kbd kbd{padding:0;font-size:1em;font-weight:700}figure{margin:0 0 1rem}img,svg{vertical-align:middle}table{caption-side:bottom;border-collapse:collapse}caption{padding-top:.5rem;padding-bottom:.5rem;color:#6c757d;text-align:right}th{text-align:inherit;text-align:-webkit-match-parent}tbody,td,tfoot,th,thead,tr{border-color:inherit;border-style:solid;border-width:0}label{display:inline-block}button{border-radius:0}button:focus:not(:focus-visible){outline:0}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}select:disabled{opacity:1}[list]::-webkit-calendar-picker-indicator{display:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}::-moz-focus-inner{padding:0;border-style:none}textarea{resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{float:right;width:100%;padding:0;margin-bottom:.5rem;font-size:calc(1.275rem + .3vw);line-height:inherit}@media (min-width:1200px){legend{font-size:1.5rem}}legend+*{clear:right}::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-fields-wrapper,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-minute,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-text,::-webkit-datetime-edit-year-field{padding:0}::-webkit-inner-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:textfield}[type=email],[type=number],[type=tel],[type=url]{direction:ltr}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-color-swatch-wrapper{padding:0}::file-selector-button{font:inherit}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}iframe{border:0}summary{display:list-item;cursor:pointer}progress{vertical-align:baseline}[hidden]{display:none!important}
/*# sourceMappingURL=bootstrap-reboot.rtl.min.css.map */

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,12 @@
Copyright (c) .NET Foundation. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
these files except in compliance with the License. You may obtain a copy of the
License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied. See the License for the
specific language governing permissions and limitations under the License.

View File

@@ -0,0 +1,432 @@
// Unobtrusive validation support library for jQuery and jQuery Validate
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
// @version v3.2.11
/*jslint white: true, browser: true, onevar: true, undef: true, nomen: true, eqeqeq: true, plusplus: true, bitwise: true, regexp: true, newcap: true, immed: true, strict: false */
/*global document: false, jQuery: false */
(function (factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define("jquery.validate.unobtrusive", ['jquery-validation'], factory);
} else if (typeof module === 'object' && module.exports) {
// CommonJS-like environments that support module.exports
module.exports = factory(require('jquery-validation'));
} else {
// Browser global
jQuery.validator.unobtrusive = factory(jQuery);
}
}(function ($) {
var $jQval = $.validator,
adapters,
data_validation = "unobtrusiveValidation";
function setValidationValues(options, ruleName, value) {
options.rules[ruleName] = value;
if (options.message) {
options.messages[ruleName] = options.message;
}
}
function splitAndTrim(value) {
return value.replace(/^\s+|\s+$/g, "").split(/\s*,\s*/g);
}
function escapeAttributeValue(value) {
// As mentioned on http://api.jquery.com/category/selectors/
return value.replace(/([!"#$%&'()*+,./:;<=>?@\[\\\]^`{|}~])/g, "\\$1");
}
function getModelPrefix(fieldName) {
return fieldName.substr(0, fieldName.lastIndexOf(".") + 1);
}
function appendModelPrefix(value, prefix) {
if (value.indexOf("*.") === 0) {
value = value.replace("*.", prefix);
}
return value;
}
function onError(error, inputElement) { // 'this' is the form element
var container = $(this).find("[data-valmsg-for='" + escapeAttributeValue(inputElement[0].name) + "']"),
replaceAttrValue = container.attr("data-valmsg-replace"),
replace = replaceAttrValue ? $.parseJSON(replaceAttrValue) !== false : null;
container.removeClass("field-validation-valid").addClass("field-validation-error");
error.data("unobtrusiveContainer", container);
if (replace) {
container.empty();
error.removeClass("input-validation-error").appendTo(container);
}
else {
error.hide();
}
}
function onErrors(event, validator) { // 'this' is the form element
var container = $(this).find("[data-valmsg-summary=true]"),
list = container.find("ul");
if (list && list.length && validator.errorList.length) {
list.empty();
container.addClass("validation-summary-errors").removeClass("validation-summary-valid");
$.each(validator.errorList, function () {
$("<li />").html(this.message).appendTo(list);
});
}
}
function onSuccess(error) { // 'this' is the form element
var container = error.data("unobtrusiveContainer");
if (container) {
var replaceAttrValue = container.attr("data-valmsg-replace"),
replace = replaceAttrValue ? $.parseJSON(replaceAttrValue) : null;
container.addClass("field-validation-valid").removeClass("field-validation-error");
error.removeData("unobtrusiveContainer");
if (replace) {
container.empty();
}
}
}
function onReset(event) { // 'this' is the form element
var $form = $(this),
key = '__jquery_unobtrusive_validation_form_reset';
if ($form.data(key)) {
return;
}
// Set a flag that indicates we're currently resetting the form.
$form.data(key, true);
try {
$form.data("validator").resetForm();
} finally {
$form.removeData(key);
}
$form.find(".validation-summary-errors")
.addClass("validation-summary-valid")
.removeClass("validation-summary-errors");
$form.find(".field-validation-error")
.addClass("field-validation-valid")
.removeClass("field-validation-error")
.removeData("unobtrusiveContainer")
.find(">*") // If we were using valmsg-replace, get the underlying error
.removeData("unobtrusiveContainer");
}
function validationInfo(form) {
var $form = $(form),
result = $form.data(data_validation),
onResetProxy = $.proxy(onReset, form),
defaultOptions = $jQval.unobtrusive.options || {},
execInContext = function (name, args) {
var func = defaultOptions[name];
func && $.isFunction(func) && func.apply(form, args);
};
if (!result) {
result = {
options: { // options structure passed to jQuery Validate's validate() method
errorClass: defaultOptions.errorClass || "input-validation-error",
errorElement: defaultOptions.errorElement || "span",
errorPlacement: function () {
onError.apply(form, arguments);
execInContext("errorPlacement", arguments);
},
invalidHandler: function () {
onErrors.apply(form, arguments);
execInContext("invalidHandler", arguments);
},
messages: {},
rules: {},
success: function () {
onSuccess.apply(form, arguments);
execInContext("success", arguments);
}
},
attachValidation: function () {
$form
.off("reset." + data_validation, onResetProxy)
.on("reset." + data_validation, onResetProxy)
.validate(this.options);
},
validate: function () { // a validation function that is called by unobtrusive Ajax
$form.validate();
return $form.valid();
}
};
$form.data(data_validation, result);
}
return result;
}
$jQval.unobtrusive = {
adapters: [],
parseElement: function (element, skipAttach) {
/// <summary>
/// Parses a single HTML element for unobtrusive validation attributes.
/// </summary>
/// <param name="element" domElement="true">The HTML element to be parsed.</param>
/// <param name="skipAttach" type="Boolean">[Optional] true to skip attaching the
/// validation to the form. If parsing just this single element, you should specify true.
/// If parsing several elements, you should specify false, and manually attach the validation
/// to the form when you are finished. The default is false.</param>
var $element = $(element),
form = $element.parents("form")[0],
valInfo, rules, messages;
if (!form) { // Cannot do client-side validation without a form
return;
}
valInfo = validationInfo(form);
valInfo.options.rules[element.name] = rules = {};
valInfo.options.messages[element.name] = messages = {};
$.each(this.adapters, function () {
var prefix = "data-val-" + this.name,
message = $element.attr(prefix),
paramValues = {};
if (message !== undefined) { // Compare against undefined, because an empty message is legal (and falsy)
prefix += "-";
$.each(this.params, function () {
paramValues[this] = $element.attr(prefix + this);
});
this.adapt({
element: element,
form: form,
message: message,
params: paramValues,
rules: rules,
messages: messages
});
}
});
$.extend(rules, { "__dummy__": true });
if (!skipAttach) {
valInfo.attachValidation();
}
},
parse: function (selector) {
/// <summary>
/// Parses all the HTML elements in the specified selector. It looks for input elements decorated
/// with the [data-val=true] attribute value and enables validation according to the data-val-*
/// attribute values.
/// </summary>
/// <param name="selector" type="String">Any valid jQuery selector.</param>
// $forms includes all forms in selector's DOM hierarchy (parent, children and self) that have at least one
// element with data-val=true
var $selector = $(selector),
$forms = $selector.parents()
.addBack()
.filter("form")
.add($selector.find("form"))
.has("[data-val=true]");
$selector.find("[data-val=true]").each(function () {
$jQval.unobtrusive.parseElement(this, true);
});
$forms.each(function () {
var info = validationInfo(this);
if (info) {
info.attachValidation();
}
});
}
};
adapters = $jQval.unobtrusive.adapters;
adapters.add = function (adapterName, params, fn) {
/// <summary>Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation.</summary>
/// <param name="adapterName" type="String">The name of the adapter to be added. This matches the name used
/// in the data-val-nnnn HTML attribute (where nnnn is the adapter name).</param>
/// <param name="params" type="Array" optional="true">[Optional] An array of parameter names (strings) that will
/// be extracted from the data-val-nnnn-mmmm HTML attributes (where nnnn is the adapter name, and
/// mmmm is the parameter name).</param>
/// <param name="fn" type="Function">The function to call, which adapts the values from the HTML
/// attributes into jQuery Validate rules and/or messages.</param>
/// <returns type="jQuery.validator.unobtrusive.adapters" />
if (!fn) { // Called with no params, just a function
fn = params;
params = [];
}
this.push({ name: adapterName, params: params, adapt: fn });
return this;
};
adapters.addBool = function (adapterName, ruleName) {
/// <summary>Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation, where
/// the jQuery Validate validation rule has no parameter values.</summary>
/// <param name="adapterName" type="String">The name of the adapter to be added. This matches the name used
/// in the data-val-nnnn HTML attribute (where nnnn is the adapter name).</param>
/// <param name="ruleName" type="String" optional="true">[Optional] The name of the jQuery Validate rule. If not provided, the value
/// of adapterName will be used instead.</param>
/// <returns type="jQuery.validator.unobtrusive.adapters" />
return this.add(adapterName, function (options) {
setValidationValues(options, ruleName || adapterName, true);
});
};
adapters.addMinMax = function (adapterName, minRuleName, maxRuleName, minMaxRuleName, minAttribute, maxAttribute) {
/// <summary>Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation, where
/// the jQuery Validate validation has three potential rules (one for min-only, one for max-only, and
/// one for min-and-max). The HTML parameters are expected to be named -min and -max.</summary>
/// <param name="adapterName" type="String">The name of the adapter to be added. This matches the name used
/// in the data-val-nnnn HTML attribute (where nnnn is the adapter name).</param>
/// <param name="minRuleName" type="String">The name of the jQuery Validate rule to be used when you only
/// have a minimum value.</param>
/// <param name="maxRuleName" type="String">The name of the jQuery Validate rule to be used when you only
/// have a maximum value.</param>
/// <param name="minMaxRuleName" type="String">The name of the jQuery Validate rule to be used when you
/// have both a minimum and maximum value.</param>
/// <param name="minAttribute" type="String" optional="true">[Optional] The name of the HTML attribute that
/// contains the minimum value. The default is "min".</param>
/// <param name="maxAttribute" type="String" optional="true">[Optional] The name of the HTML attribute that
/// contains the maximum value. The default is "max".</param>
/// <returns type="jQuery.validator.unobtrusive.adapters" />
return this.add(adapterName, [minAttribute || "min", maxAttribute || "max"], function (options) {
var min = options.params.min,
max = options.params.max;
if (min && max) {
setValidationValues(options, minMaxRuleName, [min, max]);
}
else if (min) {
setValidationValues(options, minRuleName, min);
}
else if (max) {
setValidationValues(options, maxRuleName, max);
}
});
};
adapters.addSingleVal = function (adapterName, attribute, ruleName) {
/// <summary>Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation, where
/// the jQuery Validate validation rule has a single value.</summary>
/// <param name="adapterName" type="String">The name of the adapter to be added. This matches the name used
/// in the data-val-nnnn HTML attribute(where nnnn is the adapter name).</param>
/// <param name="attribute" type="String">[Optional] The name of the HTML attribute that contains the value.
/// The default is "val".</param>
/// <param name="ruleName" type="String" optional="true">[Optional] The name of the jQuery Validate rule. If not provided, the value
/// of adapterName will be used instead.</param>
/// <returns type="jQuery.validator.unobtrusive.adapters" />
return this.add(adapterName, [attribute || "val"], function (options) {
setValidationValues(options, ruleName || adapterName, options.params[attribute]);
});
};
$jQval.addMethod("__dummy__", function (value, element, params) {
return true;
});
$jQval.addMethod("regex", function (value, element, params) {
var match;
if (this.optional(element)) {
return true;
}
match = new RegExp(params).exec(value);
return (match && (match.index === 0) && (match[0].length === value.length));
});
$jQval.addMethod("nonalphamin", function (value, element, nonalphamin) {
var match;
if (nonalphamin) {
match = value.match(/\W/g);
match = match && match.length >= nonalphamin;
}
return match;
});
if ($jQval.methods.extension) {
adapters.addSingleVal("accept", "mimtype");
adapters.addSingleVal("extension", "extension");
} else {
// for backward compatibility, when the 'extension' validation method does not exist, such as with versions
// of JQuery Validation plugin prior to 1.10, we should use the 'accept' method for
// validating the extension, and ignore mime-type validations as they are not supported.
adapters.addSingleVal("extension", "extension", "accept");
}
adapters.addSingleVal("regex", "pattern");
adapters.addBool("creditcard").addBool("date").addBool("digits").addBool("email").addBool("number").addBool("url");
adapters.addMinMax("length", "minlength", "maxlength", "rangelength").addMinMax("range", "min", "max", "range");
adapters.addMinMax("minlength", "minlength").addMinMax("maxlength", "minlength", "maxlength");
adapters.add("equalto", ["other"], function (options) {
var prefix = getModelPrefix(options.element.name),
other = options.params.other,
fullOtherName = appendModelPrefix(other, prefix),
element = $(options.form).find(":input").filter("[name='" + escapeAttributeValue(fullOtherName) + "']")[0];
setValidationValues(options, "equalTo", element);
});
adapters.add("required", function (options) {
// jQuery Validate equates "required" with "mandatory" for checkbox elements
if (options.element.tagName.toUpperCase() !== "INPUT" || options.element.type.toUpperCase() !== "CHECKBOX") {
setValidationValues(options, "required", true);
}
});
adapters.add("remote", ["url", "type", "additionalfields"], function (options) {
var value = {
url: options.params.url,
type: options.params.type || "GET",
data: {}
},
prefix = getModelPrefix(options.element.name);
$.each(splitAndTrim(options.params.additionalfields || options.element.name), function (i, fieldName) {
var paramName = appendModelPrefix(fieldName, prefix);
value.data[paramName] = function () {
var field = $(options.form).find(":input").filter("[name='" + escapeAttributeValue(paramName) + "']");
// For checkboxes and radio buttons, only pick up values from checked fields.
if (field.is(":checkbox")) {
return field.filter(":checked").val() || field.filter(":hidden").val() || '';
}
else if (field.is(":radio")) {
return field.filter(":checked").val() || '';
}
return field.val();
};
});
setValidationValues(options, "remote", value);
});
adapters.add("password", ["min", "nonalphamin", "regex"], function (options) {
if (options.params.min) {
setValidationValues(options, "minlength", options.params.min);
}
if (options.params.nonalphamin) {
setValidationValues(options, "nonalphamin", options.params.nonalphamin);
}
if (options.params.regex) {
setValidationValues(options, "regex", options.params.regex);
}
});
adapters.add("fileextensions", ["extensions"], function (options) {
setValidationValues(options, "extension", options.params.extensions);
});
$(function () {
$jQval.unobtrusive.parse(document);
});
return $jQval.unobtrusive;
}));

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,22 @@
The MIT License (MIT)
=====================
Copyright Jörn Zaefferer
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show More