redis-browser 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+