Sweep all .cshtml files for encoding corruption; add pre-commit guard
Replace all corruption variants with HTML entities across 226 view files: - 3-char UTF-8-as-Win1252 sequences (ae-corruption) - Standalone smart/curly quotes that break C# Razor expressions - Partially re-corrupted variants where the 3rd byte was normalised to ASCII tools/Fix-Encoding.ps1: re-runnable sweep; uses [char] code points so the script itself never contains a literal non-ASCII character; supports -DryRun .githooks/pre-commit: blocks commits containing the ae-corruption byte signature (xc3xa2xe2x82xac); git core.hooksPath = .githooks so the hook is repo-committed and active for all future work on this machine. Build clean; 225 unit tests pass. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
@model PowderCoating.Application.DTOs.Scheduling.OvenSchedulerViewModel
|
||||
@model PowderCoating.Application.DTOs.Scheduling.OvenSchedulerViewModel
|
||||
@{
|
||||
ViewData["Title"] = "Oven Scheduler";
|
||||
var dateStr = Model.ScheduledDate.ToString("yyyy-MM-dd");
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
@section Styles {
|
||||
<style>
|
||||
/* ─── Layout ─────────────────────────────────────── */
|
||||
/* --- Layout --------------------------------------- */
|
||||
.scheduler-layout {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
@@ -39,7 +39,7 @@
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* ─── Batch cards ────────────────────────────────── */
|
||||
/* --- Batch cards ---------------------------------- */
|
||||
.batch-card {
|
||||
border-radius: 10px;
|
||||
border: 2px solid transparent;
|
||||
@@ -52,14 +52,14 @@
|
||||
.batch-card.status-completed { border-color: #198754; opacity: .85; }
|
||||
.batch-card.drag-over { border-color: #0d6efd !important; box-shadow: 0 0 12px rgba(13,110,253,.4) !important; }
|
||||
|
||||
/* ─── Capacity bar ───────────────────────────────── */
|
||||
/* --- Capacity bar --------------------------------- */
|
||||
.capacity-bar-wrap { height: 6px; border-radius: 3px; background: #e9ecef; overflow: hidden; }
|
||||
.capacity-bar-fill { height: 100%; border-radius: 3px; transition: width .3s; }
|
||||
.cap-ok { background: #198754; }
|
||||
.cap-warn { background: #ffc107; }
|
||||
.cap-over { background: #dc3545; }
|
||||
|
||||
/* ─── Queue items ────────────────────────────────── */
|
||||
/* --- Queue items ---------------------------------- */
|
||||
.queue-job-card {
|
||||
border-radius: 8px;
|
||||
cursor: grab;
|
||||
@@ -90,7 +90,7 @@
|
||||
.batch-item-row:hover { background: var(--bs-secondary-bg); }
|
||||
.batch-item-row.dragging { opacity: .5; }
|
||||
|
||||
/* ─── AI panel ───────────────────────────────────── */
|
||||
/* --- AI panel ------------------------------------- */
|
||||
.ai-suggestion-panel {
|
||||
position: fixed;
|
||||
top: 0; right: 0;
|
||||
@@ -115,7 +115,7 @@
|
||||
}
|
||||
.ai-panel-backdrop.open { display: block; }
|
||||
|
||||
/* ─── Drop zone hint ─────────────────────────────── */
|
||||
/* --- Drop zone hint ------------------------------- */
|
||||
.drop-zone-empty {
|
||||
min-height: 80px;
|
||||
border: 2px dashed var(--bs-border-color);
|
||||
@@ -275,7 +275,7 @@
|
||||
<p class="small text-muted mb-2">
|
||||
The Oven Scheduler helps you plan which jobs go into which oven on a given day.
|
||||
Jobs waiting to be coated appear in the <strong>Queue</strong> on the left.
|
||||
Each oven gets its own column — create <strong>batches</strong> and drag jobs into them
|
||||
Each oven gets its own column — create <strong>batches</strong> and drag jobs into them
|
||||
to build your day's run sheet.
|
||||
</p>
|
||||
<p class="small text-muted mb-0">
|
||||
@@ -292,8 +292,8 @@
|
||||
<li class="mb-1">Use the <strong>date arrows</strong> to navigate to the day you want to schedule.</li>
|
||||
<li class="mb-1">Click <strong>New Batch</strong> and pick an oven to create a batch slot.</li>
|
||||
<li class="mb-1"><strong>Drag job coat items</strong> from the Queue into a batch, or drag between batches to reorder.</li>
|
||||
<li class="mb-1">Set a <strong>start time</strong> on each batch and monitor the capacity bar — it turns yellow at 80 % and red when over capacity.</li>
|
||||
<li class="mb-1">Use the batch <strong>status buttons</strong> (Planned → Loading → In Progress → Completed) to track real-time progress.</li>
|
||||
<li class="mb-1">Set a <strong>start time</strong> on each batch and monitor the capacity bar — it turns yellow at 80 % and red when over capacity.</li>
|
||||
<li class="mb-1">Use the batch <strong>status buttons</strong> (Planned â†' Loading â†' In Progress â†' Completed) to track real-time progress.</li>
|
||||
<li class="mb-0">Drag an item back to the Queue to unschedule it.</li>
|
||||
</ol>
|
||||
</div>
|
||||
@@ -303,23 +303,23 @@
|
||||
<h6 class="fw-semibold mb-2"><i class="bi bi-gear-fill text-warning me-1"></i>Setup for best results</h6>
|
||||
<ul class="small text-muted mb-0 ps-3">
|
||||
<li class="mb-1">
|
||||
<strong>Ovens in Equipment</strong> — each oven must exist as an Equipment record
|
||||
<strong>Ovens in Equipment</strong> — each oven must exist as an Equipment record
|
||||
with <em>Type = Oven</em> and Status = Operational for it to appear as a column.
|
||||
</li>
|
||||
<li class="mb-1">
|
||||
<strong>Oven capacity</strong> — set a <em>capacity (sq ft)</em> on each oven so
|
||||
<strong>Oven capacity</strong> — set a <em>capacity (sq ft)</em> on each oven so
|
||||
the capacity bar can warn you before you overload a batch.
|
||||
</li>
|
||||
<li class="mb-1">
|
||||
<strong>Job items with surface area</strong> — enter <em>surface area (sq ft)</em>
|
||||
<strong>Job items with surface area</strong> — enter <em>surface area (sq ft)</em>
|
||||
on each job item so the scheduler can calculate load accurately.
|
||||
</li>
|
||||
<li class="mb-1">
|
||||
<strong>Coat quantities</strong> — job items need at least one coat defined
|
||||
<strong>Coat quantities</strong> — job items need at least one coat defined
|
||||
(powder color + quantity) so they appear as draggable coat rows in the Queue.
|
||||
</li>
|
||||
<li class="mb-0">
|
||||
<strong>Due dates & priorities</strong> — set due dates and priorities on
|
||||
<strong>Due dates & priorities</strong> — set due dates and priorities on
|
||||
jobs so the AI and sorting tools can recommend the most urgent work first.
|
||||
</li>
|
||||
</ul>
|
||||
@@ -341,7 +341,7 @@
|
||||
<!-- Main layout -->
|
||||
<div class="scheduler-layout">
|
||||
|
||||
<!-- ── JOB QUEUE (left sidebar) ───────────────── -->
|
||||
<!-- -- JOB QUEUE (left sidebar) ----------------- -->
|
||||
<div class="scheduler-queue">
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-header d-flex align-items-center py-2">
|
||||
@@ -408,7 +408,7 @@
|
||||
<span class="color-dot" style="background:@GetColorHex(coat.ColorName, coat.ColorCode)"></span>
|
||||
}
|
||||
<span class="fw-medium">@coat.CoatName</span>
|
||||
<span class="text-muted ms-1">— @coat.ItemDescription</span>
|
||||
<span class="text-muted ms-1">— @coat.ItemDescription</span>
|
||||
</div>
|
||||
<div class="text-muted" style="font-size:.75rem;">
|
||||
Pass @coat.CoatPassNumber · @coat.SurfaceAreaSqFt.ToString("F1") sqft
|
||||
@@ -426,7 +426,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ── OVEN COLUMNS ───────────────────────────── -->
|
||||
<!-- -- OVEN COLUMNS ----------------------------- -->
|
||||
<div class="scheduler-board">
|
||||
<div class="oven-columns" id="ovenColumns">
|
||||
@foreach (var oven in Model.Ovens)
|
||||
@@ -547,7 +547,7 @@
|
||||
@if (!Model.QueuedJobs.Any())
|
||||
{
|
||||
<div class="alert alert-info alert-permanent small">
|
||||
<i class="bi bi-info-circle me-1"></i>The queue is empty — no jobs need oven scheduling right now.
|
||||
<i class="bi bi-info-circle me-1"></i>The queue is empty — no jobs need oven scheduling right now.
|
||||
</div>
|
||||
}
|
||||
else
|
||||
@@ -561,7 +561,7 @@
|
||||
|
||||
@section Scripts {
|
||||
<script>
|
||||
// ── Info panel (always visible on load; dismiss hides for this visit only) ─
|
||||
// -- Info panel (always visible on load; dismiss hides for this visit only) -
|
||||
document.getElementById('btnDismissInfo').addEventListener('click', function () {
|
||||
document.getElementById('schedulerInfoPanel').style.display = 'none';
|
||||
});
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
@Model.ScheduledStartTime.Value.ToString("h:mm tt")
|
||||
@if (Model.EstimatedEndTime.HasValue)
|
||||
{
|
||||
<span>– @Model.EstimatedEndTime.Value.ToString("h:mm tt")</span>
|
||||
<span>– @Model.EstimatedEndTime.Value.ToString("h:mm tt")</span>
|
||||
}
|
||||
<span class="ms-1">(@Model.CycleMinutes min)</span>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user