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

feat: add cd onboarding path #1269

Merged
merged 7 commits into from
Nov 13, 2023
Merged
Show file tree
Hide file tree
Changes from all 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
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
Loading