mirror of
https://github.com/Theodor-Springmann-Stiftung/hamann-ausgabe-core.git
synced 2025-10-29 09:15:33 +00:00
Formatted everything; completed upload capabilities
This commit is contained in:
13
HaWeb/.vscode/launch.json
vendored
13
HaWeb/.vscode/launch.json
vendored
@@ -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"
|
||||
},
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
@@ -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<string>();
|
||||
var recivers = meta.Receivers.Select(x => _lib.Persons[x].Name) ?? new List<string>();
|
||||
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)
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
@@ -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 });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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?}")]
|
||||
|
||||
@@ -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<CommentModel>();
|
||||
foreach (var comm in comments)
|
||||
{
|
||||
foreach (var comm in comments) {
|
||||
var parsedComment = HTMLHelpers.CommentHelpers.CreateHTML(_lib, _readerService, comm, category, Settings.ParsingState.CommentType.Comment);
|
||||
List<string>? parsedSubComments = null;
|
||||
if (comm.Kommentare != null)
|
||||
{
|
||||
if (comm.Kommentare != null) {
|
||||
parsedSubComments = new List<string>();
|
||||
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<CommentModel>();
|
||||
foreach (var comm in comments)
|
||||
{
|
||||
foreach (var comm in comments) {
|
||||
var parsedComment = HTMLHelpers.CommentHelpers.CreateHTML(_lib, _readerService, comm, category, Settings.ParsingState.CommentType.Comment);
|
||||
List<string>? parsedSubComments = null;
|
||||
if (comm.Kommentare != null)
|
||||
{
|
||||
if (comm.Kommentare != null) {
|
||||
parsedSubComments = new List<string>();
|
||||
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<Comment>? 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<CommentModel>();
|
||||
foreach (var comm in comments)
|
||||
{
|
||||
foreach (var comm in comments) {
|
||||
var parsedComment = HTMLHelpers.CommentHelpers.CreateHTML(_lib, _readerService, comm, category, Settings.ParsingState.CommentType.Comment);
|
||||
List<string>? parsedSubComments = null;
|
||||
if (comm.Kommentare != null)
|
||||
{
|
||||
if (comm.Kommentare != null) {
|
||||
parsedSubComments = new List<string>();
|
||||
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<string> permitted)
|
||||
{
|
||||
if (!permitted.Contains(id))
|
||||
{
|
||||
private bool validationCheck(HashSet<string> permitted) {
|
||||
if (!permitted.Contains(id)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private IActionResult error404()
|
||||
{
|
||||
private IActionResult error404() {
|
||||
Response.StatusCode = 404;
|
||||
return Redirect("/Error404");
|
||||
}
|
||||
|
||||
@@ -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 });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
@@ -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<IActionResult> Post() {
|
||||
//// 1. Stage: Check Request format and request spec
|
||||
List<XMLRootDocument>? 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<XMLRootDocument>();
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -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<XDocument?> 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}");
|
||||
}
|
||||
|
||||
|
||||
@@ -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<string, List<byte[]>> _fileSignature = new Dictionary<string, List<byte[]>>
|
||||
{
|
||||
@@ -33,9 +32,9 @@ public static class XMLFileHelpers
|
||||
new byte[] { 0xFF, 0xD8, 0xFF, 0xE8 },
|
||||
}
|
||||
},
|
||||
{ ".zip", new List<byte[]>
|
||||
{ ".zip", new List<byte[]>
|
||||
{
|
||||
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<byte>();
|
||||
// }
|
||||
|
||||
|
||||
// if (formFile.Length > sizeLimit)
|
||||
// {
|
||||
// var megabyteSizeLimit = sizeLimit / 1048576;
|
||||
@@ -141,20 +140,16 @@ public static class XMLFileHelpers
|
||||
// }
|
||||
|
||||
public static async Task<byte[]?> 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:<br>" +
|
||||
"1. The file must hava a .xml File-Extension<br>" +
|
||||
"2. To make sure the file isn't executable the file must start with: <?xml version=\"1.0\" encoding=\"utf-8\"?> or <?xml version=\"1.0\"?>");
|
||||
|
||||
|
||||
// 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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<IAntiforgery>();
|
||||
|
||||
// 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) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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<FormValueProviderFactory>();
|
||||
factories.RemoveType<FormFileValueProviderFactory>();
|
||||
factories.RemoveType<JQueryFormValueProviderFactory>();
|
||||
}
|
||||
|
||||
public void OnResourceExecuted(ResourceExecutedContext context)
|
||||
{
|
||||
public void OnResourceExecuted(ResourceExecutedContext context) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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<Marginal>? marginals, IEnumerable<Hand>? hands, IEnumerable<Editreason>? edits)
|
||||
{
|
||||
public static class LetterHelpers {
|
||||
public static LetterState CreateLetter(ILibrary lib, IReaderService readerService, Meta meta, Letter letter, IEnumerable<Marginal>? marginals, IEnumerable<Hand>? hands, IEnumerable<Editreason>? edits) {
|
||||
var rd = readerService.RequestStringReader(letter.Element);
|
||||
var letterState = new LetterState(lib, readerService, meta, marginals, hands, edits);
|
||||
new HaWeb.HTMLParser.XMLHelper<LetterState>(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<Marginal>? marginals, Tradition tradition, IEnumerable<Hand>? hands, IEnumerable<Editreason>? edits)
|
||||
{
|
||||
public static TraditionState CreateTraditions(ILibrary lib, IReaderService readerService, IEnumerable<Marginal>? marginals, Tradition tradition, IEnumerable<Hand>? hands, IEnumerable<Editreason>? edits) {
|
||||
var rd = readerService.RequestStringReader(tradition.Element);
|
||||
var traditionState = new TraditionState(lib, rd, readerService, marginals, hands, edits);
|
||||
new HaWeb.HTMLParser.XMLHelper<TraditionState>(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<Editreason> editreasons)
|
||||
{
|
||||
public static List<(string, string, string, string, string, string)> CreateEdits(ILibrary lib, IReaderService readerService, IEnumerable<Editreason> 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<EditState>(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<Hand> hands)
|
||||
{
|
||||
public static List<(string, string, string, string, string)> CreateHands(ILibrary lib, ImmutableList<Hand> 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));
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -2,17 +2,15 @@ using System.Web;
|
||||
|
||||
namespace HaWeb.HTMLHelpers;
|
||||
public static class StringHelpers {
|
||||
public static string GetEnumerationString(IEnumerable<string> strlist)
|
||||
{
|
||||
public static string GetEnumerationString(IEnumerable<string> 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;
|
||||
|
||||
@@ -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 });
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
namespace HaWeb.HTMLParser;
|
||||
|
||||
class GenericParser<T> where T : IState {
|
||||
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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<string>? ParsedSubComments { get; private set; }
|
||||
|
||||
public CommentModel(string parsedComment, List<string>? parsedSubComments)
|
||||
{
|
||||
public CommentModel(string parsedComment, List<string>? parsedSubComments) {
|
||||
this.ParsedComment = parsedComment;
|
||||
this.ParsedSubComments = parsedSubComments;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
namespace HaWeb.Models;
|
||||
|
||||
public class ErrorViewModel
|
||||
{
|
||||
public class ErrorViewModel {
|
||||
public string? RequestId { get; set; }
|
||||
|
||||
public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
|
||||
|
||||
@@ -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<CommentModel> 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<CommentModel> parsedComments, string title)
|
||||
{
|
||||
public RegisterViewModel(string category, string id, List<CommentModel> parsedComments, string title) {
|
||||
this.Category = HttpUtility.HtmlAttributeEncode(category);
|
||||
this.Id = HttpUtility.HtmlAttributeEncode(id);
|
||||
this.ParsedComments = parsedComments;
|
||||
|
||||
@@ -26,10 +26,8 @@ public class DocumentResult {
|
||||
}
|
||||
}
|
||||
|
||||
public class LetterComparer : IComparer<DocumentSearchResult>
|
||||
{
|
||||
public int Compare(DocumentSearchResult first, DocumentSearchResult second)
|
||||
{
|
||||
public class LetterComparer : IComparer<DocumentSearchResult> {
|
||||
public int Compare(DocumentSearchResult first, DocumentSearchResult second) {
|
||||
var cmp = new DefaultComparer();
|
||||
return cmp.Compare(first.MetaData, second.MetaData);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
namespace HaWeb.Models;
|
||||
using HaWeb.XMLParser;
|
||||
|
||||
public class UploadViewModel {
|
||||
public List<(string, string)>? AvailableRoots { get; set; }
|
||||
public List<IXMLRoot>? AvailableRoots { get; set; }
|
||||
public List<XMLRootDocument>? AvailableFiles { get; set; }
|
||||
public Dictionary<string, List<XMLRootDocument>>? UsedFiles { get; set; }
|
||||
}
|
||||
@@ -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<string>("StoredFilesPath"));
|
||||
// // To list physical files in the temporary files folder, use:
|
||||
// //var physicalProvider = new PhysicalFileProvider(Path.GetTempPath());
|
||||
// services.AddSingleton<IFileProvider>(physicalProvider);
|
||||
// // To get files from a path provided by configuration:
|
||||
string? filepath = null;
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) {
|
||||
filepath = builder.Configuration.GetValue<string>("StoredFilePathWindows");
|
||||
}
|
||||
else {
|
||||
filepath = builder.Configuration.GetValue<string>("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<IFileProvider>(physicalProvider);
|
||||
builder.Services.AddSingleton<ILibrary>(HaDocument.Document.Create(new Options()));
|
||||
builder.Services.AddTransient<IReaderService, ReaderService>();
|
||||
builder.Services.AddSingleton<IXMLService, XMLService>();
|
||||
|
||||
@@ -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
|
||||
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
|
||||
@@ -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
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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("<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"feather feather-external-link\"><path d=\"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6\"></path><polyline points=\"15 3 21 3 21 9\"></polyline><line x1=\"10\" y1=\"14\" x2=\"21\" y2=\"3\"></line></svg>");
|
||||
sb.Append(HaWeb.HTMLHelpers.TagHelpers.CreateEndElement("a"));
|
||||
}
|
||||
}
|
||||
})};
|
||||
|
||||
public static readonly WhitespaceFuncList WhitespaceRules = new WhitespaceFuncList() {
|
||||
( (x, _) => true, ( sb, txt, _) => sb.Append(txt.Value) )
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -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")) )
|
||||
};
|
||||
|
||||
@@ -7,8 +7,7 @@ using TextFuncList = List<(Func<HaXMLReader.EvArgs.Text, HaWeb.HTMLParser.XMLHel
|
||||
using WhitespaceFuncList = List<(Func<HaXMLReader.EvArgs.Whitespace, HaWeb.HTMLParser.XMLHelper<HaWeb.Settings.ParsingState.LetterState>, bool>, Action<System.Text.StringBuilder, HaXMLReader.EvArgs.Whitespace, HaWeb.HTMLParser.XMLHelper<HaWeb.Settings.ParsingState.LetterState>>)>;
|
||||
|
||||
// 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) => {
|
||||
|
||||
@@ -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)) ),
|
||||
|
||||
@@ -6,8 +6,7 @@ using TagFuncList = List<(Func<HaXMLReader.EvArgs.Tag, HaWeb.HTMLParser.XMLHelpe
|
||||
using TextFuncList = List<(Func<HaXMLReader.EvArgs.Text, HaWeb.HTMLParser.XMLHelper<HaWeb.Settings.ParsingState.TraditionState>, bool>, Action<System.Text.StringBuilder, HaXMLReader.EvArgs.Text, HaWeb.HTMLParser.XMLHelper<HaWeb.Settings.ParsingState.TraditionState>>)>;
|
||||
using WhitespaceFuncList = List<(Func<HaXMLReader.EvArgs.Whitespace, HaWeb.HTMLParser.XMLHelper<HaWeb.Settings.ParsingState.TraditionState>, bool>, Action<System.Text.StringBuilder, HaXMLReader.EvArgs.Whitespace, HaWeb.HTMLParser.XMLHelper<HaWeb.Settings.ParsingState.TraditionState>>)>;
|
||||
|
||||
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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -34,8 +34,7 @@ public class TraditionState : HaWeb.HTMLParser.IState {
|
||||
|
||||
internal IReader rd_tradition;
|
||||
|
||||
public TraditionState(ILibrary lib, IReader reader, IReaderService readerService, IEnumerable<Marginal>? marginals, IEnumerable<Hand>? hands, IEnumerable<Editreason>? edits)
|
||||
{
|
||||
public TraditionState(ILibrary lib, IReader reader, IReaderService readerService, IEnumerable<Marginal>? marginals, IEnumerable<Hand>? hands, IEnumerable<Editreason>? 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";
|
||||
|
||||
@@ -12,7 +12,7 @@ public class CommentRoot : HaWeb.XMLParser.IXMLRoot {
|
||||
else return false;
|
||||
};
|
||||
|
||||
public Func<XElement, string?> GetKey { get; } = (elem) => {
|
||||
public Func<XElement, string?> 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);
|
||||
}
|
||||
|
||||
@@ -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<XElement> IsCollectedObject { get; } = (elem) => {
|
||||
if (elem.Name == "letterDesc") return true;
|
||||
return false;
|
||||
};
|
||||
|
||||
public Func<XElement, string?> GetKey { get; } = (elem) => {
|
||||
public Func<XElement, string?> GetKey { get; } = (elem) => {
|
||||
var index = elem.Attribute("ref");
|
||||
if (index != null && !String.IsNullOrWhiteSpace(index.Value))
|
||||
return index.Value;
|
||||
|
||||
@@ -12,7 +12,7 @@ public class DocumentRoot : HaWeb.XMLParser.IXMLRoot {
|
||||
else return false;
|
||||
};
|
||||
|
||||
public Func<XElement, string?> GetKey { get; } = (elem) => {
|
||||
public Func<XElement, string?> GetKey { get; } = (elem) => {
|
||||
var index = elem.Attribute("index");
|
||||
if (index != null && !String.IsNullOrWhiteSpace(index.Value))
|
||||
return index.Value;
|
||||
|
||||
@@ -12,7 +12,7 @@ public class EditsRoot : HaWeb.XMLParser.IXMLRoot {
|
||||
else return false;
|
||||
};
|
||||
|
||||
public Func<XElement, string?> GetKey { get; } = (elem) => {
|
||||
public Func<XElement, string?> GetKey { get; } = (elem) => {
|
||||
var index = elem.Attribute("index");
|
||||
if (index != null && !String.IsNullOrWhiteSpace(index.Value))
|
||||
return index.Value;
|
||||
|
||||
@@ -12,7 +12,7 @@ public class MarginalsRoot : HaWeb.XMLParser.IXMLRoot {
|
||||
else return false;
|
||||
};
|
||||
|
||||
public Func<XElement, string?> GetKey { get; } = (elem) => {
|
||||
public Func<XElement, string?> GetKey { get; } = (elem) => {
|
||||
var index = elem.Attribute("index");
|
||||
if (index != null && !String.IsNullOrWhiteSpace(index.Value))
|
||||
return index.Value;
|
||||
|
||||
@@ -13,7 +13,7 @@ public class ReferencesRoot : HaWeb.XMLParser.IXMLRoot {
|
||||
return false;
|
||||
};
|
||||
|
||||
public Func<XElement, string?> GetKey { get; } = (elem) => {
|
||||
public Func<XElement, string?> GetKey { get; } = (elem) => {
|
||||
return elem.Name.ToString();
|
||||
};
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ public class TraditionsRoot : HaWeb.XMLParser.IXMLRoot {
|
||||
else return false;
|
||||
};
|
||||
|
||||
public Func<XElement, string?> GetKey { get; } = (elem) => {
|
||||
public Func<XElement, string?> GetKey { get; } = (elem) => {
|
||||
var index = elem.Attribute("ref");
|
||||
if (index != null && !String.IsNullOrWhiteSpace(index.Value))
|
||||
return index.Value;
|
||||
|
||||
@@ -1,57 +1,79 @@
|
||||
@model UploadViewModel;
|
||||
Hello from Upload Index!
|
||||
|
||||
<form id="uploadForm" action="Upload" method="post"
|
||||
enctype="multipart/form-data" onsubmit="AJAXSubmit(this);return false;">
|
||||
<dl>
|
||||
<dt>
|
||||
<label for="file">File</label>
|
||||
</dt>
|
||||
<dd>
|
||||
<input id="file" type="file" name="file" />
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<input class="btn" type="submit" value="Upload" />
|
||||
|
||||
<div style="margin-top:15px">
|
||||
<output form="uploadForm" name="result"></output>
|
||||
<div class="ha-adminuploadfields">
|
||||
@foreach (var item in Model.AvailableRoots.OrderBy(x => x.Type)) {
|
||||
<div class="ha-uploadfield">
|
||||
<div class="ha-uploadfieldname">@item.Type</div>
|
||||
@if (Model.UsedFiles != null && Model.UsedFiles.ContainsKey(item.Prefix)) {
|
||||
@foreach(var file in Model.UsedFiles[item.Prefix]) {
|
||||
<span>@file.File.Name</span>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@foreach (var item in Model.AvailableRoots.OrderBy(x => x.Item1))
|
||||
{
|
||||
<div>@item.Item1</div>
|
||||
}
|
||||
}
|
||||
<form class="ha-uploadform" id="uploadForm" action="Upload" method="post" enctype="multipart/form-data">
|
||||
<label class="filelabel" id="dropzone">
|
||||
<input class="hidden" id="file" type="file" accept=".xml" name="file" />
|
||||
Upload2 es
|
||||
</label>
|
||||
<div class="ha-uploadmessage">
|
||||
<output form="uploadForm" name="result"></output>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@section Scripts {
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"
|
||||
asp-fallback-src="~/lib/jquery/dist/jquery.min.js"
|
||||
asp-fallback-test="window.jQuery"
|
||||
crossorigin="anonymous"
|
||||
integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=">
|
||||
</script>
|
||||
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
async function AJAXSubmit (oFormElement) {
|
||||
const formData = new FormData(oFormElement);
|
||||
const dropHandler = function (formelement, ev, dropzone) {
|
||||
ev.preventDefault();
|
||||
|
||||
try {
|
||||
const response = await fetch(oFormElement.action, {
|
||||
if (ev.dataTransfer.items) {
|
||||
if (ev.dataTransfer.items[0].kind === 'file') {
|
||||
var file = ev.dataTransfer.items[0].getAsFile();
|
||||
AJAXSubmit(formelement, file);
|
||||
} else {
|
||||
var file = ev.dataTransfer.files[0];
|
||||
AJAXSubmit(formelement, file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const dragOverHandler = function (ev, dropzone) {
|
||||
ev.preventDefault();
|
||||
}
|
||||
|
||||
const dragLeaveHander = function (ev, dropzone) {
|
||||
ev.preventDefault();
|
||||
}
|
||||
|
||||
const dragEnterHandler = function (ev, dropzone) {
|
||||
ev.preventDefault();
|
||||
}
|
||||
|
||||
const AJAXSubmit = async function (oFormElement, file = null) {
|
||||
var fd = new FormData();
|
||||
if (file !== null) fd.append("file", file);
|
||||
else fd = new FormData(oFormElement);
|
||||
oFormElement.elements.namedItem("result").value = "Wait";
|
||||
await fetch(oFormElement.action, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'RequestVerificationToken': getCookie('RequestVerificationToken')
|
||||
},
|
||||
body: formData
|
||||
});
|
||||
|
||||
oFormElement.elements.namedItem("result").value =
|
||||
'Result: ' + response.status + ' ' + response.statusText;
|
||||
} catch (error) {
|
||||
console.error('Error:', error);
|
||||
}
|
||||
body: fd
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(json => {
|
||||
if ("Error" in json) {
|
||||
oFormElement.elements.namedItem("result").value = json.Error;
|
||||
} else {
|
||||
oFormElement.elements.namedItem("result").value = "Erfolg!";
|
||||
}
|
||||
})
|
||||
.catch ((e) => console.error('Error:', error))
|
||||
}
|
||||
|
||||
function getCookie(name) {
|
||||
@@ -59,5 +81,18 @@ Hello from Upload Index!
|
||||
var parts = value.split("; " + name + "=");
|
||||
if (parts.length == 2) return parts.pop().split(";").shift();
|
||||
}
|
||||
|
||||
window.addEventListener("load", function () {
|
||||
var submitelement = document.getElementById("file");
|
||||
var formelement = document.getElementById("uploadForm");
|
||||
var dropzone = document.getElementById("dropzone");
|
||||
submitelement.addEventListener("change", () => AJAXSubmit(formelement));
|
||||
dropzone.addEventListener("drop", (ev) => dropHandler(formelement, ev, dropzone));
|
||||
dropzone.addEventListener("dragover", (ev) => dragOverHandler(ev, dropzone));
|
||||
dropzone.addEventListener("dragleave", (ev) => dragLeaveHander(ev, dropzone));
|
||||
dropzone.addEventListener("dragenter", (ev) => dragEnterHandler(ev, dropzone));
|
||||
});
|
||||
|
||||
|
||||
</script>
|
||||
}
|
||||
|
||||
@@ -7,46 +7,44 @@
|
||||
if (Model.MinWidthTrad)
|
||||
minwidthtrads = "ha-minwidth";
|
||||
}
|
||||
<div class="ha-twilighttogglebar">
|
||||
<div class="ha-letterheader">
|
||||
@await Html.PartialAsync("/Views/Shared/_LetterHead.cshtml", Model.MetaData)
|
||||
<div class="ha-letterheadernav">
|
||||
<div class="ha-lettertabs">
|
||||
@if (Model.ParsedText != null && !String.IsNullOrWhiteSpace(Model.ParsedText))
|
||||
{
|
||||
<a class="" id="ha-lettertextbtn">Brieftext</a>
|
||||
@if (Model.ParsedMarginals != null)
|
||||
{
|
||||
<a class="ha-marginalsbtn " id="ha-marginalsbtn">Stellenkommentar</a>
|
||||
}
|
||||
}
|
||||
<a class="" id="ha-additionsbtn">Überlieferung & Textkritik</a>
|
||||
<a class="">PDF</a>
|
||||
</div>
|
||||
|
||||
@if (Model.MetaData.Next != null || Model.MetaData.Prev != null)
|
||||
<div class="ha-letterheader">
|
||||
@await Html.PartialAsync("/Views/Shared/_LetterHead.cshtml", Model.MetaData)
|
||||
<div class="ha-letterheadernav">
|
||||
<div class="ha-lettertabs">
|
||||
@if (Model.ParsedText != null && !String.IsNullOrWhiteSpace(Model.ParsedText))
|
||||
{
|
||||
<div class="ha-lettermetalinks">
|
||||
@if (Model.MetaData.Prev != null)
|
||||
{
|
||||
<a href="@Model.MetaData.Prev.Value.Item2">
|
||||
@Model.MetaData.Prev.Value.Item1.Meta.Autopsic ◀
|
||||
</a>
|
||||
}
|
||||
|
||||
<div class="ha-hkb">
|
||||
HKB
|
||||
</div>
|
||||
|
||||
@if (Model.MetaData.Next != null)
|
||||
{
|
||||
<a href="@Model.MetaData.Next.Value.Item2">
|
||||
▶ @Model.MetaData.Next.Value.Item1.Meta.Autopsic
|
||||
</a>
|
||||
}
|
||||
</div>
|
||||
<a class="" id="ha-lettertextbtn">Brieftext</a>
|
||||
@if (Model.ParsedMarginals != null)
|
||||
{
|
||||
<a class="ha-marginalsbtn " id="ha-marginalsbtn">Stellenkommentar</a>
|
||||
}
|
||||
}
|
||||
<a class="" id="ha-additionsbtn">Überlieferung & Textkritik</a>
|
||||
<a class="">PDF</a>
|
||||
</div>
|
||||
|
||||
@if (Model.MetaData.Next != null || Model.MetaData.Prev != null)
|
||||
{
|
||||
<div class="ha-lettermetalinks">
|
||||
@if (Model.MetaData.Prev != null)
|
||||
{
|
||||
<a href="@Model.MetaData.Prev.Value.Item2">
|
||||
@Model.MetaData.Prev.Value.Item1.Meta.Autopsic ◀
|
||||
</a>
|
||||
}
|
||||
|
||||
<div class="ha-hkb">
|
||||
HKB
|
||||
</div>
|
||||
|
||||
@if (Model.MetaData.Next != null)
|
||||
{
|
||||
<a href="@Model.MetaData.Next.Value.Item2">
|
||||
▶ @Model.MetaData.Next.Value.Item1.Meta.Autopsic
|
||||
</a>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -3,10 +3,8 @@
|
||||
<div class="flex grow shrink-0">
|
||||
<div class="ha-themetoggles">
|
||||
<input type="radio" id="ha-toggledark" name="ha-themetoggle">
|
||||
<input type="radio" id="ha-toggletwilight" name="ha-themetoggle">
|
||||
<input type="radio" id="ha-togglebright" name="ha-themetoggle">
|
||||
<label for="ha-toggledark"></label>
|
||||
<label for="ha-toggletwilight"></label>
|
||||
<label for="ha-togglebright"></label>
|
||||
<div class="ha-themetoggleslider">
|
||||
</div>
|
||||
|
||||
@@ -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<XElement>();
|
||||
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.
|
||||
|
||||
@@ -5,5 +5,7 @@ using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||
public interface IXMLService {
|
||||
public IXMLRoot? GetRoot(string name);
|
||||
public List<IXMLRoot>? GetRoots();
|
||||
public List<XMLRootDocument>? ProbeHamannFile(XDocument document, ModelStateDictionary ModelState);
|
||||
public Task<List<XMLRootDocument>?> ProbeHamannFile(XDocument document, ModelStateDictionary ModelState);
|
||||
public Task UpdateAvailableFiles(XMLRootDocument doc, string basefilepath, ModelStateDictionary ModelState);
|
||||
public Dictionary<string, List<XMLRootDocument>> GetUsed();
|
||||
}
|
||||
34
HaWeb/XMLParser/JSONConverters.cs
Normal file
34
HaWeb/XMLParser/JSONConverters.cs
Normal file
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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<string, List<XMLRootDocument>?>? _availableFilesObj;
|
||||
private Dictionary<string, List<XMLRootDocument>?>? _availableFiles {
|
||||
get {
|
||||
if (_availableFilesObj == null) {
|
||||
_availableFilesObj = _GetAvailableFiles();
|
||||
AutoDetermineUsed();
|
||||
}
|
||||
return _availableFilesObj;
|
||||
} }
|
||||
|
||||
private IFileProvider _fileProvider;
|
||||
private IFeatureManager _featureManager;
|
||||
private Dictionary<string, IXMLRoot>? _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<IXMLRoot>().ToList();
|
||||
types.ForEach( x => {
|
||||
if (this._Roots == null) this._Roots = new Dictionary<string, IXMLRoot>();
|
||||
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<IXMLRoot>? GetRoots() => this._Roots == null ? null : this._Roots.Values.ToList();
|
||||
|
||||
public List<XMLRootDocument>? ProbeHamannFile(XDocument document, ModelStateDictionary ModelState) {
|
||||
public async Task<List<XMLRootDocument>?> ProbeHamannFile(XDocument document, ModelStateDictionary ModelState) {
|
||||
if (document.Root!.Name != "opus") {
|
||||
ModelState.AddModelError("Error", "A valid Hamann-Docuemnt must begin with <opus>");
|
||||
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<string, List<XMLRootDocument>?>? _GetAvailableFiles() {
|
||||
if (_Roots == null) return null;
|
||||
Dictionary<string, List<XMLRootDocument>?>? 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<string, List<XMLRootDocument>?>();
|
||||
res.Add(dir.Name, _GetAvailableFiles(dir.Name));
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
private List<XMLRootDocument>? _GetAvailableFiles(string prefix) {
|
||||
List<XMLRootDocument>? 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<XMLRootDocument>();
|
||||
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<string, List<XMLRootDocument>>? 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);
|
||||
}
|
||||
}
|
||||
16
HaWeb/omnisharp.json
Normal file
16
HaWeb/omnisharp.json
Normal file
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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");
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user