sinatra-hexacta 0.0.2 → 0.1.0

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 (46) 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/init.rb +4 -0
  5. data/lib/sinatra/extensions/notification.rb +41 -0
  6. data/lib/sinatra/handlers/errors.rb +10 -3
  7. data/lib/sinatra/handlers/init.rb +3 -1
  8. data/lib/sinatra/handlers/notifications.rb +17 -28
  9. data/lib/sinatra/handlers/params.rb +26 -0
  10. data/lib/sinatra/handlers/reports.rb +28 -1
  11. data/lib/sinatra/helpers/alerts.rb +27 -0
  12. data/lib/sinatra/helpers/cas.rb +92 -0
  13. data/lib/sinatra/helpers/charts.rb +20 -4
  14. data/lib/sinatra/helpers/init.rb +4 -0
  15. data/lib/sinatra/helpers/inputs.rb +2 -2
  16. data/lib/sinatra/helpers/libraries.rb +2 -2
  17. data/lib/sinatra/helpers/mailer.rb +74 -0
  18. data/lib/sinatra/helpers/reports.rb +27 -0
  19. data/lib/sinatra/helpers/schedule.rb +68 -0
  20. data/lib/sinatra/helpers/subscriptions.rb +1 -1
  21. data/lib/sinatra/hexacta.rb +13 -5
  22. data/lib/sinatra/public/css/app.min.1.css +130 -12
  23. data/lib/sinatra/public/js/app.js +49 -42
  24. data/lib/sinatra/public/vendors/chartist/chartist-plugin-legend.js +237 -0
  25. data/lib/sinatra/views/alerts/empty.slim +7 -0
  26. data/lib/sinatra/views/alerts/error.slim +7 -0
  27. data/lib/sinatra/views/alerts/info.slim +7 -0
  28. data/lib/sinatra/views/alerts/warning.slim +7 -0
  29. data/lib/sinatra/views/charts/bar.slim +56 -0
  30. data/lib/sinatra/views/charts/gauge.slim +30 -0
  31. data/lib/sinatra/views/charts/{simple_line.slim → line.slim} +7 -8
  32. data/lib/sinatra/views/charts/pie.slim +34 -0
  33. data/lib/sinatra/views/charts/stacked_bar.slim +36 -0
  34. data/lib/sinatra/views/inputs/multiple_select.slim +4 -0
  35. data/lib/sinatra/views/inputs/select.slim +3 -0
  36. data/lib/sinatra/views/libraries/include_js_after.slim +0 -24
  37. data/lib/sinatra/views/libraries/include_js_before.slim +1 -0
  38. data/lib/sinatra/views/notifications.slim +37 -31
  39. data/lib/sinatra/views/notifications/form.slim +4 -4
  40. data/lib/sinatra/views/notifications/new.slim +4 -4
  41. data/lib/sinatra/views/notifications/widget.slim +9 -5
  42. data/lib/sinatra/views/reports/pick_date.slim +14 -0
  43. data/lib/sinatra/views/reports/pick_dates.slim +16 -0
  44. data/lib/sinatra/views/reports/pick_month.slim +14 -0
  45. data/lib/sinatra/views/reports/pick_year.slim +14 -0
  46. metadata +26 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: acbebd0dade426417f396054c4d2e277402fc59cbad3b7e27c248a193e59859d
4
- data.tar.gz: beaf9fcfffa445c4b7f39e49be20132bf8103199dc972b4b1235d89280e6c4b6
3
+ metadata.gz: 57e2b70893a33833d923a230a2efc0112358d81961b1897b6894bde81c49672a
4
+ data.tar.gz: 9eb2b5cce23ac52c1bb105df09c4543b7291ad047f0150762ae13303a2bf1a97
5
5
  SHA512:
6
- metadata.gz: 9b374e1e2f8106c23168de0312034f4dab4669d11582f51e935ed436eab1b7f1965fd1963f3fc64a39de16f199c19ad3948655de3f04fb1b77d8c64a17aac186
7
- data.tar.gz: 268e659e4ae71122214d640c33a4c5e3a2cc6a5f1338aa6659633a18673671278ec1752d19ecd9febc1988ba632c7d836d751915544811c11fec8e4f64e72bfa
6
+ metadata.gz: 4e9c5a79fe2a7b4e33c3b37ec4b732f7306ae7f5402528dedce8e7f26f80e6b5e7ce13b3d5f86cbd6899fded25ee380c027c12570189475882e7567624783d76
7
+ data.tar.gz: 8fd1274ede9d5e51882f02f7fdbda786d8a8f1f05d1346a422ae68435ca3f818d85e7586d40b4a2443e95fc6ee2a6bd998c06ce704463ad5a37a86a27c309f54
@@ -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,4 @@
1
+ # encoding: utf-8
2
+ require_relative 'date'
3
+ require_relative 'antiquity'
4
+ require_relative 'notification'
@@ -0,0 +1,41 @@
1
+ # encoding: utf-8
2
+ class NotificationSender
3
+
4
+ def self.send_to(user,creator,title,message,label,link=nil)
5
+ notification = Notification.find_or_create(:user_id => user.id,
6
+ :creator_id => creator.id,
7
+ :title => title,
8
+ :message => message,
9
+ :label => label,
10
+ :link => link,
11
+ :creation_date => Date.today)
12
+ if link.nil?
13
+ notification.link = "/notifications/#{notification.id}"
14
+ notification.save
15
+ end
16
+ notification
17
+ end
18
+
19
+ def self.send_to_subscriptors(creator,title,message,label,link=nil)
20
+ Subscription.where(:label => label).all.each do |subscription|
21
+ notification = NotificationSender.send_to(subscription.user,creator,title,message,label,link)
22
+ end
23
+ end
24
+
25
+ def self.send_error(creator,title,message)
26
+ Subscription.where(:label => 'error').all.each do |subscription|
27
+ creator = subscription.user if creator.nil?
28
+ notification = Notification.find(:user_id => subscription.user_id,
29
+ :creator_id => creator.id,
30
+ :title => title,
31
+ :message => message,
32
+ :label => 'error',
33
+ :read_date => nil)
34
+ if notification.nil?
35
+ notification = NotificationSender.send_to(subscription.user,creator,title,message,'error')
36
+ end
37
+ end
38
+
39
+ end
40
+
41
+ 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
16
  ErrorHandler.symlink("/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.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.symlink("/lib/sinatra/views/notifications.slim","/app/views/#{Hexacta::GEM_FILE_DIR}/notifications.slim")
10
+ NotificationHandler.symlink_all("/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.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.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
@@ -0,0 +1,26 @@
1
+ # encoding: utf-8
2
+ module Sinatra
3
+ module ParamsHandler
4
+
5
+ def enable_params
6
+ p "Enabling params handler..."
7
+
8
+ before "*" do
9
+ unless params.nil?
10
+ tmp = {}
11
+ for key in params.keys
12
+ value = params[key]
13
+ value = value.join(",").split(",") if value.respond_to? :join
14
+ tmp[key.to_sym] = value
15
+ end
16
+ @params.clear
17
+ @params = tmp
18
+ end
19
+ end
20
+
21
+ end
22
+
23
+ end
24
+
25
+ register ParamsHandler
26
+ end
@@ -1 +1,28 @@
1
- #TOBEDONE
1
+ # encoding: utf-8
2
+ module Sinatra
3
+ module ReportHandler
4
+ extend Hexacta
5
+
6
+ def enable_reports
7
+ p "Enabling reports..."
8
+ before '/reports/*' do
9
+ error(403) if authenticated(User).permissions.empty?
10
+ end
11
+
12
+ get '/reports' do
13
+ slim :reports
14
+ end
15
+
16
+ get '/reports/:report_name' do |report_name|
17
+ date = Date.parse(params["date"]) unless params["date"].nil?
18
+ date ||= Date.today
19
+ headers "Content-Disposition" => "attachment;filename=#{report_name}.#{date}.xls",
20
+ "Content-Type" => "application/octet-stream"
21
+ slim "reports/#{report_name}".to_sym, locals: { :date => date }, :layout => false
22
+ end
23
+ end
24
+
25
+ end
26
+
27
+ register ReportHandler
28
+ end
@@ -0,0 +1,27 @@
1
+ # encoding: utf-8
2
+ module Sinatra
3
+ module AlertHelper
4
+ extend Hexacta
5
+
6
+ def info_alert(option_hash)
7
+ slim "#{Hexacta::GEM_FILE_DIR}/alerts/info".to_sym, locals: option_hash
8
+ end
9
+
10
+ def empty_alert(option_hash)
11
+ slim "#{Hexacta::GEM_FILE_DIR}/alerts/empty".to_sym, locals: option_hash
12
+ end
13
+
14
+ def warning_alert(option_hash)
15
+ slim "#{Hexacta::GEM_FILE_DIR}/alerts/warning".to_sym, locals: option_hash
16
+ end
17
+
18
+ def error_alert(option_hash)
19
+ slim "#{Hexacta::GEM_FILE_DIR}/alerts/error".to_sym, locals: option_hash
20
+ end
21
+
22
+ setup_dir("/app/views/#{Hexacta::GEM_FILE_DIR}/alerts")
23
+ symlink_all("/lib/sinatra/views/alerts","/app/views/#{Hexacta::GEM_FILE_DIR}/alerts")
24
+ end
25
+
26
+ helpers AlertHelper
27
+ end
@@ -0,0 +1,92 @@
1
+ require 'active_support/all' #bug in rubycas client requires this
2
+ require 'rubycas-client'
3
+
4
+ module Sinatra
5
+ module CasHelper
6
+
7
+ CAS_CLIENT = CASClient::Client.new(:cas_base_url => ENV['CAS_BASE_URL'], :log => Logger.new(STDOUT), :ticket_store_config => {:storage_dir => ENV['TICKET_STORE_DIR']})
8
+
9
+ def need_authentication(request, session)
10
+ if session[:cas_ticket]
11
+ if request[:ticket] && session[:cas_ticket] != request[:ticket]
12
+ true
13
+ else
14
+ false
15
+ end
16
+ else
17
+ true
18
+ end
19
+ end
20
+
21
+ def process_cas_login(request, session)
22
+ if request[:ticket] && request[:ticket] != session[:ticket]
23
+
24
+ service_url = read_service_url(request)
25
+ service_ticket = read_ticket(request[:ticket], service_url)
26
+
27
+ CAS_CLIENT.validate_service_ticket(service_ticket)
28
+
29
+ if service_ticket.success
30
+ session[:cas_ticket] = service_ticket.ticket
31
+ session[:cas_user] = service_ticket.user
32
+ else
33
+ redirect request.path_info
34
+ #raise "Service Ticket validation failed! #{st.failure_code} - #{st.failure_message}"
35
+ end
36
+ end
37
+
38
+ end
39
+
40
+ def logged_in?(request, session)
41
+ session[:cas_ticket] && !session[:cas_ticket].empty?
42
+ end
43
+
44
+ def require_authorization(request, session)
45
+ if !logged_in?(request, session)
46
+ service_url = read_service_url(request)
47
+ url = CAS_CLIENT.add_service_to_login_url(service_url)
48
+ redirect url
49
+ end
50
+ end
51
+
52
+ def authenticated(model)
53
+ raise 500 if session[:cas_user].nil? || session[:cas_user].empty?
54
+ model.find(:hxt_id => "#{session[:cas_user]}")
55
+ end
56
+
57
+ private
58
+ def read_ticket(ticket_str, service_url)
59
+ return nil unless ticket_str and !ticket_str.empty?
60
+
61
+ if ticket_str =~ /^PT-/
62
+ CASClient::ProxyTicket.new(ticket_str, service_url)
63
+ else
64
+ CASClient::ServiceTicket.new(ticket_str, service_url)
65
+ end
66
+ end
67
+
68
+ def read_service_url(request)
69
+ service_url = url(request.path_info)
70
+ if request.GET
71
+ params = request.GET.dup
72
+ params.delete(:ticket)
73
+ if params
74
+ [service_url, Rack::Utils.build_nested_query(params)].join('?')
75
+ end
76
+ end
77
+ return service_url
78
+ end
79
+
80
+ def logout_cas(request, session)
81
+ if logged_in?(request, session)
82
+ url = CAS_CLIENT.logout_url()
83
+ session.clear
84
+ str = request.referer
85
+ comeback = "=" + (str.include?("?")? str.slice(0..(str.index('?')-1)) : str) #Hack mal!
86
+ redirect url + (url.include?("?service")? "" : "?service") + comeback
87
+ end
88
+ end
89
+ end
90
+
91
+ helpers CasHelper
92
+ end