Skip to content

Commit

Permalink
Merge branch 'feature/redesign-accountability-turbo' into feature/red…
Browse files Browse the repository at this point in the history
…esign-staging

* feature/redesign-accountability-turbo:
  Ensure the correct use of only one h1 displaying/hidding drawers
  Avoid initialize and open drawer twice
  Display a preview of index on background of results show
  Update close drawer url with filtered path
  Improve drawers navigation
  Initialize drawers dialog with the turbo:frame-render event
  Display results show inside a drawer using a turbo frame
  Allow card_l_cell to open linked resource on a turbo frame
  Fix proposal etiquette and length validator with base64 images (#9639)
  • Loading branch information
entantoencuanto committed Nov 2, 2022
2 parents 717aaa2 + 3042976 commit d98f844
Show file tree
Hide file tree
Showing 18 changed files with 231 additions and 75 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<h2 class="h2 decorator"><%= title %></h2>
<h1 class="h2 decorator" data-heading-tag><%= title %></h1>

<div class="editor-content mt-8">
<%= description %>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
<% results.each do |result| %>
<%= card_for result, link_whole_card: true, render_extra_data: true %>
<%= card_for result, link_whole_card: true, render_extra_data: true, turbo_frame: "project_frame" %>
<% end %>
Original file line number Diff line number Diff line change
@@ -1,27 +1,4 @@
<%# REDESIGN_PENDING: Remove the mock content once integrated in the index view %>
<!-- MOCK CONTENT -->
<div class="container">
<button class="button button__lg button__primary" data-drawer-open>Trigger</button>
</div>
<!-- end MOCK CONTENT -->

<% content_for :aside do %>
<div class="accountability__project-aside">
<% if component_settings.display_progress_enabled? %>
<%= cell(
"decidim/accountability/status",
result,
title: t("models.result.fields.progress", scope: "decidim.accountability"),
extra_classes: "accountability__status__project"
) %>
<% end %>
<%= cell("decidim/accountability/result_metadata", result, template: :project_aside) %>
</div>
<% end %>
<%# REDESIGN_PENDING: Resolve the drawer feature using turbo %>
<%= render layout: "layouts/decidim/shared/drawer" , locals: { next: "https://www.." , prev: "https://www.." } do %>
<%= render layout: "layouts/decidim/shared/drawer" , locals: { next: "https://www..", prev: "https://www..", close_url: results_path } do %>
<%= cell("decidim/accountability/project", result) %>

<div class="mt-8 accountability__project-actions">
Expand All @@ -40,4 +17,19 @@
<div class="mt-8">
<%= cell "decidim/accountability/result_metadata", result, template: :show_footer %>
</div>

<% content_for :drawer_aside do %>
<div class="accountability__project-aside">
<% if component_settings.display_progress_enabled? %>
<%= cell(
"decidim/accountability/status",
result,
title: t("models.result.fields.progress", scope: "decidim.accountability"),
extra_classes: "accountability__status__project"
) %>
<% end %>
<%= cell("decidim/accountability/result_metadata", result, template: :project_aside) %>
</div>
<% end %>
<% end %>
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<% if local_assigns[:main_action] %>
<h1 class="h1 decorator" data-heading-tag><%= component_name %></h1>
<% else %>
<h2 class="h1 decorator"><%= component_name %></h2>
<% end %>

<div class="accountability__status-container" turbo="false">
<%= cell(
"decidim/accountability/status",
nil,
url: root_path,
title: t("decidim.accountability.results.home_header.global_status"),
extra_classes: "accountability__status__parent",
render_blank: true
) %>
<% categories_hierarchy.each do |category| %>
<%= cell(
"decidim/accountability/status",
category,
url: results_path(filter: { with_category: category, with_scope: current_scope }),
extra_classes: "accountability__status__parent",
render_count: false,
render_blank: true
) %>
<% end %>
<% if category.present? %>
<div>
<%= external_icon "media/images/breadcrumb_arrow.svg" %>
<%= cell(
"decidim/accountability/status",
category,
extra_classes: "accountability__status__child",
url: results_path(filter: { with_category: category, with_scope: current_scope }),
render_blank: true
) %>
</div>
<% end %>
</div>

<%= render partial: "scope_filters" if current_component.has_subscopes? %>
Original file line number Diff line number Diff line change
Expand Up @@ -7,43 +7,7 @@
<% end %>
<% content_for :aside do %>
<h1 class="h1 decorator"><%= component_name %></h1>

<div class="accountability__status-container">
<%= cell(
"decidim/accountability/status",
nil,
url: root_path,
title: t("decidim.accountability.results.home_header.global_status"),
extra_classes: "accountability__status__parent",
render_blank: true
) %>
<% categories_hierarchy.each do |category| %>
<%= cell(
"decidim/accountability/status",
category,
url: results_path(filter: { with_category: category, with_scope: current_scope }),
extra_classes: "accountability__status__parent",
render_count: false,
render_blank: true
) %>
<% end %>
<% if category.present? %>
<div>
<%= external_icon "media/images/breadcrumb_arrow.svg" %>
<%= cell(
"decidim/accountability/status",
category,
extra_classes: "accountability__status__child",
url: results_path(filter: { with_category: category, with_scope: current_scope }),
render_blank: true
) %>
</div>
<% end %>
</div>

<%= render partial: "scope_filters" if current_component.has_subscopes? %>
<%= render partial: "projects_aside", locals: { main_action: true } %>
<% end %>
<%= render layout: "layouts/decidim/shared/layout_two_col" do %>
Expand All @@ -58,3 +22,4 @@
<%= decidim_paginate results, order_start_time: params[:order_start_time], with_scope: params.dig(:filter, :with_scope) %>
</div>
<% end %>
<%= turbo_frame_tag "project_frame", data: { filtered_path: results_path(filter: filter_params.compact_blank) } %>
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<% content_for :js_content do %>
<%= javascript_pack_tag "decidim_accountability" %>
<% end %>
<% content_for :css_content do %>
<%= stylesheet_pack_tag "decidim_accountability", media: "all" %>
<% end %>
<%= turbo_frame_tag "main_frame" do %>
<% content_for :aside do %>
<%= render partial: "projects_aside" %>
<% end %>
<%= render layout: "layouts/decidim/shared/layout_two_col" do %>
<% if category.present? %>
<h2 class="h4"><%= translated_attribute category.name %></h2>
<% else %>
<h2 class="h4"><%= t("decidim.accountability.results.home_header.global_status") %></h2>
<% end %>

<div id="results" class="my-20">
<%= t("decidim.accountability.results.preview.loading") %>
</div>
<% end %>
<% end %>
<%# <%= turbo_frame_tag "project_frame" %1> %>
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,9 @@ edit_link(
<%= stylesheet_pack_tag "decidim_accountability", media: "all" %>
<% end %>
<%# REDESIGN_PENDING: this content must go inside the drawer, now the displayed result is kinda odd %>
<%= render partial: "project", locals: { result: result } %>
<%= turbo_frame_tag "main_frame", src: preview_results_path %>
<%= turbo_frame_tag "project_frame" do %>
<%= render partial: "project", locals: { result: result } %>
<%= turbo_stream_action_tag :open_drawer, frame_id: :project_frame %>
<% end %>
2 changes: 2 additions & 0 deletions decidim-accountability/config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,8 @@ en:
global_status: Global execution status
nav_breadcrumb:
global: Global execution
preview:
loading: Loading…
search:
search: Search for actions
show:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ class Engine < ::Rails::Engine

routes do
resources :results, only: [:index, :show] do
get :preview, on: :collection
resources :versions, only: [:show, :index]
end
root to: "results#home"
Expand Down
2 changes: 1 addition & 1 deletion decidim-core/app/cells/decidim/card_l/show.erb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<% if has_link_to_resource? && link_whole_card? %>
<%= link_to resource_path, class: "item-list #{extra_class}", id: resource_id do %>
<%= link_to resource_path, class: "item-list #{extra_class}", id: resource_id, **html_options do %>
<%= render :content %>
<% end %>
<% else %>
Expand Down
2 changes: 1 addition & 1 deletion decidim-core/app/cells/decidim/card_l/title.erb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<%= content_tag title_tag, class: "h4 item-list__title" do %>
<% if has_link_to_resource? && !link_whole_card? %>
<%= link_to title, resource_path %>
<%= link_to title, resource_path, **html_options %>
<% else %>
<%= title %>
<% end %>
Expand Down
10 changes: 10 additions & 0 deletions decidim-core/app/cells/decidim/card_l_cell.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,16 @@ def extra_class
""
end

def html_options
@html_options ||= (options[:html_options] || {}).deep_merge(turbo_frame_options)
end

def turbo_frame_options
return {} if options[:turbo_frame].blank?

{ data: { turbo_frame: options[:turbo_frame], turbo_action: "replace" } }
end

def presented_resource
present(resource)
end
Expand Down
35 changes: 34 additions & 1 deletion decidim-core/app/packs/src/decidim/redesigned_index.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ import backToListLink from "./back_to_list"
import markAsReadNotifications from "./notifications"
import RemoteModal from "./redesigned_ajax_modals"
import addFloatingHelp from "./redesigned_floating_help"
import { StreamActions } from "@hotwired/turbo"

// bad practice: window namespace should avoid be populated as much as possible
// rails-translations could be referrenced through a single Decidim.I18n object
Expand Down Expand Up @@ -202,14 +203,46 @@ const initializer = () => {

// Initialize the floating help blocks for the participatory processes
document.querySelectorAll("[data-floating-help]").forEach((elem) => addFloatingHelp(elem))

document.querySelectorAll("[data-drawer]").forEach(
({ dataset: { drawer } }) =>
new Dialogs(`[data-drawer="${drawer}"]`, {
closingSelector: `[data-drawer-close="${drawer}"]`
}).open()
)

}

if ("Turbo" in window) {
document.addEventListener("turbo:frame-render", () => initializer());
document.addEventListener("turbo:frame-render", (frame) => {
initializer()

// This ensures the aside heading tag is transformed to h2 or h1 if the drawer is shown or hidden
const element = document.querySelector("aside [data-heading-tag]")
if (element) {
const tagName = frame.target.querySelector("[data-drawer]") ? "H2" : "H1"

const newItem = document.createElement(tagName);
newItem.className = element.className;
newItem.dataset.headingTag = element.dataset.headingTag;
newItem.innerHTML = element.innerHTML;
element.parentNode.replaceChild(newItem, element);
}
});
document.addEventListener("turbo:load", () => initializer());
} else {
// If no jQuery is used the Tribute feature used in comments to autocomplete
// mentions stops working
// document.addEventListener("DOMContentLoaded", () => {
$(() => initializer());
}

StreamActions.open_drawer = function() {
const frameId = this.getAttribute("frame_id");
const drawerItem = document.getElementById(frameId);
const filteredPath = drawerItem.dataset.filteredPath;

if (filteredPath) {
drawerItem.querySelector("a[data-drawer-close]").setAttribute("href", filteredPath);
}
}
10 changes: 7 additions & 3 deletions decidim-core/app/validators/etiquette_validator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,16 @@
# This validator takes care of ensuring the validated content is
# respectful, doesn't use caps, and overall is meaningful.
class EtiquetteValidator < ActiveModel::EachValidator
include ActionView::Helpers::SanitizeHelper

def validate_each(record, attribute, value)
return if value.blank?

validate_caps(record, attribute, value)
validate_marks(record, attribute, value)
validate_caps_first(record, attribute, value)
text_value = strip_tags(value)

validate_caps(record, attribute, text_value)
validate_marks(record, attribute, text_value)
validate_caps_first(record, attribute, text_value)
end

private
Expand Down
12 changes: 10 additions & 2 deletions decidim-core/app/views/layouts/decidim/shared/_drawer.html.erb
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
<div data-drawer>
<div>
<div data-drawer-close><%= icon "close-line", class: "w-5 h-5 text-secondary fill-current" %></div>
<% close_url = local_assigns[:close_url] %>
<% turbo_frame = local_assigns[:turbo_frame] || "main_frame" %>
<% if close_url.present? %>
<%= link_to close_url, data: { drawer_close: "", turbo_frame:, turbo_action: "replace" } do %>
<%= icon "close-line", class: "w-5 h-5 text-secondary fill-current" %>
<% end %>
<% else %>
<div data-drawer-close><%= icon "close-line", class: "w-5 h-5 text-secondary fill-current" %></div>
<% end %>
<% if local_assigns[:prev].present? %>
<div data-drawer-prev><%= icon "arrow-right-s-line", class: "w-8 h-8 text-secondary fill-current" %></div>
<% end %>
Expand All @@ -9,7 +17,7 @@
<% end %>
<div data-drawer-content>
<div><%= yield %></div>
<div><%= yield :aside %></div>
<div><%= yield :drawer_aside %></div>
</div>
</div>
</div>
15 changes: 15 additions & 0 deletions decidim-core/spec/validators/etiquette_validator_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -81,4 +81,19 @@ def self.model_name
it { is_expected.to be_valid }
end
end

context "when the text is written in HTML" do
let(:body) do
data = File.read(Decidim::Dev.asset("avatar.jpg"))
encoded = Base64.encode64(data)

<<~HTML
<p>Text before the image.</p>
<p><img src="data:image/jpeg;base64,#{encoded.strip}"></p>
<p>Some other text after the image.</p>
HTML
end

it { is_expected.to be_valid }
end
end
7 changes: 5 additions & 2 deletions decidim-proposals/app/validators/proposal_length_validator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,14 @@
# allows the minimum and maximum values to be lambdas allowing us to fetch the
# maximum length dynamically for each proposals component.
class ProposalLengthValidator < ActiveModel::EachValidator
include ActionView::Helpers::SanitizeHelper

def validate_each(record, attribute, value)
return if value.blank?

validate_min_length(record, attribute, value)
validate_max_length(record, attribute, value)
text_value = strip_tags(value)
validate_min_length(record, attribute, text_value)
validate_max_length(record, attribute, text_value)
end

private
Expand Down
Loading

0 comments on commit d98f844

Please sign in to comment.