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.
- checksums.yaml +4 -4
- data/lib/sinatra/extensions/antiquity.rb +34 -0
- data/lib/sinatra/extensions/date.rb +49 -0
- data/lib/sinatra/extensions/init.rb +4 -0
- data/lib/sinatra/extensions/notification.rb +41 -0
- data/lib/sinatra/handlers/errors.rb +10 -3
- data/lib/sinatra/handlers/init.rb +3 -1
- data/lib/sinatra/handlers/notifications.rb +17 -28
- data/lib/sinatra/handlers/params.rb +26 -0
- data/lib/sinatra/handlers/reports.rb +28 -1
- data/lib/sinatra/helpers/alerts.rb +27 -0
- data/lib/sinatra/helpers/cas.rb +92 -0
- data/lib/sinatra/helpers/charts.rb +20 -4
- data/lib/sinatra/helpers/init.rb +4 -0
- data/lib/sinatra/helpers/inputs.rb +2 -2
- data/lib/sinatra/helpers/libraries.rb +2 -2
- data/lib/sinatra/helpers/mailer.rb +74 -0
- data/lib/sinatra/helpers/reports.rb +27 -0
- data/lib/sinatra/helpers/schedule.rb +68 -0
- data/lib/sinatra/helpers/subscriptions.rb +1 -1
- data/lib/sinatra/hexacta.rb +13 -5
- data/lib/sinatra/public/css/app.min.1.css +130 -12
- data/lib/sinatra/public/js/app.js +49 -42
- data/lib/sinatra/public/vendors/chartist/chartist-plugin-legend.js +237 -0
- data/lib/sinatra/views/alerts/empty.slim +7 -0
- data/lib/sinatra/views/alerts/error.slim +7 -0
- data/lib/sinatra/views/alerts/info.slim +7 -0
- data/lib/sinatra/views/alerts/warning.slim +7 -0
- data/lib/sinatra/views/charts/bar.slim +56 -0
- data/lib/sinatra/views/charts/gauge.slim +30 -0
- data/lib/sinatra/views/charts/{simple_line.slim → line.slim} +7 -8
- data/lib/sinatra/views/charts/pie.slim +34 -0
- data/lib/sinatra/views/charts/stacked_bar.slim +36 -0
- data/lib/sinatra/views/inputs/multiple_select.slim +4 -0
- data/lib/sinatra/views/inputs/select.slim +3 -0
- data/lib/sinatra/views/libraries/include_js_after.slim +0 -24
- data/lib/sinatra/views/libraries/include_js_before.slim +1 -0
- data/lib/sinatra/views/notifications.slim +37 -31
- data/lib/sinatra/views/notifications/form.slim +4 -4
- data/lib/sinatra/views/notifications/new.slim +4 -4
- data/lib/sinatra/views/notifications/widget.slim +9 -5
- data/lib/sinatra/views/reports/pick_date.slim +14 -0
- data/lib/sinatra/views/reports/pick_dates.slim +16 -0
- data/lib/sinatra/views/reports/pick_month.slim +14 -0
- data/lib/sinatra/views/reports/pick_year.slim +14 -0
- metadata +26 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 57e2b70893a33833d923a230a2efc0112358d81961b1897b6894bde81c49672a
|
4
|
+
data.tar.gz: 9eb2b5cce23ac52c1bb105df09c4543b7291ad047f0150762ae13303a2bf1a97
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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,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
|
-
|
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
|
@@ -3,71 +3,60 @@ module Sinatra
|
|
3
3
|
module NotificationHandler
|
4
4
|
extend Hexacta
|
5
5
|
|
6
|
-
def
|
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[
|
9
|
-
|
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[
|
12
|
-
|
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[
|
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[
|
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[
|
57
|
-
params[
|
58
|
-
limit = params[
|
59
|
-
offset = params[
|
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(
|
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
|
-
#
|
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
|