rocketjob_mission_control 5.0.1 → 6.0.0.beta

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/app/assets/config/manifest.js +3 -0
  4. data/app/assets/javascripts/rocket_job_mission_control/application.js +1 -1
  5. data/app/assets/javascripts/rocket_job_mission_control/nested_fields.js +112 -0
  6. data/app/assets/stylesheets/rocket_job_mission_control/{application.scss → application.css} +9 -8
  7. data/app/assets/stylesheets/rocket_job_mission_control/base.css +420 -0
  8. data/app/assets/stylesheets/rocket_job_mission_control/{callout.scss → callout.css} +50 -52
  9. data/app/assets/stylesheets/rocket_job_mission_control/jobs.css +57 -0
  10. data/app/assets/stylesheets/rocket_job_mission_control/worker_processes.css +7 -0
  11. data/app/controllers/rocket_job_mission_control/dirmon_entries_controller.rb +20 -20
  12. data/app/controllers/rocket_job_mission_control/jobs_controller.rb +44 -4
  13. data/app/datatables/rocket_job_mission_control/jobs_datatable.rb +1 -1
  14. data/app/helpers/rocket_job_mission_control/application_helper.rb +43 -26
  15. data/app/helpers/rocket_job_mission_control/dirmon_entries_helper.rb +8 -0
  16. data/app/helpers/rocket_job_mission_control/jobs_helper.rb +76 -8
  17. data/app/models/rocket_job_mission_control/dirmon_sanitizer.rb +68 -0
  18. data/app/models/rocket_job_mission_control/job_sanitizer.rb +35 -0
  19. data/app/views/rocket_job_mission_control/dirmon_entries/_form.html.erb +78 -42
  20. data/app/views/rocket_job_mission_control/dirmon_entries/_input_categories.html.erb +59 -0
  21. data/app/views/rocket_job_mission_control/dirmon_entries/_input_category_fields.html.erb +56 -0
  22. data/app/views/rocket_job_mission_control/dirmon_entries/_output_categories.html.erb +44 -0
  23. data/app/views/rocket_job_mission_control/dirmon_entries/_output_category_fields.html.erb +36 -0
  24. data/app/views/rocket_job_mission_control/dirmon_entries/_status.html.erb +22 -16
  25. data/app/views/rocket_job_mission_control/dirmon_entries/copy.html.erb +1 -1
  26. data/app/views/rocket_job_mission_control/dirmon_entries/edit.html.erb +7 -3
  27. data/app/views/rocket_job_mission_control/dirmon_entries/show.html.erb +2 -3
  28. data/app/views/rocket_job_mission_control/jobs/_attributes.html.erb +89 -0
  29. data/app/views/rocket_job_mission_control/jobs/_dates.html.erb +39 -0
  30. data/app/views/rocket_job_mission_control/jobs/_details.html.erb +86 -0
  31. data/app/views/rocket_job_mission_control/jobs/_exception.html.erb +33 -0
  32. data/app/views/rocket_job_mission_control/jobs/_input_categories.html.erb +126 -0
  33. data/app/views/rocket_job_mission_control/jobs/_input_category_fields.html.erb +56 -0
  34. data/app/views/rocket_job_mission_control/jobs/_output_categories.html.erb +60 -0
  35. data/app/views/rocket_job_mission_control/jobs/_output_category_fields.html.erb +36 -0
  36. data/app/views/rocket_job_mission_control/jobs/_retryable.html.erb +27 -0
  37. data/app/views/rocket_job_mission_control/jobs/_status.html.erb +21 -49
  38. data/app/views/rocket_job_mission_control/jobs/edit.html.erb +28 -0
  39. data/app/views/rocket_job_mission_control/jobs/exception.html.erb +1 -1
  40. data/app/views/rocket_job_mission_control/jobs/index.html.erb +24 -18
  41. data/app/views/rocket_job_mission_control/jobs/show.html.erb +32 -58
  42. data/app/views/rocket_job_mission_control/jobs/view_slice.html.erb +4 -4
  43. data/config/initializers/assets.rb +3 -4
  44. data/lib/rocket_job_mission_control/engine.rb +0 -1
  45. data/lib/rocket_job_mission_control/version.rb +1 -1
  46. data/test/controllers/rocket_job_mission_control/jobs_controller_test.rb +2 -1
  47. data/test/models/rocket_job_mission_control/dirmon_sanitizer_test.rb +146 -0
  48. data/test/test_helper.rb +5 -11
  49. data/vendor/assets/fonts/glyphicons-halflings-regular.eot +0 -0
  50. data/vendor/assets/fonts/glyphicons-halflings-regular.svg +288 -0
  51. data/vendor/assets/fonts/glyphicons-halflings-regular.ttf +0 -0
  52. data/vendor/assets/fonts/glyphicons-halflings-regular.woff +0 -0
  53. data/vendor/assets/fonts/glyphicons-halflings-regular.woff2 +0 -0
  54. data/vendor/assets/stylesheets/bootstrap.min.css.erb +6 -0
  55. metadata +37 -29
  56. data/app/assets/stylesheets/rocket_job_mission_control/base.scss +0 -436
  57. data/app/assets/stylesheets/rocket_job_mission_control/bootstrap_and_overrides.scss +0 -488
  58. data/app/assets/stylesheets/rocket_job_mission_control/jobs.scss +0 -72
  59. data/app/assets/stylesheets/rocket_job_mission_control/worker_processes.scss +0 -9
  60. data/vendor/assets/stylesheets/bootstrap.min.css +0 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1a7a9ef0aac59fd6cb345b13c503922ea80232f0eedb8d4eb29ea1d535e04c8a
4
- data.tar.gz: 360b3994feec93243b9b4cfadf8fa89416538aafb0fbc927b2db31399cc850e4
3
+ metadata.gz: d421e76cdd7a629d0f28598e52f2d6321bcdb0f062d50cf99b0e3ac791c0c823
4
+ data.tar.gz: fa9f46ebbb28043994c98d42efc368973b57cf243ff793447c3985e6f56f152e
5
5
  SHA512:
6
- metadata.gz: c8782d8a249ee6de70705f806386d1f6fb3afbea4f33451ef7e0337641e87c3b88f0cbc804de35131ef46da8f85e3121a694cd79f4171a912809b0330d5e4e6d
7
- data.tar.gz: f051ec5acb746f52c71924d757e35c955715838dfc994c82eb6d2cfaa630bb9b50d8b26c2d8fe7a34d392e06084cf9121906591f8951a0b7feae372093021d0b
6
+ metadata.gz: 4cd18b8160af0cfa244403d522f4aa98d3e18c945f2e2fcc03001adb29e27a47c5dbcab50384b8e89630aa9a0302320d779307376fcfa720deb7535ff2201020
7
+ data.tar.gz: 42b3d18cfa224ea50b25fd5eaeab7f4409a8452e4791dd91edf49358359e02b1418cecaf132710abca86d2f32d6198fc8e2ff3497e9273648f7ea11f755b4442
data/README.md CHANGED
@@ -1,5 +1,5 @@
1
1
  # Rocket Job Mission Control
2
- [![Gem Version](https://badge.fury.io/rb/rocketjob_mission_control.svg)](http://badge.fury.io/rb/rocketjob_mission_control) [![Build Status](https://secure.travis-ci.org/rocketjob/rocketjob_mission_control.png?branch=master)](http://travis-ci.org/rocketjob/rocketjob_mission_control)
2
+ [![Gem Version](https://img.shields.io/gem/v/rocketjob_mission_control.svg)](https://rubygems.org/gems/rocketjob_mission_control) [![Downloads](https://img.shields.io/gem/dt/rocketjob_mission_control.svg)](https://rubygems.org/gems/rocketjob_mission_control) [![License](https://img.shields.io/badge/license-Apache%202.0-brightgreen.svg)](http://opensource.org/licenses/Apache-2.0) ![](https://img.shields.io/badge/status-Production%20Ready-blue.svg) [![Gitter chat](https://img.shields.io/badge/IRC%20(gitter)-Support-brightgreen.svg)](https://gitter.im/rocketjob/support)
3
3
 
4
4
  Web based management interface for [Rocket Job][0].
5
5
 
@@ -0,0 +1,3 @@
1
+ //= link_tree ../images
2
+ //= link_directory ../javascripts .js
3
+ //= link_directory ../stylesheets .css
@@ -10,7 +10,7 @@
10
10
  // Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
11
11
  // about supported directives.
12
12
  //
13
- //= require jquery
13
+ //= require jquery3
14
14
  //= require jquery_ujs
15
15
  //= require datatables.min.js
16
16
  //= require bootstrap.min
@@ -0,0 +1,112 @@
1
+ "use strict";
2
+
3
+ var _createClass = function () {
4
+ function defineProperties(target, props) {
5
+ for (var i = 0; i < props.length; i++) {
6
+ var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true;
7
+
8
+ if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor);
9
+ }
10
+ } return function (Constructor, protoProps, staticProps) {
11
+ if (protoProps) defineProperties(Constructor.prototype, protoProps);
12
+ if (staticProps) defineProperties(Constructor, staticProps); return Constructor;
13
+ };
14
+ }();
15
+
16
+ function _classCallCheck(instance, Constructor) {
17
+ if (!(instance instanceof Constructor)) {
18
+ throw new TypeError("Cannot call a class as a function");
19
+ }
20
+ }
21
+
22
+ var addFields = function () {
23
+ // This executes when the function is instantiated.
24
+ function addFields() {
25
+ _classCallCheck(this, addFields);
26
+
27
+ this.links = document.querySelectorAll('.add_fields');
28
+ this.iterateLinks();
29
+ }
30
+
31
+ _createClass(addFields, [{
32
+ key: 'iterateLinks',
33
+ value: function iterateLinks() {
34
+ var _this = this;
35
+
36
+ // If there are no links on the page, stop the function from executing.
37
+ if (this.links.length === 0) return; // Loop over each link on the page. A page could have multiple nested forms.
38
+
39
+ this.links.forEach(function (link) {
40
+ link.addEventListener('click', function (e) {
41
+ _this.handleClick(link, e);
42
+ });
43
+ });
44
+ }
45
+ }, {
46
+ key: 'handleClick',
47
+ value: function handleClick(link, e) {
48
+ // Stop the function from executing if a link or event were not passed into the function.
49
+ if (!link || !e) return; // Prevent the browser from following the URL.
50
+
51
+ e.preventDefault(); // Save a unique timestamp to ensure the key of the associated array is unique.
52
+
53
+ var time = new Date().getTime(); // Save the data id attribute into a variable. This corresponds to `new_object.object_id`.
54
+ var linkId = link.dataset.id; // Create a new regular expression needed to find any instance of the `new_object.object_id` used in the fields data attribute if there's a value in `linkId`.
55
+ var regexp = linkId ? new RegExp(linkId, 'g') : null; // Replace all instances of the `new_object.object_id` with `time`, and save markup into a variable if there's a value in `regexp`.
56
+ var newFields = regexp ? link.dataset.fields.replace(regexp, time) : null; // Add the new markup to the form if there are fields to add.
57
+
58
+ newFields ? link.insertAdjacentHTML('beforebegin', newFields) : null;
59
+ }
60
+ }]);
61
+
62
+ return addFields;
63
+ }();
64
+
65
+ var removeFields = function () {
66
+ // This executes when the function is instantiated.
67
+ function removeFields() {
68
+ _classCallCheck(this, removeFields);
69
+
70
+ this.iterateLinks();
71
+ }
72
+
73
+ _createClass(removeFields, [{
74
+ key: 'iterateLinks',
75
+ value: function iterateLinks() {
76
+ var _this2 = this;
77
+
78
+ // Use event delegation to ensure any fields added after the page loads are captured.
79
+ document.addEventListener('click', function (e) {
80
+ if (e.target && e.target.className == "remove_fields btn btn-danger") {
81
+ _this2.handleClick(e.target, e);
82
+ }
83
+ });
84
+ }
85
+ }, {
86
+ key: 'handleClick',
87
+ value: function handleClick(link, e) {
88
+ // Stop the function from executing if a link or event were not passed into the function.
89
+ if (!link || !e) return; // Prevent the browser from following the URL.
90
+
91
+ e.preventDefault(); // Find the parent wrapper for the set of nested fields.
92
+
93
+ var fieldParent = link.closest('.nested-fields'); // If there is a parent wrapper, find the hidden delete field.
94
+ var deleteField = fieldParent ? fieldParent.querySelector('input[type="hidden"]') : null; // If there is a delete field, update the value to `1` and hide the corresponding nested fields.
95
+
96
+ if (deleteField) {
97
+ deleteField.value = 1;
98
+ fieldParent.style.display = 'none';
99
+ }
100
+ }
101
+ }]);
102
+
103
+ return removeFields;
104
+ }(); // Wait for turbolinks to load, otherwise `document.querySelectorAll()` won't work
105
+
106
+
107
+ window.addEventListener('DOMContentLoaded', function () {
108
+ return new addFields();
109
+ });
110
+ window.addEventListener('DOMContentLoaded', function () {
111
+ return new removeFields();
112
+ });
@@ -10,12 +10,13 @@
10
10
  * defined in the other CSS/SCSS files in this directory. It is generally better to create a new
11
11
  * file per style scope.
12
12
  *
13
- *= require_self
14
- *= require_tree .
13
+ *= require bootstrap.min
14
+ *= require fontawesome-all.min
15
+ *= require selectize
16
+ *= require selectize.bootstrap3
17
+ *= require datatables.min
18
+ *= require rocket_job_mission_control/base
19
+ *= require rocket_job_mission_control/callout
20
+ *= require rocket_job_mission_control/jobs
21
+ *= require rocket_job_mission_control/worker_processes
15
22
  */
16
-
17
- @import 'bootstrap.min';
18
- @import 'fontawesome-all.min';
19
- @import 'selectize';
20
- @import 'selectize.bootstrap3';
21
- @import 'datatables.min';
@@ -0,0 +1,420 @@
1
+ html, body, #wrapper, #wrapper > .container-fluid, #main, .row.row-offcanvas.row-offcanvas-left {
2
+ height: 100%;
3
+ }
4
+
5
+ .navbar-default { background-image: linear-gradient(90deg, #000, #99120f); }
6
+ .navbar-default .navbar-nav > li > a { color: #fff; }
7
+ .navbar-default .navbar-nav > li > a:hover { color: #aaa; }
8
+ .navbar-default .navbar-collapse, .navbar-default .navbar-form {
9
+ border: 0;
10
+ }
11
+
12
+ #wrapper { background-color: #f7f7f7; }
13
+
14
+ .footer {
15
+ position: relative;
16
+ height: 100px;
17
+ clear: both;
18
+ padding-top: 20px;
19
+ }
20
+
21
+ /* Datatables */
22
+ table.datatable { border-collapse: collapse; }
23
+ .dataTables_wrapper { margin-top: 2em; }
24
+
25
+ table.dataTable thead .sorting:after, table.dataTable thead .sorting_asc:after, table.dataTable thead .sorting_desc:after {
26
+ position: absolute;
27
+ top: 8px;
28
+ left: 8px;
29
+ display: block;
30
+ font-family: "Font Awesome 5 Free";
31
+ font-size: inherit;
32
+ text-rendering: auto;
33
+ -webkit-font-smoothing: antialiased;
34
+ -moz-osx-font-smoothing: grayscale;
35
+ }
36
+
37
+ table.dataTable thead .sorting:after { content: "\f0c9"; }
38
+ table.dataTable thead .sorting_asc:after { content: "\f160"; }
39
+ table.dataTable thead .sorting_desc:after { content: "\f161"; }
40
+ table.dataTable thead > tr > th { padding-left: 30px; }
41
+
42
+ div.row {
43
+ margin-left: -15px;
44
+ margin-right: -15px;
45
+ }
46
+
47
+ .dataTables_info, .dataTables_paginate { margin-top: 20px !important; }
48
+
49
+ .datatable .card td { vertical-align: middle; }
50
+
51
+ .inline-job-actions > a {
52
+ display: inline-block;
53
+ padding: 1px 5px;
54
+ font-size: 12px;
55
+ line-height: 1.5;
56
+ border-radius: 1px;
57
+ }
58
+
59
+ .job-list {
60
+ height: 100%;
61
+ min-height: 768px;
62
+ }
63
+
64
+ /* Job Edit Page */
65
+ .edit_job textarea.description-block { height: 166px; }
66
+ .edit_job .buttons { margin-top: 1em; }
67
+
68
+ .job-status .lead {
69
+ color: #50555b;
70
+ float: left;
71
+ margin-top: 1em;
72
+ vertical-align: middle;
73
+ }
74
+
75
+ .job-status p {
76
+ font-size: 14px;
77
+ color: #666;
78
+ }
79
+
80
+ .job-status .welcome_screen {
81
+ text-align: center;
82
+ margin-top: 2%;
83
+ }
84
+
85
+ .job-status .welcome_screen h1 { margin-bottom: 10px; }
86
+ .job-status .welcome_screen p { font-size: 16px; }
87
+
88
+ .job-status .job-actions {
89
+ float: left;
90
+ margin-top: 23px;
91
+ margin-left: 20px;
92
+ }
93
+
94
+ .job-status .job-actions .btn { padding: 2px 6px; }
95
+
96
+ .job-status .pagination-buttons {
97
+ float: left;
98
+ margin-top: 23px;
99
+ margin-left: 20px;
100
+ }
101
+
102
+ .job-status .job-state {
103
+ margin-left: 20px;
104
+ padding: 0;
105
+ font-size: 12px;
106
+ margin-top: 0;
107
+ vertical-align: middle;
108
+ float: left;
109
+ }
110
+
111
+ h3 { margin-top: 0; }
112
+
113
+ .job-status .job-state .left {
114
+ float: left;
115
+ text-shadow: 0 2px 3px #000;
116
+ font-weight: bold;
117
+ background-color: #404650;
118
+ color: #fff;
119
+ padding: 6px 12px;
120
+ border-top-left-radius: 3px;
121
+ border-bottom-left-radius: 3px;
122
+ }
123
+
124
+ .job-status .job-state .right {
125
+ float: left;
126
+ font-weight: bold;
127
+ color: #fff;
128
+ padding: 6px 12px;
129
+ border-top-right-radius: 3px;
130
+ border-bottom-right-radius: 3px;
131
+ }
132
+
133
+ .job-status .job-state .queued, .job-status .job-state .pending { background-color: #a29f00; }
134
+ .job-status .job-state .scheduled { background-color: purple; }
135
+ .job-status .job-state .running { background-color: #337ab7; }
136
+ .job-status .job-state .sleeping { background-color: darkcyan; }
137
+ .job-status .job-state .completed, .job-status .job-state .enabled { background-color: green; }
138
+ .job-status .job-state .paused, .job-status .job-state .disabled { background-color: orange; }
139
+ .job-status .job-state .failed { background-color: red; }
140
+ .job-status .job-state .aborted { background-color: darkorange; }
141
+
142
+ .job-status .priority {
143
+ display: inline-block;
144
+ vertical-align: middle;
145
+ float: right;
146
+ margin-top: 20px;
147
+ }
148
+
149
+ .job-status .priority .form-control {
150
+ width: 47px;
151
+ height: 34px;
152
+ }
153
+
154
+ .job-status .priority-set {
155
+ float: right;
156
+ padding: 7px 14px;
157
+ font-weight: bold;
158
+ border-top-left-radius: 0;
159
+ border-bottom-left-radius: 0;
160
+ }
161
+
162
+ #content {
163
+ margin-top: 60px;
164
+ padding: 40px;
165
+ }
166
+
167
+ #main { padding-left: 0; }
168
+
169
+ .white-background { background-color: #fff; }
170
+
171
+ /* Sidebar */
172
+ #sidebar {
173
+ padding: 0px;
174
+ padding-top: 15px;
175
+ margin-top: 5em;
176
+ }
177
+
178
+ #sidebar, #sidebar a {
179
+ color: #555;
180
+ background-color: transparent;
181
+ padding-left: 5px;
182
+ }
183
+
184
+ #sidebar .nav li > a:hover {
185
+ color: #000;
186
+ background-color: #ddd;
187
+ }
188
+
189
+ @media screen and (max-width: 768px) {
190
+ .row-offcanvas {
191
+ position: relative;
192
+ -webkit-transition: all 0.25s ease-out;
193
+ -moz-transition: all 0.25s ease-out;
194
+ transition: all 0.25s ease-out;
195
+ }
196
+
197
+ .row-offcanvas-left.active { left: 33%; }
198
+
199
+ .row-offcanvas-left.active .sidebar-offcanvas {
200
+ left: -33%;
201
+ position: absolute;
202
+ top: 0;
203
+ width: 33%;
204
+ margin-left: 5px;
205
+ }
206
+
207
+ #sidebar, #sidebar a, #sidebar-footer a { padding-left: 6px; }
208
+ }
209
+
210
+ /* Header Styles */
211
+ #header {
212
+ padding: 5px;
213
+ border-radius: 0;
214
+ border: 0;
215
+ position: fixed;
216
+ z-index: 1000;
217
+ right: 0;
218
+ left: 0;
219
+ }
220
+
221
+ #header .navbar { position: relative; }
222
+
223
+ #header .brand {
224
+ position: absolute;
225
+ left: 50%;
226
+ margin-left: -96px !important;
227
+ display: block;
228
+ }
229
+
230
+ #header .brand img {
231
+ display: inline;
232
+ height: 40px;
233
+ position: relative;
234
+ bottom: 3px;
235
+ left: 8px;
236
+ }
237
+
238
+ #header .first { left: 15px; }
239
+ #header .last { right: 15px; }
240
+
241
+ #header a.navbar-brand.brand {
242
+ font-size: 23px;
243
+ color: white;
244
+ font-weight: bold;
245
+ top: -5px;
246
+ }
247
+
248
+ #header a.navbar-brand.brand span {
249
+ display: inline-block;
250
+ position: relative;
251
+ left: -3px;
252
+ color: orangered;
253
+ font-weight: bold;
254
+ }
255
+
256
+ #jobs-menu {
257
+ margin-top: 1.5em;
258
+ background-color: #b3b3b3;
259
+ border-color: white;
260
+ }
261
+
262
+ .job-search-box { padding: 20px 100px; }
263
+
264
+ .list .card:nth-child(1) { border-top: 1px solid #ddd; }
265
+ .list .card:nth-child(odd) { background-color: #fff; }
266
+
267
+ .list .card {
268
+ border-bottom: 1px solid #ddd;
269
+ border-right: 1px solid #ddd;
270
+ height: 100%;
271
+ background-color: #f7f7f7;
272
+ }
273
+
274
+ .list .card:hover {
275
+ cursor: pointer;
276
+ background-color: #dadada;
277
+ }
278
+
279
+ .list .card .inner {
280
+ padding: 0.5em;
281
+ position: relative;
282
+ margin: 0 0 0 10px;
283
+ }
284
+
285
+ .list .card .inner .title {
286
+ display: inline-block;
287
+ vertical-align: middle;
288
+ }
289
+
290
+ .list .card .inner .title i.queued { color: #a29f00; }
291
+ .list .card .inner .title i.scheduled { color: purple; }
292
+ .list .card .inner .title i.running { color: #337ab7; }
293
+ .list .card .inner .title i.sleeping { color: darkcyan; }
294
+ .list .card .inner .title i.completed { color: green; }
295
+ .list .card .inner .title i.paused { color: orange; }
296
+ .list .card .inner .title i.failed { color: red; }
297
+ .list .card .inner .title i.aborted { color: darkorange; }
298
+ .list .card .inner .title i.enabled { color: green; }
299
+ .list .card .inner .title i.disabled { color: orange; }
300
+
301
+ .list .card .inner .title h3 {
302
+ font-weight: bold;
303
+ margin: 0;
304
+ font-size: 16px;
305
+ }
306
+
307
+ .list .card .inner .lead {
308
+ margin-bottom: 5px;
309
+ font-size: 18px;
310
+ }
311
+
312
+ .list .card .inner .duration, .list .card .inner .description, .list .card .inner .completion {
313
+ color: #7c735c;
314
+ font-size: 18px;
315
+ font-weight: 200;
316
+ }
317
+
318
+ .list .card .inner .batch {
319
+ position: absolute;
320
+ right: -10px;
321
+ top: -10px;
322
+ background-color: #444;
323
+ border-radius: 30px;
324
+ padding: 4px 10px;
325
+ color: #fff;
326
+ z-index: 2;
327
+ }
328
+
329
+ .list .selected {
330
+ border-bottom: 1px solid blue;
331
+ border-right: 1px solid blue;
332
+ border-top: 1px solid blue;
333
+ background-color: lightcyan;
334
+ }
335
+
336
+ .grid {
337
+ padding: 1em;
338
+ font-size: 0.85em;
339
+ }
340
+
341
+ .grid .card { padding: 1em; }
342
+
343
+ .grid .card .inner {
344
+ padding: 1em;
345
+ border-radius: 3px;
346
+ display: inline-block;
347
+ background: #fff;
348
+ width: 100%;
349
+ min-height: 250px;
350
+ box-sizing: border-box;
351
+ -moz-box-sizing: border-box;
352
+ -webkit-box-sizing: border-box;
353
+ box-shadow: 0px 1px 2px 0 #ccc;
354
+ position: relative;
355
+ text-align: center;
356
+ }
357
+
358
+ .grid .card .inner .title,
359
+ .grid .card .inner .state,
360
+ .grid .card .inner .threads,
361
+ .grid .card .inner .time {
362
+ margin-bottom: 10px;
363
+ }
364
+
365
+ .grid .card .inner .actions {
366
+ padding: 10px 0;
367
+ background: #f5f5f5;
368
+ border: 1px solid #eee;
369
+ border-radius: 2px;
370
+ }
371
+
372
+ .grid .card .inner .title { text-align: center; }
373
+
374
+ .grid .card .inner .title h3 {
375
+ font-weight: bold;
376
+ margin: 0;
377
+ font-size: 16px;
378
+ }
379
+
380
+ .priority-group {
381
+ width: 67px;
382
+ margin: 0 auto;
383
+ }
384
+
385
+ .priority-group input { text-align: right; }
386
+
387
+ .priority-group .input-group-btn-vertical {
388
+ position: relative;
389
+ white-space: nowrap;
390
+ width: 1%;
391
+ vertical-align: middle;
392
+ display: table-cell;
393
+ }
394
+
395
+ .priority-group .input-group-btn-vertical > .btn {
396
+ display: block;
397
+ float: none;
398
+ width: 100%;
399
+ max-width: 100%;
400
+ padding: 8px;
401
+ margin-left: -1px;
402
+ position: relative;
403
+ border-radius: 0;
404
+ }
405
+
406
+ .priority-group .input-group-btn-vertical > .btn:first-child { border-right: 0; }
407
+
408
+ .priority-group .input-group-btn-vertical > .btn:last-child {
409
+ margin-top: -2px;
410
+ border-right: 0;
411
+ }
412
+
413
+ .priority-group .input-group-btn-vertical i {
414
+ position: absolute;
415
+ top: 0;
416
+ left: 4px;
417
+ }
418
+
419
+ .code-block { margin-top: 25px; }
420
+ .status { padding: 1em; }