Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -106,3 +106,9 @@ NEXT_SERVER_ACTIONS_ENCRYPTION_KEY=
# configure its API key. If you don't configure this correctly the onboarding
# will not work (but you can skip it).
DEFAULT_PROVIDER_API_KEY=openai-api-key


# For the new onboarding to work, when in the select agent page, you must add the documentUuid of the agents you want to clone that must be created in your admin workspace
NEXT_PUBLIC_CONTENT_CREATOR_SELECT_AGENT_UUID=
NEXT_PUBLIC_COLD_EMAIL_OUTREACH_SELECT_AGENT_UUID=
NEXT_PUBLIC_NEWS_CURATOR_SELECT_AGENT_UUID=
4 changes: 3 additions & 1 deletion .github/workflows/build-and-push.yml
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,9 @@ jobs:
NEXT_PUBLIC_POSTHOG_KEY=${{ secrets.NEXT_PUBLIC_POSTHOG_KEY }}
S3_BUCKET=${{ vars.STATIC_ASSETS_S3_BUCKET }}
STATIC_ASSETS_HOST=${{ vars.STATIC_ASSETS_HOST }}

NEXT_PUBLIC_COLD_EMAIL_OUTREACH_SELECT_AGENT_UUID=${{ vars.NEXT_PUBLIC_COLD_EMAIL_OUTREACH_SELECT_AGENT_UUID }}
NEXT_PUBLIC_CONTENT_CREATOR_SELECT_AGENT_UUID=${{ vars.NEXT_PUBLIC_CONTENT_CREATOR_SELECT_AGENT_UUID }}
NEXT_PUBLIC_NEWS_CURATOR_SELECT_AGENT_UUID=${{ vars.NEXT_PUBLIC_NEWS_CURATOR_SELECT_AGENT_UUID }}
run-migrations:
needs: [build-and-push-private]
uses: ./.github/workflows/run-migrations.yml
Expand Down
9 changes: 9 additions & 0 deletions apps/web/docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,9 @@ ARG NEXT_PUBLIC_DOCS_URL
ARG NEXT_PUBLIC_LATITUDE_CLOUD_PAYMENT_URL
ARG NEXT_PUBLIC_POSTHOG_HOST
ARG NEXT_PUBLIC_POSTHOG_KEY
ARG NEXT_PUBLIC_COLD_EMAIL_OUTREACH_SELECT_AGENT_UUID
ARG NEXT_PUBLIC_CONTENT_CREATOR_SELECT_AGENT_UUID
ARG NEXT_PUBLIC_NEWS_CURATOR_SELECT_AGENT_UUID

ARG PROJECT
ARG STATIC_ASSETS_HOST
Expand All @@ -102,6 +105,9 @@ ENV NEXT_PUBLIC_DOCS_URL=$NEXT_PUBLIC_DOCS_URL
ENV NEXT_PUBLIC_LATITUDE_CLOUD_PAYMENT_URL=$NEXT_PUBLIC_LATITUDE_CLOUD_PAYMENT_URL
ENV NEXT_PUBLIC_POSTHOG_HOST=$NEXT_PUBLIC_POSTHOG_HOST
ENV NEXT_PUBLIC_POSTHOG_KEY=$NEXT_PUBLIC_POSTHOG_KEY
ENV NEXT_PUBLIC_COLD_EMAIL_OUTREACH_SELECT_AGENT_UUID=$NEXT_PUBLIC_COLD_EMAIL_OUTREACH_SELECT_AGENT_UUID
ENV NEXT_PUBLIC_CONTENT_CREATOR_SELECT_AGENT_UUID=$NEXT_PUBLIC_CONTENT_CREATOR_SELECT_AGENT_UUID
ENV NEXT_PUBLIC_NEWS_CURATOR_SELECT_AGENT_UUID=$NEXT_PUBLIC_NEWS_CURATOR_SELECT_AGENT_UUID

ENV STATIC_ASSETS_HOST=${STATIC_ASSETS_HOST:-}
ENV RELEASE_VERSION=${DD_GIT_COMMIT_SHA:-unknown}
Expand Down Expand Up @@ -130,6 +136,9 @@ RUN --mount=type=cache,id=pnpm,target=/pnpm/store \
NEXT_PUBLIC_POSTHOG_KEY=$NEXT_PUBLIC_POSTHOG_KEY && \
NEXT_PUBLIC_POSTHOG_HOST=$NEXT_PUBLIC_POSTHOG_HOST && \
NEXT_PUBLIC_LATITUDE_CLOUD_PAYMENT_URL=$NEXT_PUBLIC_LATITUDE_CLOUD_PAYMENT_URL && \
NEXT_PUBLIC_COLD_EMAIL_OUTREACH_SELECT_AGENT_UUID=$NEXT_PUBLIC_COLD_EMAIL_OUTREACH_SELECT_AGENT_UUID && \
NEXT_PUBLIC_CONTENT_CREATOR_SELECT_AGENT_UUID=$NEXT_PUBLIC_CONTENT_CREATOR_SELECT_AGENT_UUID && \
NEXT_PUBLIC_NEWS_CURATOR_SELECT_AGENT_UUID=$NEXT_PUBLIC_NEWS_CURATOR_SELECT_AGENT_UUID && \
NEXT_SERVER_ACTIONS_ENCRYPTION_KEY="$(cat /run/secrets/NEXT_SERVER_ACTIONS_ENCRYPTION_KEY 2>/dev/null || echo '')" && \
NEXT_PUBLIC_DOCS_URL=$NEXT_PUBLIC_DOCS_URL && \
AWS_REGION=$AWS_REGION && \
Expand Down
1 change: 0 additions & 1 deletion apps/web/src/actions/events/publishEventAction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ export const publishEventAction = authProcedure
publisher.publishLater({
// @ts-expect-error - eventtype is more strict than string
type: eventType,
// @ts-expect-error - data is more strict than any() record
data: data,
})
})
2 changes: 1 addition & 1 deletion apps/web/src/actions/user/setupAction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export const setupAction = errorHandlingProcedure
}
const isNewOnboardingEnabled = isNewOnboardingEnabledResult.unwrap()
if (isNewOnboardingEnabled) {
return frontendRedirect(ROUTES.auth.setup.questionnaire)
return frontendRedirect(ROUTES.auth.setup.form)
}
return frontendRedirect(ROUTES.dashboard.root)
}
Expand Down
29 changes: 24 additions & 5 deletions apps/web/src/actions/workspaceOnboarding/complete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,37 @@
import { markWorkspaceOnboardingComplete } from '@latitude-data/core/services/workspaceOnboarding/update'
import { getWorkspaceOnboarding } from '@latitude-data/core/services/workspaceOnboarding/get'
import { authProcedure } from '../procedures'
import { frontendRedirect } from '$/lib/frontendRedirect'
import { ROUTES } from '$/services/routes'
import { z } from 'zod'

/**
* Mark onboarding as complete
*/
export const completeOnboardingAction = authProcedure.action(
async ({ ctx }) => {
export const completeOnboardingAction = authProcedure
.inputSchema(
z.object({
projectId: z.number().optional(),
commitUuid: z.string().optional(),
}),
)
.action(async ({ parsedInput, ctx }) => {
const { projectId, commitUuid } = parsedInput
const onboarding = await getWorkspaceOnboarding({
workspace: ctx.workspace,
}).then((r) => r.unwrap())

return await markWorkspaceOnboardingComplete({
await markWorkspaceOnboardingComplete({
onboarding,
}).then((r) => r.unwrap())
},
)

if (!projectId || !commitUuid) {
return frontendRedirect(ROUTES.dashboard.root)
}

return frontendRedirect(
ROUTES.projects
.detail({ id: projectId })
.commits.detail({ uuid: commitUuid }).preview.root,
)
})
3 changes: 2 additions & 1 deletion apps/web/src/app/(onboarding)/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import { CSPostHogProvider, IdentifyUser } from '$/app/providers'
import { getCurrentUserOrRedirect } from '$/services/auth/getCurrentUser'
import { ReactNode } from 'react'
import { WorkspaceProvider } from '../providers/WorkspaceProvider'

export default async function OnboardingLayout({
children,
Expand All @@ -14,7 +15,7 @@ export default async function OnboardingLayout({
return (
<CSPostHogProvider>
<IdentifyUser user={user} workspace={workspace}>
{children}
<WorkspaceProvider workspace={workspace}>{children}</WorkspaceProvider>
</IdentifyUser>
</CSPostHogProvider>
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@

import { Text } from '@latitude-data/web-ui/atoms/Text'
import AgentCard from './AgentCard'
import HoverCard from './HoverCard'
import HoverCard from '../../../../../components/HoverCard'
import { Icon, IconName } from '@latitude-data/web-ui/atoms/Icons'
import { Button } from '@latitude-data/web-ui/atoms/Button'
import { BackgroundHoverColor } from '@latitude-data/web-ui/tokens'
import { redirect } from 'next/navigation'
import { ROUTES } from '$/services/routes'
import { useCallback } from 'react'
import useWorkspaceOnboarding from '$/stores/workspaceOnboarding'
import { envClient } from '$/envClient'
import { useNavigate } from '$/hooks/useNavigate'

export type AgentCardProps = {
mainIcon: IconName
Expand All @@ -26,12 +27,12 @@ const agents: AgentCardProps[] = [
description:
'Finds new AI-tool leads, writes and sends tailored cold emails, follows up, and updates deal status.',
color: 'accentForeground',
// TODO(onboarding): change to production uuid when opening to production
documentUuid: 'ddada8e6-ae2c-4fa6-8969-724a8a938cd6',
documentUuid: envClient.NEXT_PUBLIC_COLD_EMAIL_OUTREACH_SELECT_AGENT_UUID
? envClient.NEXT_PUBLIC_COLD_EMAIL_OUTREACH_SELECT_AGENT_UUID
: '',
usedThirdPartyIconsSrc: [
// These are the pipedream assets that end up being cached and saved in the database once the integration is created
'https://assets.pipedream.net/s.v0/app_OkrhlP/logo/orig',
'https://assets.pipedream.net/s.v0/app_1dBhRX/logo/orig',
'https://assets.pipedream.net/s.v0/app_OQYhq7/logo/orig',
],
},
Expand All @@ -41,8 +42,9 @@ const agents: AgentCardProps[] = [
description:
'Turns each new blog post into a LinkedIn thread, Reddit post, and newsletter — then posts them on schedule and tracks performance.',
color: 'latte',
// TODO(onboarding): change to production uuid when opening to production
documentUuid: 'ddada8e6-ae2c-4fa6-8969-724a8a938cd6',
documentUuid: envClient.NEXT_PUBLIC_CONTENT_CREATOR_SELECT_AGENT_UUID
? envClient.NEXT_PUBLIC_CONTENT_CREATOR_SELECT_AGENT_UUID
: '',
usedThirdPartyIconsSrc: [
'https://assets.pipedream.net/s.v0/app_X7Lhxr/logo/orig',
'https://assets.pipedream.net/s.v0/app_1dBhRX/logo/orig',
Expand All @@ -56,27 +58,30 @@ const agents: AgentCardProps[] = [
description:
'Fetches the latest articles on any topic or company, summarizes the top 3 in plain language, and emails you the highlights.',
color: 'destructive',
// TODO(onboarding): change to production uuid when opening to production
documentUuid: '1152b1ab-1bd7-4091-94bc-fe00cdd03f30',
documentUuid: envClient.NEXT_PUBLIC_NEWS_CURATOR_SELECT_AGENT_UUID
? envClient.NEXT_PUBLIC_NEWS_CURATOR_SELECT_AGENT_UUID
: '',
usedThirdPartyIconsSrc: [
'https://assets.pipedream.net/s.v0/app_X7Lhxr/logo/orig',
'https://assets.pipedream.net/s.v0/app_1dBhRX/logo/orig',
'https://assets.pipedream.net/s.v0/app_mo7hbd/logo/orig',
'https://assets.pipedream.net/s.v0/app_OQYhq7/logo/orig',
],
},
]

export function SelectAgents() {
const { executeCompleteOnboarding } = useWorkspaceOnboarding()

const handleStartFromScratch = useCallback(() => {
executeCompleteOnboarding()
redirect(ROUTES.dashboard.root)
}, [executeCompleteOnboarding])
const router = useNavigate()
const handleSkipOnboarding = useCallback(() => {
executeCompleteOnboarding({})
router.push(ROUTES.dashboard.root)
}, [executeCompleteOnboarding, router])

const handleSelectAgent = useCallback((documentUuid: string) => {
redirect(`/actions/clone-agent?uuid=${documentUuid}`)
}, [])
const handleSelectAgent = useCallback(
(documentUuid: string) => {
router.push(`/actions/clone-agent?uuid=${documentUuid}`)
},
[router],
)

return (
<div className='flex flex-col gap-y-10 p-16 items-center'>
Expand Down Expand Up @@ -111,9 +116,9 @@ export function SelectAgents() {
fancy
variant='outline'
iconProps={{ name: 'plus' }}
onClick={handleStartFromScratch}
onClick={handleSkipOnboarding}
>
Start from scratch
Skip onboarding
</Button>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { getCurrentUserOrRedirect } from '$/services/auth/getCurrentUser'
import { env } from '@latitude-data/env'
import BasicHeader from '../../_components/BasicHeader/BasicHeader'
import { SelectAgents } from './_components/SelectAgents'
import { PageTrackingWrapper } from '$/components/PageTrackingWrapper'
import { isFeatureEnabledByName } from '@latitude-data/core/services/workspaceFeatures/isFeatureEnabledByName'
import { Result } from '@latitude-data/core/lib/Result'
import { ROUTES } from '$/services/routes'
Expand All @@ -28,9 +29,13 @@ export default async function SelectAgentPage() {
}

return (
<div className={'flex flex-col h-screen overflow-hidden relative gap-y-16'}>
<BasicHeader currentUser={user} isCloud={isCloud} />
<SelectAgents />
</div>
<PageTrackingWrapper namePageVisited='selectAgent'>
<div
className={'flex flex-col h-screen overflow-hidden relative gap-y-16'}
>
<BasicHeader currentUser={user} isCloud={isCloud} />
<SelectAgents />
</div>
</PageTrackingWrapper>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const statusFlagColors: Record<StatusFlagState, BackgroundColor> = {
[StatusFlagState.completed]: 'mutedForeground',
}

export function NavbarItem({
export function AgentNavbarItem({
title,
description,
state,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,35 +1,60 @@
import { Fragment, useCallback } from 'react'
import { NavbarItem } from './NavbarItem'
import { AgentNavbarItem } from './AgentNavbarItem'
import { Separator } from '@latitude-data/web-ui/atoms/Separator'
import { Text } from '@latitude-data/web-ui/atoms/Text'
import { Button } from '@latitude-data/web-ui/atoms/Button'
import { cn } from '@latitude-data/web-ui/utils'
import { StatusFlagState } from '@latitude-data/web-ui/molecules/StatusFlag'
import { ROUTES } from '$/services/routes'
import { ONBOARDING_STEP_CONTENT } from '../../constants'
import { calculateState } from './calculateState'
import { OnboardingStepKey } from '@latitude-data/constants/onboardingSteps'
import { useCurrentProject } from '$/app/providers/ProjectProvider'
import { redirect } from 'next/navigation'
import { useCurrentWorkspace } from '$/app/providers/WorkspaceProvider'
import useLatitudeAction from '$/hooks/useLatitudeAction'
import { publishEventAction } from '$/actions/events/publishEventAction'
import { useCurrentCommit } from '$/app/providers/CommitProvider'

export default function NocodersNavbar({
export default function AgentOnboardingNavbar({
onboardingSteps,
currentStep,
isLoadingOnboarding,
executeCompleteOnboarding,
}: {
onboardingSteps: OnboardingStepKey[]
executeCompleteOnboarding: () => void
executeCompleteOnboarding: ({
projectId,
commitUuid,
}: {
projectId: number
commitUuid: string
}) => void
currentStep: OnboardingStepKey | undefined | null // TODO(onboarding): remove null when data migration is done
isLoadingOnboarding: boolean
}) {
const { execute: publishEvent } = useLatitudeAction(publishEventAction)
const { project } = useCurrentProject()
const { workspace } = useCurrentWorkspace()
const { commit } = useCurrentCommit()

const skipOnboarding = useCallback(() => {
//TODO(onboarding): review this logic and see if we can stop the playground stream here
executeCompleteOnboarding()
redirect(ROUTES.dashboard.root)
}, [executeCompleteOnboarding])
executeCompleteOnboarding({
projectId: project.id,
commitUuid: commit.uuid,
})
publishEvent({
eventType: 'agentOnboardingSkipped',
payload: {
workspaceId: workspace.id,
},
})
}, [
executeCompleteOnboarding,
publishEvent,
workspace.id,
project.id,
commit.uuid,
])

const ONBOARDING_STEPS = Object.entries(ONBOARDING_STEP_CONTENT)
const isLast = ONBOARDING_STEPS.length - 1
Expand All @@ -49,7 +74,7 @@ export default function NocodersNavbar({
{filteredNavbarSteps.map(([key, item], index) => (
<Fragment key={index}>
<div className={cn(currentStep === key ? '' : 'opacity-70')}>
<NavbarItem
<AgentNavbarItem
title={item.title}
description={item.description}
state={
Expand Down
Loading
Loading