mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-18 21:16:47 +00:00
feat(journey): set a journey's status by hand (#762)
This commit is contained in:
@@ -5421,6 +5421,15 @@ function runMigrations(db: Database.Database): void {
|
||||
if (!has('quantity')) db.exec('ALTER TABLE packing_template_items ADD COLUMN quantity INTEGER NOT NULL DEFAULT 1');
|
||||
if (!has('bag_name')) db.exec('ALTER TABLE packing_template_items ADD COLUMN bag_name TEXT');
|
||||
},
|
||||
/**
|
||||
* A journey's state as its owner sets it (#762): draft, live or completed.
|
||||
* NULL keeps the state derived from the linked trips' dates, which is what
|
||||
* every journey had so far; a journey with no trip could only ever be a draft.
|
||||
*/
|
||||
() => {
|
||||
const cols = db.prepare("SELECT name FROM pragma_table_info('journeys')").all() as { name: string }[];
|
||||
if (!cols.some(c => c.name === 'status_override')) db.exec('ALTER TABLE journeys ADD COLUMN status_override TEXT');
|
||||
},
|
||||
];
|
||||
|
||||
if (currentVersion < migrations.length) {
|
||||
|
||||
@@ -351,6 +351,7 @@ export class JourneyDomainService {
|
||||
cover_gradient: string;
|
||||
cover_image: string;
|
||||
status: string;
|
||||
status_override: string | null;
|
||||
show_trip_tracks: boolean | number;
|
||||
show_verdict: boolean | number;
|
||||
show_mood: boolean | number;
|
||||
@@ -362,12 +363,15 @@ export class JourneyDomainService {
|
||||
if (!this.isOwner(journeyId, userId)) return null;
|
||||
|
||||
const ALLOWED_STATUSES = ['draft', 'active', 'completed', 'archived'];
|
||||
// null hands the state back to the trip dates (#762).
|
||||
const ALLOWED_OVERRIDES: (string | null)[] = [null, 'draft', 'live', 'completed'];
|
||||
const allowed = [
|
||||
'title',
|
||||
'subtitle',
|
||||
'cover_gradient',
|
||||
'cover_image',
|
||||
'status',
|
||||
'status_override',
|
||||
'show_trip_tracks',
|
||||
'show_verdict',
|
||||
'show_mood',
|
||||
@@ -381,6 +385,7 @@ export class JourneyDomainService {
|
||||
for (const [key, val] of Object.entries(data)) {
|
||||
if (val !== undefined && allowed.includes(key)) {
|
||||
if (key === 'status' && !ALLOWED_STATUSES.includes(val as string)) continue;
|
||||
if (key === 'status_override' && !ALLOWED_OVERRIDES.includes(val as string | null)) continue;
|
||||
fields.push(`${key} = ?`);
|
||||
values.push(BOOLEAN_FIELDS.has(key) ? (val ? 1 : 0) : val);
|
||||
}
|
||||
|
||||
@@ -241,12 +241,13 @@ export class JourneyMcp {
|
||||
|
||||
@Tool({
|
||||
name: 'update_journey',
|
||||
description: "Update an existing journey's title, subtitle, cover, or status. Owner only.",
|
||||
description: "Update an existing journey's title, subtitle, cover, or status. Owner only. status_override sets the state shown for the journey (draft, live, completed) instead of deriving it from the linked trips' dates; null goes back to the dates.",
|
||||
inputSchema: {
|
||||
journeyId: z.number().int().positive(),
|
||||
title: z.string().min(1).max(200).optional(),
|
||||
subtitle: z.string().max(300).optional(),
|
||||
status: z.enum(['draft', 'active', 'completed', 'archived']).optional(),
|
||||
status_override: z.enum(['draft', 'live', 'completed']).nullable().optional().describe('Shown state set by hand, or null to follow the trip dates'),
|
||||
show_verdict: z.boolean().optional().describe('Whether entries in this journey offer a pros/cons list'),
|
||||
show_mood: z.boolean().optional().describe('Whether entries in this journey offer a mood'),
|
||||
show_weather: z.boolean().optional().describe('Whether entries in this journey offer a weather note'),
|
||||
@@ -257,7 +258,7 @@ export class JourneyMcp {
|
||||
})
|
||||
updateJourney(
|
||||
{ journeyId, ...data }: {
|
||||
journeyId: number; title?: string; subtitle?: string; status?: string;
|
||||
journeyId: number; title?: string; subtitle?: string; status?: string; status_override?: string | null;
|
||||
show_verdict?: boolean; show_mood?: boolean; show_weather?: boolean;
|
||||
},
|
||||
ctx: McpContext,
|
||||
|
||||
@@ -337,6 +337,15 @@ describe('updateJourney', () => {
|
||||
expect(result!.title).toBe('Same');
|
||||
});
|
||||
|
||||
it('JOURNEY-SVC-762: the owner sets the shown state by hand, null hands it back, anything else is ignored', () => {
|
||||
const { user } = createUser(testDb);
|
||||
const journey = createJourney(testDb, user.id);
|
||||
|
||||
expect(svc.updateJourney(journey.id, user.id, { status_override: 'live' })!.status_override).toBe('live');
|
||||
expect(svc.updateJourney(journey.id, user.id, { status_override: 'upcoming' })!.status_override).toBe('live');
|
||||
expect(svc.updateJourney(journey.id, user.id, { status_override: null })!.status_override).toBeNull();
|
||||
});
|
||||
|
||||
it('JOURNEY-SVC-021b: accepts archived status', () => {
|
||||
const { user } = createUser(testDb);
|
||||
const journey = createJourney(testDb, user.id, { title: 'To Archive' });
|
||||
|
||||
Reference in New Issue
Block a user