diff --git a/Gemfile b/Gemfile index ac6c7a849..e38f8d656 100644 --- a/Gemfile +++ b/Gemfile @@ -97,6 +97,8 @@ gem 'openstack' gem 'browser' +gem 'simple_form' + group :test do gem 'capybara' gem 'launchy' diff --git a/Gemfile.lock b/Gemfile.lock index b30c53477..3cbdc6776 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -540,6 +540,9 @@ GEM shellany (0.0.1) shoulda-matchers (3.1.1) activesupport (>= 4.0.0) + simple_form (3.4.0) + actionpack (> 4, < 5.1) + activemodel (> 4, < 5.1) simplecov (0.12.0) docile (~> 1.1.0) json (>= 1.8, < 3) @@ -688,6 +691,7 @@ DEPENDENCIES selenium-webdriver sentry-raven shoulda-matchers + simple_form simplecov smart_listing spreadsheet_architect diff --git a/app/controllers/admin/mail_templates_controller.rb b/app/controllers/admin/mail_templates_controller.rb new file mode 100644 index 000000000..39f2b7955 --- /dev/null +++ b/app/controllers/admin/mail_templates_controller.rb @@ -0,0 +1,24 @@ +class Admin::MailTemplatesController < AdminController + before_action :retrieve_procedure + + def index + @mail_templates = @procedure.mail_templates + end + + def edit + @mail_template = @procedure.mail_templates.find(params[:id]) + end + + def update + mail_template = @procedure.mail_templates.find(params[:id]) + mail_template.update_attributes(update_params) + + redirect_to admin_procedure_mail_templates_path + end + + private + + def update_params + params.require(:mail_template).permit(:body, :object) + end +end diff --git a/app/controllers/admin/mails_controller.rb b/app/controllers/admin/mails_controller.rb deleted file mode 100644 index 6101ac8c3..000000000 --- a/app/controllers/admin/mails_controller.rb +++ /dev/null @@ -1,20 +0,0 @@ -class Admin::MailsController < AdminController - before_action :retrieve_procedure - - def index - - end - - def update - mail = current_administrateur.procedures.find(params[:procedure_id]).mail_templates.find(params[:id]) - mail.update_attributes(update_params) - - redirect_to admin_procedure_mails_path - end - - private - - def update_params - params.require(:mail_received).permit(:body, :object) - end -end \ No newline at end of file diff --git a/app/decorators/mail_template_decorator.rb b/app/decorators/mail_template_decorator.rb new file mode 100644 index 000000000..4c61981d6 --- /dev/null +++ b/app/decorators/mail_template_decorator.rb @@ -0,0 +1,14 @@ +class MailTemplateDecorator < Draper::Decorator + delegate_all + + def name + case object.type + when "MailReceived" + "E-mail d'accusé de réception" + when "MailValidated" + "E-mail de validation" + else + object.type + end + end +end diff --git a/app/mailers/notification_mailer.rb b/app/mailers/notification_mailer.rb index f42be257c..f23e501f4 100644 --- a/app/mailers/notification_mailer.rb +++ b/app/mailers/notification_mailer.rb @@ -4,11 +4,11 @@ class NotificationMailer < ApplicationMailer end def dossier_received dossier - send_mail dossier, MailTemplate.replace_tags(dossier.procedure.mail_received.object, dossier) + send_mail dossier, dossier.procedure.mail_received.object_for_dossier(dossier) end def dossier_validated dossier - send_mail dossier, "Votre dossier TPS N°#{dossier.id} a été validé" + send_mail dossier, dossier.procedure.mail_validated.object_for_dossier(dossier) end def dossier_submitted dossier diff --git a/app/models/mail_template.rb b/app/models/mail_template.rb index d51c8dbb8..77e9d9e35 100644 --- a/app/models/mail_template.rb +++ b/app/models/mail_template.rb @@ -1,31 +1,45 @@ class MailTemplate < ActiveRecord::Base + include Rails.application.routes.url_helpers + include ActionView::Helpers::UrlHelper + belongs_to :procedure - enum tags: { - numero_dossier: { - description: "Permet d'afficher le numéro de dossier de l'utilisateur." - }, - libelle_procedure: { - description: "Permet d'afficher le libellé de la procédure." - } - } + TAGS = { + numero_dossier: { + description: "Permet d'afficher le numéro de dossier de l'utilisateur." + }, + lien_dossier: { + description: "Permet d'afficher un lien vers le dossier de l'utilisateur." + }, + libelle_procedure: { + description: "Permet d'afficher le libellé de la procédure." + } + } - def self.replace_tags string, dossier - @dossier = dossier + def object_for_dossier dossier + replace_tags(object, dossier) + end - tags.inject(string) do |acc, tag| - acc.gsub!("--#{tag.first}--", replace_tag(tag.first.to_sym)) || acc + def body_for_dossier dossier + replace_tags(body, dossier) + end + + def replace_tags string, dossier + TAGS.inject(string) do |acc, tag| + acc.gsub!("--#{tag.first}--", replace_tag(tag.first.to_sym, dossier)) || acc end end private - def self.replace_tag tag + def replace_tag tag, dossier case tag when :numero_dossier - @dossier.id.to_s + dossier.id.to_s + when :lien_dossier + link_to users_dossier_recapitulatif_url(dossier), users_dossier_recapitulatif_url(dossier), target: '_blank' when :libelle_procedure - @dossier.procedure.libelle + dossier.procedure.libelle else '--BALISE_NON_RECONNUE--' end diff --git a/app/models/mail_validated.rb b/app/models/mail_validated.rb new file mode 100644 index 000000000..2691c4181 --- /dev/null +++ b/app/models/mail_validated.rb @@ -0,0 +1,18 @@ +class MailValidated < MailTemplate + before_save :default_values + + def default_values + self.object ||= "[TPS] Votre dossier TPS N°--numero_dossier-- a été validé" + self.body ||= "Bonjour,
+
+ Votre dossier N°--numero_dossier-- est prêt à être déposé pour instruction.
+
+ Afin de finaliser son dépôt, merci de vous rendre sur --lien_dossier--.,
+
+ Bonne journée,
+ ---
+ Merci de ne pas répondre à ce mail. Postez directement vos questions dans votre dossier sur la plateforme.
+ ---
+ L'équipe TPS" + end +end diff --git a/app/models/procedure.rb b/app/models/procedure.rb index 9a81ed2b6..6f43a774e 100644 --- a/app/models/procedure.rb +++ b/app/models/procedure.rb @@ -5,6 +5,7 @@ class Procedure < ActiveRecord::Base has_many :dossiers has_many :mail_templates has_one :mail_received + has_one :mail_validated has_one :procedure_path, dependent: :destroy @@ -32,7 +33,8 @@ class Procedure < ActiveRecord::Base after_save :build_default_mails, if: Proc.new { id_changed? } def build_default_mails - MailReceived.create(procedure: self) + MailReceived.create(procedure: self) unless mail_received + MailValidated.create(procedure: self) unless mail_validated end def path @@ -109,4 +111,5 @@ class Procedure < ActiveRecord::Base def total_dossier self.dossiers.where.not(state: :draft).size end + end diff --git a/app/views/admin/mail_templates/edit.html.haml b/app/views/admin/mail_templates/edit.html.haml new file mode 100644 index 000000000..a5471782a --- /dev/null +++ b/app/views/admin/mail_templates/edit.html.haml @@ -0,0 +1,30 @@ +.white-back + %h3 + = @mail_template.decorate.name + + = simple_form_for @mail_template.becomes(MailTemplate), url: admin_procedure_mail_template_path(@procedure, @mail_template) do |f| + .row + .col-md-6 + = f.input :object, label: "Objet de l'email" + = f.input :body, label: "Corps de l'email", input_html: {class: 'wysihtml5'} + .text-right + = link_to "Annuler", admin_procedure_mail_templates_path(@procedure), class: "btn btn-default" + = f.button :submit, 'Mettre à jour', class: "btn-success" + + .row + .col-md-6 + %table.table + %tr + %th + Balise + %th + Description + - MailTemplate::TAGS.each do |balise| + %tr + %td.center + %b.text-success + \-- + = balise.first + \-- + %td + =balise.second[:description] diff --git a/app/views/admin/mail_templates/index.html.haml b/app/views/admin/mail_templates/index.html.haml new file mode 100644 index 000000000..8f7df9420 --- /dev/null +++ b/app/views/admin/mail_templates/index.html.haml @@ -0,0 +1,15 @@ +.row.white-back + %h1 E-mails personnalisables + + .row + .col-md-6 + %table.table + %tr + %th{ colspan: 2 } + Type d'email + - @procedure.mail_templates.each do |mt| + %tr + %td + = mt.decorate.name + %td.text-right + = link_to "Personnaliser l'e-mail", edit_admin_procedure_mail_template_path(@procedure, mt) diff --git a/app/views/admin/mails/index.html.haml b/app/views/admin/mails/index.html.haml deleted file mode 100644 index 14c6db2eb..000000000 --- a/app/views/admin/mails/index.html.haml +++ /dev/null @@ -1,28 +0,0 @@ -.row.white-back - %h3 - E-mail d'accusé de réception - - - unless @procedure.mail_received.blank? - = form_for @procedure.mail_received, url: {controller: 'admin/mails', action: 'update', id: @procedure.mail_received.id} do |f| - =f.text_field :object, {class:'form-control', style:'width: 40%'} - %br - =f.text_area :body, {class: 'form-control wysihtml5'} - %br - =f.submit 'Mettre à jour', {class:'btn btn-success', style:'float: right'} - - - %table.table{style:'width: 50%'} - %tr - %th - Balise - %th - Description - - MailTemplate.tags.each do |balise| - %tr - %td.center - %b.text-success - \-- - = balise.first - \-- - %td - =balise.second[:description] diff --git a/app/views/layouts/left_panels/_left_panel_admin_mailscontroller_index.html.haml b/app/views/layouts/left_panels/_left_panel_admin_mailtemplatescontroller_edit.html.haml similarity index 100% rename from app/views/layouts/left_panels/_left_panel_admin_mailscontroller_index.html.haml rename to app/views/layouts/left_panels/_left_panel_admin_mailtemplatescontroller_edit.html.haml diff --git a/app/views/layouts/left_panels/_left_panel_admin_mailtemplatescontroller_index.html.haml b/app/views/layouts/left_panels/_left_panel_admin_mailtemplatescontroller_index.html.haml new file mode 100644 index 000000000..1bdf2e3b1 --- /dev/null +++ b/app/views/layouts/left_panels/_left_panel_admin_mailtemplatescontroller_index.html.haml @@ -0,0 +1 @@ += render partial: 'layouts/left_panels/left_panel_admin_procedurescontroller_navbar', locals: {active: 'E-mails'} diff --git a/app/views/layouts/left_panels/_left_panel_admin_procedurescontroller_navbar.html.haml b/app/views/layouts/left_panels/_left_panel_admin_procedurescontroller_navbar.html.haml index 01774dbe0..66ab55a3f 100644 --- a/app/views/layouts/left_panels/_left_panel_admin_procedurescontroller_navbar.html.haml +++ b/app/views/layouts/left_panels/_left_panel_admin_procedurescontroller_navbar.html.haml @@ -39,7 +39,7 @@ %div.procedure_list_element{class: ('active' if active == 'Champs privés')} Champs privés - %a{:href => "#{url_for admin_procedure_mails_path(@procedure)}", id: 'onglet-inemailsfos'} + %a{:href => "#{url_for admin_procedure_mail_templates_path(@procedure)}", id: 'onglet-inemailsfos'} %div.procedure_list_element{class: ('active' if active == 'E-mails')} E-mails diff --git a/app/views/layouts/mailer.html.haml b/app/views/layouts/mailer.html.haml index 28739ee90..5ef091a74 100644 --- a/app/views/layouts/mailer.html.haml +++ b/app/views/layouts/mailer.html.haml @@ -1,3 +1,3 @@ -%hmtl +%html %body - = yield \ No newline at end of file + = yield diff --git a/app/views/notification_mailer/dossier_received.html.erb b/app/views/notification_mailer/dossier_received.html.erb index 2b39f1abe..6c2c537d2 100644 --- a/app/views/notification_mailer/dossier_received.html.erb +++ b/app/views/notification_mailer/dossier_received.html.erb @@ -1 +1 @@ -<%= MailTemplate.replace_tags(@dossier.procedure.mail_received.body, @dossier).html_safe %> \ No newline at end of file +<%= @dossier.procedure.mail_received.body_for_dossier(@dossier).html_safe %> diff --git a/app/views/notification_mailer/dossier_validated.html.erb b/app/views/notification_mailer/dossier_validated.html.erb new file mode 100644 index 000000000..6f3ad09b3 --- /dev/null +++ b/app/views/notification_mailer/dossier_validated.html.erb @@ -0,0 +1 @@ +<%= @dossier.procedure.mail_validated.body_for_dossier(@dossier).html_safe %> diff --git a/app/views/notification_mailer/dossier_validated.text.erb b/app/views/notification_mailer/dossier_validated.text.erb deleted file mode 100644 index a5b19304b..000000000 --- a/app/views/notification_mailer/dossier_validated.text.erb +++ /dev/null @@ -1,14 +0,0 @@ -Bonjour <%= @user.email %> - -Votre dossier N°<%=@dossier.id%> est prêt à être déposé pour instruction. - -Afin de finaliser son dépôt, merci de vous rendre sur <%=users_dossier_recapitulatif_url(dossier_id: @dossier.id)%> - -Bonne journée, - ---- -Merci de ne pas répondre à ce mail. Postez directement vos questions dans votre dossier sur la plateforme. ---- - ---- -L'équide TPS - tps@apientreprise.fr \ No newline at end of file diff --git a/config/environments/development.rb b/config/environments/development.rb index 96dc809bb..6631a522c 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -42,6 +42,17 @@ Rails.application.configure do # Action Mailer settings config.action_mailer.delivery_method = :smtp config.action_mailer.default_url_options = { host: 'localhost', port: 3000 } + Rails.application.routes.default_url_options = { + host: 'localhost:3000', + protocol: :http + } + + # Config for mailcatcher https://mailcatcher.me/ + config.action_mailer.smtp_settings = { + :address => "localhost", + :port => 1025, + :locale => 'fr' + } # Config for mailcatcher https://mailcatcher.me/ config.action_mailer.smtp_settings = { diff --git a/config/environments/production.rb b/config/environments/production.rb index 8640a6aae..79e0eed48 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -76,4 +76,8 @@ Rails.application.configure do # Do not dump schema after migrations. config.active_record.dump_schema_after_migration = false + + Rails.application.routes.default_url_options = { + protocol: :https + } end diff --git a/config/environments/test.rb b/config/environments/test.rb index 2d98c2462..902e927e1 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -39,6 +39,10 @@ Rails.application.configure do config.action_mailer.delivery_method = :test config.action_mailer.default_url_options = { :host => 'localhost:3000' } + Rails.application.routes.default_url_options = { + host: 'localhost:3000', + protocol: :http + } # Raises error for missing translations # config.action_view.raise_on_missing_translations = true diff --git a/config/initializers/simple_form.rb b/config/initializers/simple_form.rb new file mode 100644 index 000000000..f306c195a --- /dev/null +++ b/config/initializers/simple_form.rb @@ -0,0 +1,169 @@ +# Use this setup block to configure all options available in SimpleForm. +SimpleForm.setup do |config| + # Wrappers are used by the form builder to generate a + # complete input. You can remove any component from the + # wrapper, change the order or even add your own to the + # stack. The options given below are used to wrap the + # whole input. + config.wrappers :default, class: :input, + hint_class: :field_with_hint, error_class: :field_with_errors do |b| + ## Extensions enabled by default + # Any of these extensions can be disabled for a + # given input by passing: `f.input EXTENSION_NAME => false`. + # You can make any of these extensions optional by + # renaming `b.use` to `b.optional`. + + # Determines whether to use HTML5 (:email, :url, ...) + # and required attributes + b.use :html5 + + # Calculates placeholders automatically from I18n + # You can also pass a string as f.input placeholder: "Placeholder" + b.use :placeholder + + ## Optional extensions + # They are disabled unless you pass `f.input EXTENSION_NAME => true` + # to the input. If so, they will retrieve the values from the model + # if any exists. If you want to enable any of those + # extensions by default, you can change `b.optional` to `b.use`. + + # Calculates maxlength from length validations for string inputs + # and/or database column lengths + b.optional :maxlength + + # Calculate minlength from length validations for string inputs + b.optional :minlength + + # Calculates pattern from format validations for string inputs + b.optional :pattern + + # Calculates min and max from length validations for numeric inputs + b.optional :min_max + + # Calculates readonly automatically from readonly attributes + b.optional :readonly + + ## Inputs + b.use :label_input + b.use :hint, wrap_with: { tag: :span, class: :hint } + b.use :error, wrap_with: { tag: :span, class: :error } + + ## full_messages_for + # If you want to display the full error message for the attribute, you can + # use the component :full_error, like: + # + # b.use :full_error, wrap_with: { tag: :span, class: :error } + end + + # The default wrapper to be used by the FormBuilder. + config.default_wrapper = :default + + # Define the way to render check boxes / radio buttons with labels. + # Defaults to :nested for bootstrap config. + # inline: input + label + # nested: label > input + config.boolean_style = :nested + + # Default class for buttons + config.button_class = 'btn' + + # Method used to tidy up errors. Specify any Rails Array method. + # :first lists the first message for each field. + # Use :to_sentence to list all errors for each field. + # config.error_method = :first + + # Default tag used for error notification helper. + config.error_notification_tag = :div + + # CSS class to add for error notification helper. + config.error_notification_class = 'error_notification' + + # ID to add for error notification helper. + # config.error_notification_id = nil + + # Series of attempts to detect a default label method for collection. + # config.collection_label_methods = [ :to_label, :name, :title, :to_s ] + + # Series of attempts to detect a default value method for collection. + # config.collection_value_methods = [ :id, :to_s ] + + # You can wrap a collection of radio/check boxes in a pre-defined tag, defaulting to none. + # config.collection_wrapper_tag = nil + + # You can define the class to use on all collection wrappers. Defaulting to none. + # config.collection_wrapper_class = nil + + # You can wrap each item in a collection of radio/check boxes with a tag, + # defaulting to :span. + # config.item_wrapper_tag = :span + + # You can define a class to use in all item wrappers. Defaulting to none. + # config.item_wrapper_class = nil + + # How the label text should be generated altogether with the required text. + # config.label_text = lambda { |label, required, explicit_label| "#{required} #{label}" } + + # You can define the class to use on all labels. Default is nil. + # config.label_class = nil + + # You can define the default class to be used on forms. Can be overriden + # with `html: { :class }`. Defaulting to none. + # config.default_form_class = nil + + # You can define which elements should obtain additional classes + # config.generate_additional_classes_for = [:wrapper, :label, :input] + + # Whether attributes are required by default (or not). Default is true. + # config.required_by_default = true + + # Tell browsers whether to use the native HTML5 validations (novalidate form option). + # These validations are enabled in SimpleForm's internal config but disabled by default + # in this configuration, which is recommended due to some quirks from different browsers. + # To stop SimpleForm from generating the novalidate option, enabling the HTML5 validations, + # change this configuration to true. + config.browser_validations = false + + # Collection of methods to detect if a file type was given. + # config.file_methods = [ :mounted_as, :file?, :public_filename ] + + # Custom mappings for input types. This should be a hash containing a regexp + # to match as key, and the input type that will be used when the field name + # matches the regexp as value. + # config.input_mappings = { /count/ => :integer } + + # Custom wrappers for input types. This should be a hash containing an input + # type as key and the wrapper that will be used for all inputs with specified type. + # config.wrapper_mappings = { string: :prepend } + + # Namespaces where SimpleForm should look for custom input classes that + # override default inputs. + # config.custom_inputs_namespaces << "CustomInputs" + + # Default priority for time_zone inputs. + # config.time_zone_priority = nil + + # Default priority for country inputs. + # config.country_priority = nil + + # When false, do not use translations for labels. + # config.translate_labels = true + + # Automatically discover new inputs in Rails' autoload path. + # config.inputs_discovery = true + + # Cache SimpleForm inputs discovery + # config.cache_discovery = !Rails.env.development? + + # Default class for inputs + # config.input_class = nil + + # Define the default class of the input wrapper of the boolean input. + config.boolean_label_class = 'checkbox' + + # Defines if the default input wrapper class should be included in radio + # collection wrappers. + # config.include_default_input_wrapper_class = true + + # Defines which i18n scope will be used in Simple Form. + # config.i18n_scope = 'simple_form' +end diff --git a/config/initializers/simple_form_bootstrap.rb b/config/initializers/simple_form_bootstrap.rb new file mode 100644 index 000000000..c7705e8e7 --- /dev/null +++ b/config/initializers/simple_form_bootstrap.rb @@ -0,0 +1,154 @@ +# Use this setup block to configure all options available in SimpleForm. +SimpleForm.setup do |config| + config.error_notification_class = 'alert alert-danger' + config.button_class = 'btn btn-default' + config.boolean_label_class = nil + + config.wrappers :vertical_form, tag: 'div', class: 'form-group', error_class: 'has-error' do |b| + b.use :html5 + b.use :placeholder + b.optional :maxlength + b.optional :minlength + b.optional :pattern + b.optional :min_max + b.optional :readonly + b.use :label, class: 'control-label' + + b.use :input, class: 'form-control' + b.use :error, wrap_with: { tag: 'span', class: 'help-block' } + b.use :hint, wrap_with: { tag: 'p', class: 'help-block' } + end + + config.wrappers :vertical_file_input, tag: 'div', class: 'form-group', error_class: 'has-error' do |b| + b.use :html5 + b.use :placeholder + b.optional :maxlength + b.optional :minlength + b.optional :readonly + b.use :label, class: 'control-label' + + b.use :input + b.use :error, wrap_with: { tag: 'span', class: 'help-block' } + b.use :hint, wrap_with: { tag: 'p', class: 'help-block' } + end + + config.wrappers :vertical_boolean, tag: 'div', class: 'form-group', error_class: 'has-error' do |b| + b.use :html5 + b.optional :readonly + + b.wrapper tag: 'div', class: 'checkbox' do |ba| + ba.use :label_input + end + + b.use :error, wrap_with: { tag: 'span', class: 'help-block' } + b.use :hint, wrap_with: { tag: 'p', class: 'help-block' } + end + + config.wrappers :vertical_radio_and_checkboxes, tag: 'div', class: 'form-group', error_class: 'has-error' do |b| + b.use :html5 + b.optional :readonly + b.use :label, class: 'control-label' + b.use :input + b.use :error, wrap_with: { tag: 'span', class: 'help-block' } + b.use :hint, wrap_with: { tag: 'p', class: 'help-block' } + end + + config.wrappers :horizontal_form, tag: 'div', class: 'form-group', error_class: 'has-error' do |b| + b.use :html5 + b.use :placeholder + b.optional :maxlength + b.optional :minlength + b.optional :pattern + b.optional :min_max + b.optional :readonly + b.use :label, class: 'col-sm-3 control-label' + + b.wrapper tag: 'div', class: 'col-sm-9' do |ba| + ba.use :input, class: 'form-control' + ba.use :error, wrap_with: { tag: 'span', class: 'help-block' } + ba.use :hint, wrap_with: { tag: 'p', class: 'help-block' } + end + end + + config.wrappers :horizontal_file_input, tag: 'div', class: 'form-group', error_class: 'has-error' do |b| + b.use :html5 + b.use :placeholder + b.optional :maxlength + b.optional :minlength + b.optional :readonly + b.use :label, class: 'col-sm-3 control-label' + + b.wrapper tag: 'div', class: 'col-sm-9' do |ba| + ba.use :input + ba.use :error, wrap_with: { tag: 'span', class: 'help-block' } + ba.use :hint, wrap_with: { tag: 'p', class: 'help-block' } + end + end + + config.wrappers :horizontal_boolean, tag: 'div', class: 'form-group', error_class: 'has-error' do |b| + b.use :html5 + b.optional :readonly + + b.wrapper tag: 'div', class: 'col-sm-offset-3 col-sm-9' do |wr| + wr.wrapper tag: 'div', class: 'checkbox' do |ba| + ba.use :label_input + end + + wr.use :error, wrap_with: { tag: 'span', class: 'help-block' } + wr.use :hint, wrap_with: { tag: 'p', class: 'help-block' } + end + end + + config.wrappers :horizontal_radio_and_checkboxes, tag: 'div', class: 'form-group', error_class: 'has-error' do |b| + b.use :html5 + b.optional :readonly + + b.use :label, class: 'col-sm-3 control-label' + + b.wrapper tag: 'div', class: 'col-sm-9' do |ba| + ba.use :input + ba.use :error, wrap_with: { tag: 'span', class: 'help-block' } + ba.use :hint, wrap_with: { tag: 'p', class: 'help-block' } + end + end + + config.wrappers :inline_form, tag: 'div', class: 'form-group', error_class: 'has-error' do |b| + b.use :html5 + b.use :placeholder + b.optional :maxlength + b.optional :minlength + b.optional :pattern + b.optional :min_max + b.optional :readonly + b.use :label, class: 'sr-only' + + b.use :input, class: 'form-control' + b.use :error, wrap_with: { tag: 'span', class: 'help-block' } + b.use :hint, wrap_with: { tag: 'p', class: 'help-block' } + end + + config.wrappers :multi_select, tag: 'div', class: 'form-group', error_class: 'has-error' do |b| + b.use :html5 + b.optional :readonly + b.use :label, class: 'control-label' + b.wrapper tag: 'div', class: 'form-inline' do |ba| + ba.use :input, class: 'form-control' + ba.use :error, wrap_with: { tag: 'span', class: 'help-block' } + ba.use :hint, wrap_with: { tag: 'p', class: 'help-block' } + end + end + # Wrappers for forms and inputs using the Bootstrap toolkit. + # Check the Bootstrap docs (http://getbootstrap.com) + # to learn about the different styles for forms and inputs, + # buttons and other elements. + config.default_wrapper = :vertical_form + config.wrapper_mappings = { + check_boxes: :vertical_radio_and_checkboxes, + radio_buttons: :vertical_radio_and_checkboxes, + file: :vertical_file_input, + boolean: :vertical_boolean, + datetime: :multi_select, + date: :multi_select, + time: :multi_select + } +end diff --git a/config/locales/simple_form.en.yml b/config/locales/simple_form.en.yml new file mode 100644 index 000000000..237438334 --- /dev/null +++ b/config/locales/simple_form.en.yml @@ -0,0 +1,31 @@ +en: + simple_form: + "yes": 'Yes' + "no": 'No' + required: + text: 'required' + mark: '*' + # You can uncomment the line below if you need to overwrite the whole required html. + # When using html, text and mark won't be used. + # html: '*' + error_notification: + default_message: "Please review the problems below:" + # Examples + # labels: + # defaults: + # password: 'Password' + # user: + # new: + # email: 'E-mail to sign in.' + # edit: + # email: 'E-mail.' + # hints: + # defaults: + # username: 'User name to sign in.' + # password: 'No special characters, please.' + # include_blanks: + # defaults: + # age: 'Rather not say' + # prompts: + # defaults: + # age: 'Select your age' diff --git a/config/locales/simple_form.fr.yml b/config/locales/simple_form.fr.yml new file mode 100644 index 000000000..73dbc13fc --- /dev/null +++ b/config/locales/simple_form.fr.yml @@ -0,0 +1,31 @@ +fr: + simple_form: + "yes": 'Oui' + "no": 'Non' + required: + text: 'obligatoire' + mark: '*' + # You can uncomment the line below if you need to overwrite the whole required html. + # When using html, text and mark won't be used. + # html: '*' + error_notification: + default_message: "Erreur, veuillez vérifier vos réponses:" + # Examples + # labels: + # defaults: + # password: 'Password' + # user: + # new: + # email: 'E-mail to sign in.' + # edit: + # email: 'E-mail.' + # hints: + # defaults: + # username: 'User name to sign in.' + # password: 'No special characters, please.' + # include_blanks: + # defaults: + # age: 'Rather not say' + # prompts: + # defaults: + # age: 'Select your age' diff --git a/config/routes.rb b/config/routes.rb index f56350720..66ab9bdf5 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,5 +1,4 @@ Rails.application.routes.draw do - default_url_options protocol: :https get "/ping" => "ping#index", :constraints => {:ip => /127.0.0.1/} @@ -130,7 +129,7 @@ Rails.application.routes.draw do post '/:index/move_down' => 'pieces_justificatives#move_down', as: :move_down end - resources 'mails' + resources :mail_templates, only: [:index, :edit, :update] put 'archive' => 'procedures#archive', as: :archive put 'publish' => 'procedures#publish', as: :publish diff --git a/db/migrate/20170125152856_init_mail_validated_for_all_procedure.rb b/db/migrate/20170125152856_init_mail_validated_for_all_procedure.rb new file mode 100644 index 000000000..74c261fa2 --- /dev/null +++ b/db/migrate/20170125152856_init_mail_validated_for_all_procedure.rb @@ -0,0 +1,9 @@ +class InitMailValidatedForAllProcedure < ActiveRecord::Migration[5.0] + def change + Procedure.all.each do |p| + unless p.mail_validated + p.mail_templates << MailValidated.create + end + end + end +end diff --git a/lib/templates/haml/scaffold/_form.html.haml b/lib/templates/haml/scaffold/_form.html.haml new file mode 100644 index 000000000..ac3aa7bc1 --- /dev/null +++ b/lib/templates/haml/scaffold/_form.html.haml @@ -0,0 +1,10 @@ += simple_form_for(@<%= singular_table_name %>) do |f| + = f.error_notification + + .form-inputs + <%- attributes.each do |attribute| -%> + = f.<%= attribute.reference? ? :association : :input %> :<%= attribute.name %> + <%- end -%> + + .form-actions + = f.button :submit diff --git a/spec/controllers/admin/mail_templates_controller_spec.rb b/spec/controllers/admin/mail_templates_controller_spec.rb new file mode 100644 index 000000000..e80ba6c5b --- /dev/null +++ b/spec/controllers/admin/mail_templates_controller_spec.rb @@ -0,0 +1,51 @@ +require 'spec_helper' + +describe Admin::MailTemplatesController, type: :controller do + let(:mail_template) { create :mail_template, :dossier_received } + let(:procedure) { create :procedure, mail_templates: [mail_template]} + + before do + sign_in procedure.administrateur + end + + describe 'GET index' do + render_views + + subject { get :index, params: {procedure_id: procedure.id} } + + it { expect(subject.status).to eq 200 } + it { expect(subject.body).to include("E-mails personnalisables") } + it { expect(subject.body).to include(*procedure.mail_templates.map{ |mt| mt.decorate.name }) } + end + + describe 'PATCH update' do + let(:object) { 'plop modif' } + let(:body) { 'plip modif' } + + context 'when is mail_template id' do + subject { patch :update, + params: {procedure_id: mail_template.procedure.id, + id: mail_template.id, + mail_template: { + object: object, + body: body + }} } + + it { expect(subject).to redirect_to admin_procedure_mail_templates_path(mail_template.procedure) } + + it { + expect { + subject + mail_template.reload + }.to change(mail_template, :object).from("[TPS] Accusé de réception pour votre dossier n°--numero_dossier--").to(object) + } + + it { + expect { + subject + mail_template.reload + }.to change(mail_template, :body).from("Votre administration vous confirme la bonne réception de votre dossier n°--numero_dossier--").to(body) + } + end + end +end diff --git a/spec/controllers/admin/mails_controller_spec.rb b/spec/controllers/admin/mails_controller_spec.rb deleted file mode 100644 index a51045d9e..000000000 --- a/spec/controllers/admin/mails_controller_spec.rb +++ /dev/null @@ -1,42 +0,0 @@ -require 'spec_helper' - -describe Admin::MailsController, type: :controller do - let(:procedure) { create :procedure } - - before do - sign_in procedure.administrateur - end - - describe 'GET index' do - subject { get :index, params: {procedure_id: procedure.id} } - - it { expect(subject.status).to eq 200 } - end - - describe 'PATCH update' do - let(:object) { 'plop modif' } - let(:body) { 'plip modif' } - - context 'when is mail_received id' do - subject { patch :update, - params: {procedure_id: procedure.id, - id: procedure.mail_received.id, - mail_received: { - object: object, - body: body - }} } - - it { expect(subject).to redirect_to admin_procedure_mails_path } - - describe 'values in database for mail received' do - before do - subject - procedure.reload - end - - it { expect(procedure.mail_received.object).to eq object } - it { expect(procedure.mail_received.body).to eq body } - end - end - end -end \ No newline at end of file diff --git a/spec/decorators/mail_template_decorator_spec.rb b/spec/decorators/mail_template_decorator_spec.rb new file mode 100644 index 000000000..4cfce8226 --- /dev/null +++ b/spec/decorators/mail_template_decorator_spec.rb @@ -0,0 +1,21 @@ +require 'spec_helper' + +describe MailTemplateDecorator do + let(:mail_template) {create :mail_template} + let(:decorator) { mail_template.decorate } + + context '#name' do + subject { decorator.name } + + context 'when mail_template is a MailValidated' do + it { is_expected.to eq "E-mail de validation" } + end + + context 'when mail_template is a MailReceived' do + let(:mail_template) {create :mail_template, :dossier_received} + it { is_expected.to eq "E-mail d'accusé de réception" } + end + + end + +end diff --git a/spec/factories/mail_templates.rb b/spec/factories/mail_templates.rb new file mode 100644 index 000000000..aac0d3615 --- /dev/null +++ b/spec/factories/mail_templates.rb @@ -0,0 +1,21 @@ +FactoryGirl.define do + factory :mail_template do + object "Object, voila voila" + body "Blabla ceci est mon body" + type 'MailValidated' + + trait :dossier_submitted do + type 'MailSubmitted' + end + + trait :dossier_refused do + type 'MailRefused' + end + + trait :dossier_received do + object "[TPS] Accusé de réception pour votre dossier n°--numero_dossier--" + body "Votre administration vous confirme la bonne réception de votre dossier n°--numero_dossier--" + type 'MailReceived' + end + end +end diff --git a/spec/factories/procedure.rb b/spec/factories/procedure.rb index 740faf5bc..c92a8ee5b 100644 --- a/spec/factories/procedure.rb +++ b/spec/factories/procedure.rb @@ -8,6 +8,7 @@ FactoryGirl.define do direction "direction SGMAP" published false administrateur { create(:administrateur) } + mail_templates { [create(:mail_template, :dossier_received)]} after(:build) do |procedure, _evaluator| if procedure.module_api_carto.nil? diff --git a/spec/mailers/notification_mailer_spec.rb b/spec/mailers/notification_mailer_spec.rb index 730ce70de..4acc90c57 100644 --- a/spec/mailers/notification_mailer_spec.rb +++ b/spec/mailers/notification_mailer_spec.rb @@ -18,9 +18,11 @@ RSpec.describe NotificationMailer, type: :mailer do subject(:subject) { described_class.dossier_validated(dossier) } + before { dossier.reload } + it { expect(subject.body).to match("Votre dossier N°#{dossier.id} est prêt à être déposé pour instruction.") } - it { expect(subject.body).to include("Afin de finaliser son dépôt, merci de vous rendre sur #{users_dossier_recapitulatif_url(dossier_id: dossier.id)}") } - it { expect(subject.subject).to eq("Votre dossier TPS N°#{dossier.id} a été validé") } + it { expect(subject.body).to include("Afin de finaliser son dépôt, merci de vous rendre sur", users_dossier_recapitulatif_url(dossier_id: dossier.id)) } + it { expect(subject.subject).to eq("[TPS] Votre dossier TPS N°#{dossier.id} a été validé") } end describe ".dossier_submitted" do @@ -29,6 +31,8 @@ RSpec.describe NotificationMailer, type: :mailer do subject(:subject) { described_class.dossier_submitted(dossier) } + before { dossier.reload } + it { expect(subject.body).to match("Nous vous confirmons que votre dossier N°#{dossier.id} a été déposé") } it { expect(subject.body).to match("auprès de #{dossier.procedure.organisation} avec succès") } it { expect(subject.body).to match("ce jour à #{dossier.updated_at}.") } @@ -41,6 +45,8 @@ RSpec.describe NotificationMailer, type: :mailer do subject(:subject) { described_class.dossier_received(dossier) } + before { dossier.reload } + it { expect(subject.subject).to eq("[TPS] Accusé de réception pour votre dossier n°#{dossier.id}") } it { expect(subject.body).to match("Votre administration vous confirme la bonne réception de votre dossier n°#{dossier.id}") } end diff --git a/spec/mailers/previews/notification_mailer_preview.rb b/spec/mailers/previews/notification_mailer_preview.rb new file mode 100644 index 000000000..f1af33905 --- /dev/null +++ b/spec/mailers/previews/notification_mailer_preview.rb @@ -0,0 +1,11 @@ +class NotificationMailerPreview < ActionMailer::Preview + + def dossier_received + NotificationMailer.dossier_received(Dossier.last) + end + + def dossier_validated + NotificationMailer.dossier_validated(Dossier.last) + end + +end diff --git a/spec/models/mail_template_spec.rb b/spec/models/mail_template_spec.rb index dbbe349ef..fb27e5d94 100644 --- a/spec/models/mail_template_spec.rb +++ b/spec/models/mail_template_spec.rb @@ -7,25 +7,34 @@ describe MailTemplate do it { is_expected.to belong_to(:procedure) } describe '.tags' do - subject { MailTemplate.tags } + subject { MailTemplate::TAGS } - it { expect(subject.size).to eq 2 } + it { expect(subject.size).to eq 3 } describe 'numero_dossier' do - subject { super()['numero_dossier'] } + subject { super()[:numero_dossier] } describe 'attr and description value' do - it { expect(subject['description']).to eq "Permet d'afficher le numéro de dossier de l'utilisateur." } + it { expect(subject[:description]).to eq "Permet d'afficher le numéro de dossier de l'utilisateur." } end end - describe 'numero_dossier' do - subject { super()['libelle_procedure'] } + describe 'libelle_procedure' do + subject { super()[:libelle_procedure] } describe 'attr and description value' do - it { expect(subject['description']).to eq "Permet d'afficher le libellé de la procédure." } + it { expect(subject[:description]).to eq "Permet d'afficher le libellé de la procédure." } + end + end + + describe 'lien_dossier' do + subject { super()[:lien_dossier] } + + describe 'attr and description value' do + + it { expect(subject[:description]).to eq "Permet d'afficher un lien vers le dossier de l'utilisateur." } end end end @@ -40,7 +49,7 @@ describe MailTemplate do procedure.mail_received.update_column(:object, '[TPS] Dossier n°--numero_dossier--') end - subject { MailTemplate.replace_tags procedure.mail_received.object, dossier } + subject { procedure.mail_received.object_for_dossier dossier } it { expect(subject).to eq "[TPS] Dossier n°#{dossier.id}" } end @@ -50,17 +59,30 @@ describe MailTemplate do procedure.mail_received.update_column(:object, '[TPS] Dossier pour la procédure --libelle_procedure--') end - subject { MailTemplate.replace_tags procedure.mail_received.object, dossier } + subject { procedure.mail_received.object_for_dossier dossier } it { expect(subject).to eq "[TPS] Dossier pour la procédure #{procedure.libelle}" } end + describe 'for tag --lien_dossier--' do + include Rails.application.routes.url_helpers + include ActionView::Helpers::UrlHelper + + before do + procedure.mail_received.update_column(:body, 'Consultez votre dossier ici --lien_dossier--') + end + + subject { procedure.mail_received.body_for_dossier dossier } + + it { is_expected.to eq "Consultez votre dossier ici #{link_to users_dossier_recapitulatif_url(dossier), users_dossier_recapitulatif_url(dossier), target: '_blank'}" } + end + describe 'multiple tags' do before do procedure.mail_received.update_column(:object, '[TPS] Dossier n°--numero_dossier-- pour la procédure --libelle_procedure-- et encore le numéro : --numero_dossier--') end - subject { MailTemplate.replace_tags procedure.mail_received.object, dossier } + subject { procedure.mail_received.object_for_dossier dossier } it { expect(subject).to eq "[TPS] Dossier n°#{dossier.id} pour la procédure #{procedure.libelle} et encore le numéro : #{dossier.id}" } end diff --git a/spec/models/procedure_spec.rb b/spec/models/procedure_spec.rb index 6b7434208..5219587ba 100644 --- a/spec/models/procedure_spec.rb +++ b/spec/models/procedure_spec.rb @@ -6,7 +6,6 @@ describe Procedure do it { is_expected.to have_many(:types_de_champ) } it { is_expected.to have_many(:dossiers) } it { is_expected.to have_many(:mail_templates) } - it { is_expected.to have_one(:mail_received) } it { is_expected.to have_one(:module_api_carto) } it { is_expected.to belong_to(:administrateur) } it { is_expected.to have_many(:preference_list_dossiers) } @@ -36,7 +35,7 @@ describe Procedure do end describe '#build_default_mails' do - subject { build :procedure } + subject { build :procedure, mail_templates: [] } it 'call the fonction build_default_mails' do expect(subject).to receive(:build_default_mails) @@ -47,10 +46,13 @@ describe Procedure do before do subject.save + subject.reload end - it { expect(subject.mail_templates.size).to eq 1 } + it { expect(subject.mail_templates.size).to eq 2 } + it { expect(subject.mail_received).not_to be_nil } + it { expect(subject.mail_validated).not_to be_nil } end end