Replace literal Unicode special chars with HTML entities across all 233 views
Sweeps em dashes, en dashes, multiplication signs, ellipses, and curly quotes to their HTML entity equivalents (— – × … ‘ ’) in all .cshtml files, skipping <script> blocks. Prevents encoding corruption from AI tools and Windows encoding mismatches that caused recurring symbol bugs. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,364 +0,0 @@
|
||||
@model List<PowderCoating.Application.DTOs.BugReport.BugReportDto>
|
||||
@using PowderCoating.Core.Enums
|
||||
@{
|
||||
ViewData["Title"] = "Bug Reports";
|
||||
ViewData["PageIcon"] = "bi-bug";
|
||||
var sortCol = ViewBag.SortColumn as string ?? "CreatedAt";
|
||||
var sortDir = ViewBag.SortDirection as string ?? "desc";
|
||||
int totalCount = ViewBag.TotalCount ?? 0;
|
||||
int pageNumber = ViewBag.PageNumber ?? 1;
|
||||
int pageSize = ViewBag.PageSize ?? 25;
|
||||
int totalPages = ViewBag.TotalPages ?? 1;
|
||||
|
||||
string NextDir(string col) => sortCol == col && sortDir == "asc" ? "desc" : "asc";
|
||||
string SortIcon(string col) => sortCol == col
|
||||
? (sortDir == "asc" ? "bi-sort-up" : "bi-sort-down")
|
||||
: "bi-arrow-down-up text-muted";
|
||||
}
|
||||
|
||||
@section Styles {
|
||||
<style>
|
||||
[data-bs-theme="dark"] .table-light th,
|
||||
[data-bs-theme="dark"] .table-light td {
|
||||
background-color: var(--bs-secondary-bg);
|
||||
color: var(--bs-body-color);
|
||||
}
|
||||
[data-bs-theme="dark"] .card {
|
||||
border-color: var(--bs-border-color) !important;
|
||||
}
|
||||
[data-bs-theme="dark"] .sort-link {
|
||||
color: var(--bs-body-color) !important;
|
||||
}
|
||||
[data-bs-theme="dark"] .border-top {
|
||||
border-color: var(--bs-border-color) !important;
|
||||
}
|
||||
[data-bs-theme="dark"] .pagination .page-link {
|
||||
background-color: var(--bs-body-bg);
|
||||
border-color: var(--bs-border-color);
|
||||
color: var(--bs-body-color);
|
||||
}
|
||||
[data-bs-theme="dark"] .pagination .page-item.active .page-link {
|
||||
background-color: var(--bs-primary);
|
||||
border-color: var(--bs-primary);
|
||||
color: #fff;
|
||||
}
|
||||
</style>
|
||||
}
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="mb-4"></div>
|
||||
|
||||
@if (TempData["SuccessMessage"] != null)
|
||||
{
|
||||
<div class="alert alert-success alert-dismissible fade show" role="alert">
|
||||
<i class="bi bi-check-circle"></i> @TempData["SuccessMessage"]
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
}
|
||||
@if (TempData["ErrorMessage"] != null)
|
||||
{
|
||||
<div class="alert alert-danger alert-dismissible fade show" role="alert">
|
||||
<i class="bi bi-exclamation-triangle"></i> @TempData["ErrorMessage"]
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
}
|
||||
|
||||
<!-- Filters -->
|
||||
<div class="card mb-3">
|
||||
<div class="card-body py-2">
|
||||
<form method="get" class="row g-2 align-items-end">
|
||||
<div class="col-md-4">
|
||||
<label class="form-label small mb-1">Search</label>
|
||||
<input type="text" name="searchTerm" value="@ViewBag.SearchTerm" class="form-control form-control-sm"
|
||||
placeholder="Title, description, or submitter..." />
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<label class="form-label small mb-1">Status</label>
|
||||
<select name="statusFilter" class="form-select form-select-sm">
|
||||
<option value="">All Statuses</option>
|
||||
@foreach (var s in Enum.GetValues<BugReportStatus>())
|
||||
{
|
||||
<option value="@s" selected="@(ViewBag.StatusFilter == s.ToString())">@s.ToString()</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<label class="form-label small mb-1">Priority</label>
|
||||
<select name="priorityFilter" class="form-select form-select-sm">
|
||||
<option value="">All Priorities</option>
|
||||
@foreach (var p in Enum.GetValues<BugReportPriority>())
|
||||
{
|
||||
<option value="@p" selected="@(ViewBag.PriorityFilter == p.ToString())">@p.ToString()</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<label class="form-label small mb-1">Per page</label>
|
||||
<select name="pageSize" class="form-select form-select-sm">
|
||||
@foreach (var n in new[] { 10, 25, 50, 100 })
|
||||
{
|
||||
<option value="@n" selected="@(pageSize == n)">@n</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
<input type="hidden" name="sortColumn" value="@sortCol" />
|
||||
<input type="hidden" name="sortDirection" value="@sortDir" />
|
||||
<div class="col-md-2">
|
||||
<button type="submit" class="btn btn-primary btn-sm w-100">
|
||||
<i class="bi bi-search"></i> Filter
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Table -->
|
||||
<div class="card">
|
||||
<div class="card-body p-0">
|
||||
@if (!Model.Any())
|
||||
{
|
||||
<div class="text-center py-5 text-muted">
|
||||
<i class="bi bi-check-circle display-4 d-block mb-2"></i>
|
||||
<p>No bug reports found.</p>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover mb-0">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th>
|
||||
<a asp-action="Index"
|
||||
asp-route-searchTerm="@ViewBag.SearchTerm"
|
||||
asp-route-statusFilter="@ViewBag.StatusFilter"
|
||||
asp-route-priorityFilter="@ViewBag.PriorityFilter"
|
||||
asp-route-pageSize="@pageSize"
|
||||
asp-route-sortColumn="Title"
|
||||
asp-route-sortDirection="@NextDir("Title")"
|
||||
class="text-decoration-none sort-link">
|
||||
Title <i class="bi @SortIcon("Title")"></i>
|
||||
</a>
|
||||
</th>
|
||||
<th>
|
||||
<a asp-action="Index"
|
||||
asp-route-searchTerm="@ViewBag.SearchTerm"
|
||||
asp-route-statusFilter="@ViewBag.StatusFilter"
|
||||
asp-route-priorityFilter="@ViewBag.PriorityFilter"
|
||||
asp-route-pageSize="@pageSize"
|
||||
asp-route-sortColumn="Priority"
|
||||
asp-route-sortDirection="@NextDir("Priority")"
|
||||
class="text-decoration-none sort-link">
|
||||
Priority <i class="bi @SortIcon("Priority")"></i>
|
||||
</a>
|
||||
</th>
|
||||
<th>
|
||||
<a asp-action="Index"
|
||||
asp-route-searchTerm="@ViewBag.SearchTerm"
|
||||
asp-route-statusFilter="@ViewBag.StatusFilter"
|
||||
asp-route-priorityFilter="@ViewBag.PriorityFilter"
|
||||
asp-route-pageSize="@pageSize"
|
||||
asp-route-sortColumn="Status"
|
||||
asp-route-sortDirection="@NextDir("Status")"
|
||||
class="text-decoration-none sort-link">
|
||||
Status <i class="bi @SortIcon("Status")"></i>
|
||||
</a>
|
||||
</th>
|
||||
<th>
|
||||
<a asp-action="Index"
|
||||
asp-route-searchTerm="@ViewBag.SearchTerm"
|
||||
asp-route-statusFilter="@ViewBag.StatusFilter"
|
||||
asp-route-priorityFilter="@ViewBag.PriorityFilter"
|
||||
asp-route-pageSize="@pageSize"
|
||||
asp-route-sortColumn="Submitted"
|
||||
asp-route-sortDirection="@NextDir("Submitted")"
|
||||
class="text-decoration-none sort-link">
|
||||
Submitted By <i class="bi @SortIcon("Submitted")"></i>
|
||||
</a>
|
||||
</th>
|
||||
<th>Company</th>
|
||||
<th>
|
||||
<a asp-action="Index"
|
||||
asp-route-searchTerm="@ViewBag.SearchTerm"
|
||||
asp-route-statusFilter="@ViewBag.StatusFilter"
|
||||
asp-route-priorityFilter="@ViewBag.PriorityFilter"
|
||||
asp-route-pageSize="@pageSize"
|
||||
asp-route-sortColumn="CreatedAt"
|
||||
asp-route-sortDirection="@NextDir("CreatedAt")"
|
||||
class="text-decoration-none sort-link">
|
||||
Submitted <i class="bi @SortIcon("CreatedAt")"></i>
|
||||
</a>
|
||||
</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var report in Model)
|
||||
{
|
||||
<tr style="cursor:pointer" onclick="window.location='@Url.Action("Edit", new { id = report.Id })'">
|
||||
<td>
|
||||
<div class="fw-semibold">@report.Title</div>
|
||||
<div class="text-muted small text-truncate" style="max-width:320px;" title="@report.Description">
|
||||
@report.Description
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
@{
|
||||
var priClass = report.Priority switch
|
||||
{
|
||||
BugReportPriority.Critical => "bg-danger",
|
||||
BugReportPriority.High => "bg-warning text-dark",
|
||||
BugReportPriority.Normal => "bg-primary",
|
||||
_ => "bg-secondary"
|
||||
};
|
||||
}
|
||||
<span class="badge @priClass">@report.Priority</span>
|
||||
</td>
|
||||
<td>
|
||||
@{
|
||||
var statusClass = report.Status switch
|
||||
{
|
||||
BugReportStatus.New => "bg-info text-dark",
|
||||
BugReportStatus.InProgress => "bg-warning text-dark",
|
||||
BugReportStatus.Completed => "bg-success",
|
||||
BugReportStatus.Cancelled => "bg-secondary",
|
||||
_ => "bg-secondary"
|
||||
};
|
||||
var statusLabel = report.Status switch
|
||||
{
|
||||
BugReportStatus.InProgress => "In Progress",
|
||||
_ => report.Status.ToString()
|
||||
};
|
||||
}
|
||||
<span class="badge @statusClass">@statusLabel</span>
|
||||
</td>
|
||||
<td class="small">@report.SubmittedByUserName</td>
|
||||
<td class="small text-muted">@report.CompanyId</td>
|
||||
<td class="small text-muted text-nowrap">@report.CreatedAt.Tz(ViewBag.CompanyTimeZone as string).ToString("MM/dd/yyyy h:mm tt")</td>
|
||||
<td onclick="event.stopPropagation()">
|
||||
<a asp-action="Edit" asp-route-id="@report.Id" class="btn btn-sm btn-outline-primary">
|
||||
<i class="bi bi-pencil"></i> Edit
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- Mobile card view — shown on screens < 992px -->
|
||||
<div class="mobile-card-view">
|
||||
<div class="mobile-card-list">
|
||||
@foreach (var report in Model)
|
||||
{
|
||||
var mPriClass = report.Priority switch
|
||||
{
|
||||
BugReportPriority.Critical => "bg-danger",
|
||||
BugReportPriority.High => "bg-warning text-dark",
|
||||
BugReportPriority.Normal => "bg-primary",
|
||||
_ => "bg-secondary"
|
||||
};
|
||||
var mStatusClass = report.Status switch
|
||||
{
|
||||
BugReportStatus.New => "bg-info text-dark",
|
||||
BugReportStatus.InProgress => "bg-warning text-dark",
|
||||
BugReportStatus.Completed => "bg-success",
|
||||
BugReportStatus.Cancelled => "bg-secondary",
|
||||
_ => "bg-secondary"
|
||||
};
|
||||
var mStatusLabel = report.Status switch
|
||||
{
|
||||
BugReportStatus.InProgress => "In Progress",
|
||||
_ => report.Status.ToString()
|
||||
};
|
||||
<a href="@Url.Action("Edit", new { id = report.Id })" class="mobile-data-card text-decoration-none">
|
||||
<div class="mobile-card-header">
|
||||
<div class="mobile-card-icon bg-danger"><i class="bi bi-bug"></i></div>
|
||||
<div class="mobile-card-title">
|
||||
<h6>@report.Title</h6>
|
||||
<small>@report.CreatedAt.Tz(ViewBag.CompanyTimeZone as string).ToString("MM/dd/yyyy h:mm tt")</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mobile-card-body">
|
||||
<div class="mobile-card-row">
|
||||
<span class="mobile-card-label">Status</span>
|
||||
<span class="mobile-card-value"><span class="badge @mStatusClass">@mStatusLabel</span></span>
|
||||
</div>
|
||||
<div class="mobile-card-row">
|
||||
<span class="mobile-card-label">Priority</span>
|
||||
<span class="mobile-card-value"><span class="badge @mPriClass">@report.Priority</span></span>
|
||||
</div>
|
||||
<div class="mobile-card-row">
|
||||
<span class="mobile-card-label">Reporter</span>
|
||||
<span class="mobile-card-value">@report.SubmittedByUserName</span>
|
||||
</div>
|
||||
@if (report.CompanyId > 0)
|
||||
{
|
||||
<div class="mobile-card-row">
|
||||
<span class="mobile-card-label">Company ID</span>
|
||||
<span class="mobile-card-value">@report.CompanyId</span>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<div class="mobile-card-footer">
|
||||
<span class="btn btn-sm btn-outline-primary">Edit →</span>
|
||||
</div>
|
||||
</a>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Pagination -->
|
||||
@if (totalPages > 1)
|
||||
{
|
||||
<div class="d-flex justify-content-between align-items-center px-3 py-2 border-top">
|
||||
<small class="text-muted">
|
||||
Showing @((pageNumber - 1) * pageSize + 1)–@(Math.Min(pageNumber * pageSize, totalCount)) of @totalCount
|
||||
</small>
|
||||
<nav>
|
||||
<ul class="pagination pagination-sm mb-0">
|
||||
<li class="page-item @(pageNumber <= 1 ? "disabled" : "")">
|
||||
<a class="page-link" asp-action="Index"
|
||||
asp-route-searchTerm="@ViewBag.SearchTerm"
|
||||
asp-route-statusFilter="@ViewBag.StatusFilter"
|
||||
asp-route-priorityFilter="@ViewBag.PriorityFilter"
|
||||
asp-route-sortColumn="@sortCol"
|
||||
asp-route-sortDirection="@sortDir"
|
||||
asp-route-pageSize="@pageSize"
|
||||
asp-route-pageNumber="@(pageNumber - 1)">
|
||||
<i class="bi bi-chevron-left"></i>
|
||||
</a>
|
||||
</li>
|
||||
@for (int i = Math.Max(1, pageNumber - 2); i <= Math.Min(totalPages, pageNumber + 2); i++)
|
||||
{
|
||||
<li class="page-item @(i == pageNumber ? "active" : "")">
|
||||
<a class="page-link" asp-action="Index"
|
||||
asp-route-searchTerm="@ViewBag.SearchTerm"
|
||||
asp-route-statusFilter="@ViewBag.StatusFilter"
|
||||
asp-route-priorityFilter="@ViewBag.PriorityFilter"
|
||||
asp-route-sortColumn="@sortCol"
|
||||
asp-route-sortDirection="@sortDir"
|
||||
asp-route-pageSize="@pageSize"
|
||||
asp-route-pageNumber="@i">@i</a>
|
||||
</li>
|
||||
}
|
||||
<li class="page-item @(pageNumber >= totalPages ? "disabled" : "")">
|
||||
<a class="page-link" asp-action="Index"
|
||||
asp-route-searchTerm="@ViewBag.SearchTerm"
|
||||
asp-route-statusFilter="@ViewBag.StatusFilter"
|
||||
asp-route-priorityFilter="@ViewBag.PriorityFilter"
|
||||
asp-route-sortColumn="@sortCol"
|
||||
asp-route-sortDirection="@sortDir"
|
||||
asp-route-pageSize="@pageSize"
|
||||
asp-route-pageNumber="@(pageNumber + 1)">
|
||||
<i class="bi bi-chevron-right"></i>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user