Created settings page and converted MainHeader into functional component

This commit is contained in:
Alejandro Celaya 2020-04-18 20:31:20 +02:00
parent aa59a95f91
commit 7516ca8dd9
8 changed files with 59 additions and 41 deletions

View file

@ -1,7 +1,8 @@
import React from 'react';
import { Route, Switch } from 'react-router-dom';
import './App.scss';
import NotFound from './common/NotFound';
import Settings from './settings/Settings';
import './App.scss';
const App = (MainHeader, Home, MenuLayout, CreateServer, EditServer) => () => (
<div className="container-fluid app-container">
@ -12,6 +13,7 @@ const App = (MainHeader, Home, MenuLayout, CreateServer, EditServer) => () => (
<Route exact path="/" component={Home} />
<Route exact path="/server/create" component={CreateServer} />
<Route exact path="/server/:serverId/edit" component={EditServer} />
<Route exact path="/settings" component={Settings} />
<Route path="/server/:serverId" component={MenuLayout} />
<Route component={NotFound} />
</Switch>

View file

@ -1,37 +1,28 @@
import { faPlus as plusIcon, faChevronDown as arrowIcon } from '@fortawesome/free-solid-svg-icons';
import { faPlus as plusIcon, faChevronDown as arrowIcon, faCogs as cogsIcon } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import React from 'react';
import React, { useEffect } from 'react';
import { Link } from 'react-router-dom';
import { Collapse, Nav, Navbar, NavbarBrand, NavbarToggler, NavItem, NavLink } from 'reactstrap';
import classnames from 'classnames';
import classNames from 'classnames';
import PropTypes from 'prop-types';
import { useToggle } from '../utils/helpers/hooks';
import shlinkLogo from './shlink-logo-white.png';
import './MainHeader.scss';
const MainHeader = (ServersDropdown) => class MainHeader extends React.Component {
static propTypes = {
location: PropTypes.object,
};
const propTypes = {
location: PropTypes.object,
};
state = { isOpen: false };
handleToggle = () => {
this.setState(({ isOpen }) => ({
isOpen: !isOpen,
}));
};
const MainHeader = (ServersDropdown) => {
const MainHeaderComp = ({ location }) => {
const [ isOpen, toggleOpen, , close ] = useToggle();
const { pathname } = location;
componentDidUpdate(prevProps) {
if (this.props.location !== prevProps.location) {
this.setState({ isOpen: false });
}
}
useEffect(close, [ location ]);
render() {
const { location } = this.props;
const createServerPath = '/server/create';
const toggleClass = classnames('main-header__toggle-icon', {
'main-header__toggle-icon--opened': this.state.isOpen,
});
const settingsPath = '/settings';
const toggleClass = classNames('main-header__toggle-icon', { 'main-header__toggle-icon--opened': isOpen });
return (
<Navbar color="primary" dark fixed="top" className="main-header" expand="md">
@ -39,18 +30,19 @@ const MainHeader = (ServersDropdown) => class MainHeader extends React.Component
<img src={shlinkLogo} alt="Shlink" className="main-header__brand-logo" /> Shlink
</NavbarBrand>
<NavbarToggler onClick={this.handleToggle}>
<NavbarToggler onClick={toggleOpen}>
<FontAwesomeIcon icon={arrowIcon} className={toggleClass} />
</NavbarToggler>
<Collapse navbar isOpen={this.state.isOpen}>
<Collapse navbar isOpen={isOpen}>
<Nav navbar className="ml-auto">
<NavItem>
<NavLink
tag={Link}
to={createServerPath}
active={location.pathname === createServerPath}
>
<NavLink tag={Link} to={settingsPath} active={pathname === settingsPath}>
<FontAwesomeIcon icon={cogsIcon} />&nbsp; Settings
</NavLink>
</NavItem>
<NavItem>
<NavLink tag={Link} to={createServerPath} active={pathname === createServerPath}>
<FontAwesomeIcon icon={plusIcon} />&nbsp; Add server
</NavLink>
</NavItem>
@ -59,7 +51,11 @@ const MainHeader = (ServersDropdown) => class MainHeader extends React.Component
</Collapse>
</Navbar>
);
}
};
MainHeaderComp.propTypes = propTypes;
return MainHeaderComp;
};
export default MainHeader;

View file

@ -0,0 +1,13 @@
import React from 'react';
import PropTypes from 'prop-types';
import './NoMenuLayout.scss';
const propTypes = {
children: PropTypes.node,
};
const NoMenuLayout = ({ children }) => <div className="no-menu-wrapper">{children}</div>;
NoMenuLayout.propTypes = propTypes;
export default NoMenuLayout;

View file

@ -0,0 +1,3 @@
.no-menu-wrapper {
padding: 40px 20px;
}

View file

@ -1,8 +1,9 @@
import React, { useEffect } from 'react';
import { v4 as uuid } from 'uuid';
import PropTypes from 'prop-types';
import './CreateServer.scss';
import NoMenuLayout from '../common/NoMenuLayout';
import { ServerForm } from './helpers/ServerForm';
import './CreateServer.scss';
const SHOW_IMPORT_MSG_TIME = 4000;
const propTypes = {
@ -29,7 +30,7 @@ const CreateServer = (ImportServersBtn, useStateFlagTimeout) => {
}, []);
return (
<div className="create-server">
<NoMenuLayout>
<ServerForm onSubmit={handleSubmit}>
<ImportServersBtn onImport={setServersImported} />
<button className="btn btn-outline-primary">Create server</button>
@ -44,7 +45,7 @@ const CreateServer = (ImportServersBtn, useStateFlagTimeout) => {
</div>
</div>
)}
</div>
</NoMenuLayout>
);
};

View file

@ -1,9 +1,5 @@
@import '../utils/base';
.create-server {
padding: 40px 20px;
}
.create-server__label {
font-weight: 700;
cursor: pointer;

View file

@ -1,5 +1,6 @@
import React from 'react';
import PropTypes from 'prop-types';
import NoMenuLayout from '../common/NoMenuLayout';
import { ServerForm } from './helpers/ServerForm';
import { withSelectedServer } from './helpers/withSelectedServer';
import { serverType } from './prop-types';
@ -20,11 +21,11 @@ export const EditServer = (ServerError) => {
};
return (
<div className="create-server">
<NoMenuLayout>
<ServerForm initialValues={selectedServer} onSubmit={handleSubmit}>
<button className="btn btn-outline-primary">Save</button>
</ServerForm>
</div>
</NoMenuLayout>
);
};

6
src/settings/Settings.js Normal file
View file

@ -0,0 +1,6 @@
import React from 'react';
import NoMenuLayout from '../common/NoMenuLayout';
const Settings = () => <NoMenuLayout>Settings</NoMenuLayout>;
export default Settings;