@page "/docedit" @page "/docedit/{docID:int}" @using System.Reflection; @using HyperCube.Models; @inject NavigationManager NavigationManager; @inject IJSRuntime JsRuntime; @attribute [Authorize] @*@attribute [Authorize(Roles = "admin")]*@ @inject AuthenticationStateProvider AuthenticationStateProvider @using Microsoft.AspNetCore.Identity; @inject UserManager<IdentityUser> UserManager; <EditForm Model="@articleModel" OnValidSubmit="@HandleValidSubmit"> <DataAnnotationsValidator /> <ValidationSummary /> <h1>@header</h1> <br> <div style="width: 50%;"> @if (docID < 1) { <p><InputFile id="inputDefault" OnChange="@HandleSelection" accept="application/pdf" /></p> //accept="application/pdf, application/msword, application/vnd.openxmlformats-officedocument.wordprocessingml.document" } else { <p>Исходный документ: <a href=@FOLDER_NAME download="@articleModel.Filename" target="_top">@articleModel.Filename</a></p> } <p><InputText id="article_name" class="form-control" @bind-Value="articleModel.Name" placeholder="Наименование статьи" /></p> <p><InputDate id="date_publish" class="form-control" @bind-Value="articleModel.PublishDate" placeholder="Дата издания" /></p> <p><InputText id="author" class="form-control" @bind-Value="articleModel.Authors" placeholder="Автор" /></p> <p><InputTextArea id="keywords" class="form-control" @bind-Value="articleModel.Keywords" placeholder="Ключевые слова" /></p> <p><InputTextArea rows="5" id="annotation" class="form-control" @bind-Value="articleModel.Annotation" placeholder="Аннотация" /></p> <p><InputTextArea rows="10" id="text" class="form-control" @bind-Value="articleModel.Text" placeholder="Текст" /></p> @if (docID < 1) { <p><button class="btn btn-primary" type="submit">Загрузить</button></p> } else { @*<p> <InputRadioGroup @bind-Value="articleModel.Status"> Оценка: <br> @foreach (var status in (ArticleStatus[])Enum.GetValues(typeof(ArticleStatus))) { <InputRadio Value="status" /> @status <br /> } </InputRadioGroup> </p>*@ <p> <InputRadioGroup @bind-Value="articleModel.Rating"> Оценка: <br> @for (int i = 1; i < 6; i++) { <InputRadio Value="i" /> @i <br /> } </InputRadioGroup> </p> <p> <button class="btn btn-danger" type="button" @onclick="@Cancel">Отклонить</button> <button @onclick="Verify" class="btn btn-primary" type="submit">Утвердить</button> </p> } <p>Статус: @status</p> </div> </EditForm> @code { [Parameter] public int docID { get; set; } const string FOLDER_NAME = "articles_storage"; const long MAX_FILE_SIZE = 5120000; //bytes //const int ACC_ID = 1; //temp ArticleModel oldArticleModel = new(); ArticleModel articleModel = new(); AccountModel currentAcc = new(); string status; string header; string storageFolderPath; MemoryStream memoryStream; async Task Verify() { try { VerifyContract verifyContract = SmartContract.Find("Verify") as VerifyContract; if (verifyContract != null) { await verifyContract.Run(articleModel); } } catch (Exception e) { Console.WriteLine(e.Message); } } protected override async Task OnInitializedAsync() { currentAcc = await GetCurrentAcc(); string path = AppDomain.CurrentDomain.BaseDirectory; storageFolderPath = (Path.Combine(path, FOLDER_NAME)); if (docID > 0) { header = "Проверка материала"; MySQLConnector dbCon = MySQLConnector.Instance(); string stringSQL = $"SELECT articles.id, filename, article_name, authors, date_publish, annotation, keywords, action_type, rating " + $"FROM articles " + $"JOIN actions_history ON actions_history.article_id = articles.id " + $"WHERE articles.id={docID} " + $"ORDER BY actions_history.id DESC LiMIT 1"; oldArticleModel = await dbCon.SQLSelectArticle(stringSQL); articleModel = (ArticleModel)oldArticleModel.Clone(); string initiator = await articleModel.GetInitiatorUUID(); status = $"Article ID={docID} loaded, status: {articleModel.Status}, initiatorUUID: {await articleModel.GetInitiatorUUID()}"; } else header = "Загрузка материала"; InitializeAccount(); //int count = await articleModel.GetEditsCount(); //int countbyid = await articleModel.GetEditsCount(currentAcc.UUID); //header += $", uuid:{currentAcc.UUID}, name: {currentAcc.Name}, edits count:{count}, count by accid: {countbyid}"; } private async void HandleValidSubmit() { MySQLConnector dbCon = MySQLConnector.Instance(); long id = 0; string stringSQL; if (docID > 0) { id = docID; stringSQL = $"UPDATE articles " + $"SET filename='{articleModel.Filename}', article_name='{articleModel.Name}', authors='{articleModel.Authors}', " + $"date_publish='{articleModel.PublishDate.ToString("yyyy-MM-dd")}', annotation='{articleModel.Annotation}', " + $"keywords='{articleModel.Keywords}', rating={articleModel.Rating} " + $"WHERE id={docID}"; dbCon.SQLInsert(stringSQL); } else { stringSQL = $"INSERT INTO articles (filename, article_name, authors, date_publish, annotation, keywords) " + $"VALUES ('{articleModel.Filename}', '{articleModel.Name}', '{articleModel.Authors}', '{articleModel.PublishDate.ToString("yyyy-MM-dd")}'," + $"'{articleModel.Annotation}', '{articleModel.Keywords}')"; id = dbCon.SQLInsert(stringSQL); } ///temp int action_type = docID > 0 ? 2 : 1; stringSQL = $"INSERT INTO actions_history (article_id, action_type, acc_id) " + $"VALUES ('{id}', '{action_type}', '{currentAcc.UUID}')"; dbCon.SQLInsert(stringSQL); Dictionary<string, PropertyInfo> propDict = Compare.SimpleCompare<ArticleModel>(articleModel, oldArticleModel); foreach (KeyValuePair<string, PropertyInfo> prop in propDict) { //Console.WriteLine($"property name: {prop.Key}, value: {prop.Value.GetValue(articleModel, null)}"); stringSQL = $"INSERT INTO articles_edit_log (article_id, acc_id, field_name, field_prevvalue, field_newvalue) " + $"VALUES ('{id}', '{currentAcc.UUID}', '{prop.Key}', '{prop.Value.GetValue(oldArticleModel, null)}', '{prop.Value.GetValue(articleModel, null)}')"; dbCon.SQLInsert(stringSQL); } dbCon.Close(); if (docID > 0) { status = propDict.Count > 0 ? "All changes saved, article has veryfied." : "Article verifyed without any changes."; } else { string fullpath = Path.Combine(storageFolderPath, $"{id}_{articleModel.Filename}"); Directory.CreateDirectory(storageFolderPath); FileStream fs = new(fullpath, FileMode.Create, FileAccess.Write); memoryStream.Position = 0; await memoryStream.CopyToAsync(fs); Console.WriteLine($"User has saved new article data, {id}_{articleModel.Filename}, memory size:{memoryStream.Length}b, file size: {fs.Length}b"); memoryStream.Close(); fs.Close(); status = "New article data saved."; bool confirmed = await JsRuntime.InvokeAsync<bool>("confirm", "Хотите загрузить еще статью?"); if (confirmed) NavigationManager.NavigateTo("docedit", true); else NavigationManager.NavigateTo(""); } } private async Task HandleSelection(InputFileChangeEventArgs e) { IBrowserFile file = e.File; if (file != null) { Stream stream = file.OpenReadStream(MAX_FILE_SIZE); memoryStream = new(); await stream.CopyToAsync(memoryStream); status = $"Finished loading {memoryStream.Length} bytes from {file.Name}"; DocParse docParse = new DocParse(); oldArticleModel = DocParse.ReadPDF(memoryStream); oldArticleModel.Filename = file.Name; articleModel = (ArticleModel)oldArticleModel.Clone(); } } private async void Cancel() { bool confirmed = await JsRuntime.InvokeAsync<bool>("confirm", "Вы уверены, что хотите отклонить статью?"); if (confirmed) { ///какая-то логика отмены... NavigationManager.NavigateTo(""); } } public async void InitializeAccount() { AccountModel.Current = await GetCurrentAcc(); Console.WriteLine("InitializeAccount in DocEdit "+ AccountModel.Current.Name); } private async Task<AccountModel> GetCurrentAcc() { AccountModel account = new(); var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync(); var user = authState.User; if (user.Identity.IsAuthenticated) { var currentUser = await UserManager.GetUserAsync(user); account.UUID = currentUser.Id; account.Name = currentUser.UserName; account.Email = currentUser.Email; var acc = AccountModel.Find(account.Email); if (acc != null) account = acc; ///tmp account.AccRole = Role.User; return account; } return null; } }