rocketjob_mission_control 5.0.1 → 6.0.0.beta

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 (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; }