This commit is contained in:
2017-11-02 22:22:38 +00:00
parent 7099ea57c2
commit bd9ca29c34
15 changed files with 555 additions and 414 deletions

View File

@@ -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

View File

@@ -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>

View File

@@ -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;
}

View File

@@ -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>

View 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;
}
}

View 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();
});
});
}
}

View 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 || {});
};
}
};
}

View 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];
}
};
}
}

View 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;
}
}

View File

@@ -0,0 +1,9 @@
export default class DataStore {
constructor(mediator){
this.mediator = mediator;
}
load(entry){}
save(entry){}
add(entry){}
delete(entry){}
}

View 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);
}
}

View File

@@ -0,0 +1,6 @@
export default {
LOAD: 'load',
SAVE: 'save',
ADD: 'add',
DELETE: 'delete'
}

View File

@@ -1,119 +1,81 @@
@color-black: #000000;
@color-white: #eeeeee;
@color-main: #0eb8c0;
@color-container: #333333;
@default-padding: 16px;
@default-margin: 16px;
@input-height: 24px;
body {
background: @color-black;
color: @color-main;
margin: 0;
padding: 0;
ul {
padding: 0;
li {
margin: 0 0 @default-margin 0;
}
}
p {
padding: 0;
margin: 0;
}
.content {
padding: @default-padding * 2;
.heading {
font-size: 1.2em;
margin-bottom: @default-margin;
display: block;
}
.container {
background: @color-container;
padding: @default-padding;
}
input {
height: @input-height;
}
}
.sidebar {
.item {
}
}
}
.settings {
.flex-outer li,
.flex-inner {
display: flex;
flex-wrap: wrap;
align-items: center;
}
.flex-outer > li > label,
.flex-outer li p {
flex: 1 0;
}
.flex-outer > li > label + *,
.flex-inner {
flex: 1 0;
}
}
.spiro-control {
label { label {
width: 10%; width: 10%;
display: inline-block; display: inline-block;
} }
.slider { 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;
}

View 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;
}

View File

@@ -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",