/**
* Copyright (c) 2000-present Liferay, Inc. All rights reserved.
*
* 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.
*/
import 'clay-alert';
import 'clay-button';
import 'clay-select';
import 'clay-sticker';
import {PortletBase} from 'frontend-js-web';
import Soy from 'metal-soy';
import {Config} from 'metal-state';
import templates from './ManageCollaborators.soy';
/**
* Handles actions to delete or change permissions of the
* collaborators for a file entry.
*/
class ManageCollaborators extends PortletBase {
/**
* @inheritDoc
*/
attached() {
this._deleteSharingEntryIds = [];
this._sharingEntryIdsAndPermissions = {};
this._sharingEntryIdsAndExpirationDate = {};
this._sharingEntryIdsAndShareables = {};
let tomorrow = new Date();
tomorrow = tomorrow.setDate(tomorrow.getDate() + 1);
this._tomorrowDate = new Date(tomorrow).toISOString().split('T')[0];
}
/**
* Checks if the date is after today.
* @param {String} expirationDate
* @protected
*
* @return {Bool} returns true if the expiration date
* is after today, false in other case.
*/
_checkExpirationDate(expirationDate) {
const date = new Date(expirationDate);
return date >= new Date(this._tomorrowDate);
}
/**
* Closes the dialog.
* @protected
*/
_closeDialog() {
const collaboratorsDialog = Liferay.Util.getWindow(this._dialogId);
if (collaboratorsDialog && collaboratorsDialog.hide) {
collaboratorsDialog.hide();
}
}
_convertToPair(sharingEntryObject) {
const keys = Object.keys(sharingEntryObject);
const result = [];
keys.forEach(key => {
result.push(key + ',' + sharingEntryObject[key]);
});
return result;
}
/**
* Looks if there is a collaborator with an invalid
* expiration date.
*
* @return {Boolean} If a collaborator has an invalid expiration date
*/
_findExpirationDateError() {
const collaborator = this.collaborators.find(
collaborator =>
collaborator.sharingEntryExpirationDateError === true
);
this.expirationDateError = collaborator != null;
return this.expirationDateError;
}
/**
* Finds a collaborator by his id
*
* @param {String} collaboratorId The id of a collaborator
* @return {Object} Collaborator
*/
_getCollaborator(collaboratorId) {
const collaboratorIdNumber = Number(collaboratorId);
const collaborator = this.collaborators.find(
collaborator => collaborator.userId === collaboratorIdNumber
);
return collaborator;
}
/**
* Closes the dialog.
* @protected
*/
_handleCancelButtonClick() {
this._closeDialog();
}
/**
* Gets the new permission key for the selected
* collaborator.
*
* @param {Event} event
* @protected
*/
_handleChangePermission(event) {
const sharingEntryId = event.target.getAttribute('name');
const sharingEntryPermissionKey = event.target.value;
this._sharingEntryIdsAndPermissions[
sharingEntryId
] = sharingEntryPermissionKey;
}
/**
* Gets the selected expiration date.
*
* @param {Event} event
* @protected
*/
_handleBlurExpirationDate(event) {
const collaboratorId = event.target.dataset.collaboratorId;
const sharingEntryExpirationDate = event.target.value;
const sharingEntryId = event.target.dataset.sharingentryId;
const collaborator = this._getCollaborator(collaboratorId);
const dateError = !this._checkExpirationDate(
sharingEntryExpirationDate
);
collaborator.sharingEntryExpirationDateError = dateError;
if (!dateError) {
collaborator.sharingEntryExpirationDateTooltip = this._getTooltipDate(
sharingEntryExpirationDate
);
this._sharingEntryIdsAndExpirationDate[
sharingEntryId
] = sharingEntryExpirationDate;
}
this.collaborators = this.collaborators;
setTimeout(() => this._findExpirationDateError(), 0);
}
/**
* Get shareable permissions
*
* @param {Event} event
* @protected
*/
_handleChangeShareable(event) {
const target = event.delegateTarget;
const collaboratorId = target.dataset.collaboratorId;
const shareable = target.checked;
const sharingEntryId = target.dataset.sharingentryId;
const collaborator = this._getCollaborator(collaboratorId);
if (collaborator) {
collaborator.sharingEntryShareable = shareable;
this.collaborators = this.collaborators;
}
this._sharingEntryIdsAndShareables[sharingEntryId] = shareable;
}
/**
* Deletes the collaborator.
*
* @param {Event} event
* @protected
*/
_handleDeleteCollaborator(event) {
const target = event.delegateTarget;
const collaboratorId = Number(target.dataset.collaboratorId);
const sharingEntryId = target.dataset.sharingentryId;
event.stopPropagation();
this.collaborators = this.collaborators.filter(
collaborator => collaborator.userId != collaboratorId
);
this._deleteSharingEntryIds.push(sharingEntryId);
}
/**
* Enable and disable the expiration date field
* @param {Event} event
* @protected
*/
_handleEnableDisableExpirationDate(event) {
const target = event.delegateTarget;
const collaboratorId = target.dataset.collaboratorId;
const enabled = target.checked;
const collaborator = this._getCollaborator(collaboratorId);
if (collaborator) {
const sharingEntryExpirationDate = enabled
? this._tomorrowDate
: '';
collaborator.enabledExpirationDate = enabled;
if (!enabled) {
collaborator.sharingEntryExpirationDateError = false;
this._findExpirationDateError();
}
collaborator.sharingEntryExpirationDate = sharingEntryExpirationDate;
collaborator.sharingEntryExpirationDateTooltip = this._getTooltipDate(
sharingEntryExpirationDate
);
this._sharingEntryIdsAndExpirationDate[
collaborator.sharingEntryId
] = sharingEntryExpirationDate;
this.collaborators = this.collaborators;
}
}
/**
* Expand configuration for sharing permissions and expiration
*
* @param {Event} event
* @protected
*/
_handleExpandCollaborator(event) {
const invalidElements = 'select,option,button';
if (
invalidElements.indexOf(event.target.nodeName.toLowerCase()) == -1
) {
this.expandedCollaboratorId =
event.delegateTarget.dataset.collaboratorid;
}
}
/**
* Sends a request to the server to update permissions
* or delete collaborators.
*
* @protected
*/
_handleSaveButtonClick() {
if (this._findExpirationDateError()) {
return;
}
this.fetch(this.actionUrl, {
deleteSharingEntryIds: this._deleteSharingEntryIds,
sharingEntryIdActionIdPairs: this._convertToPair(
this._sharingEntryIdsAndPermissions
),
sharingEntryIdExpirationDatePairs: this._convertToPair(
this._sharingEntryIdsAndExpirationDate
),
sharingEntryIdShareablePairs: this._convertToPair(
this._sharingEntryIdsAndShareables
)
})
.then(response => {
this.submitting = false;
const jsonResponse = response.json();
return response.ok
? jsonResponse
: jsonResponse.then(json => {
const error = new Error(
json.errorMessage || response.statusText
);
throw Object.assign(error, {response});
});
})
.then(json => {
this._loadingResponse = false;
this._showNotification(json.successMessage);
})
.catch(error => {
this._loadingResponse = false;
this._showNotification(error.message, true);
});
this._loadingResponse = true;
}
/**
* Get the formatted date that has to be shown
* in the tooltip.
*
* @param {Date} expirationDate [description]
* @return {String} [description]
*/
_getTooltipDate(expirationDate) {
return Liferay.Util.sub(
Liferay.Language.get('until-x'),
new Date(expirationDate).toLocaleDateString(
Liferay.ThemeDisplay.getBCP47LanguageId()
)
);
}
/**
* Cleans the error.
* @protected
*/
_removeExpirationDateError() {
this.expirationDateError = false;
}
/**
* Show notification in the opener and closes dialog
* after is rendered
* @param {string} message message for notification
* @param {boolean} error Flag indicating if is an error or not
* @private
* @review
*/
_showNotification(message, error) {
const parentOpenToast = Liferay.Util.getOpener().Liferay.Util.openToast;
const openToastParams = {
events: {
attached: this._closeDialog.bind(this)
},
message
};
if (error) {
openToastParams.title = Liferay.Language.get('error');
openToastParams.type = 'danger';
}
parentOpenToast(openToastParams);
}
}
/**
* State definition.
* @ignore
* @static
* @type {!Object}
*/
ManageCollaborators.STATE = {
/**
* Uri to send the manage collaborators fetch request.
* @instance
* @memberof ManageCollaborators
* @type {String}
*/
actionUrl: Config.string().required(),
/**
* List of collaborators
* @type {Array.<Object>}
*/
collaborators: Config.arrayOf(
Config.shapeOf({
fullName: Config.string(),
sharingEntryExpirationDate: Config.string(),
sharingEntryExpirationDateTooltip: Config.string(),
sharingEntryId: Config.string(),
sharingEntryPermissionDisplaySelectOptions: Config.arrayOf(
Config.shapeOf({
label: Config.string(),
selected: Config.bool(),
value: Config.string()
})
),
sharingEntryShareable: Config.bool(),
userId: Config.number()
})
).required(),
/**
* Id of the dialog
* @type {String}
*/
dialogId: Config.string().required,
/**
* Id of the expanded collaborator
* @memberof ManageCollaborators
* @type {String}
*/
expandedCollaboratorId: Config.string(),
/**
* Path to images.
* @instance
* @memberof ManageCollaborators
* @type {String}
*/
spritemap: Config.string().required()
};
// Register component
Soy.register(ManageCollaborators, templates);
export default ManageCollaborators;