mirror of
https://github.com/0x1d/esp8266-laser.git
synced 2025-12-14 18:15:22 +01:00
ui
This commit is contained in:
@@ -103,6 +103,9 @@ Frontend development requires NodeJS / npm.
|
|||||||
The development server watches all files in the frontend directory and automatically builds and copies the frontend code to the data folder.
|
The development server watches all files in the frontend directory and automatically builds and copies the frontend code to the data folder.
|
||||||
|
|
||||||
```
|
```
|
||||||
|
### install dependencies
|
||||||
|
npm install
|
||||||
|
|
||||||
### run development server on port 8080
|
### run development server on port 8080
|
||||||
npm run dev
|
npm run dev
|
||||||
|
|
||||||
|
|||||||
113
data/index.html
113
data/index.html
@@ -7,92 +7,9 @@
|
|||||||
<link rel="stylesheet" type="text/css" href="styles.css">
|
<link rel="stylesheet" type="text/css" href="styles.css">
|
||||||
<script src="scripts.js"></script>
|
<script src="scripts.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body id="index" style="margin:0; padding:0;">
|
<body>
|
||||||
<div id="Main">
|
<div class="content">
|
||||||
<div id="pageTitle">
|
<div id="prototypControls" class="spiro-control container">
|
||||||
<!-- SVG Glitch from: http://codepen.io/DirkWeber/pen/ArFvk -->
|
|
||||||
<svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="580px" height="45px" viewBox="0 0 580 45">
|
|
||||||
<defs>
|
|
||||||
<filter id="filter">
|
|
||||||
<feFlood flood-color="#66bebe" result="black" />
|
|
||||||
<feFlood flood-color="#206060" result="flood1" />
|
|
||||||
<feFlood flood-color="#369e9e" result="flood2" />
|
|
||||||
<feOffset in="SourceGraphic" dx="3" dy="0" result="off1a"/>
|
|
||||||
<feOffset in="SourceGraphic" dx="2" dy="0" result="off1b"/>
|
|
||||||
<feOffset in="SourceGraphic" dx="-4" dy="0" result="off2a"/>
|
|
||||||
<feOffset in="SourceGraphic" dx="-2" dy="0" result="off2b"/>
|
|
||||||
<feComposite in="flood1" in2="off1a" operator="in" result="comp1" />
|
|
||||||
<feComposite in="flood2" in2="off2a" operator="in" result="comp2" />
|
|
||||||
|
|
||||||
<feMerge x="0" width="100%" result="merge1">
|
|
||||||
<feMergeNode in = "black" />
|
|
||||||
<feMergeNode in = "comp1" />
|
|
||||||
<feMergeNode in = "off1b" />
|
|
||||||
|
|
||||||
<animate
|
|
||||||
attributeName="y"
|
|
||||||
id = "y"
|
|
||||||
dur ="4s"
|
|
||||||
|
|
||||||
values = '104px; 104px; 30px; 105px; 30px; 2px; 2px; 50px; 40px; 105px; 105px; 20px; 6ßpx; 40px; 104px; 40px; 70px; 10px; 30px; 104px; 102px'
|
|
||||||
|
|
||||||
keyTimes = '0; 0.362; 0.368; 0.421; 0.440; 0.477; 0.518; 0.564; 0.593; 0.613; 0.644; 0.693; 0.721; 0.736; 0.772; 0.818; 0.844; 0.894; 0.925; 0.939; 1'
|
|
||||||
|
|
||||||
repeatCount = "indefinite" />
|
|
||||||
|
|
||||||
<animate attributeName="height"
|
|
||||||
id = "h"
|
|
||||||
dur ="4s"
|
|
||||||
|
|
||||||
values = '10px; 0px; 10px; 30px; 50px; 0px; 10px; 0px; 0px; 0px; 10px; 50px; 40px; 0px; 0px; 0px; 40px; 30px; 10px; 0px; 50px'
|
|
||||||
|
|
||||||
keyTimes = '0; 0.362; 0.368; 0.421; 0.440; 0.477; 0.518; 0.564; 0.593; 0.613; 0.644; 0.693; 0.721; 0.736; 0.772; 0.818; 0.844; 0.894; 0.925; 0.939; 1'
|
|
||||||
|
|
||||||
repeatCount = "indefinite" />
|
|
||||||
</feMerge>
|
|
||||||
|
|
||||||
|
|
||||||
<feMerge x="0" width="100%" y="60px" height="65px" result="merge2">
|
|
||||||
<feMergeNode in = "black" />
|
|
||||||
<feMergeNode in = "comp2" />
|
|
||||||
<feMergeNode in = "off2b" />
|
|
||||||
|
|
||||||
<animate attributeName="y"
|
|
||||||
id = "y"
|
|
||||||
dur ="4s"
|
|
||||||
values = '103px; 104px; 69px; 53px; 42px; 104px; 78px; 89px; 96px; 100px; 67px; 50px; 96px; 66px; 88px; 42px; 13px; 100px; 100px; 104px;'
|
|
||||||
|
|
||||||
keyTimes = '0; 0.055; 0.100; 0.125; 0.159; 0.182; 0.202; 0.236; 0.268; 0.326; 0.357; 0.400; 0.408; 0.461; 0.493; 0.513; 0.548; 0.577; 0.613; 1'
|
|
||||||
|
|
||||||
repeatCount = "indefinite" />
|
|
||||||
|
|
||||||
<animate attributeName="height"
|
|
||||||
id = "h"
|
|
||||||
dur = "4s"
|
|
||||||
|
|
||||||
values = '0px; 0px; 0px; 16px; 16px; 12px; 12px; 0px; 0px; 5px; 10px; 22px; 33px; 11px; 0px; 0px; 10px'
|
|
||||||
|
|
||||||
keyTimes = '0; 0.055; 0.100; 0.125; 0.159; 0.182; 0.202; 0.236; 0.268; 0.326; 0.357; 0.400; 0.408; 0.461; 0.493; 0.513; 1'
|
|
||||||
|
|
||||||
repeatCount = "indefinite" />
|
|
||||||
</feMerge>
|
|
||||||
|
|
||||||
<feMerge>
|
|
||||||
<feMergeNode in="SourceGraphic" />
|
|
||||||
|
|
||||||
<feMergeNode in="merge1" />
|
|
||||||
<feMergeNode in="merge2" />
|
|
||||||
|
|
||||||
</feMerge>
|
|
||||||
</filter>
|
|
||||||
</defs>
|
|
||||||
<g>
|
|
||||||
<text id="titleGlitch" style="filter: url(#filter);" x="0" y="35">Laserspiro controller</text>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="prototypControls">
|
|
||||||
<label>L</label>
|
<label>L</label>
|
||||||
<input type="range" class="laser slider" value="1" min="1" max="128">
|
<input type="range" class="laser slider" value="1" min="1" max="128">
|
||||||
<label>M1</label>
|
<label>M1</label>
|
||||||
@@ -111,6 +28,30 @@
|
|||||||
</div>
|
</div>
|
||||||
<br>
|
<br>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="settings container">
|
||||||
|
<span class="heading">Wifi Settings</span>
|
||||||
|
<form>
|
||||||
|
<ul class="flex-outer">
|
||||||
|
<li>
|
||||||
|
<label for="first-name">SSID</label>
|
||||||
|
<input type="text" id="first-name" placeholder="service station id">
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<label for="last-name">Password</label>
|
||||||
|
<input type="text" id="last-name" placeholder="station password">
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<p>Age</p>
|
||||||
|
<ul class="flex-inner">
|
||||||
|
<!-- list items here -->
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<button type="submit">Submit</button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
149
data/styles.css
149
data/styles.css
@@ -1,108 +1,53 @@
|
|||||||
label {
|
body {
|
||||||
|
background: #000000;
|
||||||
|
color: #0eb8c0;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
body ul {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
body ul li {
|
||||||
|
margin: 0 0 16px 0;
|
||||||
|
}
|
||||||
|
body p {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
body .content {
|
||||||
|
padding: 32px;
|
||||||
|
}
|
||||||
|
body .content .heading {
|
||||||
|
font-size: 1.2em;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
body .content .container {
|
||||||
|
background: #333333;
|
||||||
|
padding: 16px;
|
||||||
|
}
|
||||||
|
body .content input {
|
||||||
|
height: 24px;
|
||||||
|
}
|
||||||
|
.settings .flex-outer li,
|
||||||
|
.settings .flex-inner {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
.settings .flex-outer > li > label,
|
||||||
|
.settings .flex-outer li p {
|
||||||
|
flex: 1 0;
|
||||||
|
}
|
||||||
|
.settings .flex-outer > li > label + *,
|
||||||
|
.settings .flex-inner {
|
||||||
|
flex: 1 0;
|
||||||
|
}
|
||||||
|
.spiro-control label {
|
||||||
width: 10%;
|
width: 10%;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
.slider {
|
.spiro-control input[type="range"] {
|
||||||
width: 80%;
|
width: 80%;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
body {
|
|
||||||
font-size: 14px;
|
|
||||||
font-family: "Bookman Old Style", "Serifa BT", "URW Bookman L", "itc bookman", times, serif;
|
|
||||||
background: #00979d none repeat scroll 0px 0px;
|
|
||||||
align: Center;
|
|
||||||
}
|
|
||||||
#Main {
|
|
||||||
width: 600px;
|
|
||||||
margin: 5px 3px 3px 12px;
|
|
||||||
}
|
|
||||||
text#titleGlitch {
|
|
||||||
fill: #006666;
|
|
||||||
font-weight: bold;
|
|
||||||
text-shadow: 2px 2px black;
|
|
||||||
font-family: sans-serif;
|
|
||||||
font-size: 36px;
|
|
||||||
-webkit-font-smoothing: antialiased;
|
|
||||||
-moz-osx-font-smoothing: grayscale;
|
|
||||||
}
|
|
||||||
text#titleText {
|
|
||||||
fill: #006666;
|
|
||||||
text-shadow: 1px 1px black;
|
|
||||||
font-family: sans-serif;
|
|
||||||
font-size: 26px;
|
|
||||||
-webkit-font-smoothing: antialiased;
|
|
||||||
-moz-osx-font-smoothing: grayscale;
|
|
||||||
}
|
|
||||||
svg {
|
|
||||||
border: solid 1px black;
|
|
||||||
width: 100%;
|
|
||||||
height: 50px;
|
|
||||||
display: block;
|
|
||||||
position: relative;
|
|
||||||
/*overflow: hidden; */
|
|
||||||
background: #66bebe;
|
|
||||||
-webkit-border-radius: 10px;
|
|
||||||
-moz-border-radius: 10px;
|
|
||||||
border-radius: 10px;
|
|
||||||
}
|
|
||||||
#prototypControls {
|
|
||||||
margin-top: 3px;
|
|
||||||
padding: 10px;
|
|
||||||
border: solid black 1px;
|
|
||||||
background: #66bebe;
|
|
||||||
-webkit-border-radius: 10px;
|
|
||||||
-moz-border-radius: 10px;
|
|
||||||
border-radius: 10px;
|
|
||||||
}
|
|
||||||
.sectionTitle {
|
|
||||||
font-size: 28px;
|
|
||||||
font-weight: bold;
|
|
||||||
font-family: "impact", "Bookman Old Style", "Serifa BT", "URW Bookman L", "itc bookman", times, serif;
|
|
||||||
float: left;
|
|
||||||
clear: left;
|
|
||||||
color: #006666;
|
|
||||||
text-shadow: 2px 2px black;
|
|
||||||
}
|
|
||||||
.sectionDesc {
|
|
||||||
font-weight: bold;
|
|
||||||
float: left;
|
|
||||||
clear: left;
|
|
||||||
}
|
|
||||||
#ledMacroButtonsCont {
|
|
||||||
padding: 18px 5px 15px 5px;
|
|
||||||
text-decoration: none;
|
|
||||||
float: none;
|
|
||||||
clear: left;
|
|
||||||
}
|
|
||||||
.ledMacroButton {
|
|
||||||
height: 50px;
|
|
||||||
background: #00989d;
|
|
||||||
background-image: -webkit-linear-gradient(top, #00989d, #0a787a);
|
|
||||||
background-image: -moz-linear-gradient(top, #00989d, #0a787a);
|
|
||||||
background-image: -ms-linear-gradient(top, #00989d, #0a787a);
|
|
||||||
background-image: -o-linear-gradient(top, #00989d, #0a787a);
|
|
||||||
background-image: linear-gradient(to bottom, #00989d, #0a787a);
|
|
||||||
-webkit-border-radius: 17;
|
|
||||||
-moz-border-radius: 17;
|
|
||||||
border-radius: 17px;
|
|
||||||
text-shadow: 6px 4px 4px #4d424d;
|
|
||||||
-webkit-box-shadow: 0px 1px 3px #666666;
|
|
||||||
-moz-box-shadow: 0px 1px 3px #666666;
|
|
||||||
box-shadow: 0px 1px 3px #666666;
|
|
||||||
color: #fafafa;
|
|
||||||
font-size: 12px;
|
|
||||||
padding: 10px 15px 10px 15px;
|
|
||||||
border: solid #26b3b3 4px;
|
|
||||||
text-decoration: none;
|
|
||||||
margin: 23px 4px 23px 6px;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
.ledMacroButton:hover {
|
|
||||||
background: #307070;
|
|
||||||
background-image: -webkit-linear-gradient(top, #307070, #66bebe);
|
|
||||||
background-image: -moz-linear-gradient(top, #307070, #66bebe);
|
|
||||||
background-image: -ms-linear-gradient(top, #307070, #66bebe);
|
|
||||||
background-image: -o-linear-gradient(top, #307070, #66bebe);
|
|
||||||
background-image: linear-gradient(to bottom, #307070, #66bebe);
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -7,92 +7,9 @@
|
|||||||
<link rel="stylesheet" type="text/css" href="styles.css">
|
<link rel="stylesheet" type="text/css" href="styles.css">
|
||||||
<script src="scripts.js"></script>
|
<script src="scripts.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body id="index" style="margin:0; padding:0;">
|
<body>
|
||||||
<div id="Main">
|
<div class="content">
|
||||||
<div id="pageTitle">
|
<div id="prototypControls" class="spiro-control container">
|
||||||
<!-- SVG Glitch from: http://codepen.io/DirkWeber/pen/ArFvk -->
|
|
||||||
<svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="580px" height="45px" viewBox="0 0 580 45">
|
|
||||||
<defs>
|
|
||||||
<filter id="filter">
|
|
||||||
<feFlood flood-color="#66bebe" result="black" />
|
|
||||||
<feFlood flood-color="#206060" result="flood1" />
|
|
||||||
<feFlood flood-color="#369e9e" result="flood2" />
|
|
||||||
<feOffset in="SourceGraphic" dx="3" dy="0" result="off1a"/>
|
|
||||||
<feOffset in="SourceGraphic" dx="2" dy="0" result="off1b"/>
|
|
||||||
<feOffset in="SourceGraphic" dx="-4" dy="0" result="off2a"/>
|
|
||||||
<feOffset in="SourceGraphic" dx="-2" dy="0" result="off2b"/>
|
|
||||||
<feComposite in="flood1" in2="off1a" operator="in" result="comp1" />
|
|
||||||
<feComposite in="flood2" in2="off2a" operator="in" result="comp2" />
|
|
||||||
|
|
||||||
<feMerge x="0" width="100%" result="merge1">
|
|
||||||
<feMergeNode in = "black" />
|
|
||||||
<feMergeNode in = "comp1" />
|
|
||||||
<feMergeNode in = "off1b" />
|
|
||||||
|
|
||||||
<animate
|
|
||||||
attributeName="y"
|
|
||||||
id = "y"
|
|
||||||
dur ="4s"
|
|
||||||
|
|
||||||
values = '104px; 104px; 30px; 105px; 30px; 2px; 2px; 50px; 40px; 105px; 105px; 20px; 6ßpx; 40px; 104px; 40px; 70px; 10px; 30px; 104px; 102px'
|
|
||||||
|
|
||||||
keyTimes = '0; 0.362; 0.368; 0.421; 0.440; 0.477; 0.518; 0.564; 0.593; 0.613; 0.644; 0.693; 0.721; 0.736; 0.772; 0.818; 0.844; 0.894; 0.925; 0.939; 1'
|
|
||||||
|
|
||||||
repeatCount = "indefinite" />
|
|
||||||
|
|
||||||
<animate attributeName="height"
|
|
||||||
id = "h"
|
|
||||||
dur ="4s"
|
|
||||||
|
|
||||||
values = '10px; 0px; 10px; 30px; 50px; 0px; 10px; 0px; 0px; 0px; 10px; 50px; 40px; 0px; 0px; 0px; 40px; 30px; 10px; 0px; 50px'
|
|
||||||
|
|
||||||
keyTimes = '0; 0.362; 0.368; 0.421; 0.440; 0.477; 0.518; 0.564; 0.593; 0.613; 0.644; 0.693; 0.721; 0.736; 0.772; 0.818; 0.844; 0.894; 0.925; 0.939; 1'
|
|
||||||
|
|
||||||
repeatCount = "indefinite" />
|
|
||||||
</feMerge>
|
|
||||||
|
|
||||||
|
|
||||||
<feMerge x="0" width="100%" y="60px" height="65px" result="merge2">
|
|
||||||
<feMergeNode in = "black" />
|
|
||||||
<feMergeNode in = "comp2" />
|
|
||||||
<feMergeNode in = "off2b" />
|
|
||||||
|
|
||||||
<animate attributeName="y"
|
|
||||||
id = "y"
|
|
||||||
dur ="4s"
|
|
||||||
values = '103px; 104px; 69px; 53px; 42px; 104px; 78px; 89px; 96px; 100px; 67px; 50px; 96px; 66px; 88px; 42px; 13px; 100px; 100px; 104px;'
|
|
||||||
|
|
||||||
keyTimes = '0; 0.055; 0.100; 0.125; 0.159; 0.182; 0.202; 0.236; 0.268; 0.326; 0.357; 0.400; 0.408; 0.461; 0.493; 0.513; 0.548; 0.577; 0.613; 1'
|
|
||||||
|
|
||||||
repeatCount = "indefinite" />
|
|
||||||
|
|
||||||
<animate attributeName="height"
|
|
||||||
id = "h"
|
|
||||||
dur = "4s"
|
|
||||||
|
|
||||||
values = '0px; 0px; 0px; 16px; 16px; 12px; 12px; 0px; 0px; 5px; 10px; 22px; 33px; 11px; 0px; 0px; 10px'
|
|
||||||
|
|
||||||
keyTimes = '0; 0.055; 0.100; 0.125; 0.159; 0.182; 0.202; 0.236; 0.268; 0.326; 0.357; 0.400; 0.408; 0.461; 0.493; 0.513; 1'
|
|
||||||
|
|
||||||
repeatCount = "indefinite" />
|
|
||||||
</feMerge>
|
|
||||||
|
|
||||||
<feMerge>
|
|
||||||
<feMergeNode in="SourceGraphic" />
|
|
||||||
|
|
||||||
<feMergeNode in="merge1" />
|
|
||||||
<feMergeNode in="merge2" />
|
|
||||||
|
|
||||||
</feMerge>
|
|
||||||
</filter>
|
|
||||||
</defs>
|
|
||||||
<g>
|
|
||||||
<text id="titleGlitch" style="filter: url(#filter);" x="0" y="35">Laserspiro controller</text>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="prototypControls">
|
|
||||||
<label>L</label>
|
<label>L</label>
|
||||||
<input type="range" class="laser slider" value="1" min="1" max="128">
|
<input type="range" class="laser slider" value="1" min="1" max="128">
|
||||||
<label>M1</label>
|
<label>M1</label>
|
||||||
@@ -111,6 +28,30 @@
|
|||||||
</div>
|
</div>
|
||||||
<br>
|
<br>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="settings container">
|
||||||
|
<span class="heading">Wifi Settings</span>
|
||||||
|
<form>
|
||||||
|
<ul class="flex-outer">
|
||||||
|
<li>
|
||||||
|
<label for="first-name">SSID</label>
|
||||||
|
<input type="text" id="first-name" placeholder="service station id">
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<label for="last-name">Password</label>
|
||||||
|
<input type="text" id="last-name" placeholder="station password">
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<p>Age</p>
|
||||||
|
<ul class="flex-inner">
|
||||||
|
<!-- list items here -->
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<button type="submit">Submit</button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
62
frontend/scripts/core/App.js
Normal file
62
frontend/scripts/core/App.js
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
import $ from 'jquery';
|
||||||
|
|
||||||
|
import * as Components from '../components/exports';
|
||||||
|
|
||||||
|
|
||||||
|
export default class App {
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.dataStores = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
withDataStore(dataStore) {
|
||||||
|
this.dataStores[dataStore.constructor.name] = dataStore;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
getStore(dataStore) {
|
||||||
|
return this.dataStores[dataStore];
|
||||||
|
}
|
||||||
|
|
||||||
|
run(ctx) {
|
||||||
|
this._loadComponents(ctx);
|
||||||
|
this._beforeInitComponents();
|
||||||
|
this._initComponents();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
_loadComponents(ctx) {
|
||||||
|
this.components = this.components || [];
|
||||||
|
for (let c in Components) {
|
||||||
|
let nodes = ctx ? ctx.find('.' + c) : [];
|
||||||
|
for (let i = 0; i < nodes.length; i++) {
|
||||||
|
let component = new Components[c](this, $(nodes[i]));
|
||||||
|
this.components.push(component);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_initComponents() {
|
||||||
|
this.components.forEach(this._initComponent);
|
||||||
|
}
|
||||||
|
|
||||||
|
_beforeInitComponents() {
|
||||||
|
this.components.forEach(this._beforeInitComponent);
|
||||||
|
}
|
||||||
|
|
||||||
|
_initComponent(component) {
|
||||||
|
component.init();
|
||||||
|
}
|
||||||
|
|
||||||
|
_beforeInitComponent(component) {
|
||||||
|
component.beforeInit();
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
for (let component in this.components) {
|
||||||
|
this.components[component].render();
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
45
frontend/scripts/core/Component.js
Normal file
45
frontend/scripts/core/Component.js
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
import Mustache from 'mustache';
|
||||||
|
import $ from 'jquery';
|
||||||
|
import DataField from './data/DataField';
|
||||||
|
|
||||||
|
export default class Component {
|
||||||
|
|
||||||
|
constructor(ctx, node, withTemplate = true) {
|
||||||
|
this.ctx = ctx;
|
||||||
|
this.node = node;
|
||||||
|
this.component = this.constructor.name;
|
||||||
|
this.template = withTemplate ? $.get(this.component + '.html') : undefined; //document.querySelector('#' + this.component).import.body.textContent;
|
||||||
|
this.data = {};
|
||||||
|
//console.log('init ' + this.component);
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeInit() {
|
||||||
|
this.subscribe();
|
||||||
|
}
|
||||||
|
|
||||||
|
init() {}
|
||||||
|
subscribe() {}
|
||||||
|
templateHelpers() { return {}; }
|
||||||
|
|
||||||
|
bindData() {
|
||||||
|
let _this = this;
|
||||||
|
this.node.find('[data-bind]').each(function() {
|
||||||
|
var field = $(this);
|
||||||
|
_this.data[field.data('bind')] = new DataField(field);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
render(data) {
|
||||||
|
if (data) data.helpers = this.templateHelpers();
|
||||||
|
return this.template
|
||||||
|
.then((template) => {
|
||||||
|
return new Promise((fulfill, reject) => {
|
||||||
|
this.node.html(Mustache.render(template, data));
|
||||||
|
this.bindData();
|
||||||
|
//this.ctx._loadComponents(this.node);
|
||||||
|
fulfill();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
20
frontend/scripts/core/Mediator.js
Normal file
20
frontend/scripts/core/Mediator.js
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
export default class Mediator {
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.events = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
on(event, callback, context){
|
||||||
|
this.events[event] = this.events[event] || [];
|
||||||
|
this.events[event].push(context ? callback.bind(context) : callback);
|
||||||
|
};
|
||||||
|
|
||||||
|
trigger(event, args){
|
||||||
|
if(this.events[event]){
|
||||||
|
for (var i = this.events[event].length - 1; i >= 0; i--) {
|
||||||
|
this.events[event][i](args || {});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
28
frontend/scripts/core/data/DataBinding.js
Normal file
28
frontend/scripts/core/data/DataBinding.js
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import $ from 'jquery';
|
||||||
|
|
||||||
|
export default class DataBinding {
|
||||||
|
|
||||||
|
inputChange(node, model = {}) {
|
||||||
|
node.on('keyup', function() {
|
||||||
|
model.value = this.value;
|
||||||
|
});
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
inputHandler() {
|
||||||
|
return {
|
||||||
|
set: function(target, prop, newValue) {
|
||||||
|
if (prop == 'value' && target.id) {
|
||||||
|
target[prop] = newValue;
|
||||||
|
$('[data-bind="' + target.id + '"]').val(newValue);
|
||||||
|
return true;
|
||||||
|
} else return false;
|
||||||
|
|
||||||
|
},
|
||||||
|
get: function(target, name) {
|
||||||
|
return target[name];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
23
frontend/scripts/core/data/DataField.js
Normal file
23
frontend/scripts/core/data/DataField.js
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import DataBinding from './DataBinding';
|
||||||
|
|
||||||
|
export default class DataField {
|
||||||
|
|
||||||
|
constructor(node, data) {
|
||||||
|
this.node = node;
|
||||||
|
this.data = {
|
||||||
|
id: this.node.data('bind')
|
||||||
|
};
|
||||||
|
this.bind();
|
||||||
|
}
|
||||||
|
bind() {
|
||||||
|
this.dataBinding = new DataBinding();
|
||||||
|
this.dataBinding.inputChange(this.node, this.data);
|
||||||
|
this.proxy = new Proxy(this.data, this.dataBinding.inputHandler());
|
||||||
|
}
|
||||||
|
get value() {
|
||||||
|
return this.proxy.value;
|
||||||
|
}
|
||||||
|
set value(newValue) {
|
||||||
|
this.proxy.value = newValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
9
frontend/scripts/core/store/DataStore.js
Normal file
9
frontend/scripts/core/store/DataStore.js
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
export default class DataStore {
|
||||||
|
constructor(mediator){
|
||||||
|
this.mediator = mediator;
|
||||||
|
}
|
||||||
|
load(entry){}
|
||||||
|
save(entry){}
|
||||||
|
add(entry){}
|
||||||
|
delete(entry){}
|
||||||
|
}
|
||||||
37
frontend/scripts/core/store/RestStore.js
Normal file
37
frontend/scripts/core/store/RestStore.js
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
import $ from 'jquery';
|
||||||
|
import Mediator from '../Mediator';
|
||||||
|
import DataStore from './DataStore';
|
||||||
|
import StoreAction from './StoreAction';
|
||||||
|
|
||||||
|
export default class RestStore extends DataStore {
|
||||||
|
constructor(endpoint, mediator = new Mediator()){
|
||||||
|
super(mediator);
|
||||||
|
this.endpoint = endpoint;
|
||||||
|
}
|
||||||
|
load(entry){
|
||||||
|
return this.request(StoreAction.LOAD, 'GET', entry);
|
||||||
|
}
|
||||||
|
save(entry){
|
||||||
|
return this.request(StoreAction.SAVE, 'POST', entry);
|
||||||
|
}
|
||||||
|
add(entry){
|
||||||
|
return this.request(StoreAction.ADD, 'PUT', entry);
|
||||||
|
}
|
||||||
|
delete(entry){
|
||||||
|
return this.request(StoreAction.DELETE, 'POST', entry);
|
||||||
|
}
|
||||||
|
request(event, type, payload){
|
||||||
|
return $.ajax({
|
||||||
|
url: this.endpoint,
|
||||||
|
type: type,
|
||||||
|
data: payload
|
||||||
|
})
|
||||||
|
.then(JSON.parse)
|
||||||
|
.then((response) => {
|
||||||
|
this.mediator.trigger(event, response);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
on(event, subscriber, context){
|
||||||
|
this.mediator.on(event, subscriber, context);
|
||||||
|
}
|
||||||
|
}
|
||||||
6
frontend/scripts/core/store/StoreAction.js
Normal file
6
frontend/scripts/core/store/StoreAction.js
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
export default {
|
||||||
|
LOAD: 'load',
|
||||||
|
SAVE: 'save',
|
||||||
|
ADD: 'add',
|
||||||
|
DELETE: 'delete'
|
||||||
|
}
|
||||||
@@ -1,119 +1,81 @@
|
|||||||
|
|
||||||
label {
|
@color-black: #000000;
|
||||||
width: 10%;
|
@color-white: #eeeeee;
|
||||||
display: inline-block;
|
@color-main: #0eb8c0;
|
||||||
}
|
@color-container: #333333;
|
||||||
.slider {
|
|
||||||
width: 80%;
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@default-padding: 16px;
|
||||||
|
@default-margin: 16px;
|
||||||
|
|
||||||
|
@input-height: 24px;
|
||||||
|
|
||||||
body {
|
body {
|
||||||
font-size: 14px;
|
background: @color-black;
|
||||||
font-family: "Bookman Old Style","Serifa BT","URW Bookman L","itc bookman",times,serif;
|
color: @color-main;
|
||||||
background: #00979d none repeat scroll 0px 0px;
|
|
||||||
align: Center;
|
|
||||||
}
|
|
||||||
#Main {
|
|
||||||
width: 600px;
|
|
||||||
margin: 5px 3px 3px 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
text#titleGlitch {
|
margin: 0;
|
||||||
fill: #006666;
|
padding: 0;
|
||||||
font-weight: bold;
|
|
||||||
text-shadow: 2px 2px black;
|
ul {
|
||||||
font-family: sans-serif;
|
padding: 0;
|
||||||
font-size: 36px;
|
li {
|
||||||
-webkit-font-smoothing: antialiased;
|
margin: 0 0 @default-margin 0;
|
||||||
-moz-osx-font-smoothing: grayscale;
|
}
|
||||||
}
|
}
|
||||||
text#titleText {
|
|
||||||
fill: #006666;
|
p {
|
||||||
text-shadow: 1px 1px black;
|
padding: 0;
|
||||||
font-family: sans-serif;
|
margin: 0;
|
||||||
font-size: 26px;
|
}
|
||||||
-webkit-font-smoothing: antialiased;
|
|
||||||
-moz-osx-font-smoothing: grayscale;
|
.content {
|
||||||
}
|
padding: @default-padding * 2;
|
||||||
svg {
|
.heading {
|
||||||
border: solid 1px black;
|
font-size: 1.2em;
|
||||||
width: 100%;
|
margin-bottom: @default-margin;
|
||||||
height: 50px;
|
|
||||||
display: block;
|
display: block;
|
||||||
position: relative;
|
}
|
||||||
/*overflow: hidden; */
|
.container {
|
||||||
background: #66bebe;
|
background: @color-container;
|
||||||
-webkit-border-radius: 10px;
|
padding: @default-padding;
|
||||||
-moz-border-radius: 10px;
|
}
|
||||||
border-radius: 10px;
|
input {
|
||||||
}
|
height: @input-height;
|
||||||
#prototypControls {
|
}
|
||||||
margin-top:3px;
|
}
|
||||||
padding: 10px;
|
.sidebar {
|
||||||
border: solid black 1px;
|
.item {
|
||||||
background: #66bebe;
|
|
||||||
-webkit-border-radius: 10px;
|
}
|
||||||
-moz-border-radius: 10px;
|
}
|
||||||
border-radius: 10px;
|
|
||||||
}
|
|
||||||
.sectionTitle {
|
|
||||||
font-size: 28px;
|
|
||||||
font-weight: bold;
|
|
||||||
font-family: "impact","Bookman Old Style","Serifa BT","URW Bookman L","itc bookman",times,serif;
|
|
||||||
float: left;
|
|
||||||
clear: left;
|
|
||||||
color: #006666;
|
|
||||||
text-shadow: 2px 2px black;
|
|
||||||
}
|
|
||||||
.sectionDesc {
|
|
||||||
font-weight: bold;
|
|
||||||
float: left;
|
|
||||||
clear: left;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.settings {
|
||||||
|
.flex-outer li,
|
||||||
|
.flex-inner {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
#ledMacroButtonsCont {
|
.flex-outer > li > label,
|
||||||
padding: 18px 5px 15px 5px;
|
.flex-outer li p {
|
||||||
text-decoration: none;
|
flex: 1 0;
|
||||||
float:none;
|
}
|
||||||
clear:left;
|
|
||||||
|
.flex-outer > li > label + *,
|
||||||
|
.flex-inner {
|
||||||
|
flex: 1 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.spiro-control {
|
||||||
.ledMacroButton {
|
label {
|
||||||
height: 50px;
|
width: 10%;
|
||||||
background: #00989d;
|
display: inline-block;
|
||||||
background-image: -webkit-linear-gradient(top, #00989d, #0a787a);
|
}
|
||||||
background-image: -moz-linear-gradient(top, #00989d, #0a787a);
|
input[type="range"] {
|
||||||
background-image: -ms-linear-gradient(top, #00989d, #0a787a);
|
width: 80%;
|
||||||
background-image: -o-linear-gradient(top, #00989d, #0a787a);
|
display: inline-block;
|
||||||
background-image: linear-gradient(to bottom, #00989d, #0a787a);
|
}
|
||||||
-webkit-border-radius: 17;
|
|
||||||
-moz-border-radius: 17;
|
|
||||||
border-radius: 17px;
|
|
||||||
text-shadow: 6px 4px 4px #4d424d;
|
|
||||||
-webkit-box-shadow: 0px 1px 3px #666666;
|
|
||||||
-moz-box-shadow: 0px 1px 3px #666666;
|
|
||||||
box-shadow: 0px 1px 3px #666666;
|
|
||||||
color: #fafafa;
|
|
||||||
font-size:12px;
|
|
||||||
padding: 10px 15px 10px 15px;
|
|
||||||
border: solid #26b3b3 4px;
|
|
||||||
text-decoration: none;
|
|
||||||
margin: 23px 4px 23px 6px;
|
|
||||||
position: relative;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.ledMacroButton:hover {
|
|
||||||
background: #307070;
|
|
||||||
background-image: -webkit-linear-gradient(top, #307070, #66bebe);
|
|
||||||
background-image: -moz-linear-gradient(top, #307070, #66bebe);
|
|
||||||
background-image: -ms-linear-gradient(top, #307070, #66bebe);
|
|
||||||
background-image: -o-linear-gradient(top, #307070, #66bebe);
|
|
||||||
background-image: linear-gradient(to bottom, #307070, #66bebe);
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
119
frontend/styles/styles.old.css
Normal file
119
frontend/styles/styles.old.css
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
|
||||||
|
label {
|
||||||
|
width: 10%;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
.slider {
|
||||||
|
width: 80%;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-size: 14px;
|
||||||
|
font-family: "Bookman Old Style","Serifa BT","URW Bookman L","itc bookman",times,serif;
|
||||||
|
background: #00979d none repeat scroll 0px 0px;
|
||||||
|
align: Center;
|
||||||
|
}
|
||||||
|
#Main {
|
||||||
|
width: 600px;
|
||||||
|
margin: 5px 3px 3px 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
text#titleGlitch {
|
||||||
|
fill: #006666;
|
||||||
|
font-weight: bold;
|
||||||
|
text-shadow: 2px 2px black;
|
||||||
|
font-family: sans-serif;
|
||||||
|
font-size: 36px;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
}
|
||||||
|
text#titleText {
|
||||||
|
fill: #006666;
|
||||||
|
text-shadow: 1px 1px black;
|
||||||
|
font-family: sans-serif;
|
||||||
|
font-size: 26px;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
}
|
||||||
|
svg {
|
||||||
|
border: solid 1px black;
|
||||||
|
width: 100%;
|
||||||
|
height: 50px;
|
||||||
|
display: block;
|
||||||
|
position: relative;
|
||||||
|
/*overflow: hidden; */
|
||||||
|
background: #66bebe;
|
||||||
|
-webkit-border-radius: 10px;
|
||||||
|
-moz-border-radius: 10px;
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
#prototypControls {
|
||||||
|
margin-top:3px;
|
||||||
|
padding: 10px;
|
||||||
|
border: solid black 1px;
|
||||||
|
background: #66bebe;
|
||||||
|
-webkit-border-radius: 10px;
|
||||||
|
-moz-border-radius: 10px;
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
.sectionTitle {
|
||||||
|
font-size: 28px;
|
||||||
|
font-weight: bold;
|
||||||
|
font-family: "impact","Bookman Old Style","Serifa BT","URW Bookman L","itc bookman",times,serif;
|
||||||
|
float: left;
|
||||||
|
clear: left;
|
||||||
|
color: #006666;
|
||||||
|
text-shadow: 2px 2px black;
|
||||||
|
}
|
||||||
|
.sectionDesc {
|
||||||
|
font-weight: bold;
|
||||||
|
float: left;
|
||||||
|
clear: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ledMacroButtonsCont {
|
||||||
|
padding: 18px 5px 15px 5px;
|
||||||
|
text-decoration: none;
|
||||||
|
float:none;
|
||||||
|
clear:left;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.ledMacroButton {
|
||||||
|
height: 50px;
|
||||||
|
background: #00989d;
|
||||||
|
background-image: -webkit-linear-gradient(top, #00989d, #0a787a);
|
||||||
|
background-image: -moz-linear-gradient(top, #00989d, #0a787a);
|
||||||
|
background-image: -ms-linear-gradient(top, #00989d, #0a787a);
|
||||||
|
background-image: -o-linear-gradient(top, #00989d, #0a787a);
|
||||||
|
background-image: linear-gradient(to bottom, #00989d, #0a787a);
|
||||||
|
-webkit-border-radius: 17;
|
||||||
|
-moz-border-radius: 17;
|
||||||
|
border-radius: 17px;
|
||||||
|
text-shadow: 6px 4px 4px #4d424d;
|
||||||
|
-webkit-box-shadow: 0px 1px 3px #666666;
|
||||||
|
-moz-box-shadow: 0px 1px 3px #666666;
|
||||||
|
box-shadow: 0px 1px 3px #666666;
|
||||||
|
color: #fafafa;
|
||||||
|
font-size:12px;
|
||||||
|
padding: 10px 15px 10px 15px;
|
||||||
|
border: solid #26b3b3 4px;
|
||||||
|
text-decoration: none;
|
||||||
|
margin: 23px 4px 23px 6px;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ledMacroButton:hover {
|
||||||
|
background: #307070;
|
||||||
|
background-image: -webkit-linear-gradient(top, #307070, #66bebe);
|
||||||
|
background-image: -moz-linear-gradient(top, #307070, #66bebe);
|
||||||
|
background-image: -ms-linear-gradient(top, #307070, #66bebe);
|
||||||
|
background-image: -o-linear-gradient(top, #307070, #66bebe);
|
||||||
|
background-image: linear-gradient(to bottom, #307070, #66bebe);
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
"watch:css": "nodemon -q -w frontend/styles --ext \".\" --exec \"npm run build:css\"",
|
"watch:css": "nodemon -q -w frontend/styles --ext \".\" --exec \"npm run build:css\"",
|
||||||
"watch:js": "nodemon -q -w frontend/scripts --ext \".\" --exec \"npm run build:js\"",
|
"watch:js": "nodemon -q -w frontend/scripts --ext \".\" --exec \"npm run build:js\"",
|
||||||
"watch:config": "nodemon -q -w config --ext \".\" --exec \"npm run cp:config\"",
|
"watch:config": "nodemon -q -w config --ext \".\" --exec \"npm run cp:config\"",
|
||||||
"watch:livereload": "cd data && live-server",
|
"watch:livereload": "cd data && live-server --port=3000",
|
||||||
"build:fs": "pio run -t buildfs",
|
"build:fs": "pio run -t buildfs",
|
||||||
"upload:fs": "pio run -t uploadfs",
|
"upload:fs": "pio run -t uploadfs",
|
||||||
"build:firmware": "pio run -t clean && pio run",
|
"build:firmware": "pio run -t clean && pio run",
|
||||||
|
|||||||
Reference in New Issue
Block a user