From 5673dd8275ada1881c63fa4cb61551959897a39a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20Verg=C3=A9s?= Date: Tue, 20 Jun 2023 13:37:37 +0200 Subject: [PATCH 01/24] prevent changing document if annotations. Remove sections if not --- .../admin/update_document.rb | 19 +++++++ .../admin/documents_controller.rb | 26 +++++----- .../admin/documents/_form.html.erb | 5 +- config/locales/en.yml | 12 ++++- .../participatory_documents/test/factories.rb | 12 +++++ ...in_manages_participatory_documents_spec.rb | 49 ++++++++++++++++++- 6 files changed, 107 insertions(+), 16 deletions(-) diff --git a/app/commands/decidim/participatory_documents/admin/update_document.rb b/app/commands/decidim/participatory_documents/admin/update_document.rb index e2bbb57c..80108219 100644 --- a/app/commands/decidim/participatory_documents/admin/update_document.rb +++ b/app/commands/decidim/participatory_documents/admin/update_document.rb @@ -17,9 +17,13 @@ def call begin transaction do + destroy_sections! update_document end broadcast(:ok, document) + rescue ActiveRecord::RecordNotDestroyed + # if sections contains annotations, cannot be deleted + broadcast(:error, document.sections.filter_map { |sec| sec.errors[:base].presence }.flatten) rescue ActiveRecord::RecordInvalid form.errors.add(:file, document.errors[:file]) if document.errors.include? :file broadcast(:invalid) @@ -46,6 +50,21 @@ def update_document **attributes ) end + + def destroy_sections! + return if form.file.blank? + return unless document.sections.any? + + document.sections.each do |section| + Decidim.traceability.perform_action!( + "delete", + section, + current_user + ) do + section.destroy! + end + end + end end end end diff --git a/app/controllers/decidim/participatory_documents/admin/documents_controller.rb b/app/controllers/decidim/participatory_documents/admin/documents_controller.rb index 3c2b9bb3..4d28444f 100644 --- a/app/controllers/decidim/participatory_documents/admin/documents_controller.rb +++ b/app/controllers/decidim/participatory_documents/admin/documents_controller.rb @@ -6,7 +6,7 @@ module Admin # This controller allows admins to manage documents in a participatory process. class DocumentsController < Admin::ApplicationController include Decidim::ApplicationHelper - include Decidim::ParticipatoryDocuments::Admin::NeedsAdminSnippets + include NeedsAdminSnippets helper Decidim::LayoutHelper helper_method :sections @@ -22,14 +22,14 @@ def index def new enforce_permission_to :create, :participatory_document - @form = form(Decidim::ParticipatoryDocuments::Admin::DocumentForm).from_params(params) + @form = form(DocumentForm).from_params(params) end def create enforce_permission_to :create, :participatory_document - @form = form(Decidim::ParticipatoryDocuments::Admin::DocumentForm).from_params(params) + @form = form(DocumentForm).from_params(params) - Admin::CreateDocument.call(@form) do + CreateDocument.call(@form) do on(:ok) do |document| flash[:notice] = I18n.t("documents.create.success", scope: "decidim.participatory_documents.admin") redirect_to edit_pdf_documents_path(id: document.id) @@ -43,20 +43,24 @@ def create end def edit - # TODO: before uploading a new PDF, check no participation associated (no boxes/groups created) enforce_permission_to :update, :participatory_document, document: document - @form = form(Admin::DocumentForm).from_model(document) + @form = form(DocumentForm).from_model(document) end def update enforce_permission_to :update, :participatory_document, document: document - @form = form(Admin::DocumentForm).from_params(params) - Admin::UpdateDocument.call(@form, document) do - on(:ok) do |_proposal| + @form = form(DocumentForm).from_params(params) + UpdateDocument.call(@form, document) do + on(:ok) do flash[:notice] = t("documents.update.success", scope: "decidim.participatory_documents.admin") redirect_to documents_path end + on(:error) do |error| + flash[:alert] = t("documents.update.error", scope: "decidim.participatory_documents.admin") + " #{error}" + redirect_to documents_path + end + on(:invalid) do flash.now[:alert] = t("documents.update.error", scope: "decidim.participatory_documents.admin") render :edit @@ -65,7 +69,7 @@ def update end def pdf_viewer - @form = form(Decidim::ParticipatoryDocuments::Admin::SectionForm).from_params({}) + @form = form(SectionForm).from_params({}) render layout: false end @@ -76,7 +80,7 @@ def edit_pdf private def sections - @sections ||= document.sections + @sections ||= document&.sections end end end diff --git a/app/views/decidim/participatory_documents/admin/documents/_form.html.erb b/app/views/decidim/participatory_documents/admin/documents/_form.html.erb index d54d0e1c..17a60f1a 100644 --- a/app/views/decidim/participatory_documents/admin/documents/_form.html.erb +++ b/app/views/decidim/participatory_documents/admin/documents/_form.html.erb @@ -8,7 +8,10 @@
- <%= form.upload( :file, optional: !current_component.published?) %> + <% if sections&.any? %> +
<%= t document&.annotations&.any? ? ".alert_annotations_html" : ".warning_sections_html" %>
+ <% end %> + <%= form.upload :file, optional: !current_component.published?, help_i18n_messages: "pdf_message" %>
diff --git a/config/locales/en.yml b/config/locales/en.yml index 005ebf77..0742a385 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -81,6 +81,10 @@ en: administrator notification_title: A suggestion you submitted on "%{resource_title}" document has been answered by an administrator + forms: + file_help: + file: + pdf_message: Only PDF files are allowed participatory_documents: actions: back: Back @@ -97,12 +101,16 @@ en: title: Edit Participatory document update: Update form: + alert_annotations_html: "IMPORTANT: This document cannot + be changed or removed because it already has suggestions attached." box_style_preview: 'Box style preview:' + warning_sections_html: "Warning: If you upload a new + document, all the participatory areas will be deleted!" index: start: Please upload a PDF to start new: - create: Create Participatory document - title: New Participatory document + create: Create participatory document + title: New participatory document sections: empty: "(empty)" update: diff --git a/lib/decidim/participatory_documents/test/factories.rb b/lib/decidim/participatory_documents/test/factories.rb index 0d0ab209..9bd54a51 100644 --- a/lib/decidim/participatory_documents/test/factories.rb +++ b/lib/decidim/participatory_documents/test/factories.rb @@ -17,6 +17,18 @@ trait :with_file do file { Decidim::Dev.test_file("Exampledocument.pdf", "application/pdf") } end + + trait :with_sections do + after :create do |document| + document.sections = create_list(:participatory_documents_section, 2, document: document) + end + end + + trait :with_annotations do + after :create do |document| + document.sections = create_list(:participatory_documents_section, 2, :with_annotations, document: document) + end + end end factory :participatory_documents_section, class: "Decidim::ParticipatoryDocuments::Section" do diff --git a/spec/system/admin/admin_manages_participatory_documents_spec.rb b/spec/system/admin/admin_manages_participatory_documents_spec.rb index d900f3c5..8981fd36 100644 --- a/spec/system/admin/admin_manages_participatory_documents_spec.rb +++ b/spec/system/admin/admin_manages_participatory_documents_spec.rb @@ -50,7 +50,7 @@ def upload_file expect(page.execute_script("return window.getComputedStyle(document.querySelector('.box-preview .box')).borderColor")).to eq("rgb(240, 15, 0)") if create - click_button "Create Participatory document" + click_button "Create participatory document" else click_button "Update" end @@ -72,6 +72,10 @@ def upload_file end it_behaves_like "creating a document", true + + it "has no areas delete warning" do + expect(page).not_to have_content("all the participatory areas will be deleted!") + end end context "when a file is not uploaded" do @@ -86,7 +90,7 @@ def upload_file end end - context "when document needs update" do + context "when document is updated" do let!(:document) { create :participatory_documents_document, :with_file, component: component } let(:default_color) { "rgb(250, 170, 170)" } let!(:default_color_with_opacity) { "rgba(250, 170, 170, 0.2)" } @@ -97,6 +101,47 @@ def upload_file end it_behaves_like "creating a document", false + + it "has no sections delete warning" do + expect(page).not_to have_content("all the participatory areas will be deleted!") + end + + context "when document has areas" do + let!(:document) { create :participatory_documents_document, :with_file, :with_sections, component: component } + + it "has sections delete warning" do + expect(page).to have_content("all the participatory areas will be deleted!") + expect(document.sections.count).to eq(2) + attach_file :document_file, Decidim::Dev.asset("Exampledocument.pdf") + click_button "Update" + expect(document.sections.reload.count).to eq(0) + end + + context "and areas have suggestions" do + let!(:document) { create :participatory_documents_document, :with_file, :with_annotations, component: component } + + it "do not remove the document" do + expect(page).not_to have_content("all the participatory areas will be deleted!") + expect(page).to have_content("This document cannot be changed or removed because it already has suggestions attached") + expect(document.sections.count).to eq(2) + attach_file :document_file, Decidim::Dev.asset("Exampledocument.pdf") + click_button "Update" + expect(document.sections.reload.count).to eq(2) + expect(page).to have_content("Cannot delete record because dependent annotations exist") + end + + it "updates other parts of the document" do + fill_in_i18n_editor( + :document_description, + "#document-description-tabs", + en: "This is description of the file" + ) + click_button "Update" + expect(page).to have_content("Document has been successfully updated") + expect(document.reload.description["en"]).to include("This is description of the file") + end + end + end end context "when a file is uploaded" do From f7fe346f91d5d5b3369d3b3641591d977e7a2946 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20Verg=C3=A9s?= Date: Wed, 21 Jun 2023 16:32:21 +0200 Subject: [PATCH 02/24] add webkit compatiblity css --- .../participatory_documents/pdf/admin_polygons.scss | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/app/packs/stylesheets/decidim/participatory_documents/pdf/admin_polygons.scss b/app/packs/stylesheets/decidim/participatory_documents/pdf/admin_polygons.scss index 78dd932b..c1c7aceb 100644 --- a/app/packs/stylesheets/decidim/participatory_documents/pdf/admin_polygons.scss +++ b/app/packs/stylesheets/decidim/participatory_documents/pdf/admin_polygons.scss @@ -84,6 +84,9 @@ width: 100%; height: 100%; background: var(--box-color); + -webkit-mask-repeat: no-repeat; + -webkit-mask-size: 37px 37px; + -webkit-mask-position: 4px 2px; mask-repeat: no-repeat; mask-size: 37px 37px; mask-position: 4px 2px; @@ -94,6 +97,9 @@ display: none; &::after { + -webkit-mask-image: url(../images/group.svg); + -webkit-mask-size: 30px 30px; + -webkit-mask-position: 7px 5px; mask-image: url(../images/group.svg); mask-size: 30px 30px; mask-position: 7px 5px; @@ -104,6 +110,7 @@ cursor: move; &::after { + -webkit-mask-image: url(../images/move.svg); mask-image: url(../images/move.svg); } } From 252d02f0172f3af369b22c320eabb8f2eead5992 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20Verg=C3=A9s?= Date: Wed, 21 Jun 2023 17:49:12 +0200 Subject: [PATCH 03/24] javascript reordering of boxes --- .../participatory_documents/pdf_admin.js | 4 +- .../admin/documents/pdf_viewer.html.erb | 42 +++++++++++++++++-- 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/app/packs/src/decidim/participatory_documents/pdf_admin.js b/app/packs/src/decidim/participatory_documents/pdf_admin.js index 8f3c17b5..ecc7c97f 100644 --- a/app/packs/src/decidim/participatory_documents/pdf_admin.js +++ b/app/packs/src/decidim/participatory_documents/pdf_admin.js @@ -34,7 +34,7 @@ window.InitDocumentManagers = function(options) { }; // Call this on an annotation layer to initialize the polygon editor (admin side) -window.InitPolygonEditor = function(layer, boxes, options) { +window.InitPolygonEditor = function(layer, boxes, options, change_callback = () => {}) { let editor = new PolygonEditor(layer, boxes, { i18n: options.i18n }); // Open the global box modal settings when a box is clicked editor.onBoxClick = (box) => { @@ -47,9 +47,11 @@ window.InitPolygonEditor = function(layer, boxes, options) { // update the global state manager when a box is edited or destroyed using the polygon editor (mouse interaction) editor.onBoxChange = (box) => { window.PdfDocStateManager.add(box); + change_callback(box); }; editor.onBoxDestroy = (box) => { window.PdfDocStateManager.remove(box); + change_callback(box); }; return editor; diff --git a/app/views/decidim/participatory_documents/admin/documents/pdf_viewer.html.erb b/app/views/decidim/participatory_documents/admin/documents/pdf_viewer.html.erb index 948c4bb7..313c0ef3 100644 --- a/app/views/decidim/participatory_documents/admin/documents/pdf_viewer.html.erb +++ b/app/views/decidim/participatory_documents/admin/documents/pdf_viewer.html.erb @@ -37,8 +37,8 @@ PDFViewerApplication.initializedPromise.then(function() { var options = { i18n: I18n, - editSectionPath: (group) => SectionPath + `/${group}/edit`, - sectionPath: (group) => SectionPath + `/${group}`, + editSectionPath: function(group) { return SectionPath + `/${group}/edit`; }, + sectionPath: function(group) { return SectionPath + `/${group}`; }, newSectionPath: SectionPath + "/new", annotationsPath: AnnotationsPath, pdfViewer: PDFViewerApplication.pdfViewer, @@ -56,10 +56,46 @@ var page = PDFViewerApplication.pdfViewer._pages[doc.pageNumber - 1]; var annotationsLayer = page.annotationEditorLayer && page.annotationEditorLayer.div; var savedPage = pages[doc.pageNumber]; + var boxChanged = function(box) { + // reorder box numbers according to page, x position, and y position + var boxes = Array.from(document.querySelectorAll(".polygon-ready .box")); + boxes.sort(function(a, b) { + var aPage = parseInt(a.parentElement.dataset.pageNumber, 10); + var bPage = parseInt(b.parentElement.dataset.pageNumber, 10) + var aLeft = parseInt(a.style.left, 10); + var bLeft = parseInt(b.style.left, 10); + var aTop = parseInt(a.style.top, 10); + var bTop = parseInt(b.style.top, 10); + if(aPage === bPage) { + if(aTop === bTop) { + return aLeft - bLeft; + } else { + return aTop - bTop; + } + } else { + return aPage - bPage; + } + }); + var sectionNumber = 0; + var allSections = {}; + boxes.forEach(function(box, index) { + box.dataset.position = index + 1; + box.querySelector("span").innerText = index + 1; + if(allSections[box.dataset.section]) { + box.dataset.sectionNumber = allSections[box.dataset.section]; + } else { + sectionNumber++; + box.dataset.sectionNumber = sectionNumber; + } + allSections[box.dataset.section] = sectionNumber; + }); + }; + // Let's render the object only if not already existing. // Note that the PDF library might redraw the annotation layer, if this happens we need to re-render the areas. if(annotationsLayer && (!savedPage || savedPage.boxEditor.div !== annotationsLayer)) { - page.boxEditor = window.InitPolygonEditor(annotationsLayer, CurrentBoxes.filter(box => box.page_number === doc.pageNumber), options); + annotationsLayer.dataset.pageNumber = doc.pageNumber; + page.boxEditor = window.InitPolygonEditor(annotationsLayer, CurrentBoxes.filter(function(box) { return box.page_number === doc.pageNumber; }), options, boxChanged); pages[doc.pageNumber] = page; } }); From c527fa934a91eb5f5f9126ad2ffecbc099fe6562 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20Verg=C3=A9s?= Date: Thu, 22 Jun 2023 11:52:56 +0200 Subject: [PATCH 04/24] add postion in db --- ...m_participatory_documents_box_positions.rb | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 db/migrate/20230622081831_add_decidim_participatory_documents_box_positions.rb diff --git a/db/migrate/20230622081831_add_decidim_participatory_documents_box_positions.rb b/db/migrate/20230622081831_add_decidim_participatory_documents_box_positions.rb new file mode 100644 index 00000000..48577425 --- /dev/null +++ b/db/migrate/20230622081831_add_decidim_participatory_documents_box_positions.rb @@ -0,0 +1,35 @@ +# frozen_string_literal: true + +class AddDecidimParticipatoryDocumentsBoxPositions < ActiveRecord::Migration[6.0] + class Document < ApplicationRecord + self.table_name = :decidim_participatory_documents_documents + has_many :sections + has_many :annotations, through: :sections + end + + class Section < ApplicationRecord + self.table_name = :decidim_participatory_documents_sections + belongs_to :document + has_many :annotations + end + + class Annotation < ApplicationRecord + self.table_name = :decidim_participatory_documents_annotations + belongs_to :section + end + + def change + add_column :decidim_participatory_documents_annotations, :position, :integer, null: false, default: 0 + add_index :decidim_participatory_documents_annotations, :position + add_column :decidim_participatory_documents_sections, :position, :integer, null: false, default: 0 + add_index :decidim_participatory_documents_sections, :position + + Section.find_each do |section| + section.update_column(:position, section.document.sections.where("id < ?", section.id).count + 1) + end + + Annotation.find_each do |annotation| + annotation.update_column(:position, annotation.section.document.annotations.where("decidim_participatory_documents_annotations.id < ?", annotation.id).count + 1) + end + end +end From 755254a1bd7ec2530578060acffaa70a255f8521 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20Verg=C3=A9s?= Date: Thu, 22 Jun 2023 12:11:26 +0200 Subject: [PATCH 05/24] fix prevent document modifications on suggestions --- .../admin/update_document.rb | 20 +++++- .../admin/documents_controller.rb | 6 -- .../participatory_documents/annotation.rb | 9 +-- .../participatory_documents/document.rb | 4 ++ .../participatory_documents/section.rb | 4 -- .../admin/documents/_form.html.erb | 4 +- config/locales/en.yml | 9 ++- .../participatory_documents/test/factories.rb | 24 +++++++ .../participatory_documents/document_spec.rb | 20 ++++++ ...in_manages_participatory_documents_spec.rb | 66 ++++++++++++------- 10 files changed, 119 insertions(+), 47 deletions(-) diff --git a/app/commands/decidim/participatory_documents/admin/update_document.rb b/app/commands/decidim/participatory_documents/admin/update_document.rb index 80108219..0225b1da 100644 --- a/app/commands/decidim/participatory_documents/admin/update_document.rb +++ b/app/commands/decidim/participatory_documents/admin/update_document.rb @@ -21,9 +21,10 @@ def call update_document end broadcast(:ok, document) - rescue ActiveRecord::RecordNotDestroyed - # if sections contains annotations, cannot be deleted - broadcast(:error, document.sections.filter_map { |sec| sec.errors[:base].presence }.flatten) + rescue ActiveRecord::RecordNotDestroyed => e + # if sections contains annotations, can be deleted + # if sections contains suggestions, cannot be deleted + broadcast(:error, e.message) rescue ActiveRecord::RecordInvalid form.errors.add(:file, document.errors[:file]) if document.errors.include? :file broadcast(:invalid) @@ -53,8 +54,21 @@ def update_document def destroy_sections! return if form.file.blank? + + raise ActiveRecord::RecordNotDestroyed, I18n.t("activemodel.errors.models.document.has_suggestions") if document.has_suggestions? + return unless document.sections.any? + document.annotations.each do |annotation| + Decidim.traceability.perform_action!( + "delete", + annotation, + current_user + ) do + annotation.destroy! + end + end + document.sections.each do |section| Decidim.traceability.perform_action!( "delete", diff --git a/app/controllers/decidim/participatory_documents/admin/documents_controller.rb b/app/controllers/decidim/participatory_documents/admin/documents_controller.rb index 4d28444f..069d120f 100644 --- a/app/controllers/decidim/participatory_documents/admin/documents_controller.rb +++ b/app/controllers/decidim/participatory_documents/admin/documents_controller.rb @@ -76,12 +76,6 @@ def pdf_viewer def edit_pdf enforce_permission_to :update, :participatory_document, document: document end - - private - - def sections - @sections ||= document&.sections - end end end end diff --git a/app/models/decidim/participatory_documents/annotation.rb b/app/models/decidim/participatory_documents/annotation.rb index 9b795ab0..2d4df243 100644 --- a/app/models/decidim/participatory_documents/annotation.rb +++ b/app/models/decidim/participatory_documents/annotation.rb @@ -4,18 +4,15 @@ module Decidim module ParticipatoryDocuments class Annotation < ApplicationRecord belongs_to :section, class_name: "Decidim::ParticipatoryDocuments::Section" + has_many :suggestions, class_name: "Decidim::ParticipatoryDocuments::Suggestion", dependent: :restrict_with_error, as: :suggestable + delegate :document, to: :section + delegate :organization, :participatory_space, :component, to: :document, allow_nil: true def self.log_presenter_class_for(_log) Decidim::ParticipatoryDocuments::AdminLog::AnnotationPresenter end - # to have a consecutive number of the boxes - # Suggestion: try to order by rect coordinates so number go according the UI in the document - def position - @position ||= document.annotations.where("decidim_participatory_documents_annotations.id < ?", id).count + 1 - end - def serialize @serialize ||= { id: id, diff --git a/app/models/decidim/participatory_documents/document.rb b/app/models/decidim/participatory_documents/document.rb index 4b386c20..c7b825a8 100644 --- a/app/models/decidim/participatory_documents/document.rb +++ b/app/models/decidim/participatory_documents/document.rb @@ -26,6 +26,10 @@ class Document < ApplicationRecord def self.log_presenter_class_for(_log) Decidim::ParticipatoryDocuments::AdminLog::DocumentPresenter end + + def has_suggestions? + suggestions.any? || annotations.any? { |annotation| annotation.suggestions.any? } + end end end end diff --git a/app/models/decidim/participatory_documents/section.rb b/app/models/decidim/participatory_documents/section.rb index 5d6b4683..46f04c63 100644 --- a/app/models/decidim/participatory_documents/section.rb +++ b/app/models/decidim/participatory_documents/section.rb @@ -25,10 +25,6 @@ def title artificial_title.merge(super.reject { |_key, value| value.blank? }) end - def position - @position ||= document.sections.where("id < ?", id).count + 1 - end - private def artificial_title diff --git a/app/views/decidim/participatory_documents/admin/documents/_form.html.erb b/app/views/decidim/participatory_documents/admin/documents/_form.html.erb index 17a60f1a..9b3442b3 100644 --- a/app/views/decidim/participatory_documents/admin/documents/_form.html.erb +++ b/app/views/decidim/participatory_documents/admin/documents/_form.html.erb @@ -8,8 +8,8 @@
- <% if sections&.any? %> -
<%= t document&.annotations&.any? ? ".alert_annotations_html" : ".warning_sections_html" %>
+ <% if document&.sections&.any? || document&.has_suggestions? %> +
<%= t document&.has_suggestions? ? ".alert_suggestions_html" : ".warning_sections_html" %>
<% end %> <%= form.upload :file, optional: !current_component.published?, help_i18n_messages: "pdf_message" %>
diff --git a/config/locales/en.yml b/config/locales/en.yml index 7ee76de9..2763365d 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -13,9 +13,12 @@ en: attributes: state: inclusion: It's not possible to publish with status "not answered" + document: + has_suggestions: This document cannot be changed or removed because it has + suggestions suggestion: attributes: - not_blank: 'Validation failed: Please provide a message or upload a file.' + not_blank: 'Validation failed: Please provide a message or upload a file' too_long: is too long (over %{max_length} characters) too_short: is too short (under %{min_length} characters) decidim: @@ -103,8 +106,8 @@ en: title: Edit Participatory document update: Update form: - alert_annotations_html: "IMPORTANT: This document cannot - be changed or removed because it already has suggestions attached." + alert_suggestions_html: "IMPORTANT: This document cannot + be changed or removed because it already has suggestions attached" box_style_preview: 'Box style preview:' warning_sections_html: "Warning: If you upload a new document, all the participatory areas will be deleted!" diff --git a/lib/decidim/participatory_documents/test/factories.rb b/lib/decidim/participatory_documents/test/factories.rb index 9bd54a51..7eceae91 100644 --- a/lib/decidim/participatory_documents/test/factories.rb +++ b/lib/decidim/participatory_documents/test/factories.rb @@ -29,6 +29,18 @@ document.sections = create_list(:participatory_documents_section, 2, :with_annotations, document: document) end end + + trait :with_global_suggestions do + after :create do |document| + document.suggestions = create_list(:participatory_documents_suggestion, 2, suggestable: document) + end + end + + trait :with_suggestions do + after :create do |document| + document.sections = create_list(:participatory_documents_section, 2, :with_suggestions, document: document) + end + end end factory :participatory_documents_section, class: "Decidim::ParticipatoryDocuments::Section" do @@ -46,6 +58,12 @@ section.annotations = create_list(:participatory_documents_annotation, 2, section: section) end end + + trait :with_suggestions do + after :create do |section| + section.annotations = create_list(:participatory_documents_annotation, 2, :with_suggestions, section: section) + end + end end factory :participatory_documents_annotation, class: "Decidim::ParticipatoryDocuments::Annotation" do @@ -58,6 +76,12 @@ annotation.rect = { top: top, left: left, width: 15.9411, height: 18.0857 } end + + trait :with_suggestions do + after :create do |annotation| + annotation.suggestions = create_list(:participatory_documents_suggestion, 2, suggestable: annotation) + end + end end factory :participatory_documents_suggestion, class: "Decidim::ParticipatoryDocuments::Suggestion" do diff --git a/spec/models/decidim/participatory_documents/document_spec.rb b/spec/models/decidim/participatory_documents/document_spec.rb index 571f7a34..70275379 100644 --- a/spec/models/decidim/participatory_documents/document_spec.rb +++ b/spec/models/decidim/participatory_documents/document_spec.rb @@ -18,6 +18,10 @@ module ParticipatoryDocuments it { expect(described_class.reflect_on_association(:annotations).macro).to eq(:has_many) } end + it "has not suggestions" do + expect(document).not_to be_has_suggestions + end + include_examples "has component" include_examples "authorable" do subject { document } @@ -31,6 +35,22 @@ module ParticipatoryDocuments it { is_expected.to be_valid } it { is_expected.to be_versioned } + + context "when has global suggestions" do + let(:document) { create(:participatory_documents_document, :with_global_suggestions, component: component) } + + it "has suggestions" do + expect(document).to be_has_suggestions + end + end + + context "when has section suggestions" do + let(:document) { create(:participatory_documents_document, :with_suggestions, component: component) } + + it "has suggestions" do + expect(document).to be_has_suggestions + end + end end end end diff --git a/spec/system/admin/admin_manages_participatory_documents_spec.rb b/spec/system/admin/admin_manages_participatory_documents_spec.rb index 8981fd36..fd0f4e0a 100644 --- a/spec/system/admin/admin_manages_participatory_documents_spec.rb +++ b/spec/system/admin/admin_manages_participatory_documents_spec.rb @@ -106,9 +106,7 @@ def upload_file expect(page).not_to have_content("all the participatory areas will be deleted!") end - context "when document has areas" do - let!(:document) { create :participatory_documents_document, :with_file, :with_sections, component: component } - + shared_examples "removes sections" do it "has sections delete warning" do expect(page).to have_content("all the participatory areas will be deleted!") expect(document.sections.count).to eq(2) @@ -116,30 +114,52 @@ def upload_file click_button "Update" expect(document.sections.reload.count).to eq(0) end + end - context "and areas have suggestions" do + shared_examples "does not remove sections" do |with_sections| + it "do not remove the document" do + expect(page).not_to have_content("all the participatory areas will be deleted!") + expect(page).to have_content("This document cannot be changed or removed because it already has suggestions attached") + expect(document.sections.count).to eq(2) if with_sections + attach_file :document_file, Decidim::Dev.asset("Exampledocument.pdf") + click_button "Update" + expect(document.sections.reload.count).to eq(2) if with_sections + expect(page).to have_content("This document cannot be changed or removed because it has suggestions") + end + + it "updates other parts of the document" do + fill_in_i18n_editor( + :document_description, + "#document-description-tabs", + en: "This is description of the file" + ) + click_button "Update" + expect(page).to have_content("Document has been successfully updated") + expect(document.reload.description["en"]).to include("This is description of the file") + end + end + + context "when document has sections" do + let!(:document) { create :participatory_documents_document, :with_file, :with_sections, component: component } + + it_behaves_like "removes sections" + + context "and have global suggestions" do + let!(:document) { create :participatory_documents_document, :with_file, :with_global_suggestions, component: component } + + it_behaves_like "does not remove sections", false + end + + context "and areas have annotations (boxes)" do let!(:document) { create :participatory_documents_document, :with_file, :with_annotations, component: component } - it "do not remove the document" do - expect(page).not_to have_content("all the participatory areas will be deleted!") - expect(page).to have_content("This document cannot be changed or removed because it already has suggestions attached") - expect(document.sections.count).to eq(2) - attach_file :document_file, Decidim::Dev.asset("Exampledocument.pdf") - click_button "Update" - expect(document.sections.reload.count).to eq(2) - expect(page).to have_content("Cannot delete record because dependent annotations exist") - end + it_behaves_like "removes sections" + end - it "updates other parts of the document" do - fill_in_i18n_editor( - :document_description, - "#document-description-tabs", - en: "This is description of the file" - ) - click_button "Update" - expect(page).to have_content("Document has been successfully updated") - expect(document.reload.description["en"]).to include("This is description of the file") - end + context "and areas have suggestions" do + let!(:document) { create :participatory_documents_document, :with_file, :with_suggestions, component: component } + + it_behaves_like "does not remove sections", true end end end From 11b5be9b4b183983fd47a4d04b35e4b9294e314a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20Verg=C3=A9s?= Date: Thu, 22 Jun 2023 16:17:58 +0200 Subject: [PATCH 06/24] reorder in backend --- .../needs_positions_sorting.rb | 44 ++++ .../participatory_documents/annotation.rb | 2 + .../participatory_documents/section.rb | 3 + .../participatory_documents/section_spec.rb | 191 +++++++++++++++--- 4 files changed, 216 insertions(+), 24 deletions(-) create mode 100644 app/models/concerns/decidim/participatory_documents/needs_positions_sorting.rb diff --git a/app/models/concerns/decidim/participatory_documents/needs_positions_sorting.rb b/app/models/concerns/decidim/participatory_documents/needs_positions_sorting.rb new file mode 100644 index 00000000..ab6d7fd9 --- /dev/null +++ b/app/models/concerns/decidim/participatory_documents/needs_positions_sorting.rb @@ -0,0 +1,44 @@ +# frozen_string_literal: true + +module Decidim + module ParticipatoryDocuments + module NeedsPositionsSorting + extend ActiveSupport::Concern + + included do + after_commit :update_positions + + private + + # rubocop:disable Rails/SkipsModelValidations + def update_positions + boxes = document.annotations.reload.sort do |a, b| + if a.page_number == b.page_number + if a.rect["top"].to_i == b.rect["top"].to_i + a.rect["left"].to_i <=> b.rect["left"].to_i + else + a.position <=> b.position + end + else + a.page_number <=> b.page_number + end + end + + section_number = 0 + all_sections = {} + boxes.each_with_index do |box, index| + box.update_column(:position, index + 1) + if all_sections[box.section_id] + box.section.update_column(:position, all_sections[box.section_id]) + else + section_number += 1 + box.section.update_column(:position, section_number) + end + all_sections[box.section_id] = section_number + end + end + # rubocop:enable Rails/SkipsModelValidations + end + end + end +end diff --git a/app/models/decidim/participatory_documents/annotation.rb b/app/models/decidim/participatory_documents/annotation.rb index 2d4df243..fb6bb1a5 100644 --- a/app/models/decidim/participatory_documents/annotation.rb +++ b/app/models/decidim/participatory_documents/annotation.rb @@ -3,6 +3,8 @@ module Decidim module ParticipatoryDocuments class Annotation < ApplicationRecord + include NeedsPositionsSorting + belongs_to :section, class_name: "Decidim::ParticipatoryDocuments::Section" has_many :suggestions, class_name: "Decidim::ParticipatoryDocuments::Suggestion", dependent: :restrict_with_error, as: :suggestable diff --git a/app/models/decidim/participatory_documents/section.rb b/app/models/decidim/participatory_documents/section.rb index 46f04c63..73ab6c6c 100644 --- a/app/models/decidim/participatory_documents/section.rb +++ b/app/models/decidim/participatory_documents/section.rb @@ -8,6 +8,8 @@ class Section < ApplicationRecord include Decidim::TranslatableResource include Decidim::TranslatableAttributes include Decidim::Publicable + include NeedsPositionsSorting + belongs_to :document, class_name: "Decidim::ParticipatoryDocuments::Document" has_many :annotations, class_name: "Decidim::ParticipatoryDocuments::Annotation", dependent: :restrict_with_error has_many :suggestions, class_name: "Decidim::ParticipatoryDocuments::Suggestion", dependent: :restrict_with_error, as: :suggestable @@ -15,6 +17,7 @@ class Section < ApplicationRecord delegate :organization, :participatory_space, :component, to: :document, allow_nil: true translatable_fields :title + def self.log_presenter_class_for(_log) Decidim::ParticipatoryDocuments::AdminLog::SectionPresenter end diff --git a/spec/models/decidim/participatory_documents/section_spec.rb b/spec/models/decidim/participatory_documents/section_spec.rb index 6aacbdc6..eb9367d6 100644 --- a/spec/models/decidim/participatory_documents/section_spec.rb +++ b/spec/models/decidim/participatory_documents/section_spec.rb @@ -30,42 +30,185 @@ module ParticipatoryDocuments end context "when is not being provided" do - context "when is the first section" do - let!(:after_section) { create_list(:participatory_documents_section, 2, document: section.document) } - let(:section) { create(:participatory_documents_section, title: nil) } + let(:position) { 1 } + let(:section) { create(:participatory_documents_section, title: nil, position: position) } - it "returns computed value" do - expect(translated(subject.title)).to eq("Section 1") - expect(subject.document.sections.size).to eq(3) - end + it "returns computed value" do + expect(translated(subject.title)).to eq("Section 1") end context "when has an intermediary position" do - let(:section_count) { 5 } - let(:expected_position) { section_count + 1 } - let(:document) { create(:participatory_documents_document) } - let(:precedent_section) { create_list(:participatory_documents_section, section_count, document: document) } - let(:section) { create(:participatory_documents_section, document: precedent_section.first.document, title: nil) } - let!(:after_section) { create_list(:participatory_documents_section, section_count, document: section.document) } + let(:position) { 5 } it "returns computed value" do - expect(translated(subject.document.sections[section_count].title)).to eq("Section #{expected_position}") - expect(subject.document.sections.size).to eq(expected_position + section_count) + expect(translated(subject.title)).to eq("Section 5") end end + end + end - context "when is last" do - let(:section_count) { 5 } - let(:expected_position) { section_count + 1 } - let(:document) { create(:participatory_documents_document) } - let(:precedent_section) { create_list(:participatory_documents_section, section_count, document: document) } - let(:section) { create(:participatory_documents_section, document: precedent_section.first.document, title: nil) } + describe "with annotations" do + let(:section1) { create :participatory_documents_section } + let(:section2) { create :participatory_documents_section, document: section1.document } + let(:section3) { create :participatory_documents_section, document: section1.document } - it "returns computed value" do - expect(translated(subject.document.sections.last.title)).to eq("Section #{expected_position}") - expect(subject.document.sections.size).to eq(expected_position) + let!(:annotation1) { create(:participatory_documents_annotation, section: section1, rect: rect1, page_number: page1) } + let!(:annotation2) { create(:participatory_documents_annotation, section: section2, rect: rect2, page_number: page2) } + let!(:annotation3) { create(:participatory_documents_annotation, section: section3, rect: rect3, page_number: page3) } + let(:next_section_annotations) { create_list :participatory_documents_annotation, 3 } + + let(:rect1) do + { + "top" => 20.0, + "left" => 0.0, + "width" => 0.0, + "height" => 0.0 + } + end + let(:rect2) do + { + "top" => 10.0, + "left" => 20.0, + "width" => 0.0, + "height" => 0.0 + } + end + let(:rect3) do + { + "top" => 10.0, + "left" => 10.0, + "width" => 0.0, + "height" => 0.0 + } + end + let(:page1) { 1 } + let(:page2) { 1 } + let(:page3) { 1 } + + it "reorders annotations and sections" do + expect(annotation1.reload.position).to eq(3) + expect(annotation2.reload.position).to eq(2) + expect(annotation3.reload.position).to eq(1) + expect(section1.reload.position).to eq(3) + expect(section2.reload.position).to eq(2) + expect(section3.reload.position).to eq(1) + end + + context "when repeating section3" do + let(:section3) { section1 } + + it "reorders annotations and sections" do + expect(annotation1.reload.position).to eq(3) + expect(annotation2.reload.position).to eq(2) + expect(annotation3.reload.position).to eq(1) + expect(section1.reload.position).to eq(1) + expect(section2.reload.position).to eq(2) + expect(section3.reload.position).to eq(1) + end + end + + context "when repeating section2" do + let(:section2) { section1 } + + it "reorders annotations and sections" do + expect(annotation1.reload.position).to eq(3) + expect(annotation2.reload.position).to eq(2) + expect(annotation3.reload.position).to eq(1) + expect(section1.reload.position).to eq(2) + expect(section2.reload.position).to eq(2) + expect(section3.reload.position).to eq(1) + end + end + + context "when different pages" do + let(:page2) { 3 } + let(:page3) { 2 } + + it "reorders annotations and sections" do + expect(annotation1.reload.position).to eq(1) + expect(annotation2.reload.position).to eq(3) + expect(annotation3.reload.position).to eq(2) + expect(section1.reload.position).to eq(1) + expect(section2.reload.position).to eq(3) + expect(section3.reload.position).to eq(2) + end + + context "and repeating section3" do + let(:section3) { section1 } + + it "reorders annotations and sections" do + expect(annotation1.reload.position).to eq(1) + expect(annotation2.reload.position).to eq(3) + expect(annotation3.reload.position).to eq(2) + expect(section1.reload.position).to eq(1) + expect(section2.reload.position).to eq(2) + expect(section3.reload.position).to eq(1) + end + end + + context "and repeating section2" do + let(:section2) { section1 } + + it "reorders annotations and sections" do + expect(annotation1.reload.position).to eq(1) + expect(annotation2.reload.position).to eq(3) + expect(annotation3.reload.position).to eq(2) + expect(section1.reload.position).to eq(1) + expect(section2.reload.position).to eq(1) + expect(section3.reload.position).to eq(2) + end + end + end + + context "when combined pages" do + let(:page3) { 2 } + + it "reorders annotations and sections" do + expect(annotation1.reload.position).to eq(2) + expect(annotation2.reload.position).to eq(1) + expect(annotation3.reload.position).to eq(3) + expect(section1.reload.position).to eq(2) + expect(section2.reload.position).to eq(1) + expect(section3.reload.position).to eq(3) + end + + context "and repeating section3" do + let(:section3) { section1 } + + it "reorders annotations and sections" do + expect(annotation1.reload.position).to eq(2) + expect(annotation2.reload.position).to eq(1) + expect(annotation3.reload.position).to eq(3) + expect(section1.reload.position).to eq(2) + expect(section2.reload.position).to eq(1) + expect(section3.reload.position).to eq(2) end end + + context "and repeating section2" do + let(:section2) { section1 } + + it "reorders annotations and sections" do + expect(annotation1.reload.position).to eq(2) + expect(annotation2.reload.position).to eq(1) + expect(annotation3.reload.position).to eq(3) + expect(section1.reload.position).to eq(1) + expect(section2.reload.position).to eq(1) + expect(section3.reload.position).to eq(2) + end + end + end + + context "when no annotations" do + let(:annotation1) { nil } + let(:annotation2) { nil } + let(:annotation3) { nil } + + it "sections are not reordered" do + expect(section1.reload.position).to eq(0) + expect(section2.reload.position).to eq(0) + expect(section3.reload.position).to eq(0) + end end end end From c571f0b2fce36da87fd0a4e104c21096bb49e466 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20Verg=C3=A9s?= Date: Thu, 22 Jun 2023 18:24:43 +0200 Subject: [PATCH 07/24] backedn reorder & tests --- .../admin/destroy_annotation.rb | 1 + .../admin/update_or_create_annotation.rb | 1 + .../needs_positions_sorting.rb | 44 ----- .../participatory_documents/annotation.rb | 2 - .../participatory_documents/document.rb | 31 ++++ .../participatory_documents/section.rb | 1 - .../participatory_documents/test/factories.rb | 13 +- .../admin/create_annotation_spec.rb | 5 + .../admin/destroy_annotation_spec.rb | 17 ++ .../admin/update_annotation_spec.rb | 5 + .../participatory_documents/document_spec.rb | 168 ++++++++++++++++++ .../participatory_documents/section_spec.rb | 165 ----------------- 12 files changed, 235 insertions(+), 218 deletions(-) delete mode 100644 app/models/concerns/decidim/participatory_documents/needs_positions_sorting.rb diff --git a/app/commands/decidim/participatory_documents/admin/destroy_annotation.rb b/app/commands/decidim/participatory_documents/admin/destroy_annotation.rb index 2238fb00..a4ac1781 100644 --- a/app/commands/decidim/participatory_documents/admin/destroy_annotation.rb +++ b/app/commands/decidim/participatory_documents/admin/destroy_annotation.rb @@ -22,6 +22,7 @@ def call end destroy_old_section! + document.update_positions! broadcast(:ok) rescue ActiveRecord::RecordInvalid diff --git a/app/commands/decidim/participatory_documents/admin/update_or_create_annotation.rb b/app/commands/decidim/participatory_documents/admin/update_or_create_annotation.rb index 73e7a18e..6f0842d2 100644 --- a/app/commands/decidim/participatory_documents/admin/update_or_create_annotation.rb +++ b/app/commands/decidim/participatory_documents/admin/update_or_create_annotation.rb @@ -27,6 +27,7 @@ def call end destroy_old_section! + document.update_positions! broadcast(:ok, annotation) rescue ActiveRecord::RecordInvalid diff --git a/app/models/concerns/decidim/participatory_documents/needs_positions_sorting.rb b/app/models/concerns/decidim/participatory_documents/needs_positions_sorting.rb deleted file mode 100644 index ab6d7fd9..00000000 --- a/app/models/concerns/decidim/participatory_documents/needs_positions_sorting.rb +++ /dev/null @@ -1,44 +0,0 @@ -# frozen_string_literal: true - -module Decidim - module ParticipatoryDocuments - module NeedsPositionsSorting - extend ActiveSupport::Concern - - included do - after_commit :update_positions - - private - - # rubocop:disable Rails/SkipsModelValidations - def update_positions - boxes = document.annotations.reload.sort do |a, b| - if a.page_number == b.page_number - if a.rect["top"].to_i == b.rect["top"].to_i - a.rect["left"].to_i <=> b.rect["left"].to_i - else - a.position <=> b.position - end - else - a.page_number <=> b.page_number - end - end - - section_number = 0 - all_sections = {} - boxes.each_with_index do |box, index| - box.update_column(:position, index + 1) - if all_sections[box.section_id] - box.section.update_column(:position, all_sections[box.section_id]) - else - section_number += 1 - box.section.update_column(:position, section_number) - end - all_sections[box.section_id] = section_number - end - end - # rubocop:enable Rails/SkipsModelValidations - end - end - end -end diff --git a/app/models/decidim/participatory_documents/annotation.rb b/app/models/decidim/participatory_documents/annotation.rb index fb6bb1a5..2d4df243 100644 --- a/app/models/decidim/participatory_documents/annotation.rb +++ b/app/models/decidim/participatory_documents/annotation.rb @@ -3,8 +3,6 @@ module Decidim module ParticipatoryDocuments class Annotation < ApplicationRecord - include NeedsPositionsSorting - belongs_to :section, class_name: "Decidim::ParticipatoryDocuments::Section" has_many :suggestions, class_name: "Decidim::ParticipatoryDocuments::Suggestion", dependent: :restrict_with_error, as: :suggestable diff --git a/app/models/decidim/participatory_documents/document.rb b/app/models/decidim/participatory_documents/document.rb index c7b825a8..98a5b023 100644 --- a/app/models/decidim/participatory_documents/document.rb +++ b/app/models/decidim/participatory_documents/document.rb @@ -30,6 +30,37 @@ def self.log_presenter_class_for(_log) def has_suggestions? suggestions.any? || annotations.any? { |annotation| annotation.suggestions.any? } end + + # rubocop:disable Rails/SkipsModelValidations + def update_positions! + transaction do + boxes = annotations.reload.sort do |a, b| + if a.page_number == b.page_number + if a.rect["top"].to_i == b.rect["top"].to_i + a.rect["left"].to_i <=> b.rect["left"].to_i + else + a.rect["top"].to_i <=> b.rect["top"].to_i + end + else + a.page_number <=> b.page_number + end + end + + section_number = 0 + all_sections = {} + boxes.each_with_index do |box, index| + box.update_column(:position, index + 1) + if all_sections[box.section_id] + box.section.update_column(:position, all_sections[box.section_id]) + else + section_number += 1 + box.section.update_column(:position, section_number) + end + all_sections[box.section_id] = section_number + end + end + end + # rubocop:enable Rails/SkipsModelValidations end end end diff --git a/app/models/decidim/participatory_documents/section.rb b/app/models/decidim/participatory_documents/section.rb index 73ab6c6c..686e99e7 100644 --- a/app/models/decidim/participatory_documents/section.rb +++ b/app/models/decidim/participatory_documents/section.rb @@ -8,7 +8,6 @@ class Section < ApplicationRecord include Decidim::TranslatableResource include Decidim::TranslatableAttributes include Decidim::Publicable - include NeedsPositionsSorting belongs_to :document, class_name: "Decidim::ParticipatoryDocuments::Document" has_many :annotations, class_name: "Decidim::ParticipatoryDocuments::Annotation", dependent: :restrict_with_error diff --git a/lib/decidim/participatory_documents/test/factories.rb b/lib/decidim/participatory_documents/test/factories.rb index 7eceae91..af1f89cd 100644 --- a/lib/decidim/participatory_documents/test/factories.rb +++ b/lib/decidim/participatory_documents/test/factories.rb @@ -69,12 +69,13 @@ factory :participatory_documents_annotation, class: "Decidim::ParticipatoryDocuments::Annotation" do section { create(:participatory_documents_section) } page_number { 1 } - - after(:build) do |annotation| - top = rand(1.0..60.0) - left = rand(1.0..100.0) - - annotation.rect = { top: top, left: left, width: 15.9411, height: 18.0857 } + rect do + { + top: rand(1.0..60.0), + left: rand(1.0..100.0), + width: rand(1.0..15.0), + height: rand(1.0..20.0) + } end trait :with_suggestions do diff --git a/spec/commands/decidim/participatory_documents/admin/create_annotation_spec.rb b/spec/commands/decidim/participatory_documents/admin/create_annotation_spec.rb index c790d0fd..d87eed03 100644 --- a/spec/commands/decidim/participatory_documents/admin/create_annotation_spec.rb +++ b/spec/commands/decidim/participatory_documents/admin/create_annotation_spec.rb @@ -54,6 +54,11 @@ module Admin expect { subject.call }.to change(Decidim::ParticipatoryDocuments::Annotation, :count).by(1) expect(Decidim::ParticipatoryDocuments::Section.count).to eq(1) end + + it "updates the position" do + subject.call + expect(Decidim::ParticipatoryDocuments::Annotation.last.position).to eq(1) + end end end end diff --git a/spec/commands/decidim/participatory_documents/admin/destroy_annotation_spec.rb b/spec/commands/decidim/participatory_documents/admin/destroy_annotation_spec.rb index 99e77a94..6e47cf1a 100644 --- a/spec/commands/decidim/participatory_documents/admin/destroy_annotation_spec.rb +++ b/spec/commands/decidim/participatory_documents/admin/destroy_annotation_spec.rb @@ -29,6 +29,9 @@ module Admin end context "when everything is ok" do + let!(:another_annotation) { create(:participatory_documents_annotation, section: another_section) } + let(:another_section) { create(:participatory_documents_section, document: annotation.section.document) } + it "Removes a annotation" do expect { subject.call }.to change(Decidim::ParticipatoryDocuments::Annotation, :count).by(-1) end @@ -36,6 +39,20 @@ module Admin it "Removes a section" do expect { subject.call }.to change(Decidim::ParticipatoryDocuments::Section, :count).by(-1) end + + it "updates the position" do + subject.call + expect(Decidim::ParticipatoryDocuments::Annotation.last.position).to eq(1) + end + + context "when other annotation is not in the same document" do + let!(:another_section) { create(:participatory_documents_section) } + + it "does not udpate the position" do + subject.call + expect(Decidim::ParticipatoryDocuments::Annotation.last.position).to eq(1) + end + end end end end diff --git a/spec/commands/decidim/participatory_documents/admin/update_annotation_spec.rb b/spec/commands/decidim/participatory_documents/admin/update_annotation_spec.rb index 8d48803c..24c46fd9 100644 --- a/spec/commands/decidim/participatory_documents/admin/update_annotation_spec.rb +++ b/spec/commands/decidim/participatory_documents/admin/update_annotation_spec.rb @@ -40,6 +40,11 @@ module Admin annotation.reload expect(annotation.rect).to eq(rect) end + + it "updates the position" do + subject.call + expect(Decidim::ParticipatoryDocuments::Annotation.last.position).to eq(1) + end end end end diff --git a/spec/models/decidim/participatory_documents/document_spec.rb b/spec/models/decidim/participatory_documents/document_spec.rb index 70275379..eadf8577 100644 --- a/spec/models/decidim/participatory_documents/document_spec.rb +++ b/spec/models/decidim/participatory_documents/document_spec.rb @@ -51,6 +51,174 @@ module ParticipatoryDocuments expect(document).to be_has_suggestions end end + + describe "with annotations" do + let(:section1) { create :participatory_documents_section, document: document } + let(:rect1) do + { + "top" => 20.0, + "left" => 0.0 + } + end + let(:rect2) do + { + "top" => 10.0, + "left" => 20.0 + } + end + let(:rect3) do + { + "top" => 10.0, + "left" => 10.0 + } + end + let(:page1) { 1 } + let(:page2) { 1 } + let(:page3) { 1 } + let(:section2) { create :participatory_documents_section, document: document } + let(:section3) { create :participatory_documents_section, document: document } + + let!(:annotation1) { create(:participatory_documents_annotation, section: section1, rect: rect1, page_number: page1) } + let!(:annotation2) { create(:participatory_documents_annotation, section: section2, rect: rect2, page_number: page2) } + let!(:annotation3) { create(:participatory_documents_annotation, section: section3, rect: rect3, page_number: page3) } + + before do + document.update_positions! + annotation1&.reload + annotation2&.reload + annotation3&.reload + section1&.reload + section2&.reload + section3&.reload + end + + it "reorders annotations and sections" do + expect(annotation1.position).to eq(3) + expect(annotation2.position).to eq(2) + expect(annotation3.position).to eq(1) + expect(section1.position).to eq(3) + expect(section2.position).to eq(2) + expect(section3.position).to eq(1) + end + + context "when repeating section3" do + let(:section3) { section1 } + + it "reorders annotations and sections" do + expect(annotation1.position).to eq(3) + expect(annotation2.position).to eq(2) + expect(annotation3.position).to eq(1) + expect(section1.position).to eq(1) + expect(section2.position).to eq(2) + expect(section3.position).to eq(1) + end + end + + context "when repeating section2" do + let(:section2) { section1 } + + it "reorders annotations and sections" do + annotation1.save + expect(annotation1.position).to eq(3) + expect(annotation2.position).to eq(2) + expect(annotation3.position).to eq(1) + expect(section1.position).to eq(2) + expect(section2.position).to eq(2) + expect(section3.position).to eq(1) + end + end + + context "when different pages" do + let(:page2) { 3 } + let(:page3) { 2 } + + it "reorders annotations and sections" do + expect(annotation1.position).to eq(1) + expect(annotation2.position).to eq(3) + expect(annotation3.position).to eq(2) + expect(section1.position).to eq(1) + expect(section2.position).to eq(3) + expect(section3.position).to eq(2) + end + + context "and repeating section3" do + let(:section3) { section1 } + + it "reorders annotations and sections" do + expect(annotation1.position).to eq(1) + expect(annotation2.position).to eq(3) + expect(annotation3.position).to eq(2) + expect(section1.position).to eq(1) + expect(section2.position).to eq(2) + expect(section3.position).to eq(1) + end + end + + context "and repeating section2" do + let(:section2) { section1 } + + it "reorders annotations and sections" do + expect(annotation1.position).to eq(1) + expect(annotation2.position).to eq(3) + expect(annotation3.position).to eq(2) + expect(section1.position).to eq(1) + expect(section2.position).to eq(1) + expect(section3.position).to eq(2) + end + end + end + + context "when combined pages" do + let(:page3) { 2 } + + it "reorders annotations and sections" do + expect(annotation1.position).to eq(2) + expect(annotation2.position).to eq(1) + expect(annotation3.position).to eq(3) + expect(section1.position).to eq(2) + expect(section2.position).to eq(1) + expect(section3.position).to eq(3) + end + + context "and repeating section3" do + let(:section3) { section1 } + + it "reorders annotations and sections" do + expect(annotation1.position).to eq(2) + expect(annotation2.position).to eq(1) + expect(annotation3.position).to eq(3) + expect(section1.position).to eq(2) + expect(section2.position).to eq(1) + expect(section3.position).to eq(2) + end + end + + context "and repeating section2" do + let(:section2) { section1 } + + it "reorders annotations and sections" do + expect(annotation1.position).to eq(2) + expect(annotation2.position).to eq(1) + expect(annotation3.position).to eq(3) + expect(section1.position).to eq(1) + expect(section2.position).to eq(1) + expect(section3.position).to eq(2) + end + end + end + + context "when no annotations" do + let(:annotation1) { nil } + let(:annotation2) { nil } + let(:annotation3) { nil } + + it "sections are not reordered" do + expect(section1.position).to eq(0) + expect(section2.position).to eq(0) + expect(section3.position).to eq(0) + end + end + end end end end diff --git a/spec/models/decidim/participatory_documents/section_spec.rb b/spec/models/decidim/participatory_documents/section_spec.rb index eb9367d6..313f6c35 100644 --- a/spec/models/decidim/participatory_documents/section_spec.rb +++ b/spec/models/decidim/participatory_documents/section_spec.rb @@ -46,171 +46,6 @@ module ParticipatoryDocuments end end end - - describe "with annotations" do - let(:section1) { create :participatory_documents_section } - let(:section2) { create :participatory_documents_section, document: section1.document } - let(:section3) { create :participatory_documents_section, document: section1.document } - - let!(:annotation1) { create(:participatory_documents_annotation, section: section1, rect: rect1, page_number: page1) } - let!(:annotation2) { create(:participatory_documents_annotation, section: section2, rect: rect2, page_number: page2) } - let!(:annotation3) { create(:participatory_documents_annotation, section: section3, rect: rect3, page_number: page3) } - let(:next_section_annotations) { create_list :participatory_documents_annotation, 3 } - - let(:rect1) do - { - "top" => 20.0, - "left" => 0.0, - "width" => 0.0, - "height" => 0.0 - } - end - let(:rect2) do - { - "top" => 10.0, - "left" => 20.0, - "width" => 0.0, - "height" => 0.0 - } - end - let(:rect3) do - { - "top" => 10.0, - "left" => 10.0, - "width" => 0.0, - "height" => 0.0 - } - end - let(:page1) { 1 } - let(:page2) { 1 } - let(:page3) { 1 } - - it "reorders annotations and sections" do - expect(annotation1.reload.position).to eq(3) - expect(annotation2.reload.position).to eq(2) - expect(annotation3.reload.position).to eq(1) - expect(section1.reload.position).to eq(3) - expect(section2.reload.position).to eq(2) - expect(section3.reload.position).to eq(1) - end - - context "when repeating section3" do - let(:section3) { section1 } - - it "reorders annotations and sections" do - expect(annotation1.reload.position).to eq(3) - expect(annotation2.reload.position).to eq(2) - expect(annotation3.reload.position).to eq(1) - expect(section1.reload.position).to eq(1) - expect(section2.reload.position).to eq(2) - expect(section3.reload.position).to eq(1) - end - end - - context "when repeating section2" do - let(:section2) { section1 } - - it "reorders annotations and sections" do - expect(annotation1.reload.position).to eq(3) - expect(annotation2.reload.position).to eq(2) - expect(annotation3.reload.position).to eq(1) - expect(section1.reload.position).to eq(2) - expect(section2.reload.position).to eq(2) - expect(section3.reload.position).to eq(1) - end - end - - context "when different pages" do - let(:page2) { 3 } - let(:page3) { 2 } - - it "reorders annotations and sections" do - expect(annotation1.reload.position).to eq(1) - expect(annotation2.reload.position).to eq(3) - expect(annotation3.reload.position).to eq(2) - expect(section1.reload.position).to eq(1) - expect(section2.reload.position).to eq(3) - expect(section3.reload.position).to eq(2) - end - - context "and repeating section3" do - let(:section3) { section1 } - - it "reorders annotations and sections" do - expect(annotation1.reload.position).to eq(1) - expect(annotation2.reload.position).to eq(3) - expect(annotation3.reload.position).to eq(2) - expect(section1.reload.position).to eq(1) - expect(section2.reload.position).to eq(2) - expect(section3.reload.position).to eq(1) - end - end - - context "and repeating section2" do - let(:section2) { section1 } - - it "reorders annotations and sections" do - expect(annotation1.reload.position).to eq(1) - expect(annotation2.reload.position).to eq(3) - expect(annotation3.reload.position).to eq(2) - expect(section1.reload.position).to eq(1) - expect(section2.reload.position).to eq(1) - expect(section3.reload.position).to eq(2) - end - end - end - - context "when combined pages" do - let(:page3) { 2 } - - it "reorders annotations and sections" do - expect(annotation1.reload.position).to eq(2) - expect(annotation2.reload.position).to eq(1) - expect(annotation3.reload.position).to eq(3) - expect(section1.reload.position).to eq(2) - expect(section2.reload.position).to eq(1) - expect(section3.reload.position).to eq(3) - end - - context "and repeating section3" do - let(:section3) { section1 } - - it "reorders annotations and sections" do - expect(annotation1.reload.position).to eq(2) - expect(annotation2.reload.position).to eq(1) - expect(annotation3.reload.position).to eq(3) - expect(section1.reload.position).to eq(2) - expect(section2.reload.position).to eq(1) - expect(section3.reload.position).to eq(2) - end - end - - context "and repeating section2" do - let(:section2) { section1 } - - it "reorders annotations and sections" do - expect(annotation1.reload.position).to eq(2) - expect(annotation2.reload.position).to eq(1) - expect(annotation3.reload.position).to eq(3) - expect(section1.reload.position).to eq(1) - expect(section2.reload.position).to eq(1) - expect(section3.reload.position).to eq(2) - end - end - end - - context "when no annotations" do - let(:annotation1) { nil } - let(:annotation2) { nil } - let(:annotation3) { nil } - - it "sections are not reordered" do - expect(section1.reload.position).to eq(0) - expect(section2.reload.position).to eq(0) - expect(section3.reload.position).to eq(0) - end - end - end end end end From 44161e9030f9a57b8a74b93d85fbf0187f166d85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20Verg=C3=A9s?= Date: Thu, 22 Jun 2023 18:28:23 +0200 Subject: [PATCH 08/24] linting --- .../src/decidim/participatory_documents/pdf_admin.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/app/packs/src/decidim/participatory_documents/pdf_admin.js b/app/packs/src/decidim/participatory_documents/pdf_admin.js index ecc7c97f..31ce3c06 100644 --- a/app/packs/src/decidim/participatory_documents/pdf_admin.js +++ b/app/packs/src/decidim/participatory_documents/pdf_admin.js @@ -1,3 +1,5 @@ +/* eslint-disable max-params */ + import "src/decidim/participatory_documents/global"; import "src/decidim/participatory_documents/pdf_notifications"; import PolygonEditor from "src/decidim/participatory_documents/pdf/polygon_editor"; @@ -34,7 +36,7 @@ window.InitDocumentManagers = function(options) { }; // Call this on an annotation layer to initialize the polygon editor (admin side) -window.InitPolygonEditor = function(layer, boxes, options, change_callback = () => {}) { +window.InitPolygonEditor = function(layer, boxes, options, changeCallback = () => {}) { let editor = new PolygonEditor(layer, boxes, { i18n: options.i18n }); // Open the global box modal settings when a box is clicked editor.onBoxClick = (box) => { @@ -47,11 +49,11 @@ window.InitPolygonEditor = function(layer, boxes, options, change_callback = () // update the global state manager when a box is edited or destroyed using the polygon editor (mouse interaction) editor.onBoxChange = (box) => { window.PdfDocStateManager.add(box); - change_callback(box); + changeCallback(box); }; editor.onBoxDestroy = (box) => { window.PdfDocStateManager.remove(box); - change_callback(box); + changeCallback(box); }; return editor; From af99cd07896e00ab9aebdca900a50e8bc0cff6c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20Verg=C3=A9s?= Date: Thu, 22 Jun 2023 18:58:58 +0200 Subject: [PATCH 09/24] do not restore boxes on save --- app/packs/src/decidim/participatory_documents/pdf/box.js | 4 ++-- .../participatory_documents/pdf/pdf_modal_manager.js | 1 - .../participatory_documents/pdf/pdf_state_manager.js | 4 ++++ .../decidim/participatory_documents/pdf/polygon_editor.js | 4 ++++ .../decidim/participatory_documents/pdf/polygon_viewer.js | 6 +++++- 5 files changed, 15 insertions(+), 4 deletions(-) diff --git a/app/packs/src/decidim/participatory_documents/pdf/box.js b/app/packs/src/decidim/participatory_documents/pdf/box.js index 9bab7e22..0feae6e2 100644 --- a/app/packs/src/decidim/participatory_documents/pdf/box.js +++ b/app/packs/src/decidim/participatory_documents/pdf/box.js @@ -80,9 +80,9 @@ export default class Box { setInfo(data) { if (data) { if (data.id) { - Reflect.deleteProperty(this.layer.boxes, this.id); + this.layer.removeBox(this) this.id = data.id; - this.layer.boxes[this.id] = this; + this.layer.addBox(this) } this.section = data.section || this.section; this.div.dataset.section = this.section; diff --git a/app/packs/src/decidim/participatory_documents/pdf/pdf_modal_manager.js b/app/packs/src/decidim/participatory_documents/pdf/pdf_modal_manager.js index bbd8e90c..366d9733 100644 --- a/app/packs/src/decidim/participatory_documents/pdf/pdf_modal_manager.js +++ b/app/packs/src/decidim/participatory_documents/pdf/pdf_modal_manager.js @@ -116,7 +116,6 @@ export default class PdfModalManager { this.onError(box, error); }); } else { - Reflect.deleteProperty(box.layer.boxes, box.id); box.destroy(); } this.modalLayout.classList.remove("show"); diff --git a/app/packs/src/decidim/participatory_documents/pdf/pdf_state_manager.js b/app/packs/src/decidim/participatory_documents/pdf/pdf_state_manager.js index 876aefce..620fca4b 100644 --- a/app/packs/src/decidim/participatory_documents/pdf/pdf_state_manager.js +++ b/app/packs/src/decidim/participatory_documents/pdf/pdf_state_manager.js @@ -32,6 +32,10 @@ export default class PdfStateManager { this.reset(); } } + console.log(this.pdfViewer._pages) + this.pdfViewer._pages. + filter((page) => page.boxEditor). + filter((page) => page.boxEditor.removeBox(box)); } isEmpty() { diff --git a/app/packs/src/decidim/participatory_documents/pdf/polygon_editor.js b/app/packs/src/decidim/participatory_documents/pdf/polygon_editor.js index 7b4e0af5..209097ef 100644 --- a/app/packs/src/decidim/participatory_documents/pdf/polygon_editor.js +++ b/app/packs/src/decidim/participatory_documents/pdf/polygon_editor.js @@ -24,6 +24,10 @@ export default class PolygonEditor extends PolygonViewer { return this.div.classList.contains("blocked"); } + removeBox(box) { + Reflect.deleteProperty(this.boxes, box.id); + } + _mouseDown(evt) { if (!this.creating && !this.isBlocked()) { this.blockBoxes(); diff --git a/app/packs/src/decidim/participatory_documents/pdf/polygon_viewer.js b/app/packs/src/decidim/participatory_documents/pdf/polygon_viewer.js index 7d6fb3fd..86b732cf 100644 --- a/app/packs/src/decidim/participatory_documents/pdf/polygon_viewer.js +++ b/app/packs/src/decidim/participatory_documents/pdf/polygon_viewer.js @@ -20,7 +20,7 @@ export default class PolygonViewer { this.div.style.pointerEvents = "all"; this.div.classList.add("polygon-ready"); this.json.forEach((box) => { - this.boxes[box.id] = new Box(this, box); + this.addBox(new Box(this, box)); this.bindBoxEvents(this.boxes[box.id]); }); } @@ -46,4 +46,8 @@ export default class PolygonViewer { unBlockBoxes() { this.div.querySelectorAll(".box").forEach((div) => div.classList.remove("blocked")); } + + addBox(box) { + this.boxes[box.id] = box; + } } From fcdf41636b908e2104f7ef90a2a77e2a9aa8c965 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20Verg=C3=A9s?= Date: Thu, 22 Jun 2023 19:07:03 +0200 Subject: [PATCH 10/24] update pdf --- app/packs/src/decidim/participatory_documents/pdf/box.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/packs/src/decidim/participatory_documents/pdf/box.js b/app/packs/src/decidim/participatory_documents/pdf/box.js index 0feae6e2..c91bea95 100644 --- a/app/packs/src/decidim/participatory_documents/pdf/box.js +++ b/app/packs/src/decidim/participatory_documents/pdf/box.js @@ -165,7 +165,7 @@ export default class Box { _mouseLeave(evt) { if (!this.layer.creating && !this.isGrouping()) { - this.div.classList.remove("hover"); + this.div.classList.remove("hover", "resizing"); this.blurGroup() this.unBlockSibilings(); this.onLeave(evt); From a16768c5eaf09d9d91a46f5810d67d9f826207a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20Verg=C3=A9s?= Date: Thu, 22 Jun 2023 19:39:55 +0200 Subject: [PATCH 11/24] test fix --- .../admin/annotation_form.rb | 12 ++++++- .../admin/destroy_annotation_spec.rb | 4 +-- .../section_suggestions_controller_spec.rb | 2 +- .../admin/annotation_form_spec.rb | 32 +++++++++++++++++++ .../system/admin/admin_sees_dashboard_spec.rb | 2 +- 5 files changed, 47 insertions(+), 5 deletions(-) create mode 100644 spec/forms/decidim/participatory_documents/admin/annotation_form_spec.rb diff --git a/app/forms/decidim/participatory_documents/admin/annotation_form.rb b/app/forms/decidim/participatory_documents/admin/annotation_form.rb index 64c819b2..c1f8a6fa 100644 --- a/app/forms/decidim/participatory_documents/admin/annotation_form.rb +++ b/app/forms/decidim/participatory_documents/admin/annotation_form.rb @@ -7,9 +7,19 @@ class AnnotationForm < Decidim::Form mimic :annotation attribute :id, Integer - attribute :rect + attribute :rect, Hash attribute :page_number, Integer attribute :section, Integer + + validate :rect_valid_hash + + private + + def rect_valid_hash + return if rect[:left] && rect[:top] + + errors.add(:rect, :invalid) + end end end end diff --git a/spec/commands/decidim/participatory_documents/admin/destroy_annotation_spec.rb b/spec/commands/decidim/participatory_documents/admin/destroy_annotation_spec.rb index 6e47cf1a..ca45f835 100644 --- a/spec/commands/decidim/participatory_documents/admin/destroy_annotation_spec.rb +++ b/spec/commands/decidim/participatory_documents/admin/destroy_annotation_spec.rb @@ -48,9 +48,9 @@ module Admin context "when other annotation is not in the same document" do let!(:another_section) { create(:participatory_documents_section) } - it "does not udpate the position" do + it "does not update the position" do subject.call - expect(Decidim::ParticipatoryDocuments::Annotation.last.position).to eq(1) + expect(Decidim::ParticipatoryDocuments::Annotation.last.position).to eq(0) end end end diff --git a/spec/controllers/decidim/participatory_documents/admin/section_suggestions_controller_spec.rb b/spec/controllers/decidim/participatory_documents/admin/section_suggestions_controller_spec.rb index 9266a243..07f9c9db 100644 --- a/spec/controllers/decidim/participatory_documents/admin/section_suggestions_controller_spec.rb +++ b/spec/controllers/decidim/participatory_documents/admin/section_suggestions_controller_spec.rb @@ -34,7 +34,7 @@ module Admin end it "Changes the database record" do - expect(section.title["en"]).to eq("Section 1") + expect(section.title["en"]).to eq("Section 0") post(:update, params: params) section.reload expect(section.title["en"]).to eq("Title") diff --git a/spec/forms/decidim/participatory_documents/admin/annotation_form_spec.rb b/spec/forms/decidim/participatory_documents/admin/annotation_form_spec.rb new file mode 100644 index 00000000..c80541e3 --- /dev/null +++ b/spec/forms/decidim/participatory_documents/admin/annotation_form_spec.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true + +require "spec_helper" + +module Decidim + module ParticipatoryDocuments + module Admin + describe AnnotationForm do + subject { described_class.from_params(attributes) } + + let(:rect) do + { "left" => 0, "top" => 50, "width" => 100, "height" => 100 } + end + let(:attributes) do + { + "rect" => rect + } + end + + it { is_expected.to be_valid } + + context "when rect is not valid" do + let(:rect) do + { "left" => 50 } + end + + it { is_expected.not_to be_valid } + end + end + end + end +end diff --git a/spec/system/admin/admin_sees_dashboard_spec.rb b/spec/system/admin/admin_sees_dashboard_spec.rb index cb74ea04..47fda76e 100644 --- a/spec/system/admin/admin_sees_dashboard_spec.rb +++ b/spec/system/admin/admin_sees_dashboard_spec.rb @@ -242,7 +242,7 @@ double( invalid?: false, page_number: 1, - rect: [50, 50, 100, 100], + rect: { left: 50, top: 50, width: 100, height: 100 }, id: annotation2.id, section: section1.id, current_user: current_user From 02d438850eec6c5e91a8495d9f25a82e7d3efedc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20Verg=C3=A9s?= Date: Fri, 23 Jun 2023 10:28:50 +0200 Subject: [PATCH 12/24] fix tests --- .../admin/annotations_controller_spec.rb | 8 ++++---- spec/system/admin/admin_sees_dashboard_spec.rb | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/spec/controllers/decidim/participatory_documents/admin/annotations_controller_spec.rb b/spec/controllers/decidim/participatory_documents/admin/annotations_controller_spec.rb index 720968d0..b30d6fc4 100644 --- a/spec/controllers/decidim/participatory_documents/admin/annotations_controller_spec.rb +++ b/spec/controllers/decidim/participatory_documents/admin/annotations_controller_spec.rb @@ -26,9 +26,9 @@ module Admin describe ".create" do let(:params) do { - "document_id": document.id, - "page_number": 1, - "rect": [50, 50, 100, 100] + "document_id" => document.id, + "page_number" => 1, + "rect" => { left: 50, top: 50, width: 100, height: 100 } } end @@ -43,7 +43,7 @@ module Admin let!(:annotation) { create(:participatory_documents_annotation) } let!(:section) { create(:participatory_documents_section, document: document, annotations: [annotation]) } - let(:params) { { document_id: document.id, id: annotation.id, page_number: 1, rect: [50, 50, 100, 100] } } + let(:params) { { document_id: document.id, id: annotation.id, page_number: 1, rect: { left: 50, top: 50, width: 100, height: 100 } } } it "deletes the annotation and section" do expect { delete(:destroy, params: params) }.to change(model, :count).by(-1).and change(sections, :count).by(-1) diff --git a/spec/system/admin/admin_sees_dashboard_spec.rb b/spec/system/admin/admin_sees_dashboard_spec.rb index 47fda76e..1609359f 100644 --- a/spec/system/admin/admin_sees_dashboard_spec.rb +++ b/spec/system/admin/admin_sees_dashboard_spec.rb @@ -66,7 +66,7 @@ double( invalid?: false, page_number: 1, - rect: [50, 50, 100, 100], + rect: { left: 50, top: 50, width: 100, height: 100 }, id: "annotationid", group: "groupid", current_user: current_user, @@ -93,7 +93,7 @@ double( invalid?: false, page_number: 1, - rect: [0, 50, 100, 100], + rect: { left: 0, top: 50, width: 100, height: 100 }, id: annotation.id, section: annotation.section.id, current_user: current_user @@ -140,7 +140,7 @@ title: { en: "Title test Section" }, invalid?: false, page_number: 1, - rect: [50, 50, 100, 100], + rect: { left: 50, top: 50, width: 100, height: 100 }, id: "annotationid", group: "groupid", current_user: current_user, From 6c9d6bd8927d89e736400c39473f53938d97f499 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20Verg=C3=A9s?= Date: Fri, 23 Jun 2023 13:51:08 +0200 Subject: [PATCH 13/24] fix pending tests --- .../create_suggestion.rb | 2 +- .../document_suggestions_controller.rb | 8 +-- .../section_suggestions_controller.rb | 2 +- .../decidim_participatory_documents_editor.js | 4 +- .../decidim/participatory_documents/pdf.js | 8 +-- .../participatory_documents/pdf/box.js | 2 +- .../pdf/suggestion_form.js | 10 ++-- .../document_suggestions/_form.html.erb | 2 +- .../document_suggestions/index.html.erb | 1 + .../documents/_pdfjs_base.html.erb | 4 +- .../documents/index.html.erb | 1 + .../section_suggestions/_form.html.erb | 2 +- .../section_suggestions/index.html.erb | 1 + .../user_interacts_with_pdf_viewer_spec.rb | 50 +++++++++++++------ 14 files changed, 60 insertions(+), 37 deletions(-) diff --git a/app/commands/decidim/participatory_documents/create_suggestion.rb b/app/commands/decidim/participatory_documents/create_suggestion.rb index 26c80461..ad275099 100644 --- a/app/commands/decidim/participatory_documents/create_suggestion.rb +++ b/app/commands/decidim/participatory_documents/create_suggestion.rb @@ -20,7 +20,7 @@ def call broadcast(:ok, suggestion) rescue ActiveRecord::RecordInvalid => e Rails.logger.info e.message - broadcast(:invalid) + broadcast(:invalid, e.message) end end diff --git a/app/controllers/decidim/participatory_documents/document_suggestions_controller.rb b/app/controllers/decidim/participatory_documents/document_suggestions_controller.rb index e428fae8..1558b101 100644 --- a/app/controllers/decidim/participatory_documents/document_suggestions_controller.rb +++ b/app/controllers/decidim/participatory_documents/document_suggestions_controller.rb @@ -10,18 +10,18 @@ class DocumentSuggestionsController < Decidim::ParticipatoryDocuments::Applicati layout false def index - @form = form(Decidim::ParticipatoryDocuments::SuggestionForm).from_params({}) + @form = form(Decidim::ParticipatoryDocuments::SuggestionForm).instance end def create - @form = form(Decidim::ParticipatoryDocuments::SuggestionForm).from_params(params).with_context(current_component: current_component) + @form = form(Decidim::ParticipatoryDocuments::SuggestionForm).from_params(params) CreateSuggestion.call(@form, section) do on(:ok) do |_suggestion| redirect_to(document_suggestions_path(document)) && return end - on(:invalid) do - render template: "decidim/participatory_documents/document_suggestions/index", format: [:html], status: :bad_request + on(:invalid) do |error| + render template: "decidim/participatory_documents/document_suggestions/index", locals: { error_message: error }, format: [:html], status: :bad_request end end end diff --git a/app/controllers/decidim/participatory_documents/section_suggestions_controller.rb b/app/controllers/decidim/participatory_documents/section_suggestions_controller.rb index 41407f1b..08facf75 100644 --- a/app/controllers/decidim/participatory_documents/section_suggestions_controller.rb +++ b/app/controllers/decidim/participatory_documents/section_suggestions_controller.rb @@ -10,7 +10,7 @@ class SectionSuggestionsController < Decidim::ParticipatoryDocuments::Applicatio layout false def index - @form = form(Decidim::ParticipatoryDocuments::SuggestionForm).from_params({}) + @form = form(Decidim::ParticipatoryDocuments::SuggestionForm).instance end def create diff --git a/app/packs/entrypoints/decidim_participatory_documents_editor.js b/app/packs/entrypoints/decidim_participatory_documents_editor.js index e81d3337..c51ed88c 100644 --- a/app/packs/entrypoints/decidim_participatory_documents_editor.js +++ b/app/packs/entrypoints/decidim_participatory_documents_editor.js @@ -6,7 +6,7 @@ import $ from "jquery"; // eslint-disable-line id-length import "foundation-sites"; -const csrfToken = document.getElementsByName("csrf-token")[0].content; +const csrfToken = document.getElementsByName("csrf-token"); $.ajaxSetup({ - headers: { "X-CSRF-Token": csrfToken } + headers: { "X-CSRF-Token": csrfToken.length && csrfToken[0].content } }); diff --git a/app/packs/src/decidim/participatory_documents/pdf.js b/app/packs/src/decidim/participatory_documents/pdf.js index fca91377..a094daf4 100644 --- a/app/packs/src/decidim/participatory_documents/pdf.js +++ b/app/packs/src/decidim/participatory_documents/pdf.js @@ -3,17 +3,17 @@ import SuggestionForm from "src/decidim/participatory_documents/pdf/suggestion_f import "src/decidim/participatory_documents/pdf_notifications"; import "src/decidim/participatory_documents/global"; -window.InitDocumentManagers = function(options) { +window.InitDocumentManagers = (options) => { options.globalSuggestionsButton.addEventListener("click", () => { (new SuggestionForm(options.documentPath, null)).fetchGroup(); }); }; // Call this on an annotation layer to initialize the polygon viewer (public side) -window.InitPolygonViewer = function(layer, boxes, options) { +window.InitPolygonViewer = (layer, boxes, options) => { let viewer = new PolygonViewer(layer, boxes, { i18n: options.i18n}); - viewer.onBoxClick = function(box, evt) { + viewer.onBoxClick = (box, evt) => { console.log("click on box", box, evt); options.participationLayout.classList.add("active"); (new SuggestionForm(options.documentPath, box.section)).fetchGroup(); @@ -27,7 +27,7 @@ window.InitPolygonViewer = function(layer, boxes, options) { }; const modal = document.getElementById("participation-modal"); - document.addEventListener("click", function(event) { + document.addEventListener("click", (event) => { if (event.target.closest("#participation-modal") === null && modal.classList.contains("active")) { modal.classList.remove("active"); } diff --git a/app/packs/src/decidim/participatory_documents/pdf/box.js b/app/packs/src/decidim/participatory_documents/pdf/box.js index c91bea95..dec6a620 100644 --- a/app/packs/src/decidim/participatory_documents/pdf/box.js +++ b/app/packs/src/decidim/participatory_documents/pdf/box.js @@ -140,7 +140,7 @@ export default class Box { _click(evt) { if (!this.layer.creating && !this.isMoving() && !this.isGrouping() && !this.isResizing()) { - console.log("box click", evt, this); + // console.log("box click", evt, this); evt.stopPropagation(); this.onClick(evt); window.addEventListener("click", this._blur.bind(this), { once: true }); diff --git a/app/packs/src/decidim/participatory_documents/pdf/suggestion_form.js b/app/packs/src/decidim/participatory_documents/pdf/suggestion_form.js index 867d386e..127c4038 100644 --- a/app/packs/src/decidim/participatory_documents/pdf/suggestion_form.js +++ b/app/packs/src/decidim/participatory_documents/pdf/suggestion_form.js @@ -4,7 +4,6 @@ export default class SuggestionForm { this.group = group; this.div = document.getElementById("participation-modal"); this.div.classList.remove("section", "document", "active"); - console.log(this.div.style, getComputedStyle(this.div)) if (group) { this.div.classList.add("section"); } else { @@ -13,7 +12,9 @@ export default class SuggestionForm { } getCSRFToken() { - return document.getElementsByName("csrf-token")[0].content; + const token = document.getElementsByName("csrf-token") + + return token.length && token[0].content; } // Sanitize internal path @@ -53,7 +54,6 @@ export default class SuggestionForm { if (close && modal) { close.addEventListener("click", () => { - console.log("close"); modal.classList.remove("active"); close.style.display = "none"; }, { once: true }); @@ -91,7 +91,6 @@ export default class SuggestionForm { }).then((response) => { return response.text(); }).then((data) => { - console.log("data", data); this.div.innerHTML = data; this.addFormHandler(); this.addCloseHandler(); @@ -99,6 +98,7 @@ export default class SuggestionForm { console.error(error); }); }); + document.getElementById("suggestion_body").focus(); } } @@ -114,7 +114,7 @@ export default class SuggestionForm { if (response.ok) { return response.text(); } - throw new Error(" "); + throw new Error(response); }). then((data) => { this.populateArea(data); diff --git a/app/views/decidim/participatory_documents/document_suggestions/_form.html.erb b/app/views/decidim/participatory_documents/document_suggestions/_form.html.erb index e14459f2..d7bb0c1a 100644 --- a/app/views/decidim/participatory_documents/document_suggestions/_form.html.erb +++ b/app/views/decidim/participatory_documents/document_suggestions/_form.html.erb @@ -23,7 +23,7 @@
- + <%= form.submit t("send_suggestion", scope: "decidim.participatory_documents.document"), id: "editor-modal-save", name: "editor-modal-save" %>
<% end %> diff --git a/app/views/decidim/participatory_documents/document_suggestions/index.html.erb b/app/views/decidim/participatory_documents/document_suggestions/index.html.erb index 96f13adc..c0a55918 100644 --- a/app/views/decidim/participatory_documents/document_suggestions/index.html.erb +++ b/app/views/decidim/participatory_documents/document_suggestions/index.html.erb @@ -9,5 +9,6 @@
+
<%= error_message if defined?(error_message) %>
<%= render "decidim/participatory_documents/document_suggestions/form" %>
diff --git a/app/views/decidim/participatory_documents/documents/_pdfjs_base.html.erb b/app/views/decidim/participatory_documents/documents/_pdfjs_base.html.erb index a1b771d1..ecbca4da 100644 --- a/app/views/decidim/participatory_documents/documents/_pdfjs_base.html.erb +++ b/app/views/decidim/participatory_documents/documents/_pdfjs_base.html.erb @@ -306,12 +306,12 @@ See https://github.com/adobe-type-tools/cmap-resources
<% if defined?(displaySave) && displaySave == true %> - <% end %> <% if defined?(globalSuggestions) && globalSuggestions == true %> - <% end %> diff --git a/app/views/decidim/participatory_documents/documents/index.html.erb b/app/views/decidim/participatory_documents/documents/index.html.erb index a164dea9..edcd047a 100644 --- a/app/views/decidim/participatory_documents/documents/index.html.erb +++ b/app/views/decidim/participatory_documents/documents/index.html.erb @@ -15,3 +15,4 @@

<%= t("decidim.participatory_documents.documents.missing") %>

<% end %> +<% console %> \ No newline at end of file diff --git a/app/views/decidim/participatory_documents/section_suggestions/_form.html.erb b/app/views/decidim/participatory_documents/section_suggestions/_form.html.erb index 1fe33283..f3e6e9be 100644 --- a/app/views/decidim/participatory_documents/section_suggestions/_form.html.erb +++ b/app/views/decidim/participatory_documents/section_suggestions/_form.html.erb @@ -3,6 +3,6 @@ <%= form.text_area :body %>
- + <%= form.submit t("send_suggestion", scope: "decidim.participatory_documents.document"), id: "editor-modal-save", name: "editor-modal-save" %>
<% end %> diff --git a/app/views/decidim/participatory_documents/section_suggestions/index.html.erb b/app/views/decidim/participatory_documents/section_suggestions/index.html.erb index 007faf4b..a72b93cf 100644 --- a/app/views/decidim/participatory_documents/section_suggestions/index.html.erb +++ b/app/views/decidim/participatory_documents/section_suggestions/index.html.erb @@ -9,5 +9,6 @@
+
<%= error_message if defined?(error_message) %>
<%= render "decidim/participatory_documents/section_suggestions/form" %>
diff --git a/spec/system/user_interacts_with_pdf_viewer_spec.rb b/spec/system/user_interacts_with_pdf_viewer_spec.rb index d0bd8373..0deb4878 100644 --- a/spec/system/user_interacts_with_pdf_viewer_spec.rb +++ b/spec/system/user_interacts_with_pdf_viewer_spec.rb @@ -186,24 +186,44 @@ login_as document.author, scope: :user page.visit Decidim::EngineRouter.main_proxy(component).pdf_viewer_documents_path(file: document.attached_uploader(:file).path) - annotation = section.annotations.first + end - find("#box-#{annotation.id}").click + it "submits a box content" do + find("#box-#{section.annotations.first.id}").click + sleep 1 + expect(page).to have_css("#participation-modal.active") + expect(page).not_to have_content("upload a file") + + within "#new_suggestion_" do + fill_in :suggestion_body, with: "Some random string longer than 15 chrs" + click_button("Send suggestion") + end + expect(page).to have_content("Some random string longer than 15 chrs") + expect(Decidim::ParticipatoryDocuments::Suggestion.count).to eq(1) + # hide the modal + find("#close-suggestions").click + expect(page).not_to have_content("Some random string longer than 15 chrs") + page.find("#box-#{section.annotations.first.id}").click + expect(page).to have_content("Some random string longer than 15 chrs") end - it "submits the content" do - pending "There for some reason Capybara does not handle this" - raise "Pending" - # expect(page).to have_selector("#participation-modal", count: 1) - # expect(page).to have_css("#participation-modal.active") - # - # within "#new_suggestion_" do - # fill_in :suggestion_body, with: "Some random string longer than 15 chrs" - # click_button("Send suggestion") - # end - # - # page.find("#box-#{section.annotations.first.id}").click - # expect(page).to have_content("Some random string longer than 15 chrs") + it "submits a global content" do + click_button "Global suggestions" + sleep 1 + expect(page).to have_css("#participation-modal.active") + expect(page).to have_content("upload a file") + + within "#new_suggestion_" do + fill_in :suggestion_body, with: "Some random string longer than 15 chrs" + click_button("Send suggestion") + end + expect(page).to have_content("Some random string longer than 15 chrs") + expect(Decidim::ParticipatoryDocuments::Suggestion.count).to eq(1) + # hide the modal + find("#close-suggestions").click + expect(page).not_to have_content("Some random string longer than 15 chrs") + click_button "Global suggestions" + expect(page).to have_content("Some random string longer than 15 chrs") end end end From 4baf7358803a9425251cf41e10ad9076662ff02b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20Verg=C3=A9s?= Date: Fri, 23 Jun 2023 14:03:41 +0200 Subject: [PATCH 14/24] remove debug --- .../decidim/participatory_documents/documents/index.html.erb | 1 - 1 file changed, 1 deletion(-) diff --git a/app/views/decidim/participatory_documents/documents/index.html.erb b/app/views/decidim/participatory_documents/documents/index.html.erb index edcd047a..a164dea9 100644 --- a/app/views/decidim/participatory_documents/documents/index.html.erb +++ b/app/views/decidim/participatory_documents/documents/index.html.erb @@ -15,4 +15,3 @@

<%= t("decidim.participatory_documents.documents.missing") %>

<% end %> -<% console %> \ No newline at end of file From bedb1eaa9df5e5aa27b37699ed67072998132a2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20Verg=C3=A9s?= Date: Fri, 23 Jun 2023 15:34:06 +0200 Subject: [PATCH 15/24] fix --- spec/system/user_interacts_with_pdf_viewer_spec.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/spec/system/user_interacts_with_pdf_viewer_spec.rb b/spec/system/user_interacts_with_pdf_viewer_spec.rb index 0deb4878..057bb0cc 100644 --- a/spec/system/user_interacts_with_pdf_viewer_spec.rb +++ b/spec/system/user_interacts_with_pdf_viewer_spec.rb @@ -199,7 +199,6 @@ click_button("Send suggestion") end expect(page).to have_content("Some random string longer than 15 chrs") - expect(Decidim::ParticipatoryDocuments::Suggestion.count).to eq(1) # hide the modal find("#close-suggestions").click expect(page).not_to have_content("Some random string longer than 15 chrs") @@ -218,7 +217,6 @@ click_button("Send suggestion") end expect(page).to have_content("Some random string longer than 15 chrs") - expect(Decidim::ParticipatoryDocuments::Suggestion.count).to eq(1) # hide the modal find("#close-suggestions").click expect(page).not_to have_content("Some random string longer than 15 chrs") From 082b11efa511c2e3ff4b8d4470d03dfb8cfaf597 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20Verg=C3=A9s?= Date: Fri, 7 Jul 2023 09:36:43 +0200 Subject: [PATCH 16/24] update versiosn --- .github/workflows/lint.yml | 5 +- .github/workflows/test.yml | 9 +- .ruby-version | 2 +- Gemfile.lock | 601 ++++++++++-------- babel.config.json | 7 +- decidim-participatory_documents.gemspec | 2 +- .../participatory_documents/version.rb | 6 +- 7 files changed, 336 insertions(+), 296 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index ea91fbb0..557a4b1a 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -7,11 +7,12 @@ on: pull_request: env: - RUBY_VERSION: 2.7.6 + RUBY_VERSION: 3.0.5 + NODE_VERSION: 16.9.1 jobs: lint-report: - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 with: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 6619800a..5cd491e1 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -7,11 +7,12 @@ on: pull_request: env: - RUBY_VERSION: 2.7.6 + RUBY_VERSION: 3.0.5 + NODE_VERSION: 16.9.1 jobs: test-report: - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest services: postgres: @@ -39,6 +40,10 @@ jobs: ruby-version: ${{ env.RUBY_VERSION }} bundler-cache: true + - uses: actions/setup-node@master + with: + node-version: ${{ env.NODE_VERSION }} + - name: Setup Database run: bundle exec rake test_app diff --git a/.ruby-version b/.ruby-version index 5b013b97..7da3c168 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -2.7.6 \ No newline at end of file +3.0.5 \ No newline at end of file diff --git a/Gemfile.lock b/Gemfile.lock index ca4e2cf2..083b9cea 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,44 +1,46 @@ PATH remote: . specs: - decidim-participatory_documents (0.1.0) - decidim-core (>= 0.25.0, < 0.27) + decidim-participatory_documents (0.2.0) + decidim-core (>= 0.27.0, < 0.28) GEM remote: https://rubygems.org/ specs: - actioncable (6.0.5.1) - actionpack (= 6.0.5.1) + actioncable (6.1.7.4) + actionpack (= 6.1.7.4) + activesupport (= 6.1.7.4) nio4r (~> 2.0) websocket-driver (>= 0.6.1) - actionmailbox (6.0.5.1) - actionpack (= 6.0.5.1) - activejob (= 6.0.5.1) - activerecord (= 6.0.5.1) - activestorage (= 6.0.5.1) - activesupport (= 6.0.5.1) + actionmailbox (6.1.7.4) + actionpack (= 6.1.7.4) + activejob (= 6.1.7.4) + activerecord (= 6.1.7.4) + activestorage (= 6.1.7.4) + activesupport (= 6.1.7.4) mail (>= 2.7.1) - actionmailer (6.0.5.1) - actionpack (= 6.0.5.1) - actionview (= 6.0.5.1) - activejob (= 6.0.5.1) + actionmailer (6.1.7.4) + actionpack (= 6.1.7.4) + actionview (= 6.1.7.4) + activejob (= 6.1.7.4) + activesupport (= 6.1.7.4) mail (~> 2.5, >= 2.5.4) rails-dom-testing (~> 2.0) - actionpack (6.0.5.1) - actionview (= 6.0.5.1) - activesupport (= 6.0.5.1) - rack (~> 2.0, >= 2.0.8) + actionpack (6.1.7.4) + actionview (= 6.1.7.4) + activesupport (= 6.1.7.4) + rack (~> 2.0, >= 2.0.9) rack-test (>= 0.6.3) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.2.0) - actiontext (6.0.5.1) - actionpack (= 6.0.5.1) - activerecord (= 6.0.5.1) - activestorage (= 6.0.5.1) - activesupport (= 6.0.5.1) + actiontext (6.1.7.4) + actionpack (= 6.1.7.4) + activerecord (= 6.1.7.4) + activestorage (= 6.1.7.4) + activesupport (= 6.1.7.4) nokogiri (>= 1.8.5) - actionview (6.0.5.1) - activesupport (= 6.0.5.1) + actionview (6.1.7.4) + activesupport (= 6.1.7.4) builder (~> 3.1) erubi (~> 1.4) rails-dom-testing (~> 2.0) @@ -46,31 +48,33 @@ GEM active_link_to (1.0.5) actionpack addressable - activejob (6.0.5.1) - activesupport (= 6.0.5.1) + activejob (6.1.7.4) + activesupport (= 6.1.7.4) globalid (>= 0.3.6) - activemodel (6.0.5.1) - activesupport (= 6.0.5.1) - activerecord (6.0.5.1) - activemodel (= 6.0.5.1) - activesupport (= 6.0.5.1) - activestorage (6.0.5.1) - actionpack (= 6.0.5.1) - activejob (= 6.0.5.1) - activerecord (= 6.0.5.1) + activemodel (6.1.7.4) + activesupport (= 6.1.7.4) + activerecord (6.1.7.4) + activemodel (= 6.1.7.4) + activesupport (= 6.1.7.4) + activestorage (6.1.7.4) + actionpack (= 6.1.7.4) + activejob (= 6.1.7.4) + activerecord (= 6.1.7.4) + activesupport (= 6.1.7.4) marcel (~> 1.0) - activesupport (6.0.5.1) + mini_mime (>= 1.1.0) + activesupport (6.1.7.4) concurrent-ruby (~> 1.0, >= 1.0.2) - i18n (>= 0.7, < 2) - minitest (~> 5.1) - tzinfo (~> 1.1) - zeitwerk (~> 2.2, >= 2.2.2) + i18n (>= 1.6, < 2) + minitest (>= 5.1) + tzinfo (~> 2.0) + zeitwerk (~> 2.3) acts_as_list (0.9.19) activerecord (>= 3.0) - addressable (2.8.1) + addressable (2.8.4) public_suffix (>= 2.0.2, < 6.0) ast (2.4.2) - axe-core-api (4.4.1) + axe-core-api (4.7.0) dumb_delegator virtus axe-core-rspec (4.1.0) @@ -82,7 +86,7 @@ GEM ice_nine (~> 0.11.0) thread_safe (~> 0.3, >= 0.3.1) batch-loader (1.5.0) - bcrypt (3.1.18) + bcrypt (3.1.19) better_html (1.0.16) actionview (>= 4.0) activesupport (>= 4.0) @@ -92,12 +96,12 @@ GEM parser (>= 2.4) smart_properties bindex (0.8.1) - bootsnap (1.13.0) + bootsnap (1.16.0) msgpack (~> 1.2) browser (2.7.1) builder (3.2.4) byebug (11.1.3) - capybara (3.37.1) + capybara (3.39.2) addressable matrix mini_mime (>= 0.1.3) @@ -106,7 +110,7 @@ GEM rack-test (>= 0.6.3) regexp_parser (>= 1.5, < 3.0) xpath (~> 3.2) - carrierwave (2.2.2) + carrierwave (2.2.4) activemodel (>= 5.0.0) activesupport (>= 5.0.0) addressable (~> 2.6) @@ -126,9 +130,9 @@ GEM actionpack (>= 5.0) cells (>= 4.1.6, < 5.0.0) charlock_holmes (0.7.7) - chef-utils (17.10.0) + chef-utils (18.2.7) concurrent-ruby - childprocess (3.0.0) + childprocess (4.1.0) codecov (0.6.0) simplecov (>= 0.15, < 0.22) coercible (1.0.0) @@ -140,65 +144,67 @@ GEM coffee-script-source execjs coffee-script-source (1.12.2) - concurrent-ruby (1.1.10) + commonmarker (0.23.9) + concurrent-ruby (1.2.2) crack (0.4.5) rexml crass (1.0.6) - css_parser (1.11.0) + css_parser (1.14.0) addressable - date_validator (0.9.0) - activemodel - activesupport + date (3.3.3) + date_validator (0.12.0) + activemodel (>= 3) + activesupport (>= 3) db-query-matchers (0.10.0) activesupport (>= 4.0, < 7) rspec (~> 3.0) - decidim (0.26.2) - decidim-accountability (= 0.26.2) - decidim-admin (= 0.26.2) - decidim-api (= 0.26.2) - decidim-assemblies (= 0.26.2) - decidim-blogs (= 0.26.2) - decidim-budgets (= 0.26.2) - decidim-comments (= 0.26.2) - decidim-core (= 0.26.2) - decidim-debates (= 0.26.2) - decidim-forms (= 0.26.2) - decidim-generators (= 0.26.2) - decidim-meetings (= 0.26.2) - decidim-pages (= 0.26.2) - decidim-participatory_processes (= 0.26.2) - decidim-proposals (= 0.26.2) - decidim-sortitions (= 0.26.2) - decidim-surveys (= 0.26.2) - decidim-system (= 0.26.2) - decidim-templates (= 0.26.2) - decidim-verifications (= 0.26.2) - decidim-accountability (0.26.2) - decidim-comments (= 0.26.2) - decidim-core (= 0.26.2) - decidim-admin (0.26.2) + decidim (0.27.3) + decidim-accountability (= 0.27.3) + decidim-admin (= 0.27.3) + decidim-api (= 0.27.3) + decidim-assemblies (= 0.27.3) + decidim-blogs (= 0.27.3) + decidim-budgets (= 0.27.3) + decidim-comments (= 0.27.3) + decidim-core (= 0.27.3) + decidim-debates (= 0.27.3) + decidim-forms (= 0.27.3) + decidim-generators (= 0.27.3) + decidim-meetings (= 0.27.3) + decidim-pages (= 0.27.3) + decidim-participatory_processes (= 0.27.3) + decidim-proposals (= 0.27.3) + decidim-sortitions (= 0.27.3) + decidim-surveys (= 0.27.3) + decidim-system (= 0.27.3) + decidim-templates (= 0.27.3) + decidim-verifications (= 0.27.3) + decidim-accountability (0.27.3) + decidim-comments (= 0.27.3) + decidim-core (= 0.27.3) + decidim-admin (0.27.3) active_link_to (~> 1.0) - decidim-core (= 0.26.2) + decidim-core (= 0.27.3) devise (~> 4.7) devise-i18n (~> 1.2) devise_invitable (~> 2.0) - decidim-api (0.26.2) + decidim-api (0.27.3) graphql (~> 1.12, < 1.13) + graphql-docs (~> 2.1.0) rack-cors (~> 1.0) + decidim-assemblies (0.27.3) + decidim-core (= 0.27.3) + decidim-blogs (0.27.3) + decidim-admin (= 0.27.3) + decidim-comments (= 0.27.3) + decidim-core (= 0.27.3) + decidim-budgets (0.27.3) + decidim-comments (= 0.27.3) + decidim-core (= 0.27.3) + decidim-comments (0.27.3) + decidim-core (= 0.27.3) redcarpet (~> 3.5, >= 3.5.1) - decidim-assemblies (0.26.2) - decidim-core (= 0.26.2) - decidim-blogs (0.26.2) - decidim-admin (= 0.26.2) - decidim-comments (= 0.26.2) - decidim-core (= 0.26.2) - decidim-budgets (0.26.2) - decidim-comments (= 0.26.2) - decidim-core (= 0.26.2) - decidim-comments (0.26.2) - decidim-core (= 0.26.2) - redcarpet (~> 3.5, >= 3.5.1) - decidim-core (0.26.2) + decidim-core (0.27.3) active_link_to (~> 1.0) acts_as_list (~> 0.9) batch-loader (~> 1.2) @@ -207,17 +213,17 @@ GEM cells-erb (~> 0.1.0) cells-rails (~> 0.1.3) charlock_holmes (~> 0.7) - date_validator (~> 0.9.0) - decidim-api (= 0.26.2) + date_validator (~> 0.12.0) + decidim-api (= 0.27.3) devise (~> 4.7) devise-i18n (~> 1.2) diffy (~> 3.3) doorkeeper (~> 5.1) doorkeeper-i18n (~> 4.0) - file_validators (~> 2.1) + file_validators (~> 3.0) fog-local (~> 0.6) - foundation_rails_helper - geocoder (~> 1.7.5) + foundation_rails_helper (~> 4.0) + geocoder (~> 1.8) hashdiff (>= 0.4.0, < 2.0.0) invisible_captcha (~> 0.12) kaminari (~> 1.2, >= 1.2.1) @@ -236,117 +242,115 @@ GEM premailer-rails (~> 1.10) rack (~> 2.2, >= 2.2.3) rack-attack (~> 6.0) - rails (~> 6.0.4) + rails (~> 6.1.0) rails-i18n (~> 6.0) ransack (~> 2.4.1) - rectify (~> 0.13.0) redis (~> 4.1) request_store (~> 1.5.0) rubyXL (~> 3.4) rubyzip (~> 2.0) - searchlight (~> 4.1) seven_zip_ruby (~> 1.3) social-share-button (~> 1.2, >= 1.2.1) valid_email2 (~> 2.1) webpacker (= 6.0.0.rc.5) + webpush (~> 1.1) wisper (~> 2.0) - decidim-debates (0.26.2) - decidim-comments (= 0.26.2) - decidim-core (= 0.26.2) - decidim-dev (0.26.2) + decidim-debates (0.27.3) + decidim-comments (= 0.27.3) + decidim-core (= 0.27.3) + decidim-dev (0.27.3) axe-core-rspec (~> 4.1.0) byebug (~> 11.0) capybara (~> 3.24) db-query-matchers (~> 0.10.0) - decidim (= 0.26.2) + decidim (= 0.27.3) erb_lint (~> 0.0.35) factory_bot_rails (~> 4.8) i18n-tasks (~> 0.9.18) mdl (~> 0.5) - nokogiri (~> 1.12) + nokogiri (~> 1.13) + parallel_tests (~> 3.7) puma (~> 5.0) rails-controller-testing (~> 1.0) - rspec-cells (~> 0.3.4) + rspec-cells (~> 0.3.7) rspec-html-matchers (~> 0.9.1) rspec-rails (~> 4.0) rspec-retry (~> 0.6.2) rspec_junit_formatter (~> 0.3.0) - rubocop (~> 0.92.0) - rubocop-rails (~> 2.8) - rubocop-rspec (= 1.43.2) - selenium-webdriver (~> 3.142) - simplecov (~> 0.19.0) - simplecov-cobertura (~> 1.3.1) - system_test_html_screenshots (~> 0.2) + rubocop (~> 1.28.0) + rubocop-rails (~> 2.14) + rubocop-rspec (~> 2.10) + selenium-webdriver (~> 4.1.0) + simplecov (~> 0.21.0) + simplecov-cobertura (~> 2.1.0) w3c_rspec_validators (~> 0.3.0) webmock (~> 3.6) wisper-rspec (~> 1.0) - decidim-forms (0.26.2) - decidim-core (= 0.26.2) + decidim-forms (0.27.3) + decidim-core (= 0.27.3) wicked_pdf (~> 2.1) wkhtmltopdf-binary (~> 0.12) - decidim-generators (0.26.2) - decidim-core (= 0.26.2) - decidim-meetings (0.26.2) - decidim-core (= 0.26.2) - decidim-forms (= 0.26.2) + decidim-generators (0.27.3) + decidim-core (= 0.27.3) + decidim-meetings (0.27.3) + decidim-core (= 0.27.3) + decidim-forms (= 0.27.3) icalendar (~> 2.5) - decidim-pages (0.26.2) - decidim-core (= 0.26.2) - decidim-participatory_processes (0.26.2) - decidim-core (= 0.26.2) - decidim-proposals (0.26.2) - decidim-comments (= 0.26.2) - decidim-core (= 0.26.2) - doc2text (~> 0.4.4) + decidim-pages (0.27.3) + decidim-core (= 0.27.3) + decidim-participatory_processes (0.27.3) + decidim-core (= 0.27.3) + decidim-proposals (0.27.3) + decidim-comments (= 0.27.3) + decidim-core (= 0.27.3) + doc2text (~> 0.4.5) redcarpet (~> 3.5, >= 3.5.1) - decidim-sortitions (0.26.2) - decidim-admin (= 0.26.2) - decidim-comments (= 0.26.2) - decidim-core (= 0.26.2) - decidim-proposals (= 0.26.2) - decidim-surveys (0.26.2) - decidim-core (= 0.26.2) - decidim-forms (= 0.26.2) - decidim-templates (= 0.26.2) - decidim-system (0.26.2) + decidim-sortitions (0.27.3) + decidim-admin (= 0.27.3) + decidim-comments (= 0.27.3) + decidim-core (= 0.27.3) + decidim-proposals (= 0.27.3) + decidim-surveys (0.27.3) + decidim-core (= 0.27.3) + decidim-forms (= 0.27.3) + decidim-templates (= 0.27.3) + decidim-system (0.27.3) active_link_to (~> 1.0) - decidim-core (= 0.26.2) + decidim-core (= 0.27.3) devise (~> 4.7) devise-i18n (~> 1.2) devise_invitable (~> 2.0) - decidim-templates (0.26.2) - decidim-core (= 0.26.2) - decidim-forms (= 0.26.2) - decidim-verifications (0.26.2) - decidim-core (= 0.26.2) + decidim-templates (0.27.3) + decidim-core (= 0.27.3) + decidim-forms (= 0.27.3) + decidim-verifications (0.27.3) + decidim-core (= 0.27.3) declarative-builder (0.1.0) declarative-option (< 0.2.0) declarative-option (0.1.0) descendants_tracker (0.0.4) thread_safe (~> 0.3, >= 0.3.1) - devise (4.8.1) + devise (4.9.2) bcrypt (~> 3.0) orm_adapter (~> 0.1) railties (>= 4.1.0) responders warden (~> 1.2.3) - devise-i18n (1.10.2) - devise (>= 4.8.0) - devise_invitable (2.0.6) + devise-i18n (1.11.0) + devise (>= 4.9.0) + devise_invitable (2.0.8) actionmailer (>= 5.0) devise (>= 4.6) diff-lcs (1.5.0) diffy (3.4.2) - doc2text (0.4.5) - nokogiri (>= 1.13.2, < 1.14.0) + doc2text (0.4.6) + nokogiri (>= 1.13.2, < 1.15.0) rubyzip (~> 2.3.0) docile (1.4.0) - doorkeeper (5.5.4) + doorkeeper (5.6.6) railties (>= 5) doorkeeper-i18n (4.0.1) dumb_delegator (1.0.0) - equalizer (0.0.11) erb_lint (0.0.37) activesupport better_html (~> 1.0.7) @@ -357,9 +361,12 @@ GEM smart_properties erbse (0.1.4) temple - erubi (1.11.0) - excon (0.92.4) + erubi (1.12.0) + escape_utils (1.3.0) + excon (0.100.0) execjs (2.8.1) + extended-markdown-filter (0.7.0) + html-pipeline (~> 2.9) factory_bot (4.11.1) activesupport (>= 3.0.0) factory_bot_rails (4.11.1) @@ -367,12 +374,12 @@ GEM railties (>= 3.0.0) faker (2.23.0) i18n (>= 1.8.11, < 2) - faraday (2.5.2) + faraday (2.7.10) faraday-net_http (>= 2.0, < 3.1) ruby2_keywords (>= 0.0.4) - faraday-net_http (3.0.0) + faraday-net_http (3.0.2) ffi (1.15.5) - file_validators (2.3.0) + file_validators (3.0.0) activemodel (>= 3.2) mime-types (>= 1.0) fog-core (2.3.0) @@ -388,16 +395,29 @@ GEM activemodel (>= 4.1, < 7.1) activesupport (>= 4.1, < 7.1) railties (>= 4.1, < 7.1) - geocoder (1.7.5) - globalid (1.0.0) + gemoji (3.0.1) + geocoder (1.8.2) + globalid (1.1.0) activesupport (>= 5.0) graphql (1.12.24) + graphql-docs (2.1.0) + commonmarker (~> 0.16) + escape_utils (~> 1.2) + extended-markdown-filter (~> 0.4) + gemoji (~> 3.0) + graphql (~> 1.12) + html-pipeline (~> 2.9) + sass (~> 3.4) hashdiff (1.0.1) hashie (5.0.0) - highline (2.0.3) + highline (2.1.0) + hkdf (0.3.0) + html-pipeline (2.14.3) + activesupport (>= 2) + nokogiri (>= 1.4) html_tokenizer (0.0.7) htmlentities (4.3.4) - i18n (1.12.0) + i18n (1.14.1) concurrent-ruby (~> 1.0) i18n-tasks (0.9.37) activesupport (>= 4.0.2) @@ -418,8 +438,8 @@ GEM ruby-vips (>= 2.0.17, < 3) invisible_captcha (0.13.0) rails (>= 3.2.0) - json (2.6.2) - jwt (2.5.0) + json (2.6.3) + jwt (2.7.1) kaminari (1.2.2) activesupport (>= 4.1.0) kaminari-actionview (= 1.2.2) @@ -436,25 +456,28 @@ GEM rexml kramdown-parser-gfm (1.1.0) kramdown (~> 2.0) - launchy (2.5.0) - addressable (~> 2.7) + launchy (2.5.2) + addressable (~> 2.8) letter_opener (1.8.1) launchy (>= 2.2, < 3) letter_opener_web (1.4.1) actionmailer (>= 3.2) letter_opener (~> 1.0) railties (>= 3.2) - listen (3.7.1) + listen (3.8.0) rb-fsevent (~> 0.10, >= 0.10.3) rb-inotify (~> 0.9, >= 0.9.10) loofah (2.3.1) crass (~> 1.0.2) nokogiri (>= 1.5.9) - mail (2.7.1) + mail (2.8.1) mini_mime (>= 0.1.1) + net-imap + net-pop + net-smtp marcel (1.0.2) matrix (0.4.2) - mdl (0.11.0) + mdl (0.12.0) kramdown (~> 2.3) kramdown-parser-gfm (~> 1.1) mixlib-cli (~> 2.1, >= 2.1.1) @@ -463,37 +486,44 @@ GEM method_source (1.0.0) mime-types (3.4.1) mime-types-data (~> 3.2015) - mime-types-data (3.2022.0105) - mini_magick (4.11.0) + mime-types-data (3.2023.0218.1) + mini_magick (4.12.0) mini_mime (1.1.2) - minitest (5.16.3) + minitest (5.18.1) mixlib-cli (2.1.8) mixlib-config (3.0.27) tomlrb mixlib-shellout (3.2.7) chef-utils - msgpack (1.5.6) + msgpack (1.7.1) multi_xml (0.6.0) mustache (1.1.1) - nio4r (2.5.8) - nokogiri (1.13.8-x86_64-darwin) - racc (~> 1.4) - nokogiri (1.13.8-x86_64-linux) + net-imap (0.3.6) + date + net-protocol + net-pop (0.1.2) + net-protocol + net-protocol (0.2.1) + timeout + net-smtp (0.3.3) + net-protocol + nio4r (2.5.9) + nokogiri (1.14.5-x86_64-linux) racc (~> 1.4) oauth (1.1.0) oauth-tty (~> 1.0, >= 1.0.1) snaky_hash (~> 2.0) version_gem (~> 1.1) - oauth-tty (1.0.3) - version_gem (~> 1.1) - oauth2 (2.0.8) + oauth-tty (1.0.5) + version_gem (~> 1.1, >= 1.1.1) + oauth2 (2.0.9) faraday (>= 0.17.3, < 3.0) jwt (>= 1.0, < 3.0) multi_xml (~> 0.5) - rack (>= 1.2, < 3) + rack (>= 1.2, < 4) snaky_hash (~> 2.0) version_gem (~> 1.1) - omniauth (2.1.0) + omniauth (2.1.1) hashie (>= 3.4.6) rack (>= 2.2.3) rack-protection @@ -520,68 +550,73 @@ GEM paper_trail (12.3.0) activerecord (>= 5.2) request_store (~> 1.1) - parallel (1.22.1) - parser (3.1.2.1) + parallel (1.23.0) + parallel_tests (3.13.0) + parallel + parser (3.2.2.3) ast (~> 2.4.1) + racc pg (1.1.4) pg_search (2.3.6) activerecord (>= 5.2) activesupport (>= 5.2) - premailer (1.16.0) + premailer (1.21.0) addressable - css_parser (>= 1.6.0) + css_parser (>= 1.12.0) htmlentities (>= 4.0.0) - premailer-rails (1.11.1) + premailer-rails (1.12.0) actionmailer (>= 3) + net-smtp premailer (~> 1.7, >= 1.7.9) - public_suffix (5.0.0) - puma (5.6.5) + public_suffix (5.0.1) + puma (5.6.6) nio4r (~> 2.0) - racc (1.6.0) - rack (2.2.4) + racc (1.7.1) + rack (2.2.7) rack-attack (6.6.1) rack (>= 1.0, < 3) rack-cors (1.1.1) rack (>= 2.0.0) - rack-protection (2.2.2) + rack-protection (3.0.6) rack - rack-proxy (0.7.2) + rack-proxy (0.7.6) rack - rack-test (2.0.2) + rack-test (2.1.0) rack (>= 1.3) - rails (6.0.5.1) - actioncable (= 6.0.5.1) - actionmailbox (= 6.0.5.1) - actionmailer (= 6.0.5.1) - actionpack (= 6.0.5.1) - actiontext (= 6.0.5.1) - actionview (= 6.0.5.1) - activejob (= 6.0.5.1) - activemodel (= 6.0.5.1) - activerecord (= 6.0.5.1) - activestorage (= 6.0.5.1) - activesupport (= 6.0.5.1) - bundler (>= 1.3.0) - railties (= 6.0.5.1) + rails (6.1.7.4) + actioncable (= 6.1.7.4) + actionmailbox (= 6.1.7.4) + actionmailer (= 6.1.7.4) + actionpack (= 6.1.7.4) + actiontext (= 6.1.7.4) + actionview (= 6.1.7.4) + activejob (= 6.1.7.4) + activemodel (= 6.1.7.4) + activerecord (= 6.1.7.4) + activestorage (= 6.1.7.4) + activesupport (= 6.1.7.4) + bundler (>= 1.15.0) + railties (= 6.1.7.4) sprockets-rails (>= 2.0.0) rails-controller-testing (1.0.5) actionpack (>= 5.0.1.rc1) actionview (>= 5.0.1.rc1) activesupport (>= 5.0.1.rc1) - rails-dom-testing (2.0.3) - activesupport (>= 4.2.0) + rails-dom-testing (2.1.1) + activesupport (>= 5.0.0) + minitest nokogiri (>= 1.6) rails-html-sanitizer (1.4.3) loofah (~> 2.3) rails-i18n (6.0.0) i18n (>= 0.7, < 2) railties (>= 6.0.0, < 7) - railties (6.0.5.1) - actionpack (= 6.0.5.1) - activesupport (= 6.0.5.1) + railties (6.1.7.4) + actionpack (= 6.1.7.4) + activesupport (= 6.1.7.4) method_source - rake (>= 0.8.7) - thor (>= 0.20.3, < 2.0) + rake (>= 12.2) + thor (~> 1.0) rainbow (3.1.1) rake (13.0.6) ransack (2.4.2) @@ -591,39 +626,33 @@ GEM rb-fsevent (0.11.2) rb-inotify (0.10.1) ffi (~> 1.0) - rectify (0.13.0) - activemodel (>= 4.1.0) - activerecord (>= 4.1.0) - activesupport (>= 4.1.0) - virtus (~> 1.0.5) - wisper (>= 1.6.1) - redcarpet (3.5.1) - redis (4.8.0) - regexp_parser (2.5.0) + redcarpet (3.6.0) + redis (4.8.1) + regexp_parser (2.8.1) request_store (1.5.1) rack (>= 1.4) - responders (3.0.1) - actionpack (>= 5.0) - railties (>= 5.0) + responders (3.1.0) + actionpack (>= 5.2) + railties (>= 5.2) rexml (3.2.5) - rspec (3.11.0) - rspec-core (~> 3.11.0) - rspec-expectations (~> 3.11.0) - rspec-mocks (~> 3.11.0) - rspec-cells (0.3.7) + rspec (3.12.0) + rspec-core (~> 3.12.0) + rspec-expectations (~> 3.12.0) + rspec-mocks (~> 3.12.0) + rspec-cells (0.3.8) cells (>= 4.0.0, < 6.0.0) - rspec-rails (< 6.0) - rspec-core (3.11.0) - rspec-support (~> 3.11.0) - rspec-expectations (3.11.0) + rspec-rails (>= 3.0.0, < 6.1.0) + rspec-core (3.12.2) + rspec-support (~> 3.12.0) + rspec-expectations (3.12.3) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.11.0) + rspec-support (~> 3.12.0) rspec-html-matchers (0.9.4) nokogiri (~> 1) rspec (>= 3.0.0.a, < 4) - rspec-mocks (3.11.1) + rspec-mocks (3.12.5) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.11.0) + rspec-support (~> 3.12.0) rspec-rails (4.1.2) actionpack (>= 4.2) activesupport (>= 4.2) @@ -634,30 +663,30 @@ GEM rspec-support (~> 3.10) rspec-retry (0.6.2) rspec-core (> 3.3) - rspec-support (3.11.0) + rspec-support (3.12.1) rspec_junit_formatter (0.3.0) rspec-core (>= 2, < 4, != 2.12.0) - rubocop (0.92.0) + rubocop (1.28.2) parallel (~> 1.10) - parser (>= 2.7.1.5) + parser (>= 3.1.0.0) rainbow (>= 2.2.2, < 4.0) - regexp_parser (>= 1.7) + regexp_parser (>= 1.8, < 3.0) rexml - rubocop-ast (>= 0.5.0) + rubocop-ast (>= 1.17.0, < 2.0) ruby-progressbar (~> 1.7) - unicode-display_width (>= 1.4.0, < 2.0) - rubocop-ast (1.21.0) - parser (>= 3.1.1.0) + unicode-display_width (>= 1.4.0, < 3.0) + rubocop-ast (1.29.0) + parser (>= 3.2.1.0) rubocop-faker (1.1.0) faker (>= 2.12.0) rubocop (>= 0.82.0) - rubocop-rails (2.9.1) + rubocop-rails (2.15.2) activesupport (>= 4.2.0) rack (>= 1.1) - rubocop (>= 0.90.0, < 2.0) - rubocop-rspec (1.43.2) - rubocop (~> 0.87) - ruby-progressbar (1.11.0) + rubocop (>= 1.7.0, < 2.0) + rubocop-rspec (2.11.1) + rubocop (~> 1.19) + ruby-progressbar (1.13.0) ruby-vips (2.1.4) ffi (~> 1.12) ruby2_keywords (0.0.5) @@ -665,58 +694,64 @@ GEM nokogiri (>= 1.10.8) rubyzip (>= 1.3.0) rubyzip (2.3.2) - searchlight (4.1.0) - selenium-webdriver (3.142.7) - childprocess (>= 0.5, < 4.0) + sass (3.7.4) + sass-listen (~> 4.0.0) + sass-listen (4.0.0) + rb-fsevent (~> 0.9, >= 0.9.4) + rb-inotify (~> 0.9, >= 0.9.7) + selenium-webdriver (4.1.0) + childprocess (>= 0.5, < 5.0) + rexml (~> 3.2, >= 3.2.5) rubyzip (>= 1.2.2) semantic_range (3.0.0) seven_zip_ruby (1.3.0) - simplecov (0.19.1) + simplecov (0.21.2) docile (~> 1.1) simplecov-html (~> 0.11) - simplecov-cobertura (1.3.1) - simplecov (~> 0.8) + simplecov_json_formatter (~> 0.1) + simplecov-cobertura (2.1.0) + rexml + simplecov (~> 0.19) simplecov-html (0.12.3) + simplecov_json_formatter (0.1.4) smart_properties (1.17.0) - snaky_hash (2.0.0) + snaky_hash (2.0.1) hashie - version_gem (~> 1.1) + version_gem (~> 1.1, >= 1.1.1) social-share-button (1.2.4) coffee-rails spring (2.1.1) spring-watcher-listen (2.0.1) listen (>= 2.7, < 4.0) spring (>= 1.2, < 3.0) - sprockets (4.1.1) + sprockets (4.2.0) concurrent-ruby (~> 1.0) - rack (> 1, < 3) + rack (>= 2.2.4, < 4) sprockets-rails (3.4.2) actionpack (>= 5.2) activesupport (>= 5.2) sprockets (>= 3.0.0) ssrf_filter (1.1.1) - system_test_html_screenshots (0.2.0) - actionpack (>= 5.2, < 6.1.a) - temple (0.8.2) + temple (0.10.2) terminal-table (3.0.2) unicode-display_width (>= 1.1.1, < 3) - thor (1.2.1) + thor (1.2.2) thread_safe (0.3.6) - tilt (2.0.11) + tilt (2.2.0) + timeout (0.4.0) tomlrb (2.0.3) - tzinfo (1.2.10) - thread_safe (~> 0.1) + tzinfo (2.0.6) + concurrent-ruby (~> 1.0) uber (0.1.0) - unicode-display_width (1.8.0) + unicode-display_width (2.4.2) valid_email2 (2.3.1) activemodel (>= 3.2) mail (~> 2.5) - version_gem (1.1.0) - virtus (1.0.5) + version_gem (1.1.3) + virtus (2.0.0) axiom-types (~> 0.1) coercible (~> 1.0) descendants_tracker (~> 0.0, >= 0.0.3) - equalizer (~> 0.0, >= 0.0.9) w3c_rspec_validators (0.3.0) rails rspec @@ -741,6 +776,9 @@ GEM rack-proxy (>= 0.6.1) railties (>= 5.2) semantic_range (>= 2.3.0) + webpush (1.1.0) + hkdf (~> 0.2) + jwt (~> 2.0) websocket-driver (0.7.5) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.5) @@ -748,21 +786,20 @@ GEM activesupport wisper (2.0.1) wisper-rspec (1.1.0) - wkhtmltopdf-binary (0.12.6.5) + wkhtmltopdf-binary (0.12.6.6) xpath (3.2.0) nokogiri (~> 1.8) - zeitwerk (2.6.0) + zeitwerk (2.6.8) PLATFORMS - x86_64-darwin-21 x86_64-linux DEPENDENCIES bootsnap (~> 1.7) byebug (~> 11.0) codecov - decidim (= 0.26.2) - decidim-dev (= 0.26.2) + decidim (= 0.27.3) + decidim-dev (= 0.27.3) decidim-participatory_documents! faker (~> 2.14) letter_opener_web (~> 1.3) @@ -774,7 +811,7 @@ DEPENDENCIES web-console RUBY VERSION - ruby 2.7.6p219 + ruby 3.0.5p211 BUNDLED WITH - 2.3.23 + 2.3.20 diff --git a/babel.config.json b/babel.config.json index a66039fb..86a38f89 100644 --- a/babel.config.json +++ b/babel.config.json @@ -20,9 +20,6 @@ "corejs": false } ], - [ "@babel/plugin-transform-regenerator", { "async": false }], - [ "@babel/plugin-proposal-private-property-in-object", { "loose": true }], - ["@babel/plugin-proposal-private-methods", { "loose": true }], - ["@babel/plugin-proposal-class-properties", { "loose": true }] + ["@babel/plugin-transform-regenerator", { "async": false }] ] -} \ No newline at end of file +} diff --git a/decidim-participatory_documents.gemspec b/decidim-participatory_documents.gemspec index fda3aaa6..975e7a46 100644 --- a/decidim-participatory_documents.gemspec +++ b/decidim-participatory_documents.gemspec @@ -14,7 +14,7 @@ Gem::Specification.new do |spec| spec.description = "A module for Decidim that facilitates the creation of proposals related to geolocated issues in a city" spec.license = "AGPL-3.0" spec.homepage = "https://github.com/openpoke/decidim-module-participatory_documents" - spec.required_ruby_version = ">= 2.7" + spec.required_ruby_version = ">= 3.0" spec.files = `git ls-files -z`.split("\x0").reject do |f| f.match(%r{^(test|spec|features)/}) diff --git a/lib/decidim/participatory_documents/version.rb b/lib/decidim/participatory_documents/version.rb index 75234140..05e7fa9e 100644 --- a/lib/decidim/participatory_documents/version.rb +++ b/lib/decidim/participatory_documents/version.rb @@ -2,8 +2,8 @@ module Decidim module ParticipatoryDocuments - VERSION = "0.1.0" - DECIDIM_VERSION = "0.26.2" - COMPAT_DECIDIM_VERSION = [">= 0.25.0", "< 0.27"].freeze + VERSION = "0.2.0" + DECIDIM_VERSION = "0.27.3" + COMPAT_DECIDIM_VERSION = [">= 0.27.0", "< 0.28"].freeze end end From 21679f0562862c0f01d03c10e25e0de96278f96a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20Verg=C3=A9s?= Date: Fri, 7 Jul 2023 09:51:37 +0200 Subject: [PATCH 17/24] update packages --- package-lock.json | 42 +++++++++++++++++++++--------------------- package.json | 6 +++--- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/package-lock.json b/package-lock.json index fb6e21cf..c0cbb228 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,9 +18,9 @@ "@babel/plugin-transform-runtime": "^7.19.6", "@babel/preset-env": "^7.20.2", "@babel/preset-react": "^7.18.6", - "@decidim/dev": "0.27.1", - "@decidim/eslint-config": "0.27.1", - "@decidim/stylelint-config": "0.27.1", + "@decidim/dev": "0.27.3", + "@decidim/eslint-config": "0.27.3", + "@decidim/stylelint-config": "0.27.3", "eslint-config-prettier": "^8.2.0", "eslint-config-standard": "^11.0.0", "eslint-plugin-import": "^2.22.0", @@ -1971,18 +1971,18 @@ } }, "node_modules/@decidim/dev": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@decidim/dev/-/dev-0.27.1.tgz", - "integrity": "sha512-zHgwSUuvCWqav5QO6Bzr0LuhieJBE9fCep196I21q9+Rj7/1FRwRQqcdtvh+w+ldjJLnU0NTW7Jeb1eem2o+mQ==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@decidim/dev/-/dev-0.27.3.tgz", + "integrity": "sha512-8g1IrhycJ4Ldc8Fy1foKMMlGWn4SdM0z2Ij+N7a08ELJTY0LOzapIMyU3W4SUpqSPoKxhirXWgulEZocyISd5Q==", "dev": true, "dependencies": { "axe-core": "^4.1.4" } }, "node_modules/@decidim/eslint-config": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@decidim/eslint-config/-/eslint-config-0.27.1.tgz", - "integrity": "sha512-NqWjOF2Se0/klVejagAZQl1hPwKwBYem255lbTdUJ/CkrgqyBzgHET5HX+9IZrN7DJg436ofJQTFgFJ0itzuYA==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@decidim/eslint-config/-/eslint-config-0.27.3.tgz", + "integrity": "sha512-bHaTzjgBgJKhRRZoLj9voIQjVB5qOwFMjdngoG4/nkBapzyqBbqZKlzDTJhavrJusKJQuNUFQA+/Hr+0I9IXeA==", "dev": true, "peerDependencies": { "eslint": "^7.25.0", @@ -1997,9 +1997,9 @@ } }, "node_modules/@decidim/stylelint-config": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@decidim/stylelint-config/-/stylelint-config-0.27.1.tgz", - "integrity": "sha512-gSFa9lJGsRRwG3WXfcl/Dbx9Wvz2MdssjowS1adT8ysWIssGAPnIMHV82HQZD0LYRG/kXqTXa4EF8lufLJdWKg==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@decidim/stylelint-config/-/stylelint-config-0.27.3.tgz", + "integrity": "sha512-bhtpi/ysOfvN2Vl1n+sUaYFxz4QscSfqca7f415tHH12DQvm808DH59mQmTiqDBtsI33f5T1UVfuBlTKkf2hiQ==", "dev": true, "peerDependencies": { "stylelint": "13.11.0" @@ -8676,25 +8676,25 @@ } }, "@decidim/dev": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@decidim/dev/-/dev-0.27.1.tgz", - "integrity": "sha512-zHgwSUuvCWqav5QO6Bzr0LuhieJBE9fCep196I21q9+Rj7/1FRwRQqcdtvh+w+ldjJLnU0NTW7Jeb1eem2o+mQ==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@decidim/dev/-/dev-0.27.3.tgz", + "integrity": "sha512-8g1IrhycJ4Ldc8Fy1foKMMlGWn4SdM0z2Ij+N7a08ELJTY0LOzapIMyU3W4SUpqSPoKxhirXWgulEZocyISd5Q==", "dev": true, "requires": { "axe-core": "^4.1.4" } }, "@decidim/eslint-config": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@decidim/eslint-config/-/eslint-config-0.27.1.tgz", - "integrity": "sha512-NqWjOF2Se0/klVejagAZQl1hPwKwBYem255lbTdUJ/CkrgqyBzgHET5HX+9IZrN7DJg436ofJQTFgFJ0itzuYA==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@decidim/eslint-config/-/eslint-config-0.27.3.tgz", + "integrity": "sha512-bHaTzjgBgJKhRRZoLj9voIQjVB5qOwFMjdngoG4/nkBapzyqBbqZKlzDTJhavrJusKJQuNUFQA+/Hr+0I9IXeA==", "dev": true, "requires": {} }, "@decidim/stylelint-config": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@decidim/stylelint-config/-/stylelint-config-0.27.1.tgz", - "integrity": "sha512-gSFa9lJGsRRwG3WXfcl/Dbx9Wvz2MdssjowS1adT8ysWIssGAPnIMHV82HQZD0LYRG/kXqTXa4EF8lufLJdWKg==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@decidim/stylelint-config/-/stylelint-config-0.27.3.tgz", + "integrity": "sha512-bhtpi/ysOfvN2Vl1n+sUaYFxz4QscSfqca7f415tHH12DQvm808DH59mQmTiqDBtsI33f5T1UVfuBlTKkf2hiQ==", "dev": true, "requires": {} }, diff --git a/package.json b/package.json index 78c5d72f..f37c2795 100644 --- a/package.json +++ b/package.json @@ -38,9 +38,9 @@ "@babel/plugin-transform-runtime": "^7.19.6", "@babel/preset-env": "^7.20.2", "@babel/preset-react": "^7.18.6", - "@decidim/dev": "0.27.1", - "@decidim/eslint-config": "0.27.1", - "@decidim/stylelint-config": "0.27.1", + "@decidim/dev": "0.27.3", + "@decidim/eslint-config": "0.27.3", + "@decidim/stylelint-config": "0.27.3", "eslint-config-prettier": "^8.2.0", "eslint-config-standard": "^11.0.0", "eslint-plugin-import": "^2.22.0", From e5fb141445669fdc08c039a2926caa31829042d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20Verg=C3=A9s?= Date: Fri, 7 Jul 2023 09:54:42 +0200 Subject: [PATCH 18/24] remove rectify --- .../decidim/participatory_documents/admin/answer_suggestion.rb | 2 +- .../admin/assign_suggestions_to_valuator.rb | 2 +- .../decidim/participatory_documents/admin/create_document.rb | 2 +- .../participatory_documents/admin/create_suggestion_note.rb | 2 +- .../decidim/participatory_documents/admin/destroy_annotation.rb | 2 +- .../participatory_documents/admin/notify_suggestion_answer.rb | 2 +- .../decidim/participatory_documents/admin/publish_answers.rb | 2 +- .../decidim/participatory_documents/admin/publish_document.rb | 2 +- .../admin/unassign_suggestions_from_valuator.rb | 2 +- .../decidim/participatory_documents/admin/update_document.rb | 2 +- .../admin/update_or_create_annotation.rb | 2 +- .../decidim/participatory_documents/admin/update_section.rb | 2 +- .../participatory_documents/admin/update_suggestion_note.rb | 2 +- .../decidim/participatory_documents/create_suggestion.rb | 2 +- 14 files changed, 14 insertions(+), 14 deletions(-) diff --git a/app/commands/decidim/participatory_documents/admin/answer_suggestion.rb b/app/commands/decidim/participatory_documents/admin/answer_suggestion.rb index 1b3ee70f..2193f701 100644 --- a/app/commands/decidim/participatory_documents/admin/answer_suggestion.rb +++ b/app/commands/decidim/participatory_documents/admin/answer_suggestion.rb @@ -3,7 +3,7 @@ module Decidim module ParticipatoryDocuments module Admin - class AnswerSuggestion < Rectify::Command + class AnswerSuggestion < Decidim::Command # Public: Initializes the command. # # form - A form object with the params. diff --git a/app/commands/decidim/participatory_documents/admin/assign_suggestions_to_valuator.rb b/app/commands/decidim/participatory_documents/admin/assign_suggestions_to_valuator.rb index 8f3520bb..4f5e5bc5 100644 --- a/app/commands/decidim/participatory_documents/admin/assign_suggestions_to_valuator.rb +++ b/app/commands/decidim/participatory_documents/admin/assign_suggestions_to_valuator.rb @@ -3,7 +3,7 @@ module Decidim module ParticipatoryDocuments module Admin - class AssignSuggestionsToValuator < Rectify::Command + class AssignSuggestionsToValuator < Decidim::Command # Public: Initializes the command. # # form - A form object with the params. diff --git a/app/commands/decidim/participatory_documents/admin/create_document.rb b/app/commands/decidim/participatory_documents/admin/create_document.rb index 854a4a10..7de2d876 100644 --- a/app/commands/decidim/participatory_documents/admin/create_document.rb +++ b/app/commands/decidim/participatory_documents/admin/create_document.rb @@ -3,7 +3,7 @@ module Decidim module ParticipatoryDocuments module Admin - class CreateDocument < Rectify::Command + class CreateDocument < Decidim::Command include ::Decidim::AttachmentAttributesMethods # Public: Initializes the command. diff --git a/app/commands/decidim/participatory_documents/admin/create_suggestion_note.rb b/app/commands/decidim/participatory_documents/admin/create_suggestion_note.rb index 6deeacc1..6e52ed2b 100644 --- a/app/commands/decidim/participatory_documents/admin/create_suggestion_note.rb +++ b/app/commands/decidim/participatory_documents/admin/create_suggestion_note.rb @@ -3,7 +3,7 @@ module Decidim module ParticipatoryDocuments module Admin - class CreateSuggestionNote < Rectify::Command + class CreateSuggestionNote < Decidim::Command # Public: Initializes the command. # # form - A form object with the params. diff --git a/app/commands/decidim/participatory_documents/admin/destroy_annotation.rb b/app/commands/decidim/participatory_documents/admin/destroy_annotation.rb index a4ac1781..c3cacbd8 100644 --- a/app/commands/decidim/participatory_documents/admin/destroy_annotation.rb +++ b/app/commands/decidim/participatory_documents/admin/destroy_annotation.rb @@ -3,7 +3,7 @@ module Decidim module ParticipatoryDocuments module Admin - class DestroyAnnotation < Rectify::Command + class DestroyAnnotation < Decidim::Command # Public: Initializes the command. # # form - A form object with the params. diff --git a/app/commands/decidim/participatory_documents/admin/notify_suggestion_answer.rb b/app/commands/decidim/participatory_documents/admin/notify_suggestion_answer.rb index be8b7da0..fc713232 100644 --- a/app/commands/decidim/participatory_documents/admin/notify_suggestion_answer.rb +++ b/app/commands/decidim/participatory_documents/admin/notify_suggestion_answer.rb @@ -3,7 +3,7 @@ module Decidim module ParticipatoryDocuments module Admin - class NotifySuggestionAnswer < Rectify::Command + class NotifySuggestionAnswer < Decidim::Command # Public: Initializes the command. # # suggestion - The suggestion to write the answer for. diff --git a/app/commands/decidim/participatory_documents/admin/publish_answers.rb b/app/commands/decidim/participatory_documents/admin/publish_answers.rb index 9c5a24ea..be5fe5d5 100644 --- a/app/commands/decidim/participatory_documents/admin/publish_answers.rb +++ b/app/commands/decidim/participatory_documents/admin/publish_answers.rb @@ -3,7 +3,7 @@ module Decidim module ParticipatoryDocuments module Admin - class PublishAnswers < Rectify::Command + class PublishAnswers < Decidim::Command # Public: Initializes the command. # # component - The component that contains the answers. diff --git a/app/commands/decidim/participatory_documents/admin/publish_document.rb b/app/commands/decidim/participatory_documents/admin/publish_document.rb index f43073b2..8ae86a02 100644 --- a/app/commands/decidim/participatory_documents/admin/publish_document.rb +++ b/app/commands/decidim/participatory_documents/admin/publish_document.rb @@ -3,7 +3,7 @@ module Decidim module ParticipatoryDocuments module Admin - class PublishDocument < Rectify::Command + class PublishDocument < Decidim::Command # Public: Initializes the command. # # document - The document to publish. diff --git a/app/commands/decidim/participatory_documents/admin/unassign_suggestions_from_valuator.rb b/app/commands/decidim/participatory_documents/admin/unassign_suggestions_from_valuator.rb index 50925ee1..f2212f2f 100644 --- a/app/commands/decidim/participatory_documents/admin/unassign_suggestions_from_valuator.rb +++ b/app/commands/decidim/participatory_documents/admin/unassign_suggestions_from_valuator.rb @@ -3,7 +3,7 @@ module Decidim module ParticipatoryDocuments module Admin - class UnassignSuggestionsFromValuator < Rectify::Command + class UnassignSuggestionsFromValuator < Decidim::Command # Public: Initializes the command. # # form - A form object with the params. diff --git a/app/commands/decidim/participatory_documents/admin/update_document.rb b/app/commands/decidim/participatory_documents/admin/update_document.rb index 0225b1da..8c779404 100644 --- a/app/commands/decidim/participatory_documents/admin/update_document.rb +++ b/app/commands/decidim/participatory_documents/admin/update_document.rb @@ -3,7 +3,7 @@ module Decidim module ParticipatoryDocuments module Admin - class UpdateDocument < Rectify::Command + class UpdateDocument < Decidim::Command include ::Decidim::AttachmentAttributesMethods def initialize(form, document) diff --git a/app/commands/decidim/participatory_documents/admin/update_or_create_annotation.rb b/app/commands/decidim/participatory_documents/admin/update_or_create_annotation.rb index 6f0842d2..e0219b6a 100644 --- a/app/commands/decidim/participatory_documents/admin/update_or_create_annotation.rb +++ b/app/commands/decidim/participatory_documents/admin/update_or_create_annotation.rb @@ -3,7 +3,7 @@ module Decidim module ParticipatoryDocuments module Admin - class UpdateOrCreateAnnotation < Rectify::Command + class UpdateOrCreateAnnotation < Decidim::Command # Public: Initializes the command. # # form - A form object with the params. diff --git a/app/commands/decidim/participatory_documents/admin/update_section.rb b/app/commands/decidim/participatory_documents/admin/update_section.rb index 57154303..192e734e 100644 --- a/app/commands/decidim/participatory_documents/admin/update_section.rb +++ b/app/commands/decidim/participatory_documents/admin/update_section.rb @@ -3,7 +3,7 @@ module Decidim module ParticipatoryDocuments module Admin - class UpdateSection < Rectify::Command + class UpdateSection < Decidim::Command # Public: Initializes the command. # # form - A form object with the params. diff --git a/app/commands/decidim/participatory_documents/admin/update_suggestion_note.rb b/app/commands/decidim/participatory_documents/admin/update_suggestion_note.rb index f9e0f541..4da7114f 100644 --- a/app/commands/decidim/participatory_documents/admin/update_suggestion_note.rb +++ b/app/commands/decidim/participatory_documents/admin/update_suggestion_note.rb @@ -4,7 +4,7 @@ module Decidim module ParticipatoryDocuments module Admin # A command with all the business logic when a user updates a suggestion note. - class UpdateSuggestionNote < Rectify::Command + class UpdateSuggestionNote < Decidim::Command # Public: Initializes the command. # # form - A form object with the params. diff --git a/app/commands/decidim/participatory_documents/create_suggestion.rb b/app/commands/decidim/participatory_documents/create_suggestion.rb index ad275099..3478b869 100644 --- a/app/commands/decidim/participatory_documents/create_suggestion.rb +++ b/app/commands/decidim/participatory_documents/create_suggestion.rb @@ -2,7 +2,7 @@ module Decidim module ParticipatoryDocuments - class CreateSuggestion < Rectify::Command + class CreateSuggestion < Decidim::Command include ::Decidim::AttachmentMethods def initialize(form, suggestable) From 0994f311d65cb86a2fa9c6be5115d87452fcdbee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20Verg=C3=A9s?= Date: Fri, 7 Jul 2023 10:08:55 +0200 Subject: [PATCH 19/24] fix babel config --- Rakefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Rakefile b/Rakefile index 36c5cc71..00b57b30 100644 --- a/Rakefile +++ b/Rakefile @@ -4,6 +4,8 @@ require "decidim/dev/common_rake" require "fileutils" def install_module(path) + # maintain until https://github.com/decidim/decidim/commit/51b81b37004708ab72e70993fef4634eef18ee6c is in the decidim version used + FileUtils.cp("babel.config.json", "#{path}/babel.config.json") Dir.chdir(path) do system("bundle exec rake decidim_participatory_documents:install:migrations") system("bundle exec rake db:migrate") From 50c442b6b17fd80197a341c04ba9c7a9c48524f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20Verg=C3=A9s?= Date: Fri, 7 Jul 2023 19:38:18 +0200 Subject: [PATCH 20/24] fix linters --- .rubocop-disabled.yml | 11 +++++ .rubocop.yml | 1 + .rubocop_rails.yml | 4 ++ .rubocop_ruby.yml | 34 +++++++++----- .simplecov | 4 +- .../admin/needs_admin_snippets.rb | 2 +- .../needs_pdf_document.rb | 13 ++++-- .../documents_controller.rb | 4 +- .../documents_helper.rb | 1 + .../decidim_participatory_documents.js | 2 + .../skip_cookie_warning.js | 19 ++++++++ .../admin/documents/edit_pdf.html.erb | 4 +- .../documents/index.html.erb | 7 ++- config/locales/en.yml | 1 + ...dim_participatory_documents_suggestions.rb | 2 +- ...articipatory_documents_suggestion_notes.rb | 2 +- ...ipatory_documents_valuation_assignments.rb | 2 +- ...cidim_participatory_documents_documents.rb | 3 +- ...m_participatory_documents_box_positions.rb | 2 + decidim-participatory_documents.gemspec | 1 + .../participatory_documents/component.rb | 44 +++++++++---------- .../assign_suggestion_to_valuator_spec.rb | 2 +- .../section_suggestions_controller_spec.rb | 4 +- .../suggestion_form_spec.rb | 8 ++-- spec/i18n_spec.rb | 2 +- .../valuation_assignment_spec.rb | 2 +- .../serializers/suggestion_serialiser_spec.rb | 4 +- .../admin/admin_filters_suggestions_spec.rb | 2 +- .../admin/index_suggestion_notes_spec.rb | 2 +- .../user_interacts_with_pdf_viewer_spec.rb | 8 ++-- 30 files changed, 130 insertions(+), 67 deletions(-) create mode 100644 .rubocop-disabled.yml create mode 100644 app/packs/src/decidim/participatory_documents/skip_cookie_warning.js diff --git a/.rubocop-disabled.yml b/.rubocop-disabled.yml new file mode 100644 index 00000000..de7949f8 --- /dev/null +++ b/.rubocop-disabled.yml @@ -0,0 +1,11 @@ +Style/OpenStructUse: + Enabled: false + +Gemspec/RequireMFA: + Enabled: false + +Naming/MemoizedInstanceVariableName: + Enabled: false + +RSpec/VerifiedDoubleReference: + Enabled: false diff --git a/.rubocop.yml b/.rubocop.yml index 870c0b9f..0975cd3a 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,3 +1,4 @@ inherit_from: - .rubocop_ruby.yml - .rubocop_rails.yml + - .rubocop-disabled.yml diff --git a/.rubocop_rails.yml b/.rubocop_rails.yml index 0cf3b441..3f9d1ccc 100644 --- a/.rubocop_rails.yml +++ b/.rubocop_rails.yml @@ -59,6 +59,7 @@ Rails/Output: - lib/**/*.rb Exclude: - db/seeds.rb + Rails/OutputSafety: Enabled: false @@ -85,3 +86,6 @@ Rails/SkipsModelValidations: Rails/Validation: Include: - app/models/**/*.rb + +Rails/CompactBlank: + Enabled: false diff --git a/.rubocop_ruby.yml b/.rubocop_ruby.yml index 59330388..657b0234 100644 --- a/.rubocop_ruby.yml +++ b/.rubocop_ruby.yml @@ -13,12 +13,13 @@ AllCops: - "**/Gemfile" - "**/Rakefile" Exclude: + - "**/node_modules/**/*" - "**/vendor/**/*" - "development_app/**/*" + - "decidim_app-design/node_modules/**/*" - "spec/decidim_dummy_app/**/*" - "node_modules/**/*" - - "db/migrate/*" - - "db/schema.rb" + - "decidim-initiatives/lib/gem_overrides/origami/date.rb" # Default formatter will be used if no -f/--format option is given. DefaultFormatter: progress # Cop names are not displayed in offense messages by default. Change behavior @@ -69,12 +70,12 @@ AllCops: # If a value is specified for TargetRubyVersion then it is used. # Else if .ruby-version exists and it contains an MRI version it is used. # Otherwise we fallback to the oldest officially supported Ruby version (2.0). - TargetRubyVersion: 2.7 + TargetRubyVersion: 3.0 - RSpec: - Patterns: - - "(?:^|/)spec/" - - "(?:^|/)test/" +# RSpec: +# Patterns: +# - "(?:^|/)spec/" +# - "(?:^|/)test/" # Indent private/protected/public as deep as method definitions Layout/AccessModifierIndentation: @@ -178,6 +179,15 @@ Layout/ParameterAlignment: # But it can be overridden by setting this parameter IndentationWidth: ~ +Style/ArrayCoercion: + Description: >- + Use Array() instead of explicit Array check or [*var], when dealing + with a variable you want to treat as an Array, but you're not certain it's an array. + StyleGuide: '#array-coercion' + Safe: false + Enabled: false + VersionAdded: '0.88' + Style/AndOr: # Whether `and` and `or` are banned only in conditionals (conditionals) # or completely (always). @@ -453,6 +463,7 @@ Naming/FileName: - "**/Gemfile" - "**/Rakefile" - "**/*.gemspec" + - "decidim-dev/lib/decidim-dev.rb" # When true, requires that each source file should define a class or module # with a name which matches the file name (converted to ... case). # It further expects it to be nested inside modules which match the names @@ -1220,7 +1231,7 @@ RSpec/ContextWording: RSpec/DescribeClass: Exclude: - spec/gemfiles_spec.rb - - spec/js_bundles_spec.rb + - spec/webpacker_spec.rb - spec/i18n_spec.rb - "**/*/spec/**/*_badge_spec.rb" - decidim-core/spec/lib/global_engines_spec.rb @@ -1250,6 +1261,8 @@ RSpec/MultipleExpectations: RSpec/MultipleMemoizedHelpers: Max: 35 + Exclude: + - decidim-assemblies/spec/forms/assembly_form_spec.rb RSpec/NestedGroups: Max: 7 @@ -1258,10 +1271,11 @@ RSpec/NamedSubject: Enabled: false RSpec/RepeatedExampleGroupDescription: - Enabled: false + Enabled: true RSpec/RepeatedExampleGroupBody: - Enabled: false + Enabled: true + RSpec/VerifiedDoubles: Enabled: false diff --git a/.simplecov b/.simplecov index a58e5c4f..2e8bb475 100644 --- a/.simplecov +++ b/.simplecov @@ -1,13 +1,13 @@ # frozen_string_literal: true SimpleCov.start do - root ENV["ENGINE_ROOT"] + root ENV.fetch("ENGINE_ROOT", nil) add_filter "lib/decidim/participatory_documents/version.rb" add_filter "lib/decidim/participatory_documents/component.rb" add_filter "/spec" end -SimpleCov.command_name ENV["COMMAND_NAME"] || File.basename(Dir.pwd) +SimpleCov.command_name ENV.fetch("COMMAND_NAME", nil) || File.basename(Dir.pwd) SimpleCov.merge_timeout 1800 diff --git a/app/controllers/concerns/decidim/participatory_documents/admin/needs_admin_snippets.rb b/app/controllers/concerns/decidim/participatory_documents/admin/needs_admin_snippets.rb index 3d6e83c9..6cc7fafc 100644 --- a/app/controllers/concerns/decidim/participatory_documents/admin/needs_admin_snippets.rb +++ b/app/controllers/concerns/decidim/participatory_documents/admin/needs_admin_snippets.rb @@ -16,7 +16,7 @@ def add_snippets return unless respond_to?(:snippets) snippets.add(:head, helpers.stylesheet_pack_tag("decidim_participatory_documents_admin")) - snippets.add(:head, helpers.javascript_pack_tag("decidim_participatory_documents_admin")) + snippets.add(:foot, helpers.javascript_pack_tag("decidim_participatory_documents_admin")) end end end diff --git a/app/controllers/concerns/decidim/participatory_documents/needs_pdf_document.rb b/app/controllers/concerns/decidim/participatory_documents/needs_pdf_document.rb index 0c3ddbd3..84021d8d 100644 --- a/app/controllers/concerns/decidim/participatory_documents/needs_pdf_document.rb +++ b/app/controllers/concerns/decidim/participatory_documents/needs_pdf_document.rb @@ -11,6 +11,13 @@ module NeedsPdfDocument protected + def add_iframe_snippets + return unless respond_to?(:snippets) + + snippets.add(:head, helpers.stylesheet_pack_tag("decidim_participatory_documents")) + snippets.add(:foot, helpers.javascript_pack_tag("decidim_participatory_documents")) + end + def document @document ||= Decidim::ParticipatoryDocuments::Document.find_by(component: current_component) end @@ -78,12 +85,12 @@ def rgb_to_hsl(red, green, blue) if c_max == red ((green - blue) / delta) % 6 elsif c_max == green - (blue - red) / delta + 2 + ((blue - red) / delta) + 2 else - (red - green) / delta + 4 + ((red - green) / delta) + 4 end - s = delta / (1 - (2 * l - 1).abs) + s = delta / (1 - ((2 * l) - 1).abs) end h = (h * 60).round diff --git a/app/controllers/decidim/participatory_documents/documents_controller.rb b/app/controllers/decidim/participatory_documents/documents_controller.rb index 0fec0abf..ab4274c4 100644 --- a/app/controllers/decidim/participatory_documents/documents_controller.rb +++ b/app/controllers/decidim/participatory_documents/documents_controller.rb @@ -6,7 +6,9 @@ class DocumentsController < Decidim::ParticipatoryDocuments::ApplicationControll include NeedsPdfDocument helper Decidim::LayoutHelper - def index; end + def index + add_iframe_snippets + end def pdf_viewer render layout: false diff --git a/app/helpers/decidim/participatory_documents/documents_helper.rb b/app/helpers/decidim/participatory_documents/documents_helper.rb index 1bdc406b..3e652fc6 100644 --- a/app/helpers/decidim/participatory_documents/documents_helper.rb +++ b/app/helpers/decidim/participatory_documents/documents_helper.rb @@ -32,6 +32,7 @@ def finish_publish_btn def preview_mode? return if document.published? + return if current_user.blank? current_component.manifest.admin_engine && user_role_config.component_is_accessible?(current_component.manifest_name) end diff --git a/app/packs/entrypoints/decidim_participatory_documents.js b/app/packs/entrypoints/decidim_participatory_documents.js index 09343ca1..71e96ea0 100644 --- a/app/packs/entrypoints/decidim_participatory_documents.js +++ b/app/packs/entrypoints/decidim_participatory_documents.js @@ -2,3 +2,5 @@ require.context("../images", true) import "entrypoints/decidim_participatory_documents.scss"; + +import "../src/decidim/participatory_documents/skip_cookie_warning.js" diff --git a/app/packs/src/decidim/participatory_documents/skip_cookie_warning.js b/app/packs/src/decidim/participatory_documents/skip_cookie_warning.js new file mode 100644 index 00000000..c4091b86 --- /dev/null +++ b/app/packs/src/decidim/participatory_documents/skip_cookie_warning.js @@ -0,0 +1,19 @@ +/* eslint-disable no-plusplus */ + +document.addEventListener("DOMContentLoaded", () => { + const original = document.getElementById("pdf-iframe"); + const iframe = document.createElement("iframe"); + + // Copy the children + while (original.firstChild) { + iframe.appendChild(original.firstChild); + } + + // Copy the attributes + for (let index = original.attributes.length - 1; index >= 0; --index) { + iframe.attributes.setNamedItem(original.attributes[index].cloneNode()); + } + + // Replace it + original.parentNode.replaceChild(iframe, original); +}); diff --git a/app/views/decidim/participatory_documents/admin/documents/edit_pdf.html.erb b/app/views/decidim/participatory_documents/admin/documents/edit_pdf.html.erb index ef0d784d..a9b4b7ec 100644 --- a/app/views/decidim/participatory_documents/admin/documents/edit_pdf.html.erb +++ b/app/views/decidim/participatory_documents/admin/documents/edit_pdf.html.erb @@ -6,8 +6,8 @@
-
diff --git a/app/views/decidim/participatory_documents/documents/index.html.erb b/app/views/decidim/participatory_documents/documents/index.html.erb index a41d7d33..f54afab2 100644 --- a/app/views/decidim/participatory_documents/documents/index.html.erb +++ b/app/views/decidim/participatory_documents/documents/index.html.erb @@ -14,11 +14,10 @@ <% end %>
- + +

<%= t("decidim.participatory_documents.documents.not_supported") %>

+
- <%= stylesheet_pack_tag "decidim_participatory_documents" %> <% else %>

<%= t("decidim.participatory_documents.documents.missing") %>

diff --git a/config/locales/en.yml b/config/locales/en.yml index 3891b21b..f6185620 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -212,6 +212,7 @@ en: upload_file: Attach a document documents: missing: There is no document uploaded yet + not_supported: This page requires JavaScript to be enabled! preview_title: Preview publish_description: 'Admin options: you are previewing the participatory sections of the document' diff --git a/db/migrate/20221115233023_create_decidim_participatory_documents_suggestions.rb b/db/migrate/20221115233023_create_decidim_participatory_documents_suggestions.rb index 1a292404..6b17af01 100644 --- a/db/migrate/20221115233023_create_decidim_participatory_documents_suggestions.rb +++ b/db/migrate/20221115233023_create_decidim_participatory_documents_suggestions.rb @@ -14,4 +14,4 @@ def change t.timestamps end end -end \ No newline at end of file +end diff --git a/db/migrate/20221115233024_create_decidim_participatory_documents_suggestion_notes.rb b/db/migrate/20221115233024_create_decidim_participatory_documents_suggestion_notes.rb index a6c06e9f..b0e1ef1e 100644 --- a/db/migrate/20221115233024_create_decidim_participatory_documents_suggestion_notes.rb +++ b/db/migrate/20221115233024_create_decidim_participatory_documents_suggestion_notes.rb @@ -12,4 +12,4 @@ def change add_column :decidim_participatory_documents_suggestions, :suggestion_notes_count, :integer, null: false, default: 0 add_index :decidim_participatory_documents_suggestion_notes, :created_at, name: :index_decidim_pd_suggestion_notes_on_created_at end -end \ No newline at end of file +end diff --git a/db/migrate/20221115233024_create_decidim_participatory_documents_valuation_assignments.rb b/db/migrate/20221115233024_create_decidim_participatory_documents_valuation_assignments.rb index 1d64a25a..0dc7666c 100644 --- a/db/migrate/20221115233024_create_decidim_participatory_documents_valuation_assignments.rb +++ b/db/migrate/20221115233024_create_decidim_participatory_documents_valuation_assignments.rb @@ -9,4 +9,4 @@ def change t.timestamps end end -end \ No newline at end of file +end diff --git a/db/migrate/20230616100340_add_published_at_to_decidim_participatory_documents_documents.rb b/db/migrate/20230616100340_add_published_at_to_decidim_participatory_documents_documents.rb index 4404063e..8e20f73c 100644 --- a/db/migrate/20230616100340_add_published_at_to_decidim_participatory_documents_documents.rb +++ b/db/migrate/20230616100340_add_published_at_to_decidim_participatory_documents_documents.rb @@ -2,6 +2,7 @@ class AddPublishedAtToDecidimParticipatoryDocumentsDocuments < ActiveRecord::Migration[6.0] def change - add_column :decidim_participatory_documents_documents, :published_at, :datetime, index: true + add_column :decidim_participatory_documents_documents, :published_at, :datetime + add_index :decidim_participatory_documents_documents, :published_at end end diff --git a/db/migrate/20230622081831_add_decidim_participatory_documents_box_positions.rb b/db/migrate/20230622081831_add_decidim_participatory_documents_box_positions.rb index 48577425..0efe2641 100644 --- a/db/migrate/20230622081831_add_decidim_participatory_documents_box_positions.rb +++ b/db/migrate/20230622081831_add_decidim_participatory_documents_box_positions.rb @@ -18,6 +18,7 @@ class Annotation < ApplicationRecord belongs_to :section end + # rubocop:disable Rails/SkipsModelValidations: def change add_column :decidim_participatory_documents_annotations, :position, :integer, null: false, default: 0 add_index :decidim_participatory_documents_annotations, :position @@ -32,4 +33,5 @@ def change annotation.update_column(:position, annotation.section.document.annotations.where("decidim_participatory_documents_annotations.id < ?", annotation.id).count + 1) end end + # rubocop:enable Rails/SkipsModelValidations: end diff --git a/decidim-participatory_documents.gemspec b/decidim-participatory_documents.gemspec index 975e7a46..bbde2803 100644 --- a/decidim-participatory_documents.gemspec +++ b/decidim-participatory_documents.gemspec @@ -26,4 +26,5 @@ Gem::Specification.new do |spec| spec.add_dependency "decidim-core", Decidim::ParticipatoryDocuments::COMPAT_DECIDIM_VERSION spec.add_development_dependency "decidim-dev", Decidim::ParticipatoryDocuments::COMPAT_DECIDIM_VERSION + spec.metadata["rubygems_mfa_required"] = "true" end diff --git a/lib/decidim/participatory_documents/component.rb b/lib/decidim/participatory_documents/component.rb index 3030828e..a91f4494 100644 --- a/lib/decidim/participatory_documents/component.rb +++ b/lib/decidim/participatory_documents/component.rb @@ -27,8 +27,8 @@ settings.attribute :min_suggestion_length, type: :integer, default: Decidim::ParticipatoryDocuments.min_suggestion_length end - component.settings(:step) do |settings| - end + # component.settings(:step) do |settings| + # end component.exports :suggestions do |exports| exports.collection do |component_instance| @@ -132,50 +132,50 @@ page_number: 1, section: group1, rect: { - "left": 25.5, - "top": 22.123, - "width": 30.1, - "height": 10.2 + left: 25.5, + top: 22.123, + width: 30.1, + height: 10.2 } }, { page_number: 1, section: group2, rect: { - "left": 5.5, - "top": 2.123, - "width": 10.1, - "height": 10.2 + left: 5.5, + top: 2.123, + width: 10.1, + height: 10.2 } }, { page_number: 1, section: group2, rect: { - "left": 15.5, - "top": 12.123, - "width": 10.1, - "height": 10.2 + left: 15.5, + top: 12.123, + width: 10.1, + height: 10.2 } }, { page_number: 1, section: group3, rect: { - "left": 75.5, - "top": 82.123, - "width": 10.1, - "height": 10.2 + left: 75.5, + top: 82.123, + width: 10.1, + height: 10.2 } }, { page_number: 2, section: group3, rect: { - "left": 15.5, - "top": 12.123, - "width": 10.1, - "height": 10.2 + left: 15.5, + top: 12.123, + width: 10.1, + height: 10.2 } } ] diff --git a/spec/commands/decidim/participatory_documents/admin/assign_suggestion_to_valuator_spec.rb b/spec/commands/decidim/participatory_documents/admin/assign_suggestion_to_valuator_spec.rb index 52d0d8a3..9a9a66d2 100644 --- a/spec/commands/decidim/participatory_documents/admin/assign_suggestion_to_valuator_spec.rb +++ b/spec/commands/decidim/participatory_documents/admin/assign_suggestion_to_valuator_spec.rb @@ -33,7 +33,7 @@ module Admin context "when the form is valid" do it "successfuly ignore the existing records" do create :suggestion_valuation_assignment, suggestion: suggestion, valuator_role: valuator_role - expect { subject.call }.to change(Decidim::ParticipatoryDocuments::ValuationAssignment, :count).by(0) + expect { subject.call }.not_to change(Decidim::ParticipatoryDocuments::ValuationAssignment, :count) expect { subject.call }.to broadcast(:ok) end diff --git a/spec/controllers/decidim/participatory_documents/admin/section_suggestions_controller_spec.rb b/spec/controllers/decidim/participatory_documents/admin/section_suggestions_controller_spec.rb index 07f9c9db..bc3cfdd5 100644 --- a/spec/controllers/decidim/participatory_documents/admin/section_suggestions_controller_spec.rb +++ b/spec/controllers/decidim/participatory_documents/admin/section_suggestions_controller_spec.rb @@ -27,8 +27,8 @@ module Admin let(:params) do { - "document_id": document.id, - "id": section.id, + document_id: document.id, + id: section.id, "title_en" => "Title" } end diff --git a/spec/forms/decidim/participatory_documents/suggestion_form_spec.rb b/spec/forms/decidim/participatory_documents/suggestion_form_spec.rb index 7d991c28..4d8d6087 100644 --- a/spec/forms/decidim/participatory_documents/suggestion_form_spec.rb +++ b/spec/forms/decidim/participatory_documents/suggestion_form_spec.rb @@ -28,13 +28,11 @@ module ParticipatoryDocuments shared_examples "validate error message" do |error_key, params| it "shows the correct error message" do form.validate - expect(form.errors[:body]).to include(I18n.t("activemodel.errors.models.suggestion.attributes.#{error_key}", params)) + expect(form.errors[:body]).to include(I18n.t("activemodel.errors.models.suggestion.attributes.#{error_key}", **params)) end end - it "is valid with valid attributes" do - expect(form).to be_valid - end + it { is_expected.to be_valid } context "when no body" do let(:body) { nil } @@ -113,7 +111,7 @@ module ParticipatoryDocuments end end - context "when :min_suggestion_length is modified in the component settings" do + context "when min length is enough" do let(:body) { "Hi" } let(:component) { double(:participatory_documents_component, settings: settings) } let(:settings) { double(:settings, min_suggestion_length: 3, max_suggestion_length: 100) } diff --git a/spec/i18n_spec.rb b/spec/i18n_spec.rb index 1e67a27e..c74b8ce0 100644 --- a/spec/i18n_spec.rb +++ b/spec/i18n_spec.rb @@ -7,7 +7,7 @@ ENV["ENFORCED_LOCALES"].presence || "en" end - let(:i18n) { I18n::Tasks::BaseTask.new({ locales: locales.split(",") }) } + let(:i18n) { I18n::Tasks::BaseTask.new(locales: locales.split(",")) } let(:missing_keys) { i18n.missing_keys } let(:unused_keys) { i18n.unused_keys } let(:non_normalized_paths) { i18n.non_normalized_paths } diff --git a/spec/models/decidim/participatory_documents/valuation_assignment_spec.rb b/spec/models/decidim/participatory_documents/valuation_assignment_spec.rb index 88c638fd..9f2ad967 100644 --- a/spec/models/decidim/participatory_documents/valuation_assignment_spec.rb +++ b/spec/models/decidim/participatory_documents/valuation_assignment_spec.rb @@ -21,7 +21,7 @@ module ParticipatoryDocuments it "destroys valuation assignments when participatory_process_user_role is destroyed" do expect(Decidim::ParticipatoryDocuments::ValuationAssignment.count).to eq(1) - expect { valuator_role.destroy }.to change { Decidim::ParticipatoryDocuments::ValuationAssignment.count }.by(-1) + expect { valuator_role.destroy }.to change(Decidim::ParticipatoryDocuments::ValuationAssignment, :count).by(-1) end end end diff --git a/spec/serializers/suggestion_serialiser_spec.rb b/spec/serializers/suggestion_serialiser_spec.rb index 7608ff77..2ff5eb52 100644 --- a/spec/serializers/suggestion_serialiser_spec.rb +++ b/spec/serializers/suggestion_serialiser_spec.rb @@ -8,7 +8,7 @@ module Decidim include Decidim::ParticipatoryDocuments::Admin::SuggestionHelper include ActionView::Helpers::TextHelper - let(:subject) { described_class.new(suggestion) } + subject { described_class.new(suggestion) } let(:suggestion) { create(:participatory_documents_suggestion, :with_answer) } let(:serialized) { subject.serialize } @@ -27,7 +27,7 @@ module Decidim Decidim::ParticipatoryDocuments.max_export_text_length = 10 end - it "returns an answer that is 10 characters long " do + it "returns an answer that is 10 characters long" do expect(serialized).to include(answer: truncate(translated_attribute(suggestion.answer), length: 10)) expect(serialized).to include(body: truncate(translated_attribute(suggestion.body), length: 10)) end diff --git a/spec/system/admin/admin_filters_suggestions_spec.rb b/spec/system/admin/admin_filters_suggestions_spec.rb index bdf5aff5..e85ec0ff 100644 --- a/spec/system/admin/admin_filters_suggestions_spec.rb +++ b/spec/system/admin/admin_filters_suggestions_spec.rb @@ -60,7 +60,7 @@ def suggestion_without_state(state) before { visit router.document_suggestions_path(document) } it "can be searched by title" do - search_by_text(suggestion2_body.split(" ").first(2).join(" ")) + search_by_text(suggestion2_body.split.first(2).join(" ")) expect(page).to have_content(suggestion2.id) end diff --git a/spec/system/admin/index_suggestion_notes_spec.rb b/spec/system/admin/index_suggestion_notes_spec.rb index e700954c..2c13ddb8 100644 --- a/spec/system/admin/index_suggestion_notes_spec.rb +++ b/spec/system/admin/index_suggestion_notes_spec.rb @@ -38,7 +38,7 @@ end context "when the form has a text inside body" do - it "creates a suggestion note ", :slow do + it "creates a suggestion note", :slow do within ".new_suggestion_note" do fill_in :suggestion_note_body, with: body diff --git a/spec/system/user_interacts_with_pdf_viewer_spec.rb b/spec/system/user_interacts_with_pdf_viewer_spec.rb index 057bb0cc..4910d1d3 100644 --- a/spec/system/user_interacts_with_pdf_viewer_spec.rb +++ b/spec/system/user_interacts_with_pdf_viewer_spec.rb @@ -46,7 +46,7 @@ end end - context "when the answer is published " do + context "when the answer is published" do let(:published) { true } it "does not render admin note" do @@ -68,7 +68,7 @@ end end - context "when the answer is published " do + context "when the answer is published" do let(:published) { true } it "renders admin note" do @@ -112,7 +112,7 @@ end end - context "when the answer is NOT draft " do + context "when the answer is NOT draft" do let(:published) { true } it "renders admin note" do @@ -134,7 +134,7 @@ end end - context "when the answer is NOT draft " do + context "when the answer is NOT draft" do let(:published) { true } it "renders admin note" do From 057ee06b6221ad736b7e253519d24407ccff44c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20Verg=C3=A9s?= Date: Fri, 7 Jul 2023 20:19:43 +0200 Subject: [PATCH 21/24] fix some tests --- .../needs_pdf_document.rb | 2 +- .../admin/documents_helper.rb | 10 +++--- .../skip_cookie_warning.js | 15 ++------- .../admin/documents/_title.html.erb | 2 +- .../admin/suggestions/index.html.erb | 2 +- config/locales/en.yml | 3 +- ...in_manages_participatory_documents_spec.rb | 33 ++++++++++--------- 7 files changed, 30 insertions(+), 37 deletions(-) diff --git a/app/controllers/concerns/decidim/participatory_documents/needs_pdf_document.rb b/app/controllers/concerns/decidim/participatory_documents/needs_pdf_document.rb index 84021d8d..efc82bd0 100644 --- a/app/controllers/concerns/decidim/participatory_documents/needs_pdf_document.rb +++ b/app/controllers/concerns/decidim/participatory_documents/needs_pdf_document.rb @@ -47,7 +47,7 @@ def pdf_custom_style css = <<~CSS