From 37b794ea054a26951ca82c0b4fab471afd8ea21a Mon Sep 17 00:00:00 2001 From: schnulller Date: Sat, 4 Jun 2022 02:42:01 +0200 Subject: [PATCH] Formatted everything; completed upload capabilities --- HaWeb/.vscode/launch.json | 13 +- HaWeb/Controllers/AdminController.cs | 11 +- HaWeb/Controllers/BriefeContoller.cs | 20 +-- HaWeb/Controllers/EditionController.cs | 24 +-- HaWeb/Controllers/ErrorController.cs | 3 +- HaWeb/Controllers/HomeController.cs | 9 +- HaWeb/Controllers/LegacyConroller.cs | 3 +- HaWeb/Controllers/RegisterController.cs | 70 +++------ HaWeb/Controllers/SucheController.cs | 9 +- HaWeb/Controllers/UpdateController.cs | 9 +- HaWeb/Controllers/UploadController.cs | 98 +++++------- HaWeb/FileHelpers/MultipartRequestHelper.cs | 12 +- HaWeb/FileHelpers/XDocumentFileHelpers.cs | 16 +- HaWeb/FileHelpers/XMLFileHelpers.cs | 39 ++--- HaWeb/Filters/Antiforgery.cs | 9 +- HaWeb/Filters/ModelBinding.cs | 9 +- HaWeb/HTMLHelpers/CommentHelper.cs | 18 +-- HaWeb/HTMLHelpers/ConversionHelpers.cs | 25 +-- HaWeb/HTMLHelpers/LetterHelpers.cs | 38 ++--- HaWeb/HTMLHelpers/LinkHelper.cs | 19 ++- HaWeb/HTMLHelpers/StringHelpers.cs | 12 +- HaWeb/HTMLHelpers/TagHelpers.cs | 23 +-- HaWeb/HTMLParser/Parser.cs | 2 +- HaWeb/Models/BriefeMetaViewModel.cs | 24 +-- HaWeb/Models/BriefeViewModel.cs | 24 +-- HaWeb/Models/CommentModel.cs | 6 +- HaWeb/Models/ErrorViewModel.cs | 3 +- HaWeb/Models/RegisterViewModel.cs | 22 +-- HaWeb/Models/SearchResult.cs | 6 +- HaWeb/Models/UploadViewModel.cs | 5 +- HaWeb/Program.cs | 25 ++- HaWeb/README.md | 4 +- HaWeb/Settings/CSSClassesSettings.cs | 2 +- HaWeb/Settings/Features.cs | 3 +- HaWeb/Settings/ParsingRules/CommentRules.cs | 6 +- HaWeb/Settings/ParsingRules/EditRules.cs | 2 +- HaWeb/Settings/ParsingRules/LetterRules.cs | 11 +- HaWeb/Settings/ParsingRules/LinkRules.cs | 2 +- HaWeb/Settings/ParsingRules/TraditionRules.cs | 3 +- HaWeb/Settings/ParsingState/LetterState.cs | 2 +- HaWeb/Settings/ParsingState/TraditionState.cs | 5 +- HaWeb/Settings/XMLRoots/CommentRoot.cs | 4 +- HaWeb/Settings/XMLRoots/DescriptionsRoot.cs | 4 +- HaWeb/Settings/XMLRoots/DocumentRoot.cs | 2 +- HaWeb/Settings/XMLRoots/EditsRoot.cs | 2 +- HaWeb/Settings/XMLRoots/MarginalsRoot.cs | 2 +- HaWeb/Settings/XMLRoots/ReferencesRoot.cs | 2 +- HaWeb/Settings/XMLRoots/TraditionsRoot.cs | 2 +- HaWeb/Views/Admin/Upload/Index.cshtml | 115 +++++++++----- HaWeb/Views/Briefe/Index.cshtml | 72 +++++---- HaWeb/Views/Shared/_Footer.cshtml | 2 - HaWeb/XMLParser/IXMLRoot.cs | 7 +- HaWeb/XMLParser/IXMLService.cs | 4 +- HaWeb/XMLParser/JSONConverters.cs | 34 ++++ HaWeb/XMLParser/XMLRootDocument.cs | 77 ++++++--- HaWeb/XMLParser/XMLService.cs | 146 +++++++++++++++++- HaWeb/omnisharp.json | 16 ++ HaWeb/wwwroot/css/output.css | 52 +++++-- HaWeb/wwwroot/css/site.css | 27 ++-- HaWeb/wwwroot/js/site.js | 17 -- XML/XML/test_empty.xml | 2 +- 61 files changed, 677 insertions(+), 558 deletions(-) create mode 100644 HaWeb/XMLParser/JSONConverters.cs create mode 100644 HaWeb/omnisharp.json diff --git a/HaWeb/.vscode/launch.json b/HaWeb/.vscode/launch.json index 6deccab..b0b920e 100644 --- a/HaWeb/.vscode/launch.json +++ b/HaWeb/.vscode/launch.json @@ -1,6 +1,12 @@ { "version": "0.2.0", "configurations": [ + { + "name": ".NET Core Attach", + "type": "coreclr", + "request": "attach", + "processName": "HaWeb", + }, { // Use IntelliSense to find out which attributes exist for C# debugging // Use hover for the description of the existing attributes @@ -24,12 +30,7 @@ }, "sourceFileMap": { "/Views": "${workspaceFolder}/Views" - } - }, - { - "name": ".NET Core Attach", - "type": "coreclr", - "request": "attach" + }, } ] } \ No newline at end of file diff --git a/HaWeb/Controllers/AdminController.cs b/HaWeb/Controllers/AdminController.cs index 6ed805b..cf27a25 100644 --- a/HaWeb/Controllers/AdminController.cs +++ b/HaWeb/Controllers/AdminController.cs @@ -4,23 +4,20 @@ using HaDocument.Interfaces; using HaXMLReader.Interfaces; using Microsoft.FeatureManagement.Mvc; -public class AdminController : Controller -{ +public class AdminController : Controller { // DI private ILibrary _lib; private IReaderService _readerService; - public AdminController(ILibrary lib, IReaderService readerService) - { + public AdminController(ILibrary lib, IReaderService readerService) { _lib = lib; _readerService = readerService; } [Route("Admin")] - [FeatureGate(Features.AdminService)] - public IActionResult Index() - { + [FeatureGate(Features.AdminService)] + public IActionResult Index() { return Redirect("/Admin/Upload"); } } \ No newline at end of file diff --git a/HaWeb/Controllers/BriefeContoller.cs b/HaWeb/Controllers/BriefeContoller.cs index 2be1cfd..c9542b1 100644 --- a/HaWeb/Controllers/BriefeContoller.cs +++ b/HaWeb/Controllers/BriefeContoller.cs @@ -7,8 +7,7 @@ using HaDocument.Models; namespace HaWeb.Controllers; -public class Briefecontroller : Controller -{ +public class Briefecontroller : Controller { [BindProperty(SupportsGet = true)] public string? id { get; set; } @@ -16,16 +15,14 @@ public class Briefecontroller : Controller private ILibrary _lib; private IReaderService _readerService; - public Briefecontroller(ILibrary lib, IReaderService readerService) - { + public Briefecontroller(ILibrary lib, IReaderService readerService) { _lib = lib; _readerService = readerService; } [Route("Briefe")] [Route("Briefe/{id?}")] - public IActionResult Index(string? id) - { + public IActionResult Index(string? id) { // Setup settings and variables var url = "/Briefe/"; var defaultID = "1"; @@ -73,25 +70,22 @@ public class Briefecontroller : Controller model.MetaData.ParsedZHString += " / " + parsedLetter.Startline; if (model.ParsedText == null || String.IsNullOrWhiteSpace(model.ParsedText)) model.MetaData.HasText = false; - } + } // Return return View(model); } - private IActionResult error404() - { + private IActionResult error404() { Response.StatusCode = 404; return Redirect("/Error404"); } - private BriefeMetaViewModel generateMetaViewModel(Meta meta, bool hasMarginals) - { + private BriefeMetaViewModel generateMetaViewModel(Meta meta, bool hasMarginals) { var senders = meta.Senders.Select(x => _lib.Persons[x].Name) ?? new List(); var recivers = meta.Receivers.Select(x => _lib.Persons[x].Name) ?? new List(); var zhstring = meta.ZH != null ? HaWeb.HTMLHelpers.LetterHelpers.CreateZHString(meta) : null; - return new BriefeMetaViewModel(meta, hasMarginals, false) - { + return new BriefeMetaViewModel(meta, hasMarginals, false) { ParsedZHString = zhstring, ParsedSenders = HTMLHelpers.StringHelpers.GetEnumerationString(senders), ParsedReceivers = HTMLHelpers.StringHelpers.GetEnumerationString(recivers) diff --git a/HaWeb/Controllers/EditionController.cs b/HaWeb/Controllers/EditionController.cs index 005b462..f5060b9 100644 --- a/HaWeb/Controllers/EditionController.cs +++ b/HaWeb/Controllers/EditionController.cs @@ -5,40 +5,32 @@ using HaWeb.Models; namespace HaWeb.Controllers; [Route("Edition/[action]")] -public class EditionController : Controller -{ +public class EditionController : Controller { [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] - public IActionResult Error() - { + public IActionResult Error() { return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier }); } - public IActionResult Kontakt() - { + public IActionResult Kontakt() { return View(); } - public IActionResult Mitwirkende() - { + public IActionResult Mitwirkende() { return View(); } - public IActionResult Richtlinien() - { + public IActionResult Richtlinien() { return View(); } - public IActionResult Werkausgabe() - { + public IActionResult Werkausgabe() { return View(); } - public IActionResult Editionsgeschichte() - { + public IActionResult Editionsgeschichte() { return View(); } - public IActionResult Datenschutzerklaerung() - { + public IActionResult Datenschutzerklaerung() { return View(); } } \ No newline at end of file diff --git a/HaWeb/Controllers/ErrorController.cs b/HaWeb/Controllers/ErrorController.cs index ee05173..e260143 100644 --- a/HaWeb/Controllers/ErrorController.cs +++ b/HaWeb/Controllers/ErrorController.cs @@ -5,8 +5,7 @@ using HaWeb.Models; namespace HaWeb.Controllers; -public class ErrorController : Controller -{ +public class ErrorController : Controller { [Route("Error404/")] public IActionResult ErrorNotFound() { return View(); diff --git a/HaWeb/Controllers/HomeController.cs b/HaWeb/Controllers/HomeController.cs index 3161953..38ac284 100644 --- a/HaWeb/Controllers/HomeController.cs +++ b/HaWeb/Controllers/HomeController.cs @@ -4,18 +4,15 @@ using HaWeb.Models; namespace HaWeb.Controllers; -public class HomeController : Controller -{ +public class HomeController : Controller { [Route("")] - public IActionResult Index() - { + public IActionResult Index() { return Redirect("/Suche"); } [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] - public IActionResult Error() - { + public IActionResult Error() { return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier }); } } diff --git a/HaWeb/Controllers/LegacyConroller.cs b/HaWeb/Controllers/LegacyConroller.cs index 0129478..faf3401 100644 --- a/HaWeb/Controllers/LegacyConroller.cs +++ b/HaWeb/Controllers/LegacyConroller.cs @@ -6,8 +6,7 @@ using HaWeb.Models; namespace HaWeb.Controllers; -public class LegacyContoller : Controller -{ +public class LegacyContoller : Controller { [Route("Supplementa/")] [Route("Supplementa/Register")] [Route("Supplementa/Register/{id?}")] diff --git a/HaWeb/Controllers/RegisterController.cs b/HaWeb/Controllers/RegisterController.cs index de2caab..a21ccb6 100644 --- a/HaWeb/Controllers/RegisterController.cs +++ b/HaWeb/Controllers/RegisterController.cs @@ -12,8 +12,7 @@ using System.Collections.Concurrent; namespace HaWeb.Controllers; [Route("Register/[action]/{id?}")] -public class RegisterController : Controller -{ +public class RegisterController : Controller { [BindProperty(SupportsGet = true)] public string? search { get; set; } @@ -24,14 +23,12 @@ public class RegisterController : Controller private ILibrary _lib; private IReaderService _readerService; - public RegisterController(ILibrary lib, IReaderService readerService) - { + public RegisterController(ILibrary lib, IReaderService readerService) { _lib = lib; _readerService = readerService; } - public IActionResult Register(string? id) - { + public IActionResult Register(string? id) { // Setup settings and variables var url = "/Register/Register/"; var category = "neuzeit"; @@ -52,15 +49,12 @@ public class RegisterController : Controller // Parsing var res = new List(); - foreach (var comm in comments) - { + foreach (var comm in comments) { var parsedComment = HTMLHelpers.CommentHelpers.CreateHTML(_lib, _readerService, comm, category, Settings.ParsingState.CommentType.Comment); List? parsedSubComments = null; - if (comm.Kommentare != null) - { + if (comm.Kommentare != null) { parsedSubComments = new List(); - foreach (var subcomm in comm.Kommentare.OrderBy(x => x.Value.Order)) - { + foreach (var subcomm in comm.Kommentare.OrderBy(x => x.Value.Order)) { parsedSubComments.Add(HTMLHelpers.CommentHelpers.CreateHTML(_lib, _readerService, subcomm.Value, category, Settings.ParsingState.CommentType.Subcomment)); } } @@ -68,8 +62,7 @@ public class RegisterController : Controller } // Model instantiation - var model = new RegisterViewModel(category, this.id, res, title) - { + var model = new RegisterViewModel(category, this.id, res, title) { AvailableCategories = availableCategories, }; @@ -77,8 +70,7 @@ public class RegisterController : Controller return View("Index", model); } - public IActionResult Bibelstellen(string? id) - { + public IActionResult Bibelstellen(string? id) { // Setup settings and variables var url = "/Register/Bibelstellen/"; var category = "bibel"; @@ -91,7 +83,7 @@ public class RegisterController : Controller if (id == null) return Redirect(url + defaultLetter); normalizeID(id, defaultLetter); if (this.id != "AT" && this.id != "AP" && this.id != "NT") return error404(); - + // Data aquisition and validation var comments = _lib.CommentsByCategory[category].ToLookup(x => x.Index.Substring(0, 2).ToUpper())[this.id].OrderBy(x => x.Order); var availableCategories = new List<(string, string)>() { ("Altes Testament", url + "AT"), ("Apogryphen", url + "AP"), ("Neues Testament", url + "NT") }; @@ -99,15 +91,12 @@ public class RegisterController : Controller // Parsing var res = new List(); - foreach (var comm in comments) - { + foreach (var comm in comments) { var parsedComment = HTMLHelpers.CommentHelpers.CreateHTML(_lib, _readerService, comm, category, Settings.ParsingState.CommentType.Comment); List? parsedSubComments = null; - if (comm.Kommentare != null) - { + if (comm.Kommentare != null) { parsedSubComments = new List(); - foreach (var subcomm in comm.Kommentare.OrderBy(x => x.Value.Lemma.Length).ThenBy(x => x.Value.Lemma)) - { + foreach (var subcomm in comm.Kommentare.OrderBy(x => x.Value.Lemma.Length).ThenBy(x => x.Value.Lemma)) { parsedSubComments.Add(HTMLHelpers.CommentHelpers.CreateHTML(_lib, _readerService, subcomm.Value, category, Settings.ParsingState.CommentType.Subcomment)); } } @@ -115,8 +104,7 @@ public class RegisterController : Controller } // Model instantiation - var model = new RegisterViewModel(category, this.id, res, title) - { + var model = new RegisterViewModel(category, this.id, res, title) { AvailableCategories = availableCategories, }; @@ -124,8 +112,7 @@ public class RegisterController : Controller return View("Index", model); } - public IActionResult Forschung(string? id) - { + public IActionResult Forschung(string? id) { // Setup settings and variables var url = "/Register/Forschung/"; var category = "forschung"; @@ -139,13 +126,12 @@ public class RegisterController : Controller normalizeID(id, defaultLetter); if (this.id != "EDITIONEN" && !_lib.CommentsByCategoryLetter[category].Contains(this.id)) return error404(); if (this.id == "EDITIONEN" && !_lib.CommentsByCategoryLetter.Keys.Contains(this.id.ToLower())) return error404(); - + // Data aquisition and validation IOrderedEnumerable? comments = null; if (this.id == "EDITIONEN") { comments = _lib.CommentsByCategory[this.id.ToLower()].OrderBy(x => x.Index); - } - else { + } else { comments = _lib.CommentsByCategoryLetter[category][this.id].OrderBy(x => x.Index); } var availableCategories = _lib.CommentsByCategoryLetter[category].Select(x => (x.Key.ToUpper(), url + x.Key.ToUpper())).OrderBy(x => x.Item1).ToList(); @@ -154,15 +140,12 @@ public class RegisterController : Controller // Parsing var res = new List(); - foreach (var comm in comments) - { + foreach (var comm in comments) { var parsedComment = HTMLHelpers.CommentHelpers.CreateHTML(_lib, _readerService, comm, category, Settings.ParsingState.CommentType.Comment); List? parsedSubComments = null; - if (comm.Kommentare != null) - { + if (comm.Kommentare != null) { parsedSubComments = new List(); - foreach (var subcomm in comm.Kommentare.OrderBy(x => x.Value.Order)) - { + foreach (var subcomm in comm.Kommentare.OrderBy(x => x.Value.Order)) { parsedSubComments.Add(HTMLHelpers.CommentHelpers.CreateHTML(_lib, _readerService, subcomm.Value, category, Settings.ParsingState.CommentType.Subcomment)); } } @@ -170,8 +153,7 @@ public class RegisterController : Controller } // Model instantiation - var model = new RegisterViewModel(category, this.id, res, title) - { + var model = new RegisterViewModel(category, this.id, res, title) { AvailableCategories = availableCategories, AvailableSideCategories = AvailableSideCategories }; @@ -180,22 +162,18 @@ public class RegisterController : Controller return View("Index", model); } - private void normalizeID(string? id, string defaultid) - { + private void normalizeID(string? id, string defaultid) { this.id = this.id.ToUpper(); } - private bool validationCheck(HashSet permitted) - { - if (!permitted.Contains(id)) - { + private bool validationCheck(HashSet permitted) { + if (!permitted.Contains(id)) { return false; } return true; } - private IActionResult error404() - { + private IActionResult error404() { Response.StatusCode = 404; return Redirect("/Error404"); } diff --git a/HaWeb/Controllers/SucheController.cs b/HaWeb/Controllers/SucheController.cs index 5438fff..6c1aeac 100644 --- a/HaWeb/Controllers/SucheController.cs +++ b/HaWeb/Controllers/SucheController.cs @@ -4,18 +4,15 @@ using HaWeb.Models; namespace HaWeb.Controllers; -public class SucheController : Controller -{ +public class SucheController : Controller { [Route("Suche")] - public IActionResult Index() - { + public IActionResult Index() { return View(); } [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] - public IActionResult Error() - { + public IActionResult Error() { return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier }); } } diff --git a/HaWeb/Controllers/UpdateController.cs b/HaWeb/Controllers/UpdateController.cs index 1c7b831..2fc3a9a 100644 --- a/HaWeb/Controllers/UpdateController.cs +++ b/HaWeb/Controllers/UpdateController.cs @@ -4,14 +4,12 @@ using HaDocument.Interfaces; using HaXMLReader.Interfaces; using Microsoft.FeatureManagement.Mvc; -public class UpdateController : Controller -{ +public class UpdateController : Controller { // DI private ILibrary _lib; private IReaderService _readerService; - public UpdateController(ILibrary lib, IReaderService readerService) - { + public UpdateController(ILibrary lib, IReaderService readerService) { _lib = lib; _readerService = readerService; } @@ -19,8 +17,7 @@ public class UpdateController : Controller [Route("Admin/Update")] [FeatureGate(Features.UpdateService)] - public IActionResult Index() - { + public IActionResult Index() { return View("../Admin/Upload/Index"); } } \ No newline at end of file diff --git a/HaWeb/Controllers/UploadController.cs b/HaWeb/Controllers/UploadController.cs index b7c8473..f09c64a 100644 --- a/HaWeb/Controllers/UploadController.cs +++ b/HaWeb/Controllers/UploadController.cs @@ -21,8 +21,7 @@ using System.Xml.Linq; using System.Text.Json.Serialization; using System.Text.Json; -public class UploadController : Controller -{ +public class UploadController : Controller { // DI private ILibrary _lib; private IReaderService _readerService; @@ -35,8 +34,7 @@ public class UploadController : Controller private static readonly FormOptions _defaultFormOptions = new FormOptions(); - public UploadController(ILibrary lib, IReaderService readerService, IXMLService xmlService, IConfiguration config) - { + public UploadController(ILibrary lib, IReaderService readerService, IXMLService xmlService, IConfiguration config) { _lib = lib; _readerService = readerService; _xmlService = xmlService; @@ -49,27 +47,28 @@ public class UploadController : Controller } [HttpGet] - [Route("Admin/Upload")] + [Route("Admin/Upload/{id?}")] [FeatureGate(Features.UploadService)] [GenerateAntiforgeryTokenCookie] - public IActionResult Index() - { + public IActionResult Index(string? id) { var model = new UploadViewModel(); - model.AvailableRoots = _xmlService.GetRoots().Select(x => (x.Type, "")).ToList(); + model.AvailableRoots = _xmlService.GetRoots(); + model.UsedFiles = _xmlService.GetUsed(); + var hello = "mama"; return View("../Admin/Upload/Index", model); } -//// UPLOAD //// + //// UPLOAD //// [HttpPost] [Route("Admin/Upload")] [DisableFormValueModelBinding] [ValidateAntiForgeryToken] public async Task Post() { -//// 1. Stage: Check Request format and request spec + List? docs = null; + //// 1. Stage: Check Request format and request spec // Checks the Content-Type Field (must be multipart + Boundary) - if (!MultipartRequestHelper.IsMultipartContentType(Request.ContentType)) - { + if (!MultipartRequestHelper.IsMultipartContentType(Request.ContentType)) { ModelState.AddModelError("Error", $"Wrong / No Content Type on the Request"); return BadRequest(ModelState); } @@ -80,80 +79,63 @@ public class UploadController : Controller MultipartSection? section = null; try { section = await reader.ReadNextSectionAsync(); - } - catch (Exception ex) { + } catch (Exception ex) { ModelState.AddModelError("Error", "The Request is bad: " + ex.Message); } - while (section != null) - { + while (section != null) { // Multipart document content disposition header read for a section: // Starts with boundary, contains field name, content-dispo, filename, content-type var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out var contentDisposition); - if (hasContentDispositionHeader && contentDisposition != null) - { + if (hasContentDispositionHeader && contentDisposition != null) { // Checks if it is a section with content-disposition, name, filename - if (!MultipartRequestHelper.HasFileContentDisposition(contentDisposition)) - { + if (!MultipartRequestHelper.HasFileContentDisposition(contentDisposition)) { ModelState.AddModelError("Error", $"Wrong Content-Dispostion Headers in Multipart Document"); return BadRequest(ModelState); } -//// 2. Stage: Check File. Sanity checks on the file on a byte level, extension checking, is it empty etc. + //// 2. Stage: Check File. Sanity checks on the file on a byte level, extension checking, is it empty etc. var streamedFileContent = await XMLFileHelpers.ProcessStreamedFile( - section, contentDisposition, ModelState, + section, contentDisposition, ModelState, _permittedExtensions, _fileSizeLimit); if (!ModelState.IsValid || streamedFileContent == null) return BadRequest(ModelState); -//// 3. Stage: Valid XML checking using a simple XDocument.Load() + //// 3. Stage: Valid XML checking using a simple XDocument.Load() var xdocument = await XDocumentFileHelper.ProcessStreamedFile(streamedFileContent, ModelState); if (!ModelState.IsValid || xdocument == null) return UnprocessableEntity(ModelState); -//// 4. Stage: Is it a Hamann-Document? What kind? - var docs = _xmlService.ProbeHamannFile(xdocument, ModelState); - if (!ModelState.IsValid || docs == null || !docs.Any()) + //// 4. Stage: Is it a Hamann-Document? What kind? + var retdocs = await _xmlService.ProbeHamannFile(xdocument, ModelState); + if (!ModelState.IsValid || retdocs == null || !retdocs.Any()) return UnprocessableEntity(ModelState); - -//// 5. Stage: Saving the File(s) - foreach (var doc in docs) { - var type = doc.Prefix; - var directory = Path.Combine(_targetFilePath, type); - if (!Directory.Exists(directory)) - Directory.CreateDirectory(directory); - var path = Path.Combine(directory, doc.FileName); - try { - using (var targetStream = System.IO.File.Create(path)) - await doc.Save(targetStream, ModelState); - if (!ModelState.IsValid) return StatusCode(500, ModelState); - } - catch (Exception ex) { - ModelState.AddModelError("Error", "Speichern der Datei fehlgeschlagen: " + ex.Message); - return StatusCode(500, ModelState); - } + + //// 5. Stage: Saving the File(s) + foreach (var doc in retdocs) { + await _xmlService.UpdateAvailableFiles(doc, _targetFilePath, ModelState); + if (!ModelState.IsValid) return StatusCode(500, ModelState); + if (docs == null) docs = new List(); + docs.Add(doc); } - -// 6. State: Returning Ok, and redirecting - JsonSerializerOptions options = new() { - ReferenceHandler = ReferenceHandler.Preserve - }; - - string json = JsonSerializer.Serialize(docs); - return Created(nameof(UploadController), json); } - try - { + try { section = await reader.ReadNextSectionAsync(); - } - catch (Exception ex) - { + } catch (Exception ex) { ModelState.AddModelError("Error", "The Request is bad: " + ex.Message); } } -//// Success! Return Last Created File View - return Created(nameof(UploadController), null); + // 6. Stage: Success! Returning Ok, and redirecting + JsonSerializerOptions options = new() { + ReferenceHandler = ReferenceHandler.Preserve, + Converters = { + new IdentificationStringJSONConverter() + } + }; + + string json = JsonSerializer.Serialize(docs); + return Created(nameof(UploadController), json); } } \ No newline at end of file diff --git a/HaWeb/FileHelpers/MultipartRequestHelper.cs b/HaWeb/FileHelpers/MultipartRequestHelper.cs index d9da021..bc268aa 100644 --- a/HaWeb/FileHelpers/MultipartRequestHelper.cs +++ b/HaWeb/FileHelpers/MultipartRequestHelper.cs @@ -3,12 +3,10 @@ using System; using System.IO; using Microsoft.Net.Http.Headers; -public static class MultipartRequestHelper -{ +public static class MultipartRequestHelper { // Content-Type: multipart/form-data; boundary="----WebKitFormBoundarymx2fSWqWSd0OxQqq" // The spec at https://tools.ietf.org/html/rfc2046#section-5.1 states that 70 characters is a reasonable limit. - public static string GetBoundary(MediaTypeHeaderValue contentType, int lengthLimit) - { + public static string GetBoundary(MediaTypeHeaderValue contentType, int lengthLimit) { var boundary = HeaderUtilities.RemoveQuotes(contentType.Boundary).Value; if (string.IsNullOrWhiteSpace(boundary)) @@ -23,8 +21,7 @@ public static class MultipartRequestHelper public static bool IsMultipartContentType(string? contentType) => !string.IsNullOrEmpty(contentType) && contentType.IndexOf("multipart/", StringComparison.OrdinalIgnoreCase) >= 0; - public static bool HasFormDataContentDisposition(ContentDispositionHeaderValue contentDisposition) - { + public static bool HasFormDataContentDisposition(ContentDispositionHeaderValue contentDisposition) { // Content-Disposition: form-data; name="key"; return contentDisposition != null && contentDisposition.DispositionType.Equals("form-data") @@ -32,8 +29,7 @@ public static class MultipartRequestHelper && string.IsNullOrEmpty(contentDisposition.FileNameStar.Value); } - public static bool HasFileContentDisposition(ContentDispositionHeaderValue? contentDisposition) - { + public static bool HasFileContentDisposition(ContentDispositionHeaderValue? contentDisposition) { return contentDisposition != null && contentDisposition.DispositionType.Equals("form-data") && (!string.IsNullOrEmpty(contentDisposition.FileName.Value) diff --git a/HaWeb/FileHelpers/XDocumentFileHelpers.cs b/HaWeb/FileHelpers/XDocumentFileHelpers.cs index e747834..70ad09b 100644 --- a/HaWeb/FileHelpers/XDocumentFileHelpers.cs +++ b/HaWeb/FileHelpers/XDocumentFileHelpers.cs @@ -6,8 +6,7 @@ using System.Xml; public static class XDocumentFileHelper { - private readonly static XmlReaderSettings _Settings = new XmlReaderSettings() - { + private readonly static XmlReaderSettings _Settings = new XmlReaderSettings() { CloseInput = true, CheckCharacters = false, ConformanceLevel = ConformanceLevel.Fragment, @@ -17,19 +16,14 @@ public static class XDocumentFileHelper { }; public static async Task ProcessStreamedFile(byte[] bytes, ModelStateDictionary modelState) { - try - { - using (var stream = new MemoryStream(bytes)) - { - using (var xmlreader = XmlReader.Create(stream, _Settings)) - { + try { + using (var stream = new MemoryStream(bytes)) { + using (var xmlreader = XmlReader.Create(stream, _Settings)) { return XDocument.Load(xmlreader, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); } } - } - catch (Exception ex) - { + } catch (Exception ex) { modelState.AddModelError("Error", $"Kein gültiges XML-Dokument geladen. Error: {ex.Message}"); } diff --git a/HaWeb/FileHelpers/XMLFileHelpers.cs b/HaWeb/FileHelpers/XMLFileHelpers.cs index 07b5341..8edc7ca 100644 --- a/HaWeb/FileHelpers/XMLFileHelpers.cs +++ b/HaWeb/FileHelpers/XMLFileHelpers.cs @@ -12,8 +12,7 @@ using Microsoft.AspNetCore.Mvc.ModelBinding; using Microsoft.AspNetCore.WebUtilities; using Microsoft.Net.Http.Headers; -public static class XMLFileHelpers -{ +public static class XMLFileHelpers { // File Signatures Database (https://www.filesignatures.net/) private static readonly Dictionary> _fileSignature = new Dictionary> { @@ -33,9 +32,9 @@ public static class XMLFileHelpers new byte[] { 0xFF, 0xD8, 0xFF, 0xE8 }, } }, - { ".zip", new List + { ".zip", new List { - new byte[] { 0x50, 0x4B, 0x03, 0x04 }, + new byte[] { 0x50, 0x4B, 0x03, 0x04 }, new byte[] { 0x50, 0x4B, 0x4C, 0x49, 0x54, 0x45 }, new byte[] { 0x50, 0x4B, 0x53, 0x70, 0x58 }, new byte[] { 0x50, 0x4B, 0x05, 0x06 }, @@ -90,7 +89,7 @@ public static class XMLFileHelpers // return Array.Empty(); // } - + // if (formFile.Length > sizeLimit) // { // var megabyteSizeLimit = sizeLimit / 1048576; @@ -141,20 +140,16 @@ public static class XMLFileHelpers // } public static async Task ProcessStreamedFile( - MultipartSection section, ContentDispositionHeaderValue contentDisposition, - ModelStateDictionary modelState, string[] permittedExtensions, long sizeLimit) - { - try - { - using (var memoryStream = new MemoryStream()) - { + MultipartSection section, ContentDispositionHeaderValue contentDisposition, + ModelStateDictionary modelState, string[] permittedExtensions, long sizeLimit) { + try { + using (var memoryStream = new MemoryStream()) { await section.Body.CopyToAsync(memoryStream); // Check if the file is empty or exceeds the size limit. if (memoryStream.Length == 0) modelState.AddModelError("Error", "The file is empty."); - else if (memoryStream.Length > sizeLimit) - { + else if (memoryStream.Length > sizeLimit) { var megabyteSizeLimit = sizeLimit / 1048576; modelState.AddModelError("Error", $"The file exceeds {megabyteSizeLimit:N1} MB."); } @@ -164,21 +159,18 @@ public static class XMLFileHelpers modelState.AddModelError("Error", "The file must be of the following specs:
" + "1. The file must hava a .xml File-Extension
" + "2. To make sure the file isn't executable the file must start with: or "); - + // Return the File as a byte array else return memoryStream.ToArray(); } - } - catch (Exception ex) - { + } catch (Exception ex) { modelState.AddModelError("Error", $"The upload failed. Error: {ex.Message}"); } - + return null; } - private static bool IsValidFileExtensionAndSignature(string fileName, Stream data, string[] permittedExtensions) - { + private static bool IsValidFileExtensionAndSignature(string fileName, Stream data, string[] permittedExtensions) { if (string.IsNullOrEmpty(fileName) || data == null || data.Length == 0) return false; @@ -189,11 +181,10 @@ public static class XMLFileHelpers data.Position = 0; - using (var reader = new BinaryReader(data)) - { + using (var reader = new BinaryReader(data)) { var signatures = _fileSignature[ext]; var headerBytes = reader.ReadBytes(signatures.Max(m => m.Length)); - return signatures.Any(signature => + return signatures.Any(signature => headerBytes.Take(signature.Length).SequenceEqual(signature)); } } diff --git a/HaWeb/Filters/Antiforgery.cs b/HaWeb/Filters/Antiforgery.cs index b6c1662..e5f8fb5 100644 --- a/HaWeb/Filters/Antiforgery.cs +++ b/HaWeb/Filters/Antiforgery.cs @@ -4,10 +4,8 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.Extensions.DependencyInjection; -public class GenerateAntiforgeryTokenCookieAttribute : ResultFilterAttribute -{ - public override void OnResultExecuting(ResultExecutingContext context) - { +public class GenerateAntiforgeryTokenCookieAttribute : ResultFilterAttribute { + public override void OnResultExecuting(ResultExecutingContext context) { var antiforgery = context.HttpContext.RequestServices.GetService(); // Send the request token as a JavaScript-readable cookie @@ -19,8 +17,7 @@ public class GenerateAntiforgeryTokenCookieAttribute : ResultFilterAttribute new CookieOptions() { HttpOnly = false }); } - public override void OnResultExecuted(ResultExecutedContext context) - { + public override void OnResultExecuted(ResultExecutedContext context) { } } diff --git a/HaWeb/Filters/ModelBinding.cs b/HaWeb/Filters/ModelBinding.cs index 37e5cf7..48fd47f 100644 --- a/HaWeb/Filters/ModelBinding.cs +++ b/HaWeb/Filters/ModelBinding.cs @@ -4,17 +4,14 @@ using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.AspNetCore.Mvc.ModelBinding; [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] -public class DisableFormValueModelBindingAttribute : Attribute, IResourceFilter -{ - public void OnResourceExecuting(ResourceExecutingContext context) - { +public class DisableFormValueModelBindingAttribute : Attribute, IResourceFilter { + public void OnResourceExecuting(ResourceExecutingContext context) { var factories = context.ValueProviderFactories; factories.RemoveType(); factories.RemoveType(); factories.RemoveType(); } - public void OnResourceExecuted(ResourceExecutedContext context) - { + public void OnResourceExecuted(ResourceExecutedContext context) { } } diff --git a/HaWeb/HTMLHelpers/CommentHelper.cs b/HaWeb/HTMLHelpers/CommentHelper.cs index dd55d99..240ff5a 100644 --- a/HaWeb/HTMLHelpers/CommentHelper.cs +++ b/HaWeb/HTMLHelpers/CommentHelper.cs @@ -7,16 +7,14 @@ using HaWeb.Settings.ParsingRules; using HaWeb.Settings.ParsingState; using System.Text; -public static class CommentHelpers -{ +public static class CommentHelpers { private static readonly string DEFAULTELEMENT = HaWeb.Settings.HTML.DEFAULTELEMENT; private static readonly string BACKLINKSCLASS = HaWeb.Settings.CSSClasses.BACKLINKSCLASS; private static readonly string LETLINKCLASS = HaWeb.Settings.CSSClasses.LETLINKCLASS; private static readonly string COMMENTHEADCLASS = HaWeb.Settings.CSSClasses.COMMENTHEADCLASS; private static readonly string BACKLINKSHKBCLASS = HaWeb.Settings.CSSClasses.BACKLINKSHKBCLASS; - public static string CreateHTML(ILibrary lib, IReaderService readerService, Comment comment, string category, CommentType type) - { + public static string CreateHTML(ILibrary lib, IReaderService readerService, Comment comment, string category, CommentType type) { var sb = new StringBuilder(); var rd = readerService.RequestStringReader(comment.Lemma); var commentState = new CommentState(category, type); @@ -28,17 +26,13 @@ public static class CommentHelpers .Where(x => lib.Metas.ContainsKey(x.Letter)) .OrderBy(x => lib.Metas[x.Letter].Sort) .ThenBy(x => lib.Metas[x.Letter].Order) : null; - if (backlinks != null) - { + if (backlinks != null) { sb.Append(HTMLHelpers.TagHelpers.CreateElement(DEFAULTELEMENT, BACKLINKSCLASS)); var arrow = false; - foreach (var blk in backlinks) - { + foreach (var blk in backlinks) { var let = lib.Metas.ContainsKey(blk.Letter) ? lib.Metas[blk.Letter] : null; - if (let != null) - { - if (!arrow) - { + if (let != null) { + if (!arrow) { sb.Append(HTMLHelpers.TagHelpers.CreateElement(DEFAULTELEMENT, BACKLINKSHKBCLASS)); sb.Append("HKB "); sb.Append(HTMLHelpers.TagHelpers.CreateEndElement(DEFAULTELEMENT)); diff --git a/HaWeb/HTMLHelpers/ConversionHelpers.cs b/HaWeb/HTMLHelpers/ConversionHelpers.cs index 33dd3af..f3f0f01 100644 --- a/HaWeb/HTMLHelpers/ConversionHelpers.cs +++ b/HaWeb/HTMLHelpers/ConversionHelpers.cs @@ -14,36 +14,27 @@ public static class ConversionHelpers { {'M', 1000} }; - public static int RomanToInteger(string roman) - { + public static int RomanToInteger(string roman) { var ro = roman.ToUpper(); int number = 0; - for (int i = 0; i < roman.Length; i++) - { - if (RomanMap.ContainsKey(ro[i]) && (i + 1 >= ro.Length || RomanMap.ContainsKey(ro[i + 1]))) - { - if (i + 1 < ro.Length && RomanMap[ro[i]] < RomanMap[ro[i + 1]]) - { + for (int i = 0; i < roman.Length; i++) { + if (RomanMap.ContainsKey(ro[i]) && (i + 1 >= ro.Length || RomanMap.ContainsKey(ro[i + 1]))) { + if (i + 1 < ro.Length && RomanMap[ro[i]] < RomanMap[ro[i + 1]]) { number -= RomanMap[ro[i]]; - } - else - { + } else { number += RomanMap[ro[i]]; } - } - else return 0; + } else return 0; } return number; } - public static int RomanOrNumberToInt(string number) - { + public static int RomanOrNumberToInt(string number) { var a = 0; if (Int32.TryParse(number, out a)) return a; else return RomanToInteger(number); } - public static string ToRoman(int number) - { + public static string ToRoman(int number) { if ((number < 0) || (number > 3999)) return string.Empty; if (number < 1) return string.Empty; if (number >= 1000) return "M" + ToRoman(number - 1000); diff --git a/HaWeb/HTMLHelpers/LetterHelpers.cs b/HaWeb/HTMLHelpers/LetterHelpers.cs index addbad6..cd504e6 100644 --- a/HaWeb/HTMLHelpers/LetterHelpers.cs +++ b/HaWeb/HTMLHelpers/LetterHelpers.cs @@ -11,10 +11,8 @@ using System.Xml.Linq; using HaWeb.Settings.ParsingState; using HaWeb.Settings.ParsingRules; -public static class LetterHelpers -{ - public static LetterState CreateLetter(ILibrary lib, IReaderService readerService, Meta meta, Letter letter, IEnumerable? marginals, IEnumerable? hands, IEnumerable? edits) - { +public static class LetterHelpers { + public static LetterState CreateLetter(ILibrary lib, IReaderService readerService, Meta meta, Letter letter, IEnumerable? marginals, IEnumerable? hands, IEnumerable? edits) { var rd = readerService.RequestStringReader(letter.Element); var letterState = new LetterState(lib, readerService, meta, marginals, hands, edits); new HaWeb.HTMLParser.XMLHelper(letterState, rd, letterState.sb_lettertext, LetterRules.OTagRules, LetterRules.STagRules, LetterRules.CTagRules, LetterRules.TextRules, LetterRules.WhitespaceRules); @@ -23,8 +21,7 @@ public static class LetterHelpers return letterState; } - public static TraditionState CreateTraditions(ILibrary lib, IReaderService readerService, IEnumerable? marginals, Tradition tradition, IEnumerable? hands, IEnumerable? edits) - { + public static TraditionState CreateTraditions(ILibrary lib, IReaderService readerService, IEnumerable? marginals, Tradition tradition, IEnumerable? hands, IEnumerable? edits) { var rd = readerService.RequestStringReader(tradition.Element); var traditionState = new TraditionState(lib, rd, readerService, marginals, hands, edits); new HaWeb.HTMLParser.XMLHelper(traditionState, rd, traditionState.sb_tradition, TraditionRules.OTagRules, TraditionRules.STagRules, TraditionRules.CTagRules, TraditionRules.TextRules, TraditionRules.WhitespaceRules); @@ -33,13 +30,11 @@ public static class LetterHelpers return traditionState; } - public static List<(string, string, string, string, string, string)> CreateEdits(ILibrary lib, IReaderService readerService, IEnumerable editreasons) - { + public static List<(string, string, string, string, string, string)> CreateEdits(ILibrary lib, IReaderService readerService, IEnumerable editreasons) { editreasons = editreasons.OrderBy(x => HaWeb.HTMLHelpers.ConversionHelpers.RomanOrNumberToInt(x.StartPage)).ThenBy(x => HaWeb.HTMLHelpers.ConversionHelpers.RomanOrNumberToInt(x.StartLine)); var editstrings = new List<(string, string, string, string, string, string)>(); var editsState = new EditState(); - foreach (var edit in editreasons) - { + foreach (var edit in editreasons) { var currstring = edit.StartPage + "/" + edit.StartLine; var endstring = ""; var refstring = ""; @@ -47,10 +42,9 @@ public static class LetterHelpers endstring += edit.EndPage + "/" + edit.EndLine; else if (edit.StartLine != edit.EndLine) endstring += edit.EndLine; - + editsState.sb_edits.Append(HaWeb.HTMLHelpers.TagHelpers.CreateElement("div", "edit")); - if (!String.IsNullOrWhiteSpace(edit.Reference)) - { + if (!String.IsNullOrWhiteSpace(edit.Reference)) { var sb2 = new StringBuilder(); sb2.Append(HaWeb.HTMLHelpers.TagHelpers.CreateElement("span", "reference")); var rd = readerService.RequestStringReader(edit.Reference); @@ -58,8 +52,7 @@ public static class LetterHelpers rd.Read(); sb2.Append(HaWeb.HTMLHelpers.TagHelpers.CreateEndElement("span")); // Old: (edit.StartPage != edit.EndPage || edit.StartLine != edit.EndLine) && - if (XElement.Parse(sb2.ToString()).Value.ToString().Length >= 20) - { + if (XElement.Parse(sb2.ToString()).Value.ToString().Length >= 20) { var text = XElement.Parse(sb2.ToString()).Value.ToString(); text = text.ToString().Split(' ').Take(1).First() + " […] " + text.ToString().Split(' ').TakeLast(1).First(); var sb3 = new StringBuilder(); @@ -67,12 +60,10 @@ public static class LetterHelpers sb3.Append(text); sb3.Append(HaWeb.HTMLHelpers.TagHelpers.CreateEndElement("span")); refstring = sb3.ToString(); - } - else + } else refstring = sb2.ToString(); } - if (!String.IsNullOrWhiteSpace(edit.Element)) - { + if (!String.IsNullOrWhiteSpace(edit.Element)) { editsState.sb_edits.Append(HaWeb.HTMLHelpers.TagHelpers.CreateElement("span", "corrections")); var rd = readerService.RequestStringReader(edit.Element); new HaWeb.HTMLParser.XMLHelper(editsState, rd, editsState.sb_edits, EditRules.OTagRules, EditRules.STagRules, EditRules.CTagRules, EditRules.TextRules, EditRules.WhitespaceRules); @@ -86,11 +77,9 @@ public static class LetterHelpers return editstrings; } - public static List<(string, string, string, string, string)> CreateHands(ILibrary lib, ImmutableList hands) - { + public static List<(string, string, string, string, string)> CreateHands(ILibrary lib, ImmutableList hands) { var handstrings = new List<(string, string, string, string, string)>(); - foreach (var hand in hands.OrderBy(x => x.StartPage.Length).ThenBy(x => x.StartPage).ThenBy(x => x.StartLine.Length).ThenBy(x => x.StartLine)) - { + foreach (var hand in hands.OrderBy(x => x.StartPage.Length).ThenBy(x => x.StartPage).ThenBy(x => x.StartLine.Length).ThenBy(x => x.StartLine)) { var currstring = hand.StartPage + "/" + hand.StartLine; var endstring = ""; var personstring = ""; @@ -100,8 +89,7 @@ public static class LetterHelpers if (hand.StartLine != hand.EndLine) endstring += hand.EndLine; var persons = lib.HandPersons.Where(x => x.Key == hand.Person); - if (persons.Any()) - { + if (persons.Any()) { personstring += " " + persons.FirstOrDefault().Value.Name; handstrings.Add((currstring, endstring, personstring, hand.StartPage, hand.StartLine)); } diff --git a/HaWeb/HTMLHelpers/LinkHelper.cs b/HaWeb/HTMLHelpers/LinkHelper.cs index 17ad629..3c647e2 100644 --- a/HaWeb/HTMLHelpers/LinkHelper.cs +++ b/HaWeb/HTMLHelpers/LinkHelper.cs @@ -37,21 +37,20 @@ public class LinkHelper { if (tag.Name == "wwwlink" || tag.Name == "intlink" || tag.Name == "link") { if (tag.EndTag && _followlinksinthis) { _sb.Append(HTMLHelpers.TagHelpers.CreateEndElement("a")); - } - else { + } else { if (tag.Name == "wwwlink" && tag.Values.ContainsKey("address") && _followlinksinthis) - _sb.Append(HTMLHelpers.TagHelpers.CreateCustomElement("a", - new HaWeb.HTMLHelpers.TagHelpers.Attribute() { Name = "class", Value = WWWLINKCLASS }, - new HaWeb.HTMLHelpers.TagHelpers.Attribute() { Name = "href", Value = tag["address"]}, - new HaWeb.HTMLHelpers.TagHelpers.Attribute() { Name = "target", Value = "_blank"}, - new HaWeb.HTMLHelpers.TagHelpers.Attribute() { Name = "rel", Value = "noopener noreferrer"})); + _sb.Append(HTMLHelpers.TagHelpers.CreateCustomElement("a", + new HaWeb.HTMLHelpers.TagHelpers.Attribute() { Name = "class", Value = WWWLINKCLASS }, + new HaWeb.HTMLHelpers.TagHelpers.Attribute() { Name = "href", Value = tag["address"] }, + new HaWeb.HTMLHelpers.TagHelpers.Attribute() { Name = "target", Value = "_blank" }, + new HaWeb.HTMLHelpers.TagHelpers.Attribute() { Name = "rel", Value = "noopener noreferrer" })); if (tag.Name == "intlink" && tag.Values.ContainsKey("letter") && _lib.Metas.ContainsKey(tag["letter"])) { var letter = _lib.Metas[tag["letter"]]; _sb.Append(HTMLHelpers.TagHelpers.CreateElement("a", LETLINKCLASS, "/Briefe/" + letter.Autopsic + "#" + tag["page"] + "-" + tag["line"])); if (!tag.Values.ContainsKey("linktext") || tag.Values["linktext"] == "true") { var linkstring = ""; var ZHstring = ""; - var pglnstring= ""; + var pglnstring = ""; linkstring += "HKB " + letter.Autopsic; if (tag.Values.ContainsKey("page")) { pglnstring += tag["page"]; @@ -70,7 +69,7 @@ public class LinkHelper { } if (tag.Name == "link" && tag.Values != null) { Comment comment = null; - if (tag.Values.ContainsKey("subref") && _lib.SubCommentsByID.ContainsKey(tag["subref"])) + if (tag.Values.ContainsKey("subref") && _lib.SubCommentsByID.ContainsKey(tag["subref"])) comment = _lib.SubCommentsByID[tag["subref"]]; else if (tag.Values.ContainsKey("ref")) if (_lib.Comments.ContainsKey(tag["ref"])) @@ -80,7 +79,7 @@ public class LinkHelper { if (comment != null) { var linkloc = String.IsNullOrWhiteSpace(comment.Parent) ? comment.Index : comment.Parent; if (_followlinksinthis) - if (comment.Type == "neuzeit") + if (comment.Type == "neuzeit") _sb.Append(HTMLHelpers.TagHelpers.CreateElement("a", REFLINKCLASS, "/Register/Register/" + linkloc[0] + "#" + comment.Index)); else if (comment.Type == "bibel") _sb.Append(HTMLHelpers.TagHelpers.CreateElement("a", REFLINKCLASS, "/Register/Bibelstellen/" + linkloc[0] + linkloc[1] + "#" + comment.Index)); diff --git a/HaWeb/HTMLHelpers/StringHelpers.cs b/HaWeb/HTMLHelpers/StringHelpers.cs index 971a55c..723eba7 100644 --- a/HaWeb/HTMLHelpers/StringHelpers.cs +++ b/HaWeb/HTMLHelpers/StringHelpers.cs @@ -2,17 +2,15 @@ using System.Web; namespace HaWeb.HTMLHelpers; public static class StringHelpers { - public static string GetEnumerationString(IEnumerable strlist) - { + public static string GetEnumerationString(IEnumerable strlist) { var res = ""; - foreach (var str in strlist) - { + foreach (var str in strlist) { if (str != strlist.First()) - if (str == strlist.Last()) + if (str == strlist.Last()) res += " und " + str; else - res += ", " + str; - else + res += ", " + str; + else res += str; } return res; diff --git a/HaWeb/HTMLHelpers/TagHelpers.cs b/HaWeb/HTMLHelpers/TagHelpers.cs index 58619dc..aa412d5 100644 --- a/HaWeb/HTMLHelpers/TagHelpers.cs +++ b/HaWeb/HTMLHelpers/TagHelpers.cs @@ -3,21 +3,18 @@ using System; using System.Collections.Generic; using System.Linq; -public static class TagHelpers -{ - public struct Attribute - { +public static class TagHelpers { + public struct Attribute { public string Name; public string Value; } - public static string CreateElement(string elementname, string classes = "", string ids = "") - { + public static string CreateElement(string elementname, string classes = "", string ids = "") { string res = "<" + elementname; if (!String.IsNullOrWhiteSpace(classes)) if (elementname == "button") res += CreateAttribute(new Attribute() { Name = "type", Value = classes }); - else + else res += CreateAttribute(new Attribute() { Name = "class", Value = classes }); if (!String.IsNullOrWhiteSpace(ids)) if (elementname == "a") @@ -27,13 +24,10 @@ public static class TagHelpers return res + ">"; } - public static string CreateCustomElement(string elementname, params Attribute[] attributes) - { + public static string CreateCustomElement(string elementname, params Attribute[] attributes) { string res = "<" + elementname; - if (!(attributes.Length == 0)) - { - foreach (var attrib in attributes) - { + if (!(attributes.Length == 0)) { + foreach (var attrib in attributes) { res += CreateAttribute(attrib); } } @@ -47,8 +41,7 @@ public static class TagHelpers public static string CreateAttribute(Attribute attr) => " " + attr.Name + "=\"" + attr.Value + "\" "; - public static string CreateEmptyElement(string elementname, string classes = "", string ids = "") - { + public static string CreateEmptyElement(string elementname, string classes = "", string ids = "") { string res = "<" + elementname; if (!String.IsNullOrWhiteSpace(classes)) res += CreateAttribute(new Attribute() { Name = "class", Value = classes }); diff --git a/HaWeb/HTMLParser/Parser.cs b/HaWeb/HTMLParser/Parser.cs index 55519f8..40ac54c 100644 --- a/HaWeb/HTMLParser/Parser.cs +++ b/HaWeb/HTMLParser/Parser.cs @@ -1,5 +1,5 @@ namespace HaWeb.HTMLParser; class GenericParser where T : IState { - + } \ No newline at end of file diff --git a/HaWeb/Models/BriefeMetaViewModel.cs b/HaWeb/Models/BriefeMetaViewModel.cs index 7159f04..dd5dca5 100644 --- a/HaWeb/Models/BriefeMetaViewModel.cs +++ b/HaWeb/Models/BriefeMetaViewModel.cs @@ -1,8 +1,7 @@ namespace HaWeb.Models; using HaDocument.Models; using System.Web; -public class BriefeMetaViewModel -{ +public class BriefeMetaViewModel { public Meta Meta { get; private set; } public bool HasMarginals { get; private set; } public bool ShowZHData { get; private set; } @@ -12,11 +11,9 @@ public class BriefeMetaViewModel private string? _ParsedReceivers; private string? _ParsedZHString; - public string? ParsedSenders - { + public string? ParsedSenders { get => _ParsedSenders; - set - { + set { if (value != null) _ParsedSenders = HttpUtility.HtmlEncode(value); else @@ -24,11 +21,9 @@ public class BriefeMetaViewModel } } - public string? ParsedReceivers - { + public string? ParsedReceivers { get => _ParsedReceivers; - set - { + set { if (value != null) _ParsedReceivers = HttpUtility.HtmlEncode(value); else @@ -37,11 +32,9 @@ public class BriefeMetaViewModel } } - public string? ParsedZHString - { + public string? ParsedZHString { get => _ParsedZHString; - set - { + set { if (value != null) _ParsedZHString = HttpUtility.HtmlEncode(value); else @@ -54,8 +47,7 @@ public class BriefeMetaViewModel public (BriefeMetaViewModel, string)? Prev { get; set; } - public BriefeMetaViewModel(Meta meta, bool hasMarginals, bool showZHData) - { + public BriefeMetaViewModel(Meta meta, bool hasMarginals, bool showZHData) { Meta = meta; HasMarginals = hasMarginals; ShowZHData = showZHData; diff --git a/HaWeb/Models/BriefeViewModel.cs b/HaWeb/Models/BriefeViewModel.cs index 1c62400..bd9d656 100644 --- a/HaWeb/Models/BriefeViewModel.cs +++ b/HaWeb/Models/BriefeViewModel.cs @@ -1,8 +1,7 @@ namespace HaWeb.Models; using System.Web; -public class BriefeViewModel -{ +public class BriefeViewModel { public string Id { get; private set; } public string Index { get; private set; } public BriefeMetaViewModel MetaData { get; private set; } @@ -17,11 +16,9 @@ public class BriefeViewModel public bool MinWidthTrad { get; set; } = false; // From, Until, Reference, Edit, sartpage, startline - public List<(string, string, string, string, string, string)>? ParsedEdits - { + public List<(string, string, string, string, string, string)>? ParsedEdits { get => _ParsedEdits; - set - { + set { if (value != null) _ParsedEdits = value.Select(x => ( HttpUtility.HtmlEncode(x.Item1), @@ -37,11 +34,9 @@ public class BriefeViewModel } // From, Until, Person, startpage, startline - public List<(string, string, string, string, string)>? ParsedHands - { + public List<(string, string, string, string, string)>? ParsedHands { get => _ParsedHands; - set - { + set { if (value != null) _ParsedHands = value.Select(x => ( HttpUtility.HtmlEncode(x.Item1), @@ -56,11 +51,9 @@ public class BriefeViewModel } // Page, Line, Element - public List<(string, string, string)>? ParsedMarginals - { + public List<(string, string, string)>? ParsedMarginals { get => _ParsedMarginals; - set - { + set { if (value != null) _ParsedMarginals = value.Select(x => ( HttpUtility.HtmlEncode(x.Item1), @@ -72,8 +65,7 @@ public class BriefeViewModel } } - public BriefeViewModel(string id, string index, BriefeMetaViewModel meta) - { + public BriefeViewModel(string id, string index, BriefeMetaViewModel meta) { Id = id; Index = index; MetaData = meta; diff --git a/HaWeb/Models/CommentModel.cs b/HaWeb/Models/CommentModel.cs index c1e8dd1..5d14237 100644 --- a/HaWeb/Models/CommentModel.cs +++ b/HaWeb/Models/CommentModel.cs @@ -5,13 +5,11 @@ using System.Text; using HaXMLReader.Interfaces; using HaXMLReader.EvArgs; -public class CommentModel -{ +public class CommentModel { public string ParsedComment { get; private set; } public List? ParsedSubComments { get; private set; } - public CommentModel(string parsedComment, List? parsedSubComments) - { + public CommentModel(string parsedComment, List? parsedSubComments) { this.ParsedComment = parsedComment; this.ParsedSubComments = parsedSubComments; } diff --git a/HaWeb/Models/ErrorViewModel.cs b/HaWeb/Models/ErrorViewModel.cs index 86a456e..142f526 100644 --- a/HaWeb/Models/ErrorViewModel.cs +++ b/HaWeb/Models/ErrorViewModel.cs @@ -1,7 +1,6 @@ namespace HaWeb.Models; -public class ErrorViewModel -{ +public class ErrorViewModel { public string? RequestId { get; set; } public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); diff --git a/HaWeb/Models/RegisterViewModel.cs b/HaWeb/Models/RegisterViewModel.cs index f7e2c82..08eedc7 100644 --- a/HaWeb/Models/RegisterViewModel.cs +++ b/HaWeb/Models/RegisterViewModel.cs @@ -1,8 +1,7 @@ namespace HaWeb.Models; using System.Web; -public class RegisterViewModel -{ +public class RegisterViewModel { public string Category { get; private set; } public string Id { get; private set; } public string Title { get; private set; } @@ -15,14 +14,12 @@ public class RegisterViewModel public List ParsedComments { get; private set; } // Title, URL - public List<(string, string)>? AvailableCategories - { + public List<(string, string)>? AvailableCategories { get => _AvailableCategories; - set - { + set { if (value != null) _AvailableCategories = value.Select(x => ( - HttpUtility.HtmlEncode(x.Item1), + HttpUtility.HtmlEncode(x.Item1), HttpUtility.HtmlAttributeEncode(x.Item2)) ).ToList(); else @@ -31,14 +28,12 @@ public class RegisterViewModel } // Title, URL - public List<(string, string)>? AvailableSideCategories - { + public List<(string, string)>? AvailableSideCategories { get => _AvailableSideCategories; - set - { + set { if (value != null) _AvailableSideCategories = value.Select(x => ( - HttpUtility.HtmlEncode(x.Item1), + HttpUtility.HtmlEncode(x.Item1), HttpUtility.HtmlAttributeEncode(x.Item2)) ).ToList(); else @@ -46,8 +41,7 @@ public class RegisterViewModel } } - public RegisterViewModel(string category, string id, List parsedComments, string title) - { + public RegisterViewModel(string category, string id, List parsedComments, string title) { this.Category = HttpUtility.HtmlAttributeEncode(category); this.Id = HttpUtility.HtmlAttributeEncode(id); this.ParsedComments = parsedComments; diff --git a/HaWeb/Models/SearchResult.cs b/HaWeb/Models/SearchResult.cs index be6a7a2..19d2e59 100644 --- a/HaWeb/Models/SearchResult.cs +++ b/HaWeb/Models/SearchResult.cs @@ -26,10 +26,8 @@ public class DocumentResult { } } -public class LetterComparer : IComparer -{ - public int Compare(DocumentSearchResult first, DocumentSearchResult second) - { +public class LetterComparer : IComparer { + public int Compare(DocumentSearchResult first, DocumentSearchResult second) { var cmp = new DefaultComparer(); return cmp.Compare(first.MetaData, second.MetaData); } diff --git a/HaWeb/Models/UploadViewModel.cs b/HaWeb/Models/UploadViewModel.cs index ce57f3d..f7f53b8 100644 --- a/HaWeb/Models/UploadViewModel.cs +++ b/HaWeb/Models/UploadViewModel.cs @@ -1,5 +1,8 @@ namespace HaWeb.Models; +using HaWeb.XMLParser; public class UploadViewModel { - public List<(string, string)>? AvailableRoots { get; set; } + public List? AvailableRoots { get; set; } + public List? AvailableFiles { get; set; } + public Dictionary>? UsedFiles { get; set; } } \ No newline at end of file diff --git a/HaWeb/Program.cs b/HaWeb/Program.cs index 9abd694..046ab3d 100644 --- a/HaWeb/Program.cs +++ b/HaWeb/Program.cs @@ -3,9 +3,7 @@ using HaXMLReader.Interfaces; using HaDocument.Interfaces; using HaWeb.XMLParser; using Microsoft.FeatureManagement; - -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; +using System.Runtime.InteropServices; using Microsoft.Extensions.FileProviders; var builder = WebApplication.CreateBuilder(args); @@ -14,12 +12,23 @@ var builder = WebApplication.CreateBuilder(args); builder.Services.AddControllersWithViews(); builder.Services.AddHttpContextAccessor(); -// // To list physical files from a path provided by configuration: -// var physicalProvider = new PhysicalFileProvider(Configuration.GetValue("StoredFilesPath")); -// // To list physical files in the temporary files folder, use: -// //var physicalProvider = new PhysicalFileProvider(Path.GetTempPath()); -// services.AddSingleton(physicalProvider); +// // To get files from a path provided by configuration: +string? filepath = null; +if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { + filepath = builder.Configuration.GetValue("StoredFilePathWindows"); +} +else { + filepath = builder.Configuration.GetValue("StoredFilePathLinux"); +} +if (filepath == null) { + throw new Exception("You need to set a specific Filepath, either StoredFilePathWindows or StoredFilePathLinux"); +} + +var physicalProvider = new PhysicalFileProvider(filepath); + + +builder.Services.AddSingleton(physicalProvider); builder.Services.AddSingleton(HaDocument.Document.Create(new Options())); builder.Services.AddTransient(); builder.Services.AddSingleton(); diff --git a/HaWeb/README.md b/HaWeb/README.md index a77fc49..1a72039 100644 --- a/HaWeb/README.md +++ b/HaWeb/README.md @@ -41,4 +41,6 @@ TODO 659 align center und align-right ueberschneidugn TODO Kommentare und min-size von ha-lettertetx TODO Word-wrap before align, tabs TODO pills are not mobile friendly (hover / click) -TODO Evtl alignment von center / right an der letzten oder nächsten zeile \ No newline at end of file +TODO Evtl alignment von center / right an der letzten oder nächsten zeile +TODO Abhärten des Konstruktors von XMLRootDokument für von außerhalb platzierte Dokumente +TODO XML-Check im Client \ No newline at end of file diff --git a/HaWeb/Settings/CSSClassesSettings.cs b/HaWeb/Settings/CSSClassesSettings.cs index da40e6d..fbc9eb1 100644 --- a/HaWeb/Settings/CSSClassesSettings.cs +++ b/HaWeb/Settings/CSSClassesSettings.cs @@ -63,7 +63,7 @@ public static class CSSClasses { // Zeilen: public const string ZHLINECLASS = "ha-zhline"; - public const string FIRSTLINECLASS ="ha-firstline"; + public const string FIRSTLINECLASS = "ha-firstline"; public const string ZHBREAKCLASS = "ha-zhbreak"; public const string LINELINECLASS = "ha-hr"; public const string LINEINDENTCLASS = "ha-indent-"; // TODO: GEN diff --git a/HaWeb/Settings/Features.cs b/HaWeb/Settings/Features.cs index fc8defa..300e270 100644 --- a/HaWeb/Settings/Features.cs +++ b/HaWeb/Settings/Features.cs @@ -1,7 +1,6 @@ namespace HaWeb; -public static class Features -{ +public static class Features { public const string AdminService = "AdminService"; public const string UploadService = "UploadService"; public const string UpdateService = "UpdateService"; diff --git a/HaWeb/Settings/ParsingRules/CommentRules.cs b/HaWeb/Settings/ParsingRules/CommentRules.cs index 836edc5..bfd4138 100644 --- a/HaWeb/Settings/ParsingRules/CommentRules.cs +++ b/HaWeb/Settings/ParsingRules/CommentRules.cs @@ -37,16 +37,16 @@ public static class CommentRules { reader.OpenTags.Any() && reader.OpenTags.Last().Name == "lemma" && !txt.Value.Contains("Stücke zu") && !txt.Value.Contains("ZusDan")) { var lnkstring = Regex.Replace(txt.Value, @"\s+", ""); - sb.Append(HTMLHelpers.TagHelpers.CreateCustomElement("a", + sb.Append(HTMLHelpers.TagHelpers.CreateCustomElement("a", new HaWeb.HTMLHelpers.TagHelpers.Attribute() { Name = "href", Value = "https://www.bibleserver.com/LUT/" + lnkstring}, new HaWeb.HTMLHelpers.TagHelpers.Attribute() { Name = "target", Value = "_blank"}, new HaWeb.HTMLHelpers.TagHelpers.Attribute() { Name = "rel", Value = "noopener noreferrer"})); sb.Append(""); sb.Append(HaWeb.HTMLHelpers.TagHelpers.CreateEndElement("a")); - } + } })}; public static readonly WhitespaceFuncList WhitespaceRules = new WhitespaceFuncList() { ( (x, _) => true, ( sb, txt, _) => sb.Append(txt.Value) ) }; -} \ No newline at end of file +} \ No newline at end of file diff --git a/HaWeb/Settings/ParsingRules/EditRules.cs b/HaWeb/Settings/ParsingRules/EditRules.cs index c1e0d65..e8cef36 100644 --- a/HaWeb/Settings/ParsingRules/EditRules.cs +++ b/HaWeb/Settings/ParsingRules/EditRules.cs @@ -149,7 +149,7 @@ public static class EditRules { sb.Append(HttpUtility.HtmlEncode(txt.Value)); sb.Append(HaWeb.HTMLHelpers.TagHelpers.CreateEndElement(DEFAULTELEMENT)); })}; - + public static readonly TagFuncList STagRules = new TagFuncList() { ( ( x, _) => x.Name == "line", (sb, tag, _) => sb.Append(HaWeb.HTMLHelpers.TagHelpers.CreateElement("br")) ) }; diff --git a/HaWeb/Settings/ParsingRules/LetterRules.cs b/HaWeb/Settings/ParsingRules/LetterRules.cs index 4043378..e0e23ed 100644 --- a/HaWeb/Settings/ParsingRules/LetterRules.cs +++ b/HaWeb/Settings/ParsingRules/LetterRules.cs @@ -7,8 +7,7 @@ using TextFuncList = List<(Func, bool>, Action>)>; // TODO: stringbuilder als Rückgabeparameter des XMHelpers ist eigentlich auch Part vom State -public class LetterRules -{ +public class LetterRules { private static readonly string DEFAULTELEMENT = HaWeb.Settings.HTML.DEFAULTELEMENT; private static readonly string LEMMACLASS = HaWeb.Settings.CSSClasses.LEMMACLASS; @@ -101,7 +100,7 @@ public class LetterRules ( ( x, _) => x.Name == "sub", (sb, tag, _) => sb.Append(HaWeb.HTMLHelpers.TagHelpers.CreateElement(DEFAULTELEMENT, SUBCLASS)) ), ( ( x, _) => x.Name == "tul", (sb, tag, _) => sb.Append(HaWeb.HTMLHelpers.TagHelpers.CreateElement(DEFAULTELEMENT, TULCLASS)) ), ( ( x, _) => x.Name == "header", (sb, tag, reader) => { - sb.Append(HaWeb.HTMLHelpers.TagHelpers.CreateElement(DEFAULTELEMENT, HEADERCLASS)); + sb.Append(HaWeb.HTMLHelpers.TagHelpers.CreateElement(DEFAULTELEMENT, HEADERCLASS)); reader.State.mustwrap = (true, true); }), ( ( x, _) => x.Name == "lemma", (sb, tag, _) => sb.Append(HaWeb.HTMLHelpers.TagHelpers.CreateElement(DEFAULTELEMENT, LEMMACLASS)) ), @@ -214,7 +213,7 @@ public class LetterRules reader.State.mustwrap = (false, false); // Linecount - if(!String.IsNullOrWhiteSpace(tag["index"])) { + if(!String.IsNullOrWhiteSpace(tag["index"])) { reader.State.currline = tag["index"]; sb.Append(HaWeb.HTMLHelpers.TagHelpers.CreateElement(DEFAULTELEMENT, ZHLINECOUNTCLASS, reader.State.currpage + "-" + reader.State.currline)); @@ -274,7 +273,7 @@ public class LetterRules } // Line type=line - if(tag["type"] == "line") { + if(tag["type"] == "line") { sb.Append(HaWeb.HTMLHelpers.TagHelpers.CreateElement(DEFAULTELEMENT, LINELINECLASS)); sb.Append(HaWeb.HTMLHelpers.TagHelpers.CreateEndElement(DEFAULTELEMENT)); reader.State.mustwrap = (false, true); @@ -288,7 +287,7 @@ public class LetterRules } } )}; - + public static readonly WhitespaceFuncList WhitespaceRules = new WhitespaceFuncList() { ( ( _, _) => true, ( sb, txt, reader) => { diff --git a/HaWeb/Settings/ParsingRules/LinkRules.cs b/HaWeb/Settings/ParsingRules/LinkRules.cs index d5128d3..6c33e12 100644 --- a/HaWeb/Settings/ParsingRules/LinkRules.cs +++ b/HaWeb/Settings/ParsingRules/LinkRules.cs @@ -16,7 +16,7 @@ public static class LinkRules { ( (x, _) => x.Name == "titel", (strbd, _, _) => strbd.Append(HTMLHelpers.TagHelpers.CreateElement(DEFAULTELEMENT, TITLECLASS)) ), ( (x, _) => x.Name == "title", (strbd, _, _) => strbd.Append(HTMLHelpers.TagHelpers.CreateElement(DEFAULTELEMENT, TITLECLASS)) ) }; - + public static readonly TagFuncList CTagRules = new TagFuncList() { ( (x, _) => x.Name == "lemma", (strbd, _, _) => strbd.Append(HTMLHelpers.TagHelpers.CreateEndElement(DEFAULTELEMENT)) ), ( (x, _) => x.Name == "titel", (strbd, _, _) => strbd.Append(HTMLHelpers.TagHelpers.CreateEndElement(DEFAULTELEMENT)) ), diff --git a/HaWeb/Settings/ParsingRules/TraditionRules.cs b/HaWeb/Settings/ParsingRules/TraditionRules.cs index 42ccbe3..3f7bc0e 100644 --- a/HaWeb/Settings/ParsingRules/TraditionRules.cs +++ b/HaWeb/Settings/ParsingRules/TraditionRules.cs @@ -6,8 +6,7 @@ using TagFuncList = List<(Func, bool>, Action>)>; using WhitespaceFuncList = List<(Func, bool>, Action>)>; -public static class TraditionRules -{ +public static class TraditionRules { private static readonly string DEFAULTELEMENT = HaWeb.Settings.HTML.DEFAULTELEMENT; private static readonly string LEMMACLASS = HaWeb.Settings.CSSClasses.LEMMACLASS; diff --git a/HaWeb/Settings/ParsingState/LetterState.cs b/HaWeb/Settings/ParsingState/LetterState.cs index 70bdcef..84f3db5 100644 --- a/HaWeb/Settings/ParsingState/LetterState.cs +++ b/HaWeb/Settings/ParsingState/LetterState.cs @@ -10,7 +10,7 @@ using System.Linq; using System.Xml.Linq; public class LetterState : HaWeb.HTMLParser.IState { - // Input + // Input internal ILibrary Lib; internal IReaderService ReaderService; internal Meta Meta; diff --git a/HaWeb/Settings/ParsingState/TraditionState.cs b/HaWeb/Settings/ParsingState/TraditionState.cs index e95d39e..40a037e 100644 --- a/HaWeb/Settings/ParsingState/TraditionState.cs +++ b/HaWeb/Settings/ParsingState/TraditionState.cs @@ -34,8 +34,7 @@ public class TraditionState : HaWeb.HTMLParser.IState { internal IReader rd_tradition; - public TraditionState(ILibrary lib, IReader reader, IReaderService readerService, IEnumerable? marginals, IEnumerable? hands, IEnumerable? edits) - { + public TraditionState(ILibrary lib, IReader reader, IReaderService readerService, IEnumerable? marginals, IEnumerable? hands, IEnumerable? edits) { Lib = lib; rd_tradition = reader; Marginals = marginals; @@ -47,7 +46,7 @@ public class TraditionState : HaWeb.HTMLParser.IState { public void SetupState() { sb_tradition = new StringBuilder(); - + active_trad = false; active_skipwhitespace = true; currline = "-1"; diff --git a/HaWeb/Settings/XMLRoots/CommentRoot.cs b/HaWeb/Settings/XMLRoots/CommentRoot.cs index 6f31e0d..bc5c58b 100644 --- a/HaWeb/Settings/XMLRoots/CommentRoot.cs +++ b/HaWeb/Settings/XMLRoots/CommentRoot.cs @@ -12,7 +12,7 @@ public class CommentRoot : HaWeb.XMLParser.IXMLRoot { else return false; }; - public Func GetKey { get; } = (elem) => { + public Func GetKey { get; } = (elem) => { var index = elem.Attribute("id"); if (index != null && !String.IsNullOrWhiteSpace(index.Value)) return index.Value; @@ -25,7 +25,7 @@ public class CommentRoot : HaWeb.XMLParser.IXMLRoot { public (string?, string?) GenerateIdentificationString(XElement element) { var kat = element.Attribute("value"); - if (kat != null && !String.IsNullOrWhiteSpace(kat.Value)) + if (kat != null && !String.IsNullOrWhiteSpace(kat.Value)) return (null, kat.Value); return (null, null); } diff --git a/HaWeb/Settings/XMLRoots/DescriptionsRoot.cs b/HaWeb/Settings/XMLRoots/DescriptionsRoot.cs index 4ea219a..25492ec 100644 --- a/HaWeb/Settings/XMLRoots/DescriptionsRoot.cs +++ b/HaWeb/Settings/XMLRoots/DescriptionsRoot.cs @@ -5,14 +5,14 @@ using HaWeb.XMLParser; public class DescriptionsRoot : HaWeb.XMLParser.IXMLRoot { public string Type { get; } = "Metadaten"; public string Prefix { get; } = "metadaten"; - public string[] XPathContainer { get; } = {".//data/descriptions", ".//descriptions" }; + public string[] XPathContainer { get; } = { ".//data/descriptions", ".//descriptions" }; public Predicate IsCollectedObject { get; } = (elem) => { if (elem.Name == "letterDesc") return true; return false; }; - public Func GetKey { get; } = (elem) => { + public Func GetKey { get; } = (elem) => { var index = elem.Attribute("ref"); if (index != null && !String.IsNullOrWhiteSpace(index.Value)) return index.Value; diff --git a/HaWeb/Settings/XMLRoots/DocumentRoot.cs b/HaWeb/Settings/XMLRoots/DocumentRoot.cs index b8001f4..62b2b80 100644 --- a/HaWeb/Settings/XMLRoots/DocumentRoot.cs +++ b/HaWeb/Settings/XMLRoots/DocumentRoot.cs @@ -12,7 +12,7 @@ public class DocumentRoot : HaWeb.XMLParser.IXMLRoot { else return false; }; - public Func GetKey { get; } = (elem) => { + public Func GetKey { get; } = (elem) => { var index = elem.Attribute("index"); if (index != null && !String.IsNullOrWhiteSpace(index.Value)) return index.Value; diff --git a/HaWeb/Settings/XMLRoots/EditsRoot.cs b/HaWeb/Settings/XMLRoots/EditsRoot.cs index c117340..e22420a 100644 --- a/HaWeb/Settings/XMLRoots/EditsRoot.cs +++ b/HaWeb/Settings/XMLRoots/EditsRoot.cs @@ -12,7 +12,7 @@ public class EditsRoot : HaWeb.XMLParser.IXMLRoot { else return false; }; - public Func GetKey { get; } = (elem) => { + public Func GetKey { get; } = (elem) => { var index = elem.Attribute("index"); if (index != null && !String.IsNullOrWhiteSpace(index.Value)) return index.Value; diff --git a/HaWeb/Settings/XMLRoots/MarginalsRoot.cs b/HaWeb/Settings/XMLRoots/MarginalsRoot.cs index bace12c..2bc86cd 100644 --- a/HaWeb/Settings/XMLRoots/MarginalsRoot.cs +++ b/HaWeb/Settings/XMLRoots/MarginalsRoot.cs @@ -12,7 +12,7 @@ public class MarginalsRoot : HaWeb.XMLParser.IXMLRoot { else return false; }; - public Func GetKey { get; } = (elem) => { + public Func GetKey { get; } = (elem) => { var index = elem.Attribute("index"); if (index != null && !String.IsNullOrWhiteSpace(index.Value)) return index.Value; diff --git a/HaWeb/Settings/XMLRoots/ReferencesRoot.cs b/HaWeb/Settings/XMLRoots/ReferencesRoot.cs index fbf7671..ec7b352 100644 --- a/HaWeb/Settings/XMLRoots/ReferencesRoot.cs +++ b/HaWeb/Settings/XMLRoots/ReferencesRoot.cs @@ -13,7 +13,7 @@ public class ReferencesRoot : HaWeb.XMLParser.IXMLRoot { return false; }; - public Func GetKey { get; } = (elem) => { + public Func GetKey { get; } = (elem) => { return elem.Name.ToString(); }; diff --git a/HaWeb/Settings/XMLRoots/TraditionsRoot.cs b/HaWeb/Settings/XMLRoots/TraditionsRoot.cs index 5675a6c..6e21235 100644 --- a/HaWeb/Settings/XMLRoots/TraditionsRoot.cs +++ b/HaWeb/Settings/XMLRoots/TraditionsRoot.cs @@ -12,7 +12,7 @@ public class TraditionsRoot : HaWeb.XMLParser.IXMLRoot { else return false; }; - public Func GetKey { get; } = (elem) => { + public Func GetKey { get; } = (elem) => { var index = elem.Attribute("ref"); if (index != null && !String.IsNullOrWhiteSpace(index.Value)) return index.Value; diff --git a/HaWeb/Views/Admin/Upload/Index.cshtml b/HaWeb/Views/Admin/Upload/Index.cshtml index c72d97b..07e46ec 100644 --- a/HaWeb/Views/Admin/Upload/Index.cshtml +++ b/HaWeb/Views/Admin/Upload/Index.cshtml @@ -1,57 +1,79 @@ @model UploadViewModel; -Hello from Upload Index! -
-
-
- -
-
- -
-
- - - -
- +
+ @foreach (var item in Model.AvailableRoots.OrderBy(x => x.Type)) { +
+
@item.Type
+ @if (Model.UsedFiles != null && Model.UsedFiles.ContainsKey(item.Prefix)) { + @foreach(var file in Model.UsedFiles[item.Prefix]) { + @file.File.Name + } + }
- - -@foreach (var item in Model.AvailableRoots.OrderBy(x => x.Item1)) -{ -
@item.Item1
-} + } +
+ +
+ +
+
+
@section Scripts { - } diff --git a/HaWeb/Views/Briefe/Index.cshtml b/HaWeb/Views/Briefe/Index.cshtml index f8cbd6b..c8ea18a 100644 --- a/HaWeb/Views/Briefe/Index.cshtml +++ b/HaWeb/Views/Briefe/Index.cshtml @@ -7,46 +7,44 @@ if (Model.MinWidthTrad) minwidthtrads = "ha-minwidth"; } -
-
- @await Html.PartialAsync("/Views/Shared/_LetterHead.cshtml", Model.MetaData) -
-
- @if (Model.ParsedText != null && !String.IsNullOrWhiteSpace(Model.ParsedText)) - { - Brieftext - @if (Model.ParsedMarginals != null) - { - Stellenkommentar - } - } - Überlieferung & Textkritik - PDF -
- - @if (Model.MetaData.Next != null || Model.MetaData.Prev != null) +
+ @await Html.PartialAsync("/Views/Shared/_LetterHead.cshtml", Model.MetaData) +
+
+ @if (Model.ParsedText != null && !String.IsNullOrWhiteSpace(Model.ParsedText)) { - + Brieftext + @if (Model.ParsedMarginals != null) + { + Stellenkommentar + } } + Überlieferung & Textkritik + PDF
+ + @if (Model.MetaData.Next != null || Model.MetaData.Prev != null) + { + + }
diff --git a/HaWeb/Views/Shared/_Footer.cshtml b/HaWeb/Views/Shared/_Footer.cshtml index 421f1fe..d30ef94 100644 --- a/HaWeb/Views/Shared/_Footer.cshtml +++ b/HaWeb/Views/Shared/_Footer.cshtml @@ -3,10 +3,8 @@
- -
diff --git a/HaWeb/XMLParser/IXMLRoot.cs b/HaWeb/XMLParser/IXMLRoot.cs index 7fe3b81..268200c 100644 --- a/HaWeb/XMLParser/IXMLRoot.cs +++ b/HaWeb/XMLParser/IXMLRoot.cs @@ -8,7 +8,7 @@ public interface IXMLRoot { // Name of the file prefix public abstract string Prefix { get; } - + // XPaths to determine if container is present public abstract string[] XPathContainer { get; } @@ -25,13 +25,14 @@ public interface IXMLRoot { var elements = root.XPathSelectElements(p); if (elements != null && elements.Any()) { if (ret == null) ret = new List(); - ret.AddRange(elements); + foreach (var e in elements) + if (!ret.Contains(e)) ret.Add(e); } } return ret; } - // Generate certain metadat fields to display about this root + // Generate certain metadata fields to display about this root public abstract List<(string, string?)>? GenerateFields(XMLRootDocument document); // Generate an identification string of which the hash will be the filename. diff --git a/HaWeb/XMLParser/IXMLService.cs b/HaWeb/XMLParser/IXMLService.cs index 769b317..ca52190 100644 --- a/HaWeb/XMLParser/IXMLService.cs +++ b/HaWeb/XMLParser/IXMLService.cs @@ -5,5 +5,7 @@ using Microsoft.AspNetCore.Mvc.ModelBinding; public interface IXMLService { public IXMLRoot? GetRoot(string name); public List? GetRoots(); - public List? ProbeHamannFile(XDocument document, ModelStateDictionary ModelState); + public Task?> ProbeHamannFile(XDocument document, ModelStateDictionary ModelState); + public Task UpdateAvailableFiles(XMLRootDocument doc, string basefilepath, ModelStateDictionary ModelState); + public Dictionary> GetUsed(); } \ No newline at end of file diff --git a/HaWeb/XMLParser/JSONConverters.cs b/HaWeb/XMLParser/JSONConverters.cs new file mode 100644 index 0000000..1170d45 --- /dev/null +++ b/HaWeb/XMLParser/JSONConverters.cs @@ -0,0 +1,34 @@ +namespace HaWeb.XMLParser; +using System.Globalization; +using System.Text.Json; +using System.Text.Json.Serialization; + + +public class IdentificationStringJSONConverter : JsonConverter<(string?, string?)> +{ + public override (string?, string?) Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options) { + var s = reader.GetString(); + if (s == null) return (null, null); + var split = s.Split('-'); + string? str1 = null; + if (!String.IsNullOrWhiteSpace(split[0])) str1 = split[0]; + if (s.Length > 1 && !String.IsNullOrWhiteSpace(split[1])) return (str1, split[1]); + else return (str1, null); + } + + public override void Write( + Utf8JsonWriter writer, + (string?, string?) value, + JsonSerializerOptions options) + { + if (value.Item1 == null && value.Item2 == null) return; + var res = ""; + if (value.Item1 != null) res += value.Item1; + if (value.Item2 != null) res += "-" + value.Item2; + writer.WriteStringValue(res); + } +} + diff --git a/HaWeb/XMLParser/XMLRootDocument.cs b/HaWeb/XMLParser/XMLRootDocument.cs index af834e2..4927648 100644 --- a/HaWeb/XMLParser/XMLRootDocument.cs +++ b/HaWeb/XMLParser/XMLRootDocument.cs @@ -2,42 +2,45 @@ namespace HaWeb.XMLParser; using System.Xml.Linq; using System.Text.Json.Serialization; using Microsoft.AspNetCore.Mvc.ModelBinding; +using Microsoft.Extensions.FileProviders; public class XMLRootDocument { private XElement? _Element; private string? _filename; - private string? _path; private IXMLService _xmlService; [JsonIgnore] - public XElement Root { + public XElement Root { get { if (_Element == null) { - _Element = GetElement(); + _Element = _GetElement(); } return _Element; - } } + } + } - public string FileName { get { - if (_filename == null) - _filename = _CreateFilename(); - return _filename; - } } + public string FileName { + get { + if (_filename == null) + _filename = _CreateFilename(); + return _filename; + } + } + [JsonIgnore] + public IFileInfo? File { get; private set; } public string Prefix { get; private set; } public DateTime Date { get; private set; } - + public bool Used { get; private set; } = false; + public (string?, string?) IdentificationString { get; private set; } [JsonIgnore] public List<(string, string)>? Fields { get; set; } // Entry point for file reading - public XMLRootDocument(IXMLService xmlService, string prefix, (string?, string?) idString, DateTime date, string path) { + public XMLRootDocument(IXMLService xmlService, IFileInfo file) { _xmlService = xmlService; - _path = path; - Prefix = prefix; - IdentificationString = idString; - Date = date; + SetFile(file); } // Entry point for XML upload reading @@ -49,6 +52,19 @@ public class XMLRootDocument { _Element = element; } + public void SetFile(IFileInfo file) { + File = file; + Date = file.LastModified.DateTime; + _GenerateFieldsFromFilename(file.Name); + } + + public void SetUsed(bool used) { + Used = used; + if (used && _Element == null) { + _GetElement(); + } + } + private string _CreateFilename() { var filename = _removeInvalidChars(Prefix) + "_"; if (!String.IsNullOrWhiteSpace(IdentificationString.Item1)) { @@ -69,28 +85,39 @@ public class XMLRootDocument { return s; } - private XElement GetElement() { - if (_path == null || String.IsNullOrWhiteSpace(_path)) + private void _GenerateFieldsFromFilename(string filename) { + var split = filename.Split('_'); + Prefix = split[0]; + if (split.Length == 3) { + IdentificationString = (null, split[1]); + } else if (split.Length == 4) { + IdentificationString = (split[1], split[2]); + } else { + IdentificationString = (null, null); + } + } + + private XElement _GetElement() { + if (File == null || String.IsNullOrWhiteSpace(File.PhysicalPath) || !File.Exists) throw new Exception("Es ist kein Pfad für die XML-Datei vorhanden."); - + var root = _xmlService.GetRoot(Prefix); if (root == null) - throw new Exception("Kein gültiges Hamann-Dokument: " + _path + "Vom Prefix: " + Prefix); - + throw new Exception("Kein gültiges Hamann-Dokument: " + File.PhysicalPath + "Vom Prefix: " + Prefix); + XDocument? doc = null; try { - doc = XDocument.Load(_path, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - } - catch (Exception ex) { + doc = XDocument.Load(File.PhysicalPath, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + } catch (Exception ex) { throw new Exception("Fehler beim Lesen des Dokuments: " + ex.Message); } if (doc == null || doc.Root == null) - throw new Exception("Das Dokument ist ungültig und kann nicht gelesen werden: " + _path); + throw new Exception("Das Dokument ist ungültig und kann nicht gelesen werden: " + File.PhysicalPath); var element = root.IsTypeOf(doc.Root); if (element == null || !element.Any()) - throw new Exception("Kein gültiges Hamann-Dokument: " + _path + "Vom Prefix: " + Prefix); + throw new Exception("Kein gültiges Hamann-Dokument: " + File.PhysicalPath + "Vom Prefix: " + Prefix); return element.First(); } diff --git a/HaWeb/XMLParser/XMLService.cs b/HaWeb/XMLParser/XMLService.cs index c9d910b..faed6fd 100644 --- a/HaWeb/XMLParser/XMLService.cs +++ b/HaWeb/XMLParser/XMLService.cs @@ -2,17 +2,43 @@ namespace HaWeb.XMLParser; using HaWeb.Settings.XMLRoots; using System.Xml.Linq; using Microsoft.AspNetCore.Mvc.ModelBinding; +using Microsoft.Extensions.FileProviders; +using Microsoft.FeatureManagement; public class XMLService : IXMLService { + private Dictionary?>? _availableFilesObj; + private Dictionary?>? _availableFiles { + get { + if (_availableFilesObj == null) { + _availableFilesObj = _GetAvailableFiles(); + AutoDetermineUsed(); + } + return _availableFilesObj; + } } + + private IFileProvider _fileProvider; + private IFeatureManager _featureManager; private Dictionary? _Roots; - public XMLService() { + public bool UploadEnabled = false; + public bool UpdateEnabled = false; + + public XMLService(IFileProvider provider, IFeatureManager featureManager) { + _fileProvider = provider; + _featureManager = featureManager; + if (provider == null) + throw new Exception("To Upload Files you need a FileProvider"); + + // Getting all classes which implement IXMLRoot for possible upload endpoints var types = _GetAllTypesThatImplementInterface().ToList(); types.ForEach( x => { if (this._Roots == null) this._Roots = new Dictionary(); var instance = (IXMLRoot)Activator.CreateInstance(x)!; if (instance != null) this._Roots.Add(instance.Prefix, instance); }); + + if (_Roots == null || !_Roots.Any()) + throw new Exception("No classes for upload endpoints were found!"); } public IXMLRoot? GetRoot(string name) { @@ -22,7 +48,7 @@ public class XMLService : IXMLService { public List? GetRoots() => this._Roots == null ? null : this._Roots.Values.ToList(); - public List? ProbeHamannFile(XDocument document, ModelStateDictionary ModelState) { + public async Task?> ProbeHamannFile(XDocument document, ModelStateDictionary ModelState) { if (document.Root!.Name != "opus") { ModelState.AddModelError("Error", "A valid Hamann-Docuemnt must begin with "); return null; @@ -43,6 +69,63 @@ public class XMLService : IXMLService { return res; } + public void UpdateAvailableFiles() { + _availableFilesObj = _GetAvailableFiles(); + } + + public void UpdateAvailableFiles(string prefix) { + if (_availableFilesObj == null) { + UpdateAvailableFiles(); + return; + } + if (_availableFilesObj.ContainsKey(prefix)) + _availableFilesObj.Remove(prefix); + if (_fileProvider.GetDirectoryContents(prefix).Exists) { + _availableFilesObj.Add(prefix, _GetAvailableFiles(prefix)); + } + + AutoDetermineUsed(prefix); + } + + public async Task UpdateAvailableFiles(XMLRootDocument doc, string basefilepath, ModelStateDictionary ModelState) { + await _setEnabled(); + if (!UploadEnabled) { + ModelState.AddModelError("Error", "The uploading of files is deactivated"); + return; + } + + await _Save(doc, basefilepath, ModelState); + if (!ModelState.IsValid) return; + + UpdateAvailableFiles(doc.Prefix); + } + + private async Task _Save(XMLRootDocument doc, string basefilepath, ModelStateDictionary ModelState) { + var type = doc.Prefix; + var directory = Path.Combine(basefilepath, type); + if (!Directory.Exists(directory)) + Directory.CreateDirectory(directory); + var path = Path.Combine(directory, doc.FileName); + try { + using (var targetStream = System.IO.File.Create(path)) + await doc.Save(targetStream, ModelState); + } + catch (Exception ex) { + ModelState.AddModelError("Error", "Speichern der Datei fehlgeschlagen: " + ex.Message); + return; + } + + var info = _fileProvider.GetFileInfo(Path.Combine(doc.Prefix, doc.FileName)); + if (info == null) { + ModelState.AddModelError("Error", "Auf die neu erstellte Dtaei konnte nicht zugegriffen werden"); + return; + } + doc.SetFile(info); + + UpdateAvailableFiles(type); + } + + private XMLRootDocument _createXMLRootDocument(IXMLRoot Root, XElement element) { var doc = new XMLRootDocument(this, Root.Prefix, Root.GenerateIdentificationString(element), element); doc.Fields = Root.GenerateFields(doc); @@ -56,4 +139,63 @@ public class XMLService : IXMLService { .Where(type => typeof(T).IsAssignableFrom(type) && !type.IsInterface); } + private async Task _setEnabled() { + if (await _featureManager.IsEnabledAsync(HaWeb.Features.UploadService)) + UploadEnabled = true; + if (await _featureManager.IsEnabledAsync(HaWeb.Features.UpdateService)) + UpdateEnabled = true; + } + + private Dictionary?>? _GetAvailableFiles() { + if (_Roots == null) return null; + Dictionary?>? res = null; + var dirs = _fileProvider.GetDirectoryContents(string.Empty).Where(x => x.IsDirectory); + foreach(var dir in dirs) { + if(_Roots.ContainsKey(dir.Name)) { + if (res == null) res = new Dictionary?>(); + res.Add(dir.Name, _GetAvailableFiles(dir.Name)); + } + } + return res; + } + + private List? _GetAvailableFiles(string prefix) { + List? res = null; + var files = _fileProvider.GetDirectoryContents(prefix).Where(x => !x.IsDirectory && x.Name.StartsWith(prefix) && x.Name.EndsWith(".xml")); + foreach (var file in files) { + if (res == null) res = new List(); + res.Add(new XMLRootDocument(this, file)); + } + return res; + } + + public void AutoDetermineUsed() { + if (_availableFilesObj == null) return; + foreach (var (prefix, _) in _availableFilesObj) + AutoDetermineUsed(prefix); + } + + public void AutoDetermineUsed(string prefix) { + if (_Roots == null || _availableFilesObj == null) return; + _Roots.TryGetValue(prefix, out var root); + _availableFilesObj.TryGetValue(prefix, out var files); + if (files == null || root == null) return; + + //TODO: Item1 + var lookup = files.ToLookup(x => x.IdentificationString.Item2); + foreach (var idstring in lookup) { + var ordered = idstring.OrderBy(x => x.Date); + ordered.Last().SetUsed(true); + ordered.Take(ordered.Count() - 1).ToList().ForEach(x => x.SetUsed(false)); + } + } + + public Dictionary>? GetUsed() { + if (_availableFiles == null) return null; + return _availableFiles + .Where(x => x.Value != null) + .Select(x => x.Value!.Where(x => x.Used).ToList()) + .Where(x => x.Any()) + .ToDictionary(x => x.First().Prefix); + } } \ No newline at end of file diff --git a/HaWeb/omnisharp.json b/HaWeb/omnisharp.json new file mode 100644 index 0000000..6048437 --- /dev/null +++ b/HaWeb/omnisharp.json @@ -0,0 +1,16 @@ +{ + "FormattingOptions": { + "NewLinesForBracesInLambdaExpressionBody": false, + "NewLinesForBracesInAnonymousMethods": false, + "NewLinesForBracesInAnonymousTypes": false, + "NewLinesForBracesInControlBlocks": false, + "NewLinesForBracesInTypes": false, + "NewLinesForBracesInMethods": false, + "NewLinesForBracesInProperties": false, + "NewLinesForBracesInObjectCollectionArrayInitializers": false, + "NewLinesForBracesInAccessors": false, + "NewLineForElse": false, + "NewLineForCatch": false, + "NewLineForFinally": false + } +} \ No newline at end of file diff --git a/HaWeb/wwwroot/css/output.css b/HaWeb/wwwroot/css/output.css index 7b2ea91..25e74a5 100644 --- a/HaWeb/wwwroot/css/output.css +++ b/HaWeb/wwwroot/css/output.css @@ -468,6 +468,14 @@ Ensure the default browser behavior of the `hidden` attribute. --tw-backdrop-sepia: ; } +* { + transition-property: color, background-color, border-color, fill, stroke, -webkit-text-decoration-color; + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke; + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, -webkit-text-decoration-color; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 100ms; +} + /* TODO: check what can be inlined (eg. used once in the code, has no double paths etc...) */ /* Everything related to theme color */ @@ -570,21 +578,36 @@ body { --tw-shadow: inset 0 2px 4px 0 rgb(0 0 0 / 0.05); --tw-shadow-colored: inset 0 2px 4px 0 var(--tw-shadow-color); box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); + transition-property: color, background-color, border-color, fill, stroke, -webkit-text-decoration-color; + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke; + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, -webkit-text-decoration-color; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 300ms; } -.ha-footer .ha-themetoggles #ha-toggledark:checked ~ .ha-themetoggleslider { +.dark .ha-footer .ha-themetoggles { --tw-bg-opacity: 1; background-color: rgb(30 41 59 / var(--tw-bg-opacity)); } -.ha-footer .ha-themetoggles #ha-toggletwilight:checked ~ .ha-themetoggleslider { +.ha-footer .ha-themetoggles #ha-toggledark:checked ~ .ha-themetoggleslider { --tw-bg-opacity: 1; - background-color: rgb(100 116 139 / var(--tw-bg-opacity)); + background-color: rgb(226 232 240 / var(--tw-bg-opacity)); + transition-property: color, background-color, border-color, fill, stroke, -webkit-text-decoration-color; + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke; + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, -webkit-text-decoration-color; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 300ms; } .ha-footer .ha-themetoggles #ha-togglebright:checked ~ .ha-themetoggleslider { --tw-bg-opacity: 1; background-color: rgb(248 250 252 / var(--tw-bg-opacity)); + transition-property: color, background-color, border-color, fill, stroke, -webkit-text-decoration-color; + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke; + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, -webkit-text-decoration-color; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 300ms; } .ha-static { @@ -1013,6 +1036,8 @@ body { } .ha-tradzhtext .ha-marginalbox.ha-expanded-box .ha-marginallist, .ha-lettertext .ha-marginalbox.ha-expanded-box .ha-marginallist { + --tw-bg-opacity: 1; + background-color: rgb(241 245 249 / var(--tw-bg-opacity)); padding-bottom: 0.25rem; --tw-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1); --tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color); @@ -1020,6 +1045,8 @@ body { } .dark .ha-tradzhtext .ha-marginalbox.ha-expanded-box .ha-marginallist, .dark .ha-lettertext .ha-marginalbox.ha-expanded-box .ha-marginallist { + --tw-bg-opacity: 1; + background-color: rgb(71 85 105 / var(--tw-bg-opacity)); --tw-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1); --tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color); box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); @@ -1115,6 +1142,8 @@ body { color: rgb(31 41 55 / var(--tw-text-opacity)) !important; } +/* Classes */ + body { height: 100%; width: 100%; @@ -1258,7 +1287,7 @@ body { .ha-footer .ha-themetoggles { position: relative; height: 1rem; - width: 49px; + width: 34px; white-space: nowrap; border-radius: 1.5rem; padding-left: 0.125rem; @@ -1305,12 +1334,8 @@ body { left: 0.25rem; } -.ha-footer .ha-themetoggles #ha-toggletwilight:checked ~ .ha-themetoggleslider { - left: 19px; -} - .ha-footer .ha-themetoggles #ha-togglebright:checked ~ .ha-themetoggleslider { - left: 34px; + left: 19px; } /* Classes for static pages */ @@ -2254,6 +2279,7 @@ body { flex-wrap: wrap; -moz-column-gap: 1.5rem; column-gap: 1.5rem; + padding-right: 0.25rem; font-size: 0.875rem; line-height: 1.25rem; line-height: 1.25; @@ -2791,6 +2817,10 @@ body { width: 2rem; } +.max-w-\[25\%\] { + max-width: 25%; +} + .shrink-0 { flex-shrink: 0; } @@ -2827,6 +2857,10 @@ body { flex-wrap: wrap; } +.gap-5 { + gap: 1.25rem; +} + .overflow-hidden { overflow: hidden; } diff --git a/HaWeb/wwwroot/css/site.css b/HaWeb/wwwroot/css/site.css index 19eb4cc..4691aa2 100644 --- a/HaWeb/wwwroot/css/site.css +++ b/HaWeb/wwwroot/css/site.css @@ -80,6 +80,9 @@ } @layer components { + * { + @apply transition-colors duration-100 + } /* TODO: check what can be inlined (eg. used once in the code, has no double paths etc...) */ /* Everything related to theme color */ @@ -118,19 +121,15 @@ } .ha-footer .ha-themetoggles { - @apply bg-slate-200 shadow-inner + @apply bg-slate-200 dark:bg-slate-800 transition-colors duration-300 shadow-inner } .ha-footer .ha-themetoggles #ha-toggledark:checked ~ .ha-themetoggleslider { - @apply bg-slate-800 - } - - .ha-footer .ha-themetoggles #ha-toggletwilight:checked ~ .ha-themetoggleslider { - @apply bg-slate-500 + @apply bg-slate-200 transition-colors duration-300 } .ha-footer .ha-themetoggles #ha-togglebright:checked ~ .ha-themetoggleslider { - @apply bg-slate-50 + @apply bg-slate-50 transition-colors duration-300 } .ha-static { @@ -278,7 +277,7 @@ .ha-tradzhtext .ha-marginalbox.ha-expanded-box .ha-marginallist, .ha-lettertext .ha-marginalbox.ha-expanded-box .ha-marginallist { - @apply shadow-md dark:shadow-lg pb-1 + @apply shadow-md dark:shadow-lg pb-1 bg-slate-100 dark:bg-slate-600 } .ha-tradzhtext .ha-btn-collapsed-box, @@ -322,7 +321,7 @@ @apply !text-hamannHighlight dark:!text-gray-800 } - +/* Classes */ body { @apply text-base desktop:text-lg w-full h-full; } @@ -373,7 +372,7 @@ } .ha-footer .ha-themetoggles { - @apply whitespace-nowrap relative px-0.5 rounded-3xl h-4 w-[49px] + @apply whitespace-nowrap relative px-0.5 rounded-3xl h-4 w-[34px] } .ha-footer .ha-themetoggles * { @@ -396,12 +395,8 @@ @apply left-1 } - .ha-footer .ha-themetoggles #ha-toggletwilight:checked ~ .ha-themetoggleslider { - @apply left-[19px] - } - .ha-footer .ha-themetoggles #ha-togglebright:checked ~ .ha-themetoggleslider { - @apply left-[34px] + @apply left-[19px] } /* Classes for static pages */ @@ -898,7 +893,7 @@ .ha-tradzhtext .ha-marginalbox .ha-marginallist, .ha-lettertext .ha-marginalbox .ha-marginallist { - @apply text-sm leading-tight flex flex-wrap gap-x-6 + @apply text-sm leading-tight flex flex-wrap gap-x-6 pr-1 } .ha-tradzhtext .ha-marginalbox .ha-marginallist .ha-marginal, diff --git a/HaWeb/wwwroot/js/site.js b/HaWeb/wwwroot/js/site.js index cb6523a..5ed597c 100644 --- a/HaWeb/wwwroot/js/site.js +++ b/HaWeb/wwwroot/js/site.js @@ -221,21 +221,8 @@ const go_to_dark = function () { document.documentElement.classList.add("dark"); }; -const go_to_twilight = function () { - document.documentElement.classList.remove("dark"); - let elements = document.getElementsByClassName("ha-twilighttogglebar"); - for (let el of elements) { - el.classList.add("dark"); - } - localStorage.setItem("theme", "ha-toggletwilight"); -}; - const go_to_bright = function () { document.documentElement.classList.remove("dark"); - let elements = document.getElementsByClassName("ha-twilighttogglebar"); - for (let el of elements) { - el.classList.remove("dark"); - } localStorage.setItem("theme", "ha-togglebright"); }; @@ -335,7 +322,6 @@ window.addEventListener("load", function () { // Register theme toggler if ( document.getElementById("ha-togglebright") !== null && - document.getElementById("ha-toggletwilight") !== null && this.document.getElementById("ha-toggledark") !== null ) { document @@ -344,9 +330,6 @@ window.addEventListener("load", function () { document .getElementById("ha-toggledark") .addEventListener("click", go_to_dark); - document - .getElementById("ha-toggletwilight") - .addEventListener("click", go_to_twilight); } get_theme_settings("ha-togglebright"); }); diff --git a/XML/XML/test_empty.xml b/XML/XML/test_empty.xml index 8192c21..0f20d8e 100644 --- a/XML/XML/test_empty.xml +++ b/XML/XML/test_empty.xml @@ -1,2 +1,2 @@ - \ No newline at end of file + \ No newline at end of file