1
0
Fork 0
mirror of https://github.com/portainer/portainer.git synced 2025-08-05 05:45:22 +02:00

feat(ui): portainer wizard ui change for ce EE-3576 (#7405)

* ui change for wizard
This commit is contained in:
Richard Wei 2022-08-12 08:43:01 +12:00 committed by GitHub
parent a7ab0a5662
commit ee1ee633d7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
33 changed files with 272 additions and 77 deletions

View file

@ -10,6 +10,8 @@
margin-bottom: 5px;
font-weight: bold;
user-select: none;
color: var(--text-boxselector-header);
padding: 0px 10px;
}
.boxselector_header .fa,
@ -115,6 +117,16 @@
padding-left: 20px;
}
.boxselector_wrapper input[type='radio']:not(:disabled) ~ label,
.box-selector-item input[type='radio']:not(:disabled) ~ label {
background-color: var(--bg-boxselector-color);
}
.boxselector_img_container {
line-height: 90px;
margin-bottom: 0;
}
.box-selector-item p {
margin-bottom: 0;
}

View file

@ -19,7 +19,7 @@ export function NavTabs({ options, selectedId, onSelect = () => {} }: Props) {
const selected = options.find((option) => option.id === selectedId);
return (
<>
<div className="nav-container">
<ul className="nav nav-tabs">
{options.map((option) => (
<li
@ -49,7 +49,7 @@ export function NavTabs({ options, selectedId, onSelect = () => {} }: Props) {
{selected && selected.children && (
<div className="tab-content">{selected.children}</div>
)}
</>
</div>
);
function handleSelect(option: Option) {

View file

@ -18,18 +18,18 @@
position: absolute;
content: '';
width: 100%;
top: 20px;
top: 15px;
left: -100%;
z-index: 2;
border-bottom: 5px solid var(--bg-stepper-item-counter);
border-bottom: 3px solid var(--border-stepper-color);
}
.step-wrapper::after {
position: absolute;
content: '';
border-bottom: 5px solid var(--bg-stepper-item-counter);
border-bottom: 3px solid var(--border-stepper-color);
width: 100%;
top: 20px;
top: 15px;
left: 0;
z-index: 2;
}
@ -46,11 +46,13 @@
display: flex;
justify-content: center;
align-items: center;
width: 40px;
height: 40px;
width: 30px;
height: 30px;
border-radius: 50%;
background: var(--bg-stepper-item-counter);
/* background: var(--ui-white); */
background: var(--bg-stepper-color);
margin-bottom: 6px;
border: 1px solid var(--ui-gray-6);
}
.step-wrapper.active {
@ -59,27 +61,29 @@
}
.step-wrapper.active .step {
background: #337ab7;
background: var(--bg-stepper-active-color);
border: 2px solid var(--ui-blue-8);
}
.step-wrapper.active .step-counter {
color: #fff;
color: var(--text-stepper-active-color);
}
.step-wrapper.completed .step {
background-color: #48b400;
background: var(--bg-stepper-active-color);
border: 2px solid var(--ui-blue-8);
}
.step-wrapper.completed .step-counter {
color: #fff;
color: var(--text-stepper-active-color);
}
.step-wrapper.completed::after {
position: absolute;
content: '';
border-bottom: 5px solid #48b400;
border-bottom: 3px solid var(--ui-blue-8);
width: 100%;
top: 20px;
top: 15px;
left: 0;
z-index: 3;
}

View file

@ -3,6 +3,12 @@ import automode from '@/assets/ico/theme/auto.svg?c';
import darkmode from '@/assets/ico/theme/darkmode.svg?c';
import lightmode from '@/assets/ico/theme/lightmode.svg?c';
import highcontrastmode from '@/assets/ico/theme/highcontrastmode.svg?c';
// wizard icons
import agent from '@/assets/ico/wizard/agent.svg?c';
import api from '@/assets/ico/wizard/api.svg?c';
import edgeagent from '@/assets/ico/wizard/edge-agent.svg?c';
import cloudimport from '@/assets/ico/wizard/import.svg?c';
import socket from '@/assets/ico/wizard/socket.svg?c';
// general icons
import arrowsupdown from '@/assets/ico/arrows-updown.svg?c';
import arrowright from '@/assets/ico/arrow-right-long.svg?c';
@ -25,6 +31,7 @@ import heartbeat from '@/assets/ico/heartbeat.svg?c';
import laptop from '@/assets/ico/laptop.svg?c';
import laptopcode from '@/assets/ico/laptop-code.svg?c';
import ldap from '@/assets/ico/ldap.svg?c';
import magic from '@/assets/ico/magic.svg?c';
import magicwand from '@/assets/ico/magic-wand.svg?c';
import memory from '@/assets/ico/memory.svg?c';
import objectgroup from '@/assets/ico/object-group.svg?c';
@ -71,6 +78,11 @@ import internal from '@/assets/ico/vendor/internal.svg?c';
const placeholder = Placeholder;
export const SvgIcons = {
agent,
api,
edgeagent,
cloudimport,
socket,
automode,
darkmode,
lightmode,
@ -96,6 +108,7 @@ export const SvgIcons = {
laptop,
laptopcode,
ldap,
magic,
magicwand,
memory,
objectgroup,

View file

@ -46,7 +46,7 @@ export function FileUploadField({
</Button>
<span className="vertical-center">
{value ? value.name : <Icon icon="x" feather mode="danger" />}
{value ? value.name : <Icon icon="x-circle" feather mode="danger" />}
</span>
</div>
);

View file

@ -33,7 +33,7 @@ export function EnvironmentTypeSelectView() {
<div className="row">
<div className="col-sm-12">
<Widget>
<WidgetTitle icon="fa-magic" title="Environment Wizard" />
<WidgetTitle icon="svg-magic" title="Environment Wizard" />
<WidgetBody>
<EnvironmentSelector
value={types}

View file

@ -12,6 +12,7 @@ import { Widget, WidgetBody, WidgetTitle } from '@@/Widget';
import { PageHeader } from '@@/PageHeader';
import { Button } from '@@/buttons';
import { FormSection } from '@@/form-components/FormSection';
import { Icon } from '@@/Icon';
import { environmentTypes } from '../EnvironmentTypeSelectView/environment-types';
import { EnvironmentSelectorValue } from '../EnvironmentTypeSelectView/EnvironmentSelector';
@ -65,7 +66,7 @@ export function EnvironmentCreationView() {
<div className={styles.wizardWrapper}>
<Widget>
<WidgetTitle icon="fa-magic" title="Environment Wizard" />
<WidgetTitle icon="svg-magic" title="Environment Wizard" />
<WidgetBody>
<Stepper steps={steps} currentStep={currentStepIndex + 1} />
@ -83,11 +84,11 @@ export function EnvironmentCreationView() {
)}
>
<Button disabled={isFirstStep} onClick={onPreviousClick}>
<i className="fas fa-arrow-left space-right" /> Previous
<Icon icon="arrow-left" feather /> Previous
</Button>
<Button onClick={onNextClick}>
{isLastStep ? 'Finish' : 'Next'}
<i className="fas fa-arrow-right space-left" />
{isLastStep ? 'Close' : 'Next'}
<Icon icon="arrow-right" feather />
</Button>
</div>
</FormSection>

View file

@ -12,6 +12,7 @@ import { LoadingButton } from '@@/buttons/LoadingButton';
import { Input } from '@@/form-components/Input';
import { FormControl } from '@@/form-components/FormControl';
import { BoxSelector } from '@@/BoxSelector';
import { Icon } from '@@/Icon';
import { NameField, nameValidation } from '../shared/NameField';
import { AnalyticsStateKey } from '../types';
@ -37,7 +38,7 @@ const initialValues: FormValues = {
},
};
const options = [buildOption('api', 'fa fa-bolt', 'API', '', 'api')];
const options = [buildOption('api', 'svg-api', 'API', '', 'api')];
interface Props {
onCreate(environment: Environment, analytics: AnalyticsStateKey): void;
@ -116,11 +117,16 @@ export function WizardAzure({ onCreate }: Props) {
<div className="row">
<div className="col-sm-12">
<LoadingButton
className="vertical-center"
loadingText="Connecting environment..."
isLoading={mutation.isLoading}
disabled={!dirty || !isValid}
>
<i className="fa fa-plug" aria-hidden="true" /> Connect
<Icon
icon="svg-plug"
className="icon icon-sm vertical-center"
/>{' '}
Connect
</LoadingButton>
</div>
</div>

View file

@ -12,6 +12,7 @@ import {
import { LoadingButton } from '@@/buttons/LoadingButton';
import { FormControl } from '@@/form-components/FormControl';
import { Input } from '@@/form-components/Input';
import { Icon } from '@@/Icon';
import { NameField } from '../../shared/NameField';
import { MoreSettingsSection } from '../../shared/MoreSettingsSection';
@ -76,12 +77,16 @@ export function APIForm({ onCreate }: Props) {
<div className="form-group">
<div className="col-sm-12">
<LoadingButton
className="wizard-connect-button"
className="wizard-connect-button vertical-center"
loadingText="Connecting environment..."
isLoading={mutation.isLoading}
disabled={!dirty || !isValid}
>
<i className="fa fa-plug" aria-hidden="true" /> Connect
<Icon
icon="svg-plug"
className="icon icon-sm vertical-center"
/>{' '}
Connect
</LoadingButton>
</div>
</div>

View file

@ -59,7 +59,9 @@ function DeployCode({ code }: DeployCodeProps) {
<span className="text-muted small">
CLI script for installing agent on your environment with Docker Swarm:
</span>
<Code>{code}</Code>
<div className="code-script">
<Code>{code}</Code>
</div>
<CopyButton copyText={code}>Copy command</CopyButton>
</>
);

View file

@ -10,6 +10,7 @@ import { LoadingButton } from '@@/buttons/LoadingButton';
import { FormControl } from '@@/form-components/FormControl';
import { Input } from '@@/form-components/Input';
import { SwitchField } from '@@/form-components/SwitchField';
import { Icon } from '@@/Icon';
import { NameField } from '../../shared/NameField';
import { MoreSettingsSection } from '../../shared/MoreSettingsSection';
@ -54,12 +55,16 @@ export function SocketForm({ onCreate }: Props) {
<div className="form-group">
<div className="col-sm-12">
<LoadingButton
className="wizard-connect-button"
className="wizard-connect-button vertical-center"
loadingText="Connecting environment..."
isLoading={mutation.isLoading}
disabled={!dirty || !isValid}
>
<i className="fa fa-plug" aria-hidden="true" /> Connect
<Icon
icon="svg-plug"
className="icon icon-sm vertical-center"
/>{' '}
Connect
</LoadingButton>
</div>
</div>

View file

@ -22,28 +22,28 @@ const defaultOptions: BoxSelectorOption<
>[] = [
{
id: 'agent',
icon: 'fa fa-bolt',
icon: 'svg-agent',
label: 'Agent',
description: '',
value: 'agent',
},
{
id: 'api',
icon: 'fa fa-cloud',
icon: 'svg-api',
label: 'API',
description: '',
value: 'api',
},
{
id: 'socket',
icon: 'fab fa-docker',
icon: 'svg-socket',
label: 'Socket',
description: '',
value: 'socket',
},
{
id: 'edgeAgent',
icon: 'fa fa-cloud', // Todo cloud with docker
icon: 'svg-edgeagent',
label: 'Edge Agent',
description: '',
value: 'edgeAgent',

View file

@ -44,7 +44,7 @@ export function WizardEndpointsList({ environmentIds }: Props) {
return (
<Widget>
<WidgetTitle icon="fa-plug" title="New Environments" />
<WidgetTitle icon="svg-plug" title="New Environments" />
<WidgetBody>
{environments.map((environment) => (
<div className={styles.wizardListWrapper} key={environment.Id}>

View file

@ -5,6 +5,7 @@ import { FormControl } from '@@/form-components/FormControl';
import { FormSectionTitle } from '@@/form-components/FormSectionTitle';
import { Input } from '@@/form-components/Input';
import { Button } from '@@/buttons';
import { TextTip } from '@@/Tip/TextTip';
const initialValues = {
kubeConfig: '',
@ -24,26 +25,22 @@ export function KubeConfigTeaserForm() {
<div className="form-group">
<div className="col-sm-12">
<span className="text-primary">
<i
className="fa fa-exclamation-circle space-right"
aria-hidden="true"
/>
</span>
<span className="text-muted small">
Import the
<a
href="https://kubernetes.io/docs/concepts/configuration/organize-cluster-access-kubeconfig/"
target="_blank"
className="space-right space-left"
rel="noreferrer"
>
kubeconfig file
</a>
of an existing Kubernetes cluster located on-premise or on a
cloud platform. This will create a corresponding environment in
Portainer and install the agent on the cluster. Please ensure:
</span>
<TextTip color="blue">
<span className="text-muted">
<a
href="https://docs.portainer.io/start/install/agent/kubernetes/import"
target="_blank"
rel="noreferrer"
className="mx-1"
>
Import the kubeconfig file
</a>
of an existing Kubernetes cluster located on-premise or on a
cloud platform. This will create a corresponding environment
in Portainer and install the agent on the cluster. Please
ensure:
</span>
</TextTip>
</div>
<div className="col-sm-12 text-muted small">
<ul className="p-2 pl-4">

View file

@ -25,14 +25,14 @@ interface Props {
const defaultOptions: BoxSelectorOption<EnvironmentCreationTypes>[] = [
{
id: 'agent_endpoint',
icon: 'fa fa-bolt',
icon: 'svg-agent',
label: 'Agent',
value: EnvironmentCreationTypes.AgentEnvironment,
description: '',
},
{
id: 'edgeAgent',
icon: 'fa fa-cloud', // Todo cloud with docker
icon: 'svg-edgeagent',
label: 'Edge Agent',
description: '',
value: EnvironmentCreationTypes.EdgeAgentEnvironment,
@ -40,7 +40,7 @@ const defaultOptions: BoxSelectorOption<EnvironmentCreationTypes>[] = [
},
{
id: 'kubeconfig_endpoint',
icon: 'fas fa-cloud-upload-alt',
icon: 'svg-cloudimport',
label: 'Import',
value: EnvironmentCreationTypes.KubeConfigEnvironment,
description: 'Import an existing Kubernetes config',

View file

@ -7,6 +7,7 @@ import { Environment } from '@/portainer/environments/types';
import { CreateAgentEnvironmentValues } from '@/portainer/environments/environment.service/create';
import { LoadingButton } from '@@/buttons/LoadingButton';
import { Icon } from '@@/Icon';
import { NameField } from '../NameField';
import { MoreSettingsSection } from '../MoreSettingsSection';
@ -53,12 +54,16 @@ export function AgentForm({ onCreate, showGpus = false }: Props) {
<div className="form-group">
<div className="col-sm-12">
<LoadingButton
className="wizard-connect-button"
className="wizard-connect-button vertical-center"
loadingText="Connecting environment..."
isLoading={mutation.isLoading}
disabled={!dirty || !isValid}
>
<i className="fa fa-plug" aria-hidden="true" /> Connect
<Icon
icon="svg-plug"
className="icon icon-sm vertical-center"
/>{' '}
Connect
</LoadingButton>
</div>
</div>

View file

@ -8,6 +8,7 @@ import { useCreateEdgeDeviceParam } from '@/react/portainer/environments/wizard/
import { FormSection } from '@@/form-components/FormSection';
import { LoadingButton } from '@@/buttons/LoadingButton';
import { Icon } from '@@/Icon';
import { MoreSettingsSection } from '../../MoreSettingsSection';
import { Hardware } from '../../Hardware/Hardware';
@ -55,11 +56,15 @@ export function EdgeAgentForm({ onCreate, readonly, showGpus = false }: Props) {
<div className="row">
<div className="col-sm-12">
<LoadingButton
className="vertical-center"
isLoading={createMutation.isLoading}
loadingText="Creating environment..."
disabled={!isValid}
>
<i className="fa fa-plug space-right" />
<Icon
icon="svg-plug"
className="icon icon-sm vertical-center"
/>
Create
</LoadingButton>
</div>

View file

@ -23,7 +23,7 @@ export function HomeView() {
<div className="row">
<div className="col-sm-12">
<Widget>
<WidgetTitle title="Environment Wizard" icon="fa-magic" />
<WidgetTitle title="Environment Wizard" icon="svg-magic" />
<WidgetBody>
<div className="row">
<div className="col-sm-12 form-section-title">
@ -32,7 +32,7 @@ export function HomeView() {
<div className="text-muted small">
{localEnvironmentAdded.status === 'success' && (
<p>
We have connected your local environment of
We have connected your local environment of{' '}
{getTypeLabel(localEnvironmentAdded.type)} to Portainer.
</p>
)}