ab_admin 0.3.5 → 0.3.6

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