From 57ab5dc678cd60375d3100f93b7e72b1e5647a67 Mon Sep 17 00:00:00 2001 From: Nathan Gray Date: Tue, 11 Aug 2015 22:30:50 +0000 Subject: [PATCH] Calendar et2 bugs: - Fix drag to re-order calendars - Keep order in planner view --- calendar/inc/class.calendar_ui.inc.php | 2 +- calendar/inc/class.calendar_uiviews.inc.php | 6 +- calendar/js/app.js | 87 ++++++++++++++--- calendar/js/et2_widget_event.js | 3 +- calendar/js/et2_widget_planner.js | 103 +++++++++++++++----- calendar/js/et2_widget_timegrid.js | 9 +- 6 files changed, 161 insertions(+), 49 deletions(-) diff --git a/calendar/inc/class.calendar_ui.inc.php b/calendar/inc/class.calendar_ui.inc.php index b751403fc3..80c4e51986 100644 --- a/calendar/inc/class.calendar_ui.inc.php +++ b/calendar/inc/class.calendar_ui.inc.php @@ -840,7 +840,7 @@ class calendar_ui { if(is_int($event[$field])) { - $event[$field] = egw_time::to($event[$field],'Y-m-d\TH:i:s').'Z'; + $event[$field] = egw_time::to($event[$field], egw_time::ET2); } } } diff --git a/calendar/inc/class.calendar_uiviews.inc.php b/calendar/inc/class.calendar_uiviews.inc.php index 8571c9f6fa..e45e9eb58c 100644 --- a/calendar/inc/class.calendar_uiviews.inc.php +++ b/calendar/inc/class.calendar_uiviews.inc.php @@ -240,7 +240,7 @@ class calendar_uiviews extends calendar_ui $GLOBALS['egw_info']['flags']['params']['manual'] = array('page' => 'ManualCalendar'.ucfirst($this->view)); // Sidebox & iframe for old views - if(in_array($this->view,array('year','planner')) && $_GET['view']) + if(in_array($this->view,array('year')) && $_GET['view']) { $GLOBALS['egw_info']['flags']['nonavbar'] = true; $this->manage_states($_GET); @@ -269,11 +269,11 @@ class calendar_uiviews extends calendar_ui if (egw_json_request::isJSONRequest())// && strpos($_GET['menuaction'], 'calendar_uiforms') === false) { $states = array(); - foreach(array('date','cat_id','filter','owner','view') as $state) + foreach(array('date','cat_id','filter','owner','view','sortby') as $state) { if($this->$state) $states[$state] = $this->$state; } - $states['date'] = egw_time::to($states['date'],'Y-m-d\TH:i:s').'Z'; + $states['date'] = egw_time::to($states['date'],egw_time::ET2); $response = egw_json_response::get(); $response->apply('app.calendar.set_state', array($states)); } diff --git a/calendar/js/app.js b/calendar/js/app.js index 1990d647d5..406d30ab7a 100644 --- a/calendar/js/app.js +++ b/calendar/js/app.js @@ -124,7 +124,6 @@ app.classes.calendar = AppJS.extend( var egw_fw = egw_getFramework(); sidebox= $j('#favorite_sidebox_'+this.appname,egw_fw.sidemenuDiv); } - this._init_sidebox(sidebox); var content = this.et2.getArrayMgr('content'); @@ -268,22 +267,36 @@ app.classes.calendar = AppJS.extend( */ linkHandler: function(_url) { - if (_url.match('menuaction=calendar.calendar_uiviews.index')) + if (_url.match('menuaction=calendar\.calendar_uiviews\.')) { - var state = this.getState(); - if (state.view == 'listview') - { - return _url.replace(/menuaction=[^&]+/, 'menuaction=calendar.calendar_uilist.listview&ajax=true'); - } - else if (this.sidebox_et2 && typeof app.classes.calendar.views[state.view] == 'undefined') + var view = _url.match(/calendar_uiviews\.([^&?]+)/); + view = view && view.length > 1 ? view[1] : null; + + // Get query + var q = {}; + _url.split('?')[1].split('&').forEach(function(i){ + q[i.split('=')[0]]=i.split('=')[1]; + }); + delete q.ajax; + delete q.menuaction; + if((!view || view == 'index') && q.view) view = q.view; + + if (this.sidebox_et2 && typeof app.classes.calendar.views[view] == 'undefined') { this.sidebox_et2.getWidgetById('iframe').set_src(_url); return true; } - // Known AJAX view, but not loaded - else if(app.classes.calendar.views[state.view]) + // Known AJAX view + else if(app.classes.calendar.views[view]) { - return _url + '&ajax=true'; + if(typeof app.classes.calendar.views[view].etemplates[0] == 'string') + { + return _url + '&ajax=true'; + } + // Already loaded, we'll just apply any variables to our current state + var set = jQuery.extend({view: view},q); + this.update_state(set); + return true; } } else if (_url.indexOf('menuaction=calendar.calendar_') >= 0) @@ -329,13 +342,12 @@ app.classes.calendar = AppJS.extend( create: function () { var $sortItem = jQuery(this); - }, start: function (event, ui) { $j('.calendar_calTimeGrid',ui.helper).css('position', 'absolute'); // Put owners into row IDs - app.classes.calendar.views[state.view].etemplates[0].widgetContainer.iterateOver(function(widget) { + app.classes.calendar.views[app.calendar.state.view].etemplates[0].widgetContainer.iterateOver(function(widget) { widget.div.parents('tr').attr('data-owner',widget.options.owner); },this,et2_calendar_timegrid); }, @@ -344,6 +356,7 @@ app.classes.calendar = AppJS.extend( }, update: function () { + var state = app.calendar.getState(); if (state && typeof state.owner !== 'undefined') { var sortedArr = sortable.sortable('toArray', {attribute:"data-owner"}); @@ -1370,10 +1383,14 @@ app.classes.calendar = AppJS.extend( var view = app.classes.calendar.views[state.state.view]; // Sanitize owner so it's always an array + if(state.state.owner === null) + { + state.state.owner = undefined; + } switch(typeof state.state.owner) { case 'undefined': - state.state.owner = this.egw.user('account_id'); + state.state.owner = [this.egw.user('account_id')]; break; case 'string': state.state.owner = state.state.owner.split(','); @@ -2022,6 +2039,45 @@ app.classes.calendar = AppJS.extend( } }, + /** + * Initializes actions and handlers on sidebox (delete) + * Extended from parent to automatically add change handlers for resource + * menu items. + * + * @param {jQuery} sidebox jQuery of DOM node + */ + _init_sidebox: function(sidebox) + { + if( this._super.apply(this, arguments) ) + { + sidebox.parentsUntil('#calendar_sidebox_content') + .find('.egw_fw_ui_category_content').not(sidebox.parent()) + .on('change.sidebox', 'select:not(.et2_selectbox),input', this, function(event) { + var state = {}; + + // Here we look for things like owner: ['r1,r2'] and change them + // to owner: ['r1','r2'] + state[this.name.replace('[]','')] = $j(this).val(); + for(var key in state) + { + if(state[key] && typeof state[key].length !== 'undefined') + { + for(var sub_key in state[key]) + { + if(typeof state[key][sub_key] == 'string' && state[key][sub_key].indexOf(',') !== -1) + { + var explode_me = state[key][sub_key]; + delete state[key][sub_key]; + jQuery.extend(state[key], explode_me.split(',')); + } + } + } + } + app.calendar.update_state(state); + }); + } + }, + /** * The sidebox filters use some non-standard and not-exposed options. They * are set up here. @@ -2220,7 +2276,8 @@ jQuery.extend(app.classes.calendar,{ } // If the owner is not set, 0, or the current user, don't bother adding it - var _owner = (owner && owner.toString() != '0' && owner !== (app.calendar.state.owner.toString()||'')) ? owner.toString() : ''; + var state_owner = app.calendar ? app.calendar.state.owner.toString() || '' : ''; + var _owner = (owner && owner.toString() != '0' && owner !== state_owner) ? owner.toString() : ''; if(_owner == egw.user('account_id')) { _owner = ''; diff --git a/calendar/js/et2_widget_event.js b/calendar/js/et2_widget_event.js index 6785951fad..1049ba3a21 100644 --- a/calendar/js/et2_widget_event.js +++ b/calendar/js/et2_widget_event.js @@ -495,7 +495,8 @@ var et2_calendar_event = et2_valueWidget.extend([et2_IDetachedDOM], // Go over the widget & add links - this is where we decide which actions are // 'allowed' for this widget at this time var action_links = this._get_action_links(actions); - this._parent._parent._init_links_dnd(widget_object.manager,action_links); + action_links.push('egw_link_drag'); + action_links.push('egw_link_drop'); widget_object.updateActionLinks(action_links); }, diff --git a/calendar/js/et2_widget_planner.js b/calendar/js/et2_widget_planner.js index 500c7e1618..72a3cb3ca0 100644 --- a/calendar/js/et2_widget_planner.js +++ b/calendar/js/et2_widget_planner.js @@ -295,7 +295,7 @@ var et2_calendar_planner = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResize }, // Labels for the rows row_labels: function() { - var labels = {}; + var labels = []; var accounts = egw.accounts(); for(var i = 0; i < this.options.owner.length; i++) { @@ -307,25 +307,41 @@ var et2_calendar_planner = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResize } if (isNaN(user)) // resources { - labels[user] = egw.link_title('resources',user.match(/\d+/)[0],function(name) {this[user] = name;},labels); + var planner = this; + var label = egw.link_title('resources',user.match(/\d+/)[0],function(name) { + for(var j = 0; j < labels.length; j++) + { + if(labels[j].id == this) + { + labels[j].label = name; + break; + } + } + var row = planner.getWidgetById(this); + if(row && row.set_label) + { + row.set_label(name); + } + },user); + labels.push({id: user, label: label}); } else if (user < 0) // groups { egw.accountData(user,'account_fullname',true,function(result) { for(var id in result) { - this[id] = result[id]; + this.push({id: id, label: result[id]}); } },labels); } else // users { user = parseInt(user) - for(var i = 0; i < accounts.length; i++) + for(var j = 0; j < accounts.length; j++) { - if(accounts[i].value === user) + if(accounts[j].value === user) { - labels[user] = accounts[i].label; + labels.push({id: user, label: accounts[j].label}); break; } } @@ -358,14 +374,23 @@ var et2_calendar_planner = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResize for(var user in event.participants) { var participant = event.participants[user]; - if(participant && typeof labels[user] !== 'undefined' && status_to_show.indexOf(participant.substr(0,1)) >= 0 || + var label_index = false; + for(var i = 0; i < labels.length; i++) + { + if(labels[i].id == user) + { + label_index = i; + break; + } + } + if(participant && label_index !== false && status_to_show.indexOf(participant.substr(0,1)) >= 0 || this.options.filter === 'owner' && event.owner === user) { - if(typeof rows[user] === 'undefined') + if(typeof rows[label_index] === 'undefined') { - rows[user] = []; + rows[label_index] = []; } - rows[user].push(event); + rows[label_index].push(event); } } }, @@ -383,12 +408,12 @@ var et2_calendar_planner = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResize this.headers.append(this._header_day_of_month()); }, row_labels: function() { - var labels = {}; + var labels = []; var d = new Date(this.options.start_date); d = new Date(d.valueOf() + d.getTimezoneOffset() * 60 * 1000); for(var i = 0; i < 12; i++) { - labels[d.getUTCFullYear() +'-'+d.getUTCMonth()] = egw.lang(date('F',d))+' '+d.getUTCFullYear(); + labels.push({id: d.getUTCFullYear() +'-'+d.getUTCMonth(), label:egw.lang(date('F',d))+' '+d.getUTCFullYear()}); d.setUTCMonth(d.getUTCMonth()+1); } return labels; @@ -396,11 +421,20 @@ var et2_calendar_planner = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResize group: function(labels, rows,event) { var start = new Date(event.start); var key = start.getUTCFullYear() +'-'+start.getUTCMonth(); - if(typeof rows[key] === 'undefined') + var label_index = false; + for(var i = 0; i < labels.length; i++) { - rows[key] = []; + if(labels[i].id == key) + { + label_index = i; + break; + } } - rows[key].push(event); + if(typeof rows[label_index] === 'undefined') + { + rows[label_index] = []; + } + rows[label_index].push(event); // end in a different month? var end = new Date(event.end); @@ -415,7 +449,15 @@ var et2_calendar_planner = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResize month = 1; } key = sprintf('%04d-%02d',year,month); - rows[key].push(event); + for(var i = 0; i < labels.length; i++) + { + if(labels[i].id == key) + { + label_index = i; + break; + } + } + rows[label_index].push(event); } }, // Draw a single row, but split up the dates @@ -452,17 +494,22 @@ var et2_calendar_planner = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResize } }, row_labels: function() { - return {'': egw.lang('none')}; + return [{id:'',label: egw.lang('none')}]; }, group: function(labels, rows, event) { - if(typeof rows[event.category] === 'undefined') + var label_index = false; + for(var i = 0; i < labels.length; i++) { - rows[event.category] = []; + if(labels[i].id == event.category) + { + label_index = i; + break; + } } - rows[event.category].push(event); - if(typeof labels[event.category] === 'undefined') + if(label_index === false) { - labels[event.category] = ''; + label_index = labels.length; + labels.push({id: event.category, label: ''}); var im = this.getInstanceManager(); // Fake it to use the cache / call var categories = et2_selectbox.cat_options({ @@ -473,10 +520,15 @@ var et2_calendar_planner = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResize { if(parseInt(categories[i].value) === parseInt(event.category)) { - labels[event.category] = categories[i].label; + labels[labels.length-1].label = categories[i].label; } } } + if(typeof rows[label_index] === 'undefined') + { + rows[label_index] = []; + } + rows[label_index].push(event); }, draw_row: function(sort_key, label, events) { return this._drawRow(sort_key, label,events,this.options.start_date, this.options.end_date); @@ -603,7 +655,7 @@ var et2_calendar_planner = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResize // Draw the rows for(var key in labels) { - grouper.draw_row.call(this,key, labels[key], events[key] || []); + grouper.draw_row.call(this,labels[key].id, labels[key].label, events[key] || []); } }, @@ -1198,7 +1250,8 @@ var et2_calendar_planner = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResize return null; },true); } - if(actionLinks.indexOf(drag_action.id) < 0) + // The planner itself is not draggable, the action is there for the children + if(false && actionLinks.indexOf(drag_action.id) < 0) { actionLinks.push(drag_action.id); } diff --git a/calendar/js/et2_widget_timegrid.js b/calendar/js/et2_widget_timegrid.js index 61ebf1466d..6edf2a0eed 100644 --- a/calendar/js/et2_widget_timegrid.js +++ b/calendar/js/et2_widget_timegrid.js @@ -646,12 +646,11 @@ var et2_calendar_timegrid = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResiz // This binds into the egw action system. Most user interactions (drag to move, resize) // are handled internally using jQuery directly. - var widget_object = parent.getObjectById(this.id); + var widget_object = this._actionObject || parent.getObjectById(this.id); var aoi = new et2_action_object_impl(this,this.getDOMNode()); aoi.doTriggerEvent = function(_event, _data) { // Determine target node - debugger; var event = _data.event || false; if(!event) return; if(_data.ui.draggable.hasClass('rowNoEdit')) return; @@ -719,6 +718,7 @@ var et2_calendar_timegrid = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResiz { widget_object.setAOI(aoi); } + this._actionObject = widget_object; // Delete all old objects widget_object.clear(); @@ -731,7 +731,6 @@ var et2_calendar_timegrid = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResiz this._init_links_dnd(widget_object.manager, action_links); widget_object.updateActionLinks(action_links); - this._actionObject = widget_object; }, /** @@ -843,7 +842,9 @@ var et2_calendar_timegrid = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResiz return null; },true); } - if(actionLinks.indexOf(drag_action.id) < 0) + // The timegrid itself is not draggable, so don't add a link. + // The action is there for the children (events) to use + if(false && actionLinks.indexOf(drag_action.id) < 0) { actionLinks.push(drag_action.id); }