+
+ {oauthStatus === "success"
+ ? "✅ You are all set!"
+ : "❌ Slack OAuth flow failed"}
+
+
+ {oauthStatus === "success"
+ ? `Successfully installed the Slack app! You can now receive message from us in workspace: ${searchParams.get("workspace_name")}.`
+ : searchParams.get("error_description") ||
+ "Slack OAuth flow failed. Please try again or contact us."}
+
+
+
+
+
+
+
+ );
+}
diff --git a/apps/recnet/src/app/feeds/page.tsx b/apps/recnet/src/app/feeds/page.tsx
index 755d3bb8..1f7748c5 100644
--- a/apps/recnet/src/app/feeds/page.tsx
+++ b/apps/recnet/src/app/feeds/page.tsx
@@ -19,6 +19,8 @@ import {
formatDate,
} from "@recnet/recnet-date-fns";
+import { SlackOAuthModal } from "./SlackOAuthModal";
+
import { trpc } from "../_trpc/client";
import { OnboardingDialog } from "../onboard/OnboardingDialog";
@@ -124,6 +126,7 @@ export default function FeedPage({
"md:py-12"
)}
>
+
{Object.keys(recsGroupByTitle).length > 0 ? (
<>
diff --git a/apps/recnet/src/clientEnv.ts b/apps/recnet/src/clientEnv.ts
index 6f5986cf..68721d01 100644
--- a/apps/recnet/src/clientEnv.ts
+++ b/apps/recnet/src/clientEnv.ts
@@ -1,16 +1,6 @@
import { z } from "zod";
-function resolveBaseUrl(env: string | undefined) {
- /**
- * If the environment is preview, we need to use the Vercel branch URL.
- * Otherwise, we use the base URL.
- * Ref: https://vercel.com/docs/projects/environment-variables/framework-environment-variables#NEXT_PUBLIC_VERCEL_BRANCH_URL
- */
- if (env === "preview") {
- return `https://${process.env.NEXT_PUBLIC_VERCEL_BRANCH_URL}`;
- }
- return process.env.NEXT_PUBLIC_BASE_URL;
-}
+import { resolveBaseUrl } from "./utils/resolveBaseUrl";
export const clientEnvSchema = z.object({
NEXT_PUBLIC_FIREBASE_API_KEY: z.string(),
diff --git a/apps/recnet/src/components/DoubleConfirmButton.tsx b/apps/recnet/src/components/DoubleConfirmButton.tsx
index b3989b05..cb65fd3f 100644
--- a/apps/recnet/src/components/DoubleConfirmButton.tsx
+++ b/apps/recnet/src/components/DoubleConfirmButton.tsx
@@ -9,7 +9,7 @@ interface DoubleConfirmButtonProps {
onConfirm: () => Promise;
children: React.ReactNode;
title: string;
- description: string;
+ description: string | React.ReactNode;
cancelButtonProps?: React.ComponentProps;
confirmButtonProps?: React.ComponentProps;
}
diff --git a/apps/recnet/src/components/setting/subscription/SubscriptionSetting.tsx b/apps/recnet/src/components/setting/subscription/SubscriptionSetting.tsx
index 6293d31b..0f3eb5d7 100644
--- a/apps/recnet/src/components/setting/subscription/SubscriptionSetting.tsx
+++ b/apps/recnet/src/components/setting/subscription/SubscriptionSetting.tsx
@@ -8,16 +8,17 @@ import {
Flex,
Text,
CheckboxCards,
- Badge,
Button,
} from "@radix-ui/themes";
-import { ChevronDown } from "lucide-react";
+import { ChevronDown, Slack as SlackIcon } from "lucide-react";
import { useState } from "react";
import { Controller, useForm, useFormState } from "react-hook-form";
import { toast } from "sonner";
import { z } from "zod";
import { trpc } from "@recnet/recnet-web/app/_trpc/client";
+import { DoubleConfirmButton } from "@recnet/recnet-web/components/DoubleConfirmButton";
+import { RecNetLink } from "@recnet/recnet-web/components/Link";
import { LoadingBox } from "@recnet/recnet-web/components/LoadingBox";
import { cn } from "@recnet/recnet-web/utils/cn";
@@ -60,6 +61,7 @@ function SubscriptionTypeCard(props: {
const { isDirty } = useFormState({ control });
const updateSubscriptionMutation = trpc.updateSubscription.useMutation();
+ const { data: slackOAuthData } = trpc.getSlackOAuthStatus.useQuery();
return (
@@ -92,9 +94,11 @@ function SubscriptionTypeCard(props: {
onSubmit={handleSubmit(
async (data, e) => {
setIsSubmitting(true);
- // handle special case for WEEKLY DIGEST
- // for weekly digest, at least one channel must be selected
- // if no, then show error message
+ /**
+ * Special case 1: WEEKLY_DIGEST
+ * For weekly digest, at least one channel must be selected
+ * if no, then show error message
+ */
if (type === "WEEKLY_DIGEST" && data.channels.length === 0) {
setError("channels", {
type: "manual",
@@ -104,6 +108,24 @@ function SubscriptionTypeCard(props: {
setIsSubmitting(false);
return;
}
+ /*
+ * Special case 2: SLACK distribution channel
+ * When user selects slack channel, we need to check if the user has completed slack integration oauth flow or not
+ * If not, then show error message and ask user to complete slack integration
+ */
+ if (
+ slackOAuthData?.workspaceName === null &&
+ data.channels.includes(subscriptionChannelSchema.enum.SLACK)
+ ) {
+ setError("channels", {
+ type: "manual",
+ message:
+ "To enable slack distribution channel, you need to complete slack integration first. See 'Slack Integration' below to learn more",
+ });
+ setIsSubmitting(false);
+ return;
+ }
+
await updateSubscriptionMutation.mutateAsync({
type,
channels: data.channels,
@@ -151,16 +173,6 @@ function SubscriptionTypeCard(props: {
}}
/>
-
-
- BETA
-
-
- Distribute by Slack is currently in beta version. Only people in
- Cornell-NLP slack workspace can use this feature. And the email
- account of the slack account must match the RecNet account.
-
-