Normalizes manufacturer as a shared catalog entity (like device categories) instead of free text on each device, giving the admin duplicate-detection nudge a reliable signal. Adds full CRUD (including Admin direct-publish, bypassing the submission queue) for categories, manufacturers, port types, and cable types, plus a Categories & Manufacturers library modal and a browse-by-manufacturer/search view in the device palette. Adds Port.builtInCable so a captive/permanently-attached cable (a keyboard's USB lead, a budget AVR's power cord) can be flagged and excluded from the BOM. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017DUU6CnxECCDeqDNYJgr5x
58 lines
3.1 KiB
TypeScript
58 lines
3.1 KiB
TypeScript
/** Which catalog table a submission is about. Mirrors `catalog_submissions.entity_type`'s
|
|
* check constraint. */
|
|
export type CatalogEntityType = 'device_template' | 'port_type' | 'cable_type' | 'device_category' | 'manufacturer'
|
|
|
|
/**
|
|
* A user's request to change the public catalog — either promoting one of
|
|
* their own private entries to public, or proposing an edit to an existing
|
|
* public entry. Regular users can never write a public catalog row directly
|
|
* (RLS only allows Admins to), so this is the only path either kind of
|
|
* change can take; an Admin review queue (not yet built — organized-ideas.md
|
|
* §9's next sub-phase) is what actually applies an approved one.
|
|
*/
|
|
export interface CatalogSubmission {
|
|
id: string
|
|
entityType: CatalogEntityType
|
|
/** The row this submission is about — always an existing row in this
|
|
* app's flow: either your own private entry (being promoted, possibly
|
|
* with edits) or a public entry (you're suggesting an edit to). */
|
|
entityId: string
|
|
/** Proposed field values, shaped like the underlying table's row (see
|
|
* data/catalogRowMapping.ts) — so applying an approval is just writing
|
|
* this object onto the row at `entityId`, not a separate translation
|
|
* step future Admin-approval logic would otherwise have to redo. */
|
|
proposedData: Record<string, unknown>
|
|
submitterId: string
|
|
status: 'pending' | 'approved' | 'rejected'
|
|
reviewerId?: string
|
|
/** Set by an Admin on rejection — organized-ideas.md §3's "notified either
|
|
* way, with a reason attached on rejection rather than a silent disappearance." */
|
|
reviewReason?: string
|
|
createdAt: string
|
|
updatedAt: string
|
|
}
|
|
|
|
/** Storage abstraction for the catalog submission/review queue — mirrors
|
|
* DiagramRepository/CatalogRepository's role for this concern. Only covers
|
|
* the submitter's-eye view (create, revise, withdraw your own) for now; an
|
|
* Admin's view (list all pending, approve/reject) is the next sub-phase. */
|
|
export interface SubmissionRepository {
|
|
/** Every submission the current user has made, most recent first. */
|
|
listMine(): Promise<CatalogSubmission[]>
|
|
/** Submits `entityId` (a row you own privately, or a public row you're
|
|
* proposing an edit to) for Admin review. */
|
|
submit(entityType: CatalogEntityType, entityId: string, proposedData: Record<string, unknown>): Promise<CatalogSubmission>
|
|
/** Revises a still-pending or previously-rejected submission of your own
|
|
* and puts it (back) into the pending queue. */
|
|
resubmit(id: string, proposedData: Record<string, unknown>): Promise<void>
|
|
/** Updates only `proposed_data`, leaving status/reviewer/reason untouched.
|
|
* Used to keep a submission's snapshot in sync with the live private
|
|
* entry it's about (see catalogStore) — a plain edit to your library
|
|
* entry shouldn't silently pull a rejected submission back into the
|
|
* pending queue, so status changes stay a separate, explicit action
|
|
* (`resubmit`), while the data itself is kept fresh automatically. */
|
|
updateProposedData(id: string, proposedData: Record<string, unknown>): Promise<void>
|
|
/** Withdraws your own still-pending submission. */
|
|
withdraw(id: string): Promise<void>
|
|
}
|