Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 67 additions & 21 deletions src/cli/journey/journey-export.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Option } from 'commander';

import { getTokens } from '../../ops/AuthenticateOps';
import {
exportJourneyCoords,
exportJourneysToFile,
exportJourneysToFiles,
exportJourneyToFile,
Expand Down Expand Up @@ -62,6 +63,12 @@ export default function setup() {
'Do not include the x and y coordinate positions of the journey/tree nodes.'
)
)
.addOption(
new Option(
'--sep-coords',
'Export x and y coordinate positions of the journey/tree nodes to separate files.'
).default(false)
)
// .addOption(
// new Option(
// '-O, --organize <method>',
Expand All @@ -82,44 +89,82 @@ export default function setup() {
options,
command
);
if (!(await getTokens())) {
printMessage('Authentication failed.', 'error');
process.exitCode = 1;
return;
}
let outcome = false;
// export
if (options.journeyId && (await getTokens())) {
if (options.journeyId) {
verboseMessage('Exporting journey...');
const outcome = await exportJourneyToFile(
outcome = await exportJourneyToFile(
options.journeyId,
options.file,
options.metadata,
{
useStringArrays: options.useStringArrays,
deps: options.deps,
coords: options.coords,
coords: options.coords && !options.sepCoords,
}
);
if (!outcome) process.exitCode = 1;
if (outcome && options.sepCoords) {
verboseMessage('Exporting journey coordinates separately...');
await exportJourneyCoords([options.journeyId], options.metadata, {
deps: options.deps,
useStringArrays: options.useStringArrays,
coords: true,
sepCoords: true,
});
}
}
// --all -a
else if (options.all && (await getTokens())) {
else if (options.all) {
verboseMessage('Exporting all journeys to a single file...');
const outcome = await exportJourneysToFile(
options.file,
options.metadata,
{
useStringArrays: options.useStringArrays,
deps: options.deps,
coords: options.coords,
}
);
if (!outcome) process.exitCode = 1;
outcome = await exportJourneysToFile(options.file, options.metadata, {
useStringArrays: options.useStringArrays,
deps: options.deps,
coords: options.coords && !options.sepCoords,
});
if (outcome && options.sepCoords) {
verboseMessage(
'Exporting coordinates of all journeys to a separate file...'
);
await exportJourneyCoords(
'all',
options.metadata,
{
deps: options.deps,
useStringArrays: options.useStringArrays,
coords: true,
},
'all'
);
}
}
// --all-separate -A
else if (options.allSeparate && (await getTokens())) {
else if (options.allSeparate) {
verboseMessage('Exporting all journeys to separate files...');
const outcome = await exportJourneysToFiles(options.metadata, {
outcome = await exportJourneysToFiles(options.metadata, {
useStringArrays: options.useStringArrays,
deps: options.deps,
coords: options.coords,
coords: options.coords && !options.sepCoords,
});
if (!outcome) process.exitCode = 1;
if (outcome && options.sepCoords) {
verboseMessage(
'Exporting coordinates of all journeys to separate files...'
);
await exportJourneyCoords(
'all',
options.metadata,
{
deps: options.deps,
useStringArrays: options.useStringArrays,
coords: true,
},
'allSeparate'
);
}
}
// unrecognized combination of options or no options
else {
Expand All @@ -129,10 +174,11 @@ export default function setup() {
);
program.help();
process.exitCode = 1;
return;
}

if (!outcome) process.exitCode = 1;
}
// end command logic inside action handler
);

return program;
}
123 changes: 123 additions & 0 deletions src/ops/JourneyOps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,129 @@ export async function exportJourneysToFiles(
return false;
}

export async function exportJourneyCoords(
journeyIds: string[] | 'all',
includeMeta: boolean = true,
options: TreeExportOptions = {
deps: false,
useStringArrays: false,
coords: true,
},
mode: 'single' | 'all' | 'allSeparate' = 'single'
): Promise<boolean> {
try {
let idsToExport: string[] = [];
if (journeyIds === 'all') {
const journeysExport = await exportJourneys(options, errorHandler);
idsToExport = Object.keys(journeysExport.trees);
} else {
idsToExport = journeyIds;
}
if (mode === 'all') {
const allCoords: Record<
string,
{
nodeCoordinates: Record<string, { x: number; y: number }>;
staticNodeCoordinates: Record<string, { x: number; y: number }>;
}
> = {};
for (const treeId of idsToExport) {
const treeExport = await exportJourney(treeId, options);
const nodeCoordinates: Record<string, { x: number; y: number }> = {};
const staticNodeCoordinates: Record<string, { x: number; y: number }> =
{};
const justNodes: typeof treeExport.tree.nodes = {};
for (const [nodeId, nodeData] of Object.entries(
treeExport.tree.nodes
)) {
const { x, y, ...etc } = nodeData as any;
if (typeof x === 'number' && typeof y === 'number')
nodeCoordinates[nodeId] = { x, y };
justNodes[nodeId] = etc;
}
const justStaticNodes: typeof treeExport.tree.staticNodes = {};
for (const [nodeId, nodeData] of Object.entries(
treeExport.tree.staticNodes ?? {}
)) {
const { x, y, ...etc } = nodeData as any;
if (typeof x === 'number' && typeof y === 'number')
staticNodeCoordinates[nodeId] = { x, y };
justStaticNodes[nodeId] = etc;
}
allCoords[treeId] = { nodeCoordinates, staticNodeCoordinates };
}
const coordsFile = getFilePath(
getTypedFilename(`allJourneys`, 'coords'),
true
);
saveJsonToFile({ coordinates: allCoords }, coordsFile, includeMeta);
return true;
}
for (const treeId of idsToExport) {
try {
const treeExport = await exportJourney(treeId, options);
const nodeCoordinates: Record<string, { x: number; y: number }> = {};
const staticNodeCoordinates: Record<string, { x: number; y: number }> =
{};
const justNodes: typeof treeExport.tree.nodes = {};
for (const [nodeId, nodeData] of Object.entries(
treeExport.tree.nodes
)) {
const { x, y, ...etc } = nodeData as any;
if (typeof x === 'number' && typeof y === 'number')
nodeCoordinates[nodeId] = { x, y };
justNodes[nodeId] = etc;
}
const justStaticNodes: typeof treeExport.tree.staticNodes = {};
for (const [nodeId, nodeData] of Object.entries(
treeExport.tree.staticNodes ?? {}
)) {
const { x, y, ...etc } = nodeData as any;
if (typeof x === 'number' && typeof y === 'number')
staticNodeCoordinates[nodeId] = { x, y };
justStaticNodes[nodeId] = etc;
}
const justTree = {
...treeExport,
tree: {
...treeExport.tree,
nodes: justNodes,
staticNodes: justStaticNodes,
},
};
if (mode === 'single') {
const journeyFile = getFilePath(
getTypedFilename(treeId, 'journey'),
true
);
delete justTree.meta;
saveJsonToFile(
{ trees: { [treeId]: justTree } },
journeyFile,
includeMeta
);
}
const coordsFile = getFilePath(
getTypedFilename(treeId, 'coords'),
true
);
saveJsonToFile(
{ nodeCoordinates, staticNodeCoordinates },
coordsFile,
includeMeta
);
printMessage(`${treeId} node coordinates saved.`, 'info');
} catch (error) {
throw new FrodoError(`Error saving ${treeId}`, error);
}
}
return true;
} catch (error) {
printError(error);
}
return false;
}

/**
* Import a journey from file
* @param {string} journeyId journey id/name
Expand Down
3 changes: 3 additions & 0 deletions test/client_cli/en/__snapshots__/journey-export.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ Options:
--no-deps Do not include any dependencies (scripts, email
templates, SAML entity providers and circles of
trust, social identity providers, themes).
--sep-coords Export x and y coordinate positions of the
journey/tree nodes to separate files. (default:
false)
--use-string-arrays Where applicable, use string arrays to store
multi-line text (e.g. scripts). (default: off)
-h, --help Help
Expand Down
Loading