kuroko2 0.3.2 → 0.3.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ee9ce17462b9270fa8f45c122123f20175131a84
4
- data.tar.gz: 2914136d1c86da76c97b0739fa26ab7560c13e52
3
+ metadata.gz: 7faaf6688a807693ea34cc14fbbe75da627fef56
4
+ data.tar.gz: 425c499e7bea2f5a410a07ea5f79adf3931b0b57
5
5
  SHA512:
6
- metadata.gz: 60988ce35420ffef7b77a3862b518b5b3adff3c15f8d5137acb474d1f8aed098a145d6944d81b920cf7e5bb5cdd39db9bcdf2269f3cf89dfa7696fcfd9339c7a
7
- data.tar.gz: e59d33a39735b8bb0064e44a5f24882afd809ad62c519d00e9421c51a46a45d3b5fd62d3f564b94292b9933a9d237a2675d0b36b97080cbaa0ee9f0656ae88a4
6
+ metadata.gz: f6556c97853e85ab23416591bb234751ad86f5f422df9c6062bb2c9982ac522ce225f2014e6b98e6fec90487ae687e2a827c6b42af7f388bf85969cfc316800f
7
+ data.tar.gz: 9f28a7dbc3409c2027fd9928bdc672b926989c4320f71f9fa64e69c8cb776ae35a127b9a29a2d816e804f6a9f85cc69decf99e41b4eede8fcc4a09fe31619d60
data/README.md CHANGED
@@ -25,5 +25,11 @@ Documentation is available at [docs/index.md](docs/index.md).
25
25
  - Taiki Ono
26
26
  - Takashi Kokubun
27
27
 
28
+ ## Contributors
29
+
30
+ - Shota Iguchi
31
+ - Hiroyuki Inoue
32
+ - hogelog
33
+
28
34
  ## License
29
35
  The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
@@ -1,6 +1,7 @@
1
1
  //= require jquery
2
2
  //= require jquery_ujs
3
3
  //= require ./bootstrap
4
+ //= require ./js.cookie.js
4
5
  //= stub kuroko2/instance_linker
5
6
  //= require_tree
6
7
  //= require moment
@@ -25,4 +26,42 @@ jQuery(function ($) {
25
26
  $(".right-side").toggleClass("strech");
26
27
  }
27
28
  });
29
+
30
+ var showNotificationStatus = function () {
31
+ if (Notification.permission === 'granted') {
32
+ if (Cookies.get('notification') === 'on') {
33
+ $('#notification').html("<i class=\"fa fa-volume-up\"></i> on");
34
+ } else {
35
+ $('#notification').html("<i class=\"fa fa-volume-off\"></i> off");
36
+ }
37
+ } else if (Notification.permission === 'denied') {
38
+ $('#notification').html("<i class=\"fa fa-volume-off\"></i> off");
39
+ }
40
+ }
41
+
42
+ $('#notification').click(function (e) {
43
+ if (!('Notification' in window)) {
44
+ return;
45
+ }
46
+
47
+ if (Notification.permission === 'default') {
48
+ Notification.requestPermission(function (permission) {
49
+ if (permission === "granted") {
50
+ Cookies.set('notification', 'on');
51
+ }
52
+ showNotificationStatus();
53
+ });
54
+ } else if (Notification.permission === 'granted') {
55
+ if (Cookies.get('notification') === 'on') {
56
+ Cookies.set('notification', 'off');
57
+ } else {
58
+ Cookies.set('notification', 'on');
59
+ }
60
+ showNotificationStatus();
61
+ }
62
+ });
63
+
64
+ if ('Notification' in window) {
65
+ showNotificationStatus();
66
+ }
28
67
  });
@@ -3,11 +3,25 @@
3
3
 
4
4
  jQuery(function ($) {
5
5
  var logIntervalId;
6
+ var notifyIfNeeded = function (status, name, image) {
7
+ if (!('Notification' in window)) {
8
+ return;
9
+ }
10
+
11
+ if (Notification.permission === 'granted' && Cookies.get('notification') === 'on') {
12
+ var notification = new Notification("[" + status + "] " + name, {"icon": image[status.toLowerCase()]});
13
+ notification.onclick = function () {
14
+ notification.close();
15
+ window.focus();
16
+ };
17
+ }
18
+ };
6
19
  var updateInstance = function () {
7
20
  var instancePath = $('#instance').data("instance-path");
8
21
 
9
22
  $.get(instancePath, function (data) {
10
23
  $('#instance').replaceWith(data);
24
+ notifyIfNeeded($('#instance-status').text(), $('#definition-name').text(), $('#notification').data());
11
25
  });
12
26
  };
13
27
  var updateLogs = function () {
@@ -0,0 +1,156 @@
1
+ /*!
2
+ * JavaScript Cookie v2.1.3
3
+ * https://github.com/js-cookie/js-cookie
4
+ *
5
+ * Copyright 2006, 2015 Klaus Hartl & Fagner Brack
6
+ * Released under the MIT license
7
+ */
8
+ ;(function (factory) {
9
+ var registeredInModuleLoader = false;
10
+ if (typeof define === 'function' && define.amd) {
11
+ define(factory);
12
+ registeredInModuleLoader = true;
13
+ }
14
+ if (typeof exports === 'object') {
15
+ module.exports = factory();
16
+ registeredInModuleLoader = true;
17
+ }
18
+ if (!registeredInModuleLoader) {
19
+ var OldCookies = window.Cookies;
20
+ var api = window.Cookies = factory();
21
+ api.noConflict = function () {
22
+ window.Cookies = OldCookies;
23
+ return api;
24
+ };
25
+ }
26
+ }(function () {
27
+ function extend () {
28
+ var i = 0;
29
+ var result = {};
30
+ for (; i < arguments.length; i++) {
31
+ var attributes = arguments[ i ];
32
+ for (var key in attributes) {
33
+ result[key] = attributes[key];
34
+ }
35
+ }
36
+ return result;
37
+ }
38
+
39
+ function init (converter) {
40
+ function api (key, value, attributes) {
41
+ var result;
42
+ if (typeof document === 'undefined') {
43
+ return;
44
+ }
45
+
46
+ // Write
47
+
48
+ if (arguments.length > 1) {
49
+ attributes = extend({
50
+ path: '/'
51
+ }, api.defaults, attributes);
52
+
53
+ if (typeof attributes.expires === 'number') {
54
+ var expires = new Date();
55
+ expires.setMilliseconds(expires.getMilliseconds() + attributes.expires * 864e+5);
56
+ attributes.expires = expires;
57
+ }
58
+
59
+ try {
60
+ result = JSON.stringify(value);
61
+ if (/^[\{\[]/.test(result)) {
62
+ value = result;
63
+ }
64
+ } catch (e) {}
65
+
66
+ if (!converter.write) {
67
+ value = encodeURIComponent(String(value))
68
+ .replace(/%(23|24|26|2B|3A|3C|3E|3D|2F|3F|40|5B|5D|5E|60|7B|7D|7C)/g, decodeURIComponent);
69
+ } else {
70
+ value = converter.write(value, key);
71
+ }
72
+
73
+ key = encodeURIComponent(String(key));
74
+ key = key.replace(/%(23|24|26|2B|5E|60|7C)/g, decodeURIComponent);
75
+ key = key.replace(/[\(\)]/g, escape);
76
+
77
+ return (document.cookie = [
78
+ key, '=', value,
79
+ attributes.expires ? '; expires=' + attributes.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
80
+ attributes.path ? '; path=' + attributes.path : '',
81
+ attributes.domain ? '; domain=' + attributes.domain : '',
82
+ attributes.secure ? '; secure' : ''
83
+ ].join(''));
84
+ }
85
+
86
+ // Read
87
+
88
+ if (!key) {
89
+ result = {};
90
+ }
91
+
92
+ // To prevent the for loop in the first place assign an empty array
93
+ // in case there are no cookies at all. Also prevents odd result when
94
+ // calling "get()"
95
+ var cookies = document.cookie ? document.cookie.split('; ') : [];
96
+ var rdecode = /(%[0-9A-Z]{2})+/g;
97
+ var i = 0;
98
+
99
+ for (; i < cookies.length; i++) {
100
+ var parts = cookies[i].split('=');
101
+ var cookie = parts.slice(1).join('=');
102
+
103
+ if (cookie.charAt(0) === '"') {
104
+ cookie = cookie.slice(1, -1);
105
+ }
106
+
107
+ try {
108
+ var name = parts[0].replace(rdecode, decodeURIComponent);
109
+ cookie = converter.read ?
110
+ converter.read(cookie, name) : converter(cookie, name) ||
111
+ cookie.replace(rdecode, decodeURIComponent);
112
+
113
+ if (this.json) {
114
+ try {
115
+ cookie = JSON.parse(cookie);
116
+ } catch (e) {}
117
+ }
118
+
119
+ if (key === name) {
120
+ result = cookie;
121
+ break;
122
+ }
123
+
124
+ if (!key) {
125
+ result[name] = cookie;
126
+ }
127
+ } catch (e) {}
128
+ }
129
+
130
+ return result;
131
+ }
132
+
133
+ api.set = api;
134
+ api.get = function (key) {
135
+ return api.call(api, key);
136
+ };
137
+ api.getJSON = function () {
138
+ return api.apply({
139
+ json: true
140
+ }, [].slice.call(arguments));
141
+ };
142
+ api.defaults = {};
143
+
144
+ api.remove = function (key, attributes) {
145
+ api(key, '', extend(attributes, {
146
+ expires: -1
147
+ }));
148
+ };
149
+
150
+ api.withConverter = init;
151
+
152
+ return api;
153
+ }
154
+
155
+ return init(function () {});
156
+ }));
@@ -88,3 +88,7 @@
88
88
  font-size: 1.3em;
89
89
  fill: #666;
90
90
  }
91
+
92
+ #notification {
93
+ cursor: pointer;
94
+ }
@@ -1,6 +1,6 @@
1
1
  .box#instance data-instance-path="#{naked_job_definition_job_instance_path(@definition, @instance)}"
2
2
  .box-header
3
- h2.box-title
3
+ h2#definition-name.box-title
4
4
  = link_to "##{@definition.id} #{@definition.name}", job_definition_path(@definition)
5
5
  .box-body
6
6
  table.table
@@ -31,6 +31,9 @@ html
31
31
  img.img-circle src='#{current_user.image}' alt="#{current_user.name}"
32
32
  .pull-left.info
33
33
  p Hello, #{current_user.name}
34
+ p#notification data-success='#{asset_url('kuroko2/kuroko-logo-success.png')}' data-error='#{asset_url('kuroko2/kuroko-logo-error.png')}'
35
+ i.fa.fa-volume-off
36
+ | Turn on notification
34
37
  ul.sidebar-menu
35
38
  li class=('active' if controller_name == 'dashboard')
36
39
  = link_to raw('<i class="fa fa-dashboard"></i> Dashboard'), root_path
@@ -50,6 +50,8 @@ module Kuroko2
50
50
  config.action_mailer.smtp_settings =
51
51
  Kuroko2.config.action_mailer.smtp_settings.to_h.symbolize_keys || {}
52
52
 
53
+ app.config.assets.precompile += %w(kuroko2/kuroko-logo-success.png kuroko2/kuroko-logo-error.png)
54
+
53
55
  if Kuroko2.config.extentions && Kuroko2.config.extentions.controller
54
56
  Kuroko2.config.extentions.controller.each do |extention|
55
57
  Kuroko2::ApplicationController.include(Module.const_get(extention, false))
@@ -1,3 +1,3 @@
1
1
  module Kuroko2
2
- VERSION = '0.3.2'
2
+ VERSION = '0.3.3'
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kuroko2
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.2
4
+ version: 0.3.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Naoto Takai
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2017-02-08 00:00:00.000000000 Z
12
+ date: 2017-02-15 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails
@@ -541,7 +541,9 @@ files:
541
541
  - README.md
542
542
  - Rakefile
543
543
  - app/assets/images/kuroko2/avatar.png
544
+ - app/assets/images/kuroko2/kuroko-logo-error.png
544
545
  - app/assets/images/kuroko2/kuroko-logo-horizontal.png
546
+ - app/assets/images/kuroko2/kuroko-logo-success.png
545
547
  - app/assets/javascripts/kuroko2/application.js
546
548
  - app/assets/javascripts/kuroko2/bootstrap.js
547
549
  - app/assets/javascripts/kuroko2/instance_linker.js
@@ -549,6 +551,7 @@ files:
549
551
  - app/assets/javascripts/kuroko2/job_definitions.js
550
552
  - app/assets/javascripts/kuroko2/job_instances.js
551
553
  - app/assets/javascripts/kuroko2/job_timelines.js.coffee
554
+ - app/assets/javascripts/kuroko2/js.cookie.js
552
555
  - app/assets/javascripts/kuroko2/narrow_job_definitions.js
553
556
  - app/assets/stylesheets/kuroko2/admin-lte.css
554
557
  - app/assets/stylesheets/kuroko2/application.scss
@@ -642,7 +645,6 @@ files:
642
645
  - app/views/kuroko2/job_timelines/index.html.slim
643
646
  - app/views/kuroko2/kaminari/history/_paginator.html.slim
644
647
  - app/views/kuroko2/kaminari/list/_paginator.html.slim
645
- - app/views/kuroko2/layouts/application.html.slim
646
648
  - app/views/kuroko2/logs/index.html.slim
647
649
  - app/views/kuroko2/notifications/executor_not_assigned.text.erb
648
650
  - app/views/kuroko2/notifications/job_failure.html.slim
@@ -1,68 +0,0 @@
1
- doctype html
2
- html
3
- head
4
- title #{yield(:title)} « Kuroko 2
5
- meta charset='UTF-8'
6
- meta content='width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no' name='viewport'
7
- link rel='icon' href='/favicon.ico'
8
- link type='application/opensearchdescription+xml' rel='search' href='#{osd_path(format: 'xml')}' title='Kuroko2'
9
- = csrf_meta_tag
10
- = stylesheet_link_tag 'application'
11
- = javascript_include_tag 'application'
12
-
13
- body.skin-black
14
- header.header
15
- = link_to 'Kuroko 2', root_path, class: 'logo'
16
- nav.navbar.navbar-static-top role='navigation'
17
- a.navbar-btn.sidebar-toggle data-toggle='offcanvas' role='button' href='#'
18
- span.sr-only Toggle navigation
19
- span.icon-bar
20
- span.icon-bar
21
- span.icon-bar
22
- .navbar-right
23
- ul.nav.navbar-nav
24
- li.dropdown
25
- = link_to raw('<i class="fa fa-sign-out"></i> Sign out'), sign_out_path, method: :delete
26
- .wrapper.row-offcanvas.row-offcanvas-left
27
- aside.left-side.sidebar-offcanvas
28
- section.sidebar
29
- .user-panel
30
- .pull-left.image
31
- img.img-circle src='#{current_user.image}' alt="#{current_user.name}"
32
- .pull-left.info
33
- p Hello, #{current_user.name}
34
- ul.sidebar-menu
35
- li class=('active' if controller_name == 'dashboard')
36
- = link_to raw('<i class="fa fa-dashboard"></i> Dashboard'), root_path
37
- li
38
- a name="#"
39
- i.fa.fa-database
40
- 'Job Definitions
41
- ul.menu-child
42
- li.menu-child-item class=('active' if controller_name == 'job_definitions' && action_name == 'index')
43
- = link_to raw('<i class="fa fa-angle-double-right"></i> All Job Definitions'), job_definitions_path
44
- li.menu-child-item class=('active' if controller_name == 'job_definitions' && action_name == 'new')
45
- = link_to raw('<i class="fa fa-angle-double-right"></i> Create New'), new_job_definition_path
46
- li class=('active' if controller_name == 'job_instances' && action_name == 'working')
47
- = link_to raw('<i class="fa fa-spinner"></i> Working Jobs'), working_job_instances_path
48
- li class=('active' if controller_name == 'workers')
49
- = link_to raw('<i class="fa fa-rocket"></i> Kuroko Workers'), workers_path
50
- li
51
- a name="#"
52
- i.fa.fa-users
53
- 'Users
54
- ul.menu-child
55
- li.menu-child-item class=('active' if controller_name == 'users' && action_name == 'index' && !params[:target])
56
- = link_to raw('<i class="fa fa-angle-double-right"></i> All '), users_path
57
- li.menu-child-item class=('active' if controller_name == 'users' && params[:target] == 'group')
58
- = link_to raw('<i class="fa fa-angle-double-right"></i> Groups'), users_path(target: 'group')
59
-
60
- aside.right-side
61
- section.content-header
62
- h1= yield(:content_title).presence || yield(:title)
63
- = yield :breadcrumb
64
- section.content
65
- .container-fluid
66
- .row
67
- .col-xs-12
68
- = yield