Workspace transfer: custom themes ride the export/import envelope

This commit is contained in:
2026-06-12 21:45:44 +03:00
parent 80d13c9b6f
commit dbb4522d78
11 changed files with 405 additions and 173 deletions
+24 -9
View File
@@ -12,6 +12,7 @@
* migration target — see snippet.ts / dataset.ts).
*/
import type { CustomTheme } from './custom-theme';
import type { Dataset } from './dataset';
import type { Snippet } from './snippet';
@@ -24,8 +25,9 @@ export const EXPORT_ENVELOPE_VERSION = '1.0';
/**
* The downloaded file's top-level shape (spec §08 → Export envelope shape): format
* metadata plus the two complete-record arrays. Each record keeps its own `version`
* field unchanged.
* metadata plus the complete-record arrays. Each record keeps its own `version`
* field unchanged. `themes` is additive (always written, optional on read) so
* pre-theme envelopes and importers remain compatible without a format bump.
*/
export interface ExportEnvelope {
/** Export format version (currently `"1.0"`). */
@@ -38,6 +40,8 @@ export interface ExportEnvelope {
snippets: Snippet[];
/** All datasets, as complete records (each including its record `version`). */
datasets: Dataset[];
/** All custom chart themes, as complete records (each including its record `version`). */
themes: CustomTheme[];
}
/**
@@ -50,6 +54,7 @@ export interface ExportEnvelope {
export function buildExportEnvelope(
snippets: ReadonlyArray<Snippet>,
datasets: ReadonlyArray<Dataset>,
themes: ReadonlyArray<CustomTheme>,
opts: { now: Date },
): ExportEnvelope {
return {
@@ -58,6 +63,7 @@ export function buildExportEnvelope(
exportedBy: 'Astrolabe',
snippets: [...snippets],
datasets: [...datasets],
themes: [...themes],
};
}
@@ -82,12 +88,21 @@ function countClause(count: number, noun: string): string {
}
/**
* Success-toast message reporting the export counts (spec §08 → Feedback), e.g.
* "Exported 4 snippets and 2 datasets". The dataset clause is omitted entirely when
* there are no datasets; singular/plural wording adapts to the counts.
* Success-toast message reporting transfer counts (spec §08 → Feedback) for both
* directions, e.g. "Exported 4 snippets, 2 datasets and 1 theme" / "Imported 1
* snippet". The dataset and theme clauses are omitted entirely when their counts
* are zero; singular/plural wording adapts. One builder for export and import so
* a new record kind or wording change lands in both messages at once.
*/
export function exportSummaryMessage(snippetCount: number, datasetCount: number): string {
const snippets = countClause(snippetCount, 'snippet');
if (datasetCount === 0) return `Exported ${snippets}`;
return `Exported ${snippets} and ${countClause(datasetCount, 'dataset')}`;
export function transferSummaryMessage(
verb: 'Exported' | 'Imported',
snippetCount: number,
datasetCount: number,
themeCount: number,
): string {
const clauses = [countClause(snippetCount, 'snippet')];
if (datasetCount > 0) clauses.push(countClause(datasetCount, 'dataset'));
if (themeCount > 0) clauses.push(countClause(themeCount, 'theme'));
const last = clauses.pop()!;
return clauses.length === 0 ? `${verb} ${last}` : `${verb} ${clauses.join(', ')} and ${last}`;
}