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.
- 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
|