diff --git a/plugins/tasklist/drivers/kolab/tasklist_kolab_driver.php b/plugins/tasklist/drivers/kolab/tasklist_kolab_driver.php
index 7322e1f3..c3a220a4 100644
--- a/plugins/tasklist/drivers/kolab/tasklist_kolab_driver.php
+++ b/plugins/tasklist/drivers/kolab/tasklist_kolab_driver.php
@@ -26,7 +26,7 @@ class tasklist_kolab_driver extends tasklist_driver
{
// features supported by the backend
public $alarms = false;
- public $attachments = false;
+ public $attachments = true;
public $undelete = false; // task undelete action
private $rc;
@@ -346,6 +346,18 @@ class tasklist_kolab_driver extends tasklist_driver
$task['changed'] = $record['dtstamp'];
}
+ if (!empty($record['_attachments'])) {
+ foreach ($record['_attachments'] as $key => $attachment) {
+ if ($attachment !== false) {
+ if (!$attachment['name'])
+ $attachment['name'] = $key;
+ $attachments[] = $attachment;
+ }
+ }
+
+ $task['attachments'] = $attachments;
+ }
+
return $task;
}
@@ -387,6 +399,47 @@ class tasklist_kolab_driver extends tasklist_driver
$object[$key] = $val;
}
+ // delete existing attachment(s)
+ if (!empty($task['deleted_attachments'])) {
+ foreach ($task['deleted_attachments'] as $attachment) {
+ if (is_array($object['_attachments'])) {
+ foreach ($object['_attachments'] as $idx => $att) {
+ if ($att['id'] == $attachment)
+ $object['_attachments'][$idx] = false;
+ }
+ }
+ }
+ unset($task['deleted_attachments']);
+ }
+
+ // in kolab_storage attachments are indexed by content-id
+ if (is_array($task['attachments'])) {
+ foreach ($task['attachments'] as $idx => $attachment) {
+ $key = null;
+ // Roundcube ID has nothing to do with the storage ID, remove it
+ if ($attachment['content']) {
+ unset($attachment['id']);
+ }
+ else {
+ foreach ((array)$old['_attachments'] as $cid => $oldatt) {
+ if ($oldatt && $attachment['id'] == $oldatt['id'])
+ $key = $cid;
+ }
+ }
+
+ // replace existing entry
+ if ($key) {
+ $object['_attachments'][$key] = $attachment;
+ }
+ // append as new attachment
+ else {
+ $object['_attachments'][] = $attachment;
+ }
+ }
+
+ unset($task['attachments']);
+ }
+
unset($object['tempid'], $object['raw']);
return $object;
}
@@ -442,7 +495,8 @@ class tasklist_kolab_driver extends tasklist_driver
$saved = false;
}
else {
- $task['id'] = $task['uid'];
+ $task = $this->_to_rcube_task($object);
+ $task['list'] = $list_id;
$this->tasks[$task['uid']] = $task;
}
@@ -480,6 +534,54 @@ class tasklist_kolab_driver extends tasklist_driver
}
+ /**
+ * Get attachment properties
+ *
+ * @param string $id Attachment identifier
+ * @param array $task Hash array with event properties:
+ * id: Task identifier
+ * list: List identifier
+ *
+ * @return array Hash array with attachment properties:
+ * id: Attachment identifier
+ * name: Attachment name
+ * mimetype: MIME content type of the attachment
+ * size: Attachment size
+ */
+ public function get_attachment($id, $task)
+ {
+ $task['uid'] = $task['id'];
+ $task = $this->get_task($task);
+
+ if ($task && !empty($task['attachments'])) {
+ foreach ($task['attachments'] as $att) {
+ if ($att['id'] == $id)
+ return $att;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Get attachment body
+ *
+ * @param string $id Attachment identifier
+ * @param array $task Hash array with event properties:
+ * id: Task identifier
+ * list: List identifier
+ *
+ * @return string Attachment body
+ */
+ public function get_attachment_body($id, $task)
+ {
+ if ($storage = $this->folders[$task['list']]) {
+ return $storage->get_attachment($task['id'], $id);
+ }
+
+ return false;
+ }
+
/**
*
*/
diff --git a/plugins/tasklist/drivers/tasklist_driver.php b/plugins/tasklist/drivers/tasklist_driver.php
index c86eca8d..924da21e 100644
--- a/plugins/tasklist/drivers/tasklist_driver.php
+++ b/plugins/tasklist/drivers/tasklist_driver.php
@@ -174,6 +174,34 @@ abstract class tasklist_driver
return false;
}
+ /**
+ * Get attachment properties
+ *
+ * @param string $id Attachment identifier
+ * @param array $task Hash array with event properties:
+ * id: Task identifier
+ * list: List identifier
+ *
+ * @return array Hash array with attachment properties:
+ * id: Attachment identifier
+ * name: Attachment name
+ * mimetype: MIME content type of the attachment
+ * size: Attachment size
+ */
+ public function get_attachment($id, $task) { }
+
+ /**
+ * Get attachment body
+ *
+ * @param string $id Attachment identifier
+ * @param array $task Hash array with event properties:
+ * id: Task identifier
+ * list: List identifier
+ *
+ * @return string Attachment body
+ */
+ public function get_attachment_body($id, $task) { }
+
/**
* List availabale categories
* The default implementation reads them from config/user prefs
diff --git a/plugins/tasklist/localization/de_CH.inc b/plugins/tasklist/localization/de_CH.inc
index a702a70d..9d21692f 100644
--- a/plugins/tasklist/localization/de_CH.inc
+++ b/plugins/tasklist/localization/de_CH.inc
@@ -36,6 +36,11 @@ $labels['save'] = 'Speichern';
$labels['cancel'] = 'Abbrechen';
$labels['addsubtask'] = 'Neue Teilaufgabe';
+$labels['tabsummary'] = 'Übersicht';
+$labels['tabrecurrence'] = 'Wiederholung';
+$labels['tabattachments'] = 'Anhänge';
+$labels['tabsharing'] = 'Freigabe';
+
$labels['editlist'] = 'Ressource bearbeiten';
$labels['createlist'] = 'Neue Ressource';
$labels['listactions'] = 'Ressourcenoptionen...';
diff --git a/plugins/tasklist/localization/en_US.inc b/plugins/tasklist/localization/en_US.inc
index ccf93584..ba7be2e9 100644
--- a/plugins/tasklist/localization/en_US.inc
+++ b/plugins/tasklist/localization/en_US.inc
@@ -36,6 +36,11 @@ $labels['save'] = 'Save';
$labels['cancel'] = 'Cancel';
$labels['addsubtask'] = 'Add subtask';
+$labels['tabsummary'] = 'Summary';
+$labels['tabrecurrence'] = 'Recurrence';
+$labels['tabattachments'] = 'Attachments';
+$labels['tabsharing'] = 'Sharing';
+
$labels['editlist'] = 'Edit resource';
$labels['createlist'] = 'Add resource';
$labels['listactions'] = 'Resource options...';
diff --git a/plugins/tasklist/skins/larry/tasklist.css b/plugins/tasklist/skins/larry/tasklist.css
index ad7d05a8..32eee745 100644
--- a/plugins/tasklist/skins/larry/tasklist.css
+++ b/plugins/tasklist/skins/larry/tasklist.css
@@ -373,13 +373,14 @@ ul.toolbarmenu li span.icon.taskadd {
}
.taskhead .tags {
+ display: block;
position: absolute;
- top: 4px;
+ top: 3px;
right: 110px;
max-width: 14em;
+ height: 16px;
overflow: hidden;
padding-top: 1px;
- padding-bottom: 4px;
text-align: right;
}
@@ -388,7 +389,7 @@ ul.toolbarmenu li span.icon.taskadd {
background: #d9ecf4;
border: 1px solid #c2dae5;
border-radius: 4px;
- padding: 2px 8px;
+ padding: 1px 7px;
margin-right: 3px;
}
@@ -529,6 +530,13 @@ ul.toolbarmenu li span.delete {
display:none;
}
+#taskedit {
+ position: relative;
+ top: -1.5em;
+ padding: 0.5em 0.1em;
+ margin: 0 -0.2em;
+}
+
#taskshow h2 {
margin-top: -0.5em;
}
@@ -553,11 +561,43 @@ a.morelink:hover {
text-decoration: underline;
}
+#taskedit .ui-tabs-panel {
+ min-height: 24em;
+}
+
#taskeditform input.text,
#taskeditform textarea {
width: 97%;
}
+#taskeditform .formbuttons {
+ margin: 0.5em 0;
+}
+
+#taskedit-attachments {
+ margin: 0.6em 0;
+}
+
+#taskedit-attachments ul li {
+ display: block;
+ color: #333;
+ font-weight: bold;
+ padding: 8px 4px 3px 30px;
+ text-shadow: 0px 1px 1px #fff;
+ text-decoration: none;
+ white-space: nowrap;
+}
+
+#taskedit-attachments ul li a.file {
+ padding: 0;
+}
+
+#taskedit-attachments-form {
+ margin-top: 1em;
+ padding-top: 0.8em;
+ border-top: 2px solid #fafafa;
+}
+
div.form-section {
position: relative;
margin-top: 0.2em;
@@ -568,6 +608,7 @@ div.form-section {
display: inline-block;
min-width: 7em;
padding-right: 0.5em;
+ margin-bottom: 0.3em;
}
label.block {
@@ -587,6 +628,38 @@ label.block {
width: 97%;
}
+#taskedit .droptarget {
+ background-image: url(../../../../skins/larry/images/filedrop.png) !important;
+ background-position: center bottom !important;
+ background-repeat: no-repeat !important;
+}
+
+#taskedit .droptarget.hover,
+#taskedit .droptarget.active {
+ border-color: #019bc6;
+ box-shadow: 0 0 3px 2px rgba(71,135,177, 0.5);
+ -moz-box-shadow: 0 0 3px 2px rgba(71,135,177, 0.5);
+ -webkit-box-shadow: 0 0 3px 2px rgba(71,135,177, 0.5);
+ -o-box-shadow: 0 0 3px 2px rgba(71,135,177, 0.5);
+}
+
+#taskedit .droptarget.hover {
+ background-color: #d9ecf4;
+ box-shadow: 0 0 5px 2px rgba(71,135,177, 0.9);
+ -moz-box-shadow: 0 0 5px 2px rgba(71,135,177, 0.9);
+ -webkit-box-shadow: 0 0 5px 2px rgba(71,135,177, 0.9);
+ -o-box-shadow: 0 0 5px 2px rgba(71,135,177, 0.9);
+}
+
+#task-attachments .attachmentslist li {
+ float: left;
+ margin-right: 1em;
+}
+
+#task-attachments .attachmentslist li a {
+ outline: none;
+}
+
/**
* Styles of the tagedit inputsforms
diff --git a/plugins/tasklist/skins/larry/templates/attachment.html b/plugins/tasklist/skins/larry/templates/attachment.html
new file mode 100644
index 00000000..4d4789da
--- /dev/null
+++ b/plugins/tasklist/skins/larry/templates/attachment.html
@@ -0,0 +1,36 @@
+