help_desk_dashboard 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/help_desk_dashboard.rb +19 -0
- data/lib/help-desk-dashboard/provider_factory.rb +9 -0
- data/lib/help-desk-dashboard/providers/service-desk-plus/8.1/provider.rb +11 -0
- data/lib/help-desk-dashboard/providers/track-it/2003.10.1/navigator.rb +13 -0
- data/lib/help-desk-dashboard/providers/track-it/2003.10.1/parallel_request_scraper.rb +42 -0
- data/lib/help-desk-dashboard/providers/track-it/2003.10.1/provider.rb +27 -0
- data/lib/help-desk-dashboard/providers/track-it/2003.10.1/request_scraper.rb +48 -0
- data/lib/help-desk-dashboard/providers/track-it/2003.10.1/user_operations.rb +40 -0
- data/lib/help-desk-dashboard/providers/track-it/2003.10.1/user_request_scraper.rb +33 -0
- data/lib/help-desk-dashboard/web/config.ru +16 -0
- data/lib/help-desk-dashboard/web/public/bootstrap/css/bootstrap-responsive.css +1109 -0
- data/lib/help-desk-dashboard/web/public/bootstrap/css/bootstrap-responsive.min.css +9 -0
- data/lib/help-desk-dashboard/web/public/bootstrap/css/bootstrap.css +6158 -0
- data/lib/help-desk-dashboard/web/public/bootstrap/css/bootstrap.min.css +9 -0
- data/lib/help-desk-dashboard/web/public/bootstrap/img/glyphicons-halflings-white.png +0 -0
- data/lib/help-desk-dashboard/web/public/bootstrap/img/glyphicons-halflings.png +0 -0
- data/lib/help-desk-dashboard/web/public/bootstrap/js/bootstrap.js +2268 -0
- data/lib/help-desk-dashboard/web/public/bootstrap/js/bootstrap.min.js +6 -0
- data/lib/help-desk-dashboard/web/public/css/app.css +64 -0
- data/lib/help-desk-dashboard/web/public/index.html +16 -0
- data/lib/help-desk-dashboard/web/public/js/app.js +107 -0
- data/lib/help-desk-dashboard/web/public/js/jquery-1.10.1.min.js +6 -0
- data/lib/help-desk-dashboard/web/public/js/moment.min.js +6 -0
- metadata +102 -0
@@ -0,0 +1,19 @@
|
|
1
|
+
$stdout.sync = true
|
2
|
+
|
3
|
+
require_relative '../lib/help-desk-dashboard/provider_factory'
|
4
|
+
|
5
|
+
ENV['HTTP_PROXY'] = nil
|
6
|
+
ENV['CONFIG_FILE'] ||= 'config.json'
|
7
|
+
|
8
|
+
config = JSON.parse File.read(ENV['CONFIG_FILE'])
|
9
|
+
config['thread_limit'] = ENV['THREAD_LIMIT'] ||= '5'
|
10
|
+
provider_factory = ProviderFactory.new
|
11
|
+
provider = provider_factory.create config
|
12
|
+
requests = provider.get_requests
|
13
|
+
|
14
|
+
public_web_dir = File.join File.dirname(__FILE__) + '/../lib/help-desk-dashboard/web/public'
|
15
|
+
data_file = File.join public_web_dir, 'data.json'
|
16
|
+
File.write data_file, requests.to_json
|
17
|
+
FileUtils.cp_r "#{public_web_dir}/.", config['output_dir']
|
18
|
+
|
19
|
+
puts 'Done.'
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'thread'
|
2
|
+
require 'watir-webdriver'
|
3
|
+
require_relative 'request_scraper'
|
4
|
+
require_relative 'user_operations'
|
5
|
+
|
6
|
+
class ParallelRequestScraper
|
7
|
+
|
8
|
+
def initialize(url, user, thread_limit)
|
9
|
+
@url = url
|
10
|
+
@user = user
|
11
|
+
@thread_limit = thread_limit
|
12
|
+
end
|
13
|
+
|
14
|
+
def scrape(request_ids)
|
15
|
+
queue = request_ids.clone
|
16
|
+
threads = []
|
17
|
+
requests = []
|
18
|
+
mutex = Mutex.new
|
19
|
+
|
20
|
+
@thread_limit.times do
|
21
|
+
threads << Thread.new do
|
22
|
+
b = Watir::Browser.new
|
23
|
+
navigator = Navigator.new b, @url
|
24
|
+
user_operations = UserOperations.new b, navigator
|
25
|
+
user_operations.login @user
|
26
|
+
request_scraper = RequestScraper.new b, navigator
|
27
|
+
until queue.empty?
|
28
|
+
id = nil
|
29
|
+
mutex.synchronize do
|
30
|
+
id = queue.pop
|
31
|
+
end
|
32
|
+
break unless id
|
33
|
+
requests << request_scraper.scrape(id)
|
34
|
+
end
|
35
|
+
b.close
|
36
|
+
end
|
37
|
+
end
|
38
|
+
threads.each { |t| t.join }
|
39
|
+
requests
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'watir-webdriver'
|
2
|
+
require_relative 'navigator'
|
3
|
+
require_relative 'parallel_request_scraper'
|
4
|
+
require_relative 'user_operations'
|
5
|
+
|
6
|
+
class Provider
|
7
|
+
|
8
|
+
def initialize(config)
|
9
|
+
@config = config
|
10
|
+
end
|
11
|
+
|
12
|
+
def get_requests
|
13
|
+
url = @config['url']
|
14
|
+
users = @config['users']
|
15
|
+
|
16
|
+
b = Watir::Browser.new
|
17
|
+
navigator = Navigator.new b, url
|
18
|
+
user_operations = UserOperations.new b, navigator
|
19
|
+
request_ids = user_operations.get_request_ids users
|
20
|
+
b.close
|
21
|
+
|
22
|
+
user = users.first
|
23
|
+
parallel_request_scraper = ParallelRequestScraper.new url, user, @config['thread_limit'].to_i
|
24
|
+
parallel_request_scraper.scrape request_ids
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'time'
|
2
|
+
|
3
|
+
class RequestScraper
|
4
|
+
|
5
|
+
def initialize(b, navigator)
|
6
|
+
@b = b
|
7
|
+
@navigator = navigator
|
8
|
+
end
|
9
|
+
|
10
|
+
def scrape(id)
|
11
|
+
@navigator.goto "hd/ticket/euTicketView.ssp?ticket_id=#{id}&log=show"
|
12
|
+
cells = @b.tables[1].tds.to_a
|
13
|
+
{
|
14
|
+
id: @b.text.match(/Request #(\d+)/)[1],
|
15
|
+
title: cells[0].text,
|
16
|
+
status: cells[2].text,
|
17
|
+
service: cells[3].text,
|
18
|
+
request_type: cells[4].text,
|
19
|
+
time_spent: cells[6].text,
|
20
|
+
priority: cells[7].text,
|
21
|
+
deadline: Time.parse(cells[8].text),
|
22
|
+
submitted_to: cells[10].text,
|
23
|
+
submitted_by: cells[11].text.upcase,
|
24
|
+
submitted_on: Time.parse(cells[12].text),
|
25
|
+
assigned_to: cells[15].text.upcase,
|
26
|
+
assigned_by: cells[16].text,
|
27
|
+
assigned_on: Time.parse(cells[17].text),
|
28
|
+
department_id: cells[19].text,
|
29
|
+
closed_by: cells[20].text,
|
30
|
+
closed_on: cells[21].text == 'None' ? 'None' : Time.parse(cells[21].text)
|
31
|
+
}.merge scrape_resolved_data_from_audit_log
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def scrape_resolved_data_from_audit_log
|
37
|
+
rows = @b.tables[3].trs.to_a
|
38
|
+
index = rows.index { |r| r.text =~ /Resolved by/ }
|
39
|
+
return {} unless index
|
40
|
+
text = rows[index-1].text
|
41
|
+
matches = text.match /(.+) by (.+)/
|
42
|
+
{
|
43
|
+
resolved_on: Time.parse(matches[1]),
|
44
|
+
resolved_by: matches[2].upcase
|
45
|
+
}
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
class UserOperations
|
2
|
+
|
3
|
+
def initialize(b, navigator)
|
4
|
+
@b = b
|
5
|
+
@navigator = navigator
|
6
|
+
end
|
7
|
+
|
8
|
+
def login(user)
|
9
|
+
@navigator.goto 'hd/index.ssp'
|
10
|
+
@b.text_field(name: 'user_id').set user['username']
|
11
|
+
@b.text_field(name: 'user_pwd').set user['password']
|
12
|
+
@b.button(value: 'Log on').click
|
13
|
+
end
|
14
|
+
|
15
|
+
def get_request_ids(users)
|
16
|
+
users = [users].flatten
|
17
|
+
request_ids = users.map do |user|
|
18
|
+
login user
|
19
|
+
@navigator.goto 'hd/ticket/euTicketFind.ssp'
|
20
|
+
@b.button(value: 'Find').click
|
21
|
+
request_locations = get_request_locations
|
22
|
+
request_locations.map { |l| l.match(/ticket_id=(\d+)/)[1].to_i }
|
23
|
+
end
|
24
|
+
request_ids.flatten
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def get_request_locations
|
30
|
+
links = []
|
31
|
+
5.times do
|
32
|
+
links = @b.links(href: /euTicketView\.ssp\?ticket_id=/).to_a
|
33
|
+
break unless links.empty?
|
34
|
+
sleep 2
|
35
|
+
end
|
36
|
+
puts "No requests found.\n\n#{@b.html}" if links.empty?
|
37
|
+
links.map { |link| link.href }.reverse
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'time'
|
2
|
+
require 'watir-webdriver'
|
3
|
+
require_relative 'request_scraper'
|
4
|
+
|
5
|
+
class UserRequestScraper
|
6
|
+
|
7
|
+
def initialize(b)
|
8
|
+
@b = b
|
9
|
+
end
|
10
|
+
|
11
|
+
def scrape
|
12
|
+
@b.goto 'hd/ticket/euTicketFind.ssp'
|
13
|
+
@b.button(value: 'Find').click
|
14
|
+
request_locations = get_request_locations
|
15
|
+
request_ids = request_locations.map { |l| l.match(/ticket_id=(\d+)/)[1].to_i }
|
16
|
+
request_scraper = RequestScraper.new @b
|
17
|
+
request_scraper.scrape_range request_ids
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def get_request_locations
|
23
|
+
links = []
|
24
|
+
5.times do
|
25
|
+
links = @b.links(href: /euTicketView\.ssp\?ticket_id=/).to_a
|
26
|
+
break unless links.empty?
|
27
|
+
sleep 2
|
28
|
+
end
|
29
|
+
puts "No requests found.\n\n#{@b.html}" if links.empty?
|
30
|
+
links.map { |link| link.href }.reverse
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'rack'
|
2
|
+
|
3
|
+
use Rack::Static,
|
4
|
+
:urls => %w(/bootstrap /css /js /data.json),
|
5
|
+
:root => 'public'
|
6
|
+
|
7
|
+
run lambda { |env|
|
8
|
+
[
|
9
|
+
200,
|
10
|
+
{
|
11
|
+
'Content-Type' => 'text/html',
|
12
|
+
'Cache-Control' => 'public, max-age=86400'
|
13
|
+
},
|
14
|
+
File.open('public/index.html', File::RDONLY)
|
15
|
+
]
|
16
|
+
}
|