Skip to content
This repository has been archived by the owner on Apr 6, 2022. It is now read-only.

Commit

Permalink
#1 Refactor communication with menu.
Browse files Browse the repository at this point in the history
That is inspired a bit by MDC. Aim is that menu and application now
more separated adn communicate now through a adapter.

Also:
* Preparation for router
* Optimize SW pre cache plugin
* Add webp for icons.
  • Loading branch information
enbock committed Oct 13, 2017
1 parent ff6f3f8 commit 4e10c55
Show file tree
Hide file tree
Showing 16 changed files with 229 additions and 52 deletions.
3 changes: 3 additions & 0 deletions .idea/dictionaries/User.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions config/webpack.config.prod.js
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,13 @@ module.exports = {
// Ignores URLs starting from /__ (useful for Firebase):
// https://github.com/facebookincubator/create-react-app/issues/2237#issuecomment-302693219
navigateFallbackWhitelist: [/^(?!\/__).*/],
staticFileGlobs: [
'public/css/**.*',
'public/lib/**.*',
'public/Template/**.*',
],
stripPrefix: 'src/static/', // stripPrefixMulti is also supported
mergeStaticsConfig: true, // if you don't set this to true, you won't see any webpack-emitted assets in your serviceworker config
// Don't precache sourcemaps (they're large) and build asset manifest:
staticFileGlobsIgnorePatterns: [/\.map$/, /asset-manifest\.json$/],
}),
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"eslint-plugin-jsx-a11y": "5.1.1",
"eslint-plugin-react": "7.1.0",
"extract-text-webpack-plugin": "3.0.0",
"fbjs": "^0.8.16",
"file-loader": "0.11.2",
"fs-extra": "3.0.1",
"gh-pages": "^1.0.0",
Expand Down
13 changes: 9 additions & 4 deletions public/Template/Application.html.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,25 @@
<section class="mdc-toolbar__section mdc-toolbar__section--align-start">
<a
class="material-icons mdc-toolbar__icon--menu"
onClick={this.onMenuButtonClick.bind(this)}
onClick={this.onMainButtonClick.bind(this)}
>menu</a>
<span class="mdc-toolbar__title catalog-title">Time Tracker</span>
</section>
</div>
</header>
<this.components.MainMenu
class="mdc-temporary-drawer"
open={this.state.menuOpen}
onClose={this.onMenuClose.bind(this)}
adapter={this.menuAdapter}
page={this.state.history.page}
onMenu={this.onMenuChange.bind(this)}
/>

<main>
<h1 class="mdc-typography--display1">Hello World!</h1>
<br />
<div style={{textAlign:"right"}}>
Page: {this.state.history.page}<br />
Component: {this.state.currentComponent}
</div>
</main>
</div>
</div>
12 changes: 6 additions & 6 deletions public/Template/Menu/Main.html.tpl
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
<MDC.Drawer class="mdc-temporary-drawer" open={this.props.open} onClose={this.onClose.bind(this)}>
<MDC.Drawer class="mdc-temporary-drawer" open={this.state.open} onClose={this.closeMenu.bind(this)}>
<aside class={this.props.className}>
<nav class={this.props.className + "__drawer"}>
<div class={this.props.className + "__toolbar-spacer"}></div>
<div class="mdc-list-group">
<nav class="mdc-list">
<a class={this.props.className + "--selected mdc-list-item"}>
<i class="material-icons mdc-list-item__start-detail" aria-hidden="true">inbox</i>Inbox
</a>
<a class="mdc-list-item">
<i class="material-icons mdc-list-item__start-detail" aria-hidden="true">star</i>Star
<a
ref="settingsMenu"
class={(this.props.page == 'settings' ? this.props.className + "--selected mdc-list--theme-dark" : "") + " mdc-list-item"}
>
<i class="material-icons mdc-list-item__start-detail" aria-hidden="true">settings applications</i> Anwendungseinstellungen
</a>
</nav>
</div>
Expand Down
Binary file added public/favicon-196x196.webp
Binary file not shown.
Binary file added public/favicon-512x512.webp
Binary file not shown.
10 changes: 5 additions & 5 deletions public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,33 +16,33 @@
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
<link rel="stylesheet" href="%PUBLIC_URL%/css/material-components-web.min.css">
<script src="%PUBLIC_URL%/lib/babel.min.js"></script>
<script src="%PUBLIC_URL%/lib/material-components-web.min.js"></script>
<!--script src="%PUBLIC_URL%/lib/material-components-web.min.js"></script-->
<style>
html {
height: 100%;
}
body {
padding: 0;
margin: 0;
height: 100%;
height: 100vh;
}
.height100p {
height: 100%;
height: 100vh;
}
.page-wrapper {
display: flex;
flex-direction: row;
padding: 0;
margin: 0;
box-sizing: border-box;
height: 100%;
height: 100vh;
width: 100%;
}
.content {
display: inline-flex;
flex-direction: column;
flex-grow: 1;
height: 100%;
height: 100vh;
box-sizing: border-box;
}

Expand Down
4 changes: 2 additions & 2 deletions public/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
"name": "Codefrog Time Tracker",
"icons": [
{
"src": "favicon-196x196.png",
"src": "favicon-196x196.webp",
"sizes": "196x196",
"type": "image/png"
"type": "image/webp"
},
{
"src": "favicon-512x512.png",
Expand Down
58 changes: 52 additions & 6 deletions src/Application/Application.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import React from 'react';
import Component from '../Shared/LiveJSX';
import Menu from '../Menu';
import Router from './Router';

/**
* Root Application.
Expand Down Expand Up @@ -31,23 +33,67 @@ class Application extends Component {
this.state = Object.assign(
this.state,
{
menuOpen: false
currentComponent: <div/>,
history: {
page: 'none'
}
}
);

this.menuAdapter = {
registerMenuToggleHandler: this.registerMenuToggleHandler.bind(this),
deregisterMenuToggleHandler: this.deregisterMenuToggleHandler.bind(this)
};

this.registeredButtonHandler = [];
}

onMainButtonClick() {
this.registeredButtonHandler.forEach(handler => handler());
}

/**
* Set state to menu is closed.
*/
onMenuClose() {
this.setState({menuOpen: false});
onMenuChange(menu) {
// TODO: router stuff here?
this.setState({history: {page: menu}});
}

/**
* Toggle open state.
* Register handle for the main button click.
*
* @param {[[Function]]} handler
*/
onMenuButtonClick() {
this.setState({menuOpen: !this.state.menuOpen});
registerMenuToggleHandler(handler) {
this.registeredButtonHandler.push(handler);
}

/**
* Remove handler for main button click.
*
* @param {[[Function]]} handler
*/
deregisterMenuToggleHandler(handler) {
const index = this.registeredButtonHandler.indexOf(handler);
if (index === -1) {
return;
}
this.registeredButtonHandler.splice(index, 1);
}

/**
* Adding singleton components to application.
*
* @returns {XML}
*/
render() {
return (
<div>
<Router/>
{super.render()}
</div>
);
}
}

Expand Down
16 changes: 12 additions & 4 deletions src/Application/Application.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ describe('Application', function testApplication() {
Babel.transform.mockClear();
});


/**
* Test if correct layout loaded.
*/
Expand Down Expand Up @@ -45,15 +44,24 @@ describe('Application', function testApplication() {
);
Babel.transform.mockReturnValue(
{
code: 'React.createElement(\'button\', { onClick: this.onMenuButtonClick.bind(this) })'
code: 'React.createElement(\'button\', { onClick: this.onMainButtonClick.bind(this) })'
}
);

const wrapper = shallow(<Application/>);
const wrapper = shallow(<Application/>);
const instance = wrapper.instance();
const buttonClick = jest.fn();

instance.menuAdapter.registerMenuToggleHandler(buttonClick);
bound({data: 'TEMPLATE'});
wrapper.update();

wrapper.find('button').simulate('click');
wrapper.instance().onMenuClose();
expect(buttonClick).toHaveBeenCalled();
expect(success).toBe(true);

instance.onMenuChange('newMenu');
instance.menuAdapter.deregisterMenuToggleHandler(buttonClick);
instance.menuAdapter.deregisterMenuToggleHandler(buttonClick); // check that double remove don't break
});
});
13 changes: 13 additions & 0 deletions src/Application/Router/Router.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import React from 'react';

/**
* The History API connection.
*/
class Router extends React.Component
{
render() {
return null;
}
}

export default Router;
6 changes: 6 additions & 0 deletions src/Application/Router/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import Router from './Router';

export default Object.assign(
Router,
{}
);
93 changes: 79 additions & 14 deletions src/Menu/Main/Main.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import Component from '../../Shared/LiveJSX';
import PropTypes from 'prop-types';
import emptyFunction from 'fbjs/lib/emptyFunction';

/**
* The Main menu.
Expand All @@ -23,30 +24,94 @@ class MainMenu extends Component
static get propTypes() {
return {
className: PropTypes.string.isRequired,
onOpen: PropTypes.func,
onClose: PropTypes.func,
open: PropTypes.bool
adapter: PropTypes.object,
onMenu: PropTypes.func
};
}

/**
* Proxy open event, if bound.
* @param event
* Default adapter to interact with outer world.
*
* @returns {Object}
*/
onOpen(event) {
if (this.props.onOpen) {
this.props.onOpen(event);
}
static get defaultAdapter() {
return {
registerMenuToggleHandler: emptyFunction,
deregisterMenuToggleHandler: emptyFunction
};
}

/**
* Constructor.
*
* @param {Object} props
* @param {Object} context
* @param {Object} updater
*/
constructor(props, context, updater) {
super(props, context, updater);

Object.assign(
this.state,
{
open: false
}
);

/**
* @type {MainMenu.defaultAdapter}
*/
this.adapter = Object.assign(
MainMenu.defaultAdapter,
props.adapter
);

this.boundToggleMenu = this.toggleMenu.bind(this);
this.boundMenuSettingsClick = this.onMenuClick.bind(this, 'settings');
}

/**
* Menu state toggle.
*/
toggleMenu() {
this.setState({open: !this.state.open});
}

/**
* Proxy close event, if bound.
* @param event
* Close menu.
*/
onClose(event) {
if (this.props.onClose) {
this.props.onClose(event);
closeMenu() {
this.setState({open: false});
}

/**
* Menu click proxy.
*
* @param {string} menu
*/
onMenuClick(menu) {
if (this.props.onMenu) {
this.props.onMenu(menu);
}
this.closeMenu();
}

/**
* Connect low level events and adapter interactions.
*
* *Notice:* MDC Drawer caches the event, so take them from low level.
*/
onTemplateMounted(domNode) {
this.refs.settingsMenu.addEventListener('click', this.boundMenuSettingsClick);
this.adapter.registerMenuToggleHandler(this.boundToggleMenu);
}

/**
* Release interaction connections.
*/
componentWillUnmount() {
this.refs.settingsMenu.removeEventListener('click', this.boundMenuSettingsClick);
this.adapter.deregisterMenuToggleHandler(this.boundToggleMenu);
}
}

Expand Down
Loading

0 comments on commit 4e10c55

Please sign in to comment.