ditty 0.9.1 → 0.10.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.
Files changed (105) hide show
  1. checksums.yaml +4 -4
  2. data/.env.test +2 -0
  3. data/.gitignore +1 -0
  4. data/.rubocop.yml +23 -4
  5. data/.travis.yml +2 -7
  6. data/Gemfile.ci +0 -15
  7. data/ditty.gemspec +19 -15
  8. data/lib/ditty.rb +2 -2
  9. data/lib/ditty/cli.rb +5 -0
  10. data/lib/ditty/components/ditty.rb +4 -7
  11. data/lib/ditty/controllers/application_controller.rb +6 -5
  12. data/lib/ditty/controllers/audit_logs_controller.rb +2 -0
  13. data/lib/ditty/controllers/auth_controller.rb +5 -2
  14. data/lib/ditty/controllers/component_controller.rb +3 -3
  15. data/lib/ditty/controllers/user_login_traits_controller.rb +28 -1
  16. data/lib/ditty/controllers/users_controller.rb +3 -2
  17. data/lib/ditty/db.rb +4 -3
  18. data/lib/ditty/emails/base.rb +32 -30
  19. data/lib/ditty/generators/crud_generator.rb +51 -41
  20. data/lib/ditty/generators/project_generator.rb +1 -0
  21. data/lib/ditty/helpers/pundit.rb +4 -4
  22. data/lib/ditty/helpers/response.rb +6 -11
  23. data/lib/ditty/helpers/views.rb +21 -3
  24. data/lib/ditty/listener.rb +1 -1
  25. data/lib/ditty/models/base.rb +5 -0
  26. data/lib/ditty/models/identity.rb +7 -7
  27. data/lib/ditty/models/user.rb +9 -1
  28. data/lib/ditty/policies/user_policy.rb +1 -1
  29. data/lib/ditty/services/authentication.rb +19 -9
  30. data/lib/ditty/services/email.rb +13 -13
  31. data/lib/ditty/services/logger.rb +26 -20
  32. data/lib/ditty/services/pagination_wrapper.rb +7 -5
  33. data/lib/ditty/services/settings.rb +7 -6
  34. data/lib/ditty/tasks/ditty.rake +2 -1
  35. data/lib/ditty/templates/application.rb +1 -1
  36. data/lib/ditty/templates/config.ru +2 -2
  37. data/lib/ditty/templates/controller.rb.erb +7 -1
  38. data/{public → lib/ditty/templates/public}/browserconfig.xml +0 -0
  39. data/{public → lib/ditty/templates/public}/css/styles.css +0 -0
  40. data/lib/ditty/templates/public/favicon.ico +0 -0
  41. data/{public → lib/ditty/templates/public}/images/apple-icon.png +0 -0
  42. data/{public → lib/ditty/templates/public}/images/favicon-16x16.png +0 -0
  43. data/{public → lib/ditty/templates/public}/images/favicon-32x32.png +0 -0
  44. data/{public → lib/ditty/templates/public}/images/launcher-icon-1x.png +0 -0
  45. data/{public → lib/ditty/templates/public}/images/launcher-icon-2x.png +0 -0
  46. data/{public → lib/ditty/templates/public}/images/launcher-icon-4x.png +0 -0
  47. data/{public → lib/ditty/templates/public}/images/mstile-150x150.png +0 -0
  48. data/{public → lib/ditty/templates/public}/images/safari-pinned-tab.svg +0 -0
  49. data/{public → lib/ditty/templates/public}/js/scripts.js +0 -0
  50. data/{public/manifest.json → lib/ditty/templates/public/manifest.json.erb} +2 -2
  51. data/lib/ditty/templates/settings.yml.erb +1 -0
  52. data/lib/ditty/templates/spec_helper.rb +1 -1
  53. data/lib/ditty/templates/views/display.haml.tt +1 -1
  54. data/lib/ditty/templates/views/edit.haml.tt +1 -1
  55. data/lib/ditty/templates/views/index.haml.tt +1 -1
  56. data/lib/ditty/templates/views/new.haml.tt +1 -1
  57. data/lib/ditty/version.rb +1 -1
  58. data/spec/ditty/api_spec.rb +1 -1
  59. data/spec/ditty/emails/base_spec.rb +3 -3
  60. data/spec/ditty/emails/forgot_password_spec.rb +3 -2
  61. data/spec/ditty/models/user_spec.rb +3 -3
  62. data/spec/ditty/services/logger_spec.rb +7 -6
  63. data/spec/ditty/services/settings_spec.rb +2 -2
  64. data/spec/factories.rb +4 -4
  65. data/spec/spec_helper.rb +5 -1
  66. data/views/403.haml +1 -1
  67. data/views/500.haml +11 -0
  68. data/views/audit_logs/index.haml +12 -11
  69. data/views/auth/forgot_password.haml +29 -24
  70. data/views/auth/ldap.haml +1 -1
  71. data/views/auth/login.haml +3 -2
  72. data/views/auth/register.haml +3 -2
  73. data/views/auth/reset_password.haml +36 -19
  74. data/views/blank.haml +1 -0
  75. data/views/embedded.haml +17 -11
  76. data/views/layout.haml +16 -8
  77. data/views/partials/actions.haml +15 -14
  78. data/views/partials/filter_control.haml +1 -1
  79. data/views/partials/footer.haml +10 -2
  80. data/views/partials/form_tag.haml +1 -1
  81. data/views/partials/navitems.haml +25 -27
  82. data/views/partials/pager.haml +44 -25
  83. data/views/partials/search.haml +14 -9
  84. data/views/partials/sidebar.haml +2 -2
  85. data/views/partials/sort_ui.haml +2 -0
  86. data/views/partials/timespan_selector.haml +64 -0
  87. data/views/partials/topbar.haml +0 -15
  88. data/views/partials/user_associations.haml +32 -0
  89. data/views/quick_start.haml +23 -0
  90. data/views/roles/display.haml +3 -3
  91. data/views/roles/edit.haml +1 -1
  92. data/views/roles/index.haml +2 -2
  93. data/views/roles/new.haml +1 -1
  94. data/views/user_login_traits/display.haml +1 -1
  95. data/views/user_login_traits/edit.haml +1 -1
  96. data/views/user_login_traits/index.haml +23 -25
  97. data/views/user_login_traits/new.haml +1 -1
  98. data/views/users/display.haml +5 -5
  99. data/views/users/edit.haml +1 -1
  100. data/views/users/index.haml +5 -5
  101. data/views/users/login_traits.haml +2 -2
  102. data/views/users/new.haml +1 -1
  103. data/views/users/profile.haml +4 -4
  104. data/views/users/user.haml +1 -1
  105. metadata +116 -54
@@ -1,26 +1,45 @@
1
1
  %nav{"aria-label" => "Page navigation"}
2
- - if list.pagination_record_count > 0
3
- %p.text-center Showing #{list.current_page_record_range} of #{list.pagination_record_count} records
4
- %ul.pagination.justify-content-center
5
- - if list.first_page?
6
- %li.page-item.disabled
7
- %span.page-link First
8
- %li.page-item.disabled
9
- %span.page-link Previous
10
- - else
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
- - if list.last_page?
16
- %li.page-item.disabled
17
- %span.page-link Next
18
- %li.page-item.disabled
19
- %span.page-link Last
20
- - else
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
- - else
26
- %p.text-center No records to show
2
+ .row
3
+ .col-sm-12.col-md-6
4
+ %p.my-2
5
+ - if list.pagination_record_count > 0
6
+ Showing #{list.current_page_record_range} of #{list.pagination_record_count} records
7
+ - else
8
+ %p.text-center No records to show
9
+ .col-sm-12.col-md-6
10
+ - if list.pagination_record_count > 0
11
+ %ul.pagination.justify-content-end
12
+ - if list.first_page?
13
+ %li.page-item.disabled
14
+ %span.page-link First
15
+ %li.page-item.disabled
16
+ %span.page-link Previous
17
+ - else
18
+ %li.page-item
19
+ %a.page-link{ href: first_link } First
20
+ %li.page-item
21
+ %a.page-link{ href: prev_link } Previous
22
+ %li.page-item
23
+ .dropdown
24
+ %button.page-link.dropdown-toggle{ type: 'button', id: 'dropdownMenuButton', 'data-toggle': 'dropdown', 'aria-haspopup': 'true', 'aria-expanded': 'false' }
25
+ = params[:count] || 10
26
+ .dropdown-menu
27
+ %a.dropdown-item{ href: "#{base_path}?#{query_string(count: 10)}" } 10
28
+ %a.dropdown-item{ href: "#{base_path}?#{query_string(count: 25)}" } 25
29
+ %a.dropdown-item{ href: "#{base_path}?#{query_string(count: 50)}" } 50
30
+ %a.dropdown-item{ href: "#{base_path}?#{query_string(count: 100)}" } 100
31
+ - if list.last_page?
32
+ %li.page-item.disabled
33
+ %span.page-link Next
34
+ %li.page-item.disabled
35
+ %span.page-link Last
36
+ - else
37
+ %li.page-item
38
+ %a.page-link{ href: next_link } Next
39
+ %li.page-item
40
+ %a.page-link{ href: last_link } Last
41
+ %li
42
+  
43
+ %li
44
+ %a.page-link{ href: "#{base_path}/.csv?#{URI.encode_www_form(params.merge(count: 'all'))}" }
45
+ Export
@@ -1,20 +1,25 @@
1
- - if self.class.const_defined?(:SEARCHABLE) || self.class.const_defined?(:FILTERS)
1
+ - if self.class.const_defined?(:SEARCHABLE) && SEARCHABLE.count.positive? || self.class.const_defined?(:FILTERS) && FILTERS.count.positive?
2
2
  = form_tag(base_path, form_verb: :get, attributes: { class: '' }) do
3
- - if self.class.const_defined?(:SEARCHABLE)
3
+ - if self.class.const_defined?(:SEARCHABLE) && SEARCHABLE.count.positive?
4
4
  .form-group
5
5
  .input-group
6
6
  %input.form-control{ name: 'q', type: 'text', placeholder: 'Search...', value: params[:q] }
7
7
  .input-group-btn
8
8
  %button.btn.btn-primary{ type: 'submit' }
9
9
  %span.fa.fa-search
10
- - if self.class.const_defined? :FILTERS
10
+ - if self.class.const_defined?(:FILTERS) && FILTERS.count.positive?
11
11
  .input-group-btn
12
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
- - if self.class.const_defined?(:FILTERS)
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
15
+ - if self.class.const_defined?(:FILTERS) && FILTERS.count.positive?
16
+ #filter-form{ class: self.class.const_defined?(:SEARCHABLE) && SEARCHABLE.count.positive? ? 'collapse' : '' }
17
+ .card.card-default.mb-2
18
+ .card-body
19
+ .row
20
+ - FILTERS.each do |filter|
21
+ = filter_control(filter, filters: FILTERS.count)
22
+ - unless self.class.const_defined?(:SEARCHABLE) && SEARCHABLE.count.positive?
23
+ .form-group
24
+ %label
25
+ %button.form-control.btn.btn-secondary{ type: 'submit'} Go
@@ -3,12 +3,12 @@
3
3
  / Sidebar - Brand
4
4
  %a.sidebar-brand.d-flex.align-items-center.justify-content-center{ href: config('ditty.home_page', settings.map_path || '/') }
5
5
  .sidebar-brand-icon.rotate-n-15
6
- %i.fas.fa-laugh-wink
6
+ %i.fas{ class: config('ditty.brand-icon', 'fa-laugh-wink') }
7
7
  .sidebar-brand-text.mx-3
8
8
  = config('ditty.title', 'Ditty')
9
9
 
10
- / Divider
11
10
  %hr.sidebar-divider.my-0
11
+
12
12
  = haml :'partials/navitems'
13
13
 
14
14
  .text-center.d-none.d-md-inline
@@ -0,0 +1,2 @@
1
+ %a{ href: "#{base_path}?#{sort_query(field)}" }
2
+ %i.fa{ class: sort_icon(field) }
@@ -0,0 +1,64 @@
1
+ - if defined?(context)
2
+ - if context.interval
3
+ %li.nav-item.dropdown.no-arrow
4
+ %a#intervalDropdown.nav-link.dropdown-toggle{ href: '#', role: 'button', 'aria-haspopup': 'true', 'area-expanded': 'false', 'data-toggle': 'dropdown' }
5
+ %span.mr-2.d-none.d-lg-inline.text-gray-600
6
+ Interval /
7
+ %strong
8
+ = context.interval
9
+ .dropdown-menu.dropdown-menu-right.shadow.animated--grow-in{ 'aria-labelledby': 'intervalDropdown' }
10
+ %a.dropdown-item{ href: "?#{URI.encode_www_form(and_params.merge(interval: '1m'))}", class: context.interval == '1m' ? 'active' : '' }
11
+ 1 Minute
12
+ %a.dropdown-item{ href: "?#{URI.encode_www_form(and_params.merge(interval: '5m'))}", class: context.interval == '5m' ? 'active' : '' }
13
+ 5 Minutes
14
+ %a.dropdown-item{ href: "?#{URI.encode_www_form(and_params.merge(interval: '15m'))}", class: context.interval == '15m' ? 'active' : '' }
15
+ 15 Minutes
16
+ .dropdown-divider
17
+ %a.dropdown-item{ href: "?#{URI.encode_www_form(and_params.merge(interval: '1h'))}", class: context.interval == '1h' ? 'active' : '' }
18
+ 1 Hour
19
+ %a.dropdown-item{ href: "?#{URI.encode_www_form(and_params.merge(interval: '3h'))}", class: context.interval == '3h' ? 'active' : '' }
20
+ 3 Hours
21
+ %a.dropdown-item{ href: "?#{URI.encode_www_form(and_params.merge(interval: '6h'))}", class: context.interval == '6h' ? 'active' : '' }
22
+ 6 Hours
23
+ .dropdown-divider
24
+ %a.dropdown-item{ href: "?#{URI.encode_www_form(and_params.merge(interval: '1d'))}", class: context.interval == '1d' ? 'active' : '' }
25
+ 1 Day
26
+ %a.dropdown-item{ href: "?#{URI.encode_www_form(and_params.merge(interval: '2d'))}", class: context.interval == '2d' ? 'active' : '' }
27
+ 2 Days
28
+ %a.dropdown-item{ href: "?#{URI.encode_www_form(and_params.merge(interval: '1w'))}", class: context.interval == '1w' ? 'active' : '' }
29
+ 1 Week
30
+
31
+ - if context.timespan
32
+ %li.nav-item.dropdown.no-arrow
33
+ %a#timespanDropdown.nav-link.dropdown-toggle{ href: '#', role: 'button', 'aria-haspopup': 'true', 'area-expanded': 'false', 'data-toggle': 'dropdown' }
34
+ %span.mr-2.d-none.d-lg-inline.text-gray-600
35
+ Timespan /
36
+ %strong
37
+ = context.timespan.split('/').first
38
+ .dropdown-menu.dropdown-menu-right.shadow.animated--grow-in{ 'aria-labelledby': 'timespanDropdown' }
39
+ %a.dropdown-item{ href: "?#{URI.encode_www_form(and_params.merge(timespan: '1h', interval: ''))}", class: context.timespan == '1h' ? 'active' : '' }
40
+ %i.fas.fa-chevron-right.fa-sm.fa-fw.mr-2.text-gray-400
41
+ 1 Hour
42
+ %a.dropdown-item{ href: "?#{URI.encode_www_form(and_params.merge(timespan: '1d', interval: ''))}", class: context.timespan == '1d' ? 'active' : '' }
43
+ %i.fas.fa-chevron-right.fa-sm.fa-fw.mr-2.text-gray-400
44
+ 1 Day
45
+ .dropdown-divider
46
+ %a.dropdown-item{ href: "?#{URI.encode_www_form(and_params.merge(timespan: '1w/d', interval: ''))}", class: context.timespan == '1w/d' ? 'active' : '' }
47
+ %i.fas.fa-chevron-right.fa-sm.fa-fw.mr-2.text-gray-400
48
+ 1 Week
49
+ %a.dropdown-item{ href: "?#{URI.encode_www_form(and_params.merge(timespan: '2w/d', interval: ''))}", class: context.timespan == '2w/d' ? 'active' : '' }
50
+ %i.fas.fa-chevron-right.fa-sm.fa-fw.mr-2.text-gray-400
51
+ 2 Weeks
52
+ %a.dropdown-item{ href: "?#{URI.encode_www_form(and_params.merge(timespan: '1M/d', interval: ''))}", class: context.timespan == '1M/d' ? 'active' : '' }
53
+ %i.fas.fa-chevron-right.fa-sm.fa-fw.mr-2.text-gray-400
54
+ 1 Month
55
+ .dropdown-divider
56
+ %a.dropdown-item{ href: "?#{URI.encode_www_form(and_params.merge(timespan: '3M/d', interval: ''))}", class: context.timespan == '3M/d' ? 'active' : '' }
57
+ %i.fas.fa-chevron-right.fa-sm.fa-fw.mr-2.text-gray-400
58
+ 3 Months
59
+ %a.dropdown-item{ href: "?#{URI.encode_www_form(and_params.merge(timespan: '6M/d', interval: ''))}", class: context.timespan == '6M/d' ? 'active' : '' }
60
+ %i.fas.fa-chevron-right.fa-sm.fa-fw.mr-2.text-gray-400
61
+ 6 Months
62
+ %a.dropdown-item{ href: "?#{URI.encode_www_form(and_params.merge(timespan: '1y/d', interval: ''))}", class: context.timespan == '1y/d' ? 'active' : '' }
63
+ %i.fas.fa-chevron-right.fa-sm.fa-fw.mr-2.text-gray-400
64
+ 1 Year
@@ -1,18 +1,3 @@
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
1
  %nav.navbar.navbar-expand.navbar-light.bg-white.topbar.mb-4.static-top.shadow
17
2
  / Sidebar Toggle
18
3
  %button#sidebarToggleTop.btn.btn-link.d-md-none.rounded-circle.mr-3
@@ -0,0 +1,32 @@
1
+ - group = entity.class.to_s.demodulize.underscore
2
+ %table.table.mb-0
3
+ %tbody
4
+ - if entity.users.count.positive?
5
+ - entity.users.each do |user|
6
+ %tr
7
+ %td
8
+ - if policy(user).read?
9
+ %a{ href: "#{settings.map_path}/users/#{user.id}" }
10
+ = user.username
11
+ - else
12
+ = user.username
13
+ %td.text-right
14
+ = delete_form_tag "#{base_path}/#{entity.display_id}/users/#{user.id}" do
15
+ %button.btn.btn-danger.btn-sm{ type: 'submit' } ×
16
+ - else
17
+ %tr
18
+ %td{ colspan: 2 } No Users Associated
19
+ %tr
20
+ %td{ colspan: 2 }
21
+ - users = user_options.select { |k, v| entity.users.map(&:id).include?(k) == false }
22
+ - if users && users.count.positive?
23
+ = new_form_tag "#{base_path}/#{entity.display_id}/users" do
24
+ .input-group
25
+ %select.form-control{ name: "#{group}[user_id]", id: 'user_id' }
26
+ %option{ value: '' } Select User
27
+ - users.each do |key, value|
28
+ %option{ value: key }= value
29
+ %span.input-group-append
30
+ %button.btn.btn-primary{ type: 'submit' } Add User
31
+ - else
32
+ No Users available to link
@@ -0,0 +1,23 @@
1
+ %link{ rel: 'stylesheet', href: 'https://cdnjs.cloudflare.com/ajax/libs/prism/1.20.0/themes/prism-okaidia.min.css' }
2
+
3
+ .row.mb-4
4
+ .col-2
5
+ .col-8
6
+ .card.card-default.border-left-dark.shadow.h-100
7
+ %h4.card-header Run on a folder
8
+ .card-body
9
+ %pre
10
+ %code.lang-shell
11
+ :preserve
12
+ docker run -d -e ELASTICSEARCH_HOSTS=192.168.1.200:9200 \
13
+ --volume=/var/log/nginx/:/usr/share/incoming/ \
14
+ hackerplanet/requestd-filebeat:latest
15
+ .card.card-default.border-left-dark.shadow.h-100
16
+ %h4.card-header Run on a single file
17
+ .card-body
18
+ %pre
19
+ %code.lang-shell
20
+ :preserve
21
+ docker run -d -e ELASTICSEARCH_HOSTS=elastic.hackerpla.net:9200 \
22
+ --volume=/var/log/nginx/access.log:/usr/share/incoming/access.log \
23
+ hackerplanet/requestd-filebeat:latest
@@ -1,7 +1,7 @@
1
1
  .row.mb-4
2
2
  .col-md-2
3
3
  .col-md-8
4
- .card.card-default
4
+ .card.card-default.shadow
5
5
  .card-body
6
6
  %p.description
7
7
  %label Name:
@@ -22,10 +22,10 @@
22
22
  .row
23
23
  .col-md-2
24
24
  .col-md-8
25
- .card.card-default
25
+ .card.card-default.shadow
26
26
  .card-body
27
27
  %h4.card-title Included Roles
28
- %table.table.table-striped
28
+ %table.table.table-striped.mb-0
29
29
  %tbody
30
30
  - if entity.descendants.count > 0
31
31
  - entity.descendants.each do |role|
@@ -1,7 +1,7 @@
1
1
  .row
2
2
  .col-md-2
3
3
  .col-md-8
4
- .card
4
+ .card.card-default.shadow
5
5
  .card-body
6
6
  = edit_form_tag "#{base_path}/#{entity.display_id}" do
7
7
  = haml :'roles/form', locals: { entity: entity }
@@ -4,7 +4,7 @@
4
4
  %table.table.table-striped.table-bordered.table-hover
5
5
  %thead.thead-dark
6
6
  %tr
7
- %th Name
7
+ %th= "Name#{sort_ui(:name)}"
8
8
  %th Parent
9
9
  %th
10
10
  %tbody
@@ -24,4 +24,4 @@
24
24
  %td.text-center{ colspan: 3 } No Roles
25
25
 
26
26
  - if list.count > 0
27
- =pagination(list, base_path)
27
+ = pagination(list, base_path)
data/views/roles/new.haml CHANGED
@@ -1,7 +1,7 @@
1
1
  .row
2
2
  .col-md-2
3
3
  .col-md-8
4
- .card.card-default
4
+ .card.card-default.shadow
5
5
  .card-body
6
6
  = new_form_tag base_path do
7
7
  = haml :'roles/form', locals: { entity: entity }
@@ -1,7 +1,7 @@
1
1
  .row
2
2
  .col-md-2
3
3
  .col-md-8
4
- .card.card-default
4
+ .card.card-default.shadow
5
5
  .card-body
6
6
  %p.description
7
7
  %label User:
@@ -1,7 +1,7 @@
1
1
  .row
2
2
  .col-md-2
3
3
  .col-md-8
4
- .card.card-default
4
+ .card.card-default.shadow
5
5
  .card-body
6
6
  = edit_form_tag "#{base_path}/#{entity.display_id}" do
7
7
  = haml :'user_login_traits/form', locals: { entity: entity }
@@ -1,30 +1,28 @@
1
1
  .row
2
2
  .col-md-12
3
- .card.card-default
4
- .card-body
5
- = haml :'partials/search'
6
- %table.table.table-striped
7
- %thead.thead-dark
8
- %tr
9
- %th User
10
- %th IP Address
11
- %th Device
12
- %th Platform
13
- %th Browser
14
- %th Last Seen
15
- %tbody
16
- - if list.count.positive?
17
- - list.all.each do |entity|
18
- %tr
19
- %td= entity.user&.email || 'Unknown'
20
- %td
21
- %a{ href: "#{base_path}/#{entity.display_id}" }= entity.ip_address || 'Unknown'
22
- %td= entity.device || 'Unknown'
23
- %td= entity.platform || 'Unknown'
24
- %td= entity.browser || 'Unknown'
25
- %td= entity.updated_at
26
- - else
3
+ = haml :'partials/search'
4
+ %table.table.table-striped.table-bordered.table-hover
5
+ %thead.thead-dark
6
+ %tr
7
+ %th= "User #{sort_ui(:user_id)}"
8
+ %th= "IP Address #{sort_ui(:ip_address)}"
9
+ %th= "Device #{sort_ui(:device)}"
10
+ %th= "Platform #{sort_ui(:platform)}"
11
+ %th= "Browser #{sort_ui(:browser)}"
12
+ %th= "Last Seen #{sort_ui(:updated_at)}"
13
+ %tbody
14
+ - if list.count.positive?
15
+ - list.all.each do |entity|
27
16
  %tr
28
- %td.text-center{ colspan: 6 } No records
17
+ %td= entity.user&.email || 'Unknown'
18
+ %td
19
+ %a{ href: "#{base_path}/#{entity.display_id}" }= entity.ip_address || 'Unknown'
20
+ %td= entity.device || 'Unknown'
21
+ %td= entity.platform || 'Unknown'
22
+ %td= entity.browser || 'Unknown'
23
+ %td= entity.updated_at
24
+ - else
25
+ %tr
26
+ %td.text-center{ colspan: 6 } No records
29
27
 
30
28
  =pagination(list, base_path)
@@ -1,7 +1,7 @@
1
1
  .row
2
2
  .col-md-2
3
3
  .col-md-8
4
- .card.card-default
4
+ .card.card-default.shadow
5
5
  .card-body
6
6
  = new_form_tag base_path do
7
7
  = haml :'user_login_traits/form', locals: { entity: entity }
@@ -1,19 +1,19 @@
1
1
  .row.mb-4
2
2
  .col-md-2
3
3
  .col-md-8
4
- .card.card-default
4
+ .card.card-default.shadow
5
5
  .card-body
6
6
  .author
7
7
  %img.float-right.img-thumbnail{ src: entity.gravatar }
8
- %h4= entity.email
8
+ %h4= entity.display_name
9
9
 
10
10
  %hr
11
11
  %p.description
12
12
  %label Name:
13
- = entity.name
13
+ = entity.name || '(None)'
14
14
  %p.description
15
15
  %label Surname:
16
- = entity.surname
16
+ = entity.surname || '(None)'
17
17
  %p.description
18
18
  %label Roles:
19
19
  = entity.roles_dataset.map(:name).map(&:titlecase).join(', ')
@@ -35,7 +35,7 @@
35
35
  .row.mb-4
36
36
  .col-md-2
37
37
  .col-md-8
38
- .card.card-default
38
+ .card.card-default.shadow
39
39
  .card-body
40
40
  %h4.card-title Change Password
41
41
  = edit_form_tag("#{base_path}/#{entity.display_id}/identity") do