Extracted some pages to their own assembly and finished the artifact display page code

This commit is contained in:
Vincent Allen
2025-10-08 13:08:12 -04:00
parent fd0e6290fe
commit 02c2660b09
626 changed files with 39989 additions and 1553 deletions

View File

@@ -18,6 +18,8 @@
<script src="_framework/blazor.web.js"></script>
<script src=@Assets["_content/MudBlazor/MudBlazor.min.js"]></script>
<script src="_content/CodeBeam.MudBlazor.Extensions/MudExtensions.min.js"></script>
<script src="js/downloadHelper.js"></script>
<script src="js/imageSizeGetter.js"></script>
</body>
</html>

View File

@@ -5,9 +5,17 @@
@* Loop through and display each item as a chip *@
@foreach (var item in Items)
{
<MudChip Color="Color.Primary" OnClose="() => RemoveItem(item)" T="T">
@DisplayFunc(item)
</MudChip>
@if (DeleteEnabled)
{
<MudChip Color="Color.Primary" OnClose="() => RemoveItem(item)" T="T">
@DisplayFunc(item)
</MudChip>
} else
{
<MudChip Color="Color.Primary" T="T">
@DisplayFunc(item)
</MudChip>
}
}
@* Render the input control provided by the consumer *@
@@ -22,6 +30,9 @@
</div>
@code {
[Parameter]
public bool DeleteEnabled { get; set; } = true;
/// <summary>
/// The list of items to display and manage.
/// </summary>
@@ -51,8 +62,6 @@
[Parameter]
public Func<T, string> DisplayFunc { get; set; } = item => item?.ToString() ?? string.Empty;
/// <summary>
/// A public method that the consumer's input control can call to add a new item.
/// </summary>

View File

@@ -230,4 +230,19 @@
private void ClearDragClass()
=> _dragClass = DefaultDragClass;
public void RemoveFile(string filename)
{
var existingFile = ExistingFiles.Where(f => f.OriginalName == filename).FirstOrDefault();
if (existingFile is not null)
{
ExistingFiles.Remove(existingFile);
}
var file = Files.Where(f => f.Name == filename).FirstOrDefault();
if (file is not null)
{
Files.Remove(file);
}
}
}

View File

@@ -44,6 +44,7 @@
if (result is not null && !result.Canceled)
{
}
}
*/

View File

@@ -2,6 +2,7 @@
@using OpenArchival.Blazor.Components.Pages.Administration.Categories
@using OpenArchival.DataAccess;
@using System.ComponentModel.DataAnnotations
@using MudBlazor
@inject IDialogService DialogService
@inject NavigationManager NavigationManager;
@@ -193,6 +194,9 @@
{
// The data entry should only be shown if a category has been selected
_isFormDivVisible = true;
} else
{
_isFormDivVisible = false;
}
if (Model is not null)
@@ -223,11 +227,11 @@
if (IsValid && ClearOnPublish)
{
Model = new();
Model = new();
await _uploadComponent.ClearClicked.InvokeAsync();
StateHasChanged();
}
await GroupingPublished.InvokeAsync(oldModel);
}
@@ -343,10 +347,10 @@
return categories;
}
private async void OnDeleteEntryClicked(int index)
private async void OnDeleteEntryClicked((int index, string filename) data)
{
Model.ArtifactEntries.RemoveAt(index);
_uploadComponent.Files.RemoveAt(index);
Model.ArtifactEntries.RemoveAt(data.index);
_uploadComponent.RemoveFile(data.filename);
StateHasChanged();
}
}

View File

@@ -96,7 +96,7 @@
<MudDivider DividerType="DividerType.Middle"></MudDivider>
<ChipContainer T="DateTime" @ref="_assocaitedDatesChipContainer" @bind-Items="Model.AssociatedDates" DisplayFunc="date => date.ToShortDateString()">
<InputContent>
<MudDatePicker @bind-Date=_associatedDateInputValue>
<MudDatePicker @bind-Date=_associatedDateInputValue MinDate="new DateTime(1000, 1, 1)">
</MudDatePicker>
</InputContent>
<SubmitButton>
@@ -149,7 +149,7 @@
For="@(() => Model.FileTextContent)"></MudTextField>
<MudText Typo=Typo.h6 Color="Color.Primary">Additional files</MudText>
<UploadDropBox FilesUploaded="OnFilesUploaded"></UploadDropBox>
<UploadDropBox @ref=_uploadDropBox FilesUploaded="OnFilesUploaded"></UploadDropBox>
</MudPaper>
@@ -170,7 +170,7 @@
public required int ArtifactEntryIndex {get; set;}
[Parameter]
public EventCallback<int> OnEntryDeletedClicked { get; set; }
public EventCallback<(int index, string filename)> OnEntryDeletedClicked { get; set; }
private ChipContainer<string> _tagsChipContainer;
@@ -198,6 +198,23 @@
public List<ValidationResult> ValidationResults { get; private set; } = [];
public UploadDropBox _uploadDropBox = default!;
protected override Task OnParametersSetAsync()
{
if (_uploadDropBox is not null && Model is not null && Model.Files is not null)
{
_uploadDropBox.ExistingFiles = Model.Files.GetRange(1, Model.Files.Count - 1);
}
if (Model.Files is not null && Model.Files.Any())
{
MainFilePath = Model.Files[0];
}
return base.OnParametersSetAsync();
}
public async Task OnInputsChanged()
{
// 1. Clear previous validation errors
@@ -217,12 +234,17 @@
{
if (MainFilePath is not null)
{
var oldFiles = Model.Files.GetRange(1, Model.Files.Count - 1);
Model.Files = [MainFilePath];
Model.Files.AddRange(oldFiles);
Model.Files.AddRange(filePathListings);
} else
{
Model.Files = [];
}
Model.Files.AddRange(filePathListings);
StateHasChanged();
}
private async Task OnFilesCleared()
@@ -296,6 +318,6 @@
}
private async Task OnDeleteEntryClicked(MouseEventArgs args)
{
await OnEntryDeletedClicked.InvokeAsync(ArtifactEntryIndex);
await OnEntryDeletedClicked.InvokeAsync((ArtifactEntryIndex, MainFilePath.OriginalName));
}
}

View File

@@ -6,6 +6,11 @@ using System.ComponentModel.DataAnnotations;
public class ArtifactEntryValidationModel
{
/// <summary>
/// Used when translating between the validation model and the database model
/// </summary>
public int? Id { get; set; }
[Required(AllowEmptyStrings = false, ErrorMessage = "An artifact numbering must be supplied")]
public string? ArtifactNumber { get; set; }
@@ -33,14 +38,8 @@ public class ArtifactEntryValidationModel
public string? FileTextContent { get; set; }
public List<ArtifactEntry> RelatedArtifacts { get; set; } = [];
/*
public IEnumerable<ValidationResult> Validate(ValidationContext context)
{
}
*/
public bool IsPublicallyVisible { get; set; }
public bool IsPublicallyVisible { get; set; } = true;
public ArtifactEntry ToArtifactEntry(ArtifactGrouping? parent = null)
{
@@ -59,10 +58,9 @@ public class ArtifactEntryValidationModel
defects.Add(new ArtifactDefect() { Description=defect});
}
var entry = new ArtifactEntry()
{
Id = Id ?? 0,
Files = Files,
Type = new DataAccess.ArtifactType() { Name = Type },
ArtifactNumber = ArtifactNumber,

View File

@@ -26,7 +26,7 @@ public class ArtifactGroupingValidationModel : IValidatableObject
public List<ArtifactEntryValidationModel> ArtifactEntries { get; set; } = new();
public bool IsPublicallyVisible { get; set; }
public bool IsPublicallyVisible { get; set; } = true;
public ArtifactGrouping ToArtifactGrouping()
{
@@ -75,6 +75,7 @@ public class ArtifactGroupingValidationModel : IValidatableObject
var validationModel = new ArtifactEntryValidationModel()
{
Id = entry.Id,
Title = entry.Title,
StorageLocation = entry.StorageLocation.Location,
ArtifactNumber = entry.ArtifactNumber,
@@ -131,7 +132,7 @@ public class ArtifactGroupingValidationModel : IValidatableObject
}
}
if (ArtifactEntries.IsNullOrEmpty())
if (ArtifactEntries is null || ArtifactEntries.Count == 0)
{
yield return new ValidationResult("Must upload one or more files");
}

View File

@@ -29,7 +29,7 @@ public class CategoryValidationModel
public IEnumerable<ValidationResult> Validate(ValidationContext context)
{
if (FieldNames.IsNullOrEmpty() || FieldDescriptions.IsNullOrEmpty())
if ((FieldNames is null || FieldNames.Count == 0) || (FieldDescriptions is null || FieldDescriptions.Count == 0))
{
yield return new ValidationResult(
"Either the FieldNames or FieldDescriptions were null or empty. At least one is required",

View File

@@ -1,5 +1,85 @@
<h3>ArchiveEntryDisplay</h3>
@using OpenArchival.Blazor.FileViewer
<MudPaper Class="pa-4 ma-2 rounded" Elevation="3">
<MudGrid Spacing="2">
<MudItem lg="8" xs="12" Class="d-flex align-center justify-center flex-column">
<MudText Class="d-flex" Typo=Typo.h6>@ArtifactEntry.Title</MudText>
<FileViewerCarousel FilePathListings="ArtifactEntry.Files" MaxHeight="350" ShowUnsupportedFiles=true></FileViewerCarousel>
</MudItem>
<MudItem lg="4" xs="12">
<MudText Typo="Typo.h6">Artifact Identifier</MudText>
<MudDivider></MudDivider>
<MudText Typo="Typo.caption">@ArtifactEntry.ArtifactIdentifier</MudText>
<MudText Typo="Typo.h6">Primary Artifact Type</MudText>
<MudDivider></MudDivider>
<MudText Typo="Typo.caption">@ArtifactEntry.Type.Name</MudText>
@if (!string.IsNullOrEmpty(ArtifactEntry.StorageLocation.Location))
{
<MudText Typo="Typo.h6">Storage Location</MudText>
<MudDivider></MudDivider>
<MudText Typo="Typo.caption">@ArtifactEntry.StorageLocation.Location</MudText>
}
@if (ArtifactEntry.Tags.Count > 0)
{
<MudText Typo="Typo.h6">Tags</MudText>
<MudDivider></MudDivider>
<OpenArchival.Blazor.Components.CustomComponents.ChipContainer DeleteEnabled=false @bind-Items="ArtifactEntry.Tags"></OpenArchival.Blazor.Components.CustomComponents.ChipContainer>
}
@if (ArtifactEntry.ListedNames.Count > 0)
{
<MudText Typo="Typo.h6">Listed Names</MudText>
<MudDivider></MudDivider>
<OpenArchival.Blazor.Components.CustomComponents.ChipContainer DeleteEnabled=false @bind-Items="ArtifactEntry.ListedNames"></OpenArchival.Blazor.Components.CustomComponents.ChipContainer>
}
@if (ArtifactEntry.AssociatedDates.Count > 0)
{
<MudText Typo="Typo.h6">Associated Dates</MudText>
<MudDivider></MudDivider>
<OpenArchival.Blazor.Components.CustomComponents.ChipContainer DeleteEnabled=false @bind-Items="ArtifactEntry.AssociatedDates" DisplayFunc="@(date => date.ToString("d"))"></OpenArchival.Blazor.Components.CustomComponents.ChipContainer>
}
</MudItem>
</MudGrid>
<MudText Class="mt-4" Typo="Typo.h6">Description</MudText>
<MudDivider></MudDivider>
<MudText Typo="Typo.body1">@ArtifactEntry.Description</MudText>
<MudExpansionPanel Text="Downloads">
<MudList T="string">
@foreach (FilePathListing file in ArtifactEntry.Files)
{
<MudListItem Icon="@Icons.Material.Filled.Download" IconColor="Color.Primary" OnClick="() => OnFileDownloadClicked(file)">@file.OriginalName</MudListItem>
}
</MudList>
</MudExpansionPanel>
</MudPaper>
@inject IJSRuntime JSRuntime
@inject ISnackbar Snackbar
@code {
[Parameter]
public required ArtifactEntry ArtifactEntry { get; set; }
private async Task OnFileDownloadClicked(FilePathListing file)
{
try
{
byte[] fileBytes = await File.ReadAllBytesAsync(file.Path);
string mimeType = "";
await JSRuntime.InvokeVoidAsync("downloadFileFromBytes", file.OriginalName, mimeType, Convert.ToBase64String(fileBytes));
}
catch (Exception ex)
{
Snackbar.Add($"Failed to download file {file.OriginalName}", Severity.Error);
throw ex;
}
}
}

View File

@@ -1,12 +1,55 @@
@page "/archive/{GroupingIdString}"
@using OpenArchival.DataAccess;
@using OpenArchival.Blazor.FileViewer
@inject IArtifactGroupingProvider GroupingProvider;
@inject NavigationManager NavigationManager;
@if (_artifactGrouping is not null)
{
<MudText Typo="Typo.h1">@_artifactGrouping.Title</MudText>
<MudContainer MaxWidth="MaxWidth.Large">
<MudPaper Class="pa-4 ma-2 rounded d-flex justify-center" Elevation="3">
<MudText Typo="Typo.h3">@_artifactGrouping.Title</MudText>
</MudPaper>
<MudPaper Class="pa-4 ma-2 rounded d-flex justify-center" Elevation="3">
@*<MudImage Class="d-flex justify-center" Src="https://dummyimage.com/600x400/000/fff"></MudImage>*@
<FileViewerCarousel FilePathListings="_artifactGrouping.ChildFilePathListings" MaxHeight="500" ShowUnsupportedFiles=false></FileViewerCarousel>
</MudPaper>
<MudGrid Spacing="2">
<MudItem xs="8">
<MudPaper Style="height: 100%;" Class="pa-4 ma-2 rounded" Elevation="3">
<MudText Typo="Typo.h6">Description</MudText>
<MudDivider></MudDivider>
<MudText Typo="Typo.body2">@_artifactGrouping.Description</MudText>
</MudPaper>
</MudItem>
<MudItem xs="4">
<MudPaper Style="height: 100%;" Class="pa-4 ma-2 rounded" Elevation="3">
<MudText Typo="Typo.h6">Artifact Identifier</MudText>
<MudDivider></MudDivider>
<MudText Typo="Typo.caption">@_artifactGrouping.ArtifactGroupingIdentifier</MudText>
<MudText Typo="Typo.h6">Primary Artifact Category</MudText>
<MudDivider></MudDivider>
<MudText Typo="Typo.caption">@_artifactGrouping.Category.Name</MudText>
<MudText Typo="Typo.h6">Primary Artifact Type</MudText>
<MudDivider></MudDivider>
<MudText Typo="Typo.caption">@_artifactGrouping.Type.Name</MudText>
</MudPaper>
</MudItem>
</MudGrid>
<MudPaper Class="pa-4 mt-8 ma-2 rounded" Elevation="3">
@foreach (ArtifactEntry child in _artifactGrouping.ChildArtifactEntries) {
<ArchiveEntryDisplay ArtifactEntry="child"></ArchiveEntryDisplay>
}
</MudPaper>
</MudContainer>
}
@code {

View File

@@ -1,5 +0,0 @@
<h3>FileDisplayBase</h3>
@code {
}

View File

@@ -0,0 +1,34 @@
@if (File is not null)
{
<MudImage Fluid="true" Src="@File.Path" Alt="Swedish Farm House" Class="rounded-lg"/>
}
@code {
[Parameter]
public required FilePathListing File { get; set; }
/// <summary>
/// Sets the width of the image box while it loads
/// </summary>
[Parameter]
public int Width { get; set; } = 600;
/// <summary>
/// Sets the height of the image box while it loads
/// </summary>
[Parameter]
public int Height { get; set; } = 400;
[Parameter]
public string AltText { get; set; } = "";
protected override Task OnParametersSetAsync()
{
if (File is not null || !string.IsNullOrEmpty(AltText))
{
StateHasChanged();
}
return base.OnParametersSetAsync();
}
}

View File

@@ -0,0 +1,46 @@
using OpenArchival.Blazor.Components.Pages.ArchiveDisplay;
using System.Collections.Generic;
using System.Collections.Specialized;
namespace OpenArchival.Blazor;
public class FileDisplayComponentFactory
{
private Dictionary<string, Type> _extensionToComponents { get; set; } = [];
public FileDisplayComponentFactory()
{
// Supported image file types taken from https://developer.mozilla.org/en-US/docs/Web/Media/Guides/Formats/Image_types
RegisterComponent<FileDisplayImage>(".apng");
RegisterComponent<FileDisplayImage>(".png");
RegisterComponent<FileDisplayImage>(".avif");
RegisterComponent<FileDisplayImage>(".gif");
RegisterComponent<FileDisplayImage>(".jpg");
RegisterComponent<FileDisplayImage>(".jpeg");
RegisterComponent<FileDisplayImage>(".jfif");
RegisterComponent<FileDisplayImage>(".pjpeg");
RegisterComponent<FileDisplayImage>(".pjg");
RegisterComponent<FileDisplayImage>(".png");
RegisterComponent<FileDisplayImage>(".svg");
RegisterComponent<FileDisplayImage>(".webp");
}
private string GetExtensionKey(string pathOrExtension)
{
return Path.GetExtension(pathOrExtension).ToUpperInvariant();
}
public bool RegisterComponent<ComponentType>(string filenameOrExtension) where ComponentType : IFileDisplayComponent
{
string extensionString = GetExtensionKey(filenameOrExtension);
_extensionToComponents.Add(extensionString, typeof(ComponentType));
return true;
}
public Type? GetDisplayComponentType(string filenameOrExtension) {
var result = _extensionToComponents.TryGetValue(GetExtensionKey(filenameOrExtension), out var component);
return (result) ? component : null;
}
}

View File

@@ -1,5 +1,7 @@
<h3>FileDisplayImage</h3>
@implements IFileDisplayComponent
<h3>FileDisplayImage</h3>
@code {
[Parameter]
public required FilePathListing FilePath { get; set; }
}

View File

@@ -1,5 +1,8 @@
namespace OpenArchival.Blazor;
using OpenArchival.DataAccess;
namespace OpenArchival.Blazor;
public interface IFileDisplayComponent
{
public FilePathListing FilePath { get; set; }
}

View File

@@ -1,5 +1,7 @@
@using OpenArchival.Blazor.Components.Account.Shared
<Router AppAssembly="typeof(Program).Assembly">
<Router AppAssembly="typeof(Program).Assembly"
AdditionalAssemblies="new[] {typeof(OpenArchival.Blazor.AdminPages.ArchiveConfiguration).Assembly}">
<Found Context="routeData">
<AuthorizeRouteView RouteData="routeData" DefaultLayout="typeof(Layout.MainLayout)">
<NotAuthorized>

View File

@@ -0,0 +1,53 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using OpenArchival.DataAccess; // Assuming your DbContext or service is here
[Route("api/[controller]")]
[ApiController]
public class FilesController : ControllerBase
{
// Inject your database context or a service to find file paths
private readonly IDbContextFactory<ApplicationDbContext> _context;
public FilesController(IDbContextFactory<ApplicationDbContext> dbFactory)
{
_context = dbFactory;
}
[HttpGet("{id}")]
public async Task<IActionResult> GetFile(int id)
{
await using var context = await _context.CreateDbContextAsync();
FilePathListing fileRecord = await context.ArtifactFilePaths.FindAsync(id);
if (fileRecord == null)
{
return NotFound();
}
var physicalPath = fileRecord.Path;
if (!System.IO.File.Exists(physicalPath))
{
return NotFound();
}
var fileStream = new FileStream(physicalPath, FileMode.Open, FileAccess.Read);
return new FileStreamResult(fileStream, GetMimeType(physicalPath));
}
private static string GetMimeType(string filePath)
{
var extension = Path.GetExtension(filePath).ToLowerInvariant();
return extension switch
{
".jpg" => "image/jpeg",
".jpeg" => "image/jpeg",
".png" => "image/png",
".gif" => "image/gif",
_ => "application/octet-stream", // Default for unknown file types
};
}
}

View File

@@ -15,6 +15,7 @@ WORKDIR /src
COPY ["nuget.config", "."]
COPY ["OpenArchival.Blazor/OpenArchival.Blazor.csproj", "OpenArchival.Blazor/"]
COPY ["OpenArchival.DataAccess/OpenArchival.DataAccess.csproj", "OpenArchival.DataAccess/"]
COPY ["OpenArchival.FileViewer/OpenArchival.FileViewer.csproj", "OpenArchival.FileViewer/"]
RUN dotnet restore "./OpenArchival.Blazor/OpenArchival.Blazor.csproj"
COPY . .
WORKDIR "/src/OpenArchival.Blazor"

View File

@@ -14,7 +14,7 @@
<PackageReference Include="CodeBeam.MudExtensions" Version="6.3.0" />
<PackageReference Include="Dapper" Version="2.1.66" />
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="9.*" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.8" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.9" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.*" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="9.*" />
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.22.1" />
@@ -22,10 +22,14 @@
<PackageReference Include="Npgsql" Version="9.0.3" />
<PackageReference Include="Npgsql.DependencyInjection" Version="9.0.3" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.4" />
<PackageReference Include="System.Collections" Version="4.3.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\OpenArchival.Blazor.AdminPages\OpenArchival.Blazor.AdminPages.csproj" />
<ProjectReference Include="..\OpenArchival.Blazor.CustomComponents\OpenArchival.Blazor.CustomComponents.csproj" />
<ProjectReference Include="..\OpenArchival.Blazor.FileViewer\OpenArchival.Blazor.FileViewer.csproj" />
<ProjectReference Include="..\OpenArchival.DataAccess\OpenArchival.DataAccess.csproj" />
</ItemGroup>

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

View File

@@ -0,0 +1,196 @@
# Language part removed. With clang-format >=20.1, the C and Cpp are separately handled,
# so either there is no language at all, or we need to create 2 formats for C and Cpp, separately
---
# Language: Cpp
# BasedOnStyle: LLVM
AccessModifierOffset: -2
AlignAfterOpenBracket: Align
AlignArrayOfStructures: None
AlignConsecutiveMacros:
Enabled: true
AcrossEmptyLines: true
AcrossComments: true
AlignConsecutiveAssignments: None
AlignConsecutiveBitFields:
Enabled: true
AcrossEmptyLines: true
AcrossComments: true
AlignConsecutiveDeclarations: None
AlignEscapedNewlines: Right
AlignOperands: Align
SortIncludes: true
InsertBraces: true # Control statements must have curly brackets
AlignTrailingComments: true
AllowAllArgumentsOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortEnumsOnASingleLine: true
AllowShortBlocksOnASingleLine: Empty
AllowShortCaseLabelsOnASingleLine: true
AllowShortFunctionsOnASingleLine: All
AllowShortLambdasOnASingleLine: All
AllowShortIfStatementsOnASingleLine: Never
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: AllDefinitions
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: Yes
AttributeMacros:
- __capability
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
AfterCaseLabel: false
AfterClass: false
AfterControlStatement: Never
AfterEnum: false
AfterFunction: false
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
AfterExternBlock: false
BeforeCatch: false
BeforeElse: false
BeforeLambdaBody: false
BeforeWhile: false
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakBeforeBinaryOperators: NonAssignment
BreakBeforeConceptDeclarations: true
BreakBeforeBraces: Attach
BreakBeforeInheritanceComma: false
BreakInheritanceList: BeforeColon
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeColon
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
ColumnLimit: 120
CommentPragmas: "^ IWYU pragma:"
QualifierAlignment: Leave
CompactNamespaces: false
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DeriveLineEnding: true
DerivePointerAlignment: false
DisableFormat: false
EmptyLineAfterAccessModifier: Never
EmptyLineBeforeAccessModifier: LogicalBlock
ExperimentalAutoDetectBinPacking: false
PackConstructorInitializers: BinPack
BasedOnStyle: ""
ConstructorInitializerAllOnOneLineOrOnePerLine: false
AllowAllConstructorInitializersOnNextLine: true
FixNamespaceComments: true
ForEachMacros:
- foreach
- Q_FOREACH
- BOOST_FOREACH
IfMacros:
- KJ_IF_MAYBE
IncludeBlocks: Preserve
IncludeCategories:
- Regex: "^<(.*)>"
Priority: 0
- Regex: '^"(.*)"'
Priority: 1
- Regex: "(.*)"
Priority: 2
IncludeIsMainRegex: "(Test)?$"
IncludeIsMainSourceRegex: ""
IndentAccessModifiers: false
IndentCaseLabels: true
IndentCaseBlocks: false
IndentGotoLabels: true
IndentPPDirectives: None
IndentExternBlock: AfterExternBlock
IndentRequires: true
IndentWidth: 4
IndentWrappedFunctionNames: false
InsertTrailingCommas: None
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: true
LambdaBodyIndentation: Signature
MacroBlockBegin: ""
MacroBlockEnd: ""
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBinPackProtocolList: Auto
ObjCBlockIndentWidth: 2
ObjCBreakBeforeNestedBlockParam: true
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakOpenParenthesis: 0
PenaltyBreakString: 1000
PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60
PenaltyIndentedWhitespace: 0
PointerAlignment: Left
PPIndentWidth: -1
ReferenceAlignment: Pointer
ReflowComments: false
RemoveBracesLLVM: false
SeparateDefinitionBlocks: Always
ShortNamespaceLines: 1
SortJavaStaticImport: Before
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeCaseColon: false
SpaceBeforeParens: ControlStatements
SpaceBeforeParensOptions:
AfterControlStatements: true
AfterForeachMacros: true
AfterFunctionDefinitionName: false
AfterFunctionDeclarationName: false
AfterIfMacros: true
AfterOverloadedOperator: false
BeforeNonEmptyParentheses: false
SpaceAroundPointerQualifiers: Default
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyBlock: false
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: Never
SpacesInConditionalStatement: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInLineCommentPrefix:
Minimum: 1
Maximum: -1
SpacesInParentheses: false
SpacesInSquareBrackets: false
SpaceBeforeSquareBrackets: false
BitFieldColonSpacing: Both
Standard: Latest
StatementAttributeLikeMacros:
- Q_EMIT
StatementMacros:
- Q_UNUSED
- QT_REQUIRE_VERSION
TabWidth: 8
UseCRLF: false
UseTab: Never
WhitespaceSensitiveMacros:
- STRINGIZE
- PP_STRINGIZE
- BOOST_PP_STRINGIZE
- NS_SWIFT_NAME
- CF_SWIFT_NAME
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
---

View File

@@ -0,0 +1,10 @@
[Interface]
PrivateKey = SHZ+vDoQyTFLr+sEYBY8r0TXMFnMtsMaA5pcxcKSUWI=
Address = 10.88.203.3/24,fd11:5ee:bad:c0de::a58:cb03/64
DNS = 10.88.203.1
[Peer]
PublicKey = FVK/Fqod0nha+1l1sGZi2cx1LUU+Ihj6IKF4+g4dmA0=
PresharedKey = UdNe7MRgwjEBZ05wg+x7kXEfZJGOCggvtSwCYvMhU4s=
Endpoint = pihole.vtallen.com:51820
AllowedIPs = 0.0.0.0/0, ::0/0

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

View File

@@ -0,0 +1,10 @@
[Interface]
PrivateKey = SHZ+vDoQyTFLr+sEYBY8r0TXMFnMtsMaA5pcxcKSUWI=
Address = 10.88.203.3/24,fd11:5ee:bad:c0de::a58:cb03/64
DNS = 10.88.203.1
[Peer]
PublicKey = FVK/Fqod0nha+1l1sGZi2cx1LUU+Ihj6IKF4+g4dmA0=
PresharedKey = UdNe7MRgwjEBZ05wg+x7kXEfZJGOCggvtSwCYvMhU4s=
Endpoint = pihole.vtallen.com:51820
AllowedIPs = 0.0.0.0/0, ::0/0

View File

@@ -0,0 +1,10 @@
[Interface]
PrivateKey = SHZ+vDoQyTFLr+sEYBY8r0TXMFnMtsMaA5pcxcKSUWI=
Address = 10.88.203.3/24,fd11:5ee:bad:c0de::a58:cb03/64
DNS = 10.88.203.1
[Peer]
PublicKey = FVK/Fqod0nha+1l1sGZi2cx1LUU+Ihj6IKF4+g4dmA0=
PresharedKey = UdNe7MRgwjEBZ05wg+x7kXEfZJGOCggvtSwCYvMhU4s=
Endpoint = pihole.vtallen.com:51820
AllowedIPs = 0.0.0.0/0, ::0/0

View File

@@ -0,0 +1,10 @@
[Interface]
PrivateKey = SHZ+vDoQyTFLr+sEYBY8r0TXMFnMtsMaA5pcxcKSUWI=
Address = 10.88.203.3/24,fd11:5ee:bad:c0de::a58:cb03/64
DNS = 10.88.203.1
[Peer]
PublicKey = FVK/Fqod0nha+1l1sGZi2cx1LUU+Ihj6IKF4+g4dmA0=
PresharedKey = UdNe7MRgwjEBZ05wg+x7kXEfZJGOCggvtSwCYvMhU4s=
Endpoint = pihole.vtallen.com:51820
AllowedIPs = 0.0.0.0/0, ::0/0

View File

@@ -0,0 +1,10 @@
[Interface]
PrivateKey = SHZ+vDoQyTFLr+sEYBY8r0TXMFnMtsMaA5pcxcKSUWI=
Address = 10.88.203.3/24,fd11:5ee:bad:c0de::a58:cb03/64
DNS = 10.88.203.1
[Peer]
PublicKey = FVK/Fqod0nha+1l1sGZi2cx1LUU+Ihj6IKF4+g4dmA0=
PresharedKey = UdNe7MRgwjEBZ05wg+x7kXEfZJGOCggvtSwCYvMhU4s=
Endpoint = pihole.vtallen.com:51820
AllowedIPs = 0.0.0.0/0, ::0/0

View File

@@ -0,0 +1,10 @@
[Interface]
PrivateKey = SHZ+vDoQyTFLr+sEYBY8r0TXMFnMtsMaA5pcxcKSUWI=
Address = 10.88.203.3/24,fd11:5ee:bad:c0de::a58:cb03/64
DNS = 10.88.203.1
[Peer]
PublicKey = FVK/Fqod0nha+1l1sGZi2cx1LUU+Ihj6IKF4+g4dmA0=
PresharedKey = UdNe7MRgwjEBZ05wg+x7kXEfZJGOCggvtSwCYvMhU4s=
Endpoint = pihole.vtallen.com:51820
AllowedIPs = 0.0.0.0/0, ::0/0

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

View File

@@ -0,0 +1,10 @@
[Interface]
PrivateKey = SHZ+vDoQyTFLr+sEYBY8r0TXMFnMtsMaA5pcxcKSUWI=
Address = 10.88.203.3/24,fd11:5ee:bad:c0de::a58:cb03/64
DNS = 10.88.203.1
[Peer]
PublicKey = FVK/Fqod0nha+1l1sGZi2cx1LUU+Ihj6IKF4+g4dmA0=
PresharedKey = UdNe7MRgwjEBZ05wg+x7kXEfZJGOCggvtSwCYvMhU4s=
Endpoint = pihole.vtallen.com:51820
AllowedIPs = 0.0.0.0/0, ::0/0

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

View File

@@ -0,0 +1,10 @@
[Interface]
PrivateKey = SHZ+vDoQyTFLr+sEYBY8r0TXMFnMtsMaA5pcxcKSUWI=
Address = 10.88.203.3/24,fd11:5ee:bad:c0de::a58:cb03/64
DNS = 10.88.203.1
[Peer]
PublicKey = FVK/Fqod0nha+1l1sGZi2cx1LUU+Ihj6IKF4+g4dmA0=
PresharedKey = UdNe7MRgwjEBZ05wg+x7kXEfZJGOCggvtSwCYvMhU4s=
Endpoint = pihole.vtallen.com:51820
AllowedIPs = 0.0.0.0/0, ::0/0

View File

@@ -0,0 +1,10 @@
[Interface]
PrivateKey = SHZ+vDoQyTFLr+sEYBY8r0TXMFnMtsMaA5pcxcKSUWI=
Address = 10.88.203.3/24,fd11:5ee:bad:c0de::a58:cb03/64
DNS = 10.88.203.1
[Peer]
PublicKey = FVK/Fqod0nha+1l1sGZi2cx1LUU+Ihj6IKF4+g4dmA0=
PresharedKey = UdNe7MRgwjEBZ05wg+x7kXEfZJGOCggvtSwCYvMhU4s=
Endpoint = pihole.vtallen.com:51820
AllowedIPs = 0.0.0.0/0, ::0/0

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

View File

@@ -0,0 +1,10 @@
[Interface]
PrivateKey = SHZ+vDoQyTFLr+sEYBY8r0TXMFnMtsMaA5pcxcKSUWI=
Address = 10.88.203.3/24,fd11:5ee:bad:c0de::a58:cb03/64
DNS = 10.88.203.1
[Peer]
PublicKey = FVK/Fqod0nha+1l1sGZi2cx1LUU+Ihj6IKF4+g4dmA0=
PresharedKey = UdNe7MRgwjEBZ05wg+x7kXEfZJGOCggvtSwCYvMhU4s=
Endpoint = pihole.vtallen.com:51820
AllowedIPs = 0.0.0.0/0, ::0/0

View File

@@ -0,0 +1,10 @@
[Interface]
PrivateKey = SHZ+vDoQyTFLr+sEYBY8r0TXMFnMtsMaA5pcxcKSUWI=
Address = 10.88.203.3/24,fd11:5ee:bad:c0de::a58:cb03/64
DNS = 10.88.203.1
[Peer]
PublicKey = FVK/Fqod0nha+1l1sGZi2cx1LUU+Ihj6IKF4+g4dmA0=
PresharedKey = UdNe7MRgwjEBZ05wg+x7kXEfZJGOCggvtSwCYvMhU4s=
Endpoint = pihole.vtallen.com:51820
AllowedIPs = 0.0.0.0/0, ::0/0

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

View File

@@ -0,0 +1,10 @@
[Interface]
PrivateKey = SHZ+vDoQyTFLr+sEYBY8r0TXMFnMtsMaA5pcxcKSUWI=
Address = 10.88.203.3/24,fd11:5ee:bad:c0de::a58:cb03/64
DNS = 10.88.203.1
[Peer]
PublicKey = FVK/Fqod0nha+1l1sGZi2cx1LUU+Ihj6IKF4+g4dmA0=
PresharedKey = UdNe7MRgwjEBZ05wg+x7kXEfZJGOCggvtSwCYvMhU4s=
Endpoint = pihole.vtallen.com:51820
AllowedIPs = 0.0.0.0/0, ::0/0

View File

@@ -0,0 +1,10 @@
[Interface]
PrivateKey = SHZ+vDoQyTFLr+sEYBY8r0TXMFnMtsMaA5pcxcKSUWI=
Address = 10.88.203.3/24,fd11:5ee:bad:c0de::a58:cb03/64
DNS = 10.88.203.1
[Peer]
PublicKey = FVK/Fqod0nha+1l1sGZi2cx1LUU+Ihj6IKF4+g4dmA0=
PresharedKey = UdNe7MRgwjEBZ05wg+x7kXEfZJGOCggvtSwCYvMhU4s=
Endpoint = pihole.vtallen.com:51820
AllowedIPs = 0.0.0.0/0, ::0/0

View File

@@ -0,0 +1,10 @@
[Interface]
PrivateKey = SHZ+vDoQyTFLr+sEYBY8r0TXMFnMtsMaA5pcxcKSUWI=
Address = 10.88.203.3/24,fd11:5ee:bad:c0de::a58:cb03/64
DNS = 10.88.203.1
[Peer]
PublicKey = FVK/Fqod0nha+1l1sGZi2cx1LUU+Ihj6IKF4+g4dmA0=
PresharedKey = UdNe7MRgwjEBZ05wg+x7kXEfZJGOCggvtSwCYvMhU4s=
Endpoint = pihole.vtallen.com:51820
AllowedIPs = 0.0.0.0/0, ::0/0

View File

@@ -14,6 +14,7 @@ builder.Services.AddRazorComponents()
.AddInteractiveServerComponents();
builder.Services.AddMudServices();
builder.Services.AddMudExtensions();
builder.Services.AddControllers();
// --- Database & Identity Configuration ---
// Get the single connection string for your PostgreSQL database.
@@ -69,6 +70,8 @@ builder.Services.AddLogging();
var app = builder.Build();
app.MapControllers();
using (var scope = app.Services.CreateScope())
{
var serviceProvider = scope.ServiceProvider;

File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show More