From 3b0b5a5c0b47432e4c7e8a25343d9812ac5f0722 Mon Sep 17 00:00:00 2001 From: Christoph Haas Date: Sat, 30 Mar 2013 13:55:18 +0000 Subject: [PATCH] merged 2.0 branch --- build.xml | 11 +- changelog.txt | 24 +- config.php | 4 + index.html | 124 - js/ABOUT.js | 52 +- js/data/ResponseHandler.js | 57 +- js/data/timezones.js | 37 +- js/dialogs/ImportContentPanel.js | 46 +- js/dialogs/ImportPanel.js | 467 ++- js/plugin.calendarimporter.js | 166 +- js/timezone-js/Jakefile | 87 - js/timezone-js/README.md | 192 - js/timezone-js/fleegix.js | 1894 ---------- js/timezone-js/package.json | 31 - js/timezone-js/spec/date.spec.js | 466 --- js/timezone-js/spec/test-utils.js | 86 - js/timezone-js/spec/tz.async.spec.js | 37 - js/timezone-js/spec/tz.default.spec.js | 15 - js/timezone-js/spec/tz.manual.spec.js | 25 - js/timezone-js/spec/tz.preload.spec.js | 23 - js/timezone-js/spec/tz.sync.spec.js | 176 - js/timezone-js/src/date.js | 993 ----- js/timezone-js/src/node-preparse.js | 56 - js/timezone-js/src/preparse.js | 65 - js/timezone-js/src/strip_olson_comments.rb | 30 - manifest.xml | 12 +- php/download.php | 21 + php/ical/calendar - Kopie.txt | 216 -- php/ical/calendar.txt | 33 - php/ical/class.icalcreator.php | 774 ++-- php/ical/class.icalparser.php | 152 +- ...lendarexporter.php => module.calendar.php} | 268 +- php/plugin.calendarimporter.php | 3 +- php/upload.php | 92 +- resources/images/import_icon.png | Bin 3153 -> 3100 bytes resources/images/import_icon.xcf | Bin 0 -> 11213 bytes resources/tz/africa | 1181 ------ resources/tz/antarctica | 413 --- resources/tz/asia | 2717 -------------- resources/tz/australasia | 1719 --------- resources/tz/backward | 117 - resources/tz/etcetera | 81 - resources/tz/europe | 2856 --------------- resources/tz/factory | 10 - resources/tz/iso3166.tab | 276 -- resources/tz/leapseconds | 100 - resources/tz/northamerica | 3235 ----------------- resources/tz/pacificnew | 28 - resources/tz/solar87 | 390 -- resources/tz/solar88 | 390 -- resources/tz/solar89 | 395 -- resources/tz/southamerica | 1711 --------- resources/tz/systemv | 38 - resources/tz/yearistype.sh | 38 - resources/tz/zone.tab | 441 --- 55 files changed, 1510 insertions(+), 21361 deletions(-) delete mode 100644 index.html delete mode 100644 js/timezone-js/Jakefile delete mode 100644 js/timezone-js/README.md delete mode 100644 js/timezone-js/fleegix.js delete mode 100644 js/timezone-js/package.json delete mode 100644 js/timezone-js/spec/date.spec.js delete mode 100644 js/timezone-js/spec/test-utils.js delete mode 100644 js/timezone-js/spec/tz.async.spec.js delete mode 100644 js/timezone-js/spec/tz.default.spec.js delete mode 100644 js/timezone-js/spec/tz.manual.spec.js delete mode 100644 js/timezone-js/spec/tz.preload.spec.js delete mode 100644 js/timezone-js/spec/tz.sync.spec.js delete mode 100644 js/timezone-js/src/date.js delete mode 100644 js/timezone-js/src/node-preparse.js delete mode 100644 js/timezone-js/src/preparse.js delete mode 100644 js/timezone-js/src/strip_olson_comments.rb delete mode 100644 php/ical/calendar - Kopie.txt delete mode 100644 php/ical/calendar.txt rename php/{module.calendarexporter.php => module.calendar.php} (57%) create mode 100644 resources/images/import_icon.xcf delete mode 100644 resources/tz/africa delete mode 100644 resources/tz/antarctica delete mode 100644 resources/tz/asia delete mode 100644 resources/tz/australasia delete mode 100644 resources/tz/backward delete mode 100644 resources/tz/etcetera delete mode 100644 resources/tz/europe delete mode 100644 resources/tz/factory delete mode 100644 resources/tz/iso3166.tab delete mode 100644 resources/tz/leapseconds delete mode 100644 resources/tz/northamerica delete mode 100644 resources/tz/pacificnew delete mode 100644 resources/tz/solar87 delete mode 100644 resources/tz/solar88 delete mode 100644 resources/tz/solar89 delete mode 100644 resources/tz/southamerica delete mode 100644 resources/tz/systemv delete mode 100644 resources/tz/yearistype.sh delete mode 100644 resources/tz/zone.tab diff --git a/build.xml b/build.xml index 367e265..db4f49a 100644 --- a/build.xml +++ b/build.xml @@ -1,7 +1,6 @@ - - + @@ -87,7 +86,7 @@ - + @@ -97,14 +96,13 @@ - + - @@ -148,7 +146,6 @@ var Ext = {}; var Zarafa = {}; - var timezoneJS = {}; var container = {}; var _ = function(key, domain) {}; var dgettext = function(domain, msgid) {}; @@ -242,8 +239,6 @@ - - diff --git a/changelog.txt b/changelog.txt index 2b9214e..552b9ed 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,6 +1,24 @@ -calendarimporter 1.1, 26.02.2013: - - daylight saving time - - webapp 1.3 about text added +calendarimporter 2.0.2: + - fixed crash when public store does not exist + - check if temporary directory is writeable + - disabled display_error with ini_set + +calendarimporter 2.0.1: + - removed debug line "utc = true;" + - Fixed problems with colons in value fields (improved regex) + - minor fixes/improvements + +calendarimporter 2.0: + - updated iCalcreator to 2.16.12 + - fixed exporter problem: now you can export more than 50 events + - fixed button visibility for attachment importing + - minor fixes/improvements + +calendarimporter 2.0b: + - Completely rewritten timezone management + - Import of iCal attachments possible + - webapp 1.3 about page added + - bugfixes calendarimporter 1.2: - New timezone management diff --git a/config.php b/config.php index c03312e..88cf48c 100644 --- a/config.php +++ b/config.php @@ -6,4 +6,8 @@ /** The default calendar to import to*/ define('PLUGIN_CALENDARIMPORTER_DEFAULT', "calendar"); + define('PLUGIN_CALENDARIMPORTER_DEFAULT_TIMEZONE', "Europe/Vienna"); + + /** Tempory path for uploaded files... */ + define('PLUGIN_CALENDARIMPORTER_TMP_UPLOAD', "/var/lib/zarafa-webapp/tmp/"); ?> diff --git a/index.html b/index.html deleted file mode 100644 index 93f96a6..0000000 --- a/index.html +++ /dev/null @@ -1,124 +0,0 @@ - - - - DST Calculator - - - - - - \ No newline at end of file diff --git a/js/ABOUT.js b/js/ABOUT.js index 15c8040..244bd6b 100644 --- a/js/ABOUT.js +++ b/js/ABOUT.js @@ -1,3 +1,25 @@ +/** + * ABOUT.js zarafa calender to ics im/exporter + * + * Author: Christoph Haas + * Copyright (C) 2012-2013 Christoph Haas + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + Ext.namespace('Zarafa.plugins.calendarimporter'); /** @@ -9,28 +31,36 @@ Ext.namespace('Zarafa.plugins.calendarimporter'); Zarafa.plugins.calendarimporter.ABOUT = "" + "

Copyright (C) 2012-2013 Christoph Haas <christoph.h@sprinternet.at>

" - + "

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

" + + "

This program is free software; you can redistribute it and/or " + + "modify it under the terms of the GNU Lesser General Public " + + "License as published by the Free Software Foundation; either " + + "version 2.1 of the License, or (at your option) any later version.

" - + "

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

" + + "

This program 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 " + + "Lesser General Public License for more details.

" + + + "

You should have received a copy of the GNU Lesser General Public " + + "License along with this program; if not, write to the Free Software " + + "Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

" - + "

THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

" - + "
" + "

The calendarimporter plugin contains the following third-party components:

" - + "

TimezoneJS.Date

" + + "

iCalcreator v2.16.12

" - + "

Copyright 2010 Matthew Eernisse <mde@fleegix.org> and Open Source Applications Foundation.

" + + "

Copyright 2007-2013 Kjell-Inge Gustafsson kigkonsult

" - + "

Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0

" + + "

This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.

" - + "

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

" + + "

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 Lesser General Public License for more details.

" - + "

Fleegix.js JavaScript Toolkit

" + + "

Ics-parser

" - + "

Copyright 2002-2007 Matthew Eernisse <mde@fleegix.org> and Open Source Applications Foundation.

" + + "

Copyright 2002-2007 Martin Thoma

" - + "

Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0

" + + "

Licensed under the MIT License.

" + "

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

" \ No newline at end of file diff --git a/js/data/ResponseHandler.js b/js/data/ResponseHandler.js index 9595b6c..a155466 100644 --- a/js/data/ResponseHandler.js +++ b/js/data/ResponseHandler.js @@ -1,11 +1,29 @@ +/** + * ResponseHandler.js zarafa calender to ics im/exporter + * + * Author: Christoph Haas + * Copyright (C) 2012-2013 Christoph Haas + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + /** * ResponseHandler * * This class handles all responses from the php backend - * - * @author Christoph Haas - * @modified 29.12.2012 - * @license http://www.opensource.org/licenses/mit-license.php MIT License */ Ext.namespace('Zarafa.plugins.calendarimporter.data'); @@ -13,7 +31,7 @@ Ext.namespace('Zarafa.plugins.calendarimporter.data'); * @class Zarafa.plugins.calendarimporter.data.ResponseHandler * @extends Zarafa.plugins.calendarimporter.data.AbstractResponseHandler * - * Export specific response handler. + * Calendar specific response handler. */ Zarafa.plugins.calendarimporter.data.ResponseHandler = Ext.extend(Zarafa.core.data.AbstractResponseHandler, { /** @@ -21,13 +39,12 @@ Zarafa.plugins.calendarimporter.data.ResponseHandler = Ext.extend(Zarafa.core.da * will be called after success request. */ successCallback : null, - + /** * Call the successCallback callback function. * @param {Object} response Object contained the response data. */ - doExport : function(response) - { + doExport : function(response) { this.successCallback(response); }, @@ -35,8 +52,23 @@ Zarafa.plugins.calendarimporter.data.ResponseHandler = Ext.extend(Zarafa.core.da * Call the successCallback callback function. * @param {Object} response Object contained the response data. */ - doList : function(response) - { + doList : function(response) { + this.successCallback(response); + }, + + /** + * Call the successCallback callback function. + * @param {Object} response Object contained the response data. + */ + doImport : function(response) { + this.successCallback(response); + }, + + /** + * Call the successCallback callback function. + * @param {Object} response Object contained the response data. + */ + doAttachmentpath : function(response) { this.successCallback(response); }, @@ -45,10 +77,9 @@ Zarafa.plugins.calendarimporter.data.ResponseHandler = Ext.extend(Zarafa.core.da * exception response with the code of exception. * @param {Object} response Object contained the response data. */ - doError: function(response) - { + doError: function(response) { alert("error response code: " + response.error.info.code); } }); -Ext.reg('calendarimporter.calendarexporterresponsehandler', Zarafa.plugins.calendarimporter.data.ResponseHandler); \ No newline at end of file +Ext.reg('calendarimporter.calendarresponsehandler', Zarafa.plugins.calendarimporter.data.ResponseHandler); \ No newline at end of file diff --git a/js/data/timezones.js b/js/data/timezones.js index 778f328..9fb34c7 100644 --- a/js/data/timezones.js +++ b/js/data/timezones.js @@ -1,13 +1,30 @@ +/** + * timezones.js zarafa calender to ics im/exporter + * + * Author: Christoph Haas + * Copyright (C) 2012-2013 Christoph Haas + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + /** * Timezone class * * This class can handle all our timezone operations and conversions. - * - * @author Christoph Haas - * @modified 29.12.2012 - * @license http://www.opensource.org/licenses/mit-license.php MIT License - */ - + */ Ext.namespace("Zarafa.plugins.calendarimporter.data"); Zarafa.plugins.calendarimporter.data.Timezones = Ext.extend(Object, { @@ -81,7 +98,7 @@ Zarafa.plugins.calendarimporter.data.Timezones = Ext.extend(Object, { ['Pacific/Chatham','(UTC +12:45) Chatham', 765], ['Pacific/Enderbury','(UTC +13:00) Enderbury, Tongatapu', 780], ['Pacific/Apia','(UTC +13:00) Apia', 780], - ['Pacific/Kiritimati','(UTC +14:00) Kiritimati', 840] + ['Pacific/Kiritimati','(UTC +14:00) Kiritimati', 840] ], /* map all citys to the above timezones */ @@ -725,7 +742,7 @@ Zarafa.plugins.calendarimporter.data.Timezones = Ext.extend(Object, { /*+14:00*/ 'Etc/GMT-14' : 'Pacific/Kiritimati', 'Pacific/Fakaofo' : 'Pacific/Kiritimati', - 'Pacific/Kiritimati' : 'Pacific/Kiritimati' + 'Pacific/Kiritimati' : 'Pacific/Kiritimati' }, /* return unmapped timezone... */ @@ -744,10 +761,6 @@ Zarafa.plugins.calendarimporter.data.Timezones = Ext.extend(Object, { } return 0; // no offset found... - }, - - getDstOffset: function(time, timezone) { - return 0; // no offset } }); diff --git a/js/dialogs/ImportContentPanel.js b/js/dialogs/ImportContentPanel.js index 16667d1..84e6961 100644 --- a/js/dialogs/ImportContentPanel.js +++ b/js/dialogs/ImportContentPanel.js @@ -1,11 +1,29 @@ +/** + * ImportContentPanel.js zarafa calender to ics im/exporter + * + * Author: Christoph Haas + * Copyright (C) 2012-2013 Christoph Haas + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + /** * ImportContentPanel * * Container for the importpanel. - * - * @author Christoph Haas - * @modified 29.12.2012 - * @license http://www.opensource.org/licenses/mit-license.php MIT License */ Ext.namespace("Zarafa.plugins.calendarimporter.dialogs"); @@ -22,25 +40,23 @@ Zarafa.plugins.calendarimporter.dialogs.ImportContentPanel = Ext.extend(Zarafa.c * @constructor * @param config Configuration structure */ - constructor : function(config) - { + constructor : function(config) { config = config || {}; - var title = _('Import Calendar File'); if(container.getSettingsModel().get("zarafa/v1/plugins/calendarimporter/enable_export")){ title = _('Import/Export Calendar File'); } - Ext.applyIf(config, { - layout : 'fit', - title : title, - closeOnSave : true, - width : 400, - height : 300, + layout : 'fit', + title : title, + closeOnSave : true, + width : 620, + height : 465, //Add panel - items : [ + items : [ { - xtype : 'calendarimporter.importpanel' + xtype : 'calendarimporter.importpanel', + filename : config.filename } ] }); diff --git a/js/dialogs/ImportPanel.js b/js/dialogs/ImportPanel.js index bee7b1d..10cf38f 100644 --- a/js/dialogs/ImportPanel.js +++ b/js/dialogs/ImportPanel.js @@ -1,11 +1,29 @@ +/** + * ImportPanel.js zarafa calender to ics im/exporter + * + * Author: Christoph Haas + * Copyright (C) 2012-2013 Christoph Haas + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + /** * ImportPanel * * The main Panel of the calendarimporter plugin. - * - * @author Christoph Haas - * @modified 30.12.2012 - * @license http://www.opensource.org/licenses/mit-license.php MIT License */ Ext.namespace("Zarafa.plugins.calendarimporter.dialogs"); @@ -18,11 +36,23 @@ Zarafa.plugins.calendarimporter.dialogs.ImportPanel = Ext.extend(Ext.Panel, { /* store the imported timezone here... */ timezone: null, - /* store the imported timezone here... */ - dst: true, + /* ignore daylight saving time... */ + ignoredst: null, - /* keep the parsed result here, for timezone changes... */ - parsedresult: null, + /* path to ics file on server... */ + icsfile: null, + + /* loadmask for timezone/dst changes... */ + loadMask: null, + + /* export event buffer */ + exportResponse: new Array(), + + /* how many requests are still running? */ + runningRequests: null, + + /* The store for the selection grid */ + store: null, /** * The internal 'iframe' which is hidden from the user, which is used for downloading @@ -30,23 +60,47 @@ Zarafa.plugins.calendarimporter.dialogs.ImportPanel = Ext.extend(Ext.Panel, { * @property * @type Ext.Element */ - downloadFrame : undefined, + downloadFrame : undefined, /** * @constructor * @param {object} config */ - constructor : function (config) - { + constructor : function (config) { config = config || {}; var self = this; + this.timezone = container.getSettingsModel().get("zarafa/v1/plugins/calendarimporter/default_timezone"); + + if(typeof config.filename !== "undefined") { + this.icsfile = config.filename; + } + + // create the data store + this.store = new Ext.data.ArrayStore({ + fields: [ + {name: 'title'}, + {name: 'start'}, + {name: 'end'}, + {name: 'location'}, + {name: 'description'}, + {name: 'priority'}, + {name: 'label'}, + {name: 'busy'}, + {name: 'privatestate'}, + {name: 'organizer'}, + {name: 'trigger'} + ] + }); + Ext.apply(config, { xtype : 'calendarimporter.importpanel', + ref : "importpanel", + id : "importpanel", layout : { type : 'form', align : 'stretch' }, - anchor : '100%', + anchor : '100%', bodyStyle : 'background-color: inherit;', defaults : { border : true, @@ -56,16 +110,36 @@ Zarafa.plugins.calendarimporter.dialogs.ImportPanel = Ext.extend(Ext.Panel, { this.createSelectBox(), this.createTimezoneBox(), this.createDaylightSavingCheckBox(), - this.initForm() + this.initForm(), + this.createGrid() ], buttons: [ this.createExportAllButton(), this.createSubmitAllButton(), this.createSubmitButton(), this.createCancelButton() - ] + ], + listeners: { + afterrender: function (cmp) { + Ext.getCmp('importbutton').disable(); + this.loadMask = new Ext.LoadMask(Ext.getCmp("importpanel").getEl(), {msg:'Loading...'}); + + if(this.icsfile != null) { // if we have got the filename from an attachment + this.parseCalendar(this.icsfile, this.timezone, this.ignoredst); + } + }, + close: function (cmp) { + Ext.getCmp('importbutton').enable(); + }, + hide: function (cmp) { + Ext.getCmp('importbutton').enable(); + }, + destroy: function (cmp) { + Ext.getCmp('importbutton').enable(); + } + } }); - + Zarafa.plugins.calendarimporter.dialogs.ImportPanel.superclass.constructor.call(this, config); }, @@ -74,8 +148,7 @@ Zarafa.plugins.calendarimporter.dialogs.ImportPanel = Ext.extend(Ext.Panel, { * posted and contains the attachments * @private */ - initForm : function () - { + initForm : function () { return { xtype: 'form', ref: 'addFormPanel', @@ -95,139 +168,72 @@ Zarafa.plugins.calendarimporter.dialogs.ImportPanel = Ext.extend(Ext.Panel, { }, /** - * Init embedded form, this is the form that is - * posted and contains the attachments + * Reloads the data of the grid * @private */ - createGrid : function(eventdata) { - - /* remove the grid if it already exists because of an old calendar file */ - this.remove("eventgrid"); - + reloadGridStore: function(eventdata) { var parsedData = []; - /* this is used to get rid of the local timezone... */ - var local_tz_offset = new Date().getTimezoneOffset() * 60; // getTimezoneOffset returns minutes... we need milliseconds - var tz_offset = local_tz_offset; + // this is done to get rid of the local browser timezone.... + // because all timezone specific stuff is done via php + var local_tz_offset = new Date().getTimezoneOffset() * 60000; // getTimezoneOffset returns minutes... we need milliseconds - if(this.timezone != null) { - tz_offset = Zarafa.plugins.calendarimporter.data.Timezones.getOffset(this.timezone); - } if(eventdata !== null) { parsedData = new Array(eventdata.events.length); var i = 0; for(i = 0; i < eventdata.events.length; i++) { var trigger = null; - var dtrigger = null; if(eventdata.events[i]["VALARM"]) { trigger = eventdata.events[i]["VALARM"]["TRIGGER"]; - dtrigger = new timezoneJS.Date(parseInt(trigger) + local_tz_offset + tz_offset, "Etc/UTC"); - if(typeof this.timezone !== "undefined" && this.timezone !== null) { - dtrigger.setTimezone(this.timezone); - var realtzoffset = dtrigger.getTimezoneOffset() * 60; - dtrigger = new timezoneJS.Date(parseInt(trigger) + local_tz_offset + realtzoffset, this.timezone); - } + trigger = new Date(parseInt(trigger) + local_tz_offset); } - - var dstart = new timezoneJS.Date(parseInt(eventdata.events[i]["DTSTART"]) + local_tz_offset + tz_offset, "Etc/UTC"); - var dend = new timezoneJS.Date(parseInt(eventdata.events[i]["DTEND"]) + local_tz_offset + tz_offset, "Etc/UTC"); - - - if(typeof this.timezone !== "undefined" && this.timezone !== null) { - dstart.setTimezone(this.timezone); - dend.setTimezone(this.timezone); - - dstart = new Date(dstart.getUTCTime() + local_tz_offset + tz_offset); - dend = new Date(dend.getUTCTime() + local_tz_offset + tz_offset); - } - console.log(this.timezone); - console.log(dstart); - - parsedData[i] = new Array(eventdata.events[i]["SUMMARY"], dstart, dend, eventdata.events[i]["LOCATION"], eventdata.events[i]["DESCRIPTION"],eventdata.events[i]["PRIORITY"],eventdata.events[i]["X-ZARAFA-LABEL"],eventdata.events[i]["X-MICROSOFT-CDO-BUSYSTATUS"],eventdata.events[i]["CLASS"],eventdata.events[i]["ORGANIZER"], dtrigger); + parsedData[i] = new Array(eventdata.events[i]["SUMMARY"], new Date(parseInt(eventdata.events[i]["DTSTART"]) + local_tz_offset), new Date(parseInt(eventdata.events[i]["DTEND"]) + local_tz_offset), eventdata.events[i]["LOCATION"], eventdata.events[i]["DESCRIPTION"],eventdata.events[i]["PRIORITY"],eventdata.events[i]["X-ZARAFA-LABEL"],eventdata.events[i]["X-MICROSOFT-CDO-BUSYSTATUS"],eventdata.events[i]["CLASS"],eventdata.events[i]["ORGANIZER"],trigger); } } else { return null; } - // create the data store - var store = new Ext.data.ArrayStore({ - fields: [ - {name: 'title'}, - {name: 'start'}, - {name: 'end'}, - {name: 'location'}, - {name: 'description'}, - {name: 'priority'}, - {name: 'label'}, - {name: 'busy'}, - {name: 'privatestate'}, - {name: 'organizer'}, - {name: 'trigger'} - ], - data: parsedData - }); - + this.store.loadData(parsedData, false); + }, + + /** + * Init embedded form, this is the form that is + * posted and contains the attachments + * @private + */ + createGrid : function() { return { xtype: 'grid', ref: 'eventgrid', id: 'eventgrid', columnWidth: 1.0, - store: store, + store: this.store, width: '100%', height: 300, title: 'Select events to import', - frame: true, + frame: false, + viewConfig:{ + forceFit:true + }, colModel: new Ext.grid.ColumnModel({ defaults: { width: 300, sortable: true }, columns: [ - {id: 'Summary', header: 'Title', width: 300, sortable: true, dataIndex: 'title'}, - { - header: 'Start', - width: 150, - sortable: true, - dataIndex: 'start', - renderer : function(value, p, record) { - p.css = 'mail_date'; - - // # TRANSLATORS: See http://docs.sencha.com/ext-js/3-4/#!/api/Date for the meaning of these formatting instructions - return ((value !== null) && ((typeof value) == "object") && ((typeof value.getTime) == "function")) ? value.toString("yyyy-MM-dd HH:mm:ss Z") :_('None'); - } - }, - { - header: 'End', - width: 150, - sortable: true, - dataIndex: 'end', - renderer : function(value, p, record) { - p.css = 'mail_date'; - - // # TRANSLATORS: See http://docs.sencha.com/ext-js/3-4/#!/api/Date for the meaning of these formatting instructions - return ((value !== null) && ((typeof value) == "object") && ((typeof value.getTime) == "function")) ? value.toString("yyyy-MM-dd HH:mm:ss Z") :_('None'); - } - }, + {id: 'Summary', header: 'Title', width: 200, sortable: true, dataIndex: 'title'}, + {header: 'Start', width: 200, sortable: true, dataIndex: 'start', renderer : Zarafa.common.ui.grid.Renderers.datetime}, + {header: 'End', width: 200, sortable: true, dataIndex: 'end', renderer : Zarafa.common.ui.grid.Renderers.datetime}, {header: 'Location', width: 150, sortable: true, dataIndex: 'location'}, - {header: 'Description', width: 150, sortable: true, dataIndex: 'description'}, + {header: 'Description', sortable: true, dataIndex: 'description'}, {header: "Priority", dataIndex: 'priority', hidden: true}, {header: "Label", dataIndex: 'label', hidden: true}, {header: "Busystatus", dataIndex: 'busy', hidden: true}, {header: "Privacystatus", dataIndex: 'privatestate', hidden: true}, {header: "Organizer", dataIndex: 'organizer', hidden: true}, - { - header: "Alarm", - dataIndex: 'trigger', - hidden: true, - renderer : function(value, p, record) { - p.css = 'mail_date'; - - // # TRANSLATORS: See http://docs.sencha.com/ext-js/3-4/#!/api/Date for the meaning of these formatting instructions - return ((value !== null) && ((typeof value) == "object") && ((typeof value.getTime) == "function")) ? value.toString("yyyy-MM-dd HH:mm:ss Z") :_('None'); - } - } + {header: "Alarm", dataIndex: 'trigger', hidden: true, renderer : Zarafa.common.ui.grid.Renderers.datetime} ] }), sm: new Ext.grid.RowSelectionModel({multiSelect:true}) @@ -237,7 +243,7 @@ Zarafa.plugins.calendarimporter.dialogs.ImportPanel = Ext.extend(Ext.Panel, { createSelectBox: function() { var defaultFolder = container.getHierarchyStore().getDefaultFolder('calendar'); // @type: Zarafa.hierarchy.data.MAPIFolderRecord var subFolders = defaultFolder.getChildren(); - var myStore = []; + var myStore = []; /* add all local calendar folders */ var i = 0; @@ -249,12 +255,20 @@ Zarafa.plugins.calendarimporter.dialogs.ImportPanel = Ext.extend(Ext.Panel, { /* add all shared calendar folders */ var pubStore = container.getHierarchyStore().getPublicStore(); - var pubFolder = pubStore.getDefaultFolder("publicfolders"); - var pubSubFolders = pubFolder.getChildren(); - for(i = 0; i < pubSubFolders.length; i++) { - if(pubSubFolders[i].isContainerClass("IPF.Appointment")){ - myStore.push(new Array(pubSubFolders[i].getDisplayName(), pubSubFolders[i].getDisplayName() + " [Shared]", true)); // 3rd field = isPublicfolder + if(typeof pubStore !== "undefined") { + try { + var pubFolder = pubStore.getDefaultFolder("publicfolders"); + var pubSubFolders = pubFolder.getChildren(); + + for(i = 0; i < pubSubFolders.length; i++) { + if(pubSubFolders[i].isContainerClass("IPF.Appointment")){ + myStore.push(new Array(pubSubFolders[i].getDisplayName(), pubSubFolders[i].getDisplayName() + " [Shared]", true)); // 3rd field = isPublicfolder + } + } + } catch (e) { + console.log("Error opening the shared folder..."); + console.log(e); } } @@ -284,6 +298,7 @@ Zarafa.plugins.calendarimporter.dialogs.ImportPanel = Ext.extend(Ext.Panel, { id: 'timezoneselector', editable: false, name: "choosen_timezone", + value: Zarafa.plugins.calendarimporter.data.Timezones.unMap(container.getSettingsModel().get("zarafa/v1/plugins/calendarimporter/default_timezone")), width: 100, fieldLabel: "Select a timezone (optional)", store: Zarafa.plugins.calendarimporter.data.Timezones.store, @@ -307,7 +322,8 @@ Zarafa.plugins.calendarimporter.dialogs.ImportPanel = Ext.extend(Ext.Panel, { id: 'dstcheck', name: "dst_check", width: 100, - fieldLabel: "Ignore Daylight Saving Time (optional)", + fieldLabel: "Ignore DST (optional)", + boxLabel: 'This will ignore "Daylight saving time" offsets.', labelSeperator: ":", border: false, anchor: "100%", @@ -408,25 +424,22 @@ Zarafa.plugins.calendarimporter.dialogs.ImportPanel = Ext.extend(Ext.Panel, { */ onTimezoneSelected : function(combo, record, index) { this.timezone = record.data.field1; - - if(this.parsedresult != null) { - this.add(this.createGrid(this.parsedresult)); - this.doLayout(); + + if(this.icsfile != null) { + this.parseCalendar(this.icsfile, this.timezone, this.ignoredst); } }, /** * This is called when the dst checkbox has been selected - * @param {Ext.form.ComboBox} combo - * @param {Ext.data.Record} record - * @param {Number} index + * @param {Ext.form.CheckBox} combo + * @param {boolean} checked */ onDstChecked : function(checkbox, checked) { - this.dst = !checked; - - if(this.parsedresult != null) { - this.add(this.createGrid(this.parsedresult)); - this.doLayout(); + this.ignoredst = checked; + + if(this.icsfile != null) { + this.parseCalendar(this.icsfile, this.timezone, this.ignoredst); } }, @@ -435,7 +448,7 @@ Zarafa.plugins.calendarimporter.dialogs.ImportPanel = Ext.extend(Ext.Panel, { * in the {@link Ext.ux.form.FileUploadField} and the dialog is closed * @param {Ext.ux.form.FileUploadField} uploadField being added a file to */ - onFileSelected : function(uploadField) { + onFileSelected : function(uploadField) { var form = this.addFormPanel.getForm(); if (form.isValid()) { @@ -447,30 +460,64 @@ Zarafa.plugins.calendarimporter.dialogs.ImportPanel = Ext.extend(Ext.Panel, { Ext.getCmp('submitAllButton').disable(); Zarafa.common.dialogs.MessageBox.show({ title : _('Error'), - msg : _(action.result.errors[action.result.errors.type]), + msg : _(action.result.error), icon : Zarafa.common.dialogs.MessageBox.ERROR, buttons : Zarafa.common.dialogs.MessageBox.OK }); }, success: function(file, action){ uploadField.reset(); - Ext.getCmp('submitButton').enable(); - Ext.getCmp('submitAllButton').enable(); - this.parsedresult = action.result.response; + this.icsfile = action.result.ics_file; - if(this.timezone == null) {; - this.timezone = action.result.response.calendar["X-WR-TIMEZONE"]; - this.timezoneselector.setValue(Zarafa.plugins.calendarimporter.data.Timezones.unMap(this.timezone)); - } else { - this.timezone = this.timezoneselector.value; - } - this.add(this.createGrid(action.result.response)); - this.doLayout(); + this.parseCalendar(this.icsfile, this.timezone, this.ignoredst); }, scope : this }); } }, + + parseCalendar: function (icsPath, timezone, ignoredst) { + this.loadMask.show(); + // call export function here! + var responseHandler = new Zarafa.plugins.calendarimporter.data.ResponseHandler({ + successCallback: this.handleParsingResult.createDelegate(this) + }); + + container.getRequest().singleRequest( + 'calendarmodule', + 'import', + { + ics_filepath: icsPath, + timezone: timezone, + ignore_dst: ignoredst + }, + responseHandler + ); + }, + + handleParsingResult: function(response) { + this.loadMask.hide(); + + if(response["status"] == true) { + Ext.getCmp('submitButton').enable(); + Ext.getCmp('submitAllButton').enable(); + + if(typeof response.parsed.calendar["X-WR-TIMEZONE"] !== "undefined") {; + this.timezone = response.parsed.calendar["X-WR-TIMEZONE"]; + this.timezoneselector.setValue(Zarafa.plugins.calendarimporter.data.Timezones.unMap(this.timezone)); + } + this.reloadGridStore(response.parsed); + } else { + Ext.getCmp('submitButton').disable(); + Ext.getCmp('submitAllButton').disable(); + Zarafa.common.dialogs.MessageBox.show({ + title : _('Parser Error'), + msg : _(response["message"]), + icon : Zarafa.common.dialogs.MessageBox.ERROR, + buttons : Zarafa.common.dialogs.MessageBox.OK + }); + } + }, close: function () { this.addFormPanel.getForm().reset(); @@ -497,11 +544,11 @@ Zarafa.plugins.calendarimporter.dialogs.ImportPanel = Ext.extend(Ext.Panel, { var busystate = new Array("FREE", "TENTATIVE", "BUSY", "OOF"); var zlabel = new Array("NONE", "IMPORTANT", "WORK", "PERSONAL", "HOLIDAY", "REQUIRED", "TRAVEL REQUIRED", "PREPARATION REQUIERED", "BIRTHDAY", "SPECIAL DATE", "PHONE INTERVIEW"); - + /* optional fields */ if(entry.priority !== "") { newRecord.data.importance = entry.priority; - } + } if(entry.label !== "") { newRecord.data.label = zlabel.indexOf(entry.label); } @@ -540,7 +587,7 @@ Zarafa.plugins.calendarimporter.dialogs.ImportPanel = Ext.extend(Ext.Panel, { exportAllEvents: function () { //receive existing calendar store var calValue = this.calendarselector.value; - + if(calValue == undefined) { // no calendar choosen Zarafa.common.dialogs.MessageBox.show({ title : _('Error'), @@ -616,7 +663,7 @@ Zarafa.plugins.calendarimporter.dialogs.ImportPanel = Ext.extend(Ext.Panel, { // call export function here! var responseHandler = new Zarafa.plugins.calendarimporter.data.ResponseHandler({ - successCallback: this.exportDone.createDelegate(this) + successCallback: this.exportPagedEvents.createDelegate(this) }); container.getRequest().singleRequest( @@ -625,8 +672,10 @@ Zarafa.plugins.calendarimporter.dialogs.ImportPanel = Ext.extend(Ext.Panel, { { groupDir: "ASC", restriction: { - startdate: 0, - duedate: 2145826800 // 2037... nearly highest unix timestamp + //start: 0, + //limit: 500, // limit to 500 events.... not working because of hardcoded limit in listmodule + //startdate: 0, + //duedate: 2145826800 // 2037... nearly highest unix timestamp }, sort: [{ "field": "startdate", @@ -642,33 +691,97 @@ Zarafa.plugins.calendarimporter.dialogs.ImportPanel = Ext.extend(Ext.Panel, { }, /** - * Export done =) + * Calculate needed Requests for all events + * Needed because the listmodule has hardcoded pageing setting -.- * @param {Object} response - * @private */ - exportDone : function(response) { - if(response.item.length > 0) { - // call export function here! - var responseHandler = new Zarafa.plugins.calendarimporter.data.ResponseHandler({ - successCallback: this.downLoadICS.createDelegate(this) - }); - - container.getRequest().singleRequest( - 'calendarexportermodule', - 'export', - { - data: response, - calendar: this.calendarselector.value - }, - responseHandler - ); - container.getNotifier().notify('info', 'Exported', 'Found ' + response.item.length + ' entries to export.'); - } else { + exportPagedEvents:function(response) { + + if(response.page.start = 0 && response.item.length <= 0) { container.getNotifier().notify('info', 'Export Failed', 'There were no items to export!'); Zarafa.common.dialogs.MessageBox.hide(); + } else { + this.exportResponse = response.item; } - this.dialog.close(); - }, + + if(this.totalExportCount == null) { + this.totalExportCount = response.page.totalrowcount; + } + + var requests = Math.ceil(response.page.totalrowcount / response.page.rowcount); + this.runningRequests = requests; + + var i = 0; + + for(i = 0; i < requests; i++) { + var responseHandler = new Zarafa.plugins.calendarimporter.data.ResponseHandler({ + successCallback: this.storeResult.createDelegate(this) + }); + this.requestNext(responseHandler, response.page.rowcount *(i+1), response.page.rowcount); + } + }, + + /** + * Responsehandler for the single requests... will merge all events into one array + * @param {Object} response + */ + storeResult: function(response) { + var tmp = this.exportResponse; + + this.exportResponse = tmp.concat(response.item); + + if(this.runningRequests <= 1) { + // final request =) + var responseHandler = new Zarafa.plugins.calendarimporter.data.ResponseHandler({ + successCallback: this.downLoadICS.createDelegate(this) + }); + + container.getRequest().singleRequest( + 'calendarmodule', + 'export', + { + data: this.exportResponse, + calendar: this.calendarselector.value + }, + responseHandler + ); + container.getNotifier().notify('info', 'Exported', 'Found ' + this.exportResponse.length + ' entries to export. Preparing download...'); + this.dialog.close(); + } + + this.runningRequests--; + }, + + /** + * build a new event request for the listmodule + * @param {Object} responseHandler (should be storeResult) + * @param {int} start + * @param {int} limit + */ + requestNext: function(responseHandler, start, limit) { + var calendarFolder = container.getHierarchyStore().getDefaultFolder('calendar'); + + container.getRequest().singleRequest( + 'appointmentlistmodule', + 'list', + { + groupDir: "ASC", + restriction: { + start: start, + limit: limit + //startdate: 0, + //duedate: 2145826800 // 2037... nearly highest unix timestamp + }, + sort: [{ + "field": "startdate", + "direction": "DESC" + }], + store_entryid : calendarFolder.data.store_entryid, + entryid : calendarFolder.data.entryid + }, + responseHandler + ); + }, /** * download ics file =) @@ -677,7 +790,7 @@ Zarafa.plugins.calendarimporter.dialogs.ImportPanel = Ext.extend(Ext.Panel, { */ downLoadICS : function(response) { Zarafa.common.dialogs.MessageBox.hide(); - if(response.status === true) { + if(response.status === true) { if(!this.downloadFrame){ this.downloadFrame = Ext.getBody().createChild({ tag: 'iframe', @@ -688,9 +801,13 @@ Zarafa.plugins.calendarimporter.dialogs.ImportPanel = Ext.extend(Ext.Panel, { this.downloadFrame.dom.contentWindow.location = url; } else { container.getNotifier().notify('error', 'Export Failed', 'ICal File creation failed!'); - } + } }, + /** + * This function stores all given events to the appointmentstore + * @param events + */ importEvents: function (events) { //receive existing calendar store var calValue = this.calendarselector.value; @@ -721,7 +838,7 @@ Zarafa.plugins.calendarimporter.dialogs.ImportPanel = Ext.extend(Ext.Panel, { if(calValue != "calendar") { var subFolders = calendarFolder.getChildren(); var i = 0; - for(i = 0; i < pubSubFolders.length; i++) { + for(i = 0; i < pubSubFolders.length; i++) { if(pubSubFolders[i].isContainerClass("IPF.Appointment")){ subFolders.push(pubSubFolders[i]); } @@ -747,13 +864,16 @@ Zarafa.plugins.calendarimporter.dialogs.ImportPanel = Ext.extend(Ext.Panel, { } if(calexist) { + this.loadMask.show(); //receive Records from grid rows Ext.each(events, function(newRecord) { var record = this.convertToAppointmentRecord(calendarFolder,newRecord.data); calendarStore.add(record); }, this); calendarStore.save(); + this.loadMask.hide(); this.dialog.close(); + container.getNotifier().notify('info', 'Imported', 'Imported ' + events.length + ' events. Please reload your calendar!'); } } } @@ -761,4 +881,3 @@ Zarafa.plugins.calendarimporter.dialogs.ImportPanel = Ext.extend(Ext.Panel, { }); Ext.reg('calendarimporter.importpanel', Zarafa.plugins.calendarimporter.dialogs.ImportPanel); -; diff --git a/js/plugin.calendarimporter.js b/js/plugin.calendarimporter.js index 0f93c35..5c93b33 100644 --- a/js/plugin.calendarimporter.js +++ b/js/plugin.calendarimporter.js @@ -1,14 +1,26 @@ /** - * Calendarimporter + * plugin.calendarimporter.js zarafa calender to ics im/exporter * - * Main entry point for the plugin + * Author: Christoph Haas + * Copyright (C) 2012-2013 Christoph Haas + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * @author Christoph Haas - * @modified 26.02.2013 - * @license http://www.opensource.org/licenses/mit-license.php MIT License */ -Ext.namespace("Zarafa.plugins.calendarimporter"); // Assign the right namespace +Ext.namespace("Zarafa.plugins.calendarimporter"); // Assign the right namespace Zarafa.plugins.calendarimporter.ImportPlugin = Ext.extend(Zarafa.core.Plugin, { // create new import plugin @@ -20,13 +32,13 @@ Zarafa.plugins.calendarimporter.ImportPlugin = Ext.extend(Zarafa.core.Plugin, { constructor: function (config) { config = config || {}; - Ext.applyIf(config, { + Ext.applyIf(config, { name : 'calendarimporter', displayName : _('Calendarimporter Plugin'), about : Zarafa.plugins.calendarimporter.ABOUT }); - - Zarafa.plugins.calendarimporter.ImportPlugin.superclass.constructor.call(this, config); + + Zarafa.plugins.calendarimporter.ImportPlugin.superclass.constructor.call(this, config); }, /** @@ -34,15 +46,13 @@ Zarafa.plugins.calendarimporter.ImportPlugin = Ext.extend(Zarafa.core.Plugin, { * @protected */ initPlugin : function() { - - // First of all initialize timezone-js.... - timezoneJS.timezone.zoneFileBasePath = 'plugins/calendarimporter/resources/tz'; - timezoneJS.timezone.defaultZoneFile = @_@PLUGIN_TIMEZONES@_@; // replaced by buildscript -> https://github.com/mde/timezone-js - timezoneJS.timezone.init({async: false}); - - Zarafa.plugins.calendarimporter.ImportPlugin.superclass.initPlugin.apply(this, arguments); + Zarafa.plugins.calendarimporter.ImportPlugin.superclass.initPlugin.apply(this, arguments); + + /* our panel */ Zarafa.core.data.SharedComponentType.addProperty('plugins.calendarimporter.dialogs.importevents'); + /* directly import received icals */ + this.registerInsertionPoint('common.contextmenu.attachment.actions', this.createAttachmentImportButton); /* add import button to south navigation */ this.registerInsertionPoint("navigation.south", this.createImportButton, this); }, @@ -51,12 +61,13 @@ Zarafa.plugins.calendarimporter.ImportPlugin = Ext.extend(Zarafa.core.Plugin, { * Creates the button * * @return {Object} Configuration object for a {@link Ext.Button button} - * @private + * */ createImportButton: function () { - var button= - { + var button = { xtype : 'button', + ref : "importbutton", + id : "importbutton", text : _('Import Calendar'), iconCls : 'icon_calendarimporter_button', navigationContext : container.getContextByName('calendar'), @@ -71,10 +82,113 @@ Zarafa.plugins.calendarimporter.ImportPlugin = Ext.extend(Zarafa.core.Plugin, { return button; }, + /** + * Insert import button in all attachment suggestions + + * @return {Object} Configuration object for a {@link Ext.Button button} + */ + createAttachmentImportButton : function(include, btn) { + return { + text : _('Import Calendar'), + handler : this.getAttachmentFileName.createDelegate(this, [btn, this.gotAttachmentFileName]), + scope : this, + iconCls : 'icon_calendarimporter_button', + beforeShow : function(item, record) { + var extension = record.data.name.split('.').pop().toLowerCase(); + + if(record.data.filetype == "text/calendar" || extension == "ics" || extension == "ifb" || extension == "ical" || extension == "ifbf") { + item.setDisabled(false); + } else { + item.setDisabled(true); + } + } + }; + }, + + /** + * Callback for getAttachmentFileName + */ + gotAttachmentFileName: function(response) { + if(response.status == true) { + Zarafa.core.data.UIFactory.openLayerComponent(Zarafa.core.data.SharedComponentType['plugins.calendarimporter.dialogs.importevents'], undefined, { + manager : Ext.WindowMgr, + filename : response.tmpname + }); + } else { + Zarafa.common.dialogs.MessageBox.show({ + title : _('Error'), + msg : _(response["message"]), + icon : Zarafa.common.dialogs.MessageBox.ERROR, + buttons : Zarafa.common.dialogs.MessageBox.OK + }); + } + }, + /** * Clickhandler for the button */ - onImportButtonClick: function () { + getAttachmentFileName: function (btn, callback) { + Zarafa.common.dialogs.MessageBox.show({ + title: 'Please wait', + msg: 'Loading attachment...', + progressText: 'Initializing...', + width:300, + progress:true, + closable:false + }); + + // progress bar... ;) + var f = function(v){ + return function(){ + if(v == 100){ + Zarafa.common.dialogs.MessageBox.hide(); + }else{ + Zarafa.common.dialogs.MessageBox.updateProgress(v/100, Math.round(v)+'% loaded'); + } + }; + }; + + for(var i = 1; i < 101; i++){ + setTimeout(f(i), 20*i); + } + + /* store the attachment to a temporary folder and prepare it for uploading */ + var attachmentRecord = btn.records; + var attachmentStore = attachmentRecord.store; + + var store = attachmentStore.getParentRecord().get('store_entryid'); + var entryid = attachmentStore.getAttachmentParentRecordEntryId(); + var attachNum = new Array(1); + if (attachmentRecord.get('attach_num') != -1) + attachNum[0] = attachmentRecord.get('attach_num'); + else + attachNum[0] = attachmentRecord.get('tmpname'); + var dialog_attachments = attachmentStore.getId(); + var filename = attachmentRecord.data.name; + + var responseHandler = new Zarafa.plugins.calendarimporter.data.ResponseHandler({ + successCallback: callback + }); + + // request attachment preperation + container.getRequest().singleRequest( + 'calendarmodule', + 'attachmentpath', + { + entryid : entryid, + store: store, + attachNum: attachNum, + dialog_attachments: dialog_attachments, + filename: filename + }, + responseHandler + ); + }, + + /** + * Clickhandler for the button + */ + onImportButtonClick: function () { Zarafa.core.data.UIFactory.openLayerComponent(Zarafa.core.data.SharedComponentType['plugins.calendarimporter.dialogs.importevents'], undefined, { manager : Ext.WindowMgr }); @@ -88,11 +202,9 @@ Zarafa.plugins.calendarimporter.ImportPlugin = Ext.extend(Zarafa.core.Plugin, { * @param {Ext.data.Record} record Optionally passed record. * @return {Number} The bid for the shared component */ - bidSharedComponent : function(type, record) - { + bidSharedComponent : function(type, record) { var bid = -1; - switch(type) - { + switch(type) { case Zarafa.core.data.SharedComponentType['plugins.calendarimporter.dialogs.importevents']: bid = 2; break; @@ -107,11 +219,9 @@ Zarafa.plugins.calendarimporter.ImportPlugin = Ext.extend(Zarafa.core.Plugin, { * @param {Ext.data.Record} record Optionally passed record. * @return {Ext.Component} Component */ - getSharedComponent : function(type, record) - { + getSharedComponent : function(type, record) { var component; - switch(type) - { + switch(type) { case Zarafa.core.data.SharedComponentType['plugins.calendarimporter.dialogs.importevents']: component = Zarafa.plugins.calendarimporter.dialogs.ImportContentPanel; break; diff --git a/js/timezone-js/Jakefile b/js/timezone-js/Jakefile deleted file mode 100644 index 9561690..0000000 --- a/js/timezone-js/Jakefile +++ /dev/null @@ -1,87 +0,0 @@ -var fs = require('fs') - , path = require('path'); - -namespace('test', function () { - - desc('Sets up tests by downloading the timezone data.'); - task('init', ['updateTzData'], function () { - complete(); - }, {async: true}); - - task('clobberTzData', function () { - console.log('Removing old timezone data.'); - jake.rmRf('lib/tz'); - }); - - desc('Downloads the newest timezone data.'); - task('updateTzData', ['clobberTzData'], function () { - var cmds = [ - 'echo "Downloading new timezone data ..."' - , 'curl ftp://ftp.iana.org/tz/tzdata-latest.tar.gz ' + - '-o lib/tz/tzdata-latest.tar.gz' - , 'echo "Expanding archive ..."' - , 'tar -xvzf lib/tz/tzdata-latest.tar.gz -C lib/tz' - ]; - jake.mkdirP('lib/tz'); - jake.exec(cmds, function () { - console.log('Retrieved new timezone data'); - console.log('Parsing tz...'); - jake.exec('node src/node-preparse.js lib/tz > lib/all_cities.json', function () { - console.log('Done parsing tz'); - complete(); - }, {printStdout: true, printStderr: true}); - }, {printStdout: true}); - }, {async: true}); - - task('run', function () { - //Comply to 0.8.0 and 0.6.x - var existsSync = fs.existsSync || path.existsSync; - if (!existsSync('lib/tz')) { - fail('No timezone data. Please run "jake test:init".'); - } - jake.exec(['jasmine-node spec'], function () { - complete(); - }, {printStdout: true}); - - }, {async: true}); - - task('cli', ['init', 'run']); - -}); - -desc('Runs the tests.'); -task('test', ['test:run'], function () {}); - -namespace('doc', function () { - task('generate', ['doc:clobber'], function () { - var cmd = 'docco src/date.js'; - console.log('Generating docs ...'); - jake.exec([cmd], function () { - console.log('Done.'); - complete(); - }); - }, {async: true}); - - task('clobber', function () { - var cmd = 'rm -fr ./docs'; - jake.exec([cmd], function () { - console.log('Clobbered old docs.'); - complete(); - }); - }, {async: true}); - -}); - -desc('Generates docs.'); -task('doc', ['doc:generate']); - -var p = new jake.NpmPublishTask('timezone-js', [ - 'Jakefile' -, 'README.md' -, 'package.json' -, 'spec/*' -, 'src/*' -]); - -jake.Task['npm:definePackage'].invoke(); - diff --git a/js/timezone-js/README.md b/js/timezone-js/README.md deleted file mode 100644 index 0dc1374..0000000 --- a/js/timezone-js/README.md +++ /dev/null @@ -1,192 +0,0 @@ -# TimezoneJS.Date - -[![Build Status](https://secure.travis-ci.org/mde/timezone-js.png)](https://secure.travis-ci.org/mde/timezone-js) - -A timezone-enabled, drop-in replacement for the stock JavaScript Date. The `timezoneJS.Date` object is API-compatible with JS Date, with the same getter and setter methods -- it should work fine in any code that works with normal JavaScript Dates. - -[Mailing list](http://groups.google.com/group/timezone-js) - -## Overview - -The `timezoneJS.Date` object gives you full-blown timezone support, independent from the timezone set on the end-user's machine running the browser. It uses the Olson zoneinfo files for its timezone data. - -The constructor function and setter methods use proxy JavaScript Date objects behind the scenes, so you can use strings like '10/22/2006' with the constructor. You also get the same sensible wraparound behavior with numeric parameters (like setting a value of 14 for the month wraps around to the next March). - -The other significant difference from the built-in JavaScript Date is that `timezoneJS.Date` also has named properties that store the values of year, month, date, etc., so it can be directly serialized to JSON and used for data transfer. - -## Setup - -First you'll need to include the code on your page. Both `timezoneJS.Date`, and the supporting code it needs in `timezoneJS.timezone` are bundled in the `date.js` file in `src` directory. Include the code on your page with a normal JavaScript script include, like so: - -