Skip to content
Snippets Groups Projects
Commit 7d3ae26c authored by Ayc0's avatar Ayc0
Browse files

Refactor front using preact

parent cc95ab4b
No related branches found
No related tags found
No related merge requests found
{
"presets": ["es2015"],
"plugins": [["transform-react-jsx", { "pragma": "h" }]]
"presets": ["preact"],
"plugins": ["transform-class-properties"]
}
{
"parser": "babel-eslint",
"extends": "airbnb-base"
"extends": "airbnb",
"rules": {
"react/jsx-filename-extension": "off",
"react/prop-types": "off"
},
"settings": {
"react": {
"pragma": "h"
}
}
}
const toDash = string => string.replace(/([A-Z])/g, char => `-${char.toLowerCase()}`);
const cssStringify = (object) => {
const array = Object.keys(object).map((cssAttribute) => {
if (typeof object[cssAttribute] === 'object') {
return `${toDash(cssAttribute)} {${cssStringify(object[cssAttribute])}}`;
}
return `${toDash(cssAttribute)}: ${object[cssAttribute]};`;
});
return array.join('');
};
export default cssStringify;
const diffNodes = (parentNode, newNodes) => {
const previousChildNumber = parentNode.childElementCount;
const newChildNumber = newNodes.length;
const previousChildren = parentNode.childNodes;
for (let index = 0; index < Math.min(previousChildNumber, newChildNumber); index += 1) {
parentNode.replaceChild(newNodes[index], previousChildren[index]);
}
for (
let index = Math.min(previousChildNumber, newChildNumber);
index < previousChildNumber;
index += 1
) {
parentNode.removeChild(previousChildren[index]);
}
for (
let index = Math.min(previousChildNumber, newChildNumber);
index < newChildNumber;
index += 1
) {
parentNode.appendChild(newNodes[index]);
}
};
export default diffNodes;
import cssStringify from './cssStringify';
const concatTextParts = textParts =>
textParts.map((part) => {
const style = 'style' in part ? cssStringify(part.style) : '';
return (
<span className="text-element" style={style}>
{part.text}
</span>
);
});
const jsonTextToHtml = data => <div className="bloc text-bloc">{concatTextParts(data.text)}</div>;
const jsonImageToHtml = (data) => {
const style =
'heightFactor' in data ? `height: calc(${data.heightFactor} * var(--rowHeight))` : '';
return (
<div className="bloc image-bloc" style={style}>
<img src={data.image} />
</div>
);
};
const jsonImageTextToHtml = data => (
<div className="bloc image-text-bloc">
<img src={data.image} />
<div className="text-section">{concatTextParts(data.text)}</div>
</div>
);
export default (data) => {
const head = <div style="background-color:#F2F2FF; padding:10px" />;
data.rows
.map((row) => {
if (!row) {
return '';
}
switch (row.type) {
case 0:
return jsonTextToHtml(row);
case 1:
return jsonImageTextToHtml(row);
case 2:
return jsonImageToHtml(row);
default:
return '';
}
})
.forEach((row) => {
if (typeof row !== 'string') {
head.appendChild(row);
}
});
const foot = (
<div className="mini">
<p>
Last data: {new Date(Date.now()).toLocaleString()}; TTL: {data.ttl / 1000}s
</p>
<p>Hermod version {data.version}, 2018</p>
</div>
);
return [<hr className="mini" />, head, <hr style="color: #DDDDDD" />, foot];
};
import h from 'hyperscript';
Object.defineProperty(window, 'h', {
value: h,
writable: false,
configurable: false,
});
import { h, Component } from 'preact';
import Row from './Row';
import socketIO from './socket';
class App extends Component {
state = { data: { rows: [], version: null } };
componentDidMount = () => {
socketIO.on('panel_data', this.onReceiveMessage);
};
componentWillUnmount = () => {
socketIO.removeListener('panel_data', this.onReceiveMessage);
};
onReceiveMessage = (data) => {
this.setState({ data });
setTimeout(() => {
socketIO.emit('panel_data');
}, data.ttl);
};
render() {
return (
<div>
<hr className="mini" />
{this.state.data.rows.map(row => <Row row={row} />)}
<hr style={{ color: '#DDDDDD' }} />
<div className="mini">
<p>
Last data: {new Date(Date.now()).toLocaleString()}; TTL: {this.state.data.ttl / 1000}s
</p>
<p>Hermod version {this.state.data.version}, 2018</p>
</div>
</div>
);
}
}
export default App;
import { h } from 'preact';
const TextElement = ({ element: { style, text } }) => (
<span className="text-element" style={style}>
{text}
</span>
);
const PureTextRow = ({ row }) => (
<div className="bloc text-bloc">{row.text.map(element => <TextElement element={element} />)}</div>
);
const PureImageRow = ({ row }) => {
const style =
'heightFactor' in row ? { height: `calc(${row.heightFactor} * var(--rowHeight))` } : {};
return (
<div className="bloc image-bloc" style={style}>
<img src={row.image} alt="" />
</div>
);
};
const TextAndImageRow = ({ row }) => (
<div className="bloc image-text-bloc">
<img src={row.image} alt="" />
<div className="text-section">{row.text.map(element => <TextElement element={element} />)}</div>
</div>
);
const Row = ({ row }) => {
let SubRow;
switch (row.type) {
case 0:
SubRow = PureTextRow;
break;
case 1:
SubRow = TextAndImageRow;
break;
case 2:
SubRow = PureImageRow;
break;
default:
SubRow = null;
break;
}
return (
<div style={{ backgroundColor: '#F2F2FF', padding: '10px' }}>
<SubRow row={row} />
</div>
);
};
export default Row;
File moved
......@@ -18,8 +18,7 @@
<style type="text/css" id="root"></style>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.4/socket.io.slim.js"></script>
<script type="text/javascript" src="./setup.js" defer></script>
<script type="text/javascript" src="./socket.js" defer></script>
<script type="text/javascript" src="./index.js" defer></script>
</body>
</html>
\ No newline at end of file
import jsonToHtmlArray from './display';
import diffNodes from './diffNodes';
import { port, host } from './config';
import { h, render } from 'preact';
const socketIO = io.connect(`http://${host || 'localhost'}:${port || 3000}/`);
import App from './App';
import socketIO from './socket';
socketIO.on('connect', () => {
socketIO.emit('date');
setInterval(() => {
socketIO.emit('date');
}, 1000);
socketIO.emit('panel_data');
});
const container = document.getElementById('panel_data');
const existingNode = container.querySelector('*');
render(<App />, container, existingNode);
socketIO.on('config', (data) => {
document.getElementById('root').innerHTML = `html
......@@ -24,17 +18,3 @@ socketIO.on('config', (data) => {
socketIO.on('date', (data) => {
document.getElementById('date').innerHTML = new Date(data.date).toLocaleString();
});
socketIO.on('panel_data', (data) => {
// console.log(data);
// data.ttl = 500000;
setTimeout(() => {
socketIO.emit('panel_data');
}, data.ttl);
const panelData = document.getElementById('panel_data');
diffNodes(panelData, jsonToHtmlArray(data));
});
// socketIO.on('message', (data) => {
// console.log(data);
// });
import { port, host } from './config';
const socketIO = io.connect(`http://${host || 'localhost'}:${port || 3000}/`);
socketIO.on('connect', () => {
socketIO.emit('date');
setInterval(() => {
socketIO.emit('date');
}, 1000);
socketIO.emit('panel_data');
});
export default socketIO;
......@@ -29,7 +29,7 @@
}
.image-bloc img {
height: 100px;
height: 100%;
margin-left: auto;
margin-right: auto;
}
......
......@@ -9,27 +9,30 @@
"start": "yarn start:dev",
"start:dev": "nodemon ./server/index.js",
"start:prod": "node ./server/index.js",
"start:front": "parcel serve ./front/ -d build",
"start:front": "parcel serve ./front/src/ -d build",
"build:front":
"rm -f build/* && parcel build ./front/ -d build --public-url / --no-cache && mv build/*.html build/index.html",
"rm -f ./front/build/* && parcel build ./front/src/index.html -d ./front/build --public-url / --no-cache",
"sslGenKey": "openssl genrsa 2048 > key.pem",
"sslGenCert": "openssl req -x509 -days 1000 -new -key key.pem -out cert.pem",
"sslGen": "npm run sslGenKey && npm run sslGenCert"
},
"dependencies": {
"hyperscript": "^2.0.2",
"css-in-js-stringify": "^1.0.0",
"jsonwebtoken": "^8.1.1",
"node-fetch": "^2.0.0",
"parcel-bundler": "^1.5.1",
"preact": "^8.2.7",
"socket.io": "^2.0.4"
},
"devDependencies": {
"babel-eslint": "^8.2.1",
"babel-plugin-transform-react-jsx": "^6.24.1",
"babel-preset-es2015": "^6.24.1",
"babel-plugin-transform-class-properties": "^6.24.1",
"babel-preset-preact": "^1.1.0",
"eslint": "^4.17.0",
"eslint-config-airbnb-base": "^12.1.0",
"eslint-config-airbnb": "^16.1.0",
"eslint-plugin-import": "^2.8.0",
"eslint-plugin-jsx-a11y": "^6.0.3",
"eslint-plugin-react": "^7.4.0",
"nodemon": "^1.14.12"
}
}
This diff is collapsed.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment