Merge: client: fix mobile layout for install page
Squashed commit of the following:
commit 5e620f2d8576b08ebfee08e9781cd4927c4dcf2a
Merge: d82d5a902 679bbcdc2
Author: Ildar Kamalov <ik@adguard.com>
Date: Mon Jan 18 14:57:00 2021 +0300
Merge branch 'master' into 2554-mobile-install
commit d82d5a9028be0be72e612fc4c375d2be81c6c8c3
Author: Ildar Kamalov <ik@adguard.com>
Date: Mon Jan 18 14:09:25 2021 +0300
client: fix mobile layout for install page
This commit is contained in:
@@ -1,14 +0,0 @@
|
||||
.layout {
|
||||
background-image: url('../../assets/img/background_min.png');
|
||||
background-repeat: no-repeat;
|
||||
min-height: 100vh;
|
||||
background-color: #f1f3f7;
|
||||
}
|
||||
.container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding: 40px;
|
||||
}
|
||||
.content {
|
||||
max-width: 404px;
|
||||
}
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
} from 'Consts/install';
|
||||
import { notifyError } from 'Common/ui';
|
||||
import InstallStore from 'Store/stores/Install';
|
||||
import theme from 'Lib/theme';
|
||||
|
||||
import AdminInterface from './components/AdminInterface';
|
||||
import Auth from './components/Auth';
|
||||
@@ -21,8 +22,6 @@ import Stepper from './components/Stepper';
|
||||
import Welcome from './components/Welcome';
|
||||
import ConfigureDevices from './components/ConfigureDevices';
|
||||
|
||||
import s from './Install.module.pcss';
|
||||
|
||||
const { Content } = Layout;
|
||||
|
||||
export type FormValues = IInitialConfigurationBeta & { step: number };
|
||||
@@ -85,7 +84,7 @@ const InstallForm: FC = observer(() => {
|
||||
onSubmit={onNext}
|
||||
>
|
||||
{({ values, handleSubmit, setFieldValue }) => (
|
||||
<form noValidate className={s.content} onSubmit={handleSubmit}>
|
||||
<form noValidate onSubmit={handleSubmit}>
|
||||
<Stepper currentStep={values.step} />
|
||||
{values.step === 0 && (
|
||||
<Welcome onNext={() => setFieldValue('step', 1)}/>
|
||||
@@ -110,8 +109,8 @@ const InstallForm: FC = observer(() => {
|
||||
|
||||
const Install: FC = () => {
|
||||
return (
|
||||
<Layout className={s.layout}>
|
||||
<Content className={s.container}>
|
||||
<Layout className={theme.install.layout}>
|
||||
<Content className={theme.install.container}>
|
||||
<InstallForm />
|
||||
</Content>
|
||||
<Icons/>
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
.manualOptions {
|
||||
margin-bottom: 48px;
|
||||
}
|
||||
|
||||
.name {
|
||||
padding-bottom: 5px;
|
||||
border-bottom: 1px solid var(--gray300);
|
||||
margin-bottom: 16px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.manualOption {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: baseline;
|
||||
|
||||
}
|
||||
@@ -9,7 +9,6 @@ import { chechNetworkType, NETWORK_TYPE } from 'Helpers/installHelpers';
|
||||
import theme from 'Lib/theme';
|
||||
import Store from 'Store/installStore';
|
||||
|
||||
import s from './AdminInterface.module.pcss';
|
||||
import { FormValues } from '../../Install';
|
||||
import StepButtons from '../StepButtons';
|
||||
|
||||
@@ -39,7 +38,7 @@ const AdminInterface: FC<AdminInterfaceProps> = observer(({
|
||||
};
|
||||
|
||||
const getManualBlock = () => (
|
||||
<div className={s.manualOptions}>
|
||||
<div className={theme.install.options}>
|
||||
{addresses?.interfaces.map((a) => {
|
||||
let name = '';
|
||||
const type = chechNetworkType(a.name);
|
||||
@@ -56,29 +55,27 @@ const AdminInterface: FC<AdminInterfaceProps> = observer(({
|
||||
}
|
||||
return (
|
||||
<div key={a.name}>
|
||||
<div>
|
||||
<div className={s.name}>
|
||||
{name}
|
||||
</div>
|
||||
{a.ipAddresses?.map((addrIp) => (
|
||||
<div key={addrIp} className={s.manualOption}>
|
||||
<div className={theme.typography.subtext}>
|
||||
http://{addrIp}
|
||||
</div>
|
||||
<Switch
|
||||
checked={values.web.ip.includes(addrIp)}
|
||||
onChange={() => {
|
||||
const temp = new Set(ip);
|
||||
if (temp.has(addrIp)) {
|
||||
temp.delete(addrIp);
|
||||
} else {
|
||||
temp.add(addrIp);
|
||||
}
|
||||
setFieldValue('web.ip', Array.from(temp.values()));
|
||||
}}/>
|
||||
</div>
|
||||
))}
|
||||
<div className={theme.install.name}>
|
||||
{name}
|
||||
</div>
|
||||
{a.ipAddresses?.map((addrIp) => (
|
||||
<div key={addrIp} className={theme.install.option}>
|
||||
<div className={theme.install.address}>
|
||||
http://{addrIp}
|
||||
</div>
|
||||
<Switch
|
||||
checked={values.web.ip.includes(addrIp)}
|
||||
onChange={() => {
|
||||
const temp = new Set(ip);
|
||||
if (temp.has(addrIp)) {
|
||||
temp.delete(addrIp);
|
||||
} else {
|
||||
temp.add(addrIp);
|
||||
}
|
||||
setFieldValue('web.ip', Array.from(temp.values()));
|
||||
}}/>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
@@ -86,17 +83,17 @@ const AdminInterface: FC<AdminInterfaceProps> = observer(({
|
||||
);
|
||||
|
||||
return (
|
||||
<div className={s.content}>
|
||||
<div className={theme.typography.title}>
|
||||
<>
|
||||
<div className={theme.install.title}>
|
||||
{intl.getMessage('install_admin_interface_title')}
|
||||
</div>
|
||||
<div className={cn(theme.typography.text, theme.typography.text_block)}>
|
||||
<div className={cn(theme.install.text, theme.install.text_block)}>
|
||||
{intl.getMessage('install_admin_interface_title_decs')}
|
||||
</div>
|
||||
<div className={theme.typography.subTitle}>
|
||||
<div className={theme.install.subtitle}>
|
||||
{intl.getMessage('install_admin_interface_where_interface')}
|
||||
</div>
|
||||
<div className={cn(theme.typography.text, theme.typography.text_base)}>
|
||||
<div className={cn(theme.install.text, theme.install.text_base)}>
|
||||
{intl.getMessage('install_admin_interface_where_interface_desc')}
|
||||
</div>
|
||||
<Radio
|
||||
@@ -116,10 +113,10 @@ const AdminInterface: FC<AdminInterfaceProps> = observer(({
|
||||
]}
|
||||
/>
|
||||
{ radioValue !== NETWORK_OPTIONS.ALL && getManualBlock()}
|
||||
<div className={theme.typography.subTitle}>
|
||||
<div className={theme.install.subtitle}>
|
||||
{intl.getMessage('install_admin_interface_port')}
|
||||
</div>
|
||||
<div className={cn(theme.typography.text, theme.typography.text_base)}>
|
||||
<div className={cn(theme.install.text, theme.install.text_base)}>
|
||||
{intl.getMessage('install_admin_interface_port_desc')}
|
||||
</div>
|
||||
<Input
|
||||
@@ -138,7 +135,7 @@ const AdminInterface: FC<AdminInterfaceProps> = observer(({
|
||||
currentStep={1}
|
||||
values={values}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@@ -22,11 +22,11 @@ const Auth: FC<AuthProps> = observer(({
|
||||
const { ui: { intl } } = useContext(Store);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className={theme.typography.title}>
|
||||
<>
|
||||
<div className={theme.install.title}>
|
||||
{intl.getMessage('install_auth_title')}
|
||||
</div>
|
||||
<div className={cn(theme.typography.text, theme.typography.text_block)}>
|
||||
<div className={cn(theme.install.text, theme.install.text_block)}>
|
||||
{intl.getMessage('install_auth_description')}
|
||||
</div>
|
||||
<Input
|
||||
@@ -48,7 +48,7 @@ const Auth: FC<AuthProps> = observer(({
|
||||
currentStep={2}
|
||||
values={values}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
.tabs {
|
||||
width: 505px;
|
||||
margin-left: -131px;
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { FC, useContext } from 'react';
|
||||
import { Tabs } from 'antd';
|
||||
import { Tabs, Grid } from 'antd';
|
||||
import cn from 'classnames';
|
||||
import { FormikHelpers } from 'formik';
|
||||
|
||||
@@ -10,8 +10,8 @@ import { DEFAULT_DNS_PORT, DEFAULT_IP_ADDRESS, DEFAULT_IP_PORT } from 'Consts/in
|
||||
|
||||
import { FormValues } from '../../Install';
|
||||
import StepButtons from '../StepButtons';
|
||||
import s from './ConfigureDevices.module.pcss';
|
||||
|
||||
const { useBreakpoint } = Grid;
|
||||
const { TabPane } = Tabs;
|
||||
|
||||
interface ConfigureDevicesProps {
|
||||
@@ -23,10 +23,18 @@ const ConfigureDevices: FC<ConfigureDevicesProps> = ({
|
||||
values, setFieldValue,
|
||||
}) => {
|
||||
const { ui: { intl }, install: { addresses } } = useContext(Store);
|
||||
const screens = useBreakpoint();
|
||||
const tabsPosition = screens.md ? 'left' : 'top';
|
||||
|
||||
const dhcp = (e: string) => (
|
||||
// TODO: link to dhcp
|
||||
<a href="http://" target="_blank" rel="noopener noreferrer">{e}</a>
|
||||
<a
|
||||
href="https://github.com/AdguardTeam/AdGuardHome/wiki/DHCP"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className={theme.link.link}
|
||||
>
|
||||
{e}
|
||||
</a>
|
||||
);
|
||||
|
||||
const allIps = addresses?.interfaces.reduce<string[]>((all, data) => {
|
||||
@@ -44,76 +52,92 @@ const ConfigureDevices: FC<ConfigureDevicesProps> = ({
|
||||
? allIps : dnsIp;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className={theme.typography.title}>
|
||||
<>
|
||||
<div className={theme.install.title}>
|
||||
{intl.getMessage('install_configure_title')}
|
||||
</div>
|
||||
<div className={cn(theme.typography.text, theme.typography.text_block)}>
|
||||
<div className={cn(theme.install.text, theme.install.text_block)}>
|
||||
{intl.getMessage('install_configure_danger_notice', { danger })}
|
||||
</div>
|
||||
<div className={theme.typography.subTitle}>
|
||||
{intl.getMessage('install_configure_how_to_title')}
|
||||
</div>
|
||||
<Tabs defaultActiveKey="1" tabPosition="left" className={s.tabs}>
|
||||
<TabPane tab="Router" key="1">
|
||||
<div className={cn(theme.typography.text, theme.typography.text_base)}>
|
||||
|
||||
<Tabs defaultActiveKey="1" tabPosition={tabsPosition} className={theme.install.tabs}>
|
||||
<TabPane tab={intl.getMessage('router')} key="1">
|
||||
<div className={theme.install.subtitle}>
|
||||
{intl.getMessage('install_configure_how_to_title', { value: intl.getMessage('router') })}
|
||||
</div>
|
||||
<div className={cn(theme.install.text, theme.install.text_base)}>
|
||||
{intl.getMessage('install_configure_router', { p })}
|
||||
</div>
|
||||
</TabPane>
|
||||
<TabPane tab="Windows" key="2">
|
||||
<div className={cn(theme.typography.text, theme.typography.text_base)}>
|
||||
<div className={theme.install.subtitle}>
|
||||
{intl.getMessage('install_configure_how_to_title', { value: 'Windows' })}
|
||||
</div>
|
||||
<div className={cn(theme.install.text, theme.install.text_base)}>
|
||||
{intl.getMessage('install_configure_windows', { p })}
|
||||
</div>
|
||||
</TabPane>
|
||||
<TabPane tab="Macos" key="3">
|
||||
<div className={cn(theme.typography.text, theme.typography.text_base)}>
|
||||
<TabPane tab="macOS" key="3">
|
||||
<div className={theme.install.subtitle}>
|
||||
{intl.getMessage('install_configure_how_to_title', { value: 'macOS' })}
|
||||
</div>
|
||||
<div className={cn(theme.install.text, theme.install.text_base)}>
|
||||
{intl.getMessage('install_configure_macos', { p })}
|
||||
</div>
|
||||
</TabPane>
|
||||
<TabPane tab="Linux" key="4">
|
||||
<div className={cn(theme.typography.text, theme.typography.text_base)}>
|
||||
<div className={theme.install.subtitle}>
|
||||
{intl.getMessage('install_configure_how_to_title', { value: 'Linux' })}
|
||||
</div>
|
||||
<div className={cn(theme.install.text, theme.install.text_base)}>
|
||||
{/* TODO: add linux setup */}
|
||||
{intl.getMessage('install_configure_router', { p })}
|
||||
</div>
|
||||
</TabPane>
|
||||
<TabPane tab="Android" key="5">
|
||||
<div className={cn(theme.typography.text, theme.typography.text_base)}>
|
||||
<div className={theme.install.subtitle}>
|
||||
{intl.getMessage('install_configure_how_to_title', { value: 'Android' })}
|
||||
</div>
|
||||
<div className={cn(theme.install.text, theme.install.text_base)}>
|
||||
{intl.getMessage('install_configure_android', { p })}
|
||||
</div>
|
||||
</TabPane>
|
||||
<TabPane tab="iOs" key="6">
|
||||
<div className={cn(theme.typography.text, theme.typography.text_base)}>
|
||||
<TabPane tab="iOS" key="6">
|
||||
<div className={theme.install.subtitle}>
|
||||
{intl.getMessage('install_configure_how_to_title', { value: 'iOS' })}
|
||||
</div>
|
||||
<div className={cn(theme.install.text, theme.install.text_base)}>
|
||||
{intl.getMessage('install_configure_ios', { p })}
|
||||
</div>
|
||||
</TabPane>
|
||||
</Tabs>
|
||||
|
||||
<div className={theme.typography.subTitle}>
|
||||
<div className={theme.install.subtitle}>
|
||||
{intl.getMessage('install_configure_adresses')}
|
||||
</div>
|
||||
<div className={cn(theme.typography.text, theme.typography.text_base)}>
|
||||
<p>
|
||||
<div className={cn(theme.install.text, theme.install.text_block)}>
|
||||
<div className={cn(theme.install.text, theme.install.text_base)}>
|
||||
{intl.getMessage('install_admin_interface_title')}
|
||||
</p>
|
||||
<p>
|
||||
</div>
|
||||
<div className={cn(theme.install.text, theme.install.text_base)}>
|
||||
{selectedWebIps?.map((ip) => (
|
||||
<div key={ip}>
|
||||
<div key={ip} className={theme.install.ip}>
|
||||
{ip}{values.web.port !== DEFAULT_IP_PORT && `:${values.web.port}`}
|
||||
</div>
|
||||
))}
|
||||
</p>
|
||||
<p>
|
||||
</div>
|
||||
<div className={cn(theme.install.text, theme.install.text_base)}>
|
||||
{intl.getMessage('install_dns_server_title')}
|
||||
</p>
|
||||
<div>
|
||||
</div>
|
||||
<div className={cn(theme.install.text, theme.install.text_base)}>
|
||||
{selectedDnsIps?.map((ip) => (
|
||||
<div key={ip}>
|
||||
<div key={ip} className={theme.install.ip}>
|
||||
{ip}{values.dns.port !== DEFAULT_DNS_PORT && `:${values.dns.port}`}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<div className={cn(theme.typography.text, theme.typography.text_base)}>
|
||||
<div className={cn(theme.install.text, theme.install.text_base)}>
|
||||
{intl.getMessage('install_configure_dhcp', { dhcp })}
|
||||
</div>
|
||||
<StepButtons
|
||||
@@ -121,7 +145,7 @@ const ConfigureDevices: FC<ConfigureDevicesProps> = ({
|
||||
currentStep={4}
|
||||
values={values}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
.manualOptions {
|
||||
margin-bottom: 48px;
|
||||
}
|
||||
|
||||
.manualOption {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: baseline;
|
||||
padding-bottom: 16px;
|
||||
border-bottom: 1px solid var(--gray300);
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
@@ -9,7 +9,6 @@ import { chechNetworkType, NETWORK_TYPE } from 'Helpers/installHelpers';
|
||||
import theme from 'Lib/theme';
|
||||
import Store from 'Store/installStore';
|
||||
|
||||
import s from './DnsServer.module.pcss';
|
||||
import { FormValues } from '../../Install';
|
||||
import StepButtons from '../StepButtons';
|
||||
|
||||
@@ -39,7 +38,7 @@ const DnsServer: FC<DnsServerProps> = observer(({
|
||||
};
|
||||
|
||||
const getManualBlock = () => (
|
||||
<div className={s.manualOptions}>
|
||||
<div className={theme.install.options}>
|
||||
{addresses?.interfaces.map((a) => {
|
||||
let name = '';
|
||||
const type = chechNetworkType(a.name);
|
||||
@@ -56,29 +55,27 @@ const DnsServer: FC<DnsServerProps> = observer(({
|
||||
}
|
||||
return (
|
||||
<div key={a.name}>
|
||||
<div>
|
||||
<div className={s.name}>
|
||||
{name}
|
||||
</div>
|
||||
{a.ipAddresses?.map((addrIp) => (
|
||||
<div key={addrIp} className={s.manualOption}>
|
||||
<div className={theme.typography.subtext}>
|
||||
{addrIp}
|
||||
</div>
|
||||
<Switch
|
||||
checked={values.dns.ip.includes(addrIp)}
|
||||
onChange={() => {
|
||||
const temp = new Set(ip);
|
||||
if (temp.has(addrIp)) {
|
||||
temp.delete(addrIp);
|
||||
} else {
|
||||
temp.add(addrIp);
|
||||
}
|
||||
setFieldValue('dns.ip', Array.from(temp.values()));
|
||||
}}/>
|
||||
</div>
|
||||
))}
|
||||
<div className={theme.install.name}>
|
||||
{name}
|
||||
</div>
|
||||
{a.ipAddresses?.map((addrIp) => (
|
||||
<div key={addrIp} className={theme.install.option}>
|
||||
<div className={theme.install.address}>
|
||||
{addrIp}
|
||||
</div>
|
||||
<Switch
|
||||
checked={values.dns.ip.includes(addrIp)}
|
||||
onChange={() => {
|
||||
const temp = new Set(ip);
|
||||
if (temp.has(addrIp)) {
|
||||
temp.delete(addrIp);
|
||||
} else {
|
||||
temp.add(addrIp);
|
||||
}
|
||||
setFieldValue('dns.ip', Array.from(temp.values()));
|
||||
}}/>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
@@ -87,16 +84,16 @@ const DnsServer: FC<DnsServerProps> = observer(({
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className={theme.typography.title}>
|
||||
<div className={theme.install.title}>
|
||||
{intl.getMessage('install_dns_server_title')}
|
||||
</div>
|
||||
<div className={cn(theme.typography.text, theme.typography.text_block)}>
|
||||
<div className={cn(theme.install.text, theme.install.text_block)}>
|
||||
{intl.getMessage('install_dns_server_desc')}
|
||||
</div>
|
||||
<div className={theme.typography.subTitle}>
|
||||
<div className={theme.install.subtitle}>
|
||||
{intl.getMessage('install_dns_server_network_interfaces')}
|
||||
</div>
|
||||
<div className={cn(theme.typography.text, theme.typography.text_base)}>
|
||||
<div className={cn(theme.install.text, theme.install.text_base)}>
|
||||
{intl.getMessage('install_dns_server_network_interfaces_desc')}
|
||||
</div>
|
||||
<Radio
|
||||
@@ -116,10 +113,10 @@ const DnsServer: FC<DnsServerProps> = observer(({
|
||||
]}
|
||||
/>
|
||||
{ radioValue !== NETWORK_OPTIONS.ALL && getManualBlock()}
|
||||
<div className={theme.typography.subTitle}>
|
||||
<div className={theme.install.subtitle}>
|
||||
{intl.getMessage('install_dns_server_port')}
|
||||
</div>
|
||||
<div className={cn(theme.typography.text, theme.typography.text_base)}>
|
||||
<div className={cn(theme.install.text, theme.install.text_base)}>
|
||||
{intl.getMessage('install_dns_server_port_desc')}
|
||||
</div>
|
||||
<Input
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
.button {
|
||||
margin-top: 48px;
|
||||
width: 190px;
|
||||
|
||||
&.inGroup {
|
||||
margin-right: 24px;
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,12 @@
|
||||
import React, { FC, useContext } from 'react';
|
||||
import { Button } from 'antd';
|
||||
import cn from 'classnames';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { FormikHelpers } from 'formik';
|
||||
|
||||
import Store from 'Store/installStore';
|
||||
import theme from 'Lib/theme';
|
||||
|
||||
import { FormValues } from '../../Install';
|
||||
import s from './StepButtons.module.pcss';
|
||||
|
||||
interface StepButtonsProps {
|
||||
setFieldValue: FormikHelpers<FormValues>['setFieldValue'];
|
||||
@@ -21,11 +20,11 @@ const StepButtons: FC<StepButtonsProps> = observer(({
|
||||
}) => {
|
||||
const { ui: { intl } } = useContext(Store);
|
||||
return (
|
||||
<div>
|
||||
<div className={theme.install.actions}>
|
||||
<Button
|
||||
size="large"
|
||||
type="ghost"
|
||||
className={cn(s.button, s.inGroup)}
|
||||
className={theme.install.button}
|
||||
onClick={() => setFieldValue('step', currentStep - 1)}
|
||||
>
|
||||
{intl.getMessage('back')}
|
||||
@@ -34,7 +33,7 @@ const StepButtons: FC<StepButtonsProps> = observer(({
|
||||
size="large"
|
||||
type="primary"
|
||||
htmlType="submit"
|
||||
className={cn(s.button)}
|
||||
className={theme.install.button}
|
||||
>
|
||||
{intl.getMessage('next')}
|
||||
</Button>
|
||||
|
||||
@@ -1,3 +1,66 @@
|
||||
.stepper {
|
||||
margin-bottom: 48px;
|
||||
}
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
height: 16px;
|
||||
margin-bottom: 32px;
|
||||
|
||||
@media (--m-viewport) {
|
||||
margin-bottom: 48px;
|
||||
}
|
||||
}
|
||||
|
||||
.wrap {
|
||||
flex: 1;
|
||||
position: relative;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
height: 16px;
|
||||
|
||||
&:before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 7px;
|
||||
width: 100%;
|
||||
height: 1px;
|
||||
background-color: var(--gray400);
|
||||
}
|
||||
|
||||
&:first-child {
|
||||
flex: 0;
|
||||
|
||||
&:before {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
&.current .circle {
|
||||
transform: scale(2);
|
||||
background-color: var(--green400);
|
||||
border-color: var(--green400);
|
||||
}
|
||||
|
||||
&.active .circle {
|
||||
background-color: var(--green400);
|
||||
border-color: var(--green400);
|
||||
}
|
||||
|
||||
&.current:before,
|
||||
&.active:before {
|
||||
background-color: var(--green400);
|
||||
}
|
||||
}
|
||||
|
||||
.circle {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
background-color: var(--white);
|
||||
border-radius: 50%;
|
||||
border: 1px solid var(--gray400);
|
||||
transition: var(--transition) transform, var(--transition) background, var(--transition) border;
|
||||
}
|
||||
|
||||
@@ -1,23 +1,34 @@
|
||||
import React, { FC } from 'react';
|
||||
import { Steps } from 'antd';
|
||||
import cn from 'classnames';
|
||||
|
||||
import s from './Stepper.module.pcss';
|
||||
|
||||
interface StepProps {
|
||||
active: boolean;
|
||||
current: boolean;
|
||||
}
|
||||
|
||||
const Step: FC<StepProps> = ({ active, current }) => {
|
||||
return (
|
||||
<div className={cn(s.wrap, { [s.active]: active, [s.current]: current })}>
|
||||
<div className={s.circle} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
interface StepperProps {
|
||||
currentStep: number;
|
||||
}
|
||||
|
||||
const { Step } = Steps;
|
||||
|
||||
const Stepper: FC<StepperProps> = ({ currentStep }) => {
|
||||
return (
|
||||
<Steps progressDot current={currentStep} className={s.stepper}>
|
||||
<Step/>
|
||||
<Step/>
|
||||
<Step/>
|
||||
<Step/>
|
||||
<Step/>
|
||||
</Steps>
|
||||
<div className={s.stepper}>
|
||||
<Step current={currentStep === 0} active={currentStep >= 0} />
|
||||
<Step current={currentStep === 1} active={currentStep >= 1} />
|
||||
<Step current={currentStep === 2} active={currentStep >= 2} />
|
||||
<Step current={currentStep === 3} active={currentStep >= 3} />
|
||||
<Step current={currentStep === 4} active={currentStep >= 4} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
.iconContainer{
|
||||
margin-bottom: 48px;
|
||||
}
|
||||
.icon {
|
||||
width: 185px;
|
||||
height: 57px;
|
||||
}
|
||||
.button {
|
||||
margin-top: 48px;
|
||||
width: 190px;
|
||||
|
||||
&.inGroup {
|
||||
margin-right: 24px;
|
||||
}
|
||||
}
|
||||
@@ -6,8 +6,6 @@ import Store from 'Store/installStore';
|
||||
import Icon from 'Common/ui/Icon';
|
||||
import theme from 'Lib/theme';
|
||||
|
||||
import s from './Welcome.module.pcss';
|
||||
|
||||
interface WelcomeProps {
|
||||
onNext: () => void;
|
||||
}
|
||||
@@ -15,25 +13,25 @@ interface WelcomeProps {
|
||||
const Welcome: FC<WelcomeProps> = observer(({ onNext }) => {
|
||||
const { ui: { intl } } = useContext(Store);
|
||||
return (
|
||||
<div className={s.content}>
|
||||
<div className={s.iconContainer}>
|
||||
<Icon icon="mainLogo" className={s.icon} />
|
||||
</div>
|
||||
<div className={theme.typography.title}>
|
||||
<>
|
||||
<Icon icon="logo" className={theme.install.logo} />
|
||||
<div className={theme.install.title}>
|
||||
{intl.getMessage('install_wellcome_title')}
|
||||
</div>
|
||||
<div className={theme.typography.text}>
|
||||
<div className={theme.install.text}>
|
||||
{intl.getMessage('install_wellcome_desc')}
|
||||
</div>
|
||||
<Button
|
||||
size="large"
|
||||
type="primary"
|
||||
className={s.button}
|
||||
onClick={onNext}
|
||||
>
|
||||
{intl.getMessage('install_wellcome_button')}
|
||||
</Button>
|
||||
</div>
|
||||
<div className={theme.install.actions}>
|
||||
<Button
|
||||
size="large"
|
||||
type="primary"
|
||||
className={theme.install.button}
|
||||
onClick={onNext}
|
||||
>
|
||||
{intl.getMessage('install_wellcome_button')}
|
||||
</Button>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@@ -13,4 +13,8 @@
|
||||
&:last-child {
|
||||
border-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.desc {
|
||||
color: var(--gray400);
|
||||
}
|
||||
|
||||
@@ -2,8 +2,6 @@ import React, { FC } from 'react';
|
||||
import { Radio } from 'antd';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
|
||||
import theme from 'Lib/theme';
|
||||
|
||||
import s from './Radio.module.pcss';
|
||||
|
||||
const { Group } = Radio;
|
||||
@@ -43,7 +41,7 @@ const RadioComponent: FC<AdminInterfaceProps> = observer(({
|
||||
{o.label}
|
||||
</div>
|
||||
{o.desc && (
|
||||
<div className={theme.typography.subtext}>
|
||||
<div className={s.desc}>
|
||||
{o.desc}
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -3,7 +3,7 @@ import theme from 'Lib/theme';
|
||||
|
||||
const danger = (e: string) => {
|
||||
return (
|
||||
<span className={theme.typography.danger}>
|
||||
<span className={theme.text.danger}>
|
||||
{e}
|
||||
</span>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user