sinatra-hexacta 0.0.2 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
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