pure-admin-rails 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/README.md +131 -0
  4. data/app/assets/images/menu-fade-left.png +0 -0
  5. data/app/assets/images/menu-fade-right.png +0 -0
  6. data/app/assets/images/pending.gif +0 -0
  7. data/app/assets/javascripts/pure_admin.js +6 -0
  8. data/app/assets/javascripts/pure_admin/dropdown.js +178 -0
  9. data/app/assets/javascripts/pure_admin/flash_messages.js +13 -0
  10. data/app/assets/javascripts/pure_admin/inputs.js +24 -0
  11. data/app/assets/javascripts/pure_admin/inputs/select.js +21 -0
  12. data/app/assets/javascripts/pure_admin/main_header.js +21 -0
  13. data/app/assets/javascripts/pure_admin/main_menu.js +108 -0
  14. data/app/assets/javascripts/pure_admin/modals.js +228 -0
  15. data/app/assets/javascripts/pure_admin/partial_refresh.js +92 -0
  16. data/app/assets/javascripts/pure_admin/portlets.js +139 -0
  17. data/app/assets/javascripts/pure_admin/tabs.js +14 -0
  18. data/app/assets/stylesheets/pure_admin.css.scss +23 -0
  19. data/app/assets/stylesheets/pure_admin/_dropdowns.scss +58 -0
  20. data/app/assets/stylesheets/pure_admin/_tabs.scss +76 -0
  21. data/app/assets/stylesheets/pure_admin/auth.css.scss +22 -0
  22. data/app/assets/stylesheets/pure_admin/breadcrumbs.css.scss +69 -0
  23. data/app/assets/stylesheets/pure_admin/buttons.css.scss +48 -0
  24. data/app/assets/stylesheets/pure_admin/details_panels.css.scss +99 -0
  25. data/app/assets/stylesheets/pure_admin/flash_messages.css.scss +97 -0
  26. data/app/assets/stylesheets/pure_admin/forms.css.scss +129 -0
  27. data/app/assets/stylesheets/pure_admin/inputs/select.css.scss +99 -0
  28. data/app/assets/stylesheets/pure_admin/jquery.tagsinput.css.scss +67 -0
  29. data/app/assets/stylesheets/pure_admin/main_menu.css.scss +146 -0
  30. data/app/assets/stylesheets/pure_admin/modals.css.scss +122 -0
  31. data/app/assets/stylesheets/pure_admin/pagination.css.scss +67 -0
  32. data/app/assets/stylesheets/pure_admin/portlets.css.scss +154 -0
  33. data/app/assets/stylesheets/pure_admin/scopes.css.scss +44 -0
  34. data/app/assets/stylesheets/pure_admin/shell.css.scss +222 -0
  35. data/app/assets/stylesheets/pure_admin/side_menu.css.scss +70 -0
  36. data/app/assets/stylesheets/pure_admin/table_filters.css.scss +90 -0
  37. data/app/assets/stylesheets/pure_admin/tables.css.scss +70 -0
  38. data/app/assets/stylesheets/pure_admin/tags.css.scss +37 -0
  39. data/app/assets/stylesheets/pure_admin/utilities.css.scss +24 -0
  40. data/app/assets/stylesheets/pure_admin/variables.css.scss +38 -0
  41. data/app/helpers/pure_admin/application_helper.rb +12 -0
  42. data/app/helpers/pure_admin/button_helper.rb +58 -0
  43. data/app/helpers/pure_admin/details_panel_helper.rb +121 -0
  44. data/app/helpers/pure_admin/dropdown_helper.rb +40 -0
  45. data/app/helpers/pure_admin/menu_helper.rb +120 -0
  46. data/app/helpers/pure_admin/portlet_helper.rb +75 -0
  47. data/app/helpers/pure_admin/table_filters_helper.rb +158 -0
  48. data/app/inputs/addon_input.rb +17 -0
  49. data/app/inputs/collection_select_input.rb +17 -0
  50. data/app/inputs/email_input.rb +5 -0
  51. data/app/inputs/tel_input.rb +5 -0
  52. data/lib/generators/pure_admin/layout/USAGE +10 -0
  53. data/lib/generators/pure_admin/layout/layout_generator.rb +8 -0
  54. data/lib/generators/pure_admin/layout/templates/admin.css.scss +8 -0
  55. data/lib/generators/pure_admin/layout/templates/admin.html.erb +105 -0
  56. data/lib/generators/pure_admin/scaffold/USAGE +11 -0
  57. data/lib/generators/pure_admin/scaffold/scaffold_generator.rb +66 -0
  58. data/lib/generators/pure_admin/scaffold/templates/_form.html.erb +12 -0
  59. data/lib/generators/pure_admin/scaffold/templates/_show.html.erb +11 -0
  60. data/lib/generators/pure_admin/scaffold/templates/_table.html.erb +21 -0
  61. data/lib/generators/pure_admin/scaffold/templates/models_controller.rb +69 -0
  62. data/lib/generators/pure_admin/simple_form/USAGE +8 -0
  63. data/lib/generators/pure_admin/simple_form/simple_form_generator.rb +7 -0
  64. data/lib/pure-admin-rails.rb +8 -0
  65. data/lib/pure-admin-rails/version.rb +5 -0
  66. metadata +261 -0
@@ -0,0 +1,40 @@
1
+ ##
2
+ # Helper methods for dropdown functionality.
3
+ #
4
+ # The recommended way of using this helper is
5
+ #
6
+ # dropdown 'Tools', class: ''do
7
+ # dropdown_item :name, 'url', item_html: { class: '' }
8
+ # end
9
+ #
10
+ # @note this helper depends {PureAdmin::MenuHelper}
11
+ module PureAdmin::DropdownHelper
12
+ ##
13
+ # Renders a dropdown to the view.
14
+ # @param name (String) the name to display on the main dropdown link.
15
+ # @param options (Hash) all options that can be passed to the menu_helper as menu_html are
16
+ # respected here.
17
+ # @yield The contents for the dropdown
18
+ def dropdown(name, options = {}, &block)
19
+ opts = {}
20
+ opts[:menu_html] = options
21
+ opts[:menu_html][:class] = merge_html_classes('dropdown pure-menu-horizontal', opts[:class])
22
+
23
+ content = capture(&block)
24
+ content = content_tag(:ul, content, class: 'pure-menu-children')
25
+ content = content_tag(:li, link_to(name, '', class: 'pure-menu-link') + content,
26
+ class: 'pure-menu-item pure-menu-has-children')
27
+
28
+ menu(opts) { content }
29
+ end
30
+
31
+ ##
32
+ # Renders a dropdown item to the view.
33
+ # @param name (String) the name to pass to PureAdmin::MenuHelper.menu_item_and_link
34
+ # @param name (url) the url to pass to PureAdmin::MenuHelper.menu_item_and_link
35
+ # @param name (Hash) the options to pass to PureAdmin::MenuHelper.menu_item_and_link
36
+ # @yield the content to pass to PureAdmin::MenuHelper.menu_item_and_link
37
+ def dropdown_item(name = nil, url = nil, options = nil, &block)
38
+ menu_item_and_link(name, url, options, &block)
39
+ end
40
+ end
@@ -0,0 +1,120 @@
1
+
2
+ ##
3
+ # Helper methods to assist in building the Pure Admin menu.
4
+ module PureAdmin::MenuHelper
5
+ ##
6
+ # Renders a pure menu wrapper to the view.
7
+ # @param options (Hash) a container for options to be passed to menus and menu lists.
8
+ # @param options[:menu_html] (Hash) all options that can be passed to content_tag are respected here.
9
+ # @param options[:list_html] (Hash) all options that can be passed to content_tag are respected here.
10
+ # @yield The contents of the menu panel
11
+ def menu(options = {}, &block)
12
+ menu_html = options.delete(:menu_html) || {}
13
+ menu_html[:class] = merge_html_classes('pure-menu', menu_html[:class])
14
+
15
+ list_html = options.delete(:list_html) || {}
16
+ list_html[:class] = merge_html_classes('pure-menu-list', list_html[:class])
17
+
18
+ content_tag(:nav, menu_html) do
19
+ content_tag(:ul, '', list_html, &block)
20
+ end
21
+ end
22
+
23
+ ##
24
+ # Renders a pure sub-menu to the view.
25
+ # @param options (Hash) all options that can be passed to content_tag are respected here.
26
+ # @yield The contents of the menu panel
27
+ def sub_menu(options = {}, &block)
28
+ options[:class] = merge_html_classes('pure-menu-list sub-menu', options[:class])
29
+ content_tag(:ul, '', options, &block)
30
+ end
31
+
32
+ ##
33
+ # Renders a "menu link" to the view.
34
+ # @param name (String, Symbol)
35
+ # @param url (String, Array)
36
+ # @param options (Hash) all options that can be passed to link_to are respected here.
37
+ def menu_link(name = nil, url = nil, options = nil, &block)
38
+ options, url, name = url, name, capture(&block) if block_given?
39
+ options ||= {}
40
+
41
+ name = name.to_s.titleize unless block_given? || name.respond_to?(:titleize)
42
+
43
+ options[:class] = merge_html_classes('pure-menu-link', options[:class])
44
+
45
+ url.present? ? link_to(name, url, options) : content_tag(:span, name, options)
46
+ end
47
+
48
+ ##
49
+ # Renders a "menu item" to the view.
50
+ # @param options (Hash) all options that can be passed to content_tag are respected here.
51
+ def menu_item(options = {}, &block)
52
+ options[:class] = merge_html_classes('pure-menu-item', options[:class])
53
+ options[:class] << 'current' if options.delete(:current)
54
+
55
+ condition = options.key?(:if) ? options.delete(:if) : true
56
+ condition = !options.delete(:unless) if options.key?(:unless)
57
+
58
+ content_tag(:li, capture(&block), options) if condition
59
+ end
60
+
61
+ ##
62
+ # Renders a "menu item" and "menu link" to the view.
63
+ # @param name (String, Symbol)
64
+ # @param url (String, Array)
65
+ # @param options (Hash) a container for options to be passed to menu items and links.
66
+ # @param options[:item_html] (Hash) all options that can be passed to content_tag are respected here.
67
+ # @param options[:link_html] (Hash) all options that can be passed to link_to are respected here.
68
+ def menu_item_and_link(name = nil, url = nil, options = nil, &block)
69
+ options, url, name = url, name, capture(&block) if block_given?
70
+ options ||= {}
71
+
72
+ item_html = options.delete(:item_html) || {}
73
+ item_html[:class] = merge_html_classes('pure-menu-item', item_html[:class])
74
+ item_html[:if] = options[:if] if options.key?(:if)
75
+ item_html[:unless] = options[:unless] if options.key?(:unless)
76
+ item_html[:current] = true if current_menu_item?(url)
77
+
78
+ link_html = options.delete(:link_html) || {}
79
+
80
+ menu_item(item_html) do
81
+ menu_link(name, url, link_html)
82
+ end
83
+ end
84
+
85
+ ##
86
+ # Check if the menu item is currently active
87
+ # @param url (String) the menu item's URL.
88
+ def current_menu_item?(url)
89
+ return false unless url
90
+
91
+ begin
92
+ menu_item_path = URI.parse(url).try(:path)
93
+ rescue
94
+ menu_item_path = nil
95
+ end
96
+
97
+ return false unless menu_item_path
98
+
99
+ # only match roots on exact match
100
+ return request.original_fullpath == menu_item_path
101
+ end
102
+
103
+ ##
104
+ # Check if the menu item is currently active. Is active if it is parent or current.
105
+ # @param url (String) the menu item's URL.
106
+ def current_parent?(url)
107
+ return false unless url
108
+
109
+ begin
110
+ menu_item_path = URI.parse(url).try(:path)
111
+ rescue
112
+ menu_item_path = nil
113
+ end
114
+
115
+ return false unless menu_item_path
116
+
117
+ # match all other items to start of original_fullpath
118
+ return request.original_fullpath =~ /^#{Regexp.escape(menu_item_path)}(\/|$)/
119
+ end
120
+ end
@@ -0,0 +1,75 @@
1
+ ##
2
+ # Helper methods to assist in building Pure Admin portlets.
3
+ module PureAdmin::PortletHelper
4
+ ##
5
+ # Renders a "portlet" to the view.
6
+ # @param title (String)
7
+ # @param options (Hash) a container for options to the portlet.
8
+ # @param options[:portlet_html] (Hash) all options that can be passed to content_tag are respected here.
9
+ # @param options[:heading_html] (Hash) all options that can be passed to content_tag are respected here.
10
+ # @param options[:body_html] (Hash) all options that can be passed to content_tag are respected here.
11
+ # @yield The contents of the portlet
12
+ def portlet(title, options = {}, &block)
13
+ portlet_html = options[:portlet_html] || {}
14
+ portlet_html[:class] = ['portlet clear-fix', portlet_html[:class]]
15
+ portlet_html[:data] ||= {}
16
+ portlet_html[:data][:source] = options[:source] unless block_given?
17
+
18
+ heading_html = options.delete(:heading_html) || {}
19
+ heading_html[:class] = merge_html_classes('portlet-heading', heading_html[:class])
20
+
21
+ body_html = options.delete(:body_html) || {}
22
+ body_html[:class] = merge_html_classes('portlet-body clear-fix', body_html[:class])
23
+
24
+ if options[:icon]
25
+ icon = content_tag(:i, nil, class: "portlet-heading-icon fa fa-fw fa-#{options[:icon].to_s.dasherize}")
26
+ end
27
+
28
+ # This determines if the portlet can be closed. If it is remote it can be closed. If not,
29
+ # it is determined by the presence of expand in the options.
30
+ # e.g. <%= portlet 'A title', expand: true do %>...
31
+ closable = options.key?(:source) || options.key?(:expand)
32
+
33
+ portlet_html[:data][:closable] = closable
34
+
35
+ controls_content = ''.html_safe
36
+ controls = options.delete(:controls)
37
+ if controls.present?
38
+ if controls.respond_to?(:each)
39
+ controls.each do |control|
40
+ controls_content << content_tag(:span, control, class: 'portlet-control-item')
41
+ end
42
+ else
43
+ controls_content << content_tag(:span, controls, class: 'portlet-control-item')
44
+ end
45
+ end
46
+
47
+ if closable
48
+ controls_content << content_tag(:span, nil, class: 'portlet-indicator')
49
+ end
50
+
51
+ if controls_content.present?
52
+ controls_wrapper = content_tag(:div, controls_content, class: 'portlet-controls')
53
+ end
54
+
55
+ # This determines if the portlet should be expanded by default. If it is explicitly given that
56
+ # takes precedence. If not, by default all remote portlets are not expanded and all static
57
+ # portlets are.
58
+ expand = options.key?(:expand) ? options[:expand] : block_given?
59
+
60
+ if expand
61
+ portlet_html[:class] << 'expanded'
62
+ portlet_html[:data][:expand] = true
63
+ end
64
+
65
+ heading_content = content_tag(:div, heading_html) do
66
+ (icon || ''.html_safe) + content_tag(:h4, title) + (controls_wrapper || ''.html_safe)
67
+ end
68
+
69
+ body_content = content_tag(:div, (capture(&block) if block_given?), body_html)
70
+
71
+ content_tag(:div, portlet_html) do
72
+ heading_content + body_content
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,158 @@
1
+ ##
2
+ # Helper methods for table filters functionality.
3
+ #
4
+ # The recommended way of using this helper is
5
+ #
6
+ # filters_for admin_members_path do |filter|
7
+ # filter.on :query the default is a text field
8
+ # filter.on :answer, options: %w(Yes No) if given an options hash, a select will be used
9
+ # filter.on :status, as: :active_status when given :active_status it will use the options
10
+ # All, Active, and Inactive and the default of
11
+ # Active. However these can be overridden by
12
+ # :options and :default respectively.
13
+ # filter.on :starts_on, as: :date when given :date, it will enable the pure_date
14
+ # input type
15
+ # end
16
+ module PureAdmin::TableFiltersHelper
17
+ ##
18
+ # Renders the table filters form to the view.
19
+ # @param path (String) the path for the form_tag
20
+ # @param options (Hash) all options that can be passed to form_tag are respected here.
21
+ # @yield The contents for the table filters
22
+ def table_filters(path, options = {}, &block)
23
+ options[:class] = merge_html_classes('pure-form pure-form-stacked table-filters
24
+ js-partial-refresh clear-fix', options[:class])
25
+
26
+ options[:remote] = false || options[:remote]
27
+ options[:method] ||= :get
28
+
29
+ content = capture(&block)
30
+
31
+ if content
32
+ content << content_tag(:div, submit_tag('Go', class: 'pure-button pure-button-primary'),
33
+ class: 'filter-group filter-submit')
34
+ content << hidden_field_tag(:sort, params[:sort])
35
+ content << hidden_field_tag(:reverse_order, params[:reverse_order])
36
+
37
+ form_tag path, options do
38
+ content
39
+ end
40
+ end
41
+ end
42
+
43
+ ##
44
+ # Renders a table filter item to the view.
45
+ # @param attribute (String, Symbol)
46
+ # @param options (Hash)
47
+ # @options options (Symbol) :type the type of field to display
48
+ # @options options (Hash) :options the select options for select inputs
49
+ # @options options (String) :default the default select option for select inputs
50
+ # @options options (Hash) :input_html any data contained within this hash will be passed to
51
+ # the appropriate *_tag method
52
+ # @options options (Boolean, String) :label the text to display as a label if a string. If false,
53
+ # this will prevent the label from being shown
54
+ # @options options (Hash) :label_html any data contained within this hash will be passed to
55
+ # the content_tag builder for the label
56
+ # @yield The contents of the table filter with the label (unless options[:label] is false)
57
+ def table_filter_item(attribute, options = {}, &block)
58
+ if block_given?
59
+ field = capture(&block)
60
+ else
61
+ type = options.delete(:as) || :string
62
+
63
+ # If we're given an options array, we assume it to be a select filter.
64
+ # This allows for more concise code in the form
65
+ # table_filter_item :status, options: %w(Yes No)
66
+ # or
67
+ # filter.on :status, options %W(Yes No)
68
+ type = :select if options[:options].present?
69
+
70
+ # We define the :active_status type to shortcut a common filter type.
71
+ if type == :active_status
72
+ type = :select
73
+ options[:options] ||= %w(All Active Inactive)
74
+ options[:default] ||= 'Active'
75
+ end
76
+
77
+ input_html = options.delete(:input_html) || {}
78
+ input_html[:class] = merge_html_classes('filter-control', input_html[:class])
79
+
80
+ # Defaulting to a simple text field, we choose which field to output here.
81
+ # @note if at some point we wish to add a new field type, here is the place to add it
82
+ case type
83
+ when :select
84
+ options[:options] ||= []
85
+ field = select_tag(attribute,
86
+ options_for_select(options[:options], params[attribute.to_sym] || options[:default]),
87
+ input_html)
88
+ when :date
89
+ input_html[:class] = merge_html_classes('pure-admin-date', input_html[:class])
90
+ field = text_field_tag(attribute, params[attribute.to_sym], input_html)
91
+ icon = content_tag(:span, nil, class: 'input-addon fa fa-fw fa-calendar')
92
+ field = content_tag(:div, icon + field, class: 'addon-wrapper')
93
+ else # :string
94
+ field = text_field_tag(attribute, params[attribute.to_sym], input_html)
95
+ end
96
+ end
97
+
98
+ label = ''.html_safe
99
+ if options[:label] != false
100
+ label_html = options.delete(:label_html) || {}
101
+ label_text = options.delete(:label) || attribute.to_s.titleize
102
+ label = label_tag(attribute, label_text, label_html)
103
+ end
104
+
105
+ content_tag(:div, label + field, class: 'filter-group')
106
+ end
107
+
108
+ ##
109
+ # Renders a table filters section to the view using the table filter builder DSL.
110
+ # @param resource (ActiveRecord::Base) the model instance to build the table filters for.
111
+ # @param options (Hash) all options that can be passed to content_tag are respected here.
112
+ # @yield The contents of the table filters section
113
+ def filters_for(path, options = {}, &block)
114
+ builder = TableFiltersBuilder.new(self)
115
+ table_filters(path, options) do
116
+ capture(builder, &block)
117
+ end
118
+ end
119
+
120
+ ##
121
+ # Allows building of table filters using a custom DSL.
122
+ #
123
+ # <%= filters_for resources_path do |filter| %>
124
+ # <%= filter.on :query %>
125
+ # <% end %>
126
+ class TableFiltersBuilder
127
+ ##
128
+ # Creates an instance of TableFiltersBuilder
129
+ # @param helper (ApplicationHelper) instance of application helper to allow access to view helpers.
130
+ # @yield instance of TableFiltersBuilder
131
+ def initialize(helper)
132
+ @helper = helper
133
+ end
134
+
135
+ ##
136
+ # Renders a table_filter_item inside the table_filters using a custom DSL.
137
+ #
138
+ # @param attribute (Symbol) the attribute on the resource
139
+ # @param options (Hash) all options that can be passed to content_tag are respected here.
140
+ # @yield The contents of the details panel item
141
+ def on(attribute, options = {}, &block)
142
+ if block_given?
143
+ helper.table_filter_item(attribute, options, &block)
144
+ else
145
+ helper.table_filter_item(attribute, options)
146
+ end
147
+ end
148
+
149
+ private
150
+
151
+ ##
152
+ # Access view helpers within the details panel builder
153
+ # @yield instance of ApplicationHelper
154
+ def helper
155
+ @helper
156
+ end
157
+ end
158
+ end
@@ -0,0 +1,17 @@
1
+ ##
2
+ # Overrides the :email input type to add a default prefix.
3
+ class AddonInput < SimpleForm::Inputs::StringInput
4
+ extend PureAdmin::ApplicationHelper
5
+
6
+ def icon
7
+ if options[:icon].present?
8
+ template.content_tag(:span, nil, class: ['input-addon', 'fa', 'fa-fw', options[:icon]])
9
+ else
10
+ ''
11
+ end
12
+ end
13
+
14
+ def input(wrapper_options = nil)
15
+ icon + super(wrapper_options)
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ ##
2
+ # Overrides SimpleForm's default CollectionSelectInput to add a class.
3
+ # This class is then used to initialise Select2 on all collection select inputs.
4
+ class CollectionSelectInput < SimpleForm::Inputs::CollectionSelectInput
5
+ def input_html_classes
6
+ super.push('pure-admin-select')
7
+ end
8
+
9
+ def input_html_options
10
+ super.deep_merge(
11
+ style: 'width: 100%;',
12
+ data: {
13
+ tags: options[:create_when_no_match] || false
14
+ }
15
+ )
16
+ end
17
+ end
@@ -0,0 +1,5 @@
1
+ ##
2
+ # Overrides the :email input type to add a default prefix.
3
+ class EmailInput < AddonInput
4
+ self.default_options = { icon: 'fa-envelope' }
5
+ end
@@ -0,0 +1,5 @@
1
+ ##
2
+ # Overrides the :tel input type to add a default prefix.
3
+ class TelInput < AddonInput
4
+ self.default_options = { icon: 'fa-phone' }
5
+ end
@@ -0,0 +1,10 @@
1
+ Description:
2
+ This will generate skeleton layout files that you will need to modify to suit your application.
3
+
4
+ Example:
5
+ rails generate pure_admin:layout
6
+
7
+ This will create:
8
+ app/views/layouts/admin.html.erb
9
+ app/assets/stylesheets/admin.css.scss
10
+