From e8f062dc935b6bd9b8047594affda491c659b79a Mon Sep 17 00:00:00 2001 From: Thomas Tanghus Date: Sun, 22 Apr 2012 20:44:11 +0200 Subject: [PATCH] Contacts: - Added overlay toolbar to contact photo with 'Delete current', 'Edit current', 'Load from OC_Filesystem' and 'Upload' options. - Made action icons translucent instead of hiding them. --- apps/contacts/ajax/currentphoto.php | 68 ++++++++++ apps/contacts/ajax/loadphoto.php | 4 + apps/contacts/ajax/oc_photo.php | 75 +++++++++++ apps/contacts/ajax/uploadphoto.php | 13 -- apps/contacts/css/contacts.css | 19 ++- apps/contacts/js/contacts.js | 116 ++++++++++++++---- apps/contacts/templates/part.contact.php | 5 +- apps/contacts/templates/part.contactphoto.php | 8 +- 8 files changed, 260 insertions(+), 48 deletions(-) create mode 100644 apps/contacts/ajax/currentphoto.php create mode 100644 apps/contacts/ajax/oc_photo.php diff --git a/apps/contacts/ajax/currentphoto.php b/apps/contacts/ajax/currentphoto.php new file mode 100644 index 0000000000..15cb6c7a08 --- /dev/null +++ b/apps/contacts/ajax/currentphoto.php @@ -0,0 +1,68 @@ + + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU AFFERO GENERAL PUBLIC LICENSE for more details. + * + * You should have received a copy of the GNU Affero General Public + * License along with this library. If not, see . + * + */ +// Init owncloud +require_once('../../../lib/base.php'); + +// Check if we are a user +// Firefox and Konqueror tries to download application/json for me. --Arthur +OC_JSON::setContentTypeHeader('text/plain'); +OC_JSON::checkLoggedIn(); +OC_JSON::checkAppEnabled('contacts'); +function bailOut($msg) { + OC_JSON::error(array('data' => array('message' => $msg))); + OC_Log::write('contacts','ajax/currentphoto.php: '.$msg, OC_Log::ERROR); + exit(); +} +function debug($msg) { + OC_Log::write('contacts','ajax/currentphoto.php: '.$msg, OC_Log::DEBUG); +} + +if (!isset($_GET['id'])) { + bailOut(OC_Contacts_App::$l10n->t('No contact ID was submitted.')); +} + +$tmpfname = tempnam("/tmp", "occOrig"); +$contact = OC_Contacts_App::getContactVCard($_GET['id']); +$image = new OC_Image(); +if(!$image) { + bailOut(OC_Contacts_App::$l10n->t('Error loading image.')); +} +// invalid vcard +if( is_null($contact)) { + bailOut(OC_Contacts_App::$l10n->t('Error reading contact photo.')); +} else { + if(!$image->loadFromBase64($contact->getAsString('PHOTO'))) { + $image->loadFromBase64($contact->getAsString('LOGO')); + } + if($image->valid()) { + if($image->save($tmpfname)) { + OC_JSON::success(array('data' => array('id'=>$_GET['id'], 'tmp'=>$tmpfname))); + exit(); + } else { + bailOut(OC_Contacts_App::$l10n->t('Error saving temporary file.')); + } + } else { + bailOut(OC_Contacts_App::$l10n->t('The loading photo is not valid.')); + } +} + +?> diff --git a/apps/contacts/ajax/loadphoto.php b/apps/contacts/ajax/loadphoto.php index 2c8bb7bf1e..2f95cdc932 100644 --- a/apps/contacts/ajax/loadphoto.php +++ b/apps/contacts/ajax/loadphoto.php @@ -38,6 +38,7 @@ function bailOut($msg) { $image = null; $id = isset($_GET['id']) ? $_GET['id'] : ''; +$refresh = isset($_GET['refresh']) ? true : false; if($id == '') { bailOut(OC_Contacts_App::$l10n->t('Missing contact id.')); @@ -54,6 +55,9 @@ foreach($vcard->children as $property){ $tmpl = new OC_TEMPLATE("contacts", "part.contactphoto"); $tmpl->assign('id', $id); +if($refresh) { + $tmpl->assign('refresh', 1); +} $page = $tmpl->fetchPage(); OC_JSON::success(array('data' => array('page'=>$page, 'checksum'=>$checksum))); ?> diff --git a/apps/contacts/ajax/oc_photo.php b/apps/contacts/ajax/oc_photo.php new file mode 100644 index 0000000000..14d77ea50b --- /dev/null +++ b/apps/contacts/ajax/oc_photo.php @@ -0,0 +1,75 @@ + + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU AFFERO GENERAL PUBLIC LICENSE for more details. + * + * You should have received a copy of the GNU Affero General Public + * License along with this library. If not, see . + * + */ +// Init owncloud +require_once('../../../lib/base.php'); + +// Check if we are a user +// Firefox and Konqueror tries to download application/json for me. --Arthur +OC_JSON::setContentTypeHeader('text/plain'); +OC_JSON::checkLoggedIn(); +OC_JSON::checkAppEnabled('contacts'); +function bailOut($msg) { + OC_JSON::error(array('data' => array('message' => $msg))); + OC_Log::write('contacts','ajax/oc_photo.php: '.$msg, OC_Log::ERROR); + exit(); +} +function debug($msg) { + OC_Log::write('contacts','ajax/oc_photo.php: '.$msg, OC_Log::DEBUG); +} + +if (!isset($_GET['id'])) { + bailOut(OC_Contacts_App::$l10n->t('No contact ID was submitted.')); +} + +if (!isset($_GET['path'])) { + bailOut(OC_Contacts_App::$l10n->t('No photo path was submitted.')); +} + +$localpath = OC_Filesystem::getLocalFile($_GET['path']); +$tmpfname = tempnam("/tmp", "occOrig"); + +if(!file_exists($localpath)) { + bailOut(OC_Contacts_App::$l10n->t('File doesn\'t exist:').$localpath); +} +file_put_contents($tmpfname, file_get_contents($localpath)); + +$image = new OC_Image(); +if(!$image) { + bailOut(OC_Contacts_App::$l10n->t('Error loading image.')); +} +if(!$image->loadFromFile($tmpfname)) { + bailOut(OC_Contacts_App::$l10n->t('Error loading image.')); +} +if($image->width() > 400 || $image->height() > 400) { + $image->resize(400); // Prettier resizing than with browser and saves bandwidth. +} +if(!$image->fixOrientation()) { // No fatal error so we don't bail out. + debug('Couldn\'t save correct image orientation: '.$tmpfname); +} +if($image->save($tmpfname)) { + OC_JSON::success(array('data' => array('mime'=>$_SERVER['CONTENT_TYPE'], 'name'=>$fn, 'id'=>$id, 'tmp'=>$tmpfname))); + exit(); +} else { + bailOut('Couldn\'t save temporary image: '.$tmpfname); +} + +?> diff --git a/apps/contacts/ajax/uploadphoto.php b/apps/contacts/ajax/uploadphoto.php index 9780df4647..15d4718241 100644 --- a/apps/contacts/ajax/uploadphoto.php +++ b/apps/contacts/ajax/uploadphoto.php @@ -36,19 +36,6 @@ function debug($msg) { OC_Log::write('contacts','ajax/uploadphoto.php: '.$msg, OC_Log::DEBUG); } -// foreach ($_SERVER as $key=>$element) { -// debug('$_SERVER: '.$key.'=>'.$element); -// } -// foreach ($_GET as $key=>$element) { -// debug('_GET: '.$key.'=>'.$element); -// } -// foreach ($_POST as $key=>$element) { -// debug('_POST: '.$key.'=>'.$element); -// } -// foreach ($_FILES as $key=>$element) { -// debug('_FILES: '.$key.'=>'.$element); -// } - // If it is a Drag'n'Drop transfer it's handled here. $fn = (isset($_SERVER['HTTP_X_FILE_NAME']) ? $_SERVER['HTTP_X_FILE_NAME'] : false); if ($fn) { diff --git a/apps/contacts/css/contacts.css b/apps/contacts/css/contacts.css index c19c6cc711..b0c68c96e6 100644 --- a/apps/contacts/css/contacts.css +++ b/apps/contacts/css/contacts.css @@ -38,14 +38,17 @@ dl.form { width: 100%; float: left; clear: right; margin: 0; padding: 0; } .ui-autocomplete-loading { background: url('../../../core/img/loading.gif') right center no-repeat; } .float { float: left; } .listactions { height: 1em; width:60px; float: left; clear: right; } -.add,.edit,.delete,.mail, .globe { cursor: pointer; width: 20px; height: 20px; margin: 0; float: left; position:relative; display: none; } +.add,.edit,.delete,.mail, .globe, .upload, .cloud { cursor: pointer; width: 20px; height: 20px; margin: 0; float: left; position:relative; opacity: 0.1; } +.add:hover,.edit:hover,.delete:hover,.mail:hover, .globe:hover, .upload:hover, .cloud:hover { opacity: 1.0 } .add { background:url('../../../core/img/actions/add.svg') no-repeat center; clear: both; } .delete { background:url('../../../core/img/actions/delete.svg') no-repeat center; } .edit { background:url('../../../core/img/actions/rename.svg') no-repeat center; } .mail { background:url('../../../core/img/actions/mail.svg') no-repeat center; } +.upload { background:url('../../../core/img/actions/upload.svg') no-repeat center; } +.cloud { background:url('../../../core/img/places/picture.svg') no-repeat center; } /*.globe { background:url('../img/globe.svg') no-repeat center; }*/ .globe { background:url('../../../core/img/actions/public.svg') no-repeat center; } - +.transparent{ opacity: 0.6; } #edit_name_dialog { padding:0; } #edit_name_dialog > input { width: 15em; } #edit_address_dialog { /*width: 30em;*/ } @@ -60,9 +63,13 @@ dl.form { width: 100%; float: left; clear: right; margin: 0; padding: 0; } .contactpart legend { width:auto; padding:.3em; border:1px solid #ddd; font-weight:bold; cursor:pointer; background:#f8f8f8; color:#555; text-shadow:#fff 0 1px 0; -moz-box-shadow:0 1px 1px #fff, 0 1px 1px #fff inset; -webkit-box-shadow:0 1px 1px #fff, 0 1px 1px #fff inset; -moz-border-radius:.5em; -webkit-border-radius:.5em; border-radius:.5em; } #cropbox { margin: auto; } -#contacts_details_photo { border-radius: 0.5em; border: thin solid #bbb; margin: 0.3em; cursor: pointer; background: url(../../../core/img/loading.gif) no-repeat center center; display: block; /* clear: right;*/ } -#contacts_details_photo:hover { background: #fff; } -/*#contacts_details_photo_progress { margin: 0.3em 0.3em 0.3em 7em; clear: left; }*/ +#contacts_details_photo { border-radius: 0.5em; border: thin solid #bbb; margin: 0.3em; background: url(../../../core/img/loading.gif) no-repeat center center; display: block; -moz-box-shadow: 0 1px 3px #777; -webkit-box-shadow: 0 1px 3px #777; box-shadow: 0 1px 3px #777; } +#contacts_details_photo:hover { background: #fff; cursor: default; } +#phototools { position:absolute; margin: 5px 0 0 10px; width:auto; height:22px; padding:0px; background-color:#fff; list-style-type:none; border-radius: 0.5em; -moz-box-shadow: 0 1px 3px #777; -webkit-box-shadow: 0 1px 3px #777; box-shadow: 0 1px 3px #777; } +#phototools li { display: inline; } +#phototools li a { float:left; cursor:pointer; width:22px; height:22px; opacity: 0.6; } +#phototools li a:hover { opacity: 0.8; } + /* Address editor */ #addressdisplay { padding: 0.5em; } dl.addresscard { background-color: #fff; float: left; width: 45%; margin: 0 0.3em 0.3em 0.3em; padding: 0; border: thin solid lightgray; } @@ -80,7 +87,7 @@ dl.addresscard dd > ul { margin: 0.3em; padding: 0.3em; } #file_upload_target, #crop_target { display:none; } -#file_upload_start { opacity:0; filter:alpha(opacity=0); z-index:1; /*position:absolute; left:0; top:0;*/ cursor:pointer; width:0; height:0;} +#file_upload_start { opacity:0; filter:alpha(opacity=0); z-index:1; /*position:absolute; left:0; top:0;*/ width:0; height:0;} input[type="checkbox"] { width: 20px; height: 20px; vertical-align: bottom; } .big { font-weight:bold; font-size:1.2em; } .huge { font-weight:bold; font-size:1.5em; } diff --git a/apps/contacts/js/contacts.js b/apps/contacts/js/contacts.js index b491b3a90e..45b2fe130e 100644 --- a/apps/contacts/js/contacts.js +++ b/apps/contacts/js/contacts.js @@ -117,13 +117,21 @@ Contacts={ loadListHandlers:function() { //$('.add,.delete').hide(); $('.globe,.mail,.delete,.edit,.tip').tipsy(); - $('.addresscard,.propertylist li,.propertycontainer').hover( + /*$('.addresscard,.propertylist li,.propertycontainer').hover( function () { $(this).find('.globe,.mail,.delete,.edit').fadeIn(100); }, function () { $(this).find('.globe,.mail,.delete,.edit').fadeOut(100); } + );*/ + $('.addresscard,.propertylist li,.propertycontainer').hover( + function () { + $(this).find('.globe,.mail,.delete,.edit').animate({ opacity: 1.0 }, 200, function() {}); + }, + function () { + $(this).find('.globe,.mail,.delete,.edit').animate({ opacity: 0.1 }, 200, function() {}); + } ); }, loadHandlers:function() { @@ -691,10 +699,11 @@ Contacts={ } }, deleteProperty:function(obj, type){ - //console.log('deleteProperty, id: ' + this.id); + console.log('deleteProperty, obj: ' + obj.attr('id') + ', container: ' + Contacts.UI.propertyContainerFor(obj).html()); Contacts.UI.loading(obj, true); var checksum = Contacts.UI.checksumFor(obj); - if(checksum != undefined) { + console.log('deleteProperty, id: ' + this.id + ', checksum: ' + checksum); + if(checksum) { $.getJSON('ajax/deleteproperty.php',{'id': this.id, 'checksum': checksum },function(jsondata){ if(jsondata.status == 'success'){ if(type == 'list') { @@ -707,13 +716,14 @@ Contacts={ var othertypes = ['NOTE', 'PHOTO']; if(othertypes.indexOf(proptype) != -1) { console.log('NOTE or PHOTO'); - Contacts.UI.propertyContainerFor(obj).hide(); Contacts.UI.propertyContainerFor(obj).data('checksum', ''); if(proptype == 'PHOTO') { console.log('Delete PHOTO'); Contacts.UI.Contacts.refreshThumbnail(Contacts.UI.Card.id); + Contacts.UI.Card.loadPhoto(); } else if(proptype == 'NOTE') { $('#note').find('textarea').val(''); + Contacts.UI.propertyContainerFor(obj).hide(); } } else { $('dl dt[data-element="'+proptype+'"],dd[data-element="'+proptype+'"]').hide(); @@ -1073,13 +1083,65 @@ Contacts={ form.submit(); } }, + loadPhotoHandlers:function(){ + $('#contacts_details_photo_wrapper').hover( + function () { + $('#phototools').slideDown(200); + }, + function () { + $('#phototools').slideUp(200); + } + ); + $('#phototools').hover( + function () { + $(this).removeClass('transparent'); + }, + function () { + $(this).addClass('transparent'); + } + ); + if(this.data.PHOTO) { + $('#phototools .delete').click(function() { + $(this).tipsy('hide'); + Contacts.UI.Card.deleteProperty($('#contacts_details_photo'), 'single'); + $(this).hide(); + }); + $('#phototools .edit').click(function() { + $(this).tipsy('hide'); + Contacts.UI.Card.editCurrentPhoto(); + }); + } else { + $('#phototools .delete').hide(); + $('#phototools .edit').hide(); + } + $('#phototools .upload').click(function() { + $('#file_upload_start').trigger('click'); + }); + $('#phototools .cloud').click(function() { + OC.dialogs.filepicker(t('contacts', 'Select photo'), Contacts.UI.Card.cloudPhotoSelected, false, 'image', true); + }); + }, + cloudPhotoSelected:function(path){ + console.log('cloudPhotoSelected: ' + path); + $.getJSON('ajax/oc_photo.php',{'path':path,'id':Contacts.UI.Card.id},function(jsondata){ + if(jsondata.status == 'success'){ + //alert(jsondata.data.page); + Contacts.UI.Card.editPhoto(jsondata.data.id, jsondata.data.tmp) + $('#edit_photo_dialog_img').html(jsondata.data.page); + } + else{ + OC.dialogs.alert(jsondata.data.message, t('contacts', 'Error')); + } + }); + }, loadPhoto:function(force){ //if(this.data.PHOTO||force==true) { $.getJSON('ajax/loadphoto.php',{'id':this.id},function(jsondata){ if(jsondata.status == 'success'){ //alert(jsondata.data.page); - $('#file_upload_form').data('checksum', jsondata.data.checksum); + $('#contacts_details_photo_wrapper').data('checksum', jsondata.data.checksum); $('#contacts_details_photo_wrapper').html(jsondata.data.page); + Contacts.UI.Card.loadPhotoHandlers(); } else{ OC.dialogs.alert(jsondata.data.message, t('contacts', 'Error')); @@ -1093,6 +1155,18 @@ Contacts={ $('#contacts_propertymenu a[data-type="PHOTO"]').parent().show(); }*/ }, + editCurrentPhoto:function(){ + $.getJSON('ajax/currentphoto.php',{'id':this.id},function(jsondata){ + if(jsondata.status == 'success'){ + //alert(jsondata.data.page); + Contacts.UI.Card.editPhoto(jsondata.data.id, jsondata.data.tmp) + $('#edit_photo_dialog_img').html(jsondata.data.page); + } + else{ + OC.dialogs.alert(jsondata.data.message, t('contacts', 'Error')); + } + }); + }, editPhoto:function(id, tmp_path){ //alert('editPhoto: ' + tmp_path); $.getJSON('ajax/cropphoto.php',{'tmp_path':tmp_path,'id':this.id},function(jsondata){ @@ -1119,6 +1193,7 @@ Contacts={ if(response != undefined && response.status == 'success'){ // load cropped photo. $('#contacts_details_photo_wrapper').html(response.data.page); + Contacts.UI.Card.loadPhotoHandlers(); }else{ OC.dialogs.alert(response.data.message, t('contacts', 'Error')); } @@ -1343,10 +1418,12 @@ $(document).ready(function(){ Contacts.UI.Card.editNew(); }); - /** - * Load the details view for a contact. - */ - $('#leftcontent li').live('click',function(){ + $('#contacts_deletecard').click(function(){ + Contacts.UI.Card.doDelete(); + }); + + // Load a contact. + $('#leftcontent li').click(function(){ var id = $(this).data('id'); $(this).addClass('active'); var oldid = $('#rightcontent').data('id'); @@ -1365,10 +1442,6 @@ $(document).ready(function(){ return false; }); - $('#contacts_deletecard').live('click',function(){ - Contacts.UI.Card.doDelete(); - }); - $('#contacts li').bind('inview', function(event, isInView, visiblePartX, visiblePartY) { if (isInView) { //NOTE: I've kept all conditions for future reference ;-) // element is now visible in the viewport @@ -1390,13 +1463,6 @@ $(document).ready(function(){ } }); - $('.button').tipsy(); - // Triggers invisible file input - $('#contacts_details_photo').live('click', function() { - $('#file_upload_start').trigger('click'); - return false; - }); - // NOTE: For some reason the selector doesn't work when I select by '.contacts_property' too... // I do the filtering in the event handler instead. //$('input[type="text"],input[type="checkbox"],input[type="email"],input[type="tel"],input[type="date"], select').live('change', function(){ @@ -1500,8 +1566,8 @@ $(document).ready(function(){ if (e.lengthComputable){ var _progress = Math.round((e.loaded * 100) / e.total); if (_progress != 100){ - $('#contacts_details_photo_progress').text(_progress + '%'); - $('#contacts_details_photo_progress').val(_progress); + //$('#contacts_details_photo_progress').text(_progress + '%'); + //$('#contacts_details_photo_progress').val(_progress); } } }; @@ -1517,12 +1583,12 @@ $(document).ready(function(){ xhr.send(file); } - $('body').live('click',function(e){ + $('body').click(function(e){ if(!$(e.target).is('#contacts_propertymenu_button')) { $('#contacts_propertymenu').hide(); } }); - $('#contacts_propertymenu_button').live('click',function(){ + $('#contacts_propertymenu_button').click(function(){ var menu = $('#contacts_propertymenu'); if(menu.is(':hidden')) { menu.show(); @@ -1531,7 +1597,7 @@ $(document).ready(function(){ menu.hide(); } }); - $('#contacts_propertymenu a').live('click',function(){ + $('#contacts_propertymenu a').click(function(){ var type = $(this).data('type'); Contacts.UI.Card.addProperty(type); $('#contacts_propertymenu').hide(); diff --git a/apps/contacts/templates/part.contact.php b/apps/contacts/templates/part.contact.php index c09c20fd4e..b90fa92c2c 100644 --- a/apps/contacts/templates/part.contact.php +++ b/apps/contacts/templates/part.contact.php @@ -23,10 +23,9 @@ $id = isset($_['id']) ? $_['id'] : '';
-
+
- -
+
diff --git a/apps/contacts/templates/part.contactphoto.php b/apps/contacts/templates/part.contactphoto.php index bcb2f75815..3c11e4d158 100644 --- a/apps/contacts/templates/part.contactphoto.php +++ b/apps/contacts/templates/part.contactphoto.php @@ -2,8 +2,14 @@ $id = $_['id']; $wattr = isset($_['width'])?'width="'.$_['width'].'"':''; $hattr = isset($_['height'])?'height="'.$_['height'].'"':''; -$rand = isset($_['refresh'])?'&'.rand().'='.rand():''; +$rand = isset($_['refresh'])?'&refresh='.rand():''; ?> + src="?id=" />