blob: 5056113b3d53d2bb24200bdf292c8688a3f4ae89 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* global Slick, nf */
$(document).ready(function () {
ua.editable = $('#attribute-updater-editable').text() === 'true';
ua.init();
});
/**
* Determine if an `element` has content overflow and adds a colored bottom border if it does.
*
* @param {HTMLElement} element The DOM element to toggle .scrollable upon.
*/
var toggleScrollable = function (element) {
if ($(element).is(':visible')){
if (element.offsetHeight < element.scrollHeight ||
element.offsetWidth < element.scrollWidth) {
// your element has overflow
$(element).css({
'border-bottom': '1px solid #d0dbe0'
});
} else {
$(element).css({
'border-bottom': '1px solid #ffffff'
});
}
}
};
var ua = {
newRuleIndex: 0,
editable: false,
/**
* Initializes this web application.
*
* @returns {undefined}
*/
init: function () {
// configure the dialogs
ua.initNewRuleDialog();
ua.initNewConditionDialog();
ua.initNewActionDialog();
ua.initOkDialog();
ua.initYesNoDialog();
// configure the grids
var conditionsGrid = ua.initConditionsGrid();
var actionsGrid = ua.initActionsGrid();
// enable grid resizing
$(window).resize(function (e) {
if (e.target === window) {
var conditionsLock = conditionsGrid.getEditorLock();
if (!conditionsLock.isActive()) {
conditionsGrid.resizeCanvas();
}
var actionsLock = actionsGrid.getEditorLock();
if (!actionsLock.isActive()) {
actionsGrid.resizeCanvas();
}
// toggle .scrollable when appropriate
toggleScrollable($('#rule-details-panel').get(0));
// resize dialogs when appropriate
var dialogs = $('.dialog');
for (var i = 0, len = dialogs.length; i < len; i++) {
if ($(dialogs[i]).is(':visible')){
setTimeout(function(dialog){
dialog.modal('resize');
}, 50, $(dialogs[i]));
}
}
}
});
toggleScrollable($('#rule-details-panel').get(0));
// initialize the rule list
ua.initRuleList();
var destroyEditors = function(){
if($('.slickgrid-nf-editor').is(':visible') || $('.slickgrid-custom-long-text-editor').is(':visible')){
$('#selected-rule-actions').data('gridInstance').getEditController().cancelCurrentEdit();
$('#selected-rule-conditions').data('gridInstance').getEditController().cancelCurrentEdit();
}
if( $('#new-condition-dialog').is(':visible')){
$('#new-condition-dialog').modal('hide');
}
if( $('#new-action-dialog').is(':visible')){
$('#new-action-dialog').modal('hide');
}
};
// button click for new rules
$('#new-rule').on('click', function () {
destroyEditors();
$('#new-rule-dialog').modal('show');
$('#new-rule-name').focus();
});
// button click for new conditions/actions
$('#new-condition').on('click', function () {
destroyEditors();
var ruleId = $('#selected-rule-id').text();
if (ruleId === '') {
$('#ok-dialog-content').text('No rule is selected.');
$('#ok-dialog').modal('setHeaderText', 'Configuration Error').modal('show');
} else {
// clear the current content
$('#new-condition-expression').nfeditor('setValue', '');
// show the dialog
$('#new-condition-dialog').center().show();
$('#new-condition-expression').nfeditor('refresh').nfeditor('focus');
}
});
$('#new-action').on('click', function () {
destroyEditors();
var ruleId = $('#selected-rule-id').text();
if (ruleId === '') {
$('#ok-dialog-content').text('No rule is selected.');
$('#ok-dialog').modal('setHeaderText', 'Configuration Error').modal('show');
} else {
// clear the current content
$('#new-action-attribute').val('');
$('#new-action-value').nfeditor('setValue', '');
// show the dialog
$('#new-action-dialog').center().show();
$('#new-action-attribute').focus();
$('#new-action-value').nfeditor('refresh');
}
});
// handle rule name changes
$('#selected-rule-name').on('blur', function () {
var ruleName = $(this).val();
var ruleItem = $('#rule-list').children('li.selected');
var rule = ruleItem.data('rule');
if (rule.name !== ruleName) {
ruleItem.addClass('unsaved');
}
}).on('focus', function () {
if (ua.editable) {
// commit any condition edits
var conditionsEditController = conditionsGrid.getEditController();
conditionsEditController.commitCurrentEdit();
// commit any action edits
var actionsEditController = actionsGrid.getEditController();
actionsEditController.commitCurrentEdit();
} else {
ua.removeAllDetailDialogs();
}
});
// add the handler for saving the rules
$('#selected-rule-save').on('click', function () {
ua.saveSelectedRule();
});
// define the function for filtering the list
$('#rule-filter').keyup(function () {
ua.applyRuleFilter();
});
// filter type
$('#rule-filter-type').combo({
options: [{
text: 'by name',
value: 'name'
}, {
text: 'by condition',
value: 'condition'
}, {
text: 'by action',
value: 'action'
}],
select: function (option) {
ua.applyRuleFilter();
}
});
// show the save button if appropriate
if (ua.editable) {
$('#selected-rule-save').show();
$('#new-rule').show();
$('#new-condition').show();
$('#new-action').show();
// make the combo for the flow file policy
$('#flowfile-policy').combo({
options: [{
text: 'use clone',
value: 'USE_CLONE',
description: 'Matching rules are executed with a copy of the original flowfile.'
}, {
text: 'use original',
value: 'USE_ORIGINAL',
description: 'Matching rules are executed with the original flowfile in the order specified below.'
}],
select: function (selectedOption) {
var selectedFlowFilePolicy = $('#selected-flowfile-policy').text();
// only consider saving the new flowfile policy when appropriate
if (selectedFlowFilePolicy !== '' && selectedFlowFilePolicy !== selectedOption.value) {
var entity = {
processorId: ua.getProcessorId(),
revision: ua.getRevision(),
clientId: ua.getClientId(),
disconnectedNodeAcknowledged: ua.getDisconnectionAcknowledged(),
flowFilePolicy: selectedOption.value
};
$.ajax({
type: 'PUT',
url: 'api/criteria/evaluation-context',
data: JSON.stringify(entity),
processData: false,
contentType: 'application/json'
}).then(function (evaluationContext) {
ua.showMessage('FlowFile Policy saved as "' + selectedOption.text + '".');
// record the newly selected value
$('#selected-flowfile-policy').text(evaluationContext.flowFilePolicy);
}, function (xhr, status, error) {
// show an error message
$('#ok-dialog-content').text('Unable to save new FlowFile Policy due to:' + xhr.responseText);
$('#ok-dialog').modal('setHeaderText', 'Error').modal('show');
});
}
}
});
} else {
// make the rule name read only when not editable
$('#selected-rule-name').attr('readonly', 'readonly');
// make the combo for the flow file policy
$('#flowfile-policy').combo({
options: [{
text: 'use clone',
value: 'USE_CLONE',
description: 'Matching rules are executed with a copy of the original flowfile.',
disabled: true
}, {
text: 'use original',
value: 'USE_ORIGINAL',
description: 'Matching rules are executed with the original flowfile in the order specified below.',
disabled: true
}]
});
}
// load the rules
ua.loadRuleList();
// initialize the tooltips
$('.info').qtip({
style: {
classes: 'ui-tooltip-tipped ui-tooltip-shadow nifi-tooltip'
},
show: {
solo: true,
effect: false
},
hide: {
effect: false
},
position: {
at: 'bottom right',
my: 'top left'
}
});
},
/**
* Initializes the new rule dialog.
*
* @returns {undefined}
*/
initNewRuleDialog: function () {
// new rule dialog configuration
$('#new-rule-dialog').modal({
headerText: 'Add Rule',
scrollableContentStyle: 'scrollable',
overlayBackground: false,
buttons: [{
buttonText: 'Add',
color: {
base: '#728E9B',
hover: '#004849',
text: '#ffffff'
},
handler: {
click: function () {
var ruleName = $('#new-rule-name').val();
var copyFromRuleField = $('#copy-from-rule-name');
var copyFromRuleAutoComplete = copyFromRuleField.data('copy-from-rule');
var copyFromRuleName = copyFromRuleField.val();
$.Deferred(function (deferred) {
// rule name must be specified
if (ruleName === '') {
deferred.rejectWith(this, ['The rule name must be specified.']);
return;
}
// use the rule from autocomplete if present
if (typeof copyFromRuleAutoComplete !== 'undefined' && copyFromRuleAutoComplete !== null) {
deferred.resolveWith(this, [copyFromRuleAutoComplete]);
return;
}
// use no existing rule
if (copyFromRuleField.hasClass('search') || copyFromRuleName === '') {
deferred.resolve();
return;
}
// query to get the details on the specified rule
$.ajax({
type: 'GET',
data: {
processorId: ua.getProcessorId(),
q: copyFromRuleName
},
dataType: 'json',
url: 'api/criteria/rules/search-results'
}).then(function (response) {
var rules = response.rules;
if ($.isArray(rules)) {
if (rules.length > 1) {
deferred.rejectWith(this, ['Unable to copy existing rule. Multiple rules match the name "' + copyFromRuleName + '".']);
} else if (rules.length === 0 || rules[0].name !== copyFromRuleName) {
deferred.rejectWith(this, ['Unable to copy existing rule. Specified rule "' + copyFromRuleName + '" does not exist.']);
} else {
deferred.resolveWith(this, [rules[0]]);
}
}
}, function (xhr, status, error) {
deferred.rejectWith(this, [xhr.responseText]);
});
}).then(function (copyFromRule) {
// add the new rule
var ruleElement = ua.createNewRuleItem({
id: 'unsaved-rule-' + (ua.newRuleIndex++),
name: ruleName
});
// select the new rule
ruleElement.click();
// if we are copying from another rule load the details
if (typeof copyFromRule !== 'undefined' && copyFromRule !== null) {
var conditionsGrid = $('#selected-rule-conditions').data('gridInstance');
var conditionsData = conditionsGrid.getData();
conditionsData.setItems(copyFromRule.conditions);
var actionsGrid = $('#selected-rule-actions').data('gridInstance');
var actionsData = actionsGrid.getData();
actionsData.setItems(copyFromRule.actions);
}
// mark the rule as modified
$('#rule-list').children('li.selected').addClass('unsaved');
// ensure the rule list is visible
if ($('#no-rules').is(':visible')) {
ua.showRuleList();
} else {
// re-apply the rule filter
ua.applyRuleFilter();
}
}, function (error) {
$('#ok-dialog-content').text(error);
$('#ok-dialog').modal('setHeaderText', 'Configuration Error').modal('show');
});
// close the dialog
$('#new-rule-dialog').modal('hide');
}
}
}, {
buttonText: 'Cancel',
color: {
base: '#E3E8EB',
hover: '#C7D2D7',
text: '#004849'
},
handler: {
click: function () {
// close the dialog
$('#new-rule-dialog').modal('hide');
}
}
}],
handler: {
close: function () {
// reset the content
$('#new-rule-name').val('');
$('#copy-from-rule-name').removeData('copy-from-rule').val('');
}
}
});
// initialize the access control auto complete
$.widget('nf.copyFromRuleAutocomplete', $.ui.autocomplete, {
_normalize: function(searchResults) {
var items = [];
items.push(searchResults);
return items;
},
_resizeMenu: function () {
var ul = this.menu.element;
var padding = ($('#copy-from-rule-name').outerWidth()-$('#copy-from-rule-name').width())/2;
ul.width($('#copy-from-rule-name').outerWidth() - padding);
},
_renderMenu: function (ul, items) {
var self = this;
// the object that holds the search results is normalized into a single element array
var searchResults = items[0];
if ($.isArray(searchResults.rules) && searchResults.rules.length > 0) {
// go through each matching rule
$.each(searchResults.rules, function (i, rule) {
// add the user match
self._renderRule(ul, rule);
});
}
// ensure there were some results
if (ul.children().length === 0) {
ul.append('<li class="unset" style="padding: 0.2em 0.4em;"><div>No rules match</div></li>');
}
},
_renderRule: function (ul, ruleMatch) {
var ruleContent = $('<a></a>').append($('<div></div>').text(ruleMatch.name));
return $('<li style="height: 20px;"></li>').data('ui-autocomplete-item', ruleMatch).append(ruleContent).appendTo(ul);
}
});
// configure the autocomplete field
$('#copy-from-rule-name').copyFromRuleAutocomplete({
minLength: 0,
appendTo: '#update-attributes-content',
position: {
my: 'left top',
at: 'left bottom',
offset: '0 1'
},
source: function (request, response) {
// create the search request
$.ajax({
type: 'GET',
data: {
processorId: ua.getProcessorId(),
q: request.term
},
dataType: 'json',
url: 'api/criteria/rules/search-results'
}).done(function (searchResponse) {
response(searchResponse);
});
},
select: function (event, ui) {
var rule = ui.item;
// store the selected rule
$(this).data('copy-from-rule', rule).val(rule.name);
// stop event propagation
return false;
}
});
},
/**
* Initializes the new condition dialog.
*/
initNewConditionDialog: function () {
var add = function () {
var conditionExpression = $('#new-condition-expression').nfeditor('getValue');
// ensure the appropriate details have been specified
if (conditionExpression === '') {
$('#ok-dialog-content').text('Expression is required.');
$('#ok-dialog').modal('setHeaderText', 'Configuration Error').modal('show');
} else {
var condition = {
expression: conditionExpression
};
var entity = {
processorId: ua.getProcessorId(),
revision: ua.getRevision(),
clientId: ua.getClientId(),
condition: condition
};
// create the condition
$.ajax({
type: 'POST',
url: 'api/criteria/rules/conditions',
data: JSON.stringify(entity),
processData: false,
contentType: 'application/json'
}).then(function (response) {
var conditionsGrid = $('#selected-rule-conditions').data('gridInstance');
var conditionsData = conditionsGrid.getData();
// add the new condition
conditionsData.addItem(response.condition);
// mark the selected rule as unsaved
$('#rule-list').children('li.selected').addClass('unsaved');
// only hide the the dialog once the condition has been validated
$('#new-condition-dialog').hide();
}, function (xhr, status, error) {
$('#ok-dialog-content').text(xhr.responseText);
$('#ok-dialog').modal('setHeaderText', 'Configuration Error').modal('show');
});
}
};
var cancel = function () {
// close the dialog
$('#new-condition-dialog').hide();
};
// create the editor
$('#new-condition-expression').addClass('nf-editor').nfeditor({
languageMode: nf.nfel,
width: 374,
minWidth: 374,
height: 135,
minHeight: 135,
resizable: true,
escape: cancel,
enter: add
});
// new condition dialog configuration
$('#new-condition-dialog').draggable({
cancel: 'input, textarea, pre, .button, .nf-editor',
containment: 'parent'
}).on('click', '#new-condition-add', add).on('click', '#new-condition-cancel', cancel);
},
/**
* Initializes the new action dialog.
*/
initNewActionDialog: function () {
var add = function () {
var actionAttribute = $('#new-action-attribute').val();
var actionValue = $('#new-action-value').nfeditor('getValue');
// ensure the appropriate details have been specified
if (actionAttribute === '') {
$('#ok-dialog-content').text('Attribute name is required.');
$('#ok-dialog').modal('setHeaderText', 'Configuration Error').modal('show');
} else {
var action = {
attribute: actionAttribute,
value: actionValue
};
var entity = {
processorId: ua.getProcessorId(),
revision: ua.getRevision(),
clientId: ua.getClientId(),
action: action
};
// create the condition
$.ajax({
type: 'POST',
url: 'api/criteria/rules/actions',
data: JSON.stringify(entity),
processData: false,
contentType: 'application/json'
}).then(function (response) {
var actionsGrid = $('#selected-rule-actions').data('gridInstance');
var actionsData = actionsGrid.getData();
// add the new condition
actionsData.addItem(response.action);
// mark the selected rule as unsaved
$('#rule-list').children('li.selected').addClass('unsaved');
// only close the dialog once the action has been validated
$('#new-action-dialog').hide();
}, function (xhr, status, error) {
$('#ok-dialog-content').text(xhr.responseText);
$('#ok-dialog').modal('setHeaderText', 'Configuration Error').modal('show');
});
}
};
var cancel = function () {
// close the dialog
$('#new-action-dialog').hide();
};
// create the editor
$('#new-action-value').addClass('nf-editor').nfeditor({
languageMode: nf.nfel,
width: 374,
minWidth: 374,
height: 135,
minHeight: 135,
resizable: true,
escape: cancel,
enter: add
});
// configuration the dialog
$('#new-action-dialog').draggable({
cancel: 'input, textarea, pre, .button, .nf-editor',
containment: 'parent'
}).on('click', '#new-action-add', add).on('click', '#new-action-cancel', cancel);
// enable tabs in the property value
$('#new-action-attribute').on('keydown', function (e) {
if (e.which === $.ui.keyCode.ENTER && !e.shiftKey) {
add();
} else if (e.which === $.ui.keyCode.ESCAPE) {
e.preventDefault();
cancel();
}
});
},
/**
* Configure the ok dialog.
*
* @returns {undefined}
*/
initOkDialog: function () {
$('#ok-dialog').modal({
overlayBackground: false,
scrollableContentStyle: 'scrollable',
buttons: [{
buttonText: 'Ok',
color: {
base: '#728E9B',
hover: '#004849',
text: '#ffffff'
},
handler: {
click: function () {
// close the dialog
$('#ok-dialog').modal('hide');
}
}
}],
handler: {
close: function () {
// clear the content
$('#ok-dialog-content').empty();
}
}
});
},
/**
* Configure the yes no dialog.
*
* @returns {undefined}
*/
initYesNoDialog: function () {
$('#yes-no-dialog').modal({
scrollableContentStyle: 'scrollable',
overlayBackground: false
});
},
/**
* Initializes the conditions grid.
*
* @returns {undefined}
*/
initConditionsGrid: function () {
// custom formatter for the actions column
var conditionsActionFormatter = function (row, cell, value, columnDef, dataContext) {
return '<div title="Delete" class="pointer fa fa-close" onclick="javascript:ua.deleteRow(\'#selected-rule-conditions\', \'' + row + '\');"></div>';
};
// initialize the conditions grid
var conditionsColumns = [
{id: "expression", name: "Expression", field: "expression", sortable: true, cssClass: 'pointer', editor: ua.getNfelEditor, validator: ua.requiredFieldValidator}
];
var conditionsOptions = {
autosizeColsMode: Slick.GridAutosizeColsMode.LegacyForceFit,
enableCellNavigation: true,
enableColumnReorder: false,
enableAddRow: false,
autoEdit: false
};
if (ua.editable) {
// add the delete column
conditionsColumns.push({id: "actions", name: "&nbsp;", formatter: conditionsActionFormatter, resizable: false, sortable: true, width: 50, maxWidth: 50});
// make the table editable
conditionsOptions = $.extend({
editable: true
}, conditionsOptions);
}
// initialize the dataview
var conditionsData = new Slick.Data.DataView({inlineFilters: false});
conditionsData.setItems([]);
// initialize the grid
var conditionsGrid = new Slick.Grid('#selected-rule-conditions', conditionsData, conditionsColumns, conditionsOptions);
conditionsGrid.setSelectionModel(new Slick.RowSelectionModel());
conditionsGrid.onBeforeEditCell.subscribe(function (e, args) {
return !ua.preventEdit(e, args);
});
conditionsGrid.onCellChange.subscribe(function (e, args) {
$('#rule-list').children('li.selected').addClass('unsaved');
});
conditionsGrid.onSort.subscribe(function (e, args) {
var comparer = function (a, b) {
return a[args.sortCol.field] > b[args.sortCol.field];
};
conditionsData.sort(comparer, args.sortAsc);
});
conditionsGrid.onClick.subscribe(function (e, args) {
if (ua.editable) {
// edits the clicked cell
conditionsGrid.gotoCell(args.row, args.cell, true);
} else {
ua.showValue(conditionsGrid, args.row, args.cell);
}
// prevents standard edit logic
e.stopImmediatePropagation();
});
if (ua.editable) {
conditionsGrid.onBeforeCellEditorDestroy.subscribe(function (e, args) {
setTimeout(function() {
conditionsGrid.resizeCanvas();
var actionsGrid = $('#selected-rule-actions').data('gridInstance');
actionsGrid.resizeCanvas();
}, 50);
});
}
// wire up the dataview to the grid
conditionsData.onRowCountChanged.subscribe(function (e, args) {
conditionsGrid.updateRowCount();
conditionsGrid.render();
});
conditionsData.onRowsChanged.subscribe(function (e, args) {
conditionsGrid.invalidateRows(args.rows);
conditionsGrid.render();
});
// hold onto an instance of the grid
$('#selected-rule-conditions').data('gridInstance', conditionsGrid);
return conditionsGrid;
},
/**
* Initializes the actions grid.
*/
initActionsGrid: function () {
// custom formatter for the actions column
var actionsActionFormatter = function (row, cell, value, columnDef, dataContext) {
return '<div title="Delete" class="pointer fa fa-close" onclick="javascript:ua.deleteRow(\'#selected-rule-actions\', \'' + row + '\');"></div>';
};
// initialize the actions grid
var actionsColumns = [
{id: "attribute", name: "Attribute", field: "attribute", sortable: true, cssClass: 'pointer', editor: ua.getCustomLongTextEditor, validator: ua.requiredFieldValidator},
{id: "value", name: "Value", field: "value", sortable: true, cssClass: 'pointer', editor: ua.getNfelEditor, validator: ua.requiredFieldValidator}
];
var actionsOptions = {
autosizeColsMode: Slick.GridAutosizeColsMode.LegacyForceFit,
enableCellNavigation: true,
enableColumnReorder: false,
enableAddRow: false,
autoEdit: false
};
if (ua.editable) {
// add the delete column
actionsColumns.push({id: "actions", name: "&nbsp;", formatter: actionsActionFormatter, resizable: false, sortable: true, width: 50, maxWidth: 50});
// make the table editable
actionsOptions = $.extend({
editable: true
}, actionsOptions);
}
// initialize the dataview
var actionsData = new Slick.Data.DataView({inlineFilters: false});
actionsData.setItems([]);
// initialize the grid
var actionsGrid = new Slick.Grid('#selected-rule-actions', actionsData, actionsColumns, actionsOptions);
actionsGrid.setSelectionModel(new Slick.RowSelectionModel());
actionsGrid.onBeforeEditCell.subscribe(function (e, args) {
return !ua.preventEdit(e, args);
});
actionsGrid.onCellChange.subscribe(function (e, args) {
$('#rule-list').children('li.selected').addClass('unsaved');
});
actionsGrid.onSort.subscribe(function (e, args) {
var comparer = function (a, b) {
return a[args.sortCol.field] > b[args.sortCol.field];
};
actionsData.sort(comparer, args.sortAsc);
});
actionsGrid.onClick.subscribe(function (e, args) {
if (ua.editable) {
// edits the clicked cell
actionsGrid.gotoCell(args.row, args.cell, true);
} else {
ua.showValue(actionsGrid, args.row, args.cell);
}
// prevents standard edit logic
e.stopImmediatePropagation();
});
if (ua.editable) {
actionsGrid.onBeforeCellEditorDestroy.subscribe(function (e, args) {
setTimeout(function() {
actionsGrid.resizeCanvas();
var conditionsGrid = $('#selected-rule-conditions').data('gridInstance');
conditionsGrid.resizeCanvas();
}, 50);
});
}
// wire up the dataview to the grid
actionsData.onRowCountChanged.subscribe(function (e, args) {
actionsGrid.updateRowCount();
actionsGrid.render();
});
actionsData.onRowsChanged.subscribe(function (e, args) {
actionsGrid.invalidateRows(args.rows);
actionsGrid.render();
});
// hold onto an instance of the grid
$('#selected-rule-actions').data('gridInstance', actionsGrid);
return actionsGrid;
},
/**
* Initializes the rule list.
*
* @returns {undefined}
*/
initRuleList: function () {
var conditionsGrid = $('#selected-rule-conditions').data('gridInstance');
var actionsGrid = $('#selected-rule-actions').data('gridInstance');
// handle rule clicks
var ruleList = $('#rule-list');
// conditionally support reordering
if (ua.editable) {
// make the list sortable
ruleList.sortable({
helper: 'clone',
cancel: 'li.unsaved',
update: function (event, ui) {
// attempt save the rule order
ua.saveRuleOrder().fail(function () {
// and if it fails, revert
ruleList.sortable('cancel');
});
}
});
}
ruleList.on('click', 'li', function () {
var li = $(this);
var rule = li.data('rule');
// get the currently selected rule to see if a change is necessary
var currentlySelectedRuleItem = ruleList.children('li.selected');
// dont do anything if this is already selected
if (li.attr('id') === currentlySelectedRuleItem.attr('id')) {
return;
}
// handle saving if necessary
var saveModifiedRule = $.Deferred(function (deferred) {
if (currentlySelectedRuleItem.length) {
// if we're editable, ensure any active edits are committed before continuing
if (ua.editable) {
// commit any condition edits
var conditionsEditController = conditionsGrid.getEditController();
conditionsEditController.commitCurrentEdit();
// commit any action edits
var actionsEditController = actionsGrid.getEditController();
actionsEditController.commitCurrentEdit();
}
// get the currently selected rule
var currentlySelectedRule = currentlySelectedRuleItem.data('rule');
// determine if the currently selected rule has been modified
if (currentlySelectedRuleItem.hasClass('unsaved')) {
$('#yes-no-dialog-content').text('Rule \'' + currentlySelectedRule.name + '\' has unsaved changes. Do you want to save?');
$('#yes-no-dialog').modal('setHeaderText', 'Save Changes').modal('setButtonModel', [{
buttonText: 'Yes',
color: {
base: '#728E9B',
hover: '#004849',
text: '#ffffff'
},
handler: {
click: function () {
// close the dialog
$('#yes-no-dialog').modal('hide');
// save the previous rule
ua.saveSelectedRule().then(function () {
deferred.resolve();
}, function () {
deferred.reject();
});
}
}
}, {
buttonText: 'No',
color: {
base: '#E3E8EB',
hover: '#C7D2D7',
text: '#004849'
},
handler: {
click: function () {
// close the dialog
$('#yes-no-dialog').modal('hide');
// since changes are being discarded, remove the modified indicator when the rule has been previously saved
if (currentlySelectedRuleItem.attr('id').indexOf('unsaved-rule') === -1) {
currentlySelectedRuleItem.removeClass('unsaved');
}
// no save selected... resolve
deferred.resolve();
}
}
}]).modal('show');
} else {
deferred.resolve();
}
} else {
deferred.resolve();
}
}).promise();
// ensure any modified rule is saved before continuing
saveModifiedRule.done(function () {
// select the specified rule
ua.selectRule(rule).done(function (rule) {
// update the selection
li.data('rule', rule).addClass('selected').siblings().removeClass('selected');
});
});
}).on('click', 'div.remove-rule', function (e) {
var li = $(this).closest('li');
var rule = li.data('rule');
// remove the rule
ua.deleteRule(rule).done(function () {
li.remove();
// attempt to get the first visible rule
var firstVisibleRule = ruleList.children('li:visible:first');
if (firstVisibleRule.length === 1) {
firstVisibleRule.click();
} else {
// only hide the rule list when we know there are no rules (could be filtered out)
if (ruleList.is(':empty')) {
// update the rule list visibility
ua.hideRuleList();
// clear the selected rule id
$('#selected-rule-id').text('');
}
// clear the rule details
ua.clearRuleDetails();
}
// re-apply the rule filter
ua.applyRuleFilter();
});
// stop event propagation;
e.stopPropagation();
}).children(':first').click();
},
/**
* Saves the current rule order
*/
saveRuleOrder: function () {
var ruleList = $('#rule-list');
// get the proper order
var ruleOrder = ruleList.sortable('toArray');
// only include existing rules
var existingRuleOrder = $.grep(ruleOrder, function (ruleId) {
return ruleId.indexOf('unsaved-rule-') === -1;
});
var entity = {
processorId: ua.getProcessorId(),
revision: ua.getRevision(),
clientId: ua.getClientId(),
disconnectedNodeAcknowledged: ua.getDisconnectionAcknowledged(),
ruleOrder: existingRuleOrder
};
return $.ajax({
type: 'PUT',
url: 'api/criteria/evaluation-context',
data: JSON.stringify(entity),
processData: false,
contentType: 'application/json'
}).then(function () {
ua.showMessage('New rule ordering saved.');
}, function (xhr, status, error) {
// show an error message
$('#ok-dialog-content').text('Unable to reorder the rules due to:' + xhr.responseText);
$('#ok-dialog').modal('setHeaderText', 'Error').modal('show');
});
},
/**
* Clears the rule details.
*/
clearRuleDetails: function () {
var conditionsGrid = $('#selected-rule-conditions').data('gridInstance');
var actionsGrid = $('#selected-rule-actions').data('gridInstance');
if (ua.editable) {
// cancel any condition edits
var conditionsEditController = conditionsGrid.getEditController();
conditionsEditController.cancelCurrentEdit();
// cancel any action edits
var actionsEditController = actionsGrid.getEditController();
actionsEditController.cancelCurrentEdit();
} else {
// ensure all detail dialogs are closed
ua.removeAllDetailDialogs();
}
// update the selected rule name
$('#selected-rule-name').val('').hide();
$('#no-rule-selected-label').show();
// clear the grids
var conditionsData = conditionsGrid.getData();
conditionsData.setItems([]);
var actionsData = actionsGrid.getData();
actionsData.setItems([]);
},
/**
* Loads the rule list.
*
* @returns {undefined}
*/
loadRuleList: function () {
var ruleList = $.ajax({
type: 'GET',
url: 'api/criteria/rules?' + $.param({
processorId: ua.getProcessorId(),
verbose: true
})
}).done(function (response) {
var rules = response.rules;
// populate the rules
if (rules && rules.length > 0) {
// add each rules
$.each(rules, function (_, rule) {
ua.createNewRuleItem(rule);
});
// show the listing
ua.showRuleList();
// select the first rule
$('#rule-list').children('li:visible:first').click();
} else {
ua.hideRuleList();
}
});
var evaluationContext = $.ajax({
type: 'GET',
url: 'api/criteria/evaluation-context?' + $.param({
processorId: ua.getProcessorId()
})
}).done(function (evaluationContext) {
// record the currently selected value
$('#selected-flowfile-policy').text(evaluationContext.flowFilePolicy);
// populate the control
$('#flowfile-policy').combo('setSelectedOption', {
value: evaluationContext.flowFilePolicy
});
});
// allow the rule list and evaluation context to load
return $.Deferred(function (deferred) {
$.when(ruleList, evaluationContext).then(function () {
deferred.resolve();
}, function () {
$('#ok-dialog-content').text('Unable to load the rule list and evalaution criteria.');
$('#ok-dialog').modal('setHeaderText', 'Error').modal('show');
deferred.reject();
});
}).promise();
},
/**
* Selects the specified rule and populates its details.
*
* @param {object} rule
* @returns
*/
selectRule: function (rule) {
var ruleId = rule.id;
var conditionsGrid = $('#selected-rule-conditions').data('gridInstance');
var conditionsData = conditionsGrid.getData();
var actionsGrid = $('#selected-rule-actions').data('gridInstance');
var actionsData = actionsGrid.getData();
return $.Deferred(function (deferred) {
// if this is an existing rule, load it
if (ruleId.indexOf('unsaved-rule-') === -1) {
$.ajax({
type: 'GET',
url: 'api/criteria/rules/' + encodeURIComponent(ruleId) + '?' + $.param({
processorId: ua.getProcessorId(),
verbose: true
})
}).then(function (response) {
deferred.resolveWith(this, [response.rule]);
}, function () {
// show an error message
$('#ok-dialog-content').text('Unable to load details for rule \'' + rule.name + '\'.');
$('#ok-dialog').modal('setHeaderText', 'Error').modal('show');
// reject the deferred
deferred.reject();
});
} else {
deferred.resolveWith(this, [$.extend({
conditions: [],
actions: []
}, rule)]);
}
}).done(function (selectedRule) {
if (!ua.editable) {
// if we are in read only mode, ensure there are no lingering pop ups
ua.removeAllDetailDialogs();
}
// populate the rule details
$('#selected-rule-id').text(selectedRule.id);
$('#selected-rule-name').val(selectedRule.name).show();
$('#no-rule-selected-label').hide();
// populate the rule conditions
conditionsGrid.setSortColumn('expression', true);
conditionsData.setItems(selectedRule.conditions);
conditionsGrid.invalidate();
// populate the rule actions
actionsGrid.setSortColumn('attribute', true);
actionsData.setItems(selectedRule.actions);
actionsGrid.invalidate();
}).promise();
},
/**
* Deletes the specified rule.
*
* @param {type} rule
* @returns
*/
deleteRule: function (rule) {
var ruleId = rule.id;
return $.Deferred(function (deferred) {
// confirm the rule deletion
$('#yes-no-dialog-content').text('Delete rule \'' + rule.name + '\'?');
$('#yes-no-dialog').modal('setHeaderText', 'Delete Confirmation').modal('setButtonModel', [{
buttonText: 'Yes',
color: {
base: '#728E9B',
hover: '#004849',
text: '#ffffff'
},
handler: {
click: function () {
// close the dialog
$('#yes-no-dialog').modal('hide');
// if this is an existing rule, delete it
if (ruleId.indexOf('unsaved-rule-') === -1) {
$.ajax({
type: 'DELETE',
url: 'api/criteria/rules/' + encodeURIComponent(ruleId) + '?' + $.param({
processorId: ua.getProcessorId(),
revision: ua.getRevision(),
clientId: ua.getClientId(),
disconnectedNodeAcknowledged: ua.getDisconnectionAcknowledged(),
verbose: true
})
}).then(function () {
ua.showMessage('Rule \'' + rule.name + '\' was deleted successfully.');
deferred.resolve();
}, function (xhr, status, error) {
$('#ok-dialog-content').text('Unable to delete the rule "' + rule.name + '" because ' + xhr.responseText);
$('#ok-dialog').modal('setHeaderText', 'Error').modal('show');
deferred.rejectWith(this, arguments);
});
} else {
deferred.resolve();
}
}
}
}, {
buttonText: 'No',
color: {
base: '#E3E8EB',
hover: '#C7D2D7',
text: '#004849'
},
handler: {
click: function () {
// close the dialog
$('#yes-no-dialog').modal('hide');
// no save selected... resolve
deferred.reject();
}
}
}]).modal('show');
}).promise();
},
/**
* Saves the currently selected rule.
*
* @returns {unresolved}
*/
saveSelectedRule: function () {
var ruleId = $('#selected-rule-id').text();
var conditionsGrid = $('#selected-rule-conditions').data('gridInstance');
var conditionsData = conditionsGrid.getData();
var actionsGrid = $('#selected-rule-actions').data('gridInstance');
var actionsData = actionsGrid.getData();
// ensure a rule was populated
if (ruleId === '') {
$('#ok-dialog-content').text('No rule is selected.');
$('#ok-dialog').modal('setHeaderText', 'Configuration Error').modal('show');
return;
}
// commit any condition edits
var conditionsEditController = conditionsGrid.getEditController();
conditionsEditController.commitCurrentEdit();
// commit any action edits
var actionsEditController = actionsGrid.getEditController();
actionsEditController.commitCurrentEdit();
// marshal the rule
var rule = {
name: $('#selected-rule-name').val(),
conditions: conditionsData.getItems(),
actions: actionsData.getItems()
};
// marshal the entity
var entity = {
processorId: ua.getProcessorId(),
clientId: ua.getClientId(),
revision: ua.getRevision(),
disconnectedNodeAcknowledged: ua.getDisconnectionAcknowledged(),
rule: rule
};
// determine the type of request to make
var url = 'api/criteria/rules';
var httpMethod = 'POST';
if (ruleId.indexOf('unsaved-rule-') === -1) {
rule['id'] = ruleId;
httpMethod = 'PUT';
url = url + '/' + encodeURIComponent(ruleId);
}
// create/update the rule
return $.ajax({
type: httpMethod,
url: url,
data: JSON.stringify(entity),
processData: false,
contentType: 'application/json'
}).then(function (response) {
var rule = response.rule;
// update the id of the rule
$('#selected-rule-id').text(rule.id);
// update the rule item
var selectedRuleItem = $('#rule-list').children('li.selected');
selectedRuleItem.data('rule', rule).attr('id', rule.id).removeClass('unsaved').children('div.rule-label').text(rule.name);
// indicate that that message was saved
ua.showMessage('Rule \'' + rule.name + '\' was saved successfully.');
}, function (xhr, status, error) {
$('#ok-dialog-content').text(xhr.responseText);
$('#ok-dialog').modal('setHeaderText', 'Error').modal('show');
});
},
/**
* Deletes the specified row from the specified grid.
*
* @param {type} gridSelector
* @param {type} row
* @returns {undefined}
*/
deleteRow: function (gridSelector, row) {
var grid = $(gridSelector).data('gridInstance');
var data = grid.getData();
var item = data.getItem(row);
data.deleteItem(item.id);
// mark the rule as modified
$('#rule-list').children('li.selected').addClass('unsaved');
},
/**
* Creates a new rule and adds it to the rule list.
*
* @param {type} rule
*/
createNewRuleItem: function (rule) {
var ruleList = $('#rule-list');
// create the rule item
var ruleLabel = $('<div></div>').addClass('rule-label ellipsis').text(rule.name).ellipsis();
var ruleItem = $('<li></li>').attr('id', rule.id).data('rule', rule).append(ruleLabel).appendTo(ruleList);
if (ua.editable) {
$('<div></div>').addClass('remove-rule fa fa-close').appendTo(ruleItem);
} else {
// remove the pointer cursor when not editable
ruleItem.css('cursor', 'default');
}
// apply the ellipsis
ruleLabel.attr('title', rule.name).ellipsis();
return ruleItem;
},
/**
* Hides the rule list.
*
* @returns {undefined}
*/
hideRuleList: function () {
$('#rule-list-container').hide();
$('#no-rules').show();
$('#rule-filter-controls').hide();
},
/**
* Shows the rule list.
*
* @returns {undefined}
*/
showRuleList: function () {
$('#rule-list-container').show();
$('#no-rules').hide();
$('#rule-filter-controls').show();
// apply the filter
ua.applyRuleFilter();
},
// Rule filter functions.
/**
* Get the filter text.
*
* @returns {unresolved}
*/
getFilterText: function () {
return $('#rule-filter').val();
},
/**
* Get the text for the rule to be filtered.
*
* @param {type} li
* @returns {Array}
*/
getRuleText: function (li) {
var rule = li.data('rule');
var filterType = $('#rule-filter-type').combo('getSelectedOption');
// determine the filter type (name, condition, action)
if (filterType.value === 'name') {
return [rule.name];
} else if (filterType.value === 'condition') {
var conditions = [];
$.each(rule.conditions, function (_, condition) {
conditions.push(condition.expression);
});
return conditions;
} else {
var actions = [];
$.each(rule.actions, function (_, action) {
actions.push(action.attribute);
actions.push(action.value);
});
return actions;
}
},
/**
* Apply the rule filter.
*
* @returns {undefined}
*/
applyRuleFilter: function () {
var ruleList = $('#rule-list');
var ruleItems = ruleList.children();
var filter = ua.getFilterText();
var matchingRules;
if (filter !== '') {
matchingRules = 0;
// determines if the specified str matches the filter
var matchRuleText = function (ruleText) {
try {
var filterExp = new RegExp(filter, 'i');
return ruleText.search(filterExp) >= 0;
} catch (e) {
// the regex is invalid
return false;
}
};
// update the displayed rule count
$.each(ruleItems, function (_, ruleItem) {
var li = $(ruleItem);
// get the rule text for matching
var ruleTextList = ua.getRuleText(li);
// see if any of the text from this rule matches
var ruleMatches = false;
$.each(ruleTextList, function (_, ruleText) {
// update the count and item visibility as appropriate
if (matchRuleText(ruleText)) {
ruleMatches = true;
// stop iteration
return false;
}
});
// handle whether the rule matches
if (ruleMatches || li.hasClass('unsaved')) {
li.show();
matchingRules++;
} else {
// if we are hiding the currently selected rule, clear it
if (li.hasClass('selected')) {
ua.clearRuleDetails();
}
// hide the rule
li.removeClass('selected').hide();
}
});
} else {
// ensure every rule is visible
ruleItems.show();
// set the number of displayed rules
matchingRules = ruleItems.length;
}
// update the rule count
$('#displayed-rules').text(matchingRules);
$('#total-rules').text(ruleItems.length);
},
/**
* Adds a hover effects to the specified selector.
*
* @param {type} selector
* @param {type} normalStyle
* @param {type} overStyle
*/
addHoverEffect: function (selector, normalStyle, overStyle) {
$(document).on('mouseenter', selector, function () {
$(this).removeClass(normalStyle).addClass(overStyle);
}).on('mouseleave', selector, function () {
$(this).removeClass(overStyle).addClass(normalStyle);
});
return $(selector).addClass(normalStyle);
},
/**
* Shows the specified text and clears it after 10 seconds.
*
* @param {type} text
* @returns {undefined}
*/
showMessage: function (text) {
toggleScrollable($('#message').text(text).get(0));
setTimeout(function () {
toggleScrollable($('#message').text('').get(0));
}, 10000);
},
/**
* Custom validator for required fields.
*
* @param {type} value
*/
requiredFieldValidator: function (value) {
if (value === null || value === undefined || !value.length) {
return {valid: false, msg: "This is a required field"};
} else {
return {valid: true, msg: null};
}
},
/**
* Function for prevent cell editing before a rule is selected.
*
* @param {type} e
* @param {type} args
*/
preventEdit: function (e, args) {
var ruleId = $('#selected-rule-id').text();
if (ruleId === '') {
$('#ok-dialog-content').text('No rule is selected.');
$('#ok-dialog').modal('setHeaderText', 'Configuration Error').modal('show');
return true;
} else {
return false;
}
},
/**
* Shows the property value for the specified row and cell.
*
* @param {slickgrid} grid
* @param {integer} row
* @param {integer} cell
*/
showValue: function (grid, row, cell) {
// remove any currently open detail dialogs
ua.removeAllDetailDialogs();
var container = $('#update-attributes-content');
// get the property in question
var data = grid.getData();
var item = data.getItem(row);
// get the column in question
var columns = grid.getColumns();
var columnDefinition = columns[cell];
var value = item[columnDefinition.field];
// get details about the location of the cell
var cellNode = $(grid.getCellNode(row, cell));
var offset = cellNode.offset();
// create the wrapper
var wrapper = $('<div class="property-detail"></div>').css({
'z-index': 100000,
'position': 'absolute',
'background': 'white',
'padding': '5px',
'overflow': 'hidden',
'border-radius': '2px',
'box-shadow': 'rgba(0, 0, 0, 0.247059) 0px 2px 5px',
'cursor': 'move',
'top': offset.top - 5,
'left': offset.left - 5
}).appendTo(container);
var editor = null;
// the attribute column does not get the nfel editor
if (columnDefinition.id === 'attribute') {
// make it draggable
wrapper.draggable({
containment: 'parent'
});
// create the input field
$('<textarea hidefocus rows="5" readonly="readonly"/>').css({
'width': Math.max((cellNode.width() - 5), 202) + 'px',
'height': '80px',
'overflow-y': 'auto',
'margin-bottom': '35px'
}).text(value).on('keydown', function (evt) {
if (evt.which === $.ui.keyCode.ESCAPE) {
cleanUp();
evt.stopImmediatePropagation();
evt.preventDefault();
}
}).appendTo(wrapper);
} else {
// prevent dragging over the nf editor
wrapper.draggable({
cancel: 'input, textarea, pre, .button, .nf-editor',
containment: 'parent'
});
// create the editor
editor = $('<div></div>').addClass('nf-editor').appendTo(wrapper).nfeditor({
languageMode: nf.nfel,
width: Math.max((cellNode.width() - 5), 200) + 'px',
content: value,
minWidth: 200,
minHeight: 100,
readOnly: true,
resizable: true,
escape: function () {
cleanUp();
}
});
}
var cleanUp = function () {
// clean up the editor
if (editor !== null) {
editor.nfeditor('destroy');
}
// clean up the rest
wrapper.hide().remove();
};
// add an ok button that will remove the entire pop up
var ok = $('<div class="button button-normal">Ok</div>').on('click', function () {
cleanUp();
});
$('<div></div>').css({
'position': 'absolute',
'bottom': '0',
'left': '0',
'right': '0'
}).append(ok).append('<div class="clear"></div>').appendTo(wrapper);
},
/**
* Removes all currently open process property detail dialogs.
*/
removeAllDetailDialogs: function () {
nf.UniversalCapture.removeAllPropertyDetailDialogs();
},
/**
* Gets a custom editor for editing long values.
*
* @param {type} args
*/
getCustomLongTextEditor: function (args) {
var scope = this;
var defaultValue = '';
var wrapper;
var input;
this.init = function () {
var container = $('#update-attributes-content');
// create the wrapper
wrapper = $('<div></div>').addClass('slickgrid-custom-long-text-editor').css({
'z-index': 100000,
'position': 'absolute',
'background': 'white',
'padding': '5px',
'overflow': 'hidden',
'border-radius': '2px',
'box-shadow': 'rgba(0, 0, 0, 0.247059) 0px 2px 5px',
'cursor': 'move',
'transform': 'translate3d(0px, 0px, 0px)'
}).draggable({
containment: 'parent'
}).appendTo(container);
// create the input field
input = $('<textarea hidefocus rows="5"/>').css({
'width': args.position.width + 'px',
'min-width': '202px',
'height': '80px',
'margin-bottom': '35px',
'resize': 'both'
}).on('keydown', scope.handleKeyDown).appendTo(wrapper);
// create the button panel
var ok = $('<div class="button button-normal">Ok</div>').on('click', scope.save);
var cancel = $('<div class="secondary-button button-normal">Cancel</div>').on('click', scope.cancel);
$('<div></div>').css({
'position': 'absolute',
'bottom': '0',
'left': '0',
'right': '0'
}).append(ok).append(cancel).append('<div class="clear"></div>').appendTo(wrapper);
// position and focus
scope.position(args.position);
input.focus().select();
};
this.handleKeyDown = function (e) {
if (e.which === $.ui.keyCode.ENTER && e.ctrlKey) {
scope.save();
} else if (e.which === $.ui.keyCode.ESCAPE) {
e.stopImmediatePropagation();
e.preventDefault();
scope.cancel();
} else if (e.which === $.ui.keyCode.TAB && e.shiftKey) {
e.preventDefault();
args.grid.navigatePrev();
} else if (e.which === $.ui.keyCode.TAB) {
e.preventDefault();
args.grid.navigateNext();
}
};
this.save = function () {
args.commitChanges();
};
this.cancel = function () {
input.val(defaultValue);
args.cancelChanges();
};
this.hide = function () {
wrapper.hide();
};
this.show = function () {
if( $('#new-condition-dialog').is(':visible')){
$('#new-condition-dialog').modal('hide');
}
if( $('#new-action-dialog').is(':visible')){
$('#new-action-dialog').modal('hide');
}
wrapper.show();
};
this.position = function (position) {
wrapper.css({
'top': position.top - 11,
'left': position.left - 5
});
};
this.destroy = function () {
wrapper.remove();
};
this.focus = function () {
input.focus();
};
this.loadValue = function (item) {
input.val(defaultValue = item[args.column.field]);
input.select();
};
this.serializeValue = function () {
return input.val();
};
this.applyValue = function (item, state) {
item[args.column.field] = state;
};
this.isValueChanged = function () {
return (!(input.val() === "" && defaultValue === null)) && (input.val() !== defaultValue);
};
this.validate = function () {
return {
valid: true,
msg: null
};
};
// initialize the custom long text editor
this.init();
},
/**
* Gets a custom editor for editing long values.
*
* @param {type} args
*/
getNfelEditor: function (args) {
var scope = this;
var defaultValue = '';
var wrapper;
var editor;
this.init = function () {
var container = $('#update-attributes-content');
// create the wrapper
wrapper = $('<div></div>').addClass('slickgrid-nf-editor').css({
'z-index': 100000,
'min-width': '200px',
'position': 'absolute',
'background': 'white',
'padding': '5px',
'overflow': 'hidden',
'border-radius': '2px',
'box-shadow': 'rgba(0, 0, 0, 0.247059) 0px 2px 5px',
'cursor': 'move',
'transform': 'translate3d(0px, 0px, 0px)'
}).draggable({
cancel: 'input, textarea, pre, .button, div.nf-editor',
containment: 'parent'
}).appendTo(container);
// create the editor
editor = $('<div></div>').addClass('nf-editor').appendTo(wrapper).nfeditor({
languageMode: nf.nfel,
width: Math.max(args.position.width, 200),
minWidth: 200,
minHeight: 80,
resizable: true,
escape: function () {
scope.cancel();
},
enter: function () {
scope.save();
}
});
// create the button panel
var ok = $('<div class="button button-normal">Ok</div>').on('click', scope.save);
var cancel = $('<div class="secondary-button button-normal">Cancel</div>').on('click', scope.cancel);
$('<div></div>').css({
'position': 'absolute',
'bottom': '0',
'left': '0',
'right': '0'
}).append(ok).append(cancel).append('<div class="clear"></div>').appendTo(wrapper);
// position and focus
scope.position(args.position);
editor.nfeditor('focus').nfeditor('selectAll');
};
this.save = function () {
args.commitChanges();
};
this.cancel = function () {
editor.nfeditor('setValue', defaultValue);
args.cancelChanges();
};
this.hide = function () {
wrapper.hide();
};
this.show = function () {
if( $('#new-condition-dialog').is(':visible')){
$('#new-condition-dialog').modal('hide');
}
if( $('#new-action-dialog').is(':visible')){
$('#new-action-dialog').modal('hide');
}
wrapper.show();
};
this.position = function (position) {
wrapper.css({
'top': position.top - 6,
'left': position.left - 25
});
};
this.destroy = function () {
wrapper.remove();
};
this.focus = function () {
editor.nfeditor('focus');
};
this.loadValue = function (item) {
defaultValue = item[args.column.field];
editor.nfeditor('setValue', defaultValue).nfeditor('selectAll');
};
this.serializeValue = function () {
return editor.nfeditor('getValue');
};
this.applyValue = function (item, state) {
item[args.column.field] = state;
};
this.isValueChanged = function () {
var value = scope.serializeValue();
return (!(value === "" && defaultValue === null)) && (value !== defaultValue);
};
this.validate = function () {
return {
valid: true,
msg: null
};
};
// initialize the custom long text editor
this.init();
},
/**
* Gets the client id.
*
* @returns
*/
getClientId: function () {
return $('#attribute-updater-client-id').text();
},
/**
* Gets the revision.
*
* @returns
*/
getRevision: function () {
return $('#attribute-updater-revision').text();
},
/**
* Gets whether the disconnected node is acknowledged.
*
* @returns
*/
getDisconnectionAcknowledged: function () {
return $('#attribute-updater-disconnected-node-acknowledged').text();
},
/**
* Gets the processor id.
*
* @returns
*/
getProcessorId: function () {
return $('#attribute-updater-processor-id').text();
}
};