ditty 0.4.0 → 0.4.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +5 -3
- data/ditty.gemspec +3 -2
- data/lib/ditty/controllers/application.rb +31 -10
- data/lib/ditty/controllers/component.rb +7 -2
- data/lib/ditty/controllers/main.rb +1 -1
- data/lib/ditty/controllers/users.rb +12 -6
- data/lib/ditty/helpers/authentication.rb +7 -20
- data/lib/ditty/helpers/component.rb +0 -4
- data/lib/ditty/helpers/pundit.rb +2 -1
- data/lib/ditty/helpers/response.rb +11 -7
- data/lib/ditty/helpers/views.rb +41 -4
- data/lib/ditty/helpers/wisper.rb +1 -1
- data/lib/ditty/models/identity.rb +1 -0
- data/lib/ditty/services/logger.rb +8 -1
- data/lib/ditty/version.rb +1 -1
- data/views/embedded.haml +42 -0
- data/views/identity/login.haml +1 -3
- data/views/identity/register.haml +11 -4
- data/views/layout.haml +8 -2
- data/views/partials/actions.haml +12 -0
- data/views/partials/delete_form.haml +2 -4
- data/views/partials/footer.haml +1 -1
- data/views/partials/form_tag.haml +6 -0
- data/views/partials/search.haml +1 -1
- data/views/roles/edit.haml +1 -2
- data/views/roles/new.haml +1 -1
- data/views/users/edit.haml +1 -2
- data/views/users/identity.haml +7 -0
- data/views/users/index.haml +2 -0
- data/views/users/new.haml +2 -2
- data/views/users/user.haml +1 -1
- metadata +24 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a6c4bdcc080384afbc372c0811697ff421ab6ed3d552ec912cd0a3c0f7ed82da
|
4
|
+
data.tar.gz: 1f09c726e251d380cd0b55d8c552b064dae7c6811f3a24b0e16a38e55a0c6408
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d0f86ea3db1913ad4c603a6ba96c535705589fd7fbd28ea3fbe3a262d956838fdc2c27e1950e6aae2f6e1bce20e3ffd0dc32e0bde74ae371869c3ac1922a5b03
|
7
|
+
data.tar.gz: ad5ea5fe818c8f8d20177082f11ecfeb176b4969b21cb5155410a4f8dbbc581dde05d3cb4c468898a86dd16a8aede7f487f3fd36b60e187df094280f805e1c8e
|
data/.travis.yml
CHANGED
@@ -1,13 +1,15 @@
|
|
1
1
|
sudo: false
|
2
2
|
language: ruby
|
3
3
|
rvm:
|
4
|
-
- 2.
|
5
|
-
- 2.
|
6
|
-
- 2.
|
4
|
+
- 2.5.1
|
5
|
+
- 2.4.0
|
6
|
+
- 2.3.3
|
7
|
+
- 2.2.6
|
7
8
|
gemfile: Gemfile.ci
|
8
9
|
env:
|
9
10
|
global:
|
10
11
|
- CC_TEST_REPORTER_ID=289860573c6284a8e277de86848caba84d840be49e35f3601bcd672ab40d1e35
|
12
|
+
- DATABASE_CLEANER_ALLOW_REMOTE_DATABASE_URL=true
|
11
13
|
matrix:
|
12
14
|
- DATABASE_URL="sqlite::memory:" RACK_ENV=test
|
13
15
|
before_install:
|
data/ditty.gemspec
CHANGED
@@ -32,13 +32,14 @@ Gem::Specification.new do |spec|
|
|
32
32
|
spec.add_dependency 'bcrypt', '~> 3.1'
|
33
33
|
spec.add_dependency 'haml', '~> 5.0'
|
34
34
|
spec.add_dependency 'logger', '~> 1.0'
|
35
|
+
spec.add_dependency 'oga', '>= 2.14'
|
35
36
|
spec.add_dependency 'omniauth', '~> 1.0'
|
36
37
|
spec.add_dependency 'omniauth-identity', '~> 1.0'
|
37
38
|
spec.add_dependency 'pundit', '~> 1.0'
|
38
39
|
spec.add_dependency 'rack-contrib', '~> 1.0'
|
39
40
|
spec.add_dependency 'rake', '~> 12.0'
|
40
|
-
spec.add_dependency 'sequel', '
|
41
|
-
spec.add_dependency 'sinatra', '
|
41
|
+
spec.add_dependency 'sequel', '>= 4.0'
|
42
|
+
spec.add_dependency 'sinatra', '>= 2.0'
|
42
43
|
spec.add_dependency 'sinatra-contrib', '~> 2.0'
|
43
44
|
spec.add_dependency 'sinatra-flash', '~> 0.3'
|
44
45
|
spec.add_dependency 'tilt', '>= 2'
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'wisper'
|
4
|
+
require 'oga'
|
4
5
|
require 'sinatra/base'
|
5
6
|
require 'sinatra/flash'
|
6
7
|
require 'sinatra/respond_with'
|
@@ -30,10 +31,16 @@ module Ditty
|
|
30
31
|
use Rack::PostBodyContentTypeParser
|
31
32
|
use Rack::MethodOverride
|
32
33
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
34
|
+
helpers do
|
35
|
+
def base_path
|
36
|
+
settings.base_path || "#{settings.map_path}/#{dasherize(view_location)}"
|
37
|
+
end
|
38
|
+
|
39
|
+
def view_location
|
40
|
+
return settings.view_location if settings.view_location
|
41
|
+
return underscore(pluralize(demodulize(settings.model_class))) if settings.model_class
|
42
|
+
underscore(demodulize(self.class))
|
43
|
+
end
|
37
44
|
end
|
38
45
|
|
39
46
|
configure :production do
|
@@ -54,7 +61,7 @@ module Ditty
|
|
54
61
|
respond_to do |format|
|
55
62
|
status 404
|
56
63
|
format.html do
|
57
|
-
haml :'404', locals: { title: '4 oh 4' }
|
64
|
+
haml :'404', locals: { title: '4 oh 4' }, layout: layout
|
58
65
|
end
|
59
66
|
format.json do
|
60
67
|
json code: 404, errors: ['Not Found']
|
@@ -67,7 +74,7 @@ module Ditty
|
|
67
74
|
status 401
|
68
75
|
format.html do
|
69
76
|
flash[:warning] = 'Please log in first.'
|
70
|
-
redirect "#{settings.map_path}/auth/identity"
|
77
|
+
redirect with_layout("#{settings.map_path}/auth/identity")
|
71
78
|
end
|
72
79
|
format.json do
|
73
80
|
json code: 401, errors: ['Not Authenticated']
|
@@ -82,10 +89,10 @@ module Ditty
|
|
82
89
|
status 400
|
83
90
|
format.html do
|
84
91
|
action = entity.id ? :edit : :new
|
85
|
-
haml :"#{view_location}/#{action}", locals: { entity: entity, title: heading(action) }
|
92
|
+
haml :"#{view_location}/#{action}", locals: { entity: entity, title: heading(action) }, layout: layout
|
86
93
|
end
|
87
94
|
format.json do
|
88
|
-
json code: 400, errors: errors
|
95
|
+
json code: 400, errors: errors, full_errors: errors.full_messages
|
89
96
|
end
|
90
97
|
end
|
91
98
|
end
|
@@ -97,7 +104,7 @@ module Ditty
|
|
97
104
|
respond_to do |format|
|
98
105
|
status 400
|
99
106
|
format.html do
|
100
|
-
haml :error, locals: { title: 'Something went wrong', error: error }
|
107
|
+
haml :error, locals: { title: 'Something went wrong', error: error }, layout: layout
|
101
108
|
end
|
102
109
|
format.json do
|
103
110
|
json code: 400, errors: ['Invalid Relation Specified']
|
@@ -112,7 +119,7 @@ module Ditty
|
|
112
119
|
respond_to do |format|
|
113
120
|
status 500
|
114
121
|
format.html do
|
115
|
-
haml :error, locals: { title: 'Something went wrong', error: error }
|
122
|
+
haml :error, locals: { title: 'Something went wrong', error: error }, layout: layout
|
116
123
|
end
|
117
124
|
format.json do
|
118
125
|
json code: 500, errors: ['Something went wrong']
|
@@ -124,9 +131,23 @@ module Ditty
|
|
124
131
|
::Ditty::Services::Logger.instance.debug "Running with #{self.class}"
|
125
132
|
if request.path =~ /.*\.json\Z/
|
126
133
|
content_type :json
|
134
|
+
request.path_info = request.path_info.gsub(/.json$/,'')
|
127
135
|
end
|
128
136
|
# Ensure the accept header is set. People forget to include it in API requests
|
129
137
|
content_type(:json) if request.accept.count.eql?(1) && request.accept.first.to_s.eql?('*/*')
|
130
138
|
end
|
139
|
+
|
140
|
+
after do
|
141
|
+
return if params['layout'].nil?
|
142
|
+
response.body = response.body.map do |resp|
|
143
|
+
document = Oga.parse_html(resp)
|
144
|
+
document.css('a').each do |elm|
|
145
|
+
unless (href = elm.get('href')).nil?
|
146
|
+
elm.set 'href', with_layout(href)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
document.to_xml
|
150
|
+
end
|
151
|
+
end
|
131
152
|
end
|
132
153
|
end
|
@@ -33,7 +33,10 @@ module Ditty
|
|
33
33
|
authorize settings.model_class, :create
|
34
34
|
|
35
35
|
entity = settings.model_class.new(permitted_attributes(settings.model_class, :create))
|
36
|
-
|
36
|
+
session[:redirect_to] = request.fullpath
|
37
|
+
haml :"#{view_location}/new",
|
38
|
+
locals: { entity: entity, title: heading(:new) },
|
39
|
+
layout: layout
|
37
40
|
end
|
38
41
|
|
39
42
|
# Create
|
@@ -63,7 +66,9 @@ module Ditty
|
|
63
66
|
halt 404 unless entity
|
64
67
|
authorize entity, :update
|
65
68
|
|
66
|
-
haml :"#{view_location}/edit",
|
69
|
+
haml :"#{view_location}/edit",
|
70
|
+
locals: { entity: entity, title: heading(:edit) },
|
71
|
+
layout: layout
|
67
72
|
end
|
68
73
|
|
69
74
|
# Update
|
@@ -40,7 +40,7 @@ module Ditty
|
|
40
40
|
self.current_user = user
|
41
41
|
log_action(:identity_login, user: user)
|
42
42
|
flash[:success] = 'Logged In'
|
43
|
-
redirect "#{settings.map_path}/"
|
43
|
+
redirect env['omniauth.origin'] || "#{settings.map_path}/"
|
44
44
|
else
|
45
45
|
# Failed Login
|
46
46
|
broadcast(:identity_failed_login)
|
@@ -8,6 +8,8 @@ require 'ditty/policies/identity_policy'
|
|
8
8
|
|
9
9
|
module Ditty
|
10
10
|
class Users < Ditty::Component
|
11
|
+
SEARCHABLE = %i[name surname email].freeze
|
12
|
+
|
11
13
|
set model_class: User
|
12
14
|
set track_actions: true
|
13
15
|
|
@@ -20,11 +22,7 @@ module Ditty
|
|
20
22
|
get '/new' do
|
21
23
|
authorize settings.model_class, :create
|
22
24
|
|
23
|
-
locals = {
|
24
|
-
title: heading(:new),
|
25
|
-
entity: User.new,
|
26
|
-
identity: Identity.new
|
27
|
-
}
|
25
|
+
locals = { title: heading(:new), entity: User.new, identity: Identity.new }
|
28
26
|
haml :"#{view_location}/new", locals: locals
|
29
27
|
end
|
30
28
|
|
@@ -43,9 +41,17 @@ module Ditty
|
|
43
41
|
identity = locals[:identity] = Identity.new(identity_params)
|
44
42
|
|
45
43
|
DB.transaction(isolation: :serializable) do
|
46
|
-
|
44
|
+
begin
|
45
|
+
identity.save
|
46
|
+
rescue Sequel::ValidationFailed
|
47
|
+
raise unless request.accept? 'text/html'
|
48
|
+
status 400
|
49
|
+
locals = { title: heading(:new), entity: user, identity: identity }
|
50
|
+
return haml(:"#{view_location}/new", locals: locals)
|
51
|
+
end
|
47
52
|
user.save
|
48
53
|
user.add_identity identity
|
54
|
+
|
49
55
|
if roles
|
50
56
|
roles.each do |role_id|
|
51
57
|
user.add_role(role_id) unless user.roles.map(&:id).include? role_id.to_i
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require 'ditty/models/user'
|
3
4
|
require 'ditty/models/role'
|
4
5
|
require 'ditty/models/identity'
|
@@ -7,10 +8,8 @@ module Ditty
|
|
7
8
|
module Helpers
|
8
9
|
module Authentication
|
9
10
|
def current_user
|
10
|
-
|
11
|
-
|
12
|
-
@users ||= Hash.new { |h, k| h[k] = User[k] }
|
13
|
-
@users[user_id]
|
11
|
+
return anonymous_user if current_user_id.nil?
|
12
|
+
User[current_user_id]
|
14
13
|
end
|
15
14
|
|
16
15
|
def current_user=(user)
|
@@ -37,25 +36,13 @@ module Ditty
|
|
37
36
|
end
|
38
37
|
|
39
38
|
def logout
|
40
|
-
env['rack.session'].delete('user_id')
|
41
|
-
|
42
|
-
|
43
|
-
def check_basic(request)
|
44
|
-
auth = Rack::Auth::Basic::Request.new(request.env)
|
45
|
-
return false unless auth.provided? && auth.basic?
|
46
|
-
|
47
|
-
identity = ::Ditty::Identity.find(username: auth.credentials[0])
|
48
|
-
identity ||= ::Ditty::Identity.find(username: CGI.unescape(auth.credentials[0]))
|
49
|
-
return false unless identity
|
50
|
-
self.current_user = identity.user if identity.authenticate(auth.credentials[1])
|
39
|
+
env['rack.session'].delete('user_id') unless env['rack.session'].nil?
|
40
|
+
env.delete('omniauth.auth')
|
51
41
|
end
|
52
42
|
|
53
43
|
def anonymous_user
|
54
|
-
|
55
|
-
|
56
|
-
role = ::Ditty::Role.where(name: 'anonymous').first
|
57
|
-
::Ditty::User.where(roles: role).first unless role.nil?
|
58
|
-
end
|
44
|
+
role = ::Ditty::Role.where(name: 'anonymous').first
|
45
|
+
::Ditty::User.where(roles: role).first unless role.nil?
|
59
46
|
end
|
60
47
|
end
|
61
48
|
|
@@ -36,10 +36,6 @@ module Ditty
|
|
36
36
|
settings.dehumanized || underscore(heading)
|
37
37
|
end
|
38
38
|
|
39
|
-
def base_path
|
40
|
-
settings.base_path || "#{settings.map_path}/#{dasherize(view_location)}"
|
41
|
-
end
|
42
|
-
|
43
39
|
def filters
|
44
40
|
self.class.const_defined?('FILTERS') ? self.class::FILTERS : []
|
45
41
|
end
|
data/lib/ditty/helpers/pundit.rb
CHANGED
@@ -21,8 +21,9 @@ module Ditty
|
|
21
21
|
'permitted_attributes'
|
22
22
|
end
|
23
23
|
|
24
|
+
policy_fields = policy.public_send(method_name)
|
24
25
|
request.params.fetch(param_key, {}).select do |key, _value|
|
25
|
-
|
26
|
+
policy_fields.include? key.to_sym
|
26
27
|
end
|
27
28
|
end
|
28
29
|
|
@@ -9,15 +9,17 @@ module Ditty
|
|
9
9
|
actions = {}
|
10
10
|
actions["#{base_path}/new"] = "New #{heading}" if policy(settings.model_class).create?
|
11
11
|
haml :"#{view_location}/index",
|
12
|
-
locals: { list: result, title: heading(:list), actions: actions }
|
12
|
+
locals: { list: result, title: heading(:list), actions: actions },
|
13
|
+
layout: layout
|
13
14
|
end
|
14
15
|
format.json do
|
15
16
|
# TODO: Add links defined by actions (New #{heading})
|
17
|
+
total = result.respond_to?(:pagination_record_count) ? result.pagination_record_count : result.count
|
16
18
|
json(
|
17
19
|
'items' => result.all.map(&:for_json),
|
18
20
|
'page' => (params['page'] || 1).to_i,
|
19
21
|
'count' => result.count,
|
20
|
-
'total' =>
|
22
|
+
'total' => total
|
21
23
|
)
|
22
24
|
end
|
23
25
|
end
|
@@ -27,7 +29,7 @@ module Ditty
|
|
27
29
|
respond_to do |format|
|
28
30
|
format.html do
|
29
31
|
flash[:success] = "#{heading} Created"
|
30
|
-
redirect "#{base_path}/#{entity.id}"
|
32
|
+
redirect with_layout("#{base_path}/#{entity.id}")
|
31
33
|
end
|
32
34
|
format.json do
|
33
35
|
content_type :json
|
@@ -42,7 +44,9 @@ module Ditty
|
|
42
44
|
actions = {}
|
43
45
|
actions["#{base_path}/#{entity.id}/edit"] = "Edit #{heading}" if policy(entity).update?
|
44
46
|
title = heading(:read) + (entity.respond_to?(:name) ? ": #{entity.name}" : '')
|
45
|
-
haml :"#{view_location}/display",
|
47
|
+
haml :"#{view_location}/display",
|
48
|
+
locals: { entity: entity, title: title, actions: actions },
|
49
|
+
layout: layout
|
46
50
|
end
|
47
51
|
format.json do
|
48
52
|
# TODO: Add links defined by actions (Edit #{heading})
|
@@ -56,7 +60,7 @@ module Ditty
|
|
56
60
|
format.html do
|
57
61
|
# TODO: Ability to customize the return path and message?
|
58
62
|
flash[:success] = "#{heading} Updated"
|
59
|
-
redirect "#{base_path}/#{entity.id}"
|
63
|
+
redirect with_layout("#{base_path}/#{entity.id}")
|
60
64
|
end
|
61
65
|
format.json do
|
62
66
|
headers 'Location' => "#{base_path}/#{entity.id}"
|
@@ -69,11 +73,11 @@ module Ditty
|
|
69
73
|
respond_to do |format|
|
70
74
|
format.html do
|
71
75
|
flash[:success] = "#{heading} Deleted"
|
72
|
-
redirect base_path.to_s
|
76
|
+
redirect with_layout(base_path.to_s)
|
73
77
|
end
|
74
78
|
format.json do
|
75
79
|
content_type :json
|
76
|
-
headers 'Location' =>
|
80
|
+
headers 'Location' => base_path.to_s
|
77
81
|
status 204
|
78
82
|
end
|
79
83
|
end
|
data/lib/ditty/helpers/views.rb
CHANGED
@@ -3,6 +3,20 @@
|
|
3
3
|
module Ditty
|
4
4
|
module Helpers
|
5
5
|
module Views
|
6
|
+
def layout
|
7
|
+
return :embedded if request.params['layout'] == 'embedded'
|
8
|
+
:layout
|
9
|
+
end
|
10
|
+
|
11
|
+
def with_layout(url)
|
12
|
+
uri = URI.parse(url)
|
13
|
+
# Don't set the layout if there's none. Don't set the layout for external URIs
|
14
|
+
return url if params['layout'].nil? || uri.host
|
15
|
+
qs = { 'layout' => params['layout'] }.merge(uri.query ? CGI.parse(uri.query) : {})
|
16
|
+
uri.query = Rack::Utils.build_query qs
|
17
|
+
uri.to_s
|
18
|
+
end
|
19
|
+
|
6
20
|
def form_control(name, model, opts = {})
|
7
21
|
label = opts.delete(:label) || name.to_s.titlecase
|
8
22
|
klass = opts.delete(:class) || 'form-control' unless opts[:type] == 'file'
|
@@ -41,15 +55,38 @@ module Ditty
|
|
41
55
|
"<div id='#{id}'>\n" + messages.join + '</div>'
|
42
56
|
end
|
43
57
|
|
58
|
+
def query_string(add = {})
|
59
|
+
qs = params.clone.merge(add)
|
60
|
+
qs.delete('captures')
|
61
|
+
Rack::Utils.build_query qs
|
62
|
+
end
|
63
|
+
|
44
64
|
def delete_form(entity, label = 'Delete')
|
45
65
|
locals = { delete_label: label, entity: entity }
|
46
66
|
haml :'partials/delete_form', locals: locals
|
47
67
|
end
|
48
68
|
|
49
|
-
def
|
50
|
-
|
51
|
-
|
52
|
-
|
69
|
+
def delete_form_tag(url, options = {}, &block)
|
70
|
+
options[:form_verb] = :delete
|
71
|
+
form_tag(url, options, &block)
|
72
|
+
end
|
73
|
+
|
74
|
+
def edit_form_tag(url, options = {}, &block)
|
75
|
+
options[:form_verb] = :put
|
76
|
+
form_tag(url, options, &block)
|
77
|
+
end
|
78
|
+
|
79
|
+
def new_form_tag(url, options = {}, &block)
|
80
|
+
options[:form_verb] = :post
|
81
|
+
form_tag(url, options, &block)
|
82
|
+
end
|
83
|
+
|
84
|
+
def form_tag(url, options = {}, &block)
|
85
|
+
options[:form_verb] ||= :post
|
86
|
+
options[:attributes] ||= {}
|
87
|
+
options[:attributes] = { 'class': 'form-horizontal' }.merge options[:attributes]
|
88
|
+
options[:url] = options[:form_verb].to_sym == :get ? url : with_layout(url)
|
89
|
+
haml :'partials/form_tag', locals: options.merge(block: block)
|
53
90
|
end
|
54
91
|
|
55
92
|
def pagination(list, base_path, qp = {})
|
data/lib/ditty/helpers/wisper.rb
CHANGED
@@ -17,7 +17,7 @@ module Ditty
|
|
17
17
|
@loggers = []
|
18
18
|
config.each do |values|
|
19
19
|
klass = values['class'].constantize
|
20
|
-
opts = values['options'] || nil
|
20
|
+
opts = tr(values['options']) || nil
|
21
21
|
logger = klass.new(opts)
|
22
22
|
if values['level']
|
23
23
|
logger.level = klass.const_get(values['level'].to_sym)
|
@@ -40,6 +40,13 @@ module Ditty
|
|
40
40
|
@config ||= File.exist?(CONFIG) ? YAML.load_file(CONFIG) : default
|
41
41
|
end
|
42
42
|
|
43
|
+
def tr(val)
|
44
|
+
{
|
45
|
+
'$stdout' => $stdout,
|
46
|
+
'$stderr' => $stderr
|
47
|
+
}[val] || val
|
48
|
+
end
|
49
|
+
|
43
50
|
def default
|
44
51
|
[{ 'name' => 'default', 'class' => 'Logger' }]
|
45
52
|
end
|
data/lib/ditty/version.rb
CHANGED
data/views/embedded.haml
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
!!! 5
|
2
|
+
%html{ lang: 'en' }
|
3
|
+
%head
|
4
|
+
%meta{ charset: 'utf-8' }
|
5
|
+
%meta{ 'http-equiv' => 'X-UA-Compatible', 'content' => 'IE=edge,chrome=1' }
|
6
|
+
%meta{ name: 'viewport', content: 'width=device-width, initial-scale=1' }
|
7
|
+
%meta{ name: 'theme-color', content: '#ffffff' }
|
8
|
+
%link{ rel: 'manifest', href: '/manifest.json' }
|
9
|
+
%link{ rel: 'icon', type: 'image/png', sizes: '32x32', href: '#{request.base_url}/images/favicon-32x32.png' }
|
10
|
+
%link{ rel: 'icon', type: 'image/png', sizes: '16x16', href: '#{request.base_url}/images/favicon-16x16.png' }
|
11
|
+
%link{ rel: 'apple-touch-icon', sizes: '76x76', href: '/images/apple-icon.png' }
|
12
|
+
%link{ rel: 'mask-icon', href: '/safari-pinned-tab.svg', color: '#5bbad5' }
|
13
|
+
|
14
|
+
%title
|
15
|
+
Ditty
|
16
|
+
- if defined? title
|
17
|
+
= "- #{title}"
|
18
|
+
|
19
|
+
%meta{ name: 'description', content: '' }
|
20
|
+
%meta{ name: 'author', content: '' }
|
21
|
+
|
22
|
+
/ Le styles
|
23
|
+
%link{ rel: 'stylesheet', href: 'https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css', media: 'screen' }
|
24
|
+
%link{ rel: 'stylesheet', href: 'https://cdnjs.cloudflare.com/ajax/libs/startbootstrap-sb-admin-2/3.3.7+1/css/sb-admin-2.min.css', media: 'screen' }
|
25
|
+
%link{ rel: 'stylesheet', href: 'https://maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css', media: 'screen' }
|
26
|
+
/[if lt IE 9] <script src="https://cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv.min.js"></script>
|
27
|
+
/[if lt IE 9] <script src="https://cdnjs.cloudflare.com/ajax/libs/respond.js/1.4.2/respond.min.js"></script>
|
28
|
+
|
29
|
+
%script{ type: 'text/javascript', src: 'https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.min.js' }
|
30
|
+
%script{ type: 'text/javascript', src: 'https://cdnjs.cloudflare.com/ajax/libs/startbootstrap-sb-admin-2/3.3.7+1/js/sb-admin-2.min.js' }
|
31
|
+
%body
|
32
|
+
.container-fluid
|
33
|
+
.row
|
34
|
+
.col-md-12
|
35
|
+
= haml :'partials/notifications'
|
36
|
+
|
37
|
+
= yield
|
38
|
+
|
39
|
+
/ Placed at the end of the document so the pages load faster
|
40
|
+
%script{ type: 'text/javascript', src: 'https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js' }
|
41
|
+
%script{ type: 'text/javascript', src: 'https://cdnjs.cloudflare.com/ajax/libs/react/15.4.1/react.min.js' }
|
42
|
+
%script{ type: 'text/javascript', src: 'https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.6.0/Chart.bundle.min.js' }
|
data/views/identity/login.haml
CHANGED
@@ -2,12 +2,10 @@
|
|
2
2
|
.col-sm-3
|
3
3
|
.col-sm-6
|
4
4
|
.panel.panel-default
|
5
|
-
.panel-heading
|
6
|
-
%h4 Login
|
7
5
|
.panel-body
|
8
6
|
%form{ method: 'post', action: "#{settings.map_path}/auth/identity/callback" }
|
9
7
|
.form-group
|
10
|
-
%label.control-label
|
8
|
+
%label.control-label Email
|
11
9
|
%input.form-control.border-input{ name: 'username' }
|
12
10
|
.form-group
|
13
11
|
%label.control-label Password
|
@@ -2,13 +2,20 @@
|
|
2
2
|
.col-md-2
|
3
3
|
.col-md-8
|
4
4
|
.panel.panel-default
|
5
|
-
.panel-heading
|
6
|
-
%h4 Register
|
7
5
|
.panel-body
|
8
6
|
%form.form-horizontal{ method: 'post', action: "#{settings.map_path}/auth/identity/new" }
|
9
|
-
= form_control(:username, identity, label: '
|
7
|
+
= form_control(:username, identity, label: 'Email', placeholder: 'your@email.com')
|
10
8
|
= form_control(:password, identity, label: 'Password', type: :password)
|
11
9
|
= form_control(:password_confirmation, identity, label: 'Confirm Password', type: :password)
|
12
10
|
|
13
|
-
|
11
|
+
- if identity.errors[:password] && identity.errors[:password].include?('is not strong enough')
|
12
|
+
.alert.alert-warning
|
13
|
+
%p Make sure your password is at least 8 characters long, and including the following
|
14
|
+
%ul
|
15
|
+
%li Upper- and lowercase letters
|
16
|
+
%li Numbers
|
17
|
+
%li Special Characters
|
18
|
+
|
19
|
+
- if policy(::Ditty::Identity).register?
|
20
|
+
%button.btn.btn-primary{ type: 'submit' } Register
|
14
21
|
.col-md-2
|
data/views/layout.haml
CHANGED
@@ -34,10 +34,16 @@
|
|
34
34
|
#wrapper
|
35
35
|
= haml :'partials/navbar', locals: { title: (defined?(title) ? title : 'Ditty') }
|
36
36
|
#page-wrapper
|
37
|
+
-if defined?(title) || defined?(actions)
|
38
|
+
.row
|
39
|
+
%h1.col-md-9= defined?(title) ? title : ' '
|
40
|
+
.col-md-3.text-left{ style: 'margin-top: 20px' }
|
41
|
+
= haml :'partials/actions', locals: { actions: defined?(actions) ? actions : {} }
|
42
|
+
-else
|
43
|
+
%div{ style: 'padding-top: 20px' }
|
44
|
+
|
37
45
|
.row
|
38
46
|
.col-md-12
|
39
|
-
-if defined? title
|
40
|
-
%h1.page-header= title
|
41
47
|
= haml :'partials/notifications'
|
42
48
|
|
43
49
|
= yield
|
@@ -0,0 +1,12 @@
|
|
1
|
+
- if actions.count > 1
|
2
|
+
.dropdown
|
3
|
+
%button.btn.btn-default.btn-block.dropdown-toggle{ type: 'button', id: 'actions-toggle', data: { toggle: 'dropdown' } }
|
4
|
+
Actions
|
5
|
+
%span.caret
|
6
|
+
%ul.dropdown-menu{ 'aria-labelledby': 'actions-toggle' }
|
7
|
+
-actions.each do |k, v|
|
8
|
+
%li
|
9
|
+
%a{ href: k }= v
|
10
|
+
- elsif actions.count > 0
|
11
|
+
-actions.each do |k, v|
|
12
|
+
%a.btn.btn-primary.btn-block{ href: k }= v
|
@@ -1,4 +1,2 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
<button type="submit" class="btn btn-danger"><%= delete_label %></button>
|
4
|
-
</form>
|
1
|
+
= delete_form_tag "#{base_path}/#{entity.id}" do
|
2
|
+
%button.btn.btn-danger{ type: 'submit' }= delete_label
|
data/views/partials/footer.haml
CHANGED
@@ -0,0 +1,6 @@
|
|
1
|
+
%form{ { method: %i[get post].include?(form_verb.to_sym) ? form_verb : :post, action: url }.merge(attributes) }
|
2
|
+
- if form_verb.to_sym == :get && layout
|
3
|
+
%input{ name: 'layout', value: layout, type: 'hidden' }
|
4
|
+
- if %i[get post].include?(form_verb.to_sym) == false
|
5
|
+
%input{ name: '_method', value: form_verb.upcase, type: 'hidden' }
|
6
|
+
= capture_haml(&block).chomp
|
data/views/partials/search.haml
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
- if self.class.const_defined?(:SEARCHABLE) || self.class.const_defined?(:FILTERS)
|
2
|
-
|
2
|
+
= form_tag(base_path, form_verb: :get, attributes: { class: '' }) do
|
3
3
|
- if self.class.const_defined?(:SEARCHABLE)
|
4
4
|
.form-group
|
5
5
|
.input-group
|
data/views/roles/edit.haml
CHANGED
@@ -3,8 +3,7 @@
|
|
3
3
|
.col-md-8
|
4
4
|
.panel.panel-default
|
5
5
|
.panel-body
|
6
|
-
|
7
|
-
%input{ name: '_method', value: 'PUT', type: 'hidden' }
|
6
|
+
= edit_form_tag "#{base_path}/#{entity.id}" do
|
8
7
|
= haml :'roles/form', locals: { entity: entity }
|
9
8
|
%button.btn.btn-primary{ type: 'submit' }
|
10
9
|
Update Role
|
data/views/roles/new.haml
CHANGED
data/views/users/edit.haml
CHANGED
@@ -3,8 +3,7 @@
|
|
3
3
|
.col-md-8
|
4
4
|
.panel.panel-default
|
5
5
|
.panel-body
|
6
|
-
|
7
|
-
%input{ name: '_method', value: 'PUT', type: 'hidden' }
|
6
|
+
= edit_form_tag "#{base_path}/#{entity.id}" do
|
8
7
|
= haml :'users/user', locals: { user: entity }
|
9
8
|
%button.btn.btn-primary{ type: 'submit' }
|
10
9
|
Update User
|
data/views/users/identity.haml
CHANGED
@@ -1,3 +1,10 @@
|
|
1
1
|
= form_control(:username, identity, label: 'Email', placeholder: 'Your email address')
|
2
|
+
- if identity.errors[:password] && identity.errors[:password].include?('is not strong enough')
|
3
|
+
.alert.alert-warning
|
4
|
+
%p Make sure your password is at least 8 characters long, and including the following
|
5
|
+
%ul
|
6
|
+
%li Upper- and lowercase letters
|
7
|
+
%li Numbers
|
8
|
+
%li Special Characters
|
2
9
|
= form_control(:password, identity, type: 'password', placeholder: 'Your password')
|
3
10
|
= form_control(:password_confirmation, identity, type: 'password', label: 'Confirm Password', placeholder: 'Confirm your password')
|
data/views/users/index.haml
CHANGED
data/views/users/new.haml
CHANGED
@@ -3,8 +3,8 @@
|
|
3
3
|
.col-md-8
|
4
4
|
.panel.panel-default
|
5
5
|
.panel-body
|
6
|
-
|
7
|
-
= haml :'users/identity', locals: { identity:
|
6
|
+
= new_form_tag base_path do
|
7
|
+
= haml :'users/identity', locals: { identity: identity }
|
8
8
|
= haml :'users/user', locals: { user: entity }
|
9
9
|
%button.btn.btn-primary{ type: 'submit' }
|
10
10
|
Create User
|
data/views/users/user.haml
CHANGED
@@ -1,4 +1,4 @@
|
|
1
1
|
= form_control(:name, user)
|
2
2
|
= form_control(:surname, user)
|
3
3
|
- if policy(user).permitted_attributes.include? :role_id
|
4
|
-
= form_control(:role_id, user, type: 'select', options: Ditty::Role.as_hash(:id, :name), name: 'user[role_id][]', field: :roles, multiple: true)
|
4
|
+
= form_control(:role_id, user, type: 'select', options: Ditty::Role.order(:name).as_hash(:id, :name), name: 'user[role_id][]', field: :roles, multiple: true)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ditty
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jurgens du Toit
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-04-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -164,6 +164,20 @@ dependencies:
|
|
164
164
|
- - "~>"
|
165
165
|
- !ruby/object:Gem::Version
|
166
166
|
version: '1.0'
|
167
|
+
- !ruby/object:Gem::Dependency
|
168
|
+
name: oga
|
169
|
+
requirement: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - ">="
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '2.14'
|
174
|
+
type: :runtime
|
175
|
+
prerelease: false
|
176
|
+
version_requirements: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - ">="
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: '2.14'
|
167
181
|
- !ruby/object:Gem::Dependency
|
168
182
|
name: omniauth
|
169
183
|
requirement: !ruby/object:Gem::Requirement
|
@@ -238,28 +252,28 @@ dependencies:
|
|
238
252
|
name: sequel
|
239
253
|
requirement: !ruby/object:Gem::Requirement
|
240
254
|
requirements:
|
241
|
-
- - "
|
255
|
+
- - ">="
|
242
256
|
- !ruby/object:Gem::Version
|
243
257
|
version: '4.0'
|
244
258
|
type: :runtime
|
245
259
|
prerelease: false
|
246
260
|
version_requirements: !ruby/object:Gem::Requirement
|
247
261
|
requirements:
|
248
|
-
- - "
|
262
|
+
- - ">="
|
249
263
|
- !ruby/object:Gem::Version
|
250
264
|
version: '4.0'
|
251
265
|
- !ruby/object:Gem::Dependency
|
252
266
|
name: sinatra
|
253
267
|
requirement: !ruby/object:Gem::Requirement
|
254
268
|
requirements:
|
255
|
-
- - "
|
269
|
+
- - ">="
|
256
270
|
- !ruby/object:Gem::Version
|
257
271
|
version: '2.0'
|
258
272
|
type: :runtime
|
259
273
|
prerelease: false
|
260
274
|
version_requirements: !ruby/object:Gem::Requirement
|
261
275
|
requirements:
|
262
|
-
- - "
|
276
|
+
- - ">="
|
263
277
|
- !ruby/object:Gem::Version
|
264
278
|
version: '2.0'
|
265
279
|
- !ruby/object:Gem::Dependency
|
@@ -384,15 +398,18 @@ files:
|
|
384
398
|
- public/manifest.json
|
385
399
|
- views/404.haml
|
386
400
|
- views/audit_logs/index.haml
|
401
|
+
- views/embedded.haml
|
387
402
|
- views/error.haml
|
388
403
|
- views/identity/login.haml
|
389
404
|
- views/identity/register.haml
|
390
405
|
- views/index.haml
|
391
406
|
- views/layout.haml
|
407
|
+
- views/partials/actions.haml
|
392
408
|
- views/partials/delete_form.haml
|
393
409
|
- views/partials/filter_control.haml
|
394
410
|
- views/partials/footer.haml
|
395
411
|
- views/partials/form_control.haml
|
412
|
+
- views/partials/form_tag.haml
|
396
413
|
- views/partials/navbar.haml
|
397
414
|
- views/partials/notifications.haml
|
398
415
|
- views/partials/pager.haml
|
@@ -430,7 +447,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
430
447
|
version: '0'
|
431
448
|
requirements: []
|
432
449
|
rubyforge_project:
|
433
|
-
rubygems_version: 2.7.
|
450
|
+
rubygems_version: 2.7.6
|
434
451
|
signing_key:
|
435
452
|
specification_version: 4
|
436
453
|
summary: Sinatra Based Application Framework
|