mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-22 23:16:46 +00:00
feat(help): in-app help center with per-screen guides and pictures
A help icon on every screen opens a panel with the screen's overview, its sub-screens, task guides with a framed picture per step, search across guides and the wiki, and a switch to any other screen's help. Guides exist for the dashboard, Vacay, Atlas, Collections, Journey (list, journal, studio), Settings (all tabs), Admin (all tabs) and the trip frame; the trip's own screens are in progress. Pictures are produced by Playwright (client/e2e/help), texts in all 23 languages.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { Controller, Get, Param, Req, Res } from '@nestjs/common';
|
||||
import { Controller, Get, HttpException, Param, Query, Req, Res } from '@nestjs/common';
|
||||
import type { Request, Response } from 'express';
|
||||
import { Public } from '../auth/public.decorator';
|
||||
import {
|
||||
@@ -6,11 +6,16 @@ import {
|
||||
getWikiPage,
|
||||
getWikiAsset,
|
||||
isLocalWiki,
|
||||
searchWiki,
|
||||
WikiNotFound,
|
||||
type WikiPage,
|
||||
type WikiNavSection,
|
||||
type WikiSearchHit,
|
||||
} from './wiki';
|
||||
|
||||
/** Longest query the search accepts; anything past it is noise, not a question. */
|
||||
const SEARCH_MAX_QUERY = 120;
|
||||
|
||||
/**
|
||||
* /api/help — embedded TREK wiki, served from the `wiki/` directory that ships
|
||||
* with the app (see wiki.ts for the GitHub fallback). Content is public docs,
|
||||
@@ -25,6 +30,26 @@ export class HelpController {
|
||||
return getWikiIndex();
|
||||
}
|
||||
|
||||
/**
|
||||
* Full-text search over the bundled pages, for the help panel's search box.
|
||||
* `q` is required; `limit` is optional and clamped by the search itself.
|
||||
*/
|
||||
@Get('search')
|
||||
async search(@Query('q') q?: string, @Query('limit') limit?: string): Promise<{ hits: WikiSearchHit[] }> {
|
||||
const query = (q ?? '').trim();
|
||||
if (!query) throw new HttpException({ error: 'A search query is required' }, 400);
|
||||
if (query.length > SEARCH_MAX_QUERY) {
|
||||
throw new HttpException({ error: `Search query too long (max ${SEARCH_MAX_QUERY} chars)` }, 400);
|
||||
}
|
||||
const n = limit === undefined ? undefined : Number(limit);
|
||||
if (n !== undefined && !Number.isInteger(n)) throw new HttpException({ error: 'limit must be an integer' }, 400);
|
||||
try {
|
||||
return { hits: await searchWiki(query, n) };
|
||||
} catch {
|
||||
throw new HttpException({ error: 'Help search unavailable' }, 502);
|
||||
}
|
||||
}
|
||||
|
||||
@Get('page/:slug')
|
||||
async page(@Param('slug') slug: string, @Res() res: Response): Promise<void> {
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user