import 'clay-button';
import 'clay-select';
import 'clay-sticker';
import {ClayStripe} from 'clay-alert';
import Soy from 'metal-soy';
import {Config} from 'metal-state';
import templates from './ManageCollaborators.soy';
import PortletBase from 'frontend-js-web/liferay/PortletBase.es';
const mapToPair = (map) => Array.from(map, pair => pair.join(','));
/**
* Handles actions to delete or change permissions of the
* collaborators for a file entry.
*/
class ManageCollaborators extends PortletBase {
/**
* @inheritDoc
*/
attached() {
this._deleteSharingEntryIds = [];
this._sharingEntryIdsAndPermissions = new Map();
this._sharingEntryIdsAndExpirationDate = new Map();
this._sharingEntryIdsAndShareables = new Map();
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();
}
}
/**
* Looks if there is a collaborator with an invalid
* expiration date.
*
* @return {Boolean} If a collaborator has an invalid expiration date
*/
_findExpirationDateError() {
let 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);
let 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) {
let sharingEntryId = event.target.getAttribute('name');
let sharingEntryPermissionKey = event.target.value;
this._sharingEntryIdsAndPermissions.set(sharingEntryId, sharingEntryPermissionKey);
}
/**
* Gets the selected expiration date.
*
* @param {Event} event
* @protected
*/
_handleBlurExpirationDate(event) {
let collaboratorId = event.target.dataset.collaboratorId;
let sharingEntryExpirationDate = event.target.value;
let sharingEntryId = event.target.dataset.sharingentryId;
let collaborator = this._getCollaborator(collaboratorId);
let dateError = !this._checkExpirationDate(sharingEntryExpirationDate);
collaborator.sharingEntryExpirationDateError = dateError;
if (!dateError) {
collaborator.sharingEntryExpirationDateTooltip = this._getTooltipDate(sharingEntryExpirationDate);
this._sharingEntryIdsAndExpirationDate.set(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;
let collaborator = this._getCollaborator(collaboratorId);
if (collaborator) {
collaborator.sharingEntryShareable = shareable;
this.collaborators = this.collaborators;
}
this._sharingEntryIdsAndShareables.set(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;
let 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.set(collaborator.sharingEntryId, sharingEntryExpirationDate);
this.collaborators = this.collaborators;
}
}
/**
* Expand configuration for sharing permissions and expiration
*
* @param {Event} event
* @protected
*/
_handleExpandCollaborator(event) {
if (!event.target.matches('select,option,button')) {
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: mapToPair(this._sharingEntryIdsAndPermissions),
sharingEntryIdExpirationDatePairs: mapToPair(this._sharingEntryIdsAndExpirationDate),
sharingEntryIdShareablePairs: mapToPair(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 expanded collaborator
* @memberof ManageCollaborators
* @type {String}
*/
expandedCollaboratorId: Config.string(),
/**
* Id of the dialog
* @type {String}
*/
dialogId: Config.string().required,
/**
* Path to images.
* @instance
* @memberof ManageCollaborators
* @type {String}
*/
spritemap: Config.string().required()
};
// Register component
Soy.register(ManageCollaborators, templates);
export default ManageCollaborators;