Browse Source

extending modals, form validation

ganahrhr 3 years ago
parent
commit
2e3284cd7c
4 changed files with 218 additions and 23 deletions
  1. 15 10
      Pages/DocEdit.razor
  2. 46 6
      Pages/DocEdit.razor.cs
  3. 10 7
      Pages/Modal.razor
  4. 147 0
      Pages/ModalLoading.razor

+ 15 - 10
Pages/DocEdit.razor

@@ -18,11 +18,11 @@
             <form class="upload__form">
                 @if (DocID < 1)
                 {
-                    <InputFile class="upload__btn" id="inputDefault" OnChange="@HandleSelection" accept="application/pdf" />                    
+                    <InputFile class="upload__btn" id="inputDefault" OnChange="@HandleSelection" accept="application/pdf" />
                 }
                 else
                 {
-                    <p>Исходный документ: <a href=@fullName download target="_top">@article.Filename</a></p>                    
+                    <p>Исходный документ: <a href=@fullName download target="_top">@article.Filename</a></p>
                 }
                 <InputText type="text" class="form-control upload__input" id="article_name" @bind-Value="article.Name" placeholder="Наименование статьи" />
                 <InputDate type="date" class="form-control upload__input" id="date_publish" @bind-Value="article.PublishDate" placeholder="Дата издания" />
@@ -36,7 +36,7 @@
 
                 @if (DocID < 1)
                 {
-                    <button type="button" class="upload__btn" @onclick="@HandleValidSubmit" disabled=@IsSubmitDisabled>загрузить на верификацию</button>
+                    <button type="button" class="upload__btn" @onclick="@HandleSubmit" disabled=@IsSubmitDisabled>загрузить на верификацию</button>
                 }
                 else
                 {
@@ -54,7 +54,7 @@
                     </p>
                     <p>
                         <button type="button" class="upload__btn" @onclick="@Cancel">oтклонить</button>
-                        <button type="button" class="upload__btn" @onclick="@HandleValidSubmit">утвердить</button>
+                        <button type="button" class="upload__btn" @onclick="@HandleSubmit">утвердить</button>
                     </p>
                 }
 
@@ -62,8 +62,7 @@
                 <p>Статус: @status</p>
 
             </form>
-
-            <Modal @ref="modal">
+            <ModalInfo @ref="modalInfo_transac">
                 <Title>Результат операции</Title>
                 <Body>
                     <p>
@@ -78,10 +77,16 @@
                         Кол-во исправлений: @editsCount
                     </p>
                 </Body>
-                <Footer>
-                    <button type="button" class="upload__btn" data-dismiss="modal" @onclick="() => modal.Close()">Закрыть</button>
-                </Footer>
-            </Modal>
+            </ModalInfo>
+            <ModalInfo @ref="modalInfo_error">
+                <Title>Ошибка</Title>
+                <Body>                    
+                </Body>
+            </ModalInfo>
+            <ModalLoading @ref="modalLoading">
+                <Body>
+                </Body>
+            </ModalLoading>
         </div>                    
     </EditForm>
 </div>

+ 46 - 6
Pages/DocEdit.razor.cs

@@ -5,9 +5,11 @@ using Microsoft.AspNetCore.Identity;
 using Microsoft.JSInterop;
 using System;
 using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
 using System.IO;
 using System.Reflection;
 using System.Threading.Tasks;
+using System.Linq;
 using System.Net;
 using System.Security.Cryptography;
 using HyperCube.Models;
@@ -41,7 +43,9 @@ namespace HyperCube.Pages
         string header;
         string storageFolderPath;
         MemoryStream memoryStream;
-        Modal modal { get; set; }
+        ModalInfo modalInfo_error { get; set; }
+        ModalInfo modalInfo_transac { get; set; }
+        ModalLoading modalLoading { get; set; }
         string fullName { get { return FOLDER_NAME + "/" + article.FilenameReal; } }
         int editsCount;
 
@@ -117,13 +121,27 @@ namespace HyperCube.Pages
             return reader.ReadToEnd();
         }
 
-        private async Task HandleValidSubmit()
+        private async Task HandleSubmit()
         {
+            Console.WriteLine($"HandleSubmit, docID: {DocID}.");
+
+            modalLoading.Open();
+
+            /// form validation
+            List<string> errorFields = ValidateForm<ArticleModel>(article);
+            if (errorFields.Count > 0)
+            {
+                modalLoading.Close();
+                string invalid_fields = string.Join(", ", errorFields);
+                modalInfo_error.Open($"Не заполнены поля: {invalid_fields}");
+                Console.WriteLine($"HandleSubmit. Required fields: '{invalid_fields}' is not filled.");
+                return;
+            }          
+
+            /// all is fine, continue
             MySQLConnector dbCon = MySQLConnector.Instance();
             long id;
-            string stringSQL;
-
-            Console.WriteLine($"HandleValidSubmit, docID: {DocID}");
+            string stringSQL;            
 
             if (DocID > 0)
             {
@@ -171,7 +189,7 @@ namespace HyperCube.Pages
 
                 ///tmp
                 editsCount = await article.GetEditsCount(currentAcc.UUID);
-                modal.Open();
+                modalInfo_transac.Open();
             }
             else
             {
@@ -200,6 +218,8 @@ namespace HyperCube.Pages
 
         private async Task HandleSelection(InputFileChangeEventArgs e)
         {
+            modalLoading.Open();
+
             IBrowserFile file = e.File;
             if (file != null)
             {
@@ -235,8 +255,13 @@ namespace HyperCube.Pages
                     Console.WriteLine(status);
 
                     IsSubmitDisabled = true;
+                    memoryStream.Close();
+                    stream.Close();
+                    modalInfo_error.Open("Загрузка не удалась, такой документ уже есть в системе.");
                 }
             }
+
+            modalLoading.Close();
         }
 
         private async Task Cancel()
@@ -288,5 +313,20 @@ namespace HyperCube.Pages
             byte[] hash = await md5Provider.ComputeHashAsync(ms);
             return Convert.ToBase64String(hash);
         }
+
+        private List<string> ValidateForm<T>(T obj)
+        {
+            var props = typeof(T).GetProperties().Where(pi => Attribute.IsDefined(pi, typeof(RequiredAttribute)));
+            List<string> result = new();
+            foreach (var prop in props)
+            {
+                var val = prop.GetValue(obj, null);
+                if (val == null || val?.ToString().Length == 0)                    
+                    result.Add(prop.Name);
+
+                //Console.WriteLine($"Required field '{prop.Name}' is not filled.");
+            }            
+            return result;
+        }
     }
 }

+ 10 - 7
Pages/Modal.razor

@@ -3,15 +3,19 @@
         <div class="modal-content">
             <div class="modal-header">
                 <h5 class="modal-title">@Title</h5>
-                <button type="button" class="close" data-dismiss="modal" aria-label="Close" @onclick="Close">
+                <button type="button" class="close" data-dismiss="modal" aria-label="Close" @onclick="@Close">
                     <span aria-hidden="true">&times;</span>
                 </button>
             </div>
             <div class="modal-body">
                 @Body
+                @if (modalMessage.Length > 0)
+                {
+                    <p>@modalMessage</p>
+                }
             </div>
-            <div class="modal-footer">
-                @Footer
+            <div class="modal-footer">                
+                <button type="button" class="upload__btn" data-dismiss="modal" @onclick="@Close">Закрыть</button>
             </div>
         </div>
     </div>
@@ -29,18 +33,17 @@
     [Parameter]
     public RenderFragment Body { get; set; }
 
-    [Parameter]
-    public RenderFragment Footer { get; set; }
-
     private string modalDisplay = "none;";
     private string modalClass = "";
+    private string modalMessage = "";
     private bool showBackdrop = false;
 
-    public void Open()
+    public void Open(string message = "")
     {
         modalDisplay = "block;";
         modalClass = "show";
         showBackdrop = true;
+        modalMessage = message;
     }
 
     public void Close()

+ 147 - 0
Pages/ModalLoading.razor

@@ -0,0 +1,147 @@
+<div class="modal @modalClass" tabindex="-1" role="dialog" style="display:@modalDisplay; overflow-y: auto;">
+    <div class="modal-dialog modal-sm" role="document">
+        <div class="modal-content">
+            <div class="modal-body">
+                <div style="text-align: center;">
+                    <div class="lds-roller"><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div></div>
+                </div>
+                <p style="text-align:center; margin-top:20px">Пожалуйста, подождите...</p>
+            </div>
+        </div>
+    </div>
+</div>
+
+@if (showBackdrop)
+{
+    <div class="modal-backdrop fade show"></div>
+}
+
+<style>
+    .lds-roller {
+        display: inline-block;
+        position: relative;
+        width: 80px;
+        height: 80px;
+    }
+
+        .lds-roller div {
+            animation: lds-roller 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite;
+            transform-origin: 40px 40px;
+        }
+
+            .lds-roller div:after {
+                content: " ";
+                display: block;
+                position: absolute;
+                width: 7px;
+                height: 7px;
+                border-radius: 50%;
+                background: #000000;
+                margin: -4px 0 0 -4px;
+            }
+
+            .lds-roller div:nth-child(1) {
+                animation-delay: -0.036s;
+            }
+
+                .lds-roller div:nth-child(1):after {
+                    top: 63px;
+                    left: 63px;
+                }
+
+            .lds-roller div:nth-child(2) {
+                animation-delay: -0.072s;
+            }
+
+                .lds-roller div:nth-child(2):after {
+                    top: 68px;
+                    left: 56px;
+                }
+
+            .lds-roller div:nth-child(3) {
+                animation-delay: -0.108s;
+            }
+
+                .lds-roller div:nth-child(3):after {
+                    top: 71px;
+                    left: 48px;
+                }
+
+            .lds-roller div:nth-child(4) {
+                animation-delay: -0.144s;
+            }
+
+                .lds-roller div:nth-child(4):after {
+                    top: 72px;
+                    left: 40px;
+                }
+
+            .lds-roller div:nth-child(5) {
+                animation-delay: -0.18s;
+            }
+
+                .lds-roller div:nth-child(5):after {
+                    top: 71px;
+                    left: 32px;
+                }
+
+            .lds-roller div:nth-child(6) {
+                animation-delay: -0.216s;
+            }
+
+                .lds-roller div:nth-child(6):after {
+                    top: 68px;
+                    left: 24px;
+                }
+
+            .lds-roller div:nth-child(7) {
+                animation-delay: -0.252s;
+            }
+
+                .lds-roller div:nth-child(7):after {
+                    top: 63px;
+                    left: 17px;
+                }
+
+            .lds-roller div:nth-child(8) {
+                animation-delay: -0.288s;
+            }
+
+                .lds-roller div:nth-child(8):after {
+                    top: 56px;
+                    left: 12px;
+                }
+
+    @@keyframes lds-roller {
+        0% {
+            transform: rotate(0deg);
+        }
+
+        100% {
+            transform: rotate(360deg);
+        }
+    }
+</style>
+
+@code {
+    [Parameter]
+    public RenderFragment Body { get; set; }
+
+    private string modalDisplay = "none;";
+    private string modalClass = "";
+    private bool showBackdrop = false;
+
+    public void Open()
+    {
+        modalDisplay = "block;";
+        modalClass = "show";
+        showBackdrop = true;
+    }
+
+    public void Close()
+    {
+        modalDisplay = "none";
+        modalClass = "";
+        showBackdrop = false;
+    }
+}