Files
OpenSquawk/server/models/BugReport.ts
itsrubberduck 034ddbab2e feat(bug-reports): trace reports by code and tell Live ATC from Classroom
Every report now gets a UUID that the notification mail quotes as
"Nenne den Fehlercode <uuid> beim Commit", so a fix can be tied back to
the report it closes. The mail also names the area it came from, and the
comment field is relabelled "Fehlerbeschreibung/Featurewunsch" since it
collects feature wishes just as often as bugs.

Classroom loses its plain feedback link and gets the same reporter as
Live ATC — screenshot, arrow annotation and all. `useBugReport` takes an
options object so the communications-engine snapshot stays optional; the
dialog moves out of `live-atc/cockpit` now that both pages use it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-26 21:11:43 +02:00

57 lines
2.2 KiB
TypeScript

import mongoose from 'mongoose'
export type BugReportStatus = 'open' | 'resolved'
/** Where the report was filed. Shown in the notification mail so we know which
* part of the app to reproduce it in. */
export type BugReportSource = 'live-atc' | 'classroom'
export interface PmStateSnapshot {
flowSlug?: string
scenarioId?: string
currentStateId?: string
variables?: Record<string, any>
flags?: Record<string, boolean>
flightContext?: Record<string, any>
communicationLog?: any[]
}
export interface BugReportDocument extends mongoose.Document {
/** Stable UUID quoted in commit messages so a fix can be traced back here. */
code: string
source: BugReportSource
comment: string
contact: string
userId?: mongoose.Types.ObjectId
screenshot?: string
pmState?: PmStateSnapshot
status: BugReportStatus
createdAt: Date
}
const bugReportSchema = new mongoose.Schema<BugReportDocument>({
// Sparse: reports created before the code existed simply have none, and a
// plain unique index would reject more than one of them.
code: { type: String, required: true, unique: true, sparse: true },
source: { type: String, enum: ['live-atc', 'classroom'], default: 'live-atc', index: true },
comment: { type: String, required: true, trim: true, maxlength: 4000 },
contact: { type: String, required: true, trim: true, maxlength: 200 },
userId: { type: mongoose.Schema.Types.ObjectId, ref: 'User', index: true },
screenshot: { type: String },
pmState: {
flowSlug: { type: String },
scenarioId: { type: String },
currentStateId: { type: String },
variables: { type: mongoose.Schema.Types.Mixed, default: {} },
flags: { type: mongoose.Schema.Types.Mixed, default: {} },
flightContext: { type: mongoose.Schema.Types.Mixed, default: {} },
communicationLog: { type: [mongoose.Schema.Types.Mixed], default: [] },
},
status: { type: String, enum: ['open', 'resolved'], default: 'open', index: true },
createdAt: { type: Date, default: () => new Date(), index: true },
})
export const BugReport =
(mongoose.models.BugReport as mongoose.Model<BugReportDocument> | undefined) ||
mongoose.model<BugReportDocument>('BugReport', bugReportSchema)