This commit is contained in:
Игорь Гордеев 2024-05-01 10:50:16 +04:00
parent e2c2b1c984
commit 85aef96efb
55 changed files with 1994 additions and 567 deletions

View File

@ -0,0 +1,92 @@
namespace SushiBarView
{
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();
buttonDelete = new Button();
((System.ComponentModel.ISupportInitialize)dataGridView).BeginInit();
SuspendLayout();
//
// dataGridView
//
dataGridView.BackgroundColor = Color.AntiqueWhite;
dataGridView.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize;
dataGridView.Dock = DockStyle.Left;
dataGridView.Location = new Point(0, 0);
dataGridView.Name = "dataGridView";
dataGridView.RowHeadersVisible = false;
dataGridView.RowHeadersWidth = 51;
dataGridView.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
dataGridView.Size = new Size(615, 450);
dataGridView.TabIndex = 0;
//
// buttonRefresh
//
buttonRefresh.Location = new Point(669, 53);
buttonRefresh.Name = "buttonRefresh";
buttonRefresh.Size = new Size(144, 54);
buttonRefresh.TabIndex = 1;
buttonRefresh.Text = "Обновить";
buttonRefresh.UseVisualStyleBackColor = true;
buttonRefresh.Click += buttonRefresh_Click;
//
// buttonDelete
//
buttonDelete.Location = new Point(669, 160);
buttonDelete.Name = "buttonDelete";
buttonDelete.Size = new Size(144, 54);
buttonDelete.TabIndex = 2;
buttonDelete.Text = "Удалить";
buttonDelete.UseVisualStyleBackColor = true;
buttonDelete.Click += buttonDelete_Click;
//
// FormClients
//
AutoScaleDimensions = new SizeF(8F, 20F);
AutoScaleMode = AutoScaleMode.Font;
BackColor = Color.BurlyWood;
ClientSize = new Size(862, 450);
Controls.Add(buttonDelete);
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 buttonDelete;
}
}

View File

@ -0,0 +1,88 @@
using Microsoft.Extensions.Logging;
using SushiBarContracts.BindingModel;
using SushiBarContracts.BusinessLogicsContracts;
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 SushiBarView
{
public partial class FormClients : Form
{
private readonly ILogger _logger;
private readonly IClientLogic _clientLogic;
public FormClients(ILogger<FormClients> logger, IClientLogic logic)
{
_logger = logger;
_clientLogic = logic;
InitializeComponent();
}
private void FormClients_Load(object sender, EventArgs e)
{
LoadData();
}
private void LoadData()
{
try
{
var list = _clientLogic.ReadList(null);
if (list != null)
{
dataGridView.DataSource = list;
dataGridView.Columns["Id"].Visible = false;
dataGridView.Columns["ClientFIO"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
_logger.LogInformation("Клиенты успешно загружены");
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message, "Ошибка загрузки клиентов");
MessageBox.Show(ex.Message, "Ошибка загрузки клиентов");
}
}
private void buttonDelete_Click(object sender, EventArgs e)
{
if (dataGridView.SelectedRows.Count == 1)
{
if (MessageBox.Show("Вы серьезно хотите удалить клиента? :_) та за что...", "Вопрос",
MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
{
try
{
int id = Convert.ToInt32(dataGridView.SelectedRows[0].Cells["Id"].Value);
_logger.LogInformation($"Удален клиент под номером {id}");
if (!_clientLogic.Delete(new ClientBindingModel
{
Id = id
}))
{
throw new Exception("Ошибка при удалении. Дополнительная информация в логах.");
}
LoadData();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Не удалось удалить клиента");
_logger.LogError(ex.Message, "Не удалось удалить клиента");
}
}
}
}
private void buttonRefresh_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

@ -42,13 +42,14 @@
buttonSetToWork = new Button(); buttonSetToWork = new Button();
buttonCreateOrder = new Button(); buttonCreateOrder = new Button();
dataGridView = new DataGridView(); dataGridView = new DataGridView();
клиентыToolStripMenuItem = new ToolStripMenuItem();
menuStrip.SuspendLayout(); menuStrip.SuspendLayout();
((System.ComponentModel.ISupportInitialize)dataGridView).BeginInit(); ((System.ComponentModel.ISupportInitialize)dataGridView).BeginInit();
SuspendLayout(); SuspendLayout();
// //
// menuStrip // menuStrip
// //
menuStrip.Items.AddRange(new ToolStripItem[] { справочникиToolStripMenuItem, отчетыToolStripMenuItem }); menuStrip.Items.AddRange(new ToolStripItem[] { справочникиToolStripMenuItem, отчетыToolStripMenuItem, клиентыToolStripMenuItem });
menuStrip.Location = new Point(0, 0); menuStrip.Location = new Point(0, 0);
menuStrip.Name = "menuStrip"; menuStrip.Name = "menuStrip";
menuStrip.Size = new Size(975, 24); menuStrip.Size = new Size(975, 24);
@ -171,6 +172,13 @@
dataGridView.Size = new Size(755, 426); dataGridView.Size = new Size(755, 426);
dataGridView.TabIndex = 7; dataGridView.TabIndex = 7;
// //
// клиентыToolStripMenuItem
//
клиентыToolStripMenuItem.Name = "клиентыToolStripMenuItem";
клиентыToolStripMenuItem.Size = new Size(67, 20);
клиентыToolStripMenuItem.Text = "Клиенты";
клиентыToolStripMenuItem.Click += клиентыToolStripMenuItem_Click;
//
// FormMain // FormMain
// //
AutoScaleDimensions = new SizeF(7F, 15F); AutoScaleDimensions = new SizeF(7F, 15F);
@ -210,5 +218,6 @@
private ToolStripMenuItem списокСушиToolStripMenuItem; private ToolStripMenuItem списокСушиToolStripMenuItem;
private ToolStripMenuItem сушиСИнгредиентамиToolStripMenuItem; private ToolStripMenuItem сушиСИнгредиентамиToolStripMenuItem;
private ToolStripMenuItem списокЗаказовToolStripMenuItem; private ToolStripMenuItem списокЗаказовToolStripMenuItem;
private ToolStripMenuItem клиентыToolStripMenuItem;
} }
} }

View File

@ -172,5 +172,14 @@ namespace SushiBarView
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();
}
}
} }
} }

View File

@ -0,0 +1,116 @@
using Microsoft.Extensions.Logging;
using SushiBarContracts.BindingModel;
using SushiBarContracts.BusinessLogicsContracts;
using SushiBarContracts.SearchModel;
using SushiBarContracts.StoragesContracts;
using SushiBarContracts.ViewModels;
namespace SushiBarBusinessLogic
{
public class ClientLogic : IClientLogic
{
private readonly ILogger _logger;
private readonly IClientStorage _clientStorage;
public ClientLogic(ILogger<ClientLogic> logger, IClientStorage clientStorage)
{
_logger = logger;
_clientStorage = clientStorage;
}
public bool Create(ClientBindingModel model)
{
CheckUser(model);
if (_clientStorage.Insert(model) == null)
{
_logger.LogWarning("Insert operation failed");
return false;
}
return true;
}
public bool Update(ClientBindingModel model)
{
CheckUser(model);
if (_clientStorage.Update(model) == null)
{
_logger.LogWarning("Update operation failed");
return false;
}
return true;
}
public bool Delete(ClientBindingModel model)
{
CheckUser(model, false);
_logger.LogInformation("Delete. Id:{Id}", model.Id);
if (_clientStorage.Delete(model) == null)
{
_logger.LogWarning("Delete operation failed");
return false;
}
return true;
}
public ClientViewModel? ReadElement(ClientSearchModel model)
{
if (model == null)
{
throw new ArgumentNullException(nameof(model));
}
_logger.LogInformation("ReadElement. UserName:{UserName}.Id:{Id}", model.Email, model.Id);
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 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 void CheckUser(ClientBindingModel model, bool withParams = true)
{
if (model == null)
{
throw new ArgumentNullException(nameof(model));
}
if (!withParams)
{
return;
}
if (string.IsNullOrEmpty(model.ClientFIO))
{
throw new ArgumentNullException("Invalid fullname of user", nameof(model.ClientFIO));
}
if (string.IsNullOrEmpty(model.Email))
{
throw new ArgumentNullException("Invalid email of user", nameof(model.Email));
}
if (string.IsNullOrEmpty(model.Password))
{
throw new ArgumentNullException("Invalid password of user", 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("User with such email already exists.");
}
}
}
}

View File

@ -1,14 +1,13 @@
using SushiBarContracts.ViewModels; using Newtonsoft.Json;
using Newtonsoft.Json; using SushiBarContracts.ViewModels;
using System.Net.Http.Headers; using System.Net.Http.Headers;
using System.Text; using System.Text;
namespace SushiBarClientApp namespace SushiBarClientApp
{ {
public class APIClient public static class APIClient
{ {
private static readonly HttpClient _client = new(); private static readonly HttpClient _client = new();
public static ClientViewModel? Client { get; set; } = null; public static ClientViewModel? Client { get; set; } = null;
public static void Connect(IConfiguration configuration) public static void Connect(IConfiguration configuration)
@ -17,7 +16,6 @@ namespace SushiBarClientApp
_client.DefaultRequestHeaders.Accept.Clear(); _client.DefaultRequestHeaders.Accept.Clear();
_client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); _client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
} }
public static T? GetRequest<T>(string requestUrl) public static T? GetRequest<T>(string requestUrl)
{ {
var response = _client.GetAsync(requestUrl); var response = _client.GetAsync(requestUrl);
@ -31,14 +29,11 @@ namespace SushiBarClientApp
throw new Exception(result); throw new Exception(result);
} }
} }
public static void PostRequest<T>(string requestUrl, T model) public static void PostRequest<T>(string requestUrl, T model)
{ {
var json = JsonConvert.SerializeObject(model); var json = JsonConvert.SerializeObject(model);
var data = new StringContent(json, Encoding.UTF8, "application/json"); var data = new StringContent(json, Encoding.UTF8, "application/json");
var response = _client.PostAsync(requestUrl, data); var response = _client.PostAsync(requestUrl, data);
var result = response.Result.Content.ReadAsStringAsync().Result; var result = response.Result.Content.ReadAsStringAsync().Result;
if (!response.Result.IsSuccessStatusCode) if (!response.Result.IsSuccessStatusCode)
{ {

View File

@ -1,6 +1,6 @@
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using SushiBarClientApp.Models; using SushiBarClientApp.Models;
using SushiBarContracts.BindingModels; using SushiBarContracts.BindingModel;
using SushiBarContracts.ViewModels; using SushiBarContracts.ViewModels;
using System.Diagnostics; using System.Diagnostics;
@ -9,21 +9,19 @@ namespace SushiBarClientApp.Controllers
public class HomeController : Controller public class HomeController : Controller
{ {
private readonly ILogger<HomeController> _logger; private readonly ILogger<HomeController> _logger;
public HomeController(ILogger<HomeController> logger) public HomeController(ILogger<HomeController> logger)
{ {
_logger = logger; _logger = logger;
} }
public IActionResult Index() public IActionResult Index()
{ {
if (APIClient.Client == null) if (APIClient.Client == null)
{ {
return Redirect("~/Home/Enter"); return Redirect("~/Home/Enter");
} }
return View(APIClient.GetRequest<List<OrderViewModel>>($"api/main/getorders?clientId={APIClient.Client.Id}")); return
View(APIClient.GetRequest<List<OrderViewModel>>($"api/main/getorders?clientId={APIClient.Client.Id}"));
} }
[HttpGet] [HttpGet]
public IActionResult Privacy() public IActionResult Privacy()
{ {
@ -33,17 +31,17 @@ namespace SushiBarClientApp.Controllers
} }
return View(APIClient.Client); return View(APIClient.Client);
} }
[HttpPost] [HttpPost]
public void Privacy(string login, string password, string fio) public void Privacy(string login, string password, string fio)
{ {
if (APIClient.Client == null) if (APIClient.Client == null)
{ {
throw new Exception("Вы как сюда попали? Сюда вход только авторизованным"); throw new Exception("Âû êàê ñóäà ïîïàëè? Ñóäà âõîä òîëüêî àâòîðèçîâàííûì");
} }
if (string.IsNullOrEmpty(login) || string.IsNullOrEmpty(password) || string.IsNullOrEmpty(fio)) if (string.IsNullOrEmpty(login) ||
string.IsNullOrEmpty(password) || string.IsNullOrEmpty(fio))
{ {
throw new Exception("Введите логин, пароль и ФИО"); throw new Exception("Ââåäèòå ëîãèí, ïàðîëü è ÔÈÎ");
} }
APIClient.PostRequest("api/client/updatedata", new ClientBindingModel APIClient.PostRequest("api/client/updatedata", new ClientBindingModel
{ {
@ -52,52 +50,49 @@ namespace SushiBarClientApp.Controllers
Email = login, Email = login,
Password = password Password = password
}); });
APIClient.Client.ClientFIO = fio; APIClient.Client.ClientFIO = fio;
APIClient.Client.Email = login; APIClient.Client.Email = login;
APIClient.Client.Password = password; APIClient.Client.Password = password;
Response.Redirect("Index"); Response.Redirect("Index");
} }
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public IActionResult Error() public IActionResult Error()
{ {
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier }); return View(new ErrorViewModel
{
RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier
});
} }
[HttpGet] [HttpGet]
public IActionResult Enter() public IActionResult Enter()
{ {
return View(); return View();
} }
[HttpPost] [HttpPost]
public void Enter(string login, string password) public void Enter(string login, string password)
{ {
if (string.IsNullOrEmpty(login) || string.IsNullOrEmpty(password)) if (string.IsNullOrEmpty(login) || string.IsNullOrEmpty(password))
{ {
throw new Exception("Введите логин и пароль"); throw new Exception("Ââåäèòå ëîãèí è ïàðîëü");
} }
APIClient.Client = APIClient.GetRequest<ClientViewModel>($"api/client/login?login={login}&password={password}"); APIClient.Client = APIClient.GetRequest<ClientViewModel>($"api/client/login?login={login}&password={password}");
if (APIClient.Client == null) if (APIClient.Client == null)
{ {
throw new Exception("Неверный логин/пароль"); throw new Exception("Íåâåðíûé ëîãèí/ïàðîëü");
} }
Response.Redirect("Index"); Response.Redirect("Index");
} }
[HttpGet] [HttpGet]
public IActionResult Register() public IActionResult Register()
{ {
return View(); return View();
} }
[HttpPost] [HttpPost]
public void Register(string login, string password, string fio) public void Register(string login, string password, string fio)
{ {
if (string.IsNullOrEmpty(login) || string.IsNullOrEmpty(password) || string.IsNullOrEmpty(fio)) if (string.IsNullOrEmpty(login) || string.IsNullOrEmpty(password) || string.IsNullOrEmpty(fio))
{ {
throw new Exception("Введите логин, пароль и ФИО"); throw new Exception("Ââåäèòå ëîãèí, ïàðîëü è ÔÈÎ");
} }
APIClient.PostRequest("api/client/register", new ClientBindingModel APIClient.PostRequest("api/client/register", new ClientBindingModel
{ {
@ -108,24 +103,22 @@ namespace SushiBarClientApp.Controllers
Response.Redirect("Enter"); Response.Redirect("Enter");
return; return;
} }
[HttpGet] [HttpGet]
public IActionResult Create() public IActionResult Create()
{ {
ViewBag.ListSushi = APIClient.GetRequest<List<SushiViewModel>>("api/main/getlistsushi"); ViewBag.Sushis = APIClient.GetRequest<List<SushiViewModel>>("api/main/getsushilist");
return View(); return View();
} }
[HttpPost] [HttpPost]
public void Create(int sushi, int count) public void Create(int sushi, int count)
{ {
if (APIClient.Client == null) if (APIClient.Client == null)
{ {
throw new Exception("Вы как сюда попали? Сюда вход только авторизованным"); throw new Exception("Âû êàê ñóäà ïîïàëè? Ñóäà âõîä òîëüêî àâòîðèçîâàííûì");
} }
if (count <= 0) if (count <= 0)
{ {
throw new Exception("Количество и сумма должны быть больше 0"); throw new Exception("Êîëè÷åñòâî è ñóììà äîëæíû áûòü áîëüøå 0");
} }
APIClient.PostRequest("api/main/createorder", new OrderBindingModel APIClient.PostRequest("api/main/createorder", new OrderBindingModel
{ {
@ -136,11 +129,11 @@ namespace SushiBarClientApp.Controllers
}); });
Response.Redirect("Index"); Response.Redirect("Index");
} }
[HttpPost] [HttpPost]
public double Calc(int count, int sushi) public double Calc(int count, int sushi)
{ {
var prod = APIClient.GetRequest<SushiViewModel>($"api/main/getsushi?sushiId={sushi}"); var prod = APIClient.GetRequest<SushiViewModel>($"api/main/getsushi?sushiId={sushi}"
);
return count * (prod?.Price ?? 1); return count * (prod?.Price ?? 1);
} }
} }

View File

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

View File

@ -1,21 +1,22 @@
{ {
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:28968",
"sslPort": 44342
}
},
"profiles": { "profiles": {
"SushiBarClientApp": { "http": {
"commandName": "Project", "commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true, "launchBrowser": true,
"applicationUrl": "https://localhost:7129;http://localhost:5129",
"environmentVariables": { "environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development" "ASPNETCORE_ENVIRONMENT": "Development"
} },
"dotnetRunMessages": true,
"applicationUrl": "http://localhost:5222"
},
"https": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"dotnetRunMessages": true,
"applicationUrl": "https://localhost:7084;http://localhost:5222"
}, },
"IIS Express": { "IIS Express": {
"commandName": "IISExpress", "commandName": "IISExpress",
@ -24,5 +25,14 @@
"ASPNETCORE_ENVIRONMENT": "Development" "ASPNETCORE_ENVIRONMENT": "Development"
} }
} }
},
"$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:41478",
"sslPort": 44302
}
} }
} }

View File

@ -1,12 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk.Web"> <Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net6.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="6.0.26" />
<PackageReference Include="Microsoft.CodeAnalysis.Common" Version="4.9.2" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
</ItemGroup> </ItemGroup>

View File

@ -8,25 +8,33 @@
<div class="row"> <div class="row">
<div class="col-4">Суши:</div> <div class="col-4">Суши:</div>
<div class="col-8"> <div class="col-8">
<select id="sushi" name="sushi" class="form-control" asp-items="@(new SelectList(@ViewBag.ListSushi,"Id", "SushiName"))"></select> <select id="sushi" name="sushi" class="form-control">
@foreach (var sushi in ViewBag.Sushis)
{
<option value="@sushi.Id">@sushi.SushiName</option>
}
</select>
</div> </div>
</div> </div>
<div class="row"> <div class="row">
<div class="col-4">Количество:</div> <div class="col-4">Количество:</div>
<div class="col-8"><input type="text" name="count" id="count" /></div> <div class="col-8">
<input type="text" name="count" id="count" />
</div>
</div> </div>
<div class="row"> <div class="row">
<div class="col-4">Сумма:</div> <div class="col-4">Сумма:</div>
<div class="col-8"><input type="text" id="sum" name="sum" readonly /></div> <div class="col-8">
<input type="text" id="sum" name="sum" readonly />
</div>
</div> </div>
<div class="row"> <div class="row">
<div class="col-8"></div> <div class="col-8"></div>
<div class="col-4"><input type="submit" value="Создать" class="btn btn-primary" /></div> <div class="col-4">
<input type="submit" value="Создать" class="btn btn-primary" />
</div>
</div> </div>
</form> </form>
@section Scripts
{
<script> <script>
$('#sushi').on('change', function () { $('#sushi').on('change', function () {
check(); check();
@ -34,7 +42,6 @@
$('#count').on('change', function () { $('#count').on('change', function () {
check(); check();
}); });
function check() { function check() {
var count = $('#count').val(); var count = $('#count').val();
var sushi = $('#sushi').val(); var sushi = $('#sushi').val();
@ -44,10 +51,10 @@
url: "/Home/Calc", url: "/Home/Calc",
data: { count: count, sushi: sushi }, data: { count: count, sushi: sushi },
success: function (result) { success: function (result) {
$("#sum").val(result); var roundedResult = parseFloat(result).toFixed(2);
$("#sum").val(roundedResult);
} }
}); });
}; };
} }
</script> </script>
}

View File

@ -1,7 +1,6 @@
@{ @{
ViewData["Title"] = "Enter"; ViewData["Title"] = "Enter";
} }
<div class="text-center"> <div class="text-center">
<h2 class="display-4">Вход в приложение</h2> <h2 class="display-4">Вход в приложение</h2>
</div> </div>
@ -16,6 +15,6 @@
</div> </div>
<div class="row"> <div class="row">
<div class="col-8"></div> <div class="col-8"></div>
<div class="col-4"><input type="submit" value="Вход" class="btn btn-primary" /></div> <div class="col-4"><input type="submit" value="Вход" class="btn btnprimary" /></div>
</div> </div>
</form> </form>

View File

@ -1,16 +1,11 @@
@using SushiBarContracts.ViewModels @using SushiBarContracts.ViewModels
@model List<OrderViewModel> @model List<OrderViewModel>
@{ @{
ViewData["Title"] = "Home Page"; ViewData["Title"] = "Home Page";
} }
<div class="text-center"> <div class="text-center">
<h1 class="display-4">Заказы</h1> <h1 class="display-4">Заказы</h1>
</div> </div>
<div class="text-center"> <div class="text-center">
@{ @{
if (Model == null) if (Model == null)
@ -18,7 +13,6 @@
<h3 class="display-4">Авторизируйтесь</h3> <h3 class="display-4">Авторизируйтесь</h3>
return; return;
} }
<p> <p>
<a asp-action="Create">Создать заказ</a> <a asp-action="Create">Создать заказ</a>
</p> </p>
@ -50,22 +44,28 @@
{ {
<tr> <tr>
<td> <td>
@Html.DisplayFor(modelItem => item.Id) @Html.DisplayFor(modelItem =>
item.Id)
</td> </td>
<td> <td>
@Html.DisplayFor(modelItem => item.SushiName) @Html.DisplayFor(modelItem =>
item.SushiName)
</td> </td>
<td> <td>
@Html.DisplayFor(modelItem => item.DateCreate) @Html.DisplayFor(modelItem =>
item.DateCreate)
</td> </td>
<td> <td>
@Html.DisplayFor(modelItem => item.Count) @Html.DisplayFor(modelItem =>
item.Count)
</td> </td>
<td> <td>
@Html.DisplayFor(modelItem => item.Sum) @Html.DisplayFor(modelItem =>
item.Sum)
</td> </td>
<td> <td>
@Html.DisplayFor(modelItem => item.Status) @Html.DisplayFor(modelItem =>
item.Status)
</td> </td>
</tr> </tr>
} }

View File

@ -1,7 +1,5 @@
@using SushiBarContracts.ViewModels @using SushiBarContracts.ViewModels
@model ClientViewModel @model ClientViewModel
@{ @{
ViewData["Title"] = "Privacy Policy"; ViewData["Title"] = "Privacy Policy";
} }
@ -11,18 +9,29 @@
<form method="post"> <form method="post">
<div class="row"> <div class="row">
<div class="col-4">Логин:</div> <div class="col-4">Логин:</div>
<div class="col-8"><input type="text" name="login" value="@Model.Email"/></div> <div class="col-8">
<input type="text" name="login"
value="@Model.Email" />
</div>
</div> </div>
<div class="row"> <div class="row">
<div class="col-4">Пароль:</div> <div class="col-4">Пароль:</div>
<div class="col-8"><input type="password" name="password" value="@Model.Password"/></div> <div class="col-8">
<input type="password" name="password"
value="@Model.Password" />
</div>
</div> </div>
<div class="row"> <div class="row">
<div class="col-4">ФИО:</div> <div class="col-4">ФИО:</div>
<div class="col-8"><input type="text" name="fio" value="@Model.ClientFIO"/></div> <div class="col-8">
<input type="text" name="fio"
value="@Model.ClientFIO" />
</div>
</div> </div>
<div class="row"> <div class="row">
<div class="col-8"></div> <div class="col-8"></div>
<div class="col-4"><input type="submit" value="Сохранить" class="btn btn-primary" /></div> <div class="col-4">
<input type="submit" value="Сохранить" class="btn btn-primary" />
</div>
</div> </div>
</form> </form>

View File

@ -1,7 +1,6 @@
@{ @{
ViewData["Title"] = "Register"; ViewData["Title"] = "Register";
} }
<div class="text-center"> <div class="text-center">
<h2 class="display-4">Регистрация</h2> <h2 class="display-4">Регистрация</h2>
</div> </div>
@ -20,6 +19,9 @@
</div> </div>
<div class="row"> <div class="row">
<div class="col-8"></div> <div class="col-8"></div>
<div class="col-4"><input type="submit" value="Регистрация" class="btn btn-primary" /></div> <div class="col-4">
<input type="submit" value="Регистрация"
class="btn btn-primary" />
</div>
</div> </div>
</form> </form>

View File

@ -5,31 +5,32 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - SushiBarClientApp</title> <title>@ViewData["Title"] - SushiBarClientApp</title>
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" /> <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
<link rel="stylesheet" href="~/css/site.css" asp-append-version="true" /> <link rel="stylesheet" href="~/css/site.css" />
<link rel="stylesheet" href="~/SushiBarClientApp.styles.css" asp-append-version="true" /> <script src="~/lib/jquery/dist/jquery.min.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
</head> </head>
<body> <body>
<header> <header>
<nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3"> <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bgwhite border-bottom box-shadow mb-3">
<div class="container-fluid"> <div class="container">
<a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index">Суши-бар</a> <a class="navbar-brand" asp-area="" asp-controller="Home" aspaction="Index">Суши бар</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target=".navbar-collapse" aria-controls="navbarSupportedContent" <button class="navbar-toggler" type="button" datatoggle="collapse" data-target=".navbar-collapse" ariacontrols="navbarSupportedContent"
aria-expanded="false" aria-label="Toggle navigation"> aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span> <span class="navbar-toggler-icon"></span>
</button> </button>
<div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse"> <div class="navbar-collapse collapse d-sm-inline-flex flex-smrow-reverse">
<ul class="navbar-nav flex-grow-1"> <ul class="navbar-nav flex-grow-1">
<li class="nav-item"> <li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Index">Заказы</a> <a class="nav-link text-dark" asparea="" asp-controller="Home" asp-action="Index">Заказы</a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Privacy">Личные данные</a> <a class="nav-link text-dark" asparea="" asp-controller="Home" asp-action="Privacy">Личные данные</a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Enter">Вход</a> <a class="nav-link text-dark" asparea="" asp-controller="Home" asp-action="Enter">Вход</a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Register">Регистрация</a> <a class="nav-link text-dark" asparea="" asp-controller="Home" asp-action="Register">Регистрация</a>
</li> </li>
</ul> </ul>
</div> </div>
@ -41,15 +42,12 @@
@RenderBody() @RenderBody()
</main> </main>
</div> </div>
<footer class="border-top footer text-muted"> <footer class="border-top footer text-muted">
<div class="container"> <div class="container">
&copy; 2023 - SushiBarClientApp - <a asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a> &copy; 2020 - Суши бар - <a asp-area="" aspcontroller="Home" asp-action="Privacy">Личные данные</a>
</div> </div>
</footer> </footer>
<script src="~/lib/jquery/dist/jquery.min.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
<script src="~/js/site.js" asp-append-version="true"></script> <script src="~/js/site.js" asp-append-version="true"></script>
@await RenderSectionAsync("Scripts", required: false) @RenderSection("Scripts", required: false)
</body> </body>
</html> </html>

View File

@ -1,4 +1,4 @@
/* Please see documentation at https://docs.microsoft.com/aspnet/core/client-side/bundling-and-minification /* Please see documentation at https://learn.microsoft.com/aspnet/core/client-side/bundling-and-minification
for details on configuring this project to bundle and minify static web assets. */ for details on configuring this project to bundle and minify static web assets. */
a.navbar-brand { a.navbar-brand {

View File

@ -7,5 +7,5 @@
}, },
"AllowedHosts": "*", "AllowedHosts": "*",
"IPAddress": "http://localhost:5292/" "IPAddress": "http://localhost:5262/"
} }

View File

@ -8,6 +8,10 @@ html {
} }
} }
.btn:focus, .btn:active:focus, .btn-link.nav-link:focus, .form-control:focus, .form-check-input:focus {
box-shadow: 0 0 0 0.1rem white, 0 0 0 0.25rem #258cfb;
}
html { html {
position: relative; position: relative;
min-height: 100%; min-height: 100%;

View File

@ -1,4 +1,4 @@
// Please see documentation at https://docs.microsoft.com/aspnet/core/client-side/bundling-and-minification // Please see documentation at https://learn.microsoft.com/aspnet/core/client-side/bundling-and-minification
// for details on configuring this project to bundle and minify static web assets. // for details on configuring this project to bundle and minify static web assets.
// Write your JavaScript code. // Write your JavaScript code.

View File

@ -1,12 +1,23 @@
Copyright (c) .NET Foundation. All rights reserved. The MIT License (MIT)
Licensed under the Apache License, Version 2.0 (the "License"); you may not use Copyright (c) .NET Foundation and Contributors
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 All rights reserved.
Unless required by applicable law or agreed to in writing, software distributed Permission is hereby granted, free of charge, to any person obtaining a copy
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR of this software and associated documentation files (the "Software"), to deal
CONDITIONS OF ANY KIND, either express or implied. See the License for the in the Software without restriction, including without limitation the rights
specific language governing permissions and limitations under the License. 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.

View File

@ -1,7 +1,10 @@
// Unobtrusive validation support library for jQuery and jQuery Validate /**
// Copyright (c) .NET Foundation. All rights reserved. * @license
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. * Unobtrusive validation support library for jQuery and jQuery Validate
// @version v3.2.11 * 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 v4.0.0
*/
/*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 */ /*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 */ /*global document: false, jQuery: false */

File diff suppressed because one or more lines are too long

View File

@ -1,9 +1,9 @@
/*! /*!
* jQuery Validation Plugin v1.17.0 * jQuery Validation Plugin v1.19.5
* *
* https://jqueryvalidation.org/ * https://jqueryvalidation.org/
* *
* Copyright (c) 2017 Jörn Zaefferer * Copyright (c) 2022 Jörn Zaefferer
* Released under the MIT license * Released under the MIT license
*/ */
(function( factory ) { (function( factory ) {
@ -43,6 +43,38 @@
}() ); }() );
/**
* This is used in the United States to process payments, deposits,
* or transfers using the Automated Clearing House (ACH) or Fedwire
* systems. A very common use case would be to validate a form for
* an ACH bill payment.
*/
$.validator.addMethod( "abaRoutingNumber", function( value ) {
var checksum = 0;
var tokens = value.split( "" );
var length = tokens.length;
// Length Check
if ( length !== 9 ) {
return false;
}
// Calc the checksum
// https://en.wikipedia.org/wiki/ABA_routing_transit_number
for ( var i = 0; i < length; i += 3 ) {
checksum += parseInt( tokens[ i ], 10 ) * 3 +
parseInt( tokens[ i + 1 ], 10 ) * 7 +
parseInt( tokens[ i + 2 ], 10 );
}
// If not zero and divisible by 10 then valid
if ( checksum !== 0 && checksum % 10 === 0 ) {
return true;
}
return false;
}, "Please enter a valid routing number." );
// Accept a value from a file input based on a required mimetype // Accept a value from a file input based on a required mimetype
$.validator.addMethod( "accept", function( value, element, param ) { $.validator.addMethod( "accept", function( value, element, param ) {
@ -87,7 +119,7 @@ $.validator.addMethod( "accept", function( value, element, param ) {
$.validator.addMethod( "alphanumeric", function( value, element ) { $.validator.addMethod( "alphanumeric", function( value, element ) {
return this.optional( element ) || /^\w+$/i.test( value ); return this.optional( element ) || /^\w+$/i.test( value );
}, "Letters, numbers, and underscores only please" ); }, "Letters, numbers, and underscores only please." );
/* /*
* Dutch bank account numbers (not 'giro' numbers) have 9 digits * Dutch bank account numbers (not 'giro' numbers) have 9 digits
@ -114,13 +146,13 @@ $.validator.addMethod( "bankaccountNL", function( value, element ) {
sum = sum + factor * digit; sum = sum + factor * digit;
} }
return sum % 11 === 0; return sum % 11 === 0;
}, "Please specify a valid bank account number" ); }, "Please specify a valid bank account number." );
$.validator.addMethod( "bankorgiroaccountNL", function( value, element ) { $.validator.addMethod( "bankorgiroaccountNL", function( value, element ) {
return this.optional( element ) || return this.optional( element ) ||
( $.validator.methods.bankaccountNL.call( this, value, element ) ) || ( $.validator.methods.bankaccountNL.call( this, value, element ) ) ||
( $.validator.methods.giroaccountNL.call( this, value, element ) ); ( $.validator.methods.giroaccountNL.call( this, value, element ) );
}, "Please specify a valid bank or giro account number" ); }, "Please specify a valid bank or giro account number." );
/** /**
* BIC is the business identifier code (ISO 9362). This BIC check is not a guarantee for authenticity. * BIC is the business identifier code (ISO 9362). This BIC check is not a guarantee for authenticity.
@ -139,7 +171,7 @@ $.validator.addMethod( "bankorgiroaccountNL", function( value, element ) {
*/ */
$.validator.addMethod( "bic", function( value, element ) { $.validator.addMethod( "bic", function( value, element ) {
return this.optional( element ) || /^([A-Z]{6}[A-Z2-9][A-NP-Z1-9])(X{3}|[A-WY-Z0-9][A-Z0-9]{2})?$/.test( value.toUpperCase() ); return this.optional( element ) || /^([A-Z]{6}[A-Z2-9][A-NP-Z1-9])(X{3}|[A-WY-Z0-9][A-Z0-9]{2})?$/.test( value.toUpperCase() );
}, "Please specify a valid BIC code" ); }, "Please specify a valid BIC code." );
/* /*
* Código de identificación fiscal ( CIF ) is the tax identification code for Spanish legal entities * Código de identificación fiscal ( CIF ) is the tax identification code for Spanish legal entities
@ -256,11 +288,141 @@ $.validator.addMethod( "cifES", function( value, element ) {
}, "Please specify a valid CIF number." ); }, "Please specify a valid CIF number." );
/*
* Brazillian CNH number (Carteira Nacional de Habilitacao) is the License Driver number.
* CNH numbers have 11 digits in total: 9 numbers followed by 2 check numbers that are being used for validation.
*/
$.validator.addMethod( "cnhBR", function( value ) {
// Removing special characters from value
value = value.replace( /([~!@#$%^&*()_+=`{}\[\]\-|\\:;'<>,.\/? ])+/g, "" );
// Checking value to have 11 digits only
if ( value.length !== 11 ) {
return false;
}
var sum = 0, dsc = 0, firstChar,
firstCN, secondCN, i, j, v;
firstChar = value.charAt( 0 );
if ( new Array( 12 ).join( firstChar ) === value ) {
return false;
}
// Step 1 - using first Check Number:
for ( i = 0, j = 9, v = 0; i < 9; ++i, --j ) {
sum += +( value.charAt( i ) * j );
}
firstCN = sum % 11;
if ( firstCN >= 10 ) {
firstCN = 0;
dsc = 2;
}
sum = 0;
for ( i = 0, j = 1, v = 0; i < 9; ++i, ++j ) {
sum += +( value.charAt( i ) * j );
}
secondCN = sum % 11;
if ( secondCN >= 10 ) {
secondCN = 0;
} else {
secondCN = secondCN - dsc;
}
return ( String( firstCN ).concat( secondCN ) === value.substr( -2 ) );
}, "Please specify a valid CNH number." );
/*
* Brazillian value number (Cadastrado de Pessoas Juridica).
* value numbers have 14 digits in total: 12 numbers followed by 2 check numbers that are being used for validation.
*/
$.validator.addMethod( "cnpjBR", function( value, element ) {
"use strict";
if ( this.optional( element ) ) {
return true;
}
// Removing no number
value = value.replace( /[^\d]+/g, "" );
// Checking value to have 14 digits only
if ( value.length !== 14 ) {
return false;
}
// Elimina values invalidos conhecidos
if ( value === "00000000000000" ||
value === "11111111111111" ||
value === "22222222222222" ||
value === "33333333333333" ||
value === "44444444444444" ||
value === "55555555555555" ||
value === "66666666666666" ||
value === "77777777777777" ||
value === "88888888888888" ||
value === "99999999999999" ) {
return false;
}
// Valida DVs
var tamanho = ( value.length - 2 );
var numeros = value.substring( 0, tamanho );
var digitos = value.substring( tamanho );
var soma = 0;
var pos = tamanho - 7;
for ( var i = tamanho; i >= 1; i-- ) {
soma += numeros.charAt( tamanho - i ) * pos--;
if ( pos < 2 ) {
pos = 9;
}
}
var resultado = soma % 11 < 2 ? 0 : 11 - soma % 11;
if ( resultado !== parseInt( digitos.charAt( 0 ), 10 ) ) {
return false;
}
tamanho = tamanho + 1;
numeros = value.substring( 0, tamanho );
soma = 0;
pos = tamanho - 7;
for ( var il = tamanho; il >= 1; il-- ) {
soma += numeros.charAt( tamanho - il ) * pos--;
if ( pos < 2 ) {
pos = 9;
}
}
resultado = soma % 11 < 2 ? 0 : 11 - soma % 11;
if ( resultado !== parseInt( digitos.charAt( 1 ), 10 ) ) {
return false;
}
return true;
}, "Please specify a CNPJ value number." );
/* /*
* Brazillian CPF number (Cadastrado de Pessoas Físicas) is the equivalent of a Brazilian tax registration number. * Brazillian CPF number (Cadastrado de Pessoas Físicas) is the equivalent of a Brazilian tax registration number.
* CPF numbers have 11 digits in total: 9 numbers followed by 2 check numbers that are being used for validation. * CPF numbers have 11 digits in total: 9 numbers followed by 2 check numbers that are being used for validation.
*/ */
$.validator.addMethod( "cpfBR", function( value ) { $.validator.addMethod( "cpfBR", function( value, element ) {
"use strict";
if ( this.optional( element ) ) {
return true;
}
// Removing special characters from value // Removing special characters from value
value = value.replace( /([~!@#$%^&*()_+=`{}\[\]\-|\\:;'<>,.\/? ])+/g, "" ); value = value.replace( /([~!@#$%^&*()_+=`{}\[\]\-|\\:;'<>,.\/? ])+/g, "" );
@ -315,7 +477,7 @@ $.validator.addMethod( "cpfBR", function( value ) {
} }
return false; return false;
}, "Please specify a valid CPF number" ); }, "Please specify a valid CPF number." );
// https://jqueryvalidation.org/creditcard-method/ // https://jqueryvalidation.org/creditcard-method/
// based on https://en.wikipedia.org/wiki/Luhn_algorithm // based on https://en.wikipedia.org/wiki/Luhn_algorithm
@ -337,7 +499,7 @@ $.validator.addMethod( "creditcard", function( value, element ) {
value = value.replace( /\D/g, "" ); value = value.replace( /\D/g, "" );
// Basing min and max length on // Basing min and max length on
// https://developer.ean.com/general_info/Valid_Credit_Card_Types // https://dev.ean.com/general-info/valid-card-types/
if ( value.length < 13 || value.length > 19 ) { if ( value.length < 13 || value.length > 19 ) {
return false; return false;
} }
@ -359,7 +521,7 @@ $.validator.addMethod( "creditcard", function( value, element ) {
}, "Please enter a valid credit card number." ); }, "Please enter a valid credit card number." );
/* NOTICE: Modified version of Castle.Components.Validator.CreditCardValidator /* NOTICE: Modified version of Castle.Components.Validator.CreditCardValidator
* Redistributed under the the Apache License 2.0 at http://www.apache.org/licenses/LICENSE-2.0 * Redistributed under the Apache License 2.0 at http://www.apache.org/licenses/LICENSE-2.0
* Valid Types: mastercard, visa, amex, dinersclub, enroute, discover, jcb, unknown, all (overrides all other settings) * Valid Types: mastercard, visa, amex, dinersclub, enroute, discover, jcb, unknown, all (overrides all other settings)
*/ */
$.validator.addMethod( "creditcardtypes", function( value, element, param ) { $.validator.addMethod( "creditcardtypes", function( value, element, param ) {
@ -398,7 +560,7 @@ $.validator.addMethod( "creditcardtypes", function( value, element, param ) {
if ( param.all ) { if ( param.all ) {
validTypes = 0x0001 | 0x0002 | 0x0004 | 0x0008 | 0x0010 | 0x0020 | 0x0040 | 0x0080; validTypes = 0x0001 | 0x0002 | 0x0004 | 0x0008 | 0x0010 | 0x0020 | 0x0040 | 0x0080;
} }
if ( validTypes & 0x0001 && /^(5[12345])/.test( value ) ) { // Mastercard if ( validTypes & 0x0001 && ( /^(5[12345])/.test( value ) || /^(2[234567])/.test( value ) ) ) { // Mastercard
return value.length === 16; return value.length === 16;
} }
if ( validTypes & 0x0002 && /^(4)/.test( value ) ) { // Visa if ( validTypes & 0x0002 && /^(4)/.test( value ) ) { // Visa
@ -468,7 +630,7 @@ $.validator.addMethod( "currency", function( value, element, param ) {
regex = new RegExp( regex ); regex = new RegExp( regex );
return this.optional( element ) || regex.test( value ); return this.optional( element ) || regex.test( value );
}, "Please specify a valid currency" ); }, "Please specify a valid currency." );
$.validator.addMethod( "dateFA", function( value, element ) { $.validator.addMethod( "dateFA", function( value, element ) {
return this.optional( element ) || /^[1-4]\d{3}\/((0?[1-6]\/((3[0-1])|([1-2][0-9])|(0?[1-9])))|((1[0-2]|(0?[7-9]))\/(30|([1-2][0-9])|(0?[1-9]))))$/.test( value ); return this.optional( element ) || /^[1-4]\d{3}\/((0?[1-6]\/((3[0-1])|([1-2][0-9])|(0?[1-9])))|((1[0-2]|(0?[7-9]))\/(30|([1-2][0-9])|(0?[1-9]))))$/.test( value );
@ -529,7 +691,31 @@ $.validator.addMethod( "extension", function( value, element, param ) {
*/ */
$.validator.addMethod( "giroaccountNL", function( value, element ) { $.validator.addMethod( "giroaccountNL", function( value, element ) {
return this.optional( element ) || /^[0-9]{1,7}$/.test( value ); return this.optional( element ) || /^[0-9]{1,7}$/.test( value );
}, "Please specify a valid giro account number" ); }, "Please specify a valid giro account number." );
$.validator.addMethod( "greaterThan", function( value, element, param ) {
var target = $( param );
if ( this.settings.onfocusout && target.not( ".validate-greaterThan-blur" ).length ) {
target.addClass( "validate-greaterThan-blur" ).on( "blur.validate-greaterThan", function() {
$( element ).valid();
} );
}
return value > target.val();
}, "Please enter a greater value." );
$.validator.addMethod( "greaterThanEqual", function( value, element, param ) {
var target = $( param );
if ( this.settings.onfocusout && target.not( ".validate-greaterThanEqual-blur" ).length ) {
target.addClass( "validate-greaterThanEqual-blur" ).on( "blur.validate-greaterThanEqual", function() {
$( element ).valid();
} );
}
return value >= target.val();
}, "Please enter a greater value." );
/** /**
* IBAN is the international bank account number. * IBAN is the international bank account number.
@ -666,11 +852,11 @@ $.validator.addMethod( "iban", function( value, element ) {
cRest = cOperator % 97; cRest = cOperator % 97;
} }
return cRest === 1; return cRest === 1;
}, "Please specify a valid IBAN" ); }, "Please specify a valid IBAN." );
$.validator.addMethod( "integer", function( value, element ) { $.validator.addMethod( "integer", function( value, element ) {
return this.optional( element ) || /^-?\d+$/.test( value ); return this.optional( element ) || /^-?\d+$/.test( value );
}, "A positive or negative non-decimal number please" ); }, "A positive or negative non-decimal number please." );
$.validator.addMethod( "ipv4", function( value, element ) { $.validator.addMethod( "ipv4", function( value, element ) {
return this.optional( element ) || /^(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)$/i.test( value ); return this.optional( element ) || /^(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)$/i.test( value );
@ -680,17 +866,103 @@ $.validator.addMethod( "ipv6", function( value, element ) {
return this.optional( element ) || /^((([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){5}:([0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){4}:([0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){3}:([0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){2}:([0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(([0-9A-Fa-f]{1,4}:){0,5}:((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(::([0-9A-Fa-f]{1,4}:){0,5}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|([0-9A-Fa-f]{1,4}::([0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})|(::([0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){1,7}:))$/i.test( value ); return this.optional( element ) || /^((([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){5}:([0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){4}:([0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){3}:([0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){2}:([0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(([0-9A-Fa-f]{1,4}:){0,5}:((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(::([0-9A-Fa-f]{1,4}:){0,5}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|([0-9A-Fa-f]{1,4}::([0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})|(::([0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){1,7}:))$/i.test( value );
}, "Please enter a valid IP v6 address." ); }, "Please enter a valid IP v6 address." );
$.validator.addMethod( "lessThan", function( value, element, param ) {
var target = $( param );
if ( this.settings.onfocusout && target.not( ".validate-lessThan-blur" ).length ) {
target.addClass( "validate-lessThan-blur" ).on( "blur.validate-lessThan", function() {
$( element ).valid();
} );
}
return value < target.val();
}, "Please enter a lesser value." );
$.validator.addMethod( "lessThanEqual", function( value, element, param ) {
var target = $( param );
if ( this.settings.onfocusout && target.not( ".validate-lessThanEqual-blur" ).length ) {
target.addClass( "validate-lessThanEqual-blur" ).on( "blur.validate-lessThanEqual", function() {
$( element ).valid();
} );
}
return value <= target.val();
}, "Please enter a lesser value." );
$.validator.addMethod( "lettersonly", function( value, element ) { $.validator.addMethod( "lettersonly", function( value, element ) {
return this.optional( element ) || /^[a-z]+$/i.test( value ); return this.optional( element ) || /^[a-z]+$/i.test( value );
}, "Letters only please" ); }, "Letters only please." );
$.validator.addMethod( "letterswithbasicpunc", function( value, element ) { $.validator.addMethod( "letterswithbasicpunc", function( value, element ) {
return this.optional( element ) || /^[a-z\-.,()'"\s]+$/i.test( value ); return this.optional( element ) || /^[a-z\-.,()'"\s]+$/i.test( value );
}, "Letters or punctuation only please" ); }, "Letters or punctuation only please." );
// Limit the number of files in a FileList.
$.validator.addMethod( "maxfiles", function( value, element, param ) {
if ( this.optional( element ) ) {
return true;
}
if ( $( element ).attr( "type" ) === "file" ) {
if ( element.files && element.files.length > param ) {
return false;
}
}
return true;
}, $.validator.format( "Please select no more than {0} files." ) );
// Limit the size of each individual file in a FileList.
$.validator.addMethod( "maxsize", function( value, element, param ) {
if ( this.optional( element ) ) {
return true;
}
if ( $( element ).attr( "type" ) === "file" ) {
if ( element.files && element.files.length ) {
for ( var i = 0; i < element.files.length; i++ ) {
if ( element.files[ i ].size > param ) {
return false;
}
}
}
}
return true;
}, $.validator.format( "File size must not exceed {0} bytes each." ) );
// Limit the size of all files in a FileList.
$.validator.addMethod( "maxsizetotal", function( value, element, param ) {
if ( this.optional( element ) ) {
return true;
}
if ( $( element ).attr( "type" ) === "file" ) {
if ( element.files && element.files.length ) {
var totalSize = 0;
for ( var i = 0; i < element.files.length; i++ ) {
totalSize += element.files[ i ].size;
if ( totalSize > param ) {
return false;
}
}
}
}
return true;
}, $.validator.format( "Total size of all files must not exceed {0} bytes." ) );
$.validator.addMethod( "mobileNL", function( value, element ) { $.validator.addMethod( "mobileNL", function( value, element ) {
return this.optional( element ) || /^((\+|00(\s|\s?\-\s?)?)31(\s|\s?\-\s?)?(\(0\)[\-\s]?)?|0)6((\s|\s?\-\s?)?[0-9]){8}$/.test( value ); return this.optional( element ) || /^((\+|00(\s|\s?\-\s?)?)31(\s|\s?\-\s?)?(\(0\)[\-\s]?)?|0)6((\s|\s?\-\s?)?[0-9]){8}$/.test( value );
}, "Please specify a valid mobile number" ); }, "Please specify a valid mobile number." );
$.validator.addMethod( "mobileRU", function( phone_number, element ) {
var ruPhone_number = phone_number.replace( /\(|\)|\s+|-/g, "" );
return this.optional( element ) || ruPhone_number.length > 9 && /^((\+7|7|8)+([0-9]){10})$/.test( ruPhone_number );
}, "Please specify a valid mobile number." );
/* For UK phone functions, do the following server side processing: /* For UK phone functions, do the following server side processing:
* Compare original input with this RegEx pattern: * Compare original input with this RegEx pattern:
@ -704,7 +976,7 @@ $.validator.addMethod( "mobileUK", function( phone_number, element ) {
phone_number = phone_number.replace( /\(|\)|\s+|-/g, "" ); phone_number = phone_number.replace( /\(|\)|\s+|-/g, "" );
return this.optional( element ) || phone_number.length > 9 && return this.optional( element ) || phone_number.length > 9 &&
phone_number.match( /^(?:(?:(?:00\s?|\+)44\s?|0)7(?:[1345789]\d{2}|624)\s?\d{3}\s?\d{3})$/ ); phone_number.match( /^(?:(?:(?:00\s?|\+)44\s?|0)7(?:[1345789]\d{2}|624)\s?\d{3}\s?\d{3})$/ );
}, "Please specify a valid mobile number" ); }, "Please specify a valid mobile number." );
$.validator.addMethod( "netmask", function( value, element ) { $.validator.addMethod( "netmask", function( value, element ) {
return this.optional( element ) || /^(254|252|248|240|224|192|128)\.0\.0\.0|255\.(254|252|248|240|224|192|128|0)\.0\.0|255\.255\.(254|252|248|240|224|192|128|0)\.0|255\.255\.255\.(254|252|248|240|224|192|128|0)/i.test( value ); return this.optional( element ) || /^(254|252|248|240|224|192|128)\.0\.0\.0|255\.(254|252|248|240|224|192|128|0)\.0\.0|255\.255\.(254|252|248|240|224|192|128|0)\.0|255\.255\.255\.(254|252|248|240|224|192|128|0)/i.test( value );
@ -804,13 +1076,71 @@ $.validator.addMethod( "nipPL", function( value ) {
return ( intControlNr === parseInt( value[ 9 ], 10 ) ); return ( intControlNr === parseInt( value[ 9 ], 10 ) );
}, "Please specify a valid NIP number." ); }, "Please specify a valid NIP number." );
/**
* Created for project jquery-validation.
* @Description Brazillian PIS or NIS number (Número de Identificação Social Pis ou Pasep) is the equivalent of a
* Brazilian tax registration number NIS of PIS numbers have 11 digits in total: 10 numbers followed by 1 check numbers
* that are being used for validation.
* @copyright (c) 21/08/2018 13:14, Cleiton da Silva Mendonça
* @author Cleiton da Silva Mendonça <cleiton.mendonca@gmail.com>
* @link http://gitlab.com/csmendonca Gitlab of Cleiton da Silva Mendonça
* @link http://github.com/csmendonca Github of Cleiton da Silva Mendonça
*/
$.validator.addMethod( "nisBR", function( value ) {
var number;
var cn;
var sum = 0;
var dv;
var count;
var multiplier;
// Removing special characters from value
value = value.replace( /([~!@#$%^&*()_+=`{}\[\]\-|\\:;'<>,.\/? ])+/g, "" );
// Checking value to have 11 digits only
if ( value.length !== 11 ) {
return false;
}
//Get check number of value
cn = parseInt( value.substring( 10, 11 ), 10 );
//Get number with 10 digits of the value
number = parseInt( value.substring( 0, 10 ), 10 );
for ( count = 2; count < 12; count++ ) {
multiplier = count;
if ( count === 10 ) {
multiplier = 2;
}
if ( count === 11 ) {
multiplier = 3;
}
sum += ( ( number % 10 ) * multiplier );
number = parseInt( number / 10, 10 );
}
dv = ( sum % 11 );
if ( dv > 1 ) {
dv = ( 11 - dv );
} else {
dv = 0;
}
if ( cn === dv ) {
return true;
} else {
return false;
}
}, "Please specify a valid NIS/PIS number." );
$.validator.addMethod( "notEqualTo", function( value, element, param ) { $.validator.addMethod( "notEqualTo", function( value, element, param ) {
return this.optional( element ) || !$.validator.methods.equalTo.call( this, value, element, param ); return this.optional( element ) || !$.validator.methods.equalTo.call( this, value, element, param );
}, "Please enter a different value, values must not be the same." ); }, "Please enter a different value, values must not be the same." );
$.validator.addMethod( "nowhitespace", function( value, element ) { $.validator.addMethod( "nowhitespace", function( value, element ) {
return this.optional( element ) || /^\S+$/i.test( value ); return this.optional( element ) || /^\S+$/i.test( value );
}, "No white space please" ); }, "No white space please." );
/** /**
* Return true if the field value matches the given format RegExp * Return true if the field value matches the given format RegExp
@ -842,6 +1172,30 @@ $.validator.addMethod( "phoneNL", function( value, element ) {
return this.optional( element ) || /^((\+|00(\s|\s?\-\s?)?)31(\s|\s?\-\s?)?(\(0\)[\-\s]?)?|0)[1-9]((\s|\s?\-\s?)?[0-9]){8}$/.test( value ); return this.optional( element ) || /^((\+|00(\s|\s?\-\s?)?)31(\s|\s?\-\s?)?(\(0\)[\-\s]?)?|0)[1-9]((\s|\s?\-\s?)?[0-9]){8}$/.test( value );
}, "Please specify a valid phone number." ); }, "Please specify a valid phone number." );
/**
* Polish telephone numbers have 9 digits.
*
* Mobile phone numbers starts with following digits:
* 45, 50, 51, 53, 57, 60, 66, 69, 72, 73, 78, 79, 88.
*
* Fixed-line numbers starts with area codes:
* 12, 13, 14, 15, 16, 17, 18, 22, 23, 24, 25, 29, 32, 33,
* 34, 41, 42, 43, 44, 46, 48, 52, 54, 55, 56, 58, 59, 61,
* 62, 63, 65, 67, 68, 71, 74, 75, 76, 77, 81, 82, 83, 84,
* 85, 86, 87, 89, 91, 94, 95.
*
* Ministry of National Defence numbers and VoIP numbers starts with 26 and 39.
*
* Excludes intelligent networks (premium rate, shared cost, free phone numbers).
*
* Poland National Numbering Plan http://www.itu.int/oth/T02020000A8/en
*/
$.validator.addMethod( "phonePL", function( phone_number, element ) {
phone_number = phone_number.replace( /\s+/g, "" );
var regexp = /^(?:(?:(?:\+|00)?48)|(?:\(\+?48\)))?(?:1[2-8]|2[2-69]|3[2-49]|4[1-68]|5[0-9]|6[0-35-9]|[7-8][1-9]|9[145])\d{7}$/;
return this.optional( element ) || regexp.test( phone_number );
}, "Please specify a valid phone number." );
/* For UK phone functions, do the following server side processing: /* For UK phone functions, do the following server side processing:
* Compare original input with this RegEx pattern: * Compare original input with this RegEx pattern:
* ^\(?(?:(?:00\)?[\s\-]?\(?|\+)(44)\)?[\s\-]?\(?(?:0\)?[\s\-]?\(?)?|0)([1-9]\d{1,4}\)?[\s\d\-]+)$ * ^\(?(?:(?:00\)?[\s\-]?\(?|\+)(44)\)?[\s\-]?\(?(?:0\)?[\s\-]?\(?)?|0)([1-9]\d{1,4}\)?[\s\d\-]+)$
@ -856,7 +1210,7 @@ $.validator.addMethod( "phonesUK", function( phone_number, element ) {
phone_number = phone_number.replace( /\(|\)|\s+|-/g, "" ); phone_number = phone_number.replace( /\(|\)|\s+|-/g, "" );
return this.optional( element ) || phone_number.length > 9 && return this.optional( element ) || phone_number.length > 9 &&
phone_number.match( /^(?:(?:(?:00\s?|\+)44\s?|0)(?:1\d{8,9}|[23]\d{9}|7(?:[1345789]\d{8}|624\d{6})))$/ ); phone_number.match( /^(?:(?:(?:00\s?|\+)44\s?|0)(?:1\d{8,9}|[23]\d{9}|7(?:[1345789]\d{8}|624\d{6})))$/ );
}, "Please specify a valid uk phone number" ); }, "Please specify a valid uk phone number." );
/* For UK phone functions, do the following server side processing: /* For UK phone functions, do the following server side processing:
* Compare original input with this RegEx pattern: * Compare original input with this RegEx pattern:
@ -870,7 +1224,7 @@ $.validator.addMethod( "phoneUK", function( phone_number, element ) {
phone_number = phone_number.replace( /\(|\)|\s+|-/g, "" ); phone_number = phone_number.replace( /\(|\)|\s+|-/g, "" );
return this.optional( element ) || phone_number.length > 9 && return this.optional( element ) || phone_number.length > 9 &&
phone_number.match( /^(?:(?:(?:00\s?|\+)44\s?)|(?:\(?0))(?:\d{2}\)?\s?\d{4}\s?\d{4}|\d{3}\)?\s?\d{3}\s?\d{3,4}|\d{4}\)?\s?(?:\d{5}|\d{3}\s?\d{3})|\d{5}\)?\s?\d{4,5})$/ ); phone_number.match( /^(?:(?:(?:00\s?|\+)44\s?)|(?:\(?0))(?:\d{2}\)?\s?\d{4}\s?\d{4}|\d{3}\)?\s?\d{3}\s?\d{3,4}|\d{4}\)?\s?(?:\d{5}|\d{3}\s?\d{3})|\d{5}\)?\s?\d{4,5})$/ );
}, "Please specify a valid phone number" ); }, "Please specify a valid phone number." );
/** /**
* Matches US phone number format * Matches US phone number format
@ -891,8 +1245,8 @@ $.validator.addMethod( "phoneUK", function( phone_number, element ) {
$.validator.addMethod( "phoneUS", function( phone_number, element ) { $.validator.addMethod( "phoneUS", function( phone_number, element ) {
phone_number = phone_number.replace( /\s+/g, "" ); phone_number = phone_number.replace( /\s+/g, "" );
return this.optional( element ) || phone_number.length > 9 && return this.optional( element ) || phone_number.length > 9 &&
phone_number.match( /^(\+?1-?)?(\([2-9]([02-9]\d|1[02-9])\)|[2-9]([02-9]\d|1[02-9]))-?[2-9]([02-9]\d|1[02-9])-?\d{4}$/ ); phone_number.match( /^(\+?1-?)?(\([2-9]([02-9]\d|1[02-9])\)|[2-9]([02-9]\d|1[02-9]))-?[2-9]\d{2}-?\d{4}$/ );
}, "Please specify a valid phone number" ); }, "Please specify a valid phone number." );
/* /*
* Valida CEPs do brasileiros: * Valida CEPs do brasileiros:
@ -921,21 +1275,21 @@ $.validator.addMethod( "postalcodeBR", function( cep_value, element ) {
*/ */
$.validator.addMethod( "postalCodeCA", function( value, element ) { $.validator.addMethod( "postalCodeCA", function( value, element ) {
return this.optional( element ) || /^[ABCEGHJKLMNPRSTVXY]\d[ABCEGHJKLMNPRSTVWXYZ] *\d[ABCEGHJKLMNPRSTVWXYZ]\d$/i.test( value ); return this.optional( element ) || /^[ABCEGHJKLMNPRSTVXY]\d[ABCEGHJKLMNPRSTVWXYZ] *\d[ABCEGHJKLMNPRSTVWXYZ]\d$/i.test( value );
}, "Please specify a valid postal code" ); }, "Please specify a valid postal code." );
/* Matches Italian postcode (CAP) */ /* Matches Italian postcode (CAP) */
$.validator.addMethod( "postalcodeIT", function( value, element ) { $.validator.addMethod( "postalcodeIT", function( value, element ) {
return this.optional( element ) || /^\d{5}$/.test( value ); return this.optional( element ) || /^\d{5}$/.test( value );
}, "Please specify a valid postal code" ); }, "Please specify a valid postal code." );
$.validator.addMethod( "postalcodeNL", function( value, element ) { $.validator.addMethod( "postalcodeNL", function( value, element ) {
return this.optional( element ) || /^[1-9][0-9]{3}\s?[a-zA-Z]{2}$/.test( value ); return this.optional( element ) || /^[1-9][0-9]{3}\s?[a-zA-Z]{2}$/.test( value );
}, "Please specify a valid postal code" ); }, "Please specify a valid postal code." );
// Matches UK postcode. Does not match to UK Channel Islands that have their own postcodes (non standard UK) // Matches UK postcode. Does not match to UK Channel Islands that have their own postcodes (non standard UK)
$.validator.addMethod( "postcodeUK", function( value, element ) { $.validator.addMethod( "postcodeUK", function( value, element ) {
return this.optional( element ) || /^((([A-PR-UWYZ][0-9])|([A-PR-UWYZ][0-9][0-9])|([A-PR-UWYZ][A-HK-Y][0-9])|([A-PR-UWYZ][A-HK-Y][0-9][0-9])|([A-PR-UWYZ][0-9][A-HJKSTUW])|([A-PR-UWYZ][A-HK-Y][0-9][ABEHMNPRVWXY]))\s?([0-9][ABD-HJLNP-UW-Z]{2})|(GIR)\s?(0AA))$/i.test( value ); return this.optional( element ) || /^((([A-PR-UWYZ][0-9])|([A-PR-UWYZ][0-9][0-9])|([A-PR-UWYZ][A-HK-Y][0-9])|([A-PR-UWYZ][A-HK-Y][0-9][0-9])|([A-PR-UWYZ][0-9][A-HJKSTUW])|([A-PR-UWYZ][A-HK-Y][0-9][ABEHMNPRVWXY]))\s?([0-9][ABD-HJLNP-UW-Z]{2})|(GIR)\s?(0AA))$/i.test( value );
}, "Please specify a valid UK postcode" ); }, "Please specify a valid UK postcode." );
/* /*
* Lets you say "at least X inputs that match selector Y must be filled." * Lets you say "at least X inputs that match selector Y must be filled."
@ -1072,24 +1426,24 @@ $.validator.addMethod( "stateUS", function( value, element, options ) {
regex = caseSensitive ? new RegExp( regex ) : new RegExp( regex, "i" ); regex = caseSensitive ? new RegExp( regex ) : new RegExp( regex, "i" );
return this.optional( element ) || regex.test( value ); return this.optional( element ) || regex.test( value );
}, "Please specify a valid state" ); }, "Please specify a valid state." );
// TODO check if value starts with <, otherwise don't try stripping anything // TODO check if value starts with <, otherwise don't try stripping anything
$.validator.addMethod( "strippedminlength", function( value, element, param ) { $.validator.addMethod( "strippedminlength", function( value, element, param ) {
return $( value ).text().length >= param; return $( value ).text().length >= param;
}, $.validator.format( "Please enter at least {0} characters" ) ); }, $.validator.format( "Please enter at least {0} characters." ) );
$.validator.addMethod( "time", function( value, element ) { $.validator.addMethod( "time", function( value, element ) {
return this.optional( element ) || /^([01]\d|2[0-3]|[0-9])(:[0-5]\d){1,2}$/.test( value ); return this.optional( element ) || /^([01]\d|2[0-3]|[0-9])(:[0-5]\d){1,2}$/.test( value );
}, "Please enter a valid time, between 00:00 and 23:59" ); }, "Please enter a valid time, between 00:00 and 23:59." );
$.validator.addMethod( "time12h", function( value, element ) { $.validator.addMethod( "time12h", function( value, element ) {
return this.optional( element ) || /^((0?[1-9]|1[012])(:[0-5]\d){1,2}(\ ?[AP]M))$/i.test( value ); return this.optional( element ) || /^((0?[1-9]|1[012])(:[0-5]\d){1,2}(\ ?[AP]M))$/i.test( value );
}, "Please enter a valid time in 12-hour am/pm format" ); }, "Please enter a valid time in 12-hour am/pm format." );
// Same as url, but TLD is optional // Same as url, but TLD is optional
$.validator.addMethod( "url2", function( value, element ) { $.validator.addMethod( "url2", function( value, element ) {
return this.optional( element ) || /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)*(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test( value ); return this.optional( element ) || /^(?:(?:(?:https?|ftp):)?\/\/)(?:(?:[^\]\[?\/<~#`!@$^&*()+=}|:";',>{ ]|%[0-9A-Fa-f]{2})+(?::(?:[^\]\[?\/<~#`!@$^&*()+=}|:";',>{ ]|%[0-9A-Fa-f]{2})*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z0-9\u00a1-\uffff][a-z0-9\u00a1-\uffff_-]{0,62})?[a-z0-9\u00a1-\uffff]\.)+(?:[a-z\u00a1-\uffff]{2,}\.?)|(?:(?:[a-z0-9\u00a1-\uffff][a-z0-9\u00a1-\uffff_-]{0,62})?[a-z0-9\u00a1-\uffff])|(?:(?:[a-z0-9\u00a1-\uffff][a-z0-9\u00a1-\uffff_-]{0,62}\.)))(?::\d{2,5})?(?:[/?#]\S*)?$/i.test( value );
}, $.validator.messages.url ); }, $.validator.messages.url );
/** /**
@ -1149,10 +1503,10 @@ $.validator.addMethod( "vinUS", function( v ) {
$.validator.addMethod( "zipcodeUS", function( value, element ) { $.validator.addMethod( "zipcodeUS", function( value, element ) {
return this.optional( element ) || /^\d{5}(-\d{4})?$/.test( value ); return this.optional( element ) || /^\d{5}(-\d{4})?$/.test( value );
}, "The specified US ZIP Code is invalid" ); }, "The specified US ZIP Code is invalid." );
$.validator.addMethod( "ziprange", function( value, element ) { $.validator.addMethod( "ziprange", function( value, element ) {
return this.optional( element ) || /^90[2-5]\d\{2\}-\d{4}$/.test( value ); return this.optional( element ) || /^90[2-5]\d\{2\}-\d{4}$/.test( value );
}, "Your ZIP-code must be in the range 902xx-xxxx to 905xx-xxxx" ); }, "Your ZIP-code must be in the range 902xx-xxxx to 905xx-xxxx." );
return $; return $;
})); }));

File diff suppressed because one or more lines are too long

View File

@ -1,9 +1,9 @@
/*! /*!
* jQuery Validation Plugin v1.17.0 * jQuery Validation Plugin v1.19.5
* *
* https://jqueryvalidation.org/ * https://jqueryvalidation.org/
* *
* Copyright (c) 2017 Jörn Zaefferer * Copyright (c) 2022 Jörn Zaefferer
* Released under the MIT license * Released under the MIT license
*/ */
(function( factory ) { (function( factory ) {
@ -67,6 +67,7 @@ $.extend( $.fn, {
// Prevent form submit to be able to see console output // Prevent form submit to be able to see console output
event.preventDefault(); event.preventDefault();
} }
function handle() { function handle() {
var hidden, result; var hidden, result;
@ -82,7 +83,7 @@ $.extend( $.fn, {
.appendTo( validator.currentForm ); .appendTo( validator.currentForm );
} }
if ( validator.settings.submitHandler ) { if ( validator.settings.submitHandler && !validator.settings.debug ) {
result = validator.settings.submitHandler.call( validator, validator.currentForm, event ); result = validator.settings.submitHandler.call( validator, validator.currentForm, event );
if ( hidden ) { if ( hidden ) {
@ -142,6 +143,7 @@ $.extend( $.fn, {
// https://jqueryvalidation.org/rules/ // https://jqueryvalidation.org/rules/
rules: function( command, argument ) { rules: function( command, argument ) {
var element = this[ 0 ], var element = this[ 0 ],
isContentEditable = typeof this.attr( "contenteditable" ) !== "undefined" && this.attr( "contenteditable" ) !== "false",
settings, staticRules, existingRules, data, param, filtered; settings, staticRules, existingRules, data, param, filtered;
// If nothing is selected, return empty object; can't chain anyway // If nothing is selected, return empty object; can't chain anyway
@ -149,7 +151,7 @@ $.extend( $.fn, {
return; return;
} }
if ( !element.form && element.hasAttribute( "contenteditable" ) ) { if ( !element.form && isContentEditable ) {
element.form = this.closest( "form" )[ 0 ]; element.form = this.closest( "form" )[ 0 ];
element.name = this.attr( "name" ); element.name = this.attr( "name" );
} }
@ -214,18 +216,25 @@ $.extend( $.fn, {
} }
} ); } );
// JQuery trim is deprecated, provide a trim method based on String.prototype.trim
var trim = function( str ) {
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/trim#Polyfill
return str.replace( /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, "" );
};
// Custom selectors // Custom selectors
$.extend( $.expr.pseudos || $.expr[ ":" ], { // '|| $.expr[ ":" ]' here enables backwards compatibility to jQuery 1.7. Can be removed when dropping jQ 1.7.x support $.extend( $.expr.pseudos || $.expr[ ":" ], { // '|| $.expr[ ":" ]' here enables backwards compatibility to jQuery 1.7. Can be removed when dropping jQ 1.7.x support
// https://jqueryvalidation.org/blank-selector/ // https://jqueryvalidation.org/blank-selector/
blank: function( a ) { blank: function( a ) {
return !$.trim( "" + $( a ).val() ); return !trim( "" + $( a ).val() );
}, },
// https://jqueryvalidation.org/filled-selector/ // https://jqueryvalidation.org/filled-selector/
filled: function( a ) { filled: function( a ) {
var val = $( a ).val(); var val = $( a ).val();
return val !== null && !!$.trim( "" + val ); return val !== null && !!trim( "" + val );
}, },
// https://jqueryvalidation.org/unchecked-selector/ // https://jqueryvalidation.org/unchecked-selector/
@ -393,7 +402,8 @@ $.extend( $.validator, {
this.invalid = {}; this.invalid = {};
this.reset(); this.reset();
var groups = ( this.groups = {} ), var currentForm = this.currentForm,
groups = ( this.groups = {} ),
rules; rules;
$.each( this.settings.groups, function( key, value ) { $.each( this.settings.groups, function( key, value ) {
if ( typeof value === "string" ) { if ( typeof value === "string" ) {
@ -409,13 +419,20 @@ $.extend( $.validator, {
} ); } );
function delegate( event ) { function delegate( event ) {
var isContentEditable = typeof $( this ).attr( "contenteditable" ) !== "undefined" && $( this ).attr( "contenteditable" ) !== "false";
// Set form expando on contenteditable // Set form expando on contenteditable
if ( !this.form && this.hasAttribute( "contenteditable" ) ) { if ( !this.form && isContentEditable ) {
this.form = $( this ).closest( "form" )[ 0 ]; this.form = $( this ).closest( "form" )[ 0 ];
this.name = $( this ).attr( "name" ); this.name = $( this ).attr( "name" );
} }
// Ignore the element if it belongs to another form. This will happen mainly
// when setting the `form` attribute of an input to the id of another form.
if ( currentForm !== this.form ) {
return;
}
var validator = $.data( this.form, "validator" ), var validator = $.data( this.form, "validator" ),
eventType = "on" + event.type.replace( /^validate/, "" ), eventType = "on" + event.type.replace( /^validate/, "" ),
settings = validator.settings; settings = validator.settings;
@ -610,7 +627,7 @@ $.extend( $.validator, {
try { try {
$( this.findLastActive() || this.errorList.length && this.errorList[ 0 ].element || [] ) $( this.findLastActive() || this.errorList.length && this.errorList[ 0 ].element || [] )
.filter( ":visible" ) .filter( ":visible" )
.focus() .trigger( "focus" )
// Manually trigger focusin event; without it, focusin handler isn't called, findLastActive won't have anything to find // Manually trigger focusin event; without it, focusin handler isn't called, findLastActive won't have anything to find
.trigger( "focusin" ); .trigger( "focusin" );
@ -639,16 +656,23 @@ $.extend( $.validator, {
.not( this.settings.ignore ) .not( this.settings.ignore )
.filter( function() { .filter( function() {
var name = this.name || $( this ).attr( "name" ); // For contenteditable var name = this.name || $( this ).attr( "name" ); // For contenteditable
var isContentEditable = typeof $( this ).attr( "contenteditable" ) !== "undefined" && $( this ).attr( "contenteditable" ) !== "false";
if ( !name && validator.settings.debug && window.console ) { if ( !name && validator.settings.debug && window.console ) {
console.error( "%o has no name assigned", this ); console.error( "%o has no name assigned", this );
} }
// Set form expando on contenteditable // Set form expando on contenteditable
if ( this.hasAttribute( "contenteditable" ) ) { if ( isContentEditable ) {
this.form = $( this ).closest( "form" )[ 0 ]; this.form = $( this ).closest( "form" )[ 0 ];
this.name = name; this.name = name;
} }
// Ignore elements that belong to other/nested forms
if ( this.form !== validator.currentForm ) {
return false;
}
// Select only the first element for each name, and only those with rules specified // Select only the first element for each name, and only those with rules specified
if ( name in rulesCache || !validator.objectLength( $( this ).rules() ) ) { if ( name in rulesCache || !validator.objectLength( $( this ).rules() ) ) {
return false; return false;
@ -694,6 +718,7 @@ $.extend( $.validator, {
elementValue: function( element ) { elementValue: function( element ) {
var $element = $( element ), var $element = $( element ),
type = element.type, type = element.type,
isContentEditable = typeof $element.attr( "contenteditable" ) !== "undefined" && $element.attr( "contenteditable" ) !== "false",
val, idx; val, idx;
if ( type === "radio" || type === "checkbox" ) { if ( type === "radio" || type === "checkbox" ) {
@ -702,7 +727,7 @@ $.extend( $.validator, {
return element.validity.badInput ? "NaN" : $element.val(); return element.validity.badInput ? "NaN" : $element.val();
} }
if ( element.hasAttribute( "contenteditable" ) ) { if ( isContentEditable ) {
val = $element.text(); val = $element.text();
} else { } else {
val = $element.val(); val = $element.val();
@ -763,10 +788,6 @@ $.extend( $.validator, {
if ( normalizer ) { if ( normalizer ) {
val = normalizer.call( element, val ); val = normalizer.call( element, val );
if ( typeof val !== "string" ) {
throw new TypeError( "The normalizer should return a string value." );
}
// Delete the normalizer from rules to avoid treating it as a pre-defined method. // Delete the normalizer from rules to avoid treating it as a pre-defined method.
delete rules.normalizer; delete rules.normalizer;
} }
@ -1029,6 +1050,10 @@ $.extend( $.validator, {
// meta-characters that should be escaped in order to be used with JQuery // meta-characters that should be escaped in order to be used with JQuery
// as a literal part of a name/id or any selector. // as a literal part of a name/id or any selector.
escapeCssMeta: function( string ) { escapeCssMeta: function( string ) {
if ( string === undefined ) {
return "";
}
return string.replace( /([\\!"#$%&'()*+,./:;<=>?@\[\]^`{|}~])/g, "\\$1" ); return string.replace( /([\\!"#$%&'()*+,./:;<=>?@\[\]^`{|}~])/g, "\\$1" );
}, },
@ -1105,8 +1130,8 @@ $.extend( $.validator, {
} }
delete this.pending[ element.name ]; delete this.pending[ element.name ];
$( element ).removeClass( this.settings.pendingClass ); $( element ).removeClass( this.settings.pendingClass );
if ( valid && this.pendingRequest === 0 && this.formSubmitted && this.form() ) { if ( valid && this.pendingRequest === 0 && this.formSubmitted && this.form() && this.pendingRequest === 0 ) {
$( this.currentForm ).submit(); $( this.currentForm ).trigger( "submit" );
// Remove the hidden input that was used as a replacement for the // Remove the hidden input that was used as a replacement for the
// missing submit button. The hidden input is added by `handle()` // missing submit button. The hidden input is added by `handle()`
@ -1142,7 +1167,19 @@ $.extend( $.validator, {
.removeData( "validator" ) .removeData( "validator" )
.find( ".validate-equalTo-blur" ) .find( ".validate-equalTo-blur" )
.off( ".validate-equalTo" ) .off( ".validate-equalTo" )
.removeClass( "validate-equalTo-blur" ); .removeClass( "validate-equalTo-blur" )
.find( ".validate-lessThan-blur" )
.off( ".validate-lessThan" )
.removeClass( "validate-lessThan-blur" )
.find( ".validate-lessThanEqual-blur" )
.off( ".validate-lessThanEqual" )
.removeClass( "validate-lessThanEqual-blur" )
.find( ".validate-greaterThanEqual-blur" )
.off( ".validate-greaterThanEqual" )
.removeClass( "validate-greaterThanEqual-blur" )
.find( ".validate-greaterThan-blur" )
.off( ".validate-greaterThan" )
.removeClass( "validate-greaterThan-blur" );
} }
}, },
@ -1199,7 +1236,7 @@ $.extend( $.validator, {
// Exception: the jquery validate 'range' method // Exception: the jquery validate 'range' method
// does not test for the html5 'range' type // does not test for the html5 'range' type
rules[ method ] = true; rules[ type === "date" ? "dateISO" : method ] = true;
} }
}, },
@ -1246,6 +1283,12 @@ $.extend( $.validator, {
for ( method in $.validator.methods ) { for ( method in $.validator.methods ) {
value = $element.data( "rule" + method.charAt( 0 ).toUpperCase() + method.substring( 1 ).toLowerCase() ); value = $element.data( "rule" + method.charAt( 0 ).toUpperCase() + method.substring( 1 ).toLowerCase() );
// Cast empty attributes like `data-rule-required` to `true`
if ( value === "" ) {
value = true;
}
this.normalizeAttributeRule( rules, type, method, value ); this.normalizeAttributeRule( rules, type, method, value );
} }
return rules; return rules;
@ -1292,7 +1335,7 @@ $.extend( $.validator, {
// Evaluate parameters // Evaluate parameters
$.each( rules, function( rule, parameter ) { $.each( rules, function( rule, parameter ) {
rules[ rule ] = $.isFunction( parameter ) && rule !== "normalizer" ? parameter( element ) : parameter; rules[ rule ] = typeof parameter === "function" && rule !== "normalizer" ? parameter( element ) : parameter;
} ); } );
// Clean number parameters // Clean number parameters
@ -1304,7 +1347,7 @@ $.extend( $.validator, {
$.each( [ "rangelength", "range" ], function() { $.each( [ "rangelength", "range" ], function() {
var parts; var parts;
if ( rules[ this ] ) { if ( rules[ this ] ) {
if ( $.isArray( rules[ this ] ) ) { if ( Array.isArray( rules[ this ] ) ) {
rules[ this ] = [ Number( rules[ this ][ 0 ] ), Number( rules[ this ][ 1 ] ) ]; rules[ this ] = [ Number( rules[ this ][ 0 ] ), Number( rules[ this ][ 1 ] ) ];
} else if ( typeof rules[ this ] === "string" ) { } else if ( typeof rules[ this ] === "string" ) {
parts = rules[ this ].replace( /[\[\]]/g, "" ).split( /[\s,]+/ ); parts = rules[ this ].replace( /[\[\]]/g, "" ).split( /[\s,]+/ );
@ -1371,7 +1414,7 @@ $.extend( $.validator, {
if ( this.checkable( element ) ) { if ( this.checkable( element ) ) {
return this.getLength( value, element ) > 0; return this.getLength( value, element ) > 0;
} }
return value.length > 0; return value !== undefined && value !== null && value.length > 0;
}, },
// https://jqueryvalidation.org/email-method/ // https://jqueryvalidation.org/email-method/
@ -1391,13 +1434,30 @@ $.extend( $.validator, {
// https://gist.github.com/dperini/729294 // https://gist.github.com/dperini/729294
// see also https://mathiasbynens.be/demo/url-regex // see also https://mathiasbynens.be/demo/url-regex
// modified to allow protocol-relative URLs // modified to allow protocol-relative URLs
return this.optional( element ) || /^(?:(?:(?:https?|ftp):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})).?)(?::\d{2,5})?(?:[/?#]\S*)?$/i.test( value ); return this.optional( element ) || /^(?:(?:(?:https?|ftp):)?\/\/)(?:(?:[^\]\[?\/<~#`!@$^&*()+=}|:";',>{ ]|%[0-9A-Fa-f]{2})+(?::(?:[^\]\[?\/<~#`!@$^&*()+=}|:";',>{ ]|%[0-9A-Fa-f]{2})*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z0-9\u00a1-\uffff][a-z0-9\u00a1-\uffff_-]{0,62})?[a-z0-9\u00a1-\uffff]\.)+(?:[a-z\u00a1-\uffff]{2,}\.?))(?::\d{2,5})?(?:[/?#]\S*)?$/i.test( value );
}, },
// https://jqueryvalidation.org/date-method/ // https://jqueryvalidation.org/date-method/
date: function( value, element ) { date: ( function() {
var called = false;
return function( value, element ) {
if ( !called ) {
called = true;
if ( this.settings.debug && window.console ) {
console.warn(
"The `date` method is deprecated and will be removed in version '2.0.0'.\n" +
"Please don't use it, since it relies on the Date constructor, which\n" +
"behaves very differently across browsers and locales. Use `dateISO`\n" +
"instead or one of the locale specific methods in `localizations/`\n" +
"and `additional-methods.js`."
);
}
}
return this.optional( element ) || !/Invalid|NaN/.test( new Date( value ).toString() ); return this.optional( element ) || !/Invalid|NaN/.test( new Date( value ).toString() );
}, };
}() ),
// https://jqueryvalidation.org/dateISO-method/ // https://jqueryvalidation.org/dateISO-method/
dateISO: function( value, element ) { dateISO: function( value, element ) {
@ -1416,19 +1476,19 @@ $.extend( $.validator, {
// https://jqueryvalidation.org/minlength-method/ // https://jqueryvalidation.org/minlength-method/
minlength: function( value, element, param ) { minlength: function( value, element, param ) {
var length = $.isArray( value ) ? value.length : this.getLength( value, element ); var length = Array.isArray( value ) ? value.length : this.getLength( value, element );
return this.optional( element ) || length >= param; return this.optional( element ) || length >= param;
}, },
// https://jqueryvalidation.org/maxlength-method/ // https://jqueryvalidation.org/maxlength-method/
maxlength: function( value, element, param ) { maxlength: function( value, element, param ) {
var length = $.isArray( value ) ? value.length : this.getLength( value, element ); var length = Array.isArray( value ) ? value.length : this.getLength( value, element );
return this.optional( element ) || length <= param; return this.optional( element ) || length <= param;
}, },
// https://jqueryvalidation.org/rangelength-method/ // https://jqueryvalidation.org/rangelength-method/
rangelength: function( value, element, param ) { rangelength: function( value, element, param ) {
var length = $.isArray( value ) ? value.length : this.getLength( value, element ); var length = Array.isArray( value ) ? value.length : this.getLength( value, element );
return this.optional( element ) || ( length >= param[ 0 ] && length <= param[ 1 ] ); return this.optional( element ) || ( length >= param[ 0 ] && length <= param[ 1 ] );
}, },

File diff suppressed because one or more lines are too long

View File

@ -1,13 +1,5 @@
Copyright JS Foundation and other contributors, https://js.foundation/
This software consists of voluntary contributions made by many Copyright OpenJS Foundation and other contributors, https://openjsf.org/
individuals. For exact contribution history, see the revision history
available at https://github.com/jquery/jquery
The following license applies to all parts of this software except as
documented below:
====
Permission is hereby granted, free of charge, to any person obtaining Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the a copy of this software and associated documentation files (the
@ -27,10 +19,3 @@ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
====
All files located in the node_modules and external directories are
externally maintained libraries used by this software which have their
own licenses; we recommend you read them, as their terms may differ from
the terms above.

View File

@ -1,15 +1,15 @@
/*! /*!
* jQuery JavaScript Library v3.5.1 * jQuery JavaScript Library v3.6.0
* https://jquery.com/ * https://jquery.com/
* *
* Includes Sizzle.js * Includes Sizzle.js
* https://sizzlejs.com/ * https://sizzlejs.com/
* *
* Copyright JS Foundation and other contributors * Copyright OpenJS Foundation and other contributors
* Released under the MIT license * Released under the MIT license
* https://jquery.org/license * https://jquery.org/license
* *
* Date: 2020-05-04T22:49Z * Date: 2021-03-02T17:08Z
*/ */
( function( global, factory ) { ( function( global, factory ) {
@ -80,7 +80,11 @@ var isFunction = function isFunction( obj ) {
// In some browsers, typeof returns "function" for HTML <object> elements // In some browsers, typeof returns "function" for HTML <object> elements
// (i.e., `typeof document.createElement( "object" ) === "function"`). // (i.e., `typeof document.createElement( "object" ) === "function"`).
// We don't want to classify *any* DOM node as a function. // We don't want to classify *any* DOM node as a function.
return typeof obj === "function" && typeof obj.nodeType !== "number"; // Support: QtWeb <=3.8.5, WebKit <=534.34, wkhtmltopdf tool <=0.12.5
// Plus for old WebKit, typeof returns "function" for HTML collections
// (e.g., `typeof document.getElementsByTagName("div") === "function"`). (gh-4756)
return typeof obj === "function" && typeof obj.nodeType !== "number" &&
typeof obj.item !== "function";
}; };
@ -147,7 +151,7 @@ function toType( obj ) {
var var
version = "3.5.1", version = "3.6.0",
// Define a local copy of jQuery // Define a local copy of jQuery
jQuery = function( selector, context ) { jQuery = function( selector, context ) {
@ -496,9 +500,9 @@ if ( typeof Symbol === "function" ) {
// Populate the class2type map // Populate the class2type map
jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ),
function( _i, name ) { function( _i, name ) {
class2type[ "[object " + name + "]" ] = name.toLowerCase(); class2type[ "[object " + name + "]" ] = name.toLowerCase();
} ); } );
function isArrayLike( obj ) { function isArrayLike( obj ) {
@ -518,14 +522,14 @@ function isArrayLike( obj ) {
} }
var Sizzle = var Sizzle =
/*! /*!
* Sizzle CSS Selector Engine v2.3.5 * Sizzle CSS Selector Engine v2.3.6
* https://sizzlejs.com/ * https://sizzlejs.com/
* *
* Copyright JS Foundation and other contributors * Copyright JS Foundation and other contributors
* Released under the MIT license * Released under the MIT license
* https://js.foundation/ * https://js.foundation/
* *
* Date: 2020-03-14 * Date: 2021-02-16
*/ */
( function( window ) { ( function( window ) {
var i, var i,
@ -1108,8 +1112,8 @@ support = Sizzle.support = {};
* @returns {Boolean} True iff elem is a non-HTML XML node * @returns {Boolean} True iff elem is a non-HTML XML node
*/ */
isXML = Sizzle.isXML = function( elem ) { isXML = Sizzle.isXML = function( elem ) {
var namespace = elem.namespaceURI, var namespace = elem && elem.namespaceURI,
docElem = ( elem.ownerDocument || elem ).documentElement; docElem = elem && ( elem.ownerDocument || elem ).documentElement;
// Support: IE <=8 // Support: IE <=8
// Assume HTML when documentElement doesn't yet exist, such as inside loading iframes // Assume HTML when documentElement doesn't yet exist, such as inside loading iframes
@ -3026,7 +3030,7 @@ function nodeName( elem, name ) {
return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
}; }
var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i ); var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i );
@ -3997,8 +4001,8 @@ jQuery.extend( {
resolveContexts = Array( i ), resolveContexts = Array( i ),
resolveValues = slice.call( arguments ), resolveValues = slice.call( arguments ),
// the master Deferred // the primary Deferred
master = jQuery.Deferred(), primary = jQuery.Deferred(),
// subordinate callback factory // subordinate callback factory
updateFunc = function( i ) { updateFunc = function( i ) {
@ -4006,30 +4010,30 @@ jQuery.extend( {
resolveContexts[ i ] = this; resolveContexts[ i ] = this;
resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;
if ( !( --remaining ) ) { if ( !( --remaining ) ) {
master.resolveWith( resolveContexts, resolveValues ); primary.resolveWith( resolveContexts, resolveValues );
} }
}; };
}; };
// Single- and empty arguments are adopted like Promise.resolve // Single- and empty arguments are adopted like Promise.resolve
if ( remaining <= 1 ) { if ( remaining <= 1 ) {
adoptValue( singleValue, master.done( updateFunc( i ) ).resolve, master.reject, adoptValue( singleValue, primary.done( updateFunc( i ) ).resolve, primary.reject,
!remaining ); !remaining );
// Use .then() to unwrap secondary thenables (cf. gh-3000) // Use .then() to unwrap secondary thenables (cf. gh-3000)
if ( master.state() === "pending" || if ( primary.state() === "pending" ||
isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) { isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) {
return master.then(); return primary.then();
} }
} }
// Multiple arguments are aggregated like Promise.all array elements // Multiple arguments are aggregated like Promise.all array elements
while ( i-- ) { while ( i-- ) {
adoptValue( resolveValues[ i ], updateFunc( i ), master.reject ); adoptValue( resolveValues[ i ], updateFunc( i ), primary.reject );
} }
return master.promise(); return primary.promise();
} }
} ); } );
@ -5089,10 +5093,7 @@ function buildFragment( elems, context, scripts, selection, ignored ) {
} }
var var rtypenamespace = /^([^.]*)(?:\.(.+)|)/;
rkeyEvent = /^key/,
rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/,
rtypenamespace = /^([^.]*)(?:\.(.+)|)/;
function returnTrue() { function returnTrue() {
return true; return true;
@ -5656,7 +5657,13 @@ function leverageNative( el, type, expectSync ) {
// Cancel the outer synthetic event // Cancel the outer synthetic event
event.stopImmediatePropagation(); event.stopImmediatePropagation();
event.preventDefault(); event.preventDefault();
return result.value;
// Support: Chrome 86+
// In Chrome, if an element having a focusout handler is blurred by
// clicking outside of it, it invokes the handler synchronously. If
// that handler calls `.remove()` on the element, the data is cleared,
// leaving `result` undefined. We need to guard against this.
return result && result.value;
} }
// If this is an inner synthetic event for an event with a bubbling surrogate // If this is an inner synthetic event for an event with a bubbling surrogate
@ -5821,34 +5828,7 @@ jQuery.each( {
targetTouches: true, targetTouches: true,
toElement: true, toElement: true,
touches: true, touches: true,
which: true
which: function( event ) {
var button = event.button;
// Add which for key events
if ( event.which == null && rkeyEvent.test( event.type ) ) {
return event.charCode != null ? event.charCode : event.keyCode;
}
// Add which for click: 1 === left; 2 === middle; 3 === right
if ( !event.which && button !== undefined && rmouseEvent.test( event.type ) ) {
if ( button & 1 ) {
return 1;
}
if ( button & 2 ) {
return 3;
}
if ( button & 4 ) {
return 2;
}
return 0;
}
return event.which;
}
}, jQuery.event.addProp ); }, jQuery.event.addProp );
jQuery.each( { focus: "focusin", blur: "focusout" }, function( type, delegateType ) { jQuery.each( { focus: "focusin", blur: "focusout" }, function( type, delegateType ) {
@ -5874,6 +5854,12 @@ jQuery.each( { focus: "focusin", blur: "focusout" }, function( type, delegateTyp
return true; return true;
}, },
// Suppress native focus or blur as it's already being fired
// in leverageNative.
_default: function() {
return true;
},
delegateType: delegateType delegateType: delegateType
}; };
} ); } );
@ -6541,6 +6527,10 @@ var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" );
// set in CSS while `offset*` properties report correct values. // set in CSS while `offset*` properties report correct values.
// Behavior in IE 9 is more subtle than in newer versions & it passes // Behavior in IE 9 is more subtle than in newer versions & it passes
// some versions of this test; make sure not to make it pass there! // some versions of this test; make sure not to make it pass there!
//
// Support: Firefox 70+
// Only Firefox includes border widths
// in computed dimensions. (gh-4529)
reliableTrDimensions: function() { reliableTrDimensions: function() {
var table, tr, trChild, trStyle; var table, tr, trChild, trStyle;
if ( reliableTrDimensionsVal == null ) { if ( reliableTrDimensionsVal == null ) {
@ -6548,17 +6538,32 @@ var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" );
tr = document.createElement( "tr" ); tr = document.createElement( "tr" );
trChild = document.createElement( "div" ); trChild = document.createElement( "div" );
table.style.cssText = "position:absolute;left:-11111px"; table.style.cssText = "position:absolute;left:-11111px;border-collapse:separate";
tr.style.cssText = "border:1px solid";
// Support: Chrome 86+
// Height set through cssText does not get applied.
// Computed height then comes back as 0.
tr.style.height = "1px"; tr.style.height = "1px";
trChild.style.height = "9px"; trChild.style.height = "9px";
// Support: Android 8 Chrome 86+
// In our bodyBackground.html iframe,
// display for all div elements is set to "inline",
// which causes a problem only in Android 8 Chrome 86.
// Ensuring the div is display: block
// gets around this issue.
trChild.style.display = "block";
documentElement documentElement
.appendChild( table ) .appendChild( table )
.appendChild( tr ) .appendChild( tr )
.appendChild( trChild ); .appendChild( trChild );
trStyle = window.getComputedStyle( tr ); trStyle = window.getComputedStyle( tr );
reliableTrDimensionsVal = parseInt( trStyle.height ) > 3; reliableTrDimensionsVal = ( parseInt( trStyle.height, 10 ) +
parseInt( trStyle.borderTopWidth, 10 ) +
parseInt( trStyle.borderBottomWidth, 10 ) ) === tr.offsetHeight;
documentElement.removeChild( table ); documentElement.removeChild( table );
} }
@ -7761,6 +7766,7 @@ jQuery.fn.extend( {
anim.stop( true ); anim.stop( true );
} }
}; };
doAnimation.finish = doAnimation; doAnimation.finish = doAnimation;
return empty || optall.queue === false ? return empty || optall.queue === false ?
@ -8707,9 +8713,7 @@ jQuery.extend( jQuery.event, {
special.bindType || type; special.bindType || type;
// jQuery handler // jQuery handler
handle = ( handle = ( dataPriv.get( cur, "events" ) || Object.create( null ) )[ event.type ] &&
dataPriv.get( cur, "events" ) || Object.create( null )
)[ event.type ] &&
dataPriv.get( cur, "handle" ); dataPriv.get( cur, "handle" );
if ( handle ) { if ( handle ) {
handle.apply( cur, data ); handle.apply( cur, data );
@ -8856,7 +8860,7 @@ var rquery = ( /\?/ );
// Cross-browser xml parsing // Cross-browser xml parsing
jQuery.parseXML = function( data ) { jQuery.parseXML = function( data ) {
var xml; var xml, parserErrorElem;
if ( !data || typeof data !== "string" ) { if ( !data || typeof data !== "string" ) {
return null; return null;
} }
@ -8865,12 +8869,17 @@ jQuery.parseXML = function( data ) {
// IE throws on parseFromString with invalid input. // IE throws on parseFromString with invalid input.
try { try {
xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" ); xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" );
} catch ( e ) { } catch ( e ) {}
xml = undefined;
}
if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) { parserErrorElem = xml && xml.getElementsByTagName( "parsererror" )[ 0 ];
jQuery.error( "Invalid XML: " + data ); if ( !xml || parserErrorElem ) {
jQuery.error( "Invalid XML: " + (
parserErrorElem ?
jQuery.map( parserErrorElem.childNodes, function( el ) {
return el.textContent;
} ).join( "\n" ) :
data
) );
} }
return xml; return xml;
}; };
@ -8971,16 +8980,14 @@ jQuery.fn.extend( {
// Can add propHook for "elements" to filter or add form elements // Can add propHook for "elements" to filter or add form elements
var elements = jQuery.prop( this, "elements" ); var elements = jQuery.prop( this, "elements" );
return elements ? jQuery.makeArray( elements ) : this; return elements ? jQuery.makeArray( elements ) : this;
} ) } ).filter( function() {
.filter( function() {
var type = this.type; var type = this.type;
// Use .is( ":disabled" ) so that fieldset[disabled] works // Use .is( ":disabled" ) so that fieldset[disabled] works
return this.name && !jQuery( this ).is( ":disabled" ) && return this.name && !jQuery( this ).is( ":disabled" ) &&
rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) && rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&
( this.checked || !rcheckableType.test( type ) ); ( this.checked || !rcheckableType.test( type ) );
} ) } ).map( function( _i, elem ) {
.map( function( _i, elem ) {
var val = jQuery( this ).val(); var val = jQuery( this ).val();
if ( val == null ) { if ( val == null ) {
@ -9033,7 +9040,8 @@ var
// Anchor tag for parsing the document origin // Anchor tag for parsing the document origin
originAnchor = document.createElement( "a" ); originAnchor = document.createElement( "a" );
originAnchor.href = location.href;
originAnchor.href = location.href;
// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport // Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
function addToPrefiltersOrTransports( structure ) { function addToPrefiltersOrTransports( structure ) {
@ -9727,8 +9735,10 @@ jQuery.extend( {
response = ajaxHandleResponses( s, jqXHR, responses ); response = ajaxHandleResponses( s, jqXHR, responses );
} }
// Use a noop converter for missing script // Use a noop converter for missing script but not if jsonp
if ( !isSuccess && jQuery.inArray( "script", s.dataTypes ) > -1 ) { if ( !isSuccess &&
jQuery.inArray( "script", s.dataTypes ) > -1 &&
jQuery.inArray( "json", s.dataTypes ) < 0 ) {
s.converters[ "text script" ] = function() {}; s.converters[ "text script" ] = function() {};
} }
@ -10466,12 +10476,6 @@ jQuery.offset = {
options.using.call( elem, props ); options.using.call( elem, props );
} else { } else {
if ( typeof props.top === "number" ) {
props.top += "px";
}
if ( typeof props.left === "number" ) {
props.left += "px";
}
curElem.css( props ); curElem.css( props );
} }
} }
@ -10640,8 +10644,11 @@ jQuery.each( [ "top", "left" ], function( _i, prop ) {
// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods // Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
jQuery.each( { Height: "height", Width: "width" }, function( name, type ) { jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name }, jQuery.each( {
function( defaultExtra, funcName ) { padding: "inner" + name,
content: type,
"": "outer" + name
}, function( defaultExtra, funcName ) {
// Margin is only for outerHeight, outerWidth // Margin is only for outerHeight, outerWidth
jQuery.fn[ funcName ] = function( margin, value ) { jQuery.fn[ funcName ] = function( margin, value ) {
@ -10726,7 +10733,8 @@ jQuery.fn.extend( {
} }
} ); } );
jQuery.each( ( "blur focus focusin focusout resize scroll click dblclick " + jQuery.each(
( "blur focus focusin focusout resize scroll click dblclick " +
"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
"change select submit keydown keypress keyup contextmenu" ).split( " " ), "change select submit keydown keypress keyup contextmenu" ).split( " " ),
function( _i, name ) { function( _i, name ) {
@ -10737,7 +10745,8 @@ jQuery.each( ( "blur focus focusin focusout resize scroll click dblclick " +
this.on( name, null, data, fn ) : this.on( name, null, data, fn ) :
this.trigger( name ); this.trigger( name );
}; };
} ); }
);

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 @@
using SushiBarDataModels;
namespace SushiBarContracts.BindingModel
{
public class ClientBindingModel : IClientModel
{
public int Id { get; set; }
public string ClientFIO { get; set; } = string.Empty;
public string Email { get; set; } = string.Empty;
public string Password { get; set; } = string.Empty;
}
}

View File

@ -0,0 +1,20 @@
using SushiBarContracts.BindingModel;
using SushiBarContracts.SearchModel;
using SushiBarContracts.ViewModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SushiBarContracts.BusinessLogicsContracts
{
public interface IClientLogic
{
List<ClientViewModel>? ReadList(ClientSearchModel? model);
ClientViewModel? ReadElement(ClientSearchModel model);
bool Create(ClientBindingModel model);
bool Update(ClientBindingModel model);
bool Delete(ClientBindingModel model);
}
}

View File

@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SushiBarContracts.SearchModel
{
public class ClientSearchModel
{
public int? Id { get; set; }
public string? ClientFIO { get; set; }
public string? Email { get; set; }
public string? Password { get; set; }
}
}

View File

@ -0,0 +1,21 @@
using SushiBarContracts.BindingModel;
using SushiBarContracts.SearchModel;
using SushiBarContracts.ViewModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SushiBarContracts.StoragesContracts
{
public interface IClientStorage
{
List<ClientViewModel> GetFullList();
List<ClientViewModel> GetFilteredList(ClientSearchModel model);
ClientViewModel? GetElement(ClientSearchModel model);
ClientViewModel? Insert(ClientBindingModel model);
ClientViewModel? Update(ClientBindingModel model);
ClientViewModel? Delete(ClientBindingModel model);
}
}

View File

@ -0,0 +1,26 @@
using SushiBarDataModels;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SushiBarContracts.ViewModels
{
public class ClientViewModel : IClientModel
{
public int Id { get; set; }
[DisplayName("ФИО Клиента")]
public string ClientFIO { get; set; } = string.Empty;
[DisplayName("Логин (эл. почтаы)")]
public string Email { get; set; } = string.Empty;
[DisplayName("Пароль")]
public string Password { get; set; } = string.Empty;
}
}

View File

@ -0,0 +1,9 @@
namespace SushiBarDataModels
{
public interface IClientModel : IId
{
string ClientFIO { get; }
string Email { get; }
string Password { get; }
}
}

View File

@ -0,0 +1,84 @@
using Microsoft.IdentityModel.Tokens;
using SushiBarContracts.BindingModel;
using SushiBarContracts.SearchModel;
using SushiBarContracts.StoragesContracts;
using SushiBarContracts.ViewModels;
using SushiBarDatabaseImplement.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SushiBarDatabaseImplement.Implements
{
public class ClientStorage : IClientStorage
{
public ClientViewModel? Insert(ClientBindingModel model)
{
using var context = new SushiBarDatabase();
var newClient = Client.Create(model);
if (newClient == null) { return null; }
context.Clients.Add(newClient);
context.SaveChanges();
return newClient.GetViewModel;
}
public ClientViewModel? Update(ClientBindingModel model)
{
using var context = new SushiBarDatabase();
var client = context.Clients.FirstOrDefault(x => x.Id == model.Id);
if (client == null) { return null; };
client.Update(model);
context.SaveChanges();
return client.GetViewModel;
}
public ClientViewModel? Delete(ClientBindingModel model)
{
using var context = new SushiBarDatabase();
var element = context.Clients.FirstOrDefault(rec => rec.Id == model.Id);
if (element != null)
{
context.Clients.Remove(element);
context.SaveChanges();
return element.GetViewModel;
}
return null;
}
public ClientViewModel? GetElement(ClientSearchModel model)
{
return GetFilteredList(model).FirstOrDefault();
}
public List<ClientViewModel> GetFilteredList(ClientSearchModel model)
{
using var context = new SushiBarDatabase();
var clients = context.Clients.Select(x => x.GetViewModel).ToList();
if (model.Id.HasValue)
{
clients = clients.Where(x => x.Id == model.Id.Value).ToList();
}
if (!model.Email.IsNullOrEmpty())
{
clients = clients.Where(x => x.Email == model.Email).ToList();
}
if (!model.Password.IsNullOrEmpty())
{
clients = clients.Where(x => x.Password == model.Password).ToList();
}
if (!model.ClientFIO.IsNullOrEmpty())
{
clients = clients.Where(x => x.ClientFIO == model.ClientFIO).ToList();
}
return clients;
}
public List<ClientViewModel> GetFullList()
{
using var context = new SushiBarDatabase();
return context.Clients.Select(x => x.GetViewModel).ToList();
}
}
}

View File

@ -0,0 +1,58 @@
using SushiBarContracts.BindingModel;
using SushiBarContracts.ViewModels;
using System.ComponentModel.DataAnnotations.Schema;
using System.ComponentModel.DataAnnotations;
using SushiBarDataModels;
namespace SushiBarDatabaseImplement.Models
{
public class Client : IClientModel
{
public int Id { get; private set; }
[Required]
public string ClientFIO { get; private set; } = string.Empty;
[Required]
public string Email { get; private set; } = string.Empty;
[Required]
public string Password { get; private set; } = string.Empty;
[Required]
[ForeignKey("ClientId")]
public virtual List<Order> Orders { get; set; } = new();
public static Client? Create(ClientBindingModel? model)
{
if (model == null)
{
return null;
}
return new Client()
{
Id = model.Id,
ClientFIO = model.ClientFIO,
Email = model.Email,
Password = model.Password
};
}
public void Update(ClientBindingModel? model)
{
if (model == null) return;
ClientFIO = model.ClientFIO;
Email = model.Email;
Password = model.Password;
}
public ClientViewModel GetViewModel => new()
{
Id = Id,
ClientFIO = ClientFIO,
Email = Email,
Password = Password
};
}
}

View File

@ -21,5 +21,6 @@ namespace SushiBarDatabaseImplement
public virtual DbSet<SushiIngredient> SushiIngredients { set; get; } public virtual DbSet<SushiIngredient> SushiIngredients { set; get; }
public virtual DbSet<Order> Orders { set; get; } public virtual DbSet<Order> Orders { set; get; }
public virtual DbSet<Client> Clients { set; get; }
} }
} }

View File

@ -9,9 +9,12 @@ namespace SushiBarFileImplement
private readonly string IngredientFileName = "Ingredient.xml"; private readonly string IngredientFileName = "Ingredient.xml";
private readonly string OrderFileName = "Order.xml"; private readonly string OrderFileName = "Order.xml";
private readonly string SushiFileName = "Sushi.xml"; private readonly string SushiFileName = "Sushi.xml";
private readonly string ClientFileName = "Client.xml";
public List<Ingredient> Ingredients { get; private set; } public List<Ingredient> Ingredients { get; private set; }
public List<Order> Orders { get; private set; } public List<Order> Orders { get; private set; }
public List<Sushi> ListSushi { get; private set; } public List<Sushi> ListSushi { get; private set; }
public List<Client> Clients { get; private set; }
public static DataFileSingleton GetInstance() public static DataFileSingleton GetInstance()
{ {
if (instance == null) if (instance == null)
@ -25,11 +28,13 @@ namespace SushiBarFileImplement
public void SaveListSushi() => SaveData(ListSushi, SushiFileName, public void SaveListSushi() => SaveData(ListSushi, SushiFileName,
"ListSushi", x => x.GetXElement); "ListSushi", x => x.GetXElement);
public void SaveOrders() => SaveData(Orders, OrderFileName, "Orders", x => x.GetXElement); public void SaveOrders() => SaveData(Orders, OrderFileName, "Orders", x => x.GetXElement);
public void SaveClients() => SaveData(Clients, ClientFileName, "Clients", x => x.GetXElement);
private DataFileSingleton() private DataFileSingleton()
{ {
Ingredients = LoadData(IngredientFileName, "Ingredient", x => Ingredient.Create(x)!)!; Ingredients = LoadData(IngredientFileName, "Ingredient", x => Ingredient.Create(x)!)!;
ListSushi = LoadData(SushiFileName, "Sushi", x => Sushi.Create(x)!)!; ListSushi = LoadData(SushiFileName, "Sushi", x => Sushi.Create(x)!)!;
Orders = LoadData(OrderFileName, "Order", x => Order.Create(x)!)!; Orders = LoadData(OrderFileName, "Order", x => Order.Create(x)!)!;
Clients = LoadData(ClientFileName, "Client", x => Client.Create(x)!)!;
} }
private static List<T>? LoadData<T>(string filename, string xmlNodeName, private static List<T>? LoadData<T>(string filename, string xmlNodeName,
Func<XElement, T> selectFunction) Func<XElement, T> selectFunction)

View File

@ -0,0 +1,71 @@
using SushiBarContracts.BindingModel;
using SushiBarContracts.SearchModel;
using SushiBarContracts.ViewModels;
using SushiBarFileImplement.Models;
namespace SushiBarFileImplement.Implements
{
public class ClientStorage
{
private readonly DataFileSingleton source;
public ClientStorage()
{
source = DataFileSingleton.GetInstance();
}
public List<ClientViewModel> GetFullList()
{
return source.Clients.Select(x => x.GetViewModel).ToList();
}
public List<ClientViewModel> GetFilteredList(ClientSearchModel model)
{
if (string.IsNullOrEmpty(model.Email))
{
return new();
}
return source.Clients.Where(x => x.Email.Contains(model.Email)).Select(x => x.GetViewModel).ToList();
}
public ClientViewModel? GetElement(ClientSearchModel model)
{
if (string.IsNullOrEmpty(model.Email) && !model.Id.HasValue)
{
return null;
}
return source.Clients.FirstOrDefault(x => (!string.IsNullOrEmpty(model.Email) &&
x.Email == model.Email) || (model.Id.HasValue && x.Id == model.Id))?.GetViewModel;
}
public ClientViewModel? Insert(ClientBindingModel model)
{
model.Id = source.Clients.Count > 0 ? source.Clients.Max(x => x.Id) + 1 : 1;
var newClient = Client.Create(model);
if (newClient == null)
{
return null;
}
source.Clients.Add(newClient);
source.SaveClients();
return newClient.GetViewModel;
}
public ClientViewModel? Update(ClientBindingModel model)
{
var client = source.Clients.FirstOrDefault(x => x.Id == model.Id);
if (client == null)
{
return null;
}
client.Update(model);
source.SaveClients();
return client.GetViewModel;
}
public ClientViewModel? Delete(ClientBindingModel model)
{
var element = source.Clients.FirstOrDefault(x => x.Id == model.Id);
if (element != null)
{
source.Clients.Remove(element);
source.SaveClients();
return element.GetViewModel;
}
return null;
}
}
}

View File

@ -0,0 +1,67 @@
using SushiBarContracts.BindingModel;
using SushiBarContracts.ViewModels;
using SushiBarDataModels;
using System.Xml.Linq;
namespace SushiBarFileImplement.Models
{
public class Client : IClientModel
{
public int Id { get; private set; }
public string ClientFIO { get; private set; } = string.Empty;
public string Email { get; private set; } = string.Empty;
public string Password { get; private set; } = string.Empty;
public static Client? Create(ClientBindingModel model)
{
if (model == null)
{
return null;
}
return new Client()
{
Id = model.Id,
ClientFIO = model.ClientFIO,
Email = model.Email,
Password = model.Password
};
}
public static Client? Create(XElement element)
{
if (element == null)
{
return null;
}
return new Client()
{
Id = Convert.ToInt32(element.Attribute("Id")!.Value),
ClientFIO = element.Element("ClientFIO")!.Value,
Email = element.Element("Email")!.Value,
Password = element.Element("Password")!.Value,
};
}
public void Update(ClientBindingModel model)
{
if (model == null)
{
return;
}
ClientFIO = model.ClientFIO;
Email = model.Email;
Password = model.Password;
}
public ClientViewModel GetViewModel => new()
{
Id = Id,
ClientFIO = ClientFIO,
Email = Email,
Password = Password
};
public XElement GetXElement =>
new("Client",
new XAttribute("Id", Id),
new XElement("ClientFIO", ClientFIO),
new XElement("Email", Email),
new XElement("Password", Password)
);
}
}

View File

@ -1,4 +1,5 @@
using SushiBarListImplement.Models; using SushiBarListImplement.Models;
using SushiBarListImplements.Models;
namespace SushiBarListImplement namespace SushiBarListImplement
{ {
@ -8,11 +9,13 @@ namespace SushiBarListImplement
public List<Ingredient> Ingredients { get; set; } public List<Ingredient> Ingredients { get; set; }
public List<Order> Orders { get; set; } public List<Order> Orders { get; set; }
public List<Sushi> ListSushi { get; set; } public List<Sushi> ListSushi { get; set; }
public List<Client> Clients { get; set; }
private DataListSingleton() private DataListSingleton()
{ {
Ingredients = new List<Ingredient>(); Ingredients = new List<Ingredient>();
Orders = new List<Order>(); Orders = new List<Order>();
ListSushi = new List<Sushi>(); ListSushi = new List<Sushi>();
Clients = new List<Client>();
} }
public static DataListSingleton GetInstance() public static DataListSingleton GetInstance()
{ {

View File

@ -0,0 +1,106 @@
using SushiBarContracts.BindingModel;
using SushiBarContracts.SearchModel;
using SushiBarContracts.ViewModels;
using SushiBarListImplement;
using SushiBarListImplements.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SushiBarListImplements.Implements
{
public class ClientStorage
{
private readonly DataListSingleton _source;
public ClientStorage()
{
_source = DataListSingleton.GetInstance();
}
public List<ClientViewModel> GetFullList()
{
var result = new List<ClientViewModel>();
foreach (var client in _source.Clients)
{
result.Add(client.GetViewModel);
}
return result;
}
public List<ClientViewModel> GetFilteredList(ClientSearchModel model)
{
var result = new List<ClientViewModel>();
if (string.IsNullOrEmpty(model.Email))
{
return result;
}
foreach (var client in _source.Clients)
{
if (client.Email.Contains(model.Email))
{
result.Add(client.GetViewModel);
}
}
return result;
}
public ClientViewModel? GetElement(ClientSearchModel model)
{
if (string.IsNullOrEmpty(model.Email) && !model.Id.HasValue)
{
return null;
}
foreach (var client in _source.Clients)
{
if (!string.IsNullOrEmpty(model.Email) && client.Email == model.Email ||
model.Id.HasValue && client.Email == model.Email)
{
return client.GetViewModel;
}
}
return null;
}
public ClientViewModel? Insert(ClientBindingModel model)
{
model.Id = 1;
foreach (var client in _source.Clients)
{
if (model.Id <= client.Id)
{
model.Id = client.Id + 1;
}
}
var newClient = Client.Create(model);
if (newClient == null)
{
return null;
}
_source.Clients.Add(newClient);
return newClient.GetViewModel;
}
public ClientViewModel? Update(ClientBindingModel model)
{
foreach (var client in _source.Clients)
{
if (client.Id == model.Id)
{
client.Update(model);
return client.GetViewModel;
}
}
return null;
}
public ClientViewModel? Delete(ClientBindingModel model)
{
for (int i = 0; i < _source.Clients.Count; ++i)
{
if (_source.Clients[i].Id == model.Id)
{
var element = _source.Clients[i];
_source.Clients.RemoveAt(i);
return element.GetViewModel;
}
}
return null;
}
}
}

View File

@ -0,0 +1,45 @@
using SushiBarContracts.BindingModel;
using SushiBarContracts.ViewModels;
using SushiBarDataModels;
namespace SushiBarListImplements.Models
{
public class Client : IClientModel
{
public int Id { get; private set; }
public string ClientFIO { get; private set; } = string.Empty;
public string Email { get; set; } = string.Empty;
public string Password { get; set; } = string.Empty;
public static Client? Create(ClientBindingModel? model)
{
if (model == null)
{
return null;
}
return new Client()
{
Id = model.Id,
ClientFIO = model.ClientFIO,
Email = model.Email,
Password = model.Password,
};
}
public void Update(ClientBindingModel? model)
{
if (model == null)
{
return;
}
ClientFIO = model.ClientFIO;
Email = model.Email;
Password = model.Password;
}
public ClientViewModel GetViewModel => new()
{
Id = Id,
ClientFIO = ClientFIO,
Email = Email,
Password = Password
};
}
}

View File

@ -1,8 +1,8 @@
using SushiBarContracts.BindingModels; using Microsoft.AspNetCore.Mvc;
using SushiBarContracts.BindingModel;
using SushiBarContracts.BusinessLogicsContracts; using SushiBarContracts.BusinessLogicsContracts;
using SushiBarContracts.SearchModels; using SushiBarContracts.SearchModel;
using SushiBarContracts.ViewModels; using SushiBarContracts.ViewModels;
using Microsoft.AspNetCore.Mvc;
namespace SushiBarRestApi.Controllers namespace SushiBarRestApi.Controllers
{ {
@ -11,15 +11,13 @@ namespace SushiBarRestApi.Controllers
public class ClientController : Controller public class ClientController : Controller
{ {
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly IClientLogic _logic; private readonly IClientLogic _logic;
public ClientController(IClientLogic logic, ILogger<ClientController>
public ClientController(IClientLogic logic, ILogger<ClientController> logger) logger)
{ {
_logger = logger; _logger = logger;
_logic = logic; _logic = logic;
} }
[HttpGet] [HttpGet]
public ClientViewModel? Login(string login, string password) public ClientViewModel? Login(string login, string password)
{ {
@ -37,7 +35,6 @@ namespace SushiBarRestApi.Controllers
throw; throw;
} }
} }
[HttpPost] [HttpPost]
public void Register(ClientBindingModel model) public void Register(ClientBindingModel model)
{ {
@ -51,7 +48,6 @@ namespace SushiBarRestApi.Controllers
throw; throw;
} }
} }
[HttpPost] [HttpPost]
public void UpdateData(ClientBindingModel model) public void UpdateData(ClientBindingModel model)
{ {

View File

@ -1,8 +1,9 @@
using SushiBarContracts.BindingModels; using DocumentFormat.OpenXml.Office2010.Excel;
using SushiBarContracts.BusinessLogicsContracts;
using SushiBarContracts.SearchModels;
using SushiBarContracts.ViewModels;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using SushiBarContracts.BindingModel;
using SushiBarContracts.BusinessLogicsContracts;
using SushiBarContracts.SearchModel;
using SushiBarContracts.ViewModels;
namespace SushiBarRestApi.Controllers namespace SushiBarRestApi.Controllers
{ {
@ -11,20 +12,16 @@ namespace SushiBarRestApi.Controllers
public class MainController : Controller public class MainController : Controller
{ {
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly IOrderLogic _order; private readonly IOrderLogic _order;
private readonly ISushiLogic _sushi; private readonly ISushiLogic _sushi;
public MainController(ILogger<MainController> logger, IOrderLogic order, ISushiLogic sushi) public MainController(ILogger<MainController> logger, IOrderLogic order, ISushiLogic sushi)
{ {
_logger = logger; _logger = logger;
_order = order; _order = order;
_sushi = sushi; _sushi = sushi;
} }
[HttpGet] [HttpGet]
public List<SushiViewModel>? GetListSushi() public List<SushiViewModel>? GetSushiList()
{ {
try try
{ {
@ -32,17 +29,19 @@ namespace SushiBarRestApi.Controllers
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex, "Ошибка получения списка суши"); _logger.LogError(ex, "Ошибка получения списка продуктов");
throw; throw;
} }
} }
[HttpGet] [HttpGet]
public SushiViewModel? GetSushi(int sushiId) public SushiViewModel? GetSushi(int sushiId)
{ {
try try
{ {
return _sushi.ReadElement(new SushiSearchModel { Id = sushiId }); return _sushi.ReadElement(new SushiSearchModel
{
Id = sushiId
});
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -50,21 +49,22 @@ namespace SushiBarRestApi.Controllers
throw; throw;
} }
} }
[HttpGet] [HttpGet]
public List<OrderViewModel>? GetOrders(int clientId) public List<OrderViewModel>? GetOrders(int clientId)
{ {
try try
{ {
return _order.ReadList(new OrderSearchModel { ClientId = clientId }); return _order.ReadList(new OrderSearchModel
{
ClientId = clientId
});
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex, "Ошибка получения списка заказов клиента id={Id}", clientId); _logger.LogError(ex, "Ошибка получения списка заказов клиента id = {Id} ", clientId);
throw; throw;
} }
} }
[HttpPost] [HttpPost]
public void CreateOrder(OrderBindingModel model) public void CreateOrder(OrderBindingModel model)
{ {

View File

@ -1,44 +1,39 @@
using SushiBarBusinessLogic.BusinessLogics;
using SushiBarContracts.BusinessLogicsContracts; using SushiBarContracts.BusinessLogicsContracts;
using SushiBarContracts.StoragesContracts; using SushiBarContracts.StoragesContracts;
using SushiBarDatabaseImplement.Implements; using SushiBarDatabaseImplement.Implements;
using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Models;
using SushiBarBusinessLogic.BusinessLogic;
using SushiBarBusinessLogic;
var builder = WebApplication.CreateBuilder(args); var builder = WebApplication.CreateBuilder(args);
builder.Logging.SetMinimumLevel(LogLevel.Trace); builder.Logging.SetMinimumLevel(LogLevel.Trace);
builder.Logging.AddLog4Net("log4net.config"); builder.Logging.AddLog4Net("log4net.config");
// Add services to the container. // Add services to the container.
builder.Services.AddTransient<IClientStorage, ClientStorage>(); builder.Services.AddTransient<IClientStorage, ClientStorage>();
builder.Services.AddTransient<IOrderStorage, OrderStorage>(); builder.Services.AddTransient<IOrderStorage, OrderStorage>();
builder.Services.AddTransient<ISushiStorage, SushiStorage>(); builder.Services.AddTransient<ISushiStorage, SushiStorage>();
builder.Services.AddTransient<IOrderLogic, OrderLogic>(); builder.Services.AddTransient<IOrderLogic, OrderLogic>();
builder.Services.AddTransient<IClientLogic, ClientLogic>(); builder.Services.AddTransient<IClientLogic, ClientLogic>();
builder.Services.AddTransient<ISushiLogic, SushiLogic>(); builder.Services.AddTransient<ISushiLogic, SushiLogic>();
builder.Services.AddControllers(); builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer(); builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(c => builder.Services.AddSwaggerGen(c =>
{ {
c.SwaggerDoc("v1", new OpenApiInfo { Title = "SushiBarRestApi", Version = "v1" }); c.SwaggerDoc("v1", new OpenApiInfo
{
Title = "SushiBarRestApi",
Version = "v1"
});
}); });
var app = builder.Build(); var app = builder.Build();
// Configure the HTTP request pipeline. // Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment()) if (app.Environment.IsDevelopment())
{ {
app.UseSwagger(); app.UseSwagger();
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "SushiBarRestApi v1")); app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "SushiBarRestApi v1"));
} }
app.UseHttpsRedirection(); app.UseHttpsRedirection();
app.UseAuthorization(); app.UseAuthorization();
app.MapControllers(); app.MapControllers();
app.Run(); app.Run();

View File

@ -1,20 +1,30 @@
{ {
"$schema": "https://json.schemastore.org/launchsettings.json", "$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": { "iisSettings": {
"windowsAuthentication": false, "windowsAuthentication": false,
"anonymousAuthentication": true, "anonymousAuthentication": true,
"iisExpress": { "iisExpress": {
"applicationUrl": "http://localhost:63931", "applicationUrl": "http://localhost:2876",
"sslPort": 44396 "sslPort": 44332
} }
}, },
"profiles": { "profiles": {
"SushiBarRestApi": { "http": {
"commandName": "Project", "commandName": "Project",
"dotnetRunMessages": true, "dotnetRunMessages": true,
"launchBrowser": true, "launchBrowser": true,
"launchUrl": "swagger", "launchUrl": "swagger",
"applicationUrl": "https://localhost:7292;http://localhost:5292", "applicationUrl": "http://localhost:5262",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "https://localhost:7106;http://localhost:5262",
"environmentVariables": { "environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development" "ASPNETCORE_ENVIRONMENT": "Development"
} }

View File

@ -1,20 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk.Web"> <Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net6.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.Extensions.Logging.Log4Net.AspNetCore" Version="6.1.0" /> <PackageReference Include="Microsoft.CodeAnalysis.Common" Version="4.9.2" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.2.3" /> <PackageReference Include="Microsoft.Extensions.Logging.Log4Net.AspNetCore" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\SushiBarBusinessLogic\SushiBarBusinessLogic.csproj" /> <ProjectReference Include="..\SushiBarBusinessLogic\SushiBarBusinessLogic.csproj" />
<ProjectReference Include="..\SushiBarDatabaseImplement\SushiBarDatabaseImplement.csproj" /> <ProjectReference Include="..\SushiBarDatabaseImplement\SushiBarDatabaseImplement.csproj" />
<ProjectReference Include="..\SushiBarDataModels\SushiBarDataModels.csproj" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -0,0 +1,6 @@
@SushiBarRestApi_HostAddress = http://localhost:5262
GET {{SushiBarRestApi_HostAddress}}/weatherforecast/
Accept: application/json
###

View File

@ -1,7 +1,9 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="utf-8"?>
<log4net> <configuration>
<log4net>
<appender name="RollingFile" type="log4net.Appender.RollingFileAppender"> <appender name="RollingFile" type="log4net.Appender.RollingFileAppender">
<file value="d:/temp/SushiBarRestApi.log" /> <file value="logs/SushiBarRestApi.log" />
<appendToFile value="true" /> <appendToFile value="true" />
<maximumFileSize value="100KB" /> <maximumFileSize value="100KB" />
<maxSizeRollBackups value="2" /> <maxSizeRollBackups value="2" />
@ -13,4 +15,6 @@
<level value="TRACE" /> <level value="TRACE" />
<appender-ref ref="RollingFile" /> <appender-ref ref="RollingFile" />
</root> </root>
</log4net> </log4net>
</configuration>