ditty 0.8.0 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/.pryrc +2 -0
- data/.rubocop.yml +1 -1
- data/.travis.yml +5 -4
- data/CNAME +1 -0
- data/Dockerfile +18 -0
- data/Gemfile.ci +0 -2
- data/Rakefile +2 -2
- data/_config.yml +1 -0
- data/config.ru +4 -4
- data/ditty.gemspec +9 -3
- data/docs/CNAME +1 -0
- data/docs/_config.yml +1 -0
- data/docs/index.md +34 -0
- data/exe/ditty +2 -0
- data/lib/ditty.rb +4 -2
- data/lib/ditty/cli.rb +28 -4
- data/lib/ditty/components/{app.rb → ditty.rb} +19 -14
- data/lib/ditty/controllers/{application.rb → application_controller.rb} +58 -29
- data/lib/ditty/controllers/{audit_logs.rb → audit_logs_controller.rb} +2 -2
- data/lib/ditty/controllers/{auth.rb → auth_controller.rb} +17 -16
- data/lib/ditty/controllers/{component.rb → component_controller.rb} +19 -18
- data/lib/ditty/controllers/{main.rb → main_controller.rb} +6 -2
- data/lib/ditty/controllers/roles_controller.rb +23 -0
- data/lib/ditty/controllers/{user_login_traits.rb → user_login_traits_controller.rb} +4 -3
- data/lib/ditty/controllers/{users.rb → users_controller.rb} +11 -10
- data/lib/ditty/db.rb +4 -3
- data/lib/ditty/emails/base.rb +5 -2
- data/lib/ditty/generators/crud_generator.rb +104 -0
- data/lib/ditty/generators/migration_generator.rb +26 -0
- data/lib/ditty/generators/project_generator.rb +51 -0
- data/lib/ditty/helpers/component.rb +2 -1
- data/lib/ditty/helpers/pundit.rb +20 -4
- data/lib/ditty/helpers/response.rb +20 -13
- data/lib/ditty/helpers/views.rb +7 -3
- data/lib/ditty/listener.rb +5 -3
- data/lib/ditty/memcached.rb +8 -0
- data/lib/ditty/middleware/accept_extension.rb +2 -2
- data/lib/ditty/middleware/error_catchall.rb +2 -2
- data/lib/ditty/models/base.rb +4 -0
- data/lib/ditty/models/role.rb +1 -0
- data/lib/ditty/models/user.rb +14 -1
- data/lib/ditty/policies/role_policy.rb +1 -1
- data/lib/ditty/policies/user_login_trait_policy.rb +1 -1
- data/lib/ditty/services/authentication.rb +11 -10
- data/lib/ditty/services/email.rb +8 -4
- data/lib/ditty/services/logger.rb +1 -1
- data/lib/ditty/tasks/ditty.rake +17 -0
- data/lib/ditty/tasks/omniauth-ldap.rake +2 -2
- data/lib/ditty/templates/.gitignore +5 -0
- data/lib/ditty/templates/.rspec +2 -0
- data/lib/ditty/templates/.rubocop.yml +7 -0
- data/lib/ditty/templates/Rakefile +12 -0
- data/lib/ditty/templates/application.rb +12 -0
- data/lib/ditty/templates/config.ru +37 -0
- data/lib/ditty/templates/controller.rb.erb +58 -0
- data/lib/ditty/templates/env.example +4 -0
- data/lib/ditty/templates/lib/project.rb.erb +5 -0
- data/lib/ditty/templates/migration.rb.erb +7 -0
- data/lib/ditty/templates/model.rb.erb +26 -0
- data/lib/ditty/templates/pids/.empty_directory +0 -0
- data/lib/ditty/templates/policy.rb.erb +48 -0
- data/lib/ditty/templates/public/css/sb-admin-2.min.css +10 -0
- data/lib/ditty/templates/public/js/sb-admin-2.min.js +7 -0
- data/lib/ditty/templates/settings.yml.erb +18 -0
- data/lib/ditty/templates/sidekiq.rb +18 -0
- data/lib/ditty/templates/sidekiq.yml +9 -0
- data/lib/ditty/templates/spec_helper.rb +43 -0
- data/lib/ditty/templates/type.rb.erb +21 -0
- data/lib/ditty/templates/views/display.haml.tt +20 -0
- data/lib/ditty/templates/views/edit.haml.tt +10 -0
- data/lib/ditty/templates/views/form.haml.tt +11 -0
- data/lib/ditty/templates/views/index.haml.tt +29 -0
- data/lib/ditty/templates/views/new.haml.tt +10 -0
- data/lib/ditty/version.rb +1 -1
- data/lib/rubocop/cop/ditty/call_services_directly.rb +2 -2
- data/migrate/20181209_add_user_login_traits.rb +4 -4
- data/migrate/20190220_add_parent_id_to_roles.rb +9 -0
- data/public/css/styles.css +13 -0
- data/public/js/scripts.js +1 -0
- data/views/404.haml +2 -4
- data/views/audit_logs/index.haml +32 -34
- data/views/auth/forgot_password.haml +27 -16
- data/views/auth/identity.haml +14 -13
- data/views/auth/ldap.haml +2 -2
- data/views/auth/login.haml +22 -17
- data/views/auth/register.haml +19 -18
- data/views/auth/register_identity.haml +27 -12
- data/views/auth/reset_password.haml +2 -2
- data/views/blank.haml +42 -0
- data/views/index.haml +1 -1
- data/views/layout.haml +37 -30
- data/views/partials/content_tag.haml +0 -0
- data/views/partials/delete_form.haml +1 -1
- data/views/partials/filter_control.haml +1 -1
- data/views/partials/footer.haml +5 -5
- data/views/partials/form_control.haml +19 -12
- data/views/partials/navitems.haml +44 -0
- data/views/partials/notifications.haml +12 -8
- data/views/partials/pager.haml +17 -17
- data/views/partials/search.haml +6 -7
- data/views/partials/sidebar.haml +15 -37
- data/views/partials/topbar.haml +68 -0
- data/views/roles/display.haml +27 -6
- data/views/roles/edit.haml +3 -3
- data/views/roles/form.haml +1 -0
- data/views/roles/index.haml +23 -16
- data/views/roles/new.haml +2 -2
- data/views/user_login_traits/display.haml +4 -4
- data/views/user_login_traits/edit.haml +3 -3
- data/views/user_login_traits/index.haml +4 -4
- data/views/user_login_traits/new.haml +2 -2
- data/views/users/display.haml +11 -12
- data/views/users/edit.haml +3 -3
- data/views/users/form.haml +0 -0
- data/views/users/index.haml +31 -24
- data/views/users/login_traits.haml +6 -8
- data/views/users/new.haml +2 -2
- data/views/users/profile.haml +13 -13
- metadata +143 -15
- data/lib/ditty/controllers/roles.rb +0 -13
- data/views/partials/navbar.haml +0 -22
@@ -1,8 +1,8 @@
|
|
1
1
|
.row
|
2
2
|
.col-md-2
|
3
3
|
.col-md-8
|
4
|
-
.
|
5
|
-
.
|
4
|
+
.card.card-default
|
5
|
+
.card-body
|
6
6
|
= edit_form_tag("#{settings.map_path}/auth/reset-password") do
|
7
7
|
%input{ name: 'token', value: params[:token], type: 'hidden' }
|
8
8
|
- if identity.errors[:password] && identity.errors[:password].include?('is not strong enough')
|
data/views/blank.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: '/images/favicon-32x32.png' }
|
10
|
+
%link{ rel: 'icon', type: 'image/png', sizes: '16x16', href: '/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
|
+
= config('ditty.title', '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: '/css/sb-admin-2.min.css', media: 'screen' }
|
24
|
+
%link{ rel: 'stylesheet', href: '/css/styles.css', media: 'screen' }
|
25
|
+
%link{ rel: 'stylesheet', href: 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.8.2/css/all.min.css', media: 'screen' }
|
26
|
+
%body.bg-gradient-primary
|
27
|
+
= yield
|
28
|
+
|
29
|
+
/ Placed at the end of the document so the pages load faster
|
30
|
+
%script{ type: 'text/javascript', src: 'https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js' }
|
31
|
+
%script{ type: 'text/javascript', src: 'https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/js/bootstrap.min.js' }
|
32
|
+
%script{ type: 'text/javascript', src: 'https://cdnjs.cloudflare.com/ajax/libs/jquery-easing/1.4.1/jquery.easing.min.js' }
|
33
|
+
/ %script{ type: 'text/javascript', src: 'https://cdnjs.cloudflare.com/ajax/libs/react/16.8.6/umd/react.production.min.js' }
|
34
|
+
%script{ type: 'text/javascript', src: 'https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.min.js' }
|
35
|
+
%script{ type: 'text/javascript', src: 'https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.7/js/select2.min.js' }
|
36
|
+
%script{ type: 'text/javascript', src: '/js/sb-admin-2.min.js' }
|
37
|
+
%script{ type: 'text/javascript', src: '/js/scripts.js' }
|
38
|
+
:javascript
|
39
|
+
$(function() {
|
40
|
+
$('.select2').select2();
|
41
|
+
});
|
42
|
+
|
data/views/index.haml
CHANGED
@@ -1 +1 @@
|
|
1
|
-
%
|
1
|
+
%h1.h3.mb-4.text-gray-800 Home Page
|
data/views/layout.haml
CHANGED
@@ -12,7 +12,7 @@
|
|
12
12
|
%link{ rel: 'mask-icon', href: '/safari-pinned-tab.svg', color: '#5bbad5' }
|
13
13
|
|
14
14
|
%title
|
15
|
-
Ditty
|
15
|
+
= config('ditty.title', 'Ditty')
|
16
16
|
- if defined? title
|
17
17
|
= "- #{title}"
|
18
18
|
|
@@ -20,43 +20,50 @@
|
|
20
20
|
%meta{ name: 'author', content: '' }
|
21
21
|
|
22
22
|
/ Le styles
|
23
|
-
%link{ rel: 'stylesheet', href: '
|
24
|
-
%link{ rel: 'stylesheet', href: '
|
25
|
-
%link{ rel: 'stylesheet', href: 'https://cdnjs.cloudflare.com/ajax/libs/
|
26
|
-
|
27
|
-
/
|
28
|
-
/[if lt IE 9] <script src="https://cdnjs.cloudflare.com/ajax/libs/respond.js/1.4.2/respond.min.js"></script>
|
29
|
-
|
30
|
-
%script{ type: 'text/javascript', src: 'https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.min.js' }
|
31
|
-
%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' }
|
32
|
-
%script{ type: 'text/javascript', src: 'https://cdnjs.cloudflare.com/ajax/libs/metisMenu/2.5.2/metisMenu.min.js' }
|
33
|
-
%body
|
23
|
+
%link{ rel: 'stylesheet', href: '/css/sb-admin-2.min.css', media: 'screen' }
|
24
|
+
%link{ rel: 'stylesheet', href: '/css/styles.css', media: 'screen' }
|
25
|
+
%link{ rel: 'stylesheet', href: 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.8.2/css/all.min.css', media: 'screen' }
|
26
|
+
%body#page-top
|
27
|
+
/ Page Wrapper
|
34
28
|
#wrapper
|
35
|
-
= haml :'partials/
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
.row
|
46
|
-
.col-md-12
|
29
|
+
= haml :'partials/sidebar', locals: { title: (defined?(title) ? title : 'Ditty') }
|
30
|
+
|
31
|
+
#content-wrapper.d-flex.flex-column
|
32
|
+
#content
|
33
|
+
= haml :'partials/topbar'
|
34
|
+
.container-fluid
|
35
|
+
/ TODO
|
36
|
+
/ .row
|
37
|
+
/ .col-md-12
|
47
38
|
= haml :'partials/notifications'
|
39
|
+
- if defined?(title) || defined?(actions)
|
40
|
+
.row
|
41
|
+
.col-md-9
|
42
|
+
%h1.text-dark.mb-2= defined?(title) ? title : ' '
|
43
|
+
.col-md-3.text-right.mt-1
|
44
|
+
= haml :'partials/actions', locals: { actions: defined?(actions) ? actions : {} }
|
45
|
+
- else
|
46
|
+
%div{ style: 'padding-top: 20px' }
|
47
|
+
|
48
|
+
= yield
|
48
49
|
|
49
|
-
= yield
|
50
50
|
= haml :'partials/footer'
|
51
51
|
|
52
|
+
/ Scroll to Top Button
|
53
|
+
%a.scroll-to-top.rounded{ href: '#page-top' }
|
54
|
+
%i.fas.fa-angle-up
|
55
|
+
|
52
56
|
/ Placed at the end of the document so the pages load faster
|
53
|
-
%script{ type: 'text/javascript', src: 'https://
|
54
|
-
%script{ type: 'text/javascript', src: 'https://cdnjs.cloudflare.com/ajax/libs/
|
55
|
-
%script{ type: 'text/javascript', src: 'https://cdnjs.cloudflare.com/ajax/libs/
|
56
|
-
%script{ type: 'text/javascript', src: 'https://cdnjs.cloudflare.com/ajax/libs/
|
57
|
+
%script{ type: 'text/javascript', src: 'https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js' }
|
58
|
+
%script{ type: 'text/javascript', src: 'https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/js/bootstrap.min.js' }
|
59
|
+
%script{ type: 'text/javascript', src: 'https://cdnjs.cloudflare.com/ajax/libs/jquery-easing/1.4.1/jquery.easing.min.js' }
|
60
|
+
/ %script{ type: 'text/javascript', src: 'https://cdnjs.cloudflare.com/ajax/libs/react/16.8.6/umd/react.production.min.js' }
|
61
|
+
%script{ type: 'text/javascript', src: 'https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.min.js' }
|
62
|
+
%script{ type: 'text/javascript', src: 'https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.7/js/select2.min.js' }
|
63
|
+
%script{ type: 'text/javascript', src: '/js/sb-admin-2.min.js' }
|
64
|
+
%script{ type: 'text/javascript', src: '/js/scripts.js' }
|
57
65
|
:javascript
|
58
66
|
$(function() {
|
59
|
-
$('.sidebar-nav').metisMenu();
|
60
67
|
$('.select2').select2();
|
61
68
|
});
|
62
69
|
|
File without changes
|
@@ -1,2 +1,2 @@
|
|
1
|
-
= delete_form_tag "#{base_path}/#{entity.
|
1
|
+
= delete_form_tag "#{base_path}/#{entity.display_id}" do
|
2
2
|
%button.btn.btn-danger{ type: 'submit' }= delete_label
|
data/views/partials/footer.haml
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
.
|
4
|
-
|
5
|
-
©
|
1
|
+
/ Footer
|
2
|
+
%footer.sticky-footer.bg-light
|
3
|
+
.container.my-auto
|
4
|
+
.copyright.text-center.my-auto.text-dark
|
5
|
+
%span Copyright © Ditty.io 2019
|
@@ -1,24 +1,31 @@
|
|
1
1
|
- type = attributes.delete(:type)
|
2
|
+
- attributes[:value] ||= model.send(field) || default
|
3
|
+
- if help_text
|
4
|
+
- attributes[:'aria-describedby'] = "#{attributes[:id]}_helptext"
|
2
5
|
- if type == 'hidden'
|
3
|
-
%input{attributes, type: type, value: model
|
6
|
+
%input{attributes, type: type, value: model.send(field) || default}
|
4
7
|
- else
|
5
|
-
|
8
|
+
.form-group
|
6
9
|
- if type != 'file'
|
7
|
-
%label
|
8
|
-
.col-sm-9
|
10
|
+
%label{ for: attributes[:id] }= label
|
9
11
|
- if type == 'select'
|
10
12
|
- options = attributes.delete(:options)
|
13
|
+
- value = attributes.delete(:value)
|
14
|
+
- if attributes[:multiple]
|
15
|
+
- attributes[:name] = "#{attributes[:name]}[]" unless attributes[:name][-2..-1] == '[]'
|
11
16
|
%select{attributes}
|
12
17
|
- if attributes[:multiple]
|
13
|
-
- options.each do |k,v| k
|
14
|
-
%option{ value: k, selected:
|
18
|
+
- options.each do |k, v| k = v if k.nil?; v = k if v.nil?;
|
19
|
+
%option{ value: k.to_s, selected: value&.include?(k) }= v
|
15
20
|
- else
|
16
|
-
%option{ value: ""} -- Select One --
|
17
|
-
- options.each do |k,v| k
|
18
|
-
%option{ value: k, selected:
|
21
|
+
%option{ value: "" } -- Select One --
|
22
|
+
- options.each do |k, v| k = v if k.nil?; v = k if v.nil?;
|
23
|
+
%option{ value: k.to_s, selected: value == k }= v
|
19
24
|
- elsif type == 'textarea'
|
20
|
-
%textarea{attributes}= preserve(model
|
25
|
+
%textarea{attributes}= preserve(model.send(field) || default)
|
21
26
|
- else
|
22
|
-
%input{attributes, type: type
|
27
|
+
%input{ attributes, type: type }
|
23
28
|
- if model.errors[field]
|
24
|
-
|
29
|
+
.invalid-feedback= model.errors[field].join(', ')
|
30
|
+
- if help_text
|
31
|
+
%small.form-text.text-muted{ id: "#{attributes[:id]}_helptext" }= help_text
|
@@ -0,0 +1,44 @@
|
|
1
|
+
- if authenticated?
|
2
|
+
- Ditty::Components.components.each do |key, comp|
|
3
|
+
- next unless comp.respond_to?(:navigation) && comp.navigation.count.positive?
|
4
|
+
- if comp.respond_to?(:title)
|
5
|
+
.sidebar-heading= comp.title
|
6
|
+
- comp.navigation.each do |item|
|
7
|
+
- if item[:target].nil? || policy(item[:target]).list?
|
8
|
+
- if item[:group]
|
9
|
+
%li.nav-item
|
10
|
+
%a.nav-link.collapsed{ href: '#', 'data-toggle': 'collapse', 'data-target': "##{item[:group].parameterize}", 'aria-expanded': 'true', 'aria-controls': item[:group].parameterize }
|
11
|
+
- if item[:icon]
|
12
|
+
%i.fas.fa-fw{ class: "fa-#{item[:icon]}" }
|
13
|
+
%span= item[:group]
|
14
|
+
.collapse{ id: item[:group].parameterize, 'data-parent': '#accordionSidebar' }
|
15
|
+
.bg-white.py-2.collapse-inner.rounded
|
16
|
+
- item[:items].each do |sub_item|
|
17
|
+
- next unless sub_item[:target] && policy(sub_item[:target]).list?
|
18
|
+
%a.collapse-item{ href: "#{settings.map_path}#{sub_item[:link]}" }
|
19
|
+
- if sub_item[:icon]
|
20
|
+
%i.fa.fa-fw{ class: "fa-#{sub_item[:icon]}" }
|
21
|
+
= sub_item[:text]
|
22
|
+
- else
|
23
|
+
%li.nav-item
|
24
|
+
%a.nav-link{ href: "#{settings.map_path}#{item[:link]}" }
|
25
|
+
- if item[:icon]
|
26
|
+
%i.fas.fa-fw{ class: "fa-#{item[:icon]}" }
|
27
|
+
%span= item[:text]
|
28
|
+
%hr.sidebar-divider
|
29
|
+
%li.nav-item
|
30
|
+
= delete_form_tag("#{settings.map_path}/auth", attributes: { id: 'logout-form' }) do
|
31
|
+
%a.nav-link{ type: 'submit', onClick: 'document.getElementById("logout-form").submit()' }
|
32
|
+
%i.fas.fa-fw.fa-sign-out-alt
|
33
|
+
%span Logout
|
34
|
+
- else
|
35
|
+
%li.nav-item
|
36
|
+
%a.nav-link{ href: "#{settings.map_path}/auth/login" }
|
37
|
+
%i.fas.fa-fw.fa-user
|
38
|
+
%span Log In
|
39
|
+
- if policy(::Ditty::User).register?
|
40
|
+
%li.nav-item
|
41
|
+
%a.nav-link{ href: "#{settings.map_path}/auth/register" }
|
42
|
+
%i.fas.fa-fw.fa-pen-square
|
43
|
+
%span Register
|
44
|
+
|
@@ -1,28 +1,32 @@
|
|
1
1
|
- if flash[:danger]
|
2
2
|
.alert.alert-danger.alert-dismissible{ role: "alert" }
|
3
|
-
%button.close{
|
4
|
-
|
3
|
+
%button.close{ type: 'button', 'aria-label': 'Close', 'data-dismiss': 'alert' }
|
4
|
+
%span{ 'aria-hidden': 'true' } ×
|
5
|
+
%ul.mb-0
|
5
6
|
- [*flash[:danger]].each do |msg|
|
6
7
|
%li= msg
|
7
8
|
|
8
9
|
- if flash[:warning]
|
9
10
|
.alert.alert-warning.alert-dismissible{ role: "alert" }
|
10
|
-
%button.close{
|
11
|
-
|
11
|
+
%button.close{ type: 'button', 'aria-label': 'Close', 'data-dismiss': 'alert' }
|
12
|
+
%span{ 'aria-hidden': 'true' } ×
|
13
|
+
%ul.mb-0
|
12
14
|
- [*flash[:warning]].each do |msg|
|
13
15
|
%li= msg
|
14
16
|
|
15
17
|
- if flash[:success]
|
16
18
|
.alert.alert-success.alert-dismissible{ role: "alert" }
|
17
|
-
%button.close{
|
18
|
-
|
19
|
+
%button.close{ type: 'button', 'aria-label': 'Close', 'data-dismiss': 'alert' }
|
20
|
+
%span{ 'aria-hidden': 'true' } ×
|
21
|
+
%ul.mb-0
|
19
22
|
- [*flash[:success]].each do |msg|
|
20
23
|
%li= msg
|
21
24
|
|
22
25
|
|
23
26
|
- if flash[:info]
|
24
27
|
.alert.alert-info.alert-dismissible{ role: "alert" }
|
25
|
-
%button.close{
|
26
|
-
|
28
|
+
%button.close{ type: 'button', 'aria-label': 'Close', 'data-dismiss': 'alert' }
|
29
|
+
%span{ 'aria-hidden': 'true' } ×
|
30
|
+
%ul.mb-0
|
27
31
|
- [*flash[:info]].each do |msg|
|
28
32
|
%li= msg
|
data/views/partials/pager.haml
CHANGED
@@ -1,26 +1,26 @@
|
|
1
1
|
%nav{"aria-label" => "Page navigation"}
|
2
2
|
- if list.pagination_record_count > 0
|
3
3
|
%p.text-center Showing #{list.current_page_record_range} of #{list.pagination_record_count} records
|
4
|
-
%ul.
|
4
|
+
%ul.pagination.justify-content-center
|
5
5
|
- if list.first_page?
|
6
|
-
%li.disabled
|
7
|
-
%span First
|
8
|
-
%li.disabled
|
9
|
-
%span Previous
|
6
|
+
%li.page-item.disabled
|
7
|
+
%span.page-link First
|
8
|
+
%li.page-item.disabled
|
9
|
+
%span.page-link Previous
|
10
10
|
- else
|
11
|
-
%li
|
12
|
-
%a{href: first_link} First
|
13
|
-
%li
|
14
|
-
%a{href: prev_link} Previous
|
11
|
+
%li.page-item
|
12
|
+
%a.page-link{href: first_link} First
|
13
|
+
%li.page-item
|
14
|
+
%a.page-link{href: prev_link} Previous
|
15
15
|
- if list.last_page?
|
16
|
-
%li.disabled
|
17
|
-
%span Next
|
18
|
-
%li.disabled
|
19
|
-
%span Last
|
16
|
+
%li.page-item.disabled
|
17
|
+
%span.page-link Next
|
18
|
+
%li.page-item.disabled
|
19
|
+
%span.page-link Last
|
20
20
|
- else
|
21
|
-
%li
|
22
|
-
%a{href: next_link} Next
|
23
|
-
%li
|
24
|
-
%a{href: last_link} Last
|
21
|
+
%li.page-item
|
22
|
+
%a.page-link{href: next_link} Next
|
23
|
+
%li.page-item
|
24
|
+
%a.page-link{href: last_link} Last
|
25
25
|
- else
|
26
26
|
%p.text-center No records to show
|
data/views/partials/search.haml
CHANGED
@@ -9,13 +9,12 @@
|
|
9
9
|
%span.fa.fa-search
|
10
10
|
- if self.class.const_defined? :FILTERS
|
11
11
|
.input-group-btn
|
12
|
-
%button.btn.btn-
|
12
|
+
%button.btn.btn-secondary{ type: 'button', :'data-toggle' => 'collapse', :'data-target' => '#filter-form', :'aria-expanded' => 'false', :'aria-controls' => '#filter-form'}
|
13
13
|
%span.fa.fa-arrow-down
|
14
14
|
|
15
15
|
- if self.class.const_defined?(:FILTERS)
|
16
|
-
#filter-form{ class: self.class.const_defined?(:SEARCHABLE) ? 'collapse' : '' }
|
17
|
-
.
|
18
|
-
|
19
|
-
|
20
|
-
-
|
21
|
-
%button.btn.btn-default{ type: 'submit'} Go
|
16
|
+
#filter-form.row{ class: self.class.const_defined?(:SEARCHABLE) ? 'collapse' : '' }
|
17
|
+
- FILTERS.each do |filter|
|
18
|
+
= filter_control(filter, filters: FILTERS.count)
|
19
|
+
- unless self.class.const_defined?(:SEARCHABLE)
|
20
|
+
%button.btn.btn-secondary{ type: 'submit'} Go
|
data/views/partials/sidebar.haml
CHANGED
@@ -1,37 +1,15 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
%ul.nav.nav-second-level
|
17
|
-
- item[:items].each do |sub_item|
|
18
|
-
- if sub_item[:target].nil? || policy(sub_item[:target]).list?
|
19
|
-
%li
|
20
|
-
%a{ href: "#{settings.map_path}#{sub_item[:link]}" }
|
21
|
-
%i.fa.fa-fw{ class: "fa-#{sub_item[:icon]}" }
|
22
|
-
= sub_item[:text]
|
23
|
-
- else
|
24
|
-
%li
|
25
|
-
%a{ href: "#{settings.map_path}#{item[:link]}" }
|
26
|
-
%i.fa.fa-fw{ class: "fa-#{item[:icon]}" }
|
27
|
-
= item[:text]
|
28
|
-
- else
|
29
|
-
%li
|
30
|
-
%a{ href: "#{settings.map_path}/auth/login" }
|
31
|
-
%i.fa.fa-user.fa-fw
|
32
|
-
Log In
|
33
|
-
- if policy(::Ditty::User).register?
|
34
|
-
%li
|
35
|
-
%a{ href: "#{settings.map_path}/auth/register" }
|
36
|
-
%i.fa.fa-pencil-square-o.fa-fw
|
37
|
-
Register
|
1
|
+
/ Sidebar
|
2
|
+
%ul#accordionSidebar.navbar-nav.bg-gradient-primary.sidebar.sidebar-dark.accordion
|
3
|
+
/ Sidebar - Brand
|
4
|
+
%a.sidebar-brand.d-flex.align-items-center.justify-content-center{ href: config('ditty.home_page', settings.map_path || '/') }
|
5
|
+
.sidebar-brand-icon.rotate-n-15
|
6
|
+
%i.fas.fa-laugh-wink
|
7
|
+
.sidebar-brand-text.mx-3
|
8
|
+
= config('ditty.title', 'Ditty')
|
9
|
+
|
10
|
+
/ Divider
|
11
|
+
%hr.sidebar-divider.my-0
|
12
|
+
= haml :'partials/navitems'
|
13
|
+
|
14
|
+
.text-center.d-none.d-md-inline
|
15
|
+
%button#sidebarToggle.rounded-circle.border-0
|
@@ -0,0 +1,68 @@
|
|
1
|
+
/ Logout Modal
|
2
|
+
#logoutModal.modal.fade{ tabindex: -1, role: 'dialog', 'aria-hidden': 'true' }
|
3
|
+
.modal-dialog{ role: 'document' }
|
4
|
+
.modal-content
|
5
|
+
.modal-header
|
6
|
+
%h5.modal-title Ready to Leave?
|
7
|
+
%button.close{ type: 'button', 'data-dismiss': 'modal', 'aria-label': 'Close' }
|
8
|
+
%span{ 'aria-hidden': 'true' } ×
|
9
|
+
.modal-body
|
10
|
+
Select "Logout" below if you are ready to end your current session.
|
11
|
+
.modal-footer
|
12
|
+
%button.btn.btn-secondary{ type: 'button', 'data-dismiss': 'modal' } Cancel
|
13
|
+
= delete_form_tag("#{settings.map_path}/auth") do
|
14
|
+
%button.btn.btn-primary{ type: 'submit' } Logout
|
15
|
+
|
16
|
+
%nav.navbar.navbar-expand.navbar-light.bg-white.topbar.mb-4.static-top.shadow
|
17
|
+
/ Sidebar Toggle
|
18
|
+
%button#sidebarToggleTop.btn.btn-link.d-md-none.rounded-circle.mr-3
|
19
|
+
%i.fa.fa-bars
|
20
|
+
|
21
|
+
/ Topbar Search
|
22
|
+
%form.d-none.d-sm-inline-block.form-inline.mr-auto.ml-md-3.my-2.my-md-0.mw-100.navbar-search
|
23
|
+
.input-group
|
24
|
+
%input.form-control.bg-light.border-0.small{ type: 'text', placeholder: 'Search for...', 'aria-label': 'Search', 'aria-describedby': 'basic-addon2' }
|
25
|
+
.input-group-append
|
26
|
+
%button.btn.btn-primary{ type: 'button' }
|
27
|
+
%i.fas.fa-search.fa-sm
|
28
|
+
|
29
|
+
/ Topbar Navbar
|
30
|
+
%ul.navbar-nav.ml-auto
|
31
|
+
/ Nav Item - Search Dropdown (Visible Only XS)
|
32
|
+
%li.nav-item.dropdown.no-arrow.d-sm-none
|
33
|
+
%a#searchDropdown.nav-link.dropdown-toggle{ href: '#', role: 'button', 'data-toggle': 'dropdown', 'aria-haspopup': 'true', 'aria-expanded': 'false' }
|
34
|
+
%i.fas.fa-search.fa-fw
|
35
|
+
/ Dropdown - Messages
|
36
|
+
.dropdown-menu.dropdown-menu-right.p-3.shadow.animated--grow-in{ :'aria-labelledby' => 'searchDropdown' }
|
37
|
+
%form.form-inline.mr-auto.w-100.navbar-search
|
38
|
+
.input-group
|
39
|
+
%input.form-control.bg-light.border-0.small{ type: 'text', placeholder: 'Search for...', :'aria-label' => 'Search', :'aria-describedby' => 'basic-addon2' }
|
40
|
+
.input-group-append
|
41
|
+
%button.btn.btn-primary{ type: 'button' }
|
42
|
+
%i.fas.fa-.fa-sm
|
43
|
+
|
44
|
+
|
45
|
+
.topbar-divider.d-none.d-sm-block
|
46
|
+
|
47
|
+
/ Nav Item - User Information
|
48
|
+
- if authenticated?
|
49
|
+
%li.nav-item.dropdown.no-arrow
|
50
|
+
%a#userDropdown.nav-link.dropdown-toggle{ href: '#', role: 'button', 'aria-haspopup': 'true', 'area-expanded': 'false', 'data-toggle': 'dropdown' }
|
51
|
+
%span.mr-2.d-none.d-lg-inline.text-gray-600.small= current_user.display_name
|
52
|
+
%img.img-profile.rounded-circle{ src: current_user.gravatar }
|
53
|
+
/ Dropdown - User Information
|
54
|
+
.dropdown-menu.dropdown-menu-right.shadow.animated--grow-in{ 'aria-labelledby': 'userDropdown' }
|
55
|
+
%a.dropdown-item{ href: "#{settings.map_path}/users/profile" }
|
56
|
+
%i.fas.fa-user.fa-sm.fa-fw.mr-2.text-gray-400
|
57
|
+
Profile
|
58
|
+
/ %a.dropdown-item{ href: '#' }
|
59
|
+
/ %i.fas.fa-cogs.fa-sm.fa-fw.mr-2.text-gray-400
|
60
|
+
/ Settings
|
61
|
+
%a.dropdown-item{ href: "#{settings.map_path}/login-traits" }
|
62
|
+
%i.fas.fa-list.fa-sm.fa-fw.mr-2.text-gray-400
|
63
|
+
Past Logins
|
64
|
+
.dropdown-divider
|
65
|
+
%a.dropdown-item{ href: '#', data: { toggle: 'modal', target: '#logoutModal' } }
|
66
|
+
%i.fas.fa-sign-out-alt.fa-sm.fa-fw.mr-2.text-gray-400
|
67
|
+
Logout
|
68
|
+
- else
|