adminka 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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%'}