state after adding all of the user stuff and messing around with the wierd brave bug

This commit is contained in:
2026-03-08 14:45:38 -04:00
commit dde9ffcedb
4283 changed files with 124077 additions and 0 deletions

View File

@@ -0,0 +1,8 @@
using Microsoft.AspNetCore.Identity;
namespace OpenArchival.DataAccess;
// Add profile data for application users by adding properties to the ApplicationUser class
public class ApplicationUser : IdentityUser
{
}

View File

@@ -0,0 +1,21 @@
using Microsoft.EntityFrameworkCore;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace OpenArchival.DataAccess;
public class ArchiveCategory
{
[Key]
public int Id { get; set; }
[System.ComponentModel.DataAnnotations.Schema.Index(IsUnique =true)]
public required string Name { get; set; }
public string? Description { get; set; }
public required string FieldSeparator { get; set; } = "-";
public List<string> FieldNames { get; set; } = [];
public List<string> FieldDescriptions { get; set; } = [];
}

View File

@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OpenArchival.DataAccess;
public class ArtifactDefect
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public required string Description { get; set; }
public List<ArtifactEntry> ArtifactEntries { get; set; } = [];
}

View File

@@ -0,0 +1,99 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Text;
namespace OpenArchival.DataAccess;
public class ArtifactEntry
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
/// <summary>
/// This value gets appended on the end of the contianing ArtifactGrouping's
/// Category value
/// </summary>
public string? ArtifactIdentifier
{
get
{
return (ArtifactGrouping is not null)
? ModelHelpers.MakeIdentifier(ArtifactGrouping.IdentifierFields.Values, ArtifactGrouping.Category.FieldSeparator, ArtifactNumber)
: null;
}
}
public string? ArtifactNumber { get; set; }
public required string Title { get; set; }
public string? Description { get; set; }
public required ArtifactStorageLocation StorageLocation { get; set; }
//public List<ArtifactEntryTag>? Tags { get; set; } = [];
public List<ArtifactEntryTag> Tags { get; set; } = [];
public List<ListedName>? ListedNames { get; set; } = [];
public List<DateTime>? AssociatedDates { get; set; } = [];
public List<ArtifactDefect>? Defects { get; set; } = [];
public List<string>? Links { get; set; } = [];
public required List<FilePathListing> Files { get; set; } = [];
public string? FileTextContent { get; set; } = null;
public required ArtifactType Type { get; set; }
public bool IsPubliclyVisible { get; set; }
public int Quantity { get; set; }
// Relationships this artifact has TO other artifacts
public List<ArtifactEntry> RelatedTo { get; set; } = [];
// Relationships other artifacts have TO this artifact
public List<ArtifactEntry> RelatedBy { get; set; } = [];
public int ArtifactGroupingId { get; set; }
public required ArtifactGrouping ArtifactGrouping { get; set; }
public override string ToString()
{
var sb = new StringBuilder();
sb.AppendLine($"--- ArtifactEntry (ID: {Id}) ---");
sb.AppendLine($" Title: {Title}");
sb.AppendLine($" ArtifactIdentifier: {ArtifactIdentifier ?? "N/A"}");
sb.AppendLine($" ArtifactNumber: {ArtifactNumber ?? "N/A"}");
sb.AppendLine($" StorageLocation: {StorageLocation}"); // Assumes ArtifactStorageLocation has a useful ToString()
sb.AppendLine($" IsPubliclyVisible: {IsPubliclyVisible}");
// Handle Description (it could be long, so you might truncate it if needed)
sb.AppendLine($" Description: {(string.IsNullOrWhiteSpace(Description) ? "N/A" : Description)}");
// Handle Lists
sb.AppendLine($" Tags: {(Tags is not null && Tags.Any() ? string.Join(", ", Tags) : "None")}");
sb.AppendLine($" ListedNames: {(ListedNames is not null && ListedNames.Any() ? string.Join(", ", ListedNames) : "None")}");
sb.AppendLine($" AssociatedDates: {(AssociatedDates is not null && AssociatedDates.Any() ? string.Join(", ", AssociatedDates.Select(d => d.ToShortDateString())) : "None")}");
sb.AppendLine($" Defects: {(Defects is not null && Defects.Any() ? string.Join(", ", Defects) : "None")}");
sb.AppendLine($" Links: {(Links is not null && Links.Any() ? string.Join(", ", Links) : "None")}");
sb.AppendLine($" Files: {(Files is not null && Files.Any() ? string.Join(", ", Files) : "None")}");
// Handle potentially very large text content
sb.AppendLine($" FileTextContent: {(string.IsNullOrEmpty(FileTextContent) ? "Not Present" : $"Present (Length: {FileTextContent.Length})")}");
sb.Append("--------------------------");
return sb.ToString();
}
}

View File

@@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OpenArchival.DataAccess;
public class ArtifactEntryTag
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Index(IsUnique = true)]
public required string Name { get; set; }
public List<ArtifactEntry> ArtifactEntries { get; set; } = [];
public List<SearchPageSliderEntry> SearchPageSliders { get; set; } = [];
public override string ToString()
{
return Name;
}
}

View File

@@ -0,0 +1,158 @@
using NpgsqlTypes;
using Persic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Diagnostics.CodeAnalysis;
using System.Text;
namespace OpenArchival.DataAccess;
public class ArtifactGrouping
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string? ArtifactGroupingIdentifier
{
get
{
return ModelHelpers.MakeIdentifier(IdentifierFields.Values, Category.FieldSeparator, null);
}
}
[NotMapped]
public List<FilePathListing> ChildFilePathListings
{
get
{
var list = new List<FilePathListing>();
foreach (ArtifactEntry entry in ChildArtifactEntries)
{
list.AddRange(entry.Files);
}
return list;
}
}
public required ArchiveCategory Category { get; set; }
private IdentifierFields _identifierFields;
public required IdentifierFields IdentifierFields
{
get => _identifierFields;
set
{
if (value.Values.Count != Category.FieldNames.Count)
{
throw new ArgumentException(nameof(IdentifierFields), $"The number of field values must be equal to the field count of the {nameof(ArchiveCategory)}");
}
_identifierFields = value;
}
}
public required string Title { get; set; }
public string? Description { get; set; }
public ArtifactType Type { get; set; }
public bool IsPublicallyVisible { get; set; }
public required List<ArtifactEntry> ChildArtifactEntries { get; set; } = new();
public ArtifactGroupingViewCount? ViewCount { get; set; }
/// <summary>
/// The list of all blog posts about this grouping
/// </summary>
public List<BlogPost> BlogPosts { get; set; } = [];
public override string ToString()
{
var sb = new StringBuilder();
sb.AppendLine($"Id: {Id}");
sb.AppendLine($"Artifact Grouping Identifier: {ArtifactGroupingIdentifier}");
sb.AppendLine($"Category:");
sb.AppendLine(Category.ToString());
sb.AppendLine($"Title: {Title}");
sb.AppendLine($"Description: {Description}");
sb.AppendLine($"Type:{Type}");
sb.AppendLine($"Publically Visible: {IsPublicallyVisible}");
sb.AppendLine($"Artifact Entries:");
foreach (var artifact in ChildArtifactEntries)
{
sb.AppendLine(artifact.ToString());
sb.AppendLine();
}
return sb.ToString();
}
[NotMapped]
public IEnumerable<ArtifactEntryTag> ChildTags
{
get
{
HashSet<ArtifactEntryTag> seenTags = [];
for (int index = 0; index < ChildArtifactEntries.Count; ++index)
{
// Get the tags for this entry, skip if no tags
List<ArtifactEntryTag>? tags = ChildArtifactEntries[index].Tags;
if (tags is null)
{
continue;
}
// Only yield a tag if we have not yielded it yet
foreach (ArtifactEntryTag tag in tags)
{
if (seenTags.Contains(tag))
{
continue;
}
seenTags.Add(tag);
yield return tag;
}
}
}
}
/// <summary>
/// Enables searching using postgres full text search
/// </summary>
///
public string AllSearchString { get; set; } = "";
public NpgsqlTsVector? AllSearchVector { get; set; }
public string TagsSearchString { get; set; } = "";
public NpgsqlTsVector? TagsSearchVector { get; set; }
public string DefectsSearchString { get; set; } = "";
public NpgsqlTsVector? DefectsSearchVector { get; set; }
public string ListedNamesSearchString { get; set; } = "";
public NpgsqlTsVector? ListedNamesSearchVector { get; set; }
public string TitleSearchString { get; set; } = "";
public NpgsqlTsVector? TitleSearchVector { get; set; }
public string DescriptionSearchString { get; set; } = "";
public NpgsqlTsVector? DescriptionSearchVector { get; set; }
public string FilenamesSearchString { get; set; } = "";
public NpgsqlTsVector FilenamesSearchVector { get; set; }
public string FileContentSearchString { get; set; } = "";
public NpgsqlTsVector FileContentSearchVector { get; set; }
}

View File

@@ -0,0 +1,12 @@
namespace OpenArchival.DataAccess;
public class ArtifactGroupingViewCount
{
public int Id { get; set; }
public required ArtifactGrouping Grouping { get; set; }
public int ArtifactGroupingId { get; set; }
public int Views { get; set; }
}

View File

@@ -0,0 +1,16 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace OpenArchival.DataAccess;
public class ArtifactStorageLocation
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[System.ComponentModel.DataAnnotations.Schema.Index(IsUnique =true)]
public required string Location { get; set; }
public List<ArtifactEntry> ArtifactEntries { get; set; } = [];
}

View File

@@ -0,0 +1,16 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace OpenArchival.DataAccess;
public class ArtifactType
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[System.ComponentModel.DataAnnotations.Schema.Index(IsUnique =true)]
public required string Name { get; set; }
public List<ArtifactEntry>? ArtifactEntries { get; set; } = [];
}

View File

@@ -0,0 +1,43 @@
using NpgsqlTypes;
using System.ComponentModel.DataAnnotations;
namespace OpenArchival.DataAccess;
public class BlogPost
{
[Key]
public int Id { get; set; }
/// <summary>
/// The title of the blog post
/// </summary>
public string Title { get; set; } = "";
/// <summary>
/// The HTML content of the post
/// </summary>
public string Content { get; set; } = "";
public DateTime CreationTime { get; set; }
public DateTime ModifiedTime { get; set; }
public List<BlogPostTag> Tags { get; set; } = [];
public BlogPostViewCount Views { get; set; } = default!;
public FilePathListing MainPhoto { get; set; } = default!;
public List<ArtifactGrouping> ArtifactGroupings { get; set; } = [];
public NpgsqlTsVector ContentSearchVector { get; set; } = default!;
public NpgsqlTsVector TitleSearchVector { get; set; } = default!;
public string TagsSearchString { get; set; } = "";
public NpgsqlTsVector TagsSearchVector { get; set; } = default!;
public string AllSearchString { get; set; } = "";
public NpgsqlTsVector AllSearchVector { get; set; } = default!;
}

View File

@@ -0,0 +1,24 @@
using System.ComponentModel.DataAnnotations;
namespace OpenArchival.DataAccess;
public class BlogPostTag
{
[Key]
public int Id { get; set; }
/// <summary>
/// The name of this tags
/// </summary>
public string Name { get; set; } = "";
/// <summary>
/// Blog posts assocaited with this tag
/// </summary>
public List<BlogPost> BlogPosts { get; set; } = [];
public override string ToString()
{
return Name;
}
}

View File

@@ -0,0 +1,12 @@
namespace OpenArchival.DataAccess;
public class BlogPostViewCount
{
public int Id { get; set; }
public required BlogPost Post { get; set; }
public int BlogPostId { get; set; }
public int Views { get; set; }
}

View File

@@ -0,0 +1,23 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace OpenArchival.DataAccess;
public class FilePathListing
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public int? ParentArtifactEntryId { get; set; }
public ArtifactEntry? ParentArtifactEntry { get; set; }
public BlogPost? ParentBlogPost { get; set; }
public int? ParentBlogPostId { get; set; }
public required string OriginalName { get; set; }
public required string Path { get; set; }
}

View File

@@ -0,0 +1,6 @@
namespace OpenArchival.DataAccess;
public class IdentifierFields
{
public List<string> Values { get; set; } = [];
}

View File

@@ -0,0 +1,20 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace OpenArchival.DataAccess;
public class ListedName
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public required string Value { get; set; }
public List<ArtifactEntry> ArtifactEntries { get; set; } = [];
public override string ToString()
{
return Value;
}
}

View File

@@ -0,0 +1,11 @@
namespace OpenArchival.DataAccess;
public class ModelHelpers
{
public static string? MakeIdentifier(List<string>? values, string fieldSeperator, string? archiveEntryNumber)
{
if (values is null || values.Count == 0) return null;
return (archiveEntryNumber is not null) ? $"{string.Join(fieldSeperator, values)}{archiveEntryNumber}" : string.Join(fieldSeperator, values);
}
}

View File

@@ -0,0 +1,26 @@
using System.ComponentModel.DataAnnotations;
namespace OpenArchival.DataAccess;
/// <summary>
/// Used to display sliders of featured artifacts on the search page before a search is entered.
/// </summary>
public class SearchPageSliderEntry
{
[Key]
public int Id { get; set; }
public string Title { get; set; } = "";
public string Description { get; set; } = "";
/// <summary>
/// The tags used to find artifacts for the slider
/// </summary>
public List<ArtifactEntryTag> FilterTags { get; set; } = [];
/// <summary>
/// The maximum number of artifact entries that should be pulled for this slider
/// </summary>
public int MaxCount { get; set; } = 10;
}