Обновления веб-отображения

This commit is contained in:
2025-10-07 00:12:20 +04:00
parent aecabfbb56
commit 5df20825c7
12 changed files with 377 additions and 201 deletions
+1 -1
View File
@@ -134,7 +134,7 @@ public class FullEntity
.Include(d => d.DeitySpells) .Include(d => d.DeitySpells)
.ThenInclude(ds => ds.Spell) .ThenInclude(ds => ds.Spell)
.Include(d => d.DeityWeapons) .Include(d => d.DeityWeapons)
.ThenInclude(dw => dw.Weapon) //.ThenInclude(dw => dw.Weapon)
.Include(d => d.CategoryEntity) .Include(d => d.CategoryEntity)
.Include(d => d.Skills) .Include(d => d.Skills)
), ),
+247
View File
@@ -0,0 +1,247 @@
using System.Collections;
using System.ComponentModel;
using Pf2e.Database.Model;
using Pf2e.Database.Model.Base.Keywords;
using Pf2e.Database.Model.Base.Source;
using Pf2e.Database.Model.Base.Targets;
using Pf2e.Database.Model.Common.I18n;
using Pf2e.Database.Model.Enum;
namespace Pf2e.Web.Helpers;
public class EntityFieldFormatter
{
/// <summary>
/// Форматировать значение для отображения.
/// </summary>
public string? FormatValue(object? value)
{
if (value == null)
return null;
Type type = value.GetType();
foreach (ValueFormatter formatter in _formatters)
{
if (formatter.CanFormat(type))
{
return formatter.Format(value);
}
}
return null;
}
/// <summary>
/// Абстрактный класс форматтера значений.
/// </summary>
private abstract class ValueFormatter
{
/// <summary>
/// Проверяет, может ли форматтер обработать указанный тип.
/// </summary>
/// <param name="type">Тип значения.</param>
/// <returns><c>true</c>, если форматтер может обработать тип, иначе <c>false</c>.</returns>
public abstract bool CanFormat(Type type);
/// <summary>
/// Форматирует значение для отображения.
/// </summary>
/// <param name="value">Значение для форматирования.</param>
/// <returns>Строковое представление отформатированного значения.</returns>
public abstract string Format(object value);
}
/// <summary>
/// Форматтер для конкретного типа.
/// </summary>
/// <typeparam name="T">Тип значения.</typeparam>
/// <param name="formatter">Функция форматирования значения.</param>
private class TypeValueFormatter<T>(Func<object, string> formatter) : ValueFormatter
{
public override bool CanFormat(Type type) => type == typeof(T);
public override string Format(object value) => formatter(value);
}
/// <summary>
/// Форматтер с пользовательскими функциями проверки и форматирования.
/// </summary>
/// <param name="checker">Функция проверки типа.</param>
/// <param name="formatter">Функция форматирования значения.</param>
private class CustomValueFormatter(Func<Type, bool> checker, Func<object, string> formatter)
: ValueFormatter
{
public override bool CanFormat(Type type) => checker(type);
public override string Format(object value) => formatter(value);
}
/// <summary>
/// Форматтер для коллекций.
/// </summary>
private class CollectionFormatter(EntityFieldFormatter fieldFormatter) : ValueFormatter
{
public override bool CanFormat(Type type) =>
typeof(IEnumerable).IsAssignableFrom(type) && type != typeof(string);
public override string Format(object value)
{
IEnumerable collection = (IEnumerable)value;
List<string> items = [];
foreach (object? item in collection)
{
string? itemDisplay = fieldFormatter.FormatValue(item);
items.Add(itemDisplay ?? "null");
}
return items.Count == 0 ? "(empty)" : string.Join("<br/>", items);
}
}
/// <summary>
/// Коллекция форматтеров.
/// </summary>
private readonly List<ValueFormatter> _formatters;
/// <summary>
/// Получить описание элемента перечисления из DescriptionAttribute.
/// </summary>
/// <param name="value">Элемент перечисления.</param>
/// <returns>Описание или имя элемента, если атрибут не найден.</returns>
private static string GetEnumDescription(Enum value)
{
Type type = value.GetType();
string name = Enum.GetName(type, value) ?? value.ToString();
System.Reflection.FieldInfo? field = type.GetField(name);
if (field == null)
return value.ToString();
if (
Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute))
is DescriptionAttribute attr
)
{
return attr.Description;
}
return value.ToString();
}
/// <summary>
/// Конструктор EntitySerializer.
/// </summary>
public EntityFieldFormatter()
{
_formatters =
[
// Форматтеры для перечислений
new CustomValueFormatter(
(type) => type.IsEnum,
(value) =>
{
Enum enumValue = (Enum)value;
string description = GetEnumDescription(enumValue);
return $"{description} ({enumValue})";
}
),
// Примитивные типы
new CustomValueFormatter(
(type) => type.IsPrimitive || type == typeof(string) || type == typeof(decimal),
(value) => value.ToString() ?? "null"
),
// LocaleString
new TypeValueFormatter<LocaleString>(
(value) =>
{
LocaleString localeString = (LocaleString)value;
List<string> items = [];
foreach (LocaleItem item in localeString)
{
items.Add($"{item.Locale}: {item.Value}");
}
return string.Join("<br/>", items);
}
),
// IEntity
new CustomValueFormatter(
(type) => typeof(IEntity).IsAssignableFrom(type),
(value) =>
{
IEntity entity = (IEntity)value;
EntityType entityType = entity.Entity.Type;
string typeName = PgNameHelper.GetPgName(entityType);
string slug = entity.Entity.Slug;
string name = entity.Entity.Name[LocaleType.English];
return $"<a href=\"/{typeName}/{slug}\">{name}</a>";
}
),
// EntitySource
new TypeValueFormatter<EntitySource>(
(value) =>
{
EntitySource entitySource = (EntitySource)value;
string sourceName = entitySource.Source.Name;
string suffix = !string.IsNullOrEmpty(entitySource.Suffix)
? $" ({entitySource.Suffix})"
: "";
string isRemaster = entitySource.IsRemaster ? " [Remaster]" : "";
return $"{sourceName}{suffix}{isRemaster}";
}
),
// Keyword
new TypeValueFormatter<Keyword>(
(value) =>
{
Keyword keyword = (Keyword)value;
string name = keyword.Name[LocaleType.English];
return $"{name}";
}
),
// KeywordAlias
new TypeValueFormatter<KeywordAlias>(
(value) =>
{
KeywordAlias alias = (KeywordAlias)value;
return $"{alias.Value}";
}
),
// ExternalTarget
new TypeValueFormatter<ExternalTarget>(
(value) =>
{
ExternalTarget target = (ExternalTarget)value;
return $"{target.Name} (Icon: {target.Icon}, Prefix: {target.Prefix})";
}
),
// EntityExternal
new TypeValueFormatter<EntityExternal>(
(value) =>
{
EntityExternal entityExternal = (EntityExternal)value;
string targetName = entityExternal.Target?.Name ?? "Unknown";
string externalId = !string.IsNullOrEmpty(entityExternal.ExternalId)
? $" ID: {entityExternal.ExternalId}"
: "";
string suffix = !string.IsNullOrEmpty(entityExternal.Suffix)
? $" Suffix: {entityExternal.Suffix}"
: "";
return $"{targetName}{externalId}{suffix}";
}
),
// Source
new TypeValueFormatter<Source>(
(value) =>
{
Source source = (Source)value;
string releaseDate = source.ReleaseDate?.ToString("yyyy-MM-dd") ?? "Unknown";
return $"{source.Name} (Category: {source.Category}, Release: {releaseDate})";
}
),
// Коллекции
new CollectionFormatter(this),
];
}
}
+20 -158
View File
@@ -1,10 +1,5 @@
using System.Collections;
using System.Reflection; using System.Reflection;
using Pf2e.Common; using Pf2e.Common;
using Pf2e.Database.Model;
using Pf2e.Database.Model.Base;
using Pf2e.Database.Model.Common.I18n;
using Pf2e.Database.Model.Enum;
namespace Pf2e.Web.Helpers; namespace Pf2e.Web.Helpers;
@@ -42,6 +37,11 @@ public class EntitySerializer
public bool IsImplemented { get; set; } = true; public bool IsImplemented { get; set; } = true;
} }
/// <summary>
/// Форматтер полей сущности.
/// </summary>
public EntityFieldFormatter FieldFormatter { get; } = new();
/// <summary> /// <summary>
/// Сериализовать FullEntity. /// Сериализовать FullEntity.
/// </summary> /// </summary>
@@ -65,11 +65,6 @@ public class EntitySerializer
result.Groups.Add(subEntityGroup); result.Groups.Add(subEntityGroup);
} }
// Группа для ссылок
FieldGroup referencesGroup = new() { Name = "Ссылки" };
AddReferencesToGroup(referencesGroup, fullEntity);
result.Groups.Add(referencesGroup);
return result; return result;
} }
@@ -87,162 +82,29 @@ public class EntitySerializer
if (property.Name == "Entity") if (property.Name == "Entity")
continue; continue;
FieldInfo fieldInfo = new() object? value = property.GetValue(obj);
{ FieldInfo fieldInfo = CreateFieldInfo(property, value);
Name = property.Name,
Type = GetTypeDisplayName(property.PropertyType),
Value = property.GetValue(obj),
};
// Обработка значения для отображения
var (displayValue, isImplemented) = FormatValue(fieldInfo.Value);
fieldInfo.DisplayValue = displayValue;
fieldInfo.IsImplemented = isImplemented;
group.Fields.Add(fieldInfo); group.Fields.Add(fieldInfo);
} }
} }
/// <summary> /// <summary>
/// Добавить ссылки в группу. /// Создать FieldInfo для свойства.
/// </summary> /// </summary>
private void AddReferencesToGroup(FieldGroup group, FullEntity fullEntity) /// <param name="property">Поле класса.</param>
/// <param name="value">Значение поля.</param>
/// <returns>Информация о поле.</returns>
private FieldInfo CreateFieldInfo(PropertyInfo property, object? value)
{ {
// Добавляем информацию о связанных сущностях string? displayValue = FieldFormatter.FormatValue(value);
Entity entity = fullEntity.Entity;
// Traits return new()
if (entity.Traits?.Any() == true)
{ {
var (displayValue, isImplemented) = FormatValue(entity.Traits); Name = property.Name,
group.Fields.Add( Type = property.PropertyType.Name,
new FieldInfo Value = value,
{ DisplayValue = displayValue ?? "null",
Name = "Traits", IsImplemented = displayValue is not null,
Type = "ICollection<Trait>", };
Value = entity.Traits,
DisplayValue = displayValue,
IsImplemented = isImplemented,
}
);
}
// Keywords
if (entity.Keywords?.Any() == true)
{
var (displayValue, isImplemented) = FormatValue(entity.Keywords);
group.Fields.Add(
new FieldInfo
{
Name = "Keywords",
Type = "ICollection<Keyword>",
Value = entity.Keywords,
DisplayValue = displayValue,
IsImplemented = isImplemented,
}
);
}
// Sources
if (entity.Sources?.Any() == true)
{
var (displayValue, isImplemented) = FormatValue(entity.Sources);
group.Fields.Add(
new FieldInfo
{
Name = "Sources",
Type = "ICollection<EntitySource>",
Value = entity.Sources,
DisplayValue = displayValue,
IsImplemented = isImplemented,
}
);
}
// Externals
if (entity.Externals?.Any() == true)
{
var (displayValue, isImplemented) = FormatValue(entity.Externals);
group.Fields.Add(
new()
{
Name = "Externals",
Type = "ICollection<EntityExternal>",
Value = entity.Externals,
DisplayValue = displayValue,
IsImplemented = isImplemented,
}
);
}
}
/// <summary>
/// Получить отображаемое имя типа.
/// </summary>
private string GetTypeDisplayName(Type type)
{
if (type.IsEnum)
return "enum";
return type.Name;
}
/// <summary>
/// Форматировать значение для отображения.
/// </summary>
private (string displayValue, bool isImplemented) FormatValue(object? value)
{
if (value == null)
return ("null", true);
Type type = value.GetType();
// Обработка перечислений
if (type.IsEnum)
{
Enum enumValue = (Enum)value;
return ($"{enumValue} ({(int)(object)enumValue})", true);
}
// Обработка примитивных типов
if (type.IsPrimitive || type == typeof(string) || type == typeof(decimal))
{
return (value.ToString() ?? "null", true);
}
// Обработка IEntity
if (typeof(IEntity).IsAssignableFrom(type))
{
var entity = (IEntity)value;
var entityType = entity.Entity.Type;
var typeName = PgNameHelper.GetPgName(entityType);
var slug = entity.Entity.Slug;
var name = entity.Entity.Name[LocaleType.English];
return ($"<a href=\"/{typeName}/{slug}\">{name}</a>", true);
}
// Обработка коллекций
if (typeof(IEnumerable).IsAssignableFrom(type) && type != typeof(string))
{
var collection = (IEnumerable)value;
var items = new List<string>();
bool allImplemented = true;
foreach (var item in collection)
{
var (itemDisplay, itemImplemented) = FormatValue(item);
items.Add(itemDisplay);
if (!itemImplemented)
allImplemented = false;
}
if (items.Count == 0)
return ("(empty)", true);
return (string.Join(", ", items), allImplemented);
}
// Для остальных сложных объектов
return ($"[{type.Name}] - НЕ РЕАЛИЗОВАНО", false);
} }
} }
+10 -3
View File
@@ -1,16 +1,23 @@
using System;
using System.Reflection; using System.Reflection;
using NpgsqlTypes; using NpgsqlTypes;
using Pf2e.Database.Model.Enum; using Pf2e.Database.Model.Enum;
namespace Pf2e.Web.Helpers namespace Pf2e.Web.Helpers
{ {
/// <summary>
/// Âñïîìîãàòåëüíûé êëàññ äëÿ ïîëó÷åíèÿ èìåí PostgresSQL èç ïåðå÷èñëåíèé.
/// </summary>
public static class PgNameHelper public static class PgNameHelper
{ {
/// <summary>
/// Ïîëó÷àåò èìÿ PostgresSQL äëÿ çàäàííîãî òèïà ñóùíîñòè.
/// </summary>
/// <param name="entityType">Òèï ñóùíîñòè.</param>
/// <returns>Ñòðîêîâîå ïðåäñòàâëåíèå èìåíè PostgresSQL.</returns>
public static string GetPgName(EntityType entityType) public static string GetPgName(EntityType entityType)
{ {
var fieldInfo = entityType.GetType().GetField(entityType.ToString()); FieldInfo? fieldInfo = entityType.GetType().GetField(entityType.ToString());
var pgNameAttribute = fieldInfo?.GetCustomAttribute<PgNameAttribute>(); PgNameAttribute? pgNameAttribute = fieldInfo?.GetCustomAttribute<PgNameAttribute>();
return pgNameAttribute?.PgName ?? entityType.ToString().ToLower(); return pgNameAttribute?.PgName ?? entityType.ToString().ToLower();
} }
} }
+7 -9
View File
@@ -1,4 +1,4 @@
@page "{type}/{slug}" @page "/{type}/{slug}"
@model Pf2e.Web.Pages.EntityModel @model Pf2e.Web.Pages.EntityModel
@{ @{
@@ -17,18 +17,16 @@
<dl class="row"> <dl class="row">
@foreach (var field in group.Fields) @foreach (var field in group.Fields)
{ {
<dt class="col-sm-3">@field.Name</dt> <dt class="col-sm-3">
<dd class="col-sm-9"> @field.Name
<span class="text-muted">[@field.Type]</span> <span class="text-muted">[@field.Type]</span>
@if (field.IsImplemented) </dt>
{ <dd class="col-sm-9">
@Html.Raw(field.DisplayValue) @if (!field.IsImplemented)
}
else
{ {
<span class="badge bg-warning text-dark">НЕ РЕАЛИЗОВАНО:</span> <span class="badge bg-warning text-dark">НЕ РЕАЛИЗОВАНО:</span>
@Html.Raw(field.DisplayValue)
} }
@Html.Raw(field.DisplayValue)
</dd> </dd>
} }
</dl> </dl>
+33 -7
View File
@@ -26,39 +26,65 @@ namespace Pf2e.Web.Pages
public IActionResult OnGet(string type, string slug) public IActionResult OnGet(string type, string slug)
{ {
// Добавим отладочную информацию // Добавим отладочную информацию
System.Diagnostics.Debug.WriteLine($"EntityModel.OnGet called with type: {type}, slug: {slug}"); System.Diagnostics.Debug.WriteLine(
$"EntityModel.OnGet called with type: {type}, slug: {slug}"
);
// Логируем в консоль для веб-сервера
Console.WriteLine($"EntityModel.OnGet called with type: {type}, slug: {slug}");
try try
{ {
// Получаем тип сущности // Получаем тип сущности
EntityType entityType = EntityTypeModel.Enum<EntityType>(type); EntityType entityType = EntityTypeModel.Enum<EntityType>(type);
System.Diagnostics.Debug.WriteLine($"EntityType resolved to: {entityType}"); System.Diagnostics.Debug.WriteLine($"EntityType resolved to: {entityType}");
Console.WriteLine($"EntityType resolved to: {entityType}");
// Находим сущность по slug и типу // Находим сущность по slug и типу
Entity? entity = _context.Entities.FirstOrDefault(e => Entity? entity = _context
e.Slug.ToLower() == slug.ToLower() && e.Type == entityType .Entities.AsNoTracking()
); .FirstOrDefault(e =>
e.Slug.ToLower() == slug.ToLower() && e.Type == entityType
);
if (entity == null) if (entity == null)
{ {
System.Diagnostics.Debug.WriteLine($"Entity not found: type={entityType}, slug={slug}"); System.Diagnostics.Debug.WriteLine(
$"Entity not found: type={entityType}, slug={slug}"
);
Console.WriteLine($"Entity not found: type={entityType}, slug={slug}");
return NotFound(); return NotFound();
} }
System.Diagnostics.Debug.WriteLine($"Entity found: {entity.Id} - {entity.Name[Pf2e.Database.Model.Common.I18n.LocaleType.English]}"); System.Diagnostics.Debug.WriteLine(
$"Entity found: {entity.Id} - {entity.Name[Pf2e.Database.Model.Common.I18n.LocaleType.English]}"
);
Console.WriteLine(
$"Entity found: {entity.Id} - {entity.Name[Pf2e.Database.Model.Common.I18n.LocaleType.English]}"
);
// Создаём FullEntity // Создаём FullEntity
FullEntity = new(_context, entity); FullEntity = new(_context, entityType, entity.Id);
// Сериализуем для отображения // Сериализуем для отображения
EntitySerializer serializer = new(); EntitySerializer serializer = new();
SerializationResult = serializer.Serialize(FullEntity); SerializationResult = serializer.Serialize(FullEntity);
// Set breadcrumbs
var typeName = Pf2e.Web.Helpers.PgNameHelper.GetPgName(entityType);
ViewData["Breadcrumbs"] = new List<(string, string)>
{
("Home", "/"),
(entityType.ToString(), $"/{typeName}"),
(entity.Name[Pf2e.Database.Model.Common.I18n.LocaleType.English], "")
};
return Page(); return Page();
} }
catch (Exception ex) catch (Exception ex)
{ {
System.Diagnostics.Debug.WriteLine($"Error in EntityModel.OnGet: {ex.Message}"); System.Diagnostics.Debug.WriteLine($"Error in EntityModel.OnGet: {ex.Message}");
Console.WriteLine($"Error in EntityModel.OnGet: {ex.Message}");
return NotFound(); return NotFound();
} }
} }
+19 -16
View File
@@ -10,24 +10,15 @@ using Pf2e.Database;
using Pf2e.Database.Model.Base; using Pf2e.Database.Model.Base;
using Pf2e.Database.Model.Enum; using Pf2e.Database.Model.Enum;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace Pf2e.Web.Pages namespace Pf2e.Web.Pages
{ {
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public class EntityTypeModel : PageModel public class EntityTypeModel(Pf2eDbContext context) : PageModel
{ {
private readonly Pf2eDbContext _context;
public EntityTypeModel(Pf2eDbContext context)
{
_context = context;
}
[BindProperty(SupportsGet = true)] [BindProperty(SupportsGet = true)]
public int? PageNum { get; set; } = 1; public int? PageNum { get; set; } = 1;
public IList<Entity> Entity { get; set; } = default!; public IList<Entity> Entity { get; set; } = null!;
public EntityType CurrentType; public EntityType CurrentType;
@@ -53,18 +44,26 @@ namespace Pf2e.Web.Pages
return NotFound(); return NotFound();
} }
int count = _context.Entities.Count(entity => entity.Type == CurrentType); int count = context.Entities.Count(entity => entity.Type == CurrentType);
System.Diagnostics.Debug.WriteLine($"Count for {CurrentType}: {count}"); System.Diagnostics.Debug.WriteLine($"Count for {CurrentType}: {count}");
LastPage = (int)Math.Ceiling(count / (double)PerPage); LastPage = (int)Math.Ceiling(count / (double)PerPage);
Entity = _context Entity = context
.Entities.Where(entity => entity.Type == CurrentType) .Entities.Where(entity => entity.Type == CurrentType)
.Skip((CurrentPage - 1) * PerPage) .Skip((CurrentPage - 1) * PerPage)
.Take(PerPage) .Take(PerPage)
.ToList(); .ToList();
System.Diagnostics.Debug.WriteLine($"Returning page with {Entity.Count} entities"); System.Diagnostics.Debug.WriteLine($"Returning page with {Entity.Count} entities");
// Set breadcrumbs
ViewData["Breadcrumbs"] = new List<(string, string)>
{
("Home", "/"),
(CurrentType.ToString(), ""),
};
return Page(); return Page();
} }
@@ -72,11 +71,13 @@ namespace Pf2e.Web.Pages
/// Преобразование значения из JSON в перечисление. /// Преобразование значения из JSON в перечисление.
/// </summary> /// </summary>
/// <param name="value">Значение, которое нужно преобразовать</param> /// <param name="value">Значение, которое нужно преобразовать</param>
/// <returns>Объект типа `T`, если преобразование успешно, иначе выбрасывает исключение</returns> /// <returns>Объект типа <c>T</c>, если преобразование успешно, иначе выбрасывает исключение</returns>
public static T Enum<T>(string value) public static T Enum<T>(string value)
where T : Enum where T : Enum
{ {
System.Diagnostics.Debug.WriteLine($"Trying to resolve enum value: {value} for type {typeof(T)}"); System.Diagnostics.Debug.WriteLine(
$"Trying to resolve enum value: {value} for type {typeof(T)}"
);
foreach (System.Reflection.FieldInfo field in typeof(T).GetFields()) foreach (System.Reflection.FieldInfo field in typeof(T).GetFields())
{ {
@@ -90,7 +91,9 @@ namespace Pf2e.Web.Pages
variants.Add(pgAttribute.PgName); variants.Add(pgAttribute.PgName);
} }
System.Diagnostics.Debug.WriteLine($"Checking field: {field.Name}, variants: {string.Join(", ", variants)}"); System.Diagnostics.Debug.WriteLine(
$"Checking field: {field.Name}, variants: {string.Join(", ", variants)}"
);
if (variants.Contains(value)) if (variants.Contains(value))
{ {
+5
View File
@@ -24,5 +24,10 @@ public class IndexModel : PageModel
Data = Context Data = Context
.Entities.GroupBy(e => e.Type) .Entities.GroupBy(e => e.Type)
.ToDictionary(entities => entities.Key, entities => entities.Count()); .ToDictionary(entities => entities.Key, entities => entities.Count());
ViewData["Breadcrumbs"] = new List<(string, string)>
{
("Home", "")
};
} }
} }
+5
View File
@@ -13,6 +13,11 @@ public class PrivacyModel : PageModel
public void OnGet() public void OnGet()
{ {
ViewData["Breadcrumbs"] = new List<(string, string)>
{
("Home", "/"),
("Privacy Policy", "")
};
} }
} }
+22
View File
@@ -32,6 +32,28 @@
</nav> </nav>
</header> </header>
<div class="container"> <div class="container">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
@if (ViewData["Breadcrumbs"] != null)
{
@foreach (var crumb in (List<(string, string)>)ViewData["Breadcrumbs"]!)
{
if (!string.IsNullOrEmpty(crumb.Item2))
{
<li class="breadcrumb-item"><a href="@crumb.Item2">@crumb.Item1</a></li>
}
else
{
<li class="breadcrumb-item active" aria-current="page">@crumb.Item1</li>
}
}
}
else
{
<li class="breadcrumb-item active" aria-current="page">Home</li>
}
</ol>
</nav>
<main role="main" class="pb-3"> <main role="main" class="pb-3">
@RenderBody() @RenderBody()
</main> </main>
+1
View File
@@ -9,6 +9,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="dotenv.net" Version="4.0.0" /> <PackageReference Include="dotenv.net" Version="4.0.0" />
<PackageReference Include="Markdig" Version="0.42.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="9.0.9"> <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="9.0.9">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
+2 -2
View File
@@ -13,12 +13,12 @@ builder.Services.AddDbContext<Pf2eDbContext>(options =>
options.UseNpgsql(EnvReader.GetStringValue("DATABASE_CONNECTION")) options.UseNpgsql(EnvReader.GetStringValue("DATABASE_CONNECTION"))
); );
var app = builder.Build(); WebApplication app = builder.Build();
// Configure the HTTP request pipeline. // Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment()) if (!app.Environment.IsDevelopment())
{ {
app.UseExceptionHandler("/Error"); //app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts(); app.UseHsts();
} }