Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor(wizard): break up wizard endpoints screen [EE-3167] (#1629)
- Loading branch information
Showing
16 changed files
with
406 additions
and
78 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
30 changes: 30 additions & 0 deletions
30
app/portainer/components/form-components/FormSection/FormSection.stories.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import { Meta, Story } from '@storybook/react'; | ||
|
||
import { FormSection } from './FormSection'; | ||
|
||
export default { | ||
component: FormSection, | ||
title: 'Components/Form/FormSection', | ||
} as Meta; | ||
|
||
interface Args { | ||
title: string; | ||
content: string; | ||
} | ||
|
||
function Template({ title, content }: Args) { | ||
return <FormSection title={title}>{content}</FormSection>; | ||
} | ||
|
||
export const Example: Story<Args> = Template.bind({}); | ||
Example.args = { | ||
title: 'title', | ||
content: `Content | ||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam egestas turpis magna, | ||
vel pretium dui rhoncus nec. Maecenas felis purus, consectetur non porta sit amet, | ||
auctor sed sapien. Aliquam eu nunc felis. Pellentesque pulvinar velit id quam pellentesque, | ||
nec imperdiet dui finibus. In blandit augue nibh, nec tincidunt nisi porttitor quis. | ||
Nullam nec nibh maximus, consequat quam sed, dapibus purus. Donec facilisis commodo mi, in commodo augue molestie sed. | ||
`, | ||
}; |
17 changes: 17 additions & 0 deletions
17
app/portainer/components/form-components/FormSection/FormSection.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import { PropsWithChildren } from 'react'; | ||
|
||
import { FormSectionTitle } from '../FormSectionTitle'; | ||
|
||
interface Props { | ||
title: string; | ||
} | ||
|
||
export function FormSection({ title, children }: PropsWithChildren<Props>) { | ||
return ( | ||
<> | ||
<FormSectionTitle>{title}</FormSectionTitle> | ||
|
||
{children} | ||
</> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export { FormSection } from './FormSection'; |
75 changes: 75 additions & 0 deletions
75
app/portainer/views/wizard/EnvironmentTypeSelectView/EndpointTypeView.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
import { useState } from 'react'; | ||
import { useRouter } from '@uirouter/react'; | ||
import _ from 'lodash'; | ||
|
||
import { Button } from '@/portainer/components/Button'; | ||
import { PageHeader } from '@/portainer/components/PageHeader'; | ||
import { Widget, WidgetBody, WidgetTitle } from '@/portainer/components/widget'; | ||
import { useAnalytics } from '@/angulartics.matomo/analytics-services'; | ||
import { r2a } from '@/react-tools/react2angular'; | ||
|
||
import { EnvironmentSelector, Value } from './EnvironmentSelector'; | ||
import { environmentTypes } from './environment-types'; | ||
|
||
export function EnvironmentTypeSelectView() { | ||
const [types, setTypes] = useState<Value[]>([]); | ||
const { trackEvent } = useAnalytics(); | ||
const router = useRouter(); | ||
|
||
return ( | ||
<> | ||
<PageHeader | ||
title="Quick Setup" | ||
breadcrumbs={[{ label: 'Environment Wizard' }]} | ||
/> | ||
|
||
<div className="row"> | ||
<div className="col-sm-12"> | ||
<Widget> | ||
<WidgetTitle icon="fa-magic" title="Environment Wizard" /> | ||
<WidgetBody> | ||
<EnvironmentSelector value={types} onChange={setTypes} /> | ||
|
||
<div className="row"> | ||
<div className="col-sm-12"> | ||
<Button | ||
disabled={types.length === 0} | ||
onClick={() => startWizard()} | ||
> | ||
Start Wizard | ||
</Button> | ||
</div> | ||
</div> | ||
</WidgetBody> | ||
</Widget> | ||
</div> | ||
</div> | ||
</> | ||
); | ||
|
||
function startWizard() { | ||
if (types.length === 0) { | ||
return; | ||
} | ||
|
||
const steps = _.compact( | ||
types.map((id) => environmentTypes.find((eType) => eType.id === id)) | ||
); | ||
|
||
trackEvent('endpoint-wizard-endpoint-select', { | ||
category: 'portainer', | ||
metadata: { | ||
environment: steps.map((step) => step.title).join('/'), | ||
}, | ||
}); | ||
|
||
router.stateService.go('portainer.wizard.endpoints.create', { | ||
envType: types, | ||
}); | ||
} | ||
} | ||
|
||
export const EnvironmentTypeSelectViewAngular = r2a( | ||
EnvironmentTypeSelectView, | ||
[] | ||
); |
51 changes: 51 additions & 0 deletions
51
app/portainer/views/wizard/EnvironmentTypeSelectView/EnvironmentSelector.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import { FormSection } from '@/portainer/components/form-components/FormSection'; | ||
import { r2a } from '@/react-tools/react2angular'; | ||
|
||
import { EnvironmentSelectorItem } from './EnvironmentSelectorItem'; | ||
import { environmentTypes } from './environment-types'; | ||
|
||
export type Value = typeof environmentTypes[number]['id']; | ||
|
||
interface Props { | ||
value: Value[]; | ||
onChange(value: Value[]): void; | ||
} | ||
|
||
export function EnvironmentSelector({ value, onChange }: Props) { | ||
return ( | ||
<div className="row"> | ||
<FormSection title="Select your environment(s)"> | ||
<p className="text-muted small"> | ||
You can onboard different types of environments, select all that | ||
apply. | ||
</p> | ||
<div className="col-sm-12"> | ||
{environmentTypes.map((eType) => ( | ||
<EnvironmentSelectorItem | ||
key={eType.id} | ||
title={eType.title} | ||
description={eType.description} | ||
icon={eType.icon} | ||
active={value.includes(eType.id)} | ||
onClick={() => handleClick(eType.id)} | ||
/> | ||
))} | ||
</div> | ||
</FormSection> | ||
</div> | ||
); | ||
|
||
function handleClick(eType: Value) { | ||
if (value.includes(eType)) { | ||
onChange(value.filter((v) => v !== eType)); | ||
return; | ||
} | ||
|
||
onChange([...value, eType]); | ||
} | ||
} | ||
|
||
export const EnvironmentSelectorAngular = r2a(EnvironmentSelector, [ | ||
'value', | ||
'onChange', | ||
]); |
38 changes: 38 additions & 0 deletions
38
app/portainer/views/wizard/EnvironmentTypeSelectView/EnvironmentSelectorItem.module.css
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
.root { | ||
--selected-item-color: var(--blue-2); | ||
display: block; | ||
width: 200px; | ||
height: 300px; | ||
border: 1px solid rgb(163, 163, 163); | ||
border-radius: 5px; | ||
float: left; | ||
margin-right: 15px; | ||
padding: 25px 20px; | ||
cursor: pointer; | ||
box-shadow: 0 3px 10px -2px rgb(161 170 166 / 60%); | ||
} | ||
|
||
.root:hover { | ||
box-shadow: 0 3px 10px -2px rgb(161 170 166 / 80%); | ||
border: 1px solid var(--blue-2); | ||
color: #337ab7; | ||
} | ||
|
||
.active:hover { | ||
color: #fff; | ||
} | ||
|
||
.active { | ||
background: #337ab7; | ||
color: #fff; | ||
border: 1px solid var(--blue-2); | ||
box-shadow: 0 3px 10px -2px rgb(161 170 166 / 80%); | ||
} | ||
|
||
.icon { | ||
font-size: 80px; | ||
} | ||
|
||
.icon-component { | ||
font-size: 40px; | ||
} |
46 changes: 46 additions & 0 deletions
46
app/portainer/views/wizard/EnvironmentTypeSelectView/EnvironmentSelectorItem.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
import clsx from 'clsx'; | ||
import { ComponentType } from 'react'; | ||
|
||
import styles from './EnvironmentSelectorItem.module.css'; | ||
|
||
export interface SelectorItemType { | ||
icon: string | ComponentType<{ selected?: boolean; className?: string }>; | ||
title: string; | ||
description: string; | ||
} | ||
|
||
interface Props extends SelectorItemType { | ||
active: boolean; | ||
onClick(): void; | ||
} | ||
|
||
export function EnvironmentSelectorItem({ | ||
icon, | ||
active, | ||
description, | ||
title, | ||
onClick, | ||
}: Props) { | ||
const Icon = typeof icon !== 'string' ? icon : null; | ||
|
||
return ( | ||
<button | ||
className={clsx('border-0', styles.root, { [styles.active]: active })} | ||
type="button" | ||
onClick={onClick} | ||
> | ||
<div className="text-center mt-2"> | ||
{Icon ? ( | ||
<Icon selected={active} className={styles.iconComponent} /> | ||
) : ( | ||
<i className={clsx(icon, 'block', styles.icon)} /> | ||
)} | ||
</div> | ||
|
||
<div className="mt-3 text-center"> | ||
<h3>{title}</h3> | ||
<h5>{description}</h5> | ||
</div> | ||
</button> | ||
); | ||
} |
13 changes: 13 additions & 0 deletions
13
app/portainer/views/wizard/EnvironmentTypeSelectView/KaaSIcon.module.css
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
.selected .mask-icon { | ||
color: var(--selected-item-color); | ||
} | ||
|
||
:global(:root[theme='highcontrast']) .mask-icon, | ||
:global(:root[theme='dark']) .mask-icon { | ||
color: var(--bg-boxselector-wrapper-disabled-color); | ||
} | ||
|
||
.mask-icon { | ||
color: var(--bg-boxselector-color); | ||
transform: scale(1.2); | ||
} |
21 changes: 21 additions & 0 deletions
21
app/portainer/views/wizard/EnvironmentTypeSelectView/KaaSIcon.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import clsx from 'clsx'; | ||
|
||
import styles from './KaaSIcon.module.css'; | ||
|
||
interface Props { | ||
selected?: boolean; | ||
className?: string; | ||
} | ||
|
||
export function KaaSIcon({ selected, className }: Props) { | ||
return ( | ||
<span | ||
className={clsx('fa-stack fa-1x', styles.root, className, { | ||
[styles.selected]: selected, | ||
})} | ||
> | ||
<i className="fas fa-cloud fa-stack-2x" /> | ||
<i className={clsx('fas fa-dharmachakra fa-stack-1x', styles.maskIcon)} /> | ||
</span> | ||
); | ||
} |
35 changes: 35 additions & 0 deletions
35
app/portainer/views/wizard/EnvironmentTypeSelectView/environment-types.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import { KaaSIcon } from './KaaSIcon'; | ||
|
||
export const environmentTypes = [ | ||
{ | ||
id: 'docker', | ||
title: 'Docker', | ||
icon: 'fab fa-docker', | ||
description: | ||
'Connect to Docker Standalone / Swarm via URL/IP, API or Socket', | ||
}, | ||
{ | ||
id: 'kubernetes', | ||
title: 'Kubernetes', | ||
icon: 'fas fa-dharmachakra', | ||
description: 'Connect to a kubernetes environment via URL/IP', | ||
}, | ||
{ | ||
id: 'kaas', | ||
title: 'KaaS', | ||
description: 'Provision a Kubernetes environment with a cloud provider', | ||
icon: KaaSIcon, | ||
}, | ||
{ | ||
id: 'aci', | ||
title: 'ACI', | ||
description: 'Connect to ACI environment via API', | ||
icon: 'fab fa-microsoft', | ||
}, | ||
{ | ||
id: 'nomad', | ||
title: 'Nomad', | ||
description: 'Connect to HashiCorp Nomad environment via API', | ||
icon: 'nomad-icon', | ||
}, | ||
] as const; |
Oops, something went wrong.