decidim-forms 0.22.0 → 0.23.0

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 (113) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/config/admin/decidim_forms_manifest.css +3 -0
  3. data/app/assets/config/decidim_forms_manifest.css +1 -0
  4. data/app/assets/javascripts/decidim/forms/admin/auto_select_options_from_url.component.js.es6 +40 -0
  5. data/app/assets/javascripts/decidim/forms/admin/forms.js.es6 +181 -25
  6. data/app/assets/javascripts/decidim/forms/autosortable_checkboxes.component.js.es6 +54 -34
  7. data/app/assets/javascripts/decidim/forms/display_conditions.component.js.es6 +204 -0
  8. data/app/assets/javascripts/decidim/forms/forms.js.es6 +8 -1
  9. data/app/assets/stylesheets/decidim/forms/questionnaire-answers-pdf.scss +69 -0
  10. data/app/commands/decidim/forms/admin/update_questionnaire.rb +25 -1
  11. data/app/commands/decidim/forms/answer_questionnaire.rb +1 -1
  12. data/app/controllers/decidim/forms/admin/concerns/has_questionnaire.rb +47 -1
  13. data/app/controllers/decidim/forms/admin/concerns/has_questionnaire_answers.rb +97 -0
  14. data/app/forms/decidim/forms/admin/display_condition_form.rb +100 -0
  15. data/app/forms/decidim/forms/admin/question_form.rb +1 -0
  16. data/app/forms/decidim/forms/answer_form.rb +15 -0
  17. data/app/helpers/decidim/forms/admin/application_helper.rb +21 -0
  18. data/app/helpers/decidim/forms/admin/concerns/has_questionnaire_answers_pagination_helper.rb +49 -0
  19. data/app/helpers/decidim/forms/admin/concerns/has_questionnaire_answers_url_helper.rb +40 -0
  20. data/app/helpers/decidim/forms/admin/questionnaire_answers_helper.rb +27 -0
  21. data/app/jobs/decidim/forms/export_questionnaire_answers_job.rb +19 -0
  22. data/app/models/decidim/forms/answer.rb +0 -3
  23. data/app/models/decidim/forms/answer_option.rb +14 -0
  24. data/app/models/decidim/forms/display_condition.rb +51 -0
  25. data/app/models/decidim/forms/question.rb +34 -0
  26. data/app/models/decidim/forms/question_matrix_row.rb +3 -0
  27. data/app/models/decidim/forms/questionnaire.rb +11 -1
  28. data/app/presenters/decidim/forms/admin/questionnaire_answer_presenter.rb +43 -0
  29. data/app/presenters/decidim/forms/admin/questionnaire_participant_presenter.rb +60 -0
  30. data/app/presenters/decidim/forms/answer_option_presenter.rb +20 -0
  31. data/app/presenters/decidim/forms/question_presenter.rb +16 -0
  32. data/app/queries/decidim/forms/questionnaire_participant.rb +35 -0
  33. data/app/queries/decidim/forms/questionnaire_participants.rb +43 -0
  34. data/app/views/decidim/forms/admin/questionnaires/_display_condition.html.erb +88 -0
  35. data/app/views/decidim/forms/admin/questionnaires/_display_condition_template.html.erb +7 -0
  36. data/app/views/decidim/forms/admin/questionnaires/_form.html.erb +30 -4
  37. data/app/views/decidim/forms/admin/questionnaires/_question.html.erb +19 -3
  38. data/app/views/decidim/forms/admin/questionnaires/answers/export/_answer.html.erb +31 -0
  39. data/app/views/decidim/forms/admin/questionnaires/answers/export/pdf.html.erb +13 -0
  40. data/app/views/decidim/forms/admin/questionnaires/answers/index.html.erb +53 -0
  41. data/app/views/decidim/forms/admin/questionnaires/answers/show.html.erb +48 -0
  42. data/app/views/decidim/forms/admin/questionnaires/edit.html.erb +9 -5
  43. data/app/views/decidim/forms/questionnaires/_answer.html.erb +1 -1
  44. data/app/views/decidim/forms/questionnaires/show.html.erb +22 -2
  45. data/app/views/layouts/decidim/forms/admin/questionnaires/questionnaire_answers.html.erb +12 -0
  46. data/config/initializers/wicked_pdf.rb +25 -0
  47. data/config/locales/am-ET.yml +1 -0
  48. data/config/locales/ar.yml +0 -1
  49. data/config/locales/bg-BG.yml +0 -2
  50. data/config/locales/bg.yml +14 -0
  51. data/config/locales/ca.yml +56 -4
  52. data/config/locales/cs.yml +54 -2
  53. data/config/locales/da.yml +1 -0
  54. data/config/locales/de.yml +51 -1
  55. data/config/locales/el.yml +0 -2
  56. data/config/locales/en.yml +54 -2
  57. data/config/locales/eo.yml +1 -0
  58. data/config/locales/es-MX.yml +53 -1
  59. data/config/locales/es-PY.yml +53 -1
  60. data/config/locales/es.yml +54 -2
  61. data/config/locales/et.yml +1 -0
  62. data/config/locales/eu.yml +0 -1
  63. data/config/locales/fi-plain.yml +53 -1
  64. data/config/locales/fi.yml +53 -1
  65. data/config/locales/fr-CA.yml +54 -2
  66. data/config/locales/fr.yml +54 -2
  67. data/config/locales/gl.yml +0 -1
  68. data/config/locales/hr.yml +1 -0
  69. data/config/locales/hu.yml +0 -2
  70. data/config/locales/id-ID.yml +0 -1
  71. data/config/locales/is.yml +1 -0
  72. data/config/locales/it.yml +53 -1
  73. data/config/locales/ja-JP.yml +51 -1
  74. data/config/locales/ja.yml +170 -0
  75. data/config/locales/ko-KR.yml +1 -0
  76. data/config/locales/ko.yml +1 -0
  77. data/config/locales/lt.yml +1 -0
  78. data/config/locales/{lv-LV.yml → lv.yml} +0 -1
  79. data/config/locales/mt.yml +1 -0
  80. data/config/locales/nl.yml +59 -7
  81. data/config/locales/no.yml +47 -2
  82. data/config/locales/om-ET.yml +1 -0
  83. data/config/locales/pl.yml +52 -3
  84. data/config/locales/pt-BR.yml +0 -1
  85. data/config/locales/pt.yml +51 -2
  86. data/config/locales/ro-RO.yml +51 -2
  87. data/config/locales/ru.yml +0 -1
  88. data/config/locales/sk.yml +0 -2
  89. data/config/locales/sl.yml +7 -0
  90. data/config/locales/so-SO.yml +1 -0
  91. data/config/locales/sv.yml +51 -2
  92. data/config/locales/ti-ER.yml +1 -0
  93. data/config/locales/tr-TR.yml +0 -1
  94. data/config/locales/vi-VN.yml +1 -0
  95. data/config/locales/vi.yml +1 -0
  96. data/config/locales/zh-CN.yml +172 -0
  97. data/config/locales/zh-TW.yml +1 -0
  98. data/db/migrate/20200130194123_create_decidim_forms_display_conditions.rb +20 -0
  99. data/lib/decidim/exporters/form_pdf.rb +33 -0
  100. data/lib/decidim/exporters/form_pdf_controller_helper.rb +11 -0
  101. data/lib/decidim/forms.rb +5 -0
  102. data/lib/decidim/forms/admin_engine.rb +1 -1
  103. data/lib/decidim/forms/test.rb +6 -0
  104. data/lib/decidim/forms/test/factories.rb +30 -0
  105. data/lib/decidim/forms/test/shared_examples/has_questionnaire.rb +619 -38
  106. data/lib/decidim/forms/test/shared_examples/manage_questionnaire_answers.rb +108 -0
  107. data/lib/decidim/forms/test/shared_examples/manage_questionnaires.rb +21 -894
  108. data/lib/decidim/forms/test/shared_examples/manage_questionnaires/add_display_conditions.rb +179 -0
  109. data/lib/decidim/forms/test/shared_examples/manage_questionnaires/add_questions.rb +463 -0
  110. data/lib/decidim/forms/test/shared_examples/manage_questionnaires/update_display_conditions.rb +93 -0
  111. data/lib/decidim/forms/test/shared_examples/manage_questionnaires/update_questions.rb +461 -0
  112. data/lib/decidim/forms/version.rb +1 -1
  113. metadata +91 -11
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 73b7dd5e0d7e94151c79b989666d5a3d1e3790db9c97cee7a35c587a0a00977e
4
- data.tar.gz: 4e7f6a2d27f58079d5eed9d08404373a66636f6960a220dc1572809a482dfbb3
3
+ metadata.gz: 0f8714ccc1417cbe818e4eac8a9aba7c5ae7882047c6bbb89c74615421e603cd
4
+ data.tar.gz: 5632f71135c4614f6ebcaca269c2779f3ed131b90ba756e4154baa753878ddba
5
5
  SHA512:
6
- metadata.gz: b2eed83cff858299ee6fef944b1951150ad4634a193fec095ca20a393bfec8de0f1a2fe1e09447728d40dbb2898ce4b884d4ab82cdecaf93c6025efd1d677bd5
7
- data.tar.gz: e1e84f6aa8d5a1cb2ea2fe95593bd0ba0977d536c4abb3a3cc66726cf66a425dd7c1622f462cc9324c5fbf0d375e0dcc43c2844eb0b0fafc5457f97d34a6de70
6
+ metadata.gz: 58a20ef3965ef39541a29a672f2322b284047083750f9d3c9be87db8a8acfebea1aad8a51d8890c04346afd8665cdb9c6aa625422b52102baf3322dd686bd2d1
7
+ data.tar.gz: c0658ed8a17502cb807e2616f7ebb09e78b119ab8473e0e65955d5706cc5ba3cad58321f741c17ea3e09ae5c71ac7daed8d18480dcdd2a6cfda892e22efdb18f
@@ -0,0 +1,3 @@
1
+ /*
2
+ *= link decidim/forms/questionnaire-answers-pdf.scss
3
+ */
@@ -1,3 +1,4 @@
1
1
  /*
2
2
  *= link decidim/forms/forms.scss
3
+ *= link decidim/forms/questionnaire-answers-pdf.scss
3
4
  */
@@ -0,0 +1,40 @@
1
+ ((exports) => {
2
+ class AutoSelectOptionsFromUrl {
3
+ constructor(options = {}) {
4
+ this.$source = options.source;
5
+ this.$select = options.select;
6
+ this.sourceToParams = options.sourceToParams;
7
+ this.run();
8
+ }
9
+
10
+ run() {
11
+ this.$source.on("change", this._onSourceChange.bind(this));
12
+ this._onSourceChange();
13
+ }
14
+
15
+ _onSourceChange() {
16
+ const select = this.$select;
17
+ const params = this.sourceToParams(this.$source);
18
+ const url = this.$source.data("url");
19
+
20
+ $.getJSON(url, params, function (data) {
21
+ select.find("option:not([value=''])").remove();
22
+ const selectedValue = select.data("selected");
23
+
24
+ data.forEach((option) => {
25
+ let optionElement = $(`<option value="${option.id}">${option.body}</option>`).appendTo(select);
26
+ if (option.id === selectedValue) {
27
+ optionElement.attr("selected", true);
28
+ }
29
+ });
30
+
31
+ if (selectedValue) {
32
+ select.val(selectedValue);
33
+ }
34
+ });
35
+ }
36
+ }
37
+
38
+ exports.DecidimAdmin = exports.DecidimAdmin || {};
39
+ exports.DecidimAdmin.AutoSelectOptionsFromUrl = AutoSelectOptionsFromUrl;
40
+ })(window);
@@ -1,9 +1,12 @@
1
+ /* eslint-disable max-lines */
2
+
1
3
  // = require ./auto_buttons_by_min_items.component
2
4
  // = require ./auto_select_options_by_total_items.component
5
+ // = require ./auto_select_options_from_url.component
3
6
  // = require ./live_text_update.component
4
7
 
5
8
  ((exports) => {
6
- const { AutoLabelByPositionComponent, AutoButtonsByPositionComponent, AutoButtonsByMinItemsComponent, AutoSelectOptionsByTotalItemsComponent, createLiveTextUpdateComponent, createFieldDependentInputs, createDynamicFields, createSortList } = exports.DecidimAdmin;
9
+ const { AutoLabelByPositionComponent, AutoButtonsByPositionComponent, AutoButtonsByMinItemsComponent, AutoSelectOptionsByTotalItemsComponent, AutoSelectOptionsFromUrl, createLiveTextUpdateComponent, createFieldDependentInputs, createDynamicFields, createSortList } = exports.DecidimAdmin;
7
10
  const { createQuillEditor } = exports.Decidim;
8
11
 
9
12
  const wrapperSelector = ".questionnaire-questions";
@@ -18,22 +21,54 @@
18
21
  const addMatrixRowButtonSelector = ".add-matrix-row";
19
22
  const maxChoicesWrapperSelector = ".questionnaire-question-max-choices";
20
23
 
21
- const MULTIPLE_CHOICE_VALUES = ["single_option", "multiple_option", "sorting", "matrix_single", "matrix_multiple"];
22
- const MATRIX_VALUES = ["matrix_single", "matrix_multiple"];
24
+ const displayConditionFieldSelector = ".questionnaire-question-display-condition";
25
+ const displayConditionsWrapperSelector = ".questionnaire-question-display-conditions";
26
+ const displayConditionRemoveFieldButtonSelector = ".remove-display-condition";
27
+
28
+ const displayConditionQuestionSelector = "select[name$=\\[decidim_condition_question_id\\]]";
29
+ const displayConditionAnswerOptionSelector = "select[name$=\\[decidim_answer_option_id\\]]";
30
+ const displayConditionTypeSelector = "select[name$=\\[condition_type\\]]";
31
+ const deletedInputSelector = "input[name$=\\[deleted\\]]";
32
+
33
+ const displayConditionValueWrapperSelector = ".questionnaire-question-display-condition-value";
34
+ const displayconditionAnswerOptionWrapperSelector = ".questionnaire-question-display-condition-answer-option";
35
+
36
+ const addDisplayConditionButtonSelector = ".add-display-condition";
37
+
38
+ const removeDisplayConditionsForFirstQuestion = () => {
39
+ $(fieldSelector).each((idx, el) => {
40
+ const $question = $(el);
41
+ if (idx) {
42
+ $question.find(displayConditionsWrapperSelector).find(deletedInputSelector).val("false");
43
+ $question.find(displayConditionsWrapperSelector).show();
44
+ }
45
+ else {
46
+ $question.find(displayConditionsWrapperSelector).find(deletedInputSelector).val("true");
47
+ $question.find(displayConditionsWrapperSelector).hide();
48
+ }
49
+ });
50
+ };
51
+
52
+ const autoButtonsByPosition = new AutoButtonsByPositionComponent({
53
+ listSelector: ".questionnaire-question:not(.hidden)",
54
+ hideOnFirstSelector: ".move-up-question",
55
+ hideOnLastSelector: ".move-down-question"
56
+ });
23
57
 
24
58
  const autoLabelByPosition = new AutoLabelByPositionComponent({
25
59
  listSelector: ".questionnaire-question:not(.hidden)",
26
60
  labelSelector: ".card-title span:first",
27
61
  onPositionComputed: (el, idx) => {
28
62
  $(el).find("input[name$=\\[position\\]]").val(idx);
63
+
64
+ autoButtonsByPosition.run();
65
+
66
+ removeDisplayConditionsForFirstQuestion();
29
67
  }
30
68
  });
31
69
 
32
- const autoButtonsByPosition = new AutoButtonsByPositionComponent({
33
- listSelector: ".questionnaire-question:not(.hidden)",
34
- hideOnFirstSelector: ".move-up-question",
35
- hideOnLastSelector: ".move-down-question"
36
- });
70
+ const MULTIPLE_CHOICE_VALUES = ["single_option", "multiple_option", "sorting", "matrix_single", "matrix_multiple"];
71
+ const MATRIX_VALUES = ["matrix_single", "matrix_multiple"];
37
72
 
38
73
  const createAutoMaxChoicesByNumberOfAnswerOptions = (fieldId) => {
39
74
  return new AutoSelectOptionsByTotalItemsComponent({
@@ -52,6 +87,14 @@
52
87
  })
53
88
  };
54
89
 
90
+ const createAutoSelectOptionsFromUrl = ($field) => {
91
+ return new AutoSelectOptionsFromUrl({
92
+ source: $field.find(displayConditionQuestionSelector),
93
+ select: $field.find(displayConditionAnswerOptionSelector),
94
+ sourceToParams: ($element) => { return { id: $element.val() } }
95
+ })
96
+ };
97
+
55
98
  const createSortableList = () => {
56
99
  createSortList(".questionnaire-questions-list:not(.published)", {
57
100
  handle: ".question-divider",
@@ -80,6 +123,15 @@
80
123
  });
81
124
  }
82
125
 
126
+ const createCollapsibleQuestion = ($target) => {
127
+ const $collapsible = $target.find(".collapsible");
128
+ if ($collapsible.length > 0) {
129
+ const collapsibleId = $collapsible.attr("id").replace("-question-card", "");
130
+ const toggleAttr = `${collapsibleId}-question-card button--collapse-question-${collapsibleId} button--expand-question-${collapsibleId}`;
131
+ $target.find(".question--collapse").data("toggle", toggleAttr);
132
+ }
133
+ };
134
+
83
135
  const createDynamicFieldsForAnswerOptions = (fieldId) => {
84
136
  const autoButtons = createAutoButtonsByMinItemsForAnswerOptions(fieldId);
85
137
  const autoSelectOptions = createAutoMaxChoicesByNumberOfAnswerOptions(fieldId);
@@ -123,22 +175,122 @@
123
175
 
124
176
  const dynamicFieldsForMatrixRows = {};
125
177
 
126
- const isMultipleChoiceOption = ($selectField) => {
127
- const value = $selectField.val();
128
-
178
+ const isMultipleChoiceOption = (value) => {
129
179
  return MULTIPLE_CHOICE_VALUES.indexOf(value) >= 0;
130
180
  }
131
181
 
132
- const isMatrix = ($selectField) => {
133
- const value = $selectField.val();
134
-
182
+ const isMatrix = (value) => {
135
183
  return MATRIX_VALUES.indexOf(value) >= 0;
136
184
  }
137
185
 
186
+ const getSelectedQuestionType = (select) => {
187
+ const selectedOption = select.options[select.selectedIndex];
188
+ return $(selectedOption).data("type");
189
+ };
190
+
191
+ const onDisplayConditionQuestionChange = ($field) => {
192
+ const $questionSelector = $field.find(displayConditionQuestionSelector);
193
+ const selectedQuestionType = getSelectedQuestionType($questionSelector[0]);
194
+
195
+ const isMultiple = isMultipleChoiceOption(selectedQuestionType);
196
+
197
+ let conditionTypes = ["answered", "not_answered"];
198
+
199
+ if (isMultiple) {
200
+ conditionTypes.push("equal");
201
+ conditionTypes.push("not_equal");
202
+ }
203
+
204
+ conditionTypes.push("match");
205
+
206
+ const $conditionTypeSelect = $field.find(displayConditionTypeSelector);
207
+
208
+ $conditionTypeSelect.find("option").each((idx, option) => {
209
+ const $option = $(option);
210
+ const value = $option.val();
211
+
212
+ if (!value) {
213
+ return;
214
+ }
215
+
216
+ $option.show();
217
+
218
+ if (conditionTypes.indexOf(value) < 0) {
219
+ $option.hide();
220
+ }
221
+ });
222
+
223
+ if (conditionTypes.indexOf($conditionTypeSelect.val()) < 0) {
224
+ $conditionTypeSelect.val(conditionTypes[0]);
225
+ }
226
+
227
+ $conditionTypeSelect.trigger("change");
228
+ };
229
+
230
+ const onDisplayConditionTypeChange = ($field) => {
231
+ const value = $field.find(displayConditionTypeSelector).val();
232
+ const $valueWrapper = $field.find(displayConditionValueWrapperSelector);
233
+ const $answerOptionWrapper = $field.find(displayconditionAnswerOptionWrapperSelector);
234
+
235
+ const $questionSelector = $field.find(displayConditionQuestionSelector);
236
+ const selectedQuestionType = getSelectedQuestionType($questionSelector[0]);
237
+
238
+ const isMultiple = isMultipleChoiceOption(selectedQuestionType);
239
+
240
+ if (value === "match") {
241
+ $valueWrapper.show();
242
+ }
243
+ else {
244
+ $valueWrapper.hide();
245
+ }
246
+
247
+ if (isMultiple && (value === "not_equal" || value === "equal")) {
248
+ $answerOptionWrapper.show();
249
+ }
250
+ else {
251
+ $answerOptionWrapper.hide();
252
+ }
253
+ };
254
+
255
+ const initializeDisplayConditionField = ($field) => {
256
+ const autoSelectByUrl = createAutoSelectOptionsFromUrl($field);
257
+ autoSelectByUrl.run();
258
+
259
+ $field.find(displayConditionQuestionSelector).on("change", () => {
260
+ onDisplayConditionQuestionChange($field);
261
+ });
262
+
263
+ $field.find(displayConditionTypeSelector).on("change", () => {
264
+ onDisplayConditionTypeChange($field);
265
+ });
266
+
267
+ onDisplayConditionTypeChange($field);
268
+ onDisplayConditionQuestionChange($field);
269
+ }
270
+
271
+ const createDynamicFieldsForDisplayConditions = (fieldId) => {
272
+ return createDynamicFields({
273
+ placeholderId: "questionnaire-question-display-condition-id",
274
+ wrapperSelector: `#${fieldId} ${displayConditionsWrapperSelector}`,
275
+ containerSelector: ".questionnaire-question-display-conditions-list",
276
+ fieldSelector: displayConditionFieldSelector,
277
+ addFieldButtonSelector: addDisplayConditionButtonSelector,
278
+ removeFieldButtonSelector: displayConditionRemoveFieldButtonSelector,
279
+ onAddField: ($field) => {
280
+ initializeDisplayConditionField($field);
281
+ },
282
+ onRemoveField: () => {
283
+ }
284
+ });
285
+ };
286
+
287
+ const dynamicFieldsForDisplayConditions = {};
288
+
138
289
  const setupInitialQuestionAttributes = ($target) => {
139
290
  const fieldId = $target.attr("id");
140
291
  const $fieldQuestionTypeSelect = $target.find(questionTypeSelector);
141
292
 
293
+ createCollapsibleQuestion($target);
142
294
  createDynamicQuestionTitle(fieldId);
143
295
 
144
296
  createFieldDependentInputs({
@@ -147,7 +299,7 @@
147
299
  dependentFieldsSelector: answerOptionsWrapperSelector,
148
300
  dependentInputSelector: `${answerOptionFieldSelector} input`,
149
301
  enablingCondition: ($field) => {
150
- return isMultipleChoiceOption($field);
302
+ return isMultipleChoiceOption($field.val());
151
303
  }
152
304
  });
153
305
 
@@ -167,18 +319,19 @@
167
319
  dependentFieldsSelector: matrixRowsWrapperSelector,
168
320
  dependentInputSelector: `${matrixRowFieldSelector} input`,
169
321
  enablingCondition: ($field) => {
170
- return isMatrix($field);
322
+ return isMatrix($field.val());
171
323
  }
172
324
  });
173
325
 
174
326
  dynamicFieldsForAnswerOptions[fieldId] = createDynamicFieldsForAnswerOptions(fieldId);
175
327
  dynamicFieldsForMatrixRows[fieldId] = createDynamicFieldsForMatrixRows(fieldId);
328
+ dynamicFieldsForDisplayConditions[fieldId] = createDynamicFieldsForDisplayConditions(fieldId);
176
329
 
177
330
  const dynamicFieldsAnswerOptions = dynamicFieldsForAnswerOptions[fieldId];
178
331
  const dynamicFieldsMatrixRows = dynamicFieldsForMatrixRows[fieldId];
179
332
 
180
333
  const onQuestionTypeChange = () => {
181
- if (isMultipleChoiceOption($fieldQuestionTypeSelect)) {
334
+ if (isMultipleChoiceOption($fieldQuestionTypeSelect.val())) {
182
335
  const nOptions = $fieldQuestionTypeSelect.parents(fieldSelector).find(answerOptionFieldSelector).length;
183
336
 
184
337
  if (nOptions === 0) {
@@ -187,7 +340,7 @@
187
340
  }
188
341
  }
189
342
 
190
- if (isMatrix($fieldQuestionTypeSelect)) {
343
+ if (isMatrix($fieldQuestionTypeSelect.val())) {
191
344
  const nRows = $fieldQuestionTypeSelect.parents(fieldSelector).find(matrixRowFieldSelector).length;
192
345
 
193
346
  if (nRows === 0) {
@@ -224,13 +377,6 @@
224
377
  moveUpFieldButtonSelector: ".move-up-question",
225
378
  moveDownFieldButtonSelector: ".move-down-question",
226
379
  onAddField: ($field) => {
227
- const $collapsible = $field.find(".collapsible");
228
- if ($collapsible.length > 0) {
229
- const collapsibleId = $collapsible.attr("id").replace("-question-card", "");
230
- const toggleAttr = `${collapsibleId}-question-card button--collapse-question-${collapsibleId} button--expand-question-${collapsibleId}`;
231
- $field.find(".question--collapse").data("toggle", toggleAttr);
232
- }
233
-
234
380
  setupInitialQuestionAttributes($field);
235
381
  createSortableList();
236
382
 
@@ -248,9 +394,14 @@
248
394
  $field.find(answerOptionRemoveFieldButtonSelector).each((idx, el) => {
249
395
  dynamicFieldsForAnswerOptions[$field.attr("id")]._removeField(el);
250
396
  });
397
+
251
398
  $field.find(matrixRowRemoveFieldButtonSelector).each((idx, el) => {
252
399
  dynamicFieldsForMatrixRows[$field.attr("id")]._removeField(el);
253
400
  });
401
+
402
+ $field.find(displayConditionRemoveFieldButtonSelector).each((idx, el) => {
403
+ dynamicFieldsForDisplayConditions[$field.attr("id")]._removeField(el);
404
+ });
254
405
  },
255
406
  onMoveUpField: () => {
256
407
  autoLabelByPosition.run();
@@ -271,6 +422,11 @@
271
422
  setupInitialQuestionAttributes($target);
272
423
  });
273
424
 
425
+ $(displayConditionFieldSelector).each((idx, el) => {
426
+ const $field = $(el);
427
+ initializeDisplayConditionField($field)
428
+ });
429
+
274
430
  autoLabelByPosition.run();
275
431
  autoButtonsByPosition.run();
276
432
  })(window);
@@ -1,59 +1,79 @@
1
+ /* eslint-disable no-ternary */
2
+
1
3
  ((exports) => {
2
4
  class AutosortableCheckboxesComponent {
3
5
  constructor(options = {}) {
4
6
  this.wrapperField = options.wrapperField;
5
7
  this._bindEvent();
6
- this._run();
8
+ this._order();
9
+ this._normalize();
7
10
  }
8
11
 
9
- _run() {
10
- $(this.wrapperField).find("input[type=checkbox]").each((idx, el) => {
11
- const $parentLabel = $(el).parents("label");
12
-
13
- if ($(el).is(":checked")) {
14
- const $lastSorted = this.wrapperField.find("label.sorted").last();
15
-
16
- if ($lastSorted.length > 0) {
17
- $lastSorted.removeClass("last-sorted");
18
- $parentLabel.insertAfter($lastSorted);
19
- } else {
20
- $parentLabel.insertBefore(this.wrapperField.find("label:first-child"));
21
- }
12
+ // Order by position
13
+ _order() {
14
+ const max = $(this.wrapperField).find(".collection-input").length;
15
+ $(this.wrapperField).find(".collection-input").each((idx, el) => {
16
+ const $positionField = $(el).find("input[name$=\\[position\\]]");
17
+ const position = $positionField.val()
18
+ ? parseInt($positionField.val(), 10)
19
+ : max;
22
20
 
23
- $parentLabel.addClass("sorted");
24
- $parentLabel.addClass("last-sorted");
25
- } else {
26
- const $lastUnsorted = this.wrapperField.find("label:not(.sorted)").last();
21
+ let $next = $(el).next();
22
+ while ($next.length > 0) {
23
+ const $nextPositionField = $next.find("input[name$=\\[position\\]]");
24
+ const nextPosition = $nextPositionField.val()
25
+ ? parseInt($nextPositionField.val(), 10)
26
+ : max;
27
27
 
28
- if ($lastUnsorted.length > 0) {
29
- $parentLabel.insertBefore($lastUnsorted);
30
- } else {
31
- $parentLabel.insertAfter(this.wrapperField.find("label:last-child"));
28
+ if (position > nextPosition) {
29
+ $next.insertBefore($(el));
32
30
  }
33
-
34
- $parentLabel.removeClass("sorted");
31
+ $next = $next.next();
35
32
  }
36
33
  });
34
+ }
37
35
 
38
- $(this.wrapperField).find("label").each((idx, el) => {
39
- const $positionSelector = $(el).find(".position");
36
+ _findLastPosition() {
37
+ let lastPosition = 0;
38
+ $(this.wrapperField).find(".collection-input").each((idx, el) => {
40
39
  const $positionField = $(el).find("input[name$=\\[position\\]]");
40
+ const position = parseInt($positionField.val(), 10);
41
+ if (position > lastPosition) {
42
+ lastPosition = position;
43
+ }
44
+ });
45
+ return lastPosition;
46
+ }
41
47
 
42
- if ($(el).hasClass("sorted")) {
48
+ _normalize() {
49
+ $(this.wrapperField).find(".collection-input .position").each((idx, el) => {
50
+ const $positionField = $(el).parent().find("input[name$=\\[position\\]]");
51
+ if ($positionField.val()) {
43
52
  $positionField.val(idx);
44
53
  $positionField.prop("disabled", false);
45
- $positionSelector.html(`${idx + 1}. `);
46
- } else {
47
- $positionField.val("");
48
- $positionField.prop("disabled", true);
49
- $positionSelector.html("");
54
+ $(el).html(`${idx + 1}. `);
50
55
  }
51
56
  });
52
57
  }
53
58
 
54
59
  _bindEvent() {
55
- $(this.wrapperField).find("input[type=checkbox]").on("change", () => {
56
- this._run();
60
+ $(this.wrapperField).find("input[type=checkbox]").on("change", (el) => {
61
+ const $parentLabel = $(el.target).parents("label");
62
+ const $positionSelector = $parentLabel.find(".position");
63
+ const $positionField = $parentLabel.find("input[name$=\\[position\\]]");
64
+ const lastPosition = this._findLastPosition();
65
+
66
+ if (el.target.checked) {
67
+ $positionField.val(lastPosition + 1);
68
+ $positionField.prop("disabled", false);
69
+ $positionSelector.html(lastPosition + 1);
70
+ } else {
71
+ $positionField.val("");
72
+ $positionField.prop("disabled", true);
73
+ $positionSelector.html("");
74
+ }
75
+ this._order();
76
+ this._normalize();
57
77
  });
58
78
  }
59
79
  }