* Martech

* Record zip downloads

* fix

---------

Co-authored-by: Martin Sosic <sosic.martin@gmail.com>
Co-authored-by: Martin Šošić <Martinsos@users.noreply.github.com>
This commit is contained in:
Filip Sodić 2023-07-14 12:10:55 +02:00 committed by Martin Sosic
parent f605726712
commit bcbd138244
8 changed files with 79 additions and 9 deletions

View File

@ -75,6 +75,11 @@ action startGeneratingNewApp {
]
}
action registerZipDownload {
fn: import { registerZipDownload } from "@server/operations.js",
entities: [Project]
}
query getAppGenerationResult {
fn: import { getAppGenerationResult } from "@server/operations.js",
entities: [
@ -116,6 +121,8 @@ entity Project {=psl
creativityLevel String @default("balanced")
createdAt DateTime @default(now())
status String @default("pending")
referrer String @default("unknown")
zipDownloadedAt DateTime?
userId Int?
user User? @relation(fields: [userId], references: [id])
files File[]

View File

@ -0,0 +1,2 @@
-- AlterTable
ALTER TABLE "Project" ADD COLUMN "referrer" TEXT NOT NULL DEFAULT 'unknown';

View File

@ -0,0 +1,2 @@
-- AlterTable
ALTER TABLE "Project" ADD COLUMN "zipDownloadedAt" TIMESTAMP(3);

View File

@ -1,9 +1,10 @@
import { useEffect, useMemo } from "react";
import { useLocation } from "react-router-dom";
import { useHistory, useLocation } from "react-router-dom";
import Prism from "prismjs";
import "prismjs/components/prism-json";
import addWaspLangauge from "./prism/wasp";
import addPrismaLanguage from "./prism/prisma";
import { saveReferrerToLocalStorage } from "./storage";
import "./Main.css";
@ -11,18 +12,26 @@ addPrismaLanguage(Prism);
addWaspLangauge(Prism);
export function RootComponent({ children }) {
function recordAndDeleteReferrer() {
const urlParams = new URLSearchParams(window.location.search);
saveReferrerToLocalStorage(urlParams);
history.replace({
search: "",
});
}
// const { isAlreadyShown } = useWelcomeDialog();
// const [isDialogOpen, setIsDialogOpen] = useState(!isAlreadyShown);
const history = useHistory();
const location = useLocation();
const shouldDisplayTopBanner = useMemo(() => {
return !(location.pathname.startsWith("/result/"));
}, [location]);
useEffect(() => {
recordAndDeleteReferrer();
const script = document.createElement("script");
script.src = "https://buttons.github.io/buttons.js"; // <----- add your script url
script.async = true;
@ -88,7 +97,7 @@ export function RootComponent({ children }) {
rel="noopener noreferrer"
className="text-sky-500 hover:text-sky-600"
>
Wasp {'=}'}
Wasp {"=}"}
</a>
</p>
<p className="text-center text-slate-500 text-sm mt-2">

View File

@ -8,6 +8,7 @@ import { availableColors } from "../components/Color";
import { Faq } from "../components/Faq";
import { exampleIdeas } from "../examples";
import { PiMagicWandDuotone } from "react-icons/pi";
import { readReferrerFromLocalStorage } from "../storage";
const MainPage = () => {
const [appName, setAppName] = useState("");
@ -74,7 +75,9 @@ const MainPage = () => {
message: "Starting...",
});
try {
const referrer = readReferrerFromLocalStorage();
const appId = await startGeneratingNewApp({
referrer,
appName,
appDesc,
appPrimaryColor: appPrimaryColor.name,

View File

@ -1,6 +1,7 @@
import { useState, useEffect, useMemo } from "react";
import getAppGenerationResult from "@wasp/queries/getAppGenerationResult";
import startGeneratingNewApp from "@wasp/actions/startGeneratingNewApp";
import registerZipDownload from "@wasp/actions/registerZipDownload";
import { useQuery } from "@wasp/queries";
import { CodeHighlight } from "../components/CodeHighlight";
import { FileTree } from "../components/FileTree";
@ -146,14 +147,21 @@ export const ResultPage = () => {
setIsMobileFileBrowserOpen(false);
}, [activeFilePath]);
function downloadZip() {
async function downloadZip() {
const zipName = getUniqueZipName();
createFilesAndDownloadZip(files, zipName);
registerZipDownload({
appId: appGenerationResult?.project?.id,
});
}
function getUniqueZipName() {
const safeAppName = appGenerationResult?.project?.name.replace(
/[^a-zA-Z0-9]/g,
"_"
);
const randomSuffix = Math.random().toString(36).substring(2, 7);
const appNameWithSuffix = `${safeAppName}-${randomSuffix}`;
createFilesAndDownloadZip(files, appNameWithSuffix);
return `${safeAppName}-${randomSuffix}`;
}
async function retry() {

View File

@ -0,0 +1,14 @@
const REFERRER_KEY = "ref";
const UNKNOWN_REFERRER = "unknown";
export function saveReferrerToLocalStorage(urlParams: URLSearchParams) {
const newRefValue = urlParams.get(REFERRER_KEY) ?? UNKNOWN_REFERRER;
const oldRefValue = localStorage.getItem(REFERRER_KEY);
if (oldRefValue === null) {
localStorage.setItem(REFERRER_KEY, newRefValue);
}
}
export function readReferrerFromLocalStorage() {
return localStorage.getItem(REFERRER_KEY) ?? UNKNOWN_REFERRER;
}

View File

@ -1,10 +1,14 @@
import { StartGeneratingNewApp } from "@wasp/actions/types";
import {
RegisterZipDownload,
StartGeneratingNewApp,
} from "@wasp/actions/types";
import { GetAppGenerationResult, GetStats } from "@wasp/queries/types";
import HttpError from "@wasp/core/HttpError.js";
import { checkPendingAppsJob } from "@wasp/jobs/checkPendingAppsJob.js";
export const startGeneratingNewApp: StartGeneratingNewApp<
{
referrer: string;
appName: string;
appDesc: string;
appPrimaryColor: string;
@ -42,6 +46,7 @@ export const startGeneratingNewApp: StartGeneratingNewApp<
primaryColor: args.appPrimaryColor,
authMethod: args.appAuthMethod,
creativityLevel: args.appCreativityLevel,
referrer: args.referrer,
...optionalUser,
},
});
@ -53,6 +58,24 @@ export const startGeneratingNewApp: StartGeneratingNewApp<
return appId;
};
export const registerZipDownload: RegisterZipDownload<{
appId: string;
}> = async (args, context) => {
const appId = args.appId;
try {
await context.entities.Project.update({
where: { id: appId },
data: {
zipDownloadedAt: new Date(),
},
});
} catch (e) {
if (e.name === "NotFoundError") {
throw new HttpError(404, "App not found.");
} else { throw e; }
}
};
export const getAppGenerationResult = (async (args, context) => {
const appId = args.appId;
const { Project } = context.entities;
@ -84,7 +107,9 @@ export const getAppGenerationResult = (async (args, context) => {
numberOfProjectsAheadInQueue,
};
} catch (e) {
throw new HttpError(404, "App not found.");
if (e.name === "NotFoundError") {
throw new HttpError(404, "App not found.");
} else { throw e; }
}
}) satisfies GetAppGenerationResult<{
appId: string;