From 78863696b7d2c443f742d23dd94acefe60157779 Mon Sep 17 00:00:00 2001 From: Bart Visscher Date: Mon, 12 Sep 2011 21:28:28 +0200 Subject: [PATCH 01/38] First version of tasks app --- apps/tasks/ajax/addtask.php | 38 +++++++++ apps/tasks/ajax/addtaskform.php | 19 +++++ apps/tasks/ajax/delete.php | 49 +++++++++++ apps/tasks/ajax/edittask.php | 46 ++++++++++ apps/tasks/ajax/edittaskform.php | 33 ++++++++ apps/tasks/ajax/getdetails.php | 22 +++++ apps/tasks/appinfo/app.php | 15 ++++ apps/tasks/appinfo/info.xml | 10 +++ apps/tasks/css/style.css | 2 + apps/tasks/index.php | 52 ++++++++++++ apps/tasks/js/tasks.js | 97 ++++++++++++++++++++++ apps/tasks/templates/part.addtaskform.php | 15 ++++ apps/tasks/templates/part.details.php | 9 ++ apps/tasks/templates/part.edittaskform.php | 5 ++ apps/tasks/templates/part.property.php | 8 ++ apps/tasks/templates/part.taskform.php | 2 + apps/tasks/templates/part.tasks.php | 3 + apps/tasks/templates/tasks.php | 13 +++ 18 files changed, 438 insertions(+) create mode 100644 apps/tasks/ajax/addtask.php create mode 100644 apps/tasks/ajax/addtaskform.php create mode 100644 apps/tasks/ajax/delete.php create mode 100644 apps/tasks/ajax/edittask.php create mode 100644 apps/tasks/ajax/edittaskform.php create mode 100644 apps/tasks/ajax/getdetails.php create mode 100644 apps/tasks/appinfo/app.php create mode 100644 apps/tasks/appinfo/info.xml create mode 100644 apps/tasks/css/style.css create mode 100644 apps/tasks/index.php create mode 100644 apps/tasks/js/tasks.js create mode 100644 apps/tasks/templates/part.addtaskform.php create mode 100644 apps/tasks/templates/part.details.php create mode 100644 apps/tasks/templates/part.edittaskform.php create mode 100644 apps/tasks/templates/part.property.php create mode 100644 apps/tasks/templates/part.taskform.php create mode 100644 apps/tasks/templates/part.tasks.php create mode 100644 apps/tasks/templates/tasks.php diff --git a/apps/tasks/ajax/addtask.php b/apps/tasks/ajax/addtask.php new file mode 100644 index 0000000000..434fbc5fdd --- /dev/null +++ b/apps/tasks/ajax/addtask.php @@ -0,0 +1,38 @@ + 'error', 'data' => array( 'message' => $l10n->t('You need to log in!')))); + exit(); +} + +$cid = $_POST['id']; +$calendar = OC_Calendar_Calendar::findCalendar( $cid ); +if( $calendar === false || $calendar['userid'] != OC_USER::getUser()){ + echo json_encode( array( 'status' => 'error', 'data' => array( 'message' => $l10n->t('This is not your calendar!')))); + exit(); +} + +$summary = $_POST['summary']; + +$vcalendar = new Sabre_VObject_Component('VCALENDAR'); +$vcalendar->add(new Sabre_VObject_Property('PRODID', 'ownCloud Calendar')); +$vcalendar->add(new Sabre_VObject_Property('VERSION', '2.0')); +$vtodo = new Sabre_VObject_Component('VTODO'); +$vtodo->add(new Sabre_VObject_Property('SUMMARY',$summary)); +$vtodo->add(new Sabre_VObject_Property('UID',OC_Calendar_Calendar::createUID())); +$vcalendar->add($vtodo); +$id = OC_Calendar_Object::add($cid, $vcalendar->serialize()); + +$details = OC_Contacts_Addressbook::structureContact($vtodo); +$tmpl = new OC_Template('tasks','part.details'); +$tmpl->assign('details',$details); +$tmpl->assign('id',$id); +$page = $tmpl->fetchPage(); + +echo json_encode( array( 'status' => 'success', 'data' => array( 'id' => $id, 'page' => $page ))); diff --git a/apps/tasks/ajax/addtaskform.php b/apps/tasks/ajax/addtaskform.php new file mode 100644 index 0000000000..297c590060 --- /dev/null +++ b/apps/tasks/ajax/addtaskform.php @@ -0,0 +1,19 @@ + 'error', 'data' => array( 'message' => $l10n->t('You need to log in!')))); + exit(); +} + +$calendars = OC_Calendar_Calendar::allCalendars(OC_User::getUser(), true); +$tmpl = new OC_Template('tasks','part.addtaskform'); +$tmpl->assign('calendars',$calendars); +$page = $tmpl->fetchPage(); + +echo json_encode( array( 'status' => 'success', 'data' => array( 'page' => $page ))); diff --git a/apps/tasks/ajax/delete.php b/apps/tasks/ajax/delete.php new file mode 100644 index 0000000000..1d96a058d7 --- /dev/null +++ b/apps/tasks/ajax/delete.php @@ -0,0 +1,49 @@ +. + * + */ + +// Init owncloud +require_once('../../../lib/base.php'); + +$l10n = new OC_L10N('tasks'); + +// Check if we are a user +if( !OC_User::isLoggedIn()){ + echo json_encode( array( 'status' => 'error', 'data' => array( 'message' => $l10n->t('You need to log in!')))); + exit(); +} + + +$id = $_GET['id']; +$task = OC_Calendar_Object::find( $id ); +if( $task === false ){ + echo json_encode( array( 'status' => 'error', 'data' => array( 'message' => $l10n->t('Can not find Task!')))); + exit(); +} + +$calendar = OC_Calendar_Calendar::findCalendar( $task['calendarid'] ); +if( $calendar === false || $calendar['userid'] != OC_USER::getUser()){ + echo json_encode( array( 'status' => 'error', 'data' => array( 'message' => $l10n->t('This is not your task!')))); + exit(); +} + +OC_Calendar_Object::delete($id); +echo json_encode( array( 'status' => 'success', 'data' => array( 'id' => $id ))); diff --git a/apps/tasks/ajax/edittask.php b/apps/tasks/ajax/edittask.php new file mode 100644 index 0000000000..f98bcf3f59 --- /dev/null +++ b/apps/tasks/ajax/edittask.php @@ -0,0 +1,46 @@ + 'error', 'data' => array( 'message' => $l10n->t('You need to log in!')))); + exit(); +} + +$id = $_POST['id']; +$task = OC_Calendar_Object::find( $id ); +if( $task === false ){ + echo json_encode( array( 'status' => 'error', 'data' => array( 'message' => $l10n->t('Can not find Task!')))); + exit(); +} + +$calendar = OC_Calendar_Calendar::findCalendar( $task['calendarid'] ); +if( $calendar === false || $calendar['userid'] != OC_USER::getUser()){ + echo json_encode( array( 'status' => 'error', 'data' => array( 'message' => $l10n->t('This is not your task!')))); + exit(); +} + +$summary = $_POST['summary']; + +$vtodo = Sabre_VObject_Reader::read($task['calendardata'])->VTODO[0]; +$uid = $vtodo->UID[0]->value; + +$vcalendar = new Sabre_VObject_Component('VCALENDAR'); +$vcalendar->add(new Sabre_VObject_Property('PRODID', 'ownCloud Calendar')); +$vcalendar->add(new Sabre_VObject_Property('VERSION', '2.0')); +$vtodo = new Sabre_VObject_Component('VTODO'); +$vtodo->add(new Sabre_VObject_Property('SUMMARY',$summary)); +$vtodo->add(new Sabre_VObject_Property('UID', $uid)); +$vcalendar->add($vtodo); +OC_Calendar_Object::edit($id, $vcalendar->serialize()); + +$tmpl = new OC_Template('tasks','part.details'); +$tmpl->assign('details',$vtodo); +$tmpl->assign('id',$id); +$page = $tmpl->fetchPage(); + +echo json_encode( array( 'status' => 'success', 'data' => array( 'id' => $id, 'page' => $page ))); diff --git a/apps/tasks/ajax/edittaskform.php b/apps/tasks/ajax/edittaskform.php new file mode 100644 index 0000000000..6cc7d2787c --- /dev/null +++ b/apps/tasks/ajax/edittaskform.php @@ -0,0 +1,33 @@ + 'error', 'data' => array( 'message' => $l10n->t('You need to log in!')))); + exit(); +} + +$id = $_GET['id']; +$task = OC_Calendar_Object::find( $id ); +if( $task === false ){ + echo json_encode( array( 'status' => 'error', 'data' => array( 'message' => $l10n->t('Can not find Task!')))); + exit(); +} + +$calendar = OC_Calendar_Calendar::findCalendar( $task['calendarid'] ); +if( $calendar === false || $calendar['userid'] != OC_USER::getUser()){ + echo json_encode( array( 'status' => 'error', 'data' => array( 'message' => $l10n->t('This is not your task!')))); + exit(); +} + +$details = Sabre_VObject_Reader::read($task['calendardata'])->VTODO; +$tmpl = new OC_Template('tasks','part.edittaskform'); +$tmpl->assign('task',$task); +$tmpl->assign('details',$details); +$page = $tmpl->fetchPage(); + +echo json_encode( array( 'status' => 'success', 'data' => array( 'page' => $page ))); diff --git a/apps/tasks/ajax/getdetails.php b/apps/tasks/ajax/getdetails.php new file mode 100644 index 0000000000..d264aeab85 --- /dev/null +++ b/apps/tasks/ajax/getdetails.php @@ -0,0 +1,22 @@ + 'error', 'data' => array( 'message' => $l10n->t('You need to log in!')))); + exit(); +} + +$id = $_GET['id']; +$task = OC_Calendar_Object::find($id); +$details = Sabre_VObject_Reader::read($task['calendardata'])->VTODO; +$tmpl = new OC_Template('tasks','part.details'); +$tmpl->assign('details',$details); +$tmpl->assign('id',$id); +$page = $tmpl->fetchPage(); + +echo json_encode( array( 'status' => 'success', 'data' => array( 'id' => $id, 'page' => $page ))); diff --git a/apps/tasks/appinfo/app.php b/apps/tasks/appinfo/app.php new file mode 100644 index 0000000000..8bcc6085ec --- /dev/null +++ b/apps/tasks/appinfo/app.php @@ -0,0 +1,15 @@ + 11, + 'id' => 'tasks', + 'name' => 'Tasks' )); + +OC_App::addNavigationEntry( array( + 'id' => 'tasks_index', + 'order' => 11, + 'href' => OC_Helper::linkTo( 'tasks', 'index.php' ), + //'icon' => OC_Helper::imagePath( 'tasks', 'icon.png' ), + 'name' => $l->t('Tasks'))); diff --git a/apps/tasks/appinfo/info.xml b/apps/tasks/appinfo/info.xml new file mode 100644 index 0000000000..21ab9a2476 --- /dev/null +++ b/apps/tasks/appinfo/info.xml @@ -0,0 +1,10 @@ + + + tasks + Tasks + 0.1 + AGPL + Bart Visscher + 2 + Tasks view from calendar + diff --git a/apps/tasks/css/style.css b/apps/tasks/css/style.css new file mode 100644 index 0000000000..3867f07012 --- /dev/null +++ b/apps/tasks/css/style.css @@ -0,0 +1,2 @@ +#task_details th { padding:2px; text-align:right ;vertical-align:top; } +#task_details td { padding:2px; text-align:left ;vertical-align:top; } diff --git a/apps/tasks/index.php b/apps/tasks/index.php new file mode 100644 index 0000000000..696ab11dd6 --- /dev/null +++ b/apps/tasks/index.php @@ -0,0 +1,52 @@ + $task['summary'], 'id' => $task['id'] ); + } +} + +if( !is_null($id) || count($tasks)){ + if(is_null($id)) $id = $tasks[0]['id']; + $task = OC_Calendar_Object::find($id); + $details = Sabre_VObject_Reader::read($task['calendardata'])->VTODO; +} + +OC_UTIL::addScript('tasks', 'tasks'); +OC_UTIL::addStyle('tasks', 'style'); +OC_APP::setActiveNavigationEntry('tasks_index'); +$output = new OC_Template('tasks', 'tasks', 'user'); +$output->assign('tasks', $tasks); +$output->assign('details', $details); +$output->assign('id',$id); +$output -> printPage(); diff --git a/apps/tasks/js/tasks.js b/apps/tasks/js/tasks.js new file mode 100644 index 0000000000..528363f423 --- /dev/null +++ b/apps/tasks/js/tasks.js @@ -0,0 +1,97 @@ +$(document).ready(function(){ + /*------------------------------------------------------------------------- + * Actions for startup + *-----------------------------------------------------------------------*/ + if( $('#tasks li').length > 0 ){ + $('#tasks li').first().addClass('active'); + } + + /*------------------------------------------------------------------------- + * Event handlers + *-----------------------------------------------------------------------*/ + $('#tasks li').live('click',function(){ + var id = $(this).data('id'); + var oldid = $('#task_details').data('id'); + if(oldid != 0){ + $('#tasks li[data-id="'+oldid+'"]').removeClass('active'); + } + $.getJSON('ajax/getdetails.php',{'id':id},function(jsondata){ + if(jsondata.status == 'success'){ + $('#task_details').data('id',jsondata.data.id); + $('#task_details').html(jsondata.data.page); + $('#tasks li[data-id="'+jsondata.data.id+'"]').addClass('active'); + } + else{ + alert(jsondata.data.message); + } + }); + return false; + }); + + $('#tasks_delete').live('click',function(){ + var id = $('#task_details').data('id'); + $.getJSON('ajax/delete.php',{'id':id},function(jsondata){ + if(jsondata.status == 'success'){ + $('#tasks [data-id="'+jsondata.data.id+'"]').remove(); + $('#task_details').data('id',''); + $('#task_details').html(''); + } + else{ + alert(jsondata.data.message); + } + }); + return false; + }); + + $('#tasks_newtask').click(function(){ + $.getJSON('ajax/addtaskform.php',{},function(jsondata){ + if(jsondata.status == 'success'){ + $('#task_details').data('id',''); + $('#task_details').html(jsondata.data.page); + } + else{ + alert(jsondata.data.message); + } + }); + return false; + }); + + $('#tasks_addtaskform input[type="submit"]').live('click',function(){ + $.post('ajax/addtask.php',$('#tasks_addtaskform').serialize(),function(jsondata){ + if(jsondata.status == 'success'){ + $('#task_details').data('id',jsondata.data.id); + $('#task_details').html(jsondata.data.page); + } + else{ + alert(jsondata.data.message); + } + }, 'json'); + return false; + }); + + $('#tasks_edit').live('click',function(){ + var id = $('#task_details').data('id'); + $.getJSON('ajax/edittaskform.php',{'id':id},function(jsondata){ + if(jsondata.status == 'success'){ + $('#task_details').html(jsondata.data.page); + } + else{ + alert(jsondata.data.message); + } + }); + return false; + }); + + $('#tasks_edittaskform input[type="submit"]').live('click',function(){ + $.post('ajax/edittask.php',$('#tasks_edittaskform').serialize(),function(jsondata){ + if(jsondata.status == 'success'){ + $('#task_details').data('id',jsondata.data.id); + $('#task_details').html(jsondata.data.page); + } + else{ + alert(jsondata.data.message); + } + }, 'json'); + return false; + }); +}); diff --git a/apps/tasks/templates/part.addtaskform.php b/apps/tasks/templates/part.addtaskform.php new file mode 100644 index 0000000000..0fad5592aa --- /dev/null +++ b/apps/tasks/templates/part.addtaskform.php @@ -0,0 +1,15 @@ +
+ + + + + +
+ + inc('part.taskform'); ?> + +
diff --git a/apps/tasks/templates/part.details.php b/apps/tasks/templates/part.details.php new file mode 100644 index 0000000000..574f4c6b8e --- /dev/null +++ b/apps/tasks/templates/part.details.php @@ -0,0 +1,9 @@ +SUMMARY)): ?> + +inc('part.property', array('label' => $l->t('Summary'), 'property' => $_['details']->SUMMARY)); ?> +
+
+ + +
+ diff --git a/apps/tasks/templates/part.edittaskform.php b/apps/tasks/templates/part.edittaskform.php new file mode 100644 index 0000000000..3e26c42038 --- /dev/null +++ b/apps/tasks/templates/part.edittaskform.php @@ -0,0 +1,5 @@ +
+ + inc('part.taskform'); ?> + +
diff --git a/apps/tasks/templates/part.property.php b/apps/tasks/templates/part.property.php new file mode 100644 index 0000000000..68acd68954 --- /dev/null +++ b/apps/tasks/templates/part.property.php @@ -0,0 +1,8 @@ + + + + + + value ?> + + diff --git a/apps/tasks/templates/part.taskform.php b/apps/tasks/templates/part.taskform.php new file mode 100644 index 0000000000..8fe917c946 --- /dev/null +++ b/apps/tasks/templates/part.taskform.php @@ -0,0 +1,2 @@ + +
diff --git a/apps/tasks/templates/part.tasks.php b/apps/tasks/templates/part.tasks.php new file mode 100644 index 0000000000..50be1cd6be --- /dev/null +++ b/apps/tasks/templates/part.tasks.php @@ -0,0 +1,3 @@ + +
  • + diff --git a/apps/tasks/templates/tasks.php b/apps/tasks/templates/tasks.php new file mode 100644 index 0000000000..70f14b4215 --- /dev/null +++ b/apps/tasks/templates/tasks.php @@ -0,0 +1,13 @@ +
    +
    + +
    +
    +
    + +
    +
    + inc("part.details"); ?> +
    From 8826aa8056062d608db962ca2e1b55cf3e204c13 Mon Sep 17 00:00:00 2001 From: Bart Visscher Date: Tue, 13 Sep 2011 22:44:15 +0200 Subject: [PATCH 02/38] Add basic fields to tasks app --- apps/tasks/ajax/addtask.php | 19 ++- apps/tasks/ajax/edittask.php | 24 ++-- apps/tasks/ajax/edittaskform.php | 14 ++ apps/tasks/ajax/getdetails.php | 3 + apps/tasks/appinfo/app.php | 1 + apps/tasks/js/tasks.js | 10 +- apps/tasks/lib/vtodo.php | 186 +++++++++++++++++++++++++ apps/tasks/templates/part.details.php | 35 ++++- apps/tasks/templates/part.property.php | 16 ++- apps/tasks/templates/part.taskform.php | 42 +++++- 10 files changed, 323 insertions(+), 27 deletions(-) create mode 100644 apps/tasks/lib/vtodo.php diff --git a/apps/tasks/ajax/addtask.php b/apps/tasks/ajax/addtask.php index 434fbc5fdd..81905666ff 100644 --- a/apps/tasks/ajax/addtask.php +++ b/apps/tasks/ajax/addtask.php @@ -18,20 +18,19 @@ if( $calendar === false || $calendar['userid'] != OC_USER::getUser()){ exit(); } -$summary = $_POST['summary']; +$errors = OC_Task_VTodo::validateRequest($_POST, $l10n); +if (!empty($errors)) { + echo json_encode( array( 'status' => 'error', 'data' => array( 'errors' => $errors ))); + exit(); +} -$vcalendar = new Sabre_VObject_Component('VCALENDAR'); -$vcalendar->add(new Sabre_VObject_Property('PRODID', 'ownCloud Calendar')); -$vcalendar->add(new Sabre_VObject_Property('VERSION', '2.0')); -$vtodo = new Sabre_VObject_Component('VTODO'); -$vtodo->add(new Sabre_VObject_Property('SUMMARY',$summary)); -$vtodo->add(new Sabre_VObject_Property('UID',OC_Calendar_Calendar::createUID())); -$vcalendar->add($vtodo); +$vcalendar = OC_Task_VTodo::createVCalendarFromRequest($_POST); $id = OC_Calendar_Object::add($cid, $vcalendar->serialize()); -$details = OC_Contacts_Addressbook::structureContact($vtodo); +$priority_options = OC_Task_VTodo::getPriorityOptions($l10n); $tmpl = new OC_Template('tasks','part.details'); -$tmpl->assign('details',$details); +$tmpl->assign('priority_options', $priority_options); +$tmpl->assign('details',$vcalendar->VTODO); $tmpl->assign('id',$id); $page = $tmpl->fetchPage(); diff --git a/apps/tasks/ajax/edittask.php b/apps/tasks/ajax/edittask.php index f98bcf3f59..9f836f1f8a 100644 --- a/apps/tasks/ajax/edittask.php +++ b/apps/tasks/ajax/edittask.php @@ -24,23 +24,21 @@ if( $calendar === false || $calendar['userid'] != OC_USER::getUser()){ exit(); } -$summary = $_POST['summary']; +$errors = OC_Task_VTodo::validateRequest($_POST, $l10n); +if (!empty($errors)) { + echo json_encode( array( 'status' => 'error', 'data' => array( 'errors' => $errors ))); + exit(); +} -$vtodo = Sabre_VObject_Reader::read($task['calendardata'])->VTODO[0]; -$uid = $vtodo->UID[0]->value; - -$vcalendar = new Sabre_VObject_Component('VCALENDAR'); -$vcalendar->add(new Sabre_VObject_Property('PRODID', 'ownCloud Calendar')); -$vcalendar->add(new Sabre_VObject_Property('VERSION', '2.0')); -$vtodo = new Sabre_VObject_Component('VTODO'); -$vtodo->add(new Sabre_VObject_Property('SUMMARY',$summary)); -$vtodo->add(new Sabre_VObject_Property('UID', $uid)); -$vcalendar->add($vtodo); +$vcalendar = Sabre_VObject_Reader::read($task['calendardata']); +OC_Task_VTodo::updateVCalendarFromRequest($_POST, $vcalendar); OC_Calendar_Object::edit($id, $vcalendar->serialize()); +$priority_options = OC_Task_VTodo::getPriorityOptions($l10n); $tmpl = new OC_Template('tasks','part.details'); -$tmpl->assign('details',$vtodo); -$tmpl->assign('id',$id); +$tmpl->assign('priority_options', $priority_options); +$tmpl->assign('details', $vcalendar->VTODO); +$tmpl->assign('id', $id); $page = $tmpl->fetchPage(); echo json_encode( array( 'status' => 'success', 'data' => array( 'id' => $id, 'page' => $page ))); diff --git a/apps/tasks/ajax/edittaskform.php b/apps/tasks/ajax/edittaskform.php index 6cc7d2787c..dc8bb60e64 100644 --- a/apps/tasks/ajax/edittaskform.php +++ b/apps/tasks/ajax/edittaskform.php @@ -25,9 +25,23 @@ if( $calendar === false || $calendar['userid'] != OC_USER::getUser()){ } $details = Sabre_VObject_Reader::read($task['calendardata'])->VTODO; +$categories = array(); +if (isset($details->CATEGORIES)){ + $categories = explode(',', $details->CATEGORIES->value); + $categories = array_map('trim', $categories); +} + +$category_options = OC_Calendar_Object::getCategoryOptions($l10n); +$percent_options = range(0, 100, 10); +$priority_options = OC_Task_VTodo::getPriorityOptions($l10n); + $tmpl = new OC_Template('tasks','part.edittaskform'); +$tmpl->assign('category_options', $category_options); +$tmpl->assign('percent_options', $percent_options); +$tmpl->assign('priority_options', $priority_options); $tmpl->assign('task',$task); $tmpl->assign('details',$details); +$tmpl->assign('categories', $categories); $page = $tmpl->fetchPage(); echo json_encode( array( 'status' => 'success', 'data' => array( 'page' => $page ))); diff --git a/apps/tasks/ajax/getdetails.php b/apps/tasks/ajax/getdetails.php index d264aeab85..f111a399b3 100644 --- a/apps/tasks/ajax/getdetails.php +++ b/apps/tasks/ajax/getdetails.php @@ -14,7 +14,10 @@ if( !OC_User::isLoggedIn()){ $id = $_GET['id']; $task = OC_Calendar_Object::find($id); $details = Sabre_VObject_Reader::read($task['calendardata'])->VTODO; + +$priority_options = OC_Task_VTodo::getPriorityOptions($l10n); $tmpl = new OC_Template('tasks','part.details'); +$tmpl->assign('priority_options', $priority_options); $tmpl->assign('details',$details); $tmpl->assign('id',$id); $page = $tmpl->fetchPage(); diff --git a/apps/tasks/appinfo/app.php b/apps/tasks/appinfo/app.php index 8bcc6085ec..e94f991f73 100644 --- a/apps/tasks/appinfo/app.php +++ b/apps/tasks/appinfo/app.php @@ -1,6 +1,7 @@ 11, diff --git a/apps/tasks/js/tasks.js b/apps/tasks/js/tasks.js index 528363f423..e145389a95 100644 --- a/apps/tasks/js/tasks.js +++ b/apps/tasks/js/tasks.js @@ -82,6 +82,14 @@ $(document).ready(function(){ return false; }); + $('#tasks_edittaskform #percent_complete').live('change',function(event){ + if ($(event.target).val() == 100){ + $('#tasks_edittaskform #complete').show(); + }else{ + $('#tasks_edittaskform #complete').hide(); + } + }); + $('#tasks_edittaskform input[type="submit"]').live('click',function(){ $.post('ajax/edittask.php',$('#tasks_edittaskform').serialize(),function(jsondata){ if(jsondata.status == 'success'){ @@ -89,7 +97,7 @@ $(document).ready(function(){ $('#task_details').html(jsondata.data.page); } else{ - alert(jsondata.data.message); + alert(jsondata.data.errors);//TODO } }, 'json'); return false; diff --git a/apps/tasks/lib/vtodo.php b/apps/tasks/lib/vtodo.php new file mode 100644 index 0000000000..925ad77dea --- /dev/null +++ b/apps/tasks/lib/vtodo.php @@ -0,0 +1,186 @@ +. + * + */ + +/** + * This class manages our calendars + */ +class OC_Task_VTodo extends OC_Calendar_Object{ + public static function getPriorityOptions($l10n) + { + return array( + '' => $l10n->t('Unspecified'), + '1' => $l10n->t('1=highest'), + '2' => '2', + '3' => '3', + '4' => '4', + '5' => $l10n->t('5=medium'), + '6' => '6', + '7' => '7', + '8' => '8', + '9' => $l10n->t('9=lowest'), + ); + } + public static function validateRequest($request, $l10n) + { + $errors = array(); + if($request['summary'] == ''){ + $errors['summary'] = $l10n->t('Empty Summary'); + } + + if(isset($request['categories']) && !is_array($request['categories'])){ + $errors['categories'] = $l10n->t('Not an array'); + } + + try { + $timezone = OC_Preferences::getValue(OC_USER::getUser(), "calendar", "timezone", "Europe/London"); + $timezone = new DateTimeZone($timezone); + new DateTime($request['due'], $timezone); + } catch (Exception $e) { + $errors['due'] = $l10n->t('Invalid date/time'); + } + + if ($request['percent_complete'] < 0 || $request['percent_complete'] > 100){ + $errors['percent_complete'] = $l10n->t('Invalid percent complete'); + } + if ($request['percent_complete'] == 100 && !empty($request['completed'])){ + try { + $timezone = OC_Preferences::getValue(OC_USER::getUser(), "calendar", "timezone", "Europe/London"); + $timezone = new DateTimeZone($timezone); + new DateTime($request['completed'], $timezone); + } catch (Exception $e) { + $errors['completed'] = $l10n->t('Invalid date/time'); + } + } + + $priority_options = OC_Task_VTodo::getPriorityOptions($l10n); + if (!in_array($request['priority'], array_keys($priority_options))) { + $errors['priority'] = $l10n->t('Invalid priority'); + } + return $errors; + } + + public static function createVCalendarFromRequest($request) + { + $vcalendar = new Sabre_VObject_Component('VCALENDAR'); + $vcalendar->add('PRODID', 'ownCloud Calendar'); + $vcalendar->add('VERSION', '2.0'); + + $now = new DateTime(); + + $vtodo = new Sabre_VObject_Component('VTODO'); + $vcalendar->add($vtodo); + + $created = new Sabre_VObject_Element_DateTime('CREATED'); + $created->setDateTime($now, Sabre_VObject_Element_DateTime::UTC); + $vtodo->add($created); + + $uid = self::createUID(); + $vtodo->add('UID',$uid); + + return self::updateVCalendarFromRequest($request, $vcalendar); + } + + public static function updateVCalendarFromRequest($request, $vcalendar) + { + $summary = $request['summary']; + $categories = $request['categories']; + $priority = $request['priority']; + $percent_complete = $request['percent_complete']; + $completed = $request['completed']; + $location = $request['location']; + $due = $request['due']; + $description = $request['description']; + + $now = new DateTime(); + $vtodo = $vcalendar->VTODO[0]; + + $last_modified = new Sabre_VObject_Element_DateTime('LAST-MODIFIED'); + $last_modified->setDateTime($now, Sabre_VObject_Element_DateTime::UTC); + $vtodo->__set('LAST-MODIFIED', $last_modified); + + $dtstamp = new Sabre_VObject_Element_DateTime('DTSTAMP'); + $dtstamp->setDateTime($now, Sabre_VObject_Element_DateTime::UTC); + $vtodo->DTSTAMP = $dtstamp; + + $vtodo->SUMMARY = $summary; + + if ($location != '') { + $vtodo->LOCATION = $location; + }else{ + unset($vtodo->LOCATION); + } + + if ($categories != '') { + $vtodo->CATEGORIES = join(',',$categories); + }else{ + unset($vtodo->CATEGORIES); + } + + if ($priority != '') { + $vtodo->PRIORITY = $priority; + }else{ + unset($vtodo->PRIORITY); + } + + if ($description != '') { + $vtodo->DESCRIPTION = $description; + }else{ + unset($vtodo->DESCRIPTION); + } + + if ($due) { + $due_property = new Sabre_VObject_Element_DateTime('DUE'); + $timezone = OC_Preferences::getValue(OC_USER::getUser(), "calendar", "timezone", "Europe/London"); + $timezone = new DateTimeZone($timezone); + $due_property->setDateTime(new DateTime($due, $timezone)); + $vtodo->DUE = $due_property; + } else { + unset($vtodo->DUE); + } + + if (!empty($percent_complete)) { + $vtodo->__set('PERCENT-COMPLETE', $percent_complete); + }else{ + $vtodo->__unset('PERCENT-COMPLETE'); + } + + if ($percent_complete == 100){ + if (!$completed){ + $completed = 'now'; + } + } else { + $completed = null; + } + if ($completed) { + $completed_property = new Sabre_VObject_Element_DateTime('COMPLETED'); + $timezone = OC_Preferences::getValue(OC_USER::getUser(), "calendar", "timezone", "Europe/London"); + $timezone = new DateTimeZone($timezone); + $completed_property->setDateTime(new DateTime($completed, $timezone)); + $vtodo->COMPLETED = $completed_property; + } else { + unset($vtodo->COMPLETED); + } + + return $vcalendar; + } +} + diff --git a/apps/tasks/templates/part.details.php b/apps/tasks/templates/part.details.php index 574f4c6b8e..a6561d97be 100644 --- a/apps/tasks/templates/part.details.php +++ b/apps/tasks/templates/part.details.php @@ -1,9 +1,42 @@ SUMMARY)): ?> -inc('part.property', array('label' => $l->t('Summary'), 'property' => $_['details']->SUMMARY)); ?> +inc('part.property', array('label' => $l->t('Summary'), 'property' => $_['details']->SUMMARY)); +if(isset($_['details']->LOCATION)): + echo $this->inc('part.property', array('label' => $l->t('Location'), 'property' => $_['details']->LOCATION)); +endif; +if(isset($_['details']->CATEGORIES)): + echo $this->inc('part.property', array('label' => $l->t('Categories'), 'property' => $_['details']->CATEGORIES)); +endif; +if(isset($_['details']->DUE)): + echo $this->inc('part.property', array('label' => $l->t('Due'), 'property' => $_['details']->DUE[0])); +endif; +if(isset($_['details']->PRIORITY)): + echo $this->inc('part.property', array('label' => $l->t('Priority'), 'property' => $_['details']->PRIORITY[0], 'options' => $_['priority_options'])); +endif; +if($_['details']->__isset('PERCENT-COMPLETE') || isset($_['details']->COMPLETED)): +?> + + + '; +endif; +if(isset($_['details']->DESCRIPTION)): + echo $this->inc('part.property', array('label' => $l->t('Description'), 'property' => $_['details']->DESCRIPTION)); +endif; ?>
    + t('Complete') ?> + +__isset('PERCENT-COMPLETE')): + echo $_['details']->__get('PERCENT-COMPLETE')->value.' % '; + endif; + if(isset($_['details']->COMPLETED)): + echo $l->t('on '). $l->l('datetime', $_['details']->COMPLETED[0]->getDateTime()); + endif; + echo '
    + + diff --git a/apps/tasks/templates/part.property.php b/apps/tasks/templates/part.property.php index 68acd68954..591fd363e6 100644 --- a/apps/tasks/templates/part.property.php +++ b/apps/tasks/templates/part.property.php @@ -3,6 +3,20 @@ - value ?> + l('datetime', $_['property']->getDateTime()); + break; + default: + $value = $_['property']->value; + if (isset($_['options'])) + { + $value = $_['options'][$value]; + } + echo nl2br($value); + } + ?> diff --git a/apps/tasks/templates/part.taskform.php b/apps/tasks/templates/part.taskform.php index 8fe917c946..139693c0e9 100644 --- a/apps/tasks/templates/part.taskform.php +++ b/apps/tasks/templates/part.taskform.php @@ -1,2 +1,42 @@ -
    + +
    + + +
    + + +
    + + +
    + + + __get('PERCENT-COMPLETE') && $_['details']->__get('PERCENT-COMPLETE')->value == 100) ? '' : ' style="display:none;"' ?>> + +
    + + +
    +
    + +
    From 0dd5fd5cd3c39fa7ffa1858dbfb5292a347a4aa2 Mon Sep 17 00:00:00 2001 From: Bart Visscher Date: Tue, 20 Sep 2011 21:25:28 +0200 Subject: [PATCH 03/38] Mark form field with error message --- apps/tasks/css/style.css | 2 ++ apps/tasks/js/tasks.js | 10 +++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/apps/tasks/css/style.css b/apps/tasks/css/style.css index 3867f07012..738f4f625b 100644 --- a/apps/tasks/css/style.css +++ b/apps/tasks/css/style.css @@ -1,2 +1,4 @@ #task_details th { padding:2px; text-align:right ;vertical-align:top; } #task_details td { padding:2px; text-align:left ;vertical-align:top; } +.error_msg{color:red;} +.error{border-color:red;border-width:2px;} diff --git a/apps/tasks/js/tasks.js b/apps/tasks/js/tasks.js index e145389a95..e695925aad 100644 --- a/apps/tasks/js/tasks.js +++ b/apps/tasks/js/tasks.js @@ -92,12 +92,20 @@ $(document).ready(function(){ $('#tasks_edittaskform input[type="submit"]').live('click',function(){ $.post('ajax/edittask.php',$('#tasks_edittaskform').serialize(),function(jsondata){ + $('.error_msg').remove(); + $('.error').removeClass('error'); if(jsondata.status == 'success'){ $('#task_details').data('id',jsondata.data.id); $('#task_details').html(jsondata.data.page); } else{ - alert(jsondata.data.errors);//TODO + var errors = jsondata.data.errors; + for (k in errors){ + $('#'+k).addClass('error') + .after(''+errors[k]+''); + } + $('.error_msg').effect('highlight', {}, 3000); + $('.error').effect('highlight', {}, 3000); } }, 'json'); return false; From c30aa4ddebaefe93ec82f4f73d615a7ba1025e61 Mon Sep 17 00:00:00 2001 From: Bart Visscher Date: Thu, 6 Oct 2011 21:21:38 +0200 Subject: [PATCH 04/38] Start using OC_JSON in tasks app --- apps/tasks/ajax/addtask.php | 14 +++++--------- apps/tasks/ajax/addtaskform.php | 10 +++------- apps/tasks/ajax/delete.php | 15 +++++---------- apps/tasks/ajax/edittask.php | 16 ++++++---------- apps/tasks/ajax/edittaskform.php | 14 +++++--------- apps/tasks/ajax/getdetails.php | 10 +++------- apps/tasks/index.php | 6 ++---- 7 files changed, 29 insertions(+), 56 deletions(-) diff --git a/apps/tasks/ajax/addtask.php b/apps/tasks/ajax/addtask.php index 81905666ff..d2bd46f56a 100644 --- a/apps/tasks/ajax/addtask.php +++ b/apps/tasks/ajax/addtask.php @@ -2,25 +2,21 @@ // Init owncloud require_once('../../../lib/base.php'); +OC_JSON::checkLoggedIn(); +OC_JSON::checkAppEnabled('tasks'); $l10n = new OC_L10N('tasks'); -// Check if we are a user -if( !OC_User::isLoggedIn()){ - echo json_encode( array( 'status' => 'error', 'data' => array( 'message' => $l10n->t('You need to log in!')))); - exit(); -} - $cid = $_POST['id']; $calendar = OC_Calendar_Calendar::findCalendar( $cid ); if( $calendar === false || $calendar['userid'] != OC_USER::getUser()){ - echo json_encode( array( 'status' => 'error', 'data' => array( 'message' => $l10n->t('This is not your calendar!')))); + OC_JSON::error(array('data' => array( 'message' => $l10n->t('This is not your calendar!')))); exit(); } $errors = OC_Task_VTodo::validateRequest($_POST, $l10n); if (!empty($errors)) { - echo json_encode( array( 'status' => 'error', 'data' => array( 'errors' => $errors ))); + OC_JSON::error(array('data' => array( 'errors' => $errors ))); exit(); } @@ -34,4 +30,4 @@ $tmpl->assign('details',$vcalendar->VTODO); $tmpl->assign('id',$id); $page = $tmpl->fetchPage(); -echo json_encode( array( 'status' => 'success', 'data' => array( 'id' => $id, 'page' => $page ))); +OC_JSON::success(array('data' => array( 'id' => $id, 'page' => $page ))); diff --git a/apps/tasks/ajax/addtaskform.php b/apps/tasks/ajax/addtaskform.php index 297c590060..222ccbd79a 100644 --- a/apps/tasks/ajax/addtaskform.php +++ b/apps/tasks/ajax/addtaskform.php @@ -2,18 +2,14 @@ // Init owncloud require_once('../../../lib/base.php'); +OC_JSON::checkLoggedIn(); +OC_JSON::checkAppEnabled('tasks'); $l10n = new OC_L10N('tasks'); -// Check if we are a user -if( !OC_User::isLoggedIn()){ - echo json_encode( array( 'status' => 'error', 'data' => array( 'message' => $l10n->t('You need to log in!')))); - exit(); -} - $calendars = OC_Calendar_Calendar::allCalendars(OC_User::getUser(), true); $tmpl = new OC_Template('tasks','part.addtaskform'); $tmpl->assign('calendars',$calendars); $page = $tmpl->fetchPage(); -echo json_encode( array( 'status' => 'success', 'data' => array( 'page' => $page ))); +OC_JSON::success(array('data' => array( 'page' => $page ))); diff --git a/apps/tasks/ajax/delete.php b/apps/tasks/ajax/delete.php index 1d96a058d7..03c8a7e92e 100644 --- a/apps/tasks/ajax/delete.php +++ b/apps/tasks/ajax/delete.php @@ -22,28 +22,23 @@ // Init owncloud require_once('../../../lib/base.php'); +OC_JSON::checkLoggedIn(); +OC_JSON::checkAppEnabled('tasks'); $l10n = new OC_L10N('tasks'); -// Check if we are a user -if( !OC_User::isLoggedIn()){ - echo json_encode( array( 'status' => 'error', 'data' => array( 'message' => $l10n->t('You need to log in!')))); - exit(); -} - - $id = $_GET['id']; $task = OC_Calendar_Object::find( $id ); if( $task === false ){ - echo json_encode( array( 'status' => 'error', 'data' => array( 'message' => $l10n->t('Can not find Task!')))); + OC_JSON::error(array('data' => array( 'message' => $l10n->t('Can not find Task!')))); exit(); } $calendar = OC_Calendar_Calendar::findCalendar( $task['calendarid'] ); if( $calendar === false || $calendar['userid'] != OC_USER::getUser()){ - echo json_encode( array( 'status' => 'error', 'data' => array( 'message' => $l10n->t('This is not your task!')))); + OC_JSON::error(array('data' => array( 'message' => $l10n->t('This is not your task!')))); exit(); } OC_Calendar_Object::delete($id); -echo json_encode( array( 'status' => 'success', 'data' => array( 'id' => $id ))); +OC_JSON::success(array('data' => array( 'id' => $id ))); diff --git a/apps/tasks/ajax/edittask.php b/apps/tasks/ajax/edittask.php index 9f836f1f8a..e9603d92da 100644 --- a/apps/tasks/ajax/edittask.php +++ b/apps/tasks/ajax/edittask.php @@ -2,31 +2,27 @@ // Init owncloud require_once('../../../lib/base.php'); +OC_JSON::checkLoggedIn(); +OC_JSON::checkAppEnabled('tasks'); $l10n = new OC_L10N('tasks'); -// Check if we are a user -if( !OC_User::isLoggedIn()){ - echo json_encode( array( 'status' => 'error', 'data' => array( 'message' => $l10n->t('You need to log in!')))); - exit(); -} - $id = $_POST['id']; $task = OC_Calendar_Object::find( $id ); if( $task === false ){ - echo json_encode( array( 'status' => 'error', 'data' => array( 'message' => $l10n->t('Can not find Task!')))); + OC_JSON::error(array('data' => array( 'message' => $l10n->t('Can not find Task!')))); exit(); } $calendar = OC_Calendar_Calendar::findCalendar( $task['calendarid'] ); if( $calendar === false || $calendar['userid'] != OC_USER::getUser()){ - echo json_encode( array( 'status' => 'error', 'data' => array( 'message' => $l10n->t('This is not your task!')))); + OC_JSON::error(array('data' => array( 'message' => $l10n->t('This is not your task!')))); exit(); } $errors = OC_Task_VTodo::validateRequest($_POST, $l10n); if (!empty($errors)) { - echo json_encode( array( 'status' => 'error', 'data' => array( 'errors' => $errors ))); + OC_JSON::error(array('data' => array( 'errors' => $errors ))); exit(); } @@ -41,4 +37,4 @@ $tmpl->assign('details', $vcalendar->VTODO); $tmpl->assign('id', $id); $page = $tmpl->fetchPage(); -echo json_encode( array( 'status' => 'success', 'data' => array( 'id' => $id, 'page' => $page ))); +OC_JSON::success(array('data' => array( 'id' => $id, 'page' => $page ))); diff --git a/apps/tasks/ajax/edittaskform.php b/apps/tasks/ajax/edittaskform.php index dc8bb60e64..b309413683 100644 --- a/apps/tasks/ajax/edittaskform.php +++ b/apps/tasks/ajax/edittaskform.php @@ -2,25 +2,21 @@ // Init owncloud require_once('../../../lib/base.php'); +OC_JSON::checkLoggedIn(); +OC_JSON::checkAppEnabled('tasks'); $l10n = new OC_L10N('tasks'); -// Check if we are a user -if( !OC_User::isLoggedIn()){ - echo json_encode( array( 'status' => 'error', 'data' => array( 'message' => $l10n->t('You need to log in!')))); - exit(); -} - $id = $_GET['id']; $task = OC_Calendar_Object::find( $id ); if( $task === false ){ - echo json_encode( array( 'status' => 'error', 'data' => array( 'message' => $l10n->t('Can not find Task!')))); + OC_JSON::error(array('data' => array( 'message' => $l10n->t('Can not find Task!')))); exit(); } $calendar = OC_Calendar_Calendar::findCalendar( $task['calendarid'] ); if( $calendar === false || $calendar['userid'] != OC_USER::getUser()){ - echo json_encode( array( 'status' => 'error', 'data' => array( 'message' => $l10n->t('This is not your task!')))); + OC_JSON::error(array('data' => array( 'message' => $l10n->t('This is not your task!')))); exit(); } @@ -44,4 +40,4 @@ $tmpl->assign('details',$details); $tmpl->assign('categories', $categories); $page = $tmpl->fetchPage(); -echo json_encode( array( 'status' => 'success', 'data' => array( 'page' => $page ))); +OC_JSON::success(array('data' => array( 'page' => $page ))); diff --git a/apps/tasks/ajax/getdetails.php b/apps/tasks/ajax/getdetails.php index f111a399b3..08bf6c9ecf 100644 --- a/apps/tasks/ajax/getdetails.php +++ b/apps/tasks/ajax/getdetails.php @@ -2,15 +2,11 @@ // Init owncloud require_once('../../../lib/base.php'); +OC_JSON::checkLoggedIn(); +OC_JSON::checkAppEnabled('tasks'); $l10n = new OC_L10N('tasks'); -// Check if we are a user -if( !OC_User::isLoggedIn()){ - echo json_encode( array( 'status' => 'error', 'data' => array( 'message' => $l10n->t('You need to log in!')))); - exit(); -} - $id = $_GET['id']; $task = OC_Calendar_Object::find($id); $details = Sabre_VObject_Reader::read($task['calendardata'])->VTODO; @@ -22,4 +18,4 @@ $tmpl->assign('details',$details); $tmpl->assign('id',$id); $page = $tmpl->fetchPage(); -echo json_encode( array( 'status' => 'success', 'data' => array( 'id' => $id, 'page' => $page ))); +OC_JSON::success(array('data' => array( 'id' => $id, 'page' => $page ))); diff --git a/apps/tasks/index.php b/apps/tasks/index.php index 696ab11dd6..a653326338 100644 --- a/apps/tasks/index.php +++ b/apps/tasks/index.php @@ -9,10 +9,8 @@ *************************************************/ require_once ('../../lib/base.php'); -if(!OC_USER::isLoggedIn()) { - header('Location: ' . OC_HELPER::linkTo('', 'index.php')); - exit; -} +OC_Util::checkLoggedIn(); +OC_Util::checkAppEnabled('tasks'); $calendars = OC_Calendar_Calendar::allCalendars(OC_User::getUser(), true); if( count($calendars) == 0){ From 5e4f28ea21f32086e28740c6689d7000c1dfd488 Mon Sep 17 00:00:00 2001 From: Bart Visscher Date: Fri, 2 Dec 2011 21:33:23 +0100 Subject: [PATCH 05/38] Tasks: Fix php warnings with empty tasks list --- apps/tasks/index.php | 1 + apps/tasks/templates/part.details.php | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/tasks/index.php b/apps/tasks/index.php index a653326338..d2624a1cf0 100644 --- a/apps/tasks/index.php +++ b/apps/tasks/index.php @@ -34,6 +34,7 @@ foreach( $calendars as $calendar ){ } } +$details = null; if( !is_null($id) || count($tasks)){ if(is_null($id)) $id = $tasks[0]['id']; $task = OC_Calendar_Object::find($id); diff --git a/apps/tasks/templates/part.details.php b/apps/tasks/templates/part.details.php index a6561d97be..89636b6e76 100644 --- a/apps/tasks/templates/part.details.php +++ b/apps/tasks/templates/part.details.php @@ -38,5 +38,5 @@ endif; ?> - + From 76c37792cb322338f73f25a559a2ccfe5ae8b59d Mon Sep 17 00:00:00 2001 From: Bart Visscher Date: Fri, 9 Dec 2011 21:41:21 +0100 Subject: [PATCH 06/38] WIP --- apps/tasks/ajax/edittask.php | 2 +- apps/tasks/ajax/getdetails.php | 8 +++-- apps/tasks/index.php | 4 +++ apps/tasks/lib/vtodo.php | 62 ++++++++++------------------------ 4 files changed, 28 insertions(+), 48 deletions(-) diff --git a/apps/tasks/ajax/edittask.php b/apps/tasks/ajax/edittask.php index e9603d92da..115f2f078a 100644 --- a/apps/tasks/ajax/edittask.php +++ b/apps/tasks/ajax/edittask.php @@ -26,7 +26,7 @@ if (!empty($errors)) { exit(); } -$vcalendar = Sabre_VObject_Reader::read($task['calendardata']); +$vcalendar = OC_VObject::parse($task['calendardata']); OC_Task_VTodo::updateVCalendarFromRequest($_POST, $vcalendar); OC_Calendar_Object::edit($id, $vcalendar->serialize()); diff --git a/apps/tasks/ajax/getdetails.php b/apps/tasks/ajax/getdetails.php index 08bf6c9ecf..222c426d52 100644 --- a/apps/tasks/ajax/getdetails.php +++ b/apps/tasks/ajax/getdetails.php @@ -9,12 +9,16 @@ $l10n = new OC_L10N('tasks'); $id = $_GET['id']; $task = OC_Calendar_Object::find($id); -$details = Sabre_VObject_Reader::read($task['calendardata'])->VTODO; +$details = OC_VObject::parse($task['calendardata']); +if (!$details){ + OC_JSON::error(); + exit; +} $priority_options = OC_Task_VTodo::getPriorityOptions($l10n); $tmpl = new OC_Template('tasks','part.details'); $tmpl->assign('priority_options', $priority_options); -$tmpl->assign('details',$details); +$tmpl->assign('details',$details->VTODO); $tmpl->assign('id',$id); $page = $tmpl->fetchPage(); diff --git a/apps/tasks/index.php b/apps/tasks/index.php index d2624a1cf0..145ec145ae 100644 --- a/apps/tasks/index.php +++ b/apps/tasks/index.php @@ -44,8 +44,12 @@ if( !is_null($id) || count($tasks)){ OC_UTIL::addScript('tasks', 'tasks'); OC_UTIL::addStyle('tasks', 'style'); OC_APP::setActiveNavigationEntry('tasks_index'); + +$l10n = new OC_L10N('tasks'); +$priority_options = OC_Task_VTodo::getPriorityOptions($l10n); $output = new OC_Template('tasks', 'tasks', 'user'); $output->assign('tasks', $tasks); $output->assign('details', $details); +$output->assign('priority_options', $priority_options); $output->assign('id',$id); $output -> printPage(); diff --git a/apps/tasks/lib/vtodo.php b/apps/tasks/lib/vtodo.php index 925ad77dea..967f5b87a5 100644 --- a/apps/tasks/lib/vtodo.php +++ b/apps/tasks/lib/vtodo.php @@ -39,7 +39,7 @@ class OC_Task_VTodo extends OC_Calendar_Object{ '9' => $l10n->t('9=lowest'), ); } - public static function validateRequest($request, $l10n) + public static function validateRequest($request, $l10n=null) { $errors = array(); if($request['summary'] == ''){ @@ -102,7 +102,7 @@ class OC_Task_VTodo extends OC_Calendar_Object{ public static function updateVCalendarFromRequest($request, $vcalendar) { $summary = $request['summary']; - $categories = $request['categories']; + $categories = isset($request["categories"]) ? $request["categories"] : array(); $priority = $request['priority']; $percent_complete = $request['percent_complete']; $completed = $request['completed']; @@ -110,55 +110,28 @@ class OC_Task_VTodo extends OC_Calendar_Object{ $due = $request['due']; $description = $request['description']; - $now = new DateTime(); - $vtodo = $vcalendar->VTODO[0]; + $vtodo = $vcalendar->VTODO; - $last_modified = new Sabre_VObject_Element_DateTime('LAST-MODIFIED'); - $last_modified->setDateTime($now, Sabre_VObject_Element_DateTime::UTC); - $vtodo->__set('LAST-MODIFIED', $last_modified); + $vtodo->setDateTime('LAST-MODIFIED', 'now', Sabre_VObject_Element_DateTime::UTC); + $vtodo->setDateTime('DTSTAMP', 'now', Sabre_VObject_Element_DateTime::UTC); + $vtodo->setString('SUMMARY', $summary); - $dtstamp = new Sabre_VObject_Element_DateTime('DTSTAMP'); - $dtstamp->setDateTime($now, Sabre_VObject_Element_DateTime::UTC); - $vtodo->DTSTAMP = $dtstamp; - - $vtodo->SUMMARY = $summary; - - if ($location != '') { - $vtodo->LOCATION = $location; - }else{ - unset($vtodo->LOCATION); - } - - if ($categories != '') { - $vtodo->CATEGORIES = join(',',$categories); - }else{ - unset($vtodo->CATEGORIES); - } - - if ($priority != '') { - $vtodo->PRIORITY = $priority; - }else{ - unset($vtodo->PRIORITY); - } - - if ($description != '') { - $vtodo->DESCRIPTION = $description; - }else{ - unset($vtodo->DESCRIPTION); - } + $vtodo->setString('LOCATION', $location); + $vtodo->setString('DESCRIPTION', $description); + $vtodo->setString('CATEGORIES', join(',', $categories)); + $vtodo->setString('PRIORITY', $priority); if ($due) { - $due_property = new Sabre_VObject_Element_DateTime('DUE'); - $timezone = OC_Preferences::getValue(OC_USER::getUser(), "calendar", "timezone", "Europe/London"); + $timezone = OC_Preferences::getValue(OC_USER::getUser(), 'calendar', 'timezone', date_default_timezone_get()); $timezone = new DateTimeZone($timezone); - $due_property->setDateTime(new DateTime($due, $timezone)); - $vtodo->DUE = $due_property; + $due = new DateTime($due, $timezone); + $vtodo->setDateTime('DUE', $due); } else { unset($vtodo->DUE); } if (!empty($percent_complete)) { - $vtodo->__set('PERCENT-COMPLETE', $percent_complete); + $vtodo->setString('PERCENT-COMPLETE', $percent_complete); }else{ $vtodo->__unset('PERCENT-COMPLETE'); } @@ -171,11 +144,10 @@ class OC_Task_VTodo extends OC_Calendar_Object{ $completed = null; } if ($completed) { - $completed_property = new Sabre_VObject_Element_DateTime('COMPLETED'); - $timezone = OC_Preferences::getValue(OC_USER::getUser(), "calendar", "timezone", "Europe/London"); + $timezone = OC_Preferences::getValue(OC_USER::getUser(), 'calendar', 'timezone', date_default_timezone_get()); $timezone = new DateTimeZone($timezone); - $completed_property->setDateTime(new DateTime($completed, $timezone)); - $vtodo->COMPLETED = $completed_property; + $completed = new DateTime($completed, $timezone); + $vtodo->setDateTime('COMPLETED', $completed); } else { unset($vtodo->COMPLETED); } From 499ec15c26f23ee854a562358c43a11cd7a75e8e Mon Sep 17 00:00:00 2001 From: Bart Visscher Date: Wed, 22 Feb 2012 13:32:04 +0100 Subject: [PATCH 07/38] Add icon for tasks app --- apps/tasks/appinfo/app.php | 2 +- apps/tasks/img/icon.png | Bin 0 -> 457 bytes apps/tasks/img/icon.svg | 101 +++++++++++++++++++++++++++++++++++++ 3 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 apps/tasks/img/icon.png create mode 100644 apps/tasks/img/icon.svg diff --git a/apps/tasks/appinfo/app.php b/apps/tasks/appinfo/app.php index e94f991f73..24441c7547 100644 --- a/apps/tasks/appinfo/app.php +++ b/apps/tasks/appinfo/app.php @@ -12,5 +12,5 @@ OC_App::addNavigationEntry( array( 'id' => 'tasks_index', 'order' => 11, 'href' => OC_Helper::linkTo( 'tasks', 'index.php' ), - //'icon' => OC_Helper::imagePath( 'tasks', 'icon.png' ), + 'icon' => OC_Helper::imagePath( 'tasks', 'icon.png' ), 'name' => $l->t('Tasks'))); diff --git a/apps/tasks/img/icon.png b/apps/tasks/img/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..df281f3ba8605658e9769156c4a4fdb9918e1220 GIT binary patch literal 457 zcmV;)0XF`LP)5*)6z`h(ouW>>E;_q2k9clp&2@ggLVjRZCX4oL9~ex?1c;W!1sS#&be2K2#YLZ zq4d0<-ENm$*IoH5)a`bcQU$ZwtPc!Zt=48*u+!;SuIpY727__4**r-IeBUntb{K|F zwrz`2>TBooc?p7G44eTXBF_NodlOC5lv=HJ59|Ovt@SQ|=Xu5HblL;fN23viLSaj5 z{g4nSrKHhltOAcf5jcp?cfbbF_dIWVGMT8<9sp>q-++s_JO^&#uy0w`Q4~c#_|!4x za=B~Z1K0!hffv&>4=a^QIM1dE%H{Gq5X5C<7{+n6T76ApvmVkdfKuwTUa$9mgR%q; zu;w_ + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + From 7f754c02f3728bf8d71e3e61264504c88e92bdd2 Mon Sep 17 00:00:00 2001 From: Bart Visscher Date: Wed, 22 Feb 2012 20:11:38 +0100 Subject: [PATCH 08/38] Change code from using OC_Tasks_VTodo to OC_Tasks_App --- apps/tasks/ajax/addtask.php | 6 +- apps/tasks/ajax/edittask.php | 6 +- apps/tasks/ajax/edittaskform.php | 2 +- apps/tasks/ajax/getdetails.php | 2 +- apps/tasks/appinfo/app.php | 2 +- apps/tasks/index.php | 2 +- apps/tasks/lib/app.php | 162 +++++++++++++++++++++++++++++++ apps/tasks/lib/vtodo.php | 133 +------------------------ 8 files changed, 173 insertions(+), 142 deletions(-) create mode 100644 apps/tasks/lib/app.php diff --git a/apps/tasks/ajax/addtask.php b/apps/tasks/ajax/addtask.php index d2bd46f56a..c768d3e7d9 100644 --- a/apps/tasks/ajax/addtask.php +++ b/apps/tasks/ajax/addtask.php @@ -14,16 +14,16 @@ if( $calendar === false || $calendar['userid'] != OC_USER::getUser()){ exit(); } -$errors = OC_Task_VTodo::validateRequest($_POST, $l10n); +$errors = OC_Task_App::validateRequest($_POST); if (!empty($errors)) { OC_JSON::error(array('data' => array( 'errors' => $errors ))); exit(); } -$vcalendar = OC_Task_VTodo::createVCalendarFromRequest($_POST); +$vcalendar = OC_Task_App::createVCalendarFromRequest($_POST); $id = OC_Calendar_Object::add($cid, $vcalendar->serialize()); -$priority_options = OC_Task_VTodo::getPriorityOptions($l10n); +$priority_options = OC_Task_App::getPriorityOptions(); $tmpl = new OC_Template('tasks','part.details'); $tmpl->assign('priority_options', $priority_options); $tmpl->assign('details',$vcalendar->VTODO); diff --git a/apps/tasks/ajax/edittask.php b/apps/tasks/ajax/edittask.php index 115f2f078a..edfca33833 100644 --- a/apps/tasks/ajax/edittask.php +++ b/apps/tasks/ajax/edittask.php @@ -20,17 +20,17 @@ if( $calendar === false || $calendar['userid'] != OC_USER::getUser()){ exit(); } -$errors = OC_Task_VTodo::validateRequest($_POST, $l10n); +$errors = OC_Task_App::validateRequest($_POST); if (!empty($errors)) { OC_JSON::error(array('data' => array( 'errors' => $errors ))); exit(); } $vcalendar = OC_VObject::parse($task['calendardata']); -OC_Task_VTodo::updateVCalendarFromRequest($_POST, $vcalendar); +OC_Task_App::updateVCalendarFromRequest($_POST, $vcalendar); OC_Calendar_Object::edit($id, $vcalendar->serialize()); -$priority_options = OC_Task_VTodo::getPriorityOptions($l10n); +$priority_options = OC_Task_App::getPriorityOptions(); $tmpl = new OC_Template('tasks','part.details'); $tmpl->assign('priority_options', $priority_options); $tmpl->assign('details', $vcalendar->VTODO); diff --git a/apps/tasks/ajax/edittaskform.php b/apps/tasks/ajax/edittaskform.php index b309413683..b9c1f700b6 100644 --- a/apps/tasks/ajax/edittaskform.php +++ b/apps/tasks/ajax/edittaskform.php @@ -29,7 +29,7 @@ if (isset($details->CATEGORIES)){ $category_options = OC_Calendar_Object::getCategoryOptions($l10n); $percent_options = range(0, 100, 10); -$priority_options = OC_Task_VTodo::getPriorityOptions($l10n); +$priority_options = OC_Task_App::getPriorityOptions(); $tmpl = new OC_Template('tasks','part.edittaskform'); $tmpl->assign('category_options', $category_options); diff --git a/apps/tasks/ajax/getdetails.php b/apps/tasks/ajax/getdetails.php index 222c426d52..2e6e8181f1 100644 --- a/apps/tasks/ajax/getdetails.php +++ b/apps/tasks/ajax/getdetails.php @@ -15,7 +15,7 @@ if (!$details){ exit; } -$priority_options = OC_Task_VTodo::getPriorityOptions($l10n); +$priority_options = OC_Task_App::getPriorityOptions(); $tmpl = new OC_Template('tasks','part.details'); $tmpl->assign('priority_options', $priority_options); $tmpl->assign('details',$details->VTODO); diff --git a/apps/tasks/appinfo/app.php b/apps/tasks/appinfo/app.php index 24441c7547..657c56c040 100644 --- a/apps/tasks/appinfo/app.php +++ b/apps/tasks/appinfo/app.php @@ -1,7 +1,7 @@ 11, diff --git a/apps/tasks/index.php b/apps/tasks/index.php index 145ec145ae..e2f559dfeb 100644 --- a/apps/tasks/index.php +++ b/apps/tasks/index.php @@ -46,7 +46,7 @@ OC_UTIL::addStyle('tasks', 'style'); OC_APP::setActiveNavigationEntry('tasks_index'); $l10n = new OC_L10N('tasks'); -$priority_options = OC_Task_VTodo::getPriorityOptions($l10n); +$priority_options = OC_Task_App::getPriorityOptions(); $output = new OC_Template('tasks', 'tasks', 'user'); $output->assign('tasks', $tasks); $output->assign('details', $details); diff --git a/apps/tasks/lib/app.php b/apps/tasks/lib/app.php new file mode 100644 index 0000000000..92be594424 --- /dev/null +++ b/apps/tasks/lib/app.php @@ -0,0 +1,162 @@ +. + * + */ + +/** + * This class manages our tasks + */ +OC_Task_App::$l10n = new OC_L10N('tasks'); +class OC_Task_App { + public static $l10n; + + public static function getPriorityOptions() + { + return array( + '' => self::$l10n->t('Unspecified'), + '1' => self::$l10n->t('1=highest'), + '2' => '2', + '3' => '3', + '4' => '4', + '5' => self::$l10n->t('5=medium'), + '6' => '6', + '7' => '7', + '8' => '8', + '9' => self::$l10n->t('9=lowest'), + ); + } + + public static function validateRequest($request) + { + $errors = array(); + if($request['summary'] == ''){ + $errors['summary'] = self::$l10n->t('Empty Summary'); + } + + if(isset($request['categories']) && !is_array($request['categories'])){ + $errors['categories'] = self::$l10n->t('Not an array'); + } + + try { + $timezone = OC_Preferences::getValue(OC_USER::getUser(), "calendar", "timezone", "Europe/London"); + $timezone = new DateTimeZone($timezone); + new DateTime($request['due'], $timezone); + } catch (Exception $e) { + $errors['due'] = self::$l10n->t('Invalid date/time'); + } + + if ($request['percent_complete'] < 0 || $request['percent_complete'] > 100){ + $errors['percent_complete'] = self::$l10n->t('Invalid percent complete'); + } + if ($request['percent_complete'] == 100 && !empty($request['completed'])){ + try { + $timezone = OC_Preferences::getValue(OC_USER::getUser(), "calendar", "timezone", "Europe/London"); + $timezone = new DateTimeZone($timezone); + new DateTime($request['completed'], $timezone); + } catch (Exception $e) { + $errors['completed'] = self::$l10n->t('Invalid date/time'); + } + } + + $priority_options = self::getPriorityOptions(); + if (!in_array($request['priority'], array_keys($priority_options))) { + $errors['priority'] = self::$l10n->t('Invalid priority'); + } + return $errors; + } + + public static function createVCalendarFromRequest($request) + { + $vcalendar = new Sabre_VObject_Component('VCALENDAR'); + $vcalendar->add('PRODID', 'ownCloud Calendar'); + $vcalendar->add('VERSION', '2.0'); + + $now = new DateTime(); + + $vtodo = new Sabre_VObject_Component('VTODO'); + $vcalendar->add($vtodo); + + $created = new Sabre_VObject_Element_DateTime('CREATED'); + $created->setDateTime($now, Sabre_VObject_Element_DateTime::UTC); + $vtodo->add($created); + + $uid = self::createUID(); + $vtodo->add('UID',$uid); + + return self::updateVCalendarFromRequest($request, $vcalendar); + } + + public static function updateVCalendarFromRequest($request, $vcalendar) + { + $summary = $request['summary']; + $categories = isset($request["categories"]) ? $request["categories"] : array(); + $priority = $request['priority']; + $percent_complete = $request['percent_complete']; + $completed = $request['completed']; + $location = $request['location']; + $due = $request['due']; + $description = $request['description']; + + $vtodo = $vcalendar->VTODO; + + $vtodo->setDateTime('LAST-MODIFIED', 'now', Sabre_VObject_Element_DateTime::UTC); + $vtodo->setDateTime('DTSTAMP', 'now', Sabre_VObject_Element_DateTime::UTC); + $vtodo->setString('SUMMARY', $summary); + + $vtodo->setString('LOCATION', $location); + $vtodo->setString('DESCRIPTION', $description); + $vtodo->setString('CATEGORIES', join(',', $categories)); + $vtodo->setString('PRIORITY', $priority); + + if ($due) { + $timezone = OC_Preferences::getValue(OC_USER::getUser(), 'calendar', 'timezone', date_default_timezone_get()); + $timezone = new DateTimeZone($timezone); + $due = new DateTime($due, $timezone); + $vtodo->setDateTime('DUE', $due); + } else { + unset($vtodo->DUE); + } + + if (!empty($percent_complete)) { + $vtodo->setString('PERCENT-COMPLETE', $percent_complete); + }else{ + $vtodo->__unset('PERCENT-COMPLETE'); + } + + if ($percent_complete == 100){ + if (!$completed){ + $completed = 'now'; + } + } else { + $completed = null; + } + if ($completed) { + $timezone = OC_Preferences::getValue(OC_USER::getUser(), 'calendar', 'timezone', date_default_timezone_get()); + $timezone = new DateTimeZone($timezone); + $completed = new DateTime($completed, $timezone); + $vtodo->setDateTime('COMPLETED', $completed); + } else { + unset($vtodo->COMPLETED); + } + + return $vcalendar; + } +} + diff --git a/apps/tasks/lib/vtodo.php b/apps/tasks/lib/vtodo.php index 967f5b87a5..dc2bfaf964 100644 --- a/apps/tasks/lib/vtodo.php +++ b/apps/tasks/lib/vtodo.php @@ -21,138 +21,7 @@ */ /** - * This class manages our calendars + * This class manages our tasks */ class OC_Task_VTodo extends OC_Calendar_Object{ - public static function getPriorityOptions($l10n) - { - return array( - '' => $l10n->t('Unspecified'), - '1' => $l10n->t('1=highest'), - '2' => '2', - '3' => '3', - '4' => '4', - '5' => $l10n->t('5=medium'), - '6' => '6', - '7' => '7', - '8' => '8', - '9' => $l10n->t('9=lowest'), - ); - } - public static function validateRequest($request, $l10n=null) - { - $errors = array(); - if($request['summary'] == ''){ - $errors['summary'] = $l10n->t('Empty Summary'); - } - - if(isset($request['categories']) && !is_array($request['categories'])){ - $errors['categories'] = $l10n->t('Not an array'); - } - - try { - $timezone = OC_Preferences::getValue(OC_USER::getUser(), "calendar", "timezone", "Europe/London"); - $timezone = new DateTimeZone($timezone); - new DateTime($request['due'], $timezone); - } catch (Exception $e) { - $errors['due'] = $l10n->t('Invalid date/time'); - } - - if ($request['percent_complete'] < 0 || $request['percent_complete'] > 100){ - $errors['percent_complete'] = $l10n->t('Invalid percent complete'); - } - if ($request['percent_complete'] == 100 && !empty($request['completed'])){ - try { - $timezone = OC_Preferences::getValue(OC_USER::getUser(), "calendar", "timezone", "Europe/London"); - $timezone = new DateTimeZone($timezone); - new DateTime($request['completed'], $timezone); - } catch (Exception $e) { - $errors['completed'] = $l10n->t('Invalid date/time'); - } - } - - $priority_options = OC_Task_VTodo::getPriorityOptions($l10n); - if (!in_array($request['priority'], array_keys($priority_options))) { - $errors['priority'] = $l10n->t('Invalid priority'); - } - return $errors; - } - - public static function createVCalendarFromRequest($request) - { - $vcalendar = new Sabre_VObject_Component('VCALENDAR'); - $vcalendar->add('PRODID', 'ownCloud Calendar'); - $vcalendar->add('VERSION', '2.0'); - - $now = new DateTime(); - - $vtodo = new Sabre_VObject_Component('VTODO'); - $vcalendar->add($vtodo); - - $created = new Sabre_VObject_Element_DateTime('CREATED'); - $created->setDateTime($now, Sabre_VObject_Element_DateTime::UTC); - $vtodo->add($created); - - $uid = self::createUID(); - $vtodo->add('UID',$uid); - - return self::updateVCalendarFromRequest($request, $vcalendar); - } - - public static function updateVCalendarFromRequest($request, $vcalendar) - { - $summary = $request['summary']; - $categories = isset($request["categories"]) ? $request["categories"] : array(); - $priority = $request['priority']; - $percent_complete = $request['percent_complete']; - $completed = $request['completed']; - $location = $request['location']; - $due = $request['due']; - $description = $request['description']; - - $vtodo = $vcalendar->VTODO; - - $vtodo->setDateTime('LAST-MODIFIED', 'now', Sabre_VObject_Element_DateTime::UTC); - $vtodo->setDateTime('DTSTAMP', 'now', Sabre_VObject_Element_DateTime::UTC); - $vtodo->setString('SUMMARY', $summary); - - $vtodo->setString('LOCATION', $location); - $vtodo->setString('DESCRIPTION', $description); - $vtodo->setString('CATEGORIES', join(',', $categories)); - $vtodo->setString('PRIORITY', $priority); - - if ($due) { - $timezone = OC_Preferences::getValue(OC_USER::getUser(), 'calendar', 'timezone', date_default_timezone_get()); - $timezone = new DateTimeZone($timezone); - $due = new DateTime($due, $timezone); - $vtodo->setDateTime('DUE', $due); - } else { - unset($vtodo->DUE); - } - - if (!empty($percent_complete)) { - $vtodo->setString('PERCENT-COMPLETE', $percent_complete); - }else{ - $vtodo->__unset('PERCENT-COMPLETE'); - } - - if ($percent_complete == 100){ - if (!$completed){ - $completed = 'now'; - } - } else { - $completed = null; - } - if ($completed) { - $timezone = OC_Preferences::getValue(OC_USER::getUser(), 'calendar', 'timezone', date_default_timezone_get()); - $timezone = new DateTimeZone($timezone); - $completed = new DateTime($completed, $timezone); - $vtodo->setDateTime('COMPLETED', $completed); - } else { - unset($vtodo->COMPLETED); - } - - return $vcalendar; - } } - From 92db4f8be099c32b477bba33412b1d2fc7a04dbc Mon Sep 17 00:00:00 2001 From: Bart Visscher Date: Wed, 22 Feb 2012 20:12:49 +0100 Subject: [PATCH 09/38] Update edittaskform for new calendar API --- apps/tasks/ajax/edittaskform.php | 16 ++-------------- apps/tasks/index.php | 4 ++-- apps/tasks/templates/part.edittaskform.php | 2 +- 3 files changed, 5 insertions(+), 17 deletions(-) diff --git a/apps/tasks/ajax/edittaskform.php b/apps/tasks/ajax/edittaskform.php index b9c1f700b6..651c26c498 100644 --- a/apps/tasks/ajax/edittaskform.php +++ b/apps/tasks/ajax/edittaskform.php @@ -8,19 +8,7 @@ OC_JSON::checkAppEnabled('tasks'); $l10n = new OC_L10N('tasks'); $id = $_GET['id']; -$task = OC_Calendar_Object::find( $id ); -if( $task === false ){ - OC_JSON::error(array('data' => array( 'message' => $l10n->t('Can not find Task!')))); - exit(); -} - -$calendar = OC_Calendar_Calendar::findCalendar( $task['calendarid'] ); -if( $calendar === false || $calendar['userid'] != OC_USER::getUser()){ - OC_JSON::error(array('data' => array( 'message' => $l10n->t('This is not your task!')))); - exit(); -} - -$details = Sabre_VObject_Reader::read($task['calendardata'])->VTODO; +$details = OC_Calendar_App::getVCalendar($id)->VTODO; $categories = array(); if (isset($details->CATEGORIES)){ $categories = explode(',', $details->CATEGORIES->value); @@ -35,7 +23,7 @@ $tmpl = new OC_Template('tasks','part.edittaskform'); $tmpl->assign('category_options', $category_options); $tmpl->assign('percent_options', $percent_options); $tmpl->assign('priority_options', $priority_options); -$tmpl->assign('task',$task); +$tmpl->assign('id',$id); $tmpl->assign('details',$details); $tmpl->assign('categories', $categories); $page = $tmpl->fetchPage(); diff --git a/apps/tasks/index.php b/apps/tasks/index.php index e2f559dfeb..f0e6c2e4dd 100644 --- a/apps/tasks/index.php +++ b/apps/tasks/index.php @@ -13,8 +13,8 @@ OC_Util::checkLoggedIn(); OC_Util::checkAppEnabled('tasks'); $calendars = OC_Calendar_Calendar::allCalendars(OC_User::getUser(), true); -if( count($calendars) == 0){ - header('Location: ' . OC_HELPER::linkTo('calendar', 'index.php')); +if( count($calendars) == 0 ) { + header('Location: ' . OC_Helper::linkTo('calendar', 'index.php')); exit; } diff --git a/apps/tasks/templates/part.edittaskform.php b/apps/tasks/templates/part.edittaskform.php index 3e26c42038..fe123f07ac 100644 --- a/apps/tasks/templates/part.edittaskform.php +++ b/apps/tasks/templates/part.edittaskform.php @@ -1,5 +1,5 @@
    - + inc('part.taskform'); ?>
    From 18bac944b4b0a63e99f6b6971de6ae788d3e39f1 Mon Sep 17 00:00:00 2001 From: Bart Visscher Date: Wed, 22 Feb 2012 20:21:27 +0100 Subject: [PATCH 10/38] Change loading of tasks to ajax call --- apps/tasks/ajax/gettasks.php | 58 ++++++++++++++++++++++++++++++++++ apps/tasks/css/style.css | 6 ++++ apps/tasks/index.php | 26 --------------- apps/tasks/js/tasks.js | 38 +++++++++++++++++++--- apps/tasks/templates/tasks.php | 17 ++++++---- 5 files changed, 109 insertions(+), 36 deletions(-) create mode 100644 apps/tasks/ajax/gettasks.php diff --git a/apps/tasks/ajax/gettasks.php b/apps/tasks/ajax/gettasks.php new file mode 100644 index 0000000000..7dc94dacb4 --- /dev/null +++ b/apps/tasks/ajax/gettasks.php @@ -0,0 +1,58 @@ + + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +// Init owncloud +require_once('../../../lib/base.php'); +OC_JSON::checkLoggedIn(); +OC_JSON::checkAppEnabled('tasks'); + +$calendars = OC_Calendar_Calendar::allCalendars(OC_User::getUser(), true); +$user_timezone = OC_Preferences::getValue(OC_USER::getUser(), 'calendar', 'timezone', date_default_timezone_get()); + +$tasks = array(); +foreach( $calendars as $calendar ){ + $calendar_tasks = OC_Calendar_Object::all($calendar['id']); + foreach( $calendar_tasks as $task ){ + if($task['objecttype']!='VTODO'){ + continue; + } + if(is_null($task['summary'])){ + continue; + } + $object = OC_VObject::parse($task['calendardata']); + $vtodo = $object->VTODO; + $task = array( 'id' => $task['id'] ); + $task['summary'] = $vtodo->getAsString('SUMMARY'); + $task['description'] = $vtodo->getAsString('DESCRIPTION'); + $task['location'] = $vtodo->getAsString('LOCATION'); + $task['categories'] = $vtodo->getAsArray('CATEGORIES'); + $due = $vtodo->DUE; + if ($due) { + $due = $due->getDateTime(); + $due->setTimezone(new DateTimeZone($user_timezone)); + $task['due'] = $due->format('Y-m-d H:i:s'); + } + else { + $task['due'] = false; + } + $task['priority'] = $vtodo->getAsString('PRIORITY'); + $completed = $vtodo->COMPLETED; + if ($completed) { + $completed = $completed->getDateTime(); + $completed->setTimezone(new DateTimeZone($user_timezone)); + $task['completed'] = $completed->format('Y-m-d H:i:s'); + } + else { + $task['completed'] = false; + } + $task['complete'] = $vtodo->getAsString('PERCENT-COMPLETE'); + $tasks[] = $task; + } +} + +OC_JSON::encodedPrint($tasks); diff --git a/apps/tasks/css/style.css b/apps/tasks/css/style.css index 738f4f625b..3a61d62716 100644 --- a/apps/tasks/css/style.css +++ b/apps/tasks/css/style.css @@ -2,3 +2,9 @@ #task_details td { padding:2px; text-align:left ;vertical-align:top; } .error_msg{color:red;} .error{border-color:red;border-width:2px;} +.task{position:relative;padding:0.5em 1em;} +.task_actions{display:none;} +.task .categories{position:absolute;right:0.6em;text-align:right;top:0.5em} +.task .categories a{background-color:#1d2d44;color:white;border-radius:0.4em;display:inline-block;opacity:0.2;margin:0 0.2em;padding:0 0.4em;} +#tasks{position:fixed; overflow: auto; top:6.4em; width:40em; background:#f8f8f8; border-right:1px solid #ddd; } +#task_details{position:absolute;left:53em;top:6.4em;} diff --git a/apps/tasks/index.php b/apps/tasks/index.php index f0e6c2e4dd..3e324e797f 100644 --- a/apps/tasks/index.php +++ b/apps/tasks/index.php @@ -18,29 +18,6 @@ if( count($calendars) == 0 ) { exit; } -$id = isset( $_GET['id'] ) ? $_GET['id'] : null; - -$tasks = array(); -foreach( $calendars as $calendar ){ - $calendar_tasks = OC_Calendar_Object::all($calendar['id']); - foreach( $calendar_tasks as $task ){ - if($task['objecttype']!='VTODO'){ - continue; - } - if(is_null($task['summary'])){ - continue; - } - $tasks[] = array( 'name' => $task['summary'], 'id' => $task['id'] ); - } -} - -$details = null; -if( !is_null($id) || count($tasks)){ - if(is_null($id)) $id = $tasks[0]['id']; - $task = OC_Calendar_Object::find($id); - $details = Sabre_VObject_Reader::read($task['calendardata'])->VTODO; -} - OC_UTIL::addScript('tasks', 'tasks'); OC_UTIL::addStyle('tasks', 'style'); OC_APP::setActiveNavigationEntry('tasks_index'); @@ -48,8 +25,5 @@ OC_APP::setActiveNavigationEntry('tasks_index'); $l10n = new OC_L10N('tasks'); $priority_options = OC_Task_App::getPriorityOptions(); $output = new OC_Template('tasks', 'tasks', 'user'); -$output->assign('tasks', $tasks); -$output->assign('details', $details); $output->assign('priority_options', $priority_options); -$output->assign('id',$id); $output -> printPage(); diff --git a/apps/tasks/js/tasks.js b/apps/tasks/js/tasks.js index e695925aad..aba3eca7ce 100644 --- a/apps/tasks/js/tasks.js +++ b/apps/tasks/js/tasks.js @@ -2,14 +2,44 @@ $(document).ready(function(){ /*------------------------------------------------------------------------- * Actions for startup *-----------------------------------------------------------------------*/ - if( $('#tasks li').length > 0 ){ - $('#tasks li').first().addClass('active'); - } + $.getJSON(OC.filePath('tasks', 'ajax', 'gettasks.php'), function(jsondata) { + var tasks = $('#tasks').empty(); + var actions = $('#task_actions_template'); + $(jsondata).each(function(i, task) { + var task_container = $('
    ').appendTo(tasks) + .addClass('task') + .data('task', task) + .attr('data-id', task.id) + .append($('

    ') + .html(''+task.summary+'') + .addClass('summary') + ) + .append(actions.clone().removeAttr('id')) + ; + if (task.categories.length > 0) { + var categories = $('

    ') + .addClass('categories') + .appendTo(task_container); + $(task.categories).each(function(i, category){ + categories.append($('') + .text(category) + ); + }); + } + }); + if( $('#tasks div').length > 0 ){ + $('#tasks div').first().addClass('active'); + } + + }); + + fillHeight($('#tasks')); + fillWindow($('#task_details')); /*------------------------------------------------------------------------- * Event handlers *-----------------------------------------------------------------------*/ - $('#tasks li').live('click',function(){ + $('#tasks div').live('click',function(){ var id = $(this).data('id'); var oldid = $('#task_details').data('id'); if(oldid != 0){ diff --git a/apps/tasks/templates/tasks.php b/apps/tasks/templates/tasks.php index 70f14b4215..60562c4a6f 100644 --- a/apps/tasks/templates/tasks.php +++ b/apps/tasks/templates/tasks.php @@ -3,11 +3,16 @@
    -
    -
      - inc("part.tasks"); ?> -
    +
    +

    t('Loading tasks...') ?>

    -
    - inc("part.details"); ?> +
    +

    + + + +   + + +

    From f3ebd2966101cd3d456a527ac0e55f88ec9d6478 Mon Sep 17 00:00:00 2001 From: Bart Visscher Date: Wed, 22 Feb 2012 21:15:57 +0100 Subject: [PATCH 11/38] Fix updating task for new calendar API --- apps/tasks/ajax/edittask.php | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/apps/tasks/ajax/edittask.php b/apps/tasks/ajax/edittask.php index edfca33833..a7215ce078 100644 --- a/apps/tasks/ajax/edittask.php +++ b/apps/tasks/ajax/edittask.php @@ -8,17 +8,7 @@ OC_JSON::checkAppEnabled('tasks'); $l10n = new OC_L10N('tasks'); $id = $_POST['id']; -$task = OC_Calendar_Object::find( $id ); -if( $task === false ){ - OC_JSON::error(array('data' => array( 'message' => $l10n->t('Can not find Task!')))); - exit(); -} - -$calendar = OC_Calendar_Calendar::findCalendar( $task['calendarid'] ); -if( $calendar === false || $calendar['userid'] != OC_USER::getUser()){ - OC_JSON::error(array('data' => array( 'message' => $l10n->t('This is not your task!')))); - exit(); -} +$vcalendar = OC_Calendar_App::getVCalendar($id); $errors = OC_Task_App::validateRequest($_POST); if (!empty($errors)) { @@ -26,7 +16,6 @@ if (!empty($errors)) { exit(); } -$vcalendar = OC_VObject::parse($task['calendardata']); OC_Task_App::updateVCalendarFromRequest($_POST, $vcalendar); OC_Calendar_Object::edit($id, $vcalendar->serialize()); From c768751c23fe6d5acdcde1124faff6f8dc587509 Mon Sep 17 00:00:00 2001 From: Bart Visscher Date: Wed, 22 Feb 2012 22:06:06 +0100 Subject: [PATCH 12/38] Display more information in the task list --- apps/tasks/css/style.css | 34 ++++++++++++++++++++++++++++------ apps/tasks/js/tasks.js | 25 ++++++++++++++++++++++++- 2 files changed, 52 insertions(+), 7 deletions(-) diff --git a/apps/tasks/css/style.css b/apps/tasks/css/style.css index 3a61d62716..72254584a5 100644 --- a/apps/tasks/css/style.css +++ b/apps/tasks/css/style.css @@ -1,10 +1,32 @@ -#task_details th { padding:2px; text-align:right ;vertical-align:top; } -#task_details td { padding:2px; text-align:left ;vertical-align:top; } +#tasks{position:fixed; overflow: auto; top:6.4em; width:50em; background:#f8f8f8; border-right:1px solid #ddd; } +#task_details{position:absolute;left:63em;top:6.4em;} +#task_details th{padding:2px;text-align:right;vertical-align:top; } +#task_details td{padding:2px;text-align:left;vertical-align:top; } .error_msg{color:red;} .error{border-color:red;border-width:2px;} .task{position:relative;padding:0.5em 1em;} .task_actions{display:none;} -.task .categories{position:absolute;right:0.6em;text-align:right;top:0.5em} -.task .categories a{background-color:#1d2d44;color:white;border-radius:0.4em;display:inline-block;opacity:0.2;margin:0 0.2em;padding:0 0.4em;} -#tasks{position:fixed; overflow: auto; top:6.4em; width:40em; background:#f8f8f8; border-right:1px solid #ddd; } -#task_details{position:absolute;left:53em;top:6.4em;} + +.task .priority{background-color:black;color:white;position:absolute;top:0.5em} +.task .priority-n{height:2.66ex;width:0.6em;} +.task .priority-1{background:rgb(255,0,0);} +.task .priority-2{background:rgb(200,0,0);} +.task .priority-3{background:rgb(150,0,0);} +.task .priority-4{background:rgb(100,0,0);} +.task .priority-5{background:rgb(255,255,0);color:black;} +.task .priority-6{background:rgb(192,255,0);color:black;} +.task .priority-7{background:rgb(128,255,0);color:black;} +.task .priority-8{background:rgb(64,255,0);color:black;} +.task .priority-9{background:rgb(0,255,0);color:black;} + +.task .completed {position:absolute;left:3em;top:0.3em;} + +.task .summary{padding-left:4em;} + +.task .tag{border-radius:0.4em;display:inline-block;opacity:0.2;margin:0 0.2em;padding:0 0.4em;} +.task .tag:hover{opacity:0.5;} + +.task .categories{position:absolute;right:6em;text-align:right;top:0.5em} +.task .categories a{background-color:#1d2d44;color:white;} + +.task .location{background-color:#442d44;color:white;position:absolute;right:0.6em;width:4.2em;text-align:left;top:0.5em} diff --git a/apps/tasks/js/tasks.js b/apps/tasks/js/tasks.js index aba3eca7ce..6400a8f512 100644 --- a/apps/tasks/js/tasks.js +++ b/apps/tasks/js/tasks.js @@ -14,14 +14,37 @@ $(document).ready(function(){ .html('
    '+task.summary+'') .addClass('summary') ) - .append(actions.clone().removeAttr('id')) + //.append(actions.clone().removeAttr('id')) ; + var checkbox = $(''); + if (task.completed) { + checkbox.attr('checked', 'checked'); + } + $('
    ') + .addClass('completed') + .append(checkbox) + .prependTo(task_container); + var priority = task.priority; + $('
    ') + .addClass('tag') + .addClass('priority') + .addClass('priority-'+(priority?priority:'n')) + .text(priority) + .prependTo(task_container); + if (task.location) { + $('
    ') + .addClass('tag') + .addClass('location') + .text(task.location) + .appendTo(task_container); + } if (task.categories.length > 0) { var categories = $('
    ') .addClass('categories') .appendTo(task_container); $(task.categories).each(function(i, category){ categories.append($('') + .addClass('tag') .text(category) ); }); From 8f9c85232508ffb9bda4f5fdeddb3e3630af0ba1 Mon Sep 17 00:00:00 2001 From: Bart Visscher Date: Thu, 23 Feb 2012 21:11:31 +0100 Subject: [PATCH 13/38] Add filtering on category, priority and location --- apps/tasks/css/style.css | 4 ++- apps/tasks/js/tasks.js | 54 +++++++++++++++++++++++++++++++++++++--- 2 files changed, 54 insertions(+), 4 deletions(-) diff --git a/apps/tasks/css/style.css b/apps/tasks/css/style.css index 72254584a5..cbfb84c6ef 100644 --- a/apps/tasks/css/style.css +++ b/apps/tasks/css/style.css @@ -23,8 +23,10 @@ .task .summary{padding-left:4em;} -.task .tag{border-radius:0.4em;display:inline-block;opacity:0.2;margin:0 0.2em;padding:0 0.4em;} +.task .tag{border-radius:0.4em;display:inline-block;opacity:0.2;margin:0 0.2em;border:1px solid transparent;padding:0 0.4em;} .task .tag:hover{opacity:0.5;} +.task .tag.active{border-color:black;opacity:0.6;} +.task .tag.active:hover{opacity:0.8;} .task .categories{position:absolute;right:6em;text-align:right;top:0.5em} .task .categories a{background-color:#1d2d44;color:white;} diff --git a/apps/tasks/js/tasks.js b/apps/tasks/js/tasks.js index 6400a8f512..37ab504a72 100644 --- a/apps/tasks/js/tasks.js +++ b/apps/tasks/js/tasks.js @@ -1,14 +1,50 @@ +OC.Tasks = { + filter:function(tag, find_filter) { + var tag_text = $(tag).text(); + var filter = !$(tag).hasClass('active'); + var show_count = $('#tasks').data('show_count'); + show_count += filter ? +1 : -1; + $('#tasks').data('show_count', show_count); + $('#tasks .task').each(function(i, task_container){ + task_container = $(task_container); + var task = task_container.data('task'); + var found = 0; + task_container.find(find_filter).each(function(){ + if ($(this).text() == tag_text) { + $(this).toggleClass('active'); + found = 1; + } + }); + var hide_count = task_container.data('show_count'); + if (!filter) { + hide_count-=found; + } + else { + hide_count+=found; + } + if (hide_count == show_count) { + task_container.show(); + } + else { + task_container.hide(); + } + task_container.data('show_count', hide_count); + }); + } +}; + $(document).ready(function(){ /*------------------------------------------------------------------------- * Actions for startup *-----------------------------------------------------------------------*/ $.getJSON(OC.filePath('tasks', 'ajax', 'gettasks.php'), function(jsondata) { - var tasks = $('#tasks').empty(); + var tasks = $('#tasks').empty().data('show_count', 0); var actions = $('#task_actions_template'); $(jsondata).each(function(i, task) { var task_container = $('
    ').appendTo(tasks) .addClass('task') .data('task', task) + .data('show_count', 0) .attr('data-id', task.id) .append($('

    ') .html(''+task.summary+'') @@ -62,8 +98,8 @@ $(document).ready(function(){ /*------------------------------------------------------------------------- * Event handlers *-----------------------------------------------------------------------*/ - $('#tasks div').live('click',function(){ - var id = $(this).data('id'); + $('#tasks div.task .summary').live('click',function(){ + var id = $(this).parent('div.task').data('id'); var oldid = $('#task_details').data('id'); if(oldid != 0){ $('#tasks li[data-id="'+oldid+'"]').removeClass('active'); @@ -81,6 +117,18 @@ $(document).ready(function(){ return false; }); + $('#tasks div.categories .tag').live('click',function(){ + OC.Tasks.filter(this, 'div.categories .tag'); + }); + + $('#tasks .priority.tag').live('click',function(){ + OC.Tasks.filter(this, '.priority.tag'); + }); + + $('#tasks .location.tag').live('click',function(){ + OC.Tasks.filter(this, '.location.tag'); + }); + $('#tasks_delete').live('click',function(){ var id = $('#task_details').data('id'); $.getJSON('ajax/delete.php',{'id':id},function(jsondata){ From d1b2c10422692e182c0ec943d3a1925677a83f38 Mon Sep 17 00:00:00 2001 From: Bart Visscher Date: Thu, 8 Mar 2012 22:26:54 +0100 Subject: [PATCH 14/38] Tasks: Update task list when adding or updating tasks --- apps/tasks/ajax/addtask.php | 11 ++-- apps/tasks/ajax/addtaskform.php | 8 +++ apps/tasks/ajax/edittask.php | 5 +- apps/tasks/ajax/gettasks.php | 27 +-------- apps/tasks/js/tasks.js | 101 ++++++++++++++++++-------------- apps/tasks/lib/app.php | 44 ++++++++++---- 6 files changed, 108 insertions(+), 88 deletions(-) diff --git a/apps/tasks/ajax/addtask.php b/apps/tasks/ajax/addtask.php index c768d3e7d9..0c8cb89e7f 100644 --- a/apps/tasks/ajax/addtask.php +++ b/apps/tasks/ajax/addtask.php @@ -8,11 +8,7 @@ OC_JSON::checkAppEnabled('tasks'); $l10n = new OC_L10N('tasks'); $cid = $_POST['id']; -$calendar = OC_Calendar_Calendar::findCalendar( $cid ); -if( $calendar === false || $calendar['userid'] != OC_USER::getUser()){ - OC_JSON::error(array('data' => array( 'message' => $l10n->t('This is not your calendar!')))); - exit(); -} +$calendar = OC_Calendar_App::getCalendar( $cid ); $errors = OC_Task_App::validateRequest($_POST); if (!empty($errors)) { @@ -30,4 +26,7 @@ $tmpl->assign('details',$vcalendar->VTODO); $tmpl->assign('id',$id); $page = $tmpl->fetchPage(); -OC_JSON::success(array('data' => array( 'id' => $id, 'page' => $page ))); +$user_timezone = OC_Preferences::getValue(OC_USER::getUser(), 'calendar', 'timezone', date_default_timezone_get()); +$task = OC_Task_App::arrayForJSON($id, $vcalendar->VTODO, $user_timezone); + +OC_JSON::success(array('data' => array( 'id' => $id, 'page' => $page, 'task' => $task ))); diff --git a/apps/tasks/ajax/addtaskform.php b/apps/tasks/ajax/addtaskform.php index 222ccbd79a..d4a0bb0310 100644 --- a/apps/tasks/ajax/addtaskform.php +++ b/apps/tasks/ajax/addtaskform.php @@ -8,8 +8,16 @@ OC_JSON::checkAppEnabled('tasks'); $l10n = new OC_L10N('tasks'); $calendars = OC_Calendar_Calendar::allCalendars(OC_User::getUser(), true); +$category_options = OC_Calendar_Object::getCategoryOptions($l10n); +$percent_options = range(0, 100, 10); +$priority_options = OC_Task_App::getPriorityOptions(); $tmpl = new OC_Template('tasks','part.addtaskform'); $tmpl->assign('calendars',$calendars); +$tmpl->assign('category_options', $category_options); +$tmpl->assign('percent_options', $percent_options); +$tmpl->assign('priority_options', $priority_options); +$tmpl->assign('details', new OC_VObject('VTODO')); +$tmpl->assign('categories', array()); $page = $tmpl->fetchPage(); OC_JSON::success(array('data' => array( 'page' => $page ))); diff --git a/apps/tasks/ajax/edittask.php b/apps/tasks/ajax/edittask.php index a7215ce078..ae937a7dca 100644 --- a/apps/tasks/ajax/edittask.php +++ b/apps/tasks/ajax/edittask.php @@ -26,4 +26,7 @@ $tmpl->assign('details', $vcalendar->VTODO); $tmpl->assign('id', $id); $page = $tmpl->fetchPage(); -OC_JSON::success(array('data' => array( 'id' => $id, 'page' => $page ))); +$user_timezone = OC_Preferences::getValue(OC_USER::getUser(), 'calendar', 'timezone', date_default_timezone_get()); +$task = OC_Task_App::arrayForJSON($id, $vcalendar->VTODO, $user_timezone); + +OC_JSON::success(array('data' => array( 'id' => $id, 'page' => $page, 'task' => $task ))); diff --git a/apps/tasks/ajax/gettasks.php b/apps/tasks/ajax/gettasks.php index 7dc94dacb4..ee871c344c 100644 --- a/apps/tasks/ajax/gettasks.php +++ b/apps/tasks/ajax/gettasks.php @@ -26,32 +26,7 @@ foreach( $calendars as $calendar ){ } $object = OC_VObject::parse($task['calendardata']); $vtodo = $object->VTODO; - $task = array( 'id' => $task['id'] ); - $task['summary'] = $vtodo->getAsString('SUMMARY'); - $task['description'] = $vtodo->getAsString('DESCRIPTION'); - $task['location'] = $vtodo->getAsString('LOCATION'); - $task['categories'] = $vtodo->getAsArray('CATEGORIES'); - $due = $vtodo->DUE; - if ($due) { - $due = $due->getDateTime(); - $due->setTimezone(new DateTimeZone($user_timezone)); - $task['due'] = $due->format('Y-m-d H:i:s'); - } - else { - $task['due'] = false; - } - $task['priority'] = $vtodo->getAsString('PRIORITY'); - $completed = $vtodo->COMPLETED; - if ($completed) { - $completed = $completed->getDateTime(); - $completed->setTimezone(new DateTimeZone($user_timezone)); - $task['completed'] = $completed->format('Y-m-d H:i:s'); - } - else { - $task['completed'] = false; - } - $task['complete'] = $vtodo->getAsString('PERCENT-COMPLETE'); - $tasks[] = $task; + $tasks[] = OC_Task_App::arrayForJSON($task['id'], $vtodo, $user_timezone); } } diff --git a/apps/tasks/js/tasks.js b/apps/tasks/js/tasks.js index 37ab504a72..3cf428b33a 100644 --- a/apps/tasks/js/tasks.js +++ b/apps/tasks/js/tasks.js @@ -1,4 +1,52 @@ OC.Tasks = { + create_task_div:function(task) { + var task_container = $('

    ') + .addClass('task') + .data('task', task) + .data('show_count', 0) + .attr('data-id', task.id) + .append($('

    ') + .html(''+task.summary+'') + .addClass('summary') + .attr('title', task.description) + ) + //.append(actions.clone().removeAttr('id')) + ; + var checkbox = $(''); + if (task.completed) { + checkbox.attr('checked', 'checked'); + } + $('

    ') + .addClass('completed') + .append(checkbox) + .prependTo(task_container); + var priority = task.priority; + $('
    ') + .addClass('tag') + .addClass('priority') + .addClass('priority-'+(priority?priority:'n')) + .text(priority) + .prependTo(task_container); + if (task.location) { + $('
    ') + .addClass('tag') + .addClass('location') + .text(task.location) + .appendTo(task_container); + } + if (task.categories.length > 0) { + var categories = $('
    ') + .addClass('categories') + .appendTo(task_container); + $(task.categories).each(function(i, category){ + categories.append($('') + .addClass('tag') + .text(category) + ); + }); + } + return task_container; + }, filter:function(tag, find_filter) { var tag_text = $(tag).text(); var filter = !$(tag).hasClass('active'); @@ -41,50 +89,7 @@ $(document).ready(function(){ var tasks = $('#tasks').empty().data('show_count', 0); var actions = $('#task_actions_template'); $(jsondata).each(function(i, task) { - var task_container = $('
    ').appendTo(tasks) - .addClass('task') - .data('task', task) - .data('show_count', 0) - .attr('data-id', task.id) - .append($('

    ') - .html(''+task.summary+'') - .addClass('summary') - ) - //.append(actions.clone().removeAttr('id')) - ; - var checkbox = $(''); - if (task.completed) { - checkbox.attr('checked', 'checked'); - } - $('

    ') - .addClass('completed') - .append(checkbox) - .prependTo(task_container); - var priority = task.priority; - $('
    ') - .addClass('tag') - .addClass('priority') - .addClass('priority-'+(priority?priority:'n')) - .text(priority) - .prependTo(task_container); - if (task.location) { - $('
    ') - .addClass('tag') - .addClass('location') - .text(task.location) - .appendTo(task_container); - } - if (task.categories.length > 0) { - var categories = $('
    ') - .addClass('categories') - .appendTo(task_container); - $(task.categories).each(function(i, category){ - categories.append($('') - .addClass('tag') - .text(category) - ); - }); - } + tasks.append(OC.Tasks.create_task_div(task)); }); if( $('#tasks div').length > 0 ){ $('#tasks div').first().addClass('active'); @@ -162,6 +167,7 @@ $(document).ready(function(){ if(jsondata.status == 'success'){ $('#task_details').data('id',jsondata.data.id); $('#task_details').html(jsondata.data.page); + $('#tasks').append(OC.Tasks.create_task_div(jsondata.data.task)); } else{ alert(jsondata.data.message); @@ -196,8 +202,13 @@ $(document).ready(function(){ $('.error_msg').remove(); $('.error').removeClass('error'); if(jsondata.status == 'success'){ - $('#task_details').data('id',jsondata.data.id); + var id = jsondata.data.id; + $('#task_details').data('id',id); $('#task_details').html(jsondata.data.page); + var task = jsondata.data.task; + $('#tasks .task[data-id='+id+']') + .data('task', task) + .html(OC.Tasks.create_task_div(task).html()); } else{ var errors = jsondata.data.errors; diff --git a/apps/tasks/lib/app.php b/apps/tasks/lib/app.php index 92be594424..a5f4ff6cdc 100644 --- a/apps/tasks/lib/app.php +++ b/apps/tasks/lib/app.php @@ -43,6 +43,36 @@ class OC_Task_App { ); } + public static function arrayForJSON($id, $vtodo, $user_timezone) + { + $task = array( 'id' => $id ); + $task['summary'] = $vtodo->getAsString('SUMMARY'); + $task['description'] = $vtodo->getAsString('DESCRIPTION'); + $task['location'] = $vtodo->getAsString('LOCATION'); + $task['categories'] = $vtodo->getAsArray('CATEGORIES'); + $due = $vtodo->DUE; + if ($due) { + $due = $due->getDateTime(); + $due->setTimezone(new DateTimeZone($user_timezone)); + $task['due'] = $due->format('Y-m-d H:i:s'); + } + else { + $task['due'] = false; + } + $task['priority'] = $vtodo->getAsString('PRIORITY'); + $completed = $vtodo->COMPLETED; + if ($completed) { + $completed = $completed->getDateTime(); + $completed->setTimezone(new DateTimeZone($user_timezone)); + $task['completed'] = $completed->format('Y-m-d H:i:s'); + } + else { + $task['completed'] = false; + } + $task['complete'] = $vtodo->getAsString('PERCENT-COMPLETE'); + return $task; + } + public static function validateRequest($request) { $errors = array(); @@ -84,22 +114,16 @@ class OC_Task_App { public static function createVCalendarFromRequest($request) { - $vcalendar = new Sabre_VObject_Component('VCALENDAR'); + $vcalendar = new OC_VObject('VCALENDAR'); $vcalendar->add('PRODID', 'ownCloud Calendar'); $vcalendar->add('VERSION', '2.0'); - $now = new DateTime(); - - $vtodo = new Sabre_VObject_Component('VTODO'); + $vtodo = new OC_VObject('VTODO'); $vcalendar->add($vtodo); - $created = new Sabre_VObject_Element_DateTime('CREATED'); - $created->setDateTime($now, Sabre_VObject_Element_DateTime::UTC); - $vtodo->add($created); - - $uid = self::createUID(); - $vtodo->add('UID',$uid); + $vtodo->setDateTime('CREATED', 'now', Sabre_VObject_Element_DateTime::UTC); + $vtodo->setUID(); return self::updateVCalendarFromRequest($request, $vcalendar); } From f8b62d49ee680084445538bbaab78fef60e22227 Mon Sep 17 00:00:00 2001 From: Bart Visscher Date: Thu, 8 Mar 2012 22:27:29 +0100 Subject: [PATCH 15/38] Tasks: Ordering of the task list --- apps/tasks/css/style.css | 2 + apps/tasks/js/tasks.js | 110 +++++++++++++++++++++++++++++++++ apps/tasks/templates/tasks.php | 12 ++-- 3 files changed, 120 insertions(+), 4 deletions(-) diff --git a/apps/tasks/css/style.css b/apps/tasks/css/style.css index cbfb84c6ef..cedb21b137 100644 --- a/apps/tasks/css/style.css +++ b/apps/tasks/css/style.css @@ -1,3 +1,4 @@ +#tasks p.loading{margin:15px;} #tasks{position:fixed; overflow: auto; top:6.4em; width:50em; background:#f8f8f8; border-right:1px solid #ddd; } #task_details{position:absolute;left:63em;top:6.4em;} #task_details th{padding:2px;text-align:right;vertical-align:top; } @@ -6,6 +7,7 @@ .error{border-color:red;border-width:2px;} .task{position:relative;padding:0.5em 1em;} .task_actions{display:none;} +#tasks h1{background-color:#1D2D44;color:white;font-size:120%;padding:0 0.5em;} .task .priority{background-color:black;color:white;position:absolute;top:0.5em} .task .priority-n{height:2.66ex;width:0.6em;} diff --git a/apps/tasks/js/tasks.js b/apps/tasks/js/tasks.js index 3cf428b33a..4a9a0b69c4 100644 --- a/apps/tasks/js/tasks.js +++ b/apps/tasks/js/tasks.js @@ -1,4 +1,16 @@ OC.Tasks = { + bool_string_cmp:function(a, b) { + if (a === b) { + return 0; + } + if (a === false) { + return -1; + } + if (b === false) { + return 1; + } + return a.localeCompare(b); + }, create_task_div:function(task) { var task_container = $('
    ') .addClass('task') @@ -78,6 +90,28 @@ OC.Tasks = { } task_container.data('show_count', hide_count); }); + }, + order:function(sort, get_property, empty_label) { + var tasks = $('#tasks .task').not('.clone'); + tasks.sort(sort); + var current = null; + tasks.detach(); + var $tasks = $('#tasks').empty(); + var container = $tasks; + tasks.each(function(){ + if (get_property) { + var label = get_property($(this).data('task')); + if(label != current) { + current = label; + container = $('
    ').appendTo($tasks); + if (label == '' && empty_label) { + label = empty_label; + } + $('

    ').text(label).appendTo(container); + } + } + container.append(this); + }); } }; @@ -134,6 +168,82 @@ $(document).ready(function(){ OC.Tasks.filter(this, '.location.tag'); }); + $('#tasks_order_category').click(function(){ + var tasks = $('#tasks .task').not('.clone'); + var collection = {}; + tasks.each(function(i, task) { + var categories = $(task).data('task').categories; + $(categories).each(function() { + if (!collection.hasOwnProperty(this)) { + collection[this] = []; + } + collection[this].push(task); + if (categories.length > 1) { + task = $(task).clone(true).addClass('clone').get(0); + } + }); + if (categories.length == 0) { + if (!collection.hasOwnProperty('')) { + collection[''] = []; + } + collection[''].push(task); + } + }); + var labels = []; + for (var label in collection) { + labels.push(label); + } + labels.sort(); + tasks.detach(); + var $tasks = $('#tasks').empty(); + for (var index in labels) { + var label = labels[index]; + var container = $('
    ').appendTo($tasks); + if (label == '') { + label = t('tasks', 'No category'); + } + $('

    ').text(label).appendTo(container); + container.append(collection[labels[index]]); + } + }); + + $('#tasks_order_due').click(function(){ + OC.Tasks.order(function(a, b){ + a = $(a).data('task').due; + b = $(b).data('task').due; + return OC.Tasks.bool_string_cmp(a, b); + }); + }); + + $('#tasks_order_complete').click(function(){ + OC.Tasks.order(function(a, b){ + return ($(a).data('task').complete - $(b).data('task').complete) || + OC.Tasks.bool_string_cmp($(a).data('task').completed, $(b).data('task').completed); + }); + }); + + $('#tasks_order_location').click(function(){ + OC.Tasks.order(function(a, b){ + a = $(a).data('task').location; + b = $(b).data('task').location; + return OC.Tasks.bool_string_cmp(a, b); + }); + }); + + $('#tasks_order_prio').click(function(){ + OC.Tasks.order(function(a, b){ + return $(a).data('task').priority + - $(b).data('task').priority; + }); + }); + + $('#tasks_order_label').click(function(){ + OC.Tasks.order(function(a, b){ + return $(a).data('task').summary.localeCompare( + $(b).data('task').summary); + }); + }); + $('#tasks_delete').live('click',function(){ var id = $('#task_details').data('id'); $.getJSON('ajax/delete.php',{'id':id},function(jsondata){ diff --git a/apps/tasks/templates/tasks.php b/apps/tasks/templates/tasks.php index 60562c4a6f..8d34a40683 100644 --- a/apps/tasks/templates/tasks.php +++ b/apps/tasks/templates/tasks.php @@ -1,10 +1,14 @@
    -
    - -
    + + + + + + +
    -

    t('Loading tasks...') ?>

    +

    t('Loading tasks...') ?>

    From 029e1aced7fc39fa5673b69927a24aa18b159a19 Mon Sep 17 00:00:00 2001 From: Bart Visscher Date: Sat, 14 Apr 2012 14:55:37 +0200 Subject: [PATCH 16/38] Tasks: Update to use new categories interface --- apps/calendar/lib/app.php | 13 +++++++++++-- apps/tasks/ajax/addtaskform.php | 4 ++-- apps/tasks/ajax/edittaskform.php | 8 ++------ apps/tasks/index.php | 4 ++++ apps/tasks/js/tasks.js | 3 +++ apps/tasks/lib/app.php | 8 ++------ apps/tasks/templates/part.taskform.php | 10 ++-------- apps/tasks/templates/tasks.php | 3 +++ 8 files changed, 29 insertions(+), 24 deletions(-) diff --git a/apps/calendar/lib/app.php b/apps/calendar/lib/app.php index 22c1133e00..660aa928a7 100644 --- a/apps/calendar/lib/app.php +++ b/apps/calendar/lib/app.php @@ -110,7 +110,7 @@ class OC_Calendar_App{ foreach($events as $event) { $vobject = OC_VObject::parse($event['calendardata']); if(!is_null($vobject)) { - $vcategories->loadFromVObject($vobject->VEVENT, true); + self::loadCategoriesFromVCalendar($vobject); } } } @@ -121,7 +121,16 @@ class OC_Calendar_App{ * @see OC_VCategories::loadFromVObject */ public static function loadCategoriesFromVCalendar(OC_VObject $calendar) { - self::getVCategories()->loadFromVObject($calendar->VEVENT, true); + $object = null; + if (isset($calendar->VEVENT)) { + $object = $calendar->VEVENT; + } else + if (isset($calendar->VTODO)) { + $object = $calendar->VTODO; + } + if ($object) { + self::getVCategories()->loadFromVObject($object, true); + } } public static function getRepeatOptions(){ diff --git a/apps/tasks/ajax/addtaskform.php b/apps/tasks/ajax/addtaskform.php index d4a0bb0310..f56549cd74 100644 --- a/apps/tasks/ajax/addtaskform.php +++ b/apps/tasks/ajax/addtaskform.php @@ -8,7 +8,7 @@ OC_JSON::checkAppEnabled('tasks'); $l10n = new OC_L10N('tasks'); $calendars = OC_Calendar_Calendar::allCalendars(OC_User::getUser(), true); -$category_options = OC_Calendar_Object::getCategoryOptions($l10n); +$category_options = OC_Calendar_App::getCategoryOptions($l10n); $percent_options = range(0, 100, 10); $priority_options = OC_Task_App::getPriorityOptions(); $tmpl = new OC_Template('tasks','part.addtaskform'); @@ -17,7 +17,7 @@ $tmpl->assign('category_options', $category_options); $tmpl->assign('percent_options', $percent_options); $tmpl->assign('priority_options', $priority_options); $tmpl->assign('details', new OC_VObject('VTODO')); -$tmpl->assign('categories', array()); +$tmpl->assign('categories', ''); $page = $tmpl->fetchPage(); OC_JSON::success(array('data' => array( 'page' => $page ))); diff --git a/apps/tasks/ajax/edittaskform.php b/apps/tasks/ajax/edittaskform.php index 651c26c498..e23eb21824 100644 --- a/apps/tasks/ajax/edittaskform.php +++ b/apps/tasks/ajax/edittaskform.php @@ -9,13 +9,9 @@ $l10n = new OC_L10N('tasks'); $id = $_GET['id']; $details = OC_Calendar_App::getVCalendar($id)->VTODO; -$categories = array(); -if (isset($details->CATEGORIES)){ - $categories = explode(',', $details->CATEGORIES->value); - $categories = array_map('trim', $categories); -} +$categories = $details->getAsString('CATEGORIES'); -$category_options = OC_Calendar_Object::getCategoryOptions($l10n); +$category_options = OC_Calendar_App::getCategoryOptions($l10n); $percent_options = range(0, 100, 10); $priority_options = OC_Task_App::getPriorityOptions(); diff --git a/apps/tasks/index.php b/apps/tasks/index.php index 3e324e797f..95bb10a77c 100644 --- a/apps/tasks/index.php +++ b/apps/tasks/index.php @@ -20,10 +20,14 @@ if( count($calendars) == 0 ) { OC_UTIL::addScript('tasks', 'tasks'); OC_UTIL::addStyle('tasks', 'style'); +OC_Util::addScript('contacts','jquery.multi-autocomplete'); +OC_Util::addScript('','oc-vcategories'); OC_APP::setActiveNavigationEntry('tasks_index'); +$categories = OC_Calendar_App::getCategoryOptions(); $l10n = new OC_L10N('tasks'); $priority_options = OC_Task_App::getPriorityOptions(); $output = new OC_Template('tasks', 'tasks', 'user'); $output->assign('priority_options', $priority_options); +$output->assign('categories', $categories); $output -> printPage(); diff --git a/apps/tasks/js/tasks.js b/apps/tasks/js/tasks.js index 4a9a0b69c4..25a2e3f268 100644 --- a/apps/tasks/js/tasks.js +++ b/apps/tasks/js/tasks.js @@ -291,6 +291,7 @@ $(document).ready(function(){ $.getJSON('ajax/edittaskform.php',{'id':id},function(jsondata){ if(jsondata.status == 'success'){ $('#task_details').html(jsondata.data.page); + $('#task_details #categories').multiple_autocomplete({source: categories}); } else{ alert(jsondata.data.message); @@ -332,4 +333,6 @@ $(document).ready(function(){ }, 'json'); return false; }); + + OCCategories.app = 'calendar'; }); diff --git a/apps/tasks/lib/app.php b/apps/tasks/lib/app.php index a5f4ff6cdc..01294b132b 100644 --- a/apps/tasks/lib/app.php +++ b/apps/tasks/lib/app.php @@ -80,10 +80,6 @@ class OC_Task_App { $errors['summary'] = self::$l10n->t('Empty Summary'); } - if(isset($request['categories']) && !is_array($request['categories'])){ - $errors['categories'] = self::$l10n->t('Not an array'); - } - try { $timezone = OC_Preferences::getValue(OC_USER::getUser(), "calendar", "timezone", "Europe/London"); $timezone = new DateTimeZone($timezone); @@ -130,7 +126,7 @@ class OC_Task_App { public static function updateVCalendarFromRequest($request, $vcalendar) { $summary = $request['summary']; - $categories = isset($request["categories"]) ? $request["categories"] : array(); + $categories = $request["categories"]; $priority = $request['priority']; $percent_complete = $request['percent_complete']; $completed = $request['completed']; @@ -146,7 +142,7 @@ class OC_Task_App { $vtodo->setString('LOCATION', $location); $vtodo->setString('DESCRIPTION', $description); - $vtodo->setString('CATEGORIES', join(',', $categories)); + $vtodo->setString('CATEGORIES', $categories); $vtodo->setString('PRIORITY', $priority); if ($due) { diff --git a/apps/tasks/templates/part.taskform.php b/apps/tasks/templates/part.taskform.php index 139693c0e9..da984d830b 100644 --- a/apps/tasks/templates/part.taskform.php +++ b/apps/tasks/templates/part.taskform.php @@ -5,14 +5,8 @@
    - + +
    <?php echo $l->t('Edit categories'); ?>
    diff --git a/apps/tasks/templates/tasks.php b/apps/tasks/templates/tasks.php index 8d34a40683..8df2a100b6 100644 --- a/apps/tasks/templates/tasks.php +++ b/apps/tasks/templates/tasks.php @@ -20,3 +20,6 @@

    + From 19d81068f62cf38f03422a0f7bc50b309351dc5f Mon Sep 17 00:00:00 2001 From: Bart Visscher Date: Sun, 15 Apr 2012 15:38:44 +0200 Subject: [PATCH 17/38] Tasks: Code cleanup --- apps/tasks/ajax/addtask.php | 2 -- apps/tasks/ajax/addtaskform.php | 4 +--- apps/tasks/ajax/delete.php | 14 +------------- apps/tasks/ajax/edittaskform.php | 4 +--- 4 files changed, 3 insertions(+), 21 deletions(-) diff --git a/apps/tasks/ajax/addtask.php b/apps/tasks/ajax/addtask.php index 0c8cb89e7f..3f129a0eb9 100644 --- a/apps/tasks/ajax/addtask.php +++ b/apps/tasks/ajax/addtask.php @@ -5,8 +5,6 @@ require_once('../../../lib/base.php'); OC_JSON::checkLoggedIn(); OC_JSON::checkAppEnabled('tasks'); -$l10n = new OC_L10N('tasks'); - $cid = $_POST['id']; $calendar = OC_Calendar_App::getCalendar( $cid ); diff --git a/apps/tasks/ajax/addtaskform.php b/apps/tasks/ajax/addtaskform.php index f56549cd74..48e1bc8d89 100644 --- a/apps/tasks/ajax/addtaskform.php +++ b/apps/tasks/ajax/addtaskform.php @@ -5,10 +5,8 @@ require_once('../../../lib/base.php'); OC_JSON::checkLoggedIn(); OC_JSON::checkAppEnabled('tasks'); -$l10n = new OC_L10N('tasks'); - $calendars = OC_Calendar_Calendar::allCalendars(OC_User::getUser(), true); -$category_options = OC_Calendar_App::getCategoryOptions($l10n); +$category_options = OC_Calendar_App::getCategoryOptions(); $percent_options = range(0, 100, 10); $priority_options = OC_Task_App::getPriorityOptions(); $tmpl = new OC_Template('tasks','part.addtaskform'); diff --git a/apps/tasks/ajax/delete.php b/apps/tasks/ajax/delete.php index 03c8a7e92e..ce80191a56 100644 --- a/apps/tasks/ajax/delete.php +++ b/apps/tasks/ajax/delete.php @@ -25,20 +25,8 @@ require_once('../../../lib/base.php'); OC_JSON::checkLoggedIn(); OC_JSON::checkAppEnabled('tasks'); -$l10n = new OC_L10N('tasks'); - $id = $_GET['id']; -$task = OC_Calendar_Object::find( $id ); -if( $task === false ){ - OC_JSON::error(array('data' => array( 'message' => $l10n->t('Can not find Task!')))); - exit(); -} - -$calendar = OC_Calendar_Calendar::findCalendar( $task['calendarid'] ); -if( $calendar === false || $calendar['userid'] != OC_USER::getUser()){ - OC_JSON::error(array('data' => array( 'message' => $l10n->t('This is not your task!')))); - exit(); -} +$task = OC_Calendar_App::getEventObject( $id ); OC_Calendar_Object::delete($id); OC_JSON::success(array('data' => array( 'id' => $id ))); diff --git a/apps/tasks/ajax/edittaskform.php b/apps/tasks/ajax/edittaskform.php index e23eb21824..42a4bfead8 100644 --- a/apps/tasks/ajax/edittaskform.php +++ b/apps/tasks/ajax/edittaskform.php @@ -5,13 +5,11 @@ require_once('../../../lib/base.php'); OC_JSON::checkLoggedIn(); OC_JSON::checkAppEnabled('tasks'); -$l10n = new OC_L10N('tasks'); - $id = $_GET['id']; $details = OC_Calendar_App::getVCalendar($id)->VTODO; $categories = $details->getAsString('CATEGORIES'); -$category_options = OC_Calendar_App::getCategoryOptions($l10n); +$category_options = OC_Calendar_App::getCategoryOptions(); $percent_options = range(0, 100, 10); $priority_options = OC_Task_App::getPriorityOptions(); From 947d2e5705ed606469d99ec4115b60f4eae3a0c4 Mon Sep 17 00:00:00 2001 From: Bart Visscher Date: Sun, 15 Apr 2012 15:39:49 +0200 Subject: [PATCH 18/38] Tasks: Mark task as complete when checking the checkbox --- apps/tasks/ajax/complete.php | 24 ++++++++++++++++++++++++ apps/tasks/css/style.css | 1 + apps/tasks/js/tasks.js | 24 +++++++++++++++++++++++- apps/tasks/lib/app.php | 10 +++++++--- 4 files changed, 55 insertions(+), 4 deletions(-) create mode 100644 apps/tasks/ajax/complete.php diff --git a/apps/tasks/ajax/complete.php b/apps/tasks/ajax/complete.php new file mode 100644 index 0000000000..22c65c0bc8 --- /dev/null +++ b/apps/tasks/ajax/complete.php @@ -0,0 +1,24 @@ + + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +// Init owncloud +require_once('../../../lib/base.php'); +OC_JSON::checkLoggedIn(); +OC_JSON::checkAppEnabled('tasks'); + +$id = $_POST['id']; +$checked = $_POST['checked']; +$vcalendar = OC_Calendar_App::getVCalendar( $id ); + +$vtodo = $vcalendar->VTODO; +OC_Task_App::setComplete($vtodo, $checked ? '100' : '0', null); +OC_Calendar_Object::edit($id, $vcalendar->serialize()); + +$user_timezone = OC_Preferences::getValue(OC_USER::getUser(), 'calendar', 'timezone', date_default_timezone_get()); +$task_info = OC_Task_App::arrayForJSON($id, $vtodo, $user_timezone); +OC_JSON::success(array('data' => $task_info)); diff --git a/apps/tasks/css/style.css b/apps/tasks/css/style.css index cedb21b137..52c7178e97 100644 --- a/apps/tasks/css/style.css +++ b/apps/tasks/css/style.css @@ -24,6 +24,7 @@ .task .completed {position:absolute;left:3em;top:0.3em;} .task .summary{padding-left:4em;} +.task.done .summary{text-decoration:line-through;} .task .tag{border-radius:0.4em;display:inline-block;opacity:0.2;margin:0 0.2em;border:1px solid transparent;padding:0 0.4em;} .task .tag:hover{opacity:0.5;} diff --git a/apps/tasks/js/tasks.js b/apps/tasks/js/tasks.js index 25a2e3f268..719c49f789 100644 --- a/apps/tasks/js/tasks.js +++ b/apps/tasks/js/tasks.js @@ -24,9 +24,11 @@ OC.Tasks = { ) //.append(actions.clone().removeAttr('id')) ; - var checkbox = $(''); + var checkbox = $('') + .click(OC.Tasks.complete_task); if (task.completed) { checkbox.attr('checked', 'checked'); + task_container.addClass('done'); } $('
    ') .addClass('completed') @@ -112,6 +114,26 @@ OC.Tasks = { } container.append(this); }); + }, + complete_task:function() { + var $task = $(this).closest('.task'), + task = $task.data('task'), + checked = $(this).is(':checked'); + $.post('ajax/complete.php', {id:task.id, checked:checked?1:0}, function(jsondata){ + if(jsondata.status == 'success') { + task = jsondata.data; + $task.data('task', task) + if (task.completed) { + $task.addClass('done'); + } + else { + $task.removeClass('done'); + } + } + else{ + alert(jsondata.data.message); + } + }, 'json'); } }; diff --git a/apps/tasks/lib/app.php b/apps/tasks/lib/app.php index 01294b132b..b564866b80 100644 --- a/apps/tasks/lib/app.php +++ b/apps/tasks/lib/app.php @@ -154,6 +154,13 @@ class OC_Task_App { unset($vtodo->DUE); } + self::setComplete($vtodo, $percent_complete, $completed); + + return $vcalendar; + } + + public static function setComplete($vtodo, $percent_complete, $completed) + { if (!empty($percent_complete)) { $vtodo->setString('PERCENT-COMPLETE', $percent_complete); }else{ @@ -175,8 +182,5 @@ class OC_Task_App { } else { unset($vtodo->COMPLETED); } - - return $vcalendar; } } - From 8afeb0fedbeadfee7beca9997817cb75eff6e29f Mon Sep 17 00:00:00 2001 From: Bart Visscher Date: Mon, 16 Apr 2012 15:17:32 +0200 Subject: [PATCH 19/38] Tasks: Implement task lists overview --- apps/tasks/css/style.css | 17 +++++++-- apps/tasks/js/tasks.js | 67 ++++++++++++++++++++++++++-------- apps/tasks/templates/tasks.php | 6 +++ 3 files changed, 70 insertions(+), 20 deletions(-) diff --git a/apps/tasks/css/style.css b/apps/tasks/css/style.css index 52c7178e97..f5c3378bc4 100644 --- a/apps/tasks/css/style.css +++ b/apps/tasks/css/style.css @@ -1,14 +1,22 @@ #tasks p.loading{margin:15px;} -#tasks{position:fixed; overflow: auto; top:6.4em; width:50em; background:#f8f8f8; border-right:1px solid #ddd; } +#tasks{position:fixed; overflow: auto; top:6.4em;width:71em;} +#tasks_lists,#tasks_list{height:100%;background:#f8f8f8; border-right:1px solid #ddd;float:left;} +#tasks_lists{width:20em;} +#tasks_lists .done{color:#C7C7C7;} +#tasks_list{width:50em;} #task_details{position:absolute;left:63em;top:6.4em;} #task_details th{padding:2px;text-align:right;vertical-align:top; } #task_details td{padding:2px;text-align:left;vertical-align:top; } .error_msg{color:red;} .error{border-color:red;border-width:2px;} -.task{position:relative;padding:0.5em 1em;} +#tasks_lists div{position:relative;padding:0.5em 1em;} +#tasks_lists .active{font-weight:bold;} .task_actions{display:none;} #tasks h1{background-color:#1D2D44;color:white;font-size:120%;padding:0 0.5em;} +.task{border-radius:0.4em;position:relative;padding:0.5em 1em;} +.task:hover {background-color:#DDDDDD;} + .task .priority{background-color:black;color:white;position:absolute;top:0.5em} .task .priority-n{height:2.66ex;width:0.6em;} .task .priority-1{background:rgb(255,0,0);} @@ -31,7 +39,8 @@ .task .tag.active{border-color:black;opacity:0.6;} .task .tag.active:hover{opacity:0.8;} -.task .categories{position:absolute;right:6em;text-align:right;top:0.5em} +.task .categories{position:absolute;right:6em;text-align:right;top:0.4em} .task .categories a{background-color:#1d2d44;color:white;} +.task .categories .tag.active{display:none} -.task .location{background-color:#442d44;color:white;position:absolute;right:0.6em;width:4.2em;text-align:left;top:0.5em} +.task .location{background-color:#442d44;color:white;position:absolute;right:0.6em;width:4.2em;text-align:left;top:0.4em} diff --git a/apps/tasks/js/tasks.js b/apps/tasks/js/tasks.js index 719c49f789..fac1708b5e 100644 --- a/apps/tasks/js/tasks.js +++ b/apps/tasks/js/tasks.js @@ -64,12 +64,7 @@ OC.Tasks = { filter:function(tag, find_filter) { var tag_text = $(tag).text(); var filter = !$(tag).hasClass('active'); - var show_count = $('#tasks').data('show_count'); - show_count += filter ? +1 : -1; - $('#tasks').data('show_count', show_count); - $('#tasks .task').each(function(i, task_container){ - task_container = $(task_container); - var task = task_container.data('task'); + OC.Tasks.filterUpdate(filter, function(task_container){ var found = 0; task_container.find(find_filter).each(function(){ if ($(this).text() == tag_text) { @@ -77,6 +72,17 @@ OC.Tasks = { found = 1; } }); + return found; + }); + }, + filterUpdate:function(filter, find_filter) { + var show_count = $('#tasks_list').data('show_count'); + show_count += filter ? +1 : -1; + $('#tasks_list').data('show_count', show_count); + $('#tasks .task').each(function(i, task_container){ + task_container = $(task_container); + var task = task_container.data('task'); + var found = find_filter(task_container); var hide_count = task_container.data('show_count'); if (!filter) { hide_count-=found; @@ -98,7 +104,7 @@ OC.Tasks = { tasks.sort(sort); var current = null; tasks.detach(); - var $tasks = $('#tasks').empty(); + var $tasks = $('#tasks_list').empty(); var container = $tasks; tasks.each(function(){ if (get_property) { @@ -134,28 +140,51 @@ OC.Tasks = { alert(jsondata.data.message); } }, 'json'); + }, + List: { + create_list_div:function(category){ + return $('
    ').text(category) + .click(function(){ + OC.Tasks.filter(this, 'div.categories .tag'); + $(this).toggleClass('active'); + }); + } } }; $(document).ready(function(){ + fillHeight($('#tasks')); + //fillHeight($('#tasks_lists')); + //fillHeight($('#tasks_list')); + //fillWindow($('#task_details')); + /*------------------------------------------------------------------------- * Actions for startup *-----------------------------------------------------------------------*/ $.getJSON(OC.filePath('tasks', 'ajax', 'gettasks.php'), function(jsondata) { - var tasks = $('#tasks').empty().data('show_count', 0); + var tasks = $('#tasks_list').empty().data('show_count', 0); var actions = $('#task_actions_template'); $(jsondata).each(function(i, task) { tasks.append(OC.Tasks.create_task_div(task)); }); - if( $('#tasks div').length > 0 ){ - $('#tasks div').first().addClass('active'); + if( $('#tasks_list div').length > 0 ){ + $('#tasks_list div').first().addClass('active'); } - + $(categories).each(function(i, category) { + $('#tasks_lists .all').after(OC.Tasks.List.create_list_div(category)); + }); + $('#tasks_lists .all').click(function(){ + $('#tasks_lists .active').click(); + }); + $('#tasks_lists .done').click(function(){ + var filter = !$(this).hasClass('active'); + OC.Tasks.filterUpdate(filter, function(task_container){ + return task_container.hasClass('done'); + }); + $(this).toggleClass('active'); + }); }); - fillHeight($('#tasks')); - fillWindow($('#task_details')); - /*------------------------------------------------------------------------- * Event handlers *-----------------------------------------------------------------------*/ @@ -180,6 +209,12 @@ $(document).ready(function(){ $('#tasks div.categories .tag').live('click',function(){ OC.Tasks.filter(this, 'div.categories .tag'); + var tag_text = $(this).text(); + $('#tasks_lists div:not(".all"):not(".done")').each(function(){ + if ($(this).text() == tag_text) { + $(this).toggleClass('active'); + } + }); }); $('#tasks .priority.tag').live('click',function(){ @@ -217,7 +252,7 @@ $(document).ready(function(){ } labels.sort(); tasks.detach(); - var $tasks = $('#tasks').empty(); + var $tasks = $('#tasks_list').empty(); for (var index in labels) { var label = labels[index]; var container = $('
    ').appendTo($tasks); @@ -299,7 +334,7 @@ $(document).ready(function(){ if(jsondata.status == 'success'){ $('#task_details').data('id',jsondata.data.id); $('#task_details').html(jsondata.data.page); - $('#tasks').append(OC.Tasks.create_task_div(jsondata.data.task)); + $('#tasks_list').append(OC.Tasks.create_task_div(jsondata.data.task)); } else{ alert(jsondata.data.message); diff --git a/apps/tasks/templates/tasks.php b/apps/tasks/templates/tasks.php index 8df2a100b6..63e0629e6a 100644 --- a/apps/tasks/templates/tasks.php +++ b/apps/tasks/templates/tasks.php @@ -8,8 +8,14 @@
    +
    +
    All
    +
    Done
    +
    +

    t('Loading tasks...') ?>

    +

    From 6ba30cb713b4abd0500fb692f6227284f620e74a Mon Sep 17 00:00:00 2001 From: Bart Visscher Date: Tue, 17 Apr 2012 17:32:21 +0200 Subject: [PATCH 20/38] Tasks: Clicking task summary opens input for edit --- .../{complete.php => update_property.php} | 16 ++++- apps/tasks/js/tasks.js | 59 +++++++++++-------- 2 files changed, 47 insertions(+), 28 deletions(-) rename apps/tasks/ajax/{complete.php => update_property.php} (65%) diff --git a/apps/tasks/ajax/complete.php b/apps/tasks/ajax/update_property.php similarity index 65% rename from apps/tasks/ajax/complete.php rename to apps/tasks/ajax/update_property.php index 22c65c0bc8..1916a2eb7b 100644 --- a/apps/tasks/ajax/complete.php +++ b/apps/tasks/ajax/update_property.php @@ -12,11 +12,23 @@ OC_JSON::checkLoggedIn(); OC_JSON::checkAppEnabled('tasks'); $id = $_POST['id']; -$checked = $_POST['checked']; +$property = $_POST['type']; $vcalendar = OC_Calendar_App::getVCalendar( $id ); $vtodo = $vcalendar->VTODO; -OC_Task_App::setComplete($vtodo, $checked ? '100' : '0', null); +switch($property) { + case 'summary': + $summary = $_POST['summary']; + $vtodo->setString('SUMMARY', $summary); + break; + case 'complete': + $checked = $_POST['checked']; + OC_Task_App::setComplete($vtodo, $checked ? '100' : '0', null); + break; + default: + OC_JSON::error(array('data'=>array('message'=>'Unknown type'))); + exit(); +} OC_Calendar_Object::edit($id, $vcalendar->serialize()); $user_timezone = OC_Preferences::getValue(OC_USER::getUser(), 'calendar', 'timezone', date_default_timezone_get()); diff --git a/apps/tasks/js/tasks.js b/apps/tasks/js/tasks.js index fac1708b5e..c6b99ac408 100644 --- a/apps/tasks/js/tasks.js +++ b/apps/tasks/js/tasks.js @@ -12,18 +12,20 @@ OC.Tasks = { return a.localeCompare(b); }, create_task_div:function(task) { + var actions = $('#task_actions_template'); + var summary_container = $('

    ') + .attr('title', task.description) + ; + OC.Tasks.setSummary(summary_container, task); var task_container = $('

    ') .addClass('task') .data('task', task) .data('show_count', 0) .attr('data-id', task.id) - .append($('

    ') - .html(''+task.summary+'') - .addClass('summary') - .attr('title', task.description) - ) + .append(summary_container) //.append(actions.clone().removeAttr('id')) ; + task_container.find('.summary a').click(OC.Tasks.summaryClickHandler); var checkbox = $('') .click(OC.Tasks.complete_task); if (task.completed) { @@ -121,11 +123,36 @@ OC.Tasks = { container.append(this); }); }, + setSummary:function(summary_container, task){ + var summary = $(''+task.summary+'') + .click(OC.Tasks.summaryClickHandler); + summary_container.html(summary); + }, + summaryClickHandler:function(event){ + event.preventDefault(); + //event.stopPropagation(); + var task = $(this).closest('.task').data('task'); + var summary_container = $(this).parent(); + var input = $('').val($(this).text()).blur(function(){ + var old_summary = task.summary; + task.summary = $(this).val(); + OC.Tasks.setSummary(summary_container, task); + $.post('ajax/update_property.php', {id:task.id, type:'summary', summary:task.summary}, function(jsondata){ + if(jsondata.status != 'success') { + task.summary = old_summary; + OC.Tasks.setSummary(summary_container, task); + } + }); + }); + summary_container.empty().append(input); + input.focus(); + return false; + }, complete_task:function() { var $task = $(this).closest('.task'), task = $task.data('task'), checked = $(this).is(':checked'); - $.post('ajax/complete.php', {id:task.id, checked:checked?1:0}, function(jsondata){ + $.post('ajax/update_property.php', {id:task.id, type:'complete', checked:checked?1:0}, function(jsondata){ if(jsondata.status == 'success') { task = jsondata.data; $task.data('task', task) @@ -163,7 +190,6 @@ $(document).ready(function(){ *-----------------------------------------------------------------------*/ $.getJSON(OC.filePath('tasks', 'ajax', 'gettasks.php'), function(jsondata) { var tasks = $('#tasks_list').empty().data('show_count', 0); - var actions = $('#task_actions_template'); $(jsondata).each(function(i, task) { tasks.append(OC.Tasks.create_task_div(task)); }); @@ -188,25 +214,6 @@ $(document).ready(function(){ /*------------------------------------------------------------------------- * Event handlers *-----------------------------------------------------------------------*/ - $('#tasks div.task .summary').live('click',function(){ - var id = $(this).parent('div.task').data('id'); - var oldid = $('#task_details').data('id'); - if(oldid != 0){ - $('#tasks li[data-id="'+oldid+'"]').removeClass('active'); - } - $.getJSON('ajax/getdetails.php',{'id':id},function(jsondata){ - if(jsondata.status == 'success'){ - $('#task_details').data('id',jsondata.data.id); - $('#task_details').html(jsondata.data.page); - $('#tasks li[data-id="'+jsondata.data.id+'"]').addClass('active'); - } - else{ - alert(jsondata.data.message); - } - }); - return false; - }); - $('#tasks div.categories .tag').live('click',function(){ OC.Tasks.filter(this, 'div.categories .tag'); var tag_text = $(this).text(); From 921fc59d8fb6f11b377531d60d3f956e90a5e617 Mon Sep 17 00:00:00 2001 From: Bart Visscher Date: Wed, 18 Apr 2012 17:28:16 +0200 Subject: [PATCH 21/38] Tasks: Add "more" block containing description --- apps/tasks/css/style.css | 13 +++++++++++-- apps/tasks/js/tasks.js | 15 ++++++++++++++- apps/tasks/templates/tasks.php | 10 +++++----- 3 files changed, 30 insertions(+), 8 deletions(-) diff --git a/apps/tasks/css/style.css b/apps/tasks/css/style.css index f5c3378bc4..9185c52f77 100644 --- a/apps/tasks/css/style.css +++ b/apps/tasks/css/style.css @@ -11,12 +11,16 @@ .error{border-color:red;border-width:2px;} #tasks_lists div{position:relative;padding:0.5em 1em;} #tasks_lists .active{font-weight:bold;} -.task_actions{display:none;} #tasks h1{background-color:#1D2D44;color:white;font-size:120%;padding:0 0.5em;} .task{border-radius:0.4em;position:relative;padding:0.5em 1em;} .task:hover {background-color:#DDDDDD;} +.task_actions{display:none;position:absolute;right:33.3333%;top:0.2em;} +.task:hover .task_actions {display:block} +.task_actions img{vertical-align:middle;} +.task_actions span{cursor:pointer;} + .task .priority{background-color:black;color:white;position:absolute;top:0.5em} .task .priority-n{height:2.66ex;width:0.6em;} .task .priority-1{background:rgb(255,0,0);} @@ -32,9 +36,10 @@ .task .completed {position:absolute;left:3em;top:0.3em;} .task .summary{padding-left:4em;} +.task .summary input{position:relative;left:5px;} .task.done .summary{text-decoration:line-through;} -.task .tag{border-radius:0.4em;display:inline-block;opacity:0.2;margin:0 0.2em;border:1px solid transparent;padding:0 0.4em;} +.task .tag{border-radius:0.4em;display:inline-block;opacity:0.2;margin:0 0.2em;border:1px solid transparent;padding:0 0.4em;cursor:pointer;} .task .tag:hover{opacity:0.5;} .task .tag.active{border-color:black;opacity:0.6;} .task .tag.active:hover{opacity:0.8;} @@ -44,3 +49,7 @@ .task .categories .tag.active{display:none} .task .location{background-color:#442d44;color:white;position:absolute;right:0.6em;width:4.2em;text-align:left;top:0.4em} + +.task .more{display:none;} + +.task .description{position:relative;left:4em;} diff --git a/apps/tasks/js/tasks.js b/apps/tasks/js/tasks.js index c6b99ac408..1381a356fb 100644 --- a/apps/tasks/js/tasks.js +++ b/apps/tasks/js/tasks.js @@ -23,7 +23,7 @@ OC.Tasks = { .data('show_count', 0) .attr('data-id', task.id) .append(summary_container) - //.append(actions.clone().removeAttr('id')) + .append(actions.clone().removeAttr('id')) ; task_container.find('.summary a').click(OC.Tasks.summaryClickHandler); var checkbox = $('') @@ -61,6 +61,14 @@ OC.Tasks = { ); }); } + task_container.find('.task_more').click(OC.Tasks.moreClickHandler); + var description = $('