para 0.12.1 → 0.12.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5ee25a77e578b14d822cbf8827991f6c6920c580acddeb2120d0e6a2570795fa
4
- data.tar.gz: 41ee3d94327eeeacfb5ee1da6430956d5862ed0e242d0d09180bef828e46a921
3
+ metadata.gz: d2e8f3dd97232094cbf6840ad5ec462068c43019dec82f3c872d48bb5f0d8ffa
4
+ data.tar.gz: 2b3d6cd3dbfa31daef6cdca4e3e040843f10e350f02c9687dec51f1c641de12c
5
5
  SHA512:
6
- metadata.gz: acd659f13038e225325293d30820d115f5054ca6ba36cccc44e5404bc2e5d0e01226815b41aa38bc3f8c76f6299891c621c4e7d1d2306eaaa76a9f1c97f24891
7
- data.tar.gz: 7da8328b9591a785d922ddd3f12c61f95d57f7c3e8a327b5667ad22cbfabeeaaabac1c7c8d0e6ed50dee7bc48ceb7e172aac92b3a9593b6919678e4b957bcc1a
6
+ metadata.gz: 1c5d0d01332d290463ac6b3c856e2260ee62625ceb9a9e76ea0887f13188ce7df691b23be95e40b20b271a19c5650975844944c6bf1f50262b8677eaa7189d86
7
+ data.tar.gz: 29ad0aba0dc5ac675f601e8891641aa28e38649550202a03858c46a9703e2a257a52e09bf5ee21ce74f6ca21e877c141888f081ffdba6b88c69fb1bafa4cadd3
@@ -31,12 +31,15 @@
31
31
  content: "\f0dc";
32
32
  opacity: .3;
33
33
  }
34
+
34
35
  .sort_link.asc:before {
35
- content: "\f0d7";
36
+ content: "\f0d8";
36
37
  }
38
+
37
39
  .sort_link.desc:before {
38
- content: "\f0d8";
40
+ content: "\f0d7";
39
41
  }
42
+
40
43
  .sort_link.asc.disabled:before,
41
44
  .sort_link.desc.disabled:before {
42
45
  opacity: .1;
@@ -22,11 +22,11 @@ function trackProgressFor(element, jobStatusUrl) {
22
22
  }
23
23
 
24
24
  document.documentElement.addEventListener('turbo:frame-load', function(e) {
25
- if (e.target.id != 'para_admin_modal') return;
25
+ if (e.target.id !== 'para_admin_modal') return;
26
26
 
27
27
  loadedElement = e.target.childNodes[0];
28
28
 
29
- var jobStatusUrl = loadedElement && loadedElement.dataset.jobStatusUrl;
29
+ var jobStatusUrl = loadedElement?.dataset?.jobStatusUrl;
30
30
  if (!jobStatusUrl) return;
31
31
 
32
32
  trackProgressFor(loadedElement, jobStatusUrl);
@@ -8,3 +8,6 @@ application.register("para-admin-flash-message", ParaAdminFlashMessageController
8
8
 
9
9
  import SelectizeFieldController from "./selectize_field_controller";
10
10
  application.register("selectize-field", SelectizeFieldController);
11
+
12
+ import NestedManyInputController from "./nested_many_input_controller";
13
+ application.register("nested-many-input", NestedManyInputController);
@@ -1,52 +1,70 @@
1
- Para.NestedManyField = class NestedManyField {
2
- constructor($field1) {
1
+ import { Controller } from '@hotwired/stimulus';
2
+
3
+ export default class extends Controller {
4
+ connect() {
3
5
  this.stoppingPropagation = this.stoppingPropagation.bind(this);
4
6
  this.afterInsertField = this.afterInsertField.bind(this);
5
7
  this.beforeRemoveField = this.beforeRemoveField.bind(this);
6
- // When a sub field is removed, update every sub field position
8
+ this.handleOrderingUpdated = this.handleOrderingUpdated.bind(this);
7
9
  this.afterRemoveField = this.afterRemoveField.bind(this);
8
10
  this.collapseShown = this.collapseShown.bind(this);
9
- this.$field = $field1;
11
+
12
+ this.$field = $(this.element);
10
13
  this.$fieldsList = this.$field.find('.fields-list');
11
- this.initializeOrderable();
14
+ this.initializeSortable();
12
15
  this.initializeCocoon();
13
16
  this.$field.on('shown.bs.collapse', this.stoppingPropagation(this.collapseShown));
14
17
  }
15
18
 
16
- initializeOrderable() {
17
- this.orderable = this.$field.hasClass('orderable');
18
- if (!this.orderable) {
19
- return;
20
- }
19
+ initializeSortable() {
20
+ this.isSortable = this.$field.hasClass('orderable');
21
+
22
+ if (!this.isSortable) return;
23
+
21
24
  return this.$fieldsList.sortable({
22
25
  handle: '.order-anchor',
23
26
  animation: 150,
24
- onUpdate: $.proxy(this.handleOrderingUpdated, this)
27
+ onUpdate: this.handleOrderingUpdated
25
28
  });
26
29
  }
27
30
 
28
31
  handleOrderingUpdated() {
29
32
  var formFields;
30
33
  formFields = [];
34
+
31
35
  return this.$fieldsList.find('.form-fields:visible').each(function(_i, el) {
32
- var $el, $parent, isNestedField, j, len;
36
+ let $parent, isNestedField, j, len;
37
+
33
38
  for (j = 0, len = formFields.length; j < len; j++) {
34
39
  $parent = formFields[j];
35
40
  isNestedField = $parent.find(el).length;
36
41
  }
42
+
37
43
  if (isNestedField) {
38
44
  return;
39
45
  }
40
- $el = $(el);
46
+
47
+ const $el = $(el);
41
48
  $el.find('.resource-position-field:eq(0)').val(formFields.length);
42
49
  return formFields.push($el);
43
50
  });
44
51
  }
45
52
 
46
53
  initializeCocoon() {
47
- this.$fieldsList.on('cocoon:after-insert', this.stoppingPropagation(this.afterInsertField));
48
- this.$fieldsList.on('cocoon:before-remove', this.stoppingPropagation(this.beforeRemoveField));
49
- return this.$fieldsList.on('cocoon:after-remove', this.stoppingPropagation(this.afterRemoveField));
54
+ this.$fieldsList.on(
55
+ 'cocoon:after-insert',
56
+ this.stoppingPropagation(this.afterInsertField)
57
+ );
58
+
59
+ this.$fieldsList.on(
60
+ 'cocoon:before-remove',
61
+ this.stoppingPropagation(this.beforeRemoveField)
62
+ );
63
+
64
+ return this.$fieldsList.on(
65
+ 'cocoon:after-remove',
66
+ this.stoppingPropagation(this.afterRemoveField)
67
+ );
50
68
  }
51
69
 
52
70
  stoppingPropagation(callback) {
@@ -61,9 +79,9 @@ Para.NestedManyField = class NestedManyField {
61
79
  if (($collapsible = $element.find('[data-open-on-insert="true"]')).length) {
62
80
  this.openInsertedField($collapsible);
63
81
  }
64
- if (this.orderable) {
82
+ if (this.isSortable) {
65
83
  this.$fieldsList.sortable('destroy');
66
- this.initializeOrderable();
84
+ this.initializeSortable();
67
85
  this.handleOrderingUpdated();
68
86
  }
69
87
  return $element.simpleForm();
@@ -90,22 +108,24 @@ Para.NestedManyField = class NestedManyField {
90
108
  }
91
109
 
92
110
  collapseShown(e) {
93
- var $target;
94
- $target = $(e.target);
95
- if ($target.is("[data-rendered]") || $target.data("rendered")) {
96
- return this.initializeCollapseContent($target);
111
+ const { target } = e;
112
+
113
+ if (target.dataset.isRendered) {
114
+ return this.initializeCollapseContent(target);
97
115
  } else {
98
- this.loadCollapseContent($target);
99
- return this.scrollToTarget($target);
116
+ this.loadCollapseContent(target);
117
+ return this.scrollToTarget(target);
100
118
  }
101
119
  }
102
120
 
103
- initializeCollapseContent($target) {
104
- this.scrollToTarget($target);
105
- return this.focusFirstField($target);
121
+ initializeCollapseContent(target) {
122
+ this.scrollToTarget(target);
123
+ return this.focusFirstVisibleInputInside(target);
106
124
  }
107
125
 
108
- scrollToTarget($target) {
126
+ scrollToTarget(target) {
127
+ const $target = $(target);
128
+
109
129
  var $affixNavTabs, $field, scrollOffset;
110
130
  $field = this.$field.find(`[data-toggle='collapse'][href='#${$target.attr('id')}']`);
111
131
  scrollOffset = -($('[data-header]').outerHeight() + 30);
@@ -117,35 +137,32 @@ Para.NestedManyField = class NestedManyField {
117
137
  });
118
138
  }
119
139
 
120
- focusFirstField($target) {
121
- return $target.find('input, textarea, select').eq('0').focus();
140
+ focusFirstVisibleInputInside(target) {
141
+ setTimeout(() => {
142
+ target.querySelector('input:not([type="hidden"]), textarea, select')?.focus();
143
+ }, 100);
122
144
  }
123
145
 
124
- loadCollapseContent($target) {
125
- var data, targetUrl;
126
- targetUrl = $target.data("render-path");
127
- if (!targetUrl) {
128
- return;
129
- }
130
- data = {
131
- "id": $target.data("id"),
132
- "object_name": $target.data("object-name"),
133
- "model_name": $target.data("model-name")
146
+ loadCollapseContent(target) {
147
+ const $target = $(target);
148
+ const targetUrl = target.dataset.renderPath;
149
+
150
+ if (!targetUrl) return;
151
+
152
+ const data = {
153
+ id: target.dataset.id,
154
+ object_name: target.dataset.objectName,
155
+ model_name: target.dataset.modelName
134
156
  };
135
- return $.get(targetUrl, data).then((resp) => {
136
- var $content;
137
- $content = $(resp);
138
- $target.find("[data-nested-form-container]:eq(0)").html($content);
157
+
158
+ $.get(targetUrl, data).then((resp) => {
159
+ const $content = $(resp);
160
+ $target.find('[data-nested-form-container]:eq(0)').html($content);
139
161
  $content.simpleForm();
140
- this.focusFirstField($target);
141
- return $target.data("rendered", true);
162
+
163
+ this.focusFirstVisibleInputInside(target);
164
+
165
+ target.dataset.isRendered = true;
142
166
  });
143
167
  }
144
-
145
168
  };
146
-
147
- $.simpleForm.onDomReady(function($document) {
148
- return $document.find('.nested-many-field').each(function(i, el) {
149
- return new Para.NestedManyField($(el));
150
- });
151
- });
@@ -14,11 +14,7 @@ import "./vendor/jquery.sortable";
14
14
 
15
15
  import "./application";
16
16
 
17
- import "./lib/page-loading";
18
-
19
- import "./inputs/material-input";
20
17
  import "./inputs/multi-select-input";
21
- import "./inputs/nested_many";
22
18
 
23
19
  import "./admin/async-progress";
24
20
  import "./admin/filters-form";
@@ -1,4 +1,4 @@
1
- .nested-many-field{ class: [('orderable' if orderable), ('nested-many-field-inset' if inset)] }
1
+ .nested-many-field{ class: [('orderable' if orderable), ('nested-many-field-inset' if inset)], data: { controller: "nested-many-input" } }
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
4
  = render partial: find_partial_for(model, 'nested_many/container', partial_dir: 'inputs'), locals: { form: nested_form, model: nested_form.object.class, subclass: subclass, allow_destroy_if: allow_destroy_if, nested_locals: nested_locals, inset: inset, uncollapsed: uncollapsed, render_partial: render_partial, remote_partial_params: remote_partial_params }
@@ -56,6 +56,10 @@ module Para
56
56
 
57
57
  reference = model.reflect_on_all_associations.find do |association|
58
58
  association.foreign_key == name
59
+ rescue ArgumentError
60
+ # This can happen when the association is polymorphic and the foreign key can't
61
+ # be determined, in this case, we just ignore the association.
62
+ false
59
63
  end
60
64
 
61
65
  if reference
@@ -75,12 +79,11 @@ module Para
75
79
  true
76
80
  end
77
81
 
78
- #
79
82
  def searchable?
80
83
  options[:searchable] != false && (
81
- [:string, :text].include?(type.to_sym) && !name.match(/password/)
84
+ %i[string text].include?(type.to_sym) && !name.match(/password/)
82
85
  ) && (
83
- !model.respond_to?(:ransackable_attributes) ||
86
+ !model.respond_to?(:ransackable_attributes) ||
84
87
  model.ransackable_attributes.include?(name.to_s)
85
88
  )
86
89
  end
@@ -94,7 +97,7 @@ module Para
94
97
  def field_options
95
98
  self.class._field_options.each_with_object({}) do |params, hash|
96
99
  value = send(params[:method_name])
97
- hash[params[:key]] = value if value != nil || params[:options][:allow_nil]
100
+ hash[params[:key]] = value if !value.nil? || params[:options][:allow_nil]
98
101
  end
99
102
  end
100
103
 
@@ -42,8 +42,10 @@ module Para
42
42
  # attributes mappings above
43
43
  next if AttributeField::RelationField == fields_hash[name]
44
44
 
45
- # Remove foreign key, if existing, from fields
46
- fields_hash.delete(reflection.foreign_key.to_s)
45
+ unless through_polymorphic_reflection?(reflection)
46
+ # Remove foreign key, if existing, from fields
47
+ fields_hash.delete(reflection.foreign_key.to_s)
48
+ end
47
49
 
48
50
  # Do not process polymorphic belongs to for now ...
49
51
  if reflection.options[:polymorphic] == true
@@ -52,27 +54,25 @@ module Para
52
54
  end
53
55
 
54
56
  if model.nested_attributes_options[name]
55
- if reflection.collection?
56
- fields_hash[name] = AttributeField::NestedManyField.new(
57
- model, name: name, type: 'has_many', field_type: 'nested_many'
58
- )
59
- else
60
- fields_hash[name] = AttributeField::NestedOneField.new(
61
- model, name: name, type: 'belongs_to', field_type: 'nested_one'
62
- )
63
- end
64
- else
65
- if reflection.collection?
66
- remove_counter_cache_column!(name, reflection)
57
+ fields_hash[name] = if reflection.collection?
58
+ AttributeField::NestedManyField.new(
59
+ model, name: name, type: 'has_many', field_type: 'nested_many'
60
+ )
61
+ else
62
+ AttributeField::NestedOneField.new(
63
+ model, name: name, type: 'belongs_to', field_type: 'nested_one'
64
+ )
65
+ end
66
+ elsif reflection.collection?
67
+ remove_counter_cache_column!(name, reflection)
67
68
 
68
- fields_hash[name] = AttributeField::HasManyField.new(
69
- model, name: name, type: 'has_many', field_type: 'multi_select'
70
- )
71
- elsif !reflection.options[:through]
72
- fields_hash[name] = AttributeField::BelongsToField.new(
73
- model, name: name, type: 'belongs_to', field_type: 'selectize'
74
- )
75
- end
69
+ fields_hash[name] = AttributeField::HasManyField.new(
70
+ model, name: name, type: 'has_many', field_type: 'multi_select'
71
+ )
72
+ elsif !reflection.options[:through]
73
+ fields_hash[name] = AttributeField::BelongsToField.new(
74
+ model, name: name, type: 'belongs_to', field_type: 'selectize'
75
+ )
76
76
  end
77
77
  end
78
78
  end
@@ -84,14 +84,23 @@ module Para
84
84
  return unless (inverse_relation = reflection.inverse_of)
85
85
  return unless (counter_name = inverse_relation.options[:counter_cache])
86
86
 
87
- counter_name = if String === counter_name
88
- counter_name
89
- else
90
- "#{ name }_count"
91
- end
87
+ counter_name = if counter_name.is_a?(String)
88
+ counter_name
89
+ else
90
+ "#{name}_count"
91
+ end
92
92
 
93
93
  fields_hash.delete(counter_name)
94
94
  end
95
+
96
+ def through_polymorphic_reflection?(reflection)
97
+ reflection.through_reflection? && (
98
+ (
99
+ reflection.through_reflection.options[:polymorphic] &&
100
+ !reflection.through_reflection.options[:source_type]
101
+ ) || through_polymorphic_reflection?(reflection.through_reflection)
102
+ )
103
+ end
95
104
  end
96
105
  end
97
106
  end
data/lib/para/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Para
4
- VERSION = '0.12.1'
4
+ VERSION = '0.12.3'
5
5
  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.12.1
4
+ version: 0.12.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Valentin Ballestrino
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-06-06 00:00:00.000000000 Z
11
+ date: 2024-08-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: active_decorator
@@ -479,15 +479,13 @@ files:
479
479
  - app/javascripts/para/application.js
480
480
  - app/javascripts/para/controllers/application.js
481
481
  - app/javascripts/para/controllers/index.js
482
+ - app/javascripts/para/controllers/nested_many_input_controller.js
482
483
  - app/javascripts/para/controllers/para_admin_flash_message_controller.js
483
484
  - app/javascripts/para/controllers/para_admin_modal_controller.js
484
485
  - app/javascripts/para/controllers/selectize_field_controller.js
485
486
  - app/javascripts/para/index.js
486
- - app/javascripts/para/inputs/material-input.js
487
487
  - app/javascripts/para/inputs/multi-select-input.js
488
- - app/javascripts/para/inputs/nested_many.js
489
488
  - app/javascripts/para/lib/fetch.js
490
- - app/javascripts/para/lib/page-loading.js
491
489
  - app/javascripts/para/plugins-includes.js.erb
492
490
  - app/javascripts/para/simple_form_extension/colorpicker.js
493
491
  - app/javascripts/para/simple_form_extension/datetimepicker.js
@@ -794,7 +792,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
794
792
  - !ruby/object:Gem::Version
795
793
  version: '0'
796
794
  requirements: []
797
- rubygems_version: 3.4.8
795
+ rubygems_version: 3.5.17
798
796
  signing_key:
799
797
  specification_version: 4
800
798
  summary: Rails admin engine
@@ -1,7 +0,0 @@
1
- $(document).on('page:change turbo:load turbo:frame-load', function() {
2
- return $('body').on('focusin focusout', 'input, select, textarea', function(e) {
3
- var focused;
4
- focused = e.type === 'focusin';
5
- return $(e.target).closest('.form-group').toggleClass('focused', focused);
6
- });
7
- });
@@ -1,42 +0,0 @@
1
- Para.PageLoading = class PageLoading {
2
- constructor() {
3
- this.start = this.start.bind(this);
4
- this.stop = this.stop.bind(this);
5
- }
6
-
7
- start() {
8
- return this.addLoadingMarkup();
9
- }
10
-
11
- stop() {
12
- return this.removeLoadingMarkup();
13
- }
14
-
15
- addLoadingMarkup() {
16
- $('<div/>', {
17
- class: 'loading-overlay',
18
- 'data-loading-overlay': true
19
- }).prependTo('body');
20
-
21
- $('<div/>', {
22
- class: 'loading-spinner',
23
- 'data-loading-spinner': true
24
- }).prependTo('body');
25
- }
26
-
27
- removeLoadingMarkup() {
28
- $('[data-loading-overlay]').remove();
29
- return $('[data-loading-spinner]').remove();
30
- }
31
-
32
- };
33
-
34
- // Global loading manager allowing to
35
- Para.loadingManager = new Para.PageLoading();
36
-
37
- $(document).on('turbo:before-fetch-request', Para.loadingManager.start);
38
-
39
- $(document).on('turbo:load turbo:frame-load turbo:before-stream-render turbo:frame-missing turbo:fetch-request-error', function() {
40
- Para.loadingManager.stop();
41
- return $('body').on('submit', '[data-para-form]:not([data-remote])', Para.loadingManager.start);
42
- });