Calendar planner:

- Hover shows current time
- Clicking a row adds event at that time for that user / category
This commit is contained in:
Nathan Gray 2015-11-06 22:57:27 +00:00
parent 00b7d2242f
commit eb999f98a6
3 changed files with 239 additions and 91 deletions

View File

@ -100,6 +100,10 @@ var et2_calendar_planner = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResize
this.rows = $j(document.createElement("div")) this.rows = $j(document.createElement("div"))
.appendTo(this.div); .appendTo(this.div);
this.vertical_bar = $j(document.createElement("div"))
.addClass('verticalBar')
.appendTo(this.div);
// Used for its date calculations // Used for its date calculations
this.date_helper = et2_createWidget('date-time',{},null); this.date_helper = et2_createWidget('date-time',{},null);
this.date_helper.loadingFinished(); this.date_helper.loadingFinished();
@ -158,7 +162,6 @@ var et2_calendar_planner = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResize
* than binding it for every calendar event. * than binding it for every calendar event.
*/ */
this.div.on('mouseover', '.calendar_calEvent:not(.ui-resizable):not(.rowNoEdit)', function() { this.div.on('mouseover', '.calendar_calEvent:not(.ui-resizable):not(.rowNoEdit)', function() {
// Load the event // Load the event
planner._get_event_info(this); planner._get_event_info(this);
var that = this; var that = this;
@ -247,6 +250,35 @@ var et2_calendar_planner = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResize
},ui.helper.outerHeight()); },ui.helper.outerHeight());
} }
}); });
})
.on('mousemove', function(event) {
// Position bar by mouse
planner.vertical_bar.position({
my: 'right-1',
of: event,
collision: 'fit'
});
planner.vertical_bar.css('top','0px');
// Get time at mouse
if(planner.options.group_by == 'month')
{
var time = planner._get_time_from_position(event.clientX, event.clientY);
}
else
{
var time = planner._get_time_from_position(event.offsetX, event.offsetY);
}
// Passing to formatter, cancel out timezone
if(time)
{
var formatDate = new Date(time.valueOf() + time.getTimezoneOffset() * 60 * 1000);
planner.vertical_bar.html('<span>'+date(egw.preference('timeformat','calendar') == 12 ? 'h:ia' : 'H:i',formatDate)+'</span>');
}
else
{
planner.vertical_bar.text('');
}
}); });
// Customize and override some draggable settings // Customize and override some draggable settings
@ -327,14 +359,14 @@ var et2_calendar_planner = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResize
row.set_label(name); row.set_label(name);
} }
},user); },user);
labels.push({id: user, label: label}); labels.push({id: user, label: label, data: {participants:user,owner:''}});
} }
else if (user < 0) // groups else if (user < 0) // groups
{ {
egw.accountData(user,'account_fullname',true,function(result) { egw.accountData(user,'account_fullname',true,function(result) {
for(var id in result) for(var id in result)
{ {
this.push({id: id, label: result[id]}); this.push({id: id, label: result[id], data: {participants:id,owner:''}});
} }
},labels); },labels);
} }
@ -345,7 +377,7 @@ var et2_calendar_planner = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResize
{ {
if(accounts[j].value === user) if(accounts[j].value === user)
{ {
labels.push({id: user, label: accounts[j].label}); labels.push({id: user, label: accounts[j].label, data: {participants:user,owner:''}});
break; break;
} }
} }
@ -475,7 +507,11 @@ var et2_calendar_planner = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResize
draw_row: function(sort_key, label, events) draw_row: function(sort_key, label, events)
{ {
var key = sort_key.split('-'); var key = sort_key.split('-');
this._drawRow(sort_key, label, events, new Date(key[0],key[1],1),new Date(key[0],parseInt(key[1])+1,0)); this._drawRow(
sort_key, label, events,
new Date(key[0]+"-"+sprintf("%02d",parseInt(key[1])+1)+"-01T00:00:00Z"),
new Date(key[0],parseInt(key[1])+1,0)
);
} }
}, },
// Group by category has one row for each [sub]category // Group by category has one row for each [sub]category
@ -508,7 +544,7 @@ var et2_calendar_planner = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResize
} }
}, },
row_labels: function() { row_labels: function() {
return [{id:'',label: egw.lang('none')}]; return [{id:'',label: egw.lang('none'), data: {}}];
}, },
group: function(labels, rows, event) { group: function(labels, rows, event) {
var label_index = false; var label_index = false;
@ -523,7 +559,7 @@ var et2_calendar_planner = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResize
if(label_index === false) if(label_index === false)
{ {
label_index = labels.length; label_index = labels.length;
labels.push({id: event.category, label: ''}); labels.push({id: event.category, label: '', data: {cat_id:event.category}});
var im = this.getInstanceManager(); var im = this.getInstanceManager();
// Fake it to use the cache / call // Fake it to use the cache / call
var categories = et2_selectbox.cat_options({ var categories = et2_selectbox.cat_options({
@ -685,7 +721,13 @@ var et2_calendar_planner = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResize
// Draw the rows // Draw the rows
for(var key in labels) for(var key in labels)
{ {
grouper.draw_row.call(this,labels[key].id, labels[key].label, events[key] || []); var row = grouper.draw_row.call(this,labels[key].id, labels[key].label, events[key] || []);
// Add extra data for clicking on row
for(var extra in labels[key].data)
{
row.getDOMNode().dataset[extra] = labels[key].data[extra];
}
} }
// Adjust header if there's a scrollbar // Adjust header if there's a scrollbar
@ -720,6 +762,8 @@ var et2_calendar_planner = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResize
// Add actual events // Add actual events
row._update_events(events); row._update_events(events);
return row;
}, },
@ -1531,7 +1575,7 @@ var et2_calendar_planner = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResize
} }
var old_date = this.options.start_date; var old_date = this.options.start_date;
this.options.start_date = this.date_helper.getValue(); this.options.start_date = new Date(this.date_helper.getValue());
if(old_date !== this.options.start_date && this.isAttached()) if(old_date !== this.options.start_date && this.isAttached())
{ {
@ -1567,7 +1611,7 @@ var et2_calendar_planner = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResize
this.date_helper.set_minutes(59); this.date_helper.set_minutes(59);
this.date_helper.date.setSeconds(59); this.date_helper.date.setSeconds(59);
var old_date = this.options.end_date; var old_date = this.options.end_date;
this.options.end_date = this.date_helper.getValue(); this.options.end_date = new Date(this.date_helper.getValue());
if(old_date !== this.options.end_date && this.isAttached()) if(old_date !== this.options.end_date && this.isAttached())
{ {
@ -1711,6 +1755,26 @@ var et2_calendar_planner = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResize
return false; return false;
} }
else if (!event.id)
{
// Clicked in row, but not on an event
// Default handler to open a new event at the selected time
if(this.options.group_by == 'month')
{
var date = this._get_time_from_position(_ev.clientX, _ev.clientY);
}
else
{
var date = this._get_time_from_position(_ev.offsetX, _ev.offsetY);
}
var data = $j(_ev.target).closest('.calendar_plannerRowWidget')[0].dataset || {};
this.egw().open(null, 'calendar', 'add', jQuery.extend({
start: date.toJSON(),
hour: date.getUTCHours(),
minute: date.getUTCMinutes()
},data) , '_blank');
return false;
}
return result; return result;
} }
else if (!jQuery.isEmptyObject(_ev.target.dataset)) else if (!jQuery.isEmptyObject(_ev.target.dataset))
@ -1787,9 +1851,38 @@ var et2_calendar_planner = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResize
y = Math.round(y); y = Math.round(y);
var rel_x = Math.min(x / $j('.calendar_eventRows',this.div).width(),1); var rel_x = Math.min(x / $j('.calendar_eventRows',this.div).width(),1);
var rel_time = 0;
var rel_time = (new Date(this.options.end_date) - new Date(this.options.start_date))*rel_x/1000; // Simple math, the x is offset from start date
this.date_helper.set_value(this.options.start_date); if(this.options.group_by !== 'month')
{
rel_time = (new Date(this.options.end_date) - new Date(this.options.start_date))*rel_x/1000;
this.date_helper.set_value(this.options.start_date.toJSON());
}
else
{
// Find the correct row so we know which month, then get the offset
var row = $j(document.elementFromPoint(x, y)).closest('.calendar_plannerRowWidget');
var row_widget = null;
for(var i = 0; i < this._children.length && row.length > 0; i++)
{
if(this._children[i].div[0] == row[0])
{
row_widget = this._children[i];
break;
}
}
if(row_widget)
{
rel_x = Math.min((x-row_widget.rows.offset().left)/row_widget.rows.width(),1);
rel_time = (new Date(row_widget.options.end_date) - new Date(row_widget.options.start_date))*rel_x/1000;
this.date_helper.set_value(row_widget.options.start_date.toJSON());
}
else
{
return false;
}
}
var interval = egw.preference('interval','calendar') || 30; var interval = egw.preference('interval','calendar') || 30;
this.date_helper.set_minutes(Math.round(rel_time / (60 * interval))*interval); this.date_helper.set_minutes(Math.round(rel_time / (60 * interval))*interval);

View File

@ -58,6 +58,10 @@ var et2_calendar_planner_row = et2_valueWidget.extend([et2_IDetachedDOM],
// Used for its date calculations // Used for its date calculations
this.date_helper = et2_createWidget('date-time',{},null); this.date_helper = et2_createWidget('date-time',{},null);
this.date_helper.loadingFinished(); this.date_helper.loadingFinished();
this.set_start_date(this.options.start_date);
this.set_end_date(this.options.end_date);
}, },
doLoadingFinished: function() { doLoadingFinished: function() {
@ -137,6 +141,43 @@ var et2_calendar_planner_row = et2_valueWidget.extend([et2_IDetachedDOM],
} }
}, },
/**
* Change the start date
*
* @param {Date} new_date New end date
* @returns {undefined}
*/
set_start_date: function(new_date)
{
if(!new_date || new_date === null)
{
throw exception('Invalid end date. ' + new_date.toString());
}
this.options.start_date = new Date(typeof new_date == 'string' ? new_date : new_date.toJSON());
this.options.start_date.setUTCHours(0);
this.options.start_date.setUTCMinutes(0);
this.options.start_date.setUTCSeconds(0);
},
/**
* Change the end date
*
* @param {string|number|Date} new_date New end date
* @returns {undefined}
*/
set_end_date: function(new_date)
{
if(!new_date || new_date === null)
{
throw exception('Invalid end date. ' + new_date.toString());
}
this.options.end_date = new Date(typeof new_date == 'string' ? new_date : new_date.toJSON());
this.options.end_date.setUTCHours(23);
this.options.end_date.setUTCMinutes(59);
this.options.end_date.setUTCSeconds(59);
},
/** /**
* Mark special days (birthdays, holidays) on the planner * Mark special days (birthdays, holidays) on the planner
* *
@ -357,7 +398,6 @@ var et2_calendar_planner_row = et2_valueWidget.extend([et2_IDetachedDOM],
// Basic scaling, doesn't consider working times // Basic scaling, doesn't consider working times
pos = (t - start) / (end - start); pos = (t - start) / (end - start);
// Month view // Month view
if(this._parent.options.group_by !== 'month') if(this._parent.options.group_by !== 'month')
{ {
@ -389,6 +429,11 @@ var et2_calendar_planner_row = et2_valueWidget.extend([et2_IDetachedDOM],
} }
*/ */
} }
else
{
// 2678400 is the number of seconds in 31 days
//pos = (t - start) / 2678400000;
}
pos = 100 * pos; pos = 100 * pos;
return pos; return pos;

View File

@ -687,8 +687,11 @@ e.g. the div with class calendar_calTimeGrid is generated by the timeGridWidget
min-height: 20px; min-height: 20px;
height: 100%; height: 100%;
} }
.calendar_eventRows {
margin-left: 2px;
}
.calendar_plannerWidget .verticalBar { .calendar_plannerWidget .verticalBar {
width: 1px; width: 8ex;
height: 100%; height: 100%;
position: absolute; position: absolute;
top: 0px; top: 0px;
@ -696,6 +699,13 @@ e.g. the div with class calendar_calTimeGrid is generated by the timeGridWidget
pointer-events: none; pointer-events: none;
z-index: 40; z-index: 40;
} }
.calendar_plannerWidget .verticalBar > span {
position: absolute;
bottom: 0px;
right: 0px;
background-color: rgba(255,255,255,.8);
}
/** /**
* Filler for month with less then 31 days in yearly planner * Filler for month with less then 31 days in yearly planner