From b5aae5ddf0f185d0ddd16a3b1a5bb3be2da64cac Mon Sep 17 00:00:00 2001 From: schnulller Date: Sun, 5 Jun 2022 21:04:22 +0200 Subject: [PATCH] Added Upload functionality; still a bit janky in selecting the files to use... --- HaDocumentV6/Reactors/MetaReactor.cs | 2 + HaWeb/Controllers/APIController.cs | 32 +- HaWeb/Controllers/BriefeContoller.cs | 6 +- HaWeb/FileHelpers/HaDocumentWrapper.cs | 13 + HaWeb/FileHelpers/IHaDocumentWrapper.cs | 2 + HaWeb/FileHelpers/IXMLProvider.cs | 4 + HaWeb/FileHelpers/XMLProvider.cs | 31 + HaWeb/Models/XMLRootDocument.cs | 2 +- HaWeb/Settings/Features.cs | 9 +- HaWeb/Settings/HaDocumentSettings.cs | 2 +- HaWeb/Settings/XMLRoots/CommentRoot.cs | 6 + HaWeb/Settings/XMLRoots/DescriptionsRoot.cs | 22 +- HaWeb/Settings/XMLRoots/DocumentRoot.cs | 11 + HaWeb/Settings/XMLRoots/EditsRoot.cs | 10 + HaWeb/Settings/XMLRoots/MarginalsRoot.cs | 10 + HaWeb/Settings/XMLRoots/ReferencesRoot.cs | 10 + HaWeb/Settings/XMLRoots/TraditionsRoot.cs | 9 + HaWeb/Views/Admin/Upload/Index.cshtml | 35 +- HaWeb/XMLParser/IXMLRoot.cs | 28 +- HaWeb/XMLParser/IXMLService.cs | 3 +- HaWeb/XMLParser/XMLService.cs | 23 +- HaWeb/appsettings.json | 4 +- XML/neuexml/2022-05-23briefe.xml | 128239 +++++++++++++++++ XML/neuexml/2022-05-23edits.xml | 21052 +++ XML/neuexml/2022-05-23meta.xml | 23946 +++ XML/neuexml/2022-05-23references.xml | 243 + XML/neuexml/2022-05-23traditions.xml | 14742 ++ 27 files changed, 188456 insertions(+), 40 deletions(-) create mode 100644 XML/neuexml/2022-05-23briefe.xml create mode 100644 XML/neuexml/2022-05-23edits.xml create mode 100644 XML/neuexml/2022-05-23meta.xml create mode 100644 XML/neuexml/2022-05-23references.xml create mode 100644 XML/neuexml/2022-05-23traditions.xml diff --git a/HaDocumentV6/Reactors/MetaReactor.cs b/HaDocumentV6/Reactors/MetaReactor.cs index 766bb1f..54c90be 100644 --- a/HaDocumentV6/Reactors/MetaReactor.cs +++ b/HaDocumentV6/Reactors/MetaReactor.cs @@ -156,6 +156,8 @@ namespace HaDocument.Reactors { (_availableVolumes == null && _availableYearRange.Item1 == 0 && _availableYearRange.Item2 == 0) ) { var ZHInfo = !inZH ? null : new ZHInfo(AltLineNumbering, dateChanged, Volume, Page); + if (Autopsic == "0") + System.Diagnostics.Debugger.Break(); var meta = new Meta( Index, Autopsic, diff --git a/HaWeb/Controllers/APIController.cs b/HaWeb/Controllers/APIController.cs index 320485b..7411747 100644 --- a/HaWeb/Controllers/APIController.cs +++ b/HaWeb/Controllers/APIController.cs @@ -50,7 +50,7 @@ public class APIController : Controller { [Route("API/Syntaxcheck/{id}")] [DisableFormValueModelBinding] [ValidateAntiForgeryToken] - [FeatureGate(Features.AdminService)] + [FeatureGate(Features.UploadService, Features.AdminService)] public async Task SyntaxCheck(string id) { return Ok(); } @@ -60,8 +60,8 @@ public class APIController : Controller { [Route("API/Upload")] [DisableFormValueModelBinding] [ValidateAntiForgeryToken] - [FeatureGate(Features.UploadService)] - public async Task Upload(string? id) { + [FeatureGate(Features.UploadService, Features.AdminService)] + public async Task Upload() { List? docs = null; //// 1. Stage: Check Request format and request spec // Checks the Content-Type Field (must be multipart + Boundary) @@ -114,19 +114,18 @@ public class APIController : Controller { return UnprocessableEntity(ModelState); //// 4. Stage: Is it a Hamann-Document? What kind? - var retdocs = await _xmlService.ProbeHamannFile(xdocument, ModelState); + var retdocs = _xmlService.ProbeHamannFile(xdocument, ModelState); if (!ModelState.IsValid || retdocs == null || !retdocs.Any()) return UnprocessableEntity(ModelState); //// 5. Stage: Saving the File(s) foreach (var doc in retdocs) { // Physical saving - var task = _xmlProvider.Save(doc, _targetFilePath, ModelState); + await _xmlProvider.Save(doc, _targetFilePath, ModelState); // Setting the new docuemnt as used _xmlService.Use(doc); // Unsetting all old docuemnts as ununsed _xmlService.AutoUse(doc.Prefix); - await task; if (!ModelState.IsValid) return StatusCode(500, ModelState); if (docs == null) docs = new List(); docs.Add(doc); @@ -137,6 +136,7 @@ public class APIController : Controller { section = await reader.ReadNextSectionAsync(); } catch (Exception ex) { ModelState.AddModelError("Error", "The Request is bad: " + ex.Message); + return BadRequest(ModelState); } } @@ -151,4 +151,24 @@ public class APIController : Controller { string json = JsonSerializer.Serialize(docs); return Created(nameof(UploadController), json); } + + + //// PUBLISH //// + [HttpPost] + [Route("API/LocalPublish")] + [DisableFormValueModelBinding] + [ValidateAntiForgeryToken] + [FeatureGate(Features.LocalPublishService, Features.AdminService, Features.UploadService)] + public async Task LocalPublish() { + var element = _xmlService.MergeUsedDocuments(ModelState); + if (!ModelState.IsValid || element == null) + return BadRequest(ModelState); + var savedfile = await _xmlProvider.SaveHamannFile(element, _targetFilePath, ModelState); + if (!ModelState.IsValid || savedfile == null) + return BadRequest(ModelState); + _ = _lib.SetLibrary(savedfile.PhysicalPath, ModelState); + if (!ModelState.IsValid) + return BadRequest(ModelState); + return Ok(); + } } \ No newline at end of file diff --git a/HaWeb/Controllers/BriefeContoller.cs b/HaWeb/Controllers/BriefeContoller.cs index 1dc9a38..9fb0bf6 100644 --- a/HaWeb/Controllers/BriefeContoller.cs +++ b/HaWeb/Controllers/BriefeContoller.cs @@ -31,8 +31,8 @@ public class Briefecontroller : Controller { // Normalisation and Validation, (some) data aquisition if (id == null) return Redirect(url + defaultID); - this.id = id.ToLower(); - var preliminarymeta = lib.Metas.Where(x => x.Value.Autopsic == this.id); + id = id.ToLower(); + var preliminarymeta = lib.Metas.Where(x => x.Value.Autopsic == id); if (preliminarymeta == null || !preliminarymeta.Any()) return error404(); // Get all neccessary data @@ -54,7 +54,7 @@ public class Briefecontroller : Controller { // Model creation var hasMarginals = false; if (marginals != null && marginals.Any()) hasMarginals = true; - var model = new BriefeViewModel(this.id, index, generateMetaViewModel(lib, meta, hasMarginals)); + var model = new BriefeViewModel(id, index, generateMetaViewModel(lib, meta, hasMarginals)); if (nextmeta != null) model.MetaData.Next = (generateMetaViewModel(lib, nextmeta, false), url + nextmeta.Autopsic); if (prevmeta != null) model.MetaData.Prev = (generateMetaViewModel(lib, prevmeta, false), url + prevmeta.Autopsic); if (hands != null && hands.Any()) model.ParsedHands = HaWeb.HTMLHelpers.LetterHelpers.CreateHands(lib, hands); diff --git a/HaWeb/FileHelpers/HaDocumentWrapper.cs b/HaWeb/FileHelpers/HaDocumentWrapper.cs index 4b1a9c7..ab1a5c4 100644 --- a/HaWeb/FileHelpers/HaDocumentWrapper.cs +++ b/HaWeb/FileHelpers/HaDocumentWrapper.cs @@ -1,5 +1,6 @@ namespace HaWeb.FileHelpers; using HaDocument.Interfaces; +using Microsoft.AspNetCore.Mvc.ModelBinding; public class HaDocumentWrapper : IHaDocumentWrappper { public ILibrary Library; @@ -13,6 +14,18 @@ public class HaDocumentWrapper : IHaDocumentWrappper { return Library; } + public ILibrary? SetLibrary(string filepath, ModelStateDictionary ModelState) { + try + { + Library = HaDocument.Document.Create(new HaWeb.Settings.HaDocumentOptions() { HamannXMLFilePath = filepath }); + } + catch (Exception ex) { + ModelState.AddModelError("Error:", "Das Dokument konnte nicht geparst werden: " + ex.Message); + return null; + } + return Library; + } + public ILibrary GetLibrary() { return Library; } diff --git a/HaWeb/FileHelpers/IHaDocumentWrapper.cs b/HaWeb/FileHelpers/IHaDocumentWrapper.cs index bfaafb5..a2ce771 100644 --- a/HaWeb/FileHelpers/IHaDocumentWrapper.cs +++ b/HaWeb/FileHelpers/IHaDocumentWrapper.cs @@ -1,7 +1,9 @@ namespace HaWeb.FileHelpers; using HaDocument.Interfaces; +using Microsoft.AspNetCore.Mvc.ModelBinding; public interface IHaDocumentWrappper { public ILibrary SetLibrary(); + public ILibrary? SetLibrary(string filepath, ModelStateDictionary ModelState); public ILibrary GetLibrary(); } \ No newline at end of file diff --git a/HaWeb/FileHelpers/IXMLProvider.cs b/HaWeb/FileHelpers/IXMLProvider.cs index 29cb9cc..7ca65c5 100644 --- a/HaWeb/FileHelpers/IXMLProvider.cs +++ b/HaWeb/FileHelpers/IXMLProvider.cs @@ -1,8 +1,12 @@ namespace HaWeb.FileHelpers; +using Microsoft.Extensions.FileProviders; +using System.Xml.Linq; using HaWeb.Models; + using Microsoft.AspNetCore.Mvc.ModelBinding; public interface IXMLProvider { public FileList? GetFiles(string prefix); public Task Save(XMLRootDocument doc, string basefilepath, ModelStateDictionary ModelState); + public Task SaveHamannFile(XElement element, string basefilepath, ModelStateDictionary ModelState); } \ No newline at end of file diff --git a/HaWeb/FileHelpers/XMLProvider.cs b/HaWeb/FileHelpers/XMLProvider.cs index 91d2553..9b4a82d 100644 --- a/HaWeb/FileHelpers/XMLProvider.cs +++ b/HaWeb/FileHelpers/XMLProvider.cs @@ -3,11 +3,13 @@ using Microsoft.Extensions.FileProviders; using Microsoft.AspNetCore.Mvc.ModelBinding; using HaWeb.Models; using HaWeb.XMLParser; +using System.Xml.Linq; public class XMLProvider : IXMLProvider { private IFileProvider _fileProvider; private Dictionary? _Files; private Dictionary? _Roots; + private List? _HamannFiles; public XMLProvider(IFileProvider provider, IXMLService xmlservice) { _fileProvider = provider; @@ -53,6 +55,35 @@ public class XMLProvider : IXMLProvider { _Files[doc.Prefix]!.Add(doc); } + public async Task SaveHamannFile(XElement element, string basefilepath, ModelStateDictionary ModelState) { + var date = DateTime.Now; + var filename = "hamann_" + date.Year + "-" + date.Month + "-" + date.Day + ".xml"; + var directory = Path.Combine(basefilepath, "hamann"); + var path = Path.Combine(directory, filename); + + try { + if (!Directory.Exists(directory)) + Directory.CreateDirectory(directory); + using (var targetStream = System.IO.File.Create(path)) + await element.SaveAsync(targetStream, SaveOptions.DisableFormatting, new CancellationToken()); + } + catch (Exception ex) { + ModelState.AddModelError("Error", "Die Datei konnte nicht gespeichert werden: " + ex.Message); + return null; + } + + var info = _fileProvider.GetFileInfo(Path.Combine("hamann", filename)); + if (info == null) { + ModelState.AddModelError("Error", "Auf die neu erstellte Dtaei konnte nicht zugegriffen werden."); + return null; + } + + if (_HamannFiles == null) _HamannFiles = new List(); + _HamannFiles.Add(info); + + return info; + } + private Dictionary? _ScanFiles() { if (_Roots == null) return null; Dictionary? res = null; diff --git a/HaWeb/Models/XMLRootDocument.cs b/HaWeb/Models/XMLRootDocument.cs index 75d526e..e4b64ca 100644 --- a/HaWeb/Models/XMLRootDocument.cs +++ b/HaWeb/Models/XMLRootDocument.cs @@ -53,7 +53,7 @@ public class XMLRootDocument { XMLRoot = xmlRoot; Prefix = prefix; IdentificationString = idString; - Date = DateTime.Today; + Date = DateTime.Now; _Element = element; } diff --git a/HaWeb/Settings/Features.cs b/HaWeb/Settings/Features.cs index 300e270..58e9b20 100644 --- a/HaWeb/Settings/Features.cs +++ b/HaWeb/Settings/Features.cs @@ -1,7 +1,14 @@ namespace HaWeb; public static class Features { + // If Admin Pages are reachable public const string AdminService = "AdminService"; + // If the Upload of files is possible, also syntaxcheck and crossreference check public const string UploadService = "UploadService"; - public const string UpdateService = "UpdateService"; + // If uploaded Files can be published locally + public const string LocalPublishService = "LocalPublishService"; + // If this server can publish files remotely (e.g. www.hamann-ausgabe.de) + public const string RemotePublishService = "RemotePublishService"; + // If this server can accept files from a remote authenticated source + public const string RemotePublishSourceService = "RemotePublishSourceService"; } diff --git a/HaWeb/Settings/HaDocumentSettings.cs b/HaWeb/Settings/HaDocumentSettings.cs index df197c8..8e8966d 100644 --- a/HaWeb/Settings/HaDocumentSettings.cs +++ b/HaWeb/Settings/HaDocumentSettings.cs @@ -5,5 +5,5 @@ class HaDocumentOptions : IHaDocumentOptions { public string HamannXMLFilePath { get; set; } = @"Hamann.xml"; public string[] AvailableVolumes { get; set; } = { }; public bool NormalizeWhitespace { get; set; } = true; - public (int, int) AvailableYearRange {get; set; } = (1751, 1788); + public (int, int) AvailableYearRange {get; set; } = (1700, 1790); } \ No newline at end of file diff --git a/HaWeb/Settings/XMLRoots/CommentRoot.cs b/HaWeb/Settings/XMLRoots/CommentRoot.cs index 4d69c33..9d53e1a 100644 --- a/HaWeb/Settings/XMLRoots/CommentRoot.cs +++ b/HaWeb/Settings/XMLRoots/CommentRoot.cs @@ -43,4 +43,10 @@ public class CommentRoot : HaWeb.XMLParser.IXMLRoot { return opus; } + public void MergeIntoFile(XElement file, XMLRootDocument document) { + if (file.Element("kommentare") == null) + file.AddFirst(new XElement("kommentare")); + file.Element("kommentare")!.AddFirst(document.Root); + } + } \ No newline at end of file diff --git a/HaWeb/Settings/XMLRoots/DescriptionsRoot.cs b/HaWeb/Settings/XMLRoots/DescriptionsRoot.cs index 739cfee..56e45ff 100644 --- a/HaWeb/Settings/XMLRoots/DescriptionsRoot.cs +++ b/HaWeb/Settings/XMLRoots/DescriptionsRoot.cs @@ -13,12 +13,12 @@ public class DescriptionsRoot : HaWeb.XMLParser.IXMLRoot { return false; }; - public Func GetKey { get; } = (elem) => { - var index = elem.Attribute("ref"); - if (index != null && !String.IsNullOrWhiteSpace(index.Value)) - return index.Value; - else return null; - }; + // public Func GetKey { get; } = (elem) => { + // var index = elem.Attribute("ref"); + // if (index != null && !String.IsNullOrWhiteSpace(index.Value)) + // return index.Value; + // else return null; + // }; public List<(string, string?)>? GenerateFields(XMLRootDocument document) { return null; @@ -38,4 +38,14 @@ public class DescriptionsRoot : HaWeb.XMLParser.IXMLRoot { return opus; } + public void MergeIntoFile(XElement file, XMLRootDocument document) { + if (file.Element("descriptions") == null) + file.AddFirst(new XElement("descriptions")); + var elements = document.Root.Elements().Where(x => IsCollectedObject(x)); + var root = file.Element("descriptions"); + foreach (var element in elements) { + root!.Add(element); + } + } + } \ No newline at end of file diff --git a/HaWeb/Settings/XMLRoots/DocumentRoot.cs b/HaWeb/Settings/XMLRoots/DocumentRoot.cs index 8b6b545..52b6121 100644 --- a/HaWeb/Settings/XMLRoots/DocumentRoot.cs +++ b/HaWeb/Settings/XMLRoots/DocumentRoot.cs @@ -2,6 +2,7 @@ namespace HaWeb.Settings.XMLRoots; using System.Xml.Linq; using HaWeb.Models; using HaWeb.XMLParser; +using System.IO; public class DocumentRoot : HaWeb.XMLParser.IXMLRoot { public string Type { get; } = "Brieftext"; @@ -38,4 +39,14 @@ public class DocumentRoot : HaWeb.XMLParser.IXMLRoot { return opus; } + public void MergeIntoFile(XElement file, XMLRootDocument document) { + if (file.Element("document") == null) + file.AddFirst(new XElement("document")); + var elements = document.Root.Elements().Where(x => IsCollectedObject(x)); + var root = file.Element("document"); + foreach (var element in elements) { + root!.Add(element); + } + } + } \ No newline at end of file diff --git a/HaWeb/Settings/XMLRoots/EditsRoot.cs b/HaWeb/Settings/XMLRoots/EditsRoot.cs index 83269b5..f90d3d5 100644 --- a/HaWeb/Settings/XMLRoots/EditsRoot.cs +++ b/HaWeb/Settings/XMLRoots/EditsRoot.cs @@ -38,4 +38,14 @@ public class EditsRoot : HaWeb.XMLParser.IXMLRoot { return opus; } + public void MergeIntoFile(XElement file, XMLRootDocument document) { + if (file.Element("edits") == null) + file.AddFirst(new XElement("edits")); + var elements = document.Root.Elements().Where(x => IsCollectedObject(x)); + var root = file.Element("edits"); + foreach (var element in elements) { + root!.Add(element); + } + } + } \ No newline at end of file diff --git a/HaWeb/Settings/XMLRoots/MarginalsRoot.cs b/HaWeb/Settings/XMLRoots/MarginalsRoot.cs index a360fed..8e2f519 100644 --- a/HaWeb/Settings/XMLRoots/MarginalsRoot.cs +++ b/HaWeb/Settings/XMLRoots/MarginalsRoot.cs @@ -38,4 +38,14 @@ public class MarginalsRoot : HaWeb.XMLParser.IXMLRoot { return opus; } + public void MergeIntoFile(XElement file, XMLRootDocument document) { + if (file.Element("marginalien") == null) + file.AddFirst(new XElement("marginalien")); + var elements = document.Root.Elements().Where(x => IsCollectedObject(x)); + var root = file.Element("marginalien"); + foreach (var element in elements) { + root!.Add(element); + } + } + } \ No newline at end of file diff --git a/HaWeb/Settings/XMLRoots/ReferencesRoot.cs b/HaWeb/Settings/XMLRoots/ReferencesRoot.cs index 330df19..74df9d1 100644 --- a/HaWeb/Settings/XMLRoots/ReferencesRoot.cs +++ b/HaWeb/Settings/XMLRoots/ReferencesRoot.cs @@ -36,4 +36,14 @@ public class ReferencesRoot : HaWeb.XMLParser.IXMLRoot { return opus; } + public void MergeIntoFile(XElement file, XMLRootDocument document) { + if (file.Element("definitions") == null) + file.AddFirst(new XElement("definitions")); + var elements = document.Root.Elements().Where(x => IsCollectedObject(x)); + var root = file.Element("definitions"); + foreach (var element in elements) { + root!.Add(element); + } + } + } \ No newline at end of file diff --git a/HaWeb/Settings/XMLRoots/TraditionsRoot.cs b/HaWeb/Settings/XMLRoots/TraditionsRoot.cs index 2c70b38..abed955 100644 --- a/HaWeb/Settings/XMLRoots/TraditionsRoot.cs +++ b/HaWeb/Settings/XMLRoots/TraditionsRoot.cs @@ -38,4 +38,13 @@ public class TraditionsRoot : HaWeb.XMLParser.IXMLRoot { return opus; } + public void MergeIntoFile(XElement file, XMLRootDocument document) { + if (file.Element("traditions") == null) + file.AddFirst(new XElement("traditions")); + var elements = document.Root.Elements().Where(x => IsCollectedObject(x)); + var root = file.Element("traditions"); + foreach (var element in elements) { + root!.Add(element); + } + } } \ No newline at end of file diff --git a/HaWeb/Views/Admin/Upload/Index.cshtml b/HaWeb/Views/Admin/Upload/Index.cshtml index 9acdbf0..1b08547 100644 --- a/HaWeb/Views/Admin/Upload/Index.cshtml +++ b/HaWeb/Views/Admin/Upload/Index.cshtml @@ -36,14 +36,13 @@ -
-