ab_admin 0.3.5 → 0.3.6

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 (63) hide show
  1. data/Gemfile +3 -3
  2. data/TODO +2 -1
  3. data/ab_admin.gemspec +2 -2
  4. data/app/assets/javascripts/ab_admin/components/admin_assets.js.coffee +2 -22
  5. data/app/assets/javascripts/ab_admin/components/croppable_image.js.coffee +3 -3
  6. data/app/assets/javascripts/ab_admin/components/gmaps.js.coffee +0 -38
  7. data/app/assets/javascripts/ab_admin/components/in_place_edit.js.coffee +2 -1
  8. data/app/assets/javascripts/ab_admin/components/init_nested_filelds.js.coffee +1 -0
  9. data/app/assets/javascripts/ab_admin/core/init.js.coffee +2 -0
  10. data/app/assets/javascripts/ab_admin/core/pjax.js.coffee +6 -6
  11. data/app/assets/javascripts/ab_admin/core/ui_utils.js.coffee +7 -7
  12. data/app/assets/javascripts/ab_admin/core/utils.js.coffee +19 -1
  13. data/app/assets/javascripts/ab_admin/core/view_layout.js.coffee +44 -0
  14. data/app/assets/stylesheets/ab_admin/bootstrap_and_overrides.css.scss +22 -0
  15. data/app/assets/stylesheets/ab_admin/components/_base.css.scss +3 -3
  16. data/app/assets/stylesheets/ab_admin/components/_form.css.scss +1 -1
  17. data/app/assets/stylesheets/ab_admin/components/_navigation.css.scss +7 -1
  18. data/app/assets/stylesheets/ab_admin/components/_table_view.css.scss +4 -0
  19. data/app/assets/stylesheets/ab_admin/components/_view_layout.css.scss +65 -0
  20. data/app/assets/stylesheets/ab_admin/fileupload.css.scss +1 -0
  21. data/app/controllers/admin/base_controller.rb +30 -14
  22. data/app/controllers/admin/static_pages_controller.rb +3 -1
  23. data/app/views/admin/base/_search_layout.html.slim +2 -0
  24. data/app/views/admin/base/create.js.erb +2 -2
  25. data/app/views/admin/base/edit.js.erb +3 -1
  26. data/app/views/admin/base/index.html.slim +5 -0
  27. data/app/views/admin/base/new.js.erb +3 -1
  28. data/app/views/admin/base/update.js.erb +1 -1
  29. data/app/views/admin/fileupload/_file.html.slim +1 -1
  30. data/app/views/admin/fileupload/_video.html.slim +9 -0
  31. data/app/views/admin/fileupload/_vtmpl.html.slim +10 -0
  32. data/app/views/admin/shared/_batch_actions.html.slim +9 -3
  33. data/app/views/admin/shared/_breadcrumbs.html.slim +5 -6
  34. data/app/views/admin/shared/_flash.js.erb +3 -0
  35. data/app/views/admin/shared/inputs/_checkbox_tree.html.slim +14 -0
  36. data/app/views/admin/structures/_form.html.slim +5 -2
  37. data/app/views/layouts/admin/_footer.html.slim +1 -0
  38. data/app/views/layouts/admin/_navigation.html.slim +5 -7
  39. data/app/views/layouts/admin/application.html.slim +1 -1
  40. data/config/locales/en.yml +4 -10
  41. data/config/locales/it.yml +1 -8
  42. data/config/locales/ru.yml +4 -10
  43. data/features/dsl/export.feature +6 -6
  44. data/lib/ab_admin/concerns/utilities.rb +3 -3
  45. data/lib/ab_admin/controllers/head_options.rb +1 -0
  46. data/lib/ab_admin/core_ext/string.rb +3 -2
  47. data/lib/ab_admin/hooks/paginate_hooks.rb +1 -0
  48. data/lib/ab_admin/models/asset.rb +4 -0
  49. data/lib/ab_admin/models/attachment_file.rb +0 -4
  50. data/lib/ab_admin/models/type_model.rb +10 -0
  51. data/lib/ab_admin/models/user.rb +1 -1
  52. data/lib/ab_admin/utils.rb +2 -0
  53. data/lib/ab_admin/version.rb +1 -1
  54. data/lib/ab_admin/views/admin_helpers.rb +14 -6
  55. data/lib/ab_admin/views/admin_navigation_helpers.rb +4 -2
  56. data/lib/ab_admin/views/form_builder.rb +5 -2
  57. data/lib/ab_admin/views/helpers.rb +4 -0
  58. data/lib/ab_admin/views/inputs/ckeditor_input.rb +0 -1
  59. data/lib/generators/ab_admin/install/templates/config/nginx.conf +12 -7
  60. data/lib/generators/ab_admin/install/templates/models/structure.rb +2 -1
  61. data/lib/generators/ab_admin/resource/templates/_form.haml.erb +1 -1
  62. data/lib/generators/ab_admin/resource/templates/_form.slim.erb +1 -1
  63. metadata +12 -22
data/Gemfile CHANGED
@@ -11,7 +11,7 @@ gem 'devise-encryptable'
11
11
  gem 'cancan'
12
12
  # for ruby 2.0
13
13
  #gem 'inherited_resources', git: 'git://github.com/josevalim/inherited_resources.git'
14
- gem 'inherited_resources', '~> 1.3.0'
14
+ gem 'inherited_resources', '~> 1.4.0'
15
15
  gem 'rack-pjax'
16
16
  gem 'configatron'
17
17
 
@@ -20,8 +20,8 @@ gem 'has_scope'
20
20
  gem 'friendly_id'
21
21
  gem 'galetahub-enum_field', require: 'enum_field'
22
22
  gem 'awesome_nested_set'
23
- gem 'sunrise-file-upload', git: 'git://github.com/leschenko/sunrise-file-upload.git', ref: '53da968'
24
- gem 'globalize3', :git => 'git://github.com/leschenko/globalize3.git', :ref => 'f16ab7f', branch: 'master'
23
+ gem 'globalize3', git: 'git://github.com/leschenko/globalize3.git', branch: 'master', ref: 'f16ab7f'
24
+ gem 'sunrise-file-upload', git: 'git://github.com/leschenko/sunrise-file-upload.git', branch: 'master', ref: '6aad0cf'
25
25
 
26
26
  gem 'carrierwave'
27
27
  gem 'mini_magick'
data/TODO CHANGED
@@ -1,3 +1,4 @@
1
1
  +settings and locales reloading
2
2
  form has_many has_one
3
- add resource history
3
+ add resource history
4
+ extract perms css
data/ab_admin.gemspec CHANGED
@@ -22,7 +22,7 @@ Gem::Specification.new do |gem|
22
22
  gem.add_dependency 'rails-i18n'
23
23
  gem.add_dependency 'slim'
24
24
  gem.add_dependency 'cancan'
25
- gem.add_dependency 'inherited_resources', '~> 1.3.0'
25
+ gem.add_dependency 'inherited_resources', '~> 1.4.0'
26
26
  gem.add_dependency 'rack-pjax'
27
27
  gem.add_dependency 'ransack'
28
28
  gem.add_dependency 'has_scope'
@@ -55,5 +55,5 @@ Gem::Specification.new do |gem|
55
55
  gem.add_development_dependency 'forgery'
56
56
  gem.add_development_dependency 'capybara'
57
57
  gem.add_development_dependency 'connection_pool'
58
- gem.add_development_dependency 'cucumber-rails'
58
+ #gem.add_development_dependency 'cucumber-rails'
59
59
  end
@@ -60,29 +60,9 @@ class window.AdminAssets
60
60
 
61
61
  initCrop: ->
62
62
  if @uploader_el.data('crop') && $.fn.Jcrop
63
- @crop = new CroppableImage(@element_id)
63
+ opts = if _.isObject(@uploader_el.data('crop')) then @uploader_el.data('crop') else {}
64
+ @crop = new CroppableImage(@element_id, opts)
64
65
 
65
66
  initFancybox: =>
66
67
  $(@query + " a.fancybox").fancybox
67
68
  afterShow: => @crop?.fancyboxHandler()
68
-
69
-
70
- #class window.AssetDescription
71
- # constructor: (@assoc, @assetable_type, @assetable_id, @guid) ->
72
- # @cont = $("[id^='#{@assoc}_']")
73
- # @addButton()
74
- #
75
- # addButton: ->
76
- # uri = $.param({assoc: @assoc, assetable_type: @assetable_type, assetable_id: @assetable_id, guid: @guid})
77
- # url = '/admin/assets/description?' + uri
78
- # html = "<button type='button' class='black_button button_description' href='#{url}'>#{I18n.t('admin_js.button_description')}</button>"
79
- # @cont.find('.fileupload-button').after(html)
80
- # @button = @cont.find('.button_description')
81
- # @button.fancybox
82
- # onComplete: ->
83
- # $cont = $(".locale_tabs.asset_description")
84
- ## $cont.tabs()
85
- # $cont.closest('#fancybox-content').width (i, w) -> w + 10
86
- # $('#fancybox-content .button_save, #fancybox-content .button_cancel').live 'click', ->
87
- # $.fancybox.close()
88
- #
@@ -1,7 +1,7 @@
1
1
  class window.CroppableImage
2
- @crop_defaults =
3
- aspectRatio: 760 / 350
4
- setSelect: [0, 0, 760, 350]
2
+ @crop_defaults = {}
3
+ # aspectRatio: 760 / 350
4
+ # setSelect: [0, 0, 760, 350]
5
5
 
6
6
  constructor: (@element_id, @options = {}) ->
7
7
  @uploader_api = qq.FileUploader.instances[@element_id]
@@ -119,18 +119,15 @@ window.codeLatLng = (lat, lng, callback = null) ->
119
119
  latlng = new google.maps.LatLng(lat, lng)
120
120
  window.geocoder.geocode {latLng: latlng}, (results, status) ->
121
121
  if status is google.maps.GeocoderStatus.OK
122
- # log results[1]
123
122
  results[1]
124
123
  callback(results[1]) if callback
125
124
  else
126
125
  false
127
126
 
128
127
  window.codeAddress = (address, callback = null) ->
129
- # log address
130
128
  window.geocoder ||= new google.maps.Geocoder()
131
129
  window.geocoder.geocode {address: address}, (results, status) ->
132
130
  if status is google.maps.GeocoderStatus.OK
133
- # log results
134
131
  callback(_.first(results)) if callback
135
132
  else
136
133
  false
@@ -139,38 +136,3 @@ window.getPlaceComponent = (place, component) ->
139
136
  res = _.filter place.address_components, (el) ->
140
137
  _.include(el.types, component)
141
138
  res[0]
142
-
143
-
144
-
145
- # typesByPrefix: ->
146
- # if _.include(['region', 'district', 'sub_district'], @options.prefix)
147
- # ['(regions)']
148
- # else if _.include(['location'], @options.prefix)
149
- # ['(cities)']
150
- # else
151
- # ['geocode']
152
-
153
- # initAutocompleteCustom: (dom_input='geo_autocomplete') ->
154
- # input = document.getElementById(dom_input)
155
- # opts =
156
- # types: ['geocode']
157
- ## componentRestrictions: {country: 'ru'}
158
- # autocomplete = new google.maps.places.Autocomplete(input, opts)
159
- # autocomplete.bindTo('bounds', @map)
160
- # google.maps.event.addListener autocomplete, 'place_changed', =>
161
- # place = autocomplete.getPlace()
162
- # @callback.call(this, place) if @callback
163
- # return unless place.geometry
164
- # pos = place.geometry.location
165
- # if place.geometry.viewport
166
- # @map.fitBounds(place.geometry.viewport)
167
- # else
168
- # @map.setCenter(pos)
169
- # @map.setZoom(17)
170
- #
171
- # @marker.setPosition(pos)
172
- # @setInputs(pos)
173
- #
174
- # $('#'+ dom_input).live "keypress", (e) ->
175
- # e.preventDefault() if e.keyCode == 13
176
-
@@ -21,4 +21,5 @@ $(document).on 'admin:init', (e) ->
21
21
  return unless window.viewType == 'list'
22
22
  $('.editable').editable
23
23
  onblur: 'submit'
24
- placement: 'bottom'
24
+ placement: 'bottom'
25
+ emptytext: I18n.t('admin_js.empty')
@@ -3,4 +3,5 @@ window.initNestedFields = (opts={}) ->
3
3
  window.locale_tabs?.initHandlers() unless opts.skip_tabs
4
4
  window.initFancySelect() unless opts.skip_fancy
5
5
  window.initPickers() unless opts.skip_pickers
6
+ window.initEditor() unless opts.skip_editor
6
7
  opts.callback.call(e) if opts.callback
@@ -6,6 +6,7 @@
6
6
  #= require ab_admin/core/search_form
7
7
  #= require ab_admin/core/pagination
8
8
  #= require ab_admin/core/columns_hider
9
+ #= require ab_admin/core/view_layout
9
10
 
10
11
  $ ->
11
12
  if $('#list')[0]
@@ -62,6 +63,7 @@ $ ->
62
63
 
63
64
  initHotkeys() if window.gon?.hotkeys
64
65
 
66
+
65
67
  # $('form .region_ac').regionAc()
66
68
  # new NestedFieldsAdder
67
69
  # region_ac: true
@@ -1,22 +1,22 @@
1
1
  $ ->
2
- $('.pjax, .pagination a, .pjax_links a').live 'click', (event) ->
3
- if event.which > 1 || event.metaKey || event.ctrlKey
2
+ $(document).on 'click', '.pjax, .pagination a, .pjax_links a', (e) ->
3
+ if e.which > 1 || e.metaKey || e.ctrlKey
4
4
  return
5
5
  else if $.support.pjax
6
- event.preventDefault()
6
+ e.preventDefault()
7
7
  $.pjax
8
8
  container: $(this).data('pjax-container') || '[data-pjax-container]'
9
9
  url: $(this).data('href') || $(this).attr('href')
10
10
  timeout: 50000
11
11
  else if $(this).data('href')
12
- event.preventDefault()
12
+ e.preventDefault()
13
13
  window.location = $(this).data('href')
14
14
 
15
15
  unless gon.test
16
- $('.pjax-form').live 'submit', (event) ->
16
+ $(document).on 'submit', '.pjax-form', (e) ->
17
17
  $el = $(this)
18
18
  if $.support.pjax
19
- event.preventDefault()
19
+ e.preventDefault()
20
20
  $.pjax
21
21
  type: $el.attr('method')
22
22
  container: $el.data('pjax-container') || '[data-pjax-container]'
@@ -3,7 +3,7 @@ window.clonePagination = ->
3
3
 
4
4
  window.initPopover = ->
5
5
  $('.popover').hide()
6
- $('a[rel=popover]').popover({trigger: 'hover'})
6
+ $('a[rel=popover]').popover({trigger: 'hover', html: true})
7
7
 
8
8
  window.initAcFileds = ->
9
9
  for el in $('.ac_field')
@@ -40,7 +40,7 @@ window.inputSetToggle = ->
40
40
  $(this).siblings().toggle()
41
41
 
42
42
  window.flash = (message, type='notice') ->
43
- $('#container').prepend $("<div class='alert alert-#{type}'><a class='close' data-dismiss='alert'>×</a>#{message}</div>")
43
+ $("<div class='alert alert-#{type}'><a class='close' data-dismiss='alert'>×</a>#{message}</div>").insertBefore $('#container')
44
44
 
45
45
  window.focusInput = (scope=null) ->
46
46
  scope ||= $('form.simple_form:first')
@@ -62,9 +62,12 @@ window.initFancySelect = ->
62
62
  $('form .fancy_select, form input.token, .without_form.fancy_select').each ->
63
63
  $el = $(this)
64
64
  return if $el.data('select2')
65
+ $el.prop('required', null)
65
66
  options = _.defaults({}, defaults)
66
67
  options.multiple = $el.data('multi') unless _.isUndefined($el.data('multi'))
67
68
  options.width = $el[0].style.width || 'resolve'
69
+ options.escapeMarkup = (m) -> m
70
+
68
71
  if $el.data('tags')
69
72
  options.tokenSeparators = [","]
70
73
  options.tags = $el.data('tags')
@@ -83,9 +86,6 @@ window.initFancySelect = ->
83
86
  if $el.data('selection')
84
87
  options.formatSelection = (item) -> fetchTemplate($el.data('selection'))(item)
85
88
 
86
- if $el.data('image') || $el.data('result') || $el.data('selection')
87
- options.escapeMarkup = (m) -> m
88
-
89
89
  options.initSelection = (el, callback) ->
90
90
  data = $el.data('pre')
91
91
  if $el.data('multi')
@@ -123,11 +123,11 @@ window.initFancySelect = ->
123
123
 
124
124
  log cond
125
125
 
126
- data = {q: term, class: $el.data('class'), token: true}
126
+ data = {q: term, class: $el.data('class'), token: true, page: page}
127
127
  _.extend(data, cond)
128
128
 
129
129
  results: (data, page) ->
130
- results: data
130
+ results: data, more: data.length > 0
131
131
 
132
132
  $el.select2(options)
133
133
 
@@ -145,6 +145,10 @@ window.to_f = (val) ->
145
145
  val = parseFloat val, 10
146
146
  if isNaN(val) then 0.0 else val
147
147
 
148
+ window.to_fixed = (val, prec = 2) ->
149
+ return 0 unless val
150
+ (parseFloat(val) + 0.0).toFixed(prec)
151
+
148
152
  window.log = (objects...) ->
149
153
  window.logging = true
150
154
  unless window.gon?.no_log
@@ -162,4 +166,18 @@ window.clone_obj = (obj) ->
162
166
  for key of obj
163
167
  newInstance[key] = clone_obj obj[key]
164
168
 
165
- return newInstance
169
+ return newInstance
170
+
171
+
172
+ window.storeData = (key, data) ->
173
+ if _.isObject(data)
174
+ str = JSON.stringify(data)
175
+ else
176
+ str = '' + data
177
+ if window.localStorage
178
+ window.localStorage[key] = str
179
+ else
180
+ $.cookie(key, str, {path: '/'})
181
+
182
+ window.fetchData = (key) ->
183
+ window.localStorage?[key] or $.cookie(key)
@@ -0,0 +1,44 @@
1
+ class window.ViewLayout
2
+ constructor: ->
3
+ @wrap = $('#main')
4
+ @initElements()
5
+ @css_classes = @control.find('.btn').map(-> $(this).data('css')).get().join(' ')
6
+ @initHandlers()
7
+ @restoreMainCss(true)
8
+ $(document).on 'pjax:end', =>
9
+ @initElements()
10
+ @restoreMainCss()
11
+
12
+ initElements: ->
13
+ @control = $('#view_layout')
14
+ @sidebar_on = $('#toggle_sidebar_on')
15
+ @sidebar_off = $('#toggle_sidebar_off')
16
+
17
+ initHandlers: ->
18
+ self = this
19
+ $(document).on 'click', '#toggle_sidebar_off', =>
20
+ @wrap.addClass('hide_sidebar')
21
+ @storeMainCss()
22
+
23
+ $(document).on 'click', '#toggle_sidebar_on', =>
24
+ @wrap.removeClass('hide_sidebar')
25
+ @storeMainCss()
26
+
27
+ $(document).on 'click', '#view_layout .btn', ->
28
+ $el = $(this)
29
+ $el.toggleClass('active').siblings().removeClass('active')
30
+ self.wrap.removeClass(self.css_classes).toggleClass($el.data('css'), $el.hasClass('active'))
31
+ self.storeMainCss()
32
+
33
+ storeMainCss: ->
34
+ storeData('view_layout', @wrap.prop('className'))
35
+
36
+ restoreMainCss: (wrap=false) =>
37
+ css = fetchData('view_layout')
38
+ if css
39
+ @wrap.prop('className', css) if wrap
40
+ @control.find("[data-css='#{css_class}']").addClass('active') for css_class in css.split(' ')
41
+
42
+ $ ->
43
+ if $('#list')[0]
44
+ window.view_layout = new ViewLayout()
@@ -17,6 +17,25 @@ $iconWhiteSpritePath: asset-url('glyphicons-halflings-white.png', image);
17
17
  @import "ab_admin/components/geo_input";
18
18
  @import "ab_admin/components/sortable_tree";
19
19
  @import "ab_admin/components/text_styles";
20
+ @import "ab_admin/components/view_layout";
21
+
22
+ img {
23
+ max-width: none;
24
+ }
25
+
26
+ .pagination a {
27
+ background-color: white;
28
+ }
29
+
30
+ .breadcrumb {
31
+ padding: 10px 14px;
32
+ margin-bottom: 10px;
33
+ }
34
+
35
+ .well {
36
+ padding: 15px;
37
+ margin-bottom: 10px;
38
+ }
20
39
 
21
40
  .dropdown .caret {
22
41
  margin-left: 5px;
@@ -141,4 +160,7 @@ label.control-label.label-reset {
141
160
  // utility
142
161
  .over {
143
162
  overflow: visible !important;
163
+ }
164
+ .clear {
165
+ clear: both;
144
166
  }
@@ -17,15 +17,15 @@ html, body {
17
17
  float: left;
18
18
  }
19
19
  .sidebar {
20
- width: 260px;
21
- margin: 0 0 20px -265px;
20
+ width: 252px;
21
+ margin: 0 0 20px -253px;
22
22
  float: left;
23
23
  &.well {
24
24
  width: 220px;
25
25
  }
26
26
  }
27
27
  .content_with_sidebar {
28
- margin-right: 280px;
28
+ margin-right: 260px;
29
29
  overflow-x: auto;
30
30
  }
31
31
  .row-fluid .alert {
@@ -52,7 +52,7 @@
52
52
  padding: 5px 0 0 130px;
53
53
  }
54
54
  #search_cancel {
55
- margin-left: 35px;
55
+ float: right;
56
56
  }
57
57
  label {
58
58
  margin-top: 5px;
@@ -31,6 +31,8 @@
31
31
 
32
32
  .resource_actions {
33
33
  float: left;
34
+ margin-top: -10px;
35
+ margin-right: 10px;
34
36
  .btn {
35
37
  margin-right: 5px;
36
38
  }
@@ -58,7 +60,7 @@
58
60
  margin-left: -30px;
59
61
  .btn-group {
60
62
  float: left;
61
- margin-left: 15px;
63
+ margin-left: 10px;
62
64
  }
63
65
  .btn-group:first-child {
64
66
  margin-left: 30px;
@@ -70,6 +72,10 @@
70
72
  margin-left: -30%;
71
73
  }
72
74
 
75
+ #columns_hider_show {
76
+ margin-left: 10px;
77
+ }
78
+
73
79
  #lang_bar img {
74
80
  height: 16px;
75
81
  width: 24px;
@@ -85,3 +85,7 @@ table.index_table {
85
85
  margin: 0;
86
86
  }
87
87
  }
88
+
89
+ #batch_action_form {
90
+ margin-bottom: 10px;
91
+ }
@@ -0,0 +1,65 @@
1
+ #main {
2
+ &.main_wide {
3
+ #container {
4
+ display: table-row;
5
+ .wrap_content {
6
+ display: table-cell;
7
+ vertical-align: top;
8
+ float: none;
9
+ }
10
+ }
11
+ }
12
+ &.main_reverse {
13
+ .wrap_content {
14
+ width: auto;
15
+ margin-left: 260px;
16
+ }
17
+ .content_with_sidebar {
18
+ margin-right: 0;
19
+ }
20
+ .sidebar {
21
+ position: absolute;
22
+ top: 0;
23
+ left: 0;
24
+ margin-left: 5px;
25
+ }
26
+ #toggle_sidebar_off {
27
+ display: block;
28
+ position: absolute;
29
+ top: 5px;
30
+ right: 5px;
31
+ z-index: 3;
32
+ }
33
+ &.hide_sidebar {
34
+ .wrap_content {
35
+ position: absolute;
36
+ left: 16px;
37
+ z-index: 2;
38
+ margin-left: 5px;
39
+ }
40
+ #toggle_sidebar_off {
41
+ display: none;
42
+ }
43
+ #toggle_sidebar_on {
44
+ display: block;
45
+ position: absolute;
46
+ top: -1px;
47
+ left: -4px;
48
+ z-index: 3;
49
+ height: 100px;
50
+ padding: 80px 5px 0;
51
+ width: 15px;
52
+ }
53
+ }
54
+ }
55
+ #toggle_sidebar_off, #toggle_sidebar_on {
56
+ display: none;
57
+ }
58
+ #view_layout {
59
+ display: none;
60
+ float: left;
61
+ }
62
+ .table_view #view_layout {
63
+ display: block;
64
+ }
65
+ }