/**
* 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 'frontend-js-web/liferay/compat/modal/Modal.es';
import {fetch} from 'frontend-js-web';
import Component from 'metal-component';
import dom from 'metal-dom';
import Soy from 'metal-soy';
import {Config} from 'metal-state';
import templates from './LayoutFinder.soy';
/**
* LayoutFinder
* @review
*/
class LayoutFinder extends Component {
/**
* @inheritDoc
* @review
*/
created() {
this._handleDocumentClick = this._handleDocumentClick.bind(this);
this._documentClickHandler = dom.on(
document,
'click',
this._handleDocumentClick
);
}
/**
* @inheritDoc
* @review
*/
disposed() {
if (this._documentClickHandler) {
this._documentClickHandler.removeListener();
this._documentClickHandler = null;
}
}
/**
* Handles close button click in order to hide the dialog
* @private
* @review
*/
_handleCloseDialogClick() {
this.layouts = [];
this.totalCount = 0;
this._keywords = '';
this._showFinder = false;
}
/**
* Handles document click in order to hide the dialog
* @param {!Event} event
* @private
* @review
*/
_handleDocumentClick(event) {
if (
this._showFinder &&
this.refs.dialog &&
!this.refs.dialog.contains(event.target)
) {
this._handleCloseDialogClick();
}
}
/**
* @param {!Event} event
* @private
* @review
*/
_handleFormSubmit(event) {
event.preventDefault();
event.stopPropagation();
}
/**
* Handles keyUp event on the filter input to filter the layouts
* @param {!KeyboardEvent} event
* @private
* @preview
*/
_handleSearchInputKeyUp(event) {
const keywords = event.delegateTarget.value;
if (keywords.length < 2) {
this.layouts = [];
this.totalCount = 0;
this._keywords = '';
} else if (keywords !== this._keywords) {
this._keywords = keywords;
this._updatePageResults(this._keywords);
}
}
/**
* Update page results with the given keywords
* @param {string} keywords
* @private
* @return {Promise}
* @review
*/
_updatePageResults(keywords) {
let promise = Promise.resolve();
if (!this._loading && keywords.length >= 2) {
this._loading = true;
const formData = new FormData();
formData.append(`${this.namespace}keywords`, keywords);
promise = fetch(this.findLayoutsURL, {
body: formData,
method: 'post'
})
.then(response => {
return response.ok
? response.json()
: {
layouts: [],
totalCount: 0
};
})
.then(response => {
this.layouts = response.layouts;
this.totalCount = response.totalCount;
this._loading = false;
this._viewInPageAdministrationURL = `${this.administrationPortletURL}&${this.administrationPortletNamespace}keywords=${keywords}`;
if (this._showFinder && keywords !== this._keywords) {
this._updatePageResults(this._keywords);
}
});
}
return promise;
}
/**
* Toggles layout finder dialog visivility
* @private
* @review
*/
_toggleDialog() {
this._showFinder = !this._showFinder;
}
}
/**
* State definition
* @review
* @static
* @type {!Object}
*/
LayoutFinder.STATE = {
/**
* Document click handler
* @default null
* @instance
* @memberOf LayoutFinder
* @review
* @type {Object}
*/
_documentClickHandler: Config.object()
.internal()
.value(null),
/**
* Keywords to find layouts with
* @default ''
* @instance
* @memberOf LayoutFinder
* @private
* @review
* @type {string}
*/
_keywords: Config.string().value(''),
/**
* True when it's loading page results
* @default false
* @instance
* @memberOf LayoutFinder
* @private
* @review
* @type {boolean}
*/
_loading: Config.bool().value(false),
/**
* Show layout finder dialog
* @default false
* @instance
* @memberOf LayoutFinder
* @review
* @type {boolean}
*/
_showFinder: Config.bool().value(false),
/**
* URL to access Pages Administration portlet with keywords parameter
* @default undefined
* @instance
* @memberOf LayoutFinder
* @review
* @type {string}
*/
_viewInPageAdministrationURL: Config.string(),
/**
* Namespace for Pages Administration portlet
* @default undefined
* @instance
* @memberOf LayoutFinder
* @review
* @type {!string}
*/
administrationPortletNamespace: Config.string().required(),
/**
* URL to access Pages Administration portlet
* @default undefined
* @instance
* @memberOf LayoutFinder
* @review
* @type {!string}
*/
administrationPortletURL: Config.string().required(),
/**
* URL to find layouts by keywords
* @default undefined
* @instance
* @memberOf LayoutFinder
* @review
* @type {!string}
*/
findLayoutsURL: Config.string().required(),
/**
* Layouts found by current keywords
* @default []
* @instance
* @memberOf LayoutFinder
* @review
* @type {!Array}
*/
layouts: Config.arrayOf(
Config.shapeOf({
name: Config.string().required(),
url: Config.string().required()
})
).required(),
/**
* Current portlet max items
* @default undefined
* @instance
* @memberOf LayoutFinder
* @review
* @type {number}
*/
maxItems: Config.number().value(10),
/**
* Current portlet namespace
* @default undefined
* @instance
* @memberOf LayoutFinder
* @review
* @type {!string}
*/
namespace: Config.string().required(),
/**
* Path of the available icons
* @default undefined
* @instance
* @memberOf LayoutFinder
* @review
* @type {!string}
*/
spritemap: Config.string().required(),
/**
* Total count of layouts found
* @default 0
* @instance
* @memberOf LayoutFinder
* @review
* @type {number}
*/
totalCount: Config.number().value(0)
};
Soy.register(LayoutFinder, templates);
export {LayoutFinder};
export default LayoutFinder;