ditty 0.8.0 → 0.10.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (169) hide show
  1. checksums.yaml +4 -4
  2. data/.env.test +2 -0
  3. data/.gitignore +3 -0
  4. data/.pryrc +2 -0
  5. data/.rubocop.yml +23 -4
  6. data/.travis.yml +4 -8
  7. data/CNAME +1 -0
  8. data/Dockerfile +18 -0
  9. data/Gemfile.ci +0 -17
  10. data/Rakefile +2 -2
  11. data/_config.yml +1 -0
  12. data/config.ru +4 -4
  13. data/ditty.gemspec +28 -18
  14. data/docs/CNAME +1 -0
  15. data/docs/_config.yml +1 -0
  16. data/docs/index.md +34 -0
  17. data/exe/ditty +2 -0
  18. data/lib/ditty/cli.rb +41 -5
  19. data/lib/ditty/components/{app.rb → ditty.rb} +18 -16
  20. data/lib/ditty/controllers/{application.rb → application_controller.rb} +63 -34
  21. data/lib/ditty/controllers/{audit_logs.rb → audit_logs_controller.rb} +4 -2
  22. data/lib/ditty/controllers/{auth.rb → auth_controller.rb} +22 -18
  23. data/lib/ditty/controllers/{component.rb → component_controller.rb} +23 -20
  24. data/lib/ditty/controllers/{main.rb → main_controller.rb} +6 -2
  25. data/lib/ditty/controllers/roles_controller.rb +23 -0
  26. data/lib/ditty/controllers/user_login_traits_controller.rb +46 -0
  27. data/lib/ditty/controllers/{users.rb → users_controller.rb} +13 -11
  28. data/lib/ditty/db.rb +7 -5
  29. data/lib/ditty/emails/base.rb +37 -32
  30. data/lib/ditty/generators/crud_generator.rb +114 -0
  31. data/lib/ditty/generators/migration_generator.rb +26 -0
  32. data/lib/ditty/generators/project_generator.rb +52 -0
  33. data/lib/ditty/helpers/component.rb +2 -1
  34. data/lib/ditty/helpers/pundit.rb +24 -8
  35. data/lib/ditty/helpers/response.rb +15 -13
  36. data/lib/ditty/helpers/views.rb +28 -6
  37. data/lib/ditty/listener.rb +6 -4
  38. data/lib/ditty/memcached.rb +8 -0
  39. data/lib/ditty/middleware/accept_extension.rb +2 -2
  40. data/lib/ditty/middleware/error_catchall.rb +2 -2
  41. data/lib/ditty/models/base.rb +9 -0
  42. data/lib/ditty/models/identity.rb +11 -7
  43. data/lib/ditty/models/role.rb +1 -0
  44. data/lib/ditty/models/user.rb +23 -2
  45. data/lib/ditty/policies/role_policy.rb +1 -1
  46. data/lib/ditty/policies/user_login_trait_policy.rb +1 -1
  47. data/lib/ditty/policies/user_policy.rb +1 -1
  48. data/lib/ditty/services/authentication.rb +27 -16
  49. data/lib/ditty/services/email.rb +19 -15
  50. data/lib/ditty/services/logger.rb +26 -20
  51. data/lib/ditty/services/pagination_wrapper.rb +7 -5
  52. data/lib/ditty/services/settings.rb +7 -6
  53. data/lib/ditty/tasks/ditty.rake +19 -1
  54. data/lib/ditty/tasks/omniauth-ldap.rake +2 -2
  55. data/lib/ditty/templates/.gitignore +5 -0
  56. data/lib/ditty/templates/.rspec +2 -0
  57. data/lib/ditty/templates/.rubocop.yml +7 -0
  58. data/lib/ditty/templates/Rakefile +12 -0
  59. data/lib/ditty/templates/application.rb +12 -0
  60. data/lib/ditty/templates/config.ru +37 -0
  61. data/lib/ditty/templates/controller.rb.erb +64 -0
  62. data/lib/ditty/templates/env.example +4 -0
  63. data/lib/ditty/templates/lib/project.rb.erb +5 -0
  64. data/lib/ditty/templates/logs/.empty_directory +0 -0
  65. data/lib/ditty/templates/migration.rb.erb +7 -0
  66. data/lib/ditty/templates/model.rb.erb +26 -0
  67. data/lib/ditty/templates/pids/.empty_directory +0 -0
  68. data/lib/ditty/templates/policy.rb.erb +48 -0
  69. data/{public → lib/ditty/templates/public}/browserconfig.xml +0 -0
  70. data/lib/ditty/templates/public/css/sb-admin-2.min.css +10 -0
  71. data/lib/ditty/templates/public/css/styles.css +13 -0
  72. data/lib/ditty/templates/public/favicon.ico +0 -0
  73. data/{public → lib/ditty/templates/public}/images/apple-icon.png +0 -0
  74. data/{public → lib/ditty/templates/public}/images/favicon-16x16.png +0 -0
  75. data/{public → lib/ditty/templates/public}/images/favicon-32x32.png +0 -0
  76. data/{public → lib/ditty/templates/public}/images/launcher-icon-1x.png +0 -0
  77. data/{public → lib/ditty/templates/public}/images/launcher-icon-2x.png +0 -0
  78. data/{public → lib/ditty/templates/public}/images/launcher-icon-4x.png +0 -0
  79. data/{public → lib/ditty/templates/public}/images/mstile-150x150.png +0 -0
  80. data/{public → lib/ditty/templates/public}/images/safari-pinned-tab.svg +0 -0
  81. data/lib/ditty/templates/public/js/sb-admin-2.min.js +7 -0
  82. data/lib/ditty/templates/public/js/scripts.js +1 -0
  83. data/{public/manifest.json → lib/ditty/templates/public/manifest.json.erb} +2 -2
  84. data/lib/ditty/templates/settings.yml.erb +29 -0
  85. data/lib/ditty/templates/sidekiq.rb +18 -0
  86. data/lib/ditty/templates/sidekiq.yml +9 -0
  87. data/lib/ditty/templates/spec_helper.rb +43 -0
  88. data/lib/ditty/templates/type.rb.erb +21 -0
  89. data/lib/ditty/templates/views/display.haml.tt +20 -0
  90. data/lib/ditty/templates/views/edit.haml.tt +10 -0
  91. data/lib/ditty/templates/views/form.haml.tt +11 -0
  92. data/lib/ditty/templates/views/index.haml.tt +29 -0
  93. data/lib/ditty/templates/views/new.haml.tt +10 -0
  94. data/lib/ditty/version.rb +1 -1
  95. data/lib/ditty.rb +6 -4
  96. data/lib/rubocop/cop/ditty/call_services_directly.rb +2 -2
  97. data/migrate/20181209_add_user_login_traits.rb +4 -4
  98. data/migrate/20190220_add_parent_id_to_roles.rb +9 -0
  99. data/spec/ditty/api_spec.rb +51 -0
  100. data/spec/ditty/controllers/roles_spec.rb +67 -0
  101. data/spec/ditty/controllers/user_login_traits_spec.rb +72 -0
  102. data/spec/ditty/controllers/users_spec.rb +72 -0
  103. data/spec/ditty/emails/base_spec.rb +76 -0
  104. data/spec/ditty/emails/forgot_password_spec.rb +20 -0
  105. data/spec/ditty/helpers/component_spec.rb +85 -0
  106. data/spec/ditty/models/user_spec.rb +36 -0
  107. data/spec/ditty/services/email_spec.rb +36 -0
  108. data/spec/ditty/services/logger_spec.rb +68 -0
  109. data/spec/ditty/services/settings_spec.rb +63 -0
  110. data/spec/ditty_spec.rb +9 -0
  111. data/spec/factories.rb +46 -0
  112. data/spec/fixtures/logger.yml +17 -0
  113. data/spec/fixtures/section.yml +3 -0
  114. data/spec/fixtures/settings.yml +8 -0
  115. data/spec/spec_helper.rb +51 -0
  116. data/spec/support/api_shared_examples.rb +250 -0
  117. data/spec/support/crud_shared_examples.rb +145 -0
  118. data/views/403.haml +1 -1
  119. data/views/404.haml +2 -4
  120. data/views/500.haml +11 -0
  121. data/views/audit_logs/index.haml +32 -33
  122. data/views/auth/forgot_password.haml +32 -16
  123. data/views/auth/identity.haml +14 -13
  124. data/views/auth/ldap.haml +2 -2
  125. data/views/auth/login.haml +23 -17
  126. data/views/auth/register.haml +20 -18
  127. data/views/auth/register_identity.haml +27 -12
  128. data/views/auth/reset_password.haml +36 -19
  129. data/views/blank.haml +43 -0
  130. data/views/embedded.haml +17 -11
  131. data/views/index.haml +1 -1
  132. data/views/layout.haml +45 -30
  133. data/views/partials/actions.haml +15 -14
  134. data/views/partials/content_tag.haml +0 -0
  135. data/views/partials/delete_form.haml +1 -1
  136. data/views/partials/filter_control.haml +2 -2
  137. data/views/partials/footer.haml +6 -5
  138. data/views/partials/form_control.haml +19 -12
  139. data/views/partials/form_tag.haml +1 -1
  140. data/views/partials/navitems.haml +42 -0
  141. data/views/partials/notifications.haml +12 -8
  142. data/views/partials/pager.haml +44 -25
  143. data/views/partials/search.haml +15 -11
  144. data/views/partials/sidebar.haml +15 -37
  145. data/views/partials/sort_ui.haml +2 -0
  146. data/views/partials/topbar.haml +53 -0
  147. data/views/partials/user_associations.haml +32 -0
  148. data/views/quick_start.haml +23 -0
  149. data/views/roles/display.haml +27 -6
  150. data/views/roles/edit.haml +3 -3
  151. data/views/roles/form.haml +1 -0
  152. data/views/roles/index.haml +23 -16
  153. data/views/roles/new.haml +2 -2
  154. data/views/user_login_traits/display.haml +4 -4
  155. data/views/user_login_traits/edit.haml +3 -3
  156. data/views/user_login_traits/index.haml +23 -25
  157. data/views/user_login_traits/new.haml +2 -2
  158. data/views/users/display.haml +14 -15
  159. data/views/users/edit.haml +3 -3
  160. data/views/users/form.haml +0 -0
  161. data/views/users/index.haml +31 -24
  162. data/views/users/login_traits.haml +6 -8
  163. data/views/users/new.haml +2 -2
  164. data/views/users/profile.haml +15 -15
  165. data/views/users/user.haml +1 -1
  166. metadata +271 -63
  167. data/lib/ditty/controllers/roles.rb +0 -13
  168. data/lib/ditty/controllers/user_login_traits.rb +0 -18
  169. data/views/partials/navbar.haml +0 -22
@@ -1,16 +1,32 @@
1
- .row
2
- .col-md-4
3
- .col-md-4
4
- .panel.panel-default
5
- .panel-body
6
- %p.text-center
7
- Enter your email address and we will send you a link to reset your password if you've registered on the system.
8
- = form_tag("#{settings.map_path}/auth/forgot-password") do
9
- .form-group
10
- .col-sm-12
11
- %input.form-control{ name: 'email', type: 'text', placeholder: 'Enter your email address' }
12
- .row.text-right
13
- .col-md-12
14
- %button.btn.btn-primary.btn-block{ type: 'submit' }
15
- Email password reset link
16
- .col-md-4
1
+ .container
2
+ / Outer Row
3
+ .row.justify-content-center
4
+ .col-xl-10.col-lg-12.col-md-9
5
+ .card.card-default.o-hidden.border-0.shadow-lg.my-5
6
+ .card-body.p-0
7
+ / Nested Row within Card Body
8
+ .row
9
+ .col-lg-6.d-none.d-lg-block.bg-password-image
10
+ .col-lg-6
11
+ .p-5
12
+ .text-center
13
+ %h1.h4.text-gray-900.mb-2
14
+ Forgot Your Password?
15
+ %p.mb-4
16
+ We get it, stuff happens. Just enter your email address below and we'll send you a link to reset your password!
17
+ .small
18
+ = haml :'partials/notifications'
19
+ = form_tag("#{settings.map_path}/auth/forgot-password", attributes: { class: 'user' }) do
20
+ .form-group
21
+ %input.form-control.form-control-user{ name: 'email', type: 'email', placeholder: 'Enter Email Address...' }
22
+ %button.btn.btn-primary.btn-user.btn-block{ type: 'submit' }
23
+ Reset Password
24
+ %hr
25
+ - if policy(::Ditty::User).register?
26
+ .text-center
27
+ %a.small{ href: "#{settings.map_path}/auth/register" } Create an Account!
28
+ .text-center
29
+ %a.small{ href: "#{settings.map_path}/auth/login" } Already have an account? Login!
30
+
31
+ .row.justify-content-center
32
+ .col-xl-10.col-lg-12.col-md-9
@@ -1,15 +1,16 @@
1
- = form_tag("#{settings.map_path}/auth/identity/callback", attributes: { class: '' }) do
1
+ = form_tag("#{settings.map_path}/auth/identity/callback", attributes: { class: 'user' }) do
2
2
  .form-group
3
- %label.control-label Email
4
- %input.form-control.border-input{ name: 'username', tabindex: '1' }
3
+ %input.form-control.form-control-user{ name: 'username', type: 'email', 'aria-describedby': 'emailHelp', placeholder: 'Enter Email Address...' }
5
4
  .form-group
6
- %label.control-label{ style: 'display: block' }
7
- Password
8
- %a{ href: "#{settings.map_path}/auth/forgot-password", style: 'float: right', tabindex: '5' }
9
- Forgot?
10
- %input.form-control.border-input{ name: 'password', type: 'password', tabindex: '2' }
11
- %button.btn.btn-primary{ type: 'submit', tabindex: '3' } Log In
12
- - if policy(::Ditty::User).register?
13
- .pull-right
14
- No account yet?
15
- %a.btn.btn-default{ href: "#{settings.map_path}/auth/register", tabindex: '4' } Register
5
+ %input.form-control.form-control-user{ name: 'password', type: 'password', placeholder: 'Password' }
6
+ / .form-group
7
+ / .custom-control.custom-checkbox.small
8
+ / <input type="checkbox" class="custom-control-input" id="customCheck">
9
+ / <label class="custom-control-label" for="customCheck">Remember Me</label>
10
+ %button.btn.btn-primary.btn-user.btn-block{ type: 'submit' } Log In
11
+ %hr
12
+ .text-center
13
+ %a.small{ href: "#{settings.map_path}/auth/forgot-password" } Forgot Password?
14
+ - if policy(::Ditty::User).register?
15
+ .text-center
16
+ %a.small{ href: "#{settings.map_path}/auth/register" } Create an Account!
data/views/auth/ldap.haml CHANGED
@@ -1,8 +1,8 @@
1
1
  .row
2
2
  .col-sm-2
3
3
  .col-sm-8
4
- .panel.panel-default
5
- .panel-body
4
+ .card.card-default.shadow
5
+ .card-body
6
6
  = form_tag("#{settings.map_path}/auth/ldap/callback", attributes: { class: '' }) do
7
7
  .form-group
8
8
  %label.control-label Username
@@ -1,18 +1,24 @@
1
- .row
2
- .col-sm-2
3
- .col-sm-8
4
- .panel.panel-default
5
- .panel-body
6
- - if Ditty::Services::Authentication.provides? 'identity'
7
- = haml :'auth/identity'
1
+ .container
2
+ / Outer Row
3
+ .row.justify-content-center
4
+ .col-xl-10.col-lg-12.col-md-9
5
+ .card.card-default.o-hidden.border-0.shadow-lg.my-5
6
+ .card-body.p-0
7
+ / Nested Row within Card Body
8
8
  .row
9
- .col-sm-12= "&nbsp;"
10
- .row
11
- .col-sm-8.col-sm-push-2
12
- - Ditty::Services::Authentication.providers.each do |name|
13
- - provider = Ditty::Services::Authentication[name]
14
- - next if provider[:login_prompt].nil?
15
- %a.btn.btn-block.btn-default{ href: "#{settings.map_path}/auth/#{name}" }
16
- %i.fa{ class: "fa-#{provider[:icon] || 'key'}"}
17
- = provider[:login_prompt]
18
- .col-sm-2
9
+ .col-lg-6.d-none.d-lg-block.bg-login-image
10
+ .col-lg-6
11
+ .p-5
12
+ .text-center
13
+ %h1.h4.text-gray-900.mb-4 Welcome Back!
14
+ .small
15
+ = haml :'partials/notifications'
16
+ - ::Ditty::Services::Authentication.providers.each do |name|
17
+ - provider = ::Ditty::Services::Authentication[name]
18
+ - next if provider[:login_prompt].nil?
19
+ %p
20
+ %a.btn.btn-block.btn-secondary{ href: "#{settings.map_path}/auth/#{name}" }
21
+ %i.fab.fw{ class: "fa-#{provider[:icon] || 'key'}"}
22
+ = provider[:login_prompt]
23
+ - if ::Ditty::Services::Authentication.provides? 'identity'
24
+ = haml :'auth/identity'
@@ -1,19 +1,21 @@
1
- / TODO: How can we detect a google registration? Extra parameter to the callback? Or a custom callback page?
2
- .row
3
- .col-md-2
4
- .col-md-8
5
- .panel.panel-default
6
- .panel-body
7
- - if Ditty::Services::Authentication.provides? 'identity'
8
- = haml :'auth/register_identity', locals: { identity: identity }
9
- .row
10
- .col-sm-12= "&nbsp;"
11
- .row
12
- .col-sm-8.col-sm-push-2
13
- - Ditty::Services::Authentication.providers.each do |name|
14
- - provider = Ditty::Services::Authentication[name]
1
+ .container
2
+ .card.card-default.o-hidden.border-0.shadow-lg.my-5
3
+ .card-body.p-0
4
+ / Nested Row within Card Body
5
+ .row
6
+ .col-lg-5.d-none.d-lg-block.bg-register-image
7
+ .col-lg-7
8
+ .p-5
9
+ .text-center
10
+ %h1.h4.text-gray-900.mb-4 Create an Account!
11
+ .small
12
+ = haml :'partials/notifications'
13
+ - ::Ditty::Services::Authentication.providers.each do |name|
14
+ - provider = ::Ditty::Services::Authentication[name]
15
15
  - next if provider[:register_prompt].nil?
16
- %a.btn.btn-block.btn-default{ href: "#{settings.map_path}/auth/#{name}" }
17
- %i.fa{ class: "fa-#{provider[:icon] || 'key'}"}
18
- = provider[:register_prompt]
19
- .col-md-2
16
+ %p
17
+ %a.btn.btn-user.btn-block{ href: "#{settings.map_path}/auth/#{name}", class: "btn-#{provider[:icon] || 'key'}" }
18
+ %i.fab.fa-fw{ class: "fa-#{provider[:icon] || 'key'}"}
19
+ = provider[:register_prompt]
20
+ - if ::Ditty::Services::Authentication.provides? 'identity'
21
+ = haml :'auth/register_identity', locals: { identity: identity }
@@ -1,14 +1,29 @@
1
- = form_tag("#{settings.map_path}/auth/register/identity") do
2
- = form_control(:username, identity, label: 'Email', placeholder: 'your@email.com')
3
- = form_control(:password, identity, label: 'Password', type: :password)
4
- = form_control(:password_confirmation, identity, label: 'Confirm Password', type: :password)
1
+ - if identity.errors[:password] && identity.errors[:password].include?('is not strong enough')
2
+ .alert.alert-warning
3
+ %p Make sure your password is at least 8 characters long, and including the following
4
+ %ul
5
+ %li Upper- and lowercase letters
6
+ %li Numbers
7
+ %li Special Characters
5
8
 
6
- - if identity.errors[:password] && identity.errors[:password].include?('is not strong enough')
7
- .alert.alert-warning
8
- %p Make sure your password is at least 8 characters long, and including the following
9
- %ul
10
- %li Upper- and lowercase letters
11
- %li Numbers
12
- %li Special Characters
9
+ = form_tag("#{settings.map_path}/auth/register/identity", attributes: { class: 'user' }) do
10
+ .form-group
11
+ %input.form-control.form-control-user{ name: 'identity[username]', type: 'email', placeholder: 'Email Address', class: identity.errors[:username] ? 'is-invalid' : 'is-valid' }
12
+ - if identity.errors[:username]
13
+ .invalid-feedback= identity.errors[:username].join(', ')
14
+ .form-group.row
15
+ .col-sm-6.mb-3.mb-sm-0
16
+ %input.form-control.form-control-user{ name: 'identity[password]', type: 'password', placeholder: 'Password', class: identity.errors[:password] ? 'is-invalid' : 'is-valid' }
17
+ - if identity.errors[:password]
18
+ .invalid-feedback= identity.errors[:password].join(', ')
19
+ .col-sm-6
20
+ %input.form-control.form-control-user{ name: 'identity[password_confirmation]', type: 'password', placeholder: 'Repeat Password', class: identity.errors[:password_confirmation] ? 'is-invalid' : 'is-valid' }
21
+ - if identity.errors[:password_confirmation]
22
+ .invalid-feedback= identity.errors[:password_confirmation].join(', ')
13
23
 
14
- %button.btn.btn-primary{ type: 'submit' } Register
24
+ %button.btn.btn-primary.btn-user.btn-block{ type: 'submit' } Register
25
+ %hr
26
+ .text-center
27
+ %a.small{ href: "#{settings.map_path}/auth/forgot-password" } Forgot Password?
28
+ .text-center
29
+ %a.small{ href: "#{settings.map_path}/auth/login" } Already have an account? Login!
@@ -1,19 +1,36 @@
1
- .row
2
- .col-md-2
3
- .col-md-8
4
- .panel.panel-default
5
- .panel-body
6
- = edit_form_tag("#{settings.map_path}/auth/reset-password") do
7
- %input{ name: 'token', value: params[:token], type: 'hidden' }
8
- - if identity.errors[:password] && identity.errors[:password].include?('is not strong enough')
9
- .alert.alert-warning
10
- %p Make sure your password is at least 8 characters long, and including the following
11
- %ul
12
- %li Upper- and lowercase letters
13
- %li Numbers
14
- %li Special Characters
15
- = form_control(:password, identity, type: 'password', placeholder: 'Your password', group: 'identity')
16
- = form_control(:password_confirmation, identity, type: 'password', label: 'Confirm Password', placeholder: 'Confirm your password', group: 'identity')
17
- %button.btn.btn-primary{ type: 'submit' }
18
- Reset Password
19
- .col-md-2
1
+ .container
2
+ / Outer Row
3
+ .row.justify-content-center
4
+ .col-xl-10.col-lg-12.col-md-9
5
+ .card.card-default.o-hidden.border-0.shadow-lg.my-5
6
+ .card-body.p-0
7
+ / Nested Row within Card Body
8
+ .row
9
+ .col-lg-6.d-none.d-lg-block.bg-password-image
10
+ .col-lg-6
11
+ .p-5
12
+ .text-center
13
+ %h1.h4.text-gray-900.mb-2
14
+ Reset your Password
15
+ = edit_form_tag("#{settings.map_path}/auth/reset-password") do
16
+ %input{ name: 'token', value: params[:token], type: 'hidden' }
17
+ - if identity.errors[:password] && identity.errors[:password].include?('is not strong enough')
18
+ .alert.alert-warning
19
+ %p Make sure your password is at least 8 characters long, and including the following
20
+ %ul
21
+ %li Upper- and lowercase letters
22
+ %li Numbers
23
+ %li Special Characters
24
+ = form_control(:password, identity, type: 'password', placeholder: 'Your password', group: 'identity')
25
+ = form_control(:password_confirmation, identity, type: 'password', label: 'Confirm Password', placeholder: 'Confirm your password', group: 'identity')
26
+ %button.btn.btn-primary{ type: 'submit' }
27
+ Reset Password
28
+ %hr
29
+ - if policy(::Ditty::User).register?
30
+ .text-center
31
+ %a.small{ href: "#{settings.map_path}/auth/register" } Create an Account!
32
+ .text-center
33
+ %a.small{ href: "#{settings.map_path}/auth/login" } Already have an account? Login!
34
+
35
+ .row.justify-content-center
36
+ .col-xl-10.col-lg-12.col-md-9
data/views/blank.haml ADDED
@@ -0,0 +1,43 @@
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
+ = Rack::Csrf.csrf_metatag(env)
9
+ %link{ rel: 'manifest', href: '/manifest.json' }
10
+ %link{ rel: 'icon', type: 'image/png', sizes: '32x32', href: '/images/favicon-32x32.png' }
11
+ %link{ rel: 'icon', type: 'image/png', sizes: '16x16', href: '/images/favicon-16x16.png' }
12
+ %link{ rel: 'apple-touch-icon', sizes: '76x76', href: '/images/apple-icon.png' }
13
+ %link{ rel: 'mask-icon', href: '/safari-pinned-tab.svg', color: '#5bbad5' }
14
+
15
+ %title
16
+ = config('ditty.title', 'Ditty')
17
+ - if defined? title
18
+ = "- #{title}"
19
+
20
+ %meta{ name: 'description', content: '' }
21
+ %meta{ name: 'author', content: '' }
22
+
23
+ / Le styles
24
+ %link{ rel: 'stylesheet', href: '/css/sb-admin-2.min.css', media: 'screen' }
25
+ %link{ rel: 'stylesheet', href: '/css/styles.css', media: 'screen' }
26
+ %link{ rel: 'stylesheet', href: 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.8.2/css/all.min.css', media: 'screen' }
27
+ %body.bg-gradient-primary
28
+ = yield
29
+
30
+ / Placed at the end of the document so the pages load faster
31
+ %script{ type: 'text/javascript', src: 'https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js' }
32
+ %script{ type: 'text/javascript', src: 'https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/js/bootstrap.min.js' }
33
+ %script{ type: 'text/javascript', src: 'https://cdnjs.cloudflare.com/ajax/libs/jquery-easing/1.4.1/jquery.easing.min.js' }
34
+ / %script{ type: 'text/javascript', src: 'https://cdnjs.cloudflare.com/ajax/libs/react/16.8.6/umd/react.production.min.js' }
35
+ %script{ type: 'text/javascript', src: 'https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.min.js' }
36
+ %script{ type: 'text/javascript', src: 'https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.7/js/select2.min.js' }
37
+ %script{ type: 'text/javascript', src: '/js/sb-admin-2.min.js' }
38
+ %script{ type: 'text/javascript', src: '/js/scripts.js' }
39
+ :javascript
40
+ $(function() {
41
+ $('.select2').select2();
42
+ });
43
+
data/views/embedded.haml CHANGED
@@ -5,6 +5,7 @@
5
5
  %meta{ 'http-equiv' => 'X-UA-Compatible', 'content' => 'IE=edge,chrome=1' }
6
6
  %meta{ name: 'viewport', content: 'width=device-width, initial-scale=1' }
7
7
  %meta{ name: 'theme-color', content: '#ffffff' }
8
+ = Rack::Csrf.csrf_metatag(env)
8
9
  %link{ rel: 'manifest', href: '/manifest.json' }
9
10
  %link{ rel: 'icon', type: 'image/png', sizes: '32x32', href: '#{request.base_url}/images/favicon-32x32.png' }
10
11
  %link{ rel: 'icon', type: 'image/png', sizes: '16x16', href: '#{request.base_url}/images/favicon-16x16.png' }
@@ -20,14 +21,9 @@
20
21
  %meta{ name: 'author', content: '' }
21
22
 
22
23
  / 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' }
24
+ %link{ rel: 'stylesheet', href: '/css/sb-admin-2.min.css', media: 'screen' }
25
+ %link{ rel: 'stylesheet', href: '/css/styles.css', media: 'screen' }
26
+ %link{ rel: 'stylesheet', href: 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.8.2/css/all.min.css', media: 'screen' }
31
27
  %body
32
28
  .container-fluid
33
29
  .row
@@ -37,6 +33,16 @@
37
33
  = yield
38
34
 
39
35
  / 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' }
36
+ %script{ type: 'text/javascript', src: 'https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js' }
37
+ %script{ type: 'text/javascript', src: 'https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/js/bootstrap.min.js' }
38
+ %script{ type: 'text/javascript', src: 'https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js' }
39
+ %script{ type: 'text/javascript', src: 'https://cdnjs.cloudflare.com/ajax/libs/jquery-easing/1.4.1/jquery.easing.min.js' }
40
+ / %script{ type: 'text/javascript', src: 'https://cdnjs.cloudflare.com/ajax/libs/react/16.8.6/umd/react.production.min.js' }
41
+ %script{ type: 'text/javascript', src: 'https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.min.js' }
42
+ %script{ type: 'text/javascript', src: 'https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.7/js/select2.min.js' }
43
+ %script{ type: 'text/javascript', src: '/js/sb-admin-2.min.js' }
44
+ %script{ type: 'text/javascript', src: '/js/scripts.js' }
45
+ :javascript
46
+ $(function() {
47
+ $('.select2').select2();
48
+ });
data/views/index.haml CHANGED
@@ -1 +1 @@
1
- %h2 Hello! Ready to get this Ditty started?
1
+ %h1.h3.mb-4.text-gray-800 Home Page
data/views/layout.haml CHANGED
@@ -5,6 +5,7 @@
5
5
  %meta{ 'http-equiv' => 'X-UA-Compatible', 'content' => 'IE=edge,chrome=1' }
6
6
  %meta{ name: 'viewport', content: 'width=device-width, initial-scale=1' }
7
7
  %meta{ name: 'theme-color', content: '#ffffff' }
8
+ = Rack::Csrf.csrf_metatag(env)
8
9
  %link{ rel: 'manifest', href: '/manifest.json' }
9
10
  %link{ rel: 'icon', type: 'image/png', sizes: '32x32', href: '/images/favicon-32x32.png' }
10
11
  %link{ rel: 'icon', type: 'image/png', sizes: '16x16', href: '/images/favicon-16x16.png' }
@@ -12,7 +13,7 @@
12
13
  %link{ rel: 'mask-icon', href: '/safari-pinned-tab.svg', color: '#5bbad5' }
13
14
 
14
15
  %title
15
- Ditty
16
+ = config('ditty.title', 'Ditty')
16
17
  - if defined? title
17
18
  = "- #{title}"
18
19
 
@@ -20,43 +21,57 @@
20
21
  %meta{ name: 'author', content: '' }
21
22
 
22
23
  / 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://cdnjs.cloudflare.com/ajax/libs/metisMenu/2.5.2/metisMenu.min.css', media: 'screen' }
26
- %link{ rel: 'stylesheet', href: 'https://maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css', media: 'screen' }
27
- /[if lt IE 9] <script src="https://cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv.min.js"></script>
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
24
+ %link{ rel: 'stylesheet', href: '/css/sb-admin-2.min.css', media: 'screen' }
25
+ %link{ rel: 'stylesheet', href: '/css/styles.css', media: 'screen' }
26
+ %link{ rel: 'stylesheet', href: 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.8.2/css/all.min.css', media: 'screen' }
27
+ %body#page-top
28
+ / Logout Modal
29
+ #logoutModal.modal.fade{ tabindex: -1, role: 'dialog', 'aria-hidden': 'true' }
30
+ .modal-dialog{ role: 'document' }
31
+ .modal-content
32
+ .modal-header
33
+ %h5.modal-title Ready to Leave?
34
+ %button.close{ type: 'button', 'data-dismiss': 'modal', 'aria-label': 'Close' }
35
+ %span{ 'aria-hidden': 'true' } ×
36
+ .modal-body
37
+ Select "Logout" below if you are ready to end your current session.
38
+ .modal-footer
39
+ %button.btn.btn-secondary{ type: 'button', 'data-dismiss': 'modal' } Cancel
40
+ = delete_form_tag("#{settings.map_path}/auth") do
41
+ %button.btn.btn-primary{ type: 'submit' } Logout
42
+ / Page Wrapper
34
43
  #wrapper
35
- = haml :'partials/navbar', locals: { title: (defined?(title) ? title : 'Ditty') }
36
- #page-wrapper
37
- -if defined?(title) || defined?(actions)
38
- .row
39
- %h1.col-md-9= defined?(title) ? title : '&nbsp;'
40
- .col-md-3.text-right{ style: 'margin-top: 20px' }
41
- = haml :'partials/actions', locals: { actions: defined?(actions) ? actions : {} }
42
- -else
43
- %div{ style: 'padding-top: 20px' }
44
-
45
- .row
46
- .col-md-12
44
+ = haml :'partials/sidebar', locals: { title: (defined?(title) ? title : 'Ditty') }
45
+
46
+ #content-wrapper.d-flex.flex-column
47
+ #content
48
+ = haml :'partials/topbar'
49
+ .container-fluid
50
+ / TODO
51
+ / .row
52
+ / .col-md-12
47
53
  = haml :'partials/notifications'
48
54
 
49
- = yield
55
+ = yield
56
+
50
57
  = haml :'partials/footer'
51
58
 
59
+ / Scroll to Top Button
60
+ %a.scroll-to-top.rounded{ href: '#page-top' }
61
+ %i.fas.fa-angle-up
62
+
52
63
  / Placed at the end of the document so the pages load faster
53
- %script{ type: 'text/javascript', src: 'https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js' }
54
- %script{ type: 'text/javascript', src: 'https://cdnjs.cloudflare.com/ajax/libs/react/15.4.1/react.min.js' }
55
- %script{ type: 'text/javascript', src: 'https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.6.0/Chart.bundle.min.js' }
56
- %script{ type: 'text/javascript', src: 'https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/js/select2.min.js' }
64
+ %script{ type: 'text/javascript', src: 'https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js' }
65
+ %script{ type: 'text/javascript', src: 'https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/js/bootstrap.min.js' }
66
+ %script{ type: 'text/javascript', src: 'https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js' }
67
+ %script{ type: 'text/javascript', src: 'https://cdnjs.cloudflare.com/ajax/libs/jquery-easing/1.4.1/jquery.easing.min.js' }
68
+ / %script{ type: 'text/javascript', src: 'https://cdnjs.cloudflare.com/ajax/libs/react/16.8.6/umd/react.production.min.js' }
69
+ %script{ type: 'text/javascript', src: 'https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.min.js' }
70
+ %script{ type: 'text/javascript', src: 'https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.7/js/select2.min.js' }
71
+ %script{ type: 'text/javascript', src: '/js/sb-admin-2.min.js' }
72
+ %script{ type: 'text/javascript', src: '/js/scripts.js' }
57
73
  :javascript
58
74
  $(function() {
59
- $('.sidebar-nav').metisMenu();
60
75
  $('.select2').select2();
61
76
  });
62
77