Implement client-side and user-adjustable sorting of tasks (#3259)
This commit is contained in:
parent
aa63f121c8
commit
b6b12069df
9 changed files with 174 additions and 37 deletions
|
@ -1,4 +1,11 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
$rcmail_config['tasklist_driver'] = 'kolab';
|
// backend type (database, kolab)
|
||||||
|
$config['tasklist_driver'] = 'kolab';
|
||||||
|
|
||||||
|
// default sorting order of tasks listing (auto, datetime, startdatetime, flagged, complete, changed)
|
||||||
|
$config['tasklist_sort_col'] = '';
|
||||||
|
|
||||||
|
// default sorting order for tasks listing (asc or desc)
|
||||||
|
$config['tasklist_sort_order'] = 'asc';
|
||||||
|
|
||||||
|
|
|
@ -794,8 +794,11 @@ class tasklist_kolab_driver extends tasklist_driver
|
||||||
if (!$record['start']->_dateonly)
|
if (!$record['start']->_dateonly)
|
||||||
$task['starttime'] = $start->format('H:i');
|
$task['starttime'] = $start->format('H:i');
|
||||||
}
|
}
|
||||||
if (is_a($record['dtstamp'], 'DateTime')) {
|
if (is_a($record['changed'], 'DateTime')) {
|
||||||
$task['changed'] = $record['dtstamp'];
|
$task['changed'] = $record['changed'];
|
||||||
|
}
|
||||||
|
if (is_a($record['created'], 'DateTime')) {
|
||||||
|
$task['created'] = $record['created'];
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($record['valarms']) {
|
if ($record['valarms']) {
|
||||||
|
@ -912,7 +915,7 @@ class tasklist_kolab_driver extends tasklist_driver
|
||||||
$object['sequence'] = $old['sequence'];
|
$object['sequence'] = $old['sequence'];
|
||||||
}
|
}
|
||||||
|
|
||||||
unset($object['tempid'], $object['raw'], $object['list'], $object['flagged'], $object['tags']);
|
unset($object['tempid'], $object['raw'], $object['list'], $object['flagged'], $object['tags'], $object['created']);
|
||||||
return $object;
|
return $object;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,10 +34,13 @@ $labels['status-in-process'] = 'In process';
|
||||||
$labels['status-completed'] = 'Completed';
|
$labels['status-completed'] = 'Completed';
|
||||||
$labels['status-cancelled'] = 'Cancelled';
|
$labels['status-cancelled'] = 'Cancelled';
|
||||||
$labels['assignedto'] = 'Assigned to';
|
$labels['assignedto'] = 'Assigned to';
|
||||||
|
$labels['created'] = 'Created';
|
||||||
|
$labels['changed'] = 'Last Modified';
|
||||||
|
|
||||||
$labels['all'] = 'All';
|
$labels['all'] = 'All';
|
||||||
$labels['flagged'] = 'Flagged';
|
$labels['flagged'] = 'Flagged';
|
||||||
$labels['complete'] = 'Complete';
|
$labels['complete'] = 'Complete';
|
||||||
|
$labels['completeness'] = 'Progress';
|
||||||
$labels['overdue'] = 'Overdue';
|
$labels['overdue'] = 'Overdue';
|
||||||
$labels['today'] = 'Today';
|
$labels['today'] = 'Today';
|
||||||
$labels['tomorrow'] = 'Tomorrow';
|
$labels['tomorrow'] = 'Tomorrow';
|
||||||
|
@ -49,6 +52,7 @@ $labels['mytasks'] = 'My tasks';
|
||||||
$labels['mytaskstitle'] = 'Tasks assigned to you';
|
$labels['mytaskstitle'] = 'Tasks assigned to you';
|
||||||
$labels['nodate'] = 'no date';
|
$labels['nodate'] = 'no date';
|
||||||
$labels['removetag'] = 'Remove';
|
$labels['removetag'] = 'Remove';
|
||||||
|
$labels['auto'] = 'Auto';
|
||||||
|
|
||||||
$labels['taskdetails'] = 'Details';
|
$labels['taskdetails'] = 'Details';
|
||||||
$labels['newtask'] = 'New Task';
|
$labels['newtask'] = 'New Task';
|
||||||
|
@ -74,7 +78,7 @@ $labels['listactions'] = 'List options...';
|
||||||
$labels['listname'] = 'Name';
|
$labels['listname'] = 'Name';
|
||||||
$labels['showalarms'] = 'Show reminders';
|
$labels['showalarms'] = 'Show reminders';
|
||||||
$labels['import'] = 'Import';
|
$labels['import'] = 'Import';
|
||||||
$labels['viewoptions'] = 'View options';
|
$labels['viewactions'] = 'View actions';
|
||||||
$labels['focusview'] = 'View only this list';
|
$labels['focusview'] = 'View only this list';
|
||||||
|
|
||||||
// date words
|
// date words
|
||||||
|
@ -172,3 +176,5 @@ $labels['itipresponseerror'] = 'Failed to send the response to this task assignm
|
||||||
$labels['itipinvalidrequest'] = 'This invitation is no longer valid';
|
$labels['itipinvalidrequest'] = 'This invitation is no longer valid';
|
||||||
$labels['sentresponseto'] = 'Successfully sent assignment response to $mailto';
|
$labels['sentresponseto'] = 'Successfully sent assignment response to $mailto';
|
||||||
$labels['successremoval'] = 'The task has been deleted successfully.';
|
$labels['successremoval'] = 'The task has been deleted successfully.';
|
||||||
|
|
||||||
|
$labels['arialabelsortmenu'] = 'Tasks sorting options';
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 6.3 KiB |
|
@ -507,13 +507,14 @@ body.tasklist.attachmentwin #mainscreen {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.buttonbar-right .listmenu .inner {
|
.buttonbar-right a.iconbutton {
|
||||||
display: inline-block;
|
|
||||||
height: 18px;
|
|
||||||
width: 20px;
|
|
||||||
padding: 0;
|
padding: 0;
|
||||||
background: url(sprites.png) 0 -237px no-repeat;
|
background-image: url(sprites.png);
|
||||||
text-indent: -5000px;
|
background-position: 0 -238px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.buttonbar-right a.iconbutton.sorting {
|
||||||
|
background-position: -18px -347px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#thelist {
|
#thelist {
|
||||||
|
@ -728,7 +729,8 @@ body.tasklist.attachmentwin #mainscreen {
|
||||||
|
|
||||||
ul.toolbarmenu li span.add,
|
ul.toolbarmenu li span.add,
|
||||||
ul.toolbarmenu li span.expand,
|
ul.toolbarmenu li span.expand,
|
||||||
ul.toolbarmenu li span.collapse {
|
ul.toolbarmenu li span.collapse,
|
||||||
|
ul.toolbarmenu.iconized .selected span.icon {
|
||||||
background-image: url(sprites.png);
|
background-image: url(sprites.png);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -748,6 +750,14 @@ ul.toolbarmenu li span.delete {
|
||||||
background-position: 0 -1508px;
|
background-position: 0 -1508px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ul.toolbarmenu.iconized .selected span.icon {
|
||||||
|
background-position: 0 -324px;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul.toolbarmenu .sortcol.by-auto a {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
.taskitem-draghelper {
|
.taskitem-draghelper {
|
||||||
/*
|
/*
|
||||||
width: 32px;
|
width: 32px;
|
||||||
|
@ -975,6 +985,10 @@ div.form-section {
|
||||||
margin-bottom: 0.3em;
|
margin-bottom: 0.3em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tasklistview div.form-section span.task-text + label {
|
||||||
|
margin-left: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
label.block {
|
label.block {
|
||||||
display: block;
|
display: block;
|
||||||
margin-bottom: 0.3em;
|
margin-bottom: 0.3em;
|
||||||
|
|
|
@ -97,12 +97,31 @@
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<div class="buttonbar-right">
|
<div class="buttonbar-right">
|
||||||
<roundcube:button name="taskviewmenulink" id="taskviewmenulink" type="link" title="tasklist.viewoptions" class="listmenu viewoptions" onclick="return UI.toggle_popup('taskviewmenu',event)" innerClass="inner" label="tasklist.viewoptions" aria-haspopup="true" aria-expanded="false" aria-owns="taskviewmenu-menu" />
|
<roundcube:button name="taskviewactionslink" id="taskviewactionslink" type="link" title="tasklist.viewactions" class="iconbutton viewactions" onclick="return UI.toggle_popup('taskviewactions',event)" label="tasklist.viewactions" aria-haspopup="true" aria-expanded="false" aria-owns="taskviewactions-menu" />
|
||||||
|
<roundcube:button name="taskviewsortmenulink" id="taskviewsortmenulink" type="link" title="sortby" class="iconbutton sorting" onclick="return UI.toggle_popup('taskviewsortmenu',event)" label="sortby" aria-haspopup="true" aria-expanded="false" aria-owns="taskviewsortmenu-menu" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="taskviewmenu" class="popupmenu" aria-hidden="true">
|
<div id="taskviewsortmenu" class="popupmenu" aria-hidden="true" data-align="right">
|
||||||
<h3 id="aria-label-taskviewmenu" class="voice"><roundcube:label name="tasklist.viewoptions" /></h3>
|
<h3 id="aria-label-taskviewsortmenu" class="voice"><roundcube:label name="tasklist.arialabelsortmenu" /></h3>
|
||||||
<ul class="toolbarmenu" id="taskviewmenu-menu" role="menu" aria-labelledby="aria-label-taskviewmenu">
|
<ul class="toolbarmenu iconized" id="taskviewsortmenu-menu" role="menu" aria-labelledby="aria-label-taskviewsortmenu">
|
||||||
|
<ul role="radiogroup" aria-label="<roundcube:label name='sortby' />">
|
||||||
|
<li><roundcube:button command="list-sort" prop="auto" type="link" label="tasklist.auto" role="radio" aria-checked="false" class="sortcol by-auto icon active" innerclass="icon" /></li>
|
||||||
|
<li><roundcube:button command="list-sort" prop="datetime" type="link" label="tasklist.datetime" role="radio" aria-checked="false" class="sortcol by-datetime icon active" innerclass="icon" /></li>
|
||||||
|
<li><roundcube:button command="list-sort" prop="startdatetime" type="link" label="tasklist.start" role="radio" aria-checked="false" class="sortcol by-startdatetime icon active" innerclass="icon" /></li>
|
||||||
|
<li><roundcube:button command="list-sort" prop="flagged" type="link" label="tasklist.flagged" role="radio" aria-checked="false" class="sortcol by-flagged icon active" innerclass="icon" /></li>
|
||||||
|
<li><roundcube:button command="list-sort" prop="complete" type="link" label="tasklist.completeness" role="radio" aria-checked="false" class="sortcol by-complete icon active" innerclass="icon" /></li>
|
||||||
|
<li><roundcube:button command="list-sort" prop="changed" type="link" label="tasklist.changed" role="radio" aria-checked="false" class="sortcol by-changed icon active" innerclass="icon" /></li>
|
||||||
|
</ul>
|
||||||
|
<li role="separator" class="separator"><label id="aria-label-taskviewsortorder"><roundcube:label name="listorder" /></label></li>
|
||||||
|
<ul role="radiogroup" aria-labelledby="aria-label-taskviewsortorder">
|
||||||
|
<li><roundcube:button command="list-order" prop="asc" type="link" label="sortasc" role="radio" aria-checked="false" class="sortorder asc icon" classAct="icon sortorder asc active" innerclass="icon" /></li>
|
||||||
|
<li><roundcube:button command="list-order" prop="desc" type="link" label="sortdesc" role="radio" aria-checked="false" class="sortorder desc icon" classAct="icon sortorder desc active" innerclass="icon" /></li>
|
||||||
|
</ul>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div id="taskviewactions" class="popupmenu" aria-hidden="true" data-align="right">
|
||||||
|
<h3 id="aria-label-taskviewactions" class="voice"><roundcube:label name="tasklist.viewactions" /></h3>
|
||||||
|
<ul class="toolbarmenu" id="taskviewactions-menu" role="menu" aria-labelledby="aria-label-taskviewactions">
|
||||||
<li role="menuitem"><roundcube:button command="expand-all" label="expand-all" class="icon" classAct="icon active" innerclass="icon expand" /></li>
|
<li role="menuitem"><roundcube:button command="expand-all" label="expand-all" class="icon" classAct="icon active" innerclass="icon expand" /></li>
|
||||||
<li role="menuitem"><roundcube:button command="collapse-all" label="collapse-all" class="icon" classAct="icon active" innerclass="icon collapse" /></li>
|
<li role="menuitem"><roundcube:button command="collapse-all" label="collapse-all" class="icon" classAct="icon active" innerclass="icon collapse" /></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
|
@ -256,6 +256,13 @@ function rcube_tasklist_ui(settings)
|
||||||
setTimeout(fetch_counts, 200);
|
setTimeout(fetch_counts, 200);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
rcmail.register_command('list-sort', list_set_sort, true);
|
||||||
|
rcmail.register_command('list-order', list_set_order, (settings.sort_col || 'auto') != 'auto');
|
||||||
|
|
||||||
|
$('#taskviewsortmenu .by-' + (settings.sort_col || 'auto')).attr('aria-checked', 'true').addClass('selected');
|
||||||
|
$('#taskviewsortmenu .sortorder.' + (settings.sort_order || 'asc')).attr('aria-checked', 'true').addClass('selected');
|
||||||
|
|
||||||
|
|
||||||
// start loading tasks
|
// start loading tasks
|
||||||
fetch_counts();
|
fetch_counts();
|
||||||
list_tasks();
|
list_tasks();
|
||||||
|
@ -743,6 +750,9 @@ function rcube_tasklist_ui(settings)
|
||||||
listdata[listdata[id].parent_id].children.push(id);
|
listdata[listdata[id].parent_id].children.push(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// sort index before rendering
|
||||||
|
listindex.sort(function(a, b) { return task_cmp(listdata[a], listdata[b]); });
|
||||||
|
|
||||||
append_tags(response.tags || []);
|
append_tags(response.tags || []);
|
||||||
render_tasklist();
|
render_tasklist();
|
||||||
|
|
||||||
|
@ -1016,6 +1026,14 @@ function rcube_tasklist_ui(settings)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// copy _depth property from old rec or derive from parent
|
||||||
|
if (rec.parent_id && listdata[rec.parent_id]) {
|
||||||
|
rec._depth = (listdata[rec.parent_id]._depth || 0) + 1;
|
||||||
|
}
|
||||||
|
else if (oldrec) {
|
||||||
|
rec._depth = oldrec._depth || 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (list.active || rec.tempid) {
|
if (list.active || rec.tempid) {
|
||||||
if (!filter || match_filter(rec, {}))
|
if (!filter || match_filter(rec, {}))
|
||||||
render_task(rec, oldid);
|
render_task(rec, oldid);
|
||||||
|
@ -1294,10 +1312,33 @@ function rcube_tasklist_ui(settings)
|
||||||
*/
|
*/
|
||||||
function task_cmp(a, b)
|
function task_cmp(a, b)
|
||||||
{
|
{
|
||||||
var d = is_complete(a) - is_complete(b);
|
// sort by hierarchy level first
|
||||||
|
if ((a._depth || 0) != (b._depth || 0))
|
||||||
|
return a._depth - b._depth;
|
||||||
|
|
||||||
|
var p, alt, inv = 1, c = is_complete(a) - is_complete(b), d = c;
|
||||||
|
|
||||||
|
// completed tasks always move to the end
|
||||||
|
if (c != 0)
|
||||||
|
return c;
|
||||||
|
|
||||||
|
// custom sorting
|
||||||
|
if (settings.sort_col && settings.sort_col != 'auto') {
|
||||||
|
alt = settings.sort_col == 'datetime' || settings.sort_col == 'startdatetime' ? 99999999999 : 0
|
||||||
|
d = (a[settings.sort_col]||alt) - (b[settings.sort_col]||alt);
|
||||||
|
inv = settings.sort_order == 'desc' ? -1 : 1;
|
||||||
|
}
|
||||||
|
// default sorting (auto)
|
||||||
|
else {
|
||||||
if (!d) d = (b._hasdate-0) - (a._hasdate-0);
|
if (!d) d = (b._hasdate-0) - (a._hasdate-0);
|
||||||
if (!d) d = (a.datetime||99999999999) - (b.datetime||99999999999);
|
if (!d) d = (a.datetime||99999999999) - (b.datetime||99999999999);
|
||||||
return d;
|
}
|
||||||
|
|
||||||
|
// fall-back to created/changed date
|
||||||
|
if (!d) d = (a.created||0) - (b.created||0);
|
||||||
|
if (!d) d = (a.changed||0) - (b.changed||0);
|
||||||
|
|
||||||
|
return d * inv;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1688,6 +1729,12 @@ function rcube_tasklist_ui(settings)
|
||||||
$('#task-recurrence').hide();
|
$('#task-recurrence').hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rec.created || rec.changed) {
|
||||||
|
$('#task-created-changed .task-created').html(Q(rec.created_ || rcmail.gettext('unknown','tasklist')))
|
||||||
|
$('#task-created-changed .task-changed').html(Q(rec.changed_ || rcmail.gettext('unknown','tasklist')))
|
||||||
|
$('#task-created-changed').show()
|
||||||
|
}
|
||||||
|
|
||||||
// build attachments list
|
// build attachments list
|
||||||
$('#task-attachments').hide();
|
$('#task-attachments').hide();
|
||||||
if ($.isArray(rec.attachments)) {
|
if ($.isArray(rec.attachments)) {
|
||||||
|
@ -2179,12 +2226,12 @@ function rcube_tasklist_ui(settings)
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
var remove_attachment = function(elem, id)
|
function remove_attachment(elem, id)
|
||||||
{
|
{
|
||||||
$(elem.parentNode).hide();
|
$(elem.parentNode).hide();
|
||||||
me.selected_task.deleted_attachments.push(id);
|
me.selected_task.deleted_attachments.push(id);
|
||||||
delete rcmail.env.attachments[id];
|
delete rcmail.env.attachments[id];
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -2363,6 +2410,45 @@ function rcube_tasklist_ui(settings)
|
||||||
return $.unqiqueStrings(itags);
|
return $.unqiqueStrings(itags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Change tasks list sorting
|
||||||
|
*/
|
||||||
|
function list_set_sort(col)
|
||||||
|
{
|
||||||
|
if (settings.sort_col != col) {
|
||||||
|
settings.sort_col = col;
|
||||||
|
$('#taskviewsortmenu .sortcol').attr('aria-checked', 'false').removeClass('selected')
|
||||||
|
.filter('.by-' + col).attr('aria-checked', 'true').addClass('selected');
|
||||||
|
|
||||||
|
// re-sort list index and re-render list
|
||||||
|
listindex.sort(function(a, b) { return task_cmp(listdata[a], listdata[b]); });
|
||||||
|
render_tasklist();
|
||||||
|
|
||||||
|
rcmail.enable_command('list-order', settings.sort_col != 'auto');
|
||||||
|
$('#taskviewsortmenu .sortorder').removeClass('selected').filter('[aria-checked=true]').addClass('selected');
|
||||||
|
|
||||||
|
rcmail.save_pref({ name: 'tasklist_sort_col', value: (col == 'auto' ? '' : col) });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Change tasks list sort order
|
||||||
|
*/
|
||||||
|
function list_set_order(order)
|
||||||
|
{
|
||||||
|
if (settings.sort_order != order) {
|
||||||
|
settings.sort_order = order;
|
||||||
|
$('#taskviewsortmenu .sortorder').attr('aria-checked', 'false').removeClass('selected')
|
||||||
|
.filter('.' + order).attr('aria-checked', 'true').addClass('selected');
|
||||||
|
|
||||||
|
// re-sort list index and re-render list
|
||||||
|
listindex.sort(function(a, b) { return task_cmp(listdata[a], listdata[b]); });
|
||||||
|
render_tasklist();
|
||||||
|
|
||||||
|
rcmail.save_pref({ name: 'tasklist_sort_order', value: order });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -51,6 +51,8 @@ class tasklist extends rcube_plugin
|
||||||
);
|
);
|
||||||
|
|
||||||
public $task = '?(?!login|logout).*';
|
public $task = '?(?!login|logout).*';
|
||||||
|
public $allowed_prefs = array('tasklist_sort_col','tasklist_sort_order');
|
||||||
|
|
||||||
public $rc;
|
public $rc;
|
||||||
public $lib;
|
public $lib;
|
||||||
public $driver;
|
public $driver;
|
||||||
|
@ -959,9 +961,8 @@ class tasklist extends rcube_plugin
|
||||||
$data[] = $rec;
|
$data[] = $rec;
|
||||||
}
|
}
|
||||||
|
|
||||||
// sort tasks according to their hierarchy level and due date
|
// assign hierarchy level indicators for later sorting
|
||||||
array_walk($data, array($this, 'task_walk_tree'));
|
array_walk($data, array($this, 'task_walk_tree'));
|
||||||
usort($data, array($this, 'task_sort_cmp'));
|
|
||||||
|
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
@ -974,7 +975,18 @@ class tasklist extends rcube_plugin
|
||||||
$rec['mask'] = $this->filter_mask($rec);
|
$rec['mask'] = $this->filter_mask($rec);
|
||||||
$rec['flagged'] = intval($rec['flagged']);
|
$rec['flagged'] = intval($rec['flagged']);
|
||||||
$rec['complete'] = floatval($rec['complete']);
|
$rec['complete'] = floatval($rec['complete']);
|
||||||
$rec['changed'] = is_object($rec['changed']) ? $rec['changed']->format('U') : null;
|
|
||||||
|
if (is_object($rec['created'])) {
|
||||||
|
$rec['created_'] = $this->rc->format_date($rec['created']);
|
||||||
|
$rec['created'] = $rec['created']->format('U');
|
||||||
|
}
|
||||||
|
if (is_object($rec['changed'])) {
|
||||||
|
$rec['changed_'] = $this->rc->format_date($rec['changed']);
|
||||||
|
$rec['changed'] = $rec['changed']->format('U');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$rec['changed'] = null;
|
||||||
|
}
|
||||||
|
|
||||||
if ($rec['date']) {
|
if ($rec['date']) {
|
||||||
try {
|
try {
|
||||||
|
@ -1045,18 +1057,6 @@ class tasklist extends rcube_plugin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Compare function for task list sorting.
|
|
||||||
* Nested tasks need to be sorted to the end.
|
|
||||||
*/
|
|
||||||
private function task_sort_cmp($a, $b)
|
|
||||||
{
|
|
||||||
$d = $a['_depth'] - $b['_depth'];
|
|
||||||
if (!$d) $d = $b['_hasdate'] - $a['_hasdate'];
|
|
||||||
if (!$d) $d = $a['datetime'] - $b['datetime'];
|
|
||||||
return $d;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compute the filter mask of the given task
|
* Compute the filter mask of the given task
|
||||||
*
|
*
|
||||||
|
|
|
@ -72,6 +72,8 @@ class tasklist_ui
|
||||||
$settings = array();
|
$settings = array();
|
||||||
|
|
||||||
$settings['invite_shared'] = (int)$this->rc->config->get('calendar_allow_invite_shared', 0);
|
$settings['invite_shared'] = (int)$this->rc->config->get('calendar_allow_invite_shared', 0);
|
||||||
|
$settings['sort_col'] = $this->rc->config->get('tasklist_sort_col', '');
|
||||||
|
$settings['sort_order'] = $this->rc->config->get('tasklist_sort_order', 'asc');
|
||||||
|
|
||||||
// get user identity to create default attendee
|
// get user identity to create default attendee
|
||||||
foreach ($this->rc->user->list_identities() as $rec) {
|
foreach ($this->rc->user->list_identities() as $rec) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue