diff --git a/calendar/inc/class.calendar_hooks.inc.php b/calendar/inc/class.calendar_hooks.inc.php index 965648b865..2c337329da 100644 --- a/calendar/inc/class.calendar_hooks.inc.php +++ b/calendar/inc/class.calendar_hooks.inc.php @@ -431,44 +431,22 @@ class calendar_hooks 'default'=> 60, ), 'default-alarm' => array( - 'type' => 'select', - 'label' => 'Default alarm for regular events', + 'type' => 'date-duration',//'select', + 'label' => lang('Default alarm for regular events').' ('.lang('empty = no alarm').')', 'name' => 'default-alarm', - 'values' => isset($bo) ? array(0 => lang('None'), -1 => lang('Custom'))+$bo->alarms : array(), 'help' => 'Alarm added automatic to new events before event start-time', 'xmlrpc' => True, 'admin' => False, - 'default' => 0, - 'onchange' => 'app.preferences.cal_def_alarm_onchange' - ), - 'custom-default-alarm' => array( - 'type' => 'date-duration', - 'label' => 'Enter custom default alarm time', - 'name' => 'custom-default-alarm', - 'help' => 'Alarm added automatic to new events before event start-time.', - 'xmlrpc' => True, - 'admin' => False, - 'default' => 0, + 'default' => '', ), 'default-alarm-wholeday' => array( - 'type' => 'select', - 'label' => 'Default alarm for whole-day events', + 'type' => 'date-duration',//'select', + 'label' => lang('Default alarm for whole-day events').' ('.lang('empty = no alarm').')', 'name' => 'default-alarm-wholeday', - 'values' => isset($bo) ? array(0 => lang('None'), -1 => lang('Custom'))+$bo->alarms : array(), 'help' => lang('Alarm added automatic to new events before event start-time').' ('.lang('Midnight').')', 'xmlrpc' => True, 'admin' => False, - 'default' => 0, - 'onchange' => 'app.preferences.cal_def_alarm_onchange' - ), - 'custom-default-alarm-wholeday' => array( - 'type' => 'date-duration', - 'label' => 'Enter custom default alarm time for wholeday event', - 'name' => 'custom-default-alarm-wholeday', - 'help' => lang('Alarm added automatic to new events before event start-time').' ('.lang('Midnight').')', - 'xmlrpc' => True, - 'admin' => False, - 'default' => 0, + 'default' => '', ), ); if (isset($bo)) // add custom time-spans set by CalDAV clients, not in our prefs @@ -479,16 +457,7 @@ class calendar_hooks 'preprocess' => true, 'type' => 'user', ); - self::verify_settings($data); - foreach(array('default-alarm', 'default-alarm-wholeday') as $name) - { - $value = $prefs[$name]; - if ($value > 0 && !isset($bo->alarms[$value])) - { - $settings[$name]['values'][$value] = calendar_bo::secs2label($value); - ksort($settings[$name]['values']); - } - } + self::verify_settings_reference($data); } $settings += array( 'defaultresource_sel' => array( @@ -767,76 +736,89 @@ class calendar_hooks * boolean $data['preprocess'] true data just shown to user, false: data stored by user */ public static function verify_settings(array $data) + { + self::verify_settings_reference($data); + } + + /** + * Verify settings hook called to generate errors about settings used here to store default alarms in CalDAV prefs + * + * @param array& $data + * array $data['prefs'] + * string $data['type'] 'user', 'default' or 'forced' + * boolean $data['preprocess'] true data just shown to user, false: data stored by user + */ + public static function verify_settings_reference(array &$data) { //error_log(__METHOD__."(".array2string($data).")"); // caldav perfs are always user specific and cant by switched off - if ($data['type'] == 'user') - { - $account_lid = $GLOBALS['egw_info']['user']['account_lid']; - foreach(array( - 'default-alarm' => 'default-alarm-vevent-datetime:/'.$account_lid.'/:urn:ietf:params:xml:ns:caldav', - 'default-alarm-wholeday' => 'default-alarm-vevent-date:/'.$account_lid.'/:urn:ietf:params:xml:ns:caldav', - ) as $name => $dav) - { - $pref =& $GLOBALS['egw_info']['user']['preferences']['groupdav'][$dav]; - if (true) $pref = str_replace("\r", '', $pref); // remove CR messing up multiline preg_match - $val = $data['prefs'][$name]; - //error_log(__METHOD__."() groupdav[$dav]=$pref, calendar[$name]=$val"); + if ($data['type'] != 'user') return; - if ($data['preprocess']) // showing preferences + $account_lid = $GLOBALS['egw_info']['user']['account_lid']; + foreach(array( + 'default-alarm' => 'default-alarm-vevent-datetime:/'.$account_lid.'/:urn:ietf:params:xml:ns:caldav', + 'default-alarm-wholeday' => 'default-alarm-vevent-date:/'.$account_lid.'/:urn:ietf:params:xml:ns:caldav', + ) as $name => $dav) + { + $pref =& $GLOBALS['egw_info']['user']['preferences']['groupdav'][$dav]; + if (true) $pref = str_replace("\r", '', $pref); // remove CR messing up multiline preg_match + $val =& $data['prefs'][$name]; + + //error_log(__METHOD__."() groupdav[$dav]=$pref, calendar[$name]=$val"); + + if ($data['preprocess']) // showing preferences + { + if (!isset($val)) // no calendar pref --> read value from caldav { - if ((string)$data['prefs'][$name] === '') // no calendar pref --> read value from caldav + $matches = null; + if (preg_match('/^ACTION:NONE$/i', $pref)) { - $matches = null; - if (preg_match('/^ACTION:NONE$/i', $pref)) - { - $data['prefs'][$name] = '0'; - } - elseif (preg_match('/^TRIGGER:-PT(\d+(M|H|D))$/mi', $pref, $matches)) - { - static $factors = array( - 'M' => 60, - 'H' => 3600, - 'D' => 86400, - ); - $factor = $factors[strtoupper($matches[2])]; - $data['prefs'][$name] = $factor*(int)$matches[1]; - } - else - { - $data['prefs'][$name] = '0'; - } - $GLOBALS['egw']->preferences->add('calendar', $name, $data['prefs'][$name], 'user'); - //error_log(__METHOD__."() setting $name={$data['prefs'][$name]} from $dav='$pref'"); + $val = ''; } - } - else // storing preferences - { - if (empty($pref) || !preg_match('/^TRIGGER:/m', $pref)) + elseif (preg_match('/^TRIGGER:-PT(\d+(M|H|D))$/mi', $pref, $matches)) { - $pref = 'BEGIN:VALARM + static $factors = array( + 'M' => 1, + 'H' => 60, + 'D' => 1440, + ); + $factor = $factors[strtoupper($matches[2])]; + $val = $factor*(int)$matches[1]; + } + else + { + $val = ''; + } + $GLOBALS['egw']->preferences->add('calendar', $name, $val, 'user'); + //error_log(__METHOD__."() setting $name={$val} from $dav='$pref'"); + } + } + else // storing preferences + { + if (empty($pref) || !preg_match('/^TRIGGER:/m', $pref)) + { + $pref = 'BEGIN:VALARM TRIGGER:-PT1H ATTACH;VALUE=URI:Basso ACTION:AUDIO END:VALARM'; - } - if (!$val) - { - $pref = preg_replace('/^ACTION:.*$/m', 'ACTION:NONE', $pref); - } - elseif ($val < 3600) - { - $pref = preg_replace('/^TRIGGER:.*$/m', 'TRIGGER:-PT'.number_format($val/60, 0).'M', $pref); - } - else - { - $pref = preg_replace('/^TRIGGER:.*$/m', 'TRIGGER:-PT'.number_format($val/3600, 0).'H', $pref); - } - $GLOBALS['egw']->preferences->add('groupdav', $dav, $pref, 'user'); - //error_log(__METHOD__."() storing $name=$val --> $dav='$pref'"); } + $trigger = $val < 0 ? 'TRIGGER:PT' : 'TRIGGER:-PT'; + if ((string)$val === '') + { + $pref = preg_replace('/^ACTION:.*$/m', 'ACTION:NONE', $pref); + } + elseif (abs($val) < 60) + { + $pref = preg_replace('/^TRIGGER:.*$/m', $trigger.number_format(abs($val), 0).'M', $pref); + } + else + { + $pref = preg_replace('/^TRIGGER:.*$/m', $trigger.number_format(abs($val)/60, 0).'H', $pref); + } + $GLOBALS['egw']->preferences->add('groupdav', $dav, $pref, 'user'); + error_log(__METHOD__."() storing $name=$val --> $dav='$pref'"); } - $GLOBALS['egw']->preferences->save_repository(); } } diff --git a/calendar/inc/class.calendar_uiforms.inc.php b/calendar/inc/class.calendar_uiforms.inc.php index 112f224a38..821dbee277 100644 --- a/calendar/inc/class.calendar_uiforms.inc.php +++ b/calendar/inc/class.calendar_uiforms.inc.php @@ -149,17 +149,21 @@ class calendar_uiforms extends calendar_ui { $participants[$this->user] = $participant_types['u'][$this->user] = calendar_so::combine_status('A',1,'CHAIR'); } - $def_alarm = $this->cal_prefs['default-alarm'] != -1?$this->cal_prefs['default-alarm']:$this->cal_prefs['custom-default-alarm'] * 60; - - $offset = $def_alarm != 0 ? $def_alarm : 600; - $prefAlarm = array( - 'default' => 1, - 'offset' => $offset , - 'time' => $start - $offset, - 'all' => false, - 'owner' => $owner, - 'id' => 1, - ); + $alarms = array(); + // if default alarm set in prefs --> add it + // we assume here that user does NOT have a whole-day but no regular default-alarm, no whole-day! + if ((string)$this->cal_prefs['default-alarm'] !== '') + { + $offset = 60 * $this->cal_prefs['default-alarm']; + $alarms[1] = array( + 'default' => 1, + 'offset' => $offset , + 'time' => $start - $offset, + 'all' => false, + 'owner' => $owner, + 'id' => 1, + ); + } return array( 'participant_types' => $participant_types, 'participants' => $participants, @@ -169,11 +173,11 @@ class calendar_uiforms extends calendar_ui 'tzid' => $this->bo->common_prefs['tz'], 'priority' => 2, // normal 'public'=> $this->cal_prefs['default_private'] ? 0 : 1, - 'alarm' => array(1 => $prefAlarm), + 'alarm' => $alarms, 'recur_exception' => array(), ); } - + /** * Process the edited event and evtl. call edit to redisplay it * @@ -248,24 +252,21 @@ class calendar_uiforms extends calendar_ui { $content['end'] = $content['start'] + $content['duration']; } - // Set the default alarm for a new whole day event - if ($content['whole_day'] && $content['alarm'][1]['default']) + // fix default alarm for a new (whole day) event, to be according to default-alarm(-wholeday) pref + if ($content['alarm'][1]['default']) { - - $default_alarm = $this->cal_prefs['default-alarm-wholeday'] != -1?$this->cal_prefs['default-alarm-wholeday']: - $this->cal_prefs['custom-default-alarm-wholeday'] * 60; - $offset = $default_alarm != 0 ? $default_alarm : 600; - $prefAlarm = array( - 'default' => 1, - 'offset' => $offset , - 'time' => $this->bo->date2ts($content['start']) - $offset, - 'all' => false, - 'owner' => $owner, - 'id' => 1, - ); - $content['alarm'][1] = $prefAlarm; + $def_alarm = $this->cal_prefs['default-alarm'.($content['whole_day'] ? '-wholeday' : '')]; + if ((string)$def_alarm === '') + { + unset($content['alarm'][1]); // '' = no alarm on whole day --> delete it + } + else + { + $content['alarm'][1]['offset'] = $offset = 60 * $def_alarm; + $content['start'][1]['offset'] = $this->bo->date2ts($content['start']) - $offset; + } } - + $event = $content; unset($event['new_alarm']); unset($event['alarm']['delete_alarm']); diff --git a/calendar/js/app.js b/calendar/js/app.js index edb3cea2c8..25fcbd2a47 100644 --- a/calendar/js/app.js +++ b/calendar/js/app.js @@ -1164,11 +1164,11 @@ app.classes.calendar = AppJS.extend( // Stop the normal bubbling if this is called on click return false; }, - + /** * Enable/Disable custom Date-time for set Alarm * - * @param {egw object} _egw + * @param {egw object} _egw * @param {widget object} _widget new_alarm[options] selectbox */ alarm_custom_date: function (_egw,_widget) @@ -1177,8 +1177,8 @@ app.classes.calendar = AppJS.extend( var alarm_options = _widget || this.et2.getWidgetById('new_alarm[options]'); var start = this.et2.getWidgetById('start'); var date = 0; - - if (alarm_date && alarm_options + + if (alarm_date && alarm_options && start) { if (alarm_options.get_value() != '0') @@ -1197,23 +1197,18 @@ app.classes.calendar = AppJS.extend( } } }, - + /** - * Set alarm options based on WD/Regular event user preferences + * Set alarm options based on WD/Regular event user preferences * Gets fired by wholeday checkbox - * - * @param {egw object} _egw + * + * @param {egw object} _egw * @param {widget object} _widget whole_day checkbox */ set_alarmOptions_WD: function (_egw,_widget) { - var alarm = this.et2.getWidgetById('alarm'); - var def_alarm_wd = this.egw.preference('default-alarm-wholeday', 'calendar')? - this.egw.preference('default-alarm-wholeday', 'calendar') - :parseInt(this.egw.preference('custom-default-alarm-wholeday', 'calendar')) * 60; - var def_alarm = this.egw.preference('default-alarm', 'calendar') != 0 ? - this.egw.preference('default-alarm', 'calendar') - :parseInt(this.egw.preference('custom-default-alarm', 'calendar')) * 60; + var alarm = this.et2.getWidgetById('alarm'); + if (!alarm) return; // no default alarm var content = this.et2.getArrayMgr('content').data; var start = this.et2.getWidgetById('start'); var self= this; @@ -1232,17 +1227,26 @@ app.classes.calendar = AppJS.extend( label = self.egw.lang('%1 hours', _secs/3600); } return label; - } - if (_widget.get_value() == "true" && typeof content['alarm'][1]['default'] != 'undefined') + }; + if (typeof content['alarm'][1]['default'] == 'undefined') { - start.date.setHours(0); - time.set_value(start.get_value() - def_alarm_wd); - event.set_value(_secs_to_label(def_alarm_wd)); + // user deleted alarm --> nothing to do } else { - time.set_value(start.get_value() - def_alarm); - event.set_value(_secs_to_label(def_alarm)); + var def_alarm = this.egw.preference(_widget.get_value() === "true" ? + 'default-alarm-wholeday' : 'default-alarm', 'calendar'); + if (!def_alarm && def_alarm !== 0) // no alarm + { + jQuery('#calendar-edit_alarm > tbody :nth-child(1)').hide(); + } + else + { + jQuery('#calendar-edit_alarm > tbody :nth-child(1)').show(); + start.date.setHours(0); + time.set_value(start.get_value() - 60 * def_alarm); + event.set_value(_secs_to_label(60 * def_alarm)); + } } - } + } }); diff --git a/calendar/lang/egw_de.lang b/calendar/lang/egw_de.lang index e86caf8f22..13db963e75 100644 --- a/calendar/lang/egw_de.lang +++ b/calendar/lang/egw_de.lang @@ -177,6 +177,7 @@ edit series calendar de Serie bearbeiten edit status or alarms for this particular day calendar de Bearbeite Status oder Alarme für diesen speziellen Tag edit this event calendar de Diesen Termin bearbeiten edit this series of recuring events calendar de Diese Serie von wiederholenden Terminen bearbeiten +empty = no alarm calendar de leer = kein Alarm empty for all calendar de leer für alle end calendar de Ende end date/time calendar de Enddatum /-zeit diff --git a/calendar/lang/egw_en.lang b/calendar/lang/egw_en.lang index 5d5e353872..988c2e733c 100644 --- a/calendar/lang/egw_en.lang +++ b/calendar/lang/egw_en.lang @@ -177,6 +177,7 @@ edit series calendar en Edit series edit status or alarms for this particular day calendar en Edit status or alarms for this particular day edit this event calendar en Edit this event edit this series of recuring events calendar en Edit this series of recurring events +empty = no alarm calendar en empty = no alarm empty for all calendar en Empty for all end calendar en End end date/time calendar en End Date/Time diff --git a/preferences/inc/class.preferences_settings.inc.php b/preferences/inc/class.preferences_settings.inc.php index 08336e8a33..a73cc60969 100644 --- a/preferences/inc/class.preferences_settings.inc.php +++ b/preferences/inc/class.preferences_settings.inc.php @@ -367,6 +367,14 @@ class preferences_settings case 'color': $setting['type'] = 'colorpicker'; break; + case 'date-duration': + if (!isset($setting['size'])) $setting['size'] = 'm,dhm,24,1'; + $attrs = explode(',', $setting['size']); + foreach(array("data_format","display_format", "hours_per_day", "empty_not_0", "short_labels") as $n => $name) + { + if ((string)$attrs[$n] !== '') $tpl->setElementAttribute($tab.'['.$setting['name'].']', $name, $attrs[$n]); + } + break; } // move values/options to sel_options array if (isset($setting['values']) && is_array($setting['values'])) @@ -414,7 +422,7 @@ class preferences_settings 'type' => $setting['type'], 'label' => preg_replace('||i', "\n", $setting['label']), 'help' => lang($setting['help']), // is html - 'size' => $setting['size'], // old eT + //'size' => $setting['size'], // old eT 'default' => !empty($default) ? lang('Default').': '.$default : null, 'onchange' => $setting['onchange'], ); diff --git a/preferences/js/app.js b/preferences/js/app.js deleted file mode 100644 index 8b947ce5b0..0000000000 --- a/preferences/js/app.js +++ /dev/null @@ -1,104 +0,0 @@ -/** - * EGroupware - Preferences - Javascript UI - * - * @link http://www.egroupware.org - * @package preferences - * @author Hadi Nategh - * @copyright (c) 2008-13 by Ralf Becker - * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License - * @version $Id: app.js 47099 2014-05-27 13:36:40Z hnategh $ - */ - -/** - * UI for Preferences - * - * @augments AppJS - */ -app.classes.preferences = AppJS.extend( -{ - appname: 'preferences', - - /** - * Constructor - * - * @memberOf app.preferences - */ - init: function() - { - // call parent - this._super.apply(this, arguments); - }, - - /** - * Destructor - */ - destroy: function() - { - // call parent - this._super.apply(this, arguments); - }, - - /** - * This function is called when the etemplate2 object is loaded - * and ready. If you must store a reference to the et2 object, - * make sure to clean it up in destroy(). - * - * @param {etemplate2} _et2 newly ready object - * @param {string} _name template name - */ - et2_ready: function(_et2, _name) - { - // call parent - this._super.apply(this, arguments); - - var app = this.et2.getWidgetById('appname'); - switch (app.get_value()) - { - case 'calendar': - var defAlarmWidgets = ['default-alarm', 'default-alarm-wholeday']; - for(var key in defAlarmWidgets) - { - this.cal_def_alarm_onchange(null, this.et2.getWidgetById(defAlarmWidgets[key])); - } - break; - } - }, - - /** - * Set/Unset Calendar custom-default-alarm for regular and wholeday event preferences - * - * @param {object} _egw - * @param {widget object} _widget - * @todo options need to be implemented in preferences to be able to set options for widget, - * then node.options should be removed from here and set by template. - */ - cal_def_alarm_onchange: function (_egw,_widget) - { - var node = {}; - if (typeof _widget != 'undefined' && _widget != null) - { - switch (_widget.id) - { - case 'default-alarm': - node = this.et2.getWidgetById('custom-default-alarm'); - break; - case 'default-alarm-wholeday': - node = this.et2.getWidgetById('custom-default-alarm-wholeday'); - } - if (typeof node != 'undefined' && node != null) - { - node.options.display_format = 'dhm'; - node.options.hours_per_day = 24; - node.set_value(node.options.value); - if (_widget.get_value() == -1) - { - jQuery(node.getParent().parentNode.parentNode).show(); - } - else - { - jQuery(node.getParent().parentNode.parentNode).hide(); - } - } - } - } -}); \ No newline at end of file