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 React from 'react';
import { Route, Switch } from 'react-router-dom'; import { Route, Switch } from 'react-router-dom';
import './App.scss';
import NotFound from './common/NotFound'; import NotFound from './common/NotFound';
import Settings from './settings/Settings';
import './App.scss';
const App = (MainHeader, Home, MenuLayout, CreateServer, EditServer) => () => ( const App = (MainHeader, Home, MenuLayout, CreateServer, EditServer) => () => (
<div className="container-fluid app-container"> <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="/" component={Home} />
<Route exact path="/server/create" component={CreateServer} /> <Route exact path="/server/create" component={CreateServer} />
<Route exact path="/server/:serverId/edit" component={EditServer} /> <Route exact path="/server/:serverId/edit" component={EditServer} />
<Route exact path="/settings" component={Settings} />
<Route path="/server/:serverId" component={MenuLayout} /> <Route path="/server/:serverId" component={MenuLayout} />
<Route component={NotFound} /> <Route component={NotFound} />
</Switch> </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 { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import React from 'react'; import React, { useEffect } from 'react';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { Collapse, Nav, Navbar, NavbarBrand, NavbarToggler, NavItem, NavLink } from 'reactstrap'; import { Collapse, Nav, Navbar, NavbarBrand, NavbarToggler, NavItem, NavLink } from 'reactstrap';
import classnames from 'classnames'; import classNames from 'classnames';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { useToggle } from '../utils/helpers/hooks';
import shlinkLogo from './shlink-logo-white.png'; import shlinkLogo from './shlink-logo-white.png';
import './MainHeader.scss'; import './MainHeader.scss';
const MainHeader = (ServersDropdown) => class MainHeader extends React.Component { const propTypes = {
static propTypes = { location: PropTypes.object,
location: PropTypes.object, };
};
state = { isOpen: false }; const MainHeader = (ServersDropdown) => {
handleToggle = () => { const MainHeaderComp = ({ location }) => {
this.setState(({ isOpen }) => ({ const [ isOpen, toggleOpen, , close ] = useToggle();
isOpen: !isOpen, const { pathname } = location;
}));
};
componentDidUpdate(prevProps) { useEffect(close, [ location ]);
if (this.props.location !== prevProps.location) {
this.setState({ isOpen: false });
}
}
render() {
const { location } = this.props;
const createServerPath = '/server/create'; const createServerPath = '/server/create';
const toggleClass = classnames('main-header__toggle-icon', { const settingsPath = '/settings';
'main-header__toggle-icon--opened': this.state.isOpen, const toggleClass = classNames('main-header__toggle-icon', { 'main-header__toggle-icon--opened': isOpen });
});
return ( return (
<Navbar color="primary" dark fixed="top" className="main-header" expand="md"> <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 <img src={shlinkLogo} alt="Shlink" className="main-header__brand-logo" /> Shlink
</NavbarBrand> </NavbarBrand>
<NavbarToggler onClick={this.handleToggle}> <NavbarToggler onClick={toggleOpen}>
<FontAwesomeIcon icon={arrowIcon} className={toggleClass} /> <FontAwesomeIcon icon={arrowIcon} className={toggleClass} />
</NavbarToggler> </NavbarToggler>
<Collapse navbar isOpen={this.state.isOpen}> <Collapse navbar isOpen={isOpen}>
<Nav navbar className="ml-auto"> <Nav navbar className="ml-auto">
<NavItem> <NavItem>
<NavLink <NavLink tag={Link} to={settingsPath} active={pathname === settingsPath}>
tag={Link} <FontAwesomeIcon icon={cogsIcon} />&nbsp; Settings
to={createServerPath} </NavLink>
active={location.pathname === createServerPath} </NavItem>
> <NavItem>
<NavLink tag={Link} to={createServerPath} active={pathname === createServerPath}>
<FontAwesomeIcon icon={plusIcon} />&nbsp; Add server <FontAwesomeIcon icon={plusIcon} />&nbsp; Add server
</NavLink> </NavLink>
</NavItem> </NavItem>
@ -59,7 +51,11 @@ const MainHeader = (ServersDropdown) => class MainHeader extends React.Component
</Collapse> </Collapse>
</Navbar> </Navbar>
); );
} };
MainHeaderComp.propTypes = propTypes;
return MainHeaderComp;
}; };
export default MainHeader; 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 React, { useEffect } from 'react';
import { v4 as uuid } from 'uuid'; import { v4 as uuid } from 'uuid';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import './CreateServer.scss'; import NoMenuLayout from '../common/NoMenuLayout';
import { ServerForm } from './helpers/ServerForm'; import { ServerForm } from './helpers/ServerForm';
import './CreateServer.scss';
const SHOW_IMPORT_MSG_TIME = 4000; const SHOW_IMPORT_MSG_TIME = 4000;
const propTypes = { const propTypes = {
@ -29,7 +30,7 @@ const CreateServer = (ImportServersBtn, useStateFlagTimeout) => {
}, []); }, []);
return ( return (
<div className="create-server"> <NoMenuLayout>
<ServerForm onSubmit={handleSubmit}> <ServerForm onSubmit={handleSubmit}>
<ImportServersBtn onImport={setServersImported} /> <ImportServersBtn onImport={setServersImported} />
<button className="btn btn-outline-primary">Create server</button> <button className="btn btn-outline-primary">Create server</button>
@ -44,7 +45,7 @@ const CreateServer = (ImportServersBtn, useStateFlagTimeout) => {
</div> </div>
</div> </div>
)} )}
</div> </NoMenuLayout>
); );
}; };

View file

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

View file

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