diff --git a/wasp-ai/main.wasp b/wasp-ai/main.wasp index 22f9e6f6d..2182f2aa9 100644 --- a/wasp-ai/main.wasp +++ b/wasp-ai/main.wasp @@ -1,6 +1,6 @@ app waspAi { wasp: { - version: "^0.11.0" + version: "^0.11.5" }, title: "MAGE - GPT Web App Generator ✨", head: [ diff --git a/wasp-ai/src/client/pages/StatsPage.jsx b/wasp-ai/src/client/pages/StatsPage.jsx index b08593628..2200fd5f8 100644 --- a/wasp-ai/src/client/pages/StatsPage.jsx +++ b/wasp-ai/src/client/pages/StatsPage.jsx @@ -45,43 +45,7 @@ export function Stats() { }, {}); }, [stats]); - function getColorValue(colorName) { - return availableColors.find((color) => color.name === colorName).color; - } - - function getStatusName(status) { - switch (status) { - case "in-progress": - return "inProgress"; - case "success": - return "success"; - case "failure": - return "error"; - case "cancelled": - return "cancelled"; - default: - return "idle"; - } - } - - function getStatusText(status) { - switch (status) { - case "in-progress": - return "In progress"; - case "success": - return "Success"; - case "failure": - return "Error"; - case "cancelled": - return "Cancelled"; - case "pending": - return "Pending"; - default: - return "Unknown"; - } - } - - const filteredStats = useMemo(() => { + const filteredProjects = useMemo(() => { const filters = []; if (filterOutExampleApps) { filters.push( @@ -103,9 +67,9 @@ export function Stats() { : []; }, [stats, stats?.projects, filterOutExampleApps, filterOutKnownUsers]); - const limitedFilteredStats = useMemo(() => { - return filteredStats.slice(0, 1000); - }, [filteredStats]); + const limitedFilteredProjects = useMemo(() => { + return filteredProjects.slice(0, 1000); + }, [filteredProjects]); if (isLoading) { return

Loading

; @@ -119,41 +83,11 @@ export function Stats() { return

Couldn't load stats

; } + const downloadStats = getDownloadStats(filteredProjects); + const downloadedPercentage = - Math.round(stats.downloadStats.downloadRatio * 10000) / 100; + Math.round(downloadStats.downloadRatio * 10000) / 100; - function getFormattedDiff(start, end) { - const diff = (end - start) / 1000; - const minutes = Math.round(diff / 60); - const remainingSeconds = Math.round(diff % 60); - return `${minutes}m ${remainingSeconds}s`; - } - - function getDuration(stat) { - if (!logsByProjectId[stat.id]) { - return "-"; - } - const logs = logsByProjectId[stat.id]; - if (logs.length < 2) { - return "-"; - } - const start = logs[logs.length - 1].createdAt; - const end = logs[0].createdAt; - return getFormattedDiff(start, end); - } - - function getWaitingInQueueDuration(stat) { - if (!logsByProjectId[stat.id]) { - return "-"; - } - const logs = logsByProjectId[stat.id]; - if (logs.length < 2) { - return "-"; - } - const start = stat.createdAt; - const end = logs[logs.length - 1].createdAt; - return getFormattedDiff(start, end); - } return ( <>
@@ -192,7 +126,7 @@ export function Stats() { {({ width, height }) => ( @@ -242,12 +176,12 @@ export function Stats() { Generated:{" "} - {filteredStats.length} + {filteredProjects.length} Downlaoded:{" "} - {`${stats.downloadStats.projectsDownloaded} (${downloadedPercentage}%)`} + {`${downloadStats.projectsDownloaded} (${downloadedPercentage}%)`}

@@ -275,29 +209,29 @@ export function Stats() { - {limitedFilteredStats.map((stat) => ( - + {filteredProjects.map((project) => ( + - {" "} + {" "} - {stat.name} + {project.name} {" "} - {stat.user && ( - + {project.user && ( + )} - {stat.zipDownloadedAt && ( + {project.zipDownloadedAt && ( @@ -307,28 +241,28 @@ export function Stats() { - - {getStatusText(stat.status)} + + {getStatusText(project.status)} - {format(stat.createdAt)} + {format(project.createdAt)} - {getWaitingInQueueDuration(stat)} →{" "} - {getDuration(stat)} + {getWaitingInQueueDuration(project, logsByProjectId)}{" "} + → {getDuration(project, logsByProjectId)} - {stat.creativityLevel} + {project.creativityLevel} View the app → @@ -338,7 +272,7 @@ export function Stats() { ))} - {filteredStats.length > limitedFilteredStats.length && ( + {filteredProjects.length > limitedFilteredProjects.length && (
Showing only the latest 1000 projects
@@ -350,3 +284,91 @@ export function Stats() { ); } + +function getDownloadStats(projects) { + const projectsAfterDownloadTracking = projects.filter( + (project) => + // This is the time of the first recorded download (after we rolled out download tracking). + project.createdAt > new Date("2023-07-14 10:36:45.12") && + project.status === "success" + ); + const downloadedProjects = projectsAfterDownloadTracking.filter( + (project) => project.zipDownloadedAt !== null + ); + return { + projectsDownloaded: downloadedProjects.length, + downloadRatio: + projectsAfterDownloadTracking.length > 0 + ? downloadedProjects.length / projectsAfterDownloadTracking.length + : 0, + }; +} + +function getFormattedDiff(start, end) { + const diff = (end - start) / 1000; + const minutes = Math.round(diff / 60); + const remainingSeconds = Math.round(diff % 60); + return `${minutes}m ${remainingSeconds}s`; +} + +function getDuration(stat, logsByProjectId) { + if (!logsByProjectId[stat.id]) { + return "-"; + } + const logs = logsByProjectId[stat.id]; + if (logs.length < 2) { + return "-"; + } + const start = logs[logs.length - 1].createdAt; + const end = logs[0].createdAt; + return getFormattedDiff(start, end); +} + +function getWaitingInQueueDuration(stat, logsByProjectId) { + if (!logsByProjectId[stat.id]) { + return "-"; + } + const logs = logsByProjectId[stat.id]; + if (logs.length < 2) { + return "-"; + } + const start = stat.createdAt; + const end = logs[logs.length - 1].createdAt; + return getFormattedDiff(start, end); +} + +function getColorValue(colorName) { + return availableColors.find((color) => color.name === colorName).color; +} + +function getStatusName(status) { + switch (status) { + case "in-progress": + return "inProgress"; + case "success": + return "success"; + case "failure": + return "error"; + case "cancelled": + return "cancelled"; + default: + return "idle"; + } +} + +function getStatusText(status) { + switch (status) { + case "in-progress": + return "In progress"; + case "success": + return "Success"; + case "failure": + return "Error"; + case "cancelled": + return "Cancelled"; + case "pending": + return "Pending"; + default: + return "Unknown"; + } +} diff --git a/wasp-ai/src/server/operations.ts b/wasp-ai/src/server/operations.ts index 7dcd91a43..177acf613 100644 --- a/wasp-ai/src/server/operations.ts +++ b/wasp-ai/src/server/operations.ts @@ -215,12 +215,9 @@ export const getStats = (async (_args, context) => { }, }); - const downloadStats = getDownloadStats(projects); - return { projects, latestProjectsWithLogs, - downloadStats, }; }) satisfies GetStats<{}>; @@ -229,20 +226,3 @@ export const getNumProjects = (async (_args, context) => { const numProjects = await Project.count(); return numProjects; }) satisfies GetNumProjects<{}>; - -function getDownloadStats(projects: Project[]) { - const projectsAfterDownloadTracking = projects.filter( - (project) => - // This is the time of the first recorded download (after we rolled out download tracking). - project.createdAt > new Date("2023-07-14 10:36:45.12") && - project.status === "success" - ); - const downloadedProjects = projectsAfterDownloadTracking.filter( - (project) => project.zipDownloadedAt !== null - ); - return { - projectsDownloaded: downloadedProjects.length, - downloadRatio: - downloadedProjects.length / projectsAfterDownloadTracking.length, - }; -}