Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/mail.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristoph Wurst <christoph@winzerhof-wurst.at>2016-05-04 12:31:11 +0300
committerChristoph Wurst <christoph@winzerhof-wurst.at>2016-05-09 09:51:25 +0300
commitd03da7c7e5192bd170f657bc9ace81e457fb87e9 (patch)
tree69f3daa84823ab425bb90c8d8a1d2db8e0d66033
parentabf8ea1cf8715bfb6f28c4c0f2a924e5e5f8bae2 (diff)
fetch and show list of calendars
-rw-r--r--bower.json4
-rwxr-xr-xcss/mail.css8
-rw-r--r--js/app.js4
-rw-r--r--js/models/dav/calendar.js26
-rw-r--r--js/radio.js16
-rw-r--r--js/require_config.js5
-rw-r--r--js/service/davservice.js108
-rw-r--r--js/templates/calendar.html1
-rw-r--r--js/templates/message-attachment.html3
-rw-r--r--js/views/app.js4
-rw-r--r--js/views/calendarspopoverview.js30
-rw-r--r--js/views/calendarview.js31
-rw-r--r--js/views/messageattachment.js43
13 files changed, 265 insertions, 18 deletions
diff --git a/bower.json b/bower.json
index 8e81edf0d..1daeb3bf7 100644
--- a/bower.json
+++ b/bower.json
@@ -25,6 +25,8 @@
"jquery-visibility": "~1.0.11",
"requirejs": "2.2.0",
"text": "^2.0.14",
- "underscore": "~1.8.3"
+ "underscore": "~1.8.3",
+ "davclient.js": "git@github.com:evert/davclient.js.git",
+ "es6-promise": "^3.2.1"
}
}
diff --git a/css/mail.css b/css/mail.css
index 8a5172a1c..cf97c2a2d 100755
--- a/css/mail.css
+++ b/css/mail.css
@@ -679,6 +679,14 @@ input.submit-message,
.attachment-import {
right: 79px;
}
+.attachment-import-popover {
+ right: -17px;
+ top: 56px;
+}
+.attachment-import-popover::after {
+ left: 30px;
+ right: initial;
+}
/* show icon + text for Download all button
as well as when there is only one attachment */
.attachments-save-to-cloud,
diff --git a/js/app.js b/js/app.js
index 57cfb47dc..67371932a 100644
--- a/js/app.js
+++ b/js/app.js
@@ -22,6 +22,9 @@
define(function(require) {
'use strict';
+ // Enable ES6 promise polyfill
+ require('es6-promise').polyfill();
+
var $ = require('jquery');
var Backbone = require('backbone');
var Handlebars = require('handlebars');
@@ -39,6 +42,7 @@ define(function(require) {
require('controller/messagecontroller');
require('service/accountservice');
require('service/attachmentservice');
+ require('service/davservice');
require('service/folderservice');
require('service/messageservice');
require('notification');
diff --git a/js/models/dav/calendar.js b/js/models/dav/calendar.js
new file mode 100644
index 000000000..e7f0b18bb
--- /dev/null
+++ b/js/models/dav/calendar.js
@@ -0,0 +1,26 @@
+/**
+ * @author Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * ownCloud - Mail
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+define(function(require) {
+ 'use strict';
+
+ var Backbone = require('backbone');
+
+ return Backbone.Model.extend({});
+}); \ No newline at end of file
diff --git a/js/radio.js b/js/radio.js
index f365b0ab8..306bcb009 100644
--- a/js/radio.js
+++ b/js/radio.js
@@ -13,22 +13,24 @@ define(function(require) {
var Radio = require('backbone.radio');
- var uiChannel = Radio.channel('ui');
- var notificationChannel = Radio.channel('notification');
- var stateChannel = Radio.channel('state');
var accountChannel = Radio.channel('account');
var folderChannel = Radio.channel('folder');
+ var davChannel = Radio.channel('dav');
var messageChannel = Radio.channel('message');
var navigationChannel = Radio.channel('navigation');
+ var notificationChannel = Radio.channel('notification');
+ var stateChannel = Radio.channel('state');
+ var uiChannel = Radio.channel('ui');
var channels = {
- ui: uiChannel,
- notification: notificationChannel,
- state: stateChannel,
account: accountChannel,
+ dav: davChannel,
folder: folderChannel,
message: messageChannel,
- navigation: navigationChannel
+ navigation: navigationChannel,
+ notification: notificationChannel,
+ state: stateChannel,
+ ui: uiChannel
};
// Log all events to the console
diff --git a/js/require_config.js b/js/require_config.js
index a990956f9..d2a272f62 100644
--- a/js/require_config.js
+++ b/js/require_config.js
@@ -21,11 +21,16 @@
*/
backbone: 'vendor/backbone/backbone',
'backbone.radio': 'vendor/backbone.radio/build/backbone.radio',
+ davclient: 'vendor/davclient.js/lib/client',
domready: 'vendor/domReady/domReady',
+ 'es6-promise': 'vendor/es6-promise/es6-promise.min',
handlebars: 'vendor/handlebars/handlebars',
marionette: 'vendor/backbone.marionette/lib/backbone.marionette',
underscore: 'vendor/underscore/underscore',
text: 'vendor/text/text'
+ },
+ davclient: {
+ exports: 'dav'
}
});
diff --git a/js/service/davservice.js b/js/service/davservice.js
new file mode 100644
index 000000000..edf83e7c9
--- /dev/null
+++ b/js/service/davservice.js
@@ -0,0 +1,108 @@
+/**
+ * @author Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * ownCloud - Mail
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+define(function(require) {
+ 'use strict';
+
+ var _ = require('underscore');
+ var $ = require('jquery');
+ var Backbone = require('backbone');
+ var dav = require('davclient');
+ var OC = require('OC');
+ var Radio = require('radio');
+ var Calendar = require('models/dav/calendar');
+
+ Radio.dav.reply('calendars', getUserCalendars);
+
+ var client = new dav.Client({
+ baseUrl: OC.linkToRemote('dav/calendars'),
+ xmlNamespaces: {
+ 'DAV:': 'd',
+ 'urn:ietf:params:xml:ns:caldav': 'c',
+ 'http://apple.com/ns/ical/': 'aapl',
+ 'http://owncloud.org/ns': 'oc',
+ 'http://calendarserver.org/ns/': 'cs'
+ }
+ });
+ var props = [
+ '{DAV:}displayname',
+ '{urn:ietf:params:xml:ns:caldav}calendar-description',
+ '{urn:ietf:params:xml:ns:caldav}calendar-timezone',
+ '{http://apple.com/ns/ical/}calendar-order',
+ '{http://apple.com/ns/ical/}calendar-color',
+ '{urn:ietf:params:xml:ns:caldav}supported-calendar-component-set',
+ '{http://owncloud.org/ns}calendar-enabled',
+ '{DAV:}acl',
+ '{DAV:}owner',
+ '{http://owncloud.org/ns}invite'
+ ];
+
+ function getResponseCodeFromHTTPResponse(t) {
+ return parseInt(t.split(' ')[1]);
+ }
+
+ function getCalendarData(properties) {
+ var data = {
+ displayname: properties['{DAV:}displayname'],
+ color: properties['{http://apple.com/ns/ical/}calendar-color'],
+ order: properties['{http://apple.com/ns/ical/}calendar-order'],
+ components: {
+ vevent: false
+ }
+ };
+
+ var components = properties['{urn:ietf:params:xml:ns:caldav}supported-calendar-component-set'] || [];
+ for (var i = 0; i < components.length; i++) {
+ var name = components[i].attributes.getNamedItem('name').textContent.toLowerCase();
+ if (data.components.hasOwnProperty(name)) {
+ data.components[name] = true;
+ }
+ }
+
+ return data;
+ }
+
+ function getUserCalendars() {
+ var defer = $.Deferred();
+ var url = OC.linkToRemote('dav/calendars') + '/' + OC.currentUser + '/';
+
+ client.propFind(url, props, 1, {
+ 'requesttoken': OC.requestToken
+ }).then(function(data) {
+ var calendars = new Backbone.Collection();
+
+ _.each(data.body, function(cal) {
+ if (cal.propStat.length < 1) {
+ return;
+ }
+ if (getResponseCodeFromHTTPResponse(cal.propStat[0].status) === 200) {
+ var properties = getCalendarData(cal.propStat[0].properties);
+ if (properties && properties.components.vevent) {
+ calendars.push(new Calendar(properties));
+ }
+ }
+ });
+ defer.resolve(calendars);
+ }, function() {
+ defer.reject();
+ });
+
+ return defer.promise();
+ }
+});
diff --git a/js/templates/calendar.html b/js/templates/calendar.html
new file mode 100644
index 000000000..c1e9bae6b
--- /dev/null
+++ b/js/templates/calendar.html
@@ -0,0 +1 @@
+<a class="select-calendar" data-calendar-url="some-url">{{displayname}}</a> \ No newline at end of file
diff --git a/js/templates/message-attachment.html b/js/templates/message-attachment.html
index 7fab1c1f1..2591d478b 100644
--- a/js/templates/message-attachment.html
+++ b/js/templates/message-attachment.html
@@ -8,4 +8,5 @@
<button class="button icon-add attachment-import calendar" title="{{ t 'Import into calendar' }}"></button>
{{/if}}
<button class="button icon-download attachment-download" title="{{ t 'Download attachment' }}"></button>
-<button class="icon-folder attachment-save-to-cloud" title="{{ t 'Save to Files' }}"></button> \ No newline at end of file
+<button class="icon-folder attachment-save-to-cloud" title="{{ t 'Save to Files' }}"></button>
+<div class="popovermenu bubble attachment-import-popover hidden"></div> \ No newline at end of file
diff --git a/js/views/app.js b/js/views/app.js
index 08a4ca699..cba1ee983 100644
--- a/js/views/app.js
+++ b/js/views/app.js
@@ -62,6 +62,10 @@ define(function(require) {
window.addEventListener('resize', this.onWindowResize);
+ $(document).on('click', function(e) {
+ Radio.ui.trigger('document:click', e);
+ });
+
// TODO: create marionette view and encapsulate events
$(document).on('click', '#forward-button', function() {
Radio.message.trigger('forward');
diff --git a/js/views/calendarspopoverview.js b/js/views/calendarspopoverview.js
new file mode 100644
index 000000000..f2693cbb2
--- /dev/null
+++ b/js/views/calendarspopoverview.js
@@ -0,0 +1,30 @@
+/**
+ * @author Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * ownCloud - Mail
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+define(function(require) {
+ 'use strict';
+
+ var Marionette = require('marionette');
+ var CalendarView = require('views/calendarview');
+
+ return Marionette.CollectionView.extend({
+ childView: CalendarView,
+ tagName: 'ul'
+ });
+});
diff --git a/js/views/calendarview.js b/js/views/calendarview.js
new file mode 100644
index 000000000..9b2e3ffee
--- /dev/null
+++ b/js/views/calendarview.js
@@ -0,0 +1,31 @@
+/**
+ * @author Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * ownCloud - Mail
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+define(function(require) {
+ 'use strict';
+
+ var Marionette = require('marionette');
+ var Handlebars = require('handlebars');
+ var CalendarTemplate = require('text!templates/calendar.html');
+
+ return Marionette.ItemView.extend({
+ template: Handlebars.compile(CalendarTemplate),
+ tagName: 'li'
+ });
+});
diff --git a/js/views/messageattachment.js b/js/views/messageattachment.js
index 4cb80998a..944c6b072 100644
--- a/js/views/messageattachment.js
+++ b/js/views/messageattachment.js
@@ -25,6 +25,7 @@ define(function(require) {
var Marionette = require('marionette');
var Radio = require('radio');
var MessageController = require('controller/messagecontroller');
+ var CalendarsPopoverView = require('views/calendarspopoverview');
var MessageAttachmentTemplate = require('text!templates/message-attachment.html');
/**
@@ -35,15 +36,26 @@ define(function(require) {
ui: {
'downloadButton': '.attachment-download',
'saveToCloudButton': '.attachment-save-to-cloud',
- 'importCalendarEventButton': '.attachment-import.calendar'
+ 'importCalendarEventButton': '.attachment-import.calendar',
+ 'attachmentImportPopover': '.attachment-import-popover'
},
events: {
- 'click': '_onDownload',
+ 'click': '_onClick',
'click @ui.saveToCloudButton': '_onSaveToCloud',
'click @ui.importCalendarEventButton': '_onImportCalendarEvent'
},
- _onDownload: function(e) {
+ initialize: function() {
+ this.listenTo(Radio.ui, 'document:click', this._closeImportPopover);
+ },
+ _onClick: function(e) {
if (!e.isDefaultPrevented()) {
+ var $target = $(e.target);
+ if ($target.hasClass('select-calendar')) {
+ var url = $target.data('calendar-url');
+ alert(url);
+ return;
+ }
+
e.preventDefault();
window.location = this.model.get('downloadUrl');
}
@@ -79,21 +91,34 @@ define(function(require) {
.addClass('icon-loading-small');
var url = this.model.get('downloadUrl');
- var downloading = Radio.message.request('attachment:download', url);
+ var downloadingAttachment = Radio.message.request('attachment:download', url);
+ var fetchingCalendars = Radio.dav.request('calendars');
var _this = this;
- $.when(downloading).done(function(data) {
- console.log(data);
- });
- $.when(downloading.fail(function() {
+ $.when(downloadingAttachment.fail(function() {
Radio.ui.trigger('error:show', t('Error while downloading calendar event'));
}));
- $.when(downloading).always(function() {
+ $.when(fetchingCalendars, downloadingAttachment).always(function() {
_this.ui.importCalendarEventButton
.removeClass('icon-loading-small')
.addClass('icon-add');
});
+ $.when(fetchingCalendars, downloadingAttachment).
+ done(function(calendars, ics) {
+ _this.ui.attachmentImportPopover.removeClass('hidden');
+ var calendarsView = new CalendarsPopoverView({
+ collection: calendars
+ });
+ calendarsView.render();
+ _this.ui.attachmentImportPopover.html(calendarsView.$el);
+ });
+ },
+ _closeImportPopover: function(e) {
+ var $target = $(e.target);
+ if (this.$el.find($target).length === 0) {
+ this.ui.attachmentImportPopover.addClass('hidden');
+ }
}
});