diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index 52495ee85..704b3a52a 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -10,6 +10,7 @@ @import 'pages'; @import 'proposal'; @import 'proposal-graph'; +@import 'dashboard_mailer_preview'; @import 'poll'; @import 'legislation'; @import 'legislation_process'; diff --git a/app/assets/stylesheets/dashboard_mailer.scss b/app/assets/stylesheets/dashboard_mailer.scss new file mode 100644 index 000000000..b59613568 --- /dev/null +++ b/app/assets/stylesheets/dashboard_mailer.scss @@ -0,0 +1,65 @@ +@import 'application'; + +body { + padding-left: 30%; + padding-right: 30%; + + p { + text-align: justify; + } +} + +header { + background-color: #3700fd; + color: white; + padding: 20pt 20pt 20pt 20pt; + margin-bottom: 0; + border-bottom: 0; + + h1 { + font-size: 40pt; + text-align: center; + } + + h2 { + font-size: 25pt; + text-align: center; + } +} + +.proposal-image { + width: 100%; +} + +.mail-body { + color: #838383; + font-size: 18pt; + margin-top: 20pt; +} + +.support-link { + display: block; + background-color: #004a84; + color: #ddffff; + text-decoration: none; + border: 1px solid $border; + width: 80%; + margin-left: auto; + margin-right: auto; + font-size: 40pt; + padding: 20pt 20pt 20pt 20pt; + border-radius: 5pt; + text-align: center; + margin-top: 50pt; + margin-bottom: 50pt; +} +.support-link:hover { + color: #ddffffff; + text-decoration: none; +} + +.share-title { + font-weight: bold; + font-size: 25pt; +} + diff --git a/app/assets/stylesheets/dashboard_mailer_preview.scss b/app/assets/stylesheets/dashboard_mailer_preview.scss new file mode 100644 index 000000000..1f967bf24 --- /dev/null +++ b/app/assets/stylesheets/dashboard_mailer_preview.scss @@ -0,0 +1,64 @@ + .dashboard-mail-preview { + + padding-left: 10%; + padding-right: 10%; + + p { + text-align: justify; + } + + .header { + background-color: #3700fd; + color: white; + padding: 20pt 20pt 20pt 20pt; + margin-bottom: 0; + border-bottom: 0; + + h1 { + font-size: 40pt; + text-align: center; + } + + h2 { + font-size: 25pt; + text-align: center; + } + } + + .proposal-image { + width: 100%; + } + + .mail-body { + color: #838383; + font-size: 18pt; + margin-top: 20pt; + } + + .support-link { + display: block; + background-color: #004a84; + color: #ddffff; + text-decoration: none; + border: 1px solid $border; + width: 80%; + margin-left: auto; + margin-right: auto; + font-size: 40pt; + padding: 20pt 20pt 20pt 20pt; + border-radius: 5pt; + text-align: center; + margin-top: 50pt; + margin-bottom: 50pt; + } + .support-link:hover { + color: #ddffffff; + text-decoration: none; + } + + .share-title { + font-weight: bold; + font-size: 25pt; + } +} + diff --git a/app/controllers/admin/settings_controller.rb b/app/controllers/admin/settings_controller.rb index c8509846b..2ae6e57fe 100644 --- a/app/controllers/admin/settings_controller.rb +++ b/app/controllers/admin/settings_controller.rb @@ -1,5 +1,6 @@ class Admin::SettingsController < Admin::BaseController - helper_method :successful_proposal_setting, :successful_proposals, :poll_feature_short_title_setting, :poll_feature_description_setting, :poll_feature_link_setting + helper_method :successful_proposal_setting, :successful_proposals, :poll_feature_short_title_setting, :poll_feature_description_setting, + :poll_feature_link_setting, :email_feature_short_title_setting, :email_feature_description_setting def index all_settings = Setting.all.group_by { |s| s.type } @@ -29,7 +30,7 @@ class Admin::SettingsController < Admin::BaseController end def successful_proposal_setting - Setting.find_by(key: 'proposals.successful_proposal_id') + @successful_proposal_setting ||= Setting.find_by(key: 'proposals.successful_proposal_id') end def successful_proposals @@ -37,14 +38,22 @@ class Admin::SettingsController < Admin::BaseController end def poll_feature_short_title_setting - Setting.find_by(key: 'proposals.poll_short_title') + @poll_feature_short_title_setting ||= Setting.find_by(key: 'proposals.poll_short_title') end def poll_feature_description_setting - Setting.find_by(key: 'proposals.poll_description') + @poll_feature_description_setting ||= Setting.find_by(key: 'proposals.poll_description') end def poll_feature_link_setting - Setting.find_by(key: 'proposals.poll_link') + @poll_feature_link_setting ||= Setting.find_by(key: 'proposals.poll_link') + end + + def email_feature_short_title_setting + @email_feature_short_title_setting ||= Setting.find_by(key: 'proposals.email_short_title') + end + + def email_feature_description_setting + @email_feature_description_setting ||= Setting.find_by(key: 'proposals.email_description') end end diff --git a/app/controllers/dashboard/mailing_controller.rb b/app/controllers/dashboard/mailing_controller.rb new file mode 100644 index 000000000..cf89fe4e8 --- /dev/null +++ b/app/controllers/dashboard/mailing_controller.rb @@ -0,0 +1,16 @@ +class Dashboard::MailingController < Dashboard::BaseController + def index + authorize! :manage_mailing, proposal + end + + def new + authorize! :manage_mailing, proposal + end + + def create + authorize! :manage_mailing, proposal + + Dashboard::Mailer.forward(proposal).deliver_later + redirect_to new_proposal_dashboard_mailing_path(proposal), flash: { notice: t("dashboard.mailing.create.sent") } + end +end diff --git a/app/helpers/proposals_dashboard_helper.rb b/app/helpers/proposals_dashboard_helper.rb index a4ec06311..9c7ebf92d 100644 --- a/app/helpers/proposals_dashboard_helper.rb +++ b/app/helpers/proposals_dashboard_helper.rb @@ -31,13 +31,21 @@ module ProposalsDashboardHelper end def resources_menu_active? - polls_menu_active? || is_resource_request? + polls_menu_active? || mailing_menu_active? || is_resource_request? end def polls_menu_active? controller_name == 'polls' end + def mailing_menu(&block) + menu_entry(mailing_menu_active?, &block) + end + + def mailing_menu_active? + controller_name == 'mailing' + end + def menu_group(id, active, &block) html_class = nil html_class = 'is-active' if active diff --git a/app/mailers/dashboard/mailer.rb b/app/mailers/dashboard/mailer.rb new file mode 100644 index 000000000..3000f7d67 --- /dev/null +++ b/app/mailers/dashboard/mailer.rb @@ -0,0 +1,8 @@ +class Dashboard::Mailer < ApplicationMailer + layout 'dashboard/mailer' + + def forward(proposal) + @proposal = proposal + mail to: proposal.author.email, subject: proposal.title + end +end diff --git a/app/models/abilities/common.rb b/app/models/abilities/common.rb index 4acd2e18a..d2e4b326b 100644 --- a/app/models/abilities/common.rb +++ b/app/models/abilities/common.rb @@ -25,6 +25,9 @@ module Abilities can :manage_polls, Proposal do |proposal| proposal.author.id == user.id end + can :manage_mailing, Proposal do |proposal| + proposal.author.id == user.id + end can :results, Poll do |poll| poll.related&.author&.id == user.id diff --git a/app/views/admin/settings/_proposals.html.erb b/app/views/admin/settings/_proposals.html.erb index b795a5208..c18d7bf11 100644 --- a/app/views/admin/settings/_proposals.html.erb +++ b/app/views/admin/settings/_proposals.html.erb @@ -34,7 +34,6 @@ <% end %> -
+ +
++ <%= Setting['proposals.email_short_title'] %> +
+Hello!
+ ++ I am writing to let you know that I am + participating in Decide Madrid, the platform for + Madrid and Madrid we can decide which city + we want. And for that, I created my own citizen proposal + and now, I'm going to need your support! But do not worry because + It is very simple. +
+ ++ You just have to click on the button that you will see below + 'Support this proposal' and you can directly inform yourself about + before promoting it. Only the proposals that achieve the + maximum support will be carried out by our City Council, + and I thought that you, I'm sure you help me achieve it! +
" + share_info: + "+ And if you also do me the great favor of sharing my proposal with + your friends, family and contacts, it would be the bomb! Can + do it next from the social network that you want or from your + email: +
" polls: all: "All" no_dates: "no date assigned" diff --git a/config/locales/en/settings.yml b/config/locales/en/settings.yml index f4334fab0..efbdd6021 100644 --- a/config/locales/en/settings.yml +++ b/config/locales/en/settings.yml @@ -68,3 +68,5 @@ en: poll_short_title: Subtitle for polls feature poll_description: Description for polls feature poll_link: Additional information link + email_short_title: Subtitle for email feature + email_description: Description for email feature diff --git a/config/locales/es/general.yml b/config/locales/es/general.yml index 44bfbc0a6..717e6bdc0 100644 --- a/config/locales/es/general.yml +++ b/config/locales/es/general.yml @@ -510,6 +510,7 @@ es: resources: Recursos community: Comunidad polls: Encuestas + mailing: Correo electrónico form: request: Solicitar create_request: @@ -586,6 +587,47 @@ es: add_answer: Añadir respuesta question_answer_fields: remove_answer: Borrar respuesta + mailing: + index: + title: Previsualización del correo electrónico + new: + title: Funcionalidad de correo electrónico + mailing_options: + send: Enviar a %{address} + preview: Previsualizar + create: + sent: El e-mail ha sido enviado + mailer: + forward: + subtitle: Si me apoyas, lo conseguiremos. + support_it: Apoyar esta propuesta + share_in: Compartir en + introduction: +¡Hola!
+ ++ Te escribo para comunicarte que estoy + participando en Decide Madrid, la plataforma para que + los madrileños y madrileñas podamos decidir qué ciudad + queremos. Y para ello, he creado mi propia propuesta ciudadana + y ahora, ¡voy a necesitar tu apoyo! Pero no te preocupes porque + es muy sencillo. +
+ ++ Tan sólo tienes que pinchar en el botón que verás a continuación + 'Apoyar esta propuesta' y directamente podrás informarte a cerca de + ella antes de impulsarla. Sólo las propuestas que consigan el + máximo apoyo se llevarán a cabo por parte de nuestro Ayuntamiento, + y he pensado que tú, ¡seguro que me ayudas a lograrlo! +
+ share_info: + "+ Y si además, me haces el gran favor de compartir mi propuesta con + tus amigos, familiares y contactos, ¡ya sería la bomba! Puedes + hacerlo a continuación desde la red social que tú quieras o desde tu + correo electrónico: +
" polls: all: "Todas" no_dates: "sin fecha asignada" diff --git a/config/locales/es/settings.yml b/config/locales/es/settings.yml index 60663ee57..8bdf33f08 100644 --- a/config/locales/es/settings.yml +++ b/config/locales/es/settings.yml @@ -68,3 +68,5 @@ es: poll_short_title: Subtítulo funcionalidad encuestas poll_description: Descripción funcionalidad encuestas poll_link: Enlace información adicional + email_short_title: Subtítulo funcionalidad de correo electrónico + email_description: Descripción funcionalidad de correo electrónico diff --git a/config/routes/proposal.rb b/config/routes/proposal.rb index 7a6f8081d..a9637af9f 100644 --- a/config/routes/proposal.rb +++ b/config/routes/proposal.rb @@ -22,6 +22,7 @@ resources :proposals do namespace :dashboard do resources :polls, except: [:show, :destroy] + resources :mailing, only: [:index, :new, :create] end member do diff --git a/db/seeds.rb b/db/seeds.rb index 01ff6d45d..1c8c19ed5 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -137,3 +137,5 @@ Setting['proposals.successful_proposal_id'] = nil Setting['proposals.poll_short_title'] = nil Setting['proposals.poll_description'] = nil Setting['proposals.poll_link'] = nil +Setting['proposals.email_short_title'] = nil +Setting['proposals.email_description'] = nil diff --git a/lib/tasks/proposal_actions.rake b/lib/tasks/proposal_actions.rake index 627c581ff..681b4e173 100644 --- a/lib/tasks/proposal_actions.rake +++ b/lib/tasks/proposal_actions.rake @@ -15,10 +15,16 @@ namespace :proposal_actions do desc 'Initialize proposal settings' task initialize_settings: :environment do - Setting['proposals.successful_proposal_id'] = nil if Setting.find_by(key: 'proposals.successful_proposal_id').nil? - Setting['proposals.poll_short_title'] = nil if Setting.find_by(key: 'proposals.poll_short_title').nil? - Setting['proposals.poll_description'] = nil if Setting.find_by(key: 'proposals.poll_description').nil? - Setting['proposals.poll_link'] = nil if Setting.find_by(key: 'proposals.poll_link').nil? + %w[ + proposals.successful_proposal_id + proposals.poll_short_title + proposals.poll_description + proposals.poll_link + proposals.email_short_title + proposals.email_description + ].each do |key| + Setting[key] = nil if Setting.find_by(key: key).nil? + end end desc 'Simulate successful proposal' diff --git a/spec/features/dashboard/dashboard_spec.rb b/spec/features/dashboard/dashboard_spec.rb index bff5e4fc4..2afe1f2d5 100644 --- a/spec/features/dashboard/dashboard_spec.rb +++ b/spec/features/dashboard/dashboard_spec.rb @@ -72,6 +72,7 @@ feature "Proposal's dashboard" do visit progress_proposal_dashboard_index_path(proposal) within 'div#available-resources-section' do expect(page).to have_content('Polls') + expect(page).to have_content('E-mail') expect(page).to have_content(available.title) expect(page).to have_content(unavailable.title) expect(page).to have_content(requested.title) @@ -99,6 +100,10 @@ feature "Proposal's dashboard" do expect(page).to have_link('Polls') end + scenario 'Dashboard has a link to e-mail feature' do + expect(page).to have_link('E-mail') + end + scenario 'Dashboard has a link to resources on main menu' do feature = create(:dashboard_action, :resource, :active) diff --git a/spec/features/dashboard/mailing_spec.rb b/spec/features/dashboard/mailing_spec.rb new file mode 100644 index 000000000..cc3f640de --- /dev/null +++ b/spec/features/dashboard/mailing_spec.rb @@ -0,0 +1,37 @@ +require 'rails_helper' + +feature 'Mailing' do + let!(:proposal) { create(:proposal, :draft) } + + before do + login_as(proposal.author) + visit new_proposal_dashboard_mailing_path(proposal) + end + + scenario 'Has a link to preview the mail' do + expect(page).to have_link('Preview') + end + + scenario 'Has a link to send the mail' do + expect(page).to have_link("Send to #{proposal.author.email}") + end + + scenario 'User receives feedback after the email is sent' do + click_link "Send to #{proposal.author.email}" + expect(page).to have_content("The email has been sent") + end + + scenario 'Preview contains the proposal title' do + click_link 'Preview' + + expect(page).to have_content(proposal.title) + end + + scenario 'Preview page can send the email as well' do + click_link 'Preview' + + expect(page).not_to have_link('Preview') + expect(page).to have_link("Send to #{proposal.author.email}") + end +end + diff --git a/spec/mailers/previews/dashboard_mailer_preview.rb b/spec/mailers/previews/dashboard_mailer_preview.rb new file mode 100644 index 000000000..eded26aef --- /dev/null +++ b/spec/mailers/previews/dashboard_mailer_preview.rb @@ -0,0 +1,6 @@ +class DashboardMailerPreview < ActionMailer::Preview + def forward + proposal = Proposal.first + Dashboard::Mailer.forward(proposal) + end +end diff --git a/spec/models/abilities/common_spec.rb b/spec/models/abilities/common_spec.rb index 56248b482..09ca0ccd8 100644 --- a/spec/models/abilities/common_spec.rb +++ b/spec/models/abilities/common_spec.rb @@ -175,6 +175,11 @@ describe Abilities::Common do it { should be_able_to(:results, poll) } end + describe 'proposal mailing' do + it { should be_able_to(:manage_mailing, own_proposal) } + it { should_not be_able_to(:manage_mailing, proposal) } + end + describe 'publishing proposals' do let(:draft_own_proposal) { create(:proposal, :draft, author: user) }