Re-enable/implement preference for showing events as a per-day list

This commit is contained in:
Nathan Gray 2016-01-12 23:55:59 +00:00
parent 703ed91caa
commit 15dd34edcb
8 changed files with 359 additions and 147 deletions

View File

@ -117,10 +117,11 @@ class calendar_hooks
'1' => lang('Yes'), '1' => lang('Yes'),
'0' => lang('No'), '0' => lang('No'),
); );
$grid_views = array( $list_views = array(
'all' => lang('all'), 0 => lang('None'),
'day_week' => lang('Dayview').', '.lang('Four days view').' & '.lang('Weekview'), 'weekN' => lang('Multiple week view'),
'day4' => lang('Dayview').' & '.lang('Four days view'), 'week' => lang('Weekview'),
'day4' => lang('Four days view'),
'day' => lang('Dayview'), 'day' => lang('Dayview'),
); );
$updates = array( $updates = array(
@ -346,19 +347,16 @@ class calendar_hooks
'admin' => False, 'admin' => False,
'forced' => 'user', 'forced' => 'user',
), ),
//ATM:Disable the use_time_grid preference 'use_time_grid' => array(
//@TODO: the whole use_time_grid preference should be removed 'type' => 'multiselect',
// after we decided that is not neccessary to have it at all 'label' => 'Views showing a list of events',
/*'use_time_grid' => array(
'type' => 'select',
'label' => 'Views with fixed time intervals',
'name' => 'use_time_grid', 'name' => 'use_time_grid',
'values' => $grid_views, 'values' => $list_views,
'help' => 'For which views should calendar show distinct lines with a fixed time interval.', 'help' => 'For which views should calendar just a list of events instead of distinct lines with a fixed time interval.',
'xmlrpc' => True, 'xmlrpc' => True,
'admin' => False, 'admin' => False,
'forced' => 'all', 'default' => ['weekN'],
),*/ ),
'link_title' => array( 'link_title' => array(
'type' => 'multiselect', 'type' => 'multiselect',
'label' => 'Link title for events to show', 'label' => 'Link title for events to show',

View File

@ -2082,6 +2082,10 @@ app.classes.calendar = AppJS.extend(
{ {
widget.set_show_weekend(view.show_weekend(state.state)); widget.set_show_weekend(view.show_weekend(state.state));
} }
if(widget.set_granularity)
{
widget.set_granularity(view.granularity(state.state));
}
if(widget.id == value[row_index].id && if(widget.id == value[row_index].id &&
widget.get_end_date().toJSON() == value[row_index].end_date widget.get_end_date().toJSON() == value[row_index].end_date
) )
@ -2097,16 +2101,6 @@ app.classes.calendar = AppJS.extend(
widget.set_value(value[row_index++]); widget.set_value(value[row_index++]);
} }
},this, et2_calendar_view); },this, et2_calendar_view);
grid.iterateOver(function(widget) {
if(widget.set_granularity)
{
widget.set_granularity(view.granularity(state.state));
}
if(widget.resize)
{
widget.resize();
}
},this,et2_calendar_view);
// Single day with multiple owners still needs owners split to satisfy // Single day with multiple owners still needs owners split to satisfy
// caching keys, otherwise they'll cache consolidated // caching keys, otherwise they'll cache consolidated
@ -3327,7 +3321,10 @@ app.classes.calendar = AppJS.extend(
* How big or small are the displayed time chunks? * How big or small are the displayed time chunks?
*/ */
granularity: function(state) { granularity: function(state) {
return parseInt(egw.preference('interval','calendar')) || 30; var list = egw.preference('use_time_grid','calendar').split(',');
return list.indexOf(state.view) >= 0 ?
0 :
parseInt(egw.preference('interval','calendar')) || 30;
}, },
extend: function(sub) extend: function(sub)
{ {
@ -3505,7 +3502,8 @@ jQuery.extend(app.classes.calendar,{
return week_start; return week_start;
}, },
granularity: function(state) { granularity: function(state) {
return 120; // Always a list, not a grid
return 0;
}, },
scroll: function(delta) scroll: function(delta)
{ {

View File

@ -160,29 +160,36 @@ var et2_calendar_daycol = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResizea
} }
} }
this.display_settings.rowsToDisplay = ((this.display_settings.wd_end - this.display_settings.wd_start)/this.display_settings.granularity); if(this.display_settings.granularity === 0)
this.display_settings.rowHeight= (100/this.display_settings.rowsToDisplay).toFixed(1);
this.display_settings.titleHeight = (this.title.height()/this.div.height())*100;
// adding divs to click on for each row / time-span
for(var t = 0,i = 1; t < 1440; t += this.display_settings.granularity,++i)
{ {
var linkData = { this.div.attr('data-date', this.options.date);
'menuaction':'calendar.calendar_uiforms.edit', }
'date' : this.options.date, else
'hour' : sprintf("%02d",Math.floor(t / 60)), {
'minute' : sprintf("%02d",Math.floor(t % 60)) this.display_settings.rowsToDisplay = ((this.display_settings.wd_end - this.display_settings.wd_start)/this.display_settings.granularity);
}; this.display_settings.rowHeight= (100/this.display_settings.rowsToDisplay).toFixed(1);
if (this.options.owner) linkData['owner'] = this.options.owner; this.display_settings.titleHeight = (this.title.height()/this.div.height())*100;
var droppableDateTime = linkData['date'] + "T" + linkData['hour'] + linkData['minute']; // adding divs to click on for each row / time-span
var droppableID='drop_'+droppableDateTime+'_O'+(this.options.owner<0?'group'+Math.abs(this.options.owner):this.options.owner); for(var t = 0,i = 1; t < 1440; t += this.display_settings.granularity,++i)
{
var linkData = {
'menuaction':'calendar.calendar_uiforms.edit',
'date' : this.options.date,
'hour' : sprintf("%02d",Math.floor(t / 60)),
'minute' : sprintf("%02d",Math.floor(t % 60))
};
if (this.options.owner) linkData['owner'] = this.options.owner;
var hour = jQuery('<div id="' + droppableID + '" style="height:'+ this._parent.rowHeight+'px; " class="calendar_calAddEvent">') var droppableDateTime = linkData['date'] + "T" + linkData['hour'] + linkData['minute'];
.attr('data-date',linkData.date) var droppableID='drop_'+droppableDateTime+'_O'+(this.options.owner<0?'group'+Math.abs(this.options.owner):this.options.owner);
.attr('data-hour',linkData.hour)
.attr('data-minute',linkData.minute) var hour = jQuery('<div id="' + droppableID + '" style="height:'+ this._parent.rowHeight+'px; " class="calendar_calAddEvent">')
.appendTo(this.div); .attr('data-date',linkData.date)
.attr('data-hour',linkData.hour)
.attr('data-minute',linkData.minute)
.appendTo(this.div);
}
} }
}, },
@ -245,7 +252,10 @@ var et2_calendar_daycol = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResizea
.attr('data-whole_day',true); .attr('data-whole_day',true);
// Avoid redrawing if date is the same // Avoid redrawing if date is the same
if(new_date === this.options.date && !force_redraw) if(new_date === this.options.date &&
this.display_settings.granularity === this._parent.options.granularity &&
!force_redraw
)
{ {
return; return;
} }
@ -361,13 +371,18 @@ var et2_calendar_daycol = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResizea
}, },
set_width: function(width) { set_width: function(width) {
this.options.width = width; if(this.width_timeout)
window.setTimeout(jQuery.proxy(function() {
if(this.div)
{ {
this.div.outerWidth(this.options.width); window.clearTimeout(this.width_timeout);
this.header.outerWidth(this.options.width);
} }
this.options.width = width;
this.width_timeout = window.setTimeout(jQuery.proxy(function() {
this.width_timeout = null;
if(this.div)
{
this.div.outerWidth(this.options.width);
this.header.outerWidth(this.options.width);
}
},this),1); },this),1);
}, },
@ -487,7 +502,6 @@ var et2_calendar_daycol = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResizea
this.div.children('.hiddenEventAfter').remove(); this.div.children('.hiddenEventAfter').remove();
var timegrid = this._parent; var timegrid = this._parent;
var day = this;
// elem is jquery div of event // elem is jquery div of event
function isHidden(elem) { function isHidden(elem) {
@ -511,12 +525,16 @@ var et2_calendar_daycol = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResizea
// Check each event // Check each event
this.iterateOver(function(event) { this.iterateOver(function(event) {
// Skip whole day events and events missing value // Skip whole day events and events missing value
if(!event.options || !event.options.value || event.options.value.whole_day_on_top) return; if(this.display_settings.granularity && (
(!event.options || !event.options.value || event.options.value.whole_day_on_top))
)
{
return;
}
// Reset // Reset
event.title.css('top',''); event.title.css('top','');
event.body.css('padding-top',''); event.body.css('padding-top','');
var hidden = isHidden.call(this,event.div); var hidden = isHidden.call(this,event.div);
if(!hidden) if(!hidden)
{ {
@ -529,68 +547,99 @@ var et2_calendar_daycol = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResizea
event.title.css('top',timegrid.scrolling.scrollTop() - event.div.position().top); event.title.css('top',timegrid.scrolling.scrollTop() - event.div.position().top);
event.body.css('padding-top',timegrid.scrolling.scrollTop() - event.div.position().top); event.body.css('padding-top',timegrid.scrolling.scrollTop() - event.div.position().top);
} }
// Too many in list view, show indicator
else if (this.display_settings.granularity === 0 && hidden.completely)
{
var day = this;
this._hidden_indicator(event, false, function() {
app.calendar.update_state({view: 'day', date: day.date});
});
}
// Completely out of view, show indicator // Completely out of view, show indicator
else if (hidden.completely) else if (hidden.completely)
{ {
var indicator = ''; this._hidden_indicator(event, hidden.hidden == 'top');
if(hidden.hidden === 'top')
{
if($j('.hiddenEventBefore',this.header).length == 0)
{
indicator = $j('<div class="hiddenEventBefore"></div>')
.appendTo(this.header)
.text(event.options.value.title)
.attr('data-hidden_count', 1)
.on('click', function() {
$j('.calendar_calEvent',day.div).first()[0].scrollIntoView();
return false;
});
}
else
{
indicator = $j('.hiddenEventBefore',this.header);
indicator.attr('data-hidden_count', parseInt(indicator.attr('data-hidden_count')) + 1);
indicator.text(day.egw().lang('%1 event(s) %2',indicator.attr('data-hidden_count'),''));
}
}
else if(hidden.hidden === 'bottom')
{
indicator = $j('.hiddenEventAfter',this.div);
if(indicator.length == 0)
{
indicator = $j('<div class="hiddenEventAfter"></div>')
.text(event.options.value.title)
.attr('data-hidden_count', 1)
.appendTo(this.div)
.on('click', function() {
$j('.calendar_calEvent',day.div).last()[0].scrollIntoView(false);
// Better re-run this to clean up
day._out_of_view();
return false;
});
}
else
{
indicator.attr('data-hidden_count', parseInt(indicator.attr('data-hidden_count')) + 1);
indicator.text(day.egw().lang('%1 event(s) %2',indicator.attr('data-hidden_count'),''));
}
indicator.css('top',timegrid.scrolling.height() + timegrid.scrolling.scrollTop()-indicator.height());
}
// Match color to the event
if(indicator !== '')
{
// Avoid white, which is hard to see
var color = jQuery.Color(event.div.css('border-top-color')).toString() !== jQuery.Color('white').toString() ?
event.div.css('border-top-color') : event.div.css('background-color');
// Use border-top-color, Firefox doesn't give a value with border-color
indicator.css('border-color', color);
}
} }
}, this, et2_calendar_event); }, this, et2_calendar_event);
}, },
/**
* Show an indicator that there are hidden events
*
* @param {et2_calendar_event} event Event we're creating the indicator for
* @param {boolean} top Events hidden at the top (true) or bottom (false)
* @param {function} [onclick] Callback for when user clicks on the indicator
*/
_hidden_indicator: function _hidden_indicator(event, top, onclick)
{
var indicator = '';
var day = this;
var timegrid = this._parent;
if(top)
{
if($j('.hiddenEventBefore',this.header).length === 0)
{
indicator = $j('<div class="hiddenEventBefore"></div>')
.appendTo(this.header)
.text(event.options.value.title)
.attr('data-hidden_count', 1)
.on('click', typeof onclick === 'function' ? onclick : function() {
$j('.calendar_calEvent',day.div).first()[0].scrollIntoView();
return false;
});
}
else
{
indicator = $j('.hiddenEventBefore',this.header);
indicator.attr('data-hidden_count', parseInt(indicator.attr('data-hidden_count')) + 1);
indicator.text(day.egw().lang('%1 event(s) %2',indicator.attr('data-hidden_count'),''));
}
}
else
{
indicator = $j('.hiddenEventAfter',this.div);
if(indicator.length === 0)
{
indicator = $j('<div class="hiddenEventAfter"></div>')
.text(event.options.value.title)
.attr('data-hidden_count', 1)
.appendTo(this.div)
.on('click', typeof onclick === 'function' ? onclick : function() {
$j('.calendar_calEvent',day.div).last()[0].scrollIntoView(false);
// Better re-run this to clean up
day._out_of_view();
return false;
});
}
else
{
var count = parseInt(indicator.attr('data-hidden_count')) + 1
indicator.attr('data-hidden_count', count);
if(this.display_settings.granularity === 0)
{
indicator.text(indicator.text() + "\n" + event.options.value.title);
}
else
{
indicator.text(day.egw().lang('%1 event(s) %2',indicator.attr('data-hidden_count'),''));
}
indicator.css('top',timegrid.scrolling.height() + timegrid.scrolling.scrollTop()-indicator.height());
}
}
// Match color to the event
if(indicator !== '')
{
// Avoid white, which is hard to see
// Use border-bottom-color, Firefox doesn't give a value with border-color
var color = jQuery.Color(event.div.css('border-bottom-color')).toString() !== jQuery.Color('white').toString() ?
event.div.css('border-bottom-color') : event.div.css('background-color');
if(color !== 'rgba(0, 0, 0, 0)')
{
indicator.css('border-color', color);
}
}
},
/** /**
* Sort a day's events into minimally overlapping columns * Sort a day's events into minimally overlapping columns
* *
@ -598,6 +647,8 @@ var et2_calendar_daycol = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResizea
*/ */
_spread_events: function() _spread_events: function()
{ {
if(!this.date) return [];
var day_start = this.date.valueOf() / 1000; var day_start = this.date.valueOf() / 1000;
var dst_check = new Date(this.date); var dst_check = new Date(this.date);
dst_check.setUTCHours(12); dst_check.setUTCHours(12);
@ -706,6 +757,21 @@ var et2_calendar_daycol = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResizea
// Calculate vertical positioning // Calculate vertical positioning
var top = 0; var top = 0;
var height = 0; var height = 0;
// Position the event
if(this.display_settings.granularity === 0)
{
if(this.all_day.has(columns[c][i].div).length)
{
columns[c][i].div.prependTo(this.div);
}
columns[c][i].div.css('top', '');
columns[c][i].div.css('height', '');
columns[c][i].div.css('left', '');
columns[c][i].div.css('width', '');
// Strip out of view padding
columns[c][i].body.css('padding-top','');
continue;
}
if(columns[c][i].options.value.whole_day_on_top) if(columns[c][i].options.value.whole_day_on_top)
{ {
if(!this.all_day.has(columns[c][i].div).length) if(!this.all_day.has(columns[c][i].div).length)
@ -878,8 +944,15 @@ var et2_calendar_daycol = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResizea
return; return;
} }
if(this.display_settings.granularity !== this._parent.options.granularity)
{
// Layout has changed
this._draw();
}
// Resize & position all events // Resize & position all events
this.position_event(); this.position_event();
this._out_of_view();
} }
}); });

View File

@ -238,8 +238,8 @@ var et2_calendar_event = et2_valueWidget.extend([et2_IDetachedDOM],
// Let timegrid always get the drag // Let timegrid always get the drag
.droppable('option','greedy',false) .droppable('option','greedy',false)
// ? // Set full day flag
.attr('data-draggable-id',event['id']+'_O'+event.owner+'_C'+(event.owner<0?'group'+Math.abs(event.owner):event.owner)) .attr('data-full_day', event.whole_day_on_top)
// Put everything we need for basic interaction here, so it's available immediately // Put everything we need for basic interaction here, so it's available immediately
.attr('data-id', event.id) .attr('data-id', event.id)
@ -312,6 +312,7 @@ var et2_calendar_event = et2_valueWidget.extend([et2_IDetachedDOM],
{ {
this.body this.body
.html('<span class="calendar_calEventTitle">'+title+'</span>') .html('<span class="calendar_calEventTitle">'+title+'</span>')
.append('<span class="calendar_calTimespan">'+this._get_timespan(event) + '</span>')
.append('<p>'+this.options.value.description+'</p>'); .append('<p>'+this.options.value.description+'</p>');
} }
this.body this.body

View File

@ -55,7 +55,7 @@ var et2_calendar_timegrid = et2_calendar_view.extend([et2_IDetachedDOM, et2_IRes
name: "Granularity", name: "Granularity",
type: "integer", type: "integer",
default: parseInt(egw.preference('interval','calendar')) || 30, default: parseInt(egw.preference('interval','calendar')) || 30,
description: "How many minutes per row" description: "How many minutes per row, or 0 to display events as a list"
}, },
"onchange": { "onchange": {
"name": "onchange", "name": "onchange",
@ -194,6 +194,9 @@ var et2_calendar_timegrid = et2_calendar_view.extend([et2_IDetachedDOM, et2_IRes
* for planner view to resize horizontally. * for planner view to resize horizontally.
*/ */
this.div.on('mouseover', '.calendar_calEvent:not(.ui-resizable):not(.rowNoEdit)', function() { this.div.on('mouseover', '.calendar_calEvent:not(.ui-resizable):not(.rowNoEdit)', function() {
// Only resize in timegrid
if(timegrid.options.granularity === 0) return;
// Load the event // Load the event
timegrid._get_event_info(this); timegrid._get_event_info(this);
var that = this; var that = this;
@ -331,7 +334,7 @@ var et2_calendar_timegrid = et2_calendar_view.extend([et2_IDetachedDOM, et2_IRes
{ {
this.scrolling.scrollTop(element.dropEnd.position().top); this.scrolling.scrollTop(element.dropEnd.position().top);
} }
else if (element.dropEnd.prev() && element.dropEnd.prev().position().top < this.scrolling[0].scrollTop) else if (element.dropEnd.prev().length && element.dropEnd.prev().position().top < this.scrolling[0].scrollTop)
{ {
this.scrolling.scrollTop(element.dropEnd.prev().position().top); this.scrolling.scrollTop(element.dropEnd.prev().position().top);
} }
@ -341,6 +344,12 @@ var et2_calendar_timegrid = et2_calendar_view.extend([et2_IDetachedDOM, et2_IRes
{ {
time = this.egw().lang('Whole day'); time = this.egw().lang('Whole day');
} }
else if (this.options.granularity === 0)
{
// No times, keep what's in the event
// Add class to helper to keep formatting
$j(helper).addClass('calendar_calTimeGridList');
}
else else
{ {
time = jQuery.datepicker.formatTime( time = jQuery.datepicker.formatTime(
@ -392,7 +401,13 @@ var et2_calendar_timegrid = et2_calendar_view.extend([et2_IDetachedDOM, et2_IRes
if(event_data.app == 'calendar' && event_widget.options.value.whole_day) if(event_data.app == 'calendar' && event_widget.options.value.whole_day)
{ {
event_widget._parent.date_helper.set_hours(0); event_widget._parent.date_helper.set_hours(0);
event_widget._parent.date_helper.set_minutes(0) event_widget._parent.date_helper.set_minutes(0);
}
else if (timegrid.options.granularity === 0)
{
// List, not time grid - keep time
event_widget._parent.date_helper.set_hours(event_widget.options.value.start.getUTCHours());
event_widget._parent.date_helper.set_minutes(event_widget.options.value.start.getUTCMinutes());
} }
else else
{ {
@ -507,6 +522,7 @@ var et2_calendar_timegrid = et2_calendar_view.extend([et2_IDetachedDOM, et2_IRes
} }
this.update_timer = window.setTimeout(jQuery.proxy(function() { this.update_timer = window.setTimeout(jQuery.proxy(function() {
this.widget.update_timer = null; this.widget.update_timer = null;
window.clearTimeout(this.resize_timer);
this.widget.loader.hide().show(); this.widget.loader.hide().show();
// Update actions // Update actions
@ -600,12 +616,8 @@ var et2_calendar_timegrid = et2_calendar_view.extend([et2_IDetachedDOM, et2_IRes
_drawTimes: function() { _drawTimes: function() {
$j('.calendar_calTimeRow',this.div).remove(); $j('.calendar_calTimeRow',this.div).remove();
var wd_start = 60*this.options.day_start; this.div.toggleClass('calendar_calTimeGridList', this.options.granularity === 0);
var wd_end = 60*this.options.day_end;
var granularity = this.options.granularity;
var totalDisplayMinutes = wd_end - wd_start;
var rowsToDisplay = Math.ceil((totalDisplayMinutes+60)/granularity);
this.gridHeader this.gridHeader
.attr('data-date', this.options.start_date) .attr('data-date', this.options.start_date)
.attr('data-owner', this.options.owner) .attr('data-owner', this.options.owner)
@ -613,14 +625,35 @@ var et2_calendar_timegrid = et2_calendar_view.extend([et2_IDetachedDOM, et2_IRes
.append(this.owner.getDOMNode()) .append(this.owner.getDOMNode())
.append(this.dayHeader) .append(this.dayHeader)
.appendTo(this.div); .appendTo(this.div);
// Max with 18 avoids problems when it's not shown
var header_height = Math.max(this.gridHeader.outerHeight(true), 18);
this.scrolling
.appendTo(this.div)
.off()
// No time grid - list
if(this.options.granularity === 0)
{
this.scrolling.css('height','100%');
this.days.css('height', '100%');
this.iterateOver(function(day) {
day.resize();
},this,et2_calendar_daycol);
return;
}
var wd_start = 60*this.options.day_start;
var wd_end = 60*this.options.day_end;
var granularity = this.options.granularity;
var totalDisplayMinutes = wd_end - wd_start;
var rowsToDisplay = Math.ceil((totalDisplayMinutes+60)/granularity);
// Max with 45 avoids problems when it's not shown
var header_height = Math.max(this.gridHeader.outerHeight(true), 45);
this.scrolling this.scrolling
.css('height', (this.div.innerHeight() - header_height)+'px') .css('height', (this.div.innerHeight() - header_height)+'px')
.appendTo(this.div) .on('scroll', jQuery.proxy(this._scroll, this));
.off().on('scroll', jQuery.proxy(this._scroll, this));
// Percent // Percent
var rowHeight = (100/rowsToDisplay).toFixed(1); var rowHeight = (100/rowsToDisplay).toFixed(1);
@ -701,6 +734,9 @@ var et2_calendar_timegrid = et2_calendar_view.extend([et2_IDetachedDOM, et2_IRes
{ {
window.clearTimeout(this.resize_timer); window.clearTimeout(this.resize_timer);
} }
// No point if it is just going to be redone completely
if(this.upate_timer) return;
this.resize_timer = window.setTimeout(jQuery.proxy(function() { this.resize_timer = window.setTimeout(jQuery.proxy(function() {
if(this._resizeTimes) if(this._resizeTimes)
{ {
@ -727,12 +763,23 @@ var et2_calendar_timegrid = et2_calendar_view.extend([et2_IDetachedDOM, et2_IRes
var new_height = this.scrolling.height() / rowsToDisplay; var new_height = this.scrolling.height() / rowsToDisplay;
this.rowHeight = new_height; this.rowHeight = new_height;
var rows = $j('.calendar_calTimeRow',this.scrolling).height(this.rowHeight); var rows = $j('.calendar_calTimeRow',this.scrolling).height(this.rowHeight);
this.days.css('height', (this.rowHeight*rows.length)+'px'); if(!rows.length && this.options.granularity)
{
return this._drawTimes();
}
this.days.css('height', this.options.granularity === 0 ?
'100%' :
(this.rowHeight*rows.length)+'px'
);
$j('.calendar_calAddEvent',this.scrolling).height(this.rowHeight); $j('.calendar_calAddEvent',this.scrolling).height(this.rowHeight);
// Scroll to start of day // Scroll to start of day
this._top_time = (wd_start * this.rowHeight) / this.options.granularity; this._top_time = (wd_start * this.rowHeight) / this.options.granularity;
this.scrolling.scrollTop(this._top_time); this.scrolling.scrollTop(this._top_time);
this.iterateOver(function(child) {
child.resize();
},this, et2_IResizeable);
}, },
/** /**
@ -749,7 +796,9 @@ var et2_calendar_timegrid = et2_calendar_view.extend([et2_IDetachedDOM, et2_IRes
this.day_list = this._calculate_day_list(this.options.start_date, this.options.end_date, this.options.show_weekend); this.day_list = this._calculate_day_list(this.options.start_date, this.options.end_date, this.options.show_weekend);
} }
// For a single day, we show each owner in their own daycol // For a single day, we show each owner in their own daycol
var daily_owner = this.day_list.length === 1 && this.options.owner.length < parseInt(egw.preference('day_consolidate','calendar')); var daily_owner = this.day_list.length === 1 &&
this.options.owner.length > 1 &&
this.options.owner.length < parseInt(egw.preference('day_consolidate','calendar'));
var daycols_needed = daily_owner ? this.options.owner.length : this.day_list.length; var daycols_needed = daily_owner ? this.options.owner.length : this.day_list.length;
var day_width = ( Math.min( $j(this.getInstanceManager().DOMContainer).width(),this.days.width())/daycols_needed); var day_width = ( Math.min( $j(this.getInstanceManager().DOMContainer).width(),this.days.width())/daycols_needed);
if(!day_width || !this.day_list) if(!day_width || !this.day_list)
@ -815,6 +864,9 @@ var et2_calendar_timegrid = et2_calendar_view.extend([et2_IDetachedDOM, et2_IRes
this.day_widgets.splice(delete_index--,1); this.day_widgets.splice(delete_index--,1);
} }
// Adjust and scroll to start of day
this.resizeTimes();
// Create / update day widgets with dates and data // Create / update day widgets with dates and data
for(var i = 0; i < this.day_widgets.length; i++) for(var i = 0; i < this.day_widgets.length; i++)
{ {
@ -848,9 +900,6 @@ var et2_calendar_timegrid = et2_calendar_view.extend([et2_IDetachedDOM, et2_IRes
this.set_label(''); this.set_label('');
} }
// Adjust and scroll to start of day
this._resizeTimes();
// Handle not fully visible elements // Handle not fully visible elements
this._scroll(); this._scroll();
@ -1356,15 +1405,24 @@ var et2_calendar_timegrid = et2_calendar_view.extend([et2_IDetachedDOM, et2_IRes
*/ */
set_granularity: function(minutes) set_granularity: function(minutes)
{ {
// Avoid 0 or less // Avoid < 0
minutes = Math.max(1,minutes); minutes = Math.max(0,minutes);
if(this.options.granularity !== minutes) if(this.options.granularity !== minutes)
{ {
this.options.granularity = minutes; if(this.options.granularity === 0 || minutes === 0)
this._drawTimes(); {
this.options.granularity = minutes;
// Need to re-do a bunch to make sure this is propagated
this.invalidate();
}
else
{
this.options.granularity = minutes;
this._drawTimes();
}
} }
else else if (!this.update_timer)
{ {
this.resizeTimes(); this.resizeTimes();
} }
@ -1545,13 +1603,20 @@ var et2_calendar_timegrid = et2_calendar_view.extend([et2_IDetachedDOM, et2_IRes
x = Math.round(x); x = Math.round(x);
y = Math.round(y); y = Math.round(y);
var nodes = $j('.calendar_calAddEvent[data-hour],.calendar_calDayColHeader',this.div).removeClass('drop-hover').filter(function() { var nodes = this.options.granularity === 0 ?
var offset = $j(this).offset(); $j('.calendar_calDayCol',this.div) :
var range={x:[offset.left,offset.left+$j(this).outerWidth()],y:[offset.top,offset.top+$j(this).outerHeight()]}; $j('.calendar_calAddEvent[data-hour],.calendar_calDayColHeader',this.div);
var i = (x >=range.x[0] && x <= range.x[1]) && (y >= range.y[0] && y <= range.y[1]); nodes = nodes
return i; .removeClass('drop-hover')
}).addClass("drop-hover"); .filter(function() {
var offset = $j(this).offset();
var range={x:[offset.left,offset.left+$j(this).outerWidth()],y:[offset.top,offset.top+$j(this).outerHeight()]};
var i = (x >=range.x[0] && x <= range.x[1]) && (y >= range.y[0] && y <= range.y[1]);
return i;
})
nodes.addClass("drop-hover");
return nodes; return nodes;
}, },
@ -1611,7 +1676,7 @@ var et2_calendar_timegrid = et2_calendar_view.extend([et2_IDetachedDOM, et2_IRes
height -= $j('#calendar-toolbar').outerHeight(true); height -= $j('#calendar-toolbar').outerHeight(true);
this.options.height = Math.floor(height / rowCount); this.options.height = Math.floor(height / rowCount);
// Allow for borders & padding // Allow for borders & padding
this.options.height -= 2*((this.div.outerWidth(true) - this.div.innerWidth()) + parseInt(this.div.parent().css('padding-top'))); this.options.height -= 2*((this.div.outerWidth(true) - this.div.innerWidth()) + parseInt(this.div.parent().css('padding-top')));
if(this.options.height+"px" !== this.div.css('height')) if(this.options.height+"px" !== this.div.css('height'))
@ -1626,9 +1691,9 @@ var et2_calendar_timegrid = et2_calendar_view.extend([et2_IDetachedDOM, et2_IRes
} }
// Try to resize width, though animations cause problems // Try to resize width, though animations cause problems
var total_width = ( $j(this.getInstanceManager().DOMContainer).width() - ( var total_width = Math.min(this.div.width(),( $j(this.getInstanceManager().DOMContainer).width() - (
this.days.innerWidth() ? this.div.innerWidth() - this.days.innerWidth() : 0 this.days.innerWidth() ? this.div.innerWidth() - this.days.innerWidth() : 0
)); )));
var day_width = (total_width > 0 ? total_width : $j(this.getInstanceManager().DOMContainer).width())/this.day_widgets.length; var day_width = (total_width > 0 ? total_width : $j(this.getInstanceManager().DOMContainer).width())/this.day_widgets.length;
// update day widgets // update day widgets
for(var i = 0; i < this.day_widgets.length; i++) for(var i = 0; i < this.day_widgets.length; i++)

View File

@ -10,7 +10,7 @@
*/ */
$setup_info['calendar']['name'] = 'calendar'; $setup_info['calendar']['name'] = 'calendar';
$setup_info['calendar']['version'] = '14.3.902'; $setup_info['calendar']['version'] = '14.3.903';
$setup_info['calendar']['app_order'] = 3; $setup_info['calendar']['app_order'] = 3;
$setup_info['calendar']['enable'] = 1; $setup_info['calendar']['enable'] = 1;
$setup_info['calendar']['index'] = 'calendar.calendar_uiviews.index&ajax=true'; $setup_info['calendar']['index'] = 'calendar.calendar_uiviews.index&ajax=true';

View File

@ -2683,3 +2683,23 @@ function calendar_upgrade14_3_901()
}); });
return $GLOBALS['setup_info']['calendar']['currentver'] = '14.3.902'; return $GLOBALS['setup_info']['calendar']['currentver'] = '14.3.902';
} }
/**
* Change grid/list preference values to list each view
*/
function calendar_upgrade14_3_902()
{
preferences::change_preference('calendar', 'use_time_grid', function($attr, $old_value, $owner) {
switch($old_value)
{
case 'all':
return 0;
case 'day_week':
return ['day','day4','week'];
case 'day4':
return ['day','day4'];
}
return null;
});
return $GLOBALS['setup_info']['calendar']['currentver'] = '14.3.903';
}

View File

@ -191,6 +191,7 @@ e.g. the div with class calendar_calTimeGrid is generated by the timeGridWidget
width: 100%; width: 100%;
overflow-y: auto; overflow-y: auto;
overflow-x: hidden; overflow-x: hidden;
cursor: default;
} }
.calendar_calTimeGrid .loading,.calendar_plannerWidget .loading { .calendar_calTimeGrid .loading,.calendar_plannerWidget .loading {
@ -298,6 +299,7 @@ e.g. the div with class calendar_calTimeGrid is generated by the timeGridWidget
border-right: 0px; border-right: 0px;
overflow: hidden; overflow: hidden;
z-index: 40; z-index: 40;
cursor: pointer;
} }
.calendar_calDayColHeader .hiddenEventBefore { .calendar_calDayColHeader .hiddenEventBefore {
height: 2px; height: 2px;
@ -602,7 +604,9 @@ e.g. the div with class calendar_calTimeGrid is generated by the timeGridWidget
.calendar_calEventBody > p, .calendar_calEventBodySmall > p { .calendar_calEventBody > p, .calendar_calEventBodySmall > p {
white-space: pre-wrap; white-space: pre-wrap;
} }
.calendar_calEventBody .calendar_calTimespan {
display: none;
}
.calendar_calEventBodySmall{ .calendar_calEventBodySmall{
font-size: 95%; font-size: 95%;
} }
@ -615,6 +619,59 @@ e.g. the div with class calendar_calTimeGrid is generated by the timeGridWidget
font-weight: bold; font-weight: bold;
} }
/* Events as displayed in a list, not sized by time */
.calendar_calTimeGridList .calendar_calTimeGridScroll {
overflow-y: hidden;
}
.calendar_calTimeGridList .calendar_calGridHeader {
min-height: 1em;
}
.calendar_calTimeGridList .calendar_calDayColAllDay {
display: none;
}
.calendar_calTimeGridList .calendar_calDayColHeader {
min-height: initial;
padding-bottom: 0px;
}
.calendar_calTimeGridList .calendar_calEvent {
min-height: 1.1em;
position: relative;
}
.calendar_calTimeGridList .calendar_calEvent:not([data-full_day]) {
border-top: none;
border-left: none;
border-right: none;
}
.calendar_calTimeGridList .calendar_calEventHeader {
display: none !important;
}
.calendar_calTimeGridList .calendar_calEventTitle {
font-weight: normal;
display: inline-block;
max-height:2.4em;
white-space: nowrap;
}
.calendar_calTimeGridList .calendar_calEventBody:not(.calendar_calEventBodySmall) {
overflow: hidden;
}
.calendar_calTimeGridList .calendar_calEventBody .calendar_calTimespan {
display: inline-block;
float: right;
padding-left: 1em;
opacity: 0.8;
font-size: 90%
}
.calendar_calTimeGridList .calendar_calEventBody > p {
display: none;
}
.calendar_calTimeGridList .calendar_calDayCol .hiddenEventAfter:hover {
/* Need !important to override calculated height*/
top: initial !important;
bottom: 0px;
white-space: pre;
height: 100%;
}
/* table of the dayView containing 2 cols: 1) day-view, 2) todos /* table of the dayView containing 2 cols: 1) day-view, 2) todos
*/ */
.calendar_calDayView{ .calendar_calDayView{