mirror of
https://github.com/Theodor-Springmann-Stiftung/hamann-ausgabe-core.git
synced 2025-10-29 09:15:33 +00:00
Created FileList with ability to set used files
This commit is contained in:
@@ -16,6 +16,7 @@ using HaXMLReader.Interfaces;
|
||||
using Microsoft.FeatureManagement.Mvc;
|
||||
using System.Runtime.InteropServices;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
using System.Text;
|
||||
|
||||
// Controlling all the API-Endpoints
|
||||
public class APIController : Controller {
|
||||
@@ -78,6 +79,7 @@ public class APIController : Controller {
|
||||
section = await reader.ReadNextSectionAsync();
|
||||
} catch (Exception ex) {
|
||||
ModelState.AddModelError("Error", "The Request is bad: " + ex.Message);
|
||||
return BadRequest(ModelState);
|
||||
}
|
||||
|
||||
while (section != null) {
|
||||
@@ -178,7 +180,82 @@ public class APIController : Controller {
|
||||
[ValidateAntiForgeryToken]
|
||||
[FeatureGate(Features.UploadService, Features.AdminService)]
|
||||
public async Task<IActionResult> SetUsed(string id) {
|
||||
return Ok();
|
||||
var f = _xmlProvider.GetFiles(id);
|
||||
if (f == null) {
|
||||
ModelState.AddModelError("Error", "Wrong Endpoint");
|
||||
return BadRequest(ModelState);
|
||||
}
|
||||
|
||||
var files = f.GetFileList();
|
||||
if (files == null) {
|
||||
ModelState.AddModelError("Error", "Wrong Endpoint");
|
||||
return BadRequest(ModelState);
|
||||
}
|
||||
|
||||
List<XMLRootDocument>? newUsed = null;
|
||||
|
||||
if (!MultipartRequestHelper.IsMultipartContentType(Request.ContentType)) {
|
||||
ModelState.AddModelError("Error", $"Wrong / No Content Type on the Request");
|
||||
return BadRequest(ModelState);
|
||||
}
|
||||
|
||||
// Same as above, check Upload()
|
||||
var boundary = MultipartRequestHelper.GetBoundary(MediaTypeHeaderValue.Parse(Request.ContentType), _defaultFormOptions.MultipartBoundaryLengthLimit);
|
||||
var reader = new MultipartReader(boundary, HttpContext.Request.Body);
|
||||
MultipartSection? section = null;
|
||||
try {
|
||||
section = await reader.ReadNextSectionAsync();
|
||||
} catch (Exception ex) {
|
||||
ModelState.AddModelError("Error", "The Request is bad: " + ex.Message);
|
||||
return BadRequest(ModelState);
|
||||
}
|
||||
|
||||
while (section != null) {
|
||||
var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out var contentDisposition);
|
||||
|
||||
if (contentDisposition != null && contentDisposition.Name == "__RequestVerificationToken") {
|
||||
try {
|
||||
section = await reader.ReadNextSectionAsync();
|
||||
} catch (Exception ex) {
|
||||
ModelState.AddModelError("Error", "The Request is bad: " + ex.Message);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
var filename = "";
|
||||
if (hasContentDispositionHeader && contentDisposition != null) {
|
||||
if (!MultipartRequestHelper.HasFormDataContentDisposition(contentDisposition)) {
|
||||
ModelState.AddModelError("Error", $"Wrong Content-Dispostion Headers in Multipart Document");
|
||||
return BadRequest(ModelState);
|
||||
}
|
||||
|
||||
filename = XMLFileHelpers.StreamToString(section.Body, ModelState);
|
||||
if (!ModelState.IsValid) return BadRequest(ModelState);
|
||||
|
||||
var isFile = files.Where(x => x.FileName == filename);
|
||||
if (isFile == null || !isFile.Any()) {
|
||||
ModelState.AddModelError("Error", "Tried to add a file that does not exist.");
|
||||
return BadRequest(ModelState);
|
||||
}
|
||||
|
||||
if (newUsed == null) newUsed = new List<XMLRootDocument>();
|
||||
newUsed.Add(isFile.First());
|
||||
}
|
||||
|
||||
try {
|
||||
section = await reader.ReadNextSectionAsync();
|
||||
} catch (Exception ex) {
|
||||
ModelState.AddModelError("Error", "The Request is bad: " + ex.Message);
|
||||
return BadRequest(ModelState);
|
||||
}
|
||||
}
|
||||
|
||||
if (newUsed != null && newUsed.Any()) {
|
||||
_xmlService.UnUse(id);
|
||||
newUsed.ForEach(x => _xmlService.Use(x));
|
||||
}
|
||||
|
||||
return Created("/", newUsed);
|
||||
}
|
||||
|
||||
|
||||
@@ -188,6 +265,84 @@ public class APIController : Controller {
|
||||
[ValidateAntiForgeryToken]
|
||||
[FeatureGate(Features.UploadService, Features.AdminService)]
|
||||
public async Task<IActionResult> SetUsedHamann() {
|
||||
return Ok();
|
||||
var hF = _xmlProvider.GetHamannFiles();
|
||||
if (hF == null) {
|
||||
ModelState.AddModelError("Error", "There are no Hamman.xml files available.");
|
||||
return BadRequest(ModelState);
|
||||
}
|
||||
|
||||
if (!MultipartRequestHelper.IsMultipartContentType(Request.ContentType)) {
|
||||
ModelState.AddModelError("Error", $"Wrong / No Content Type on the Request");
|
||||
return BadRequest(ModelState);
|
||||
}
|
||||
|
||||
// Same as above, check Upload()
|
||||
string? filename = null;
|
||||
var boundary = MultipartRequestHelper.GetBoundary(MediaTypeHeaderValue.Parse(Request.ContentType), _defaultFormOptions.MultipartBoundaryLengthLimit);
|
||||
var reader = new MultipartReader(boundary, HttpContext.Request.Body);
|
||||
MultipartSection? section = null;
|
||||
try {
|
||||
section = await reader.ReadNextSectionAsync();
|
||||
} catch (Exception ex) {
|
||||
ModelState.AddModelError("Error", "The Request is bad: " + ex.Message);
|
||||
return BadRequest(ModelState);
|
||||
}
|
||||
|
||||
while (section != null) {
|
||||
var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out var contentDisposition);
|
||||
|
||||
if (contentDisposition != null && contentDisposition.Name == "__RequestVerificationToken") {
|
||||
try {
|
||||
section = await reader.ReadNextSectionAsync();
|
||||
} catch (Exception ex) {
|
||||
ModelState.AddModelError("Error", "The Request is bad: " + ex.Message);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
filename = XMLFileHelpers.StreamToString(section.Body, ModelState);
|
||||
if (!ModelState.IsValid) return BadRequest(ModelState);
|
||||
|
||||
if (hasContentDispositionHeader && contentDisposition != null) {
|
||||
if (!MultipartRequestHelper.HasFormDataContentDisposition(contentDisposition)) {
|
||||
ModelState.AddModelError("Error", $"Wrong Content-Dispostion Headers in Multipart Document");
|
||||
return BadRequest(ModelState);
|
||||
}
|
||||
|
||||
filename = XMLFileHelpers.StreamToString(section.Body, ModelState);
|
||||
|
||||
}
|
||||
|
||||
try {
|
||||
section = await reader.ReadNextSectionAsync();
|
||||
} catch (Exception ex) {
|
||||
ModelState.AddModelError("Error", "The Request is bad: " + ex.Message);
|
||||
return BadRequest(ModelState);
|
||||
}
|
||||
}
|
||||
|
||||
if (filename == null) {
|
||||
ModelState.AddModelError("Error", "No filename given");
|
||||
return BadRequest(ModelState);
|
||||
}
|
||||
|
||||
var newFile = hF.Where(x => x.Name == filename);
|
||||
if (newFile == null || !newFile.Any()) {
|
||||
ModelState.AddModelError("Error", "Trying to set a unavailable file.");
|
||||
return BadRequest(ModelState);
|
||||
}
|
||||
|
||||
try {
|
||||
_ = _lib.SetLibrary(newFile.First().PhysicalPath, ModelState);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
ModelState.AddModelError("Error", "Error parsing the file: " + ex.Message);
|
||||
return BadRequest(ModelState);
|
||||
}
|
||||
|
||||
_xmlProvider.SetInProduction(newFile.First());
|
||||
_xmlService.UnUseProduction();
|
||||
|
||||
return Created("/", null);
|
||||
}
|
||||
}
|
||||
@@ -48,18 +48,18 @@ public class UploadController : Controller {
|
||||
if (roots == null) return error404();
|
||||
|
||||
var hF = _xmlProvider.GetHamannFiles();
|
||||
List<(string, DateTime)>? hamannFiles = null;
|
||||
List<FileModel>? hamannFiles = null;
|
||||
if (hF != null)
|
||||
hamannFiles = hF
|
||||
.OrderByDescending(x => x.LastModified)
|
||||
.Select(x => (x.Name, x.LastModified.LocalDateTime))
|
||||
.Select(x => new FileModel(x.Name, string.Empty, x.LastModified.LocalDateTime, false, x == _xmlProvider.GetInProduction()))
|
||||
.ToList();
|
||||
|
||||
|
||||
var uF = _xmlService.GetUsedDictionary();
|
||||
var pF = _xmlService.GetInProduction();
|
||||
|
||||
Dictionary<string, List<FileModel>?>? usedFiles = null;
|
||||
if (uF != null) {
|
||||
if (uF != null) {
|
||||
usedFiles = new Dictionary<string, List<FileModel>?>();
|
||||
foreach (var kv in uF) {
|
||||
if (kv.Value == null) continue;
|
||||
@@ -68,7 +68,7 @@ public class UploadController : Controller {
|
||||
}
|
||||
|
||||
Dictionary<string, List<FileModel>?>? productionFiles = null;
|
||||
if (pF != null) {
|
||||
if (pF != null) {
|
||||
productionFiles = new Dictionary<string, List<FileModel>?>();
|
||||
foreach (var kv in pF) {
|
||||
if (kv.Value == null) continue;
|
||||
@@ -81,16 +81,15 @@ public class UploadController : Controller {
|
||||
|
||||
var root = _xmlService.GetRoot(id);
|
||||
if (root == null) return error404();
|
||||
|
||||
|
||||
var model = new UploadViewModel(root.Type, id, roots, usedFiles);
|
||||
model.ProductionFiles = productionFiles;
|
||||
model.HamannFiles = hamannFiles;
|
||||
model.AvailableFiles = XMLFileHelpers.ToFileModel(_xmlProvider.GetFiles(id), pF, uF);
|
||||
|
||||
|
||||
return View("../Admin/Upload/Index", model);
|
||||
}
|
||||
else {
|
||||
var model = new UploadViewModel("Upload", id, roots, usedFiles);
|
||||
} else {
|
||||
var model = new UploadViewModel("Upload & Veröffentlichen", id, roots, usedFiles);
|
||||
model.ProductionFiles = productionFiles;
|
||||
model.HamannFiles = hamannFiles;
|
||||
|
||||
|
||||
@@ -15,15 +15,13 @@ public class HaDocumentWrapper : IHaDocumentWrappper {
|
||||
|
||||
_startYear = configuration.GetValue<int>("AvailableStartYear");
|
||||
_endYear = configuration.GetValue<int>("AvailableEndYear");
|
||||
|
||||
var filelist = xmlProvider.GetHamannFiles();
|
||||
if (filelist != null && filelist.Any())
|
||||
if (filelist != null && filelist.Any()) {
|
||||
_AutoLoad(filelist);
|
||||
|
||||
}
|
||||
// Use Fallback library
|
||||
if (Library == null)
|
||||
if (Library == null)
|
||||
Library = HaDocument.Document.Create(new HaWeb.Settings.HaDocumentOptions() { AvailableYearRange = (_startYear, _endYear) });
|
||||
|
||||
}
|
||||
|
||||
public ILibrary ResetLibrary() {
|
||||
@@ -38,6 +36,7 @@ public class HaDocumentWrapper : IHaDocumentWrappper {
|
||||
}
|
||||
catch (Exception ex) {
|
||||
if (ModelState != null) ModelState.AddModelError("Error:", "Das Dokument konnte nicht geparst werden: " + ex.Message);
|
||||
Console.WriteLine(ex.Message);
|
||||
return null;
|
||||
}
|
||||
return Library;
|
||||
@@ -50,7 +49,10 @@ public class HaDocumentWrapper : IHaDocumentWrappper {
|
||||
private void _AutoLoad(List<IFileInfo> files) {
|
||||
var orderdlist = files.OrderByDescending(x => x.LastModified);
|
||||
foreach(var item in orderdlist) {
|
||||
if (SetLibrary(item.PhysicalPath) != null) return;
|
||||
if (SetLibrary(item.PhysicalPath) != null) {
|
||||
_xmlProvider.SetInProduction(item);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,4 +10,6 @@ public interface IXMLProvider {
|
||||
public Task Save(XMLRootDocument doc, string basefilepath, ModelStateDictionary ModelState);
|
||||
public Task<IFileInfo?> SaveHamannFile(XElement element, string basefilepath, ModelStateDictionary ModelState);
|
||||
public List<IFileInfo>? GetHamannFiles();
|
||||
public IFileInfo? GetInProduction();
|
||||
public void SetInProduction(IFileInfo info);
|
||||
}
|
||||
@@ -12,6 +12,7 @@ using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||
using Microsoft.AspNetCore.WebUtilities;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
using HaWeb.Models;
|
||||
using System.Text;
|
||||
|
||||
public static class XMLFileHelpers {
|
||||
// File Signatures Database (https://www.filesignatures.net/)
|
||||
@@ -199,6 +200,20 @@ public static class XMLFileHelpers {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static string? StreamToString(System.IO.Stream stream, ModelStateDictionary modelState) {
|
||||
string? ret = null;
|
||||
try {
|
||||
using (var rd = new StreamReader(stream, Encoding.UTF8)) {
|
||||
ret = rd.ReadToEnd();
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
catch (Exception ex) {
|
||||
modelState.AddModelError("Error", "Reading of the message failed with " + ex.Message);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsValidFileExtensionAndSignature(string fileName, Stream data, string[] permittedExtensions) {
|
||||
if (string.IsNullOrEmpty(fileName) || data == null || data.Length == 0)
|
||||
return false;
|
||||
|
||||
@@ -17,7 +17,7 @@ public class XMLProvider : IXMLProvider {
|
||||
_Roots = xmlservice.GetRootsDictionary();
|
||||
_Files = _ScanFiles();
|
||||
_HamannFiles = _ScanHamannFiles();
|
||||
|
||||
|
||||
if (_Files != null)
|
||||
foreach(var category in _Files)
|
||||
if (category.Value != null)
|
||||
@@ -26,6 +26,10 @@ public class XMLProvider : IXMLProvider {
|
||||
|
||||
public List<IFileInfo>? GetHamannFiles() => this._HamannFiles;
|
||||
|
||||
public IFileInfo? GetInProduction() => this._InProduction;
|
||||
|
||||
public void SetInProduction(IFileInfo info) => _InProduction = info;
|
||||
|
||||
public FileList? GetFiles(string prefix)
|
||||
=> _Files != null && _Files.ContainsKey(prefix) ? _Files[prefix] : null;
|
||||
|
||||
@@ -83,6 +87,7 @@ public class XMLProvider : IXMLProvider {
|
||||
}
|
||||
|
||||
if (_HamannFiles == null) _HamannFiles = new List<IFileInfo>();
|
||||
_HamannFiles.RemoveAll(x => x.Name == info.Name);
|
||||
_HamannFiles.Add(info);
|
||||
_InProduction = info;
|
||||
return info;
|
||||
|
||||
@@ -8,10 +8,10 @@ public class FileModel {
|
||||
public bool InProduction { get; private set; }
|
||||
public List<(string, string?)>? Fields { get; set; }
|
||||
|
||||
public FileModel(string name, string prefix, DateTime lastModified, bool isUSed, bool inProduction) {
|
||||
public FileModel(string name, string prefix, DateTime lastModified, bool isUsed, bool inProduction) {
|
||||
FileName = name;
|
||||
IsUsed = IsUsed;
|
||||
IsUsed = isUsed;
|
||||
LastModified = lastModified;
|
||||
InProduction = InProduction;
|
||||
InProduction = inProduction;
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@ public class UploadViewModel {
|
||||
public Dictionary<string, List<FileModel>?>? UsedFiles { get; private set; }
|
||||
public Dictionary<string, List<FileModel>?>? ProductionFiles { get; set; }
|
||||
|
||||
public List<(string, DateTime)>? HamannFiles { get; set; }
|
||||
public List<FileModel>? HamannFiles { get; set; }
|
||||
|
||||
public UploadViewModel(string title, string? prefix, List<IXMLRoot>? roots, Dictionary<string, List<FileModel>?>? usedFiles) {
|
||||
Prefix = prefix;
|
||||
|
||||
@@ -30,10 +30,10 @@ if (filepath == null) {
|
||||
var physicalProvider = new PhysicalFileProvider(filepath);
|
||||
|
||||
builder.Services.AddSingleton<IFileProvider>(physicalProvider);
|
||||
builder.Services.AddSingleton<HaWeb.FileHelpers.IHaDocumentWrappper, HaWeb.FileHelpers.HaDocumentWrapper>();
|
||||
builder.Services.AddTransient<IReaderService, ReaderService>();
|
||||
builder.Services.AddSingleton<IXMLProvider, XMLProvider>();
|
||||
builder.Services.AddSingleton<IXMLService, XMLService>();
|
||||
builder.Services.AddSingleton<HaWeb.FileHelpers.IHaDocumentWrappper, HaWeb.FileHelpers.HaDocumentWrapper>();
|
||||
builder.Services.AddFeatureManagement();
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
</label>
|
||||
<div class="ha-publishmessage" id="ha-publishmessage">
|
||||
@* Fehler!<br/> *@
|
||||
<output form="uploadForm" name="publish-result"></output>
|
||||
<output form="uploadForm" name="publish-result" id="publish-result"></output>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
@@ -52,31 +52,42 @@
|
||||
|
||||
<div class="ha-uploadheader">
|
||||
<h1 class="ha-uploadtitle">@Model.ActiveTitle</h1>
|
||||
|
||||
@if (Model.Prefix != null) {
|
||||
<div class="ha-usedfilesheader">
|
||||
<div class="ha-usedfilesheaderlist">
|
||||
@if(Model.UsedFiles != null && Model.UsedFiles.ContainsKey(Model.Prefix)) {
|
||||
@foreach (var item in Model.UsedFiles[Model.Prefix]!)
|
||||
{
|
||||
<div class="ha-usedfilesheaderfile">@item.FileName</div>
|
||||
}
|
||||
}
|
||||
else {
|
||||
<div class="ha-usedfilesnone">Keine Datei geladen</div>
|
||||
}
|
||||
@if (Model.AvailableFiles != null)
|
||||
{
|
||||
<div class="ha-availablefilechooser"><div class="ha-plussign"></div><a class="ha-loadotherfilesbtn">Andere Dateien laden...</a></div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
</div>
|
||||
|
||||
<div class="ha-uploadcontainer">
|
||||
@* File Category Page File List *@
|
||||
@if (Model.AvailableFiles != null && Model.AvailableFiles.Any()) {
|
||||
<div class="ha-filesheader">
|
||||
<div class="ha-availablefiles" id="ha-availablefiles">
|
||||
<div class="ha-availablefilestitle">Datei(en)</div>
|
||||
@if(Model.UsedFiles != null && Model.UsedFiles.ContainsKey(Model.Prefix)) {
|
||||
<div class="ha-usedfilelist">
|
||||
@foreach (var item in Model.UsedFiles[Model.Prefix]!)
|
||||
{
|
||||
if(item == Model.UsedFiles[Model.Prefix]!.Last()) {
|
||||
<span class="ha-usedfile">@item.FileName</span>
|
||||
}
|
||||
else {
|
||||
<span class="ha-usedfile">@item.FileName,</span>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<div class="ha-availablefileslist hidden" id="ha-availablefileslist">
|
||||
@await Html.PartialAsync("/Views/Shared/_FileList.cshtml", (Model.AvailableFiles, "Verfügbare Dateien:", "API", "SetUsed", Model.Prefix, "/Download/XML/" + Model.Prefix + "/", true))
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
@* Start Page File List *@
|
||||
else {
|
||||
<div class="ha-hamannfilechooser">
|
||||
@await Html.PartialAsync("/Views/Shared/_FileList.cshtml", (Model.HamannFiles, "Verfügbare Hamann-Dateien", "API", "SetUsedHamann", string.Empty, "/Download/XML/", false))
|
||||
</div>
|
||||
}
|
||||
|
||||
@* File Category Page Syntax Check *@
|
||||
@if (Model.UsedFiles != null && Model.Prefix != null && Model.UsedFiles.ContainsKey(Model.Prefix)) {
|
||||
<div class="ha-errorswarnings">
|
||||
<div class="ha-criticalerrors">
|
||||
@@ -92,17 +103,25 @@
|
||||
</div>
|
||||
}
|
||||
|
||||
else {
|
||||
<form class="ha-selecthamannfilesform" id="selecthamannfilesform" asp-controller="API" asp-action="SetUsedHamann" method="post" enctype="multipart/form-data">
|
||||
|
||||
</form>
|
||||
}
|
||||
|
||||
</div>
|
||||
|
||||
@section Scripts {
|
||||
<script>
|
||||
"use strict";
|
||||
const hideshowfiles = function() {
|
||||
let elem = document.getElementById("ha-availablefileslist");
|
||||
console.log("hello!");
|
||||
if (elem.classList.contains('hidden')) {
|
||||
|
||||
elem.classList.remove('hidden');
|
||||
elem.classList.add('block');
|
||||
}
|
||||
else {
|
||||
elem.classList.add('hidden');
|
||||
elem.classList.remove('block');
|
||||
}
|
||||
}
|
||||
|
||||
const dropHandler = function (formelement, ev, dropzone) {
|
||||
ev.preventDefault();
|
||||
if (ev.dataTransfer.items) {
|
||||
@@ -145,18 +164,19 @@ else {
|
||||
document.getElementById("ha-publishfilelabel").style.pointerEvents = "auto";
|
||||
document.getElementById("ha-lds-ellipsis-publish").style.display = "none";
|
||||
document.getElementById("ha-publishmessage").style.opacity = "1";
|
||||
oFormElement.elements.namedItem("update-result").value = json.Error;
|
||||
document.getElementById("publish-result").value = json.Error;
|
||||
} else {
|
||||
document.getElementById("ha-publishfilelabel").style.pointerEvents = "auto";
|
||||
document.getElementById("ha-lds-ellipsis-publish").style.display = "none";
|
||||
document.getElementById("ha-publishmessage").style.opacity = "1";
|
||||
oFormElement.elements.namedItem("update-result").value = "Erfolg!";
|
||||
document.getElementById("publish-result").value = "Erfolg!";
|
||||
window.location.replace("/Admin/Upload/");
|
||||
}
|
||||
})
|
||||
.catch ((e) => {
|
||||
document.getElementById("ha-publishfilelabel").style.pointerEvents = "auto";
|
||||
document.getElementById("ha-lds-ellipsis-publish").style.display = "none";
|
||||
console.log('Error:', e);
|
||||
document.getElementById("publish-result").value = "Keine Antwort. Bitte Seite neu laden!";
|
||||
})
|
||||
}
|
||||
|
||||
@@ -212,6 +232,9 @@ else {
|
||||
var dropzone = document.getElementById("dropzone");
|
||||
var publishelement = document.getElementById("ha-publishform");
|
||||
var publishbutton = document.getElementById("ha-publishfilelabel");
|
||||
var filesbutton = document.getElementById("ha-availablefiles");
|
||||
if (filesbutton !== null)
|
||||
filesbutton.addEventListener("click", () => hideshowfiles());
|
||||
publishbutton.addEventListener("click", () => LOCALPUBLISHSubmit(publishelement));
|
||||
submitelement.addEventListener("change", () => UPLOADSubmit(formelement));
|
||||
dropzone.addEventListener("drop", (ev) => dropHandler(formelement, ev, dropzone));
|
||||
|
||||
71
HaWeb/Views/Shared/_FileList.cshtml
Normal file
71
HaWeb/Views/Shared/_FileList.cshtml
Normal file
@@ -0,0 +1,71 @@
|
||||
@model (List<FileModel>? files, string title, string aspcontrolller, string aspaction, string id, string downloadprefix, bool multipleallowed);
|
||||
|
||||
<fieldset class="ha-filelistfieldset">
|
||||
<legend class="ha-filelistlegend">@Model.title</legend>
|
||||
@if(Model.files != null && Model.files.Any()) {
|
||||
<form class="ha-selectfilesform" id="selecthamannfilesform" asp-controller="@Model.aspcontrolller" asp-action="@Model.aspaction" asp-route-id="@Model.id" method="post" onsubmit="USESubmit(this);return false;" enctype="multipart/form-data">
|
||||
<div class="ha-filelistlist">
|
||||
@foreach (var file in Model.files.OrderByDescending(x => x.LastModified)) {
|
||||
<div class="ha-filelistfile">
|
||||
@if (Model.multipleallowed) {
|
||||
<input type="checkbox" id="@file.FileName" name="file" value="@file.FileName" @(file.IsUsed ? "checked='checked'" : "")>
|
||||
}
|
||||
else {
|
||||
<input type="radio" id="@file.FileName" name="file" value="@file.FileName" @(file.InProduction ? "checked='checked'" : "")>
|
||||
}
|
||||
<div class="ha-filelistname">@file.FileName</div>
|
||||
@if (file.InProduction || file.IsUsed) {
|
||||
<div class="ha-filelistusedproduction">
|
||||
@if (file.InProduction) {
|
||||
<div class="ha-filelistproduction">in Verwendung</div>
|
||||
}
|
||||
@if (file.IsUsed) {
|
||||
<div class="ha-filelistused">geladen</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
@if (file.Fields != null && file.Fields.Any()) {
|
||||
<div class="ha-filelistfields">
|
||||
@foreach (var field in file.Fields) {
|
||||
@if (field.Item2 != null) {
|
||||
<div class="ha-filelistfield">field.Item2</div>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
}
|
||||
<div class="ha-filelistmodified">@file.LastModified</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<input class="btn ha-filelistbutton" type="submit" value="Laden" />
|
||||
</form>
|
||||
}
|
||||
else {
|
||||
<div>Keine Hamann-Dateien gefunden! Es wird eine fallback-Datei verwendet!</div>
|
||||
}
|
||||
</fieldset>
|
||||
|
||||
<script>
|
||||
const USESubmit = async function (oFormElement, file = null) {
|
||||
let fd = new FormData(oFormElement);
|
||||
await fetch(oFormElement.action, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'RequestVerificationToken': getCookie('RequestVerificationToken')
|
||||
},
|
||||
body: fd
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(json => {
|
||||
if ("Error" in json) {
|
||||
|
||||
}
|
||||
else {
|
||||
location.reload();
|
||||
}
|
||||
})
|
||||
.catch ((e) => {
|
||||
location.reload();
|
||||
})
|
||||
}
|
||||
</script>
|
||||
@@ -14,4 +14,6 @@ public interface IXMLService {
|
||||
public void AutoUse(string prefix);
|
||||
public void AutoUse(FileList filelist);
|
||||
public Dictionary<string, FileList?>? GetInProduction();
|
||||
public void UnUse(string prefix);
|
||||
public void UnUseProduction();
|
||||
}
|
||||
@@ -34,6 +34,8 @@ public class XMLService : IXMLService {
|
||||
|
||||
public Dictionary<string, FileList?>? GetInProduction() => this._InProduction;
|
||||
|
||||
public void UnUseProduction() => this._InProduction = null;
|
||||
|
||||
public List<XMLRootDocument>? ProbeHamannFile(XDocument document, ModelStateDictionary ModelState) {
|
||||
if (document.Root!.Name != "opus") {
|
||||
ModelState.AddModelError("Error", "A valid Hamann-Docuemnt must begin with <opus>");
|
||||
@@ -66,6 +68,11 @@ public class XMLService : IXMLService {
|
||||
_Used[doc.Prefix]!.Add(doc);
|
||||
}
|
||||
|
||||
public void UnUse(string prefix) {
|
||||
if (_Used != null && _Used.ContainsKey(prefix)) _Used.Remove(prefix);
|
||||
return;
|
||||
}
|
||||
|
||||
// Performs detection of using on the specified document type
|
||||
public void AutoUse(string prefix) {
|
||||
if (_Used == null || !_Used.ContainsKey(prefix)) return;
|
||||
|
||||
@@ -19,6 +19,7 @@ module.exports = {
|
||||
sans: ['Biolinum', 'sans-serif'],
|
||||
serif: ['Libertine', 'serif'],
|
||||
classy: ['Playfair', 'serif'],
|
||||
mono: ['ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace', 'mono']
|
||||
},
|
||||
screens: {
|
||||
'sm': '700px',
|
||||
|
||||
@@ -123,7 +123,7 @@ code,
|
||||
kbd,
|
||||
samp,
|
||||
pre {
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace, mono;
|
||||
/* 1 */
|
||||
font-size: 1em;
|
||||
/* 2 */
|
||||
@@ -478,6 +478,8 @@ Ensure the default browser behavior of the `hidden` attribute.
|
||||
|
||||
/* TODO: check what can be inlined (eg. used once in the code, has no double paths etc...) */
|
||||
|
||||
/* TODO: Copy color classes for all thing upload to colors on top */
|
||||
|
||||
/* Everything related to theme color */
|
||||
|
||||
body {
|
||||
@@ -1868,8 +1870,8 @@ body {
|
||||
.ha-adminuploadfields .ha-uploadfield.active {
|
||||
--tw-text-opacity: 1 !important;
|
||||
color: rgb(0 0 0 / var(--tw-text-opacity)) !important;
|
||||
--tw-shadow-color: #fee2e2;
|
||||
--tw-shadow: var(--tw-shadow-colored);
|
||||
--tw-brightness: brightness(1.1);
|
||||
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
|
||||
}
|
||||
|
||||
.ha-adminuploadfields .ha-uploadfield .ha-uploadfieldname {
|
||||
@@ -2022,46 +2024,6 @@ body {
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.ha-uploadheader .ha-usedfilesheader {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.ha-uploadheader .ha-usedfilesheaderlist {
|
||||
margin-left: 1.5rem;
|
||||
margin-bottom: 0.25rem;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
align-content: flex-end;
|
||||
-moz-column-gap: 0.5rem;
|
||||
column-gap: 0.5rem;
|
||||
row-gap: 0.25rem;
|
||||
align-self: flex-end;
|
||||
}
|
||||
|
||||
.ha-uploadheader .ha-usedfilesheaderlist .ha-usedfilesheaderfile {
|
||||
border-radius: 0.25rem;
|
||||
background-color: rgb(51 65 85 / var(--tw-bg-opacity));
|
||||
--tw-bg-opacity: 0.3;
|
||||
padding-left: 0.5rem;
|
||||
padding-right: 0.5rem;
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.25rem;
|
||||
}
|
||||
|
||||
.ha-uploadheader .ha-usedfilesheaderlist .ha-availablefilechooser {
|
||||
border-radius: 0.25rem;
|
||||
background-color: rgb(51 65 85 / var(--tw-bg-opacity));
|
||||
--tw-bg-opacity: 0.5;
|
||||
padding-right: 0.25rem;
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.25rem;
|
||||
}
|
||||
|
||||
.ha-uploadheader .ha-usedfilesheaderlist .ha-availablefilechooser .ha-loadotherfilesbtn {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.ha-uploadcontainer {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
@@ -2072,6 +2034,40 @@ body {
|
||||
background-color: rgb(248 250 252 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.ha-uploadcontainer .ha-availablefiles {
|
||||
cursor: pointer;
|
||||
border-width: 1px;
|
||||
--tw-border-opacity: 1;
|
||||
border-color: rgb(226 232 240 / var(--tw-border-opacity));
|
||||
padding-left: 4rem;
|
||||
padding-right: 4rem;
|
||||
padding-top: 0.5rem;
|
||||
padding-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.ha-uploadcontainer .ha-availablefiles:hover {
|
||||
--tw-border-opacity: 1;
|
||||
border-color: rgb(30 41 59 / var(--tw-border-opacity));
|
||||
}
|
||||
|
||||
.ha-uploadcontainer .ha-availablefiles .ha-availablefilestitle {
|
||||
font-size: 1.5rem;
|
||||
line-height: 2rem;
|
||||
}
|
||||
|
||||
.ha-uploadcontainer .ha-availablefiles .ha-usedfilelist {
|
||||
}
|
||||
|
||||
.ha-filesheader {
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.ha-availablefileslist {
|
||||
padding-left: 4rem;
|
||||
padding-right: 4rem;
|
||||
padding-top: 1rem;
|
||||
}
|
||||
|
||||
.ha-uploadcontainer .ha-errorswarnings {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
@@ -2109,6 +2105,98 @@ body {
|
||||
background-color: rgb(165 243 252 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.ha-uploadcontainer .ha-hamannfilechooser {
|
||||
padding-left: 4rem;
|
||||
padding-right: 4rem;
|
||||
padding-bottom: 4rem;
|
||||
}
|
||||
|
||||
/* Classes for FileList Component */
|
||||
|
||||
.ha-filelistfieldset {
|
||||
}
|
||||
|
||||
.ha-filelistfieldset .ha-filelistlegend {
|
||||
margin-bottom: 0.5rem;
|
||||
font-size: 1.25rem;
|
||||
line-height: 1.75rem;
|
||||
}
|
||||
|
||||
.ha-selectfilesform {
|
||||
}
|
||||
|
||||
.ha-selectfilesform .ha-filelistfile {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
-moz-column-gap: 1rem;
|
||||
column-gap: 1rem;
|
||||
}
|
||||
|
||||
.ha-selectfilesform .ha-filelistlist {
|
||||
height: 24rem;
|
||||
overflow-x: hidden;
|
||||
overflow-y: scroll;
|
||||
padding-right: 1rem;
|
||||
}
|
||||
|
||||
.ha-selectfilesform .ha-filelistfile .ha-filelistname {
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace, mono;
|
||||
}
|
||||
|
||||
.ha-selectfilesform .ha-filelistfile .ha-filelistusedproduction {
|
||||
align-self: flex-start;
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.25rem;
|
||||
}
|
||||
|
||||
.ha-selectfilesform .ha-filelistfile .ha-filelistusedproduction .ha-filelistproduction {
|
||||
margin-right: 0.5rem;
|
||||
display: inline-block;
|
||||
border-radius: 0.375rem;
|
||||
border-width: 1px;
|
||||
--tw-border-opacity: 1;
|
||||
border-color: rgb(13 148 136 / var(--tw-border-opacity));
|
||||
padding-left: 0.5rem;
|
||||
padding-right: 0.5rem;
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(13 148 136 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.ha-selectfilesform .ha-filelistfile .ha-filelistusedproduction .ha-filelistused {
|
||||
display: inline-block;
|
||||
border-radius: 0.375rem;
|
||||
border-width: 1px;
|
||||
--tw-border-opacity: 1;
|
||||
border-color: rgb(79 70 229 / var(--tw-border-opacity));
|
||||
padding-left: 0.5rem;
|
||||
padding-right: 0.5rem;
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(79 70 229 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.ha-selectfilesform .ha-filelistfile .ha-filelistmodified {
|
||||
flex-grow: 1;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.ha-selectfilesform .ha-filelistbutton {
|
||||
float: right;
|
||||
margin-top: 0.5rem;
|
||||
margin-left: 1.5rem;
|
||||
cursor: pointer;
|
||||
border-radius: 0.375rem;
|
||||
border-width: 2px;
|
||||
--tw-border-opacity: 1;
|
||||
border-color: rgb(29 78 216 / var(--tw-border-opacity));
|
||||
padding-left: 0.75rem;
|
||||
padding-right: 0.75rem;
|
||||
}
|
||||
|
||||
.ha-selectfilesform .ha-filelistbutton:hover {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(147 197 253 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
/* Classes for Letter View */
|
||||
|
||||
.ha-letterheader {
|
||||
@@ -3055,6 +3143,10 @@ body {
|
||||
margin-right: 0px !important;
|
||||
}
|
||||
|
||||
.block {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.inline-block {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
@@ -84,6 +84,7 @@
|
||||
@apply transition-colors duration-100
|
||||
}
|
||||
/* TODO: check what can be inlined (eg. used once in the code, has no double paths etc...) */
|
||||
/* TODO: Copy color classes for all thing upload to colors on top */
|
||||
|
||||
/* Everything related to theme color */
|
||||
body {
|
||||
@@ -678,7 +679,7 @@
|
||||
}
|
||||
|
||||
.ha-adminuploadfields .ha-uploadfield.active {
|
||||
@apply !text-black shadow-red-100
|
||||
@apply !text-black brightness-110
|
||||
}
|
||||
|
||||
.ha-adminuploadfields .ha-uploadfield .ha-uploadfieldname {
|
||||
@@ -745,30 +746,30 @@
|
||||
@apply text-5xl
|
||||
}
|
||||
|
||||
.ha-uploadheader .ha-usedfilesheader {
|
||||
@apply flex
|
||||
}
|
||||
|
||||
.ha-uploadheader .ha-usedfilesheaderlist {
|
||||
@apply flex flex-row flex-wrap ml-6 gap-x-2 gap-y-1 self-end content-end mb-1
|
||||
}
|
||||
|
||||
.ha-uploadheader .ha-usedfilesheaderlist .ha-usedfilesheaderfile {
|
||||
@apply text-sm px-2 bg-slate-700 bg-opacity-30 rounded
|
||||
}
|
||||
|
||||
.ha-uploadheader .ha-usedfilesheaderlist .ha-availablefilechooser {
|
||||
@apply text-sm pr-1 bg-slate-700 bg-opacity-50 rounded
|
||||
}
|
||||
|
||||
.ha-uploadheader .ha-usedfilesheaderlist .ha-availablefilechooser .ha-loadotherfilesbtn {
|
||||
@apply inline-block
|
||||
}
|
||||
|
||||
.ha-uploadcontainer {
|
||||
@apply w-full bg-slate-50 flex flex-col gap-y-2 h-full
|
||||
}
|
||||
|
||||
.ha-uploadcontainer .ha-availablefiles {
|
||||
@apply px-16 border border-slate-200 hover:border-slate-800 py-2 cursor-pointer
|
||||
}
|
||||
|
||||
.ha-uploadcontainer .ha-availablefiles .ha-availablefilestitle {
|
||||
@apply text-2xl
|
||||
}
|
||||
|
||||
.ha-uploadcontainer .ha-availablefiles .ha-usedfilelist {
|
||||
|
||||
}
|
||||
|
||||
.ha-filesheader {
|
||||
@apply mb-8
|
||||
}
|
||||
|
||||
.ha-availablefileslist {
|
||||
@apply px-16 pt-4
|
||||
}
|
||||
|
||||
.ha-uploadcontainer .ha-errorswarnings {
|
||||
@apply flex flex-row gap-x-2
|
||||
}
|
||||
@@ -790,6 +791,55 @@
|
||||
@apply w-full bg-cyan-200 grow shrink-0 h-full min-h-[400px]
|
||||
}
|
||||
|
||||
.ha-uploadcontainer .ha-hamannfilechooser {
|
||||
@apply px-16 pb-16
|
||||
}
|
||||
|
||||
/* Classes for FileList Component */
|
||||
.ha-filelistfieldset {
|
||||
|
||||
}
|
||||
|
||||
.ha-filelistfieldset .ha-filelistlegend {
|
||||
@apply mb-2 text-xl
|
||||
}
|
||||
|
||||
.ha-selectfilesform {
|
||||
|
||||
}
|
||||
|
||||
.ha-selectfilesform .ha-filelistfile {
|
||||
@apply flex flex-row gap-x-4
|
||||
}
|
||||
|
||||
.ha-selectfilesform .ha-filelistlist {
|
||||
@apply h-96 overflow-x-hidden overflow-y-scroll pr-4
|
||||
}
|
||||
|
||||
.ha-selectfilesform .ha-filelistfile .ha-filelistname {
|
||||
@apply font-mono
|
||||
}
|
||||
|
||||
.ha-selectfilesform .ha-filelistfile .ha-filelistusedproduction {
|
||||
@apply text-sm self-start
|
||||
}
|
||||
|
||||
.ha-selectfilesform .ha-filelistfile .ha-filelistusedproduction .ha-filelistproduction {
|
||||
@apply inline-block border rounded-md text-teal-600 border-teal-600 px-2 mr-2
|
||||
}
|
||||
|
||||
.ha-selectfilesform .ha-filelistfile .ha-filelistusedproduction .ha-filelistused {
|
||||
@apply inline-block border rounded-md text-indigo-600 border-indigo-600 px-2
|
||||
}
|
||||
|
||||
.ha-selectfilesform .ha-filelistfile .ha-filelistmodified {
|
||||
@apply grow text-right
|
||||
}
|
||||
|
||||
.ha-selectfilesform .ha-filelistbutton {
|
||||
@apply mt-2 ml-6 rounded-md px-3 border-2 border-blue-700 hover:bg-blue-300 cursor-pointer float-right;
|
||||
}
|
||||
|
||||
/* Classes for Letter View */
|
||||
|
||||
.ha-letterheader {
|
||||
|
||||
Reference in New Issue
Block a user