para 0.8.3 → 0.8.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA256:
3
- metadata.gz: 932450574c9f0ae3df18f694ec0e85292fae9c13e89bae9e0c4e3170acf31b5e
4
- data.tar.gz: affb81684ce4e7f0fba86a8e6f31c31e40aa5a43bcb400a6cf6e0effd964a0d6
2
+ SHA1:
3
+ metadata.gz: 8f7d2729a7b4605f42e736da01ed85636b39232c
4
+ data.tar.gz: 42a119d77586ef8db3eee57231c3a46154141e1c
5
5
  SHA512:
6
- metadata.gz: ecb83cf77fa7d9ac72461a9537e936bc72c890a755a36f6ad4441235dfdf9c7c9bc561aa17fd3352920d177bbf8e00909498c3e3548c7814b7393369bd739052
7
- data.tar.gz: 1728f4c124e70866df8eb0d83ede63a63c194eff93d3941361d62d7a43493b6126789187fc9de12f0523ad38c5af7239d3c734f17da515ce8eb5f2800952237c
6
+ metadata.gz: 44f44a2d7340fa890359d5f259f90b591f2436609399028bb77a54237f1e49b95d81435a807c452234cc58904a2a7773bd469be58b373d4074244a540a325442
7
+ data.tar.gz: 25280f88dd481faf6882df01416d85b31cc0a3fcc7204487ad53d7837bd7220463b0280141e1cdc203c577960ac103977abbd7d560ca9570fb00dd76325ec166
@@ -18,20 +18,20 @@ class Para.NestedManyField
18
18
  @$fieldsList.on('sortupdate', $.proxy(@sortUpdate, this))
19
19
 
20
20
  sortUpdate: ->
21
- @$fieldsList.find('.form-fields').each (i, el) ->
21
+ @$fieldsList.find('.form-fields:visible').each (i, el) ->
22
22
  $(el).find('.resource-position-field').val(i)
23
23
 
24
24
  initializeCocoon: ->
25
25
  @$fieldsList.on 'cocoon:after-insert', $.proxy(@afterInsertField, this)
26
26
  @$fieldsList.on 'cocoon:before-remove', $.proxy(@beforeRemoveField, this)
27
+ @$fieldsList.on 'cocoon:after-remove', $.proxy(@afterRemoveField, this)
27
28
 
28
29
  afterInsertField: (e, $element) ->
29
30
  if ($collapsible = $element.find('[data-open-on-insert="true"]')).length
30
31
  @openInsertedField($collapsible)
31
32
 
32
33
  if @orderable
33
- @$fieldsList.sortable('destroy')
34
- @initializeOrderable()
34
+ @$fieldsList.sortable('reload')
35
35
  @sortUpdate()
36
36
 
37
37
  $element.simpleForm()
@@ -42,6 +42,10 @@ class Para.NestedManyField
42
42
  # create an empty nested resource otherwise
43
43
  $nextEl.remove() if $nextEl.is('[data-attributes-mappings]') and not $element.is('[data-persisted]')
44
44
 
45
+ # When a sub field is removed, update every sub field position
46
+ afterRemoveField: ->
47
+ @sortUpdate();
48
+
45
49
  openInsertedField: ($field) ->
46
50
  $target = $($field.attr('href'))
47
51
  $target.collapse('show')
@@ -1,6 +1,8 @@
1
1
  module Para
2
2
  module Admin
3
3
  class SearchController < ApplicationController
4
+ include Para::Helpers::ResourceName
5
+
4
6
  def index
5
7
  # Parse ids that are provided as string into array
6
8
  if params[:q] && params[:q][:id_in].is_a?(String)
@@ -9,8 +11,16 @@ module Para
9
11
 
10
12
  model = params[:model_name].constantize
11
13
  @results = model.ransack(params[:q]).result
14
+ @results = @results.limit(params[:limit]) if params[:limit]
12
15
 
13
- render layout: false
16
+ case params[:mode]
17
+ when "selectize"
18
+ render json: @results.map { |res|
19
+ { text: resource_name(res), value: res.id }
20
+ }
21
+ else
22
+ render layout: false
23
+ end
14
24
  end
15
25
  end
16
26
  end
@@ -21,7 +21,7 @@ module Para
21
21
  allow_adding_resource = options.fetch(:addable, true)
22
22
 
23
23
  partial = :list
24
- partial = :tree if model.respond_to? :roots
24
+ partial = :tree if model.respond_to?(:roots) && can?(:tree, model)
25
25
 
26
26
  render(
27
27
  partial: find_partial_for(relation, partial),
@@ -48,6 +48,8 @@ module Para
48
48
  end
49
49
 
50
50
  def add_button_for(component, relation, model)
51
+ return unless can?(:create, model)
52
+
51
53
  partial_name = if component.subclassable?
52
54
  :subclassable_add_button
53
55
  else
@@ -4,6 +4,10 @@
4
4
  = render partial: find_partial_for(relation, :actions), locals: { relation: relation, component: component, model: model, allow_adding_resource: allow_adding_resource }
5
5
 
6
6
  - if resources.length > 0
7
+ - if resources.total_count > 100
8
+ .page-entries-info
9
+ = page_entries(resources)
10
+
7
11
  %ul.tree.root-tree{ data: { url: component.relation_path(model.model_name.route_key, action: :tree), :"max-depth" => max_depth_for(model) } }
8
12
  = render partial: find_partial_for(model, 'tree_item'), collection: resources.roots, as: :root, locals: { model: model}
9
13
 
@@ -1,10 +1,10 @@
1
1
  .nested-many-field{ class: [('orderable' if orderable), ('nested-many-field-inset' if inset)] }
2
2
  .fields-list{ id: dom_identifier }
3
3
  = form.simple_fields_for attribute_name, resources, nested_attribute_name: attribute_name, orderable: orderable, track_attribute_mappings: render_partial do |nested_form|
4
- = render partial: find_partial_for(model, 'nested_many/container', partial_dir: 'inputs'), locals: { form: nested_form, model: nested_form.object.class, subclass: subclass, nested_locals: nested_locals, inset: inset, render_partial: render_partial, remote_partial_params: remote_partial_params }
4
+ = render partial: find_partial_for(model, 'nested_many/container', partial_dir: 'inputs'), locals: { form: nested_form, model: nested_form.object.class, subclass: subclass, nested_locals: nested_locals, inset: inset, uncollapsed: uncollapsed, render_partial: render_partial, remote_partial_params: remote_partial_params }
5
5
  -# Add button
6
6
  - if add_button
7
7
  - if subclass
8
- = render partial: 'para/inputs/nested_many/add_with_subclasses', locals: { form: form, model: model, dom_identifier: dom_identifier, nested_locals: nested_locals, attribute_name: attribute_name, orderable: orderable, subclasses: subclasses, inset: inset, add_button_label: add_button_label, add_button_class: add_button_class, render_partial: render_partial, remote_partial_params: remote_partial_params }
8
+ = render partial: 'para/inputs/nested_many/add_with_subclasses', locals: { form: form, model: model, dom_identifier: dom_identifier, nested_locals: nested_locals, attribute_name: attribute_name, orderable: orderable, subclasses: subclasses, inset: inset, uncollapsed: uncollapsed, add_button_label: add_button_label, add_button_class: add_button_class, render_partial: render_partial, remote_partial_params: remote_partial_params }
9
9
  - else
10
- = render partial: 'para/inputs/nested_many/add', locals: { form: form, model: model, dom_identifier: dom_identifier, nested_locals: nested_locals, attribute_name: attribute_name, orderable: orderable, inset: inset, add_button_label: add_button_label, add_button_class: add_button_class, render_partial: render_partial, remote_partial_params: remote_partial_params }
10
+ = render partial: 'para/inputs/nested_many/add', locals: { form: form, model: model, dom_identifier: dom_identifier, nested_locals: nested_locals, attribute_name: attribute_name, orderable: orderable, inset: inset, uncollapsed: uncollapsed, add_button_label: add_button_label, add_button_class: add_button_class, render_partial: render_partial, remote_partial_params: remote_partial_params }
@@ -1,2 +1,2 @@
1
- = link_to_add_association form, attribute_name, partial: find_partial_for(model, 'nested_many/container', partial_dir: 'inputs'), form_name: 'form', class: "btn btn-shadow add-button nested-many-inset-add-button #{add_button_class}", data: { :'association-insertion-node' => "##{ dom_identifier }", :'association-insertion-method' => 'append' }, render_options: { nested_attribute_name: attribute_name, orderable: orderable, locals: { model: model, nested_locals: nested_locals, inset: inset, render_partial: render_partial, remote_partial_params: remote_partial_params } } do
1
+ = link_to_add_association form, attribute_name, partial: find_partial_for(model, 'nested_many/container', partial_dir: 'inputs'), form_name: 'form', class: "btn btn-shadow add-button nested-many-inset-add-button #{add_button_class}", data: { :'association-insertion-node' => "##{ dom_identifier }", :'association-insertion-method' => 'append' }, render_options: { nested_attribute_name: attribute_name, orderable: orderable, locals: { model: model, nested_locals: nested_locals, inset: inset, uncollapsed: uncollapsed, render_partial: render_partial, remote_partial_params: remote_partial_params } } do
2
2
  = add_button_label
@@ -5,5 +5,5 @@
5
5
  %ul.dropdown-menu
6
6
  - subclasses.each do |submodel|
7
7
  %li
8
- = link_to_add_association form, attribute_name, wrap_object: proc { submodel.new }, partial: find_partial_for(submodel, 'nested_many/container', partial_dir: 'inputs'), form_name: 'form', class: 'dropdown-link', data: { :'association-insertion-node' => "##{ dom_identifier }", :'association-insertion-method' => 'append' }, render_options: { nested_attribute_name: attribute_name, orderable: orderable, locals: { model: submodel, nested_locals: nested_locals, inset: inset, render_partial: render_partial, remote_partial_params: remote_partial_params } } do
8
+ = link_to_add_association form, attribute_name, wrap_object: proc { submodel.new }, partial: find_partial_for(submodel, 'nested_many/container', partial_dir: 'inputs'), form_name: 'form', class: 'dropdown-link', data: { :'association-insertion-node' => "##{ dom_identifier }", :'association-insertion-method' => 'append' }, render_options: { nested_attribute_name: attribute_name, orderable: orderable, locals: { model: submodel, nested_locals: nested_locals, inset: inset, uncollapsed: uncollapsed, render_partial: render_partial, remote_partial_params: remote_partial_params } } do
9
9
  = submodel.model_name.human
@@ -11,7 +11,7 @@
11
11
 
12
12
  = form.remove_association_button
13
13
 
14
- .panel-collapse.form-inputs.collapse{ id: form.nested_resource_dom_id, class: ('in' if inset && form.object.persisted?), data: { rendered: render_partial, render_path: @component.path(remote_partial_params), id: form.object.id, :"object-name" => form.object_name, :"model-name" => model.name } }
14
+ .panel-collapse.form-inputs.collapse{ id: form.nested_resource_dom_id, class: ('in' if uncollapsed && form.object.persisted?), data: { rendered: render_partial, render_path: @component.path(remote_partial_params), id: form.object.id, :"object-name" => form.object_name, :"model-name" => model.name } }
15
15
  .panel-body{ data: { :"nested-form-container" => true } }
16
16
  - if render_partial
17
17
  = render partial: find_partial_for(model, :fields), locals: { form: form }.merge(nested_locals)
@@ -27,9 +27,17 @@ Para.config do |config|
27
27
  # config.resource_name_methods += [:full_name]
28
28
 
29
29
  # Configure the theme navigation bar color not gray but blue darker
30
- #
30
+ #
31
31
  # config.dark_theme = true
32
32
 
33
+ # Do not uncollapse by default "inset" nested fields, which makes all such nested field
34
+ # blocks get collapsed on page load, and can be easier to read for big blocks.
35
+ #
36
+ # This also speeds up page loading when used in conjunction to remote partial loading
37
+ # for nested fields
38
+ #
39
+ # config.uncollapse_inset_nested_fields = false
40
+
33
41
  # Set if the Para::Breadcrumb::Controller module should be included into the
34
42
  # app, allowing easy breadcrumbs management in the app.
35
43
  #
@@ -43,8 +43,12 @@ module Para
43
43
  end
44
44
 
45
45
  # Takes an array of ids and a block. Check for each id if model exists
46
- # and create one if not. E.g: [12, "foo"] will try to create a model with
47
- # 'foo'
46
+ # and create one if not.
47
+ #
48
+ # Example : [12, "foo"] will try to create a model with
49
+ # 'foo' as a name, title or any other attribute referenced in
50
+ # the `Para.config.resource_name_methods` configuration param.
51
+ #
48
52
  def on_the_fly_creation ids, &block
49
53
  Array.wrap(ids).each do |id|
50
54
  if !reflection.klass.exists?(id: id)
@@ -56,7 +60,14 @@ module Para
56
60
  if resource.respond_to?(setter_name)
57
61
  resource.send(setter_name, id)
58
62
 
59
- if resource.save
63
+ # This check avoids multiple creation of the same resource with
64
+ # a given attribute value and ensure all resources from the form
65
+ # that reference that new resource name are associated to the
66
+ # same parent resource.
67
+ if (existing_resource = reflection.klass.find_by(method_name => id))
68
+ block.call(existing_resource, id)
69
+ break
70
+ elsif resource.save
60
71
  block.call(resource, id)
61
72
  break
62
73
  end
@@ -42,6 +42,9 @@ module Para
42
42
  mattr_accessor :dark_theme
43
43
  @@dark_theme = false
44
44
 
45
+ mattr_accessor :uncollapse_inset_nested_fields
46
+ @@uncollapse_inset_nested_fields = true
47
+
45
48
  # Allows changing default cache store used by Para to store jobs through
46
49
  # the ActiveJob::Status gem
47
50
  #
@@ -26,6 +26,9 @@ module Para
26
26
  file.save!
27
27
 
28
28
  store(:file_gid, file.to_global_id)
29
+
30
+ # Ensure that `.perform_now` returns the exporter
31
+ self
29
32
  end
30
33
 
31
34
  def file
@@ -27,7 +27,9 @@ module Para
27
27
  end
28
28
 
29
29
  def actions_buttons_for(options)
30
- names = [:submit, :submit_and_edit, :submit_and_add_another, :cancel]
30
+ names = [:submit, :submit_and_edit]
31
+ names << :submit_and_add_another if template.can?(:create, object.class)
32
+ names << :cancel
31
33
 
32
34
  names.select! { |name| Array.wrap(options[:only]).include?(name) } if options[:only]
33
35
  names.reject! { |name| Array.wrap(options[:except]).include?(name) } if options[:except]
@@ -26,6 +26,9 @@ module Para
26
26
  end
27
27
 
28
28
  save_errors!
29
+
30
+ # Ensure that `.perform_now` returns the importer
31
+ self
29
32
  end
30
33
 
31
34
  protected
@@ -32,6 +32,7 @@ module Para
32
32
  add_button_label: add_button_label,
33
33
  add_button_class: add_button_class,
34
34
  inset: inset?,
35
+ uncollapsed: uncollapsed?,
35
36
  render_partial: render_partial?,
36
37
  remote_partial_params: remote_partial_params
37
38
  }
@@ -50,9 +51,13 @@ module Para
50
51
  def inset?
51
52
  options.fetch(:inset, false)
52
53
  end
53
-
54
+
55
+ def uncollapsed?
56
+ inset? && Para.config.uncollapse_inset_nested_fields
57
+ end
58
+
54
59
  def render_partial?
55
- options[:render_partial] || object.errors.any? || (object.persisted? && inset?)
60
+ options[:render_partial] || object.errors.any? || (object.persisted? && uncollapsed?)
56
61
  end
57
62
 
58
63
  def remote_partial_params
@@ -2,14 +2,14 @@ module Para
2
2
  module Markup
3
3
  class ResourcesButtons < Para::Markup::Component
4
4
  attr_reader :component
5
-
5
+
6
6
  def initialize(component, view)
7
7
  @component = component
8
8
  super(view)
9
9
  end
10
10
 
11
11
  def clone_button(resource)
12
- return unless resource.class.cloneable?
12
+ return unless resource.class.cloneable? && view.can?(:clone, resource)
13
13
 
14
14
  path = component.relation_path(
15
15
  resource, action: :clone, return_to: view.request.fullpath
@@ -29,6 +29,8 @@ module Para
29
29
  end
30
30
 
31
31
  def edit_button(resource)
32
+ return unless view.can?(:edit, resource)
33
+
32
34
  path = component.relation_path(
33
35
  resource, action: :edit, return_to: view.request.fullpath
34
36
  )
@@ -39,6 +41,8 @@ module Para
39
41
  end
40
42
 
41
43
  def delete_button(resource)
44
+ return unless view.can?(:delete, resource)
45
+
42
46
  path = component.relation_path(resource, return_to: view.request.fullpath)
43
47
 
44
48
  options = {
@@ -5,7 +5,7 @@ module Para
5
5
  self.default_actions = [:edit, :clone, :delete]
6
6
 
7
7
  attr_reader :component, :model, :orderable, :actions
8
-
8
+
9
9
  def initialize(component, view)
10
10
  @component = component
11
11
  super(view)
@@ -15,7 +15,7 @@ module Para
15
15
  @model = options.delete(:model)
16
16
 
17
17
  if !options.key?(:orderable) || options.delete(:orderable)
18
- @orderable = model.orderable?
18
+ @orderable = model.orderable? && view.can?(:order, model)
19
19
  end
20
20
 
21
21
  @actions = build_actions(options.delete(:actions))
@@ -93,7 +93,7 @@ module Para
93
93
 
94
94
  content_tag(:th, options) do
95
95
  if (sort = options.delete(:sort))
96
- view.sort_link(search, *sort, label, hide_indicator: true)
96
+ view.sort_link(search, *sort, label, hide_indicator: true)
97
97
  elsif searchable?(field_name)
98
98
  view.sort_link(search, field_name, label, hide_indicator: true)
99
99
  else
@@ -1,3 +1,3 @@
1
1
  module Para
2
- VERSION = '0.8.3'
2
+ VERSION = '0.8.7'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: para
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.3
4
+ version: 0.8.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Valentin Ballestrino
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-08-23 00:00:00.000000000 Z
11
+ date: 2020-10-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -168,14 +168,14 @@ dependencies:
168
168
  requirements:
169
169
  - - "~>"
170
170
  - !ruby/object:Gem::Version
171
- version: '1.9'
171
+ version: '3.0'
172
172
  type: :runtime
173
173
  prerelease: false
174
174
  version_requirements: !ruby/object:Gem::Requirement
175
175
  requirements:
176
176
  - - "~>"
177
177
  - !ruby/object:Gem::Version
178
- version: '1.9'
178
+ version: '3.0'
179
179
  - !ruby/object:Gem::Dependency
180
180
  name: kaminari
181
181
  requirement: !ruby/object:Gem::Requirement
@@ -849,7 +849,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
849
849
  - !ruby/object:Gem::Version
850
850
  version: '0'
851
851
  requirements: []
852
- rubygems_version: 3.0.3
852
+ rubyforge_project:
853
+ rubygems_version: 2.6.11
853
854
  signing_key:
854
855
  specification_version: 4
855
856
  summary: Rails admin engine