adminka 0.1.0

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 (64) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +150 -0
  4. data/Rakefile +37 -0
  5. data/app/assets/config/adminka_manifest.js +2 -0
  6. data/app/assets/images/adminka/logo.png +0 -0
  7. data/app/assets/images/adminka/no-pic.jpg +0 -0
  8. data/app/assets/javascripts/adminka/application.js +28 -0
  9. data/app/assets/stylesheets/adminka/application.scss +21 -0
  10. data/app/controllers/adminka/admin_controller.rb +32 -0
  11. data/app/controllers/adminka/admins/registrations_controller.rb +61 -0
  12. data/app/controllers/adminka/admins/sessions_controller.rb +26 -0
  13. data/app/controllers/adminka/crud_controller.rb +60 -0
  14. data/app/helpers/adminka/application_helper.rb +10 -0
  15. data/app/jobs/adminka/application_job.rb +4 -0
  16. data/app/mailers/adminka/application_mailer.rb +6 -0
  17. data/app/models/adminka/admin.rb +14 -0
  18. data/app/models/adminka/application_record.rb +5 -0
  19. data/app/views/adminka/admin/index.html.haml +1 -0
  20. data/app/views/adminka/admins/confirmations/new.html.haml +10 -0
  21. data/app/views/adminka/admins/mailer/confirmation_instructions.html.haml +4 -0
  22. data/app/views/adminka/admins/mailer/password_change.html.haml +3 -0
  23. data/app/views/adminka/admins/mailer/reset_password_instructions.html.haml +6 -0
  24. data/app/views/adminka/admins/mailer/unlock_instructions.html.haml +5 -0
  25. data/app/views/adminka/admins/passwords/edit.html.haml +19 -0
  26. data/app/views/adminka/admins/passwords/new.html.haml +10 -0
  27. data/app/views/adminka/admins/registrations/edit.html.haml +44 -0
  28. data/app/views/adminka/admins/registrations/new.html.haml +29 -0
  29. data/app/views/adminka/admins/sessions/new.html.haml +17 -0
  30. data/app/views/adminka/admins/shared/_links.html.haml +19 -0
  31. data/app/views/adminka/admins/unlocks/new.html.haml +10 -0
  32. data/app/views/adminka/crud/edit.html.haml +17 -0
  33. data/app/views/adminka/crud/index.html.haml +36 -0
  34. data/app/views/adminka/crud/new.html.haml +17 -0
  35. data/app/views/adminka/crud/show.html.haml +18 -0
  36. data/app/views/adminka/form_fields/_check_box.html.haml +4 -0
  37. data/app/views/adminka/form_fields/_image.html.haml +6 -0
  38. data/app/views/adminka/form_fields/_radio.html.haml +11 -0
  39. data/app/views/adminka/form_fields/_select.html.haml +9 -0
  40. data/app/views/adminka/form_fields/_text.html.haml +4 -0
  41. data/app/views/adminka/form_fields/_textarea.html.haml +4 -0
  42. data/app/views/kaminari/bootstrap/_first_page.html.haml +2 -0
  43. data/app/views/kaminari/bootstrap/_gap.html.haml +2 -0
  44. data/app/views/kaminari/bootstrap/_last_page.html.haml +2 -0
  45. data/app/views/kaminari/bootstrap/_next_page.html.haml +2 -0
  46. data/app/views/kaminari/bootstrap/_page.html.haml +6 -0
  47. data/app/views/kaminari/bootstrap/_paginator.html.haml +11 -0
  48. data/app/views/kaminari/bootstrap/_prev_page.html.haml +2 -0
  49. data/app/views/layouts/adminka/admin.html.haml +57 -0
  50. data/app/views/layouts/adminka/auth.html.haml +28 -0
  51. data/config/initializers/devise.rb +276 -0
  52. data/config/locales/adminka.en.yml +14 -0
  53. data/config/locales/devise.en.yml +62 -0
  54. data/config/routes.rb +8 -0
  55. data/db/migrate/20161225073001_devise_create_adminka_admins.rb +45 -0
  56. data/lib/adminka.rb +11 -0
  57. data/lib/adminka/engine.rb +9 -0
  58. data/lib/adminka/staff.rb +11 -0
  59. data/lib/adminka/version.rb +3 -0
  60. data/lib/generators/adminka/controllers_generator.rb +12 -0
  61. data/lib/generators/adminka/locale_generator.rb +12 -0
  62. data/lib/generators/adminka/views_generator.rb +17 -0
  63. data/lib/tasks/adminka_tasks.rake +4 -0
  64. metadata +250 -0
@@ -0,0 +1,10 @@
1
+ module Adminka
2
+ module ApplicationHelper
3
+ include Adminka::Staff
4
+
5
+ def adminka
6
+ Adminka::Engine.routes.url_helpers
7
+ end
8
+
9
+ end
10
+ end
@@ -0,0 +1,4 @@
1
+ module Adminka
2
+ class ApplicationJob < ActiveJob::Base
3
+ end
4
+ end
@@ -0,0 +1,6 @@
1
+ module Adminka
2
+ class ApplicationMailer < ActionMailer::Base
3
+ default from: 'from@example.com'
4
+ layout 'mailer'
5
+ end
6
+ end
@@ -0,0 +1,14 @@
1
+ module Adminka
2
+ class Admin < ApplicationRecord
3
+ # Include default devise modules. Others available are:
4
+ # :confirmable, :lockable, :timeoutable and :omniauthable
5
+ devise :database_authenticatable, :registerable,
6
+ :rememberable, :trackable, :validatable
7
+
8
+ validates :first_name, :last_name, presence: true
9
+
10
+ def full_name
11
+ [first_name, last_name].join(' ')
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,5 @@
1
+ module Adminka
2
+ class ApplicationRecord < ActiveRecord::Base
3
+ self.abstract_class = true
4
+ end
5
+ end
@@ -0,0 +1,10 @@
1
+ %h2 Resend confirmation instructions
2
+ = form_for(resource, as: resource_name, url: confirmation_path(resource_name), html: { method: :post }) do |f|
3
+ = devise_error_messages!
4
+ .field
5
+ = f.label :email
6
+ %br/
7
+ = f.email_field :email, autofocus: true, value: (resource.pending_reconfirmation? ? resource.unconfirmed_email : resource.email)
8
+ .actions
9
+ = f.submit "Resend confirmation instructions"
10
+ = render "devise/shared/links"
@@ -0,0 +1,4 @@
1
+ %p
2
+ Welcome #{@email}!
3
+ %p You can confirm your account email through the link below:
4
+ %p= link_to 'Confirm my account', confirmation_url(@resource, confirmation_token: @token)
@@ -0,0 +1,3 @@
1
+ %p
2
+ Hello #{@resource.email}!
3
+ %p We're contacting you to notify you that your password has been changed.
@@ -0,0 +1,6 @@
1
+ %p
2
+ Hello #{@resource.email}!
3
+ %p Someone has requested a link to change your password. You can do this through the link below.
4
+ %p= link_to 'Change my password', edit_password_url(@resource, reset_password_token: @token)
5
+ %p If you didn't request this, please ignore this email.
6
+ %p Your password won't change until you access the link above and create a new one.
@@ -0,0 +1,5 @@
1
+ %p
2
+ Hello #{@resource.email}!
3
+ %p Your account has been locked due to an excessive number of unsuccessful sign in attempts.
4
+ %p Click the link below to unlock your account:
5
+ %p= link_to 'Unlock my account', unlock_url(@resource, unlock_token: @token)
@@ -0,0 +1,19 @@
1
+ %h2 Change your password
2
+ = form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :put }) do |f|
3
+ = devise_error_messages!
4
+ = f.hidden_field :reset_password_token
5
+ .field
6
+ = f.label :password, "New password"
7
+ %br/
8
+ - if @minimum_password_length
9
+ %em
10
+ (#{@minimum_password_length} characters minimum)
11
+ %br/
12
+ = f.password_field :password, autofocus: true, autocomplete: "off"
13
+ .field
14
+ = f.label :password_confirmation, "Confirm new password"
15
+ %br/
16
+ = f.password_field :password_confirmation, autocomplete: "off"
17
+ .actions
18
+ = f.submit "Change my password"
19
+ = render "devise/shared/links"
@@ -0,0 +1,10 @@
1
+ %h2 Forgot your password?
2
+ = form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :post }) do |f|
3
+ = devise_error_messages!
4
+ .field
5
+ = f.label :email
6
+ %br/
7
+ = f.email_field :email, autofocus: true
8
+ .actions
9
+ = f.submit "Send me reset password instructions"
10
+ = render "devise/shared/links"
@@ -0,0 +1,44 @@
1
+ %h2
2
+ Edit #{resource_name.to_s.humanize}
3
+ = form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f|
4
+ = devise_error_messages!
5
+ .field
6
+ = f.label :first_name
7
+ %br/
8
+ = f.text_field :first_name, autofocus: true
9
+ .field
10
+ = f.label :last_name
11
+ %br/
12
+ = f.text_field :last_name, autofocus: true
13
+ .field
14
+ = f.label :email
15
+ %br/
16
+ = f.email_field :email, autofocus: true
17
+ - if devise_mapping.confirmable? && resource.pending_reconfirmation?
18
+ %div
19
+ Currently waiting confirmation for: #{resource.unconfirmed_email}
20
+ .field
21
+ = f.label :password
22
+ %i (leave blank if you don't want to change it)
23
+ %br/
24
+ = f.password_field :password, autocomplete: "off"
25
+ - if @minimum_password_length
26
+ %br/
27
+ %em
28
+ = @minimum_password_length
29
+ characters minimum
30
+ .field
31
+ = f.label :password_confirmation
32
+ %br/
33
+ = f.password_field :password_confirmation, autocomplete: "off"
34
+ .field
35
+ = f.label :current_password
36
+ %i (we need your current password to confirm your changes)
37
+ %br/
38
+ = f.password_field :current_password, autocomplete: "off"
39
+ .actions
40
+ = f.submit "Update"
41
+ %h3 Cancel my account
42
+ %p
43
+ Unhappy? #{button_to "Cancel my account", registration_path(resource_name), data: { confirm: "Are you sure?" }, method: :delete}
44
+ = link_to "Back", :back
@@ -0,0 +1,29 @@
1
+ %h2 Sign up
2
+ = form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f|
3
+ = devise_error_messages!
4
+ .field
5
+ = f.label :first_name
6
+ %br/
7
+ = f.text_field :first_name, autofocus: true
8
+ .field
9
+ = f.label :last_name
10
+ %br/
11
+ = f.text_field :last_name, autofocus: true
12
+ .field
13
+ = f.label :email
14
+ %br/
15
+ = f.email_field :email, autofocus: true
16
+ .field
17
+ = f.label :password
18
+ - if @minimum_password_length
19
+ %em
20
+ (#{@minimum_password_length} characters minimum)
21
+ %br/
22
+ = f.password_field :password, autocomplete: "off"
23
+ .field
24
+ = f.label :password_confirmation
25
+ %br/
26
+ = f.password_field :password_confirmation, autocomplete: "off"
27
+ .actions
28
+ = f.submit "Sign up"
29
+ = render "devise/shared/links"
@@ -0,0 +1,17 @@
1
+ %h2 Log in
2
+ = form_for(resource, as: resource_name, url: session_path(resource_name)) do |f|
3
+ .field
4
+ = f.label :email
5
+ %br/
6
+ = f.email_field :email, autofocus: true
7
+ .field
8
+ = f.label :password
9
+ %br/
10
+ = f.password_field :password, autocomplete: "off"
11
+ - if devise_mapping.rememberable?
12
+ .field
13
+ = f.check_box :remember_me
14
+ = f.label :remember_me
15
+ .actions
16
+ = f.submit "Log in"
17
+ = render "devise/shared/links"
@@ -0,0 +1,19 @@
1
+ - if controller_name != 'sessions'
2
+ = link_to "Log in", new_session_path(resource_name)
3
+ %br/
4
+ - if devise_mapping.registerable? && controller_name != 'registrations'
5
+ = link_to "Sign up", new_registration_path(resource_name)
6
+ %br/
7
+ - if devise_mapping.recoverable? && controller_name != 'passwords' && controller_name != 'registrations'
8
+ = link_to "Forgot your password?", new_password_path(resource_name)
9
+ %br/
10
+ - if devise_mapping.confirmable? && controller_name != 'confirmations'
11
+ = link_to "Didn't receive confirmation instructions?", new_confirmation_path(resource_name)
12
+ %br/
13
+ - if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) && controller_name != 'unlocks'
14
+ = link_to "Didn't receive unlock instructions?", new_unlock_path(resource_name)
15
+ %br/
16
+ - if devise_mapping.omniauthable?
17
+ - resource_class.omniauth_providers.each do |provider|
18
+ = link_to "Sign in with #{OmniAuth::Utils.camelize(provider)}", omniauth_authorize_path(resource_name, provider)
19
+ %br/
@@ -0,0 +1,10 @@
1
+ %h2 Resend unlock instructions
2
+ = form_for(resource, as: resource_name, url: unlock_path(resource_name), html: { method: :post }) do |f|
3
+ = devise_error_messages!
4
+ .field
5
+ = f.label :email
6
+ %br/
7
+ = f.email_field :email, autofocus: true
8
+ .actions
9
+ = f.submit "Resend unlock instructions"
10
+ = render "devise/shared/links"
@@ -0,0 +1,17 @@
1
+ .panel-body
2
+ = link_to adminka.send("#{@model.to_s.pluralize.downcase}_path") do
3
+ %i{class: 'glyphicon glyphicon-arrow-left'}
4
+ Back
5
+
6
+ %ul
7
+ - @entity.errors.full_messages.each do |e|
8
+ %li{class: 'alert alert-danger'}
9
+ = e
10
+
11
+ = form_for @entity, html: {class: 'form form-vertical'} do |f|
12
+ - @config['attributes']['edit'].each do |attr|
13
+ = render partial: "adminka/form_fields/#{attr[1]['type']}", locals: {f: f, attr: attr}
14
+ .control-group
15
+ %label
16
+ .controls
17
+ = f.submit(class: 'btn btn-primary')
@@ -0,0 +1,36 @@
1
+ .col-lg-12
2
+ - if @config['search']
3
+ .col-lg-8
4
+ = search_form_for @q, class: 'form-inline' do |f|
5
+ = f.search_field @config['search'].join('_or_').concat('_cont').to_sym,
6
+ placeholder: 'Enter ' + @config['search'].join(' or ').gsub('_',' '), class: 'form-control', size: 30
7
+ = f.submit class: 'btn btn-success'
8
+ = link_to t('adminka.clear'), request.path, class: 'btn btn-default'
9
+ .pull-right
10
+ = link_to(t('adminka.add', item: @model), adminka.send("new_#{@model.to_s.downcase}_path"), class: 'btn btn-primary')
11
+
12
+ - if @entities.any?
13
+ %table.table
14
+ %thead
15
+ - @config['attributes']['list'].each do |attr|
16
+ %th= sort_link @q, attr.to_sym
17
+ %th= t('adminka.actions')
18
+ %tbody
19
+ - @entities.each do |entity|
20
+ %tr
21
+ - @config['attributes']['list'].each do |attr|
22
+ - if attr.include?('_id')
23
+ %td= entity.send(attr.sub('_id', '')).try(:send, @config['attributes']['edit'][attr]['attributes'][1])
24
+ - else
25
+ %td= entity.send(attr)
26
+ %td
27
+ = link_to(adminka.send('edit_'+entity.class.to_s.downcase+'_path', entity)) do
28
+ %i.glyphicon.glyphicon-pencil
29
+ = link_to(adminka.send(entity.class.to_s.downcase+'_path', entity)) do
30
+ %i.glyphicon.glyphicon-eye-open
31
+ = link_to(adminka.send(entity.class.to_s.downcase+'_path', entity), method: :delete,
32
+ data: {confirm: t('adminka.confirm')}) do
33
+ %i.glyphicon.glyphicon-remove
34
+
35
+ %div{align: 'center'}
36
+ = paginate @entities, theme: 'bootstrap'
@@ -0,0 +1,17 @@
1
+ .panel-body
2
+ = link_to adminka.send("#{@model.to_s.pluralize.downcase}_path") do
3
+ %i{class: 'glyphicon glyphicon-arrow-left'}
4
+ = t('adminka.back')
5
+
6
+ %ul
7
+ - @entity.errors.full_messages.each do |e|
8
+ %li{class: 'alert alert-danger'}
9
+ = e
10
+
11
+ = form_for @entity, html: {class: 'form form-vertical'} do |f|
12
+ - @config['attributes']['edit'].each do |attr|
13
+ = render partial: "adminka/form_fields/#{attr[1]['type']}", locals: {f: f, attr: attr}
14
+ .control-group
15
+ %label
16
+ .controls
17
+ = f.submit(class: 'btn btn-primary')
@@ -0,0 +1,18 @@
1
+ = link_to adminka.send("#{@model.to_s.pluralize.downcase}_path") do
2
+ %i{class: 'glyphicon glyphicon-arrow-left'}
3
+ = t('adminka.back')
4
+ %ul
5
+ - @config['attributes']['show'].each do |attr|
6
+ - if attr.include?('_id')
7
+ %li
8
+ %label #{attr.upcase}:
9
+ = @entity.send(attr.sub('_id', '')).try(:send, @config['attributes']['edit'][attr]['attributes'][1])
10
+ - else
11
+ %li
12
+ %label #{attr.upcase}:
13
+ - val = @entity.send(attr)
14
+ - if val.class.to_s.include?('Uploader') && !val.blank?
15
+ <br/>
16
+ = image_tag(@entity.send(attr).try(:url), width: '200px')
17
+ - else
18
+ = val
@@ -0,0 +1,4 @@
1
+ .control-group
2
+ = f.label attr[0].to_sym
3
+ .controls
4
+ = f.check_box attr[0].to_sym
@@ -0,0 +1,6 @@
1
+ .control-group
2
+ = f.label attr[0].to_sym
3
+ .controls
4
+ = f.file_field attr[0].to_sym, class: 'form-control', onchange: 'readURL(this)'
5
+
6
+ = image_tag @entity.send(attr[0]).url || 'adminka/no-pic.jpg', id: 'image_prev'
@@ -0,0 +1,11 @@
1
+ .control-group
2
+ = f.label attr[0].to_sym
3
+ .controls
4
+ - data = @config['attributes']['edit'][attr[0]]
5
+ - if data['value'].is_a? Hash
6
+ - data['value'].each do |v|
7
+ = v[0]
8
+ = f.radio_button attr[0].to_sym, v[1]
9
+ - else
10
+ = f.collection_radio_buttons attr[0].to_sym,
11
+ Object.const_get(data['value']).all, data['attributes'][0], data['attributes'][1]
@@ -0,0 +1,9 @@
1
+ .control-group
2
+ = f.label attr[0].to_sym
3
+ .controls
4
+ - data = @config['attributes']['edit'][attr[0]]
5
+ - if data['value'].is_a? Hash
6
+ = f.select attr[0].to_sym, data['value'], {include_blank: true}, {}, class: 'form-control'
7
+ - else
8
+ = f.collection_select attr[0].to_sym,
9
+ Object.const_get(data['value']).all, data['attributes'][0], data['attributes'][1], {}, class: 'form-control'
@@ -0,0 +1,4 @@
1
+ .control-group
2
+ = f.label attr[0].to_sym
3
+ .controls
4
+ = f.text_field attr[0].to_sym, class: 'form-control'
@@ -0,0 +1,4 @@
1
+ .control-group
2
+ = f.label attr[0].to_sym
3
+ .controls
4
+ = f.text_area attr[0].to_sym, class: 'form-control'
@@ -0,0 +1,2 @@
1
+ %li
2
+ = link_to_unless current_page.first?, raw(t 'views.pagination.first'), url, :remote => remote
@@ -0,0 +1,2 @@
1
+ %li.disabled
2
+ = content_tag :a, raw(t 'views.pagination.truncate')
@@ -0,0 +1,2 @@
1
+ %li
2
+ = link_to_unless current_page.last?, raw(t 'views.pagination.last'), url, {:remote => remote}
@@ -0,0 +1,2 @@
1
+ %li
2
+ = link_to_unless current_page.last?, raw(t 'views.pagination.next'), url, :rel => 'next', :remote => remote
@@ -0,0 +1,6 @@
1
+ - if page.current?
2
+ %li.active
3
+ = content_tag :a, page, remote: remote, rel: (page.next? ? 'next' : (page.prev? ? 'prev' : nil))
4
+ - else
5
+ %li
6
+ = link_to page, url, remote: remote, rel: (page.next? ? 'next' : (page.prev? ? 'prev' : nil))
@@ -0,0 +1,11 @@
1
+ = paginator.render do
2
+ %ul.pagination
3
+ = first_page_tag unless current_page.first?
4
+ = prev_page_tag unless current_page.first?
5
+ - each_page do |page|
6
+ - if page.left_outer? || page.right_outer? || page.inside_window?
7
+ = page_tag page
8
+ - elsif !page.was_truncated?
9
+ = gap_tag
10
+ = next_page_tag unless current_page.last?
11
+ = last_page_tag unless current_page.last?
@@ -0,0 +1,2 @@
1
+ %li
2
+ = link_to_unless current_page.first?, raw(t 'views.pagination.previous'), url, :rel => 'prev', :remote => remote
@@ -0,0 +1,57 @@
1
+ !!!
2
+ %html
3
+ %head
4
+ %title Adminka
5
+ = stylesheet_link_tag "adminka/application", media: "all"
6
+ = javascript_include_tag "adminka/application"
7
+ = csrf_meta_tags
8
+ %body
9
+ #top-nav.navbar.navbar-inverse.navbar-static-top
10
+ .container
11
+ .navbar-header
12
+ %button.navbar-toggle{"data-target" => ".navbar-collapse", "data-toggle" => "collapse", :type => "button"}
13
+ %span.icon-toggle
14
+ = link_to adminka.root_path do
15
+ = image_tag 'adminka/logo.png'
16
+ .navbar-collapse.collapse
17
+ %ul.nav.navbar-nav.navbar-right
18
+ %li.dropdown
19
+ %a.dropdown-toggle{"data-toggle" => "dropdown", :href => "#", :role => "button"}
20
+ %i.glyphicon.glyphicon-user
21
+ #{current_admin.full_name}
22
+ %span.caret
23
+ %ul#g-account-menu.dropdown-menu{:role => "menu"}
24
+ %li
25
+ = link_to t('adminka.profile'), edit_admin_registration_path
26
+ %li
27
+ = link_to destroy_admin_session_path, method: :delete do
28
+ %i.glyphicon.glyphicon-lock
29
+ = t('adminka.logout')
30
+ .container
31
+ .row
32
+ .col-sm-3
33
+ %h3
34
+ %i.glyphicon.glyphicon-briefcase
35
+ = t('adminka.menu')
36
+ %hr/
37
+ %ul.nav.nav-stacked
38
+ - @menu.each do |menu|
39
+ %li
40
+ = link_to(adminka.send("#{menu[0].pluralize(2)}_path")) do
41
+ %i.glyphicon.glyphicon-pushpin
42
+ = menu[1]['title']
43
+ %hr/
44
+ .col-sm-9
45
+ %h3
46
+ %i.glyphicon.glyphicon-dashboard
47
+ = @model.to_s.pluralize
48
+ %hr/
49
+ .row
50
+ - if notice
51
+ .alert.alert-success
52
+ #{notice}
53
+ - if alert
54
+ .alert.alert-warning
55
+ = alert
56
+ = yield
57
+ %div{style: 'margin-top: 10%'}