fe 2.1.6.1 → 2.1.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 +4 -4
- data/app/assets/javascripts/fe/fe.admin.js +12 -12
- data/app/assets/javascripts/fe/fe.common.js.erb +50 -41
- data/app/assets/javascripts/fe/fe.public.nojquery.js.erb +19 -7
- data/app/assets/javascripts/fe/jquery.html5_upload.js +1 -1
- data/app/controllers/concerns/fe/answer_pages_controller_concern.rb +1 -0
- data/app/models/concerns/fe/answer_sheet_concern.rb +1 -1
- data/app/models/concerns/fe/choice_field_concern.rb +1 -1
- data/app/models/fe/element.rb +4 -4
- data/app/models/fe/page.rb +2 -2
- data/app/models/fe/question_sheet.rb +1 -1
- data/app/views/fe/admin/elements/create.js.erb +1 -1
- data/app/views/fe/questions/fe/_reference_question.html.erb +1 -1
- data/lib/fe/version.rb +1 -1
- metadata +3 -5
- data/spec/dummy/app/views/layouts/fe/fe.admin.html.erb +0 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b64b157852e00628b533ed9826d53d40c715e023813b0e30290397a78adfcb3b
|
4
|
+
data.tar.gz: 97f8071426f54e34982967b7613439eb3e27d0e77e7cb9d7589b2857d08a8790
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2357386af9137a2b4d40f7ce981d7d48909001b066638af236fe55affa3405d50f3866133e934231bdcb9f04f2a02053222c389511214f4e9b9a306b7fd56d54
|
7
|
+
data.tar.gz: 7b228d9046ba5fd172d5199c94ab78e012d6c3205eda62aaa3da952971d34899e60b4e1fb7f073db2164a36c419c4f47f14074e05e0355c288699655e1675162
|
@@ -72,7 +72,7 @@ $(document).on('ready turbo:load', function () {
|
|
72
72
|
|
73
73
|
let currentTab = 'pages_list';
|
74
74
|
|
75
|
-
function switchTab(toTab) {
|
75
|
+
window.switchTab = function switchTab(toTab) {
|
76
76
|
if(currentTab != null) $('#tab-' + currentTab).removeClass('active');
|
77
77
|
$('#tab-' + toTab).addClass('active');
|
78
78
|
currentTab = toTab;
|
@@ -81,7 +81,7 @@ function switchTab(toTab) {
|
|
81
81
|
}
|
82
82
|
}
|
83
83
|
|
84
|
-
function selectPage() {
|
84
|
+
window.selectPage = function selectPage() {
|
85
85
|
let el = $('#link-page-name');
|
86
86
|
clearCurrentElement();
|
87
87
|
el.addClass('active');
|
@@ -90,7 +90,7 @@ function selectPage() {
|
|
90
90
|
if($('#page_label').length > 0) $('#page_label').focus();
|
91
91
|
}
|
92
92
|
|
93
|
-
function selectElement(id) {
|
93
|
+
window.selectElement = function selectElement(id) {
|
94
94
|
let el = $(id);
|
95
95
|
clearPageName();
|
96
96
|
clearCurrentElement();
|
@@ -102,28 +102,28 @@ function selectElement(id) {
|
|
102
102
|
// if( $('#element_label')) $('#element_label').focus();
|
103
103
|
}
|
104
104
|
|
105
|
-
function clearCurrentElement() {
|
105
|
+
window.clearCurrentElement = function clearCurrentElement() {
|
106
106
|
if (activeElement != '' && $(activeElement)) {
|
107
107
|
$(activeElement).removeClass('active');
|
108
108
|
}
|
109
109
|
}
|
110
110
|
|
111
|
-
function clearPageName() {
|
111
|
+
window.clearPageName = function clearPageName() {
|
112
112
|
$('#link-page-name').removeClass('active');
|
113
113
|
}
|
114
114
|
|
115
|
-
function snapElementProperties(el) {
|
115
|
+
window.snapElementProperties = function snapElementProperties(el) {
|
116
116
|
let propsTop = Position.cumulativeOffset(el)[1] - 160;
|
117
117
|
if (propsTop < 0) propsTop = 0;
|
118
118
|
$('#panel-properties-element').css({'margin-top': propsTop});
|
119
119
|
}
|
120
120
|
|
121
|
-
function addError(id) {
|
121
|
+
window.addError = function addError(id) {
|
122
122
|
$('#' + id).addClassName('fieldWithErrors');
|
123
123
|
}
|
124
124
|
|
125
125
|
// convert label to slug
|
126
|
-
function updateSlug(source, dest) {
|
126
|
+
window.updateSlug = function updateSlug(source, dest) {
|
127
127
|
let label = $(source).val();
|
128
128
|
let slug = $(dest).val();
|
129
129
|
if( label == null || slug == null) return; // oh oh
|
@@ -133,10 +133,10 @@ function updateSlug(source, dest) {
|
|
133
133
|
|
134
134
|
if( label != '' && slug == '' ) { // if slug is empty lets copy label to it
|
135
135
|
slug = label.toLowerCase();
|
136
|
-
slug = slug.
|
137
|
-
slug = slug.
|
138
|
-
slug = slug.
|
139
|
-
slug = slug.
|
136
|
+
slug = slug.replace(/[^a-z0-9]/, '_'); // only alpha-numeric
|
137
|
+
slug = slug.replace(/_{2,}/, '_'); // compact double hyphens down to one
|
138
|
+
slug = slug.replace(/_$/, ''); // remove trailing underscores
|
139
|
+
slug = slug.replace(/^([0-9])/, '_$&') // can't begin with a digit, so preprend an underscore
|
140
140
|
if( slug.length > 36 ) slug = slug.slice(0, 36) // max length
|
141
141
|
|
142
142
|
$(dest).value = slug
|
@@ -1,33 +1,35 @@
|
|
1
|
-
function setUpSortables() {
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
1
|
+
window.setUpSortables = function setUpSortables() {
|
2
|
+
$('[data-sortable]').sortable({
|
3
|
+
axis:'y',
|
4
|
+
items: '> li.sortable',
|
5
|
+
dropOnEmpty:false,
|
6
|
+
update: function(event, ui) {
|
7
|
+
let sortable = this;
|
8
|
+
$.ajax({
|
9
|
+
data:$(this).sortable('serialize',{key:sortable.id + '[]'}),
|
10
|
+
complete: function(request) {$(sortable).effect('highlight')},
|
11
|
+
success: function(request){$('#errors').html(request)},
|
12
|
+
type:'POST',
|
13
|
+
url: $(sortable).attr('data-sortable-url')
|
14
|
+
})
|
15
|
+
},
|
16
|
+
stop: function(event, ui) {
|
17
|
+
let before_dropper = $('li.before-container[data-element_id="'+ui.item.data('element_id'));
|
18
|
+
if (before_dropper.length > 0) {
|
19
|
+
before_dropper.detach();
|
20
|
+
before_dropper.insertBefore(ui.item);
|
21
|
+
}
|
22
|
+
let after_dropper = $('li.after-container[data-element_id="'+ui.item.data('element_id'));
|
23
|
+
if (after_dropper.length > 0) {
|
24
|
+
after_dropper.detach();
|
25
|
+
after_dropper.insertAfter(ui.item);
|
26
|
+
}
|
27
|
+
}
|
28
|
+
});
|
29
|
+
$('[data-sortable][data-sortable-handle]').each(function() {
|
30
|
+
const handle = $(this).attr('data-sortable-handle');
|
29
31
|
$(this).sortable("option", "handle", handle);
|
30
|
-
|
32
|
+
});
|
31
33
|
|
32
34
|
$('.droppable').droppable({
|
33
35
|
activeClass: 'droppable-active',
|
@@ -36,8 +38,8 @@ function setUpSortables() {
|
|
36
38
|
$.post($(this).attr('data-url'), {draggable_element: ui.draggable.attr('id')}, function() {}, 'script')
|
37
39
|
},
|
38
40
|
activate: function( event, ui ) {
|
39
|
-
$draggable = ui.draggable;
|
40
|
-
$container = $draggable.parents("li.element.container")
|
41
|
+
const $draggable = ui.draggable;
|
42
|
+
const $container = $draggable.parents("li.element.container");
|
41
43
|
if ($container.length == 1) {
|
42
44
|
$container.parent().find('li.around-container[data-element_id="'+$container.data('element_id')+'"]').addClass('droppable-active')
|
43
45
|
} else {
|
@@ -45,8 +47,8 @@ function setUpSortables() {
|
|
45
47
|
}
|
46
48
|
},
|
47
49
|
deactivate: function( event, ui ) {
|
48
|
-
$draggable = ui.draggable;
|
49
|
-
$container = $draggable.parents("li.element.container")
|
50
|
+
const $draggable = ui.draggable;
|
51
|
+
const $container = $draggable.parents("li.element.container");
|
50
52
|
if ($container.length == 1) {
|
51
53
|
$container.parent().find('li.around-container[data-element_id="'+$container.data('element_id')+'"]').removeClass('droppable-active')
|
52
54
|
} else {
|
@@ -56,7 +58,7 @@ function setUpSortables() {
|
|
56
58
|
});
|
57
59
|
}
|
58
60
|
|
59
|
-
function setUpCalendars() {
|
61
|
+
window.setUpCalendars = function setUpCalendars() {
|
60
62
|
let now = new Date();
|
61
63
|
let year = now.getFullYear() + 10;
|
62
64
|
$('[data-calendar]').datepicker({
|
@@ -66,11 +68,11 @@ function setUpCalendars() {
|
|
66
68
|
})
|
67
69
|
}
|
68
70
|
|
69
|
-
function setUpJsHelpers() {
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
71
|
+
window.setUpJsHelpers = function setUpJsHelpers() {
|
72
|
+
// ==================
|
73
|
+
// Sortable
|
74
|
+
setUpSortables();
|
75
|
+
// ==================
|
74
76
|
|
75
77
|
// ==================
|
76
78
|
// Calendar
|
@@ -79,8 +81,8 @@ function setUpJsHelpers() {
|
|
79
81
|
<% unless Fe.bootstrap %>$(".tip[title], a[title]").tooltip()<% end %>
|
80
82
|
}
|
81
83
|
|
82
|
-
function fixGridColumnWidths() {
|
83
|
-
|
84
|
+
window.fixGridColumnWidths = function fixGridColumnWidths() {
|
85
|
+
$("table.grid").each(function(i, grid) {
|
84
86
|
let num_columns = $(grid).find("th").length;
|
85
87
|
if (num_columns > 0) {
|
86
88
|
let width = (100 / num_columns) + "%";
|
@@ -97,6 +99,13 @@ function scrollTo(el) {
|
|
97
99
|
}, 1000);
|
98
100
|
}
|
99
101
|
|
102
|
+
window.scrollToElement = function scrollToElement(el) {
|
103
|
+
if ($(el).length == 0) { return; }
|
104
|
+
$('html, body').animate({
|
105
|
+
scrollTop: $(el).offset().top
|
106
|
+
}, 1000);
|
107
|
+
}
|
108
|
+
|
100
109
|
// jQuery 3 has removed $(document).on('ready', ...) in favor of $(document).ready(...). Manually call it from
|
101
110
|
// the new method here, so we can avoid changing over all the document ready's.
|
102
111
|
$(document).ready(function() {
|
@@ -99,7 +99,7 @@ fe.pageHandler = {
|
|
99
99
|
//
|
100
100
|
if (!isValid && $('#' + this.current_page + "-form").hasClass('enforce-valid-before-next')) {
|
101
101
|
// scroll up to where the error is
|
102
|
-
|
102
|
+
scrollToElement($(".help-block:visible")[0].closest("li"));
|
103
103
|
return;
|
104
104
|
}
|
105
105
|
|
@@ -110,9 +110,9 @@ fe.pageHandler = {
|
|
110
110
|
|
111
111
|
if (!background_load) {
|
112
112
|
if ($('a[name="main"]').length == 1) {
|
113
|
-
|
113
|
+
scrollToElement('a[name="main"]');
|
114
114
|
} else {
|
115
|
-
|
115
|
+
scrollToElement('#main');
|
116
116
|
}
|
117
117
|
}
|
118
118
|
|
@@ -157,7 +157,9 @@ fe.pageHandler = {
|
|
157
157
|
if( form_data ) {
|
158
158
|
if( page.data('form_data') == null || page.data('form_data').data !== form_data.data || force === true) { // if any changes
|
159
159
|
page.data('form_data', form_data);
|
160
|
-
|
160
|
+
const auth_token = $('meta[name=csrf-token]').attr('content');
|
161
|
+
form_data.data += '&authenticity_token=' + encodeURIComponent(auth_token);
|
162
|
+
$.ajax({url: form_data.url, type: 'put', data: form_data.data,
|
161
163
|
beforeSend: function (xhr) {
|
162
164
|
$('#spinner_' + page.attr('id')).show();
|
163
165
|
},
|
@@ -302,8 +304,9 @@ fe.pageHandler = {
|
|
302
304
|
// clear out pages array to force reload. This enables "frozen" apps
|
303
305
|
// immediately after submission - :onSuccess (for USCM which stays in the application vs. redirecting to the dashboard)
|
304
306
|
let curr = fe.pageHandler.current_page;
|
307
|
+
const auth_token = $('meta[name=csrf-token]').attr('content');
|
305
308
|
$.ajax({url: url, dataType:'script',
|
306
|
-
data: {answer_sheet_type: answer_sheet_type, a: $('input[type=hidden][name=a]').val()},
|
309
|
+
data: {answer_sheet_type: answer_sheet_type, a: $('input[type=hidden][name=a]').val(), authenticity_token: auth_token},
|
307
310
|
type:'post',
|
308
311
|
beforeSend: function(xhr) {
|
309
312
|
$('body').trigger('ajax:loading', xhr);
|
@@ -444,6 +447,8 @@ $(document).on('ready turbo:load', function () {
|
|
444
447
|
let data = form_elements.serializeArray();
|
445
448
|
|
446
449
|
data.push({name: 'answer_sheet_type', value: answer_sheet_type});
|
450
|
+
const auth_token = $('meta[name=csrf-token]').attr('content');
|
451
|
+
data.push({name: 'authenticity_token', value: auth_token});
|
447
452
|
$.ajax({url: $(el).attr('href'), data: data, dataType: 'script', type: 'POST',
|
448
453
|
beforeSend: function (xhr) {
|
449
454
|
$('body').trigger('ajax:loading', xhr);
|
@@ -495,7 +500,7 @@ $(function() {
|
|
495
500
|
});
|
496
501
|
|
497
502
|
|
498
|
-
function updateTotal(id) {
|
503
|
+
window.updateTotal = function updateTotal(id) {
|
499
504
|
try {
|
500
505
|
let total = 0;
|
501
506
|
$(".col_" + id).each(function(index, el) {
|
@@ -506,7 +511,7 @@ function updateTotal(id) {
|
|
506
511
|
}
|
507
512
|
}
|
508
513
|
|
509
|
-
function submitToFrame(id, url) {
|
514
|
+
window.submitToFrame = function submitToFrame(id, url) {
|
510
515
|
let form = $('<form method="post" action="'+url+'.js" endtype="multipart/form-data"></form>')
|
511
516
|
let csrf_token = $('meta[name=csrf-token]').attr('content'),
|
512
517
|
csrf_param = $('meta[name=csrf-param]').attr('content'),
|
@@ -531,3 +536,10 @@ if (typeof scrollTo === 'undefined') {
|
|
531
536
|
}, 1000);
|
532
537
|
}
|
533
538
|
}
|
539
|
+
|
540
|
+
window.scrollToElement = function scrollToElement(el) {
|
541
|
+
if ($(el).length == 0) { return; }
|
542
|
+
$('html, body').animate({
|
543
|
+
scrollTop: $(el).offset().top
|
544
|
+
}, 1000);
|
545
|
+
}
|
@@ -34,7 +34,7 @@ module Fe
|
|
34
34
|
|
35
35
|
unless @languages
|
36
36
|
@languages = question_sheets.first.languages
|
37
|
-
question_sheets[1..-1].each { |qs| @languages &= qs.languages
|
37
|
+
question_sheets[1..-1].each { |qs| @languages &= qs.languages&.select(&:present?) }
|
38
38
|
end
|
39
39
|
@languages
|
40
40
|
end
|
@@ -15,7 +15,7 @@ module Fe
|
|
15
15
|
included do
|
16
16
|
has_many :elements, class_name: "Element", foreign_key: "choice_field_id", dependent: :nullify#, order: :position
|
17
17
|
[:rating_before_label_translations, :rating_after_label_translations, :rating_na_label_translations].each do |column|
|
18
|
-
if Rails
|
18
|
+
if Rails.gem_version < "7.1.0"
|
19
19
|
serialize column, Hash
|
20
20
|
else
|
21
21
|
serialize column, type: Hash
|
data/app/models/fe/element.rb
CHANGED
@@ -50,7 +50,7 @@ module Fe
|
|
50
50
|
after_save :update_any_previous_conditional_elements
|
51
51
|
|
52
52
|
[:label_translations, :tip_translations, :content_translations].each do |column|
|
53
|
-
if Rails
|
53
|
+
if Rails.gem_version < "7.1.0"
|
54
54
|
serialize column, Hash
|
55
55
|
else
|
56
56
|
serialize column, type: Hash
|
@@ -65,15 +65,15 @@ module Fe
|
|
65
65
|
# HUMANIZED_ATTRIBUTES[attr.to_sym] || super
|
66
66
|
# end
|
67
67
|
def label(locale = nil)
|
68
|
-
label_translations
|
68
|
+
label_translations&.dig(locale).present? ? label_translations[locale] : self[:label]
|
69
69
|
end
|
70
70
|
|
71
71
|
def content(locale = nil)
|
72
|
-
content_translations
|
72
|
+
content_translations&.dig(locale).present? ? content_translations[locale] : self[:content]
|
73
73
|
end
|
74
74
|
|
75
75
|
def tooltip(locale = nil)
|
76
|
-
tip_translations
|
76
|
+
tip_translations&.dig(locale).present? ? tip_translations[locale] : self[:tooltip]
|
77
77
|
end
|
78
78
|
|
79
79
|
# returns all pages this element is on, whether that be directly, through a grid, or as a choice field conditional option
|
data/app/models/fe/page.rb
CHANGED
@@ -45,7 +45,7 @@ module Fe
|
|
45
45
|
|
46
46
|
# NOTE: You may need config.active_record.yaml_column_permitted_classes = [Hash, ActiveSupport::HashWithIndifferentAccess]
|
47
47
|
# in config/application.rb or you may get Psych::DisallowedClass trying to use label_translations
|
48
|
-
if Rails
|
48
|
+
if Rails.gem_version < "7.1.0"
|
49
49
|
serialize :label_translations, Hash
|
50
50
|
else
|
51
51
|
serialize :label_translations, type: Hash
|
@@ -73,7 +73,7 @@ module Fe
|
|
73
73
|
end
|
74
74
|
|
75
75
|
def label(locale = nil)
|
76
|
-
label_translations
|
76
|
+
label_translations&.dig(locale) || self[:label]
|
77
77
|
end
|
78
78
|
|
79
79
|
# returns true if there is a question element on the page, including one inside a grid
|
@@ -5,7 +5,7 @@
|
|
5
5
|
$('#element_form_<%= dom_id(@element) %>').html('<%= escape_javascript(render("fe/admin/panels/prop_element", element: @element)) %>');
|
6
6
|
$('#element_form_<%= dom_id(@element) %>').show();
|
7
7
|
selectElement("#element_<%= @element.id %>");
|
8
|
-
|
8
|
+
scrollToElement("#element_<%= @element.id %>");
|
9
9
|
setUpSortables();
|
10
10
|
<% else %>
|
11
11
|
alert('That question already exists on this question sheet')
|
@@ -43,7 +43,7 @@
|
|
43
43
|
"have edited the information in order for your reference to receive another email.") %>
|
44
44
|
</strong></em></p></li>
|
45
45
|
|
46
|
-
<li><%= link_to(_("Send Email Invitation"), @answer_sheet ? send_reference_invite_fe_answer_sheet_path(@answer_sheet, reference_id: reference.id) : "#", class: "#{"form-control" if Fe.bootstrap} reference_send_invite button no-left-margin", disabled: !reference.all_affecting_questions_answered) %>
|
46
|
+
<li><%= link_to(_("Send Email Invitation"), @answer_sheet ? send_reference_invite_fe_answer_sheet_path(@answer_sheet, reference_id: reference.id) : "#", class: "#{"form-control" if Fe.bootstrap} reference_send_invite button no-left-margin", disabled: !reference.all_affecting_questions_answered, data: { turbo: false }) %>
|
47
47
|
<% if reference.question && !reference.all_affecting_questions_answered %>
|
48
48
|
<div>
|
49
49
|
<strong><i>This button is disabled because there are questions that affect whether this reference is required that need to answered first:</i></strong>
|
data/lib/fe/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fe
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.1.
|
4
|
+
version: 2.1.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- CruGlobal
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-
|
11
|
+
date: 2025-06-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -551,7 +551,6 @@ files:
|
|
551
551
|
- spec/dummy/app/models/person.rb
|
552
552
|
- spec/dummy/app/models/user.rb
|
553
553
|
- spec/dummy/app/views/layouts/application.html.erb
|
554
|
-
- spec/dummy/app/views/layouts/fe/fe.admin.html.erb
|
555
554
|
- spec/dummy/bin/bundle
|
556
555
|
- spec/dummy/bin/rails
|
557
556
|
- spec/dummy/bin/rake
|
@@ -678,7 +677,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
678
677
|
- !ruby/object:Gem::Version
|
679
678
|
version: '0'
|
680
679
|
requirements: []
|
681
|
-
rubygems_version: 3.
|
680
|
+
rubygems_version: 3.5.17
|
682
681
|
signing_key:
|
683
682
|
specification_version: 4
|
684
683
|
summary: Form Engine
|
@@ -704,7 +703,6 @@ test_files:
|
|
704
703
|
- spec/dummy/app/models/person.rb
|
705
704
|
- spec/dummy/app/models/user.rb
|
706
705
|
- spec/dummy/app/views/layouts/application.html.erb
|
707
|
-
- spec/dummy/app/views/layouts/fe/fe.admin.html.erb
|
708
706
|
- spec/dummy/bin/bundle
|
709
707
|
- spec/dummy/bin/rails
|
710
708
|
- spec/dummy/bin/rake
|
@@ -1 +0,0 @@
|
|
1
|
-
<%= yield %>
|