mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-30 05:18:11 +00:00
92 lines
2.9 KiB
TypeScript
92 lines
2.9 KiB
TypeScript
import { MigrationInterface, QueryRunner } from "typeorm";
|
|
|
|
/**
|
|
* Folds each help section's `media[]` array into its markdown body.
|
|
*
|
|
* Attachments used to hang off the section as a separate list, rendered after
|
|
* the text — which meant an author could not put a picture next to the sentence
|
|
* it illustrates, and had two different places to manage media. They are now
|
|
* embedded with markdown's image syntax, and the renderer picks `<img>` or
|
|
* `<video>` from the file extension.
|
|
*
|
|
* Existing entries are converted rather than dropped: an uploaded object
|
|
* becomes ``, and a shipped asset path or external URL
|
|
* is kept verbatim. Sections are left alone once they have no `media` key, so
|
|
* re-running does nothing.
|
|
*/
|
|
interface LegacyMedia {
|
|
src: string;
|
|
caption?: string | null;
|
|
}
|
|
|
|
interface LegacySection {
|
|
id: string;
|
|
heading: string;
|
|
body: string;
|
|
media?: LegacyMedia[];
|
|
}
|
|
|
|
/** Uploaded objects are stored as keys; the `minio:` ref is signed on read. */
|
|
function toMarkdown(item: LegacyMedia): string {
|
|
const isStoredObject = !/^(https?:\/\/|\/)/.test(item.src);
|
|
const target = isStoredObject ? `minio:${item.src}` : item.src;
|
|
return ``;
|
|
}
|
|
|
|
export class SupportHelpInlineMedia3370000000000 implements MigrationInterface {
|
|
name = "SupportHelpInlineMedia3370000000000";
|
|
|
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
|
const rows: {
|
|
id: string;
|
|
version: number;
|
|
payload: { sections?: LegacySection[] } & Record<string, unknown>;
|
|
}[] = await queryRunner.query(`
|
|
SELECT id, version, payload
|
|
FROM freight.support_documents
|
|
WHERE slug = 'HELP'
|
|
`);
|
|
|
|
for (const row of rows) {
|
|
const sections = row.payload.sections ?? [];
|
|
if (!sections.some((section) => section.media !== undefined)) continue;
|
|
|
|
const payload = {
|
|
...row.payload,
|
|
sections: sections.map(({ media, ...section }) => {
|
|
const embeds = (media ?? []).map(toMarkdown);
|
|
return {
|
|
...section,
|
|
body: [section.body, ...embeds].filter(Boolean).join("\n\n"),
|
|
};
|
|
}),
|
|
};
|
|
const version = row.version + 1;
|
|
|
|
await queryRunner.query(
|
|
`UPDATE freight.support_documents
|
|
SET payload = $1::jsonb, version = $2, updated_at = now()
|
|
WHERE id = $3`,
|
|
[JSON.stringify(payload), version, row.id],
|
|
);
|
|
|
|
await queryRunner.query(
|
|
`INSERT INTO freight.support_document_versions
|
|
(document_id, version, payload, actor_id, note)
|
|
VALUES ($1, $2, $3::jsonb, NULL, $4)`,
|
|
[
|
|
row.id,
|
|
version,
|
|
JSON.stringify(payload),
|
|
"Moved attachments inline into the section text",
|
|
],
|
|
);
|
|
}
|
|
}
|
|
|
|
/** Not reversible — see the note on SupportHelpSections3360000000000. */
|
|
public async down(): Promise<void> {
|
|
// no-op
|
|
}
|
|
}
|