sinatra-hexacta 0.0.2 → 0.3.2

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 (50) hide show
  1. checksums.yaml +4 -4
  2. data/lib/sinatra/extensions/antiquity.rb +34 -0
  3. data/lib/sinatra/extensions/date.rb +49 -0
  4. data/lib/sinatra/extensions/generalmail.rb +26 -0
  5. data/lib/sinatra/extensions/init.rb +8 -0
  6. data/lib/sinatra/extensions/mail.rb +35 -0
  7. data/lib/sinatra/extensions/mailbuilder.rb +38 -0
  8. data/lib/sinatra/extensions/mailsender.rb +88 -0
  9. data/lib/sinatra/extensions/notification.rb +44 -0
  10. data/lib/sinatra/handlers/errors.rb +11 -4
  11. data/lib/sinatra/handlers/init.rb +3 -1
  12. data/lib/sinatra/handlers/notifications.rb +17 -28
  13. data/lib/sinatra/handlers/params.rb +26 -0
  14. data/lib/sinatra/handlers/reports.rb +28 -1
  15. data/lib/sinatra/helpers/alerts.rb +27 -0
  16. data/lib/sinatra/helpers/cas.rb +92 -0
  17. data/lib/sinatra/helpers/charts.rb +21 -5
  18. data/lib/sinatra/helpers/init.rb +4 -0
  19. data/lib/sinatra/helpers/inputs.rb +3 -3
  20. data/lib/sinatra/helpers/libraries.rb +3 -3
  21. data/lib/sinatra/helpers/reports.rb +27 -0
  22. data/lib/sinatra/helpers/schedule.rb +68 -0
  23. data/lib/sinatra/helpers/subscriptions.rb +1 -1
  24. data/lib/sinatra/hexacta.rb +15 -9
  25. data/lib/sinatra/public/css/app.min.1.css +132 -6
  26. data/lib/sinatra/public/js/app.js +49 -42
  27. data/lib/sinatra/public/vendors/chartist/chartist-plugin-legend.js +237 -0
  28. data/lib/sinatra/public/vendors/typeahead.js/typeahead.bundle.min.js +1 -2
  29. data/lib/sinatra/views/alerts/empty.slim +7 -0
  30. data/lib/sinatra/views/alerts/error.slim +7 -0
  31. data/lib/sinatra/views/alerts/info.slim +7 -0
  32. data/lib/sinatra/views/alerts/warning.slim +7 -0
  33. data/lib/sinatra/views/charts/bar.slim +56 -0
  34. data/lib/sinatra/views/charts/gauge.slim +30 -0
  35. data/lib/sinatra/views/charts/{simple_line.slim → line.slim} +7 -8
  36. data/lib/sinatra/views/charts/pie.slim +34 -0
  37. data/lib/sinatra/views/charts/stacked_bar.slim +36 -0
  38. data/lib/sinatra/views/inputs/multiple_select.slim +4 -0
  39. data/lib/sinatra/views/inputs/select.slim +3 -0
  40. data/lib/sinatra/views/libraries/include_js_after.slim +0 -24
  41. data/lib/sinatra/views/libraries/include_js_before.slim +1 -0
  42. data/lib/sinatra/views/notifications.slim +37 -31
  43. data/lib/sinatra/views/notifications/form.slim +4 -4
  44. data/lib/sinatra/views/notifications/new.slim +4 -4
  45. data/lib/sinatra/views/notifications/widget.slim +9 -5
  46. data/lib/sinatra/views/reports/pick_date.slim +14 -0
  47. data/lib/sinatra/views/reports/pick_dates.slim +16 -0
  48. data/lib/sinatra/views/reports/pick_month.slim +14 -0
  49. data/lib/sinatra/views/reports/pick_year.slim +14 -0
  50. metadata +30 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: acbebd0dade426417f396054c4d2e277402fc59cbad3b7e27c248a193e59859d
4
- data.tar.gz: beaf9fcfffa445c4b7f39e49be20132bf8103199dc972b4b1235d89280e6c4b6
3
+ metadata.gz: a6fb503a8966bb24d1526acd9e44a6b8f798967193f7b5c465c61b86c4eb4d76
4
+ data.tar.gz: 1896cd47708d90de659d4e7d5253d3588331fd2372234c7c1bc152783bbd75ff
5
5
  SHA512:
6
- metadata.gz: 9b374e1e2f8106c23168de0312034f4dab4669d11582f51e935ed436eab1b7f1965fd1963f3fc64a39de16f199c19ad3948655de3f04fb1b77d8c64a17aac186
7
- data.tar.gz: 268e659e4ae71122214d640c33a4c5e3a2cc6a5f1338aa6659633a18673671278ec1752d19ecd9febc1988ba632c7d836d751915544811c11fec8e4f64e72bfa
6
+ metadata.gz: 2cbd2de133ebff3475d3d8f398d6588d264d6d310194b150e45a061a7d094f03dfe7288ef5b27bc1d9cecf663504fd793e0d0da9c9d47852ce327f04c5fc1e0b
7
+ data.tar.gz: ff26fc925028c9a03ca3af480c9292ed8a6ba6f463180d39625fb5a6ed896d13570f41e786a9d4038235ddfd950234e0e1ef402ee8be17085e8a8eb3670319c4
@@ -0,0 +1,34 @@
1
+ # encoding: utf-8
2
+ class Antiquity
3
+
4
+ def initialize(periods)
5
+ @periods = periods.sort { |a,b| a.start_date <=> b.start_date }
6
+ end
7
+
8
+ def days
9
+ @periods.inject(0) { |total, period| total + period.days }
10
+ end
11
+
12
+ def months
13
+ @periods.inject(0) { |total, period| total + period.months }
14
+ end
15
+
16
+ def years
17
+ months.divmod(12).first
18
+ end
19
+
20
+ def to_s
21
+ date = (@periods.last && @periods.last.end_date) || Date.today
22
+ result = ""
23
+ return result if @periods.empty?
24
+ if date >= @periods.first.start_date
25
+ result += years > 1 ? "#{years} años" : "#{years} año" unless years == 0
26
+ result += ", " if years >= 1 && !(months.modulo(12).eql?(0))
27
+ result += months.modulo(12) > 1 ? "#{months.modulo(12)} meses" : "#{months.modulo(12)} mes" unless months.modulo(12) == 0
28
+ result += "#{(date - @periods.last.start_date).to_i} dias" if months.modulo(12) == 0 && years == 0 && date > @periods.last.start_date
29
+ result += "Hoy!" if months.modulo(12) == 0 && date == @periods.last.start_date
30
+ end
31
+ result += "En unos días..." if date < @periods.first.start_date
32
+ result
33
+ end
34
+ end
@@ -0,0 +1,49 @@
1
+ # encoding: utf-8
2
+ class Date
3
+
4
+ def self.year(year=Date.today.year)
5
+ Date.new(year)
6
+ end
7
+
8
+ def january(day=nil)
9
+ day.nil?? self.change(month: 1) : self.change(month: 1, day: day)
10
+ end
11
+
12
+ def october(day=nil)
13
+ day.nil?? self.change(month: 10) : self.change(month: 10, day: day)
14
+ end
15
+
16
+ def december(day=nil)
17
+ day.nil?? self.change(month: 12) : self.change(month: 12, day: day)
18
+ end
19
+
20
+ def monday
21
+ self - (self.wday - 1) % 7
22
+ end
23
+
24
+ def weekend?
25
+ self.wday == 0 || self.wday == 6
26
+ end
27
+
28
+ def display
29
+ "#{Configuration::DAYS[self.wday]} #{self.day} de #{Configuration::MONTHS[self.month-1]} #{self.year == Date.today.year ? '' : self.year}"
30
+ end
31
+
32
+ def short_display
33
+ self.strftime('%d/%m/%Y')
34
+ end
35
+
36
+ def next_working_date
37
+ add_working_days(1)
38
+ end
39
+
40
+ def prev_working_date
41
+ add_working_days(-1)
42
+ end
43
+
44
+ def first_monday_before
45
+ return self if self.monday?
46
+ (self - 1).first_monday_before
47
+ end
48
+
49
+ end
@@ -0,0 +1,26 @@
1
+ # encoding: utf-8
2
+ class GeneralMail < Mail
3
+
4
+ def initialize(args)
5
+ super(args)
6
+ @subject = args[:subject]
7
+ @description = args[:description]
8
+ @link = args[:link]
9
+ end
10
+
11
+ def template
12
+ 'general'
13
+ end
14
+
15
+ def subject
16
+ @subject
17
+ end
18
+
19
+ def values
20
+ data = {}
21
+ data["{description}"] = @description
22
+ data["{link}"] = @link
23
+ data
24
+ end
25
+
26
+ end
@@ -0,0 +1,8 @@
1
+ # encoding: utf-8
2
+ require_relative 'date'
3
+ require_relative 'antiquity'
4
+ require_relative 'notification'
5
+ require_relative 'mailsender'
6
+ require_relative 'mail'
7
+ require_relative 'generalmail'
8
+ require_relative 'mailbuilder'
@@ -0,0 +1,35 @@
1
+ # encoding: utf-8
2
+ class Mail
3
+
4
+ def initialize(args)
5
+ @receivers = args[:to]
6
+ @sender = args[:from]
7
+ end
8
+
9
+ def template
10
+ raise Exception, "You have to override 'template' method in #{self.class}"
11
+ end
12
+
13
+ def subject
14
+ raise Exception, "You have to override 'subject' method in #{self.class}"
15
+ end
16
+
17
+ def values
18
+ raise Exception, "You have to override 'values' method in #{self.class}"
19
+ end
20
+
21
+ def to
22
+ _receivers = {}
23
+ @receivers.each { |user| _receivers[user.full_name] = "Persons" }
24
+ _receivers
25
+ end
26
+
27
+ def from
28
+ @sender ||= "apps@hexacta.com"
29
+ end
30
+
31
+ def send
32
+ MailSender.perform_async(self)
33
+ end
34
+
35
+ end
@@ -0,0 +1,38 @@
1
+ # encoding: utf-8
2
+ class MailBuilder
3
+
4
+ def to(receivers)
5
+ @to = receivers
6
+ return self
7
+ end
8
+
9
+ def from(sender)
10
+ @from = "#{sender.hxt_id}@hexacta.com"
11
+ return self
12
+ end
13
+
14
+ def subject(a_subject)
15
+ @subject = a_subject
16
+ return self
17
+ end
18
+
19
+ def description(a_description)
20
+ @description = a_description
21
+ return self
22
+ end
23
+
24
+ def link(a_link)
25
+ @link = a_link
26
+ return self
27
+ end
28
+
29
+ def send
30
+ @from ||= "apps@hexacta.com"
31
+ GeneralMail.new({ :to => @to,
32
+ :from => @from,
33
+ :subject => @subject,
34
+ :description => @description,
35
+ :link => @link
36
+ }).send
37
+ end
38
+ end
@@ -0,0 +1,88 @@
1
+ # encoding: utf-8
2
+ require 'singleton'
3
+ require 'sucker_punch'
4
+
5
+ class MailSender
6
+ include SuckerPunch::Job
7
+
8
+ attr_reader :access_token, :expire, :refresh_token
9
+
10
+ def _do_connect(uri, form={},token=nil)
11
+ url = URI.parse("#{uri}")
12
+ http = Net::HTTP.new(url.host, url.port)
13
+ http.read_timeout = 1000
14
+ http.use_ssl = (url.scheme == 'https')
15
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
16
+ header = { 'Content-Type' => 'application/x-www-form-urlencoded' }
17
+ header["Authorization"] = "Bearer #{token}" unless token.nil?
18
+ request = Net::HTTP::Post.new(url, header)
19
+ request.form_data = form
20
+ http.start { |http| http.request(request) }
21
+ end
22
+
23
+ def _authorize_mail
24
+ params = [ [ "grant_type", "password" ], [ "client_id", "MailApp" ], [ "client_secret", "MailAppPRD2018!" ] ]
25
+ response = _do_connect("https://comunicacion.hexacta.com:4443/apptoken",params)
26
+ if( response.is_a?( Net::HTTPSuccess ) )
27
+ token = JSON.parse(response.body)
28
+ @access_token = token["access_token"]
29
+ @refresh_token = token["refresh_token"]
30
+ @expire = DateTime.parse(token[".expires"])
31
+ else
32
+ NotificationSender.instance.send_error(nil,'Authorize mail failed',response.body)
33
+ end
34
+ end
35
+
36
+ def _build_map_values(mail_values)
37
+ values = []
38
+ for key in mail_values.keys
39
+ index = mail_values.keys.index(key)
40
+ values << ["MailValues[#{index}].Key", key]
41
+ values << ["MailValues[#{index}].Value", mail_values[key]]
42
+ end
43
+ values
44
+ end
45
+
46
+ def _build_to_map(to_map)
47
+ values = []
48
+ for key in to_map.keys
49
+ index = to_map.keys.index(key)
50
+ values << ["ResourcesRequest[#{index}].TypeGroup", to_map[key]]
51
+ values << ["ResourcesRequest[#{index}].Name", key]
52
+ end
53
+ values
54
+ end
55
+
56
+ def _expired?
57
+ expire.nil? || DateTime.now < expire
58
+ end
59
+
60
+ def do_send(mail)
61
+ begin
62
+ if _expired?
63
+ _authorize_mail
64
+ end
65
+
66
+ params = [ [ "ApplicationCode", 2009 ], [ "Name", mail.template ], [ "Subject", mail.subject ], [ "EmailAddress", mail.from ] ]
67
+ params = params + _build_map_values(mail.values) + _build_to_map(mail.to)
68
+
69
+ response = _do_connect("https://comunicacion.hexacta.com:4444/api/app/TemplateNotification/SendMail",params,@access_token)
70
+
71
+ if( !response.is_a?( Net::HTTPSuccess ) )
72
+ NotificationSender.instance.send_error(nil,'Send mail failed',response.body)
73
+ end
74
+ rescue StandardError => error
75
+ message = error.backtrace.join(',');
76
+ NotificationSender.instance.send_error(nil,"Mail send error",message)
77
+ end
78
+ end
79
+
80
+ def send(mail)
81
+ run(mail) #Async call
82
+ end
83
+
84
+ #For async method call
85
+ def perform(mail)
86
+ do_send(mail)
87
+ end
88
+ end
@@ -0,0 +1,44 @@
1
+ # encoding: utf-8
2
+ require 'singleton'
3
+
4
+ class NotificationSender
5
+ include Singleton
6
+
7
+ def send_to(user,creator,title,message,label,link=nil)
8
+ notification = Notification.find_or_create(:user_id => user.id,
9
+ :creator_id => creator.id,
10
+ :title => title,
11
+ :message => message,
12
+ :label => label,
13
+ :link => link,
14
+ :creation_date => Date.today)
15
+ if link.nil?
16
+ notification.link = "/notifications/#{notification.id}"
17
+ notification.save
18
+ end
19
+ notification
20
+ end
21
+
22
+ def send_to_subscriptors(creator,title,message,label,link=nil)
23
+ Subscription.where(:label => label).all.each do |subscription|
24
+ notification = send_to(subscription.user,creator,title,message,label,link)
25
+ end
26
+ end
27
+
28
+ def send_error(creator,title,message)
29
+ Subscription.where(:label => 'error').all.each do |subscription|
30
+ creator = subscription.user if creator.nil?
31
+ notification = Notification.find(:user_id => subscription.user_id,
32
+ :creator_id => creator.id,
33
+ :title => title,
34
+ :message => message,
35
+ :label => 'error',
36
+ :read_date => nil)
37
+ if notification.nil?
38
+ notification = send_to(subscription.user,creator,title,message,'error')
39
+ end
40
+ end
41
+
42
+ end
43
+
44
+ end
@@ -3,20 +3,27 @@ module Sinatra
3
3
  module ErrorHandler
4
4
  extend Hexacta
5
5
 
6
+ def enable_errors
7
+ p "Enabling errors..."
8
+ ErrorHandler.setup_dir("/app/views/#{Hexacta::GEM_FILE_DIR}/errors")
9
+
10
+ error_template(404)
11
+ error_template(403)
12
+ error_template(500)
13
+ end
14
+
6
15
  def error_template(code)
7
- ErrorHandler.symlink("/lib/sinatra/views/errors/#{code}.slim","/app/views/#{Hexacta::GEM_FILE_DIR}/errors/#{code}.slim")
16
+ ErrorHandler.copy_file("/lib/sinatra/views/errors/#{code}.slim","/app/views/#{Hexacta::GEM_FILE_DIR}/errors/#{code}.slim")
8
17
  error code do
9
18
  if code == 500
10
19
  title = env['sinatra.error'].message.split(':')[0].gsub('#<','');
11
20
  message = (["in #{request.url}"] + env['sinatra.error'].backtrace).join(',');
12
- notify_error(authenticated(User),title,message)
21
+ NotificationSender.instance.send_error(authenticated(User),title,message)
13
22
  end
14
23
  slim "#{Hexacta::GEM_FILE_DIR}/errors/#{code}".to_sym, locals: { :params => params }
15
24
  end
16
25
  end
17
26
 
18
- p "Setting up errors directory..."
19
- setup_dir("/app/views/#{Hexacta::GEM_FILE_DIR}/errors")
20
27
  end
21
28
 
22
29
  register ErrorHandler
@@ -1,3 +1,5 @@
1
1
  # encoding: utf-8
2
2
  require_relative 'errors'
3
- require_relative 'notifications'
3
+ require_relative 'notifications'
4
+ require_relative 'params'
5
+ require_relative 'reports'
@@ -3,71 +3,60 @@ module Sinatra
3
3
  module NotificationHandler
4
4
  extend Hexacta
5
5
 
6
- def new_notification
6
+ def enable_notifications
7
+ p "Enabling notifications..."
8
+ NotificationHandler.setup_dir("/app/views/#{Hexacta::GEM_FILE_DIR}/notifications")
9
+ NotificationHandler.copy_file("/lib/sinatra/views/notifications.slim","/app/views/#{Hexacta::GEM_FILE_DIR}/notifications.slim")
10
+ NotificationHandler.copy_all_files("/lib/sinatra/views/notifications","/app/views/#{Hexacta::GEM_FILE_DIR}/notifications")
11
+
7
12
  post '/notification' do
8
- if params["user_ids"].blank?
9
- notify(authenticated(User),params["title"],params["message"],params["label"])
13
+ if params[:user_ids].blank?
14
+ NotificationSender.instance.send_to_subscriptors(authenticated(User),params[:title],params[:message],params[:label])
10
15
  else
11
- for id in params["user_ids"]
12
- notify_to(User.find(:id => id),authenticated(User),params["title"],params["message"],params["label"])
16
+ for id in params[:user_ids]
17
+ NotificationSender.instance.send_to(User.find(:id => id),authenticated(User),params[:title],params[:message],params[:label])
13
18
  end
14
19
  end
15
20
  redirect back
16
21
  end
17
- end
18
22
 
19
- def edit_notification
20
23
  post '/notifications/:id' do |id|
21
24
  Notification.where(:user_id => authenticated(User).id, :id => id).update(:read_date => Date.today)
22
25
  200
23
26
  end
24
- end
25
27
 
26
- def read_notifications
27
28
  post '/notifications' do
28
- Notification.where(:user_id => authenticated(User).id, :id => params["ids"]).update(:read_date => Date.today)
29
+ Notification.where(:user_id => authenticated(User).id, :id => params[:ids]).update(:read_date => Date.today)
29
30
  redirect back
30
31
  end
31
- end
32
32
 
33
- def get_notification
34
33
  get '/notifications/:id' do |id|
35
34
  notification = Notification.find(:id => id)
36
35
  redirect "/notifications" if notification.nil?
37
36
  slim "#{Hexacta::GEM_FILE_DIR}/notifications/view".to_sym, locals: { :notification => notification }
38
37
  end
39
- end
40
38
 
41
- def delete_notification
42
39
  delete '/notifications/:id' do |id|
43
40
  Notification.find(:user_id => authenticated(User).id, :id => id).destroy.to_hash.to_json.to_s
44
41
  end
45
- end
46
42
 
47
- def delete_notifications
48
43
  delete '/notifications' do
49
- Notification.where(:user_id => authenticated(User).id, :id => params["ids"]).destroy.to_s
44
+ Notification.where(:user_id => authenticated(User).id, :id => params[:ids]).destroy.to_s
50
45
  end
51
- end
52
46
 
53
- def get_notifications
54
47
  get '/notifications' do
55
48
  filters = params.select { |attribute| Notification.columns.include?(attribute.to_sym) }
56
- params["limit"] = "20" if params["limit"].to_i < 20
57
- params["limit"] = "100" if params["limit"].to_i > 100
58
- limit = params["limit"].to_i
59
- offset = params["offset"].to_i
49
+ params[:limit] = "20" if params[:limit].to_i < 20
50
+ params[:limit] = "100" if params[:limit].to_i > 100
51
+ limit = params[:limit].to_i
52
+ offset = params[:offset].to_i
60
53
 
61
- query = Notification.where(:user_id => authenticated(User).id).where(filters.to_filter).order(:read_date,Sequel.desc(:id))
54
+ query = Notification.where(:user_id => authenticated(User).id).where(filters.to_filter).order(Sequel.desc(:id))
62
55
 
63
56
  slim "#{Hexacta::GEM_FILE_DIR}/notifications".to_sym, locals: { :notifications => query.limit(limit).offset(offset*limit).all, :total => query.count, :filters => params, :query => query }
64
57
  end
65
58
  end
66
59
 
67
- p "Setting up notifications directory..."
68
- setup_dir("/app/views/#{Hexacta::GEM_FILE_DIR}/notifications")
69
- symlink("/lib/sinatra/views/notifications.slim","/app/views/#{Hexacta::GEM_FILE_DIR}/notifications.slim")
70
- symlink_all("/lib/sinatra/views/notifications","/app/views/#{Hexacta::GEM_FILE_DIR}/notifications")
71
60
  end
72
61
 
73
62
  register NotificationHandler