sinatra-hexacta 0.0.2 → 0.3.2
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/generalmail.rb +26 -0
- data/lib/sinatra/extensions/init.rb +8 -0
- data/lib/sinatra/extensions/mail.rb +35 -0
- data/lib/sinatra/extensions/mailbuilder.rb +38 -0
- data/lib/sinatra/extensions/mailsender.rb +88 -0
- data/lib/sinatra/extensions/notification.rb +44 -0
- data/lib/sinatra/handlers/errors.rb +11 -4
- 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 +21 -5
- data/lib/sinatra/helpers/init.rb +4 -0
- data/lib/sinatra/helpers/inputs.rb +3 -3
- data/lib/sinatra/helpers/libraries.rb +3 -3
- 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 +15 -9
- data/lib/sinatra/public/css/app.min.1.css +132 -6
- data/lib/sinatra/public/js/app.js +49 -42
- data/lib/sinatra/public/vendors/chartist/chartist-plugin-legend.js +237 -0
- data/lib/sinatra/public/vendors/typeahead.js/typeahead.bundle.min.js +1 -2
- 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 +30 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a6fb503a8966bb24d1526acd9e44a6b8f798967193f7b5c465c61b86c4eb4d76
|
4
|
+
data.tar.gz: 1896cd47708d90de659d4e7d5253d3588331fd2372234c7c1bc152783bbd75ff
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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,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.
|
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
|
-
|
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
|
@@ -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.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[
|
9
|
-
|
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[
|
12
|
-
|
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[
|
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
|