Skip to content

Commit

Permalink
Merge pull request #2124 from dbwinger/element-groups
Browse files Browse the repository at this point in the history
Add element groups functionality for cleaning up editors
  • Loading branch information
tvdeyen committed May 30, 2022
1 parent a871b51 commit 196243a
Show file tree
Hide file tree
Showing 8 changed files with 204 additions and 6 deletions.
26 changes: 26 additions & 0 deletions app/assets/javascripts/alchemy/alchemy.element_editors.js.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ Alchemy.ElementEditors =
init: ->
@element_area = $("#element_area")
@bindEvents()
@expandContentGroups()
return

# Binds click events on several DOM elements from element editors
Expand All @@ -36,12 +37,20 @@ Alchemy.ElementEditors =
# Binds the custom SaveElement event
@element_area.on "SaveElement.Alchemy", '.element-editor', (e, data) =>
@onSaveElement(e, data)
@element_area.on "click", '[data-toggle-content-group]', (e) =>
@onToggleContentGroup(e)
# Listen to postMessage messages from the preview frame
window.addEventListener 'message', (e) =>
@onMessage(e.data)
true
return

# Expands content groups that are stored in sessionStorage as expanded
expandContentGroups: ->
if $expanded_content_groups = sessionStorage.getItem('Alchemy.expanded_content_groups')
for header_id in JSON.parse($expanded_content_groups) then do (header_id) =>
$('#' + header_id).closest('.content-group').addClass('expanded');

# Selects and scrolls to element with given id in the preview window.
#
focusElementPreview: (element_id) ->
Expand Down Expand Up @@ -170,6 +179,23 @@ Alchemy.ElementEditors =
Alchemy.Buttons.enable($element)
true

# Toggle visibility of the content fields in the group
onToggleContentGroup: (event) ->
$group_div = $(event.currentTarget).closest('.content-group');
$group_div.toggleClass('expanded');

$expanded_content_groups = JSON.parse(sessionStorage.getItem('Alchemy.expanded_content_groups') || '[]');
# Add or remove depending on whether this content group is expanded
if $group_div.hasClass('expanded')
if $expanded_content_groups.indexOf(event.currentTarget.id) == -1
$expanded_content_groups.push(event.currentTarget.id);
else
$expanded_content_groups = $expanded_content_groups.filter (value) ->
value != event.currentTarget.id

sessionStorage.setItem('Alchemy.expanded_content_groups', JSON.stringify($expanded_content_groups))
false

# Event handlers

onMessage: (data) ->
Expand Down
35 changes: 35 additions & 0 deletions app/assets/stylesheets/alchemy/elements.scss
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,41 @@
}
}

.content-group {
width: 100%;
padding: $default-padding 0;
position: relative;
border-bottom: 1px solid $medium-gray;

&:last-child {
border-bottom: none;
padding-bottom: 0;
}

.content-group-header {
display: flex;
align-items: center;
justify-content: space-between;
font-weight: bold;
text-decoration: none;
padding: $default-padding 1px;
}

.content-group-contents {
display: none;
}

&.expanded {
.content-group-contents {
display: block;
}

.content-group-expand {
@extend .fa-angle-up;
}
}
}

.element-content-editors,
.element-ingredient-editors {
display: flex;
Expand Down
23 changes: 23 additions & 0 deletions app/decorators/alchemy/element_editor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,29 @@ def has_ingredients_defined?
element.definition.fetch(:ingredients, []).any?
end

# Returns the translated content/ingredient group for displaying in admin editor group headings
#
# Translate it in your locale yml file:
#
# alchemy:
# element_groups:
# foo: Bar
#
# Optionally you can scope your ingredient role to an element:
#
# alchemy:
# element_groups:
# article:
# foo: Baz
#
def translated_group(group)
Alchemy.t(
group,
scope: "element_groups.#{element.name}",
default: Alchemy.t("element_groups.#{group}", default: group.humanize),
)
end

# CSS classes for the element editor partial.
def css_classes
[
Expand Down
39 changes: 34 additions & 5 deletions app/views/alchemy/admin/elements/_element.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,44 @@
html: {id: "element_#{element.id}_form".html_safe, class: 'element-content'} do |f| %>

<div id="element_<%= element.id %>_errors" class="element_errors"></div>

<!-- Ingredients -->
<% if element.has_ingredients_defined? %>
<div class="element-ingredient-editors">
<%= render element.ingredients, element_form: f %>
</div>
<% else %>
<div id="element_<%= element.id %>_content" class="element-content-editors">
<%= render element.contents %>
<%= render element.ingredients.select { |i| !i.definition[:group] }, element_form: f %>

<!-- Each ingredient group -->
<% element.ingredients.select { |i| i.definition[:group] }.group_by { |i| i.definition[:group] }.each do |group, ingredients| %>
<div class="content-group">
<%= link_to '#', id: "element_#{element.id}_content_group_#{group.parameterize.underscore}_header", class: 'content-group-header', data: { toggle_content_group: true } do %>
<%= element.translated_group group %>
<i class="content-group-expand icon fa-fw fa-angle-down fas"></i>
<% end %>
<%= content_tag :div, id: "element_#{element.id}_content_group_#{group.parameterize.underscore}", class: 'content-group-contents' do %>
<%= render ingredients, element_form: f %>
<% end %>
</div>
<% end %>
</div>
<% end %>
<!-- Contents -->
<div id="element_<%= element.id %>_content" class="element-content-editors">
<%= render element.contents.select { |c| !c.definition[:group] } %>

<!-- Each content group -->
<% element.contents.select { |c| c.definition[:group] }.group_by { |c| c.definition[:group] }.each do |group, contents| %>
<div class="content-group">
<%= link_to '#', id: "element_#{element.id}_content_group_#{group.parameterize.underscore}_header", class: 'content-group-header', data: { toggle_content_group: true } do %>
<%= element.translated_group group %>
<i class="content-group-expand icon fa-fw fa-angle-down fas"></i>
<% end %>
<%= content_tag :div, id: "element_#{element.id}_content_group_#{group.parameterize.underscore}", class: 'content-group-contents' do %>
<%= render contents, element_form: f %>
<% end %>
</div>
<% end %>
</div>

<% if element.taggable? %>
<div class="autocomplete_tag_list">
<%= f.label :tag_list %>
Expand Down
35 changes: 35 additions & 0 deletions spec/dummy/config/alchemy/elements.yml
Original file line number Diff line number Diff line change
Expand Up @@ -261,3 +261,38 @@
- role: text
type: Richtext
default: :lorem_ipsum

- name: element_with_ingredient_groups
ingredients:
- role: title
type: Text
- role: description
type: Richtext
group: details
- role: width
type: Text
group: size
- role: height
type: Text
group: size
- role: key_words
type: Text
group: details

- name: element_with_content_groups
contents:
- name: title
type: EssenceText
- name: description
type: EssenceRichtext
group: details
- name: width
type: EssenceText
group: size
- name: height
type: EssenceText
group: size
- name: key_words
type: EssenceText
group: details

4 changes: 3 additions & 1 deletion spec/dummy/config/alchemy/page_layouts.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@
left_column,
old,
all_you_can_eat_ingredients,
element_with_ingredients
element_with_ingredients,
element_with_ingredient_groups,
element_with_content_groups
]
autogenerate: [all_you_can_eat, right_column, left_column]

Expand Down
46 changes: 46 additions & 0 deletions spec/features/admin/edit_elements_feature_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -133,4 +133,50 @@
end
end
end

{content: "name", ingredient: "role"}.each do |type, name_field|
describe "With an element that has #{type} groups" do
let(:element) { create(:alchemy_element, page: a_page, name: "element_with_#{type}_groups") }

# Need to be on page editor rather than just admin_elements in order to have JS interaction
before { visit alchemy.edit_admin_page_path(element.page) }

scenario "collapsed #{type} groups shown", :js do
# No group content initially visible
expect(page).not_to have_selector(".content-group-contents", visible: true)

page.find("a#element_#{element.id}_content_group_details_header", text: "Details").click
# 'Details' group content visible
expect(page).to have_selector("#element_#{element.id}_content_group_details", visible: true)
within("#element_#{element.id}_content_group_details") do
expect(page).to have_selector("[data-#{type}-#{name_field}='description']")
expect(page).to have_selector("[data-#{type}-#{name_field}='key_words']")
end
expect(page).to have_selector("#element_#{element.id}_content_group_details", visible: true)

# 'Size' group content not visible
expect(page).not_to have_selector("#element_#{element.id}_content_group_size", visible: true)

page.find("a#element_#{element.id}_content_group_size_header", text: "Size").click
# 'Size' group now visible
expect(page).to have_selector("#element_#{element.id}_content_group_size", visible: true)
within("#element_#{element.id}_content_group_size") do
expect(page).to have_selector("[data-#{type}-#{name_field}='width']")
expect(page).to have_selector("[data-#{type}-#{name_field}='height']")
end

page.find("a#element_#{element.id}_content_group_size_header", text: "Size").click
# 'Size' group hidden
expect(page).not_to have_selector("#element_#{element.id}_content_group_size", visible: true)
end

scenario "expanded content groups persist between visits", :js do
expect(page).not_to have_selector("#element_#{element.id}_content_group_details", visible: true)
page.find("a#element_#{element.id}_content_group_details_header", text: "Details").click
expect(page).to have_selector("#element_#{element.id}_content_group_details", visible: true)
visit alchemy.edit_admin_page_path(element.page)
expect(page).to have_selector("#element_#{element.id}_content_group_details", visible: true)
end
end
end
end
2 changes: 2 additions & 0 deletions spec/models/alchemy/site_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,8 @@ module Alchemy
"old",
"all_you_can_eat_ingredients",
"element_with_ingredients",
"element_with_ingredient_groups",
"element_with_content_groups",
],
},
{
Expand Down

0 comments on commit 196243a

Please sign in to comment.