diff --git a/app/assets/javascripts/legislation_annotatable.js.coffee b/app/assets/javascripts/legislation_annotatable.js.coffee index f1df2927a..cc238835e 100644 --- a/app/assets/javascripts/legislation_annotatable.js.coffee +++ b/app/assets/javascripts/legislation_annotatable.js.coffee @@ -2,24 +2,100 @@ _t = (key) -> new Gettext().gettext(key) App.LegislationAnnotatable = + makeEditableAndHighlight: (colour) -> + sel = window.getSelection() + if sel.rangeCount and sel.getRangeAt + range = sel.getRangeAt(0) + document.designMode = 'on' + if range + sel.removeAllRanges() + sel.addRange range + # Use HiliteColor since some browsers apply BackColor to the whole block + if !document.execCommand('HiliteColor', false, colour) + document.execCommand 'BackColor', false, colour + document.designMode = 'off' + return + + highlight: (colour) -> + if window.getSelection + # IE9 and non-IE + try + if !document.execCommand('BackColor', false, colour) + App.LegislationAnnotatable.makeEditableAndHighlight colour + catch ex + App.LegislationAnnotatable.makeEditableAndHighlight colour + else if document.selection and document.selection.createRange + # IE <= 8 case + range = document.selection.createRange() + range.execCommand 'BackColor', false, colour + return + + remove_highlight: -> + $('[data-legislation-draft-version-id] span[style]').replaceWith(-> + return $(this).contents() + ) + return + renderAnnotationComments: (event) -> - $('.comment-box').offset(top: event.offset) + $('#comments-box').css({top: event.offset - $('.calc-comments').offset().top}) $.ajax method: "GET" url: event.annotation_url + "/annotations/" + event.annotation_id + "/comments" dataType: 'script' + onClick: (event) -> + event.preventDefault() + event.stopPropagation() + + App.LegislationAllegations.show_comments() + $("#comments-box").show() + $.event.trigger + type: "renderLegislationAnnotation" + annotation_id: $(event.target).data("annotation-id") + annotation_url: $(event.target).closest(".legislation-annotatable").data("legislation-annotatable-base-url") + offset: $(event.target).offset()["top"] + viewerExtension: (viewer) -> viewer._onHighlightMouseover = (event) -> - App.LegislationAllegations.show_comments() - $("#comments-box").show() - $.event.trigger - type: "renderLegislationAnnotation" - annotation_id: $(event.target).data("annotation-id") - annotation_url: $(event.target).closest(".legislation-annotatable").data("legislation-annotatable-base-url") - offset: $(event.target).offset()["top"] + return + customShow: (position) -> + $(@element).html '' + # Clean comments section and open it + $('#comments-box').html '' + App.LegislationAllegations.show_comments() + $('#comments-box').show() + annotation_url = $('[data-legislation-annotatable-base-url]').data('legislation-annotatable-base-url') + $.ajax( + method: 'GET' + url: annotation_url + '/annotations/new' + dataType: 'script').done (-> + $('#new_legislation_annotation #legislation_annotation_quote').val(@annotation.quote) + $('#new_legislation_annotation #legislation_annotation_ranges').val(JSON.stringify(@annotation.ranges)) + $('#comments-box').css({top: position.top - $('.calc-comments').offset().top}) + + App.LegislationAnnotatable.highlight('#7fff9a') + $('#comments-box textarea').focus() + + $("#new_legislation_annotation").on("ajax:complete", (e, data, status, xhr) -> + if data.status == 200 + App.LegislationAnnotatable.remove_highlight() + $("#comments-box").html("").hide() + $.ajax + method: "GET" + url: annotation_url + "/annotations/" + data.responseJSON.id + "/comments" + dataType: 'script' + else + $(e.target).find('label').addClass('error') + $('' + data.responseJSON[0] + '').insertAfter($(e.target).find('textarea')) + return true + ) + return + ).bind(this) + + editorExtension: (editor) -> + editor.show = App.LegislationAnnotatable.customShow scrollToAnchor: -> annotationsLoaded: (annotations) -> @@ -35,20 +111,17 @@ App.LegislationAnnotatable = offset: el.offset()["top"] initialize: -> - $(document).on("renderLegislationAnnotation", App.LegislationAnnotatable.renderAnnotationComments) + $(document).off("renderLegislationAnnotation").on("renderLegislationAnnotation", App.LegislationAnnotatable.renderAnnotationComments) + $(document).off('click', '[data-annotation-id]').on('click', '[data-annotation-id]', App.LegislationAnnotatable.onClick) + $(document).off('click', '[data-cancel-annotation]').on('click', '[data-cancel-annotation]', (e) -> + e.preventDefault() + $('#comments-box').html('') + $('#comments-box').hide() + App.LegislationAnnotatable.remove_highlight() + return + ) current_user_id = $('html').data('current-user-id') - if current_user_id == "" - annotator.ui.editor.Editor.template = [ - '
', - '
', - ' ' + _t('Unregistered'), - '
', - ' ' + _t('Cancel') + '', - '
', - '
', - '
' - ].join('\n') $(".legislation-annotatable").each -> $this = $(this) @@ -62,7 +135,11 @@ App.LegislationAnnotatable = ann["legislation_draft_version_id"] = ann_id ann.permissions = ann.permissions || {} ann.permissions.admin = [] - .include(annotator.ui.main, { element: this, viewerExtensions: [App.LegislationAnnotatable.viewerExtension] }) + .include(annotator.ui.main, { + element: this, + viewerExtensions: [App.LegislationAnnotatable.viewerExtension], + editorExtensions: [App.LegislationAnnotatable.editorExtension] + }) .include(App.LegislationAnnotatable.scrollToAnchor) .include(annotator.storage.http, { prefix: base_url, urls: { search: "/annotations/search" } }) diff --git a/app/assets/stylesheets/legislation_process.scss b/app/assets/stylesheets/legislation_process.scss index 6de923542..50dfe7161 100644 --- a/app/assets/stylesheets/legislation_process.scss +++ b/app/assets/stylesheets/legislation_process.scss @@ -877,7 +877,6 @@ $epigraph-font-size: rem-calc(15); textarea { border-radius: 0; box-shadow: none; - border-top: none; border-bottom: 1px solid #D0D0D0; border-right: 1px solid #D0D0D0; border-left: 1px solid #D0D0D0; diff --git a/app/controllers/legislation/annotations_controller.rb b/app/controllers/legislation/annotations_controller.rb index f1c4e4401..6f5069763 100644 --- a/app/controllers/legislation/annotations_controller.rb +++ b/app/controllers/legislation/annotations_controller.rb @@ -2,6 +2,7 @@ class Legislation::AnnotationsController < ApplicationController skip_before_action :verify_authenticity_token before_action :authenticate_user!, only: [:create] + before_action :convert_ranges_parameters, only: [:create] load_and_authorize_resource :process load_and_authorize_resource :draft_version, through: :process @@ -30,7 +31,7 @@ class Legislation::AnnotationsController < ApplicationController track_event render json: @annotation.to_json else - render json: {}, status: :unprocessable_entity + render json: @annotation.errors.full_messages, status: :unprocessable_entity end end @@ -44,11 +45,17 @@ class Legislation::AnnotationsController < ApplicationController @annotation = Legislation::Annotation.find(params[:annotation_id]) end + def new + respond_to do |format| + format.js + end + end + private def annotation_params params - .require(:annotation) + .require(:legislation_annotation) .permit(:quote, :text, ranges: [:start, :startOffset, :end, :endOffset]) end @@ -58,4 +65,11 @@ class Legislation::AnnotationsController < ApplicationController "legislation_draft_version_id": @draft_version.id end + def convert_ranges_parameters + if params[:legislation_annotation] && params[:legislation_annotation][:ranges] && params[:legislation_annotation][:ranges].is_a?(String) + params[:legislation_annotation][:ranges] = JSON.parse(params[:legislation_annotation][:ranges]) + end + rescue JSON::ParserError + end + end diff --git a/app/views/legislation/annotations/_form.html.erb b/app/views/legislation/annotations/_form.html.erb new file mode 100644 index 000000000..a757b4612 --- /dev/null +++ b/app/views/legislation/annotations/_form.html.erb @@ -0,0 +1,36 @@ +
+ +
<%= t('legislation.annotations.comments.comments_count', count: 0) %>
+ <%= link_to '#' do %> + + <% end %> +
+ +
+
+ <% if !@process.open_phase?(:allegations) %> +
+ <%= t("legislation.annotations.form.phase_not_open") %> +
+ <% elsif user_signed_in? %> + <%= form_for Legislation::Annotation.new, url: legislation_process_draft_version_annotations_path(@process, @draft_version), remote: true do |f| %> + <%= f.text_area :text %> + +
+ <%= t('legislation.annotations.comments.cancel') %> + <%= f.submit t('legislation.annotations.comments.publish_comment'), class: 'button strong publish-comment' %> +
+ + <%= f.hidden_field :quote %> + <%= f.hidden_field :ranges %> + <% end %> + <% else %> +
+ <%= t("legislation.annotations.form.login_to_comment", + signin: link_to(t("legislation.annotations.form.signin"), new_user_session_path), + signup: link_to(t("legislation.annotations.form.signup"), new_user_registration_path)).html_safe %> +
+ <% end %> +
+
+ diff --git a/app/views/legislation/annotations/comments.js.erb b/app/views/legislation/annotations/comments.js.erb index 6ee83560e..75d8f35a0 100644 --- a/app/views/legislation/annotations/comments.js.erb +++ b/app/views/legislation/annotations/comments.js.erb @@ -1,2 +1,2 @@ -$("#comments-box").html("<%= j render('comments_box', annotation: @annotation) %>"); +$("#comments-box").html("<%= j render('comments_box', annotation: @annotation) %>").show(); diff --git a/app/views/legislation/annotations/new.js.erb b/app/views/legislation/annotations/new.js.erb new file mode 100644 index 000000000..9b719814c --- /dev/null +++ b/app/views/legislation/annotations/new.js.erb @@ -0,0 +1,2 @@ +$("#comments-box").html("<%= j render('form') %>"); + diff --git a/app/views/legislation/draft_versions/show.html.erb b/app/views/legislation/draft_versions/show.html.erb index d89926929..615a86fc8 100644 --- a/app/views/legislation/draft_versions/show.html.erb +++ b/app/views/legislation/draft_versions/show.html.erb @@ -54,6 +54,7 @@
<% end %> <%= @draft_version.body_html.html_safe %> diff --git a/config/locales/activerecord.en.yml b/config/locales/activerecord.en.yml index e873abc26..51ee2190b 100644 --- a/config/locales/activerecord.en.yml +++ b/config/locales/activerecord.en.yml @@ -139,10 +139,12 @@ en: status: Status final_version: Final version legislation/question: - title: "Title" + title: Title question_options: Options legislation/question_option: - value: "Value" + value: Value + legislation/annotation: + text: Comment errors: models: user: diff --git a/config/locales/activerecord.es.yml b/config/locales/activerecord.es.yml index e8f2a42eb..aa7e05875 100644 --- a/config/locales/activerecord.es.yml +++ b/config/locales/activerecord.es.yml @@ -134,10 +134,12 @@ es: status: Estado final_version: Versión final legislation/question: - title: "Título" + title: Título question_options: Respuestas legislation/question_option: - value: "Valor" + value: Valor + legislation/annotation: + text: Comentario errors: models: user: diff --git a/config/locales/en.yml b/config/locales/en.yml index 760fa67c8..d65c3b007 100755 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -235,6 +235,13 @@ en: replies_count: one: "%{count} reply" other: "%{count} replies" + cancel: Cancel + publish_comment: Publish Comment + form: + phase_not_open: This phase is not open + login_to_comment: You must %{signin} or %{signup} to leave a comment. + signin: Sign in + signup: Sign up index: title: Comments comments_about: Comments about diff --git a/config/locales/es.yml b/config/locales/es.yml index 81716214b..708a74ed2 100755 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -235,6 +235,13 @@ es: replies_count: one: "%{count} respuesta" other: "%{count} respuestas" + cancel: Cancelar + publish_comment: Publicar Comentario + form: + phase_not_open: Esta fase del proceso no está abierta + login_to_comment: Necesitas %{signin} o %{signup} para comentar. + signin: iniciar sesión + signup: registrarte index: title: Comentarios see_in_context: Ver en contexto diff --git a/spec/controllers/legislation/annotations_controller_spec.rb b/spec/controllers/legislation/annotations_controller_spec.rb index 2713fc273..4ffd91357 100644 --- a/spec/controllers/legislation/annotations_controller_spec.rb +++ b/spec/controllers/legislation/annotations_controller_spec.rb @@ -15,7 +15,7 @@ describe Legislation::AnnotationsController do post :create, process_id: @process.id, draft_version_id: @draft_version.id, - annotation: { + legislation_annotation: { "quote"=>"Ordenación Territorial", "ranges"=>[{"start"=>"/p[1]", "startOffset"=>1, "end"=>"/p[1]", "endOffset"=>3}], "text": "una anotacion" @@ -29,7 +29,7 @@ describe Legislation::AnnotationsController do post :create, process_id: @process.id, draft_version_id: @final_version.id, - annotation: { + legislation_annotation: { "quote"=>"Ordenación Territorial", "ranges"=>[{"start"=>"/p[1]", "startOffset"=>1, "end"=>"/p[1]", "endOffset"=>3}], "text": "una anotacion" @@ -44,7 +44,7 @@ describe Legislation::AnnotationsController do expect do xhr :post, :create, process_id: @process.id, draft_version_id: @draft_version.id, - annotation: { + legislation_annotation: { "quote"=>"Ordenación Territorial", "ranges"=>[{"start"=>"/p[1]", "startOffset"=>1, "end"=>"/p[1]", "endOffset"=>3}], "text": "una anotacion" @@ -59,12 +59,27 @@ describe Legislation::AnnotationsController do expect do xhr :post, :create, process_id: @process.id, draft_version_id: @draft_version.id, - annotation: { + legislation_annotation: { "quote"=>"Ordenación Territorial", "ranges"=>[{"start"=>"/p[1]", "startOffset"=>1, "end"=>"/p[1]", "endOffset"=>3}], "text": "una anotacion" } end.to_not change { @draft_version.annotations.count } end + + it 'should create an annotation by parsing parameters in JSON' do + sign_in @user + + expect do + xhr :post, :create, process_id: @process.id, + draft_version_id: @draft_version.id, + legislation_annotation: { + "quote"=>"Ordenación Territorial", + "ranges"=>[{"start"=>"/p[1]", "startOffset"=>1, "end"=>"/p[1]", "endOffset"=>3}].to_json, + "text": "una anotacion" + } + end.to change { @draft_version.annotations.count }.by(1) + end + end end diff --git a/spec/features/legislation/draft_versions_spec.rb b/spec/features/legislation/draft_versions_spec.rb index 6c39d11ce..d0f303743 100644 --- a/spec/features/legislation/draft_versions_spec.rb +++ b/spec/features/legislation/draft_versions_spec.rb @@ -135,6 +135,18 @@ feature 'Legislation Draft Versions' do let(:user) { create(:user) } background { login_as user } + scenario 'Visit as anonymous' do + logout + draft_version = create(:legislation_draft_version, :published, body: Faker::Lorem.paragraph) + + visit legislation_process_draft_version_path(draft_version.process, draft_version) + + page.find(:css, ".legislation-annotatable").double_click + page.find(:css, ".annotator-adder button").click + expect(page).to_not have_css('#legislation_annotation_text') + expect(page).to have_content "ou must Sign in or Sign up to leave a comment." + end + scenario 'Create' do draft_version = create(:legislation_draft_version, :published, body: Faker::Lorem.paragraph) @@ -142,8 +154,11 @@ feature 'Legislation Draft Versions' do page.find(:css, ".legislation-annotatable").double_click page.find(:css, ".annotator-adder button").click - fill_in 'annotator-field-0', with: 'this is my annotation' - page.find(:css, ".annotator-controls a[href='#save']").click + page.click_button "Publish Comment" + expect(page).to have_content "Comment can't be blank" + + fill_in 'legislation_annotation_text', with: 'this is my annotation' + page.click_button "Publish Comment" expect(page).to have_css ".annotator-hl" first(:css, ".annotator-hl").click @@ -167,7 +182,7 @@ feature 'Legislation Draft Versions' do first(:css, ".annotator-hl").click expect(page).to have_content "my annotation" - all(".annotator-hl")[1].trigger('mouseover') + all(".annotator-hl")[1].trigger('click') expect(page).to have_content "my other annotation" end end