redis-browser 0.1.0

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.
@@ -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()'>&times;</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">&lsaquo;</a> <a ng-click="next()" class="carousel-control right">&rsaquo;</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" -&nbsp;
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()" &times;
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
+