Skip to content

Commit

Permalink
feat: add cd onboarding path (#1269)
Browse files Browse the repository at this point in the history
Co-authored-by: Klink <[email protected]>
  • Loading branch information
floreks and dogmar authored Nov 13, 2023
1 parent 36d4ec8 commit eef9788
Show file tree
Hide file tree
Showing 12 changed files with 316 additions and 69 deletions.
20 changes: 14 additions & 6 deletions www/src/components/shell/onboarding/Onboarding.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { ContextProps, OnboardingContext } from './context/onboarding'
import {
CloudProps,
CreateCloudShellSectionState,
OnboardingPath,
SCMProps,
Section,
SectionKey,
Expand Down Expand Up @@ -112,13 +113,18 @@ interface OnboardingProps {
function OnboardingWithContext({ ...props }: OnboardingProps): ReactElement {
const { restoredContext, reset } = useContextStorage()

const [scm, setSCM] = useState<SCMProps>(restoredContext?.scm ?? {})
const [scm, setSCM] = useState<SCMProps>(
restoredContext?.scm ?? ({} as SCMProps)
)
const [valid, setValid] = useState<boolean>(restoredContext?.valid ?? true)
const [cloud, setCloud] = useState<CloudProps>(restoredContext?.cloud ?? {})
const [sections, setSections] = useState<Sections>(defaultSections())
const [section, setSection] = useState<Section>(
sections[SectionKey.ONBOARDING_OVERVIEW]!
const [cloud, setCloud] = useState<CloudProps>(
restoredContext?.cloud ?? ({} as CloudProps)
)
const [path, setPath] = useState<OnboardingPath>(
restoredContext?.path ?? OnboardingPath.None
)
const [sections, setSections] = useState<Sections>(defaultSections())
const [section, setSection] = useState<Section>(sections[SectionKey.WELCOME]!)
const [workspace, setWorkspace] = useState<WorkspaceProps>(
restoredContext?.workspace ?? {}
)
Expand Down Expand Up @@ -146,8 +152,10 @@ function OnboardingWithContext({ ...props }: OnboardingProps): ReactElement {
workspace,
setWorkspace,
impersonation,
path,
setPath,
}),
[scm, cloud, valid, sections, section, workspace, impersonation]
[scm, cloud, valid, sections, section, workspace, impersonation, path]
)

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ function OnboardingCardButton({ selected = false, children, ...props }: any) {
backgroundColor="fill-two"
border="1px solid border-fill-two"
borderColor={selected ? 'action-link-inline' : 'border-fill-two'}
width="100%"
_hover={{
backgroundColor: 'fill-two-hover',
borderColor: selected ? 'action-link-inline' : 'border-fill-two',
Expand Down
7 changes: 6 additions & 1 deletion www/src/components/shell/onboarding/OnboardingFlow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { CreateCloudShellSectionState, SectionKey } from './context/types'
import CreateShellStep from './sections/shell/CreateShellStep'
import OverviewStep from './sections/overview/OverviewStep'
import OnboardingTips from './OnboardingTips'
import WelcomeStep from './sections/welcome/WelcomeStep'

function OnboardingFlow({ onNext, onBack }) {
const token = useToken() || ''
Expand Down Expand Up @@ -48,8 +49,12 @@ function OnboardingFlow({ onNext, onBack }) {
title={isCreating ? '' : section.title}
mode={isCreating ? 'Compact' : 'Default'}
>
{section?.key === SectionKey.WELCOME && <WelcomeStep onNext={onNext} />}
{section?.key === SectionKey.ONBOARDING_OVERVIEW && (
<OverviewStep onNext={onNext} />
<OverviewStep
onBack={onBack}
onNext={onNext}
/>
)}
{section?.key === SectionKey.CONFIGURE_CLOUD && (
<CloudStep
Expand Down
7 changes: 3 additions & 4 deletions www/src/components/shell/onboarding/OnboardingHeader.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { useTheme } from 'styled-components'
import { Dispatch, useState } from 'react'
import {
Button,
Expand Down Expand Up @@ -73,16 +72,16 @@ function OnboardingHeader({
onRestart,
mode = 'wizard',
}: OnboardingHeaderProps) {
const theme = useTheme()
const [open, setOpen] = useState(false)
const { section } = useSection()

return (
<Sidebar
variant="app"
layout="horizontal"
background={theme.colors['fill-one']}
maxHeight={56}
css={{
maxHeight: 56,
}}
>
<SidebarSection
grow={1}
Expand Down
35 changes: 27 additions & 8 deletions www/src/components/shell/onboarding/context/hooks.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Dispatch, useCallback, useContext, useEffect, useMemo } from 'react'
import {
AppsIcon,
ChecklistIcon,
CloudIcon,
ListIcon,
Expand All @@ -26,35 +27,44 @@ import {

const defaultSections = (): Sections => {
const sections: Sections = {
[SectionKey.ONBOARDING_OVERVIEW]: {
[SectionKey.WELCOME]: {
index: 0,
key: SectionKey.WELCOME,
title: 'Welcome to Plural!',
IconComponent: AppsIcon,
},
[SectionKey.ONBOARDING_OVERVIEW]: {
index: 1,
key: SectionKey.ONBOARDING_OVERVIEW,
title: 'Onboarding overview',
IconComponent: ChecklistIcon,
},
[SectionKey.CONFIGURE_CLOUD]: {
index: 1,
index: 2,
key: SectionKey.CONFIGURE_CLOUD,
title: 'Configure credentials',
IconComponent: CloudIcon,
},
[SectionKey.CONFIGURE_WORKSPACE]: {
index: 2,
index: 3,
key: SectionKey.CONFIGURE_WORKSPACE,
title: 'Configure workspace',
IconComponent: WorkspaceIcon,
},
[SectionKey.CREATE_CLOUD_SHELL]: {
index: 3,
index: 4,
key: SectionKey.CREATE_CLOUD_SHELL,
title: 'Create cloud shell',
IconComponent: TerminalIcon,
},
}

// build sections flow
sections[SectionKey.WELCOME]!.next = sections[SectionKey.ONBOARDING_OVERVIEW]

sections[SectionKey.ONBOARDING_OVERVIEW]!.next =
sections[SectionKey.CONFIGURE_CLOUD]
sections[SectionKey.ONBOARDING_OVERVIEW]!.prev = sections[SectionKey.WELCOME]

sections[SectionKey.CONFIGURE_CLOUD]!.prev =
sections[SectionKey.ONBOARDING_OVERVIEW]
Expand All @@ -74,35 +84,44 @@ const defaultSections = (): Sections => {

const localCLISections = (): Sections => {
const sections: Sections = {
[SectionKey.ONBOARDING_OVERVIEW]: {
[SectionKey.WELCOME]: {
index: 0,
key: SectionKey.WELCOME,
title: 'Welcome to Plural!',
IconComponent: ChecklistIcon,
},
[SectionKey.ONBOARDING_OVERVIEW]: {
index: 1,
key: SectionKey.ONBOARDING_OVERVIEW,
title: 'Onboarding overview',
IconComponent: ChecklistIcon,
},
[SectionKey.CONFIGURE_CLOUD]: {
index: 1,
index: 2,
key: SectionKey.CONFIGURE_CLOUD,
title: 'Configure credentials',
IconComponent: CloudIcon,
},
[SectionKey.INSTALL_CLI]: {
index: 2,
index: 3,
key: SectionKey.INSTALL_CLI,
title: 'Install Plural CLI',
IconComponent: TerminalIcon,
},
[SectionKey.COMPLETE_SETUP]: {
index: 3,
index: 4,
key: SectionKey.COMPLETE_SETUP,
title: 'Complete Setup',
IconComponent: ListIcon,
},
}

// build sections flow
sections[SectionKey.WELCOME]!.next = sections[SectionKey.ONBOARDING_OVERVIEW]

sections[SectionKey.ONBOARDING_OVERVIEW]!.next =
sections[SectionKey.CONFIGURE_CLOUD]
sections[SectionKey.ONBOARDING_OVERVIEW]!.prev = sections[SectionKey.WELCOME]

sections[SectionKey.CONFIGURE_CLOUD]!.prev =
sections[SectionKey.ONBOARDING_OVERVIEW]
Expand Down
5 changes: 5 additions & 0 deletions www/src/components/shell/onboarding/context/onboarding.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Dispatch, SetStateAction, createContext } from 'react'
import {
CloudProps,
Impersonation,
OnboardingPath,
SCMProps,
Section,
Sections,
Expand All @@ -22,6 +23,8 @@ interface ContextProps {
setSections: Dispatch<SetStateAction<Sections>>
section: Section
setSection: Dispatch<SetStateAction<Section>>
path: OnboardingPath
setPath: Dispatch<SetStateAction<OnboardingPath>>
}

interface SerializableContextProps {
Expand All @@ -32,6 +35,7 @@ interface SerializableContextProps {
section: Section
sections?: Sections
impersonation?: Impersonation
path?: OnboardingPath
}

const toSerializableSection = (section: Section): Partial<Section> => ({
Expand All @@ -54,6 +58,7 @@ const toSerializableContext = (
},
section: toSerializableSection(context.section) as Section,
impersonation,
path: context?.path,
})

const OnboardingContext = createContext<ContextProps>({} as ContextProps)
Expand Down
8 changes: 8 additions & 0 deletions www/src/components/shell/onboarding/context/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ enum CloudProviderToProvider {
}

enum SectionKey {
WELCOME = 'WELCOME',
ONBOARDING_OVERVIEW = 'ONBOARDING_OVERVIEW',
CONFIGURE_CLOUD = 'CONFIGURE_CLOUD',
CONFIGURE_WORKSPACE = 'CONFIGURE_WORKSPACE',
Expand Down Expand Up @@ -133,6 +134,12 @@ interface Impersonation {
user?: User
}

enum OnboardingPath {
None,
CD,
OSS,
}

export type {
Sections,
Section,
Expand All @@ -155,4 +162,5 @@ export {
CloudProviderToProvider,
CreateCloudShellSectionState,
ConfigureCloudSectionState,
OnboardingPath,
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,11 @@ function CloudOption({
/>
}
>
<div>
<div
css={{
width: '100%',
}}
>
<OnboardingCardButton
position="relative"
selected={selected}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,23 @@ import { ImpersonationContext } from '../../../context/impersonation'
import GCPLogoIcon from '../../assets/GCPLogoIcon.svg'

import { OnboardingContext } from '../../context/onboarding'
import { CloudType } from '../../context/types'
import { CloudType, OnboardingPath } from '../../context/types'

import { CloudOption } from './CloudOption'

function ProviderSelection() {
const { cloud, setCloud, setValid } = useContext(OnboardingContext)
const {
cloud,
setCloud,
setValid,
path: onboardingPath,
} = useContext(OnboardingContext)
const {
user: { demoed },
} = useContext(ImpersonationContext)
const [path, setPath] = useState(cloud?.type)
const [path, setPath] = useState(
onboardingPath === OnboardingPath.CD ? CloudType.Cloud : cloud?.type
)
const isValid = useMemo(() => path !== undefined, [path])

useEffect(() => setCloud((c) => ({ ...c, type: path })), [path, setCloud])
Expand All @@ -49,27 +56,29 @@ function ProviderSelection() {
header="Use your own cloud"
description="Connect your own cloud credentials and spin up your own cluster."
/>
<CloudOption
data-phid="select-cloud-demo"
selected={path === CloudType.Demo}
onClick={() => setPath(CloudType.Demo)}
disabled={demoed}
tooltip={
demoed
? 'You have reached the maximum number of demo environment usage.'
: undefined
}
icon={
<img
src={GCPLogoIcon}
width={40}
/>
}
header="Try free demo"
description="A six-hour GCP sandbox for you to test-drive Plural."
/>
{onboardingPath === OnboardingPath.OSS && (
<CloudOption
data-phid="select-cloud-demo"
selected={path === CloudType.Demo}
onClick={() => setPath(CloudType.Demo)}
disabled={demoed}
tooltip={
demoed
? 'You have reached the maximum number of demo environment usage.'
: undefined
}
icon={
<img
src={GCPLogoIcon}
width={40}
/>
}
header="Try free demo"
description="A six-hour GCP sandbox for you to test-drive Plural."
/>
)}
</Flex>
<PricingCalculator />
{onboardingPath === OnboardingPath.OSS && <PricingCalculator />}
{(path === CloudType.Cloud || path === CloudType.Local) && (
<Flex
direction="column"
Expand Down
Loading

0 comments on commit eef9788

Please sign in to comment.