logster 1.2.11 → 1.3.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (126) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +18 -17
  3. data/.travis.yml +15 -16
  4. data/CHANGELOG.md +130 -130
  5. data/Gemfile +4 -4
  6. data/Guardfile +8 -8
  7. data/LICENSE.txt +22 -22
  8. data/README.md +99 -96
  9. data/Rakefile +24 -23
  10. data/assets/fonts/FontAwesome.otf +0 -0
  11. data/assets/fonts/fontawesome-webfont.eot +0 -0
  12. data/assets/fonts/fontawesome-webfont.svg +639 -639
  13. data/assets/fonts/fontawesome-webfont.ttf +0 -0
  14. data/assets/fonts/fontawesome-webfont.woff +0 -0
  15. data/assets/fonts/fontawesome-webfont.woff2 +0 -0
  16. data/assets/images/Icon-144_rounded.png +0 -0
  17. data/assets/images/Icon-144_square.png +0 -0
  18. data/assets/images/icon_144x144.png +0 -0
  19. data/assets/images/icon_64x64.png +0 -0
  20. data/assets/javascript/client-app.js +81 -0
  21. data/assets/javascript/vendor.js +5302 -0
  22. data/assets/stylesheets/client-app.css +1 -0
  23. data/assets/stylesheets/vendor.css +4 -0
  24. data/build_client_app.sh +12 -0
  25. data/client-app/.editorconfig +20 -0
  26. data/client-app/.ember-cli +9 -0
  27. data/client-app/.eslintignore +19 -0
  28. data/client-app/.eslintrc.js +46 -0
  29. data/client-app/.gitignore +23 -0
  30. data/client-app/.travis.yml +27 -0
  31. data/client-app/.watchmanconfig +3 -0
  32. data/client-app/README.md +57 -0
  33. data/client-app/app/app.js +14 -0
  34. data/client-app/app/components/message-info.js +18 -0
  35. data/client-app/app/components/message-row.js +45 -0
  36. data/client-app/app/components/panel-resizer.js +75 -0
  37. data/client-app/app/components/tab-contents.js +27 -0
  38. data/client-app/app/components/tab-link.js +5 -0
  39. data/client-app/app/components/tabbed-section.js +32 -0
  40. data/client-app/app/components/time-formatter.js +25 -0
  41. data/client-app/app/components/update-time.js +21 -0
  42. data/client-app/app/controllers/index.js +83 -0
  43. data/client-app/app/controllers/show.js +13 -0
  44. data/client-app/app/index.html +29 -0
  45. data/client-app/app/initializers/app-init.js +55 -0
  46. data/client-app/app/lib/preload.js +14 -0
  47. data/client-app/app/lib/utilities.js +140 -0
  48. data/client-app/app/models/message-collection.js +158 -0
  49. data/client-app/app/models/message.js +99 -0
  50. data/client-app/app/resolver.js +3 -0
  51. data/client-app/app/router.js +14 -0
  52. data/client-app/app/routes/index.js +53 -0
  53. data/client-app/app/routes/show.js +14 -0
  54. data/{assets/stylesheets → client-app/app/styles}/app.css +387 -390
  55. data/{assets/javascript → client-app/app}/templates/application.hbs +2 -2
  56. data/client-app/app/templates/components/message-info.hbs +44 -0
  57. data/{assets/javascript → client-app/app/templates}/components/message-row.hbs +17 -17
  58. data/client-app/app/templates/components/tabbed-section.hbs +10 -0
  59. data/client-app/app/templates/components/time-formatter.hbs +1 -0
  60. data/{assets/javascript → client-app/app}/templates/index.hbs +57 -57
  61. data/{assets/javascript → client-app/app}/templates/show.hbs +4 -4
  62. data/client-app/config/environment.js +51 -0
  63. data/client-app/config/optional-features.json +3 -0
  64. data/client-app/config/targets.js +18 -0
  65. data/client-app/ember-cli-build.js +29 -0
  66. data/client-app/package-lock.json +11365 -0
  67. data/client-app/package.json +56 -0
  68. data/client-app/testem.js +25 -0
  69. data/client-app/tests/index.html +34 -0
  70. data/client-app/tests/integration/components/message-info-test.js +26 -0
  71. data/client-app/tests/integration/components/message-row-test.js +26 -0
  72. data/client-app/tests/integration/components/panel-resizer-test.js +26 -0
  73. data/client-app/tests/integration/components/tab-contents-test.js +26 -0
  74. data/client-app/tests/integration/components/tab-link-test.js +26 -0
  75. data/client-app/tests/integration/components/tabbed-section-test.js +26 -0
  76. data/client-app/tests/integration/components/time-formatter-test.js +26 -0
  77. data/client-app/tests/integration/components/update-time-test.js +26 -0
  78. data/client-app/tests/test-helper.js +8 -0
  79. data/client-app/tests/unit/controllers/index-test.js +12 -0
  80. data/client-app/tests/unit/controllers/show-test.js +12 -0
  81. data/client-app/tests/unit/initializers/app-init-test.js +31 -0
  82. data/client-app/tests/unit/routes/index-test.js +11 -0
  83. data/client-app/tests/unit/routes/show-test.js +11 -0
  84. data/lib/examples/sidekiq_logster_reporter.rb +21 -21
  85. data/lib/logster.rb +54 -54
  86. data/lib/logster/base_store.rb +130 -130
  87. data/lib/logster/configuration.rb +25 -25
  88. data/lib/logster/ignore_pattern.rb +65 -65
  89. data/lib/logster/logger.rb +102 -101
  90. data/lib/logster/message.rb +227 -226
  91. data/lib/logster/middleware/debug_exceptions.rb +26 -26
  92. data/lib/logster/middleware/reporter.rb +56 -54
  93. data/lib/logster/middleware/viewer.rb +220 -251
  94. data/lib/logster/rails/railtie.rb +58 -58
  95. data/lib/logster/redis_store.rb +481 -477
  96. data/lib/logster/version.rb +3 -3
  97. data/lib/logster/web.rb +14 -14
  98. data/logster.gemspec +34 -33
  99. data/test/examples/test_sidekiq_reporter_example.rb +46 -46
  100. data/test/fake_data/Gemfile +4 -4
  101. data/test/fake_data/generate.rb +10 -10
  102. data/test/logster/middleware/test_reporter.rb +21 -21
  103. data/test/logster/middleware/test_viewer.rb +96 -70
  104. data/test/logster/test_base_store.rb +147 -147
  105. data/test/logster/test_ignore_pattern.rb +41 -41
  106. data/test/logster/test_logger.rb +74 -74
  107. data/test/logster/test_message.rb +34 -34
  108. data/test/logster/test_redis_rate_limiter.rb +230 -230
  109. data/test/logster/test_redis_store.rb +427 -414
  110. data/test/test_helper.rb +38 -37
  111. data/vendor/assets/javascripts/logster.js.erb +39 -39
  112. metadata +83 -24
  113. data/assets/javascript/app.js +0 -817
  114. data/assets/javascript/components/message-info.hbs +0 -47
  115. data/assets/javascript/components/panel-resizer.hbs +0 -0
  116. data/assets/javascript/components/tab-contents.hbs +0 -1
  117. data/assets/javascript/components/tab-link.hbs +0 -1
  118. data/assets/javascript/components/tabbed-section.hbs +0 -6
  119. data/assets/javascript/external/ember-template-compiler.js +0 -22346
  120. data/assets/javascript/external/ember.js +0 -58500
  121. data/assets/javascript/external/ember.min.js +0 -17
  122. data/assets/javascript/external/jquery.min.js +0 -5
  123. data/assets/javascript/external/lodash.min.js +0 -87
  124. data/assets/javascript/external/moment.min.js +0 -6
  125. data/assets/stylesheets/font-awesome.min.css +0 -4
  126. data/bower.json +0 -25
@@ -0,0 +1,99 @@
1
+ import { ajax, buildHashString } from "client-app/lib/utilities";
2
+ import Preload from "client-app/lib/preload";
3
+ import { computed } from "@ember/object";
4
+
5
+ export default Em.Object.extend({
6
+ MAX_LEN: 200,
7
+
8
+ expand() {
9
+ this.set("expanded", true);
10
+ },
11
+
12
+ solve() {
13
+ return ajax("/solve/" + this.get("key"), { type: "PUT" });
14
+ },
15
+
16
+ destroy() {
17
+ return ajax("/message/" + this.get("key"), { type: "DELETE" });
18
+ },
19
+
20
+ protect() {
21
+ this.set("protected", true);
22
+ return ajax("/protect/" + this.get("key"), { type: "PUT" });
23
+ },
24
+ unprotect() {
25
+ this.set("protected", false);
26
+ return ajax("/unprotect/" + this.get("key"), { type: "DELETE" });
27
+ },
28
+
29
+ showCount: computed("count", function() {
30
+ return this.get("count") > 1;
31
+ }),
32
+
33
+ hasMore: computed("message", "expanded", function() {
34
+ const message = this.get("message");
35
+ const expanded = this.get("expanded");
36
+
37
+ return !expanded && message.length > this.MAX_LEN;
38
+ }),
39
+
40
+ shareUrl: computed("key", function() {
41
+ return Preload.get("rootPath") + "/show/" + this.get("key");
42
+ }),
43
+
44
+ displayMessage: computed("message", "expanded", function() {
45
+ let message = this.get("message");
46
+ const expanded = this.get("expanded");
47
+
48
+ if (!expanded && message.length > this.MAX_LEN) {
49
+ message = message.substr(0, this.MAX_LEN);
50
+ }
51
+ return message;
52
+ }),
53
+
54
+ updateFromObject(other) {
55
+ // XXX Only updatable property is count right now
56
+ this.set("count", other.get("count"));
57
+ },
58
+
59
+ canSolve: computed(function() {
60
+ const backtrace = this.get("backtrace");
61
+ return (
62
+ this.get("env.application_version") && backtrace && backtrace.length > 0
63
+ );
64
+ }),
65
+
66
+ envTable: computed("env", function() {
67
+ return buildHashString(this.get("env"));
68
+ }),
69
+
70
+ rowClass: computed("severity", function() {
71
+ switch (this.get("severity")) {
72
+ case 0:
73
+ return "debug";
74
+ case 1:
75
+ return "info";
76
+ case 2:
77
+ return "warn";
78
+ case 3:
79
+ return "error";
80
+ case 4:
81
+ return "fatal";
82
+ }
83
+ }),
84
+
85
+ glyph: computed("severity", function() {
86
+ switch (this.get("severity")) {
87
+ case 0:
88
+ return "";
89
+ case 1:
90
+ return "";
91
+ case 2:
92
+ return "<i class='fa fa-exclamation-circle warning'></i>";
93
+ case 3:
94
+ return "<i class='fa fa-times-circle error'></i>";
95
+ case 4:
96
+ return "<i class='fa fa-times-circle fatal'></i>";
97
+ }
98
+ })
99
+ });
@@ -0,0 +1,3 @@
1
+ import Resolver from 'ember-resolver';
2
+
3
+ export default Resolver;
@@ -0,0 +1,14 @@
1
+ import EmberRouter from '@ember/routing/router';
2
+ import config from './config/environment';
3
+
4
+ const Router = EmberRouter.extend({
5
+ location: config.locationType,
6
+ rootURL: config.rootURL
7
+ });
8
+
9
+ Router.map(function() {
10
+ this.route("index", { path: "/" });
11
+ this.route("show", { path: "/show/:id" });
12
+ });
13
+
14
+ export default Router;
@@ -0,0 +1,53 @@
1
+ import Route from "@ember/routing/route";
2
+ import MessageCollection from "client-app/models/message-collection";
3
+ import { isHidden } from "client-app/lib/utilities";
4
+
5
+ export default Route.extend({
6
+ model() {
7
+ // TODO from preload json?
8
+ return MessageCollection.create();
9
+ },
10
+
11
+ setupController(controller, model) {
12
+ this._super(controller, model);
13
+ controller.setProperties({
14
+ showDebug: true,
15
+ showInfo: true,
16
+ showWarn: true,
17
+ showErr: true,
18
+ showFatal: true,
19
+ search: "",
20
+ initialized: true
21
+ });
22
+ model.reload();
23
+
24
+ let times = 0;
25
+ let backoff = 1;
26
+
27
+ this.refreshInterval = setInterval(() => {
28
+ times += 1;
29
+ const hidden = isHidden();
30
+ let load = !hidden;
31
+
32
+ if (hidden) {
33
+ if (times % backoff === 0) {
34
+ load = true;
35
+ if (backoff < 20) {
36
+ backoff++;
37
+ }
38
+ }
39
+ }
40
+ // refresh a lot less aggressively in background
41
+ if (load) {
42
+ model.loadMore();
43
+ if (!hidden) {
44
+ backoff = 1;
45
+ }
46
+ }
47
+ }, 3000);
48
+ },
49
+
50
+ deactivate() {
51
+ clearInterval(this.refreshInterval);
52
+ }
53
+ });
@@ -0,0 +1,14 @@
1
+ import Route from "@ember/routing/route";
2
+ import Message from "client-app/models/message";
3
+ import { preloadOrAjax } from "client-app/lib/utilities";
4
+
5
+ export default Route.extend({
6
+ model(params) {
7
+ return preloadOrAjax("/show/" + params.id + ".json");
8
+ },
9
+
10
+ setupController(controller, model) {
11
+ this._super(...arguments);
12
+ controller.set("model", Message.create(model));
13
+ }
14
+ });
@@ -1,390 +1,387 @@
1
- body {
2
- font-family: 'Roboto', Arial, 'Liberation Sans', 'DejaVu Sans', sans-serif;
3
- font-size: 12px;
4
- }
5
-
6
- pre {
7
- font-family: 'Roboto Mono', Consolas, Monaco, Ubuntu Mono, monospace;
8
- }
9
-
10
- table.env-table tbody tr td {
11
- border-top: none;
12
- line-height: 18px;
13
- vertical-align: top;
14
- }
15
-
16
- table.env-table, table.env-table table {
17
- border-spacing: 0;
18
- border-collapse: collapse;
19
- }
20
-
21
- table.env-table td {
22
- padding-right: 5px;
23
- }
24
-
25
- tbody tr {
26
- width: 98%;
27
- }
28
-
29
- tbody tr td {
30
- border-top: 1px #e9e9e9 solid;
31
- line-height: 25px;
32
- }
33
-
34
- .message-row:hover {
35
- background-color: #f8f8f8;
36
- cursor: pointer;
37
- }
38
-
39
- .message-row.selected {
40
- background-color: #dfdfdf;
41
- }
42
-
43
- th {
44
- text-align:left;
45
- padding-right: 10px;
46
- font-size: 12px;
47
- color: #222;
48
- padding-bottom: 8px;
49
- }
50
-
51
- td.time {
52
- font-size: 12px;
53
- color: #999;
54
- vertical-align: top;
55
- }
56
- .message {
57
- font-size: 13px;
58
- overflow: hidden;
59
- white-space: nowrap;
60
- text-overflow: ellipsis;
61
- padding-right: 10px;
62
- }
63
-
64
- th.count {
65
- width: 20px;
66
- }
67
-
68
- th.severity{
69
- width: 15px;
70
- }
71
-
72
- th.time{
73
- width: 90px;
74
- text-align: right;
75
- padding-right: 20px;
76
- }
77
-
78
- td.time{
79
- text-align: right;
80
- padding-right: 8px;
81
- }
82
-
83
- th.protected {
84
- width: 10px;
85
- }
86
-
87
- i.fatal {
88
- color: #E00;
89
- }
90
-
91
- i.error {
92
- color: #900;
93
- }
94
-
95
- i.warning {
96
- color: #FEB800;
97
- }
98
-
99
- .debug {
100
- color: #777;
101
- }
102
-
103
- td.count {
104
- text-align: right;
105
- padding-right: 4px;
106
- }
107
-
108
- .count span {
109
- font-size: 11px;
110
- font-weight: bold;
111
- }
112
-
113
- .action-panel .search input {
114
- border: 1px solid #DDD;
115
- padding: 3px;
116
- vertical-align: middle;
117
- }
118
-
119
- .regex input {
120
- margin-left: 2px !important;
121
- }
122
-
123
- tr.show-more {
124
- text-align: center;
125
- height: 30px;
126
- text-decoration: none;
127
- background-color: #ddd;
128
- cursor: pointer;
129
- font-size: 12px;
130
- }
131
-
132
- #bottom-panel{
133
- position: fixed;
134
- bottom: 0;
135
- left: 0;
136
- right: 100%;
137
- height: 300px;
138
- width: 100%;
139
- background-color: #F1F1F1;
140
- padding: 8px;
141
- font-size: 12px;
142
- }
143
-
144
- #bottom-panel.full {
145
- position: static;
146
- background-color: inherit;
147
- height: 90%;
148
- }
149
-
150
- #bottom-panel.full > div {
151
- padding-bottom: 40px;
152
- }
153
- #bottom-panel.full .tabs {
154
- display: none;
155
- }
156
-
157
- #bottom-panel.full .message-info {
158
- position: static;
159
- }
160
-
161
- #bottom-panel.full .message-info .content {
162
- display: block;
163
- position: static;
164
- }
165
-
166
- #bottom-panel.full .save, #bottom-panel.full .share {
167
- bottom: 10px;
168
- }
169
-
170
- #bottom-panel.full button.delete {
171
- display: none;
172
- }
173
-
174
- #bottom-panel.full .message-actions {
175
- position: fixed;
176
- height: 40px;
177
- width: 100%;
178
- left: 0;
179
- bottom: 0;
180
- background-color: #eee;
181
- border-top: 1px solid #dfdfdf;
182
- padding-left: 10px;
183
- }
184
-
185
- #bottom-panel.full .message-actions button {
186
- margin-top: 10px;
187
- }
188
-
189
-
190
-
191
- .message-actions {
192
- position: absolute;
193
- bottom: 3px;
194
- right: 30px;
195
- }
196
-
197
- .message-actions button {
198
- margin-right: 7px;
199
- }
200
-
201
- .message-actions .share {
202
- text-decoration: none;
203
- color: #333;
204
- }
205
-
206
- .divider {
207
- position: fixed;
208
- bottom: 310px;
209
- left: 0;
210
- right: 0;
211
- height: 10px;
212
- border-top: 1px solid #ddd;
213
- border-bottom: 1px solid #ddd;
214
- background-color: #fafafa;
215
- cursor: row-resize;
216
- z-index: 1;
217
- }
218
-
219
- .divider div {
220
- margin: auto;
221
- width: 24px;
222
- height: 1px;
223
- background-color: #ccc;
224
- position: relative;
225
- }
226
-
227
- .divider .line-1 {
228
- top: 3px;
229
- }
230
-
231
- .divider .line-2 {
232
- top: 4px;
233
- }
234
-
235
- .divider .line-3 {
236
- top: 5px;
237
- }
238
-
239
- #top-panel {
240
- position: fixed;
241
- top: 0;
242
- left: 0;
243
- right: 0;
244
- bottom: 320px;
245
- overflow: auto;
246
- }
247
-
248
- .message-info {
249
- position: absolute;
250
- border-bottom: 1px solid #DDD;
251
- bottom: 35px;
252
- top: 0;
253
- left: 0;
254
- right: 0;
255
- overflow: auto;
256
- }
257
-
258
- .action-panel {
259
- position: absolute;
260
- left: 0;
261
- right: 0;
262
- bottom: 0;
263
- height: 30px;
264
- font-weight: bold;
265
- }
266
- .action-panel input {
267
- position: relative;
268
- top: -1px;
269
- margin-left: 20px;
270
- vertical-align: sub;
271
- }
272
-
273
- .action-panel .clear {
274
- position: absolute;
275
- right: 30px;
276
- vertical-align: middle;
277
- }
278
-
279
- #log-table {
280
- border-collapse:collapse;
281
- margin: auto;
282
- width: 99%;
283
- table-layout: fixed;
284
- }
285
-
286
-
287
- .hidden {
288
- display: none;
289
- }
290
-
291
- .message-info pre {
292
- position: relative;
293
- margin: 10px;
294
- }
295
-
296
- #overlay {
297
- position: fixed;
298
- z-index: 99999;
299
- top: 0;
300
- bottom: 0;
301
- left: 0;
302
- right: 0;
303
- cursor: row-resize;
304
- opacity: 0;
305
- }
306
-
307
- .message-info .content {
308
- position: absolute;
309
- top: 5px;
310
- bottom: 35px;
311
- left: 5px;
312
- right: 5px;
313
- overflow: auto;
314
- display: none;
315
- }
316
-
317
- .message-info .content.active {
318
- display: block;
319
- }
320
-
321
-
322
- .tabs {
323
- position: absolute;
324
- bottom: 10px;
325
- left: 0;
326
- right: 0;
327
- list-style-type: none;
328
- border-top: 1px solid #ddd;
329
- margin: 0 0 5px;
330
- padding: 0 0 0 14px;
331
- }
332
- .tabs li {
333
- float: left;
334
- position: relative;
335
- padding-right: 5px;
336
- margin: 0;
337
- }
338
- .tabs a {
339
- position: relative;
340
- top: 4px;
341
- text-decoration: none;
342
- color: #333;
343
- border: 1px solid #ddd;
344
- border-top: none;
345
- border-bottom-left-radius: 5px;
346
- border-bottom-right-radius: 5px;
347
- padding: 4px;
348
- background-color: #e1e1e1;
349
- }
350
-
351
- .tabs a.active{
352
- border-top: 1px solid #f1f1f1;
353
- background-color: #f1f1f1;
354
- }
355
-
356
-
357
- .btn {
358
- display: inline-block;
359
- margin: 0;
360
- padding: 2px 12px;
361
- font-weight: 500;
362
- font-size: 1em;
363
- line-height: 18px;
364
- text-align: center;
365
- cursor: pointer;
366
- transition: all .25s;
367
- background-color: #DDD;
368
- text-decoration: none;
369
- border: none;
370
- color: #333;
371
- font-weight: normal;
372
- }
373
-
374
- .btn:hover {
375
- color: #000;
376
- background-color: #ccc;
377
- }
378
-
379
- .btn .fa {
380
- margin-right: 7px;
381
- }
382
-
383
- .btn:active {
384
- text-shadow: none;
385
- }
386
-
387
- .btn.danger:hover {
388
- background-color: #c63c1b;
389
- color: #EEE;
390
- }
1
+ body {
2
+ font-family: "Roboto", Arial, "Liberation Sans", "DejaVu Sans", sans-serif;
3
+ font-size: 12px;
4
+ }
5
+
6
+ pre {
7
+ font-family: "Roboto Mono", Consolas, Monaco, Ubuntu Mono, monospace;
8
+ }
9
+
10
+ table.env-table tbody tr td {
11
+ border-top: none;
12
+ line-height: 18px;
13
+ vertical-align: top;
14
+ }
15
+
16
+ table.env-table,
17
+ table.env-table table {
18
+ border-spacing: 0;
19
+ border-collapse: collapse;
20
+ }
21
+
22
+ table.env-table td {
23
+ padding-right: 5px;
24
+ }
25
+
26
+ tbody tr {
27
+ width: 98%;
28
+ }
29
+
30
+ tbody tr td {
31
+ border-top: 1px #e9e9e9 solid;
32
+ line-height: 25px;
33
+ }
34
+
35
+ .message-row:hover {
36
+ background-color: #f8f8f8;
37
+ cursor: pointer;
38
+ }
39
+
40
+ .message-row.selected {
41
+ background-color: #dfdfdf;
42
+ }
43
+
44
+ th {
45
+ text-align: left;
46
+ padding-right: 10px;
47
+ font-size: 12px;
48
+ color: #222;
49
+ padding-bottom: 8px;
50
+ }
51
+
52
+ td.time {
53
+ font-size: 12px;
54
+ color: #999;
55
+ vertical-align: top;
56
+ }
57
+ .message {
58
+ font-size: 13px;
59
+ overflow: hidden;
60
+ white-space: nowrap;
61
+ text-overflow: ellipsis;
62
+ padding-right: 10px;
63
+ }
64
+
65
+ th.count {
66
+ width: 20px;
67
+ }
68
+
69
+ th.severity {
70
+ width: 15px;
71
+ }
72
+
73
+ th.time {
74
+ width: 90px;
75
+ text-align: right;
76
+ padding-right: 20px;
77
+ }
78
+
79
+ td.time {
80
+ text-align: right;
81
+ padding-right: 8px;
82
+ }
83
+
84
+ th.protected {
85
+ width: 10px;
86
+ }
87
+
88
+ i.fatal {
89
+ color: #e00;
90
+ }
91
+
92
+ i.error {
93
+ color: #900;
94
+ }
95
+
96
+ i.warning {
97
+ color: #feb800;
98
+ }
99
+
100
+ .debug {
101
+ color: #777;
102
+ }
103
+
104
+ td.count {
105
+ text-align: right;
106
+ padding-right: 4px;
107
+ }
108
+
109
+ .count span {
110
+ font-size: 11px;
111
+ font-weight: bold;
112
+ }
113
+
114
+ .action-panel .search input {
115
+ border: 1px solid #ddd;
116
+ padding: 3px;
117
+ vertical-align: middle;
118
+ }
119
+
120
+ .regex input {
121
+ margin-left: 2px !important;
122
+ }
123
+
124
+ tr.show-more {
125
+ text-align: center;
126
+ height: 30px;
127
+ text-decoration: none;
128
+ background-color: #ddd;
129
+ cursor: pointer;
130
+ font-size: 12px;
131
+ }
132
+
133
+ #bottom-panel {
134
+ position: fixed;
135
+ bottom: 0;
136
+ left: 0;
137
+ right: 100%;
138
+ height: 300px;
139
+ width: 100%;
140
+ background-color: #f1f1f1;
141
+ padding: 8px;
142
+ font-size: 12px;
143
+ }
144
+
145
+ #bottom-panel.full {
146
+ position: static;
147
+ background-color: inherit;
148
+ height: 90%;
149
+ }
150
+
151
+ #bottom-panel.full > div {
152
+ padding-bottom: 40px;
153
+ }
154
+ #bottom-panel.full .tabs {
155
+ display: none;
156
+ }
157
+
158
+ #bottom-panel.full .message-info {
159
+ position: static;
160
+ }
161
+
162
+ #bottom-panel.full .message-info .content {
163
+ display: block;
164
+ position: static;
165
+ }
166
+
167
+ #bottom-panel.full .save,
168
+ #bottom-panel.full .share {
169
+ bottom: 10px;
170
+ }
171
+
172
+ #bottom-panel.full button.delete {
173
+ display: none;
174
+ }
175
+
176
+ #bottom-panel.full .message-actions {
177
+ position: fixed;
178
+ height: 40px;
179
+ width: 100%;
180
+ left: 0;
181
+ bottom: 0;
182
+ background-color: #eee;
183
+ border-top: 1px solid #dfdfdf;
184
+ padding-left: 10px;
185
+ }
186
+
187
+ #bottom-panel.full .message-actions button {
188
+ margin-top: 10px;
189
+ }
190
+
191
+ .message-actions {
192
+ position: absolute;
193
+ bottom: 3px;
194
+ right: 30px;
195
+ }
196
+
197
+ .message-actions button {
198
+ margin-right: 7px;
199
+ }
200
+
201
+ .message-actions .share {
202
+ text-decoration: none;
203
+ color: #333;
204
+ }
205
+
206
+ .divider {
207
+ position: fixed;
208
+ bottom: 310px;
209
+ left: 0;
210
+ right: 0;
211
+ height: 10px;
212
+ border-top: 1px solid #ddd;
213
+ border-bottom: 1px solid #ddd;
214
+ background-color: #fafafa;
215
+ cursor: row-resize;
216
+ z-index: 1;
217
+ }
218
+
219
+ .divider div {
220
+ margin: auto;
221
+ width: 24px;
222
+ height: 1px;
223
+ background-color: #ccc;
224
+ position: relative;
225
+ }
226
+
227
+ .divider .line-1 {
228
+ top: 3px;
229
+ }
230
+
231
+ .divider .line-2 {
232
+ top: 4px;
233
+ }
234
+
235
+ .divider .line-3 {
236
+ top: 5px;
237
+ }
238
+
239
+ #top-panel {
240
+ position: fixed;
241
+ top: 0;
242
+ left: 0;
243
+ right: 0;
244
+ bottom: 320px;
245
+ overflow: auto;
246
+ }
247
+
248
+ .message-info {
249
+ position: absolute;
250
+ border-bottom: 1px solid #ddd;
251
+ bottom: 35px;
252
+ top: 0;
253
+ left: 0;
254
+ right: 0;
255
+ overflow: auto;
256
+ }
257
+
258
+ .action-panel {
259
+ position: absolute;
260
+ left: 0;
261
+ right: 0;
262
+ bottom: 0;
263
+ height: 30px;
264
+ font-weight: bold;
265
+ }
266
+ .action-panel input {
267
+ position: relative;
268
+ top: -1px;
269
+ margin-left: 20px;
270
+ vertical-align: sub;
271
+ }
272
+
273
+ .action-panel .clear {
274
+ position: absolute;
275
+ right: 30px;
276
+ vertical-align: middle;
277
+ }
278
+
279
+ #log-table {
280
+ border-collapse: collapse;
281
+ margin: auto;
282
+ width: 99%;
283
+ table-layout: fixed;
284
+ }
285
+
286
+ .hidden {
287
+ display: none;
288
+ }
289
+
290
+ .message-info pre {
291
+ position: relative;
292
+ margin: 10px;
293
+ }
294
+
295
+ #overlay {
296
+ position: fixed;
297
+ z-index: 99999;
298
+ top: 0;
299
+ bottom: 0;
300
+ left: 0;
301
+ right: 0;
302
+ cursor: row-resize;
303
+ opacity: 0;
304
+ }
305
+
306
+ .message-info .content {
307
+ position: absolute;
308
+ top: 5px;
309
+ bottom: 35px;
310
+ left: 5px;
311
+ right: 5px;
312
+ overflow: auto;
313
+ display: none;
314
+ }
315
+
316
+ .message-info .content.active {
317
+ display: block;
318
+ }
319
+
320
+ .tabs {
321
+ position: absolute;
322
+ bottom: 10px;
323
+ left: 0;
324
+ right: 0;
325
+ list-style-type: none;
326
+ border-top: 1px solid #ddd;
327
+ margin: 0 0 5px;
328
+ padding: 0 0 0 14px;
329
+ }
330
+ .tabs li {
331
+ float: left;
332
+ position: relative;
333
+ padding-right: 5px;
334
+ margin: 0;
335
+ }
336
+ .tabs a {
337
+ position: relative;
338
+ top: 4px;
339
+ text-decoration: none;
340
+ color: #333;
341
+ border: 1px solid #ddd;
342
+ border-top: none;
343
+ border-bottom-left-radius: 5px;
344
+ border-bottom-right-radius: 5px;
345
+ padding: 4px;
346
+ background-color: #e1e1e1;
347
+ }
348
+
349
+ .tabs a.active {
350
+ border-top: 1px solid #f1f1f1;
351
+ background-color: #f1f1f1;
352
+ }
353
+
354
+ .btn {
355
+ display: inline-block;
356
+ margin: 0;
357
+ padding: 2px 12px;
358
+ font-weight: 500;
359
+ font-size: 1em;
360
+ line-height: 18px;
361
+ text-align: center;
362
+ cursor: pointer;
363
+ transition: all 0.25s;
364
+ background-color: #ddd;
365
+ text-decoration: none;
366
+ border: none;
367
+ color: #333;
368
+ font-weight: normal;
369
+ }
370
+
371
+ .btn:hover {
372
+ color: #000;
373
+ background-color: #ccc;
374
+ }
375
+
376
+ .btn .fa {
377
+ margin-right: 7px;
378
+ }
379
+
380
+ .btn:active {
381
+ text-shadow: none;
382
+ }
383
+
384
+ .btn.danger:hover {
385
+ background-color: #c63c1b;
386
+ color: #eee;
387
+ }