express_admin 1.6.4 → 1.6.7

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 (24) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/ace/mode-html.js +2437 -0
  3. data/app/assets/javascripts/express_admin.js +2 -0
  4. data/app/assets/javascripts/express_admin/admin.js.coffee +8 -2
  5. data/app/assets/javascripts/express_admin/form_validation.js.coffee +24 -0
  6. data/app/assets/stylesheets/express_admin/shared/_forms.sass +12 -3
  7. data/app/assets/stylesheets/express_admin/shared/_tables.sass +41 -0
  8. data/app/components/express_admin/code_editor.rb +44 -0
  9. data/{vendor/gems/express_templates/lib/express_templates/components/forms → app/components/express_admin}/country_select.rb +1 -1
  10. data/app/components/express_admin/smart_form.rb +5 -14
  11. data/app/components/express_admin/smart_table.rb +65 -26
  12. data/lib/express_admin/engine.rb +1 -0
  13. data/lib/express_admin/version.rb +1 -1
  14. data/test/dummy/test/components/code_editor_test.rb +53 -0
  15. data/test/dummy/test/components/country_select_test.rb +36 -0
  16. data/test/test_helper.rb +8 -0
  17. data/vendor/gems/express_templates/express_templates.gemspec +0 -1
  18. data/vendor/gems/express_templates/lib/express_templates/components/base.rb +29 -0
  19. data/vendor/gems/express_templates/lib/express_templates/components/configurable.rb +3 -1
  20. data/vendor/gems/express_templates/lib/express_templates/components/container.rb +3 -1
  21. data/vendor/gems/express_templates/lib/express_templates/components/forms.rb +0 -1
  22. data/vendor/gems/express_templates/lib/express_templates/version.rb +1 -1
  23. metadata +40 -6
  24. data/vendor/gems/express_templates/test/components/forms/country_select_test.rb +0 -34
@@ -5,6 +5,8 @@
5
5
  //= require tinymce-jquery
6
6
  //= require select2
7
7
  //= require dropzone
8
+ //= require jquery.validate
9
+ //= require jquery.validate.additional-methods
8
10
  //= require ace/ace
9
11
  //= require ace/worker-html
10
12
  //= require ace/mode-ruby
@@ -5,6 +5,9 @@ class AceInput
5
5
  @session = @editor.getSession()
6
6
  @renderer = @editor.renderer
7
7
  @textarea = $("##{$(editor).data('target')}")
8
+ @selectedMode = $(editor).data('mode')
9
+ if @selectedMode == "et"
10
+ @selectedMode = "ruby"
8
11
  @setOptions()
9
12
  @updateMode()
10
13
  @updateTheme()
@@ -20,7 +23,7 @@ class AceInput
20
23
  @session.setFoldStyle "markbeginend"
21
24
 
22
25
  updateMode: =>
23
- mode = require("ace/mode/ruby").Mode
26
+ mode = require("ace/mode/#{@selectedMode}").Mode
24
27
  @session.setMode new mode()
25
28
 
26
29
  updateTheme: =>
@@ -53,8 +56,11 @@ $(document).ready ->
53
56
  e.preventDefault()
54
57
  $('a.close-reveal-modal').trigger 'click'
55
58
  return
59
+
60
+ editor = []
56
61
  $('.ace-input').each (index)->
57
- editor = new AceInput(this)
62
+ editor.push(new AceInput(this))
63
+ window.editor = editor
58
64
 
59
65
  String::repeat = (num) ->
60
66
  new Array(num + 1).join this
@@ -0,0 +1,24 @@
1
+ $ ->
2
+ $('form').validate
3
+ debug: true
4
+ errorElement: 'span'
5
+
6
+ email = $('[name$="[email]"]')
7
+
8
+ if email.size() > 0
9
+ email.rules 'add',
10
+ required: true
11
+ email: true
12
+
13
+ password = $('[name$="[password]"]')
14
+
15
+ if password.size() > 0
16
+ password.rules 'add',
17
+ required: true
18
+ minlength: 8
19
+
20
+ password_confirmation = $('[name$="[password_confirmation]"]')
21
+
22
+ if password_confirmation.size() > 0
23
+ password_confirmation.rules 'add',
24
+ equalTo: $('[name$="[password]"]')
@@ -9,9 +9,18 @@
9
9
  height: 6rem
10
10
 
11
11
  .error
12
- border: none
13
- input, select, textarea, .select2-container
14
- border: 1px solid $red
12
+ border: 1px solid $red
13
+ margin-bottom: 0
14
+
15
+ span.error
16
+ display: block
17
+ border: 0
18
+ background-color: #f04124
19
+ color: $light
20
+ padding: 0.33333rem 0.5rem 0.5rem
21
+ font:
22
+ size: 0.85rem
23
+ margin-bottom: 1rem
15
24
 
16
25
  .help
17
26
  font:
@@ -36,3 +36,44 @@
36
36
  tbody
37
37
  td
38
38
  padding: 0.5rem
39
+
40
+ .smart-table
41
+ .ion-checkmark-round
42
+ color: #1fa67a
43
+
44
+ table + nav
45
+ margin-top: 50px
46
+ text-align: center
47
+
48
+ nav.pagination
49
+ span
50
+ transition: background-color 300ms ease-out
51
+ display: inline-block
52
+ height: 1.33333rem
53
+ margin-left: 0.27778rem
54
+ line-height: 20px
55
+ font:
56
+ weight: normal
57
+ size: 0.77778rem
58
+
59
+ &.gap:hover
60
+ background: inherit
61
+ border-radius: none
62
+ &:hover
63
+ background: #e6e6e6
64
+ border-radius: 3px
65
+ a
66
+ color: #999
67
+ display: block
68
+ padding: 0.05556rem 0.55556rem 0.05556rem
69
+
70
+
71
+ .current
72
+ font-weight: bold
73
+ background: #008cba
74
+ border-radius: 3px
75
+ color: #fff
76
+ padding: 0.05556rem 0.55556rem 0.05556rem
77
+ &:hover
78
+ background: #008cba
79
+
@@ -0,0 +1,44 @@
1
+ module ExpressAdmin
2
+ class CodeEditor < ExpressTemplates::Components::Forms::FormComponent
3
+
4
+ has_option :mode, "Language of the editor", type: :string
5
+ has_option :rows, "Define the number of rows", type: :int, default: 10
6
+
7
+ contains -> {
8
+ base_styles = "position: relative; height: 300px;"
9
+ text_area_tag object, object.send(field), field_helper_options.merge( id: field_id, name: field_name ) #field_name_attribute, field_helper_options
10
+ content_tag(:div, '', id: "ace_#{field_name}",
11
+ class: "ace-input", style: base_styles,
12
+ data: { target: field_id, mode: config[:mode] })
13
+ }
14
+
15
+ def field_helper_options
16
+ {rows: rows, class: "hide", hidden: true}.merge(super)
17
+ end
18
+
19
+ def object
20
+ self.send resource_name
21
+ end
22
+
23
+ def field
24
+ config[:id]
25
+ end
26
+
27
+ def rows
28
+ config[:rows]
29
+ end
30
+
31
+ def field_name
32
+ "#{object_type}[#{field}]"
33
+ end
34
+
35
+ def field_id
36
+ "#{object_type}_#{field}_#{object.id}"
37
+ end
38
+
39
+ def object_type
40
+ object.class.to_s.demodulize.underscore
41
+ end
42
+ end
43
+ end
44
+
@@ -1,5 +1,5 @@
1
1
  require 'countries'
2
- require_relative 'select'
2
+ require 'express_templates/components/forms/select'
3
3
 
4
4
  module ExpressTemplates
5
5
  module Components
@@ -38,7 +38,6 @@ module ExpressAdmin
38
38
  submit(class: 'button')
39
39
  }
40
40
 
41
-
42
41
  def form_field_for(attrib)
43
42
  field_type_substitutions = {'text_area' => 'textarea',
44
43
  'datetime_select' => 'datetime',
@@ -46,19 +45,11 @@ module ExpressAdmin
46
45
  field_type = attrib.field_type.to_s.sub(/_field$/,'')
47
46
  field_type = "password" if attrib.name.match(/password/)
48
47
  if relation = attrib.name.match(/(\w+)_id$/).try(:[], 1)
49
- # TODO: should allow select2 override
50
- select(attrib.name.to_sym, options: config["#{relation}_collection".to_sym], select2: true)
48
+ # TODO: should allow select2 override
49
+ select(attrib.name.to_sym, options: config["#{relation}_collection".to_sym], select2: true)
51
50
  else
52
51
  if field_type == 'text_area'
53
- if attrib.name == 'definition'
54
- # TODO allow other fields aside from layout.definition
55
- base_styles = "position: relative; height: 300px;"
56
- target = [attributes[:class].to_a.last, attrib.name].join("_")
57
- textarea attrib.name.to_sym, rows: 10, class: "hide", hidden: true
58
- content_tag(:div, '', id: "ace_#{attrib.name}", class: "ace-input", style: base_styles, data: { target: target })
59
- else
60
- textarea attrib.name.to_sym, rows: 10
61
- end
52
+ textarea attrib.name.to_sym, rows: 10
62
53
  else
63
54
  self.send((field_type_substitutions[field_type] || field_type), attrib.name.to_sym)
64
55
  end
@@ -118,8 +109,8 @@ module ExpressAdmin
118
109
  attribs
119
110
  end.reject {|attrib| (excluded_attributes).map(&:to_s).include? attrib.name }
120
111
  end
121
-
122
112
  end
123
113
  end
124
114
  end
125
- end
115
+ end
116
+
@@ -4,9 +4,10 @@ module ExpressAdmin
4
4
  class SmartTable < ExpressTemplates::Components::Configurable
5
5
  include ExpressTemplates::Components::Capabilities::Resourceful
6
6
 
7
- tag :table
7
+ tag :div
8
8
 
9
9
  MAX_COLS_TO_SHOW_IDX = 5
10
+ MAX_ROWS_TO_SHOW_IDX = 10
10
11
 
11
12
  attr :columns
12
13
 
@@ -32,44 +33,70 @@ module ExpressAdmin
32
33
  end
33
34
  options = options + resource_class.instance_methods.grep(/_count$/).map(&:to_s)
34
35
  }
36
+ has_option :rows, 'Specify the number of rows to show', type: :integer
37
+
38
+ has_option :pagination, 'Add pagination to the bottom of the table', type: :string, default: 'bottom'
35
39
 
36
40
  contains -> {
37
- thead {
38
- tr {
39
- display_columns.each do |column|
40
- th(class: column.name) {
41
- column.title
42
- }
43
- end
44
- actions_header if should_show_actions?
45
- hidden_columns_header_indicator if columns_hidden?
46
- }
47
- }
48
- tbody {
49
- stored_member_assigns = assigns[collection_member_name.to_sym]
50
- collection.each do |item|
51
- assigns[collection_member_name.to_sym] = item
52
- tr(id: row_id(item), class: row_class(item)) {
41
+ pagination if config[:pagination] == 'top'
42
+ table(class: table_classes) {
43
+ thead {
44
+ tr {
53
45
  display_columns.each do |column|
54
- td(class: column.name) {
55
- cell_value(item, column.accessor)
46
+ th(class: column.name) {
47
+ column.title
56
48
  }
57
49
  end
58
- actions_column(item) if should_show_actions?
59
- hidden_column_cell if columns_hidden?
50
+ actions_header if should_show_actions?
51
+ hidden_columns_header_indicator if columns_hidden?
60
52
  }
61
- assigns[collection_member_name.to_sym] = stored_member_assigns
62
- end ; nil
53
+ }
54
+ tbody {
55
+ stored_member_assigns = assigns[collection_member_name.to_sym]
56
+ collection.each do |item|
57
+ assigns[collection_member_name.to_sym] = item
58
+ tr(id: row_id(item), class: row_class(item)) {
59
+ display_columns.each do |column|
60
+ td(class: column.name) {
61
+ cell_value(item, column.accessor)
62
+ }
63
+ end
64
+ actions_column(item) if should_show_actions?
65
+ hidden_column_cell if columns_hidden?
66
+ }
67
+ assigns[collection_member_name.to_sym] = stored_member_assigns
68
+ end; nil
69
+ }
63
70
  }
64
-
65
71
  scroll_table if !!config[:scrollable]
72
+ pagination if config[:pagination] == 'bottom'
66
73
  }
67
74
 
68
75
  before_build -> {
69
76
  _initialize_columns
70
- add_class 'table striped'
71
77
  }
72
78
 
79
+ def pagination
80
+ paginate collection, :route_set => route_set
81
+ end
82
+
83
+ def table_classes
84
+ 'table striped'
85
+ end
86
+
87
+ def route_set
88
+ namespace.nil? ? namespace : eval(namespace)
89
+ end
90
+
91
+ def collection
92
+ collections = super.kind_of?(Array) ? Kaminari.paginate_array(super) : super
93
+ collections.page(index_page).per(specified_rows)
94
+ end
95
+
96
+ def index_page
97
+ helpers.params[:page] || 1 # Default page is 1
98
+ end
99
+
73
100
  def scroll_table
74
101
  script {
75
102
  %Q($('\##{config[:id]}').scrollTableBody())
@@ -124,12 +151,14 @@ module ExpressAdmin
124
151
  elsif attrib = accessor.to_s.match(/(\w+)_link$/).try(:[], 1)
125
152
  # TODO: only works with non-namespaced routes
126
153
  helpers.link_to item.send(attrib), resource_path(item)
154
+ elsif attrib = accessor.to_s.match(/(\w+)_checkmark/).try(:[], 1)
155
+ "<i class='ion-checkmark-round'></i>".html_safe if item.send(attrib)
127
156
  elsif attrib = accessor.to_s.match(/(\w+)_in_words/).try(:[], 1)
128
157
  if item.send(attrib)
129
158
  if item.send(attrib) < DateTime.now
130
159
  "#{helpers.time_ago_in_words(item.send(attrib))} ago"
131
160
  else
132
- helpers.time_ago_in_words(item.send(attrib))
161
+ "in #{helpers.time_ago_in_words(item.send(attrib))}"
133
162
  end
134
163
  else
135
164
  'never'
@@ -184,6 +213,16 @@ module ExpressAdmin
184
213
  td(class: 'more-columns-indicator')
185
214
  end
186
215
 
216
+ def specified_rows
217
+ config[:rows] || MAX_ROWS_TO_SHOW_IDX
218
+ end
219
+
220
+ def hidden_columns_header_indicator
221
+ th(class: 'more-columns-indicator') {
222
+ "..."
223
+ }
224
+ end
225
+
187
226
  private
188
227
  def _initialize_columns
189
228
  @columns =
@@ -6,6 +6,7 @@ require 'jquery-rails'
6
6
  require 'jquery-ui-rails'
7
7
  require 'select2-rails'
8
8
  require 'dropzonejs-rails'
9
+ require 'jquery-validation-rails'
9
10
  require 'foundation_apps_styles'
10
11
  require 'bourbon'
11
12
  require 'gravatar_image_tag'
@@ -1,3 +1,3 @@
1
1
  module ExpressAdmin
2
- VERSION = "1.6.4"
2
+ VERSION = "1.6.7"
3
3
  end
@@ -0,0 +1,53 @@
1
+ require 'test_helper'
2
+
3
+ class Foo
4
+ def self.columns; [] ; end
5
+ end
6
+
7
+ module Components
8
+
9
+ class CodeEditorTest < ActiveSupport::TestCase
10
+
11
+ def compiled_code_editor(*args)
12
+ arbre {
13
+ express_form(:foo){
14
+ code_editor :name, *args
15
+ }
16
+ }
17
+ end
18
+
19
+ def assigns
20
+ { foo: resource }
21
+ end
22
+
23
+ def helpers
24
+ mock_action_view do
25
+ def foos_path
26
+ '/foos'
27
+ end
28
+ end
29
+ end
30
+
31
+ test "renders the code editor" do
32
+ assert compiled_code_editor
33
+ end
34
+
35
+ test "div displays the ace editor" do
36
+ assert_match 'class="ace-input"', compiled_code_editor
37
+ end
38
+
39
+ test "text area is hidden" do
40
+ assert_match /textarea(.*?)class="hide" hidden="hidden"/, compiled_code_editor
41
+ end
42
+
43
+ test "rows can be changed" do
44
+ assert_match 'rows="15"', compiled_code_editor(rows: 15)
45
+ end
46
+
47
+ test "language mode can be changed" do
48
+ assert_match 'data-mode="html"', compiled_code_editor(mode: "html")
49
+ assert_match 'data-mode="et"', compiled_code_editor(mode: "et")
50
+ end
51
+
52
+ end
53
+ end
@@ -0,0 +1,36 @@
1
+ require 'test_helper'
2
+ require 'ostruct'
3
+ class CountrySelectTest < ActiveSupport::TestCase
4
+
5
+ def resource_assigns
6
+ {example_engine: ExampleEngine::MockRouteProxy.new}
7
+ end
8
+
9
+ def helpers
10
+ view = mock_action_view
11
+ class << view
12
+ def widgets_path
13
+ "/widgets"
14
+ end
15
+ alias collection_path widgets_path
16
+ end
17
+ view
18
+ end
19
+
20
+ test "country_select renders without an error" do
21
+ assert arbre(widget: Widget.new) {
22
+ express_form(:widget) {
23
+ country_select :column6
24
+ }
25
+ }
26
+ end
27
+
28
+ test "can change label for country_select" do
29
+ html = arbre(widget: Widget.new) {
30
+ express_form(:widget) {
31
+ country_select :column6, label: "Country"
32
+ }
33
+ }
34
+ assert_match(/<label.*Country<\/label>/, html)
35
+ end
36
+ end