import 'clay-button';
import 'clay-dropdown';
import Component from 'metal-component';
import dom from 'metal-dom';
import Soy from 'metal-soy';
import templates from './RuleList.soy.js';
import {Config} from 'metal-state';
import {EventHandler} from 'metal-events';
import {getFieldProperty} from '../LayoutProvider/util/fields.es';
import {maxPageIndex, pageOptions} from '../../util/pageSupport.es';
import {PagesVisitor} from '../../util/visitors.es';
/**
* RuleList.
* @extends Component
*/
class RuleList extends Component {
static STATE = {
dataProvider: Config.arrayOf(
Config.shapeOf(
{
id: Config.string(),
name: Config.string(),
uuid: Config.string()
}
)
),
dropdownExpandedIndex: Config.number().internal(),
pages: Config.array().required(),
roles: Config.arrayOf(
Config.shapeOf(
{
id: Config.string(),
name: Config.string()
}
)
).value([]),
/**
* @default 0
* @instance
* @memberof RuleList
* @type {?array}
*/
rules: Config.arrayOf(
Config.shapeOf(
{
actions: Config.arrayOf(
Config.shapeOf(
{
action: Config.string(),
ddmDataProviderInstanceUUID: Config.string(),
expression: Config.string(),
inputs: Config.object(),
label: Config.string(),
outputs: Config.object(),
target: Config.string()
}
)
),
conditions: Config.arrayOf(
Config.shapeOf(
{
operands: Config.arrayOf(
Config.shapeOf(
{
label: Config.string(),
repeatable: Config.bool(),
type: Config.string(),
value: Config.string()
}
)
),
operator: Config.string()
}
)
),
['logical-operator']: Config.string()
}
)
).value([]),
/**
* @default undefined
* @instance
* @memberof RuleList
* @type {!string}
*/
spritemap: Config.string().required(),
/**
* @default strings
* @instance
* @memberof RuleList
* @type {!object}
*/
strings: Config.object().value(
{
'belongs-to': Liferay.Language.get('belongs-to'),
'calculate-field': Liferay.Language.get('calculate-field-x-as-x'),
contains: Liferay.Language.get('contains'),
'equals-to': Liferay.Language.get('is-equal-to'),
'greater-than': Liferay.Language.get('is-greater-than'),
'greater-than-equals': Liferay.Language.get('is-greater-than-or-equal-to'),
'is-empty': Liferay.Language.get('is-empty'),
'less-than': Liferay.Language.get('is-less-than'),
'less-than-equals': Liferay.Language.get('is-less-than-or-equal-to'),
'not-contains': Liferay.Language.get('does-not-contain'),
'not-equals-to': Liferay.Language.get('is-not-equal-to'),
'not-is-empty': Liferay.Language.get('is-not-empty')
}
)
}
attached() {
this._eventHandler = new EventHandler();
this._eventHandler.add(
dom.on(document, 'mouseup', this._handleDocumentMouseUp.bind(this), true)
);
}
disposeInternal() {
super.disposeInternal();
this._eventHandler.removeAllListeners();
}
prepareStateForRender(states) {
const {pages} = this;
const rules = this._setDataProviderNames(states);
return {
...states,
rules: rules.map(
rule => {
let logicalOperator;
if (rule['logical-operator']) {
logicalOperator = rule['logical-operator'].toLowerCase();
}
else if (rule.logicalOperator) {
logicalOperator = rule.logicalOperator.toLowerCase();
}
return {
...rule,
actions: rule.actions.map(
action => {
let newAction = '';
if (action.action === 'auto-fill') {
const {inputs, outputs} = action;
const inputLabel = Object.values(inputs).map(input => this._getFieldLabel(input));
const outputLabel = Object.values(outputs).map(output => this._getFieldLabel(output));
action = {
...action,
inputLabel,
outputLabel
};
}
let fieldLabel = this._getFieldLabel(action.target);
if (action.action == 'jump-to-page') {
const fieldTarget = (parseInt(action.target, 10) + 1).toString();
if (action.label) {
fieldLabel = action.label;
}
else {
const maxPageIndexRes = maxPageIndex(rule.conditions, pages);
const pageOptionsList = pageOptions(pages, maxPageIndexRes);
const selectedPage = pageOptionsList.find(
option => {
return option.value == fieldTarget;
}
);
fieldLabel = selectedPage.label;
}
newAction = {
...action,
label: fieldLabel,
target: fieldTarget
};
}
else {
newAction = {
...action,
label: fieldLabel,
target: fieldLabel
};
}
return newAction;
}
),
conditions: rule.conditions.map(
condition => {
if (condition.operands.length < 2 && condition.operands[0].type === 'list') {
condition.operands = [
{
label: 'user',
repeatable: false,
type: 'user',
value: 'user'
},
{
...condition.operands[0],
label: condition.operands[0].value
}
];
}
return {
...condition,
operands: condition.operands.map(
(operand, index) => {
const label = this._getOperandLabel(condition.operands, index);
return {
...operand,
label,
value: label
};
}
)
};
}
),
logicalOperator
};
}
),
rulesCardOptions: this._getRulesCardOptions()
};
}
_getDataProviderName(id) {
const {dataProvider} = this;
return dataProvider.find(data => data.uuid == id).label;
}
_getFieldLabel(fieldName) {
const pages = this.pages;
return getFieldProperty(pages, fieldName, 'label');
}
_getFieldType(fieldName) {
const pages = this.pages;
return getFieldProperty(pages, fieldName, 'type');
}
_getOperandLabel(operands, index) {
let label = '';
const operand = operands[index];
if (operand.type === 'field') {
label = this._getFieldLabel(operand.value);
}
else if (operand.type === 'user') {
label = Liferay.Language.get('user');
}
else if (operand.type !== 'field') {
const fieldType = this._getFieldType(operands[0].value);
if (fieldType == 'select' || fieldType === 'radio') {
label = this._getOptionLabel(operands[0].value, operand.value);
}
else {
label = operand.value;
}
}
else {
label = operand.value;
}
return label;
}
_getOptionLabel(fieldName, optionValue) {
const pages = this.pages;
let fieldLabel = null;
if (pages && optionValue) {
const visitor = new PagesVisitor(pages);
visitor.findField(
field => {
let found = false;
if (field.fieldName === fieldName && field.options) {
field.options.some(
option => {
if (option.value == optionValue) {
fieldLabel = option.label;
found = true;
}
return found;
}
);
}
return found;
}
);
}
return fieldLabel;
}
_getRulesCardOptions() {
const rulesCardOptions = [
{
'label': Liferay.Language.get('edit'),
'settingsItem': 'edit'
},
{
'label': Liferay.Language.get('delete'),
'settingsItem': 'delete'
}
];
return rulesCardOptions;
}
_handleDocumentMouseUp({target}) {
const dropdownSettings = dom.closest(target, '.ddm-rule-list-settings');
if (dropdownSettings) {
return;
}
this.setState(
{
dropdownExpandedIndex: -1
}
);
}
_handleDropdownClicked(event) {
event.preventDefault();
const {dropdownExpandedIndex} = this;
const ruleNode = dom.closest(event.delegateTarget, '.component-action');
let ruleIndex = parseInt(ruleNode.dataset.ruleIndex, 10);
if (ruleIndex === dropdownExpandedIndex) {
ruleIndex = -1;
}
this.setState(
{
dropdownExpandedIndex: ruleIndex
}
);
}
_handleRuleCardClicked({data, target}) {
const cardElement = target.element.closest('[data-card-id]');
const cardId = parseInt(cardElement.getAttribute('data-card-id'), 10);
if (data.item.settingsItem == 'edit') {
this.emit(
'ruleEdited',
{
ruleId: cardId
}
);
}
else if (data.item.settingsItem == 'delete') {
this.emit(
'ruleDeleted',
{
ruleId: cardId
}
);
}
}
_setDataProviderNames(states) {
const {rules} = states;
if (this.dataProvider) {
for (let rule = 0; rule < rules.length; rule++) {
const actions = rules[rule].actions;
actions.forEach(
action => {
if (action.action === 'auto-fill') {
const dataProviderName = this._getDataProviderName(action.ddmDataProviderInstanceUUID);
action.dataProviderName = dataProviderName;
}
}
);
}
}
return rules;
}
}
Soy.register(RuleList, templates);
export default RuleList;