mirror of
https://github.com/ajisaacs/OpenNest.git
synced 2026-10-27 06:01:06 -04:00
Schema v5 stores each distinct drawing package once in drawing_packages, keyed by SHA-256; revisions point at it, so details, settings, archive and restore revisions add no blob. The v4 drawing tables are replaced outright (no production library existed); nest tables are untouched. Nesting settings (cut first, priority, rotation constraints, color) become structured record fields (DrawingLibraryRecord.Settings), returned on every read, filterable by cutFirst, editable through the metadata endpoint and applied by LibraryDrawingInsert. Canonical packages now leave every record-owned field at its default, so renaming or changing settings never changes the package hash. Saving a nest drawing to the library carries its settings into the record. The desktop library browser gains a Cut first column and an Edit Settings dialog that saves notes and settings as a new revision with the same package. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
72 lines
3.1 KiB
C#
72 lines
3.1 KiB
C#
using OpenNest;
|
|
|
|
namespace OpenNest.Data;
|
|
|
|
/// <summary>
|
|
/// One bounded page request for browsing the drawing library
|
|
/// (<c>GET /api/drawings/query</c>). The server filters and pages in SQL; the
|
|
/// client and server share these bounds.
|
|
/// </summary>
|
|
public sealed class DrawingLibraryQuery
|
|
{
|
|
public const int DefaultLimit = 100;
|
|
public const int MaxLimit = 500;
|
|
public const int MaxSearchLength = 200;
|
|
|
|
/// <summary>
|
|
/// Case-insensitive (ASCII) substring of name, customer or notes. Blank means no filter.
|
|
/// </summary>
|
|
public string Search { get; init; } = "";
|
|
|
|
/// <summary>Exact customer, compared by <see cref="SharedListNames.Key"/>. Blank means any.</summary>
|
|
public string Customer { get; init; } = "";
|
|
|
|
/// <summary>Exact material name, compared by <see cref="SharedListNames.Key"/>. Blank means any.</summary>
|
|
public string MaterialName { get; init; } = "";
|
|
|
|
/// <summary>Exact grade, compared by <see cref="SharedListNames.Key"/>. Blank means any.</summary>
|
|
public string MaterialGrade { get; init; } = "";
|
|
|
|
/// <summary>Exact thickness after rounding to four decimals; null means any.</summary>
|
|
public double? Thickness { get; init; }
|
|
|
|
public CutType? CutType { get; init; }
|
|
|
|
/// <summary>Only drawings whose Cut first setting equals this; null means any.</summary>
|
|
public bool? CutFirst { get; init; }
|
|
|
|
public bool IncludeArchived { get; init; }
|
|
|
|
/// <summary>Column to order by; ties are broken by id in the same direction.</summary>
|
|
public DrawingSortField Sort { get; init; } = DrawingSortField.SavedAt;
|
|
|
|
/// <summary>Largest/newest/Z first when true (the default, newest saved first).</summary>
|
|
public bool Descending { get; init; } = true;
|
|
|
|
public int Offset { get; init; }
|
|
|
|
public int Limit { get; init; } = DefaultLimit;
|
|
|
|
/// <summary>The search text as matched: trimmed, never null.</summary>
|
|
public string NormalizedSearch => (Search ?? "").Trim();
|
|
|
|
/// <summary>The first violated bound, or null when the query may be sent.</summary>
|
|
public string? GetValidationError()
|
|
{
|
|
if (!Enum.IsDefined(Sort))
|
|
return "sort must be a supported column.";
|
|
if (CutType is { } cutType && !Enum.IsDefined(cutType))
|
|
return "cutType must be Laser, Waterjet or Plasma.";
|
|
if (Thickness is { } thickness && (!double.IsFinite(thickness) || thickness < 0))
|
|
return "thickness must be a finite number, zero or greater.";
|
|
if (Offset < 0)
|
|
return "offset must be zero or greater.";
|
|
if (Limit < 1 || Limit > MaxLimit)
|
|
return $"limit must be between 1 and {MaxLimit}.";
|
|
return DrawingLibraryRules.TextError("search", NormalizedSearch, MaxSearchLength)
|
|
?? DrawingLibraryRules.TextError("customer", Customer ?? "", DrawingLibraryRules.MaxTextLength)
|
|
?? DrawingLibraryRules.TextError("materialName", MaterialName ?? "", DrawingLibraryRules.MaxTextLength)
|
|
?? DrawingLibraryRules.TextError("materialGrade", MaterialGrade ?? "", DrawingLibraryRules.MaxTextLength);
|
|
}
|
|
}
|