help_desk_dashboard 0.0.1
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.
- 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
|
+
}
|