Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: echo getting started page #5477

Merged
merged 24 commits into from
May 7, 2024
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
9b706fd
feat: add echo usecase and more tracking for getting started
davidsoderberg Apr 25, 2024
b95c1ea
Merge branch 'next' into nv-3695-get-started-page-update
davidsoderberg Apr 25, 2024
4c080fb
Merge branch 'next' into nv-3695-get-started-page-update
davidsoderberg Apr 26, 2024
fde399f
feat: add channel for get started link
davidsoderberg Apr 26, 2024
1564fe8
fix: so animation is displayed correctly
davidsoderberg Apr 26, 2024
90d7d54
Merge branch 'next' into nv-3695-get-started-page-update
davidsoderberg Apr 29, 2024
f1a9a78
fix: after pr comments
davidsoderberg Apr 29, 2024
e809e1b
fix: Include current radius tokens
antonjoel82 Apr 29, 2024
1d44f38
feat: Update CodeSnippet to match InfoArch examples
antonjoel82 Apr 29, 2024
1abee28
fix: after pr comment
davidsoderberg Apr 29, 2024
c13efc7
fix: so echo is default tab
davidsoderberg Apr 29, 2024
60c9a39
fix: after pr comments
davidsoderberg Apr 29, 2024
d70ed0a
refactor: echo getting started page
davidsoderberg Apr 30, 2024
e137102
feat: copy change
davidsoderberg Apr 30, 2024
33009cc
refactor: px to rem units
davidsoderberg Apr 30, 2024
ce7d8d3
feat: add echo terminal
davidsoderberg May 2, 2024
4d21902
fix: lint warning
davidsoderberg May 2, 2024
e9c0689
fix: width of echo terminal
davidsoderberg May 2, 2024
a94bb82
refactor: flex with panda
davidsoderberg May 2, 2024
72cb99d
refactor: after learning more about panda
davidsoderberg May 2, 2024
54d54a7
feat: update copy
davidsoderberg May 3, 2024
2a1db18
feat: change tabs to only be echo tab
davidsoderberg May 3, 2024
04cdc59
feat: change copy
davidsoderberg May 3, 2024
e946d88
fix: copy
davidsoderberg May 3, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 7 additions & 0 deletions apps/web/src/pages/get-started/GetStartedPage.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { Center, Loader } from '@mantine/core';
import { colors } from '@novu/design-system';
import { useSegment } from '@novu/shared-web';
import { useEffect } from 'react';
import PageContainer from '../../components/layout/components/PageContainer';
import PageHeader from '../../components/layout/components/PageHeader';
import { useAuthContext } from '../../components/providers/AuthProvider';
Expand All @@ -12,9 +14,14 @@ const PAGE_TITLE = 'Get started';
export function GetStartedPage() {
const { currentOrganization } = useAuthContext();
const { currentTab, setTab } = useGetStartedTabs();
const segment = useSegment();

usePageViewTracking();

useEffect(() => {
segment.track('Page visit - [Get Started]');
}, []);

return (
<PageContainer title={PAGE_TITLE}>
<PageHeader title={PAGE_TITLE} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { colors, Text, IconMenuBook } from '@novu/design-system';

import { Link } from '../consts/shared';
import { OnboardingUseCasesTabsEnum } from '../consts/OnboardingUseCasesTabsEnum';
import * as capitalize from 'lodash.capitalize';

interface IAdditionInformationLinkProps extends React.AnchorHTMLAttributes<HTMLAnchorElement> {
channel: OnboardingUseCasesTabsEnum;
Expand All @@ -12,7 +13,7 @@ export function AdditionInformationLink({ channel, ...linkProps }: IAdditionInfo
return (
<StyledLink {...linkProps}>
<IconMenuBook />
<StyledText>Learn about {channel}</StyledText>
<StyledText>Learn about {channel === OnboardingUseCasesTabsEnum.ECHO ? capitalize(channel) : channel}</StyledText>
</StyledLink>
);
}
Expand Down
45 changes: 45 additions & 0 deletions apps/web/src/pages/get-started/components/CodeSnippet.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { Input, inputStyles } from '@novu/design-system';
import { useClipboard } from '@mantine/hooks';
import { css, cx } from '../../../styled-system/css';
import { ClipboardIconButton } from '../../../components';

const codeValueInputClassName = css({
'& input': {
border: 'none !important',
background: 'surface.popover !important',
color: 'typography.text.secondary !important',
fontFamily: 'mono !important',
},
});

interface ICodeSnippetProps {
command: string;
onClick?: () => void;
className?: string;
'data-test-id'?: string;
}

/**
* Read-only code snippet with copy-paste functionality
*/
export const CodeSnippet = ({ command, onClick, className, ...props }: ICodeSnippetProps) => {
const { copy, copied } = useClipboard();

const handleCopy = () => {
onClick?.();
copy(command);
};

return (
<Input
readOnly
className={cx(codeValueInputClassName, className)}
styles={inputStyles}
rightSection={
<ClipboardIconButton isCopied={copied} handleCopy={handleCopy} testId={'mail-server-domain-copy'} size={'16'} />
}
value={command}
data-test-id={props['data-test-id']}
/>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ enum AnimationThemeEnum {
}

// uses `public` as the default base directory
const ROOT_ANIMATION_PATH = `animations/get-started`;
const ROOT_ANIMATION_PATH = `/animations/get-started`;
const STATE_MACHINE_NAME = 'SM';
const STATE_MACHINE_INPUT_NAME = 'theme';

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import { useSegment } from '@novu/shared-web';
import { css, cx } from '../../../../styled-system/css';
import { styled } from '../../../../styled-system/jsx';
import { OnboardingUseCasesTabsEnum } from '../../consts/OnboardingUseCasesTabsEnum';
import { AdditionInformationLink } from '../AdditionInformationLink';
import { CodeSnippet } from '../CodeSnippet';
import { text, title } from '../../../../styled-system/recipes';
import { IconCellTower, IconCloudQueue, IconCode, IconHealthAndSafety } from '@novu/design-system';

const link = 'https://docs.novu.co/echo/quickstart';

const COMMAND = 'npx novu-labs@latest echo';

const Text = styled('p', text);
const Title = styled('h2', title);
const SubTitle = styled('h3', title);

const columnText = css({ fontSize: '88', marginTop: '50', lineHeight: '125', maxW: '214px' });

const columnIcon = css({ marginBottom: '50' });

const mainText = css({ maxW: '645px', fontSize: '88', lineHeight: '125' });

export const EchoTab = () => {
const segment = useSegment();

const handleDocsLinkClick = () => {
segment.track(`Additional Info Link - [Get Started]`, { href: link, tab: OnboardingUseCasesTabsEnum.ECHO });
};

return (
<>
<Title variant="section" className={css({ marginTop: '100' })}>
Notification workflows as code
</Title>
<Text variant="secondary" className={cx(css({ marginTop: '50' }), mainText)}>
Novu Echo SDK allows you to write notification workflows in your codebase locally right in your IDE as well as
preview and edit the channel specific content in real-time.
</Text>
<Text variant="secondary" className={cx(css({ marginTop: '125', marginBottom: '150' }), mainText)}>
You can use Echo with React Email, MJML, and other template engines.
</Text>
<SubTitle variant="subsection">Try it out now</SubTitle>
<Text variant="secondary" className={mainText}>
Open your terminal and launch the Echo Studio
</Text>
<CodeSnippet
command={COMMAND}
className={cx(
css({
maxW: '400px',
marginTop: '50',
marginBottom: '250',
}),
css({
'& input': {
color: 'white !important',
},
})
)}
onClick={() => {
segment.track(`Copy Echo command - [Get Started]`);
}}
/>
<div className={css({ marginBottom: '300' })}>
<AdditionInformationLink channel={OnboardingUseCasesTabsEnum.ECHO} href={link} onClick={handleDocsLinkClick} />
</div>
<div className={css({ display: 'flex', gap: '150' })}>
<div>
<IconCode size={32} className={columnIcon} />
<SubTitle variant="subsection">Bring your own code</SubTitle>
<Text variant="secondary" className={columnText}>
Write the workflows as functions in your codebase, version, and manage via Git.
</Text>
</div>
<div>
<IconCellTower size={32} className={columnIcon} />
<SubTitle variant="subsection">Limitless integrations</SubTitle>
<Text variant="secondary" className={columnText}>
Use React.email, MJML, or fetch templates from Braze, Hubspot, Sendgrid, more…
</Text>
</div>
<div>
<IconHealthAndSafety size={32} className={columnIcon} />
<SubTitle variant="subsection">Type safety</SubTitle>
<Text variant="secondary" className={columnText}>
Bring your own JSON schemas for full, end-to-end validation and type safety.
</Text>
</div>
<div>
<IconCloudQueue size={32} className={columnIcon} />
<SubTitle variant="subsection">Cloud synchronization</SubTitle>
<Text variant="secondary" className={columnText}>
Sync your own workflows with Novu Cloud and ease collaboration.
</Text>
</div>
</div>
</>
);
};
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
import { Digest, HalfClock, IconOutlineNotificationsActive, IconOutlinePublic, Translation } from '@novu/design-system';
import {
Digest,
HalfClock,
IconComputer,
IconOutlineNotificationsActive,
IconOutlinePublic,
Translation,
} from '@novu/design-system';
import { CSSProperties } from 'react';
import { OnboardingUseCasesTabsEnum } from '../../consts/OnboardingUseCasesTabsEnum';

Expand All @@ -7,7 +14,7 @@ export interface GetStartedTabConfig {
icon: JSX.Element;
title: string;
}
const ICON_STYLE: Partial<CSSProperties> = { height: 20, width: 20, marginBottom: '12px' };
export const ICON_STYLE: Partial<CSSProperties> = { height: 20, width: 20, marginBottom: '12px' };

export const TAB_CONFIGS: GetStartedTabConfig[] = [
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { Container, Tabs } from '@mantine/core';
import { IconConnectedTv } from '@novu/design-system';
import { Outlet } from 'react-router-dom';
import { OnboardingUseCasesTabsEnum } from '../../consts/OnboardingUseCasesTabsEnum';
import { UseCasesConst } from '../../consts/UseCases.const';
import { GetStartedTab } from '../../layout/GetStartedTab';
import { GetStartedTabConfig, TAB_CONFIGS } from './GetStartedTabs.const';
import { GetStartedTabConfig, ICON_STYLE, TAB_CONFIGS } from './GetStartedTabs.const';
import useStyles from './GetStartedTabs.style';
import { useGetStartedTabs } from './useGetStartedTabs';
import { useGetStartedTabView } from './useGetStartedTabView';
import { EchoTab } from './EchoTab';

interface IGetStartedTabsProps extends ReturnType<typeof useGetStartedTabs> {
tabConfigs?: GetStartedTabConfig[];
Expand All @@ -33,6 +35,13 @@ export const GetStartedTabs: React.FC<IGetStartedTabsProps> = ({ tabConfigs = TA
mb={15}
>
<Tabs.List>
<Tabs.Tab
key={`tab-${OnboardingUseCasesTabsEnum.ECHO}`}
value={OnboardingUseCasesTabsEnum.ECHO}
icon={<IconConnectedTv style={ICON_STYLE} />}
>
Workflows
</Tabs.Tab>
{tabConfigs.map(({ value, icon, title }) => (
<Tabs.Tab key={`tab-${value}`} value={value} icon={icon}>
{title}
Expand All @@ -44,6 +53,9 @@ export const GetStartedTabs: React.FC<IGetStartedTabsProps> = ({ tabConfigs = TA
<GetStartedTab setView={setView} currentView={currentView} {...UseCasesConst[value]} />
</Tabs.Panel>
))}
<Tabs.Panel key={`tab-panel-${OnboardingUseCasesTabsEnum.ECHO}`} value={OnboardingUseCasesTabsEnum.ECHO}>
<EchoTab />
</Tabs.Panel>
</Tabs>
<Outlet />
</Container>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { useSegment } from '@novu/shared-web';
import { OnboardingUseCasesTabsEnum } from '../../consts/OnboardingUseCasesTabsEnum';

const TAB_SEARCH_PARAM_NAME = 'tab';
const DEFAULT_TAB: OnboardingUseCasesTabsEnum = OnboardingUseCasesTabsEnum.IN_APP;
const DEFAULT_TAB: OnboardingUseCasesTabsEnum = OnboardingUseCasesTabsEnum.ECHO;

interface GetStartedTabSearchParams {
[TAB_SEARCH_PARAM_NAME]: OnboardingUseCasesTabsEnum;
Expand All @@ -21,7 +21,7 @@ export const useGetStartedTabs = () => {

const currentTab = (params.get(TAB_SEARCH_PARAM_NAME) as OnboardingUseCasesTabsEnum) ?? DEFAULT_TAB;
const setTab = (tab: OnboardingUseCasesTabsEnum) => {
segment.track('Click Use-case Tab - [Get Started]', { tab: tab });
segment.track('Tab click - [Get Started]', { tab: tab });

params.set(TAB_SEARCH_PARAM_NAME, tab);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { OnboardingWorkflowRouteEnum, OnboardingUseCase } from './types';
import { GetStartedAnimation } from '../components/GetStartedAnimation';
import { OpenWorkflowButton } from '../components/OpenWorkflowButton';
import { OnboardingUseCasesTabsEnum } from './OnboardingUseCasesTabsEnum';
import { StepTypeEnum } from '@novu/shared';

const USECASE_BLUEPRINT_IDENTIFIER = 'get-started-delay';

Expand All @@ -27,6 +28,8 @@ export const DelayUseCaseConst: OnboardingUseCase = {
href={ROUTES.INTEGRATIONS_CREATE}
target="_blank"
rel="noopener noreferrer"
event="Integration store"
channel={StepTypeEnum.DELAY}
/>
<StepText>.</StepText>
</StepDescription>
Expand Down Expand Up @@ -91,6 +94,8 @@ export const DelayUseCaseConst: OnboardingUseCase = {
href={ROUTES.ACTIVITIES}
target="_blank"
rel="noopener noreferrer"
event='Discover "activity feed"'
channel={StepTypeEnum.DELAY}
/>
<StepText>
to monitor notifications activity and see potential issues with a specific provider or channel.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { OpenWorkflowButton } from '../components/OpenWorkflowButton';
import { OnboardingUseCasesTabsEnum } from './OnboardingUseCasesTabsEnum';
import { DigestPlaygroundView } from './DigestUsecasePlaygroundView.const';
import { GetStartedTabsViewsEnum } from './GetStartedTabsViewsEnum';
import { StepTypeEnum } from '@novu/shared';

const USECASE_BLUEPRINT_IDENTIFIER = 'get-started-digest';

Expand All @@ -30,6 +31,8 @@ export const DigestUseCaseConst: OnboardingUseCase = {
href={ROUTES.INTEGRATIONS_CREATE}
target="_blank"
rel="noopener noreferrer"
event="Integration store"
channel={StepTypeEnum.DIGEST}
/>
<StepText>.</StepText>
</StepDescription>
Expand Down Expand Up @@ -97,6 +100,8 @@ export const DigestUseCaseConst: OnboardingUseCase = {
href={ROUTES.ACTIVITIES}
target="_blank"
rel="noopener noreferrer"
event='Discover "activity feed"'
channel={StepTypeEnum.DIGEST}
/>
<StepText>
to monitor notifications activity and see potential issues with a specific provider or channel.
Expand Down
12 changes: 10 additions & 2 deletions apps/web/src/pages/get-started/consts/InAppUseCase.const.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ChannelTypeEnum } from '@novu/shared';
import { ChannelTypeEnum, StepTypeEnum } from '@novu/shared';
import { ROUTES } from '@novu/shared-web';

import { useGetIntegrationsByChannel } from '../../integrations/useGetIntegrationsByChannel';
Expand Down Expand Up @@ -34,7 +34,13 @@ export const InAppUseCaseConst: OnboardingUseCase = {

return (
<StepDescription>
<GetStartedLink href={getInAppIntegrationUrl()} target="_blank" rel="noopener noreferrer">
<GetStartedLink
event="Create In-app provider"
href={getInAppIntegrationUrl()}
target="_blank"
rel="noopener noreferrer"
channel={StepTypeEnum.IN_APP}
>
Create In-app provider
</GetStartedLink>
<StepText>
Expand Down Expand Up @@ -85,6 +91,8 @@ export const InAppUseCaseConst: OnboardingUseCase = {
href={ROUTES.ACTIVITIES}
target="_blank"
rel="noopener noreferrer"
event='Discover "activity feed"'
channel={StepTypeEnum.IN_APP}
/>
<StepText>
to monitor notifications activity and see potential issues with a specific provider or channel.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,12 @@ export const MultiChannelUseCaseConst: OnboardingUseCase = {
<StepText>
Novu has set up trial email and SMS providers for you. To expand your options, add more providers in the
</StepText>
<GetStartedLink href={ROUTES.INTEGRATIONS_CREATE} target="_blank" rel="noopener noreferrer">
<GetStartedLink
href={ROUTES.INTEGRATIONS_CREATE}
event="Integration store (multi-channel)"
target="_blank"
rel="noopener noreferrer"
>
{' Integration store'}
</GetStartedLink>
<StepText>.</StepText>
Expand Down Expand Up @@ -74,6 +79,7 @@ export const MultiChannelUseCaseConst: OnboardingUseCase = {
href={ROUTES.ACTIVITIES}
target="_blank"
rel="noopener noreferrer"
event='Discover "activity feed" (multi-channel)'
/>
<StepText>
to monitor notifications activity and see potential issues with a specific provider or channel.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export enum OnboardingUseCasesTabsEnum {
ECHO = 'echo',
IN_APP = 'in-app',
DIGEST = 'digest',
DELAY = 'delay',
Expand Down