diff --git a/CHANGELOG b/CHANGELOG
index a092c3688..131dff2b6 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -11,6 +11,7 @@ CHANGELOG Roundcube Webmail
- Extract RFC2231 attachment name from message headers (#6729, #6783)
- Archive: Added options to split archive by year or year+month and folder (#7216)
- Managesieve: Allow display name with email address in vacation :from field (#6760)
+- Managesieve: Improve UX on custom header input (#7207)
- Password: Added 'pwned' password strength driver (#7274)
- Add support for SameSite cookie attribute via session_samesite option (req PHP >= 7.3.0) (#6772)
- Elastic: Display a special icon for other users and shared namespace roots (#5012)
diff --git a/plugins/managesieve/Changelog b/plugins/managesieve/Changelog
index d39181cea..af4765c32 100644
--- a/plugins/managesieve/Changelog
+++ b/plugins/managesieve/Changelog
@@ -1,3 +1,4 @@
+- Improve UX on custom header input (#7207)
- Allow display name with email address in vacation :from field (#6760)
- Replace "Filter disabled" with "Filter enabled" (#7028)
- Fix so modifier type select wasn't hidden after hiding modifier select on header change
diff --git a/plugins/managesieve/lib/Roundcube/rcube_sieve_engine.php b/plugins/managesieve/lib/Roundcube/rcube_sieve_engine.php
index 72afcd069..eb57a0ad7 100644
--- a/plugins/managesieve/lib/Roundcube/rcube_sieve_engine.php
+++ b/plugins/managesieve/lib/Roundcube/rcube_sieve_engine.php
@@ -1773,11 +1773,17 @@ class rcube_sieve_engine
}
// custom header and variable inputs
- $aout .= $this->list_input($id, 'custom_header', $custom, isset($custom),
- $this->error_class($id, 'test', 'header', 'custom_header'), 15) . "\n";
-
- $aout .= $this->list_input($id, 'custom_var', $customv, isset($customv),
- $this->error_class($id, 'test', 'header', 'custom_var'), 15) . "\n";
+ $aout .= $this->list_input($id, 'custom_header', $custom, 15, false, array(
+ 'disabled' => !isset($custom),
+ 'class' => $this->error_class($id, 'test', 'header', 'custom_header'),
+ 'placeholder' => $this->plugin->gettext('headername'),
+ 'title' => $this->plugin->gettext('headername'),
+ )) . "\n";
+
+ $aout .= $this->list_input($id, 'custom_var', $customv, 15, false, array(
+ 'disabled' => !isset($customv),
+ 'class' => $this->error_class($id, 'test', 'header', 'custom_var')
+ )) . "\n";
$test = self::rule_test($rule);
$target = '';
@@ -1830,9 +1836,10 @@ class rcube_sieve_engine
}
$tout .= $this->match_type_selector('rule_op', $id, $test, $rule['test']);
- $tout .= $this->list_input($id, 'rule_target', $target,
- $rule['test'] != 'size' && $rule['test'] != 'exists' && $rule['test'] != 'duplicate',
- $this->error_class($id, 'test', 'target', 'rule_target')) . "\n";
+ $tout .= $this->list_input($id, 'rule_target', $target, null, false, array(
+ 'disabled' => $rule['test'] == 'size' || $rule['test'] == 'exists' || $rule['test'] == 'duplicate',
+ 'class' => $this->error_class($id, 'test', 'target', 'rule_target')
+ )) . "\n";
$select_size_op = new html_select(array('name' => "_rule_size_op[$id]", 'id' => 'rule_size_op'.$id, 'class' => 'input-group-prepend'));
$select_size_op->add(rcube::Q($this->plugin->gettext('filterover')), 'over');
@@ -1920,8 +1927,9 @@ class rcube_sieve_engine
$mout .= '
';
$mout .= html::span('label input-group-prepend', html::span('input-group-text', rcube::Q($this->plugin->gettext('mime'))));
$mout .= $select_mime->show($mime_type);
- $mout .= $this->list_input($id, 'rule_mime_param', $rule['mime-param'], true,
- $this->error_class($id, 'test', 'mime_param', 'rule_mime_param'), 30, $mime_type != 'param');
+ $mout .= $this->list_input($id, 'rule_mime_param', $rule['mime-param'], 30, $mime_type != 'param', array(
+ 'class' => $this->error_class($id, 'test', 'mime_param', 'rule_mime_param')
+ ));
$mout .= '
';
}
@@ -2256,8 +2264,9 @@ class rcube_sieve_engine
'class' => $this->error_class($id, 'action', 'from', 'action_from'),
));
$out .= '
' .rcube::Q($this->plugin->gettext('vacationaddr')) . '
';
- $out .= $this->list_input($id, 'action_addresses', $action['addresses'], true,
- $this->error_class($id, 'action', 'addresses', 'action_addresses'), 30)
+ $out .= $this->list_input($id, 'action_addresses', $action['addresses'], 30, false, array(
+ 'class' => $this->error_class($id, 'action', 'addresses', 'action_addresses')
+ ))
. html::a(array('href' => '#', 'onclick' => rcmail_output::JS_OBJECT_NAME . ".managesieve_vacation_addresses($id)"),
rcube::Q($this->plugin->gettext('filladdresses')));
$out .= '
' . rcube::Q($this->plugin->gettext('vacationinterval')) . '
';
@@ -2311,8 +2320,10 @@ class rcube_sieve_engine
. rcube::Q($this->plugin->gettext('flag'.$fidx))) . '
';
}
- $flout .= $this->list_input($id, 'action_flags', $custom_flags, true,
- $this->error_class($id, 'action', 'flag', 'action_flags_flag'), null, false, "action_flags_flag{$id}");
+ $flout .= $this->list_input($id, 'action_flags', $custom_flags, null, false, array(
+ 'class' => $this->error_class($id, 'action', 'flag', 'action_flags_flag'),
+ 'id' => "action_flags_flag{$id}"
+ ));
$out .= html::div(array(
'id' => 'action_flags' . $id,
@@ -2426,9 +2437,10 @@ class rcube_sieve_engine
$out .= '
' . rcube::Q($this->plugin->gettext('notifyimportance')) . '
';
$out .= $select_importance->show($action['importance'] ? (int) $action['importance'] : 2);
$out .= ''
- .'' . rcube::Q($this->plugin->gettext('notifyoptions')) . '
'
- .$this->list_input($id, 'action_notifyoption', (array)$action['options'], true,
- $this->error_class($id, 'action', 'options', 'action_notifyoption'), 30) . '
';
+ . '' . rcube::Q($this->plugin->gettext('notifyoptions')) . '
'
+ . $this->list_input($id, 'action_notifyoption', (array) $action['options'], 30, false, array(
+ 'class' => $this->error_class($id, 'action', 'options', 'action_notifyoption')
+ )) . '';
$out .= '';
if (in_array('editheader', $this->exts)) {
@@ -2484,8 +2496,9 @@ class rcube_sieve_engine
'class' => $this->error_class($id, 'action', 'name', 'action_delheader_name'),
));
$out .= '
';
- $out .= $this->list_input($id, 'action_delheader_value', $action['value'], true,
- $this->error_class($id, 'action', 'value', 'action_delheader_value')) . "\n";
+ $out .= $this->list_input($id, 'action_delheader_value', $action['value'], null, false, array(
+ 'class' => $this->error_class($id, 'action', 'value', 'action_delheader_value')
+ )) . "\n";
$out .= '
';
$out .= html::span('label input-group-prepend', html::label(array(
'class' => 'input-group-text', 'for' => 'action_delheader_op'.$id), rcube::Q($this->plugin->gettext('headermatchtype'))));
@@ -2606,22 +2619,25 @@ class rcube_sieve_engine
$this->rc->output->add_script($script, 'docready');
}
- protected function list_input($id, $name, $value, $enabled, $class, $size = null, $hidden = false, $elem_id = null)
+ protected function list_input($id, $name, $value, $size = null, $hidden = false, $attrib = array())
{
$value = (array) $value;
$value = array_map(array('rcube', 'Q'), $value);
$value = implode("\n", $value);
- return html::tag('textarea', array(
+ $attrib = array_merge($attrib, array(
'data-type' => 'list',
'data-size' => $size,
'data-hidden' => $hidden ?: null,
'name' => '_' . $name . '[' . $id . ']',
- 'id' => $elem_id ?: ($name.$id),
- 'disabled' => !$enabled,
- 'class' => $class,
'style' => 'display:none',
- ), $value);
+ ));
+
+ if (empty($attrib['id'])) {
+ $attrib['id'] = $name . $id;
+ }
+
+ return html::tag('textarea', $attrib, $value);
}
/**
@@ -3062,7 +3078,7 @@ class rcube_sieve_engine
'name' => "_{$name}[$id]",
'id' => "{$name}{$id}",
'style' => 'display:' .(!in_array($rule, array('size', 'duplicate')) ? 'inline' : 'none'),
- 'class' => 'operator_selector',
+ 'class' => 'operator_selector col-6',
'onchange' => "{$name}_select(this, '{$id}')",
));
diff --git a/plugins/managesieve/managesieve.js b/plugins/managesieve/managesieve.js
index c2fd7a536..59ba0750e 100644
--- a/plugins/managesieve/managesieve.js
+++ b/plugins/managesieve/managesieve.js
@@ -814,7 +814,7 @@ function smart_field_init(field)
// add input rows
$.each(list, function(i, v) {
- area.append(smart_field_row(v, field.name, i, $(field).data('size')));
+ area.append(smart_field_row(v, i, field));
});
area.attr('id', id);
@@ -837,25 +837,26 @@ function smart_field_init(field)
}
};
-function smart_field_row(value, name, idx, size)
+function smart_field_row(value, idx, field)
{
// build row element content
var input, content = '
'
+ '',
elem = $(content),
- attrs = {value: value, name: name + '[]'};
-
- if (size)
- attrs.size = size;
+ attrs = {
+ value: value,
+ name: field.name + '[]',
+ size: $(field).data('size'),
+ title: field.title,
+ placeholder: $(field).attr('placeholder')
+ };
- input = $('input', elem).attr(attrs).keydown(function(e) {
+ input = elem.find('input').attr(attrs).keydown(function(e) {
var input = $(this);
// element creation event (on Enter)
if (e.which == 13) {
- var name = input.attr('name').replace(/\[\]$/, ''),
- dt = (new Date()).getTime(),
- elem = smart_field_row('', name, dt, size);
+ var elem = smart_field_row('', (new Date()).getTime(), field);
input.parent().after(elem);
$('input', elem).focus();
@@ -904,7 +905,7 @@ function smart_field_reset(field, data)
// add input rows
$.each(list, function(i, v) {
- area.append(smart_field_row(v, field.name, i, $(field).data('size')));
+ area.append(smart_field_row(v, i, field));
});
}
diff --git a/skins/elastic/ui.js b/skins/elastic/ui.js
index 427f39be4..65ac3fc24 100644
--- a/skins/elastic/ui.js
+++ b/skins/elastic/ui.js
@@ -3836,7 +3836,7 @@ function rcube_elastic_ui()
// add input rows
$.each(list, function(i, v) {
- smart_field_row_add($('.content', area), v, field.name, i, $(field).data('size'));
+ smart_field_row_add($('.content', area), v, i, field);
});
area.attr('id', id);
@@ -3862,28 +3862,26 @@ function rcube_elastic_ui()
}
};
- function smart_field_row_add(area, value, name, idx, size, after)
+ function smart_field_row_add(area, value, idx, field, after)
{
// build row element content
- var input, elem = $('
');
+
+ input = elem.find('input').attr({
+ value: value,
+ name: field.name + '[]',
+ size: $(field).data('size'),
+ title: field.title,
+ placeholder: field.placeholder
+ })
.keydown(function(e) {
- var input = $(this);
-
// element creation event (on Enter)
if (e.which == 13) {
- var name = input.attr('name').replace(/\[\]$/, ''),
- dt = (new Date()).getTime(),
- elem = smart_field_row_add(area, '', name, dt, size, input.parent());
+ var elem = smart_field_row_add(area, '', (new Date()).getTime(), field, input.parent());
$('input', elem).focus();
}
@@ -3907,7 +3905,7 @@ function rcube_elastic_ui()
});
// element deletion event
- $('a.reset', elem).click(function() {
+ elem.find('a.reset').click(function() {
var record = $(this.parentNode.parentNode);
if (area.children().length > 1) {
@@ -3919,7 +3917,7 @@ function rcube_elastic_ui()
}
});
- $(elem).find('input,a')
+ elem.find('input,a')
.on('focus', function() { area.addClass('focused'); })
.on('blur', function() { area.removeClass('focused'); });
@@ -3944,7 +3942,7 @@ function rcube_elastic_ui()
// add input rows
$.each(list, function(i, v) {
- smart_field_row_add(area, v, field.name, i, $(field).data('size'));
+ smart_field_row_add(area, v, i, field);
});
};