Skip to content

Commit 050349a

Browse files
Polish model catalog workspace UX
Co-authored-by: Ishaan Jaff <ishaan-jaff@users.noreply.github.com>
1 parent 6c8485b commit 050349a

8 files changed

Lines changed: 1935 additions & 424 deletions
888 KB
Binary file not shown.
381 KB
Binary file not shown.

demo-videos/record-demo.mjs

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
import fs from "node:fs/promises";
2+
import path from "node:path";
3+
import { chromium, devices } from "playwright";
4+
5+
const baseUrl = "http://127.0.0.1:5173/";
6+
const outputDir = "/workspace/demo-videos";
7+
const tempDir = path.join(outputDir, "tmp");
8+
const chromePath = "/usr/local/bin/google-chrome";
9+
10+
async function ensureCleanDirectory(directory) {
11+
await fs.rm(directory, { recursive: true, force: true });
12+
await fs.mkdir(directory, { recursive: true });
13+
}
14+
15+
async function moveRecordedVideo(sourceDirectory, destinationPath) {
16+
const files = (await fs.readdir(sourceDirectory)).filter((file) =>
17+
file.endsWith(".webm"),
18+
);
19+
20+
if (!files.length) {
21+
throw new Error(`No video was recorded in ${sourceDirectory}`);
22+
}
23+
24+
await fs.rename(path.join(sourceDirectory, files[0]), destinationPath);
25+
}
26+
27+
async function waitForResults(page) {
28+
await page.waitForSelector(".results-count", { timeout: 30000 });
29+
await page.waitForTimeout(1200);
30+
}
31+
32+
async function recordDesktop(browser) {
33+
const videoDirectory = path.join(tempDir, "desktop");
34+
await fs.mkdir(videoDirectory, { recursive: true });
35+
36+
const context = await browser.newContext({
37+
viewport: { width: 1440, height: 1200 },
38+
recordVideo: {
39+
dir: videoDirectory,
40+
size: { width: 1440, height: 1200 },
41+
},
42+
});
43+
44+
const page = await context.newPage();
45+
46+
await page.goto(baseUrl, { waitUntil: "domcontentloaded" });
47+
await waitForResults(page);
48+
49+
const desktopQueryInput = page.locator("#query");
50+
await desktopQueryInput.evaluate((element) => {
51+
element.scrollIntoView({ block: "center" });
52+
});
53+
await desktopQueryInput.focus();
54+
await desktopQueryInput.pressSequentially("gpt-4", { delay: 100 });
55+
await page.waitForTimeout(900);
56+
57+
await page.locator(".dropdown-trigger").click();
58+
await page.locator(".dropdown-menu .search-input").fill("openai");
59+
await page.waitForTimeout(600);
60+
await page.getByRole("option", { name: /openai/i }).first().click();
61+
await page.waitForTimeout(900);
62+
63+
const desktopRowToggle = page.locator(".desktop-results tbody .row-toggle").first();
64+
await desktopRowToggle.evaluate((element) => {
65+
element.scrollIntoView({ block: "center" });
66+
});
67+
await desktopRowToggle.evaluate((element) => {
68+
element.click();
69+
});
70+
await page.waitForSelector(".desktop-results .expanded-content", { timeout: 30000 });
71+
await page.waitForTimeout(900);
72+
await page.locator(".desktop-results .expanded-content .code-tab", { hasText: "AI Gateway" }).first().click({ force: true });
73+
await page.waitForTimeout(600);
74+
await page.locator(".desktop-results .copy-code-btn").first().click();
75+
await page.waitForTimeout(900);
76+
77+
await desktopQueryInput.fill("enterprise-unknown-model-123");
78+
await page.waitForTimeout(1400);
79+
80+
const suggestion = page.locator(".suggestion-card").first();
81+
if (await suggestion.count()) {
82+
await suggestion.click();
83+
await page.waitForTimeout(1200);
84+
} else {
85+
await page.waitForTimeout(1200);
86+
}
87+
88+
await context.close();
89+
await moveRecordedVideo(
90+
videoDirectory,
91+
path.join(outputDir, "desktop-workspace-demo.webm"),
92+
);
93+
}
94+
95+
async function recordMobile(browser) {
96+
const videoDirectory = path.join(tempDir, "mobile");
97+
await fs.mkdir(videoDirectory, { recursive: true });
98+
99+
const context = await browser.newContext({
100+
...devices["iPhone 13"],
101+
recordVideo: {
102+
dir: videoDirectory,
103+
size: { width: 390, height: 844 },
104+
},
105+
});
106+
107+
const page = await context.newPage();
108+
109+
await page.goto(baseUrl, { waitUntil: "domcontentloaded" });
110+
await waitForResults(page);
111+
112+
const mobileQueryInput = page.locator("#query");
113+
await mobileQueryInput.evaluate((element) => {
114+
element.scrollIntoView({ block: "center" });
115+
});
116+
await mobileQueryInput.focus();
117+
await mobileQueryInput.pressSequentially("claude", { delay: 90 });
118+
await page.waitForTimeout(900);
119+
await page.locator(".card-expand-btn").first().click({ force: true });
120+
await page.waitForTimeout(1200);
121+
await page.locator(".model-card-detail .copy-code-btn").first().click();
122+
await page.waitForTimeout(900);
123+
124+
await page.evaluate(() => {
125+
window.scrollTo(0, 0);
126+
});
127+
await page.waitForTimeout(800);
128+
await page.locator(".mobile-menu-btn").click({ force: true });
129+
await page.waitForSelector(".mobile-menu", { timeout: 30000 });
130+
await page.locator(".mobile-request-button").click({ force: true });
131+
await page.waitForSelector(".modal-content", { timeout: 30000 });
132+
await page.waitForTimeout(900);
133+
await page.locator(".type-button", { hasText: "Model" }).click();
134+
await page.locator("#request").fill("Support a model with a 1M token context window and enterprise SLA visibility.");
135+
await page.locator("#email").fill("demo@example.com");
136+
await page.waitForTimeout(1500);
137+
138+
await context.close();
139+
await moveRecordedVideo(
140+
videoDirectory,
141+
path.join(outputDir, "mobile-workspace-and-modal-demo.webm"),
142+
);
143+
}
144+
145+
async function main() {
146+
await ensureCleanDirectory(tempDir);
147+
148+
const browser = await chromium.launch({
149+
executablePath: chromePath,
150+
headless: true,
151+
args: ["--no-sandbox", "--disable-dev-shm-usage"],
152+
});
153+
154+
try {
155+
await recordDesktop(browser);
156+
await recordMobile(browser);
157+
} finally {
158+
await browser.close();
159+
await fs.rm(tempDir, { recursive: true, force: true });
160+
}
161+
}
162+
163+
main().catch((error) => {
164+
console.error(error);
165+
process.exitCode = 1;
166+
});

0 commit comments

Comments
 (0)