Handle start date/time; fix task list sorting
This commit is contained in:
parent
e6fff6a96a
commit
78077bcb0a
9 changed files with 134 additions and 32 deletions
|
@ -32,6 +32,8 @@ CREATE TABLE `tasks` (
|
|||
`tags` text,
|
||||
`date` varchar(10) DEFAULT NULL,
|
||||
`time` varchar(5) DEFAULT NULL,
|
||||
`startdate` varchar(10) DEFAULT NULL,
|
||||
`starttime` varchar(5) DEFAULT NULL,
|
||||
`flagged` tinyint(4) NOT NULL DEFAULT '0',
|
||||
`complete` float NOT NULL DEFAULT '0',
|
||||
`alarms` varchar(255) NOT NULL,
|
||||
|
|
|
@ -343,7 +343,7 @@ class tasklist_database_driver extends tasklist_driver
|
|||
{
|
||||
$rec['id'] = $rec['task_id'];
|
||||
$rec['list'] = $rec['tasklist_id'];
|
||||
$rec['changed'] = strtotime($rec['changed']);
|
||||
$rec['changed'] = new DateTime($rec['changed']);
|
||||
$rec['tags'] = array_filter(explode(',', $rec['tags']));
|
||||
|
||||
if (!$rec['parent_id'])
|
||||
|
@ -409,7 +409,7 @@ class tasklist_database_driver extends tasklist_driver
|
|||
if (isset($prop[$col]))
|
||||
$sql_set[] = $this->rc->db->quote_identifier($col) . '=' . $this->rc->db->quote($prop[$col]);
|
||||
}
|
||||
foreach (array('parent_id', 'date', 'time') as $col) {
|
||||
foreach (array('parent_id', 'date', 'time', 'startdate', 'starttime') as $col) {
|
||||
if (isset($prop[$col]))
|
||||
$sql_set[] = $this->rc->db->quote_identifier($col) . '=' . (empty($prop[$col]) ? 'NULL' : $this->rc->db->quote($prop[$col]));
|
||||
}
|
||||
|
|
|
@ -337,8 +337,13 @@ class tasklist_kolab_driver extends tasklist_driver
|
|||
$task['date'] = $record['due']->format('Y-m-d');
|
||||
$task['time'] = $record['due']->format('h:i');
|
||||
}
|
||||
// convert from DateTime to internal date format
|
||||
if (is_a($record['start'], 'DateTime')) {
|
||||
$task['startdate'] = $record['start']->format('Y-m-d');
|
||||
$task['starttime'] = $record['start']->format('h:i');
|
||||
}
|
||||
if (is_a($record['dtstamp'], 'DateTime')) {
|
||||
$task['changed'] = $record['dtstamp']->format('U');
|
||||
$task['changed'] = $record['dtstamp'];
|
||||
}
|
||||
|
||||
return $task;
|
||||
|
@ -360,6 +365,13 @@ class tasklist_kolab_driver extends tasklist_driver
|
|||
unset($object['date']);
|
||||
}
|
||||
|
||||
if (!empty($task['startdate'])) {
|
||||
$object['start'] = new DateTime($task['startdate'].' '.$task['starttime'], $this->plugin->timezone);
|
||||
if (empty($task['starttime']))
|
||||
$object['start']->_dateonly = true;
|
||||
unset($object['startdate']);
|
||||
}
|
||||
|
||||
$object['complete'] = $task['complete'] * 100;
|
||||
if ($task['complete'] == 1.0)
|
||||
$object['status'] = 'COMPLETED';
|
||||
|
|
|
@ -30,12 +30,14 @@
|
|||
* 'parent_id' => 'ID of parent task', // null if top-level task
|
||||
* 'uid' => 'Unique identifier of this task',
|
||||
* 'list' => 'Task list identifier to add the task to or where the task is stored',
|
||||
* 'changed' => <unixtime>, // Last modification date of record
|
||||
* 'changed' => <DateTime>, // Last modification date/time of the record
|
||||
* 'title' => 'Event title/summary',
|
||||
* 'description' => 'Event description',
|
||||
* 'tags' => array(), // List of tags for this task
|
||||
* 'date' => 'Due date', // as string of format YYYY-MM-DD or null if no date is set
|
||||
* 'time' => 'Due time', // as string of format hh::ii or null if no due time is set
|
||||
* 'startdate' => 'Start date' // Delay start of the task until that date
|
||||
* 'starttime' => 'Start time' // ...and time
|
||||
* 'categories' => 'Task category',
|
||||
* 'flagged' => 'Boolean value whether this record is flagged',
|
||||
* 'complete' => 'Float value representing the completeness state (range 0..1)',
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
$labels = array();
|
||||
$labels['navtitle'] = 'Aufgaben';
|
||||
$labels['lists'] = 'Ressourcen';
|
||||
$labels['list'] = 'Ressource';
|
||||
$labels['lists'] = 'Aufgabenlisten';
|
||||
$labels['list'] = 'Liste';
|
||||
$labels['tags'] = 'Tags';
|
||||
|
||||
$labels['newtask'] = 'Neue Aufgabe';
|
||||
|
@ -15,6 +15,7 @@ $labels['delete'] = 'Löschen';
|
|||
$labels['title'] = 'Titel';
|
||||
$labels['description'] = 'Beschreibung';
|
||||
$labels['datetime'] = 'Datum/Zeit';
|
||||
$labels['start'] = 'Beginn';
|
||||
|
||||
$labels['all'] = 'Alle';
|
||||
$labels['flagged'] = 'Markiert';
|
||||
|
@ -51,3 +52,4 @@ $labels['next'] = 'nächsten';
|
|||
$labels['savingdata'] = 'Daten werden gespeichert...';
|
||||
$labels['errorsaving'] = 'Fehler beim Speichern.';
|
||||
$labels['notasksfound'] = 'Für die aktuellen Kriterien wurden keine Aufgaben gefunden.';
|
||||
$labels['invalidstartduedates'] = 'Beginn der Aufgabe darf nicht grösser als das Enddatum sein.';
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
$labels = array();
|
||||
$labels['navtitle'] = 'Tasks';
|
||||
$labels['lists'] = 'Resources';
|
||||
$labels['list'] = 'Resource';
|
||||
$labels['lists'] = 'Tasklists';
|
||||
$labels['list'] = 'Tasklist';
|
||||
$labels['tags'] = 'Tags';
|
||||
|
||||
$labels['newtask'] = 'New Task';
|
||||
|
@ -15,6 +15,7 @@ $labels['delete'] = 'Delete';
|
|||
$labels['title'] = 'Title';
|
||||
$labels['description'] = 'Description';
|
||||
$labels['datetime'] = 'Date/Time';
|
||||
$labels['start'] = 'Start';
|
||||
|
||||
$labels['all'] = 'All';
|
||||
$labels['flagged'] = 'Flagged';
|
||||
|
@ -51,3 +52,4 @@ $labels['next'] = 'next';
|
|||
$labels['savingdata'] = 'Saving data...';
|
||||
$labels['errorsaving'] = 'Failed to save data.';
|
||||
$labels['notasksfound'] = 'No tasks found for the given criteria';
|
||||
$labels['invalidstartduedates'] = 'Start date must not be greater than due date.';
|
||||
|
|
|
@ -107,6 +107,11 @@
|
|||
<span class="task-text"></span>
|
||||
<span id="task-time"></span>
|
||||
</div>
|
||||
<div id="task-start" class="form-section">
|
||||
<label><roundcube:label name="tasklist.start" /></label>
|
||||
<span class="task-text"></span>
|
||||
<span id="task-starttime"></span>
|
||||
</div>
|
||||
<div id="task-list" class="form-section">
|
||||
<label><roundcube:label name="tasklist.list" /></label>
|
||||
<span class="task-text"></span>
|
||||
|
@ -137,16 +142,22 @@
|
|||
<label for="edit-date"><roundcube:label name="tasklist.datetime" /></label>
|
||||
<input type="text" name="date" size="10" id="edit-date" tabindex="20" />
|
||||
<input type="text" name="time" size="6" id="edit-time" tabindex="21" />
|
||||
<a href="#nodate" style="margin-left:1em" id="edit-nodate"><roundcube:label name="tasklist.nodate" /></a>
|
||||
<a href="#nodate" style="margin-left:1em" class="edit-nodate" rel="#edit-date,#edit-time"><roundcube:label name="tasklist.nodate" /></a>
|
||||
</div>
|
||||
<div class="form-section">
|
||||
<label for="edit-startdate"><roundcube:label name="tasklist.start" /></label>
|
||||
<input type="text" name="startdate" size="10" id="edit-startdate" tabindex="23" />
|
||||
<input type="text" name="starttime" size="6" id="edit-starttime" tabindex="24" />
|
||||
<a href="#nodate" style="margin-left:1em" class="edit-nodate" rel="#edit-startdate,#edit-starttime"><roundcube:label name="tasklist.nodate" /></a>
|
||||
</div>
|
||||
<div class="form-section">
|
||||
<label for="edit-completeness"><roundcube:label name="tasklist.complete" /></label>
|
||||
<input type="text" name="title" id="edit-completeness" size="3" tabindex="23" /> %
|
||||
<input type="text" name="title" id="edit-completeness" size="3" tabindex="25" /> %
|
||||
<div id="edit-completeness-slider"></div>
|
||||
</div>
|
||||
<div class="form-section" id="tasklist-select">
|
||||
<label for="edit-tasklist"><roundcube:label name="tasklist.list" /></label>
|
||||
<roundcube:object name="plugin.tasklist_select" id="edit-tasklist" tabindex="24" />
|
||||
<roundcube:object name="plugin.tasklist_select" id="edit-tasklist" tabindex="26" />
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
|
|
@ -54,6 +54,7 @@ function rcube_tasklist(settings)
|
|||
var saving_lock;
|
||||
var ui_loading;
|
||||
var taskcounts = {};
|
||||
var listindex = [];
|
||||
var listdata = {};
|
||||
var tags = [];
|
||||
var draghelper;
|
||||
|
@ -354,12 +355,14 @@ function rcube_tasklist(settings)
|
|||
function data_ready(response)
|
||||
{
|
||||
listdata = {};
|
||||
listindex = [];
|
||||
loadstate.lists = response.lists;
|
||||
loadstate.filter = response.filter;
|
||||
loadstate.search = response.search;
|
||||
|
||||
for (var i=0; i < response.data.length; i++) {
|
||||
listdata[response.data[i].id] = response.data[i];
|
||||
listindex.push(response.data[i].id);
|
||||
}
|
||||
|
||||
render_tasklist();
|
||||
|
@ -373,12 +376,13 @@ function rcube_tasklist(settings)
|
|||
function render_tasklist()
|
||||
{
|
||||
// clear display
|
||||
var rec,
|
||||
var id, rec,
|
||||
count = 0,
|
||||
msgbox = $('#listmessagebox').hide(),
|
||||
list = $(rcmail.gui_objects.resultlist).html('');
|
||||
|
||||
for (var id in listdata) {
|
||||
for (var i=0; i < listindex.length; i++) {
|
||||
id = listindex[i];
|
||||
rec = listdata[id];
|
||||
if (match_filter(rec)) {
|
||||
render_task(rec);
|
||||
|
@ -436,9 +440,18 @@ function rcube_tasklist(settings)
|
|||
*/
|
||||
function update_taskitem(rec)
|
||||
{
|
||||
var id = rec.id;
|
||||
var id = rec.id,
|
||||
oldid = rec.tempid || id;
|
||||
oldindex = listindex.indexOf(oldid);
|
||||
|
||||
if (oldindex >= 0)
|
||||
listindex[oldindex] = id;
|
||||
else
|
||||
listindex.push(id);
|
||||
|
||||
listdata[id] = rec;
|
||||
render_task(rec, rec.tempid || id);
|
||||
|
||||
render_task(rec, oldid);
|
||||
append_tags(rec.tags || []);
|
||||
}
|
||||
|
||||
|
@ -525,7 +538,7 @@ function rcube_tasklist(settings)
|
|||
*/
|
||||
function resort_task(rec, li, animated)
|
||||
{
|
||||
var dir = 0, next_li, next_id, next_rec;
|
||||
var dir = 0, index, slice, next_li, next_id, next_rec;
|
||||
|
||||
// animated moving
|
||||
var insert_animated = function(li, before, after) {
|
||||
|
@ -542,6 +555,13 @@ function rcube_tasklist(settings)
|
|||
});
|
||||
}
|
||||
|
||||
// remove from list index
|
||||
var oldindex = listindex.indexOf(rec.id);
|
||||
if (oldindex >= 0) {
|
||||
slice = listindex.slice(0,oldindex);
|
||||
listindex = slice.concat(listindex.slice(oldindex+1));
|
||||
}
|
||||
|
||||
// find the right place to insert the task item
|
||||
li.siblings().each(function(i, elem){
|
||||
next_li = $(elem);
|
||||
|
@ -558,17 +578,26 @@ function rcube_tasklist(settings)
|
|||
}
|
||||
else if (next_rec && next_li && task_cmp(rec, next_rec) < 0) {
|
||||
if (animated) insert_animated(li, next_li);
|
||||
else li.insertBefore(next_li)
|
||||
else li.insertBefore(next_li);
|
||||
next_li = null;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
index = listindex.indexOf(next_id);
|
||||
|
||||
if (next_li) {
|
||||
if (animated) insert_animated(li, null, next_li);
|
||||
else li.insertAfter(next_li);
|
||||
index++;
|
||||
}
|
||||
|
||||
// insert into list index
|
||||
if (next_id && index >= 0) {
|
||||
slice = listindex.slice(0,index);
|
||||
slice.push(rec.id);
|
||||
listindex = slice.concat(listindex.slice(index));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -617,15 +646,19 @@ function rcube_tasklist(settings)
|
|||
{
|
||||
var drag_id = draggable.data('id'),
|
||||
parent_id = $(this).data('id'),
|
||||
rec = listdata[parent_id];
|
||||
drag_rec = listdata[drag_id],
|
||||
drop_rec = listdata[parent_id];
|
||||
|
||||
if (parent_id == listdata[drag_id].parent_id)
|
||||
if (drop_rec && drop_rec.list != drag_rec.list)
|
||||
return false;
|
||||
|
||||
while (rec && rec.parent_id) {
|
||||
if (rec.parent_id == drag_id)
|
||||
if (parent_id == drag_rec.parent_id)
|
||||
return false;
|
||||
rec = listdata[rec.parent_id];
|
||||
|
||||
while (drop_rec && drop_rec.parent_id) {
|
||||
if (drop_rec.parent_id == drag_id)
|
||||
return false;
|
||||
drop_rec = listdata[drop_rec.parent_id];
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -672,6 +705,8 @@ function rcube_tasklist(settings)
|
|||
$('#task-description').html(text2html(rec.description || '', 300, 6))[(rec.description ? 'show' : 'hide')]();
|
||||
$('#task-date')[(rec.date ? 'show' : 'hide')]().children('.task-text').html(Q(rec.date || rcmail.gettext('nodate','tasklist')));
|
||||
$('#task-time').html(Q(rec.time || ''));
|
||||
$('#task-start')[(rec.startdate ? 'show' : 'hide')]().children('.task-text').html(Q(rec.startdate || ''));
|
||||
$('#task-starttime').html(Q(rec.starttime || ''));
|
||||
$('#task-completeness .task-text').html(((rec.complete || 0) * 100) + '%');
|
||||
$('#task-list .task-text').html(Q(me.tasklists[rec.list] ? me.tasklists[rec.list].name : ''));
|
||||
|
||||
|
@ -732,6 +767,8 @@ function rcube_tasklist(settings)
|
|||
var description = $('#edit-description').val(rec.description || '');
|
||||
var recdate = $('#edit-date').val(rec.date || '').datepicker(datepicker_settings);
|
||||
var rectime = $('#edit-time').val(rec.time || '');
|
||||
var recstartdate = $('#edit-startdate').val(rec.startdate || '').datepicker(datepicker_settings);
|
||||
var recstarttime = $('#edit-starttime').val(rec.starttime || '');
|
||||
var complete = $('#edit-completeness').val((rec.complete || 0) * 100);
|
||||
completeness_slider.slider('value', complete.val());
|
||||
var tasklist = $('#edit-tasklist').val(rec.list || 0); // .prop('disabled', rec.parent_id ? true : false);
|
||||
|
@ -755,22 +792,31 @@ function rcube_tasklist(settings)
|
|||
texts: { removeLinkTitle: rcmail.gettext('removetag', 'tasklist') }
|
||||
});
|
||||
|
||||
$('#edit-nodate').unbind('click').click(function(){
|
||||
recdate.val('');
|
||||
rectime.val('');
|
||||
$('a.edit-nodate').unbind('click').click(function(){
|
||||
var sel = $(this).attr('rel');
|
||||
if (sel) $(sel).val('');
|
||||
return false;
|
||||
})
|
||||
|
||||
// define dialog buttons
|
||||
var buttons = {};
|
||||
buttons[rcmail.gettext('save', 'tasklist')] = function() {
|
||||
me.selected_task.title = title.val();
|
||||
me.selected_task.description = description.val();
|
||||
me.selected_task.date = recdate.val();
|
||||
me.selected_task.time = rectime.val();
|
||||
me.selected_task.list = tasklist.val();
|
||||
// copy form field contents into task object to save
|
||||
$.each({ title:title, description:description, date:recdate, time:rectime, startdate:recstartdate, starttime:recstarttime, list:tasklist }, function(key,input){
|
||||
me.selected_task[key] = input.val();
|
||||
});
|
||||
me.selected_task.tags = [];
|
||||
|
||||
// do some basic input validation
|
||||
if (me.selected_task.startdate && me.selected_task.date) {
|
||||
var startdate = $.datepicker.parseDate(datepicker_settings.dateFormat, me.selected_task.startdate, datepicker_settings);
|
||||
var duedate = $.datepicker.parseDate(datepicker_settings.dateFormat, me.selected_task.date, datepicker_settings);
|
||||
if (startdate > duedate) {
|
||||
alert(rcmail.gettext('invalidstartduedates', 'tasklist'));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$('input[name="tags[]"]', rcmail.gui_objects.edittagline).each(function(i,elem){
|
||||
if (elem.value)
|
||||
me.selected_task.tags.push(elem.value);
|
||||
|
@ -812,9 +858,10 @@ function rcube_tasklist(settings)
|
|||
$dialog.dialog('destroy').remove();
|
||||
},
|
||||
buttons: buttons,
|
||||
minHeight: 340,
|
||||
minWidth: 500,
|
||||
width: 580
|
||||
}).append(editform.show()); // adding form content AFTERWARDS massively speeds up opening on IE6
|
||||
}).append(editform.show()); // adding form content AFTERWARDS massively speeds up opening on IE
|
||||
|
||||
title.select();
|
||||
}
|
||||
|
|
|
@ -261,6 +261,18 @@ class tasklist extends rcube_plugin
|
|||
}
|
||||
}
|
||||
|
||||
if (!empty($rec['startdate'])) {
|
||||
try {
|
||||
$date = new DateTime($rec['startdate'] . ' ' . $rec['starttime'], $this->timezone);
|
||||
$rec['startdate'] = $date->format('Y-m-d');
|
||||
if (!empty($rec['starttime']))
|
||||
$rec['starttime'] = $date->format('H:i');
|
||||
}
|
||||
catch (Exception $e) {
|
||||
$rec['startdate'] = $rec['starttime'] = null;
|
||||
}
|
||||
}
|
||||
|
||||
return $rec;
|
||||
}
|
||||
|
||||
|
@ -400,6 +412,7 @@ class tasklist extends rcube_plugin
|
|||
$rec['mask'] = $this->filter_mask($rec);
|
||||
$rec['flagged'] = intval($rec['flagged']);
|
||||
$rec['complete'] = floatval($rec['complete']);
|
||||
$rec['changed'] = is_object($rec['changed']) ? $rec['changed']->format('U') : null;
|
||||
|
||||
if ($rec['date']) {
|
||||
try {
|
||||
|
@ -417,6 +430,17 @@ class tasklist extends rcube_plugin
|
|||
$rec['_hasdate'] = 0;
|
||||
}
|
||||
|
||||
if ($rec['startdate']) {
|
||||
try {
|
||||
$date = new DateTime($rec['startdate'] . ' ' . $rec['starttime'], $this->timezone);
|
||||
$rec['startdatetime'] = intval($date->format('U'));
|
||||
$rec['startdate'] = $date->format($this->rc->config->get('date_format', 'Y-m-d'));
|
||||
}
|
||||
catch (Exception $e) {
|
||||
$rec['startdate'] = $rec['startdatetime'] = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isset($rec['_depth'])) {
|
||||
$rec['_depth'] = 0;
|
||||
$parent_id = $this->task_tree[$rec['id']];
|
||||
|
|
Loading…
Add table
Reference in a new issue