mirror of
				https://github.com/Theodor-Springmann-Stiftung/hamann-ausgabe-core.git
				synced 2025-10-30 09:45:32 +00:00 
			
		
		
		
	Created FileList with ability to set used files
This commit is contained in:
		
							
								
								
									
										5
									
								
								HaDocumentNew/Document.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								HaDocumentNew/Document.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | |||||||
|  | namespace HaDocument; | ||||||
|  | public class Document | ||||||
|  | { | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										9
									
								
								HaDocumentNew/HaDocumentNew.csproj
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								HaDocumentNew/HaDocumentNew.csproj
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | |||||||
|  | <Project Sdk="Microsoft.NET.Sdk"> | ||||||
|  |  | ||||||
|  |   <PropertyGroup> | ||||||
|  |     <TargetFramework>net6.0</TargetFramework> | ||||||
|  |     <ImplicitUsings>enable</ImplicitUsings> | ||||||
|  |     <Nullable>enable</Nullable> | ||||||
|  |   </PropertyGroup> | ||||||
|  |  | ||||||
|  | </Project> | ||||||
							
								
								
									
										5
									
								
								HaDocumentNew/Interfaces/IDocument.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								HaDocumentNew/Interfaces/IDocument.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | |||||||
|  | namespace HaDocument.Interfaces; | ||||||
|  |  | ||||||
|  | public interface IDocument { | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										0
									
								
								HaDocumentNew/Interfaces/IDocumentSyntaxErrors.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								HaDocumentNew/Interfaces/IDocumentSyntaxErrors.cs
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										8
									
								
								HaDocumentNew/Interfaces/IHaDocumentOptions.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								HaDocumentNew/Interfaces/IHaDocumentOptions.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | |||||||
|  | namespace HaDocument.Interfaces; | ||||||
|  |  | ||||||
|  | public interface IHaDocumentOptions { | ||||||
|  |     string HamannXMLFilePath { get; set; } | ||||||
|  |     string[] AvailableVolumes { get; set; } | ||||||
|  |     bool NormalizeWhitespace { get; set; } | ||||||
|  |     (int, int) AvailableYearRange { get; set; } | ||||||
|  | } | ||||||
							
								
								
									
										29
									
								
								HaDocumentNew/Interfaces/ILibrary.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								HaDocumentNew/Interfaces/ILibrary.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | |||||||
|  | namespace HaDocument.Interfaces;  | ||||||
|  | using System; | ||||||
|  | using System.Collections.Immutable; | ||||||
|  | using HaDocument.Models; | ||||||
|  | using System.Linq; | ||||||
|  |  | ||||||
|  | public interface ILibrary { | ||||||
|  |     IHaDocumentOptions Options { get; } | ||||||
|  |     ImmutableDictionary<string, Tradition> Traditions { get; } | ||||||
|  |     ImmutableDictionary<string, Person> Persons { get; } | ||||||
|  |     ImmutableDictionary<string, Meta> Metas { get; } | ||||||
|  |     ImmutableDictionary<string, Marginal> Marginals { get; } | ||||||
|  |     ImmutableDictionary<string, Location> Locations { get; } | ||||||
|  |     ImmutableDictionary<string, Letter> Letters { get; } | ||||||
|  |     ImmutableDictionary<string, Person> HandPersons { get; } | ||||||
|  |     ImmutableDictionary<string, Editreason> Editreasons { get; } | ||||||
|  |     ImmutableDictionary<string, Comment> Comments { get; } | ||||||
|  |     ImmutableDictionary<string, ImmutableList<Backlink>> Backlinks { get; } | ||||||
|  |     ImmutableDictionary<string, ImmutableList<Hand>> Hands { get; } | ||||||
|  |     ImmutableDictionary<string, ImmutableDictionary<string, ImmutableDictionary<string, string>>> Structure { get; } | ||||||
|  |      | ||||||
|  |     ImmutableDictionary<string, Lookup<string, Comment>> CommentsByCategoryLetter { get; } | ||||||
|  |     Lookup<string, Comment> CommentsByCategory { get; } | ||||||
|  |     Lookup<string, Marginal> MarginalsByLetter { get; } | ||||||
|  |     Lookup<string, Editreason> EditreasonsByLetter { get; } | ||||||
|  |     ImmutableSortedSet<Meta> MetasByDate { get; } | ||||||
|  |     ILookup<string, Meta> MetasByYear { get; } | ||||||
|  |     ImmutableDictionary<string, Comment> SubCommentsByID { get; } | ||||||
|  | } | ||||||
							
								
								
									
										24
									
								
								HaDocumentNew/Models/Backlink.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								HaDocumentNew/Models/Backlink.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | |||||||
|  | namespace HaDocument.Models { | ||||||
|  |     public class Backlink { | ||||||
|  |         public string Index { get; } = ""; | ||||||
|  |  | ||||||
|  |         public string Letter { get; } = ""; | ||||||
|  |         public string Page { get; } = ""; | ||||||
|  |         public string Line { get; } = ""; | ||||||
|  |         public string MarginalIndex { get; } = ""; | ||||||
|  |  | ||||||
|  |         public Backlink( | ||||||
|  |             string index, | ||||||
|  |             string letter, | ||||||
|  |             string page, | ||||||
|  |             string line, | ||||||
|  |             string marginalindex | ||||||
|  |         ) { | ||||||
|  |             Index = index; | ||||||
|  |             Letter = letter; | ||||||
|  |             Page = page; | ||||||
|  |             Line = line; | ||||||
|  |             MarginalIndex = marginalindex; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										36
									
								
								HaDocumentNew/Models/Comment.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								HaDocumentNew/Models/Comment.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | |||||||
|  | using System; | ||||||
|  | using System.Collections.Generic; | ||||||
|  | using System.Collections.Immutable; | ||||||
|  |  | ||||||
|  | namespace HaDocument.Models { | ||||||
|  |     public class Comment{ | ||||||
|  |         public string Entry { get; } = ""; | ||||||
|  |         public string Index { get; } = ""; | ||||||
|  |         public string Type { get; } = ""; | ||||||
|  |         public string Lemma { get; } = ""; | ||||||
|  |         public string Parent { get; } = ""; | ||||||
|  |         public int Order { get; } = -1; | ||||||
|  |         public ImmutableSortedDictionary<string, Comment> Kommentare { get; }  | ||||||
|  |  | ||||||
|  |         public Comment( | ||||||
|  |             string entry, | ||||||
|  |             string index, | ||||||
|  |             string type, | ||||||
|  |             string lemma, | ||||||
|  |             int order, | ||||||
|  |             SortedDictionary<string, Comment> subComments, | ||||||
|  |             string parent="" | ||||||
|  |         ) { | ||||||
|  |             Entry = entry; | ||||||
|  |             Index = index; | ||||||
|  |             Type = type; | ||||||
|  |             Lemma = lemma; | ||||||
|  |             Order = order; | ||||||
|  |             Parent = parent; | ||||||
|  |             if (subComments != null)  | ||||||
|  |                 Kommentare = ImmutableSortedDictionary.ToImmutableSortedDictionary(subComments); | ||||||
|  |             else | ||||||
|  |                 Kommentare = null; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										32
									
								
								HaDocumentNew/Models/Editreason.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								HaDocumentNew/Models/Editreason.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | |||||||
|  | namespace HaDocument.Models { | ||||||
|  |     public class Editreason { | ||||||
|  |         public string Index { get; } = ""; | ||||||
|  |         public string Element { get; } = ""; | ||||||
|  |         public string Letter { get; } = ""; | ||||||
|  |         public string StartPage { get; } = ""; | ||||||
|  |         public string StartLine { get; } = ""; | ||||||
|  |         public string EndPage { get; } = ""; | ||||||
|  |         public string EndLine { get; } = ""; | ||||||
|  |         public string Reference { get; } = ""; | ||||||
|  |          | ||||||
|  |         public Editreason( | ||||||
|  |             string index, | ||||||
|  |             string element, | ||||||
|  |             string letter = "", | ||||||
|  |             string startpage = "", | ||||||
|  |             string startline = "", | ||||||
|  |             string endpage = "", | ||||||
|  |             string endline = "", | ||||||
|  |             string reference = "" | ||||||
|  |         ) { | ||||||
|  |             Index = index; | ||||||
|  |             Element = element; | ||||||
|  |             Letter = letter; | ||||||
|  |             StartPage = startpage; | ||||||
|  |             StartLine = startline; | ||||||
|  |             EndPage = endpage; | ||||||
|  |             EndLine = endline; | ||||||
|  |             Reference = reference; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										15
									
								
								HaDocumentNew/Models/HaModel.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								HaDocumentNew/Models/HaModel.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | |||||||
|  | using System; | ||||||
|  | using HaXMLReader.EvArgs; | ||||||
|  | using System.Collections.Generic; | ||||||
|  |  | ||||||
|  | namespace HaDocument.Models { | ||||||
|  |     public abstract class HaModel { | ||||||
|  |         protected static List<(Func<Tag, bool>, Action<Tag>)> FieldActions = null; | ||||||
|  |  | ||||||
|  |         internal static void AddAction(Func<Tag, bool> If, Action<Tag> Then) { | ||||||
|  |             if (If == null || Then == null) throw new ArgumentNullException(); | ||||||
|  |             if (FieldActions == null) FieldActions = new List<(Func<Tag, bool>, Action<Tag>)>(); | ||||||
|  |             FieldActions.Add((If, Then)); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										26
									
								
								HaDocumentNew/Models/Hand.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								HaDocumentNew/Models/Hand.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | |||||||
|  | namespace HaDocument.Models { | ||||||
|  |     public class Hand : HaModel { | ||||||
|  |         public string Letter { get; } = ""; | ||||||
|  |         public string Person { get; } = ""; | ||||||
|  |         public string StartPage { get; } = ""; | ||||||
|  |         public string StartLine { get; } = ""; | ||||||
|  |         public string EndPage { get; } = ""; | ||||||
|  |         public string EndLine {get; } = ""; | ||||||
|  |  | ||||||
|  |         public Hand( | ||||||
|  |             string letter, | ||||||
|  |             string person, | ||||||
|  |             string startpage, | ||||||
|  |             string startline, | ||||||
|  |             string endpage, | ||||||
|  |             string endline | ||||||
|  |         ) { | ||||||
|  |             Letter = letter; | ||||||
|  |             Person = person; | ||||||
|  |             StartPage = startpage; | ||||||
|  |             StartLine = startline; | ||||||
|  |             EndPage = endpage; | ||||||
|  |             EndLine = endline; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										70
									
								
								HaDocumentNew/Models/IntermediateLibrary.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								HaDocumentNew/Models/IntermediateLibrary.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,70 @@ | |||||||
|  | using System.Collections.Generic; | ||||||
|  | using HaDocument.Interfaces; | ||||||
|  |  | ||||||
|  | namespace HaDocument.Models | ||||||
|  | { | ||||||
|  |     public class IntermediateLibrary | ||||||
|  |     { | ||||||
|  |         public Dictionary<string, Tradition> Traditions; | ||||||
|  |         public Dictionary<string, Person> Persons; | ||||||
|  |         public Dictionary<string, Meta> Metas; | ||||||
|  |         public Dictionary<string, Marginal> Marginals; | ||||||
|  |         public Dictionary<string, Location> Locations; | ||||||
|  |         public Dictionary<string, Letter> Letters; | ||||||
|  |         public Dictionary<string, Person> HandPersons; | ||||||
|  |         public Dictionary<string, Editreason> Editreasons; | ||||||
|  |         public Dictionary<string, Comment> Comments; | ||||||
|  |         public Dictionary<string, List<Backlink>> Backlinks; | ||||||
|  |         public Dictionary<string, List<Hand>> Hands; | ||||||
|  |  | ||||||
|  |         // Helper Library for precalculationg the Structure of the Document: | ||||||
|  |         public Dictionary<string, Dictionary<string, HashSet<string>>> LetterPageLines; | ||||||
|  |  | ||||||
|  |         public Library GetLibrary(IHaDocumentOptions options) | ||||||
|  |         { | ||||||
|  |             var Structure = new Dictionary<string, Dictionary<string, Dictionary<string, string>>>(); | ||||||
|  |             foreach (var letter in LetterPageLines) | ||||||
|  |             { | ||||||
|  |                 if (Metas.ContainsKey(letter.Key) && | ||||||
|  |                 Metas[letter.Key].ZH != null) | ||||||
|  |                 { | ||||||
|  |                     if (!Structure.ContainsKey(Metas[letter.Key].ZH.Volume)) | ||||||
|  |                     { | ||||||
|  |                         Structure.Add(Metas[letter.Key].ZH.Volume, new Dictionary<string, Dictionary<string, string>>()); | ||||||
|  |                     } | ||||||
|  |                     foreach (var page in letter.Value) | ||||||
|  |                     { | ||||||
|  |                         if (!Structure[Metas[letter.Key].ZH.Volume].ContainsKey(page.Key)) | ||||||
|  |                         { | ||||||
|  |                             Structure[Metas[letter.Key].ZH.Volume].Add(page.Key, new Dictionary<string, string>()); | ||||||
|  |                         } | ||||||
|  |                         foreach (var line in page.Value) | ||||||
|  |                         { | ||||||
|  |                             if (!Structure[Metas[letter.Key].ZH.Volume][page.Key].ContainsKey(line)) | ||||||
|  |                             { | ||||||
|  |                                 Structure[Metas[letter.Key].ZH.Volume][page.Key].Add(line, letter.Key); | ||||||
|  |                             } | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             return new Library( | ||||||
|  |                 Traditions, | ||||||
|  |                 Persons, | ||||||
|  |                 Metas, | ||||||
|  |                 Marginals, | ||||||
|  |                 Locations, | ||||||
|  |                 Letters, | ||||||
|  |                 HandPersons, | ||||||
|  |                 Editreasons, | ||||||
|  |                 Comments, | ||||||
|  |                 Backlinks, | ||||||
|  |                 Hands, | ||||||
|  |                 Structure, | ||||||
|  |                 options | ||||||
|  |             ); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										16
									
								
								HaDocumentNew/Models/Letter.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								HaDocumentNew/Models/Letter.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | |||||||
|  | namespace HaDocument.Models { | ||||||
|  |     public class Letter : HaModel { | ||||||
|  |         public string Index { get; } = ""; | ||||||
|  |         public string Element { get; } = ""; | ||||||
|  |         public string Value { get; } = ""; | ||||||
|  |  | ||||||
|  |         public Letter( | ||||||
|  |             string index, | ||||||
|  |             string element, | ||||||
|  |             string value | ||||||
|  |         ) { | ||||||
|  |             Index = index; | ||||||
|  |             Element = element; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										150
									
								
								HaDocumentNew/Models/Library.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										150
									
								
								HaDocumentNew/Models/Library.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,150 @@ | |||||||
|  | using System; | ||||||
|  | using HaDocument.Interfaces; | ||||||
|  | using System.Collections.Immutable; | ||||||
|  | using System.Collections.Generic; | ||||||
|  | using HaDocument.Models; | ||||||
|  | using HaDocument.Comparers; | ||||||
|  | using System.Linq; | ||||||
|  |  | ||||||
|  | namespace HaDocument.Models | ||||||
|  | { | ||||||
|  |     public class Library : ILibrary | ||||||
|  |     { | ||||||
|  |         public IHaDocumentOptions Options { get; } | ||||||
|  |         public ImmutableDictionary<string, Tradition> Traditions { get; } | ||||||
|  |         public ImmutableDictionary<string, Person> Persons { get; } | ||||||
|  |         public ImmutableDictionary<string, Meta> Metas { get; } | ||||||
|  |         public ImmutableDictionary<string, Marginal> Marginals { get; } | ||||||
|  |         public ImmutableDictionary<string, Location> Locations { get; } | ||||||
|  |         public ImmutableDictionary<string, Letter> Letters { get; } | ||||||
|  |         public ImmutableDictionary<string, Person> HandPersons { get; } | ||||||
|  |         public ImmutableDictionary<string, Editreason> Editreasons { get; } | ||||||
|  |         public ImmutableDictionary<string, Comment> Comments { get; } | ||||||
|  |         public ImmutableDictionary<string, ImmutableList<Backlink>> Backlinks { get; } | ||||||
|  |         public ImmutableDictionary<string, ImmutableList<Hand>> Hands { get; } | ||||||
|  |  | ||||||
|  |         // Structure for lookups from ZH: | ||||||
|  |         public ImmutableDictionary<string, ImmutableDictionary<string, ImmutableDictionary<string, string>>> Structure { get; } | ||||||
|  |  | ||||||
|  |         // Lookups: | ||||||
|  |         // Auswählen von Kommentaren nach (1) Kategorie, (2) Anfangsbuchstaben vom Lemma. | ||||||
|  |         // So: _ = CommentsByCategoryLetter['neuzeit']['A'] | ||||||
|  |         public ImmutableDictionary<string, Lookup<string, Comment>> CommentsByCategoryLetter { get; } | ||||||
|  |         public Lookup<string, Comment> CommentsByCategory { get; } | ||||||
|  |         // Auswählen von Subkommentaren nach ID | ||||||
|  |         public ImmutableDictionary<string, Comment> SubCommentsByID { get; } | ||||||
|  |         // Auswählen von Marginalien nach Briefen | ||||||
|  |         public Lookup<string, Marginal> MarginalsByLetter { get; } | ||||||
|  |         // Ausw?hlen von Edits nach Briefen | ||||||
|  |         public Lookup<string, Editreason> EditreasonsByLetter { get; } | ||||||
|  |         // Auswählen von Briefen nach autoptischer Numemr und in zeitlich sortierter Reihenfolge. | ||||||
|  |         public ImmutableSortedSet<Meta> MetasByDate { get; } | ||||||
|  |         // Auswählen von Briefen nach dem Jahr, sortiert nach Datum | ||||||
|  |         public ILookup<string, Meta> MetasByYear { get; } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |         public Library( | ||||||
|  |             Dictionary<string, Tradition> traditions, | ||||||
|  |             Dictionary<string, Person> persons, | ||||||
|  |             Dictionary<string, Meta> meta, | ||||||
|  |             Dictionary<string, Marginal> marginals, | ||||||
|  |             Dictionary<string, Location> locations, | ||||||
|  |             Dictionary<string, Letter> letters, | ||||||
|  |             Dictionary<string, Person> handPersons, | ||||||
|  |             Dictionary<string, Editreason> editReasons, | ||||||
|  |             Dictionary<string, Comment> comments, | ||||||
|  |             Dictionary<string, List<Backlink>> backlinks, | ||||||
|  |             Dictionary<string, List<Hand>> hands, | ||||||
|  |             Dictionary<string, Dictionary<string, Dictionary<string, string>>> Structure, | ||||||
|  |             IHaDocumentOptions options | ||||||
|  |         ) | ||||||
|  |         { | ||||||
|  |             // Dictionaries | ||||||
|  |             Traditions = ImmutableDictionary.ToImmutableDictionary(traditions); | ||||||
|  |             Persons = ImmutableDictionary.ToImmutableDictionary(persons); | ||||||
|  |             Metas = ImmutableDictionary.ToImmutableDictionary(meta); | ||||||
|  |             Marginals = ImmutableDictionary.ToImmutableDictionary(marginals); | ||||||
|  |             Locations = ImmutableDictionary.ToImmutableDictionary(locations); | ||||||
|  |             Letters = ImmutableDictionary.ToImmutableDictionary(letters); | ||||||
|  |             HandPersons = ImmutableDictionary.ToImmutableDictionary(handPersons); | ||||||
|  |             Editreasons = ImmutableDictionary.ToImmutableDictionary(editReasons); | ||||||
|  |             Comments = ImmutableDictionary.ToImmutableDictionary(comments); | ||||||
|  |  | ||||||
|  |             var backbuilder = ImmutableDictionary.CreateBuilder<string, ImmutableList<Backlink>>(); | ||||||
|  |             foreach (var entry in backlinks) | ||||||
|  |                 backbuilder.Add(entry.Key, ImmutableList.ToImmutableList(entry.Value)); | ||||||
|  |             Backlinks = backbuilder.ToImmutableDictionary(); | ||||||
|  |  | ||||||
|  |             var handbuilder = ImmutableDictionary.CreateBuilder<string, ImmutableList<Hand>>(); | ||||||
|  |             foreach (var entry in hands) | ||||||
|  |                 handbuilder.Add(entry.Key, ImmutableList.ToImmutableList(entry.Value)); | ||||||
|  |             Hands = handbuilder.ToImmutableDictionary(); | ||||||
|  |  | ||||||
|  |             // Lookups | ||||||
|  |             CommentsByCategory = (Lookup<string, Comment>)Comments.Values.ToLookup(x => x.Type); | ||||||
|  |             var CommentsByLetter_builder = ImmutableDictionary.CreateBuilder<string, Lookup<string, Comment>>(); | ||||||
|  |             foreach (var ts in CommentsByCategory) | ||||||
|  |             { | ||||||
|  |                 CommentsByLetter_builder.Add(ts.Key, (Lookup<string, Comment>)ts.ToLookup(x => x.Index.Substring(0, 1).ToUpper())); | ||||||
|  |             } | ||||||
|  |             CommentsByCategoryLetter = CommentsByLetter_builder.ToImmutableDictionary(); | ||||||
|  |             MarginalsByLetter = (Lookup<string, Marginal>)Marginals.Values.ToLookup(x => x.Letter); | ||||||
|  |             EditreasonsByLetter = (Lookup<string, Editreason>)Editreasons.Values.ToLookup(x => x.Letter); | ||||||
|  |             MetasByDate = Metas.Values.ToImmutableSortedSet<Meta>(new DefaultComparer()); | ||||||
|  |             MetasByYear = Metas.Values.ToLookup(x => x.Sort.Year.ToString()); | ||||||
|  |  | ||||||
|  |             var tempbuilder = ImmutableDictionary.CreateBuilder<string, Comment>(); | ||||||
|  |             foreach (var comm in Comments) | ||||||
|  |                 if (comm.Value.Kommentare != null) | ||||||
|  |                     foreach (var subcomm in comm.Value.Kommentare) | ||||||
|  |                         if (!tempbuilder.ContainsKey(subcomm.Key)) | ||||||
|  |                             tempbuilder.Add(subcomm.Key, subcomm.Value); | ||||||
|  |             SubCommentsByID = tempbuilder.ToImmutableDictionary(); | ||||||
|  |  | ||||||
|  |             var tempstructurebuilder = ImmutableDictionary.CreateBuilder<string, ImmutableDictionary<string, ImmutableDictionary<string, string>>>(); | ||||||
|  |             foreach (var volume in Structure) | ||||||
|  |             { | ||||||
|  |                 if (volume.Value != null) | ||||||
|  |                 { | ||||||
|  |                     var tempvolbuilder = ImmutableDictionary.CreateBuilder<string, ImmutableDictionary<string, string>>(); | ||||||
|  |                     foreach (var page in volume.Value) | ||||||
|  |                     { | ||||||
|  |                         if (page.Value != null) | ||||||
|  |                         { | ||||||
|  |                             tempvolbuilder.Add(page.Key, page.Value.ToImmutableDictionary()); | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                     if (tempvolbuilder.Any()) | ||||||
|  |                     { | ||||||
|  |                         tempstructurebuilder.Add(volume.Key, tempvolbuilder.ToImmutableDictionary()); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             this.Structure = tempstructurebuilder.ToImmutableDictionary(); | ||||||
|  |  | ||||||
|  |             Options = options; | ||||||
|  |  | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // public List<Meta> MetasByDate() { | ||||||
|  |         //     var ret = Metas.OrderBy(x => x.Value, new DefaultComparer()).ToLookup(x => x.Value.Autopsic, x => x.Value); | ||||||
|  |         //     ret.Sort(new DefaultComparer()); | ||||||
|  |         //     return ret; | ||||||
|  |         // } | ||||||
|  |  | ||||||
|  |         public ImmutableList<Meta> MetasByZH() | ||||||
|  |         { | ||||||
|  |             return Metas.Values.ToImmutableList().Sort(new Comparers.ZHComparer()); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public List<Person> PersonByAlphabet() | ||||||
|  |         { | ||||||
|  |             var ret = Persons.Values.ToList(); | ||||||
|  |             ret.Sort(new PersonComparer()); | ||||||
|  |             return ret; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										14
									
								
								HaDocumentNew/Models/Location.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								HaDocumentNew/Models/Location.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | |||||||
|  | namespace HaDocument.Models { | ||||||
|  |     public class Location { | ||||||
|  |         public string Index { get; } = ""; | ||||||
|  |         public string Name { get; } = ""; | ||||||
|  |  | ||||||
|  |         public Location( | ||||||
|  |             string index,  | ||||||
|  |             string name | ||||||
|  |         ) { | ||||||
|  |             Index = index; | ||||||
|  |             Name = name; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										23
									
								
								HaDocumentNew/Models/Marginal.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								HaDocumentNew/Models/Marginal.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | |||||||
|  | namespace HaDocument.Models { | ||||||
|  |     public class Marginal { | ||||||
|  |         public string Index { get; } = ""; | ||||||
|  |         public string Letter { get; } = ""; | ||||||
|  |         public string Page { get; } = ""; | ||||||
|  |         public string Line { get; } = ""; | ||||||
|  |         public string Element { get; } = ""; | ||||||
|  |          | ||||||
|  |         public Marginal( | ||||||
|  |             string index, | ||||||
|  |             string letter, | ||||||
|  |             string page, | ||||||
|  |             string line, | ||||||
|  |             string elemnt | ||||||
|  |         ) { | ||||||
|  |             Index = index; | ||||||
|  |             Letter = letter; | ||||||
|  |             Page = page; | ||||||
|  |             Line = line; | ||||||
|  |             Element = elemnt; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										49
									
								
								HaDocumentNew/Models/Meta.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								HaDocumentNew/Models/Meta.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,49 @@ | |||||||
|  | using System; | ||||||
|  | using System.Collections.Generic; | ||||||
|  | using HaXMLReader.EvArgs; | ||||||
|  |  | ||||||
|  | namespace HaDocument.Models { | ||||||
|  |     public class Meta { | ||||||
|  |         public string Index { get; } = ""; | ||||||
|  |         public string Autopsic { get; } = ""; | ||||||
|  |         public string Date { get; } = ""; | ||||||
|  |         public DateTime Sort { get; } = new DateTime(1700, 1, 1); | ||||||
|  |         public int Order { get; } = -1; | ||||||
|  |         public string Location { get; } = ""; | ||||||
|  |         public List<string> Senders { get; } = null; | ||||||
|  |         public List<string> Receivers { get; } = null; | ||||||
|  |         public OptionalBool hasOriginal { get; } = OptionalBool.None; | ||||||
|  |         public OptionalBool isProofread { get; } = OptionalBool.None; | ||||||
|  |         public OptionalBool isDraft { get; } = OptionalBool.None; | ||||||
|  |         public ZHInfo ZH { get; } = null; | ||||||
|  |  | ||||||
|  |         public Meta( | ||||||
|  |             string index,  | ||||||
|  |             string autopsic,  | ||||||
|  |             string date,  | ||||||
|  |             DateTime sort,  | ||||||
|  |             int order, | ||||||
|  |             OptionalBool hasOriginal, | ||||||
|  |             OptionalBool isProofread, | ||||||
|  |             OptionalBool isDraft, | ||||||
|  |             string location, | ||||||
|  |             List<string> senders, | ||||||
|  |             List<string> receivers, | ||||||
|  |             ZHInfo ZH | ||||||
|  |         ) { | ||||||
|  |             Index = index; | ||||||
|  |             Autopsic = autopsic; | ||||||
|  |             Date = date; | ||||||
|  |             Sort = sort; | ||||||
|  |             Order = order; | ||||||
|  |             Location = location; | ||||||
|  |             Senders = senders; | ||||||
|  |             Receivers = receivers; | ||||||
|  |             this.hasOriginal = hasOriginal; | ||||||
|  |             this.isProofread = isProofread; | ||||||
|  |             this.isDraft = isDraft; | ||||||
|  |             this.ZH = ZH; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										13
									
								
								HaDocumentNew/Models/OptionalBool.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								HaDocumentNew/Models/OptionalBool.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | |||||||
|  | using System; | ||||||
|  | using System.Collections.Generic; | ||||||
|  | using System.Text; | ||||||
|  |  | ||||||
|  | namespace HaDocument.Models | ||||||
|  | { | ||||||
|  |     public enum OptionalBool | ||||||
|  |     { | ||||||
|  |         True, | ||||||
|  |         False, | ||||||
|  |         None | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										20
									
								
								HaDocumentNew/Models/Person.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								HaDocumentNew/Models/Person.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | |||||||
|  | namespace HaDocument.Models { | ||||||
|  |     public class Person { | ||||||
|  |         public string Index { get; } = ""; | ||||||
|  |         public string Name { get; } = ""; | ||||||
|  |         public string Prename { get; } = ""; | ||||||
|  |         public string Surname { get; } = ""; | ||||||
|  |  | ||||||
|  |         public Person( | ||||||
|  |             string index, | ||||||
|  |             string name, | ||||||
|  |             string prename, | ||||||
|  |             string surname | ||||||
|  |         ) { | ||||||
|  |             Index = index; | ||||||
|  |             Name = name; | ||||||
|  |             Prename = prename; | ||||||
|  |             Surname = surname; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										14
									
								
								HaDocumentNew/Models/Tradition.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								HaDocumentNew/Models/Tradition.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | |||||||
|  | namespace HaDocument.Models { | ||||||
|  |     public class Tradition { | ||||||
|  |         public string Index { get; } = ""; | ||||||
|  |         public string Element { get; } = ""; | ||||||
|  |  | ||||||
|  |         public Tradition( | ||||||
|  |             string index, | ||||||
|  |             string element | ||||||
|  |         ) { | ||||||
|  |             Index = index; | ||||||
|  |             Element = element; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										22
									
								
								HaDocumentNew/Models/ZHInfo.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								HaDocumentNew/Models/ZHInfo.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | |||||||
|  | using System; | ||||||
|  | using System.Collections.Generic; | ||||||
|  | using System.Text; | ||||||
|  |  | ||||||
|  | namespace HaDocument.Models | ||||||
|  | { | ||||||
|  |  | ||||||
|  |     public class ZHInfo | ||||||
|  |     { | ||||||
|  |         public bool alternativeLineNumbering { get; } = false; | ||||||
|  |         public bool dateChanged { get; } = false; | ||||||
|  |         public string Volume { get; } = ""; | ||||||
|  |         public string Page { get; } = ""; | ||||||
|  |  | ||||||
|  |         public ZHInfo(bool alternativeLineNumbering, bool dateChanged, string Volume, string Page) { | ||||||
|  |             this.alternativeLineNumbering = alternativeLineNumbering; | ||||||
|  |             this.dateChanged = dateChanged; | ||||||
|  |             this.Volume = Volume; | ||||||
|  |             this.Page = Page; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										50
									
								
								HaDocumentNew/Settings/XMLRoots/CommentRoot.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								HaDocumentNew/Settings/XMLRoots/CommentRoot.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,50 @@ | |||||||
|  | namespace HaDocument.Settings.XMLRoots; | ||||||
|  | using System.Xml.Linq; | ||||||
|  |  | ||||||
|  | public class CommentRoot : HaWeb.XMLParser.IXMLRoot { | ||||||
|  |     public string Type { get; } = "Register"; | ||||||
|  |     public string Prefix { get; } = "register"; | ||||||
|  |     public string[] XPathContainer { get; } = { ".//data//kommentare/kommcat", ".//kommentare/kommcat" }; | ||||||
|  |  | ||||||
|  |     public Predicate<XElement> IsCollectedObject { get; } = (elem) => { | ||||||
|  |         if (elem.Name == "kommentar") return true; | ||||||
|  |         else return false; | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     public Func<XElement, string?> GetKey { get; } = (elem) => { | ||||||
|  |         var index = elem.Attribute("id"); | ||||||
|  |         if (index != null && !String.IsNullOrWhiteSpace(index.Value)) | ||||||
|  |             return index.Value; | ||||||
|  |         else return null; | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     public List<(string, string?)>? GenerateFields(XMLRootDocument document) { | ||||||
|  |         return null; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public (string?, string?) GenerateIdentificationString(XElement element) { | ||||||
|  |         var kat = element.Attribute("value"); | ||||||
|  |         if (kat != null && !String.IsNullOrWhiteSpace(kat.Value)) | ||||||
|  |             return (null, kat.Value); | ||||||
|  |         return (null, null); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public bool Replaces(XMLRootDocument doc1, XMLRootDocument doc2) { | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public XElement CreateHamannDocument(XElement element) { | ||||||
|  |         var opus = new XElement("opus"); | ||||||
|  |         var kommentare = new XElement("kommentare"); | ||||||
|  |         kommentare.AddFirst(element); | ||||||
|  |         opus.AddFirst(kommentare); | ||||||
|  |         return opus; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public void MergeIntoFile(XElement file, XMLRootDocument document) { | ||||||
|  |         if (file.Element("kommentare") == null) | ||||||
|  |             file.AddFirst(new XElement("kommentare")); | ||||||
|  |         file.Element("kommentare")!.AddFirst(document.Root); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										49
									
								
								HaDocumentNew/Settings/XMLRoots/DescriptionsRoot.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								HaDocumentNew/Settings/XMLRoots/DescriptionsRoot.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,49 @@ | |||||||
|  | namespace HaDocument.Settings.XMLRoots; | ||||||
|  | using System.Xml.Linq; | ||||||
|  |  | ||||||
|  | public class DescriptionsRoot : HaWeb.XMLParser.IXMLRoot { | ||||||
|  |     public string Type { get; } = "Metadaten"; | ||||||
|  |     public string Prefix { get; } = "metadaten"; | ||||||
|  |     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) => { | ||||||
|  |     //     var index = elem.Attribute("ref"); | ||||||
|  |     //     if (index != null && !String.IsNullOrWhiteSpace(index.Value)) | ||||||
|  |     //         return index.Value; | ||||||
|  |     //     else return null; | ||||||
|  |     // }; | ||||||
|  |  | ||||||
|  |     public List<(string, string?)>? GenerateFields(XMLRootDocument document) { | ||||||
|  |         return null; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public (string?, string?) GenerateIdentificationString(XElement element) { | ||||||
|  |         return (null, null); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public bool Replaces(XMLRootDocument doc1, XMLRootDocument doc2) { | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public XElement CreateHamannDocument(XElement element) { | ||||||
|  |         var opus = new XElement("opus"); | ||||||
|  |         opus.AddFirst(element); | ||||||
|  |         return opus; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public void MergeIntoFile(XElement file, XMLRootDocument document) { | ||||||
|  |         if (file.Element("descriptions") == null) | ||||||
|  |             file.AddFirst(new XElement("descriptions")); | ||||||
|  |         var elements = document.Root.Elements().Where(x => IsCollectedObject(x)); | ||||||
|  |         var root = file.Element("descriptions"); | ||||||
|  |         foreach (var element in elements) { | ||||||
|  |             root!.Add(element); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										50
									
								
								HaDocumentNew/Settings/XMLRoots/DocumentRoot.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								HaDocumentNew/Settings/XMLRoots/DocumentRoot.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,50 @@ | |||||||
|  | namespace HaDocument.Settings.XMLRoots; | ||||||
|  | using System.Xml.Linq; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | public class DocumentRoot : HaWeb.XMLParser.IXMLRoot { | ||||||
|  |     public string Type { get; } = "Brieftext"; | ||||||
|  |     public string Prefix { get; } = "brieftext"; | ||||||
|  |     public string[] XPathContainer { get; } = { ".//data/document", ".//document" }; | ||||||
|  |  | ||||||
|  |     public Predicate<XElement> IsCollectedObject { get; } = (elem) => { | ||||||
|  |         if (elem.Name == "letterText") return true; | ||||||
|  |         else return false; | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     public Func<XElement, string?> GetKey { get; } = (elem) => { | ||||||
|  |         var index = elem.Attribute("index"); | ||||||
|  |         if (index != null && !String.IsNullOrWhiteSpace(index.Value)) | ||||||
|  |             return index.Value; | ||||||
|  |         else return null; | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     public List<(string, string?)>? GenerateFields(XMLRootDocument document) { | ||||||
|  |         return null; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public (string?, string?) GenerateIdentificationString(XElement element) { | ||||||
|  |         return (null, null); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public bool Replaces(XMLRootDocument doc1, XMLRootDocument doc2) { | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public XElement CreateHamannDocument(XElement element) { | ||||||
|  |         var opus = new XElement("opus"); | ||||||
|  |         opus.AddFirst(element); | ||||||
|  |         return opus; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public void MergeIntoFile(XElement file, XMLRootDocument document) { | ||||||
|  |         if (file.Element("document") == null) | ||||||
|  |             file.AddFirst(new XElement("document")); | ||||||
|  |         var elements = document.Root.Elements().Where(x => IsCollectedObject(x)); | ||||||
|  |         var root = file.Element("document"); | ||||||
|  |         foreach (var element in elements) { | ||||||
|  |             root!.Add(element); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										50
									
								
								HaDocumentNew/Settings/XMLRoots/EditsRoot.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								HaDocumentNew/Settings/XMLRoots/EditsRoot.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,50 @@ | |||||||
|  | namespace HaDocument.Settings.XMLRoots; | ||||||
|  | using System.Xml.Linq; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | public class EditsRoot : HaWeb.XMLParser.IXMLRoot { | ||||||
|  |     public string Type { get; } = "Texteingriffe"; | ||||||
|  |     public string Prefix { get; } = "texteingriffe"; | ||||||
|  |     public string[] XPathContainer { get; } = { ".//data/edits", ".//edits" }; | ||||||
|  |  | ||||||
|  |     public Predicate<XElement> IsCollectedObject { get; } = (elem) => { | ||||||
|  |         if (elem.Name == "editreason") return true; | ||||||
|  |         else return false; | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     public Func<XElement, string?> GetKey { get; } = (elem) => { | ||||||
|  |         var index = elem.Attribute("index"); | ||||||
|  |         if (index != null && !String.IsNullOrWhiteSpace(index.Value)) | ||||||
|  |             return index.Value; | ||||||
|  |         else return null; | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     public List<(string, string?)>? GenerateFields(XMLRootDocument document) { | ||||||
|  |         return null; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public (string?, string?) GenerateIdentificationString(XElement element) { | ||||||
|  |         return (null, null); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public bool Replaces(XMLRootDocument doc1, XMLRootDocument doc2) { | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public XElement CreateHamannDocument(XElement element) { | ||||||
|  |         var opus = new XElement("opus"); | ||||||
|  |         opus.AddFirst(element); | ||||||
|  |         return opus; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public void MergeIntoFile(XElement file, XMLRootDocument document) { | ||||||
|  |         if (file.Element("edits") == null) | ||||||
|  |             file.AddFirst(new XElement("edits")); | ||||||
|  |         var elements = document.Root.Elements().Where(x => IsCollectedObject(x)); | ||||||
|  |         var root = file.Element("edits"); | ||||||
|  |         foreach (var element in elements) { | ||||||
|  |             root!.Add(element); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										49
									
								
								HaDocumentNew/Settings/XMLRoots/MarginalsRoot.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								HaDocumentNew/Settings/XMLRoots/MarginalsRoot.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,49 @@ | |||||||
|  | namespace HaDocument.Settings.XMLRoots; | ||||||
|  | using System.Xml.Linq; | ||||||
|  |  | ||||||
|  | public class MarginalsRoot : HaWeb.XMLParser.IXMLRoot { | ||||||
|  |     public string Type { get; } = "Stellenkommentar"; | ||||||
|  |     public string Prefix { get; } = "stellenkommentar"; | ||||||
|  |     public string[] XPathContainer { get; } = { ".//data/marginalien", ".//marginalien" }; | ||||||
|  |  | ||||||
|  |     public Predicate<XElement> IsCollectedObject { get; } = (elem) => { | ||||||
|  |         if (elem.Name == "marginal") return true; | ||||||
|  |         else return false; | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     public Func<XElement, string?> GetKey { get; } = (elem) => { | ||||||
|  |         var index = elem.Attribute("index"); | ||||||
|  |         if (index != null && !String.IsNullOrWhiteSpace(index.Value)) | ||||||
|  |             return index.Value; | ||||||
|  |         else return null; | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     public List<(string, string?)>? GenerateFields(XMLRootDocument document) { | ||||||
|  |         return null; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public (string?, string?) GenerateIdentificationString(XElement element) { | ||||||
|  |         return (null, null); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public bool Replaces(XMLRootDocument doc1, XMLRootDocument doc2) { | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public XElement CreateHamannDocument(XElement element) { | ||||||
|  |         var opus = new XElement("opus"); | ||||||
|  |         opus.AddFirst(element); | ||||||
|  |         return opus; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public void MergeIntoFile(XElement file, XMLRootDocument document) { | ||||||
|  |         if (file.Element("marginalien") == null) | ||||||
|  |             file.AddFirst(new XElement("marginalien")); | ||||||
|  |         var elements = document.Root.Elements().Where(x => IsCollectedObject(x)); | ||||||
|  |         var root = file.Element("marginalien"); | ||||||
|  |         foreach (var element in elements) { | ||||||
|  |             root!.Add(element); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										48
									
								
								HaDocumentNew/Settings/XMLRoots/ReferencesRoot.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								HaDocumentNew/Settings/XMLRoots/ReferencesRoot.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,48 @@ | |||||||
|  | namespace HaDocument.Settings.XMLRoots; | ||||||
|  | using System.Xml.Linq; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | public class ReferencesRoot : HaWeb.XMLParser.IXMLRoot { | ||||||
|  |     public string Type { get; } = "Personen / Orte"; | ||||||
|  |     public string Prefix { get; } = "personenorte"; | ||||||
|  |     public string[] XPathContainer { get; } = { ".//data/definitions", ".//definitions" }; | ||||||
|  |  | ||||||
|  |     public Predicate<XElement> IsCollectedObject { get; } = (elem) => { | ||||||
|  |         if (elem.Name == "personDefs" || elem.Name == "structureDefs" || elem.Name == "handDefs" || elem.Name == "locationDefs") | ||||||
|  |             return true; | ||||||
|  |         return false; | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     public Func<XElement, string?> GetKey { get; } = (elem) => { | ||||||
|  |         return elem.Name.ToString(); | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     public List<(string, string?)>? GenerateFields(XMLRootDocument document) { | ||||||
|  |         return null; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public (string?, string?) GenerateIdentificationString(XElement element) { | ||||||
|  |         return (null, null); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public bool Replaces(XMLRootDocument doc1, XMLRootDocument doc2) { | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public XElement CreateHamannDocument(XElement element) { | ||||||
|  |         var opus = new XElement("opus"); | ||||||
|  |         opus.AddFirst(element); | ||||||
|  |         return opus; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public void MergeIntoFile(XElement file, XMLRootDocument document) { | ||||||
|  |         if (file.Element("definitions") == null) | ||||||
|  |             file.AddFirst(new XElement("definitions")); | ||||||
|  |         var elements = document.Root.Elements().Where(x => IsCollectedObject(x)); | ||||||
|  |         var root = file.Element("definitions"); | ||||||
|  |         foreach (var element in elements) { | ||||||
|  |             root!.Add(element); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										49
									
								
								HaDocumentNew/Settings/XMLRoots/TraditionsRoot.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								HaDocumentNew/Settings/XMLRoots/TraditionsRoot.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,49 @@ | |||||||
|  | namespace HaDocument.Settings.XMLRoots; | ||||||
|  | using System.Xml.Linq; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | public class TraditionsRoot : HaWeb.XMLParser.IXMLRoot { | ||||||
|  |     public string Type { get; } = "Überlieferung"; | ||||||
|  |     public string Prefix { get; } = "ueberlieferung"; | ||||||
|  |     public string[] XPathContainer { get; } = { ".//data/traditions", ".//traditions" }; | ||||||
|  |  | ||||||
|  |     public Predicate<XElement> IsCollectedObject { get; } = (elem) => { | ||||||
|  |         if (elem.Name == "letterTradition") return true; | ||||||
|  |         else return false; | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     public Func<XElement, string?> GetKey { get; } = (elem) => { | ||||||
|  |         var index = elem.Attribute("ref"); | ||||||
|  |         if (index != null && !String.IsNullOrWhiteSpace(index.Value)) | ||||||
|  |             return index.Value; | ||||||
|  |         else return null; | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     public List<(string, string?)>? GenerateFields(XMLRootDocument document) { | ||||||
|  |         return null; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public (string?, string?) GenerateIdentificationString(XElement element) { | ||||||
|  |         return (null, null); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public bool Replaces(XMLRootDocument doc1, XMLRootDocument doc2) { | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public XElement CreateHamannDocument(XElement element) { | ||||||
|  |         var opus = new XElement("opus"); | ||||||
|  |         opus.AddFirst(element); | ||||||
|  |         return opus; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public void MergeIntoFile(XElement file, XMLRootDocument document) { | ||||||
|  |         if (file.Element("traditions") == null) | ||||||
|  |             file.AddFirst(new XElement("traditions")); | ||||||
|  |         var elements = document.Root.Elements().Where(x => IsCollectedObject(x)); | ||||||
|  |         var root = file.Element("traditions"); | ||||||
|  |         foreach (var element in elements) { | ||||||
|  |             root!.Add(element); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -16,6 +16,7 @@ using HaXMLReader.Interfaces; | |||||||
| using Microsoft.FeatureManagement.Mvc; | using Microsoft.FeatureManagement.Mvc; | ||||||
| using System.Runtime.InteropServices; | using System.Runtime.InteropServices; | ||||||
| using Microsoft.AspNetCore.Http.Features; | using Microsoft.AspNetCore.Http.Features; | ||||||
|  | using System.Text; | ||||||
|  |  | ||||||
| // Controlling all the API-Endpoints | // Controlling all the API-Endpoints | ||||||
| public class APIController : Controller { | public class APIController : Controller { | ||||||
| @@ -78,6 +79,7 @@ public class APIController : Controller { | |||||||
|             section = await reader.ReadNextSectionAsync(); |             section = await reader.ReadNextSectionAsync(); | ||||||
|         } catch (Exception ex) { |         } catch (Exception ex) { | ||||||
|             ModelState.AddModelError("Error", "The Request is bad: " + ex.Message); |             ModelState.AddModelError("Error", "The Request is bad: " + ex.Message); | ||||||
|  |             return BadRequest(ModelState); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         while (section != null) { |         while (section != null) { | ||||||
| @@ -178,7 +180,82 @@ public class APIController : Controller { | |||||||
|     [ValidateAntiForgeryToken] |     [ValidateAntiForgeryToken] | ||||||
|     [FeatureGate(Features.UploadService, Features.AdminService)] |     [FeatureGate(Features.UploadService, Features.AdminService)] | ||||||
|     public async Task<IActionResult> SetUsed(string id) { |     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] |     [ValidateAntiForgeryToken] | ||||||
|     [FeatureGate(Features.UploadService, Features.AdminService)] |     [FeatureGate(Features.UploadService, Features.AdminService)] | ||||||
|     public async Task<IActionResult> SetUsedHamann() { |     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,11 +48,11 @@ public class UploadController : Controller { | |||||||
|         if (roots == null) return error404(); |         if (roots == null) return error404(); | ||||||
|  |  | ||||||
|         var hF = _xmlProvider.GetHamannFiles(); |         var hF = _xmlProvider.GetHamannFiles(); | ||||||
|         List<(string, DateTime)>? hamannFiles = null; |         List<FileModel>? hamannFiles = null; | ||||||
|         if (hF != null) |         if (hF != null) | ||||||
|             hamannFiles = hF |             hamannFiles = hF | ||||||
|                 .OrderByDescending(x => x.LastModified) |                 .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(); |                 .ToList(); | ||||||
|  |  | ||||||
|         var uF = _xmlService.GetUsedDictionary(); |         var uF = _xmlService.GetUsedDictionary(); | ||||||
| @@ -88,9 +88,8 @@ public class UploadController : Controller { | |||||||
|             model.AvailableFiles = XMLFileHelpers.ToFileModel(_xmlProvider.GetFiles(id), pF, uF); |             model.AvailableFiles = XMLFileHelpers.ToFileModel(_xmlProvider.GetFiles(id), pF, uF); | ||||||
|  |  | ||||||
|             return View("../Admin/Upload/Index", model); |             return View("../Admin/Upload/Index", model); | ||||||
|         } |         } else { | ||||||
|         else { |             var model = new UploadViewModel("Upload & Veröffentlichen", id, roots, usedFiles); | ||||||
|             var model = new UploadViewModel("Upload", id, roots, usedFiles); |  | ||||||
|             model.ProductionFiles = productionFiles; |             model.ProductionFiles = productionFiles; | ||||||
|             model.HamannFiles = hamannFiles; |             model.HamannFiles = hamannFiles; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -15,15 +15,13 @@ public class HaDocumentWrapper : IHaDocumentWrappper { | |||||||
|  |  | ||||||
|         _startYear = configuration.GetValue<int>("AvailableStartYear"); |         _startYear = configuration.GetValue<int>("AvailableStartYear"); | ||||||
|         _endYear = configuration.GetValue<int>("AvailableEndYear"); |         _endYear = configuration.GetValue<int>("AvailableEndYear"); | ||||||
|  |  | ||||||
|         var filelist = xmlProvider.GetHamannFiles(); |         var filelist = xmlProvider.GetHamannFiles(); | ||||||
|         if (filelist != null && filelist.Any()) |         if (filelist != null && filelist.Any()) { | ||||||
|             _AutoLoad(filelist); |             _AutoLoad(filelist); | ||||||
|  |         } | ||||||
|         // Use Fallback library |         // Use Fallback library | ||||||
|         if (Library == null)  |         if (Library == null)  | ||||||
|             Library = HaDocument.Document.Create(new HaWeb.Settings.HaDocumentOptions() { AvailableYearRange = (_startYear, _endYear) }); |             Library = HaDocument.Document.Create(new HaWeb.Settings.HaDocumentOptions() { AvailableYearRange = (_startYear, _endYear) }); | ||||||
|  |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public ILibrary ResetLibrary() { |     public ILibrary ResetLibrary() { | ||||||
| @@ -38,6 +36,7 @@ public class HaDocumentWrapper : IHaDocumentWrappper { | |||||||
|         } |         } | ||||||
|         catch (Exception ex) { |         catch (Exception ex) { | ||||||
|             if (ModelState != null) ModelState.AddModelError("Error:", "Das Dokument konnte nicht geparst werden: " + ex.Message); |             if (ModelState != null) ModelState.AddModelError("Error:", "Das Dokument konnte nicht geparst werden: " + ex.Message); | ||||||
|  |             Console.WriteLine(ex.Message); | ||||||
|             return null; |             return null; | ||||||
|         } |         } | ||||||
|         return Library; |         return Library; | ||||||
| @@ -50,7 +49,10 @@ public class HaDocumentWrapper : IHaDocumentWrappper { | |||||||
|     private void _AutoLoad(List<IFileInfo> files) { |     private void _AutoLoad(List<IFileInfo> files) { | ||||||
|         var orderdlist = files.OrderByDescending(x => x.LastModified); |         var orderdlist = files.OrderByDescending(x => x.LastModified); | ||||||
|         foreach(var item in orderdlist) { |         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 Save(XMLRootDocument doc, string basefilepath, ModelStateDictionary ModelState); | ||||||
|         public Task<IFileInfo?> SaveHamannFile(XElement element, string basefilepath, ModelStateDictionary ModelState); |         public Task<IFileInfo?> SaveHamannFile(XElement element, string basefilepath, ModelStateDictionary ModelState); | ||||||
|         public List<IFileInfo>? GetHamannFiles(); |         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.AspNetCore.WebUtilities; | ||||||
| using Microsoft.Net.Http.Headers; | using Microsoft.Net.Http.Headers; | ||||||
| using HaWeb.Models; | using HaWeb.Models; | ||||||
|  | using System.Text; | ||||||
|  |  | ||||||
| public static class XMLFileHelpers { | public static class XMLFileHelpers { | ||||||
|     //  File Signatures Database (https://www.filesignatures.net/) |     //  File Signatures Database (https://www.filesignatures.net/) | ||||||
| @@ -199,6 +200,20 @@ public static class XMLFileHelpers { | |||||||
|         return null; |         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) { |     private static bool IsValidFileExtensionAndSignature(string fileName, Stream data, string[] permittedExtensions) { | ||||||
|         if (string.IsNullOrEmpty(fileName) || data == null || data.Length == 0) |         if (string.IsNullOrEmpty(fileName) || data == null || data.Length == 0) | ||||||
|             return false; |             return false; | ||||||
|   | |||||||
| @@ -26,6 +26,10 @@ public class XMLProvider : IXMLProvider { | |||||||
|  |  | ||||||
|     public List<IFileInfo>? GetHamannFiles() => this._HamannFiles; |     public List<IFileInfo>? GetHamannFiles() => this._HamannFiles; | ||||||
|  |  | ||||||
|  |     public IFileInfo? GetInProduction() => this._InProduction; | ||||||
|  |  | ||||||
|  |     public void SetInProduction(IFileInfo info) => _InProduction = info; | ||||||
|  |  | ||||||
|     public FileList? GetFiles(string prefix) |     public FileList? GetFiles(string prefix) | ||||||
|         => _Files != null && _Files.ContainsKey(prefix) ? _Files[prefix] : null; |         => _Files != null && _Files.ContainsKey(prefix) ? _Files[prefix] : null; | ||||||
|  |  | ||||||
| @@ -83,6 +87,7 @@ public class XMLProvider : IXMLProvider { | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         if (_HamannFiles == null) _HamannFiles = new List<IFileInfo>(); |         if (_HamannFiles == null) _HamannFiles = new List<IFileInfo>(); | ||||||
|  |         _HamannFiles.RemoveAll(x => x.Name == info.Name); | ||||||
|         _HamannFiles.Add(info); |         _HamannFiles.Add(info); | ||||||
|         _InProduction = info; |         _InProduction = info; | ||||||
|         return info; |         return info; | ||||||
|   | |||||||
| @@ -8,10 +8,10 @@ public class FileModel { | |||||||
|     public bool InProduction { get; private set; } |     public bool InProduction { get; private set; } | ||||||
|     public List<(string, string?)>? Fields { get; 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; |         FileName = name; | ||||||
|         IsUsed = IsUsed; |         IsUsed = isUsed; | ||||||
|         LastModified = lastModified; |         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>?>? UsedFiles { get; private set; } | ||||||
|     public Dictionary<string, List<FileModel>?>? ProductionFiles { get; 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) { |     public UploadViewModel(string title, string? prefix, List<IXMLRoot>? roots, Dictionary<string, List<FileModel>?>? usedFiles) { | ||||||
|         Prefix = prefix; |         Prefix = prefix; | ||||||
|   | |||||||
| @@ -30,10 +30,10 @@ if (filepath == null) { | |||||||
| var physicalProvider = new PhysicalFileProvider(filepath); | var physicalProvider = new PhysicalFileProvider(filepath); | ||||||
|  |  | ||||||
| builder.Services.AddSingleton<IFileProvider>(physicalProvider); | builder.Services.AddSingleton<IFileProvider>(physicalProvider); | ||||||
| builder.Services.AddSingleton<HaWeb.FileHelpers.IHaDocumentWrappper, HaWeb.FileHelpers.HaDocumentWrapper>(); |  | ||||||
| builder.Services.AddTransient<IReaderService, ReaderService>(); | builder.Services.AddTransient<IReaderService, ReaderService>(); | ||||||
| builder.Services.AddSingleton<IXMLProvider, XMLProvider>(); | builder.Services.AddSingleton<IXMLProvider, XMLProvider>(); | ||||||
| builder.Services.AddSingleton<IXMLService, XMLService>(); | builder.Services.AddSingleton<IXMLService, XMLService>(); | ||||||
|  | builder.Services.AddSingleton<HaWeb.FileHelpers.IHaDocumentWrappper, HaWeb.FileHelpers.HaDocumentWrapper>(); | ||||||
| builder.Services.AddFeatureManagement(); | builder.Services.AddFeatureManagement(); | ||||||
|  |  | ||||||
| var app = builder.Build(); | var app = builder.Build(); | ||||||
|   | |||||||
| @@ -44,7 +44,7 @@ | |||||||
|         </label> |         </label> | ||||||
|         <div class="ha-publishmessage" id="ha-publishmessage"> |         <div class="ha-publishmessage" id="ha-publishmessage"> | ||||||
|           @* Fehler!<br/> *@ |           @* Fehler!<br/> *@ | ||||||
|           <output form="uploadForm" name="publish-result"></output> |           <output form="uploadForm" name="publish-result" id="publish-result"></output> | ||||||
|         </div> |         </div> | ||||||
|     </form> |     </form> | ||||||
|   </div> |   </div> | ||||||
| @@ -52,31 +52,42 @@ | |||||||
|  |  | ||||||
| <div class="ha-uploadheader"> | <div class="ha-uploadheader"> | ||||||
|   <h1 class="ha-uploadtitle">@Model.ActiveTitle</h1> |   <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> | ||||||
|  |  | ||||||
| <div class="ha-uploadcontainer"> | <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)) { | @if (Model.UsedFiles != null && Model.Prefix != null && Model.UsedFiles.ContainsKey(Model.Prefix)) { | ||||||
|   <div class="ha-errorswarnings"> |   <div class="ha-errorswarnings"> | ||||||
|     <div class="ha-criticalerrors"> |     <div class="ha-criticalerrors"> | ||||||
| @@ -92,17 +103,25 @@ | |||||||
|   </div> |   </div> | ||||||
| } | } | ||||||
|  |  | ||||||
| else { |  | ||||||
|   <form class="ha-selecthamannfilesform" id="selecthamannfilesform" asp-controller="API" asp-action="SetUsedHamann" method="post" enctype="multipart/form-data"> |  | ||||||
|      |  | ||||||
|   </form> |  | ||||||
| } |  | ||||||
|  |  | ||||||
| </div> | </div> | ||||||
|  |  | ||||||
| @section Scripts { | @section Scripts { | ||||||
|   <script> |   <script> | ||||||
|     "use strict"; |     "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) { |     const dropHandler = function (formelement, ev, dropzone) { | ||||||
|       ev.preventDefault(); |       ev.preventDefault(); | ||||||
|       if (ev.dataTransfer.items) { |       if (ev.dataTransfer.items) { | ||||||
| @@ -145,18 +164,19 @@ else { | |||||||
|             document.getElementById("ha-publishfilelabel").style.pointerEvents = "auto"; |             document.getElementById("ha-publishfilelabel").style.pointerEvents = "auto"; | ||||||
|             document.getElementById("ha-lds-ellipsis-publish").style.display = "none"; |             document.getElementById("ha-lds-ellipsis-publish").style.display = "none"; | ||||||
|             document.getElementById("ha-publishmessage").style.opacity = "1"; |             document.getElementById("ha-publishmessage").style.opacity = "1"; | ||||||
|             oFormElement.elements.namedItem("update-result").value = json.Error; |             document.getElementById("publish-result").value = json.Error; | ||||||
|           } else { |           } else { | ||||||
|             document.getElementById("ha-publishfilelabel").style.pointerEvents = "auto"; |             document.getElementById("ha-publishfilelabel").style.pointerEvents = "auto"; | ||||||
|             document.getElementById("ha-lds-ellipsis-publish").style.display = "none"; |             document.getElementById("ha-lds-ellipsis-publish").style.display = "none"; | ||||||
|             document.getElementById("ha-publishmessage").style.opacity = "1"; |             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) => { |         .catch ((e) => { | ||||||
|           document.getElementById("ha-publishfilelabel").style.pointerEvents = "auto"; |           document.getElementById("ha-publishfilelabel").style.pointerEvents = "auto"; | ||||||
|           document.getElementById("ha-lds-ellipsis-publish").style.display = "none"; |           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 dropzone = document.getElementById("dropzone"); | ||||||
|       var publishelement = document.getElementById("ha-publishform"); |       var publishelement = document.getElementById("ha-publishform"); | ||||||
|       var publishbutton = document.getElementById("ha-publishfilelabel"); |       var publishbutton = document.getElementById("ha-publishfilelabel"); | ||||||
|  |       var filesbutton = document.getElementById("ha-availablefiles"); | ||||||
|  |       if (filesbutton !== null) | ||||||
|  |         filesbutton.addEventListener("click", () => hideshowfiles()); | ||||||
|       publishbutton.addEventListener("click", () => LOCALPUBLISHSubmit(publishelement)); |       publishbutton.addEventListener("click", () => LOCALPUBLISHSubmit(publishelement)); | ||||||
|       submitelement.addEventListener("change", () => UPLOADSubmit(formelement)); |       submitelement.addEventListener("change", () => UPLOADSubmit(formelement)); | ||||||
|       dropzone.addEventListener("drop", (ev) => dropHandler(formelement, ev, dropzone)); |       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(string prefix); | ||||||
|     public void AutoUse(FileList filelist); |     public void AutoUse(FileList filelist); | ||||||
|     public Dictionary<string, FileList?>? GetInProduction(); |     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 Dictionary<string, FileList?>? GetInProduction() => this._InProduction; | ||||||
|  |  | ||||||
|  |     public void UnUseProduction() => this._InProduction = null; | ||||||
|  |  | ||||||
|     public List<XMLRootDocument>? ProbeHamannFile(XDocument document, ModelStateDictionary ModelState) { |     public List<XMLRootDocument>? ProbeHamannFile(XDocument document, ModelStateDictionary ModelState) { | ||||||
|         if (document.Root!.Name != "opus") { |         if (document.Root!.Name != "opus") { | ||||||
|             ModelState.AddModelError("Error", "A valid Hamann-Docuemnt must begin with <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); |         _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 |     // Performs detection of using on the specified document type | ||||||
|     public void AutoUse(string prefix) { |     public void AutoUse(string prefix) { | ||||||
|         if (_Used == null || !_Used.ContainsKey(prefix)) return; |         if (_Used == null || !_Used.ContainsKey(prefix)) return; | ||||||
|   | |||||||
| @@ -19,6 +19,7 @@ module.exports = { | |||||||
|       sans: ['Biolinum', 'sans-serif'], |       sans: ['Biolinum', 'sans-serif'], | ||||||
|       serif: ['Libertine', 'serif'], |       serif: ['Libertine', 'serif'], | ||||||
|       classy: ['Playfair', 'serif'], |       classy: ['Playfair', 'serif'], | ||||||
|  |       mono: ['ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace', 'mono'] | ||||||
|     }, |     }, | ||||||
|     screens: { |     screens: { | ||||||
|       'sm': '700px', |       'sm': '700px', | ||||||
|   | |||||||
| @@ -123,7 +123,7 @@ code, | |||||||
| kbd, | kbd, | ||||||
| samp, | samp, | ||||||
| pre { | 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 */ |   /* 1 */ | ||||||
|   font-size: 1em; |   font-size: 1em; | ||||||
|   /* 2 */ |   /* 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: 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 */ | /* Everything related to theme color */ | ||||||
|  |  | ||||||
| body { | body { | ||||||
| @@ -1868,8 +1870,8 @@ body { | |||||||
| .ha-adminuploadfields .ha-uploadfield.active { | .ha-adminuploadfields .ha-uploadfield.active { | ||||||
|   --tw-text-opacity: 1 !important; |   --tw-text-opacity: 1 !important; | ||||||
|   color: rgb(0 0 0 / var(--tw-text-opacity)) !important; |   color: rgb(0 0 0 / var(--tw-text-opacity)) !important; | ||||||
|   --tw-shadow-color: #fee2e2; |   --tw-brightness: brightness(1.1); | ||||||
|   --tw-shadow: var(--tw-shadow-colored); |   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 { | .ha-adminuploadfields .ha-uploadfield .ha-uploadfieldname { | ||||||
| @@ -2022,46 +2024,6 @@ body { | |||||||
|   line-height: 1; |   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 { | .ha-uploadcontainer { | ||||||
|   display: flex; |   display: flex; | ||||||
|   height: 100%; |   height: 100%; | ||||||
| @@ -2072,6 +2034,40 @@ body { | |||||||
|   background-color: rgb(248 250 252 / var(--tw-bg-opacity)); |   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 { | .ha-uploadcontainer .ha-errorswarnings { | ||||||
|   display: flex; |   display: flex; | ||||||
|   flex-direction: row; |   flex-direction: row; | ||||||
| @@ -2109,6 +2105,98 @@ body { | |||||||
|   background-color: rgb(165 243 252 / var(--tw-bg-opacity)); |   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 */ | /* Classes for Letter View */ | ||||||
|  |  | ||||||
| .ha-letterheader { | .ha-letterheader { | ||||||
| @@ -3055,6 +3143,10 @@ body { | |||||||
|   margin-right: 0px !important; |   margin-right: 0px !important; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | .block { | ||||||
|  |   display: block; | ||||||
|  | } | ||||||
|  |  | ||||||
| .inline-block { | .inline-block { | ||||||
|   display: inline-block; |   display: inline-block; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -84,6 +84,7 @@ | |||||||
|     @apply transition-colors duration-100 |     @apply transition-colors duration-100 | ||||||
|   } |   } | ||||||
|   /* TODO: check what can be inlined (eg. used once in the code, has no double paths etc...) */ |   /* 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 */ |   /* Everything related to theme color */ | ||||||
|   body { |   body { | ||||||
| @@ -678,7 +679,7 @@ | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   .ha-adminuploadfields .ha-uploadfield.active { |   .ha-adminuploadfields .ha-uploadfield.active { | ||||||
|     @apply !text-black shadow-red-100 |     @apply !text-black brightness-110 | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   .ha-adminuploadfields .ha-uploadfield .ha-uploadfieldname { |   .ha-adminuploadfields .ha-uploadfield .ha-uploadfieldname { | ||||||
| @@ -745,30 +746,30 @@ | |||||||
|     @apply text-5xl |     @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 { |   .ha-uploadcontainer { | ||||||
|     @apply w-full bg-slate-50 flex flex-col gap-y-2 h-full |     @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 { |   .ha-uploadcontainer .ha-errorswarnings { | ||||||
|     @apply flex flex-row gap-x-2 |     @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] |     @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 */ |   /* Classes for Letter View */ | ||||||
|  |  | ||||||
|   .ha-letterheader { |   .ha-letterheader { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 schnulller
					schnulller