From 26ae99a96d114406552842416e6a6a7d80452922 Mon Sep 17 00:00:00 2001 From: James Ritchie Date: Tue, 29 Apr 2025 18:45:01 +0100 Subject: [PATCH 1/2] Post new sign up reasons to slack, not plain --- apps/webapp/app/env.server.ts | 3 ++ .../webapp/app/routes/_app.orgs.new/route.tsx | 35 +++------------- apps/webapp/app/services/slack.server.ts | 40 +++++++++++++++++++ 3 files changed, 49 insertions(+), 29 deletions(-) create mode 100644 apps/webapp/app/services/slack.server.ts diff --git a/apps/webapp/app/env.server.ts b/apps/webapp/app/env.server.ts index 30410053c82..75dc32c70eb 100644 --- a/apps/webapp/app/env.server.ts +++ b/apps/webapp/app/env.server.ts @@ -714,6 +714,9 @@ const EnvironmentSchema = z.object({ QUEUE_SSE_AUTORELOAD_INTERVAL_MS: z.coerce.number().int().default(5_000), QUEUE_SSE_AUTORELOAD_TIMEOUT_MS: z.coerce.number().int().default(60_000), + + SLACK_BOT_TOKEN: z.string(), + SLACK_SIGNUP_REASON_CHANNEL_ID: z.string(), }); export type Environment = z.infer; diff --git a/apps/webapp/app/routes/_app.orgs.new/route.tsx b/apps/webapp/app/routes/_app.orgs.new/route.tsx index 29f8963f7d9..a171153510e 100644 --- a/apps/webapp/app/routes/_app.orgs.new/route.tsx +++ b/apps/webapp/app/routes/_app.orgs.new/route.tsx @@ -5,7 +5,6 @@ import { RadioGroup } from "@radix-ui/react-radio-group"; import type { ActionFunction, LoaderFunctionArgs } from "@remix-run/node"; import { json, redirect } from "@remix-run/node"; import { Form, useActionData, useNavigation } from "@remix-run/react"; -import { uiComponent } from "@team-plain/typescript-sdk"; import { typedjson, useTypedLoaderData } from "remix-typedjson"; import { z } from "zod"; import { MainCenteredContainer } from "~/components/layout/AppLayout"; @@ -23,10 +22,9 @@ import { TextArea } from "~/components/primitives/TextArea"; import { useFeatures } from "~/hooks/useFeatures"; import { createOrganization } from "~/models/organization.server"; import { NewOrganizationPresenter } from "~/presenters/NewOrganizationPresenter.server"; -import { logger } from "~/services/logger.server"; import { requireUser, requireUserId } from "~/services/session.server"; +import { sendNewOrgMessage } from "~/services/slack.server"; import { organizationPath, rootPath } from "~/utils/pathBuilder"; -import { sendToPlain } from "~/utils/plain.server"; const schema = z.object({ orgName: z.string().min(3).max(50), @@ -63,32 +61,11 @@ export const action: ActionFunction = async ({ request }) => { const whyUseUs = formData.get("whyUseUs"); if (whyUseUs) { - try { - await sendToPlain({ - userId: user.id, - email: user.email, - name: user.name ?? user.displayName ?? user.email, - title: "New org feedback", - components: [ - uiComponent.text({ - text: `${submission.value.orgName} just created a new organization.`, - }), - uiComponent.divider({ spacingSize: "M" }), - uiComponent.text({ - size: "L", - color: "NORMAL", - text: "What problem are you trying to solve?", - }), - uiComponent.text({ - size: "L", - color: "NORMAL", - text: whyUseUs.toString(), - }), - ], - }); - } catch (error) { - logger.error("Error sending data to Plain when creating an org:", { error }); - } + await sendNewOrgMessage({ + orgName: submission.value.orgName, + whyUseUs: whyUseUs.toString(), + userEmail: user.email, + }); } return redirect(organizationPath(organization)); diff --git a/apps/webapp/app/services/slack.server.ts b/apps/webapp/app/services/slack.server.ts new file mode 100644 index 00000000000..56c15503d19 --- /dev/null +++ b/apps/webapp/app/services/slack.server.ts @@ -0,0 +1,40 @@ +import { WebClient } from "@slack/web-api"; +import { env } from "~/env.server"; +import { logger } from "./logger.server"; + +const slack = new WebClient(env.SLACK_BOT_TOKEN); + +type SendNewOrgMessageParams = { + orgName: string; + whyUseUs: string; + userEmail: string; +}; + +export async function sendNewOrgMessage({ orgName, whyUseUs, userEmail }: SendNewOrgMessageParams) { + try { + await slack.chat.postMessage({ + channel: env.SLACK_SIGNUP_REASON_CHANNEL_ID, + text: `New org created: ${orgName}`, + blocks: [ + { + type: "header", + text: { type: "plain_text", text: "New org created" }, + }, + { + type: "section", + text: { type: "mrkdwn", text: `*Org name:* ${orgName}` }, + }, + { + type: "section", + text: { type: "mrkdwn", text: `*What problem are you trying to solve?*\n${whyUseUs}` }, + }, + { + type: "context", + elements: [{ type: "mrkdwn", text: `Created by: ${userEmail}` }], + }, + ], + }); + } catch (error) { + logger.error("Error sending data to Slack when creating an org:", { error }); + } +} From a78b488a930d2a3309c7b4f983d47069df84f6a3 Mon Sep 17 00:00:00 2001 From: James Ritchie Date: Wed, 30 Apr 2025 09:04:33 +0100 Subject: [PATCH 2/2] Makes the Slack env vars optional --- apps/webapp/app/env.server.ts | 4 ++-- apps/webapp/app/services/slack.server.ts | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/apps/webapp/app/env.server.ts b/apps/webapp/app/env.server.ts index 75dc32c70eb..a97e56e6497 100644 --- a/apps/webapp/app/env.server.ts +++ b/apps/webapp/app/env.server.ts @@ -715,8 +715,8 @@ const EnvironmentSchema = z.object({ QUEUE_SSE_AUTORELOAD_INTERVAL_MS: z.coerce.number().int().default(5_000), QUEUE_SSE_AUTORELOAD_TIMEOUT_MS: z.coerce.number().int().default(60_000), - SLACK_BOT_TOKEN: z.string(), - SLACK_SIGNUP_REASON_CHANNEL_ID: z.string(), + SLACK_BOT_TOKEN: z.string().optional(), + SLACK_SIGNUP_REASON_CHANNEL_ID: z.string().optional(), }); export type Environment = z.infer; diff --git a/apps/webapp/app/services/slack.server.ts b/apps/webapp/app/services/slack.server.ts index 56c15503d19..68010d68420 100644 --- a/apps/webapp/app/services/slack.server.ts +++ b/apps/webapp/app/services/slack.server.ts @@ -11,6 +11,9 @@ type SendNewOrgMessageParams = { }; export async function sendNewOrgMessage({ orgName, whyUseUs, userEmail }: SendNewOrgMessageParams) { + if (!env.SLACK_BOT_TOKEN || !env.SLACK_SIGNUP_REASON_CHANNEL_ID) { + return; + } try { await slack.chat.postMessage({ channel: env.SLACK_SIGNUP_REASON_CHANNEL_ID,