aboutsummaryrefslogtreecommitdiff
path: root/web/static/app
diff options
context:
space:
mode:
Diffstat (limited to 'web/static/app')
-rw-r--r--web/static/app/app.css152
-rw-r--r--web/static/app/app.js56
-rw-r--r--web/static/app/templates/property.html12
3 files changed, 213 insertions, 7 deletions
diff --git a/web/static/app/app.css b/web/static/app/app.css
index 090ac5e..f21c0dc 100644
--- a/web/static/app/app.css
+++ b/web/static/app/app.css
@@ -1,3 +1,153 @@
nav.navbar {
- margin-bottom: 2rem;
+ margin-bottom: 2rem;
}
+
+/*
+ * http://martinwolf.org/2015/01/08/pure-css-savingloading-dots-animation/
+ */
+.dl-dots span {
+ animation-name: dl-dots;
+ animation-duration: 1.4s;
+ animation-iteration-count: infinite;
+ animation-fill-mode: both;
+}
+
+.dl-dots span:nth-child(2) {
+ animation-delay: .2s;
+}
+
+.dl-dots span:nth-child(3) {
+ animation-delay: .4s;
+}
+
+@-webkit-keyframes dl-dots {
+ 0% {
+ opacity: .2;
+ }
+ 20% {
+ opacity: 1;
+ }
+ 100% {
+ opacity: .2;
+ }
+}
+
+@-moz-keyframes dl-dots {
+ 0% {
+ opacity: .2;
+ }
+ 20% {
+ opacity: 1;
+ }
+ 100% {
+ opacity: .2;
+ }
+}
+
+@-ms-keyframes dl-dots {
+ 0% {
+ opacity: .2;
+ }
+ 20% {
+ opacity: 1;
+ }
+ 100% {
+ opacity: .2;
+ }
+}
+
+@keyframes dl-dots {
+ 0% {
+ opacity: .2;
+ }
+ 20% {
+ opacity: 1;
+ }
+ 100% {
+ opacity: .2;
+ }
+}
+
+/*
+ * https://gist.github.com/jankorbel/2336513/cb2f68b59521438ac812ad72c1c93d8f656e49ad
+ */
+/*
+.dl-dots span {
+ background: transparent;
+ border-radius: 50%;
+ box-shadow: inset 0 0 1px rgba(0, 0, 0, 0.3);
+ display: inline-block;
+ height: 0.6em;
+ width: 0.6em;
+
+ -webkit-animation: dl-dots 0.8s linear infinite;
+ -moz-animation: dl-dots 0.8s linear infinite;
+ -ms-animation: dl-dots 0.8s linear infinite;
+ animation: dl-dots 0.8s linear infinite;
+}
+
+.dl-dots span:nth-child(1) {
+ -webkit-animation-delay: 0.4s;
+ -moz-animation-delay: 0.4s;
+ -ms-animation-delay: 0.4s;
+ animation-delay: 0.4s;
+}
+
+.dl-dots span:nth-child(2) {
+ -webkit-animation-delay: 0.2s;
+ -moz-animation-delay: 0.2s;
+ -ms-animation-delay: 0.2s;
+ animation-delay: 0.2s;
+}
+
+!*
+ Define the animation for every efing vendor prefix
+*!
+@-webkit-keyframes dl-dots {
+ 0% {
+ background: transparent;
+ }
+ 50% {
+ background: #E4E4E4;
+ }
+ 100% {
+ background: transparent;
+ }
+}
+
+@-moz-keyframes dl-dots {
+ 0% {
+ background: transparent;
+ }
+ 50% {
+ background: #E4E4E4;
+ }
+ 100% {
+ background: transparent;
+ }
+}
+
+@-ms-keyframes dl-dots {
+ 0% {
+ background: transparent;
+ }
+ 50% {
+ background: #E4E4E4;
+ }
+ 100% {
+ background: transparent;
+ }
+}
+
+@keyframes dl-dots {
+ 0% {
+ background: transparent;
+ }
+ 50% {
+ background: #E4E4E4;
+ }
+ 100% {
+ background: transparent;
+ }
+}
+*/
diff --git a/web/static/app/app.js b/web/static/app/app.js
index 5274362..6fa1f71 100644
--- a/web/static/app/app.js
+++ b/web/static/app/app.js
@@ -11,15 +11,62 @@
ctrl.device = device.data.device;
}
- function PropertyController($route, device, values) {
+ function PropertyController($timeout, $route, DillerRpc, device, values) {
var ctrl = this;
ctrl.device = device.data.device;
ctrl.property = _.find(ctrl.device.properties, {id: $route.current.params.propertyId});
ctrl.values = values.data.values;
+
+ var refreshPromise;
+ ctrl.refresh = function () {
+ $timeout.cancel(refreshPromise);
+ refreshPromise = $timeout(function () {
+ ctrl.loading = true;
+ }, 200);
+
+ DillerRpc.getValues($route.current.params.propertyId).then(function (res) {
+ ctrl.values = res.data.values;
+ ctrl.loading = false;
+ $timeout.cancel(refreshPromise);
+ })
+ };
+ }
+
+ function TimestampFilter() {
+ return function (value) {
+ if (!value) {
+ return;
+ }
+
+ return moment(value).startOf('second').fromNow();
+ }
+ }
+
+ function DlTimestampDirective() {
+ console.log('DlTimestampDirective', DlTimestampDirective);
+ return {
+ restrict: 'E',
+ scope: {
+ value: '='
+ },
+ replace: true,
+ template: '<span title="{{value|date:\'medium\'}}">{{value|timestamp}}</span>'
+ };
+ }
+
+ function DlDotsDirective() {
+ return {
+ restrict: 'E',
+ scope: {
+ value: '='
+ },
+ replace: true,
+ template: '<span class="dl-dots"><span>.</span><span>.</span><span>.</span></span>\n'
+ };
}
- function config($routeProvider, $locationProvider) {
+ function config($routeProvider) {
$routeProvider
.when('/', {
controller: FrontPageController,
@@ -49,8 +96,6 @@
.otherwise({
redirectTo: '/'
});
-
- //$locationProvider.html5Mode(true);
}
function DillerConfig() {
@@ -67,6 +112,9 @@
angular
.module('Diller', ['ngRoute'])
.config(config)
+ .filter('timestamp', TimestampFilter)
+ .directive('dlTimestamp', DlTimestampDirective)
+ .directive('dlDots', DlDotsDirective)
.service('DillerConfig', DillerConfig)
.service('DillerRpc', DillerRpc);
})();
diff --git a/web/static/app/templates/property.html b/web/static/app/templates/property.html
index 65a66e8..cd003ca 100644
--- a/web/static/app/templates/property.html
+++ b/web/static/app/templates/property.html
@@ -16,7 +16,15 @@
<li>Description: {{ctrl.property.description}}</li>
</ul>
- <h3>Latest Values</h3>
+ <h3>
+ Latest Values
+ <small ng-hide="ctrl.loading">
+ <a href ng-click="ctrl.refresh()">refresh</a>
+ </small>
+ <small ng-show="ctrl.loading">
+ Loading <dl-dots></dl-dots>
+ </small>
+ </h3>
<table class="table">
<thead>
@@ -27,7 +35,7 @@
</thead>
<tbody>
<tr ng-repeat="v in ctrl.values">
- <td>{{v.timestamp | date:'medium'}}</td>
+ <td><dl-timestamp value="v.timestamp"></dl-timestamp></td>
<td>{{v.value}}</td>
</tr>
</tbody>