Merge pull request #33 from kivitendo/f-send-emails-as-html
authorJan Büren <jan@kivitendo-premium.de>
Thu, 10 Feb 2022 11:58:06 +0000 (12:58 +0100)
committerGitHub <noreply@github.com>
Thu, 10 Feb 2022 11:58:06 +0000 (12:58 +0100)
F send emails as html

21 files changed:
SL/BackgroundJob/CreatePeriodicInvoices.pm
SL/Common.pm
SL/Controller/Admin.pm
SL/Controller/ClientConfig.pm
SL/Controller/Order.pm
SL/Form.pm
SL/HTML/Util.pm
bin/mozilla/am.pl
bin/mozilla/generictranslations.pl
js/kivi.SalesPurchase.js
locale/de/all
locale/en/all
sql/Pg-upgrade2-auth/convert_columns_to_html_for_sending_html_emails.pl [new file with mode: 0644]
sql/Pg-upgrade2/convert_columns_to_html_for_sending_html_emails.pl [new file with mode: 0644]
templates/webpages/admin/edit_user.html
templates/webpages/am/config.html
templates/webpages/client_config/_miscellaneous.html
templates/webpages/common/_send_email_dialog.html
templates/webpages/email_journal/show.html
templates/webpages/generictranslations/edit_email_strings.html
templates/webpages/oe/edit_periodic_invoices_config.html

index f411353..4e32063 100644 (file)
@@ -473,7 +473,7 @@ sub _email_invoice {
         invoice          => $data->{invoice},
         vars             => $data->{time_period_vars},
         attribute        => $_,
-        attribute_format => 'text'
+        attribute_format => ($_ eq 'email_body' ? 'html' : 'text')
       );
     }
 
@@ -489,6 +489,8 @@ sub _email_invoice {
       $mail->{bcc}         = $global_bcc;
       $mail->{subject}     = $data->{config}->email_subject;
       $mail->{message}     = $data->{config}->email_body;
+      $mail->{message}    .= SL::DB::Default->get->signature;
+      $mail->{content_type} = 'text/html';
       $mail->{attachments} = [{
         path     => $pdf_file_name,
         name     => sprintf('%s %s.pdf', $label, $data->{invoice}->invnumber),
index 15f8f7b..36635fd 100644 (file)
@@ -25,6 +25,7 @@ use Encode qw(decode);
 
 use SL::DBUtils;
 use SL::DB;
+use SL::HTML::Util;
 
 sub unique_id {
   my ($a, $b) = gettimeofday();
@@ -423,7 +424,7 @@ sub save_email_status {
       . $main::locale->text('To (email)') . ": $form->{email}\n"
       . "${cc}${bcc}"
       . $main::locale->text('Subject') . ": $form->{subject}\n\n"
-      . $main::locale->text('Message') . ": $form->{message}";
+      . $main::locale->text('Message') . ": " . SL::HTML::Util->strip($form->{message});
 
     $intnotes =~ s|\r||g;
 
index e620089..c22fdca 100644 (file)
@@ -592,6 +592,13 @@ sub use_multiselect_js {
   return $self;
 }
 
+sub use_ckeditor_js {
+  my ($self) = @_;
+
+  $::request->{layout}->use_javascript("${_}.js") for qw(ckeditor/ckeditor ckeditor/adapters/jquery);
+  return $self;
+}
+
 sub login_form {
   my ($self, %params) = @_;
   $::request->layout(SL::Layout::AdminLogin->new);
@@ -601,7 +608,7 @@ sub login_form {
 
 sub edit_user_form {
   my ($self, %params) = @_;
-  $self->use_multiselect_js->render('admin/edit_user', %params);
+  $self->use_multiselect_js->use_ckeditor_js->render('admin/edit_user', %params);
 }
 
 sub edit_client_form {
index 1212512..bc0f287 100644 (file)
@@ -246,7 +246,7 @@ sub check_auth {
 sub edit_form {
   my ($self) = @_;
 
-  $::request->layout->use_javascript("${_}.js") for qw(jquery.selectboxes jquery.multiselect2side kivi.File);
+  $::request->layout->use_javascript("${_}.js") for qw(jquery.selectboxes jquery.multiselect2side kivi.File ckeditor/ckeditor ckeditor/adapters/jquery);
 
   $self->setup_edit_form_action_bar;
   $self->render('client_config/form', title => t8('Client Configuration'),
index f24f5cf..64ad14d 100644 (file)
@@ -4,6 +4,7 @@ use strict;
 use parent qw(SL::Controller::Base);
 
 use SL::Helper::Flash qw(flash_later);
+use SL::HTML::Util;
 use SL::Presenter::Tag qw(select_tag hidden_tag div_tag);
 use SL::Locale::String qw(t8);
 use SL::SessionFile::Random;
@@ -522,7 +523,7 @@ sub action_send_email {
   $intnotes   .= t8('Cc')         . ": " . $::form->{cc}                                                              . "\n"    if $::form->{cc};
   $intnotes   .= t8('Bcc')        . ": " . $::form->{bcc}                                                             . "\n"    if $::form->{bcc};
   $intnotes   .= t8('Subject')    . ": " . $::form->{subject}                                                         . "\n\n";
-  $intnotes   .= t8('Message')    . ": " . $::form->{message};
+  $intnotes   .= t8('Message')    . ": " . SL::HTML::Util->strip($::form->{message});
 
   $self->order->update_attributes(intnotes => $intnotes);
 
index 229ad2c..9c05c33 100644 (file)
@@ -952,17 +952,15 @@ sub send_email {
   $mail->{to}     = $self->{EMAIL_RECIPIENT} ? $self->{EMAIL_RECIPIENT} : $self->{email};
   $mail->{from}   = qq|"$myconfig->{name}" <$myconfig->{email}>|;
   $mail->{fileid} = time() . '.' . $$ . '.';
+  $mail->{content_type}  =  "text/html";
   my $full_signature     =  $self->create_email_signature();
-  $full_signature        =~ s/\r//g;
 
   $mail->{attachments} =  [];
   my @attfiles;
   # if we send html or plain text inline
   if (($self->{format} eq 'html') && ($self->{sendmode} eq 'inline')) {
-    $mail->{content_type}   =  "text/html";
     $mail->{message}        =~ s/\r//g;
     $mail->{message}        =~ s{\n}{<br>\n}g;
-    $full_signature         =~ s{\n}{<br>\n}g;
     $mail->{message}       .=  $full_signature;
 
     open(IN, "<", $self->{tmpfile})
@@ -1234,10 +1232,12 @@ sub generate_email_body {
 
   return undef unless $body;
 
+  $body .= GenericTranslations->get(translation_type => "salutation_punctuation_mark", language_id => $self->{language_id});
+  $body  = '<p>' . $::locale->quote_special_chars('HTML', $body) . '</p>';
+
   my $translation_type = $params{translation_type} // "preset_text_$self->{formname}";
   my $main_body        = GenericTranslations->get(translation_type => $translation_type,                  language_id => $self->{language_id});
   $main_body           = GenericTranslations->get(translation_type => $params{fallback_translation_type}, language_id => $self->{language_id}) if !$main_body && $params{fallback_translation_type};
-  $body               .= GenericTranslations->get(translation_type => "salutation_punctuation_mark",      language_id => $self->{language_id}) . "\n\n";
   $body               .= $main_body;
 
   $body = $main::locale->unquote_special_chars('HTML', $body);
@@ -3440,19 +3440,11 @@ sub reformat_numbers {
 }
 
 sub create_email_signature {
-
   my $client_signature = $::instance_conf->get_signature;
   my $user_signature   = $::myconfig{signature};
 
-  my $signature = '';
-  if ( $client_signature or $user_signature ) {
-    $signature  = "\n\n-- \n";
-    $signature .= $user_signature   . "\n" if $user_signature;
-    $signature .= $client_signature . "\n" if $client_signature;
-  };
-  return $signature;
-
-};
+  return join '', grep { $_ } ($user_signature, $client_signature);
+}
 
 sub calculate_tax {
   # this function calculates the net amount and tax for the lines in ar, ap and
index a54425d..0703186 100644 (file)
@@ -41,6 +41,31 @@ sub strip {
   return delete $stripper{text};
 }
 
+sub plain_text_to_html {
+  my ($class_or_text) = @_;
+
+  my $text = !ref($class_or_text) && (($class_or_text // '') eq 'SL::HTML::Util') ? $_[1] : $class_or_text;
+
+  return $text if $text =~ m{^<p>.*</p>$};
+
+  $text =~ s{\r+}{}g;
+  $text =~ s{^[[:space:]]+|[[:space:]]+$}{}g;
+
+  return '' if $text eq '';
+
+  my @paragraphs;
+
+  foreach my $paragraph (split m{\n{2,}}, $text) {
+    no warnings 'once';
+    $paragraph =  $::locale->quote_special_chars('HTML', $paragraph);
+    $paragraph =~ s{\n}{<br>}g;
+
+    push @paragraphs, $paragraph;
+  }
+
+  return '<p>' . join('</p><p>', @paragraphs) . '</p>';
+}
+
 1;
 __END__
 
@@ -65,6 +90,12 @@ SL::HTML::Util - Utility functions dealing with HTML
 Removes all HTML elements and tags from C<$html_content> and returns
 the remaining plain text.
 
+=item C<plain_text_to_html $text>
+
+Converts a plain text to HTML: paragraphs will be recognized by empty
+lines; remaining newlines will be converted into forced line breaks;
+the rest will be HTML escaped.
+
 =back
 
 =head1 BUGS
index 0b35fc7..e24fae6 100644 (file)
@@ -669,14 +669,14 @@ sub config {
   $myconfig{show_form_details} = 1 unless (defined($myconfig{show_form_details}));
   $form->{CAN_CHANGE_PASSWORD} = $main::auth->can_change_password();
   $form->{todo_cfg}            = { TODO->get_user_config('login' => $::myconfig{login}) };
-
-  $::request->{layout}->use_javascript("jquery.multiselect2side.js");
   $form->{title}               = $locale->text('Edit Preferences for #1', $::myconfig{login});
 
+  $::request->{layout}->use_javascript("${_}.js") for qw(jquery.multiselect2side ckeditor/ckeditor ckeditor/adapters/jquery);
+
   setup_am_config_action_bar();
   $form->header();
 
-  $form->{full_signature} = $form->create_email_signature();
+  $form->{company_signature} = SL::DB::Default->get->signature;
 
   print $form->parse_html_template('am/config');
 
index 4e6d263..de7d924 100644 (file)
@@ -178,6 +178,7 @@ sub edit_email_strings {
   setup_generictranslations_edit_email_strings_action_bar();
 
   $form->{title} = $locale->text('Edit preset email strings');
+  $::request->{layout}->use_javascript(map { "${_}.js" } qw(ckeditor/ckeditor ckeditor/adapters/jquery));
   $form->header();
   print $form->parse_html_template('generictranslations/edit_email_strings',{ 'MAIL_STRINGS' => \%mail_strings });
 
index e8a1ba2..771351c 100644 (file)
@@ -241,9 +241,17 @@ namespace('kivi.SalesPurchase', function(ns) {
     if (!kivi.SalesPurchase.check_required_email_fields())
       return false;
 
+    // ckeditor gets de-initialized when removing the children from
+    // the DOM. Therefore we have to manually preserve its content
+    // over the children's relocation.
+
+    var message = $('#email_form_message').val();
+
     $('#send_email_dialog').children().remove().appendTo('#email_inputs');
     $('#send_email_dialog').dialog('close');
 
+    $('#email_form_message').val(message);
+
     kivi.submit_form_with_action('#form', $('#form').data('send-email-action'));
 
     return true;
@@ -255,6 +263,8 @@ namespace('kivi.SalesPurchase', function(ns) {
 
     $('#print_options').children().remove().appendTo('#email_form_print_options');
 
+    kivi.reinit_widgets();
+
     var to_focus = $('#email_form_to').val() === '' ? 'to' : 'subject';
     $('#email_form_' + to_focus).focus();
   };
index b451f51..663af42 100755 (executable)
@@ -649,7 +649,6 @@ $self->{texts} = {
   'Check Details'               => 'Bitte Angaben überprüfen',
   'Check connectivity'          => 'Verbindungstest',
   'Check for duplicates'        => 'Dublettencheck',
-  'Check full signature'        => 'Volle Signatur prüfen',
   'Check on ap transaction'     => 'Prüfen bei Kreditorenbuchung',
   'Check on ar transaction'     => 'Prüfen bei Debitorenbuchung',
   'Check on gl transaction'     => 'Prüfen bei Dialogbuchung',
@@ -698,6 +697,7 @@ $self->{texts} = {
   'Company name'                => 'Firmenname',
   'Company name and address'    => 'Firmenname und -adresse',
   'Company settings'            => 'Firmeneinstellungen',
+  'Company\'s email signature'  => 'Firmen-E-Mail-Signatur',
   'Compare to'                  => 'Gegenüberstellen zu',
   'Complexities'                => 'Komplexitätsgrade',
   'Complexity'                  => 'Komplexität',
@@ -1328,14 +1328,15 @@ $self->{texts} = {
   'Edit time recordings of all staff members' => 'Zeiterfassungseinträge aller Mitarbeiter bearbeiten',
   'Edit title'                  => 'Titiel bearbeiten',
   'Edit units'                  => 'Einheiten bearbeiten',
-  'Edit user signature'         => 'Benutzersignatur bearbeiten',
   'Editable'                    => 'Bearbeitbar',
   'Either there are no open invoices, or you have already initiated bank transfers with the open amounts for those that are still open.' => 'Entweder gibt es keine offenen Rechnungen, oder es wurden bereits Überweisungen über die offenen Beträge aller offenen Rechnungen erstellt.',
   'Element disabled'            => 'Element deaktiviert',
   'Email'                       => 'E-Mail',
+  'Email address'               => 'E-Mail-Adresse',
   'Email journal'               => 'E-Mail-Journal',
   'Email of the delivery order recipient' => 'E-Mail des Lieferscheinempfängers',
   'Email of the invoice recipient' => 'E-Mail des Rechnungsempfängers',
+  'Email signature'             => 'E-Mail-Signatur',
   'Employee'                    => 'Bearbeiter',
   'Employee #1 saved!'          => 'Benutzer #1 gespeichert!',
   'Employee (database ID)'      => 'Bearbeiter (Datenbank-ID)',
index 24a4366..7d5c502 100644 (file)
@@ -649,7 +649,6 @@ $self->{texts} = {
   'Check Details'               => '',
   'Check connectivity'          => '',
   'Check for duplicates'        => '',
-  'Check full signature'        => '',
   'Check on ap transaction'     => '',
   'Check on ar transaction'     => '',
   'Check on gl transaction'     => '',
@@ -698,6 +697,7 @@ $self->{texts} = {
   'Company name'                => '',
   'Company name and address'    => '',
   'Company settings'            => '',
+  'Company\'s email signature'  => '',
   'Compare to'                  => '',
   'Complexities'                => '',
   'Complexity'                  => '',
@@ -1328,14 +1328,15 @@ $self->{texts} = {
   'Edit time recordings of all staff members' => '',
   'Edit title'                  => '',
   'Edit units'                  => '',
-  'Edit user signature'         => '',
   'Editable'                    => '',
   'Either there are no open invoices, or you have already initiated bank transfers with the open amounts for those that are still open.' => '',
   'Element disabled'            => '',
   'Email'                       => '',
+  'Email address'               => '',
   'Email journal'               => '',
   'Email of the delivery order recipient' => '',
   'Email of the invoice recipient' => '',
+  'Email signature'             => '',
   'Employee'                    => '',
   'Employee #1 saved!'          => '',
   'Employee (database ID)'      => '',
diff --git a/sql/Pg-upgrade2-auth/convert_columns_to_html_for_sending_html_emails.pl b/sql/Pg-upgrade2-auth/convert_columns_to_html_for_sending_html_emails.pl
new file mode 100644 (file)
index 0000000..f8ffbe6
--- /dev/null
@@ -0,0 +1,46 @@
+# @tag: convert_columns_to_html_for_sending_html_emails
+# @description: Versand von E-Mails in HTML: mehrere Text-Spalten nach HTML umwandeln
+# @depends: release_3_5_8
+package SL::DBUpgrade2::Auth::convert_columns_to_html_for_sending_html_emails;
+
+use strict;
+use utf8;
+
+use parent qw(SL::DBUpgrade2::Base);
+
+use SL::HTML::Util;
+
+sub run {
+  my ($self) = @_;
+
+  my $q_fetch = <<SQL;
+    SELECT user_id, cfg_key, cfg_value
+    FROM auth.user_config
+    WHERE (cfg_key = 'signature')
+SQL
+
+  my $q_update = <<SQL;
+    UPDATE auth.user_config
+    SET cfg_value = ?
+    WHERE (user_id = ?)
+      AND (cfg_key = 'signature')
+SQL
+
+  my $h_fetch = $self->dbh->prepare($q_fetch);
+  $h_fetch->execute || $::form->dberror($q_fetch);
+
+  my $h_update = $self->dbh->prepare($q_update);
+
+  while (my $entry = $h_fetch->fetchrow_hashref) {
+    $entry->{cfg_value} //= '';
+    my $new_value = SL::HTML::Util->plain_text_to_html($entry->{cfg_value});
+
+    next if $entry->{cfg_value} eq $new_value;
+
+    $h_update->execute($new_value, $entry->{user_id}) || $::form->dberror($q_update);
+  }
+
+  return 1;
+}
+
+1;
diff --git a/sql/Pg-upgrade2/convert_columns_to_html_for_sending_html_emails.pl b/sql/Pg-upgrade2/convert_columns_to_html_for_sending_html_emails.pl
new file mode 100644 (file)
index 0000000..168ea45
--- /dev/null
@@ -0,0 +1,62 @@
+# @tag: convert_columns_to_html_for_sending_html_emails
+# @description: Versand von E-Mails in HTML: mehrere Text-Spalten nach HTML umwandeln
+# @depends: release_3_5_8
+package SL::DBUpgrade2::convert_columns_to_html_for_sending_html_emails;
+
+use strict;
+use utf8;
+
+use parent qw(SL::DBUpgrade2::Base);
+
+use SL::HTML::Util;
+
+sub convert_column {
+  my ($self, $table, $id_column, $column_to_convert, $condition) = @_;
+
+  $condition = $condition ? "WHERE $condition" : "";
+
+  my $q_fetch = <<SQL;
+    SELECT ${id_column}, ${column_to_convert}
+    FROM ${table}
+    ${condition}
+SQL
+
+  my $q_update = <<SQL;
+    UPDATE ${table}
+    SET ${column_to_convert} = ?
+    WHERE ${id_column} = ?
+SQL
+
+  my $h_fetch = $self->dbh->prepare($q_fetch);
+  $h_fetch->execute || $::form->dberror($q_fetch);
+
+  my $h_update = $self->dbh->prepare($q_update);
+
+  while (my $entry = $h_fetch->fetchrow_hashref) {
+    $entry->{$column_to_convert} //= '';
+    my $new_value = SL::HTML::Util->plain_text_to_html($entry->{$column_to_convert});
+
+    next if $entry->{$column_to_convert} eq $new_value;
+
+    $h_update->execute($new_value, $entry->{id}) || $::form->dberror($q_update);
+  }
+}
+
+sub run {
+  my ($self) = @_;
+
+  $self->convert_column('defaults',                  'id', 'signature');
+  $self->convert_column('employee',                  'id', 'deleted_signature');
+  $self->convert_column('periodic_invoices_configs', 'id', 'email_body');
+  $self->convert_column('generic_translations',      'id', 'translation', <<SQL);
+    translation_type IN (
+      'preset_text_sales_quotation', 'preset_text_sales_order', 'preset_text_sales_delivery_order',
+      'preset_text_invoice', 'preset_text_invoice_direct_debit', 'preset_text_request_quotation',
+      'preset_text_purchase_order', 'preset_text_periodic_invoices_email_body'
+    )
+SQL
+
+  return 1;
+}
+
+1;
index 1a90d3f..1676be3 100644 (file)
@@ -40,7 +40,7 @@
 
      <tr valign="top">
       <th align="right">[% LxERP.t8('Signature') %]</th>
-      <td>[% L.textarea_tag("user.config_values.signature", props.signature, rows=3, cols=35) %]</td>
+      <td>[% L.textarea_tag("user.config_values.signature", props.signature, rows=3, cols=35, class="texteditor") %]</td>
      </tr>
 
      <tr>
index 6901cba..4a8d64d 100644 (file)
@@ -1,7 +1,7 @@
 [%- USE T8 %]
 [%- USE LxERP %]
 [%- USE HTML %]
-[%- USE L %]
+[%- USE L %][%- USE P -%]
 
 <h1>[% title %]</h1>
 
      </tr>
 
      <tr>
-      <th align="right">[% 'E-mail' | $T8 %]</th>
+      <th align="right">[% 'Email address' | $T8 %]</th>
       <td><input name="email" size="30" value="[% HTML.escape(MYCONFIG.email) %]"></td>
      </tr>
 
      <tr valign="top">
-      <th align="right">[% 'Signature' | $T8 %]</th>
-      <td><textarea id="signature" name="signature" class="toggletextarea" rows="5" cols="50">[% HTML.escape(MYCONFIG.signature) %] </textarea>
-         <span id="full_signature" class="toggletextarea"> <textarea readonly name="full_signature" rows="10" cols="50" >[% HTML.escape(full_signature) %]</textarea> </span>
-         <a href="#" class="togglelink">[% 'Check full signature' | $T8 %]</a>
-         <a href="#" id="edit_signature" class="togglelink">[% 'Edit user signature' | $T8 %]</a>
-          </td> </tr>
+      <th align="right">[% 'Email signature' | $T8 %]</th>
+      <td>
+       [% P.textarea_tag("signature", MYCONFIG.signature, class="texteditor", rows="5", cols="50") %]
+      </td>
+     </tr>
+
+     <tr valign="top">
+      <th align="right">[% "Company's email signature" | $T8 %]</th>
+      <td>[% P.restricted_html(company_signature) %]</td>
+     </tr>
+
      <tr>
       <th align="right">[% 'Phone' | $T8 %]</th>
       <td><input name="tel" size="14" value="[% HTML.escape(MYCONFIG.tel) %]"></td>
    </div>
   </div>
  </form>
-
- <script type="text/javascript">
-  <!--
-$(function() {
-  $("#full_signature").toggle();
-  $("#edit_signature").toggle();
-  $('.togglelink').click(function() {
-    $('.toggletextarea').toggle();
-    $('.togglelink').toggle();
-    return false;
-  });
-});
-    -->
- </script>
index 0606767..752bcd8 100644 (file)
@@ -36,7 +36,7 @@
 
   <tr>
    <td align="right" valign="top">[% LxERP.t8("Signature") %]</td>
-   <td valign="top">[% L.textarea_tag('defaults.signature', SELF.defaults.signature, style=style, rows=4) %]</td>
+   <td valign="top">[% L.textarea_tag('defaults.signature', SELF.defaults.signature, style=style, rows=4, class='texteditor') %]</td>
   </tr>
 
   <tr>
index b039b25..23cc1a9 100644 (file)
@@ -68,7 +68,7 @@
    <th align="right" nowrap>[% LxERP.t8("Message") %]
     <sup> [% L.link("generictranslations.pl?action=edit_email_strings", "1)", title=LxERP.t8('Tired of copying always nice phrases for this message? Click here to use the new preset message option!'), target="_blank") %]</sup>
   </th>
-   <td>[% L.textarea_tag("email_form.message", email_form.message, rows="15" cols="80" wrap="soft") %]</td>
+   <td>[% L.textarea_tag("email_form.message", email_form.message, rows="15", cols="80", class="texteditor") %]</td>
   </tr>
 
 [% IF INSTANCE_CONF.get_doc_storage %]
index 20444a9..b484bc7 100644 (file)
@@ -1,4 +1,4 @@
-[% USE HTML %][% USE L %][% USE LxERP %]
+[% USE HTML %][% USE L %][% USE LxERP %][%- USE P -%]
 
  <h1>[% FORM.title %]</h1>
 
 
    <tr class="listrow">
     <th>[%- LxERP.t8("Body") %]</th>
-    <td><pre>[% HTML.escape(SELF.entry.body) %]</pre></td>
+    <td>
+     [%- IF SELF.entry.headers.match('(?i)content-type:.*text/html') %]
+      [% P.restricted_html(SELF.entry.body) %]
+     [%- ELSE %]
+      <pre>[% HTML.escape(SELF.entry.body) %]</pre>
+     [%- END %]
+    </td>
    </tr>
  </table>
 
index 2db858d..a25cc7e 100644 (file)
@@ -28,8 +28,8 @@
        [%- END %]
       </td>
       <td>
-       [%- IF mail_string.search('preset') %]
-        <textarea name="translation__[% language.id %]__[% mail_string %]" rows="4" cols="60">[% HTML.escape(language.$mail_string) %]</textarea>
+       [%- IF mail_string.search('preset') && !mail_string.search('subject')%]
+        <textarea name="translation__[% language.id %]__[% mail_string %]" rows="4" cols="60" class="texteditor">[% HTML.escape(language.$mail_string) %]</textarea>
        [%- ELSE %]
         <input name="translation__[% language.id %]__[% mail_string %]" size="40" value="[% HTML.escape(language.$mail_string) %]">
        [%- END %]
index f9802bf..d7ee726 100644 (file)
 
     <tr>
      <th align="right" valign="top">[%- LxERP.t8("Message") %]</th>
-     <td valign="top">[% L.textarea_tag("email_body", config.email_body, disabled=!config.send_email, rows=8, style=style) %]</td>
+     <td valign="top">[% L.textarea_tag("email_body", config.email_body, disabled=!config.send_email, rows=8, style=style, class="texteditor") %]</td>
     </tr>
    </table>
   </p>
       $('#email_recipient_address').prop('disabled', disabled);
       $('#email_sender').prop('disabled', disabled);
       $('#email_subject').prop('disabled', disabled);
-      $('#email_body').prop('disabled', disabled);
+      $('#email_body').data('ckeditorInstance').setReadOnly(disabled);
     }
     -->
  </script>