mirror of
https://github.com/Kaelio/ktx.git
synced 2026-06-07 07:55:13 +02:00
Merge pull request #51 from Kaelio/demo-target-dir-explain
feat(cli): add intro step and project dir to demo tour
This commit is contained in:
commit
fefbabab5f
2 changed files with 30 additions and 21 deletions
|
|
@ -209,7 +209,7 @@ describe('runDemoTour', () => {
|
|||
},
|
||||
);
|
||||
expect(result).toBe(0);
|
||||
// Navigation called once for databases step, then exits
|
||||
// Navigation called once for intro, then exits on back
|
||||
expect(navigation).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
|
|
@ -218,10 +218,11 @@ describe('runDemoTour', () => {
|
|||
let callCount = 0;
|
||||
const navigation = vi.fn().mockImplementation(() => {
|
||||
callCount++;
|
||||
// First call (databases): forward
|
||||
// Second call (sources): back
|
||||
// Third call (databases again): back (exit)
|
||||
if (callCount === 1) return Promise.resolve('forward');
|
||||
// First call (intro): forward
|
||||
// Second call (databases): forward
|
||||
// Third call (sources): back
|
||||
// Fourth call (databases again): back (exit)
|
||||
if (callCount <= 2) return Promise.resolve('forward');
|
||||
return Promise.resolve('back');
|
||||
});
|
||||
|
||||
|
|
@ -235,7 +236,7 @@ describe('runDemoTour', () => {
|
|||
},
|
||||
);
|
||||
expect(result).toBe(0);
|
||||
expect(navigation).toHaveBeenCalledTimes(3);
|
||||
expect(navigation).toHaveBeenCalledTimes(4);
|
||||
});
|
||||
|
||||
it('handles agent step returning back', async () => {
|
||||
|
|
@ -243,10 +244,10 @@ describe('runDemoTour', () => {
|
|||
let navCount = 0;
|
||||
const navigation = vi.fn().mockImplementation(() => {
|
||||
navCount++;
|
||||
// Forward through databases, sources, context
|
||||
// Forward through intro, databases, sources, context
|
||||
// Then back from context (after agents returns back)
|
||||
// Then back from sources, then back from databases (exit)
|
||||
if (navCount <= 3) return Promise.resolve('forward');
|
||||
if (navCount <= 4) return Promise.resolve('forward');
|
||||
return Promise.resolve('back');
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -62,12 +62,15 @@ function createTargetState(target: KtxPublicIngestPlanTarget): ContextBuildTarge
|
|||
// Pure rendering functions
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export function renderDemoBanner(): string {
|
||||
export function renderDemoBanner(projectDir?: string): string {
|
||||
const lines = [
|
||||
'',
|
||||
`┌ ${cyan('Demo mode')} — data has been pre-processed and KTX context is already built.`,
|
||||
'│ This walkthrough illustrates the setup steps. Selections are pre-filled and read-only.',
|
||||
];
|
||||
if (projectDir) {
|
||||
lines.push(`│ Project directory: ${dim(projectDir)}`);
|
||||
}
|
||||
return lines.join('\n');
|
||||
}
|
||||
|
||||
|
|
@ -144,16 +147,15 @@ export async function waitForDemoNavigation(
|
|||
};
|
||||
|
||||
const onData = (data: Buffer) => {
|
||||
const char = data.toString();
|
||||
if (char === '\r' || char === '\n') {
|
||||
cleanup();
|
||||
resolve('forward');
|
||||
} else if (char === '\x1b') {
|
||||
cleanup();
|
||||
resolve('back');
|
||||
} else if (char === '\x03') {
|
||||
if (data[0] === 0x03) {
|
||||
cleanup();
|
||||
reject(new KtxSetupExitError());
|
||||
} else if (data[0] === 0x0d || data[0] === 0x0a) {
|
||||
cleanup();
|
||||
resolve('forward');
|
||||
} else if (data[0] === 0x1b) {
|
||||
cleanup();
|
||||
resolve('back');
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -171,8 +173,9 @@ export async function renderDemoCard(
|
|||
io: KtxCliIo,
|
||||
stdin?: NodeJS.ReadStream,
|
||||
waitNav: (stdin?: NodeJS.ReadStream) => Promise<'forward' | 'back'> = waitForDemoNavigation,
|
||||
projectDir?: string,
|
||||
): Promise<'forward' | 'back'> {
|
||||
io.stdout.write(renderDemoBanner() + '\n\n');
|
||||
io.stdout.write(renderDemoBanner(projectDir) + '\n\n');
|
||||
io.stdout.write(renderDemoCardContent(title, selections) + '\n');
|
||||
return waitNav(stdin);
|
||||
}
|
||||
|
|
@ -337,6 +340,11 @@ export async function runDemoTour(
|
|||
const projectDir = defaultDemoProjectDir();
|
||||
await ensureProject({ projectDir, force: false });
|
||||
|
||||
io.stdout.write(renderDemoBanner(projectDir) + '\n');
|
||||
io.stdout.write(`\n│ ${dim('Press Enter to continue, Escape to go back')}\n└\n`);
|
||||
const introDirection = await waitNav();
|
||||
if (introDirection === 'back') return 0;
|
||||
|
||||
let stepIndex = 0;
|
||||
|
||||
while (stepIndex < DEMO_STEPS.length) {
|
||||
|
|
@ -344,11 +352,11 @@ export async function runDemoTour(
|
|||
let direction: 'forward' | 'back';
|
||||
|
||||
if (step === 'databases') {
|
||||
direction = await renderDemoCard('Database connection', ['PostgreSQL — Orbit Analytics (56 tables, 2 schemas)'], io, undefined, waitNav);
|
||||
direction = await renderDemoCard('Database connection', ['PostgreSQL — Orbit Analytics (56 tables, 2 schemas)'], io, undefined, waitNav, projectDir);
|
||||
} else if (step === 'sources') {
|
||||
direction = await renderDemoCard('Context sources', ['dbt — 34 transformation models', 'Metabase — 80 dashboard cards', 'Notion — 9 knowledge pages'], io, undefined, waitNav);
|
||||
direction = await renderDemoCard('Context sources', ['dbt — 34 transformation models', 'Metabase — 80 dashboard cards', 'Notion — 9 knowledge pages'], io, undefined, waitNav, projectDir);
|
||||
} else if (step === 'context') {
|
||||
io.stdout.write(renderDemoBanner() + '\n\n');
|
||||
io.stdout.write(renderDemoBanner(projectDir) + '\n\n');
|
||||
if (deps.skipReplayAnimation) {
|
||||
direction = await waitNav();
|
||||
} else {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue