sinatra-hexacta 0.0.2 → 0.1.0

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