identification document validation

This commit is contained in:
jojo aquino 2024-12-23 06:01:06 +00:00
parent e4c217f955
commit 0a4db9e0af
11 changed files with 304 additions and 49 deletions

View File

@ -1,4 +1,5 @@
using EnotaryoPH.Data.Entities;
using System.ComponentModel.DataAnnotations;
using EnotaryoPH.Data.Entities;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
@ -29,11 +30,14 @@ namespace EnotaryoPH.Web.Common.Models
[BindProperty]
public DateTime? ExpirationDate { get; set; }
[BindProperty]
public IFormFile? File { get; set; }
[BindProperty, Required]
public IFormFile File { get; set; }
[BindProperty]
public string Filename { get; set; }
public string? Filename { get; set; }
[BindProperty]
public Guid IdentificationDocument_UID { get; set; }
[BindProperty]
public string IdentificationType { get; set; }
@ -48,8 +52,5 @@ namespace EnotaryoPH.Web.Common.Models
[BindProperty]
public string PlaceIssued { get; set; }
[BindProperty]
public Guid IdentificationDocument_UID { get; set; }
}
}

View File

@ -17,7 +17,7 @@ namespace EnotaryoPH.Web.Common.Models
internal static IdentificationDocument ToEntity(this IdentificationDocumentModel model, IdentificationDocument entity)
{
ArgumentException.ThrowIfNullOrEmpty(nameof(model.File));
ArgumentNullException.ThrowIfNull(model.File, nameof(model.File));
entity.ExpirationDate = model.ExpirationDate.ToUTC();
entity.DateIssued = model.DateIssued.ToUTC();

View File

@ -14,5 +14,9 @@
<ProjectReference Include="..\EnotaryoPH.Data\EnotaryoPH.Data.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="wwwroot\lib\jquery.unobtrusive-ajax\" />
</ItemGroup>
</Project>

View File

@ -21,5 +21,8 @@
</section>
@section Scripts {
<script src="~/lib/jquery/dist/jquery.min.js"></script>
<partial name="_ValidationScriptsPartial" />
<script src="~/js/identification-document.js"></script>
}

View File

@ -1,4 +1,5 @@
using EnotaryoPH.Data;
using EnotaryoPH.Web.Common.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.Mvc.Rendering;
@ -36,14 +37,7 @@ namespace EnotaryoPH.Web.Pages.Principal.IdentificationDocument
}
else
{
var defaultImageFilename = $"{_webHostEnvironment.WebRootPath}/images/image-white-on-gray-400x300.jpg";
using var stream = new MemoryStream(System.IO.File.ReadAllBytes(defaultImageFilename));
var formFile = new FormFile(stream, 0, stream.Length, "Untitled.jpg", "Untitled.jpg");
IdentificationDocument = new Common.Models.IdentificationDocumentModel
{
File = formFile,
ImageBase64Url = formFile.ToBase64StringUrl()
};
IdentificationDocument = new Common.Models.IdentificationDocumentModel();
}
LoadIdentificationDocumentTypes();
return Page();
@ -78,19 +72,8 @@ namespace EnotaryoPH.Web.Pages.Principal.IdentificationDocument
return BadRequest();
}
}
entity.ExpirationDate = IdentificationDocument.ExpirationDate.ToUTC();
entity.DateIssued = IdentificationDocument.DateIssued.ToUTC();
entity.PlaceIssued = IdentificationDocument.PlaceIssued;
entity.IdNumber = IdentificationDocument.IdNumber;
entity.Type = IdentificationDocument.IdentificationType;
entity.UploadedOn = DateTime.UtcNow;
entity.UserID = user.UserID;
var file = IdentificationDocument.File;
var stream = new MemoryStream((int)file.Length);
file.CopyTo(stream);
entity.Filename = file.FileName;
entity.File = stream.ToArray();
entity = IdentificationDocument.ToEntity(entity);
if (entity.IdentificationDocumentID > 0)
{
@ -98,6 +81,7 @@ namespace EnotaryoPH.Web.Pages.Principal.IdentificationDocument
}
else
{
entity.UserID = user.UserID;
entity.CreatedOn = DateTime.UtcNow;
entity.IdentificationDocument_UID = Guid.NewGuid();
_notaryoDBContext.Add(entity);
@ -106,17 +90,18 @@ namespace EnotaryoPH.Web.Pages.Principal.IdentificationDocument
return RedirectToPage("/Principal/Dashboard/Dashboard");
}
private IActionResult PostbackPage()
public IActionResult OnPostDeleteIdentificationDocument()
{
if (IdentificationDocument.File != null)
if (IdentificationDocument_UID == Guid.Empty)
{
IdentificationDocument.ImageBase64Url = IdentificationDocument.File.ToBase64StringUrl();
//using var stream = IdentificationDocument.File.OpenReadStream();
//IdentificationDocument.File = new FormFile(stream, 0, stream.Length, IdentificationDocument.File.Name, IdentificationDocument.File.Name);
return BadRequest();
}
LoadIdentificationDocumentTypes();
return Page();
var user = _notaryoDBContext.Users.AsNoTracking().FirstOrDefault(u => u.User_UID == _currentUserService.GetUser_UID());
_notaryoDBContext.IdentificationDocuments.Remove(_notaryoDBContext.IdentificationDocuments.FirstOrDefault(id => id.IdentificationDocument_UID.Value == IdentificationDocument_UID && id.UserID == user.UserID));
_notaryoDBContext.SaveChanges();
return new OkObjectResult(true);
}
private void LoadIdentificationDocumentTypes()
@ -130,6 +115,12 @@ namespace EnotaryoPH.Web.Pages.Principal.IdentificationDocument
});
}
private IActionResult PostbackPage()
{
LoadIdentificationDocumentTypes();
return Page();
}
[BindProperty]
public Common.Models.IdentificationDocumentModel IdentificationDocument { get; set; }

View File

@ -4,15 +4,17 @@
}
<div class="row">
<div class="col-12 col-lg-4">
<div class="col-12 col-lg-5 col-xl-4">
<div class="card">
<a href="#" target="_self" class="identification-document__a"><img id="identification-document__a__img" class="identification-document__a__img card-img w-100 d-block fit-cover identification-document__upload__image" src="@Model.ImageBase64Url" style="height: 300px;" /></a>
<a href="#" target="_self" class="identification-document__a">
<img id="identification-document__a__img" class="identification-document__a__img card-img w-100 d-block fit-cover identification-document__upload__image" src="@(!string.IsNullOrEmpty(Model.ImageBase64Url) ? Model.ImageBase64Url : "/images/image-white-on-gray-400x300.jpg")" style="height: 300px;" />
</a>
@Html.ValidationMessageFor(m => m.File)
<div class="card-body p-2">
<input type="hidden" asp-for="ImageBase64Url" class="identification-document__base64" />
<input type="text" asp-for="Filename" class="card-text mb-1 form-control-plaintext identification-document__filename" />
<div>
<input class="identification-document__upload__file" type="file" style="display:none;" asp-for="File" accept="image/*" />
@Html.ValidationMessageFor(m => m.File)
<button class="btn btn-secondary btn-sm me-1 identification-document__upload__button" type="button">Upload Photo<i class="fas fa-upload ms-1"></i></button>
</div>
</div>
@ -33,6 +35,7 @@
<div class="mb-3">
<label class="form-label">ID Number</label>
<input class="form-control form-control" type="text" required asp-for="IdNumber" />
@Html.ValidationMessageFor(m => m.IdNumber)
</div>
</div>
</div>
@ -41,6 +44,7 @@
<div class="mb-3">
<label class="form-label">Place Issued</label>
<input class="form-control form-control" type="text" required asp-for="PlaceIssued" />
@Html.ValidationMessageFor(m => m.PlaceIssued)
</div>
</div>
<div class="col-12 col-lg-7">

View File

@ -1,2 +1,3 @@
<script src="~/lib/jquery-validation/dist/jquery.validate.min.js"></script>
<script src="~/lib/jquery-validation-unobtrusive/dist/jquery.validate.unobtrusive.min.js"></script>
<script src="~/lib/jquery.unobtrusive-ajax/dist/jquery.unobtrusive-ajax.min.js"></script>

View File

@ -1,13 +1,14 @@
"use strict";
(function () {
let
control_deleteButtons = document.querySelectorAll(".identificationdocument__delete__button"),
control_fileInput = document.querySelector(".identification-document__upload__file"),
control_uploadButton = document.querySelector(".identification-document__upload__button"),
control_filename = document.querySelector(".identification-document__filename"),
control_imageLink = document.querySelector(".identification-document__a"),
control_image = document.querySelector(".identification-document__a__img"),
control_imageBase64Url = document.querySelector(".identification-document__base64"),
x = 1;
control_imageLink = document.querySelector(".identification-document__a"),
control_uploadButton = document.querySelector(".identification-document__upload__button")
;
function _bindEvents() {
control_uploadButton.addEventListener("click", function () {
@ -16,24 +17,42 @@
control_fileInput.addEventListener("change", function (event) {
const file = event.target.files[0];
if(file) {
console.log('File name:', file.name);
console.log('File size:', file.size);
console.log('File type:', file.type);
if (file) {
control_filename.value = file.name;
const reader = new FileReader();
reader.onload = function (e) {
debugger;
const base64StringUrl = e.target.result;
control_imageLink.href = base64StringUrl;
control_image.src = base64StringUrl;
console.log('Base64 String:', base64String);
};
reader.readAsDataURL(file);
} else {
console.log('No file selected');
}
});
control_deleteButtons?.forEach(btn => {
btn.addEventListener("click", _deleteIdentificationDocument);
});
}
function _deleteIdentificationDocument(e) {
jfa.components.dialog.confirm({
message: "Are you sure you want to delete this Identification Document?",
callbackyes: function () {
let btn = e.target.closest("button");
let url = new URL(window.location.origin + '/Principal/IdentificationDocument/IdentificationDocument/' + btn.dataset.uid);
url.searchParams.append("IdentificationDocument_UID", btn.dataset.uid);
url.searchParams.append("handler", "DeleteIdentificationDocument");
jfa.utilities.request.post(url, {})
.then(resp => {
if (resp.ok === true) {
jfa.page.reload();
}
})
.catch(err => console.error(err));
}
});
}
function _init() {
@ -43,8 +62,7 @@
function _initFiles() {
if (control_imageBase64Url.value) {
debugger;
const fileContent = control_imageBase64Url.value;
const fileContent = control_imageBase64Url.value.split(',')[1];
const filename = control_filename.value;
const file = new File([fileContent], filename);
const dataTransfer = new DataTransfer();

View File

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

View File

@ -0,0 +1,205 @@
// Unobtrusive Ajax support library for jQuery
// 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 <placeholder>
//
// Microsoft grants you the right to use these script files for the sole
// purpose of either: (i) interacting through your browser with the Microsoft
// website or online service, subject to the applicable licensing or use
// terms; or (ii) using the files as included with a Microsoft product subject
// to that product's license terms. Microsoft reserves all other rights to the
// files not expressly granted by Microsoft, whether by implication, estoppel
// or otherwise. Insofar as a script file is dual licensed under GPL,
// Microsoft neither took the code under GPL nor distributes it thereunder but
// under the terms set out in this paragraph. All notices and licenses
// below are for informational purposes only.
/*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 window: false, jQuery: false */
(function ($) {
var data_click = "unobtrusiveAjaxClick",
data_target = "unobtrusiveAjaxClickTarget",
data_validation = "unobtrusiveValidation";
function getFunction(code, argNames) {
var fn = window, parts = (code || "").split(".");
while (fn && parts.length) {
fn = fn[parts.shift()];
}
if (typeof (fn) === "function") {
return fn;
}
argNames.push(code);
return Function.constructor.apply(null, argNames);
}
function isMethodProxySafe(method) {
return method === "GET" || method === "POST";
}
function asyncOnBeforeSend(xhr, method) {
if (!isMethodProxySafe(method)) {
xhr.setRequestHeader("X-HTTP-Method-Override", method);
}
}
function asyncOnSuccess(element, data, contentType) {
var mode;
if (contentType.indexOf("application/x-javascript") !== -1) { // jQuery already executes JavaScript for us
return;
}
mode = (element.getAttribute("data-ajax-mode") || "").toUpperCase();
$(element.getAttribute("data-ajax-update")).each(function (i, update) {
var top;
switch (mode) {
case "BEFORE":
$(update).prepend(data);
break;
case "AFTER":
$(update).append(data);
break;
case "REPLACE-WITH":
$(update).replaceWith(data);
break;
default:
$(update).html(data);
break;
}
});
}
function asyncRequest(element, options) {
var confirm, loading, method, duration;
confirm = element.getAttribute("data-ajax-confirm");
if (confirm && !window.confirm(confirm)) {
return;
}
loading = $(element.getAttribute("data-ajax-loading"));
duration = parseInt(element.getAttribute("data-ajax-loading-duration"), 10) || 0;
$.extend(options, {
type: element.getAttribute("data-ajax-method") || undefined,
url: element.getAttribute("data-ajax-url") || undefined,
cache: (element.getAttribute("data-ajax-cache") || "").toLowerCase() === "true",
beforeSend: function (xhr) {
var result;
asyncOnBeforeSend(xhr, method);
result = getFunction(element.getAttribute("data-ajax-begin"), ["xhr"]).apply(element, arguments);
if (result !== false) {
loading.show(duration);
}
return result;
},
complete: function () {
loading.hide(duration);
getFunction(element.getAttribute("data-ajax-complete"), ["xhr", "status"]).apply(element, arguments);
},
success: function (data, status, xhr) {
asyncOnSuccess(element, data, xhr.getResponseHeader("Content-Type") || "text/html");
getFunction(element.getAttribute("data-ajax-success"), ["data", "status", "xhr"]).apply(element, arguments);
},
error: function () {
getFunction(element.getAttribute("data-ajax-failure"), ["xhr", "status", "error"]).apply(element, arguments);
}
});
options.data.push({ name: "X-Requested-With", value: "XMLHttpRequest" });
method = options.type.toUpperCase();
if (!isMethodProxySafe(method)) {
options.type = "POST";
options.data.push({ name: "X-HTTP-Method-Override", value: method });
}
// change here:
// Check for a Form POST with enctype=multipart/form-data
// add the input file that were not previously included in the serializeArray()
// set processData and contentType to false
var $element = $(element);
if ($element.is("form") && $element.attr("enctype") == "multipart/form-data") {
var formdata = new FormData();
$.each(options.data, function (i, v) {
formdata.append(v.name, v.value);
});
$("input[type=file]", $element).each(function () {
var file = this;
$.each(file.files, function (n, v) {
formdata.append(file.name, v);
});
});
$.extend(options, {
processData: false,
contentType: false,
data: formdata
});
}
// end change
$.ajax(options);
}
function validate(form) {
var validationInfo = $(form).data(data_validation);
return !validationInfo || !validationInfo.validate || validationInfo.validate();
}
$(document).on("click", "a[data-ajax=true]", function (evt) {
evt.preventDefault();
asyncRequest(this, {
url: this.href,
type: "GET",
data: []
});
});
$(document).on("click", "form[data-ajax=true] input[type=image]", function (evt) {
var name = evt.target.name,
target = $(evt.target),
form = $(target.parents("form")[0]),
offset = target.offset();
form.data(data_click, [
{ name: name + ".x", value: Math.round(evt.pageX - offset.left) },
{ name: name + ".y", value: Math.round(evt.pageY - offset.top) }
]);
setTimeout(function () {
form.removeData(data_click);
}, 0);
});
$(document).on("click", "form[data-ajax=true] :submit", function (evt) {
var name = evt.currentTarget.name,
target = $(evt.target),
form = $(target.parents("form")[0]);
form.data(data_click, name ? [{ name: name, value: evt.currentTarget.value }] : []);
form.data(data_target, target);
setTimeout(function () {
form.removeData(data_click);
form.removeData(data_target);
}, 0);
});
$(document).on("submit", "form[data-ajax=true]", function (evt) {
var clickInfo = $(this).data(data_click) || [],
clickTarget = $(this).data(data_target),
isCancel = clickTarget && (clickTarget.hasClass("cancel") || clickTarget.attr('formnovalidate') !== undefined);
evt.preventDefault();
if (!isCancel && !validate(this)) {
return;
}
asyncRequest(this, {
url: this.action,
type: this.method || "GET",
data: clickInfo.concat($(this).serializeArray())
});
});
}(jQuery));

View File

@ -0,0 +1,16 @@
// Unobtrusive Ajax support library for jQuery
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
// @version v3.2.6
//
// Microsoft grants you the right to use these script files for the sole
// purpose of either: (i) interacting through your browser with the Microsoft
// website or online service, subject to the applicable licensing or use
// terms; or (ii) using the files as included with a Microsoft product subject
// to that product's license terms. Microsoft reserves all other rights to the
// files not expressly granted by Microsoft, whether by implication, estoppel
// or otherwise. Insofar as a script file is dual licensed under GPL,
// Microsoft neither took the code under GPL nor distributes it thereunder but
// under the terms set out in this paragraph. All notices and licenses
// below are for informational purposes only.
!function(t){function a(t,a){for(var e=window,r=(t||"").split(".");e&&r.length;)e=e[r.shift()];return"function"==typeof e?e:(a.push(t),Function.constructor.apply(null,a))}function e(t){return"GET"===t||"POST"===t}function r(t,a){e(a)||t.setRequestHeader("X-HTTP-Method-Override",a)}function n(a,e,r){var n;r.indexOf("application/x-javascript")===-1&&(n=(a.getAttribute("data-ajax-mode")||"").toUpperCase(),t(a.getAttribute("data-ajax-update")).each(function(a,r){switch(n){case"BEFORE":t(r).prepend(e);break;case"AFTER":t(r).append(e);break;case"REPLACE-WITH":t(r).replaceWith(e);break;default:t(r).html(e)}}))}function i(i,u){var o,c,d,s;if(o=i.getAttribute("data-ajax-confirm"),!o||window.confirm(o)){c=t(i.getAttribute("data-ajax-loading")),s=parseInt(i.getAttribute("data-ajax-loading-duration"),10)||0,t.extend(u,{type:i.getAttribute("data-ajax-method")||void 0,url:i.getAttribute("data-ajax-url")||void 0,cache:"true"===(i.getAttribute("data-ajax-cache")||"").toLowerCase(),beforeSend:function(t){var e;return r(t,d),e=a(i.getAttribute("data-ajax-begin"),["xhr"]).apply(i,arguments),e!==!1&&c.show(s),e},complete:function(){c.hide(s),a(i.getAttribute("data-ajax-complete"),["xhr","status"]).apply(i,arguments)},success:function(t,e,r){n(i,t,r.getResponseHeader("Content-Type")||"text/html"),a(i.getAttribute("data-ajax-success"),["data","status","xhr"]).apply(i,arguments)},error:function(){a(i.getAttribute("data-ajax-failure"),["xhr","status","error"]).apply(i,arguments)}}),u.data.push({name:"X-Requested-With",value:"XMLHttpRequest"}),d=u.type.toUpperCase(),e(d)||(u.type="POST",u.data.push({name:"X-HTTP-Method-Override",value:d}));var p=t(i);if(p.is("form")&&"multipart/form-data"==p.attr("enctype")){var f=new FormData;t.each(u.data,function(t,a){f.append(a.name,a.value)}),t("input[type=file]",p).each(function(){var a=this;t.each(a.files,function(t,e){f.append(a.name,e)})}),t.extend(u,{processData:!1,contentType:!1,data:f})}t.ajax(u)}}function u(a){var e=t(a).data(d);return!e||!e.validate||e.validate()}var o="unobtrusiveAjaxClick",c="unobtrusiveAjaxClickTarget",d="unobtrusiveValidation";t(document).on("click","a[data-ajax=true]",function(t){t.preventDefault(),i(this,{url:this.href,type:"GET",data:[]})}),t(document).on("click","form[data-ajax=true] input[type=image]",function(a){var e=a.target.name,r=t(a.target),n=t(r.parents("form")[0]),i=r.offset();n.data(o,[{name:e+".x",value:Math.round(a.pageX-i.left)},{name:e+".y",value:Math.round(a.pageY-i.top)}]),setTimeout(function(){n.removeData(o)},0)}),t(document).on("click","form[data-ajax=true] :submit",function(a){var e=a.currentTarget.name,r=t(a.target),n=t(r.parents("form")[0]);n.data(o,e?[{name:e,value:a.currentTarget.value}]:[]),n.data(c,r),setTimeout(function(){n.removeData(o),n.removeData(c)},0)}),t(document).on("submit","form[data-ajax=true]",function(a){var e=t(this).data(o)||[],r=t(this).data(c),n=r&&(r.hasClass("cancel")||void 0!==r.attr("formnovalidate"));a.preventDefault(),(n||u(this))&&i(this,{url:this.action,type:this.method||"GET",data:e.concat(t(this).serializeArray())})})}(jQuery);