diff --git a/app/components/shared/embedded_video_component.html.erb b/app/components/shared/embedded_video_component.html.erb
new file mode 100644
index 000000000..fbfff8353
--- /dev/null
+++ b/app/components/shared/embedded_video_component.html.erb
@@ -0,0 +1,5 @@
+
diff --git a/app/components/shared/embedded_video_component.rb b/app/components/shared/embedded_video_component.rb
new file mode 100644
index 000000000..9f4cdbd6a
--- /dev/null
+++ b/app/components/shared/embedded_video_component.rb
@@ -0,0 +1,59 @@
+class Shared::EmbeddedVideoComponent < ApplicationComponent
+ attr_reader :record
+
+ def initialize(record)
+ @record = record
+ end
+
+ def render?
+ record.video_url.present?
+ end
+
+ def embedded_video_code
+ if match && match[2]
+ ""
+ end
+ end
+
+ private
+
+ def link
+ record.video_url
+ end
+
+ def title
+ t("proposals.show.embed_video_title", proposal: record.title)
+ end
+
+ def server
+ if link =~ /vimeo.*/
+ "Vimeo"
+ elsif link =~ /youtu*.*/
+ "YouTube"
+ end
+ end
+
+ def regex
+ if server == "Vimeo"
+ record.class::VIMEO_REGEX
+ elsif server == "YouTube"
+ record.class::YOUTUBE_REGEX
+ end
+ end
+
+ def src
+ if server == "Vimeo"
+ "https://player.vimeo.com/video/#{match[2]}?dnt=1"
+ elsif server == "YouTube"
+ "https://www.youtube-nocookie.com/embed/#{match[2]}"
+ end
+ end
+
+ def match
+ @match ||= link.match(regex) if regex
+ end
+
+ def iframe_attributes
+ tag.attributes(src: src, style: "border:0;", allowfullscreen: true, title: title)
+ end
+end
diff --git a/app/helpers/embed_videos_helper.rb b/app/helpers/embed_videos_helper.rb
deleted file mode 100644
index 08a3179f8..000000000
--- a/app/helpers/embed_videos_helper.rb
+++ /dev/null
@@ -1,40 +0,0 @@
-module EmbedVideosHelper
- VIMEO_REGEX = /vimeo.*(staffpicks\/|channels\/|videos\/|video\/|\/)([^#\&\?]*).*/
- YOUTUBE_REGEX = /youtu.*(be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*).*/
-
- def embedded_video_code(resource)
- link = resource.video_url
- title = t("proposals.show.embed_video_title", proposal: resource.title)
- if link =~ /vimeo.*/
- server = "Vimeo"
- elsif link =~ /youtu*.*/
- server = "YouTube"
- end
-
- if server == "Vimeo"
- reg_exp = VIMEO_REGEX
- src = "https://player.vimeo.com/video/"
- elsif server == "YouTube"
- reg_exp = YOUTUBE_REGEX
- src = "https://www.youtube.com/embed/"
- end
-
- if reg_exp
- match = link.match(reg_exp)
- end
-
- if match && match[2]
- ''
- else
- ""
- end
- end
-
- def valid_video_url?
- return if video_url.blank?
- return if video_url.match(VIMEO_REGEX)
- return if video_url.match(YOUTUBE_REGEX)
-
- errors.add(:video_url, :invalid)
- end
-end
diff --git a/app/models/concerns/videoable.rb b/app/models/concerns/videoable.rb
new file mode 100644
index 000000000..1febafcce
--- /dev/null
+++ b/app/models/concerns/videoable.rb
@@ -0,0 +1,28 @@
+module Videoable
+ extend ActiveSupport::Concern
+
+ included do
+ validate :valid_video_url?
+ end
+
+ VIMEO_REGEX = /vimeo.*(staffpicks\/|channels\/|videos\/|video\/|\/)([^#\&\?]*).*/
+ YOUTUBE_REGEX = /youtu.*(be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*).*/
+
+ def valid_video_url?
+ url = send(video_url_field)
+
+ return if url.blank?
+ return if url.match(VIMEO_REGEX)
+ return if url.match(YOUTUBE_REGEX)
+
+ errors.add(video_url_field, :invalid)
+ end
+
+ def video_url_field
+ if has_attribute?(:video_url)
+ :video_url
+ else
+ :url
+ end
+ end
+end
diff --git a/app/models/poll/question/answer/video.rb b/app/models/poll/question/answer/video.rb
index 6cf9e7cc6..e353dd365 100644
--- a/app/models/poll/question/answer/video.rb
+++ b/app/models/poll/question/answer/video.rb
@@ -1,17 +1,6 @@
class Poll::Question::Answer::Video < ApplicationRecord
belongs_to :answer, class_name: "Poll::Question::Answer"
-
- VIMEO_REGEX = /vimeo.*(staffpicks\/|channels\/|videos\/|video\/|\/)([^#\&\?]*).*/
- YOUTUBE_REGEX = /youtu.*(be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*).*/
+ include Videoable
validates :title, presence: true
- validate :valid_url?
-
- def valid_url?
- return if url.blank?
- return if url.match(VIMEO_REGEX)
- return if url.match(YOUTUBE_REGEX)
-
- errors.add(:url, :invalid)
- end
end
diff --git a/app/models/proposal.rb b/app/models/proposal.rb
index f1e4f7198..ca4518b07 100644
--- a/app/models/proposal.rb
+++ b/app/models/proposal.rb
@@ -14,7 +14,7 @@ class Proposal < ApplicationRecord
include Mappable
include Notifiable
include Documentable
- include EmbedVideosHelper
+ include Videoable
include Relationable
include Milestoneable
include Randomizable
@@ -59,8 +59,6 @@ class Proposal < ApplicationRecord
validates :terms_of_service, acceptance: { allow_nil: false }, on: :create
- validate :valid_video_url?
-
before_validation :set_responsible_name
before_save :calculate_hot_score, :calculate_confidence_score
diff --git a/app/views/legislation/proposals/show.html.erb b/app/views/legislation/proposals/show.html.erb
index b1485fd99..7ef241fac 100644
--- a/app/views/legislation/proposals/show.html.erb
+++ b/app/views/legislation/proposals/show.html.erb
@@ -65,13 +65,7 @@
<%= @proposal.summary %>
- <% if @proposal.video_url.present? %>
-
- <% end %>
+ <%= render Shared::EmbeddedVideoComponent.new(@proposal) %>
<%= auto_link_already_sanitized_html wysiwyg(@proposal.description) %>
diff --git a/app/views/proposals/_info.html.erb b/app/views/proposals/_info.html.erb
index 23def8f68..3e443b243 100644
--- a/app/views/proposals/_info.html.erb
+++ b/app/views/proposals/_info.html.erb
@@ -30,13 +30,7 @@
<%= @proposal.summary %>
-<% if @proposal.video_url.present? %>
-
-<% end %>
+<%= render Shared::EmbeddedVideoComponent.new(@proposal) %>
<%= auto_link_already_sanitized_html wysiwyg(@proposal.description) %>
diff --git a/spec/components/shared/embedded_video_component_spec.rb b/spec/components/shared/embedded_video_component_spec.rb
new file mode 100644
index 000000000..e4d9e05f6
--- /dev/null
+++ b/spec/components/shared/embedded_video_component_spec.rb
@@ -0,0 +1,43 @@
+require "rails_helper"
+
+describe Shared::EmbeddedVideoComponent do
+ describe "src attribute" do
+ before do
+ dummy_class = Class.new do
+ include ActiveModel::Model
+ attr_accessor :title, :video_url
+
+ include Videoable
+ end
+
+ stub_const("DummyClass", dummy_class)
+ end
+
+ let(:record) { DummyClass.new(title: "Dummy Video", video_url: "") }
+ let(:component) { Shared::EmbeddedVideoComponent.new(record) }
+
+ it "does not render anything for empty URls" do
+ render_inline component
+
+ expect(page).not_to be_rendered
+ end
+
+ it "embeds a youtube video for youtube URLs" do
+ allow(record).to receive(:video_url).and_return "http://www.youtube.com/watch?v=a7UFm6ErMPU"
+ embed_url = "https://www.youtube-nocookie.com/embed/a7UFm6ErMPU"
+
+ render_inline component
+
+ expect(page).to have_css "[data-video-code*='src=\"#{embed_url}\"']"
+ end
+
+ it "embeds a vimeo video for vimeo URLs" do
+ allow(record).to receive(:video_url).and_return "https://vimeo.com/7232823"
+ embed_url = "https://player.vimeo.com/video/7232823?dnt=1"
+
+ render_inline component
+
+ expect(page).to have_css "[data-video-code*='src=\"#{embed_url}\"']"
+ end
+ end
+end
diff --git a/spec/system/proposals_spec.rb b/spec/system/proposals_spec.rb
index 47db7e6ba..459f7c619 100644
--- a/spec/system/proposals_spec.rb
+++ b/spec/system/proposals_spec.rb
@@ -301,23 +301,30 @@ describe "Proposals" do
context "Embedded video" do
scenario "Show YouTube video" do
proposal = create(:proposal, video_url: "http://www.youtube.com/watch?v=a7UFm6ErMPU")
+
visit proposal_path(proposal)
- expect(page).to have_css "div[id='js-embedded-video']"
- expect(page.html).to include "https://www.youtube.com/embed/a7UFm6ErMPU"
+
+ within "#js-embedded-video" do
+ expect(page).to have_css "iframe[src='https://www.youtube-nocookie.com/embed/a7UFm6ErMPU']"
+ end
end
scenario "Show Vimeo video" do
proposal = create(:proposal, video_url: "https://vimeo.com/7232823")
+
visit proposal_path(proposal)
- expect(page).to have_css "div[id='js-embedded-video']"
- expect(page.html).to include "https://player.vimeo.com/video/7232823"
+
+ within "#js-embedded-video" do
+ expect(page).to have_css "iframe[src='https://player.vimeo.com/video/7232823?dnt=1']"
+ end
end
scenario "Dont show video" do
proposal = create(:proposal, video_url: nil)
visit proposal_path(proposal)
- expect(page).not_to have_css "div[id='js-embedded-video']"
+
+ expect(page).not_to have_css "#js-embedded-video"
end
end