Skip to content

Commit 8e904a4

Browse files
committed
better field matching for basil + ui to add custom fields
1 parent 9b145e5 commit 8e904a4

File tree

3 files changed

+135
-22
lines changed

3 files changed

+135
-22
lines changed

app/controllers/basil_controller.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,16 @@ def content
198198
end
199199
@relevant_fields.compact!
200200

201+
# Get IDs of fields already included
202+
included_field_ids = @relevant_fields.map { |field, _| field.id }
203+
204+
# Get additional filled fields not in the hardcoded template
205+
@additional_fields = BasilService.get_additional_filled_fields(
206+
current_user,
207+
@content,
208+
exclude_field_ids: included_field_ids
209+
)
210+
201211
# Finally, cache some state we can reference in the view
202212
@commissions = BasilCommission.where(entity_type: @content.page_type, entity_id: @content.id)
203213
.where(saved_at: nil)

app/services/basil_service.rb

Lines changed: 64 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -88,16 +88,19 @@ def self.experimental_styles_for(page_type)
8888
end
8989
end
9090

91-
def self.include_all_fields_in_category(user, page, category_label)
92-
category = AttributeCategory.where(
91+
def self.include_all_fields_in_category(user, page, category_labels)
92+
category_labels = Array(category_labels)
93+
94+
# Find all categories matching ANY of the provided labels (case-insensitive)
95+
# This allows users with renamed categories to still match
96+
categories = AttributeCategory.where(
9397
user_id: user.id,
94-
entity_type: page.page_type.downcase,
95-
label: category_label
96-
)
97-
return nil if category.empty?
98+
entity_type: page.page_type.downcase
99+
).where('LOWER(label) IN (?)', category_labels.map(&:downcase))
100+
return nil if categories.empty?
98101

99102
fields = AttributeField.where(
100-
attribute_category_id: category.pluck(:id),
103+
attribute_category_id: categories.pluck(:id),
101104
field_type: ['name', 'text_area', 'textarea'],
102105
hidden: [nil, false]
103106
)
@@ -118,19 +121,21 @@ def self.include_all_fields_in_category(user, page, category_label)
118121
end
119122
end
120123

121-
def self.include_specific_field(user, page, category_label, field_label)
122-
category = AttributeCategory.find_by(
123-
user_id: user.id,
124-
entity_type: page.page_type.downcase,
125-
label: category_label
126-
)
127-
return nil if category.nil?
124+
def self.include_specific_field(user, page, _category_label, field_label)
125+
# Note: category_label parameter kept for backward compatibility but ignored
126+
# We now search by field label across ALL categories for this user/page_type
127+
# This allows users with custom/renamed categories to still match fields by label
128128

129-
field = AttributeField.find_by(
130-
attribute_category_id: category.id,
131-
label: field_label,
132-
hidden: [nil, false]
133-
)
129+
field = AttributeField.joins(:attribute_category)
130+
.where(
131+
attribute_categories: {
132+
user_id: user.id,
133+
entity_type: page.page_type.downcase
134+
},
135+
label: field_label,
136+
hidden: [nil, false]
137+
)
138+
.first
134139
return nil if field.nil?
135140

136141
value = Attribute.where(attribute_field_id: field.id,
@@ -144,4 +149,44 @@ def self.include_specific_field(user, page, category_label, field_label)
144149
# in the form of [field, value].
145150
return [field, value.value]
146151
end
152+
153+
def self.get_additional_filled_fields(user, page, exclude_field_ids: [])
154+
# Get all text-type fields for this page type that have values
155+
# but weren't already included in the relevant_fields
156+
157+
category_ids = AttributeCategory.where(
158+
user_id: user.id,
159+
entity_type: page.page_type.downcase,
160+
hidden: [nil, false]
161+
).where.not(label: ['Settings', 'Contributors', 'Gallery', 'Changelog'])
162+
.pluck(:id)
163+
164+
return [] if category_ids.empty?
165+
166+
fields = AttributeField.where(
167+
attribute_category_id: category_ids,
168+
field_type: ['name', 'text_area', 'textarea'],
169+
hidden: [nil, false]
170+
).where.not(id: exclude_field_ids)
171+
.includes(:attribute_category)
172+
173+
return [] if fields.empty?
174+
175+
answers = Attribute.where(
176+
attribute_field_id: fields.pluck(:id),
177+
entity_id: page.id,
178+
entity_type: page.page_type
179+
).where.not(value: IGNORED_VALUES)
180+
181+
return [] if answers.empty?
182+
183+
# Sort by category position, then field position
184+
answers.map do |answer|
185+
field = fields.find { |f| f.id == answer.attribute_field_id }
186+
next nil if field.nil?
187+
[field, answer.value]
188+
end.compact.sort_by do |field, _|
189+
[field.attribute_category&.position || 999, field.position || 999]
190+
end
191+
end
147192
end

app/views/basil/content.html.erb

Lines changed: 61 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,35 @@ function commission_basil(style) {
5555
<% end %>
5656
</ul>
5757

58-
<% if @relevant_fields.empty? %>
58+
<% if @additional_fields.any? %>
59+
<div style="margin-top: 1.5rem; border-top: 1px solid #e0e0e0; padding-top: 1rem;">
60+
<a href="#" class="js-toggle-additional-fields-section grey-text text-darken-2" style="display: block; font-weight: bold;">
61+
<i class="material-icons tiny" style="vertical-align: middle;">add_circle_outline</i>
62+
Show <%= pluralize(@additional_fields.count, 'more field') %> you can include
63+
<i class="material-icons tiny js-chevron" style="vertical-align: middle;">expand_more</i>
64+
</a>
65+
66+
<div class="js-additional-fields-container hide" style="margin-top: 0.5rem;">
67+
<ul style="margin-top: 0.5rem;">
68+
<% @additional_fields.each do |field, value| %>
69+
<li style="margin-bottom: 0.5em; opacity: 0.7;">
70+
<label>
71+
<%= check_box_tag "basil_commission[include_field][#{field.id}]", field.id, false, class: 'js-toggle-additional-field' %>
72+
<span class="grey-text"><%= field.label %></span>
73+
</label>
74+
<div class="js-additional-field-inputs hide" data-field-id="<%= field.id %>">
75+
<%= hidden_field_tag "basil_commission[field][#{field.id}][label]", field.label, disabled: true %>
76+
<%= hidden_field_tag "basil_commission[field][#{field.id}][value]", value, disabled: true %>
77+
<%= range_field_tag "basil_commission[field][#{field.id}][importance]", 1, { min: 0, max: 1.3, step: 0.1, style: 'width: 60%;', disabled: true } %>
78+
</div>
79+
</li>
80+
<% end %>
81+
</ul>
82+
</div>
83+
</div>
84+
<% end %>
85+
86+
<% if @relevant_fields.empty? && @additional_fields.empty? %>
5987
<div class="red card-panel lighten-3">
6088
<strong>Basil works best with guidance!</strong>
6189
<br /><br />
@@ -65,7 +93,7 @@ function commission_basil(style) {
6593
<% end %>
6694

6795
<div>
68-
<% if @can_request_another && @relevant_fields.any? %>
96+
<% if @can_request_another && (@relevant_fields.any? || @additional_fields.any?) %>
6997
<a href="javascript:var sliders = document.getElementsByClassName('js-importance-slider'); for(var i = 0; i < sliders.length; i++) sliders.item(i).classList.remove('hide'); document.getElementById('importance-explainer').classList.remove('hide');" class="waves-effect waves-light btn-small purple lighten-1" style="margin-bottom: 1rem;">Customize importance</a>
7098
<% end %>
7199

@@ -121,7 +149,7 @@ function commission_basil(style) {
121149
<div class="col s12 m8" style="margin-top: 1rem">
122150
<%= render partial: 'notice_dismissal/messages/19' if show_notice?(id: 19) %>
123151

124-
<% if @can_request_another && @relevant_fields.any? %>
152+
<% if @can_request_another && (@relevant_fields.any? || @additional_fields.any?) %>
125153
<div class="row" style="padding-left: 0.5rem">
126154
<div class="grey-text center" style="font-size: 1.2rem; margin-bottom: 0.5rem;"><strong>Image Styles</strong></div>
127155
<% BasilService.enabled_styles_for(@content.page_type).each do |style| %>
@@ -303,6 +331,36 @@ $(document).ready(function() {
303331

304332
e.preventDefault();
305333
});
334+
335+
// Toggle the additional fields section open/closed
336+
$('.js-toggle-additional-fields-section').click(function(e) {
337+
e.preventDefault();
338+
var container = $(this).siblings('.js-additional-fields-container');
339+
var chevron = $(this).find('.js-chevron');
340+
341+
container.toggleClass('hide');
342+
if (container.hasClass('hide')) {
343+
chevron.text('expand_more');
344+
} else {
345+
chevron.text('expand_less');
346+
}
347+
});
348+
349+
// Toggle individual additional field on/off
350+
$('.js-toggle-additional-field').change(function() {
351+
var inputs = $(this).closest('li').find('.js-additional-field-inputs');
352+
var inputFields = inputs.find('input');
353+
354+
if ($(this).is(':checked')) {
355+
inputs.removeClass('hide');
356+
inputFields.prop('disabled', false);
357+
$(this).closest('li').css('opacity', '1');
358+
} else {
359+
inputs.addClass('hide');
360+
inputFields.prop('disabled', true);
361+
$(this).closest('li').css('opacity', '0.7');
362+
}
363+
});
306364
});
307365
<% end %>
308366

0 commit comments

Comments
 (0)