cyclid-ui 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +178 -0
- data/README.md +20 -0
- data/app/cyclid_ui.rb +124 -0
- data/app/cyclid_ui/config.rb +64 -0
- data/app/cyclid_ui/controllers/auth.rb +102 -0
- data/app/cyclid_ui/controllers/base.rb +41 -0
- data/app/cyclid_ui/controllers/health.rb +96 -0
- data/app/cyclid_ui/controllers/organization.rb +64 -0
- data/app/cyclid_ui/controllers/user.rb +40 -0
- data/app/cyclid_ui/helpers.rb +55 -0
- data/app/cyclid_ui/memcache.rb +45 -0
- data/app/cyclid_ui/models/user.rb +91 -0
- data/app/cyclid_ui/templates/footer.mustache +8 -0
- data/app/cyclid_ui/templates/job.mustache +21 -0
- data/app/cyclid_ui/templates/job_info.mustache +40 -0
- data/app/cyclid_ui/templates/layout.mustache +102 -0
- data/app/cyclid_ui/templates/login.mustache +78 -0
- data/app/cyclid_ui/templates/organization.mustache +150 -0
- data/app/cyclid_ui/templates/user.mustache +97 -0
- data/app/cyclid_ui/views/job.rb +25 -0
- data/app/cyclid_ui/views/layout.rb +52 -0
- data/app/cyclid_ui/views/login.rb +25 -0
- data/app/cyclid_ui/views/organization.rb +25 -0
- data/app/cyclid_ui/views/user.rb +25 -0
- data/bin/cyclid-ui-assets +17 -0
- data/lib/cyclid_ui/app.rb +4 -0
- data/public/images/LICENSE +3 -0
- data/public/images/cyclid-logo-large.png +0 -0
- data/public/images/favicon16.png +0 -0
- data/public/images/favicon32.png +0 -0
- data/public/images/favicon48.png +0 -0
- data/public/images/favicon64.png +0 -0
- data/public/images/favicon96.png +0 -0
- data/public/js/api.js +34 -0
- data/public/js/cyclid.js +32 -0
- data/public/js/job.js +215 -0
- data/public/js/organization.js +345 -0
- data/public/js/user.js +145 -0
- data/public/vendor/bootstrap/css/bootstrap-theme.css +587 -0
- data/public/vendor/bootstrap/css/bootstrap-theme.css.map +1 -0
- data/public/vendor/bootstrap/css/bootstrap-theme.min.css +6 -0
- data/public/vendor/bootstrap/css/bootstrap-theme.min.css.map +1 -0
- data/public/vendor/bootstrap/css/bootstrap.css +6760 -0
- data/public/vendor/bootstrap/css/bootstrap.css.map +1 -0
- data/public/vendor/bootstrap/css/bootstrap.min.css +6 -0
- data/public/vendor/bootstrap/css/bootstrap.min.css.map +1 -0
- data/public/vendor/bootstrap/css/custom.css +193 -0
- data/public/vendor/bootstrap/fonts/glyphicons-halflings-regular.eot +0 -0
- data/public/vendor/bootstrap/fonts/glyphicons-halflings-regular.svg +288 -0
- data/public/vendor/bootstrap/fonts/glyphicons-halflings-regular.ttf +0 -0
- data/public/vendor/bootstrap/fonts/glyphicons-halflings-regular.woff +0 -0
- data/public/vendor/bootstrap/fonts/glyphicons-halflings-regular.woff2 +0 -0
- data/public/vendor/bootstrap/js/bootstrap.js +2363 -0
- data/public/vendor/bootstrap/js/bootstrap.min.js +7 -0
- data/public/vendor/bootstrap/js/npm.js +13 -0
- data/public/vendor/font-awesome/HELP-US-OUT.txt +7 -0
- data/public/vendor/font-awesome/css/font-awesome.css +2199 -0
- data/public/vendor/font-awesome/css/font-awesome.min.css +4 -0
- data/public/vendor/font-awesome/fonts/FontAwesome.otf +0 -0
- data/public/vendor/font-awesome/fonts/fontawesome-webfont.eot +0 -0
- data/public/vendor/font-awesome/fonts/fontawesome-webfont.svg +685 -0
- data/public/vendor/font-awesome/fonts/fontawesome-webfont.ttf +0 -0
- data/public/vendor/font-awesome/fonts/fontawesome-webfont.woff +0 -0
- data/public/vendor/font-awesome/fonts/fontawesome-webfont.woff2 +0 -0
- data/public/vendor/font-awesome/less/animated.less +34 -0
- data/public/vendor/font-awesome/less/bordered-pulled.less +25 -0
- data/public/vendor/font-awesome/less/core.less +12 -0
- data/public/vendor/font-awesome/less/fixed-width.less +6 -0
- data/public/vendor/font-awesome/less/font-awesome.less +18 -0
- data/public/vendor/font-awesome/less/icons.less +733 -0
- data/public/vendor/font-awesome/less/larger.less +13 -0
- data/public/vendor/font-awesome/less/list.less +19 -0
- data/public/vendor/font-awesome/less/mixins.less +60 -0
- data/public/vendor/font-awesome/less/path.less +15 -0
- data/public/vendor/font-awesome/less/rotated-flipped.less +20 -0
- data/public/vendor/font-awesome/less/screen-reader.less +5 -0
- data/public/vendor/font-awesome/less/stacked.less +20 -0
- data/public/vendor/font-awesome/less/variables.less +744 -0
- data/public/vendor/font-awesome/scss/_animated.scss +34 -0
- data/public/vendor/font-awesome/scss/_bordered-pulled.scss +25 -0
- data/public/vendor/font-awesome/scss/_core.scss +12 -0
- data/public/vendor/font-awesome/scss/_fixed-width.scss +6 -0
- data/public/vendor/font-awesome/scss/_icons.scss +733 -0
- data/public/vendor/font-awesome/scss/_larger.scss +13 -0
- data/public/vendor/font-awesome/scss/_list.scss +19 -0
- data/public/vendor/font-awesome/scss/_mixins.scss +60 -0
- data/public/vendor/font-awesome/scss/_path.scss +15 -0
- data/public/vendor/font-awesome/scss/_rotated-flipped.scss +20 -0
- data/public/vendor/font-awesome/scss/_screen-reader.scss +5 -0
- data/public/vendor/font-awesome/scss/_stacked.scss +20 -0
- data/public/vendor/font-awesome/scss/_variables.scss +744 -0
- data/public/vendor/font-awesome/scss/font-awesome.scss +18 -0
- data/public/vendor/jquery-2.2.4.min.js +4 -0
- data/public/vendor/jquery.md5.js +269 -0
- data/public/vendor/js.cookie.js +151 -0
- data/public/vendor/mustache.min.js +1 -0
- metadata +322 -0
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# Copyright 2016 Liqwyd Ltd.
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
|
16
|
+
module Cyclid
|
17
|
+
module UI
|
18
|
+
module Views
|
19
|
+
# Job view
|
20
|
+
class Job < Layout
|
21
|
+
attr_reader :job_url, :job_id
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# Copyright 2016 Liqwyd Ltd.
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
|
16
|
+
require 'digest/md5'
|
17
|
+
|
18
|
+
module Cyclid
|
19
|
+
module UI
|
20
|
+
module Views
|
21
|
+
# Main Layout view; everything common to the Views which use Layouts can
|
22
|
+
# be found here
|
23
|
+
class Layout < Mustache
|
24
|
+
attr_reader :organization, :api_url, :linkback_url
|
25
|
+
|
26
|
+
def username
|
27
|
+
@current_user.username || 'Nobody'
|
28
|
+
end
|
29
|
+
|
30
|
+
def organizations
|
31
|
+
@current_user.organizations
|
32
|
+
end
|
33
|
+
|
34
|
+
def title
|
35
|
+
@title || 'Cyclid'
|
36
|
+
end
|
37
|
+
|
38
|
+
# Return an array of elements to be inserted into the breadcrumb
|
39
|
+
def breadcrumbs
|
40
|
+
@crumbs.to_json
|
41
|
+
end
|
42
|
+
|
43
|
+
# Calculate the base Gravatar URL for the user
|
44
|
+
def gravatar_url
|
45
|
+
email = @current_user.email.downcase.strip
|
46
|
+
hash = Digest::MD5.hexdigest(email)
|
47
|
+
"https://www.gravatar.com/avatar/#{hash}?d=identicon&r=g"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# Copyright 2016 Liqwyd Ltd.
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
|
16
|
+
module Cyclid
|
17
|
+
module UI
|
18
|
+
module Views
|
19
|
+
# Login view. This is a non-Layout view.
|
20
|
+
class Login < Mustache
|
21
|
+
attr_reader :message
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# Copyright 2016 Liqwyd Ltd.
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
|
16
|
+
module Cyclid
|
17
|
+
module UI
|
18
|
+
module Views
|
19
|
+
# Organization view
|
20
|
+
class Organization < Layout
|
21
|
+
attr_reader :organization_url
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# Copyright 2016 Liqwyd Ltd.
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
|
16
|
+
module Cyclid
|
17
|
+
module UI
|
18
|
+
module Views
|
19
|
+
# User profile view
|
20
|
+
class User < Layout
|
21
|
+
attr_reader :user_url
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
# Copyright 2016 Liqwyd Ltd.
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
|
17
|
+
puts File.expand_path('../../public', __FILE__)
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
data/public/js/api.js
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
// Perform an authenticated GET to the API server.
|
2
|
+
function api_get(url, username, success, error) {
|
3
|
+
$.ajax({
|
4
|
+
type: 'GET',
|
5
|
+
url: encodeURI(url),
|
6
|
+
dataType: 'json',
|
7
|
+
crossDomain: true,
|
8
|
+
beforeSend: function(xhr) {
|
9
|
+
var token = Cookies.get('cyclid.token');
|
10
|
+
var authorization = `Token ${username}:${token}`
|
11
|
+
xhr.setRequestHeader('Authorization', authorization);
|
12
|
+
},
|
13
|
+
success: success,
|
14
|
+
error: error
|
15
|
+
});
|
16
|
+
}
|
17
|
+
|
18
|
+
// Perform an authenticated PUT to the API server.
|
19
|
+
function api_put(url, data, username, success, error) {
|
20
|
+
$.ajax({
|
21
|
+
type: 'PUT',
|
22
|
+
url: encodeURI(url),
|
23
|
+
data: JSON.stringify(data),
|
24
|
+
contentType: 'application/json',
|
25
|
+
crossDomain: true,
|
26
|
+
beforeSend: function(xhr) {
|
27
|
+
var token = Cookies.get('cyclid.token');
|
28
|
+
var authorization = `Token ${username}:${token}`
|
29
|
+
xhr.setRequestHeader('Authorization', authorization);
|
30
|
+
},
|
31
|
+
success: success,
|
32
|
+
error: error
|
33
|
+
});
|
34
|
+
}
|
data/public/js/cyclid.js
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
// Create an interval and store the handle with a key
|
2
|
+
function addNamedInterval(name, func, interval) {
|
3
|
+
if( window.timers == undefined ){
|
4
|
+
console.log('initializing window.timers');
|
5
|
+
window.timers = {};
|
6
|
+
}
|
7
|
+
|
8
|
+
if( window.timers[name] == null ) {
|
9
|
+
var interval = setInterval(func, interval);
|
10
|
+
console.log(`setting interval ${interval} as ${name}`);
|
11
|
+
window.timers[name] = interval;
|
12
|
+
}
|
13
|
+
}
|
14
|
+
|
15
|
+
// Remove a named interval previously created with addNamedInterval
|
16
|
+
function removeNamedInterval(name) {
|
17
|
+
var interval = window.timers[name];
|
18
|
+
|
19
|
+
if( interval != undefined ) {
|
20
|
+
console.log(`clearing interval ${interval} for ${name}`);
|
21
|
+
clearInterval(interval);
|
22
|
+
}
|
23
|
+
window.timers[name] = null;
|
24
|
+
}
|
25
|
+
|
26
|
+
// Remove all named intervals previously created with addNamedInterval
|
27
|
+
function clearAllNamedIntervals() {
|
28
|
+
for(var timer in window.timers){
|
29
|
+
console.log(`removing ${timer}`);
|
30
|
+
removeNamedInterval(timer);
|
31
|
+
}
|
32
|
+
}
|
data/public/js/job.js
ADDED
@@ -0,0 +1,215 @@
|
|
1
|
+
// Convert a Cyclid job status code to a human readable status
|
2
|
+
function ji_job_status_to_human(status_id) {
|
3
|
+
var statuses = {0: 'New',
|
4
|
+
1: 'Waiting',
|
5
|
+
2: 'Started',
|
6
|
+
3: 'Failing',
|
7
|
+
10: 'Succeeded',
|
8
|
+
11: 'Failed'};
|
9
|
+
var status = statuses[status_id];
|
10
|
+
|
11
|
+
var glyphs = {0: 'glyphicon-share-alt',
|
12
|
+
1: 'glyphicon-time',
|
13
|
+
2: 'glyphicon-refresh',
|
14
|
+
3: 'glyphicon-alert',
|
15
|
+
10: 'glyphicon-ok',
|
16
|
+
11: 'glyphicon-remove'};
|
17
|
+
var glyph = glyphs[status_id];
|
18
|
+
|
19
|
+
var labels = {0: 'label-primary',
|
20
|
+
1: 'label-primary',
|
21
|
+
2: 'label-info',
|
22
|
+
3: 'label-warning',
|
23
|
+
10: 'label-success',
|
24
|
+
11: 'label-danger'};
|
25
|
+
var label = labels[status_id];
|
26
|
+
|
27
|
+
return `<span class="label ${label}">
|
28
|
+
<span class="glyphicon ${glyph}" aria-hidden="true"></span> ${status}
|
29
|
+
</span>`
|
30
|
+
}
|
31
|
+
|
32
|
+
// Convert a Cyclid job status code to an indicator
|
33
|
+
function ji_job_status_to_indicator(status_id) {
|
34
|
+
var statuses = {0: 'New',
|
35
|
+
1: 'Waiting',
|
36
|
+
2: 'Started',
|
37
|
+
3: 'Failing',
|
38
|
+
10: 'Succeeded',
|
39
|
+
11: 'Failed'};
|
40
|
+
var status = statuses[status_id];
|
41
|
+
|
42
|
+
var glyphs = {0: 'glyphicon-share-alt',
|
43
|
+
1: 'glyphicon-time',
|
44
|
+
2: 'glyphicon-refresh',
|
45
|
+
3: 'glyphicon-alert',
|
46
|
+
10: 'glyphicon-ok',
|
47
|
+
11: 'glyphicon-remove'};
|
48
|
+
var glyph = glyphs[status_id];
|
49
|
+
|
50
|
+
var labels = {0: 'label-primary',
|
51
|
+
1: 'label-primary',
|
52
|
+
2: 'label-info',
|
53
|
+
3: 'label-warning',
|
54
|
+
10: 'label-success',
|
55
|
+
11: 'label-danger'};
|
56
|
+
var label = labels[status_id];
|
57
|
+
|
58
|
+
return `<span class="label ${label}">
|
59
|
+
<span class="glyphicon ${glyph}" aria-hidden="true" title="${status}"></span>
|
60
|
+
</span>`
|
61
|
+
}
|
62
|
+
|
63
|
+
function ji_calculate_duration(started, ended) {
|
64
|
+
var date_started = new Date(started);
|
65
|
+
var date_ended = new Date(ended);
|
66
|
+
|
67
|
+
var duration = '';
|
68
|
+
if( date_ended > 0 ){
|
69
|
+
duration = new Date(date_ended.getTime() - date_started.getTime()).toISOString().substr(11, 8);
|
70
|
+
}
|
71
|
+
|
72
|
+
return duration;
|
73
|
+
}
|
74
|
+
|
75
|
+
// Set & show the job log element
|
76
|
+
function ji_update_log(log_text) {
|
77
|
+
// Show the log
|
78
|
+
var outer = $('#ji_log_outer');
|
79
|
+
outer.removeClass('hidden');
|
80
|
+
|
81
|
+
// Find the current position of the scrollable element, before we update it
|
82
|
+
var inner = $('#ji_log_inner')
|
83
|
+
var diff = inner.prop('scrollHeight') - (inner.scrollTop() + inner.outerHeight());
|
84
|
+
|
85
|
+
// Update the log
|
86
|
+
inner.html(log_text);
|
87
|
+
|
88
|
+
// If the user hasn't scrolled up, scroll to the bottom to show the new log data
|
89
|
+
if( diff <= 0 )
|
90
|
+
inner.scrollTop(inner.prop('scrollHeight'));
|
91
|
+
}
|
92
|
+
|
93
|
+
// Is the job in a "Failed" or "Succeeded" state?
|
94
|
+
function ji_job_finished(job_status) {
|
95
|
+
if( job_status == 10 || job_status == 11 ) {
|
96
|
+
return true;
|
97
|
+
} else {
|
98
|
+
return false;
|
99
|
+
}
|
100
|
+
}
|
101
|
+
|
102
|
+
// Is the job still active?
|
103
|
+
function ji_job_active(job_status) {
|
104
|
+
return !ji_job_finished(job_status);
|
105
|
+
}
|
106
|
+
|
107
|
+
function ji_update_status(job) {
|
108
|
+
var status = ji_job_status_to_human(job.status)
|
109
|
+
$('#ji_job_status').html(status);
|
110
|
+
$('#ji_job_status').data('status', job.status);
|
111
|
+
|
112
|
+
// Update the "Waiting" message appropriately
|
113
|
+
var waiting = '<h6>Unknown</h6>';
|
114
|
+
switch(job.status) {
|
115
|
+
case 1:
|
116
|
+
case 2:
|
117
|
+
waiting = '<h6><i class="fa fa-spinner fa-pulse"></i> Waiting for job to start...</h6>'
|
118
|
+
$('#ji_job_waiting').html(waiting);
|
119
|
+
$('#ji_job_waiting').removeClass('hidden');
|
120
|
+
break;
|
121
|
+
case 3:
|
122
|
+
case 4:
|
123
|
+
waiting = '<h6><i class="fa fa-cog fa-spin"></i> Waiting for job to complete...</h6>';
|
124
|
+
$('#ji_job_waiting').html(waiting);
|
125
|
+
$('#ji_job_waiting').removeClass('hidden');
|
126
|
+
break;
|
127
|
+
case 10:
|
128
|
+
case 11:
|
129
|
+
$('#ji_job_waiting').addClass('hidden');
|
130
|
+
break;
|
131
|
+
}
|
132
|
+
|
133
|
+
// Update the status indicator, if there is one
|
134
|
+
var indicator = ji_job_status_to_indicator(job.status);
|
135
|
+
$(`#row${job.job_id} > #status`).html(indicator);
|
136
|
+
}
|
137
|
+
|
138
|
+
// Set & show the job details
|
139
|
+
function ji_update_details(job) {
|
140
|
+
var title = `<a href="${gblLinkbackURL}/job/${job.id}">${job.job_name} <small>v${job.job_version}</small></a>`;
|
141
|
+
$('#ji_header').html(title);
|
142
|
+
|
143
|
+
$('#ji_job_id').text(job.id);
|
144
|
+
|
145
|
+
if (job.started) {
|
146
|
+
var started = new Date(job.started);
|
147
|
+
$('#ji_job_started').text(started.toUTCString());
|
148
|
+
}
|
149
|
+
|
150
|
+
if (job.ended) {
|
151
|
+
var ended = new Date(job.ended);
|
152
|
+
$('#ji_job_ended').text(ended.toUTCString());
|
153
|
+
}
|
154
|
+
|
155
|
+
var duration = ji_calculate_duration(job.started, job.ended);
|
156
|
+
$('#ji_job_duration').text(duration);
|
157
|
+
|
158
|
+
$('#ji_details').removeClass('hidden');
|
159
|
+
}
|
160
|
+
|
161
|
+
// Update everything: job details, status & log
|
162
|
+
function ji_update_all(job) {
|
163
|
+
ji_update_details(job);
|
164
|
+
ji_update_status(job);
|
165
|
+
ji_update_log(job.log);
|
166
|
+
}
|
167
|
+
|
168
|
+
function ji_get_failed(xhr) {
|
169
|
+
var failure_message = `<p>
|
170
|
+
<h2>Failed to retrieve job</h2><br>
|
171
|
+
<strong>${xhr.status}:</strong> ${xhr.responseText}
|
172
|
+
</p>`
|
173
|
+
$('#ji_failure > #error_message').html(failure_message);
|
174
|
+
|
175
|
+
$('#ji_failure').removeClass('hidden');
|
176
|
+
}
|
177
|
+
|
178
|
+
function ji_update_status_and_check_completion(url, job) {
|
179
|
+
var last_status = $('#ji_job_status').data('status');
|
180
|
+
if( job.status != last_status ) {
|
181
|
+
ji_update_status(job);
|
182
|
+
}
|
183
|
+
|
184
|
+
// Did the job end?
|
185
|
+
if( ji_job_finished(job.status) ){
|
186
|
+
console.log(`job #${job.job_id} ended`);
|
187
|
+
|
188
|
+
// Update the job details so that E.g. the "Ended" time is shown
|
189
|
+
api_get(url, gblUsername, ji_update_details, ji_get_failed);
|
190
|
+
|
191
|
+
// Find any timer associated with the job info & remove it
|
192
|
+
removeNamedInterval(`watcher${job.job_id}`);
|
193
|
+
}
|
194
|
+
}
|
195
|
+
|
196
|
+
function ji_watch_job(url) {
|
197
|
+
console.log(`ji_watch_job(${url})`);
|
198
|
+
|
199
|
+
// Check job status
|
200
|
+
var status_url = `${url}/status`;
|
201
|
+
console.log(`updating status from ${status_url}`);
|
202
|
+
api_get(status_url,
|
203
|
+
gblUsername,
|
204
|
+
function(job) {
|
205
|
+
ji_update_status_and_check_completion(url, job);
|
206
|
+
},
|
207
|
+
ji_get_failed);
|
208
|
+
|
209
|
+
// Update log
|
210
|
+
var log_url = `${url}/log`;
|
211
|
+
console.log(`updating log from ${log_url}`);
|
212
|
+
api_get(log_url, gblUsername, function(data) { ji_update_log(data.log); }, ji_get_failed);
|
213
|
+
|
214
|
+
console.log(`ji_watch_job(${url}) finished`);
|
215
|
+
}
|