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.
Files changed (24) hide show
  1. data/bin/help_desk_dashboard.rb +19 -0
  2. data/lib/help-desk-dashboard/provider_factory.rb +9 -0
  3. data/lib/help-desk-dashboard/providers/service-desk-plus/8.1/provider.rb +11 -0
  4. data/lib/help-desk-dashboard/providers/track-it/2003.10.1/navigator.rb +13 -0
  5. data/lib/help-desk-dashboard/providers/track-it/2003.10.1/parallel_request_scraper.rb +42 -0
  6. data/lib/help-desk-dashboard/providers/track-it/2003.10.1/provider.rb +27 -0
  7. data/lib/help-desk-dashboard/providers/track-it/2003.10.1/request_scraper.rb +48 -0
  8. data/lib/help-desk-dashboard/providers/track-it/2003.10.1/user_operations.rb +40 -0
  9. data/lib/help-desk-dashboard/providers/track-it/2003.10.1/user_request_scraper.rb +33 -0
  10. data/lib/help-desk-dashboard/web/config.ru +16 -0
  11. data/lib/help-desk-dashboard/web/public/bootstrap/css/bootstrap-responsive.css +1109 -0
  12. data/lib/help-desk-dashboard/web/public/bootstrap/css/bootstrap-responsive.min.css +9 -0
  13. data/lib/help-desk-dashboard/web/public/bootstrap/css/bootstrap.css +6158 -0
  14. data/lib/help-desk-dashboard/web/public/bootstrap/css/bootstrap.min.css +9 -0
  15. data/lib/help-desk-dashboard/web/public/bootstrap/img/glyphicons-halflings-white.png +0 -0
  16. data/lib/help-desk-dashboard/web/public/bootstrap/img/glyphicons-halflings.png +0 -0
  17. data/lib/help-desk-dashboard/web/public/bootstrap/js/bootstrap.js +2268 -0
  18. data/lib/help-desk-dashboard/web/public/bootstrap/js/bootstrap.min.js +6 -0
  19. data/lib/help-desk-dashboard/web/public/css/app.css +64 -0
  20. data/lib/help-desk-dashboard/web/public/index.html +16 -0
  21. data/lib/help-desk-dashboard/web/public/js/app.js +107 -0
  22. data/lib/help-desk-dashboard/web/public/js/jquery-1.10.1.min.js +6 -0
  23. data/lib/help-desk-dashboard/web/public/js/moment.min.js +6 -0
  24. 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,9 @@
1
+ class ProviderFactory
2
+
3
+ def create(config)
4
+ path = File.join File.dirname(__FILE__), 'providers', config['provider'], config['version'], 'provider.rb'
5
+ load path
6
+ Provider.new config
7
+ end
8
+
9
+ end
@@ -0,0 +1,11 @@
1
+ class Provider
2
+
3
+ def initialize(config)
4
+
5
+ end
6
+
7
+ def get_requests
8
+
9
+ end
10
+
11
+ end
@@ -0,0 +1,13 @@
1
+ class Navigator
2
+
3
+ def initialize(b, base_url)
4
+ @b = b
5
+ @base_url = base_url
6
+ end
7
+
8
+ def goto(relative_url)
9
+ url = File.join @base_url, relative_url
10
+ @b.goto url
11
+ end
12
+
13
+ end
@@ -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
+ }