Skip to content
This repository has been archived by the owner on Mar 12, 2024. It is now read-only.

Commit

Permalink
Feature/posthog frontend (#242)
Browse files Browse the repository at this point in the history
* Create param validator

* Move discord

* Move user settings getter to app router

* Use standard var

* move getAllPublicUserData to app router

* Better error handling

* Delete getAllData.ts

* Delete discord

* Throw errors

* Handle error throwing

* Move updateSettings to app router

* Update confluence.svg

* Configure jest

* Create settings.test.ts

* Create updateSettings.test.ts

* Add getting test

* Use generalized validator

* Move Stripe to app router

* Move Sendgrid to app router

* Move vscode to airtable Analytics to app router

* Frontend analytics

* Change export

* Fix export

* Fix export
  • Loading branch information
EstebanDalelR authored Aug 14, 2023
1 parent fa8d582 commit 6eafdab
Show file tree
Hide file tree
Showing 11 changed files with 157 additions and 79 deletions.
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { NextResponse } from "next/server";
import validateParams from "../../../../../utils/api/validateParams";
import Airtable from "airtable";
Airtable.configure({
endpointUrl: "https://api.airtable.com",
Expand All @@ -24,13 +26,21 @@ function toRecords(infoArray) {
}
return records;
}
export default async function handler(req, res) {
const { dailyStats } = req.body;
export async function POST(request: Request) {
const req = await request.json();
const { missingParams } = validateParams(req, ["dailyStats"]);

if (missingParams.length > 0) {
return NextResponse.json({
error: `Missing parameters: ${missingParams.join(", ")}`,
});
}
const { dailyStats } = req;
let records;
if (dailyStats.length < 10) {
records = toRecords(dailyStats.slice(0, 10));
let createdRecord = await base("vscmarketplace").create(records);
res.status(200).json(createdRecord);
return NextResponse.json(createdRecord);
} else {
records = toRecords(dailyStats);
// now take the records and chunk them into groups of 10
Expand All @@ -53,6 +63,6 @@ export default async function handler(req, res) {
// @ts-ignore
createdRecords.push(createdRecord);
}
res.status(200).json(createdRecords);
return NextResponse.json(createdRecords);
}
}
28 changes: 28 additions & 0 deletions app/api/sendgrid/sendTeammateInvite/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { NextResponse } from "next/server";
import validateParams from "../../../../utils/api/validateParams";
import sendTeammateInvite from "../../../../utils/sendgrid/sendTeammateInvite";

export async function POST(request: Request) {
const req = await request.json();
const { missingParams } = validateParams(req, [
"sender",
"email",
"inviteUrl",
"teamName",
]);

if (missingParams.length > 0) {
return NextResponse.json({
error: `Missing parameters: ${missingParams.join(", ")}`,
});
}
const { sender, email, inviteUrl, teamName } = req;

let emailSent = await sendTeammateInvite({
sender,
teammateEmail: email,
inviteUrl,
teamName,
});
return NextResponse.json(emailSent);
}
18 changes: 18 additions & 0 deletions app/api/sendgrid/sendWelcome/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { NextResponse } from "next/server";
import validateParams from "../../../../utils/api/validateParams";
import sendWelcome from "../../../../utils/sendgrid/sendWelcome";

export async function POST(request: Request) {
const req = await request.json();
const { missingParams } = validateParams(req, ["sender", "emails"]);

if (missingParams.length > 0) {
return NextResponse.json({
error: `Missing parameters: ${missingParams.join(", ")}`,
});
}
const { sender, emails } = req;

let emailSent = await sendWelcome({ sender, emails });
return NextResponse.json(emailSent);
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,25 @@
import { NextResponse } from "next/server";
import Stripe from "stripe";
import validateParams from "../../../../utils/api/validateParams";

const stripe = new Stripe(process.env.NEXT_PUBLIC_STRIPE_SECRET_KEY!, {
apiVersion: "2022-08-01",
});

export default async function handler(req, res) {
export async function POST(request: Request) {
const req = await request.json();
const { missingParams } = validateParams(req, ["email"]);

if (missingParams.length > 0) {
return NextResponse.json({
error: `Missing parameters: ${missingParams.join(", ")}`,
});
}
try {
// create a stripe customer and get its id
const customerId = await stripe.customers
.create({
email: req.body.email,
email: req.email,
})
.then((customer) => {
return customer.id;
Expand All @@ -23,15 +33,15 @@ export default async function handler(req, res) {
items: [
{
price: priceId,
quantity: req.body.quantity,
quantity: req.quantity,
},
],
payment_behavior: "default_incomplete",
payment_settings: { save_default_payment_method: "on_subscription" },
expand: ["latest_invoice.payment_intent"],
});

res.send({
return NextResponse.json({
subscriptionId: subscription.id,
// We use Stripe's Expand functionality to get the latest invoice and its payment intent
// So we can pass it to the front end to confirm the payment
Expand All @@ -42,6 +52,8 @@ export default async function handler(req, res) {
} catch (error) {
// get error code
const errorCode = error.raw?.code;
return res.status(errorCode).send({ error: { message: error.message } });
return NextResponse.json({
error: { message: error.message, errorCode },
});
}
}
26 changes: 16 additions & 10 deletions app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { getServerSession } from "next-auth";
import Navbar from "../components/Navbar";
import Header from "../components/Header";
import LogInBtn from "../components/login-btn";
import { PHProvider, PostHogPageview } from "./providers";

import AuthProvider from "../lib/auth/AuthProvider";

Expand All @@ -30,17 +31,22 @@ export default async function RootLayout({

return (
<html lang="en" data-color-mode="dark" data-dark-theme="dark">
<Suspense fallback={null}>
<PostHogPageview />
</Suspense>
<body style={{ minHeight: "100vh" }}>
{userEmail ? (
<>
<Header userEmail={userEmail} userToken={userName} />
<Navbar>
<AuthProvider>{children}</AuthProvider>
</Navbar>
</>
) : (
<LogInBtn />
)}
<PHProvider>
{userEmail ? (
<>
<Header userEmail={userEmail} userToken={userName} />
<Navbar>
<AuthProvider>{children}</AuthProvider>
</Navbar>
</>
) : (
<LogInBtn />
)}
</PHProvider>
</body>
</html>
);
Expand Down
35 changes: 35 additions & 0 deletions app/providers.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// app/providers.tsx
"use client";
import posthog from "posthog-js";
import { PostHogProvider } from "posthog-js/react";
import { usePathname, useSearchParams } from "next/navigation";
import { useEffect } from "react";

if (typeof window !== "undefined") {
posthog.init(process.env.NEXT_PUBLIC_POSTHOG_KEY!, {
api_host: process.env.NEXT_PUBLIC_POSTHOG_HOST,
});
}

export function PostHogPageview(): JSX.Element {
const pathname = usePathname();
const searchParams = useSearchParams();

useEffect(() => {
if (pathname) {
let url = window.origin + pathname;
if (searchParams && searchParams.toString()) {
url = url + `?${searchParams.toString()}`;
}
posthog.capture("$pageview", {
$current_url: url,
});
}
}, [pathname, searchParams]);

return <></>;
}

export function PHProvider({ children }: { children: React.ReactNode }) {
return <PostHogProvider client={posthog}>{children}</PostHogProvider>;
}
28 changes: 14 additions & 14 deletions pages/api/extension/getContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import getUserTokens from "../../../utils/db/user/getUserTokens";
import updateTokensFromJira from "../../../utils/jira/updateTokens";
import updateTokens from "../../../utils/db/jira/updateTokens";
import searchMessageByText from "../../../utils/slack/searchMessageByText";
import validateParams from "../../../utils/api/validateParams";
function replaceSpecialChars(inputString) {
const specialChars = /[!"#$%&/()=?_"{}¨*]/g; // Edit this list to include or exclude characters
return inputString.toLowerCase().replace(specialChars, " ");
Expand Down Expand Up @@ -155,21 +156,20 @@ export default async function handler(req, res) {
properties: { user, repo, owner, gitSystem },
});

if (!user) {
return res.send({ error: "no user" });
}
if (!repo) {
return res.send({ error: "no repo" });
}
if (!owner) {
return res.send({ error: "no owner" });
}
if (!commitList) {
return res.send({ error: "no commitList" });
}
if (!gitSystem) {
return res.send({ error: "no gitSystem" });
const { missingParams } = validateParams(req.body, [
"user",
"repo",
"owner",
"gitSystem",
"commitList",
]);

if (missingParams.length > 0) {
return res.json({
error: `Missing parameters: ${missingParams.join(", ")}`,
});
}

let userTokens;
try {
userTokens = await getUserTokens({ email: user });
Expand Down
26 changes: 12 additions & 14 deletions pages/api/hover/getHoverData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { trackEvent } from "../../../utils/analytics/azureAppInsights";
import updateTokensFromJira from "../../../utils/jira/updateTokens";
import updateTokens from "../../../utils/db/jira/updateTokens";
import searchMessageByText from "../../../utils/slack/searchMessageByText";
import validateParams from "../../../utils/api/validateParams";
function replaceSpecialChars(inputString) {
const specialChars = /[!"#$%&/()=?_"{}¨*]/g; // Edit this list to include or exclude characters
return inputString.toLowerCase().replace(specialChars, " ");
Expand All @@ -14,21 +15,18 @@ function handleRejection(reason) {
}
export default async function handler(req, res) {
const { user, gitSystem, repo, owner, commitTitle } = req.body;
const { missingParams } = validateParams(req.body, [
"user",
"repo",
"owner",
"gitSystem",
"commitTitle",
]);

if (!user) {
return res.send({ error: "no user" });
}
if (!repo) {
return res.send({ error: "no repo" });
}
if (!owner) {
return res.send({ error: "no owner" });
}
if (!gitSystem) {
return res.send({ error: "no gitSystem" });
}
if (!commitTitle) {
return res.send({ error: "no commitTitle" });
if (missingParams.length > 0) {
return res.json({
error: `Missing parameters: ${missingParams.join(", ")}`,
});
}

let userTokens;
Expand Down
17 changes: 0 additions & 17 deletions pages/api/sendgrid/sendTeammateInvite.ts

This file was deleted.

12 changes: 0 additions & 12 deletions pages/api/sendgrid/sendWelcome.ts

This file was deleted.

6 changes: 3 additions & 3 deletions utils/sendgrid/sendTeammateInvite.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
export default async function sendTeammateInvite({
email,
teammateEmail,
sender,
inviteUrl,
teamName,
}: {
email: string;
teammateEmail: string;
sender: string;
inviteUrl: string;
teamName: string;
}) {
const sgMail = require("@sendgrid/mail");
sgMail.setApiKey(process.env.SENDGRID_API_KEY);
const msg = {
to: email,
to: teammateEmail,
from: "info@watermelon.tools",
templateId: "d-dd5c729f0be5439daac6b1faaf0431d6",
dynamic_template_data: {
Expand Down

1 comment on commit 6eafdab

@vercel
Copy link

@vercel vercel bot commented on 6eafdab Aug 14, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.