1
0
mirror of https://github.com/owncloudarchive/contacts.git synced 2025-01-18 07:52:21 +01:00

New FileActions script for importing from filesystem. Closes #190

Needs owncloud/core#4784 to work properly
This commit is contained in:
Thomas Tanghus 2013-09-10 00:28:16 +02:00
parent 196ad4bd34
commit 322357dba1
6 changed files with 302 additions and 126 deletions

View File

@ -146,6 +146,16 @@ $this->create('contacts_import_upload', 'addressbook/{backend}/{addressbookid}/i
)
->requirements(array('backend', 'addressbookid'));
$this->create('contacts_import_prepare', 'addressbook/{backend}/{addressbookid}/import/prepare')
->post()
->action(
function($params) {
session_write_close();
Main::main('ImportController', 'prepare', $params, new DIContainer());
}
)
->requirements(array('backend', 'addressbookid'));
$this->create('contacts_import_start', 'addressbook/{backend}/{addressbookid}/import/start')
->post()
->action(

View File

@ -4,7 +4,8 @@ OC.Contacts = OC.Contacts || {};
(function(window, $, OC) {
'use strict';
var AddressBook = function(storage, book, template) {
var AddressBook = function(storage, book, template, isFileAction) {
this.isFileAction = isFileAction || false;
this.storage = storage;
this.book = book;
this.$template = template;
@ -18,6 +19,9 @@ OC.Contacts = OC.Contacts || {};
backend: this.book.backend,
permissions: this.book.permissions
});
if(this.isFileAction) {
return this.$li;
}
this.$li.find('a.action').tipsy({gravity: 'w'});
if(!this.hasPermission(OC.PERMISSION_DELETE)) {
this.$li.find('a.action.delete').hide();
@ -227,20 +231,25 @@ OC.Contacts = OC.Contacts || {};
var AddressBookList = function(
storage,
bookTemplate,
bookItemTemplate
bookItemTemplate,
isFileAction
) {
var self = this;
this.isFileAction = isFileAction || false;
this.storage = storage;
this.$bookTemplate = bookTemplate;
this.$bookList = this.$bookTemplate.find('.addressbooklist');
this.$bookItemTemplate = bookItemTemplate;
this.$importFileInput = this.$bookTemplate.find('#import_upload_start');
this.$importIntoSelect = this.$bookTemplate.find('#import_into');
this.$importProgress = this.$bookTemplate.find('#import-status-progress');
this.$importStatusText = this.$bookTemplate.find('#import-status-text');
this.addressBooks = [];
if(this.isFileAction) {
return;
}
this.$importFileInput = this.$bookTemplate.find('#import_upload_start');
var $addInput = this.$bookTemplate.find('#add-address-book');
var self = this;
$addInput.addnew({
ok: function(event, name) {
console.log('add-address-book ok', name);
@ -256,6 +265,7 @@ OC.Contacts = OC.Contacts || {};
});
}
});
$(document).bind('status.addressbook.removed', function(e, data) {
var addressBook = data.addressbook;
self.addressBooks.splice(self.addressBooks.indexOf(addressBook), 1);
@ -289,8 +299,8 @@ OC.Contacts = OC.Contacts || {};
},
done: function (e, data) {
self.$importStatusText.text(t('contacts', 'Importing...'));
console.log('Upload done:', data.result);
self.doImport(data.result);
console.log('Upload done:', data);
self.doImport(self.storage.formatResponse(data.result, data.jqXHR));
},
fail: function(e, data) {
console.log('fail', data);
@ -303,13 +313,29 @@ OC.Contacts = OC.Contacts || {};
AddressBookList.prototype.count = function() {
return this.addressBooks.length;
}
};
/**
* For importing from oC filesyatem
*/
AddressBookList.prototype.prepareImport = function(backend, addressBookId, path, fileName) {
console.log('prepareImport', backend, addressBookId, path, fileName);
this.$importProgress.progressbar({value:false});
this.$importStatusText.text(t('contacts', 'Preparing...'));
return this.storage.prepareImport(
backend, addressBookId,
{filename:fileName, path:path}
);
};
AddressBookList.prototype.doImport = function(response) {
console.log('doImport');
var defer = $.Deferred();
var done = false;
var interval = null, isChecking = false;
var self = this;
var closeImport = function() {
defer.resolve();
self.$importProgress.fadeOut();
setTimeout(function() {
$('.import-upload').show();
@ -318,7 +344,7 @@ OC.Contacts = OC.Contacts || {};
self.$importProgress.progressbar('destroy');
}, 5000);
};
if(response.status === 'success') {
if(!response.error) {
this.importCount = response.data.count;
this.$importProgress.progressbar('value', 0);
this.$importProgress.progressbar('option', 'max', this.importCount);
@ -359,7 +385,7 @@ OC.Contacts = OC.Contacts || {};
data.backend, data.addressbookid,
{filename:data.filename, progresskey:data.progresskey}
))
.then(function(response) {
.then(function(response) {
console.log('response', response);
if(!response.error) {
console.log('Import done');
@ -369,12 +395,15 @@ OC.Contacts = OC.Contacts || {};
$(document).trigger('status.addressbook.imported', {
addressbook: addressBook
});
defer.resolve();
} else {
defer.reject(response);
self.$importStatusText.text(response.message);
$(document).trigger('status.contacts.error', response);
}
done = true;
}).fail(function(response) {
defer.reject(response);
console.log(response.message);
$(document).trigger('status.contacts.error', response);
done = true;
@ -383,17 +412,20 @@ OC.Contacts = OC.Contacts || {};
getStatus(data.backend, data.addressbookid, data.progresskey, interval, done);
}, 1500);
} else {
defer.reject(response);
done = true;
self.$importStatusText.text(response.data.message);
self.$importStatusText.text(response.message);
closeImport();
$(document).trigger('status.contacts.error', response);
}
return defer;
}
/**
* Rebuild the select to choose which address book to import into.
*/
AddressBookList.prototype.buildImportSelect = function() {
console.log('buildImportSelect');
var self = this;
this.$importIntoSelect.find('option:not([value="-1"])').remove();
var addressBooks = this.selectByPermission(OC.PERMISSION_UPDATE);
@ -401,13 +433,16 @@ OC.Contacts = OC.Contacts || {};
var $opt = $('<option />');
$opt.val(book.getId()).text(book.getDisplayName()).data('backend', book.getBackend());
self.$importIntoSelect.append($opt);
console.log('appending', $opt, 'to', self.$importIntoSelect);
});
if(addressBooks.length === 1) {
this.$importIntoSelect.val(this.$importIntoSelect.find('option:not([value="-1"])').first().val()).hide().trigger('change');
self.$importFileInput.prop('disabled', false);
} else {
this.$importIntoSelect.show();
self.$importFileInput.prop('disabled', true);
if(!this.isFileAction) {
if(addressBooks.length === 1) {
this.$importIntoSelect.val(this.$importIntoSelect.find('option:not([value="-1"])').first().val()).hide().trigger('change');
self.$importFileInput.prop('disabled', false);
} else {
this.$importIntoSelect.show();
self.$importFileInput.prop('disabled', true);
}
}
}
@ -419,9 +454,11 @@ OC.Contacts = OC.Contacts || {};
* @return AddressBook
*/
AddressBookList.prototype.insertAddressBook = function(addressBook) {
var book = new AddressBook(this.storage, addressBook, this.$bookItemTemplate);
var result = book.render();
this.$bookList.append(result);
var book = new AddressBook(this.storage, addressBook, this.$bookItemTemplate, this.isFileAction);
if(!this.isFileAction) {
var result = book.render();
this.$bookList.append(result);
}
this.addressBooks.push(book);
return book;
};
@ -553,16 +590,20 @@ OC.Contacts = OC.Contacts || {};
var book = self.insertAddressBook(addressBook);
});
self.buildImportSelect();
if(typeof OC.Share !== 'undefined') {
OC.Share.loadIcons('addressbook');
} else {
self.$bookList.find('a.action.share').css('display', 'none');
console.log('After buildImportSelect');
if(!self.isFileAction) {
if(typeof OC.Share !== 'undefined') {
OC.Share.loadIcons('addressbook');
} else {
self.$bookList.find('a.action.share').css('display', 'none');
}
}
console.log('Before resolve');
defer.resolve(self.addressBooks);
console.log('After resolve');
} else {
defer.reject(response);
$(document).trigger('status.contacts.error', response);
return false;
}
})
.fail(function(jqxhr, textStatus, error) {

View File

@ -1,95 +1,145 @@
/**
* Copyright (c) 2012 Georg Ehrke <ownclouddev at georgswebsite dot de>
* Copyright (c) 2013 Thomas Tanghus (thomas@tanghus.net)
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
*/
Contacts_Import={
importdialog: function(filename){
var path = $('#dir').val();
$('body').append('<div id="contacts_import"></div>');
$('#contacts_import').load(OC.filePath('contacts', 'ajax', 'importdialog.php'), {filename:filename, path:path}, function(){Contacts_Import.initdialog(filename);});
},
initdialog: function(filename){
$('#contacts_import_dialog').dialog({
width : 500,
close : function() {
$(this).dialog('destroy').remove();
$('#contacts_import').remove();
}
});
$('#import_done_button').click(function(){
$('#contacts_import_dialog').dialog('destroy').remove();
$('#contacts_import').remove();
});
$('#progressbar').progressbar({value: 0});
$('#startimport').click(function(){
var filename = $('#filename').val();
var path = $('#path').val();
var method = 'old';
var addressbookid = $('#contacts option:selected').val();
if($('#contacts option:selected').val() == 'newaddressbook'){
var method = 'new';
var addressbookname = $('#newaddressbook').val();
var addressbookname = $.trim(addressbookname);
if(addressbookname == ''){
$('#newaddressbook').css('background-color', '#FF2626');
$('#newaddressbook').focus(function(){
$('#newaddressbook').css('background-color', '#F8F8F8');
OC.ContactsImporter = OC.ContactsImporter || {
init:function(fileName) {
var self = OC.ContactsImporter;
self.path = $('#dir').val();
self.fileName = fileName;
console.log('fileName', self.path, self.fileName);
OC.addScript('contacts', 'addressbooks', function() {
OC.addScript('contacts', 'storage', function() {
$.when(self._getTemplate()).then(function($tmpl) {
self.$template = $tmpl;
if(self.$dialog) {
self.$dialog.ocdialog('close');
}
self.$dialog = self.$template.octemplate({
selectText: t('contacts', 'Please choose the addressbook'),
defaultText: t('contacts', 'Import into...')
});
return false;
}
}
$('#newaddressbook').attr('readonly', 'readonly');
$('#contacts').attr('disabled', 'disabled');
var progresskey = $('#progresskey').val();
$.post(OC.filePath('contacts', '', 'import.php') + '?progresskey='+progresskey, {method: String (method), addressbookname: String (addressbookname), path: String (path), file: String (filename), id: String (addressbookid)}, function(jsondata){
if(jsondata.status == 'success'){
$('#progressbar').progressbar('option', 'value', 100);
$('#import_done').find('p').html(t('contacts', 'Result: ') + jsondata.data.imported + t('contacts', ' imported, ') + jsondata.data.failed + t('contacts', ' failed.'));
} else {
$('#import_done').find('p').html(jsondata.message);
}
$('#import_done').show().find('p').addClass('bold');
$('#progressbar').fadeOut('slow');
self.$dialog.appendTo($('body'));
self.addressBooks = new OC.Contacts.AddressBookList(
new OC.Contacts.Storage(), self.$dialog, null, true
);
self.showDialog();
})
.fail(function() {
alert(t('contacts', 'Error loading import template'));
});
})
.fail(function(jqxhr, settings, exception) {
console.warn('Error loading storage backend', jqxhr, settings, exception);
});
$('#form_container').css('display', 'none');
$('#progressbar_container').css('display', 'block');
window.setTimeout('Contacts_Import.getimportstatus(\'' + progresskey + '\')', 500);
});
$('#contacts').change(function(){
if($('#contacts option:selected').val() == 'newaddressbook'){
$('#newaddressbookform').slideDown('slow');
}else{
$('#newaddressbookform').slideUp('slow');
}
})
.fail(function(jqxhr, settings, exception) {
console.warn('Error loading address book backend', jqxhr, settings, exception);
});
},
getimportstatus: function(progresskey){
$.get(OC.filePath('contacts', '', 'import.php') + '?progress=1&progresskey=' + progresskey, function(percent){
$('#progressbar').progressbar('option', 'value', parseInt(percent));
if(percent < 100){
window.setTimeout('Contacts_Import.getimportstatus(\'' + progresskey + '\')', 500);
}else{
$('#import_done').css('display', 'block');
showDialog:function() {
var self = this;
$.when(self.addressBooks.loadAddressBooks()).then(function(response) {
if(!response.error) {
self.$dialog.ocdialog({
modal: true,
title: t('contacts', 'Import contacts'),
close: function() {
$(this).ocdialog('destroy').remove();
self.$dialog = null;
}
});
self.$importIntoSelect = self.$dialog.find('#import_into');
self.$importIntoSelect.on('change', function() {
var $selected = $(this).find('option:selected');
if($(this).val() === '-1') {
self.$dialog.ocdialog('option', 'buttons', []);
} else {
self.$dialog.ocdialog('option', 'buttons', [{
text: t('contacts', 'Import'),
defaultButton: true,
click:function() {
console.log('Selected', $selected);
self.$dialog.ocdialog('option', {
buttons: [],
closeButton: false,
title: t('contacts', 'Importing...')
});
self.startImport($selected.data('backend'), $selected.val());
}
}]);
}
});
} else {
console.warn('response.message');
}
})
.fail(function(response) {
console.warn(response);
});
}
};
var openContact = function(id) {
if(typeof OC.Contacts !== 'undefined') {
OC.Contacts.openContact(id);
} else {
window.location.href = OC.linkTo('contacts', 'index.php') + '#' + id;
},
startImport: function(backend, addressBookId) {
var self = this;
$('.import-select').hide();
$('.import-status').show();
$.when(self.addressBooks.prepareImport(backend, addressBookId, this.path, this.fileName))
.then(function(response) {
if(!response.error) {
$.when(self.addressBooks.doImport(response)).then(function(response) {
self.$dialog.ocdialog('option', {
title: t('contacts', 'Import done'),
closeButton: true,
buttons: [{
text: t('contacts', 'Close'),
defaultButton: true,
click:function() {
self.$dialog.ocdialog('close');
}
}]
});
})
.fail(function(response) {
console.warn(response);
});
} else {
console.warn('response.message');
}
})
.fail(function(response) {
console.warn(response);
});
},
_getTemplate: function() {
var defer = $.Deferred(), self = this;
if(!this.$template) {
var self = this;
$.get(OC.filePath('contacts', 'templates', 'importdialog.html'), function(tmpl) {
defer.resolve($(tmpl));
})
.fail(function() {
defer.reject();
});
} else {
defer.resolve(this.$template);
}
return defer.promise();
}
};
$(document).ready(function(){
$(document).bind('status.contacts.error', function(e, data) {
console.warn(data.message);
//console.trace();
//OC.notify({message:data.message});
});
if(typeof FileActions !== 'undefined'){
FileActions.register('text/vcard','importaddressbook', OC.PERMISSION_READ, '', Contacts_Import.importdialog);
FileActions.register('text/vcard','importaddressbook', OC.PERMISSION_READ, '', OC.ContactsImporter.init);
FileActions.setDefault('text/vcard','importaddressbook');
FileActions.register('text/x-vcard','importaddressbook', OC.PERMISSION_READ, '', Contacts_Import.importdialog);
FileActions.register('text/x-vcard','importaddressbook', OC.PERMISSION_READ, '', OC.ContactsImporter.init);
FileActions.setDefault('text/x-vcard','importaddressbook');
}
});

View File

@ -27,7 +27,7 @@ OC.Contacts = OC.Contacts || {};
}
}
}
}
};
/**
* An object for saving contact data to backends
@ -43,7 +43,11 @@ OC.Contacts = OC.Contacts || {};
*/
var Storage = function(user) {
this.user = user ? user : OC.currentUser;
}
};
Storage.prototype.formatResponse = function(response, jqXHR) {
return new JSONResponse(response, jqXHR);
};
/**
* Get all address books registered for this user.
@ -62,7 +66,7 @@ OC.Contacts = OC.Contacts || {};
'GET',
{}
);
}
};
/**
* Add an address book to a specific backend
@ -88,7 +92,7 @@ OC.Contacts = OC.Contacts || {};
{backend: 'local'},
parameters
);
}
};
/**
* Update an address book in a specific backend
@ -115,7 +119,7 @@ OC.Contacts = OC.Contacts || {};
{backend: backend, addressbookid: addressbookid},
properties
);
}
};
/**
* Delete an address book from a specific backend
@ -130,7 +134,7 @@ OC.Contacts = OC.Contacts || {};
'DELETE',
{backend: backend, addressbookid: addressbookid}
);
}
};
/**
* (De)active an address book from a specific backend
@ -147,7 +151,7 @@ OC.Contacts = OC.Contacts || {};
{backend: backend, addressbookid: addressbookid},
{state: state}
);
}
};
/**
* Get contacts from an address book from a specific backend
@ -178,7 +182,7 @@ OC.Contacts = OC.Contacts || {};
verb,
{backend: backend, addressbookid: addressbookid}
);
}
};
/**
* Add a contact to an address book from a specific backend
@ -205,7 +209,7 @@ OC.Contacts = OC.Contacts || {};
'POST',
{backend: backend, addressbookid: addressbookid}
);
}
};
/**
* Delete a contact from an address book from a specific backend
@ -238,7 +242,7 @@ OC.Contacts = OC.Contacts || {};
{backend: backend, addressbookid: addressbookid},
{contacts: contactids}
);
}
};
/**
* Move a contact to an address book from a specific backend
@ -255,7 +259,7 @@ OC.Contacts = OC.Contacts || {};
{backend: backend, addressbookid: addressbookid, contactid: contactid},
target
);
}
};
/**
* Get Image instance for a contacts profile picture
@ -292,7 +296,7 @@ OC.Contacts = OC.Contacts || {};
});
});
return defer.promise();
}
};
/**
* Get Image instance for a contacts profile picture
@ -331,7 +335,7 @@ OC.Contacts = OC.Contacts || {};
});
});
return defer.promise();
}
};
/**
* Get Image instance for default profile picture
@ -357,7 +361,7 @@ OC.Contacts = OC.Contacts || {};
} else {
return this.defaultPhoto;
}
}
};
/**
* Delete a single property.
@ -377,7 +381,7 @@ OC.Contacts = OC.Contacts || {};
{backend: backend, addressbookid: addressbookid, contactid: contactid},
params
);
}
};
/**
* Save a property.
@ -399,7 +403,7 @@ OC.Contacts = OC.Contacts || {};
{backend: backend, addressbookid: addressbookid, contactid: contactid},
params
);
}
};
/**
* Save all properties. Used when merging contacts.
@ -417,7 +421,7 @@ OC.Contacts = OC.Contacts || {};
{backend: backend, addressbookid: addressbookid, contactid: contactid},
params
);
}
};
/**
* Get all groups for this user.
@ -439,7 +443,7 @@ OC.Contacts = OC.Contacts || {};
'GET',
{}
);
}
};
/**
* Add a group
@ -459,7 +463,7 @@ OC.Contacts = OC.Contacts || {};
{},
{name: name}
);
}
};
/**
* Delete a group
@ -473,7 +477,7 @@ OC.Contacts = OC.Contacts || {};
{},
{name: name}
);
}
};
/**
* Rename a group
@ -488,7 +492,7 @@ OC.Contacts = OC.Contacts || {};
{},
{from: from, to: to}
);
}
};
/**
* Add contacts to a group
@ -503,7 +507,7 @@ OC.Contacts = OC.Contacts || {};
{categoryid: categoryid},
{contactids: contactids, name: categoryname}
);
}
};
/**
* Remove contacts from a group
@ -518,7 +522,7 @@ OC.Contacts = OC.Contacts || {};
{categoryid: categoryid},
{contactids: contactids, name: categoryname}
);
}
};
/**
* Set a user preference
@ -533,7 +537,17 @@ OC.Contacts = OC.Contacts || {};
{},
{key: key, value:value}
);
}
};
Storage.prototype.prepareImport = function(backend, addressbookid, params) {
console.log('Storage.prepareImport', backend, addressbookid);
return this.requestRoute(
'contacts_import_prepare',
'POST',
{backend: backend, addressbookid: addressbookid},
params
);
};
Storage.prototype.startImport = function(backend, addressbookid, params) {
console.log('Storage.startImport', backend, addressbookid);
@ -543,7 +557,7 @@ OC.Contacts = OC.Contacts || {};
{backend: backend, addressbookid: addressbookid},
params
);
}
};
Storage.prototype.importStatus = function(backend, addressbookid, params) {
return this.requestRoute(
@ -552,7 +566,7 @@ OC.Contacts = OC.Contacts || {};
{backend: backend, addressbookid: addressbookid},
params
);
}
};
Storage.prototype.requestRoute = function(route, type, routeParams, params, dontCache) {
var isJSON = (typeof params === 'string');
@ -590,7 +604,7 @@ OC.Contacts = OC.Contacts || {};
});
return defer.promise();
}
};
OC.Contacts.Storage = Storage;

View File

@ -102,6 +102,47 @@ class ImportController extends BaseController {
return $response;
}
/**
* @IsAdminExemption
* @IsSubAdminExemption
* @Ajax
*/
public function prepare() {
$request = $this->request;
$params = $this->request->urlParams;
$response = new JSONResponse();
$filename = $request->post['filename'];
$path = $request->post['path'];
$view = \OCP\Files::getStorage('contacts');
if(!$view->file_exists('imports')) {
$view->mkdir('imports');
}
$proxyStatus = \OC_FileProxy::$enabled;
\OC_FileProxy::$enabled = false;
$content = \OC_Filesystem::file_get_contents($path . '/' . $filename);
if($view->file_put_contents('/imports/' . $filename, $content)) {
\OC_FileProxy::$enabled = $proxyStatus;
$count = substr_count($content, 'BEGIN:');
$progresskey = 'contacts-import-' . rand();
$response->setParams(
array(
'filename'=>$filename,
'count' => $count,
'progresskey' => $progresskey,
'backend' => $params['backend'],
'addressbookid' => $params['addressbookid']
)
);
\OC_Cache::set($progresskey, '10', 300);
} else {
\OC_FileProxy::$enabled = $proxyStatus;
$response->bailOut(App::$l10n->t('Error moving file to imports folder.'));
}
return $response;
}
/**
* @IsAdminExemption
* @IsSubAdminExemption

View File

@ -0,0 +1,20 @@
<div id="contacts_import_dialog">
<div class="import-select">
<p class="bold" style="text-align:center;">{selectText}</p>
<select style="width:100%;" id="import_into" name="addressbooks">
<option value="{id}" data-backend="{backend}" data-permissions="{permissions}">{displayname}</option>
<option value="-1">{defaultText}</option>
</select>
<div id="newaddressbookform" style="display: none;">
<input type="text" style="width: 97%;" placeholder="<?php echo $l->t('Name of new addressbook'); ?>" id="newaddressbook" name="newaddressbook">
</div>
</div>
<div class="import-status hidden">
<label id="import-status-text"></label>
<div id="import-status-progress"></div>
<div id="import_done" style="display: none;">
<p style="text-align:center;"></p>
<input type="button" value="<?php echo $l->t('Close'); ?>" id="import_done_button">
</div>
</div>
</div>