ditty 0.4.0 → 0.4.1
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/.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
|