robeaux 0.0.3 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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