redis-browser 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +18 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +27 -0
- data/Rakefile +1 -0
- data/bin/redis-browser +9 -0
- data/lib/redis-browser/app.rb +189 -0
- data/lib/redis-browser/public/css/app.css +42 -0
- data/lib/redis-browser/public/css/bootstrap.min.css +9 -0
- data/lib/redis-browser/public/img/glyphicons-halflings-white.png +0 -0
- data/lib/redis-browser/public/img/glyphicons-halflings.png +0 -0
- data/lib/redis-browser/public/js/angular.min.js +162 -0
- data/lib/redis-browser/public/js/localStorageModule.js +239 -0
- data/lib/redis-browser/public/js/ui-bootstrap-tpls-0.2.0.min.js +1 -0
- data/lib/redis-browser/templates/coffee/app.coffee +140 -0
- data/lib/redis-browser/templates/index.slim +179 -0
- data/lib/redis-browser/version.rb +3 -0
- data/redis-browser.gemspec +31 -0
- metadata +190 -0
@@ -0,0 +1,239 @@
|
|
1
|
+
/* Start angularLocalStorage */
|
2
|
+
|
3
|
+
var angularLocalStorage = angular.module('LocalStorageModule', []);
|
4
|
+
|
5
|
+
// You should set a prefix to avoid overwriting any local storage variables from the rest of your app
|
6
|
+
// e.g. angularLocalStorage.constant('prefix', 'youAppName');
|
7
|
+
angularLocalStorage.constant('prefix', 'ls');
|
8
|
+
// Cookie options (usually in case of fallback)
|
9
|
+
// expiry = Number of days before cookies expire // 0 = Does not expire
|
10
|
+
// path = The web path the cookie represents
|
11
|
+
angularLocalStorage.constant('cookie', { expiry:30, path: '/'});
|
12
|
+
|
13
|
+
angularLocalStorage.service('localStorageService', [
|
14
|
+
'$rootScope',
|
15
|
+
'prefix',
|
16
|
+
'cookie',
|
17
|
+
function($rootScope, prefix, cookie) {
|
18
|
+
|
19
|
+
// If there is a prefix set in the config lets use that with an appended period for readability
|
20
|
+
//var prefix = angularLocalStorage.constant;
|
21
|
+
if (prefix.substr(-1)!=='.') {
|
22
|
+
prefix = !!prefix ? prefix + '.' : '';
|
23
|
+
}
|
24
|
+
|
25
|
+
// Checks the browser to see if local storage is supported
|
26
|
+
var browserSupportsLocalStorage = function () {
|
27
|
+
try {
|
28
|
+
return ('localStorage' in window && window['localStorage'] !== null);
|
29
|
+
} catch (e) {
|
30
|
+
$rootScope.$broadcast('LocalStorageModule.notification.error',e.message);
|
31
|
+
return false;
|
32
|
+
}
|
33
|
+
};
|
34
|
+
|
35
|
+
// Directly adds a value to local storage
|
36
|
+
// If local storage is not available in the browser use cookies
|
37
|
+
// Example use: localStorageService.add('library','angular');
|
38
|
+
var addToLocalStorage = function (key, value) {
|
39
|
+
|
40
|
+
// If this browser does not support local storage use cookies
|
41
|
+
if (!browserSupportsLocalStorage()) {
|
42
|
+
$rootScope.$broadcast('LocalStorageModule.notification.warning','LOCAL_STORAGE_NOT_SUPPORTED');
|
43
|
+
return addToCookies(key, value);
|
44
|
+
}
|
45
|
+
|
46
|
+
// 0 and "" is allowed as a value but let's limit other falsey values like "undefined"
|
47
|
+
if (!value && value!==0 && value!=="") return false;
|
48
|
+
|
49
|
+
try {
|
50
|
+
localStorage.setItem(prefix+key, value);
|
51
|
+
} catch (e) {
|
52
|
+
$rootScope.$broadcast('LocalStorageModule.notification.error',e.message);
|
53
|
+
return addToCookies(key, value);
|
54
|
+
}
|
55
|
+
return true;
|
56
|
+
};
|
57
|
+
|
58
|
+
// Directly get a value from local storage
|
59
|
+
// Example use: localStorageService.get('library'); // returns 'angular'
|
60
|
+
var getFromLocalStorage = function (key) {
|
61
|
+
if (!browserSupportsLocalStorage()) {
|
62
|
+
$rootScope.$broadcast('LocalStorageModule.notification.warning','LOCAL_STORAGE_NOT_SUPPORTED');
|
63
|
+
return getFromCookies(key);
|
64
|
+
}
|
65
|
+
|
66
|
+
var item = localStorage.getItem(prefix+key);
|
67
|
+
if (!item) return null;
|
68
|
+
return item;
|
69
|
+
};
|
70
|
+
|
71
|
+
// Remove an item from local storage
|
72
|
+
// Example use: localStorageService.remove('library'); // removes the key/value pair of library='angular'
|
73
|
+
var removeFromLocalStorage = function (key) {
|
74
|
+
if (!browserSupportsLocalStorage()) {
|
75
|
+
$rootScope.$broadcast('LocalStorageModule.notification.warning','LOCAL_STORAGE_NOT_SUPPORTED');
|
76
|
+
return removeFromCookies(key);
|
77
|
+
}
|
78
|
+
|
79
|
+
try {
|
80
|
+
localStorage.removeItem(prefix+key);
|
81
|
+
} catch (e) {
|
82
|
+
$rootScope.$broadcast('LocalStorageModule.notification.error',e.message);
|
83
|
+
return removeFromCookies(key);
|
84
|
+
}
|
85
|
+
return true;
|
86
|
+
};
|
87
|
+
|
88
|
+
// Remove all data for this app from local storage
|
89
|
+
// Example use: localStorageService.clearAll();
|
90
|
+
// Should be used mostly for development purposes
|
91
|
+
var clearAllFromLocalStorage = function () {
|
92
|
+
|
93
|
+
if (!browserSupportsLocalStorage()) {
|
94
|
+
$rootScope.$broadcast('LocalStorageModule.notification.warning','LOCAL_STORAGE_NOT_SUPPORTED');
|
95
|
+
return clearAllFromCookies();
|
96
|
+
}
|
97
|
+
|
98
|
+
var prefixLength = prefix.length;
|
99
|
+
|
100
|
+
for (var key in localStorage) {
|
101
|
+
// Only remove items that are for this app
|
102
|
+
if (key.substr(0,prefixLength) === prefix) {
|
103
|
+
try {
|
104
|
+
removeFromLocalStorage(key.substr(prefixLength));
|
105
|
+
} catch (e) {
|
106
|
+
$rootScope.$broadcast('LocalStorageModule.notification.error',e.message);
|
107
|
+
return clearAllFromCookies();
|
108
|
+
}
|
109
|
+
}
|
110
|
+
}
|
111
|
+
return true;
|
112
|
+
};
|
113
|
+
|
114
|
+
// Checks the browser to see if cookies are supported
|
115
|
+
var browserSupportsCookies = function() {
|
116
|
+
try {
|
117
|
+
return navigator.cookieEnabled ||
|
118
|
+
("cookie" in document && (document.cookie.length > 0 ||
|
119
|
+
(document.cookie = "test").indexOf.call(document.cookie, "test") > -1));
|
120
|
+
} catch (e) {
|
121
|
+
$rootScope.$broadcast('LocalStorageModule.notification.error',e.message);
|
122
|
+
return false;
|
123
|
+
}
|
124
|
+
};
|
125
|
+
|
126
|
+
// Directly adds a value to cookies
|
127
|
+
// Typically used as a fallback is local storage is not available in the browser
|
128
|
+
// Example use: localStorageService.cookie.add('library','angular');
|
129
|
+
var addToCookies = function (key, value) {
|
130
|
+
|
131
|
+
if (typeof value == "undefined") return false;
|
132
|
+
|
133
|
+
if (!browserSupportsCookies()) {
|
134
|
+
$rootScope.$broadcast('LocalStorageModule.notification.error','COOKIES_NOT_SUPPORTED');
|
135
|
+
return false;
|
136
|
+
}
|
137
|
+
|
138
|
+
try {
|
139
|
+
var expiry = '', expiryDate = new Date();
|
140
|
+
if (value === null) {
|
141
|
+
cookie.expiry = -1;
|
142
|
+
value = '';
|
143
|
+
}
|
144
|
+
if (cookie.expiry !== 0) {
|
145
|
+
expiryDate.setTime(expiryDate.getTime() + (cookie.expiry*24*60*60*1000));
|
146
|
+
expiry = ", expires="+expiryDate.toGMTString();
|
147
|
+
}
|
148
|
+
if (!!key) {
|
149
|
+
document.cookie = prefix + key + "=" + encodeURIComponent(value) + expiry + ", path="+cookie.path;
|
150
|
+
}
|
151
|
+
} catch (e) {
|
152
|
+
$rootScope.$broadcast('LocalStorageModule.notification.error',e.message);
|
153
|
+
return false;
|
154
|
+
}
|
155
|
+
return true;
|
156
|
+
};
|
157
|
+
|
158
|
+
// Directly get a value from a cookie
|
159
|
+
// Example use: localStorageService.cookie.get('library'); // returns 'angular'
|
160
|
+
var getFromCookies = function (key) {
|
161
|
+
if (!browserSupportsCookies()) {
|
162
|
+
$rootScope.$broadcast('LocalStorageModule.notification.error','COOKIES_NOT_SUPPORTED');
|
163
|
+
return false;
|
164
|
+
}
|
165
|
+
|
166
|
+
var cookies = document.cookie.split(',');
|
167
|
+
for(var i=0;i < cookies.length;i++) {
|
168
|
+
var thisCookie = cookies[i];
|
169
|
+
while (thisCookie.charAt(0)==' ') {
|
170
|
+
thisCookie = thisCookie.substring(1,thisCookie.length);
|
171
|
+
}
|
172
|
+
if (thisCookie.indexOf(prefix+key+'=') === 0) {
|
173
|
+
return decodeURIComponent(thisCookie.substring(prefix.length+key.length+1,thisCookie.length));
|
174
|
+
}
|
175
|
+
}
|
176
|
+
return null;
|
177
|
+
};
|
178
|
+
|
179
|
+
var removeFromCookies = function (key) {
|
180
|
+
addToCookies(key,null);
|
181
|
+
};
|
182
|
+
|
183
|
+
var clearAllFromCookies = function () {
|
184
|
+
var thisCookie = null, thisKey = null;
|
185
|
+
var prefixLength = prefix.length;
|
186
|
+
var cookies = document.cookie.split(';');
|
187
|
+
for(var i=0;i < cookies.length;i++) {
|
188
|
+
thisCookie = cookies[i];
|
189
|
+
while (thisCookie.charAt(0)==' ') {
|
190
|
+
thisCookie = thisCookie.substring(1,thisCookie.length);
|
191
|
+
}
|
192
|
+
key = thisCookie.substring(prefixLength,thisCookie.indexOf('='));
|
193
|
+
removeFromCookies(key);
|
194
|
+
}
|
195
|
+
};
|
196
|
+
|
197
|
+
// JSON stringify functions based on https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/JSON
|
198
|
+
var stringifyJson = function (vContent, isJSON) {
|
199
|
+
// If this is only a string and not a string in a recursive run of an object then let's return the string unadulterated
|
200
|
+
if (typeof vContent === "string" && vContent.charAt(0) !== "{" && !isJSON) {
|
201
|
+
return vContent;
|
202
|
+
}
|
203
|
+
if (vContent instanceof Object) {
|
204
|
+
var sOutput = "";
|
205
|
+
if (vContent.constructor === Array) {
|
206
|
+
for (var nId = 0; nId < vContent.length; sOutput += this.stringifyJson(vContent[nId], true) + ",", nId++);
|
207
|
+
return "[" + sOutput.substr(0, sOutput.length - 1) + "]";
|
208
|
+
}
|
209
|
+
if (vContent.toString !== Object.prototype.toString) { return "\"" + vContent.toString().replace(/"/g, "\\$&") + "\""; }
|
210
|
+
for (var sProp in vContent) { sOutput += "\"" + sProp.replace(/"/g, "\\$&") + "\":" + this.stringifyJson(vContent[sProp], true) + ","; }
|
211
|
+
return "{" + sOutput.substr(0, sOutput.length - 1) + "}";
|
212
|
+
}
|
213
|
+
return typeof vContent === "string" ? "\"" + vContent.replace(/"/g, "\\$&") + "\"" : String(vContent);
|
214
|
+
};
|
215
|
+
|
216
|
+
var parseJson = function (sJSON) {
|
217
|
+
if (sJSON.charAt(0)!=='{') {
|
218
|
+
return sJSON;
|
219
|
+
}
|
220
|
+
return eval("(" + sJSON + ")");
|
221
|
+
};
|
222
|
+
|
223
|
+
return {
|
224
|
+
isSupported: browserSupportsLocalStorage,
|
225
|
+
add: addToLocalStorage,
|
226
|
+
get: getFromLocalStorage,
|
227
|
+
remove: removeFromLocalStorage,
|
228
|
+
clearAll: clearAllFromLocalStorage,
|
229
|
+
stringifyJson: stringifyJson,
|
230
|
+
parseJson: parseJson,
|
231
|
+
cookie: {
|
232
|
+
add: addToCookies,
|
233
|
+
get: getFromCookies,
|
234
|
+
remove: removeFromCookies,
|
235
|
+
clearAll: clearAllFromCookies
|
236
|
+
}
|
237
|
+
};
|
238
|
+
|
239
|
+
}]);
|
@@ -0,0 +1 @@
|
|
1
|
+
angular.module("ui.bootstrap",["ui.bootstrap.tpls","ui.bootstrap.accordion","ui.bootstrap.alert","ui.bootstrap.buttons","ui.bootstrap.carousel","ui.bootstrap.collapse","ui.bootstrap.dialog","ui.bootstrap.dropdownToggle","ui.bootstrap.modal","ui.bootstrap.pagination","ui.bootstrap.popover","ui.bootstrap.tabs","ui.bootstrap.tooltip","ui.bootstrap.transition","ui.bootstrap.typeahead"]),angular.module("ui.bootstrap.tpls",["template/accordion/accordion-group.html","template/accordion/accordion.html","template/alert/alert.html","template/carousel/carousel.html","template/carousel/slide.html","template/dialog/message.html","template/pagination/pagination.html","template/popover/popover.html","template/tabs/pane.html","template/tabs/tabs.html","template/tooltip/tooltip-popup.html","template/typeahead/typeahead.html"]),angular.module("ui.bootstrap.accordion",["ui.bootstrap.collapse"]).constant("accordionConfig",{closeOthers:!0}).controller("AccordionController",["$scope","$attrs","accordionConfig",function(e,t,n){this.groups=[],this.closeOthers=function(r){var i=angular.isDefined(t.closeOthers)?e.$eval(t.closeOthers):n.closeOthers;i&&angular.forEach(this.groups,function(e){e!==r&&(e.isOpen=!1)})},this.addGroup=function(e){var t=this;this.groups.push(e),e.$on("$destroy",function(n){t.removeGroup(e)})},this.removeGroup=function(e){var t=this.groups.indexOf(e);t!==-1&&this.groups.splice(this.groups.indexOf(e),1)}}]).directive("accordion",function(){return{restrict:"EA",controller:"AccordionController",transclude:!0,replace:!1,templateUrl:"template/accordion/accordion.html"}}).directive("accordionGroup",["$parse","$transition","$timeout",function(e,t,n){return{require:"^accordion",restrict:"EA",transclude:!0,replace:!0,templateUrl:"template/accordion/accordion-group.html",scope:{heading:"@"},controller:["$scope",function(e){this.setHeading=function(e){this.heading=e}}],link:function(t,n,r,i){var s,o;i.addGroup(t),t.isOpen=!1,r.isOpen&&(s=e(r.isOpen),o=s.assign,t.$watch(function(){return s(t.$parent)},function(n){t.isOpen=n}),t.isOpen=s?s(t.$parent):!1),t.$watch("isOpen",function(e){e&&i.closeOthers(t),o&&o(t.$parent,e)})}}}]).directive("accordionHeading",function(){return{restrict:"E",transclude:!0,template:"",replace:!0,require:"^accordionGroup",compile:function(e,t,n){return function(t,r,i,s){s.setHeading(n(t,function(){}))}}}}).directive("accordionTransclude",function(){return{require:"^accordionGroup",link:function(e,t,n,r){e.$watch(function(){return r[n.accordionTransclude]},function(e){e&&(t.html(""),t.append(e))})}}}),angular.module("ui.bootstrap.alert",[]).directive("alert",function(){return{restrict:"EA",templateUrl:"template/alert/alert.html",transclude:!0,replace:!0,scope:{type:"=",close:"&"}}}),angular.module("ui.bootstrap.buttons",[]).constant("buttonConfig",{activeClass:"active",toggleEvent:"click"}).directive("btnRadio",["buttonConfig",function(e){var t=e.activeClass||"active",n=e.toggleEvent||"click";return{require:"ngModel",link:function(e,r,i,s){var o=e.$eval(i.btnRadio);e.$watch(function(){return s.$modelValue},function(e){angular.equals(e,o)?r.addClass(t):r.removeClass(t)}),r.bind(n,function(){r.hasClass(t)||e.$apply(function(){s.$setViewValue(o)})})}}}]).directive("btnCheckbox",["buttonConfig",function(e){var t=e.activeClass||"active",n=e.toggleEvent||"click";return{require:"ngModel",link:function(e,r,i,s){var o=e.$eval(i.btnCheckboxTrue),u=e.$eval(i.btnCheckboxFalse);o=angular.isDefined(o)?o:!0,u=angular.isDefined(u)?u:!1,e.$watch(function(){return s.$modelValue},function(e){angular.equals(e,o)?r.addClass(t):r.removeClass(t)}),r.bind(n,function(){e.$apply(function(){s.$setViewValue(r.hasClass(t)?u:o)})})}}}]),angular.module("ui.bootstrap.carousel",["ui.bootstrap.transition"]).controller("CarouselController",["$scope","$timeout","$transition","$q",function(e,t,n,r){function f(){function n(){a?(e.next(),f()):e.pause()}u&&t.cancel(u);var r=+e.interval;!isNaN(r)&&r>=0&&(u=t(n,r))}var i=this,s=i.slides=[],o=-1,u,a;i.currentSlide=null,i.select=function(r,u){function l(){i.currentSlide&&angular.isString(u)&&!e.noTransition&&r.$element?(r.$element.addClass(u),r.$element[0].offsetWidth=r.$element[0].offsetWidth,angular.forEach(s,function(e){angular.extend(e,{direction:"",entering:!1,leaving:!1,active:!1})}),angular.extend(r,{direction:u,active:!0,entering:!0}),angular.extend(i.currentSlide||{},{direction:u,leaving:!0}),e.$currentTransition=n(r.$element,{}),function(t,n){e.$currentTransition.then(function(){c(t,n)},function(){c(t,n)})}(r,i.currentSlide)):c(r,i.currentSlide),i.currentSlide=r,o=a,f()}function c(t,n){angular.extend(t,{direction:"",active:!0,leaving:!1,entering:!1}),angular.extend(n||{},{direction:"",active:!1,leaving:!1,entering:!1}),e.$currentTransition=null}var a=s.indexOf(r);u===undefined&&(u=a>o?"next":"prev"),r&&r!==i.currentSlide&&(e.$currentTransition?(e.$currentTransition.cancel(),t(l)):l())},i.indexOfSlide=function(e){return s.indexOf(e)},e.next=function(){var e=(o+1)%s.length;return i.select(s[e],"next")},e.prev=function(){var e=o-1<0?s.length-1:o-1;return i.select(s[e],"prev")},e.select=function(e){i.select(e)},e.isActive=function(e){return i.currentSlide===e},e.slides=function(){return s},e.$watch("interval",f),e.play=function(){a||(a=!0,f())},e.pause=function(){a=!1,u&&t.cancel(u)},i.addSlide=function(t,n){t.$element=n,s.push(t),s.length===1||t.active?(i.select(s[s.length-1]),s.length==1&&e.play()):t.active=!1},i.removeSlide=function(e){var t=s.indexOf(e);s.splice(t,1),s.length>0&&e.active&&(t>=s.length?i.select(s[t-1]):i.select(s[t]))}}]).directive("carousel",[function(){return{restrict:"EA",transclude:!0,replace:!0,controller:"CarouselController",require:"carousel",templateUrl:"template/carousel/carousel.html",scope:{interval:"=",noTransition:"="}}}]).directive("slide",[function(){return{require:"^carousel",restrict:"EA",transclude:!0,replace:!0,templateUrl:"template/carousel/slide.html",scope:{active:"="},link:function(e,t,n,r){r.addSlide(e,t),e.$on("$destroy",function(){r.removeSlide(e)}),e.$watch("active",function(t){t&&r.select(e)})}}}]),angular.module("ui.bootstrap.collapse",["ui.bootstrap.transition"]).directive("collapse",["$transition",function(e){var t=function(e,t,n){t.removeClass("collapse"),t.css({height:n});var r=t[0].offsetWidth;t.addClass("collapse")};return{link:function(n,r,i){var s,o=!0;n.$watch(function(){return r[0].scrollHeight},function(e){r[0].scrollHeight!==0&&(s||(o?t(n,r,r[0].scrollHeight+"px"):t(n,r,"auto")))}),n.$watch(i.collapse,function(e){e?l():f()});var u,a=function(t){return u&&u.cancel(),u=e(r,t),u.then(function(){u=undefined},function(){u=undefined}),u},f=function(){o?(o=!1,s||t(n,r,"auto")):a({height:r[0].scrollHeight+"px"}).then(function(){s||t(n,r,"auto")}),s=!1},l=function(){s=!0,o?(o=!1,t(n,r,0)):(t(n,r,r[0].scrollHeight+"px"),a({height:"0"}))}}}}]);var dialogModule=angular.module("ui.bootstrap.dialog",["ui.bootstrap.transition"]);dialogModule.controller("MessageBoxController",["$scope","dialog","model",function(e,t,n){e.title=n.title,e.message=n.message,e.buttons=n.buttons,e.close=function(e){t.close(e)}}]),dialogModule.provider("$dialog",function(){var e={backdrop:!0,dialogClass:"modal",backdropClass:"modal-backdrop",transitionClass:"fade",triggerClass:"in",dialogOpenClass:"modal-open",resolve:{},backdropFade:!1,dialogFade:!1,keyboard:!0,backdropClick:!0},t={},n={value:0};this.options=function(e){t=e},this.$get=["$http","$document","$compile","$rootScope","$controller","$templateCache","$q","$transition","$injector",function(r,i,s,o,u,a,f,l,c){function p(e){var t=angular.element("<div>");return t.addClass(e),t}function d(n){var r=this,i=this.options=angular.extend({},e,t,n);this.backdropEl=p(i.backdropClass),i.backdropFade&&(this.backdropEl.addClass(i.transitionClass),this.backdropEl.removeClass(i.triggerClass)),this.modalEl=p(i.dialogClass),i.dialogFade&&(this.modalEl.addClass(i.transitionClass),this.modalEl.removeClass(i.triggerClass)),this.handledEscapeKey=function(e){e.which===27&&(r.close(),e.preventDefault(),r.$scope.$apply())},this.handleBackDropClick=function(e){r.close(),e.preventDefault(),r.$scope.$apply()}}var h=i.find("body");return d.prototype.isOpen=function(){return this._open},d.prototype.open=function(e,t){var n=this,r=this.options;e&&(r.templateUrl=e),t&&(r.controller=t);if(!r.template&&!r.templateUrl)throw new Error("Dialog.open expected template or templateUrl, neither found. Use options or open method to specify them.");return this._loadResolves().then(function(e){var t=e.$scope=n.$scope=e.$scope?e.$scope:o.$new();n.modalEl.html(e.$template);if(n.options.controller){var r=u(n.options.controller,e);n.modalEl.contents().data("ngControllerController",r)}s(n.modalEl)(t),n._addElementsToDom(),h.addClass(n.options.dialogOpenClass),setTimeout(function(){n.options.dialogFade&&n.modalEl.addClass(n.options.triggerClass),n.options.backdropFade&&n.backdropEl.addClass(n.options.triggerClass)}),n._bindEvents()}),this.deferred=f.defer(),this.deferred.promise},d.prototype.close=function(e){function i(e){e.removeClass(t.options.triggerClass)}function s(){t._open&&t._onCloseComplete(e)}var t=this,n=this._getFadingElements();h.removeClass(t.options.dialogOpenClass);if(n.length>0){for(var r=n.length-1;r>=0;r--)l(n[r],i).then(s);return}this._onCloseComplete(e)},d.prototype._getFadingElements=function(){var e=[];return this.options.dialogFade&&e.push(this.modalEl),this.options.backdropFade&&e.push(this.backdropEl),e},d.prototype._bindEvents=function(){this.options.keyboard&&h.bind("keydown",this.handledEscapeKey),this.options.backdrop&&this.options.backdropClick&&this.backdropEl.bind("click",this.handleBackDropClick)},d.prototype._unbindEvents=function(){this.options.keyboard&&h.unbind("keydown",this.handledEscapeKey),this.options.backdrop&&this.options.backdropClick&&this.backdropEl.unbind("click",this.handleBackDropClick)},d.prototype._onCloseComplete=function(e){this._removeElementsFromDom(),this._unbindEvents(),this.deferred.resolve(e)},d.prototype._addElementsToDom=function(){h.append(this.modalEl),this.options.backdrop&&(n.value===0&&h.append(this.backdropEl),n.value++),this._open=!0},d.prototype._removeElementsFromDom=function(){this.modalEl.remove(),this.options.backdrop&&(n.value--,n.value===0&&this.backdropEl.remove()),this._open=!1},d.prototype._loadResolves=function(){var e=[],t=[],n,i=this;return this.options.template?n=f.when(this.options.template):this.options.templateUrl&&(n=r.get(this.options.templateUrl,{cache:a}).then(function(e){return e.data})),angular.forEach(this.options.resolve||[],function(n,r){t.push(r),e.push(angular.isString(n)?c.get(n):c.invoke(n))}),t.push("$template"),e.push(n),f.all(e).then(function(e){var n={};return angular.forEach(e,function(e,r){n[t[r]]=e}),n.dialog=i,n})},{dialog:function(e){return new d(e)},messageBox:function(e,t,n){return new d({templateUrl:"template/dialog/message.html",controller:"MessageBoxController",resolve:{model:function(){return{title:e,message:t,buttons:n}}}})}}}]}),angular.module("ui.bootstrap.dropdownToggle",[]).directive("dropdownToggle",["$document","$location","$window",function(e,t,n){var r=null,i;return{restrict:"CA",link:function(n,s,o){n.$watch(function(){return t.path()},function(){i&&i()}),s.parent().bind("click",function(e){i&&i()}),s.bind("click",function(t){t.preventDefault(),t.stopPropagation();var n=!1;r&&(n=r===s,i()),n||(s.parent().addClass("open"),r=s,i=function(t){t&&(t.preventDefault(),t.stopPropagation()),e.unbind("click",i),s.parent().removeClass("open"),i=null,r=null},e.bind("click",i))})}}}]),angular.module("ui.bootstrap.modal",["ui.bootstrap.dialog"]).directive("modal",["$parse","$dialog",function(e,t){var n,r=angular.element(document.getElementsByTagName("body")[0]);return{restrict:"EA",terminal:!0,link:function(n,r,i){var s=angular.extend({},n.$eval(i.uiOptions||i.bsOptions||i.options)),o=i.modal||i.show,u;s=angular.extend(s,{template:r.html(),resolve:{$scope:function(){return n}}});var a=t.dialog(s);r.remove(),i.close?u=function(){e(i.close)(n)}:u=function(){angular.isFunction(e(o).assign)&&e(o).assign(n,!1)},n.$watch(o,function(e,t){e?a.open().then(function(){u()}):a.isOpen()&&a.close()})}}}]),angular.module("ui.bootstrap.pagination",[]).constant("paginationConfig",{boundaryLinks:!1,directionLinks:!0,firstText:"First",previousText:"Previous",nextText:"Next",lastText:"Last"}).directive("pagination",["paginationConfig",function(e){return{restrict:"EA",scope:{numPages:"=",currentPage:"=",maxSize:"=",onSelectPage:"&"},templateUrl:"template/pagination/pagination.html",replace:!0,link:function(t,n,r){function l(e,t,n,r){return{number:e,text:t,active:n,disabled:r}}var i=angular.isDefined(r.boundaryLinks)?t.$eval(r.boundaryLinks):e.boundaryLinks,s=angular.isDefined(r.directionLinks)?t.$eval(r.directionLinks):e.directionLinks,o=angular.isDefined(r.firstText)?r.firstText:e.firstText,u=angular.isDefined(r.previousText)?r.previousText:e.previousText,a=angular.isDefined(r.nextText)?r.nextText:e.nextText,f=angular.isDefined(r.lastText)?r.lastText:e.lastText;t.$watch("numPages + currentPage + maxSize",function(){t.pages=[];var e=t.maxSize&&t.maxSize<t.numPages?t.maxSize:t.numPages,n=t.currentPage-Math.floor(e/2);n<1&&(n=1),n+e-1>t.numPages&&(n-=n+e-1-t.numPages);for(var r=n,c=n+e;r<c;r++){var h=l(r,r,t.isActive(r),!1);t.pages.push(h)}if(s){var p=l(t.currentPage-1,u,!1,t.noPrevious());t.pages.unshift(p);var d=l(t.currentPage+1,a,!1,t.noNext());t.pages.push(d)}if(i){var v=l(1,o,!1,t.noPrevious());t.pages.unshift(v);var m=l(t.numPages,f,!1,t.noNext());t.pages.push(m)}t.currentPage>t.numPages&&t.selectPage(t.numPages)}),t.noPrevious=function(){return t.currentPage===1},t.noNext=function(){return t.currentPage===t.numPages},t.isActive=function(e){return t.currentPage===e},t.selectPage=function(e){!t.isActive(e)&&e>0&&e<=t.numPages&&(t.currentPage=e,t.onSelectPage({page:e}))}}}}]),angular.module("ui.bootstrap.popover",[]).directive("popoverPopup",function(){return{restrict:"EA",replace:!0,scope:{popoverTitle:"@",popoverContent:"@",placement:"@",animation:"&",isOpen:"&"},templateUrl:"template/popover/popover.html"}}).directive("popover",["$compile","$timeout","$parse","$window",function(e,t,n,r){var i='<popover-popup popover-title="{{tt_title}}" popover-content="{{tt_popover}}" placement="{{tt_placement}}" animation="tt_animation()" is-open="tt_isOpen"></popover-popup>';return{scope:!0,link:function(s,o,u){function l(){var e=o[0].getBoundingClientRect();return{width:o.prop("offsetWidth"),height:o.prop("offsetHeight"),top:e.top+r.pageYOffset,left:e.left+r.pageXOffset}}function c(){var e,n,r,i;f&&t.cancel(f),a.css({top:0,left:0,display:"block"}),o.after(a),e=l(),n=a.prop("offsetWidth"),r=a.prop("offsetHeight");switch(s.tt_placement){case"right":i={top:e.top+e.height/2-r/2+"px",left:e.left+e.width+"px"};break;case"bottom":i={top:e.top+e.height+"px",left:e.left+e.width/2-n/2+"px"};break;case"left":i={top:e.top+e.height/2-r/2+"px",left:e.left-n+"px"};break;default:i={top:e.top-r+"px",left:e.left+e.width/2-n/2+"px"}}a.css(i),s.tt_isOpen=!0}function h(){s.tt_isOpen=!1,angular.isDefined(s.tt_animation)&&s.tt_animation()?f=t(function(){a.remove()},500):a.remove()}var a=e(i)(s),f;u.$observe("popover",function(e){s.tt_popover=e}),u.$observe("popoverTitle",function(e){s.tt_title=e}),u.$observe("popoverPlacement",function(e){s.tt_placement=e||"top"}),u.$observe("popoverAnimation",function(e){s.tt_animation=n(e)}),s.tt_isOpen=!1,o.bind("click",function(){s.tt_isOpen?s.$apply(h):s.$apply(c)})}}}]),angular.module("ui.bootstrap.tabs",[]).controller("TabsController",["$scope","$element",function(e,t){var n=e.panes=[];this.select=e.select=function(t){angular.forEach(n,function(e){e.selected=!1}),t.selected=!0},this.addPane=function(r){n.length||e.select(r),n.push(r)},this.removePane=function(r){var i=n.indexOf(r);n.splice(i,1),r.selected&&n.length>0&&e.select(n[i<n.length?i:i-1])}}]).directive("tabs",function(){return{restrict:"EA",transclude:!0,scope:{},controller:"TabsController",templateUrl:"template/tabs/tabs.html",replace:!0}}).directive("pane",["$parse",function(e){return{require:"^tabs",restrict:"EA",transclude:!0,scope:{heading:"@"},link:function(t,n,r,i){var s,o;t.selected=!1,r.active&&(s=e(r.active),o=s.assign,t.$watch(function(){return s(t.$parent)},function(n){t.selected=n}),t.selected=s?s(t.$parent):!1),t.$watch("selected",function(e){e&&i.select(t),o&&o(t.$parent,e)}),i.addPane(t),t.$on("$destroy",function(){i.removePane(t)})},templateUrl:"template/tabs/pane.html",replace:!0}}]),angular.module("ui.bootstrap.tooltip",[]).directive("tooltipPopup",function(){return{restrict:"EA",replace:!0,scope:{tooltipTitle:"@",placement:"@",animation:"&",isOpen:"&"},templateUrl:"template/tooltip/tooltip-popup.html"}}).directive("tooltip",["$compile","$timeout","$parse","$window",function(e,t,n,r){var i='<tooltip-popup tooltip-title="{{tt_tooltip}}" placement="{{tt_placement}}" animation="tt_animation()" is-open="tt_isOpen"></tooltip-popup>';return{scope:!0,link:function(s,o,u){function l(){var e=o[0].getBoundingClientRect();return{width:o.prop("offsetWidth"),height:o.prop("offsetHeight"),top:e.top+r.pageYOffset,left:e.left+r.pageXOffset}}function c(){var e,n,r,i;if(!s.tt_tooltip)return;f&&t.cancel(f),a.css({top:0,left:0,display:"block"}),o.after(a),e=l(),n=a.prop("offsetWidth"),r=a.prop("offsetHeight");switch(s.tt_placement){case"right":i={top:e.top+e.height/2-r/2+"px",left:e.left+e.width+"px"};break;case"bottom":i={top:e.top+e.height+"px",left:e.left+e.width/2-n/2+"px"};break;case"left":i={top:e.top+e.height/2-r/2+"px",left:e.left-n+"px"};break;default:i={top:e.top-r+"px",left:e.left+e.width/2-n/2+"px"}}a.css(i),s.tt_isOpen=!0}function h(){s.tt_isOpen=!1,angular.isDefined(s.tt_animation)&&s.tt_animation()?f=t(function(){a.remove()},500):a.remove()}var a=e(i)(s),f;u.$observe("tooltip",function(e){s.tt_tooltip=e}),u.$observe("tooltipPlacement",function(e){s.tt_placement=e||"top"}),u.$observe("tooltipAnimation",function(e){s.tt_animation=n(e)}),s.tt_isOpen=!1,o.bind("mouseenter",function(){s.$apply(c)}),o.bind("mouseleave",function(){s.$apply(h)})}}}]),angular.module("ui.bootstrap.transition",[]).factory("$transition",["$q","$timeout","$rootScope",function(e,t,n){function u(e){for(var t in e)if(i.style[t]!==undefined)return e[t]}var r=function(i,s,o){o=o||{};var u=e.defer(),a=r[o.animation?"animationEndEventName":"transitionEndEventName"],f=function(e){n.$apply(function(){i.unbind(a,f),u.resolve(i)})};return a&&i.bind(a,f),t(function(){angular.isString(s)?i.addClass(s):angular.isFunction(s)?s(i):angular.isObject(s)&&i.css(s),a||u.resolve(i)}),u.promise.cancel=function(){a&&i.unbind(a,f),u.reject("Transition cancelled")},u.promise},i=document.createElement("trans"),s={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd",msTransition:"MSTransitionEnd",transition:"transitionend"},o={WebkitTransition:"webkitAnimationEnd",MozTransition:"animationend",OTransition:"oAnimationEnd",msTransition:"MSAnimationEnd",transition:"animationend"};return r.transitionEndEventName=u(s),r.animationEndEventName=u(o),r}]),angular.module("ui.bootstrap.typeahead",[]).factory("typeaheadParser",["$parse",function(e){var t=/^\s*(.*?)(?:\s+as\s+(.*?))?\s+for\s+(?:([\$\w][\$\w\d]*))\s+in\s+(.*)$/;return{parse:function(n){var r=n.match(t),i,s,o;if(!r)throw new Error("Expected typeahead specification in form of '_modelValue_ (as _label_)? for _item_ in _collection_' but got '"+n+"'.");return{itemName:r[3],source:e(r[4]),viewMapper:e(r[2]||r[1]),modelMapper:e(r[1])}}}}]).directive("typeahead",["$compile","$q","typeaheadParser",function(e,t,n){var r=[9,13,27,38,40];return{require:"ngModel",link:function(i,s,o,u){var a=u.$modelValue,f=i.$eval(o.typeaheadMinLength)||1,l=n.parse(o.typeahead),c=i.$new();i.$on("$destroy",function(){c.$destroy()});var h=function(){c.matches=[],c.activeIdx=-1},p=function(e){var n={$viewValue:e};t.when(l.source(c,n)).then(function(t){if(e===u.$viewValue)if(t.length>0){c.activeIdx=0,c.matches.length=0;for(var r=0;r<t.length;r++)n[l.itemName]=t[r],c.matches.push({label:l.viewMapper(c,n),model:t[r]});c.query=e}else h()},h)};h(),c.query=undefined,u.$parsers.push(function(e){return h(),a?e:(e&&e.length>=f&&p(e),undefined)}),u.$render=function(){var e={};e[l.itemName]=a,s.val(l.viewMapper(c,e)||u.$viewValue),a=undefined},c.select=function(e){var t={};t[l.itemName]=a=c.matches[e].model,u.$setViewValue(l.modelMapper(c,t)),u.$render()},s.bind("keydown",function(e){if(c.matches.length===0||r.indexOf(e.which)===-1)return;e.preventDefault(),e.which===40?(c.activeIdx=(c.activeIdx+1)%c.matches.length,c.$digest()):e.which===38?(c.activeIdx=(c.activeIdx?c.activeIdx:c.matches.length)-1,c.$digest()):e.which===13||e.which===9?c.$apply(function(){c.select(c.activeIdx)}):e.which===27&&(c.matches=[],c.$digest())});var d=e("<typeahead-popup matches='matches' active='activeIdx' select='select(activeIdx)' query='query'></typeahead-popup>")(c);s.after(d)}}}]).directive("typeaheadPopup",function(){return{restrict:"E",scope:{matches:"=",query:"=",active:"=",select:"&"},replace:!0,templateUrl:"template/typeahead/typeahead.html",link:function(e,t,n){e.isOpen=function(){return e.matches.length>0},e.isActive=function(t){return e.active==t},e.selectActive=function(t){e.active=t},e.selectMatch=function(t){e.select({activeIdx:t})}}}}).filter("typeaheadHighlight",function(){return function(e,t){return t?e.replace(new RegExp(t,"gi"),"<strong>$&</strong>"):t}}),angular.module("template/accordion/accordion-group.html",[]).run(["$templateCache",function(e){e.put("template/accordion/accordion-group.html",'<div class="accordion-group"> <div class="accordion-heading" ><a class="accordion-toggle" ng-click="isOpen = !isOpen" accordion-transclude="heading">{{heading}}</a></div> <div class="accordion-body" collapse="!isOpen"> <div class="accordion-inner" ng-transclude></div> </div></div>')}]),angular.module("template/accordion/accordion.html",[]).run(["$templateCache",function(e){e.put("template/accordion/accordion.html",'<div class="accordion" ng-transclude></div>')}]),angular.module("template/alert/alert.html",[]).run(["$templateCache",function(e){e.put("template/alert/alert.html","<div class='alert' ng-class='type && \"alert-\" + type'> <button type='button' class='close' ng-click='close()'>×</button> <div ng-transclude></div></div>")}]),angular.module("template/carousel/carousel.html",[]).run(["$templateCache",function(e){e.put("template/carousel/carousel.html",'<div ng-mouseenter="pause()" ng-mouseleave="play()" class="carousel"> <ol class="carousel-indicators"> <li ng-repeat="slide in slides()" ng-class="{active: isActive(slide)}" ng-click="select(slide)"></li> </ol> <div class="carousel-inner" ng-transclude></div> <a ng-click="prev()" class="carousel-control left">‹</a> <a ng-click="next()" class="carousel-control right">›</a></div>')}]),angular.module("template/carousel/slide.html",[]).run(["$templateCache",function(e){e.put("template/carousel/slide.html","<div ng-class=\"{ 'active': leaving || (active && !entering), 'prev': (next || active) && direction=='prev', 'next': (next || active) && direction=='next', 'right': direction=='prev', 'left': direction=='next' }\" class=\"item\" ng-transclude></div>")}]),angular.module("template/dialog/message.html",[]).run(["$templateCache",function(e){e.put("template/dialog/message.html",'<div class="modal-header"> <h1>{{ title }}</h1></div><div class="modal-body"> <p>{{ message }}</p></div><div class="modal-footer"> <button ng-repeat="btn in buttons" ng-click="close(btn.result)" class=btn ng-class="btn.cssClass">{{ btn.label }}</button></div>')}]),angular.module("template/pagination/pagination.html",[]).run(["$templateCache",function(e){e.put("template/pagination/pagination.html",'<div class="pagination"><ul> <li ng-repeat="page in pages" ng-class="{active: page.active, disabled: page.disabled}"><a ng-click="selectPage(page.number)">{{page.text}}</a></li> </ul></div>')}]),angular.module("template/popover/popover.html",[]).run(["$templateCache",function(e){e.put("template/popover/popover.html",'<div class="popover {{placement}}" ng-class="{ in: isOpen(), fade: animation() }"> <div class="arrow"></div> <div class="popover-inner"> <h3 class="popover-title" ng-bind="popoverTitle" ng-show="popoverTitle"></h3> <div class="popover-content" ng-bind="popoverContent"></div> </div></div>')}]),angular.module("template/tabs/pane.html",[]).run(["$templateCache",function(e){e.put("template/tabs/pane.html",'<div class="tab-pane" ng-class="{active: selected}" ng-show="selected" ng-transclude></div>')}]),angular.module("template/tabs/tabs.html",[]).run(["$templateCache",function(e){e.put("template/tabs/tabs.html",'<div class="tabbable"> <ul class="nav nav-tabs"> <li ng-repeat="pane in panes" ng-class="{active:pane.selected}"> <a href="" ng-click="select(pane)">{{pane.heading}}</a> </li> </ul> <div class="tab-content" ng-transclude></div></div>')}]),angular.module("template/tooltip/tooltip-popup.html",[]).run(["$templateCache",function(e){e.put("template/tooltip/tooltip-popup.html",'<div class="tooltip {{placement}}" ng-class="{ in: isOpen(), fade: animation() }"> <div class="tooltip-arrow"></div> <div class="tooltip-inner" ng-bind="tooltipTitle"></div></div>')}]),angular.module("template/typeahead/typeahead.html",[]).run(["$templateCache",function(e){e.put("template/typeahead/typeahead.html",'<div class="dropdown clearfix" ng-class="{open: isOpen()}"> <ul class="typeahead dropdown-menu"> <li ng-repeat="match in matches" ng-class="{active: isActive($index) }" ng-mouseenter="selectActive($index)"> <a tabindex="-1" ng-click="selectMatch($index)" ng-bind-html-unsafe="match.label | typeaheadHighlight:query"></a> </li> </ul></div>')}]);
|
@@ -0,0 +1,140 @@
|
|
1
|
+
app = angular.module('browser', ['ui.bootstrap', 'LocalStorageModule'])
|
2
|
+
|
3
|
+
# app.run ($rootScope) ->
|
4
|
+
|
5
|
+
angular.module('browser').factory 'API', ['$http', ($http) ->
|
6
|
+
(connection, database) ->
|
7
|
+
ps = {connection: connection, database: database}
|
8
|
+
{
|
9
|
+
keysTree: (pattern) -> $http.get("/keys_tree.json", {
|
10
|
+
params: ps
|
11
|
+
}).then (e) -> e.data,
|
12
|
+
|
13
|
+
get: (params) -> $http.get("/key.json", {
|
14
|
+
params: angular.extend({}, ps, params)
|
15
|
+
}).then (e) -> e.data
|
16
|
+
|
17
|
+
delete: (params) -> $http.delete("/key.json", {
|
18
|
+
params: angular.extend({}, ps, params)
|
19
|
+
})
|
20
|
+
}
|
21
|
+
]
|
22
|
+
|
23
|
+
@BrowserCtrl = ($scope, API, localStorageService, $dialog) ->
|
24
|
+
# Internal functions
|
25
|
+
fetchValue = ->
|
26
|
+
$scope.api.get(
|
27
|
+
key: $scope.key.full
|
28
|
+
start: $scope.list.start
|
29
|
+
stop: $scope.list.stop
|
30
|
+
).then((e) -> $scope.key.values = e.values)
|
31
|
+
|
32
|
+
updateList = ->
|
33
|
+
$scope.list.pages = Math.ceil($scope.key.length / $scope.list.per_page)
|
34
|
+
$scope.list.start = $scope.list.per_page * ($scope.list.current - 1)
|
35
|
+
$scope.list.stop = ($scope.list.per_page * $scope.list.current) - 1
|
36
|
+
|
37
|
+
|
38
|
+
# Init variables
|
39
|
+
$scope.keys = []
|
40
|
+
$scope.key = {type: "empty"}
|
41
|
+
$scope.list = {}
|
42
|
+
|
43
|
+
db = localStorageService
|
44
|
+
|
45
|
+
$scope.config =
|
46
|
+
connection: db.get("connection") || "127.0.0.1:6379"
|
47
|
+
database: parseInt(db.get("database")) || 0
|
48
|
+
databases: [0..15]
|
49
|
+
open: ->
|
50
|
+
$scope.config.show = true
|
51
|
+
close: ->
|
52
|
+
$scope.config.show = false
|
53
|
+
save: ->
|
54
|
+
db.add("connection", $scope.config.connection)
|
55
|
+
db.add("database", $scope.config.database)
|
56
|
+
$scope.api = API($scope.config.connection, $scope.config.database)
|
57
|
+
|
58
|
+
$scope.fetchKeys()
|
59
|
+
$scope.show($scope.key)
|
60
|
+
|
61
|
+
$scope.config.close()
|
62
|
+
opts:
|
63
|
+
backdropFade: true
|
64
|
+
dialogFade: true
|
65
|
+
|
66
|
+
$scope.api = API($scope.config.connection, $scope.config.database)
|
67
|
+
|
68
|
+
|
69
|
+
# Scope functions
|
70
|
+
$scope.fetchKeys = ->
|
71
|
+
$scope.keys = $scope.api.keysTree()
|
72
|
+
|
73
|
+
$scope.show = (key) ->
|
74
|
+
key.open = true
|
75
|
+
$scope.api.get(key: key.full).then((e) ->
|
76
|
+
$scope.key = e
|
77
|
+
|
78
|
+
switch e.type
|
79
|
+
when "list"
|
80
|
+
$scope.list =
|
81
|
+
per_page: db.get("per_page") || 100
|
82
|
+
current: 1
|
83
|
+
max: 10
|
84
|
+
|
85
|
+
updateList()
|
86
|
+
)
|
87
|
+
|
88
|
+
|
89
|
+
$scope.setPerPage = (i) ->
|
90
|
+
db.add("per_page", i)
|
91
|
+
$scope.list.per_page = i
|
92
|
+
$scope.list.current = 1
|
93
|
+
updateList()
|
94
|
+
fetchValue()
|
95
|
+
|
96
|
+
$scope.deleteKey = (key) ->
|
97
|
+
title = "Are you sure?"
|
98
|
+
msg = "Are you sure you want to delete key \n #{key.name}"
|
99
|
+
btns = [
|
100
|
+
{result:'cancel', label: 'Cancel'}
|
101
|
+
{result:'delete', label: 'Delete', cssClass: 'btn-danger'}
|
102
|
+
]
|
103
|
+
|
104
|
+
$dialog.messageBox(title, msg, btns)
|
105
|
+
.open()
|
106
|
+
.then((result) ->
|
107
|
+
if result == "delete"
|
108
|
+
$scope.api.delete(key: key.name)
|
109
|
+
$scope.show($scope.key)
|
110
|
+
)
|
111
|
+
|
112
|
+
$scope.deleteAll = ->
|
113
|
+
title = "Are you sure?"
|
114
|
+
msg = "Are you sure you want to delete ALL keys matching \n #{$scope.key.full}"
|
115
|
+
btns = [
|
116
|
+
{result:'cancel', label: 'Cancel'}
|
117
|
+
{result:'delete', label: 'Delete ALL', cssClass: 'btn-danger'}
|
118
|
+
]
|
119
|
+
|
120
|
+
$dialog.messageBox(title, msg, btns)
|
121
|
+
.open()
|
122
|
+
.then((result) ->
|
123
|
+
if result == "delete"
|
124
|
+
$scope.api.delete(key: $scope.key.full)
|
125
|
+
$scope.show($scope.key)
|
126
|
+
)
|
127
|
+
|
128
|
+
|
129
|
+
|
130
|
+
# Scope watchers
|
131
|
+
$scope.$watch "list.current", () ->
|
132
|
+
if $scope.key.type == "list"
|
133
|
+
updateList()
|
134
|
+
fetchValue()
|
135
|
+
|
136
|
+
|
137
|
+
# Init
|
138
|
+
$scope.fetchKeys()
|
139
|
+
|
140
|
+
|
@@ -0,0 +1,179 @@
|
|
1
|
+
doctype html
|
2
|
+
html ng-app="browser"
|
3
|
+
head
|
4
|
+
title Redis Browser
|
5
|
+
|
6
|
+
script type="text/javascript" src="/js/angular.min.js"
|
7
|
+
script type="text/javascript" src="/js/ui-bootstrap-tpls-0.2.0.min.js"
|
8
|
+
script type="text/javascript" src="/js/localStorageModule.js"
|
9
|
+
script type="text/javascript" src="/js/app.js"
|
10
|
+
|
11
|
+
link rel="stylesheet" href="/css/bootstrap.min.css"
|
12
|
+
link rel="stylesheet" href="/css/app.css"
|
13
|
+
|
14
|
+
script type="text/ng-template" id="nav-tree-item.html"
|
15
|
+
span ng-show="key.children.length > 0"
|
16
|
+
button.btn.tree-toggle ng-hide="key.open" ng-click="key.open = true" +
|
17
|
+
button.btn.tree-toggle ng-show="key.open" ng-click="key.open = false" -
|
18
|
+
span ng-show="key.children.length == 0" -
|
19
|
+
|
20
|
+
a href="#" ng-click="show(key)" {{ key.name }}
|
21
|
+
|
22
|
+
ul.tree ng-show="key.open"
|
23
|
+
li ng-repeat="key in key.children" ng-include="'nav-tree-item.html'"
|
24
|
+
|
25
|
+
|
26
|
+
|
27
|
+
body ng-controller="BrowserCtrl"
|
28
|
+
div modal="config.show" close="config.close()" options="config.opts"
|
29
|
+
.form-horizontal
|
30
|
+
.modal-header
|
31
|
+
button.close type="button" ng-click="config.close()" ×
|
32
|
+
h4 Configure Redis Connection
|
33
|
+
.modal-body
|
34
|
+
.control-group
|
35
|
+
label.control-label for="config-connection" Connection
|
36
|
+
.controls
|
37
|
+
input type="text" id="config-connection" ng-model="config.connection"
|
38
|
+
span.help-block
|
39
|
+
| Examples:
|
40
|
+
code 127.0.0.1:6379
|
41
|
+
| ,
|
42
|
+
code= "/tmp/redis.sock"
|
43
|
+
| etc.
|
44
|
+
|
45
|
+
.control-group
|
46
|
+
label.control-label for="config-database" Database
|
47
|
+
.controls
|
48
|
+
select id="config-database" ng-model="config.database" ng-options="i for i in config.databases"
|
49
|
+
|
50
|
+
.modal-footer
|
51
|
+
button.btn.btn-success type="submit" ng-click="config.save()" Save
|
52
|
+
|
53
|
+
.navbar.navbar-inverse.navbar-fixed-top
|
54
|
+
.navbar-inner
|
55
|
+
.container-fluid
|
56
|
+
button.btn.btn-navbar type="button" data-toggle="collapse" data-target=".nav-collapse"
|
57
|
+
span.icon-bar
|
58
|
+
span.icon-bar
|
59
|
+
a.brand href="/" Redis Browser
|
60
|
+
|
61
|
+
.nav-collapse.collapse
|
62
|
+
p.pull-right
|
63
|
+
button.btn.btn-success ng-click="config.open()" Configure
|
64
|
+
p.navbar-text.pull-right.connection-info
|
65
|
+
' Connected to
|
66
|
+
strong {{ config.connection }}
|
67
|
+
|
68
|
+
|
69
|
+
.container-fluid
|
70
|
+
.row-fluid
|
71
|
+
.span3
|
72
|
+
.well.sidebar-nav
|
73
|
+
ul.nav.nav-list
|
74
|
+
li.nav-header
|
75
|
+
' Keys
|
76
|
+
button.btn.btn-mini.pull-right ng-click="fetchKeys()" Reload
|
77
|
+
ul.tree
|
78
|
+
li ng-repeat="key in keys" ng-include="'nav-tree-item.html'"
|
79
|
+
.span9
|
80
|
+
h4
|
81
|
+
' {{ key.full }}
|
82
|
+
small {{ key.type }}
|
83
|
+
|
84
|
+
div ng-switch="key.type"
|
85
|
+
pre ng-switch-when="string" {{ key.value }}
|
86
|
+
|
87
|
+
div ng-switch-when="set"
|
88
|
+
table.table.table-striped.table-bordered.value-list
|
89
|
+
tr ng-repeat="e in key.values"
|
90
|
+
td ng-switch="e.type"
|
91
|
+
pre ng-switch-when="json" {{ e.value | json }}
|
92
|
+
pre ng-switch-when="string" {{ e.value }}
|
93
|
+
|
94
|
+
div ng-switch-when="zset"
|
95
|
+
table.table.table-striped.table-bordered.value-list
|
96
|
+
tr
|
97
|
+
th Value
|
98
|
+
th.value-zset-score Score
|
99
|
+
tr ng-repeat="e in key.values"
|
100
|
+
td ng-switch="e.type"
|
101
|
+
pre ng-switch-when="json" {{ e.value | json }}
|
102
|
+
pre ng-switch-when="string" {{ e.value }}
|
103
|
+
td {{ e.score }}
|
104
|
+
|
105
|
+
|
106
|
+
div ng-switch-when="hash"
|
107
|
+
table.table.table-striped.table-bordered.value-list
|
108
|
+
tr
|
109
|
+
th Key
|
110
|
+
th Value
|
111
|
+
tr ng-repeat="(k,e) in key.value"
|
112
|
+
td {{ k }}
|
113
|
+
td ng-switch="e.type"
|
114
|
+
pre ng-switch-when="json" {{ e.value | json }}
|
115
|
+
pre ng-switch-when="string" {{ e.value }}
|
116
|
+
|
117
|
+
div ng-switch-when="list"
|
118
|
+
.alert
|
119
|
+
' Showing
|
120
|
+
strong
|
121
|
+
' {{ list.per_page }}
|
122
|
+
' items from
|
123
|
+
strong
|
124
|
+
' {{ list.start }}
|
125
|
+
' to
|
126
|
+
strong
|
127
|
+
' {{ list.stop }}
|
128
|
+
' out of
|
129
|
+
strong
|
130
|
+
' {{ key.length }}
|
131
|
+
' ( {{ list.pages }} pages )
|
132
|
+
|
133
|
+
.row-fluid
|
134
|
+
.span8
|
135
|
+
pagination boundary-links="true" num-pages="list.pages" current-page="list.current" max-size="list.max"
|
136
|
+
|
137
|
+
.span4
|
138
|
+
.dropdown.per-page
|
139
|
+
a.dropdown-toggle
|
140
|
+
| {{ list.per_page }} per page
|
141
|
+
ul.dropdown-menu
|
142
|
+
li ng-repeat="i in [10,20,50,100,200]"
|
143
|
+
a ng-click="setPerPage(i)" {{ i }}
|
144
|
+
|
145
|
+
table.table.table-striped.table-bordered.value-list
|
146
|
+
tr
|
147
|
+
th.value-list-index Index
|
148
|
+
th Value
|
149
|
+
tr ng-repeat="e in key.values"
|
150
|
+
td {{ e.index }}
|
151
|
+
td ng-switch="e.type"
|
152
|
+
pre ng-switch-when="json" {{ e.value | json }}
|
153
|
+
pre ng-switch-when="string" {{ e.value }}
|
154
|
+
|
155
|
+
pagination boundary-links="true" num-pages="list.pages" current-page="list.current" max-size="list.max"
|
156
|
+
|
157
|
+
span.alert.alert-success ng-switch-when="empty" Select something on the left
|
158
|
+
|
159
|
+
div ng-switch-default=""
|
160
|
+
table.table.table-striped.table-bordered
|
161
|
+
tr
|
162
|
+
th Keys
|
163
|
+
th.keys-search
|
164
|
+
input.input-medium.search-query type="text" ng-model="query" placeholder="Search"
|
165
|
+
tr ng-repeat="e in key.values | filter:query"
|
166
|
+
td
|
167
|
+
a href="#" ng-click="show(e)" {{ e.name }}
|
168
|
+
td
|
169
|
+
button.btn.btn-danger ng-click="deleteKey(e)" Delete
|
170
|
+
tr
|
171
|
+
td
|
172
|
+
td
|
173
|
+
button.btn.btn-danger ng-click="deleteAll()" Delete ALL
|
174
|
+
|
175
|
+
|
176
|
+
/ span.alert.alert-danger Key not found
|
177
|
+
|
178
|
+
|
179
|
+
|