Skip to content

Commit

Permalink
Support adding files to events.
Browse files Browse the repository at this point in the history
  • Loading branch information
mrubinsk committed Jan 7, 2016
1 parent 1bec6a9 commit 834cf00
Show file tree
Hide file tree
Showing 7 changed files with 455 additions and 6 deletions.
147 changes: 144 additions & 3 deletions kronolith/js/kronolith.js
Expand Up @@ -4597,19 +4597,23 @@ KronolithCore = {
e.stop();
break;

case 'kronolithEventFileUpload':
if (!elt.disabled) {
this.attachFile();
e.stop();
}
break;
case 'kronolithTaskSave':
if (!elt.disabled) {
this.saveTask();
}
e.stop();
break;

case 'kronolithEventDeleteCancel':
$('kronolithDeleteDiv').hide();
$('kronolithEventDiv').show();
e.stop();
return;

case 'kronolithEventSendCancellationYes':
this.paramsCache.sendupdates = 1;
case 'kronolithEventSendCancellationNo':
Expand Down Expand Up @@ -5022,6 +5026,19 @@ KronolithCore = {
});
e.stop();
return;
case 'kronolithEventFileDelete':
var f = elt.retrieve('file')
if (f) {
HordeCore.doAction('deleteFile', f, {
callback: function(r) {
if (r.success) {
elt.up().remove();
}
}
});
}
e.stop();
return;
}

if (elt.hasClassName('kronolith-event')) {
Expand Down Expand Up @@ -5750,7 +5767,7 @@ KronolithCore = {
$('kronolithEventTargetRO').hide();
$('kronolithEventForm').down('.kronolithFormActions .kronolithSeparator').show();
$('kronolithEventOrganizer').clear();

$('kronolithEventFileList').update();
if (id) {
// An id passed to this function indicates we are editing an event.
RedBox.loading();
Expand Down Expand Up @@ -6202,6 +6219,13 @@ KronolithCore = {
$('kronolithEventMapZoom').value = Math.max(1, ev.gl.zoom);
}

/* Files */
if (ev.fs) {
$H(ev.fs).each(function(f) {
$('kronolithEventFileList').insert(this.insertFile(f.value, ev));
}.bind(this));
}
$('kronolithEventFileList').show();
if (!ev.pe) {
$('kronolithEventSave').hide();
HordeImple.AutoCompleter.kronolithEventTags.disable();
Expand Down Expand Up @@ -6241,6 +6265,29 @@ KronolithCore = {
}
},

insertFile: function(f, ev)
{
var view_link, dl_link;

view_link = new Element('a', {
href: Kronolith.conf.URI_FILE_VIEW.interpolate({ filename: f.name, type: f.type, source: ev.ty + '|' + ev.c, key: ev.id }),
target: '__blank'
});
dl_link = new Element('a', {
href: Kronolith.conf.URI_FILE_DOWNLOAD.interpolate({ filename: f.name, type: f.type, source: ev.ty + '|' + ev.c, key: ev.id }),
target: '__blank'
});
dl_link.insert(new Element('img', { src: Kronolith.conf.images.download, alt: Kronolith.text.download_file }));

d_link = new Element('img', {
src: Kronolith.conf.images.delete,
alt: Kronolith.text.delete_file,
class: 'kronolithEventFileDelete'
});
d_link.store({file: { source: ev.ty + '|' + ev.c, key: ev.id, name: f.name }});
return new Element('div').insert(view_link.update(f.name)).insert(dl_link).insert(d_link);
},

eventAttendanceChange: function(x)
{
this.attendanceChanged = true;
Expand Down Expand Up @@ -7051,6 +7098,100 @@ KronolithCore = {
}
},

uploadFileWait: function(f)
{
var li = new Element('li')
.insert(
new Element('span')
.addClassName('file_upload_text')
.insert(f.name.escapeHTML())
.insert(new Element('span').insert('(' + Kronolith.text.uploading + ')'))
);

$('kronolithEventFileList').show().insert(li);

return li;
},

/**
* Upload a file associated with an event.
*
*/
attachFile: function()
{
// @todo Check it's not a new event. (enable/disable the button?)

// Get file(s).
var fi = $('kronolithEventFile').files;

// @todo Size checks?
// if ($A(data).detect(function(d) {
// return (parseInt(d.size, 10) >= this.size_limit);
// }, this)) {
// HordeCore.notify(Kronolith.text.max_file_size, 'horde.error');
// return;
// }
var params = $H({ i: $F('kronolithEventId'), c: $F('kronolithEventCalendar') });
HordeCore.addRequestParams(params);

$A(fi).each(function(d) {
var fd = new FormData(), li;

params.merge({
file_upload: d
}).each(function(p) {
fd.append(p.key, p.value);
});

++this.curr_upload;
if (Object.isNumber(this.num_limit)) {
--this.num_limit;
}

HordeCore.doAction('addFile', {}, {
ajaxopts: {
postBody: fd,
requestHeaders: { "Content-type": null },
onComplete: function() {
--this.curr_upload;
li.remove();
}.bind(this),
onCreate: function(e) {
if (e.transport && e.transport.upload) {
var p = new Element('SPAN')
.addClassName('file_upload_progress')
.hide()
.insert(new Element('span'));
li = this.uploadFileWait(d);
li.insert(p);

e.transport.upload.onprogress = function(e2) {
if (e2.lengthComputable) {
console.log(parseInt((e2.loaded / e2.total) * 100, 10) + "%");
p.down('span').setStyle({
width: parseInt((e2.loaded / e2.total) * 100, 10) + "%"
});
if (!p.visible()) {
li.down('.file_upload_text')
.addClassName('file_upload_text_progress')
.down('span').remove();
p.show();
}
}
};
} else {
li = this.uploadFileWait(d);
}
}.bind(this)
},
callback: function(r) {
// @todo Add file link.
console.log(r);
}
});
}, this);
},

/**
* Closes a RedBox overlay, after saving its content to the body.
*/
Expand Down
12 changes: 11 additions & 1 deletion kronolith/lib/Ajax.php
Expand Up @@ -68,13 +68,20 @@ protected function _addBaseVars()
array('#', '#', '{', '{', '}', '}'),
strval($registry->downloadUrl('#{calendar}.ics', array('actionID' => 'export', 'all_events' => 1, 'exportID' => Horde_Data::EXPORT_ICALENDAR, 'exportCal' => 'resource_#{calendar}'))->setRaw(true))),
'URI_EVENT_EXPORT' => str_replace(array('%23', '%7B', '%7D'), array('#', '{', '}'), Horde::url('event.php', true)->add(array('view' => 'ExportEvent', 'eventID' => '#{id}', 'calendar' => '#{calendar}', 'type' => '#{type}'))),
'URI_FILE_DOWNLOAD' => str_replace(
array('%23', '%2523', '%7B', '%257B', '%7D', '%257D'),
array('#', '#', '{', '{', '}', '}'),
strval($registry->downloadUrl('#{filename}', array('actionID' => 'download_file', 'file' => '#{filename}', 'type' => '#{type}', 'source' => '#{source}', 'key' => '#{key}'))->setRaw(true))),
'URI_FILE_VIEW' => str_replace(array('%23', '%7B', '%7D'), array('#', '{', '}'), Horde::url('viewer.php', true)->add(array('file' => '#{filename}', 'type' => '#{type}', 'source' => '#{source}', 'key' => '#{key}'))),
'images' => array(
'alarm' => strval(Horde_Themes::img('alarm-fff.png')),
'attendees' => strval(Horde_Themes::img('attendees-fff.png')),
'exception' => strval(Horde_Themes::img('exception-fff.png')),
'new_event' => strval(Horde_Themes::img('new.png')),
'new_task' => strval(Horde_Themes::img('new_task.png')),
'recur' => strval(Horde_Themes::img('recur-fff.png')),
'download' => strval(Horde_Themes::img('download.png')),
'delete' => strval(Horde_Themes::img('delete.png'))
),
'new_event' => $injector->getInstance('Kronolith_View_Sidebar')->newLink
. $injector->getInstance('Kronolith_View_Sidebar')->newText
Expand Down Expand Up @@ -140,7 +147,9 @@ protected function _addBaseVars()
'alerts' => _("Notifications"),
'allday' => _("All day"),
'delete_calendar' => _("Are you sure you want to delete this calendar and all the events in it?"),
'delete_file' => _("Delete file"),
'delete_tasklist' => _("Are you sure you want to delete this task list and all the tasks in it?"),
'download_file' => _("Download file"),
'external_category' => _("Other events"),
'fix_form_values' => _("Please enter correct values in the form first."),
'geocode_error' => _("Unable to locate requested address"),
Expand All @@ -166,7 +175,8 @@ protected function _addBaseVars()
'tentative' => _("You have tentatively accepted this meeting request."),
'declined' => _("You have declined this meeting request."),
'update_attendees' => _("Send updates to attendees?"),
'update_organizer' => _("Send attendance update to organizer?")
'update_organizer' => _("Send attendance update to organizer?"),
'uploading' => _("Uploading")
);

for ($i = 1; $i <= 12; ++$i) {
Expand Down
120 changes: 120 additions & 0 deletions kronolith/lib/Ajax/Application/Handler.php
Expand Up @@ -1529,6 +1529,126 @@ public function checkResources()
return $results;
}

/**
* Add a file to an event.
*
* The following arguments are expected:
* - i: The event id.
* - c: The calendar id.
*
* The actual file data is returned in $_FILES and is handled in
* self::_addFileFromUpload()
*/
public function addFile()
{
global $notification;

$result = new stdClass;
$result->success = 0;

if (!isset($this->vars->i)) {
$notification->push(_("Your attachment was not uploaded. Most likely, the file exceeded the maximum size allowed by the server configuration."), 'horde.warning');
} else {
try {
$event = $this->_getDriver($this->vars->c)->getEvent($this->vars->i);
if ($this->_canUploadFiles()) {
foreach ($this->_addFileFromUpload() as $f) {
if ($f instanceof Kronolith_Exception) {
$notification->push($f, 'horde.error');
} else {
$event->addFile($f);
$result->success = 1;
$notification->push(_("The file was successfully uploaded."), 'horde.success');
}
}
} elseif (empty($e)) {
$notification->push(_("Uploading files has been disabled on this server."), 'horde.error');
}
} catch (Kronolith_Exception $e) {
$notification->push($e, 'horde.error');
}
}

return $result;
}

/**
* Removes a file from the specified event.
*
* The following arguments are expected:
* - source: The type|calender source string.
* - key: The event id.
* - name: The filename to delete.
*/
public function deleteFile()
{
global $notification;

$result = new StdClass;
$result->success = 0;

try {
$event = $this->_getDriver($this->vars->source)->getEvent($this->vars->key);
if (!$event->hasPermission(Horde_Perms::EDIT)) {
$notification->push(_("Permission Denied"), 'horde.error');
} else {
$event->deleteFile($this->vars->name);
$result->success = 1;
$notification->push(_("The file was successfully deleted."), 'horde.success');
}
} catch (Kronolith_Exception $e) {
$notification->push($e, 'horde.error');
}

return $result;
}

/**
* Check ability to upload files.
*
* @return integer Maximum allowed size of file.
*/
protected function _canUploadFiles()
{
global $browser, $conf;

$size = $browser->allowFileUploads();
return empty($conf['file_uploads'])
? $size
: min($size, $conf['file_uploads']['size_limit']);
}

/**
* Collect uploaded files.
*
* @return array An array of fileinfo hashes.
*/
protected function _addFileFromUpload()
{
global $browser;

try {
$browser->wasFileUploaded('file_upload');
} catch (Horde_Browser_Exception $e) {
throw new Kronolith_Exception($e);
}

$finfo = array();
if (is_array($_FILES['file_upload']['size'])) {
for ($i = 0; $i < count($_FILES['file_upload']['size']); ++$i) {
$tmp = array();
foreach ($_FILES['file_upload'] as $key => $val) {
$tmp[$key] = $val[$i];
}
$finfo[] = $tmp;
}
} else {
$finfo[] = $_FILES['file_upload'];
}

return $finfo;
}

/**
* Returns the driver object for a calendar.
*
Expand Down

0 comments on commit 834cf00

Please sign in to comment.