summaryrefslogtreecommitdiffstats
path: root/apps/files_sharing/src/share.js
diff options
context:
space:
mode:
Diffstat (limited to 'apps/files_sharing/src/share.js')
-rw-r--r--apps/files_sharing/src/share.js276
1 files changed, 276 insertions, 0 deletions
diff --git a/apps/files_sharing/src/share.js b/apps/files_sharing/src/share.js
new file mode 100644
index 00000000000..b02c6e3d9ee
--- /dev/null
+++ b/apps/files_sharing/src/share.js
@@ -0,0 +1,276 @@
+/*
+ * Copyright (c) 2014
+ *
+ * This file is licensed under the Affero General Public License version 3
+ * or later.
+ *
+ * See the COPYING-README file.
+ *
+ */
+
+(function() {
+
+ _.extend(OC.Files.Client, {
+ PROPERTY_SHARE_TYPES: '{' + OC.Files.Client.NS_OWNCLOUD + '}share-types',
+ PROPERTY_OWNER_ID: '{' + OC.Files.Client.NS_OWNCLOUD + '}owner-id',
+ PROPERTY_OWNER_DISPLAY_NAME: '{' + OC.Files.Client.NS_OWNCLOUD + '}owner-display-name'
+ });
+
+ if (!OCA.Sharing) {
+ OCA.Sharing = {};
+ }
+ /**
+ * @namespace
+ */
+ OCA.Sharing.Util = {
+ /**
+ * Initialize the sharing plugin.
+ *
+ * Registers the "Share" file action and adds additional
+ * DOM attributes for the sharing file info.
+ *
+ * @param {OCA.Files.FileList} fileList file list to be extended
+ */
+ attach: function(fileList) {
+ // core sharing is disabled/not loaded
+ if (!OC.Share) {
+ return;
+ }
+ if (fileList.id === 'trashbin' || fileList.id === 'files.public') {
+ return;
+ }
+ var fileActions = fileList.fileActions;
+ var oldCreateRow = fileList._createRow;
+ fileList._createRow = function(fileData) {
+
+ var tr = oldCreateRow.apply(this, arguments);
+ var sharePermissions = OCA.Sharing.Util.getSharePermissions(fileData);
+
+ if (fileData.permissions === 0) {
+ // no permission, disabling sidebar
+ delete fileActions.actions.all.Comment;
+ delete fileActions.actions.all.Details;
+ delete fileActions.actions.all.Goto;
+ }
+ tr.attr('data-share-permissions', sharePermissions);
+ if (fileData.shareOwner) {
+ tr.attr('data-share-owner', fileData.shareOwner);
+ tr.attr('data-share-owner-id', fileData.shareOwnerId);
+ // user should always be able to rename a mount point
+ if (fileData.mountType === 'shared-root') {
+ tr.attr('data-permissions', fileData.permissions | OC.PERMISSION_UPDATE);
+ }
+ }
+ if (fileData.recipientData && !_.isEmpty(fileData.recipientData)) {
+ tr.attr('data-share-recipient-data', JSON.stringify(fileData.recipientData));
+ }
+ if (fileData.shareTypes) {
+ tr.attr('data-share-types', fileData.shareTypes.join(','));
+ }
+ return tr;
+ };
+
+ var oldElementToFile = fileList.elementToFile;
+ fileList.elementToFile = function($el) {
+ var fileInfo = oldElementToFile.apply(this, arguments);
+ fileInfo.sharePermissions = $el.attr('data-share-permissions') || undefined;
+ fileInfo.shareOwner = $el.attr('data-share-owner') || undefined;
+ fileInfo.shareOwnerId = $el.attr('data-share-owner-id') || undefined;
+
+ if( $el.attr('data-share-types')){
+ fileInfo.shareTypes = $el.attr('data-share-types').split(',');
+ }
+
+ if( $el.attr('data-expiration')){
+ var expirationTimestamp = parseInt($el.attr('data-expiration'));
+ fileInfo.shares = [];
+ fileInfo.shares.push({expiration: expirationTimestamp});
+ }
+
+ return fileInfo;
+ };
+
+ var oldGetWebdavProperties = fileList._getWebdavProperties;
+ fileList._getWebdavProperties = function() {
+ var props = oldGetWebdavProperties.apply(this, arguments);
+ props.push(OC.Files.Client.PROPERTY_OWNER_ID);
+ props.push(OC.Files.Client.PROPERTY_OWNER_DISPLAY_NAME);
+ props.push(OC.Files.Client.PROPERTY_SHARE_TYPES);
+ return props;
+ };
+
+ fileList.filesClient.addFileInfoParser(function(response) {
+ var data = {};
+ var props = response.propStat[0].properties;
+ var permissionsProp = props[OC.Files.Client.PROPERTY_PERMISSIONS];
+
+ if (permissionsProp && permissionsProp.indexOf('S') >= 0) {
+ data.shareOwner = props[OC.Files.Client.PROPERTY_OWNER_DISPLAY_NAME];
+ data.shareOwnerId = props[OC.Files.Client.PROPERTY_OWNER_ID];
+ }
+
+ var shareTypesProp = props[OC.Files.Client.PROPERTY_SHARE_TYPES];
+ if (shareTypesProp) {
+ data.shareTypes = _.chain(shareTypesProp).filter(function(xmlvalue) {
+ return (xmlvalue.namespaceURI === OC.Files.Client.NS_OWNCLOUD && xmlvalue.nodeName.split(':')[1] === 'share-type');
+ }).map(function(xmlvalue) {
+ return parseInt(xmlvalue.textContent || xmlvalue.text, 10);
+ }).value();
+ }
+
+ return data;
+ });
+
+ // use delegate to catch the case with multiple file lists
+ fileList.$el.on('fileActionsReady', function(ev){
+ var $files = ev.$files;
+
+ _.each($files, function(file) {
+ var $tr = $(file);
+ var shareTypes = $tr.attr('data-share-types') || '';
+ var shareOwner = $tr.attr('data-share-owner');
+ if (shareTypes || shareOwner) {
+ var hasLink = false;
+ var hasShares = false;
+ _.each(shareTypes.split(',') || [], function(shareType) {
+ shareType = parseInt(shareType, 10);
+ if (shareType === OC.Share.SHARE_TYPE_LINK) {
+ hasLink = true;
+ } else if (shareType === OC.Share.SHARE_TYPE_EMAIL) {
+ hasLink = true;
+ } else if (shareType === OC.Share.SHARE_TYPE_USER) {
+ hasShares = true;
+ } else if (shareType === OC.Share.SHARE_TYPE_GROUP) {
+ hasShares = true;
+ } else if (shareType === OC.Share.SHARE_TYPE_REMOTE) {
+ hasShares = true;
+ } else if (shareType === OC.Share.SHARE_TYPE_CIRCLE) {
+ hasShares = true;
+ } else if (shareType === OC.Share.SHARE_TYPE_ROOM) {
+ hasShares = true;
+ }
+ });
+ OCA.Sharing.Util._updateFileActionIcon($tr, hasShares, hasLink);
+ }
+ });
+ });
+
+
+ fileList.$el.on('changeDirectory', function() {
+ OCA.Sharing.sharesLoaded = false;
+ });
+
+ fileActions.registerAction({
+ name: 'Share',
+ displayName: '',
+ altText: t('core', 'Share'),
+ mime: 'all',
+ permissions: OC.PERMISSION_ALL,
+ iconClass: 'icon-shared',
+ type: OCA.Files.FileActions.TYPE_INLINE,
+ actionHandler: function(fileName, context) {
+ // do not open sidebar if permission is set and equal to 0
+ var permissions = parseInt(context.$file.data('share-permissions'), 10);
+ if (isNaN(permissions) || permissions > 0) {
+ fileList.showDetailsView(fileName, 'shareTabView');
+ }
+ },
+ render: function(actionSpec, isDefault, context) {
+ var permissions = parseInt(context.$file.data('permissions'), 10);
+ // if no share permissions but share owner exists, still show the link
+ if ((permissions & OC.PERMISSION_SHARE) !== 0 || context.$file.attr('data-share-owner')) {
+ return fileActions._defaultRenderAction.call(fileActions, actionSpec, isDefault, context);
+ }
+ // don't render anything
+ return null;
+ }
+ });
+
+ var shareTab = new OCA.Sharing.ShareTabView('shareTabView', {order: -20});
+ // detect changes and change the matching list entry
+ shareTab.on('sharesChanged', function(shareModel) {
+ var fileInfoModel = shareModel.fileInfoModel;
+ var $tr = fileList.findFileEl(fileInfoModel.get('name'));
+
+ // We count email shares as link share
+ var hasLinkShares = shareModel.hasLinkShares();
+ shareModel.get('shares').forEach(function (share) {
+ if (share.share_type === OC.Share.SHARE_TYPE_EMAIL) {
+ hasLinkShares = true;
+ }
+ });
+
+ OCA.Sharing.Util._updateFileListDataAttributes(fileList, $tr, shareModel);
+ if (!OCA.Sharing.Util._updateFileActionIcon($tr, shareModel.hasUserShares(), hasLinkShares)) {
+ // remove icon, if applicable
+ OC.Share.markFileAsShared($tr, false, false);
+ }
+
+ // FIXME: this is too convoluted. We need to get rid of the above updates
+ // and only ever update the model and let the events take care of rerendering
+ fileInfoModel.set({
+ shareTypes: shareModel.getShareTypes(),
+ // in case markFileAsShared decided to change the icon,
+ // we need to modify the model
+ // (FIXME: yes, this is hacky)
+ icon: $tr.attr('data-icon')
+ });
+ });
+ fileList.registerTabView(shareTab);
+
+ var breadCrumbSharingDetailView = new OCA.Sharing.ShareBreadCrumbView({shareTab: shareTab});
+ fileList.registerBreadCrumbDetailView(breadCrumbSharingDetailView);
+ },
+
+ /**
+ * Update file list data attributes
+ */
+ _updateFileListDataAttributes: function(fileList, $tr, shareModel) {
+ // files app current cannot show recipients on load, so we don't update the
+ // icon when changed for consistency
+ if (fileList.id === 'files') {
+ return;
+ }
+ var recipients = _.pluck(shareModel.get('shares'), 'share_with_displayname');
+ // note: we only update the data attribute because updateIcon()
+ if (recipients.length) {
+ var recipientData = _.mapObject(shareModel.get('shares'), function (share) {
+ return {shareWith: share.share_with, shareWithDisplayName: share.share_with_displayname};
+ });
+ $tr.attr('data-share-recipient-data', JSON.stringify(recipientData));
+ }
+ else {
+ $tr.removeAttr('data-share-recipient-data');
+ }
+ },
+
+ /**
+ * Update the file action share icon for the given file
+ *
+ * @param $tr file element of the file to update
+ * @param {boolean} hasUserShares true if a user share exists
+ * @param {boolean} hasLinkShares true if a link share exists
+ *
+ * @return {boolean} true if the icon was set, false otherwise
+ */
+ _updateFileActionIcon: function($tr, hasUserShares, hasLinkShares) {
+ // if the statuses are loaded already, use them for the icon
+ // (needed when scrolling to the next page)
+ if (hasUserShares || hasLinkShares || $tr.attr('data-share-recipient-data') || $tr.attr('data-share-owner')) {
+ OC.Share.markFileAsShared($tr, true, hasLinkShares);
+ return true;
+ }
+ return false;
+ },
+
+ /**
+ * @param {Array} fileData
+ * @returns {String}
+ */
+ getSharePermissions: function(fileData) {
+ return fileData.sharePermissions;
+ }
+ };
+})();
+
+OC.Plugins.register('OCA.Files.FileList', OCA.Sharing.Util);