memcached-manager 0.4.0 → 1.0.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.
Files changed (67) hide show
  1. checksums.yaml +13 -5
  2. data/.travis.yml +1 -1
  3. data/CONTRIBUTING.md +4 -4
  4. data/Dockerfile +7 -0
  5. data/Gemfile +0 -1
  6. data/Gemfile.lock +23 -19
  7. data/README.rdoc +8 -5
  8. data/Rakefile +6 -6
  9. data/VERSION +1 -1
  10. data/features/api/run_command.feature +6 -0
  11. data/features/api/search_memcached_keys.feature +6 -0
  12. data/features/step_definitions/api/create_memcached_key.rb +1 -1
  13. data/features/step_definitions/api/list_memcached_keys.rb +1 -0
  14. data/features/step_definitions/api/run_command.rb +12 -0
  15. data/features/step_definitions/api/search_memcached_keys.rb +6 -0
  16. data/features/step_definitions/webapp/create_memcached_key.rb +13 -7
  17. data/features/step_definitions/webapp/delete_memcached_key.rb +7 -13
  18. data/features/step_definitions/webapp/edit_configs.rb +7 -0
  19. data/features/support/env.rb +3 -2
  20. data/features/webapp/edit_configs.feature +9 -0
  21. data/features/webapp/edit_memcached_key.feature +1 -1
  22. data/fig.yml +13 -0
  23. data/githubpage_idea +23 -0
  24. data/lib/api.rb +25 -7
  25. data/lib/extensions.rb +6 -0
  26. data/lib/extensions/memcached_command.rb +14 -0
  27. data/lib/extensions/memcached_connection.rb +9 -0
  28. data/lib/extensions/memcached_inspector.rb +12 -5
  29. data/lib/extensions/memcached_settings.rb +2 -2
  30. data/lib/public/images/favicon.png +0 -0
  31. data/lib/public/images/glyphicons-halflings.png +0 -0
  32. data/lib/public/images/logo.png +0 -0
  33. data/lib/public/images/org-logo.png +0 -0
  34. data/lib/public/images/search.png +0 -0
  35. data/lib/public/javascripts/angular/controllers.js +48 -3
  36. data/lib/public/javascripts/angular/filters.js +85 -0
  37. data/lib/public/javascripts/angular/routes.js +26 -0
  38. data/lib/public/javascripts/angular/services/notification.js +41 -6
  39. data/lib/public/javascripts/angular/services/query_params_singleton.js +10 -0
  40. data/lib/public/javascripts/angular/services/resources.js +13 -0
  41. data/lib/public/javascripts/application.js +38 -1
  42. data/lib/public/javascripts/humanize.js +473 -0
  43. data/lib/public/javascripts/humanize_duration.js +329 -0
  44. data/lib/public/javascripts/jquery-terminal.js +4335 -0
  45. data/lib/public/javascripts/underscore.js +5 -0
  46. data/lib/public/stylesheets/app.css +196 -10
  47. data/lib/public/stylesheets/buttons.css +107 -0
  48. data/lib/public/stylesheets/inputs.css +119 -0
  49. data/lib/public/stylesheets/jquery-terminal.css +184 -0
  50. data/lib/public/stylesheets/media_queries.css +162 -0
  51. data/lib/public/templates/config.html.erb +8 -0
  52. data/lib/public/templates/edit.html.erb +5 -3
  53. data/lib/public/templates/keys.html.erb +42 -31
  54. data/lib/public/templates/new.html.erb +6 -4
  55. data/lib/public/templates/show.html.erb +1 -1
  56. data/lib/public/templates/stats.html.erb +1 -2
  57. data/lib/routes.rb +3 -0
  58. data/lib/views/index.erb +24 -3
  59. data/lib/views/layout.erb +14 -1
  60. data/memcached-manager.gemspec +31 -5
  61. data/spec/lib/extensions/api_response_spec.rb +9 -7
  62. data/spec/lib/extensions/memcached_command_spec.rb +13 -0
  63. data/spec/lib/extensions/memcached_connection_spec.rb +9 -4
  64. data/spec/lib/extensions/memcached_inspector_spec.rb +38 -17
  65. data/spec/lib/extensions/memcached_settings_spec.rb +16 -16
  66. data/spec/spec_helper.rb +2 -4
  67. metadata +48 -21
@@ -0,0 +1,184 @@
1
+ /*
2
+ * This css file is part of jquery terminal
3
+ *
4
+ * Licensed under GNU LGPL Version 3 license
5
+ * Copyright (c) 2011-2013 Jakub Jankiewicz <http://jcubic.pl>
6
+ *
7
+ */
8
+ .terminal .terminal-output .format, .cmd .format,
9
+ .cmd .prompt, .cmd .prompt div, .terminal .terminal-output div div{
10
+ display: inline-block;
11
+ }
12
+ .cmd .clipboard {
13
+ position: absolute;
14
+ bottom: 0;
15
+ left: 0;
16
+ opacity: 0.01;
17
+ filter: alpha(opacity = 0.01);
18
+ filter: progid:DXImageTransform.Microsoft.Alpha(opacity=0.01);
19
+ width: 2px;
20
+ }
21
+ .cmd > .clipboard {
22
+ position: fixed;
23
+ }
24
+ .terminal {
25
+ padding: 10px;
26
+ position: relative;
27
+ overflow: hidden;
28
+ }
29
+ .cmd {
30
+ padding: 0;
31
+ margin: 0;
32
+ height: 1.3em;
33
+ /*margin-top: 3px; */
34
+ }
35
+ .cmd .cursor.blink {
36
+ -webkit-animation: blink 1s infinite steps(1, start);
37
+ -moz-animation: blink 1s infinite steps(1, start);
38
+ -ms-animation: blink 1s infinite steps(1, start);
39
+ animation: blink 1s infinite steps(1, start);
40
+ }
41
+ @keyframes blink {
42
+ 0%, 100% {
43
+ background-color: #000;
44
+ color: #0c0;
45
+ }
46
+ 50% {
47
+ background-color: #bbb; /* not #0c0 because it's seem there is Google Chrome bug */
48
+ color: #000;
49
+ }
50
+ }
51
+ @-webkit-keyframes blink {
52
+ 0%, 100% {
53
+ background-color: #000;
54
+ color: #0c0;
55
+ }
56
+ 50% {
57
+ background-color: #bbb;
58
+ color: #000;
59
+ }
60
+ }
61
+ @-ms-keyframes blink {
62
+ 0%, 100% {
63
+ background-color: #000;
64
+ color: #0c0;
65
+ }
66
+ 50% {
67
+ background-color: #bbb;
68
+ color: #000;
69
+ }
70
+ }
71
+ @-moz-keyframes blink {
72
+ 0%, 100% {
73
+ background-color: #000;
74
+ color: #0c0;
75
+ }
76
+ 50% {
77
+ background-color: #bbb;
78
+ color: #000;
79
+ }
80
+ }
81
+ .terminal .terminal-output div div, .cmd .prompt {
82
+ display: block;
83
+ line-height: 14px;
84
+ height: auto;
85
+ }
86
+ .cmd .prompt {
87
+ float: left;
88
+ }
89
+ .terminal, .cmd {
90
+ font-family: FreeMono, monospace;
91
+ color: #0c0;
92
+ background-color: #000;
93
+ font-size: 12px;
94
+ line-height: 14px;
95
+ }
96
+ .terminal-output > div {
97
+ /*padding-top: 3px;*/
98
+ min-height: 14px;
99
+ }
100
+ .terminal .terminal-output div span {
101
+ display: inline-block;
102
+ }
103
+ .cmd span {
104
+ float: left;
105
+ /*display: inline-block; */
106
+ }
107
+ .terminal .inverted, .cmd .inverted, .cmd .cursor.blink {
108
+ background-color: #0c0;
109
+ color: #000;
110
+ }
111
+ .terminal .terminal-output div div::-moz-selection,
112
+ .terminal .terminal-output div span::-moz-selection,
113
+ .terminal .terminal-output div div a::-moz-selection {
114
+ background-color: #0c0;
115
+ color: #000;
116
+ }
117
+ .terminal .terminal-output div div::selection,
118
+ .terminal .terminal-output div div a::selection,
119
+ .terminal .terminal-output div span::selection,
120
+ .cmd > span::selection,
121
+ .cmd .prompt span::selection {
122
+ background-color: #0c0;
123
+ color: #000;
124
+ }
125
+ .terminal .terminal-output div.error, .terminal .terminal-output div.error div {
126
+ color: red;
127
+ }
128
+ .tilda {
129
+ position: fixed;
130
+ top: 0;
131
+ left: 0;
132
+ width: 100%;
133
+ z-index: 1100;
134
+ }
135
+ .clear {
136
+ clear: both;
137
+ }
138
+ .terminal a {
139
+ color: #0F60FF;
140
+ }
141
+ .terminal a:hover {
142
+ color: red;
143
+ }
144
+
145
+ @keyframes blink {
146
+ 0% { opacity: 1; }
147
+ 25% { opacity: 0; }
148
+ 50% { opacity: 0; }
149
+ 100% { opacity: 1; }
150
+ }
151
+ @-webkit-keyframes blink {
152
+ 0% { opacity: 1; }
153
+ 25% { opacity: 0; }
154
+ 50% { opacity: 0; }
155
+ 100% { opacity: 1; }
156
+ }
157
+ @-ms-keyframes blink {
158
+ 0% { opacity: 1; }
159
+ 25% { opacity: 0; }
160
+ 50% { opacity: 0; }
161
+ 100% { opacity: 1; }
162
+ }
163
+ @-moz-keyframes blink {
164
+ 0% { opacity: 1; }
165
+ 25% { opacity: 0; }
166
+ 50% { opacity: 0; }
167
+ 100% { opacity: 1; }
168
+ }
169
+ .prompt, .command {
170
+ color: #0c0;
171
+ text-shadow: 0 0 3px rgba(0,100,0,50);
172
+ }
173
+ .cursor {
174
+ background: #0c0;
175
+ animation: blink 1s linear infinite;
176
+ -webkit-animation: blink 1s infinite linear;
177
+ -ms-animation: blink 1s infinite linear;
178
+ -moz-animation: blink 1s infinite linear;
179
+ -webkit-box-shadow: 0 0 5px rgba(0,100,0,50);
180
+ -moz-box-shadow: 0 0 5px rgba(0,100,0,50);
181
+ -ms-box-shadow: 0 0 5px rgba(0,100,0,50);
182
+ -o-box-shadow: 0 0 5px rgba(0,100,0,50);
183
+ box-shadow: 0 0 5px rgba(0,100,0,50);
184
+ }
@@ -0,0 +1,162 @@
1
+ @media only screen and (min-width: 768px) and (max-width: 959px) {
2
+ .menu-container {
3
+ border-bottom: 1px solid #4f4745;
4
+ -moz-border-radius:0px 0px 7px 7px;
5
+ border-radius:0px 0px 7px 7px;
6
+ background-color: #666;
7
+ height: 42px;
8
+ width: 456px;
9
+ }
10
+
11
+ .green-desktop {
12
+ text-shadow:-1px -1px 0 #2c4e4a;
13
+ background: #448780;
14
+ border:1px solid #2c4e4a;
15
+ -webkit-border-radius:5px;
16
+ -moz-border-radius:5px;
17
+ border-radius:5px;
18
+ -webkit-box-shadow:0 1px 0 rgba(255, 255, 255, .5) inset, 0 -1px 0 rgba(255, 255, 255, .1) inset, 0 4px 0 #2c4e4a, 0 4px 2px rgba(0, 0, 0, .5);
19
+ -moz-box-shadow:0 1px 0 rgba(255, 255, 255, .5) inset, 0 -1px 0 rgba(255, 255, 255, .1) inset, 0 4px 0 #2c4e4a, 0 4px 2px rgba(0, 0, 0, .5);
20
+ box-shadow:0 1px 0 rgba(255, 255, 255, .5) inset, 0 -1px 0 rgba(255, 255, 255, .1) inset, 0 4px 0 #2c4e4a, 0 4px 2px rgba(0, 0, 0, .5);
21
+ }
22
+
23
+ .green-desktop:hover, .green:focus {
24
+ background: #569c95;
25
+ }
26
+ .push_button {
27
+ margin: 0 6px 0 6px;
28
+ float: left;
29
+ letter-spacing: 1px;
30
+ position: relative;
31
+ width: 100px;
32
+ font-size: 13px;
33
+ font-weight: 600;
34
+ height: 30px;
35
+ text-align:center;
36
+ color: #FFF;
37
+ text-decoration: none;
38
+ line-height: 33px;
39
+ font-family: "Lucida Grande", "Lucida Sans Unicode", Helvetica, Arial, Verdana, sans-serif;
40
+ display: block;
41
+ }
42
+
43
+ .push_button:active {
44
+ -webkit-box-shadow:0 1px 0 rgba(255, 255, 255, .5) inset, 0 -1px 0 rgba(255, 255, 255, .1) inset;
45
+ top:5px;
46
+ }
47
+
48
+ input.green-input {
49
+ width: 206px;
50
+ }
51
+
52
+ .logo {
53
+ width: 240px;
54
+ }
55
+ }
56
+
57
+ @media (min-width: 960px) {
58
+ .menu-container {
59
+ max-width: 456px;
60
+ border-bottom: 1px solid #4f4745;
61
+ -moz-border-radius:0px 0px 7px 7px;
62
+ border-radius:0px 0px 7px 7px;
63
+ background-color: #666;
64
+ height: 42px;
65
+ width: 100%;
66
+ }
67
+
68
+ .push_button {
69
+ margin: 0 6px 0 6px;
70
+ float: left;
71
+ letter-spacing: 1px;
72
+ position: relative;
73
+ width: 100px;
74
+ font-size: 13px;
75
+ font-weight: 600;
76
+ height: 30px;
77
+ text-align:center;
78
+ color: #FFF;
79
+ text-decoration: none;
80
+ line-height: 33px;
81
+ font-family: "Lucida Grande", "Lucida Sans Unicode", Helvetica, Arial, Verdana, sans-serif;
82
+ display: block;
83
+ }
84
+
85
+ .push_button:active {
86
+ -webkit-box-shadow:0 1px 0 rgba(255, 255, 255, .5) inset, 0 -1px 0 rgba(255, 255, 255, .1) inset;
87
+ top:5px;
88
+ }
89
+
90
+ .green-desktop {
91
+ text-shadow:-1px -1px 0 #2c4e4a;
92
+ background: #448780;
93
+ border:1px solid #2c4e4a;
94
+ -webkit-border-radius:5px;
95
+ -moz-border-radius:5px;
96
+ border-radius:5px;
97
+ -webkit-box-shadow:0 1px 0 rgba(255, 255, 255, .5) inset, 0 -1px 0 rgba(255, 255, 255, .1) inset, 0 4px 0 #2c4e4a, 0 4px 2px rgba(0, 0, 0, .5);
98
+ -moz-box-shadow:0 1px 0 rgba(255, 255, 255, .5) inset, 0 -1px 0 rgba(255, 255, 255, .1) inset, 0 4px 0 #2c4e4a, 0 4px 2px rgba(0, 0, 0, .5);
99
+ box-shadow:0 1px 0 rgba(255, 255, 255, .5) inset, 0 -1px 0 rgba(255, 255, 255, .1) inset, 0 4px 0 #2c4e4a, 0 4px 2px rgba(0, 0, 0, .5);
100
+ }
101
+ .green-desktop:hover, .green:focus {
102
+ background: #569c95;
103
+ }
104
+ }
105
+
106
+ @media only screen and (max-width: 767px) {
107
+ .menu-container {
108
+ background-color: #2c4e4a;
109
+ width: 300px;
110
+ position: relative;
111
+ }
112
+
113
+ .menu-container a:hover, a:focus {
114
+ text-decoration: underline;
115
+ background-color: #448780;
116
+ }
117
+
118
+ .menu-container a {
119
+ display: block;
120
+ padding: 10px;
121
+ color: #fff;
122
+ }
123
+
124
+ .menu-container .spaced-icon{
125
+ margin-right: 5px;
126
+ }
127
+ }
128
+
129
+ @media only screen and (min-width: 480px) and (max-width: 767px) {
130
+ input.green-input {
131
+ width: 390px;
132
+ }
133
+
134
+ .logo {
135
+ width: 420px;
136
+ }
137
+
138
+ #right-side {
139
+ width: 420px;
140
+ }
141
+
142
+ .menu-container {
143
+ background-color: #2c4e4a;
144
+ width: 420px;
145
+ position: relative;
146
+ }
147
+
148
+ .menu-container a:hover, a:focus {
149
+ text-decoration: underline;
150
+ background-color: #448780;
151
+ }
152
+
153
+ .menu-container a {
154
+ display: block;
155
+ padding: 10px;
156
+ color: #fff;
157
+ }
158
+
159
+ .menu-container .spaced-icon{
160
+ margin-right: 5px;
161
+ }
162
+ }
@@ -0,0 +1,8 @@
1
+ <h1>Settings</h1>
2
+ <form ng-controller='UpdateConfigController' ng-submit='updateConfig()'>
3
+ <input ng-model='config.host' placeholder='Host' type='text' class='brown-input'></textarea>
4
+ <input ng-model='config.port' placeholder='Port' type='text' class='brown-input'></textarea>
5
+ <div class='form-button-container'>
6
+ <button class="push green form-button">Update settings</button>
7
+ </div>
8
+ </form>
@@ -1,6 +1,8 @@
1
- <h2>Edit key</h2>
1
+ <h1>Edit key</h1>
2
2
  <form ng-controller='UpdateKeyController' ng-submit='updateKey()'>
3
3
  <p>Key: {{pair.key}}</p>
4
- <textarea ng-model='pair.value' placeholder='Value' type='text'></textarea>
5
- <button>Edit</button>
4
+ <textarea ng-model='pair.value' placeholder='Value' type='text' class='brown-input'></textarea>
5
+ <div class='form-button-container'>
6
+ <button class='push green form-button'>Update key</button>
7
+ </div>
6
8
  </form>
@@ -1,36 +1,47 @@
1
- <section>
2
- <h3 ng-click="showKeys()">memcached manager</h3>
3
- <hr>
4
- <section id="key-menu">
5
- <div id="key-text">
6
- <h3>keys</h3>
7
- </div><!-- key-text -->
1
+ <section id='menu'>
2
+ <div class='nav-keys'>
3
+ <img src="images/logo.png" class='logo' />
4
+ <input id="search-box" ng-model='query' class='green-input search' ng-change='filterByQuery()' placeholder='Search keys with a regexp' type='text'>
5
+ <div ng-controller='StatsController'>
6
+ <div ng-switch on='connection.connected'>
7
+ <div ng-switch-when='true' class='left-nav-bottom'>
8
+ A total of
9
+ <span class="highlight">{{ stats | configs:"numberOfKeys" }} keys</span>
10
+ using
11
+ <span class="highlight">
12
+ {{ stats | configs:"bytes" | humanize_size }}({{ stats | configs:"percentUsage" }}%) of {{ stats | configs:"maxBytes" | humanize_size }}.
13
+ </span>
14
+ </div>
8
15
 
9
- <div id="key-new">
10
- <a href="#/new" class="button">New key</a><!-- button -->
16
+ <div ng-switch-when='false' class='left-nav-bottom'>
17
+ The memcached server is out of reach.
18
+ </div>
19
+ </div>
11
20
  </div>
12
- </section>
21
+ <section id="key-keys">
22
+ <table id='keys'>
23
+ <tr>
24
+ <th id="key">Key</th>
25
+ <th id="expires-in">Expires in</th>
26
+ <th id="size">Size</th>
27
+ <th id="actions">Actions</th>
28
+ </tr>
13
29
 
14
- <div class="clear"></div>
15
-
16
- <section id="key-keys">
17
- <ul>
18
- <li ng-repeat='key in keys' class="key">
19
- <div class="key-info">
20
- <div class="key-header">
21
- <a class="key-title" href="#/key/{{ key.key }}">{{ key.key }}</a><!-- key-title -->
22
- </div><!-- key-header -->
23
- <div id="key-data">
24
- Size: {{ key.bytes }}B
25
- </div><!-- key-data -->
26
- </div><!-- key-info -->
27
-
28
- <div class="key-actions">
29
- <a ng-click="removeKey(key)" class="icon-remove pointer" ng-controller="DeleteKeyController"></a>
30
- <a href="#/edit/{{ key.key }}" class="icon-pencil"></a>
31
- </div><!-- key-actions -->
32
- </li><!-- key -->
33
- </ul>
34
- </section><!-- key-menu -->
30
+ <tr ng-repeat='key in keys'>
31
+ <td class='keys-key'>
32
+ <a class="key-title" href="#/key/{{ key.key }}">
33
+ {{ key.key | shortify_key }}
34
+ </a>
35
+ </td>
36
+ <td class='keys-expires-in'>{{ key | humanize_timestamp }}</td>
37
+ <td class='keys-size'><span> {{ key.bytes | humanize_size }}</span></td>
38
+ <td class='keys-actions'>
39
+ <a ng-click="removeKey(key)" class="icon-remove pointer" ng-controller="DeleteKeyController"></a>
40
+ <a href="#/edit/{{ key.key }}" class="icon-pencil"></a>
41
+ </td>
42
+ </tr>
43
+ </table>
44
+ </section><!-- key-menu -->
45
+ </div>
35
46
  <div class="clear"></div>
36
47
  </section>
@@ -1,6 +1,8 @@
1
- <h2>New key</h2>
1
+ <h1>New key</h1>
2
2
  <form ng-controller='CreateKeyController' ng-submit='createKey()'>
3
- <input ng-model='pair.key' placeholder='Key' type='text'>
4
- <textarea ng-model='pair.value' placeholder='Value' type='text'></textarea>
5
- <button>Create</button>
3
+ <input ng-model='pair.key' placeholder='Key' type='text' class='brown-input'>
4
+ <textarea ng-model='pair.value' placeholder='Value' type='text' class='brown-input'></textarea>
5
+ <div class='form-button-container'>
6
+ <button class="push green form-button">Create key</button>
7
+ </div>
6
8
  </form>