robeaux 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a70c44bc8e7aebdb2d72cb0970d2b7486b655dc8
4
- data.tar.gz: 5bdeff086b5405f70fe1ef12cca62b57fc0406b2
3
+ metadata.gz: 4e9cb1794d02b9393af64856a6b291061ae9fd4f
4
+ data.tar.gz: 9df1c29727e8f1d16e971f4c1909c4b4a54d4756
5
5
  SHA512:
6
- metadata.gz: 391b05d84a2b584df0e135adb4bd5997421bde134d15e972af5e8f472ee097cdc3d62093becbfc86261a9c28b149da1b26e581d9203a70b0bc4b7c40b889fdea
7
- data.tar.gz: 8e1b4ecdd91910000057f474e1488f3e5cfa811dd863ecced663586fc6d8779a7c55d11409b3d35a2be82b6e9d601a2e003a9de15f101f5b713e5ddaeeb41084
6
+ metadata.gz: 07d8b1440b14a49f5bb95bd3898abb3610916e8b357cfce24089072789e612edfa4152943171f6e9f9ef48849f8655b4acab57fa76e485401fb70e4c174ef49e
7
+ data.tar.gz: dcd894b2fefcca0d39b88aea069060bba1cd9f57137a8d064687a590231440bc970f23a9c875506468f3bc2773e78e6ec09903ccfa1086e08a75855c1ab64ba1
data/README.md CHANGED
@@ -7,7 +7,7 @@ Robeaux is powered by [AngularJS](http://angularjs.org/), and provides
7
7
  a front-end to the API interface offered by [Artoo](http://artoo.io),
8
8
  [Cylon.js](http://cylonjs.com) and [Gobot](http://gobot.io). It looks like this:
9
9
 
10
- ![Robeaux Interface](http://i.imgur.com/rDf5inl.png)
10
+ ![Robeaux Interface](http://i.imgur.com/Uxb21j0.png)
11
11
 
12
12
  ## How It Works
13
13
 
@@ -21,14 +21,14 @@ connected to a compatible API server.
21
21
  You can see each robot that your are connected to, and then drill in to view or
22
22
  edit it.
23
23
 
24
- ![Robots View](http://i.imgur.com/4388Mce.png)
24
+ ![Robots View](http://i.imgur.com/Uxb21j0.png)
25
25
 
26
26
  ### Connections
27
27
 
28
28
  How are you connected? Serial port? WiFi? View the details for each of your
29
29
  robots.
30
30
 
31
- ![Connections View](http://i.imgur.com/ewJ9Ec2.png)
31
+ ![Connections View](http://i.imgur.com/Kof6g50.png)
32
32
 
33
33
  ### Devices
34
34
 
@@ -36,7 +36,31 @@ Each robot has one or more devices connected. You can view the device status and
36
36
  send commands all via the web interface. You can even stream the real-time
37
37
  websockets data for your buttons, switches, LEDs, sensors, and more.
38
38
 
39
- ![Devices View](http://i.imgur.com/aB5YL7Q.png)
39
+ ![Devices View](http://i.imgur.com/AMJZCe9.png)
40
+
41
+ ## Themes
42
+
43
+ You can change the theme! Pick from one of the presets, or write your own. It'll
44
+ be persisted in `localStorage` and ready to go for the next time you want to use
45
+ Robeaux.
46
+
47
+ We have three default themes:
48
+
49
+ **Default Theme**:
50
+
51
+ ![Default Theme](http://i.imgur.com/AMJZCe9.png)
52
+
53
+ **Dark Theme**:
54
+
55
+ ![Dark Theme](http://i.imgur.com/SNSLROf.png)
56
+
57
+ **Flat Theme**:
58
+
59
+ ![Flat Theme](http://i.imgur.com/AVzMd7j.png)
60
+
61
+ You can also use the theme editor to write your own custom themes:
62
+
63
+ ![Custom Theme Editor](http://i.imgur.com/pxxmhfD.png)
40
64
 
41
65
  ## Pushing new versions
42
66
 
data/index.html CHANGED
@@ -6,9 +6,19 @@
6
6
  <link rel="stylesheet" href="/stylesheets/bootstrap.css">
7
7
  <link rel="stylesheet" href="/stylesheets/font-awesome.css">
8
8
  <link rel="stylesheet" href="/stylesheets/style.css">
9
+
10
+ <span class="ng-hide" ng-controller="ThemesCtrl">
11
+ <link ng-if="!themes.current().custom" rel="stylesheet" ng-href="{{themes.current().url}}">
12
+ <style ng-if="themes.current().custom" ng-bind-template="{{themes.current().css}}"></style>
13
+ </span>
9
14
  </head>
10
15
  <body>
11
16
  <nav class="navbar navbar-default" role="navigation">
17
+ <div class="theme-selector" ng-controller="ThemesCtrl">
18
+ <select class="nav navbar-nav" ng-selected="themes.setActiveTheme()" ng-model="themes.activeTheme" ng-options="name for name in themes.list()">
19
+ </select>
20
+ </div>
21
+
12
22
  <div class="container">
13
23
  <div class="navbar-header">
14
24
  <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
@@ -21,10 +31,12 @@
21
31
  </div>
22
32
 
23
33
  <div class="collapse navbar-collapse">
24
- <ul class="nav navbar-nav" ng-app="link">
25
- <li class="active"><a href="#">Robots</a></li>
34
+ <ul class="nav navbar-nav" ng-controller="NavigationCtrl">
35
+ <li ng-class="{active: active('robots')}"><a href="#/robots">Robots</a></li>
36
+ <li ng-class="{active: active('themes')}"><a href="#/themes">Themes</a></li>
26
37
  </ul>
27
38
  </div>
39
+
28
40
  </div>
29
41
  </nav>
30
42
 
data/javascripts/app.js CHANGED
@@ -2,18 +2,120 @@
2
2
  var robeaux = angular.module("robeaux", ['ngRoute']);
3
3
 
4
4
  robeaux.config(["$routeProvider", function($routeProvider) {
5
- $routeProvider.when("/robots", {
5
+ $routeProvider
6
+
7
+ .when("/robots", {
6
8
  templateUrl: "/partials/robot-index.html",
7
9
  controller: RobotIndexCtrl
8
- }).when("/robots/:robotId", {
10
+ })
11
+
12
+ .when("/robots/:robotId", {
9
13
  templateUrl: "/partials/robot-detail.html",
10
14
  controller: RobotDetailCtrl
11
- }).otherwise({
15
+ })
16
+
17
+ .when("/themes", {
18
+ templateUrl: "/partials/themes.html",
19
+ controller: ThemesCtrl
20
+ })
21
+
22
+ .otherwise({
12
23
  redirectTo: "/robots"
13
24
  });
14
- }])
25
+ }]);
26
+
27
+ robeaux.service("Themes", function() {
28
+ var service = {};
29
+ var defaultThemes = {
30
+ "default": { custom: false, url: "/stylesheets/themes/default.css" },
31
+ "dark": { custom: false, url: "/stylesheets/themes/dark.css" },
32
+ "flat": { custom: false, url: "/stylesheets/themes/flat.css" }
33
+ };
34
+
35
+ var saveThemes = function() {
36
+ localStorage.setItem("themes", angular.toJson(service.themes));
37
+ };
38
+
39
+ var loadThemes = function() {
40
+ if (localStorage.getItem("themes")) {
41
+ return angular.fromJson(localStorage.getItem("themes"));
42
+ } else {
43
+ return defaultThemes;
44
+ }
45
+ };
46
+
47
+ var getActiveTheme = function() {
48
+ return localStorage.getItem("activeTheme") || "default";
49
+ };
50
+
51
+ service.themes = loadThemes();
52
+
53
+ service.activeTheme = getActiveTheme();
54
+
55
+ service.saveThemes = saveThemes;
56
+
57
+ service.current = function() {
58
+ return service.themes[service.activeTheme];
59
+ };
60
+
61
+ service.list = function() {
62
+ return Object.keys(service.themes);
63
+ };
64
+
65
+ service.customThemes = function() {
66
+ var themes = {};
67
+
68
+ for (var name in service.themes) {
69
+ if (service.themes[name].custom) {
70
+ themes[name] = service.themes[name];
71
+ }
72
+ }
73
+
74
+ return themes;
75
+ };
76
+
77
+ service.setActiveTheme = function() {
78
+ localStorage.setItem("activeTheme", service.activeTheme);
79
+ }
80
+
81
+ service.newTheme = function(name) {
82
+ if (service.themes[name] || name === '' || name === undefined) {
83
+ return false;
84
+ }
85
+
86
+ service.themes[name] = {css: "", custom: true};
87
+ return service.themes[name];
88
+ };
89
+
90
+ return service;
91
+ });
15
92
 
16
93
  // Controllers
94
+ var ThemesCtrl = function($scope, Themes) {
95
+ $scope.themes = Themes;
96
+
97
+ $scope.selectTheme = function(name) {
98
+ $scope.selectedTheme = Themes.themes[name];
99
+ $scope.selectedThemeName = name;
100
+ };
101
+
102
+ $scope.deleteTheme = function(name) {
103
+ delete Themes.themes[name];
104
+ $scope.selectedTheme = null;
105
+ $scope.selectedThemeName = null;
106
+ };
107
+
108
+ $scope.newTheme = function(name) {
109
+ if (Themes.newTheme(name)) { $scope.newThemeName = ''; }
110
+ }
111
+ }
112
+
113
+ var NavigationCtrl = function($scope, $location) {
114
+ $scope.active = function(path) {
115
+ return ($location.path().substring(1).split("/")[0] || "robots") === path;
116
+ }
117
+ }
118
+
17
119
  var RobotIndexCtrl = function($scope, $http, $location, $route) {
18
120
  $http.get('/robots').success(function(data) {
19
121
  $scope.robots = data;
@@ -1,14 +1,14 @@
1
1
  /*
2
- AngularJS v1.2.7
2
+ AngularJS v1.2.11
3
3
  (c) 2010-2014 Google, Inc. http://angularjs.org
4
4
  License: MIT
5
5
  */
6
6
  (function(h,e,A){'use strict';function u(w,q,k){return{restrict:"ECA",terminal:!0,priority:400,transclude:"element",link:function(a,c,b,f,n){function y(){l&&(l.$destroy(),l=null);g&&(k.leave(g),g=null)}function v(){var b=w.current&&w.current.locals;if(e.isDefined(b&&b.$template)){var b=a.$new(),f=w.current;g=n(b,function(d){k.enter(d,null,g||c,function(){!e.isDefined(t)||t&&!a.$eval(t)||q()});y()});l=f.scope=b;l.$emit("$viewContentLoaded");l.$eval(h)}else y()}var l,g,t=b.autoscroll,h=b.onload||"";
7
7
  a.$on("$routeChangeSuccess",v);v()}}}function z(e,h,k){return{restrict:"ECA",priority:-400,link:function(a,c){var b=k.current,f=b.locals;c.html(f.$template);var n=e(c.contents());b.controller&&(f.$scope=a,f=h(b.controller,f),b.controllerAs&&(a[b.controllerAs]=f),c.data("$ngControllerController",f),c.children().data("$ngControllerController",f));n(a)}}}h=e.module("ngRoute",["ng"]).provider("$route",function(){function h(a,c){return e.extend(new (e.extend(function(){},{prototype:a})),c)}function q(a,
8
- e){var b=e.caseInsensitiveMatch,f={originalPath:a,regexp:a},h=f.keys=[];a=a.replace(/([().])/g,"\\$1").replace(/(\/)?:(\w+)([\?|\*])?/g,function(a,e,b,c){a="?"===c?c:null;c="*"===c?c:null;h.push({name:b,optional:!!a});e=e||"";return""+(a?"":e)+"(?:"+(a?e:"")+(c&&"(.+?)"||"([^/]+)")+(a||"")+")"+(a||"")}).replace(/([\/$\*])/g,"\\$1");f.regexp=RegExp("^"+a+"$",b?"i":"");return f}var k={};this.when=function(a,c){k[a]=e.extend({reloadOnSearch:!0},c,a&&q(a,c));if(a){var b="/"==a[a.length-1]?a.substr(0,
9
- a.length-1):a+"/";k[b]=e.extend({redirectTo:a},q(b,c))}return this};this.otherwise=function(a){this.when(null,a);return this};this.$get=["$rootScope","$location","$routeParams","$q","$injector","$http","$templateCache","$sce",function(a,c,b,f,n,q,v,l){function g(){var d=t(),m=r.current;if(d&&m&&d.$$route===m.$$route&&e.equals(d.pathParams,m.pathParams)&&!d.reloadOnSearch&&!x)m.params=d.params,e.copy(m.params,b),a.$broadcast("$routeUpdate",m);else if(d||m)x=!1,a.$broadcast("$routeChangeStart",d,m),
10
- (r.current=d)&&d.redirectTo&&(e.isString(d.redirectTo)?c.path(u(d.redirectTo,d.params)).search(d.params).replace():c.url(d.redirectTo(d.pathParams,c.path(),c.search())).replace()),f.when(d).then(function(){if(d){var a=e.extend({},d.resolve),c,b;e.forEach(a,function(d,c){a[c]=e.isString(d)?n.get(d):n.invoke(d)});e.isDefined(c=d.template)?e.isFunction(c)&&(c=c(d.params)):e.isDefined(b=d.templateUrl)&&(e.isFunction(b)&&(b=b(d.params)),b=l.getTrustedResourceUrl(b),e.isDefined(b)&&(d.loadedTemplateUrl=
11
- b,c=q.get(b,{cache:v}).then(function(a){return a.data})));e.isDefined(c)&&(a.$template=c);return f.all(a)}}).then(function(c){d==r.current&&(d&&(d.locals=c,e.copy(d.params,b)),a.$broadcast("$routeChangeSuccess",d,m))},function(c){d==r.current&&a.$broadcast("$routeChangeError",d,m,c)})}function t(){var a,b;e.forEach(k,function(f,k){var p;if(p=!b){var s=c.path();p=f.keys;var l={};if(f.regexp)if(s=f.regexp.exec(s)){for(var g=1,q=s.length;g<q;++g){var n=p[g-1],r="string"==typeof s[g]?decodeURIComponent(s[g]):
12
- s[g];n&&r&&(l[n.name]=r)}p=l}else p=null;else p=null;p=a=p}p&&(b=h(f,{params:e.extend({},c.search(),a),pathParams:a}),b.$$route=f)});return b||k[null]&&h(k[null],{params:{},pathParams:{}})}function u(a,c){var b=[];e.forEach((a||"").split(":"),function(a,d){if(0===d)b.push(a);else{var e=a.match(/(\w+)(.*)/),f=e[1];b.push(c[f]);b.push(e[2]||"");delete c[f]}});return b.join("")}var x=!1,r={routes:k,reload:function(){x=!0;a.$evalAsync(g)}};a.$on("$locationChangeSuccess",g);return r}]});h.provider("$routeParams",
8
+ e){var b=e.caseInsensitiveMatch,f={originalPath:a,regexp:a},h=f.keys=[];a=a.replace(/([().])/g,"\\$1").replace(/(\/)?:(\w+)([\?\*])?/g,function(a,e,b,c){a="?"===c?c:null;c="*"===c?c:null;h.push({name:b,optional:!!a});e=e||"";return""+(a?"":e)+"(?:"+(a?e:"")+(c&&"(.+?)"||"([^/]+)")+(a||"")+")"+(a||"")}).replace(/([\/$\*])/g,"\\$1");f.regexp=RegExp("^"+a+"$",b?"i":"");return f}var k={};this.when=function(a,c){k[a]=e.extend({reloadOnSearch:!0},c,a&&q(a,c));if(a){var b="/"==a[a.length-1]?a.substr(0,a.length-
9
+ 1):a+"/";k[b]=e.extend({redirectTo:a},q(b,c))}return this};this.otherwise=function(a){this.when(null,a);return this};this.$get=["$rootScope","$location","$routeParams","$q","$injector","$http","$templateCache","$sce",function(a,c,b,f,n,q,v,l){function g(){var d=t(),m=r.current;if(d&&m&&d.$$route===m.$$route&&e.equals(d.pathParams,m.pathParams)&&!d.reloadOnSearch&&!x)m.params=d.params,e.copy(m.params,b),a.$broadcast("$routeUpdate",m);else if(d||m)x=!1,a.$broadcast("$routeChangeStart",d,m),(r.current=
10
+ d)&&d.redirectTo&&(e.isString(d.redirectTo)?c.path(u(d.redirectTo,d.params)).search(d.params).replace():c.url(d.redirectTo(d.pathParams,c.path(),c.search())).replace()),f.when(d).then(function(){if(d){var a=e.extend({},d.resolve),c,b;e.forEach(a,function(d,c){a[c]=e.isString(d)?n.get(d):n.invoke(d)});e.isDefined(c=d.template)?e.isFunction(c)&&(c=c(d.params)):e.isDefined(b=d.templateUrl)&&(e.isFunction(b)&&(b=b(d.params)),b=l.getTrustedResourceUrl(b),e.isDefined(b)&&(d.loadedTemplateUrl=b,c=q.get(b,
11
+ {cache:v}).then(function(a){return a.data})));e.isDefined(c)&&(a.$template=c);return f.all(a)}}).then(function(c){d==r.current&&(d&&(d.locals=c,e.copy(d.params,b)),a.$broadcast("$routeChangeSuccess",d,m))},function(c){d==r.current&&a.$broadcast("$routeChangeError",d,m,c)})}function t(){var a,b;e.forEach(k,function(f,k){var p;if(p=!b){var s=c.path();p=f.keys;var l={};if(f.regexp)if(s=f.regexp.exec(s)){for(var g=1,q=s.length;g<q;++g){var n=p[g-1],r="string"==typeof s[g]?decodeURIComponent(s[g]):s[g];
12
+ n&&r&&(l[n.name]=r)}p=l}else p=null;else p=null;p=a=p}p&&(b=h(f,{params:e.extend({},c.search(),a),pathParams:a}),b.$$route=f)});return b||k[null]&&h(k[null],{params:{},pathParams:{}})}function u(a,c){var b=[];e.forEach((a||"").split(":"),function(a,d){if(0===d)b.push(a);else{var e=a.match(/(\w+)(.*)/),f=e[1];b.push(c[f]);b.push(e[2]||"");delete c[f]}});return b.join("")}var x=!1,r={routes:k,reload:function(){x=!0;a.$evalAsync(g)}};a.$on("$locationChangeSuccess",g);return r}]});h.provider("$routeParams",
13
13
  function(){this.$get=function(){return{}}});h.directive("ngView",u);h.directive("ngView",z);u.$inject=["$route","$anchorScroll","$animate"];z.$inject=["$compile","$controller","$route"]})(window,window.angular);
14
14
  //# sourceMappingURL=angular-route.min.js.map