release version 1.10.0

This commit is contained in:
2024-12-14 04:07:49 +03:00
parent a5088587f7
commit c6b3d793c4
1916 changed files with 254306 additions and 0 deletions

View File

@ -0,0 +1,58 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-management-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var Entaxy;
(function (Entaxy) {
Entaxy._module.component('entaxyCopyToClipboardButton', {
bindings: {
title: '@',
textToCopy: '<'
},
template:
`
<button type="button" class="btn-clipboard" data-toggle="tooltip" title="{{$ctrl.title}}"
ng-click="$ctrl.copyLocationToClipboard($ctrl.textToCopy)">
<span class="fa fa-copy"></span>
</button>
`,
controller: entaxyCopyToClipboardButtonController
})
.name;
function entaxyCopyToClipboardButtonController($timeout) {
'ngInject';
let ctrl = this;
ctrl.copyLocationToClipboard = function(textToCopy) {
let clipboard = new ClipboardJS('.btn-clipboard', {
text: (trigger) => textToCopy
});
setTimeout(() => clipboard.destroy(), 1000);
}
}
entaxyCopyToClipboardButtonController.$inject = ['$timeout'];
})(Entaxy || (Entaxy = {}));

View File

@ -0,0 +1,158 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-management-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var Entaxy;
(function(Entaxy) {
'use strict';
Entaxy._module.factory('ContextMenuService', function() {
return {
element: null,
menuElement: null
};
}).directive('contextMenu', ['$document', 'ContextMenuService', function($document, ContextMenuService) {
return {
restrict: 'A',
scope: {
'item': '=',
'contextMenuOptions': '='
},
link: function($scope, $element, $attrs) {
function createMenuElement() {
let contextMenuOptions = $scope.contextMenuOptions;
if (contextMenuOptions && contextMenuOptions.length > 0) {
let menuElementContainer = document.createElement("div");
menuElementContainer.id = "context-menu";
menuElementContainer.className = "dropdown";
menuElementContainer.style.position = "fixed";
let menuElement = menuElementContainer.appendChild(document.createElement("ul"));
menuElement.className = "dropdown-menu";
contextMenuOptions.forEach(option => {
let optionElement = menuElement.appendChild(document.createElement("li"));
if (option.divider) {
optionElement.className = 'divider';
} else {
let optionRefElement = optionElement.appendChild(document.createElement("a"));
optionRefElement.appendChild(document.createTextNode(option.name));
optionRefElement.onclick = (event) => handleAction(event, option.actionFn);
}
});
return menuElementContainer;
}
}
function handleAction(event, actionFn) {
event.preventDefault();
event.stopPropagation();
if (event.button === 0) {
if (actionFn) {
actionFn($scope.item);
}
}
handleClickEvent(event);
}
let opened = false;
function open(event, menuElement) {
menuElement.addClass('open');
let viewportHeight =
Math.max(document.documentElement.clientHeight || 0, window.innerHeight || 0);
let viewportWidth =
Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0);
let elementHeight = menuElement[0].scrollHeight;
let elementWidth = menuElement[0].scrollWidth;
let top = event.clientY;
let left = event.clientX;
if (top > (viewportHeight - elementHeight)) {
top -= elementHeight;
}
if (left > (viewportWidth - elementWidth)) {
left -= elementWidth;
}
menuElement.css('top', top + 'px');
menuElement.css('left', left + 'px');
opened = true;
}
function close(menuElement) {
menuElement.removeClass('open');
menuElement.remove();
opened = false;
}
$element.bind('contextmenu', function(event) {
if (ContextMenuService.menuElement !== null) {
close(ContextMenuService.menuElement);
}
$element[0].appendChild(createMenuElement());
ContextMenuService.menuElement = angular.element(
document.getElementById("context-menu")
);
ContextMenuService.element = event.target;
event.preventDefault();
event.stopPropagation();
$scope.$apply(function() {
open(event, ContextMenuService.menuElement);
});
});
function handleKeyUpEvent(event) {
if (opened && event.keyCode === 27) {
$scope.$apply(function() {
close(ContextMenuService.menuElement);
});
}
}
function handleClickEvent(event) {
if (opened && (event.button !== 2 || event.target !== ContextMenuService.element)) {
$scope.$apply(function() {
close(ContextMenuService.menuElement);
});
}
}
$document.bind('keyup', handleKeyUpEvent);
// Firefox treats a right-click as a click and a contextmenu event
// while other browsers just treat it as a contextmenu event
$document.bind('click', handleClickEvent);
$document.bind('contextmenu', handleClickEvent);
$scope.$on('$destroy', function() {
$document.unbind('keyup', handleKeyUpEvent);
$document.unbind('click', handleClickEvent);
$document.unbind('contextmenu', handleClickEvent);
});
}
};
}]).name;
})(Entaxy || (Entaxy = {}));

View File

@ -0,0 +1,85 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-management-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var Entaxy;
(function (Entaxy) {
Entaxy._module
.directive('draggable', function() {
return function(scope, element) {
let el = element[0];
el.draggable = true;
el.addEventListener(
'dragstart',
function(e) {
e.dataTransfer.effectAllowed = 'move';
e.dataTransfer.setData("text/html", e.target.id);
this.classList.add('drag');
return false;
},
false
);
el.addEventListener(
'dragend',
function(e) {
this.classList.remove('drag');
return false;
},
false
);
}
})
.directive('droppable', ['$parse', function ($parse) {
return {
restrict: 'A',
link: function (scope, element, attrs) {
element[0].addEventListener('drop', scope.handleDrop, false);
element[0].addEventListener('dragover', scope.handleDragOver, false);
scope.handleDropFn = $parse(attrs.handleDropFn);
},
controller: ['$scope', function($scope) {
$scope.handleDrop = function (e) {
e.preventDefault();
e.stopPropagation();
if ($scope.handleDropFn) {
let droppedElementId = e.dataTransfer.getData("text/html");
$scope.droppedElementId = droppedElementId;
$scope.handleDropFn($scope);
}
};
$scope.handleDragOver = function (e) {
e.preventDefault();
return;
};
}]
};
}])
.name;
})(Entaxy || (Entaxy = {}));

View File

@ -0,0 +1,54 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-management-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var Entaxy;
(function (Entaxy) {
Entaxy._module
.directive('modalDialog', function(){
return {
restrict: 'AC',
link: function($scope, element) {
var draggableStr = "draggableModal";
var header = $(".modal-header", element);
header.on('mousedown', (mouseDownEvent) => {
var modalDialog = element;
var offset = header.offset();
modalDialog.addClass(draggableStr).parents().on('mousemove', (mouseMoveEvent) => {
$("." + draggableStr, modalDialog.parents()).offset({
top: mouseMoveEvent.pageY - (mouseDownEvent.pageY - offset.top),
left: mouseMoveEvent.pageX - (mouseDownEvent.pageX - offset.left)
});
}).on('mouseup', () => {
modalDialog.removeClass(draggableStr);
});
});
}
}
})
.name;
})(Entaxy || (Entaxy = {}));

View File

@ -0,0 +1,109 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-management-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var Entaxy;
(function (Entaxy) {
Entaxy._module
.directive('entaxyFileDrop', ['$parse', function ($parse) {
return {
restrict: 'A',
replace: false,
require: 'ngModel',
link: function (scope, element, attrs, ngModel) {
let enterTarget = null;
element.on('dragenter', function (e) {
e.preventDefault();
e.stopPropagation();
enterTarget = e.target;
element.addClass('highlighted');
createNotification();
});
element.on('dragover', function (e) {
e.preventDefault();
e.stopPropagation();
});
element.on('dragleave', function (e) {
if (e.target === enterTarget) {
e.preventDefault();
e.stopPropagation();
element.removeClass('highlighted');
removeNotification();
}
});
let notificationContainer = null;
function createNotification() {
if (notificationContainer === null) {
notificationContainer = document.createElement('div');
notificationContainer.className = 'upload-notification';
let span = document.createElement('span');
span.className = 'fa fa-upload';
notificationContainer.appendChild(span);
notificationContainer.appendChild(document.createTextNode('Drop file to upload'));
let elementWidth = element.width();
let offset = 150 + elementWidth/2 + 20;
notificationContainer.style.left = 'calc(100vw - ' + offset + 'px)';
element.append(notificationContainer);
}
}
function removeNotification() {
if (notificationContainer !== null) {
notificationContainer.parentNode.removeChild(notificationContainer);
notificationContainer = null;
}
}
element.on('drop', function (e) {
e.preventDefault();
e.stopPropagation();
element.removeClass('highlighted');
removeNotification();
if (e.originalEvent.dataTransfer && e.originalEvent.dataTransfer.files.length > 0) {
ngModel.$setViewValue(e.originalEvent.dataTransfer.files[0]);
let processFn = $parse(attrs.processFn);
if (processFn) {
processFn(scope);
}
}
return false;
});
}
};
}])
.name;
})(Entaxy || (Entaxy = {}));

View File

@ -0,0 +1,46 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-management-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var Entaxy;
(function (Entaxy) {
Entaxy._module
.directive("setFileModel", function() {
return {
require: "ngModel",
link: function postLink(scope, element, attrs, ngModel) {
element.on("click", function (e) {
element[0].value = null;
})
element.on("change", function(e) {
if (element[0].files[0]) {
ngModel.$setViewValue(element[0].files[0]);
}
})
}
}
})
.name;
})(Entaxy || (Entaxy = {}));

View File

@ -0,0 +1,201 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-management-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var Entaxy;
(function (Entaxy) {
Entaxy._module.component('entaxyExpandableList', {
bindings: {
items: '<',
itemsLabel: '@',
itemsLabelPlural: '@',
filter: '<',
actionButtons: '<',
enableButtonForItemFn: '<',
useToolbar: '<',
toolbarActionButtons: '<',
enableToolbarActionButtons: '<',
showSelectBox: '<',
onCheckBoxChangeFn: '<',
emptyStateConfig: '<'
},
template:
`
<div class="expandable-list-toolbar-container" ng-if="$ctrl.useToolbar">
<pf-toolbar class="entaxy-toolbar" config="$ctrl.toolbarConfig"></pf-toolbar>
</div>
<div class="expandable-list-container">
<pf-list-view class="entaxy-list" items="$ctrl.viewedItems" config="$ctrl.listConfig"
action-buttons="$ctrl.actionButtons" empty-state-config="$ctrl.emptyStateConfig">
<div class="list-view-pf-left ng-if="item.typeIcon">
<span class="{{item.typeIcon}} list-view-pf-icon-sm"></span>
</div>
<div class="list-view-pf-description">
<div class="list-group-item-heading">
{{item.displayName}}
</div>
<div class="list-group-item-text" ng-if="item.text">
{{item.text}}
</div>
</div>
<div class="list-view-pf-additional-info" ng-if="item.additionalInfo">
<div class="list-view-pf-additional-info-item">
{{item.additionalInfo}}
</div>
</div>
<list-expanded-content>
<div class="nested-list">
<pf-list-view class="entaxy-list" items="$parent.item.viewedSublistItems"
config="$ctrl.sublistConfig">
<div class="list-view-pf-left" ng-if="item.typeIcon">
<span class="{{item.typeIcon}} list-view-pf-icon-sm"></span>
</div>
<div class="list-view-pf-description">
<div class="list-group-item-heading">
{{item.displayName}}
</div>
<div class="list-group-item-text" ng-if="item.text">
{{item.text}}
</div>
</div>
<div class="list-view-pf-additional-info" ng-if="item.additionalInfo">
<div class="list-view-pf-additional-info-item">
{{item.additionalInfo}}
</div>
</div>
</pf-list-view>
</div>
</list-expanded-content>
</pf-list-view>
</div>
`,
controller: EntaxyExpandableListController
})
.name;
function EntaxyExpandableListController($scope) {
'ngInject';
let ctrl = this;
ctrl.$onInit = function() {
if (ctrl.useToolbar) {
ctrl.toolbarConfig.filterConfig.itemsLabel = ctrl.itemsLabel ? ctrl.itemsLabel : 'Result';
ctrl.toolbarConfig.filterConfig.itemsLabelPlural = ctrl.itemsLabelPlural ? ctrl.itemsLabelPlural : 'Results';
ctrl.toolbarConfig.actionsConfig = {primaryActions: ctrl.toolbarActionButtons};
$scope.$watch('$ctrl.enableToolbarActionButtons', function (newValue) {
ctrl.toolbarConfig.actionsConfig.primaryActions.forEach(actionButton => {
actionButton.isDisabled = !newValue;
});
});
}
ctrl.listConfig = {
selectionMatchProp: 'name',
selectItems: false,
showSelectBox: false,
useExpandingRows: true
}
let subListConfig = Entaxy.deepCopy(ctrl.listConfig);
if (ctrl.showSelectBox) {
subListConfig.showSelectBox = ctrl.showSelectBox;
subListConfig.onCheckBoxChange = ctrl.onCheckBoxChangeFn;
}
ctrl.sublistConfig = subListConfig;
}
$scope.$watchCollection('$ctrl.items', function (newValue) {
if (newValue && newValue.length > 0) {
ctrl.viewedItems = ctrl.items;
ctrl.viewedItems.forEach(item => {
if (item.sublist) {
item.viewedSublistItems = item.sublist;
}
});
ctrl.toolbarConfig.filterConfig.resultsCount = ctrl.viewedItems.length;
ctrl.listConfig.itemsAvailable = true;
} else {
ctrl.items = [];
ctrl.viewedItems = [];
ctrl.toolbarConfig.filterConfig.resultsCount = 0;
ctrl.listConfig.itemsAvailable = false;
}
});
ctrl.toolbarConfig = {
filterConfig: {
fields: [
{
id: 'displayName',
title: 'Name',
placeholder: 'Search...',
filterType: 'text'
}
],
appliedFilters: [],
onFilterChange: filterChange
},
actionsConfig: {},
isTableView: true
};
function filterChange(filters) {
applyFilters(filters);
ctrl.toolbarConfig.filterConfig.resultsCount = ctrl.viewedItems.length;
};
function applyFilters(filters) {
ctrl.viewedItems = Entaxy.applyFilters(ctrl.items, filters, matchesFilter, returnSublistsToOriginalState);
};
function matchesFilter(item, filter) {
if (ctrl.filter) {
return ctrl.filter(item, filter);
} else {
let match = true;
if (filter.id === 'displayName') {
match = item.displayName.toLowerCase().match(filter.value.toLowerCase()) !== null;
if (!match && item.sublist && item.sublist.length > 0) {
let viewedSublistItems = Entaxy.applyFilters(item.sublist, [ filter ], matchesFilter);
item.viewedSublistItems = viewedSublistItems;
match = viewedSublistItems.length > 0;
}
}
return match;
}
}
function returnSublistsToOriginalState(items) {
items.forEach(item => {
if (item.sublist) {
item.viewedSublistItems = item.sublist;
}
});
}
}
EntaxyExpandableListController.$inject = ['$scope'];
})(Entaxy || (Entaxy = {}));

View File

@ -0,0 +1,163 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-management-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var Entaxy;
(function (Entaxy) {
Entaxy._module.component('entaxyExtendedData', {
template:
`
<div id="entaxy-extended-data" class="entaxy-extended-data" ng-if="$ctrl.messages">
<uib-accordion>
<div uib-accordion-group is-open="$ctrl.isOpen">
<div uib-accordion-heading>
<div class="entaxy-extended-data-short-message {{message.type}}" ng-repeat="message in $ctrl.messages">
{{message.short}}
</div>
</div>
<div class="entaxy-extended-data-messages-container">
<uib-accordion>
<div uib-accordion-group class="entaxy-extended-data-message-container {{message.type}}"
ng-class="{'disabled': !message.extraInfo}"
is-open="message.open" is-disabled="!message.extraInfo"
ng-repeat="message in $ctrl.messages">
<div uib-accordion-heading>
<span class="pficon"
ng-class="{'pficon-edit': !message.type, 'pficon-warning-triangle-o': message.type}"></span>
<span class="entaxy-extended-data-message">{{message.full}}</span>
</div>
<div class="entaxy-extended-data-message-extra-info-container">
<pre>{{message.extraInfo}}</pre>
</div>
</div>
</uib-accordion>
</div>
</div>
</uib-accordion>
</div>
`,
controller: entaxyExtendedDataController
})
.name;
function entaxyExtendedDataController(workspace, $scope, $q, entaxyService, entaxyAttributesCacheService) {
'ngInject';
let ctrl = this;
ctrl.$onInit = function () {
readExtendedData();
$scope.$on('jmxTreeClicked', function () {
readExtendedData();
});
}
function readExtendedData() {
ctrl.messages = undefined;
let selectedMbeanName = workspace.getSelectedMBeanName();
let attributes;
if (selectedMbeanName) {
entaxyAttributesCacheService.setToUpdate(selectedMbeanName);
attributes = entaxyAttributesCacheService.getAttributes(selectedMbeanName);
}
if (attributes && attributes.RuntimeType && attributes.RuntimeType !== Entaxy.RUNTIME_TYPE.ROUTE_CONTAINER) {
let messages = [];
let promises = [];
if (attributes.BundleState) {
let status = attributes.BundleState;
if (status === 'Failure') {
promises.push(entaxyService.getBundleDiag(attributes.BundleId).then(result =>
messages.push(getStatusMessage(status, result))));
} else {
messages.push(getStatusMessage(status));
}
}
promises.push(entaxyService.readExtendedData(selectedMbeanName)
.then(result => {
let extendedData = JSON.parse(result);
if (extendedData.cluster) {
messages.push(getClusterMessage(extendedData.cluster));
}
if (extendedData.applications) {
messages.push(getApplicationsMessage(extendedData.applications.application));
}
}));
$q.all(promises).then(() => {
ctrl.messages = messages;
});
}
}
function getStatusMessage(status, extraInfo) {
return {
short: status.toLowerCase(),
full: 'Status: ' + status,
extraInfo: extraInfo,
type: status === 'Failure' ? 'error' : undefined
};
}
function getClusterMessage(cluster) {
let message = {
short: cluster.objectClusterState,
full: 'Cluster: ',
type: cluster.objectClusterState === Entaxy.OBJECT_CLUSTER_STATE.NON_CLUSTERED ? 'warning' : undefined
};
if (cluster.groups && cluster.groups.length > 0) {
message.full += cluster.groups.join(', ');
} else {
message.full += message.short;
}
return message;
}
function getApplicationsMessage(applications) {
let message = {
short: 'managed',
full: 'Object is installed as a part of the '
};
message.full += applications.length > 1 ? 'applications: ' : 'application: ';
let lastApplicationIndex = applications.length - 1;
for (let i = 0; i < lastApplicationIndex; i++) {
message.full += getApplicationFullName(applications[i]) + ', ';
}
message.full += getApplicationFullName(applications[lastApplicationIndex]);
return message;
}
function getApplicationFullName(application) {
return application.name + ':' + application.version + '/' + application.revision;
}
}
entaxyExtendedDataController.$inject = ['workspace', '$scope', '$q', 'entaxyService', 'entaxyAttributesCacheService'];
})(Entaxy || (Entaxy = {}));

View File

@ -0,0 +1,61 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-management-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var Entaxy;
(function (Entaxy) {
Entaxy._module.component('entaxyFormFieldExtraInfo', {
bindings: {
type: '<',
message: '<'
},
template:
`
<div class="entaxy-field-extra-info-container {{$ctrl.type}}">
<span class="{{$ctrl.iconClass}}"></span>
<span class="entaxy-field-extra-info-message">{{$ctrl.message}}</span>
</div>
`,
controller: entaxyFormFieldExtraInfoController
})
.name;
function entaxyFormFieldExtraInfoController() {
let ctrl = this;
ctrl.$onInit = function () {
ctrl.iconClass = getIconClassByType();
}
function getIconClassByType() {
switch (ctrl.type) {
case Entaxy.NOTIFICATION_TYPE.INFO:
default:
return 'pficon pficon-info';
}
}
}
})(Entaxy || (Entaxy = {}));

View File

@ -0,0 +1,187 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-management-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var Entaxy;
(function (Entaxy) {
Entaxy._module.component('entaxyFormFields', {
bindings: {
items: '<',
errors: '<',
mode: '<',
formController: '<',
updateFieldsAfterSelectionChangeFn: '<'
},
template:
`
<div class="form-group"
ng-class="{'has-error': $ctrl.errors[formField.name] && formField.type !== 'list'}"
ng-repeat="formField in $ctrl.items" ng-if="!formField.isBackRef && !formField.isHidden">
<entaxy-form-field-extra-info class="col-sm-12"
type="formField.ui.fieldExtraInfo.type" message="formField.ui.fieldExtraInfo.message"
ng-if="formField.ui && formField.ui.fieldExtraInfo && formField.ui.fieldExtraInfo.displayOnMode === $ctrl.mode">
</entaxy-form-field-extra-info>
<div class="col-sm-4 label-col" ng-if="!formField.excludeLabel">
<label class="control-label" ng-class="{'required-pf': formField.required}" for="{{formField.name}}">
{{formField.label}}
</label>
<button type="button" class="btn btn-link label-description-popover"
popover-placement="auto top-left" popover-trigger="'outsideClick'"
uib-popover-html="formField.description" ng-if="formField.description">
<span class="pficon pficon-help"></span>
</button>
</div>
<div ng-class="{'col-sm-7': !formField.excludeLabel, 'col-sm-12': formField.excludeLabel}">
<input type="{{formField.type}}" id="{{formField.name}}" placeholder="{{formField.placeholder}}"
ng-class="{'form-control': formField.type !== 'checkbox'}" ng-model="formField.value"
ng-readonly="formField.readOnly" ng-disabled="formField.type === 'checkbox' && formField.readOnly"
ng-if="$ctrl.isSimpleInput(formField)">
<textarea id="{{formField.name}}" class="form-control" ng-model="formField.value"
ng-readonly="formField.readOnly" ng-if="$ctrl.isTextarea(formField)"></textarea>
<entaxy-password-input id="{{formField.name}}" name="formField.name" model="formField.value"
confirmation-model="formField.confirmationValue" readonly="formField.readOnly"
ignore-confirmation-value="formField.ignoreConfirmationValue" errors="$ctrl.errors"
ng-if="$ctrl.isPassword(formField)"></entaxy-password-input>
<entaxy-url-input id="{{formField.name}}" model="formField.value" config="formField.typeInfo"
readonly="formField.readOnly" ng-if="$ctrl.isUrl(formField)"
form-controller="$ctrl.formController"></entaxy-url-input>
<entaxy-select type="formField.type" id="{{formField.name}}" filter="formField.filter"
model="formField.value" options="formField.options" readonly="formField.readOnly"
update-parent-fn="$ctrl.updateFieldsAfterSelectionChangeFn"
update-parent="formField.typeInfo ? formField.typeInfo.updateParentFields : false"
creation-enabled="formField.typeInfo && formField.typeInfo.enablePrivateObjectCreation"
is-empty-included="formField.typeInfo ? formField.typeInfo.isEmptyIncluded : false"
ng-if="$ctrl.isEntaxySelect(formField)" form-controller="$ctrl.formController"></entaxy-select>
<entaxy-select-from-enum id="{{formField.name}}" values="formField.typeInfo.values"
model="formField.value" readonly="formField.readOnly" multiple="formField.typeInfo.multiple"
is-empty-included="formField.typeInfo.isEmptyIncluded"
empty-option-name="formField.typeInfo.emptyOptionName"
ng-if="$ctrl.isSelectFromEnum(formField)"></entaxy-select-from-enum>
<entaxy-xml id="{{formField.name}}" ng-model="formField.value" mode="$ctrl.localMode"
ng-if="$ctrl.isXml(formField)" readonly="formField.readOnly"
form-controller="$ctrl.formController"></entaxy-xml>
<entaxy-list-input id="{{formField.name}}" items="formField.value" ng-if="$ctrl.isList(formField)"
creation-enabled="formField.typeInfo && formField.typeInfo.enablePrivateObjectCreation"
creation-types="formField.typeInfo ? formField.typeInfo.privateObjectTypes : undefined"
item-factory-filter="formField.itemFactoryFilter" mode="$ctrl.mode"
readonly="formField.readOnly" validation="formField.validation"
item-title-template="formField.typeInfo ? formField.typeInfo.itemTitle : undefined"
errors="$ctrl.errors[formField.name]" form-controller="$ctrl.formController"></entaxy-list-input>
<entaxy-resource-input id="{{formField.name}}" name="{{formField.name}}" model="formField.value"
ng-if="$ctrl.isResourceInput(formField)"></entaxy-resource-input>
<entaxy-inner-object-input id="{{formField.name}}" readonly="formField.readOnly"
model="formField.value" mode="$ctrl.mode" type="formField.type" form-controller="$ctrl.formController"
object-factory-filter="formField.objectFactoryFilter" field-name="formField.label"
ng-if="$ctrl.isInnerObjectInput(formField)"></entaxy-inner-object-input>
<entaxy-map-input id="{{formField.name}}" model="formField.value" items="formField.mapItems"
duplicate-keys="formField.duplicateKeys" has-errors="formField.hasErrors" readonly="formField.readOnly"
ng-if="$ctrl.isMapInput(formField)" form-controller="$ctrl.formController"></entaxy-map-input>
<span class="help-block" ng-show="$ctrl.errors[formField.name] && formField.type !== 'list'">
{{$ctrl.errors[formField.name]}}
</span>
</div>
</div>
`,
controller: entaxyFormFieldsController
})
.name;
function entaxyFormFieldsController($scope) {
'ngInject';
let ctrl = this;
ctrl.$onInit = function() {
ctrl.localMode = ctrl.mode === Entaxy.MODAL_MODES.ADD ? Entaxy.MODAL_MODES.EDIT : ctrl.mode;
}
const TYPES = {
PASSWORD: 'password',
ENUM: 'enum',
LIST: 'list',
URL: 'url',
XML_ROUTE: 'xml:route',
RESOURCE: 'resource',
MAP: 'map'
};
ctrl.isSimpleInput = function (formField) {
return !isRuntimeTyped(formField.type)
&& formField.type !== TYPES.PASSWORD
&& formField.type !== TYPES.LIST
&& formField.type !== TYPES.XML_ROUTE
&& formField.type !== TYPES.RESOURCE
&& formField.type !== TYPES.MAP
&& (!formField.typeInfo || (formField.typeInfo && formField.typeInfo.type === 'String'))
&& !formField.useTextarea;
}
ctrl.isTextarea = function (formField) {
return formField.type === 'text' && formField.useTextarea;
}
ctrl.isPassword = function (formField) {
return formField.type === TYPES.PASSWORD;
}
ctrl.isUrl = function (formField) {
return formField.type === TYPES.URL && formField.typeInfo;
}
ctrl.isEntaxySelect = function (formField) {
return isRuntimeTyped(formField.type) && !formField.innerObject;
}
ctrl.isInnerObjectInput = function (formField) {
return isRuntimeTyped(formField.type) && formField.innerObject;
}
ctrl.isSelectFromEnum = function (formField) {
return formField.typeInfo
&& (formField.typeInfo.type === TYPES.ENUM || formField.typeInfo.type === TYPES.LIST)
&& (formField.typeInfo.values || (!formField.typeInfo.values && formField.readOnly));
}
ctrl.isXml = function (formField) {
return formField.type === TYPES.XML_ROUTE;
}
ctrl.isList = function (formField) {
return formField.type === TYPES.LIST;
}
ctrl.isResourceInput = function (formField) {
return formField.type === TYPES.RESOURCE;
}
ctrl.isMapInput = function (formField) {
return formField.type === TYPES.MAP;
}
function isRuntimeTyped(formFieldType) {
return formFieldType.startsWith(Entaxy.RUNTIME_TYPE_PREFIX) ||
formFieldType.startsWith(Entaxy.RUNTIME_TYPE_SECURITY_PREFIX);
}
}
entaxyFormFieldsController.$inject = ['$scope'];
})(Entaxy || (Entaxy = {}));

View File

@ -0,0 +1,107 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-management-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var Entaxy;
(function (Entaxy) {
Entaxy._module.component('entaxyHeader', {
template:
`
<div class="entaxy-header">
<header>
<h1 id="entaxy-header-title" ng-class="{'changed': $ctrl.isChanged}">{{$ctrl.title}}</h1>
<button type="button" class="btn btn-link label-description-popover"
popover-placement="{{$ctrl.popoverPlacement}}" popover-trigger="'outsideClick'"
popover-class="entaxy-header-popover" popover-is-open="$ctrl.isPopoverOpen"
uib-popover="{{$ctrl.objectName}}" ng-if="$ctrl.objectName">
<span class="pficon pficon-info"></span>
</button>
</header>
</div>
`,
controller: entaxyHeaderController
})
.name;
function entaxyHeaderController(workspace, $scope, entaxyPrivateObjectsCacheService) {
'ngInject';
let ctrl = this;
ctrl.$onInit = function () {
let selectedMbean = workspace.getSelectedMBean();
populateData(selectedMbean);
$scope.$on('jmxTreeClicked', function (event, selectedNode) {
populateData(selectedNode);
});
}
$scope.$watch('$ctrl.isPopoverOpen', function (newValue) {
if (newValue) {
let popoverElements = document.getElementsByClassName('entaxy-header-popover');
let popoverElement = popoverElements ? popoverElements[0] : null;
if (popoverElement) {
let infoSpan = document.getElementsByClassName('pficon-info')[0];
let offsetLeft = infoSpan.offsetLeft + 18;
let headerTitle = document.getElementById('entaxy-header-title');
let offsetRight = infoSpan.offsetLeft - headerTitle.offsetLeft + 12;
let header = document.getElementsByClassName('entaxy-header')[0];
let isPositioningLeft = (header.offsetWidth - offsetLeft) >= offsetRight;
ctrl.popoverPlacement = isPositioningLeft ? 'bottom-left' : 'bottom-right';
popoverElement.style.maxWidth = isPositioningLeft ?
'calc(100% - ' + offsetLeft + 'px)' : offsetRight + 'px';
}
}
});
function populateData(selectedNode) {
ctrl.title = selectedNode.title;
ctrl.objectName = selectedNode.objectName;
if (ctrl.objectName) {
ctrl.isChanged = entaxyPrivateObjectsCacheService.isChanged(ctrl.objectName);
} else {
ctrl.isChanged = false;
let parentNode = selectedNode.parent;
if (parentNode && parentNode.objectName &&
entaxyPrivateObjectsCacheService.hasAddedChildren(parentNode.objectName)) {
let addedChildrenInfo = entaxyPrivateObjectsCacheService.getAddedObjectsInfo(parentNode.objectName);
if (addedChildrenInfo.find(addedChildInfo =>
selectedNode.key === parentNode.key + '-' + addedChildInfo.ui.id)) {
ctrl.isChanged = true;
}
}
}
}
}
entaxyHeaderController.$inject = ['workspace', '$scope', 'entaxyPrivateObjectsCacheService'];
})(Entaxy || (Entaxy = {}));

View File

@ -0,0 +1,135 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-management-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var Entaxy;
(function (Entaxy) {
Entaxy._module.component('entaxyInnerObjectInput', {
bindings: {
model: '=',
mode: '<',
type: '<',
objectFactoryFilter: '<',
fieldName: '<',
readonly: '<',
formController: '<'
},
template:
`
<div class="input-with-button">
<input type="text" ng-model="$ctrl.info" ng-class="{'form-control': true}" readonly>
<span class="pficon pficon-delete" ng-click="$ctrl.clear()" ng-if="$ctrl.model"></span>
<button class="entaxy-view-resources-form" ng-click="$ctrl.openModal()"
ng-if="!$ctrl.readonly || $ctrl.model">
{{$ctrl.buttonTitle}}
</button>
</div>
`,
controller: entaxyInnerObjectInputController
})
.name;
function entaxyInnerObjectInputController(workspace, entaxyService, $uibModal) {
'ngInject';
let ctrl = this;
ctrl.$onInit = function () {
if (ctrl.readonly) {
ctrl.mode = Entaxy.MODAL_MODES.VIEW;
}
if (ctrl.model) {
let factory = entaxyService.getFactoryByTitle(ctrl.model.factoryId);
ctrl.info = factory.displayName;
ctrl.buttonTitle = ctrl.mode === Entaxy.MODAL_MODES.VIEW ?
Entaxy.MODAL_MODES.VIEW : Entaxy.MODAL_MODES.EDIT;
} else {
ctrl.mode = Entaxy.MODAL_MODES.ADD;
ctrl.buttonTitle = Entaxy.MODAL_MODES.ADD;
}
}
ctrl.openModal = function() {
$uibModal.open({
component: 'entaxyInnerObjectInputModal',
resolve: {
type: () => ctrl.type,
mode: () => ctrl.mode,
model: () => ctrl.model,
fieldName: () => ctrl.fieldName,
objectFactoryFilter: () => ctrl.objectFactoryFilter,
outerFormController: () => ctrl.formController
},
backdrop: 'static',
size: 'xl',
windowTopClass: 'modal-top-margin-override'
})
.result.then(args => {
changeModelFromArgs(args);
});
}
function changeModelFromArgs(args) {
if (ctrl.model) {
if (ctrl.model.factoryId === args.factoryId.name) {
args.fields.forEach(field => {
if (field.changed) {
ctrl.model.properties[field.name] = field.value;
}
});
} else {
ctrl.model.factoryId = args.factoryId.name;
ctrl.model.properties = {};
args.fields.forEach(field => {
ctrl.model.properties[field.name] = field.value;
});
}
} else {
ctrl.model = {};
ctrl.model.factoryId = args.factoryId.name;
ctrl.model.scope = Entaxy.SCOPE.PRIVATE;
ctrl.model.type = ctrl.type;
ctrl.model.properties = {};
args.fields.forEach(field => {
ctrl.model.properties[field.name] = field.value;
});
ctrl.mode = Entaxy.MODAL_MODES.EDIT;
ctrl.buttonTitle = Entaxy.MODAL_MODES.EDIT;
}
ctrl.info = args.factoryId.displayName;
}
ctrl.clear = function () {
ctrl.model = undefined;
ctrl.info = undefined;
ctrl.mode = Entaxy.MODAL_MODES.ADD;
ctrl.buttonTitle = Entaxy.MODAL_MODES.ADD;
}
}
entaxyInnerObjectInputController.$inject = ['workspace', 'entaxyService', '$uibModal'];
})(Entaxy || (Entaxy = {}));

View File

@ -0,0 +1,190 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-management-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var Entaxy;
(function (Entaxy) {
Entaxy._module.component('entaxyInnerObjectInputModal', {
bindings: {
modalInstance: '<',
resolve: '<'
},
template:
`
<div class="entaxy-modal-container">
<div class="modal-header">
<button type="button" class="close" aria-label="Close" ng-click="$ctrl.cancel()">
<span class="pficon pficon-close" aria-hidden="true"></span>
</button>
<h4 class="modal-title">{{$ctrl.modalTitle}}</h4>
</div>
<div class="modal-body-header">
<h2>{{$ctrl.subTitle}}</h2>
</div>
<div class="modal-body">
<form name="entaxyInnerObjectForm" class="form-horizontal">
<entaxy-form-fields items="$ctrl.viewedFormFields" errors="$ctrl.errors" mode="$ctrl.mode"
form-controller="entaxyInnerObjectForm"></entaxy-form-fields>
</form>
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary" ng-click="$ctrl.save()">{{$ctrl.buttonTitle}}</button>
</div>
</div>
`,
controller: entaxyInnerObjectInputModalController
})
.name;
function entaxyInnerObjectInputModalController($uibModal, $scope, workspace, entaxyService) {
'ngInject';
let ctrl = this;
ctrl.$onInit = function() {
ctrl.mode = ctrl.resolve.mode;
ctrl.model = ctrl.resolve.model;
let extraInfo = ctrl.resolve.fieldName ? ': ' + ctrl.resolve.fieldName : '';
ctrl.modalTitle = ctrl.mode + ' Inner Object' + extraInfo;
ctrl.subTitle = ctrl.model ?
ctrl.mode + ' properties of inner object' + extraInfo : 'Fill in fields' + extraInfo;
ctrl.buttonTitle = 'Ok';
populateFormFields();
}
function populateFormFields() {
let promise = ctrl.resolve.objectFactoryFilter ?
entaxyService.getFactoriesByFilterSearch(ctrl.resolve.objectFactoryFilter) :
entaxyService.getFactoriesByType(ctrl.resolve.type);
promise.then(factories => {
ctrl.factories = factories;
let factoryId = ctrl.model ? ctrl.model.factoryId : factories[0].name;
ctrl.populatedFactoriesFields = [factoryId];
ctrl.formFields = [{
label: 'Factory',
name: 'factoryId',
type: 'text',
description: factories
.sort(Entaxy.compareBy('displayName'))
.map(factory => factory.displayName + ' - ' + factory.description)
.join('<br/>'),
value: factoryId,
readOnly: ctrl.mode === Entaxy.MODAL_MODES.VIEW ? true : false,
required: ctrl.mode === Entaxy.MODAL_MODES.VIEW ? false : true,
group: 'general',
typeInfo: {
type: 'enum',
values: factories
.map(factory => { return { displayValue: factory.displayName, value: factory.name };})
.sort(Entaxy.compareBy('displayValue')),
isEmptyIncluded: false
}
}];
createFormFields(factoryId);
addWatcher();
});
}
function createFormFields(factoryId) {
let mbeanName = getFactoryById(factoryId).mbeanName;
entaxyService.getFields(mbeanName)
.then((response) => {
let objectId = ctrl.model ? ctrl.model.objectId : undefined;
let properties = ctrl.model ? ctrl.model.properties : undefined;
let configurableOnly = false;
_.forEach(JSON.parse(response), (field) => {
let formField = entaxyService
.makeFormField(field, objectId, properties, configurableOnly, ctrl.mode);
if (formField) {
formField.belongsToFactory = factoryId;
ctrl.formFields.push(formField);
}
});
filterFormFields(factoryId);
});
}
function getFactoryById(factoryId) {
return ctrl.factories.find(factory => factory.name === factoryId);
}
function addWatcher() {
$scope.$watch('$ctrl.formFields[0].value', function (newValue, oldValue) {
if (newValue !== oldValue) {
if (!ctrl.populatedFactoriesFields.includes(newValue)) {
createFormFields(newValue);
ctrl.populatedFactoriesFields.push(newValue);
} else {
filterFormFields(newValue);
}
}
});
}
function filterFormFields(factoryId) {
ctrl.viewedFormFields = ctrl.formFields
.filter(formField =>
formField.name === 'factoryId' || formField.belongsToFactory === factoryId);
}
ctrl.cancel = function(reason) {
ctrl.modalInstance.dismiss(reason);
}
ctrl.save = function () {
if (ctrl.mode === Entaxy.MODAL_MODES.VIEW) {
ctrl.cancel();
} else {
let selectedFactory = ctrl.viewedFormFields.find(formField => formField.name === 'factoryId');
entaxyService.validateFields(ctrl.viewedFormFields, selectedFactory)
.then(errors => {
ctrl.errors = errors;
if (Object.keys(ctrl.errors).length === 0) {
if (ctrl.resolve.outerFormController && !ctrl.resolve.outerFormController.$dirty &&
$scope.entaxyInnerObjectForm && $scope.entaxyInnerObjectForm.$dirty) {
ctrl.resolve.outerFormController.$setDirty();
}
let args = entaxyService.getArguments(ctrl.viewedFormFields, ctrl.factories);
ctrl.modalInstance.close(args);
}
});
}
}
}
entaxyInnerObjectInputModalController.$inject = ['$uibModal', '$scope', 'workspace', 'entaxyService'];
})(Entaxy || (Entaxy = {}));

View File

@ -0,0 +1,59 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-management-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var Entaxy;
(function (Entaxy) {
Entaxy._module.component('entaxyInputWithExtension', {
bindings: {
model: '=',
modelWithoutExtension: '=',
extension: '<',
readonly: '<',
formController: '<'
},
template:
`
<div class="input-with-extension">
<input type="text" ng-model="$ctrl.modelWithoutExtension" class="form-control" ng-readonly="$ctrl.readonly"/>
<input type="text" ng-model="$ctrl.extension" class="form-control extension-input" readonly/>
</div>
`,
controller: entaxyInputWithExtensionController
})
.name;
function entaxyInputWithExtensionController(workspace, $scope) {
'ngInject';
let ctrl = this;
$scope.$watch('$ctrl.modelWithoutExtension', function () {
ctrl.model = ctrl.modelWithoutExtension + ctrl.extension;
})
}
entaxyInputWithExtensionController.$inject = ['workspace', '$scope'];
})(Entaxy || (Entaxy = {}));

View File

@ -0,0 +1,251 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-management-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var Entaxy;
(function (Entaxy) {
Entaxy._module.component('entaxyListInput', {
bindings: {
items: '=',
itemTitleTemplate: '<',
creationEnabled: '<',
creationTypes: '<',
itemFactoryFilter: '<',
readonly: '<',
validation: '<',
mode: '<',
errors: '<',
formController: '<'
},
template:
`
<div class="entaxy-empty-state" ng-if="$ctrl.showEmptyState">
<span>{{$ctrl.emptyStateMessage}}</span>
</div>
<div class="add-item-to-list-block" ng-click="$ctrl.showModal()"
ng-if="$ctrl.creationEnabled && !$ctrl.readonly">
<span class="pficon pficon-add-circle-o"></span>
<span>{{$ctrl.addItemTitle}}</span>
</div>
<div as-sortable="$ctrl.dragControlListeners" ng-model="$ctrl.items"
ng-if="$ctrl.items && $ctrl.items.length > 0">
<div ng-repeat="item in $ctrl.items"
ng-class="{'list-input-item-has-error': item.errors && !item.toDeletion}" as-sortable-item>
<div class="list-input-item" ng-class="{'disabled': item.toDeletion}">
<div class="list-input-item-heading" ng-click="$ctrl.open(item)">
<span class="fa fa-angle-right" ng-if="!item.open"></span>
<span class="fa fa-angle-down" ng-if="item.open"></span>
<label ng-class="{'new-item': item.new}">
{{$ctrl.getItemName(item.formFields)}}
</label>
</div>
<div class="list-input-item-controls" ng-if="!$ctrl.readonly">
<span class="pficon pficon-delete remove-icon"
ng-click="$ctrl.removeItem(item)" ng-if="!item.toDeletion"
data-toggle="tooltip" title="Remove"></span>
<span class="pficon pficon-history restore-icon"
ng-click="$ctrl.restoreItem(item)" ng-if="item.toDeletion"
data-toggle="tooltip" title="Restore"></span>
<span class="glyphicon glyphicon-move move-icon" as-sortable-item-handle
data-toggle="tooltip" title="Move" ng-if="!item.toDeletion"></span>
</div>
</div>
<div class="list-input-item-content" ng-show="item.open">
<entaxy-list-item-content form-fields="item.formFields" errors="item.errors" mode="$ctrl.mode">
</entaxy-list-item-content>
</div>
</div>
</div>
`,
controller: entaxyListInputController
})
.name;
function entaxyListInputController(workspace, $q, $uibModal, entaxyService) {
'ngInject';
let ctrl = this;
ctrl.dragControlListeners = {
itemMoved: function (event) {
event.source.itemScope.modelValue.status = event.dest.sortableScope.$parent.column.name;
},
orderChanged: function (event) {
setDirty();
},
containment: '#board'
};
ctrl.$onInit = function() {
ctrl.itemTypes = ctrl.creationTypes.map(type => type.displayName);
ctrl.addItemTitle = 'Add ' + ctrl.itemTypes.join(' or ');
ctrl.showEmptyState = (ctrl.mode === Entaxy.MODAL_MODES.VIEW || !ctrl.creationEnabled || ctrl.readOnly)
&& !ctrl.items || (ctrl.items && ctrl.items.length == 0);
ctrl.emptyStateMessage = 'No Items Available';
}
ctrl.getItemName = function (formFields) {
let values = [];
ctrl.itemTitleTemplate.fields.forEach(fieldName => {
let formField = formFields.find(formField => formField.name === fieldName);
values.push(formField.value);
});
return values.join(ctrl.itemTitleTemplate.delimiter);
}
function setDirty() {
if (ctrl.formController && !ctrl.formController.$dirty) {
ctrl.formController.$setDirty();
}
}
ctrl.$onChanges = function (changes) {
if (changes.errors) {
if (ctrl.items && !changes.errors.currentValue
&& (!changes.errors.previousValue || Object.keys(changes.errors.previousValue).length === 0)) {
ctrl.items.forEach(item => item.errors = undefined);
}
if (changes.errors.currentValue) {
let errors = changes.errors.currentValue;
if (typeof errors !== 'string') {
let errorKeys = Object.keys(errors);
errorKeys.forEach(errorKey => {
ctrl.items.filter(item => !item.toDeletion).forEach(item => {
let formField = item.formFields.find(formField => formField.name === errorKey);
if (formField) {
if (errors[errorKey].values) {
if (errors[errorKey].values.includes(formField.value)) {
setError(item, formField.name, errors[errorKey].message);
}
} else {
setError(item, formField.name, errors[errorKey].message);
}
}
});
});
}
}
}
}
function setError(item, formFieldName, message) {
if (!item.errors) {
item.errors = {};
}
item.errors[formFieldName] = message;
}
ctrl.open = function (item) {
if (!item.toDeletion) {
item.open = !item.open;
}
}
ctrl.removeItem = function (item) {
item.toDeletion = true;
item.open = false;
setDirty();
}
ctrl.restoreItem = function (item) {
item.toDeletion = false;
}
ctrl.showModal = function () {
let allFactories = [];
let promises = [];
if (ctrl.itemFactoryFilter) {
promises.push(
entaxyService.getFactoriesByFilterSearch(ctrl.itemFactoryFilter)
.then(factories => allFactories = factories));
} else {
ctrl.creationTypes.forEach(type => {
promises.push(
entaxyService.getFactoriesByType(type.name)
.then(factories => allFactories = allFactories.concat(factories)));
});
}
if (promises.length > 0) {
let checkUniqueness = ctrl.validation && ctrl.validation.rules && ctrl.validation.rules.checkUniqueness ?
ctrl.validation.rules.checkUniqueness : undefined;
let checkUniquenessFields = {};
if (checkUniqueness) {
checkUniqueness.fields.forEach(field => {
checkUniquenessFields[field] = [];
if (ctrl.items) {
ctrl.items.forEach(item => {
let formField = item.formFields.find(formField => formField.name === field);
checkUniquenessFields[field].push(formField.value);
});
}
});
}
$uibModal.open({
component: 'entaxyModal',
resolve: {
mode: () => Entaxy.MODAL_MODES.ADD,
itemType: () => ctrl.itemTypes.join(' or '),
factories: $q.all(promises).then(() => allFactories),
returnFormFields: () => true,
checkUniquenessParentFields: () => checkUniquenessFields
},
size: 'xl',
backdrop: 'static',
windowTopClass: 'modal-top-margin-override'
})
.result.then(formFields => {
addItem(formFields);
},
reason => {
if (reason) {
Entaxy.notificationError(reason);
}
});
}
}
function addItem(formFields) {
if (!ctrl.items) {
ctrl.items = [];
}
ctrl.items.push({
new: true,
formFields: formFields
});
setDirty();
}
}
entaxyListInputController.$inject = ['workspace', '$q', '$uibModal', 'entaxyService'];
})(Entaxy || (Entaxy = {}));

View File

@ -0,0 +1,79 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-management-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var Entaxy;
(function (Entaxy) {
Entaxy._module.component('entaxyListItemContent', {
bindings: {
formFields: '<',
mode: '<',
errors: '<'
},
template:
`
<uib-tabset active="$ctrl.selectedGroupIndex">
<uib-tab ng-repeat="group in $ctrl.groups track by $index"
heading="{{group.displayName}}" select="$ctrl.change()">
<entaxy-form-fields items="group.formFields" errors="$ctrl.errors" mode="$ctrl.mode">
</entaxy-form-fields>
</uib-tab>
</uib-tabset>
`,
controller: EntaxyListItemContentController
})
.name;
function EntaxyListItemContentController() {
let ctrl = this;
ctrl.$onInit = function() {
let groups = new Set();
groups.add('general');
ctrl.formFields.forEach(formField => {
groups.add(formField.group);
});
ctrl.groups = Array.from(groups).map((group) => {
return {
name: group,
displayName: group,
formFields: ctrl.formFields.filter(formField => formField.group === group)
};
});
if (ctrl.errors) {
let errorFields = Object.keys(ctrl.errors);
for (let i = 0; i < ctrl.groups.length; i++) {
if (ctrl.groups[i].formFields.find(formField => errorFields.includes(formField.name))) {
ctrl.selectedGroupIndex = i;
break;
}
}
}
}
}
})(Entaxy || (Entaxy = {}));

View File

@ -0,0 +1,204 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-management-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var Entaxy;
(function (Entaxy) {
Entaxy._module.component('entaxyMapInput', {
bindings: {
model: '=',
items: '=',
duplicateKeys: '=',
hasErrors: '=',
readonly: '<',
formController: '<'
},
template:
`
<div class="entaxy-map-input-table" ng-if="$ctrl.items && $ctrl.items.length > 0">
<table>
<tbody>
<tr role="row" ng-repeat="field in $ctrl.items">
<td class="input-cell">
<input type="text" class="form-control" ng-model="field.key" ng-change="$ctrl.changeKey(field)"
ng-class="{'has-error': field.hasError}" ng-readonly="$ctrl.readonly || field.removed"/>
</td>
<td class="input-cell">
<input type="text" class="form-control" ng-model="field.value" ng-change="$ctrl.changeValue(field)"
ng-readonly="$ctrl.readonly || field.removed"/>
</td>
<td ng-if="!$ctrl.readonly">
<button type="button" ng-click="$ctrl.remove(field)" data-toggle="tooltip" title="Remove"
ng-if="!field.removed">
<span class="pficon pficon-delete"></span>
</button>
<button type="button" ng-click="$ctrl.restore(field)" data-toggle="tooltip" title="Restore"
ng-if="field.removed">
<span class="pficon pficon-history"></span>
</button>
</td>
</tr>
</tbody>
</table>
</div>
<input type="text" class="form-control" ng-model="$ctrl.emptyValueInfo" ng-if="$ctrl.emptyValueInfo" readonly/>
<button type="button" class="entaxy-map-input-add-button" ng-if="!$ctrl.readonly" ng-click="$ctrl.add()">
<span class="pficon pficon-add-circle-o"></span>
<span>{{$ctrl.addItemTitle}}</span>
</button>
`,
controller: entaxyMapInputController
})
.name;
function entaxyMapInputController() {
let ctrl = this;
ctrl.$onInit = function () {
ctrl.addItemTitle = 'Add Property';
if (!ctrl.items) {
if (ctrl.model) {
ctrl.items = Object.entries(ctrl.model).map(([key, value]) => {
return {
key: key,
value: value
};
}).sort(Entaxy.compareBy('key'));
} else {
ctrl.items = [];
}
}
if (ctrl.items.length === 0 && ctrl.readonly) {
ctrl.emptyValueInfo = '--Map is empty--';
}
if (!ctrl.duplicateKeys) {
ctrl.duplicateKeys = new Set();
}
}
ctrl.changeKey = function (field) {
validateKey(field);
updateDuplicatesStatus();
updateErrorsState();
updateModel();
}
ctrl.changeValue = function (field) {
updateModel();
}
function validateKey(field) {
if (field.key.trim().length === 0) {
field.hasError = true;
} else {
let duplicates = getItemsByKey(field.key);
if (duplicates.length > 1) {
ctrl.duplicateKeys.add(field.key);
duplicates.forEach(item => item.hasError = true);
} else {
field.hasError = false;
}
}
}
function updateDuplicatesStatus() {
let expiredDuplicateKeys = new Set();
ctrl.duplicateKeys.forEach(duplicateKey => {
let duplicates = getItemsByKey(duplicateKey);
if (duplicates.length <= 1) {
expiredDuplicateKeys.add(duplicateKey);
duplicates.forEach(item => item.hasError = false);
}
});
if (expiredDuplicateKeys.size === ctrl.duplicateKeys.size) {
ctrl.duplicateKeys.clear();
} else {
expiredDuplicateKeys.forEach(expiredDuplicateKey => ctrl.duplicateKeys.delete(expiredDuplicateKey));
}
}
function getItemsByKey(key) {
return ctrl.items.filter(item => !item.removed && item.key === key);
}
function updateErrorsState() {
ctrl.hasErrors = ctrl.items.filter(item => !item.removed && item.hasError).length === 0 ? false : true;
}
function updateModel() {
if (!ctrl.hasErrors) {
ctrl.model = ctrl.items.length > 0 ? {} : undefined;
ctrl.items.forEach(item => {
if (!item.removed && !item.hasError) {
ctrl.model[item.key] = item.value;
}
});
}
}
ctrl.add = function () {
ctrl.items.push({type: 'text', key: '', value: ''});
validateKey(ctrl.items[ctrl.items.length - 1]);
updateErrorsState();
ctrl.setDirty();
}
ctrl.remove = function (field) {
field.removed = true;
field.hasError = false;
updateDuplicatesStatus();
updateErrorsState();
updateModel();
ctrl.setDirty();
}
ctrl.restore = function (field) {
field.removed = false;
validateKey(field);
updateDuplicatesStatus();
updateErrorsState();
updateModel();
ctrl.setDirty();
}
ctrl.setDirty = function () {
if (ctrl.formController && !ctrl.formController.$dirty) {
ctrl.formController.$setDirty();
}
}
}
})(Entaxy || (Entaxy = {}));

View File

@ -0,0 +1,110 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-management-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var Entaxy;
(function (Entaxy) {
Entaxy._module.component('entaxyPasswordInput', {
bindings: {
name: '<',
model: '=',
confirmationModel: '=',
ignoreConfirmationValue: '=',
readonly: '<',
errors: '='
},
template:
`
<div class="password-input">
<input type="{{$ctrl.type}}" class="form-control" ng-model="$ctrl.model" ng-readonly="$ctrl.readonly"
autocomplete="new-password">
<span ng-class="{'fa fa-eye': !$ctrl.isVisible(), 'fa fa-eye-slash': $ctrl.isVisible()}"
ng-click="$ctrl.view()"></span>
</div>
<input type="{{$ctrl.type}}" class="form-control confirmation-password-input"
ng-model="$ctrl.confirmationModel" ng-if="!$ctrl.readonly"
placeholder="confirm password here" ng-show="$ctrl.model && !$ctrl.ignoreConfirmationValue">
`,
controller: entaxyPasswordInputController
})
.name;
function entaxyPasswordInputController($scope) {
'ngInject';
let ctrl = this;
const TYPES = {
PASSWORD: 'password',
TEXT: 'text'
}
ctrl.$onInit = function() {
ctrl.type = TYPES.PASSWORD;
}
ctrl.view = function () {
ctrl.type = ctrl.isVisible() ? TYPES.PASSWORD : TYPES.TEXT;
}
ctrl.isVisible = function () {
return ctrl.type !== TYPES.PASSWORD;
}
$scope.$watch('$ctrl.model', function () {
if (ctrl.ignoreConfirmationValue && ctrl.valueAssigned) {
ctrl.ignoreConfirmationValue = false;
}
if (!ctrl.ignoreConfirmationValue) {
validate();
} else {
ctrl.valueAssigned = true;
}
})
$scope.$watch('$ctrl.confirmationModel', function () {
if (!ctrl.ignoreConfirmationValue) {
validate();
}
});
function validate() {
let message = Entaxy.ERROR_MESSAGE.PASSWORD_CONFIRMATION;
if (ctrl.errors) {
if (ctrl.model && ctrl.model !== ctrl.confirmationModel) {
ctrl.errors[ctrl.name] = message;
} else {
if (ctrl.errors[ctrl.name] === message) {
ctrl.errors[ctrl.name] = undefined;
}
}
} else {
if (ctrl.confirmationModel !== ctrl.model) {
ctrl.errors = {[ctrl.name]: message};
}
}
}
}
entaxyPasswordInputController.$inject = ['$scope'];
})(Entaxy || (Entaxy = {}));

View File

@ -0,0 +1,72 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-management-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var Entaxy;
(function (Entaxy) {
Entaxy._module
.component('entaxyResourceInput', {
bindings: {
name: '@',
model: '=',
formController: '<'
},
template:
`
<div class="entaxy-resource-input" entaxy-file-drop ng-model="$ctrl.file" ng-click="$ctrl.triggerUpload()">
<span class="fa fa-upload"></span>
<span ng-if="!$ctrl.file">Drop file to upload</span>
<span ng-if="$ctrl.file">
File {{($ctrl.file.name | limitTo: 15) + ($ctrl.file.name.length > 15 ? '...' : '')}} is ready to upload
</span>
<input type="file" id="{{$ctrl.name}}-file-input" set-file-model ng-model="$ctrl.file">
</div>
`,
controller: entaxyResourceInputController
})
.name;
function entaxyResourceInputController(workspace, $scope) {
'ngInject';
let ctrl = this;
ctrl.$onInit = function () {
if (ctrl.model) {
ctrl.file = ctrl.model;
}
}
$scope.$watch('$ctrl.file', function () {
ctrl.model = ctrl.file;
});
ctrl.triggerUpload = function () {
document.getElementById(ctrl.name + '-file-input').click();
}
}
entaxyResourceInputController.$inject = ['workspace', '$scope'];
})(Entaxy || (Entaxy = {}));

View File

@ -0,0 +1,239 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-management-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var Entaxy;
(function (Entaxy) {
Entaxy._module
.component('entaxySelect', {
bindings: {
type: '<',
filter: '<',
model: '=',
readonly: '<',
updateParent: '<',
updateParentFn: '<',
options: '=',
creationEnabled: '<',
isEmptyIncluded: '<',
formController: '<'
},
template:
`
<div class="custom-select" ng-if="!$ctrl.readonly">
<button type="button" class="btn-select form-control dropdown-toggle" id="filter"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="selected-option">{{$ctrl.selectedOption.displayName}}</span>
<span class="caret"></span>
</button>
<ul class="dropdown-menu">
<li ng-repeat="option in $ctrl.options" id="option.name" ng-click="$ctrl.changeSelection(option)">
{{ option.displayName }}
</li>
<li id="addItem" class="dropdown-option-new" ng-click="$ctrl.showModal()" ng-if="$ctrl.creationEnabled">
<span class="pficon pficon-add-circle-o"></span>
{{$ctrl.createObjectOptionTitle}}
</li>
</ul>
</div>
<input type="text" class="form-control" ng-model="$ctrl.selectedOption.displayName"
ng-if="$ctrl.readonly" readonly>
`,
controller: entaxySelectController
})
.name;
function entaxySelectController(workspace, jolokiaService, jolokia, $q, $uibModal, entaxyService) {
'ngInject';
let ctrl = this;
let emptyValue;
ctrl.$onInit = function() {
if (!ctrl.readonly) {
ctrl.itemType = Entaxy.getItemTypeFromRuntimeType(ctrl.type);
if (ctrl.creationEnabled) {
ctrl.createObjectOptionTitle = 'New private ' + ctrl.itemType + '...';
}
populateOptions();
} else {
let domain = entaxyService.getDomainFolder();
entaxyService.getAllChildMBeansByRuntimeType(domain, ctrl.type).then((mbeans) => {
let mbean = mbeans.find(mbean => mbean.attributes.Name === ctrl.model);
ctrl.selectedOption = mbean ? createOptionFromMbean(mbean) : { displayName: ctrl.model };
});
}
}
function populateOptions() {
if (!ctrl.options) {
let emptyOptionName = '--No ' + ctrl.itemType + ' selected--';
emptyValue = {name: emptyOptionName, displayName: emptyOptionName};
let domain = entaxyService.getDomainFolder();
if (ctrl.filter) {
entaxyService.findObjectsByFilter(ctrl.filter).then(result => {
let objectFullIds = JSON.parse(result);
entaxyService.getMBeansByObjectFullIds(objectFullIds).then((mbeans) => {
populateOptionsFromMbeans(mbeans);
});
}).catch(error => {
Entaxy.notificationError(error);
Entaxy.log.error(error);
});
} else {
entaxyService.getAllChildMBeansByRuntimeType(domain, ctrl.type).then((mbeans) => {
populateOptionsFromMbeans(mbeans);
});
}
} else {
if (ctrl.isEmptyIncluded) {
emptyValue = ctrl.options[0];
}
ctrl.selectedOption = getOptionByModel();
}
}
function populateOptionsFromMbeans(mbeans) {
let items = mbeans.map(mbean => createOptionFromMbean(mbean));
if (items && items.length > 0) {
ctrl.options = items.sort(Entaxy.compareBy('displayName'));
if (ctrl.isEmptyIncluded) {
ctrl.options.unshift(emptyValue);
}
ctrl.changeSelection(ctrl.model ? getOptionByModel() : items[0]);
} else {
ctrl.options = [];
let notificationType = ctrl.creationEnabled ?
Entaxy.NOTIFICATION_TYPE.WARNING : Entaxy.NOTIFICATION_TYPE.DANGER;
Core.notification(notificationType, 'There is no suitable ' + ctrl.itemType.toLowerCase(),
Entaxy.configuration[Entaxy.CONFIGURATION_KEYS.NOTIFICATION_TIMEOUT_ERROR]);
// todo close the modal if creation is disabled
}
}
function createOptionFromMbean(mbean) {
let displayName = mbean.attributes.DisplayName;
let name = mbean.attributes.Name;
return {
name: name,
displayName: createDisplayName(displayName, name),
mbeanName: mbean.mbean.objectName
};
}
function createDisplayName(displayName, name) {
return displayName && displayName !== name ? displayName + ' [' + name + ']' : name;
}
function getOptionByModel() {
return ctrl.options.find((option) => option.name === ctrl.model || option.value === ctrl.model);
}
ctrl.changeSelection = function (option) {
if (ctrl.selectedOption !== option) {
let previousOption = ctrl.selectedOption;
ctrl.selectedOption = option;
ctrl.model = option.name === emptyValue.name ? undefined : (option.value ? option.value : option.name);
if (previousOption && ctrl.formController && !ctrl.formController.$dirty) {
ctrl.formController.$setDirty();
}
if (ctrl.updateParent) {
if (previousOption) {
Core.notification(Entaxy.NOTIFICATION_TYPE.WARNING,
'Changing ' + ctrl.itemType +
' field value may lead to changes in other fields of the current object. ' +
'Please, make sure to revise all fields before accepting.',
Entaxy.configuration[Entaxy.CONFIGURATION_KEYS.NOTIFICATION_TIMEOUT_INFO]);
}
ctrl.updateParentFn(previousOption, option);
}
}
}
ctrl.showModal = function() {
$uibModal.open({
component: 'entaxyModal',
resolve: {
mode: () => Entaxy.MODAL_MODES.ADD,
itemType: () => Entaxy.capitalize(ctrl.itemType),
factories: entaxyService.getFactoriesByType(ctrl.type, ctrl.filter).then(factories => factories)
},
size: 'xl',
backdrop: 'static',
windowTopClass: 'modal-top-margin-override'
})
.result.then(args => {
addItem(args);
},
reason => {
if (reason) {
Entaxy.notificationError(reason);
}
});
}
function addItem(args) {
let factoryId = args.factoryId.name;
let objectId = args.fields.find((field) => field.name === 'objectId').value;
let fields = objectId ? args.fields.filter((field) => field.name !== 'objectId') : args.fields;
let properties = fields.reduce((obj, cur) => ({ ...obj, [cur.name] : cur.value }), {});
let newObjectProperties = {
factoryId: factoryId,
objectId: objectId,
scope: 'private',
properties: properties
};
let newObjectOption = {
name: objectId ? objectId : ('private-' + ctrl.itemType),
value: newObjectProperties
};
ctrl.options.push(newObjectOption);
ctrl.changeSelection(newObjectOption);
}
}
entaxySelectController.$inject = ['workspace', 'jolokiaService', 'jolokia', '$q', '$uibModal', 'entaxyService'];
})(Entaxy || (Entaxy = {}));

View File

@ -0,0 +1,113 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-management-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var Entaxy;
(function (Entaxy) {
Entaxy._module
.component('entaxySelectFromEnum', {
bindings: {
values: '<',
isEmptyIncluded: '<',
emptyOptionName: '<',
model: '=',
readonly: '<',
multiple: '<'
},
template:
`
<select class="form-control" ng-options="option.displayName for option in $ctrl.options"
ng-model="$ctrl.selectedOption" ng-change="$ctrl.changeSelection()" ng-disabled="$ctrl.readonly">
`,
controller: entaxySelectFromEnumController
})
.name;
function entaxySelectFromEnumController($scope) {
'ngInject';
let ctrl = this;
let emptyValue = { name: '--Empty value--' };
ctrl.$onInit = function() {
emptyValue.displayName = ctrl.emptyOptionName ? ctrl.emptyOptionName : emptyValue.name;
populateOptions();
if (ctrl.options.length == 1 || (!ctrl.isEmptyIncluded && !ctrl.model)) {
ctrl.selectedOption = ctrl.options[0];
ctrl.changeSelection();
}
}
function populateOptions() {
ctrl.options = (ctrl.values && ctrl.values.length > 0) ?
ctrl.values.map(value => {
return angular.isObject(value) ?
{ displayName: value.displayValue ? value.displayValue : value.value, name: value.value } :
{ displayName: value, name: value }
}) : [];
if (ctrl.isEmptyIncluded !== false) {
ctrl.options.unshift(emptyValue);
}
}
$scope.$watchCollection('$ctrl.values', function(newValue, oldValue) {
if (newValue !== oldValue) {
populateOptions();
let currentSelectedOption = ctrl.options.find((option) => option.name === ctrl.selectedOption.name);
ctrl.selectedOption = currentSelectedOption ? currentSelectedOption : ctrl.options[0];
ctrl.changeSelection();
}
});
$scope.$watch('$ctrl.model', function() {
if (ctrl.multiple) {
if (ctrl.model && ctrl.model.length > 0) {
if (!ctrl.selectedOption || ctrl.selectedOption.name !== ctrl.model[0]) {
ctrl.selectedOption = ctrl.options.find((option) => option.name === ctrl.model[0]);
}
} else {
if (!ctrl.selectedOption || ctrl.selectedOption.name !== ctrl.options[0].name) {
ctrl.selectedOption = ctrl.options[0];
}
}
} else {
ctrl.selectedOption = ctrl.model ?
ctrl.options.find((option) => option.name === ctrl.model) : ctrl.options[0];
}
});
ctrl.changeSelection = function () {
if (ctrl.selectedOption.name === emptyValue.name) {
ctrl.model = ctrl.multiple ? [] : undefined;
} else {
ctrl.model = ctrl.multiple ? [ctrl.selectedOption.name] : ctrl.selectedOption.name;
}
}
}
entaxySelectFromEnumController.$inject = ['$scope'];
})(Entaxy || (Entaxy = {}));

View File

@ -0,0 +1,81 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-management-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var Entaxy;
(function (Entaxy) {
Entaxy._module
.component('entaxyUrlInput', {
bindings: {
model: '=',
config: '<',
readonly: '<',
formController: '<'
},
template:
`
<div class="input-with-button">
<input type="text" ng-model="$ctrl.model" ng-class="{'form-control': true}" readonly>
<span class="pficon pficon-delete" ng-click="$ctrl.clear()" ng-if="$ctrl.model"></span>
<button class="entaxy-view-resources-form" ng-click="$ctrl.openViewer()" ng-if="!$ctrl.readonly">
Select...
</button>
</div>
`,
controller: entaxyUrlInputController
})
.name;
function entaxyUrlInputController(workspace, $uibModal) {
'ngInject';
let ctrl = this;
ctrl.openViewer = function() {
$uibModal.open({
component: 'entaxyResourceViewerModal',
resolve: {
location: () => ctrl.model,
config: () => ctrl.config
},
size: 'xl',
backdrop: 'static',
windowTopClass: 'modal-top-margin-override'
})
.result.then(location => {
if (ctrl.model !== location && ctrl.formController && !ctrl.formController.$dirty) {
ctrl.formController.$setDirty();
}
ctrl.model = location;
});
}
ctrl.clear = function () {
ctrl.model = undefined;
}
}
entaxyUrlInputController.$inject = ['workspace', '$uibModal'];
})(Entaxy || (Entaxy = {}));

View File

@ -0,0 +1,79 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-management-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var Entaxy;
(function (Entaxy) {
Entaxy._module
.component('entaxyXml', {
bindings: {
ngModel: '=',
mode: '<',
readonly: '<',
formController: '<'
},
template:
`
<button class="entaxy-xml-form" ng-click="$ctrl.openEditor()" ng-disabled="$ctrl.disabled">
{{$ctrl.buttonTitle}}
</button>
`,
controller: entaxyXmlController
})
.name;
function entaxyXmlController(workspace, $scope, $uibModal) {
'ngInject';
let ctrl = this;
$scope.$watch('$ctrl.readonly', function () {
ctrl.buttonTitle = ctrl.readonly ? Entaxy.MODAL_MODES.VIEW : ctrl.mode;
ctrl.disabled = ctrl.readonly &&
(ctrl.ngModel === undefined || (angular.isString(ctrl.ngModel) && ctrl.ngModel.trim().length === 0));
});
ctrl.openEditor = function() {
$uibModal.open({
component: 'entaxyXmlModal',
resolve: {
xml: () => ctrl.ngModel,
mode: () => ctrl.readonly ? Entaxy.MODAL_MODES.VIEW : ctrl.mode
},
size: 'xl',
backdrop: 'static',
windowTopClass: 'modal-top-margin-override'
})
.result.then(xml => {
if (ctrl.ngModel !== xml && ctrl.formController && !ctrl.formController.$dirty) {
ctrl.formController.$setDirty();
}
ctrl.ngModel = xml;
});
}
}
entaxyXmlController.$inject = ['workspace', '$scope', '$uibModal'];
})(Entaxy || (Entaxy = {}));

View File

@ -0,0 +1,214 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-management-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var Entaxy;
(function (Entaxy) {
Entaxy._module.component('entaxyAddConnectorModal', {
bindings: {
modalInstance: '<',
resolve: '<'
},
template:
`
<div class="entaxy-modal-container">
<div class="modal-header">
<button type="button" class="close" aria-label="Close" ng-click="$ctrl.cancel()">
<span class="pficon pficon-close" aria-hidden="true"></span>
</button>
<h4 class="modal-title">{{$ctrl.modalTitle}}</h4>
</div>
<div ng-if="$ctrl.step1 && $ctrl.profiles">
<div class="modal-body-header">
<h2>Choose profile to attach connector to</h2>
</div>
<div class="modal-body" style="height:433px; max-height:433px">
<entaxy-modal-list items="$ctrl.profiles" selected="$ctrl.selectedProfile"
change-selection="$ctrl.changeProfileSelection" enable-dbl-click="true"></entaxy-modal-list>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" ng-click="$ctrl.next()"
ng-disabled="!$ctrl.selectedProfile">Next</button>
</div>
</div>
<div ng-if="$ctrl.step2">
<div class="modal-body-header">
<h2>Choose connector template</h2>
</div>
<div class="modal-body" style="height:433px; max-height:433px">
<entaxy-modal-list items="$ctrl.templates" selected="$ctrl.selectedTemplate"
change-selection="$ctrl.changeTemplateSelection" enable-dbl-click="true"></entaxy-modal-list>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" ng-click="$ctrl.back()" ng-if="$ctrl.profiles">Back</button>
<button type="button" class="btn btn-default" ng-click="$ctrl.next()"
ng-disabled="!$ctrl.selectedTemplate">Next</button>
</div>
</div>
<form name="connectorForm" class="form-horizontal" ng-if="$ctrl.step3" ng-submit="$ctrl.saveConnector($ctrl.formFields)">
<div class="modal-body" style="height:503px; max-height:503px;">
<div class="modal-body-header">
<h2>Fill in connector template parameters</h2>
</div>
<div class="form-group" ng-class="{'has-error': $ctrl.errors[formField.name]}"
ng-repeat="formField in $ctrl.formFields" style="margin:15px;">
<label class="col-sm-3 control-label" ng-class="{'required-pf': formField.isRequired}" for="{{formField.name}}">{{formField.label}}</label>
<div class="col-sm-8">
<input type="{{formField.type}}" id="{{formField.name}}" ng-class="{'form-control': formField.type !== 'checkbox'}"
ng-model="formField.value" ng-readonly="formField.isReadOnly" ng-if="!formField.typeInfo">
<span class="help-block" ng-show="$ctrl.errors[formField.name]">{{$ctrl.errors[formField.name]}}</span>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" ng-click="$ctrl.back()">Back</button>
<button type="submit" class="btn btn-primary">Add</button>
</div>
</form>
</div>
`,
controller: EntaxyAddConnectorModalController
})
.name;
function EntaxyAddConnectorModalController(workspace, jolokia) {
'ngInject';
var ctrl = this;
ctrl.$onInit = function() {
let templates = Entaxy.getConnectorTemplates();
ctrl.templates = templates.map(template => { return { name: template, displayName: template }});
ctrl.profiles = ctrl.resolve.profiles;
if (ctrl.profiles) {
ctrl.step1 = true;
ctrl.step2 = false;
ctrl.step3 = false;
} else {
ctrl.step1 = false;
ctrl.step2 = true;
ctrl.step3 = false;
}
ctrl.modalTitle = ctrl.resolve.profileName ?
'Add Legacy Connector to ' + ctrl.resolve.profileName : 'Add Legacy Connector';
}
ctrl.changeProfileSelection = function(item, isDblClicked) {
ctrl.selectedProfile = item;
if (isDblClicked) {
ctrl.next();
}
}
ctrl.changeTemplateSelection = function(item, isDblClicked) {
ctrl.selectedTemplate = item;
if (isDblClicked) {
ctrl.next();
}
}
ctrl.next = function() {
if (ctrl.step1 === true) {
ctrl.step1 = false;
ctrl.step2 = true;
} else if (ctrl.step2 === true) {
ctrl.step2 = false;
ctrl.step3 = true;
}
if (ctrl.step3 === true) {
defineFormFields();
}
}
function defineFormFields() {
if (!ctrl.formFields || ctrl.selectedTemplate.name !== ctrl.formFields[0].value) {
ctrl.formFields = Entaxy.getConnectorTemplateParams(ctrl.selectedTemplate.name);
ctrl.formFields.unshift({
label: 'templateName',
displayName: 'Template Name',
type: 'java.lang.String',
helpText: null,
value: ctrl.selectedTemplate.name,
isReadOnly: true
});
ctrl.formFields.forEach(formField => {
formField.name = formField.label;
if (formField.displayName) {
formField.label = formField.displayName;
}
formField.type = Entaxy.convertToHtmlInputType(formField.type);
});
}
}
ctrl.back = function() {
if (ctrl.step2 === true) {
ctrl.step1 = true;
ctrl.step2 = false;
} else if (ctrl.step3 === true) {
ctrl.step2 = true;
ctrl.step3 = false;
}
}
ctrl.cancel = function() {
ctrl.modalInstance.dismiss();
}
ctrl.saveConnector = function(fields) {
ctrl.errors = validateFields(fields);
if (Object.keys(ctrl.errors).length === 0) {
let connectorArgs = {
profile: ctrl.selectedProfile,
connectorTemplateName: ctrl.formFields.shift().value,
connectorFields: ctrl.formFields.map(formField => { return { label: formField.name, value: formField.value }; })
};
ctrl.modalInstance.close(connectorArgs);
}
}
function validateFields(fields) {
let errors = {};
_.forEach(fields, (field) => {
if (field.isRequired &&
(!field.value || (field.type !== 'checkbox' ? field.value.toString().trim().length === 0 : false))) {
errors[field.name] = Entaxy.ERROR_MESSAGE.EMPTY;
}
});
return errors;
}
}
EntaxyAddConnectorModalController.$inject = ['workspace', 'jolokia'];
})(Entaxy || (Entaxy = {}));

View File

@ -0,0 +1,77 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-management-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var Entaxy;
(function (Entaxy) {
Entaxy._module.component('entaxyConfirmationModal', {
bindings: {
modalInstance: '<',
resolve: '<'
},
template:
`
<div class="entaxy-simple-modal-container message-modal-container">
<div class="modal-header">
<button type="button" class="close" aria-label="Close" ng-click="$ctrl.cancel()">
<span class="pficon pficon-close" aria-hidden="true"></span>
</button>
<h4 class="modal-title">{{$ctrl.title}}</h4>
</div>
<div class="modal-body-small">
<span class="simple-modal-message">
{{$ctrl.message}}
</span>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" ng-click="$ctrl.cancel()">Cancel</button>
<button type="submit" class="btn btn-primary" ng-click="$ctrl.confirm()">Confirm</button>
</div>
</div>
`,
controller: entaxyConfirmationModalController
})
.name;
function entaxyConfirmationModalController($uibModal) {
'ngInject';
let ctrl = this;
ctrl.$onInit = function() {
ctrl.title = ctrl.resolve.title;
ctrl.message = ctrl.resolve.message;
}
ctrl.cancel = function(reason) {
ctrl.modalInstance.dismiss(reason);
}
ctrl.confirm = function() {
ctrl.modalInstance.close(true);
}
}
entaxyConfirmationModalController.$inject = ['$uibModal'];
})(Entaxy || (Entaxy = {}));

View File

@ -0,0 +1,346 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-management-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var Entaxy;
(function (Entaxy) {
Entaxy._module.component('entaxyModal', {
bindings: {
modalInstance: '<',
resolve: '<'
},
template:
`
<div class="entaxy-modal-container">
<div class="modal-header">
<button type="button" class="close" aria-label="Close" ng-click="$ctrl.cancel()">
<span class="pficon pficon-close" aria-hidden="true"></span>
</button>
<h4 class="modal-title">{{$ctrl.modalTitle}}</h4>
</div>
<div ng-if="$ctrl.step1">
<div class="modal-body-header">
<h2>{{$ctrl.firstStepTitle}}</h2>
</div>
<div class="modal-body">
<entaxy-modal-list items="$ctrl.profiles" selected="$ctrl.selectedProfile"
change-selection="$ctrl.changeProfileSelection" enable-dbl-click="true"></entaxy-modal-list>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" ng-click="$ctrl.next()" ng-disabled="!$ctrl.selectedProfile">Next</button>
</div>
</div>
<div ng-if="$ctrl.step2">
<div class="modal-body-header">
<h2>{{$ctrl.secondStepTitle}}</h2>
</div>
<div class="modal-body">
<entaxy-modal-list-with-description items="$ctrl.factories" selected-item="$ctrl.selectedFactory"
change-selection="$ctrl.changeFactorySelection" show-deprecated="$ctrl.showDeprecated">
</entaxy-modal-list-with-description>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" ng-if="$ctrl.profiles" ng-click="$ctrl.back()">Back</button>
<button type="button" class="btn btn-default" ng-click="$ctrl.next()" ng-disabled="!$ctrl.selectedFactory">Next</button>
</div>
</div>
<div ng-if="$ctrl.step3">
<div class="modal-body-header form-header">
<h2>{{$ctrl.thirdStepTitle}}</h2>
<span ng-if="$ctrl.shouldShowChangesNote()">
There are unsaved changes
</span>
</div>
<div class="modal-body">
<entaxy-modal-group-fields groups="$ctrl.groups" fields="$ctrl.formFields"
use-form-dirty="true" is-form-dirty="$ctrl.isFormDirty"
errors="$ctrl.errors" mode="$ctrl.mode"></entaxy-modal-group-fields>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" ng-if="$ctrl.factories.length > 1 || $ctrl.profiles" ng-click="$ctrl.back()">Back</button>
<button type="submit" class="btn btn-primary" ng-click="$ctrl.save()">{{$ctrl.submitBtnTitle}}</button>
</div>
<div>
</div>
`,
controller: entaxyModalController
})
.name;
function entaxyModalController($scope, entaxyService, entaxyPrivateObjectsCacheService, entaxyProfileDiagramService) {
'ngInject';
var ctrl = this;
ctrl.$onInit = function() {
ctrl.mode = ctrl.resolve.mode;
if (!ctrl.mode) {
ctrl.cancel('Mode is not defined');
}
ctrl.hasChangedPrivateObjects = ctrl.mode !== Entaxy.MODAL_MODES.ADD ?
entaxyPrivateObjectsCacheService.isChanged(ctrl.resolve.itemMbeanName) : false;
ctrl.hasChangesFromDiagram = ctrl.mode === Entaxy.MODAL_MODES.EDIT ?
entaxyProfileDiagramService.hasChanges(ctrl.resolve.itemMbeanName) : false;
ctrl.itemType = ctrl.resolve.itemType ? ctrl.resolve.itemType : 'Item';
let extraToTitle = ctrl.resolve.parentName ? (' to ' + ctrl.resolve.parentName) : '';
ctrl.modalTitle = ctrl.mode + ' ' + ctrl.itemType + extraToTitle;
ctrl.submitBtnTitle = Entaxy.getButtonTitleByMode(ctrl.mode);
let itemName = ctrl.resolve.itemName;
ctrl.firstStepTitle = 'Choose profile to attach connector to';
ctrl.secondStepTitle = ctrl.resolve.secondStepTitle ? ctrl.resolve.secondStepTitle : 'Choose factory';
ctrl.thirdStepTitle = itemName ? ctrl.mode + ' properties for ' + itemName
: ctrl.resolve.thirdStepTitle ? ctrl.resolve.thirdStepTitle : 'Fill in fields';
if (ctrl.mode !== Entaxy.MODAL_MODES.ADD) {
ctrl.properties = ctrl.resolve.info.properties;
ctrl.configurableOnly = ctrl.resolve.info.configurableOnly;
}
ctrl.profiles = ctrl.resolve.profiles;
ctrl.factories = ctrl.resolve.factories ? ctrl.resolve.factories : null;
if (!ctrl.factories || ctrl.factories.length === 0) {
ctrl.cancel('Factories are not found');
}
ctrl.factories.sort(Entaxy.compareBy('displayName'));
if (ctrl.profiles) {
ctrl.step1 = true;
ctrl.step2 = false;
ctrl.step3 = false
} else {
if (ctrl.factories.length > 1) {
ctrl.step1 = false;
ctrl.step2 = true;
ctrl.step3 = false;
} else if (ctrl.factories.length === 1) {
ctrl.next();
}
}
}
ctrl.next = function() {
if (ctrl.step1 === true) {
if (ctrl.factories.length > 1) {
ctrl.step1 = false;
ctrl.step2 = true;
} else if (ctrl.factories.length === 1) {
defineFormFields();
}
} else {
defineFormFields();
}
}
function defineFormFields() {
let container = ctrl.formFields ? ctrl.formFields.find(field => field.name === '__entaxyContainerId') : undefined;
if (!ctrl.formFields || ctrl.selectedFactory.name !== ctrl.formFields[0].value
|| (ctrl.profiles && container.value !== ctrl.selectedProfile.name)) {
ctrl.formFields = [];
let currentFactory = ctrl.factories.length > 1 ? ctrl.selectedFactory : ctrl.factories[0];
ctrl.formFields.push({
label: 'Factory',
name: 'factoryId',
type: 'text',
description: currentFactory.description,
value: currentFactory.displayName,
originalValue: currentFactory.name,
readOnly: true,
required: ctrl.mode === Entaxy.MODAL_MODES.VIEW ? false : true,
group: 'general'
});
let mbeanName = ctrl.factories.length > 1 ? ctrl.selectedFactory.mbeanName : ctrl.factories[0].mbeanName;
entaxyService.getFields(mbeanName)
.then((response) => {
let groups = new Set();
groups.add('general');
_.forEach(JSON.parse(response), (field) => {
let objectId = undefined;
if (ctrl.mode !== Entaxy.MODAL_MODES.ADD) {
objectId = ctrl.resolve.info['objectId'];
}
let profileName = ctrl.selectedProfile ?
ctrl.selectedProfile.name : ctrl.resolve.parentName;
let formField = entaxyService.makeFormField(field, objectId, ctrl.properties,
ctrl.configurableOnly, ctrl.mode, ctrl.resolve.itemMbeanName, profileName);
if (formField) {
ctrl.formFields.push(formField);
groups.add(formField.group);
}
});
if (ctrl.mode !== Entaxy.MODAL_MODES.VIEW) {
processDependencies();
}
ctrl.groups = Array.from(groups).map((group) => { return { name: group, displayName: group }; });
ctrl.step1 = false;
ctrl.step2 = false;
ctrl.step3 = true;
});
} else {
ctrl.step1 = false;
ctrl.step2 = false;
ctrl.step3 = true;
}
}
let watchers = [];
function processDependencies() {
let dependentFormFields = entaxyService.getDependentFormFields(ctrl.formFields, ctrl.configurableOnly);
ctrl.definingFormFields = entaxyService.getDefiningFormFields(dependentFormFields, ctrl.formFields);
for (let i = 0; i < ctrl.definingFormFields.length; i++) {
if (ctrl.definingFormFields[i].value) {
let initialRunDependentFormFields = ctrl.mode === Entaxy.MODAL_MODES.ADD ?
dependentFormFields :
dependentFormFields.filter(field => (field.typeInfo && field.typeInfo.type === 'list'));
entaxyService.processDependencies(initialRunDependentFormFields,
ctrl.definingFormFields,
ctrl.definingFormFields[i].name,
ctrl.definingFormFields[i].value,
undefined);
}
watchers.push(
$scope.$watch('$ctrl.definingFormFields[' + i + '].value', function(newValue, oldValue) {
if (newValue !== oldValue) {
entaxyService.processDependencies(dependentFormFields,
ctrl.definingFormFields,
ctrl.definingFormFields[i].name,
newValue,
oldValue);
}
})
);
}
}
ctrl.back = function() {
if (ctrl.step2 === true) {
ctrl.step1 = true;
ctrl.step2 = false;
} else if (ctrl.step3 === true) {
ctrl.errors = undefined;
clearWatchers();
ctrl.step2 = true;
ctrl.step3 = false;
}
}
function clearWatchers() {
if (watchers && watchers.length > 0) {
watchers.forEach(watcher => {
watcher();
});
}
}
ctrl.cancel = function(reason) {
ctrl.modalInstance.dismiss(reason);
}
ctrl.changeProfileSelection = function(item, isDblClicked) {
ctrl.selectedProfile = item;
if (isDblClicked) {
ctrl.next();
}
}
ctrl.changeFactorySelection = function(item, isDblClicked) {
ctrl.selectedFactory = item;
if (isDblClicked) {
ctrl.next();
}
}
ctrl.shouldShowChangesNote = function () {
return ctrl.mode !== Entaxy.MODAL_MODES.ADD &&
(ctrl.isFormDirty || ctrl.hasChangedPrivateObjects || ctrl.hasChangesFromDiagram);
}
ctrl.save = function() {
if (ctrl.mode === Entaxy.MODAL_MODES.VIEW) {
ctrl.cancel();
}
let isConfirmationNeeded = ctrl.mode === Entaxy.MODAL_MODES.EDIT &&
!ctrl.isFormDirty && !ctrl.hasChangedPrivateObjects && !ctrl.hasChangesFromDiagram;
entaxyService.requestConfirmationForSavingIfNeededAndProceed(isConfirmationNeeded, save);
}
function save () {
let selectedFactory = ctrl.selectedFactory ? ctrl.selectedFactory : ctrl.factories[0];
let profileMBeanName = ctrl.selectedProfile ? ctrl.selectedProfile.mbeanName : undefined;
entaxyService.validateFields(ctrl.formFields, selectedFactory, ctrl.itemType,
profileMBeanName, ctrl.resolve.checkUniquenessParentFields)
.then(errors => {
ctrl.errors = errors;
if (Object.keys(ctrl.errors).length === 0) {
if (ctrl.resolve.returnFormFields) {
ctrl.modalInstance.close(Entaxy.deepCopy(ctrl.formFields));
} else {
let args = entaxyService.getArguments(ctrl.formFields, ctrl.factories);
args.configProperties = ctrl.properties;
args.configurableOnly = ctrl.configurableOnly;
ctrl.modalInstance.close(args);
}
}
});
}
}
entaxyModalController.$inject = ['$scope', 'entaxyService', 'entaxyPrivateObjectsCacheService',
'entaxyProfileDiagramService'];
})(Entaxy || (Entaxy = {}));

View File

@ -0,0 +1,86 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-management-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var Entaxy;
(function (Entaxy) {
Entaxy._module.component('entaxyOperationTableRequestModal', {
bindings: {
modalInstance: '<',
resolve: '<'
},
template:
`
<div class="entaxy-modal-container simple-modal-content operation-table-request-modal">
<div class="modal-header">
<button type="button" class="close" aria-label="Close" ng-click="$ctrl.cancel()">
<span class="pficon pficon-close" aria-hidden="true"></span>
</button>
<h4 class="modal-title">{{$ctrl.modalTitle}}</h4>
</div>
<div class="modal-body">
<p>{{$ctrl.message}}</p>
<div class="operation-affected-table-container">
<entaxy-operation-affected-table items="$ctrl.affectedObjects"></entaxy-operation-affected-table>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" ng-click="$ctrl.cancel()">Cancel</button>
<button type="button" class="btn btn-primary" ng-click="$ctrl.apply('current')">Apply only to current</button>
<button type="button" class="btn btn-primary" ng-click="$ctrl.apply('all')">Apply to all</button>
</div>
</div>
`,
controller: entaxyOperationTableRequestModalController
})
.name;
function entaxyOperationTableRequestModalController($uibModal) {
'ngInject';
let ctrl = this;
ctrl.$onInit = function() {
ctrl.operationType = ctrl.resolve.operationType.toUpperCase();
ctrl.modalTitle = 'Confirm operation ' + ctrl.operationType;
ctrl.message = 'To execute operation ' + ctrl.operationType + ' on '
+ ctrl.resolve.objectDisplayName + ' [' + ctrl.resolve.objectFullId + '] '
+ 'corresponding operations should be applied to the following affected objects:';
ctrl.affectedObjects = ctrl.resolve.affectedObjects;
}
ctrl.cancel = function(reason) {
ctrl.modalInstance.dismiss(reason);
}
ctrl.apply = function (flag) {
ctrl.modalInstance.close(flag);
}
}
entaxyOperationTableRequestModalController.$inject = ['$uibModal'];
})(Entaxy || (Entaxy = {}));

View File

@ -0,0 +1,229 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-management-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var Entaxy;
(function (Entaxy) {
Entaxy._module.component('entaxyResourceViewerModal', {
bindings: {
modalInstance: '<',
resolve: '<'
},
template:
`
<div class="entaxy-modal-container">
<div class="modal-header">
<button type="button" class="close" aria-label="Close" ng-click="$ctrl.cancel()">
<span class="pficon pficon-close" aria-hidden="true"></span>
</button>
<h4 class="modal-title">{{$ctrl.modalTitle}}</h4>
</div>
<div class="modal-body-without-header">
<div class="modal-resources-viewer-container">
<div class="modal-resources-viewer-header-container">
<entaxy-crumbs root-crumb="$ctrl.protocol" crumbs="$ctrl.crumbs"></entaxy-crumbs>
<button type="button" data-toggle="tooltip" title="Create folder"
ng-click="$ctrl.addFolder()" ng-if="$ctrl.enableFolderAdding">
<span class="pficon pficon-add-circle-o"></span>
</button>
</div>
<entaxy-file-panel items="$ctrl.items" selected-item="$ctrl.selectedItem" view="$ctrl.view"
change-selection-fn="$ctrl.changeSelection" open-fn="$ctrl.open"></entaxy-file-panel>
</div>
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary" ng-click="$ctrl.save()">Select</button>
</div>
</div>
`,
controller: entaxyResourceViewerModalController
})
.name;
function entaxyResourceViewerModalController($uibModal, $scope, entaxyResourcesService) {
'ngInject';
let ctrl = this;
ctrl.$onInit = function() {
ctrl.modalTitle = 'Select Resources';
ctrl.view = 'tiles';
ctrl.protocol = ctrl.resolve.config.resourceProvider;
let provider = entaxyResourcesService.getProviderMbean(ctrl.protocol);
ctrl.providerMBeanName = provider.objectName;
ctrl.filter = ctrl.resolve.config.filter;
ctrl.enableFolderSelection = ctrl.resolve.config.target === 'folder' ? true : false;
ctrl.enableFolderAdding = ctrl.resolve.config.enableFolderAdding;
let location = ctrl.resolve.location;
ctrl.useShortUrl = ctrl.resolve.config.useShortUrl;
if (location && location.includes(':')) {
let path = ctrl.useShortUrl ? location.split(':')[1] : location.slice(18);
if (path.length > 0) {
let splitPath = path.split('/');
if (!ctrl.useShortUrl) {
splitPath.shift();
}
if (!ctrl.enableFolderSelection) {
splitPath.pop();
}
// todo else check if the last item in path is folder or not
ctrl.crumbs = splitPath;
} else {
ctrl.crumbs = [];
}
} else {
ctrl.crumbs = [];
}
}
$scope.$watchCollection('$ctrl.crumbs', function(newValue, oldValue) {
ctrl.selectedItem = null;
updateItems();
})
ctrl.changeSelection = function (item) {
if (!item.error) {
ctrl.selectedItem = item;
} else {
Entaxy.notificationError('Cannot select the resource containing an error');
}
}
ctrl.open = function (item) {
if (item.isFolder === true) {
ctrl.crumbs.push(item.name);
} else {
ctrl.changeSelection(item);
if (!item.error) {
ctrl.save();
}
}
}
let clientFolders = [];
ctrl.addFolder = function () {
entaxyResourcesService.addFolder(ctrl.items, clientFolders, ctrl.crumbs);
}
function updateItems() {
let path = entaxyResourcesService.getPath(ctrl.crumbs);
getItems(path).then(originItems => {
if (ctrl.enableFolderAdding && ctrl.crumbs.length > 0 &&
originItems.length == 0 && clientFolders.length == 0) {
populateAddedFoldersFromLocation(ctrl.crumbs);
}
let items = originItems
.concat(entaxyResourcesService.getClientFoldersToAdd(clientFolders, originItems, ctrl.crumbs));
if (ctrl.filter === 'foldersOnly') {
items = items.filter(item => item.isFolder);
} else if (Array.isArray(ctrl.filter) && ctrl.filter.length > 0) {
items = items.filter(item => {
let match = false;
if (item.isFolder) {
return true;
}
ctrl.filter.forEach(filter => {
if (filter.startsWith('*') && item.name.endsWith(filter.substring(1, filter.length))) {
match = true;
}
});
return match;
});
} else if (ctrl.filter && ctrl.filter.startsWith('*')) {
items = items.filter(item => item.isFolder || item.name.endsWith(ctrl.filter.substring(1, ctrl.filter.length)));
}
ctrl.items = items.sort(Entaxy.compareBy('name')).sort((a, b) => b.isFolder - a.isFolder);
})
}
function populateAddedFoldersFromLocation(originCrumbs) {
let crumbs = Entaxy.deepCopy(originCrumbs);
if (crumbs.length > 0) {
let lastFolderName = crumbs.pop();
let path = entaxyResourcesService.getPath(crumbs);
getItems(path).then(result => {
let items = JSON.parse(result);
if (items.length == 0) {
let addedFolder = entaxyResourcesService.createFolder(lastFolderName, crumbs);
clientFolders.push(addedFolder);
populateAddedFoldersFromLocation(crumbs);
} else {
if (!items.map(item => item.name).includes(lastFolderName)) {
let addedFolder = entaxyResourcesService.createFolder(lastFolderName, crumbs);
clientFolders.push(addedFolder);
}
}
});
}
}
function getItems(path) {
return entaxyResourcesService.getResourcesInfo(ctrl.providerMBeanName, path);
}
ctrl.cancel = function(reason) {
ctrl.modalInstance.dismiss(reason);
}
ctrl.save = function() {
if (ctrl.selectedItem) {
if (!ctrl.selectedItem.isFolder || ctrl.enableFolderSelection) {
let path = entaxyResourcesService.getPath(ctrl.crumbs);
let folderLocation = getFolderLocation(path);
let separator = path.length > 0 ? '/' : '';
let location = folderLocation + separator + ctrl.selectedItem.name;
ctrl.modalInstance.close(location);
}
} else {
if (ctrl.enableFolderSelection) {
let path = entaxyResourcesService.getPath(ctrl.crumbs);
let folderLocation = getFolderLocation(path);
ctrl.modalInstance.close(folderLocation);
} else {
Entaxy.notificationError('There is no selected resource');
}
}
}
function getFolderLocation(path) {
return ctrl.useShortUrl ? ctrl.protocol + ':' + path : 'entaxy-resource://' + ctrl.protocol + '/' + path;
}
}
entaxyResourceViewerModalController.$inject = ['$uibModal', '$scope', 'entaxyResourcesService'];
})(Entaxy || (Entaxy = {}));

View File

@ -0,0 +1,117 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-management-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var Entaxy;
(function (Entaxy) {
Entaxy._module.component('entaxySimpleResourceNameInputModal', {
bindings: {
modalInstance: '<',
resolve: '<'
},
template:
`
<div class="entaxy-simple-modal-container">
<div class="modal-header">
<button type="button" class="close" aria-label="Close" ng-click="$ctrl.cancel()">
<span class="pficon pficon-close" aria-hidden="true"></span>
</button>
<h4 class="modal-title">{{$ctrl.title}}</h4>
</div>
<div class="modal-body-small">
<div class="form-group" ng-class="{'has-error': $ctrl.error}">
<div class="col-sm-12">
<input type="text" class="form-control" ng-model="$ctrl.name" ng-if="!$ctrl.extension">
<entaxy-input-with-extension model="$ctrl.name" ng-if="$ctrl.extension"
model-without-extension="$ctrl.nameWithoutExtension" extension="$ctrl.extension">
</entaxy-input-with-extension>
<span class="help-block" ng-show="$ctrl.error">{{$ctrl.error}}</span>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" ng-click="$ctrl.cancel()">Cancel</button>
<button type="submit" class="btn btn-primary" ng-click="$ctrl.save()">Save</button>
</div>
</div>
`,
controller: entaxySimpleResourceNameInputModalController
})
.name;
function entaxySimpleResourceNameInputModalController($uibModal) {
'ngInject';
let ctrl = this;
ctrl.$onInit = function() {
ctrl.title = ctrl.resolve.title;
ctrl.type = ctrl.resolve.type ? ctrl.resolve.type : 'Resource';
ctrl.name = ctrl.resolve.name;
if (ctrl.name && ctrl.type === 'Resource') {
let dotIndex = ctrl.name.lastIndexOf('.');
if (dotIndex > -1) {
ctrl.nameWithoutExtension = ctrl.name.slice(0, dotIndex);
ctrl.extension = ctrl.name.slice(dotIndex);
}
}
ctrl.names = ctrl.resolve.names;
}
ctrl.cancel = function(reason) {
ctrl.modalInstance.dismiss(reason);
}
ctrl.save = function() {
ctrl.error = validate();
if (!ctrl.error) {
ctrl.modalInstance.close(ctrl.name);
}
}
function validate() {
let error;
if (isEmpty(ctrl.name) || (ctrl.extension && isEmpty(ctrl.nameWithoutExtension))) {
return ctrl.type + ' name must not be empty';
}
['/', '\\', ':', '*', '?', '<', '>', '|'].forEach((symbol) => {
if (ctrl.name.indexOf(symbol) >= 0) {
error = ctrl.type + ' name must not include symbols /\\:*?<>|';
}
});
ctrl.names.forEach((name) => {
if (name === ctrl.name) {
error = ctrl.type + ' with this name already exists';
}
});
return error;
}
function isEmpty(value) {
return !value || value.length == 0 || value.trim().length == 0;
}
}
entaxySimpleResourceNameInputModalController.$inject = ['$uibModal'];
})(Entaxy || (Entaxy = {}));

View File

@ -0,0 +1,88 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-management-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var Entaxy;
(function (Entaxy) {
Entaxy._module.component('entaxyXmlModal', {
bindings: {
modalInstance: '<',
resolve: '<'
},
template:
`
<div class="entaxy-modal-container">
<div class="modal-header">
<button type="button" class="close" aria-label="Close" ng-click="$ctrl.cancel()">
<span class="pficon pficon-close" aria-hidden="true"></span>
</button>
<h4 class="modal-title">{{$ctrl.modalTitle}}</h4>
</div>
<div class="modal-body-without-header">
<div class="xml-editor-container">
<entaxy-xml-editor class="xml-editor" source-doc="$ctrl.xml" read-only="$ctrl.readOnly"></entaxy-xml-editor>
</div>
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary" ng-click="$ctrl.save($ctrl.formFields)">{{$ctrl.btnTitle}}</button>
</div>
</div>
`,
controller: entaxyXmlModalController
})
.name;
function entaxyXmlModalController($uibModal) {
'ngInject';
let ctrl = this;
ctrl.$onInit = function() {
ctrl.mode = ctrl.resolve.mode;
ctrl.modalTitle = ctrl.mode + ' XML';
ctrl.btnTitle = ctrl.resolve.defineButtonTitleByMode ? Entaxy.getButtonTitleByMode(ctrl.mode) : 'Ok';
ctrl.readOnly = ctrl.mode === Entaxy.MODAL_MODES.VIEW;
ctrl.xml = ctrl.resolve.xml;
}
ctrl.cancel = function(reason) {
ctrl.modalInstance.dismiss(reason);
}
ctrl.save = function() {
if (ctrl.readOnly) {
ctrl.cancel();
} else {
if ((ctrl.xml && angular.isString(ctrl.xml) && ctrl.xml.trim().length > 0) ||
!angular.isString(ctrl.xml)) {
ctrl.modalInstance.close(ctrl.xml);
} else {
Entaxy.notificationError('Value should not be empty');
}
}
}
}
entaxyXmlModalController.$inject = ['$uibModal'];
})(Entaxy || (Entaxy = {}));

View File

@ -0,0 +1,174 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-management-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var Entaxy;
(function (Entaxy) {
Entaxy._module
.component('entaxyConnectorsWithFlow', {
bindings: {
direction: '@',
connectors: '<',
profileName: '<',
editCustomizationPointFn: '<',
editProfilePropertiesFn: '<',
editPropertiesFn: '<',
saveConnectorFn: '<',
updateFn: '<'
},
template:
`
<div class="connectors-group-container">
<span class="connectors-group-title">{{$ctrl.connectorsGroupTitle}}</span>
<div class="connectors-with-flow-container">
<div class="connectors-container">
<div class="connector-block" ng-repeat="connector in $ctrl.connectors"
ng-class="{'has-changes': connector.isChanged}"
ng-click="$ctrl.editConnectorProperties(connector, $event)">
<div class="connector-info">
<div class="connector-title-container">
<span class="profile-diagram-support-span" ng-if="connector.isChanged"></span>
<span class="bold connector-title" data-toggle="tooltip" title="{{connector.displayName}}">
{{connector.displayName}}
</span>
<span class="pficon pficon-save" ng-click="$ctrl.saveConnector(connector, $event)"
data-toggle="tooltip" title="Save connector changes" ng-if="connector.isChanged"></span>
</div>
<span class="connector-classifier">{{connector.classifier}}</span>
</div>
<div id="{{connector.name}}_{{customizationPoint}}" class="customization-point-block"
ng-repeat="customizationPoint in $ctrl.connectorCustomizationPoints"
ng-click="$ctrl.editConnectorCustomizationPoint(connector, customizationPoint, $event)">
{{customizationPoint}}
</div>
</div>
</div>
<div id="{{$ctrl.direction}}-flow-block" class="flow-block"
ng-click="$ctrl.editProfileProperties($ctrl.direction + '-flow', $event)">
<span>{{$ctrl.flowName}}</span>
<div class="out-flow-customization-points-container" ng-if="$ctrl.isDirectionOut">
<div id="{{$ctrl.direction}}-flow_connector-selector"
class="customization-point-block connector-selector"
ng-click="$ctrl.editFlowCustomizationPoint('connector-selector', $event)"
data-toggle="tooltip" title="connector-selector">
<span class="connector-selector-icon"></span>
</div>
<div id="{{$ctrl.direction}}-flow_pre-route"
class="customization-point-block pre-route"
ng-click="$ctrl.editFlowCustomizationPoint('pre-route', $event)">
pre-route
</div>
</div>
<div id="{{$ctrl.direction}}-flow_{{customizationPoint}}" class="customization-point-block"
ng-repeat="customizationPoint in $ctrl.flowCustomizationPoints"
ng-click="$ctrl.editFlowCustomizationPoint(customizationPoint, $event)">
{{customizationPoint}}
</div>
</div>
</div>
</div>
`,
controller: entaxyConnectorsWithFlowController
})
.name;
function entaxyConnectorsWithFlowController(workspace) {
'ngInject';
let ctrl = this;
ctrl.$onInit = function() {
if (ctrl.direction) {
let isDirectionIn = ctrl.direction === 'in';
ctrl.isDirectionOut = !isDirectionIn;
ctrl.connectorsGroupTitle = '--- ' + ctrl.direction.toUpperCase() + ' ---';
ctrl.flowName = ctrl.direction.toUpperCase() + '-FLOW';
ctrl.connectorCustomizationPoints = isDirectionIn ? ['pre-route', 'response'] : ['pre-output', 'postprocess'];
ctrl.flowCustomizationPoints = isDirectionIn ? ['pre-route', 'response'] : ['postprocess'];
} else {
Entaxy.log.error('Connectors group direction is not defined');
}
}
ctrl.editConnectorProperties = function (connector, event) {
event.stopPropagation();
ctrl.editPropertiesFn(connector, Entaxy.RUNTIME_TYPE.CONNECTOR, 'Connector');
}
ctrl.editConnectorCustomizationPoint = function (connector, customizationPoint, event) {
event.stopPropagation();
let propertyName = getPropertyNameForConnectorCustomizationPoint(customizationPoint);
ctrl.editCustomizationPointFn(connector.mbeanName, propertyName, connector);
}
ctrl.editProfileProperties = function (groupName, event) {
event.stopPropagation();
ctrl.editProfilePropertiesFn(groupName);
}
ctrl.editFlowCustomizationPoint = function (customizationPoint, event) {
event.stopPropagation();
let selectedMbeanName = workspace.getSelectedMBeanName();
let propertyName = getPropertyNameForFlowCustomizationPoint(customizationPoint);
ctrl.editCustomizationPointFn(selectedMbeanName, propertyName);
}
function getPropertyNameForConnectorCustomizationPoint(customizationPointName) {
switch (customizationPointName) {
case 'pre-route':
case 'pre-output':
return customizationPointName;
case 'response':
case 'postprocess':
return 'responseRoute';
};
}
function getPropertyNameForFlowCustomizationPoint(customizationPointName) {
switch (customizationPointName) {
case 'pre-route':
return ctrl.direction + '-flow-' + customizationPointName;
case 'response':
case 'postprocess':
return ctrl.direction + '-flow-response';
case 'connector-selector':
return customizationPointName;
};
}
ctrl.saveConnector = function (connector, event) {
event.stopPropagation();
ctrl.saveConnectorFn(connector.mbeanName, true, false);
}
}
entaxyConnectorsWithFlowController.$inject = ['workspace'];
})(Entaxy || (Entaxy = {}));

View File

@ -0,0 +1,699 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-management-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var Entaxy;
(function (Entaxy) {
Entaxy._module
.component('entaxyProfileDiagramExternalSystemPoints', {
bindings: {
connectors: '<',
type: '@'
},
template:
`
<div ng-repeat="connector in $ctrl.connectors" ng-if="$ctrl.connectors && $ctrl.connectors.length > 0"
id="{{$ctrl.type}}-{{connector.name}}-block" class="external-system-point-block">
<span>{{$ctrl.type}}</span>
<div>
<span class="left-bracket"></span>
<span class="connector-info"
data-toggle="tooltip" title="{{connector.protocol}}">{{connector.protocol}}</span>
<span class="right-bracket"></span>
</div>
</div>
`
})
.component('entaxyProfileDiagram', {
template:
`
<div id="leader-lines-container" class="profile-diagram-with-palette-container">
<div class="profile-diagram-container">
<div class="blocks-container">
<entaxy-profile-diagram-external-system-points connectors="$ctrl.inConnectors" type="source">
</entaxy-profile-diagram-external-system-points>
<entaxy-profile-diagram-external-system-points connectors="$ctrl.outConnectors" type="target">
</entaxy-profile-diagram-external-system-points>
</div>
<div droppable handle-drop-fn="$ctrl.handleDropFn(droppedElementId)" class="profile-block"
ng-class="{'has-changes': $ctrl.isProfileChanged}"
ng-click="$ctrl.editProfileProperties('general')">
<div class="profile-title-container">
<span class="profile-diagram-support-span" ng-if="$ctrl.isProfileChanged"></span>
<span class="profile-title">{{$ctrl.profileTitle}}</span>
<span class="pficon pficon-save" ng-click="$ctrl.saveProfile($event)"
data-toggle="tooltip" title="Save profile changes" ng-if="$ctrl.isProfileChanged"></span>
</div>
<entaxy-connectors-with-flow direction="in" connectors="$ctrl.inConnectors"
profile-name="$ctrl.profileName" edit-customization-point-fn="$ctrl.editCustomizationPoint"
ng-if="$ctrl.inConnectors && $ctrl.inConnectors.length > 0" update-fn="$ctrl.update"
edit-profile-properties-fn="$ctrl.editProfileProperties"
edit-properties-fn="$ctrl.editProperties" save-connector-fn="$ctrl.save">
</entaxy-connectors-with-flow>
<entaxy-connectors-with-flow direction="out" connectors="$ctrl.outConnectors"
profile-name="$ctrl.profileName" edit-customization-point-fn="$ctrl.editCustomizationPoint"
ng-if="$ctrl.outConnectors && $ctrl.outConnectors.length > 0" update-fn="$ctrl.update"
edit-profile-properties-fn="$ctrl.editProfileProperties"
edit-properties-fn="$ctrl.editProperties" save-connector-fn="$ctrl.save">
</entaxy-connectors-with-flow>
</div>
<div class="blocks-container">
<div id="integrations-in-block" class="integrations-block"
ng-if="$ctrl.inConnectors && $ctrl.inConnectors.length > 0">
<span>integrations</span>
</div>
<div id="default-route-block" class="default-route-block"
ng-class="{'has-changes': $ctrl.isDefaultRouteChanged}"
ng-click="$ctrl.editDefaultRouteProperties()"
ng-if="$ctrl.inConnectors && $ctrl.inConnectors.length > 0">
<div class="default-route-title-container">
<span class="default-route-title">default-route</span>
<span class="pficon pficon-save" ng-click="$ctrl.saveDefaultRoute($event)"
data-toggle="tooltip" title="Save default route changes"
ng-if="$ctrl.isDefaultRouteChanged"></span>
</div>
<div class="customization-point-block"
ng-click="$ctrl.editDefaultRouteCustomizationPoint($event)">
route
</div>
</div>
<div id="integrations-out-block" class="integrations-block"
ng-if="$ctrl.outConnectors && $ctrl.outConnectors.length > 0">
<span>integrations</span>
</div>
</div>
</div>
<entaxy-profile-diagram-palette></entaxy-profile-diagram-palette>
</div>
`,
controller: entaxyProfileDiagramController
})
.name;
function entaxyProfileDiagramController($scope, workspace, jolokia, $location, $q,
entaxyService, entaxyProfileDiagramService, entaxyAttributesCacheService,
entaxyPrivateObjectsCacheService, $uibModal, $route, $cookies) {
'ngInject';
let ctrl = this;
let selectedMBean = workspace.getSelectedMBean();
let defaultRouteMbean = selectedMBean.findDescendant(child =>
child.objectName && child.objectName.endsWith('route=default'));
ctrl.$onInit = function () {
ctrl.profileName = jolokia.getAttribute(selectedMBean.objectName, 'Name')
ctrl.profileTitle = 'Profile: ' + ctrl.profileName;
ctrl.isProfileChanged = entaxyProfileDiagramService.isProfileChanged();
ctrl.isDefaultRouteChanged = entaxyProfileDiagramService.isDefaultRouteChanged();
populateConnectors();
}
setTimeout(function () {
let contentElement = document.getElementsByClassName("contents")[0];
contentElement.style.setProperty("padding", "0", "important");
}, 10);
function populateConnectors() {
let inConnectors = [];
let outConnectors = [];
if (selectedMBean && selectedMBean.isFolder) {
entaxyService.getAllChildMBeansByRuntimeType(selectedMBean, Entaxy.RUNTIME_TYPE.CONNECTOR)
.then((mbeans) => {
mbeans.forEach((mbean) => {
let direction = mbean.attributes.Direction;
let connectorMbeanName = mbean.mbean.objectName;
let isConnectorChanged = entaxyProfileDiagramService.isConnectorChanged(connectorMbeanName);
let connector = {
name: mbean.attributes.Name,
displayName: mbean.attributes.DisplayName,
classifier: mbean.attributes.Classifier,
protocol: mbean.attributes.Protocol,
mbeanName: connectorMbeanName,
isChanged: isConnectorChanged
};
if (direction === 'in') {
inConnectors.push(connector);
} else if (direction === 'out') {
outConnectors.push(connector);
}
if (isConnectorChanged) {
entaxyProfileDiagramService.getChanges(connectorMbeanName).connector = connector;
}
});
ctrl.inConnectors = inConnectors.sort(Entaxy.compareBy('name'));
ctrl.outConnectors = outConnectors.sort(Entaxy.compareBy('name'));
setMarginForAdditionalBlocks();
if (ctrl.inConnectors.length > 0) {
drawLinesForInDirectedConnectors();
}
if (ctrl.outConnectors.length > 0) {
drawLinesForOutDirectedConnectors();
}
});
}
}
ctrl.handleDropFn = function (factoryName) {
let factory = entaxyService.getFactoryByTitle(factoryName);
let selectedMbeanName = workspace.getSelectedMBeanName();
let parentName = jolokia.getAttribute(selectedMbeanName, 'Name');
let resolve = {
mode: () => Entaxy.MODAL_MODES.ADD,
itemType: () => 'Connector',
parentName: () => parentName,
factories: () => [ factory ]
};
entaxyService.openModalAndProcessResults(resolve, false, null, () => ctrl.connectorAdded = true);
}
// sets top margin for source, target, default-route and integration blocks
function setMarginForAdditionalBlocks() {
setTimeout(function () {
let sourceBlocksOccupiedHeight = 0;
let defaultRouteBlockMarginPlusHeight = 0;
let padding = 10;
if (ctrl.inConnectors && ctrl.inConnectors.length > 0) {
let integrationsInBlock = document.getElementById("integrations-in-block");
let inFlowBlock = document.getElementById("in-flow-block");
let inFlowPreRouteBlock = document.getElementById("in-flow_pre-route");
let defaultRouteBlock = document.getElementById("default-route-block");
let integrationsInBlockHeight = integrationsInBlock.offsetHeight;
let integrationsInBlockMarginTop = inFlowBlock.offsetTop -
integrationsInBlockHeight - padding;
let defaultRouteBlockMarginTop = inFlowPreRouteBlock.offsetTop -
integrationsInBlockMarginTop - integrationsInBlockHeight - padding;
integrationsInBlock.style.marginTop = integrationsInBlockMarginTop + 'px';
defaultRouteBlock.style.marginTop = defaultRouteBlockMarginTop + 'px';
defaultRouteBlockMarginPlusHeight = integrationsInBlockMarginTop + integrationsInBlockHeight +
defaultRouteBlockMarginTop + defaultRouteBlock.offsetHeight;
sourceBlocksOccupiedHeight =
setMarginForSourceOrTargetBlocks(ctrl.inConnectors, true, sourceBlocksOccupiedHeight, padding);
}
if (ctrl.outConnectors && ctrl.outConnectors.length > 0) {
let outFlowPreRouteBlock = document.getElementById("out-flow_pre-route");
let integrationsBlock = document.getElementById("integrations-out-block");
let integrationsBlockMarginTop = outFlowPreRouteBlock.offsetTop -
defaultRouteBlockMarginPlusHeight - padding;
integrationsBlock.style.marginTop = integrationsBlockMarginTop + 'px';
setMarginForSourceOrTargetBlocks(ctrl.outConnectors, false, sourceBlocksOccupiedHeight, padding);
}
});
};
function setMarginForSourceOrTargetBlocks(connectors, isSource, previousBlocksOccupiedHeight, padding) {
connectors.forEach(connector => {
let manageableBlock = isSource ?
document.getElementById("source-" + connector.name + "-block") :
document.getElementById("target-" + connector.name + "-block");
let connectorCustomizationPointBlock = isSource ?
document.getElementById(connector.name + "_pre-route") :
document.getElementById(connector.name + "_pre-output");
let manageableBlockMarginTop = connectorCustomizationPointBlock.offsetTop -
previousBlocksOccupiedHeight - padding;
manageableBlock.style.marginTop = manageableBlockMarginTop + 'px';
previousBlocksOccupiedHeight += manageableBlockMarginTop + manageableBlock.offsetHeight;
});
return previousBlocksOccupiedHeight;
}
let lines = [];
// draws lines for in-directed connector block
function drawLinesForInDirectedConnectors () {
setTimeout(function () {
if (ctrl.inConnectors) {
ctrl.inConnectors.forEach((connector) => {
lines.push(new LeaderLine(
LeaderLine.pointAnchor(
document.getElementById('source-' + connector.name + '-block'),
{x: '100%', y: 11}
),
document.getElementById(connector.name + '_pre-route'),
{color: 'green', size: 2, path: 'straight'}
));
lines.push(new LeaderLine(
document.getElementById(connector.name + '_pre-route'),
document.getElementById('in-flow_pre-route'),
{color: 'green', size: 2, path: 'grid', startSocketGravity: [10, 0]}
));
lines.push(new LeaderLine(
document.getElementById(connector.name + '_response'),
LeaderLine.pointAnchor(
document.getElementById('source-' + connector.name + '-block'),
{x: '100%', y: 43}
),
{color: 'blue', size: 2, path: 'straight'}
));
lines.push(new LeaderLine(
LeaderLine.pointAnchor(
document.getElementById('in-flow_response'),
{x: 0, y: '50%'}
),
document.getElementById(connector.name + '_response'),
{color: 'blue', size: 2, path: 'grid', startSocketGravity: [-10, 0]}
));
});
lines.push(new LeaderLine(
document.getElementById('in-flow_pre-route'),
LeaderLine.pointAnchor(
document.getElementById('default-route-block'),
{x: 0, y: 11}
),
{color: 'green', size: 2, path: 'straight'}
));
lines.push(new LeaderLine(
LeaderLine.pointAnchor(
document.getElementById('default-route-block'),
{x: 0, y: 43}
),
document.getElementById('in-flow_response'),
{color: 'blue', size: 2, path: 'straight'}
));
lines.push(new LeaderLine(
LeaderLine.pointAnchor(
document.getElementById('default-route-block'),
{x: 32.5, y: 0}
),
LeaderLine.pointAnchor(
document.getElementById('integrations-in-block'),
{x: 32.5, y: '100%'}
),
{color: 'green', size: 2, path: 'straight'}
));
lines.push(new LeaderLine(
LeaderLine.pointAnchor(
document.getElementById('integrations-in-block'),
{x: 64.5, y: '100%'}
),
LeaderLine.pointAnchor(
document.getElementById('default-route-block'),
{x: 64.5, y: 0}
),
{color: 'blue', size: 2, path: 'straight'}
));
}
}, 50);
}
// draws lines for out-directed connector block
function drawLinesForOutDirectedConnectors() {
setTimeout(function () {
if (ctrl.outConnectors) {
ctrl.outConnectors.forEach((connector) => {
lines.push(new LeaderLine(
document.getElementById(connector.name + '_pre-output'),
LeaderLine.pointAnchor(
document.getElementById('target-' + connector.name + '-block'),
{x: '100%', y: 11}
),
{color: 'green', size: 2, path: 'straight'}
));
lines.push(new LeaderLine(
document.getElementById('out-flow_pre-route'),
document.getElementById('out-flow_connector-selector'),
{color: 'green', size: 2, path: 'straight'}
));
lines.push(new LeaderLine(
LeaderLine.pointAnchor(
document.getElementById('out-flow_connector-selector'),
{x: 0, y: '50%'}
),
document.getElementById(connector.name + '_pre-output'),
{color: 'green', size: 2, path: 'grid', startSocketGravity: [-10, 0]}
));
lines.push(new LeaderLine(
LeaderLine.pointAnchor(
document.getElementById('target-' + connector.name + '-block'),
{x: '100%', y: 43}
),
document.getElementById(connector.name + '_postprocess'),
{color: 'blue', size: 2, path: 'straight'}
));
lines.push(new LeaderLine(
document.getElementById(connector.name + '_postprocess'),
document.getElementById('out-flow_postprocess'),
{color: 'blue', size: 2, path: 'grid', startSocketGravity: [10, 0]}
));
})
lines.push(new LeaderLine(
LeaderLine.pointAnchor(
document.getElementById('integrations-out-block'),
{x: 0, y: 11}
),
document.getElementById('out-flow_pre-route'),
{color: 'green', size: 2, path: 'straight'}
));
lines.push(new LeaderLine(
document.getElementById('out-flow_postprocess'),
LeaderLine.pointAnchor(
document.getElementById('integrations-out-block'),
{x: 0, y: 43}
),
{color: 'blue', size: 2, path: 'straight'}
));
}
}, 50);
}
// reposition of lines while container size is changed without changing window size
let resizeObserver = new ResizeObserver(entries => {
for (let entry of entries) {
if (entry.target.handleResize) {
entry.target.handleResize(entry);
}
}
});
setTimeout(function () {
document.querySelector('#leader-lines-container').handleResize = entry => {
lines.forEach(line => line.position());
}
resizeObserver.observe(document.querySelector('#leader-lines-container'));
}, 10);
// reposition of lines on scroll event
setTimeout(function () {
let leaderLinesContainerElement = document.getElementById("leader-lines-container");
leaderLinesContainerElement.onscroll = (event) => {
lines.forEach(line => line.position());
};
}, 10);
$scope.$on(Jmx.TreeEvent.Updated, () => {
if (ctrl.connectorAdded) {
$route.reload();
}
});
$scope.$on('$destroy', function () {
lines.forEach(line => line.remove());
resizeObserver.disconnect();
$cookies.remove('profile-properties-group');
});
ctrl.editProfileProperties = function (groupName) {
$cookies.putObject('profile-properties-group', groupName);
let selectedMbeanName = workspace.getSelectedMBeanName();
let profile = createItem(selectedMbeanName);
ctrl.editProperties(profile, Entaxy.RUNTIME_TYPE.PROFILE, 'Profile');
}
ctrl.editDefaultRouteProperties = function () {
let defaultRouteMbeanName = defaultRouteMbean.objectName;
let defaultRoute = createItem(defaultRouteMbeanName);
ctrl.editProperties(defaultRoute, Entaxy.RUNTIME_TYPE.DEFAULT_ROUTE, 'Default Route');
}
function createItem(mbeanName) {
let attributes = entaxyAttributesCacheService.getAttributes(mbeanName);
return {
name: attributes.Name,
mbeanName: mbeanName
};
}
ctrl.editProperties = function (item, runtimeType, itemType) {
entaxyService.readObjectClusterState(item.mbeanName).then(objectClusterState => {
let isNonClustered = objectClusterState === Entaxy.OBJECT_CLUSTER_STATE.NON_CLUSTERED;
if (isNonClustered) {
Entaxy.notificationInfo(Entaxy.NON_CLUSTERED_MESSAGE.EDITING);
}
let mode = isNonClustered ? Entaxy.MODAL_MODES.VIEW : Entaxy.MODAL_MODES.EDIT;
item.isLocal = objectClusterState === Entaxy.OBJECT_CLUSTER_STATE.LOCAL;
let args = entaxyProfileDiagramService.hasChanges(item.mbeanName) ?
entaxyProfileDiagramService.getArgs(item.mbeanName) : undefined;
let properties = args ? args.fields.filter(field => field.name !== 'routes') : undefined;
entaxyService.openEditItemModalAndProcessResults(item, itemType, runtimeType, mode,
properties, ctrl.update);
}).catch(e => Entaxy.notificationError(e));
}
ctrl.editDefaultRouteCustomizationPoint = function (event) {
event.stopPropagation();
if (defaultRouteMbean) {
ctrl.editCustomizationPoint(defaultRouteMbean.objectName, 'routeContent');
} else {
Entaxy.notificationError('Default route is not found.');
}
}
ctrl.editCustomizationPoint = function (mbeanName, propertyName, connector) {
if (entaxyProfileDiagramService.hasChanges(mbeanName)) {
let changes = entaxyProfileDiagramService.getChanges(mbeanName);
processPropertyAndOpenXmlEditor(changes, propertyName, mbeanName, true);
} else {
entaxyService.readConfiguration(mbeanName)
.then(objectInfo => {
let args = entaxyService.getArgumentsFromConfig(objectInfo);
let changes = entaxyProfileDiagramService.createChangesConfig(mbeanName, objectInfo.objectId,
args, objectInfo.configurableOnly, connector);
processPropertyAndOpenXmlEditor(changes, propertyName, mbeanName);
}).catch(error => {
Entaxy.notificationError(error);
Entaxy.log.error(error);
});
}
}
function processPropertyAndOpenXmlEditor(changes, propertyName, mbeanName, isRoutesFieldResolved) {
let args = changes.args;
let property = args.fields.find(property => property.name === propertyName);
if (property.value) {
if (isRoutesFieldResolved) {
resolveConfirmationAndOpenXmlEditor(changes, property, propertyName, mbeanName);
} else {
let selectedMbean = workspace.getSelectedMBean();
let mbean = selectedMbean.objectName === mbeanName ?
selectedMbean : selectedMbean.findDescendant(child => child.objectName === mbeanName);
entaxyService.resolveRoutesFieldValueAndAddNew(args, mbean)
.then(() => {
resolveConfirmationAndOpenXmlEditor(changes, property, propertyName, mbeanName);
});
}
} else {
Entaxy.notificationError('Content is not found');
}
}
function resolveConfirmationAndOpenXmlEditor(changes, property, propertyName, mbeanName) {
entaxyService.readObjectClusterState(mbeanName).then(objectClusterState => {
let isNonClustered = objectClusterState === Entaxy.OBJECT_CLUSTER_STATE.NON_CLUSTERED;
if (isNonClustered) {
Entaxy.notificationInfo(Entaxy.NON_CLUSTERED_MESSAGE.EDITING);
}
if (changes.configurableOnly || isNonClustered) {
getXmlAndOpenEditor(property, mbeanName, true, changes);
} else {
let args = changes.args;
let factoryMbeanName = args.factoryId.mbeanName;
entaxyService.getFields(factoryMbeanName).then(response => {
let fields = JSON.parse(response);
let currentField = fields.find(field => field.name === propertyName);
const UI = '@UI';
let managedByFieldName = currentField[UI] ? currentField[UI].managedBy : undefined;
if (managedByFieldName) {
let managingFieldProperty = args.fields
.find(field => field.name === managedByFieldName);
if (managingFieldProperty.value) {
getXmlAndOpenEditor(property, mbeanName, changes.configurableOnly, changes);
} else {
let managingField = fields.find(field => field.name === managedByFieldName);
let title = 'Confirm editing';
let message = managingField.displayName + ' is currently disabled. ' +
'Do you want to enable it and edit the ' + currentField.displayName + '?';
entaxyService.openConfirmationWindow(title, message).then(() => {
managingFieldProperty.value = true;
getXmlAndOpenEditor(property, mbeanName, changes.configurableOnly, changes);
});
}
} else {
getXmlAndOpenEditor(property, mbeanName, changes.configurableOnly, changes);
}
});
}
}).catch(e => Entaxy.notificationError(e));
}
function getXmlAndOpenEditor(property, mbeanName, readOnly, changes) {
entaxyService.getXmlFromConfigPropertyValue(property.value)
.then(xml => openXmlEditor(xml, property, mbeanName, readOnly, changes));
}
function openXmlEditor(originXml, property, mbeanName, readOnly, changes) {
$uibModal.open({
component: 'entaxyXmlModal',
resolve: {
xml: () => originXml,
mode: () => readOnly ? Entaxy.MODAL_MODES.VIEW : Entaxy.MODAL_MODES.EDIT
},
size: 'xl',
backdrop: 'static',
windowTopClass: 'modal-top-margin-override'
})
.result.then(xml => {
if (xml && xml.trim().length > 0) { // fixme
property.value = Entaxy.stringToBase64(xml);
if (!entaxyProfileDiagramService.hasChanges(mbeanName)) {
entaxyProfileDiagramService.setChanges(mbeanName, changes);
}
if (entaxyProfileDiagramService.hasType(mbeanName, Entaxy.RUNTIME_TYPE.PROFILE)) {
entaxyProfileDiagramService.setProfileChanged();
ctrl.isProfileChanged = entaxyProfileDiagramService.isProfileChanged();
} else if (entaxyProfileDiagramService.hasType(mbeanName, Entaxy.RUNTIME_TYPE.DEFAULT_ROUTE)) {
entaxyProfileDiagramService.setDefaultRouteChanged();
ctrl.isDefaultRouteChanged = entaxyProfileDiagramService.isDefaultRouteChanged();
} else if (entaxyProfileDiagramService.hasType(mbeanName, Entaxy.RUNTIME_TYPE.CONNECTOR)) {
entaxyProfileDiagramService.setConnectorChanged(mbeanName, true);
}
entaxyProfileDiagramService.setDirty();
} else {
Entaxy.notificationError('Value cannot be empty');
}
});
}
ctrl.saveProfile = function (event) {
event.stopPropagation();
ctrl.save(selectedMBean.objectName, true, true);
}
ctrl.saveDefaultRoute = function (event) {
event.stopPropagation();
ctrl.save(defaultRouteMbean.objectName, false);
}
ctrl.save = function (mbeanName, isConfirmationNeeded, isProfile) {
if (entaxyPrivateObjectsCacheService.isChanged(mbeanName) && isConfirmationNeeded) {
let title = 'Confirm Saving';
let type = isProfile ? 'Profile' : 'Connector';
let message = type + ' has unsaved changes of routes which will also be applied. ' +
'Do you want to continue?';
entaxyService.openConfirmationWindow(title, message).then(() => save(mbeanName));
} else {
save(mbeanName);
}
}
function save(mbeanName) {
let args = entaxyProfileDiagramService.getArgs(mbeanName);
entaxyService.resolveResourceRefFields(args.fields)
.then(() => entaxyService.saveItem(args, false, ctrl.update));
}
ctrl.update = function (properties, objectId) {
entaxyProfileDiagramService.resetChanges(objectId);
ctrl.isProfileChanged = entaxyProfileDiagramService.isProfileChanged();
ctrl.isDefaultRouteChanged = entaxyProfileDiagramService.isDefaultRouteChanged();
}
setTimeout( function () {
ctrl.activeTabIndex = entaxyService.getActiveTabIndex();
})
$scope.$on("$locationChangeStart", function(event) {
if (entaxyProfileDiagramService.isDirty()) {
if (!confirm(Entaxy.CONFIRMATION.UNSAVED_CHANGES)) {
event.preventDefault();
ctrl.isTreeOrTabSelectionUpdateNeeded = true;
} else {
entaxyProfileDiagramService.clear();
}
} else {
entaxyProfileDiagramService.clear();
}
});
$scope.$watch('$ctrl.isTreeOrTabSelectionUpdateNeeded', function (newValue) {
if (newValue) {
setTimeout(function () {
entaxyService.updateTabSelection(ctrl.activeTabIndex);
});
Jmx.updateTreeSelectionFromURL($location, $(entaxyTreeElementId));
ctrl.isTreeOrTabSelectionUpdateNeeded = false;
}
});
}
entaxyProfileDiagramController.$inject = ['$scope', 'workspace', 'jolokia', '$location', '$q',
'entaxyService', 'entaxyProfileDiagramService', 'entaxyAttributesCacheService',
'entaxyPrivateObjectsCacheService', '$uibModal', '$route', '$cookies'];
})(Entaxy || (Entaxy = {}));

View File

@ -0,0 +1,155 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-management-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var Entaxy;
(function (Entaxy) {
Entaxy._module
.component('entaxyProfileDiagramPalette', {
template:
`
<div class="profile-diagram-palette">
<div class="profile-diagram-palette-title">
<span>
Connectors Palette
</span>
<input type="search" class="form-control" placeholder="Search..." ng-model="$ctrl.filter"
ng-keypress="$ctrl.onValueKeyPress($event)">
</div>
<uib-accordion>
<div class="profile-diagram-palette-group-container">
<entaxy-profile-diagram-palette-group heading="---IN---" is-open="$ctrl.isInGroupOpened"
factories="$ctrl.viewedInFactories"></entaxy-profile-diagram-palette-group>
<entaxy-profile-diagram-palette-group heading="---OUT---" is-open="$ctrl.isOutGroupOpened"
factories="$ctrl.viewedOutFactories"></entaxy-profile-diagram-palette-group>
</div>
</uib-accordion>
</div>
`,
controller: entaxyProfileDiagramPaletteController
})
.component('entaxyProfileDiagramPaletteGroup', {
bindings: {
heading: '@',
isOpen: '=',
factories: '<'
},
template:
`
<div uib-accordion-group class="panel-default" heading="{{$ctrl.heading}}" is-open="$ctrl.isOpen">
<div class="profile-diagram-palette-items-container">
<div draggable class="profile-diagram-palette-item" id="{{factory.name}}"
ng-repeat="factory in $ctrl.factories"
data-toggle="tooltip" title="{{factory.description}}">
<span>{{ factory.displayName }}</span>
</div>
</div>
</div>
`
})
.name;
function entaxyProfileDiagramPaletteController($scope, jolokia, entaxyService, $cookies) {
'ngInject';
let ctrl = this;
ctrl.$onInit = function () {
populateConnectorFactories();
ctrl.isInGroupOpened = $cookies.getObject('diagram-palette-in-group-opened');
ctrl.isOutGroupOpened = $cookies.getObject('diagram-palette-out-group-opened');
}
function populateConnectorFactories() {
let factories = [];
let factoryFolder = entaxyService.getFolderByTitle(Entaxy.RUNTIME_TYPE.CONNECTOR);
if (factoryFolder && factoryFolder.children) {
factoryFolder.children.forEach((child) => {
let attributes = jolokia.getAttribute(child.objectName);
if (!attributes.Abstract) {
factories.push({
name: attributes.Id,
displayName: attributes.ShortName ? attributes.ShortName : attributes.Id,
mbeanName: child.objectName,
description: attributes.Description ?
attributes.Description : 'There is no description for this factory.',
direction: attributes.TypeInfo.direction,
label: attributes.Label
});
}
});
}
ctrl.inFactories = factories.filter(factory => factory.direction === 'in')
.sort(Entaxy.compareBy('displayName'));
ctrl.outFactories = factories.filter(factory => factory.direction === 'out')
.sort(Entaxy.compareBy('displayName'));
ctrl.viewedInFactories = ctrl.inFactories;
ctrl.viewedOutFactories = ctrl.outFactories;
}
$scope.$watch('$ctrl.isInGroupOpened', function (newValue) {
$cookies.putObject('diagram-palette-in-group-opened', newValue);
});
$scope.$watch('$ctrl.isOutGroupOpened', function (newValue) {
$cookies.putObject('diagram-palette-out-group-opened', newValue);
});
ctrl.onValueKeyPress = function (keyEvent) {
if (keyEvent.key === 'Enter') {
keyEvent.stopPropagation();
keyEvent.preventDefault();
if (ctrl.filter && ctrl.filter.length > 0) {
filter(ctrl.filter);
} else {
ctrl.viewedInFactories = ctrl.inFactories;
ctrl.viewedOutFactories = ctrl.outFactories;
}
}
}
function filter(filter) {
ctrl.viewedInFactories = ctrl.inFactories.filter(factory => matchesFilter(factory, filter));
ctrl.viewedOutFactories = ctrl.outFactories.filter(factory => matchesFilter(factory, filter));
}
function matchesFilter(factory, filter) {
let match = false;
if (factory.displayName.toLowerCase().match(filter.toLowerCase()) !== null &&
(factory.label && factory.label.toLowerCase().match(filter.toLowerCase()) !== null)) {
match = true
}
return match;
}
}
entaxyProfileDiagramPaletteController.$inject = ['$scope', 'jolokia', 'entaxyService', '$cookies'];
})(Entaxy || (Entaxy = {}));

View File

@ -0,0 +1,184 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-management-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var Entaxy;
(function (Entaxy) {
Entaxy._module.component('entaxyAliases', {
bindings: {
objectType: '@'
},
template:
`
<h2>Aliases</h2>
<pf-toolbar class="entaxy-toolbar" config="$ctrl.toolbarConfig"></pf-toolbar>
<pf-table-view config="$ctrl.tableConfig"
columns="$ctrl.tableColumns"
action-buttons="$ctrl.tableActionButtons"
page-config="$ctrl.pageConfig"
items="$ctrl.viewedItems">
</pf-table-view>
`,
controller: entaxyAliasesController
})
.name;
function entaxyAliasesController(workspace, operationsService, $uibModal) {
'ngInject';
let ctrl = this;
let selectedMBeanName = workspace.getSelectedMBeanName();
const OBJECT_TYPE = {
KEYSTORE: 'keystore'
}
ctrl.tableConfig = {
selectionMatchProp: 'name',
showCheckboxes: false
};
ctrl.toolbarConfig = {
filterConfig: {
fields: [
{
id: 'name',
title: 'Name',
placeholder: 'Filter by Name...',
filterType: 'text'
}
],
appliedFilters: [],
onFilterChange: filterChange
},
isTableView: true
};
ctrl.tableColumns = [
{ header: 'Name', itemField: 'name' }
];
ctrl.pageConfig = Entaxy.getStandardPageConfig();
function filterChange(filters) {
ctrl.viewedItems = Entaxy.applyFilters(ctrl.items, filters, matchesFilter);
ctrl.toolbarConfig.filterConfig.resultsCount = ctrl.viewedItems.length;
};
function matchesFilter(item, filter) {
let match = true;
if (filter.id === 'name') {
match = item.name.toLowerCase().match(filter.value.toLowerCase()) !== null;
}
return match;
};
ctrl.items = [];
ctrl.viewedItems = [];
ctrl.$onInit = function () {
populateTable();
let primaryActions = [
{ name: 'Add Alias', actionFn: () => ctrl.showAddKeyModal() }
];
ctrl.toolbarConfig.actionsConfig = {
primaryActions: primaryActions
};
ctrl.tableActionButtons = [
{ name: 'Remove', title: 'Remove Alias', actionFn: removeAlias }
];
}
function populateTable() {
operationsService.executeOperation(selectedMBeanName, { name: 'listAliases' }, [])
.then(aliases => {
let items = JSON.parse(aliases);
ctrl.items = items.map(item => { return { name: item }; });
ctrl.viewedItems = ctrl.items;
let filters = ctrl.toolbarConfig.filterConfig.appliedFilters;
if (filters.length > 0) {
filterChange(filters);
} else {
ctrl.toolbarConfig.filterConfig.resultsCount = items.length;
}
});
}
ctrl.showAddKeyModal = function () {
$uibModal.open({
component: 'entaxyUserManagementModal',
resolve: {
modalTitle: () => 'Add Alias',
formFields: () => [
{
label: 'Alias',
name: 'alias',
type: 'text',
required: true
},
{
label: ctrl.objectType === OBJECT_TYPE.KEYSTORE ? 'Key Content' : 'Value',
name: ctrl.objectType === OBJECT_TYPE.KEYSTORE ? 'keyContent' : 'value',
type: 'textarea',
required: true
}
]
},
backdrop: 'static'
}).result.then((args) => {
processOperation(ctrl.objectType === OBJECT_TYPE.KEYSTORE ? 'addKey' : 'writeValue', args);
},
reason => {
if (reason) {
Entaxy.notificationError(reason);
}
});
}
function removeAlias(action, item) {
processOperation(ctrl.objectType === OBJECT_TYPE.KEYSTORE ? 'removeKey' : 'removeValue', [item.name]);
}
function processOperation (operationName, properties) {
operationsService.executeOperation(selectedMBeanName, { name: operationName }, properties)
.then(result => {
Entaxy.notificationSuccess(result);
populateTable();
})
.catch(error => {
Entaxy.notificationError(error);
Entaxy.log.error(error);
});
}
}
entaxyAliasesController.$inject = ['workspace', 'operationsService', '$uibModal'];
})(Entaxy || (Entaxy = {}));

View File

@ -0,0 +1,352 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-management-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var Entaxy;
(function (Entaxy) {
Entaxy._module
.component('entaxyAllConnectorsTable', {
template:
`
<h2>
Connectors
</h2>
<pf-toolbar class="entaxy-toolbar" config="$ctrl.toolbarConfig"></pf-toolbar>
<pf-table-view config="$ctrl.tableConfig"
columns="$ctrl.tableColumns"
action-buttons="$ctrl.tableActionButtons"
menu-actions="$ctrl.menuActions"
page-config="$ctrl.pageConfig"
items="$ctrl.viewedItems">
</pf-table-view>
`,
controller: EntaxyAllConnectorsTableController
})
.name;
function EntaxyAllConnectorsTableController($q, workspace, $scope, operationsService,
jolokia, jolokiaService, entaxyService,
entaxyLegacyConnectorService, entaxyAttributesCacheService) {
'ngInject';
let ctrl = this;
ctrl.workspace = workspace;
ctrl.itemName = "Connector";
ctrl.statusName = "BundleState";
let filterValues = Entaxy.getAllBundleStates();
ctrl.tableConfig = {
selectionMatchProp: 'displayName',
showCheckboxes: false
};
ctrl.toolbarConfig = {
filterConfig: {
fields: [
{
id: 'displayName',
title: 'Name',
placeholder: 'Filter by Name...',
filterType: 'text'
},
{
id: 'direction',
title: 'Direction',
placeholder: 'Filter by Direction...',
filterType: 'select',
filterValues: ['in', 'out']
},
{
id: 'type',
title: 'Type',
placeholder: 'Filter by Type...',
filterType: 'text'
},
{
id: 'profile',
title: 'Profile',
placeholder: 'Filter by Profile...',
filterType: 'select',
filterValues: []
},
{
id: 'status',
title: 'Status',
placeholder: 'Filter by Status...',
filterType: 'select',
filterValues: filterValues
}
],
appliedFilters: [],
onFilterChange: filterChange
},
isTableView: true
};
ctrl.tableColumns = [
{ header: 'Direction', itemField: 'direction' },
{ header: 'Name', itemField: 'displayName' },
{ header: 'Type', itemField: 'type' },
{ header: 'Profile', itemField: 'profile' },
{ header: 'Status', itemField: 'status' }
];
ctrl.pageConfig = Entaxy.getStandardPageConfig();
function filterChange(filters) {
ctrl.viewedItems = Entaxy.applyFilters(ctrl.items, filters, matchesFilter);
ctrl.toolbarConfig.filterConfig.resultsCount = ctrl.viewedItems.length;
};
function matchesFilter(item, filter) {
let match = true;
if (filter.id === 'direction') {
match = item.direction === filter.value;
} else if (filter.id === 'displayName') {
match = item.displayName.match(filter.value) !== null;
} else if (filter.id === 'type') {
match = item.type.match(filter.value) !== null;
} else if (filter.id === 'profile') {
match = item.profile === filter.value;
} else if (filter.id === 'status') {
match = item.status === filter.value;
}
return match;
};
ctrl.items = [];
ctrl.viewedItems = [];
ctrl.$onInit = function() {
entaxyService.getProfiles().then(profiles => {
ctrl.profiles = profiles.sort(Entaxy.compareBy('name'));
populateTable();
let toolbarConfigFilterProfile = ctrl.toolbarConfig.filterConfig.fields
.find(field => field.id === 'profile');
toolbarConfigFilterProfile.filterValues = ctrl.profiles.map(profile => profile.name);
let primaryActions = [
{
name: 'Add Connector',
actionFn: () => ctrl.showModal(Entaxy.MODAL_MODES.ADD),
isDisabled: ctrl.profiles.length === 0
}//,
// {
// name: 'Add Legacy Connector',
// actionFn: () => ctrl.showAddLegacyConnectorModal(),
// isDisabled: ctrl.profiles.length === 0
// }
];
ctrl.toolbarConfig.actionsConfig = {
primaryActions: primaryActions
};
});
ctrl.tableActionButtons = [
{ name: 'Start', title: 'Start ' + ctrl.itemName, actionFn: checkAndProcess },
{ name: 'Stop', title: 'Stop ' + ctrl.itemName, actionFn: checkAndProcess },
{ name: 'Edit', title: 'Edit ' + ctrl.itemName + ' Properties', actionFn: showPropertiesModal }
];
ctrl.menuActions = [
{ name: 'Uninstall', title: 'Uninstall ' + ctrl.itemName, actionFn: checkAndProcess },
{ name: 'View Properties', title: 'View ' + ctrl.itemName + ' Properties', actionFn: showPropertiesModal }
];
}
function showPropertiesModal(action, item) {
if (action.name === 'View Properties') {
ctrl.showModal(Entaxy.MODAL_MODES.VIEW, item);
} else if (action.name === 'Edit') {
entaxyService.readObjectClusterState(item.mbeanName).then(objectClusterState => {
if (objectClusterState === Entaxy.OBJECT_CLUSTER_STATE.NON_CLUSTERED) {
Entaxy.notificationInfo(Entaxy.NON_CLUSTERED_MESSAGE.OPERATIONS);
} else {
item.isLocal = objectClusterState === Entaxy.OBJECT_CLUSTER_STATE.LOCAL;
ctrl.showModal(Entaxy.MODAL_MODES.EDIT, item);
}
}).catch(e => Entaxy.notificationError(e));
}
}
function populateTable() {
let items = [];
let profilesFolder = entaxyService.getDomainFolder()
.findDescendant(child => child.objectName && child.objectName.endsWith('category=profiles'));
entaxyService.getAllChildMBeansByRuntimeType(profilesFolder, Entaxy.RUNTIME_TYPE.CONNECTOR)
.then((mbeans) => {
mbeans.forEach(mbean => {
let connectorSystemName = mbean.attributes.System;
let profile = ctrl.profiles.find(profile => profile.name === connectorSystemName);
let displayName =
mbean.attributes.DisplayName && mbean.attributes.DisplayName.trim().length > 0 ?
mbean.attributes.DisplayName : mbean.attributes.Name;
let factoryId = mbean.attributes.FactoryId;
let factoryFolder = entaxyService.getFolderByTitle(factoryId);
if (factoryFolder) {
jolokiaService.getAttribute(factoryFolder.objectName, 'TypeInfo')
.then(typeInfo => {
items.push({
name: mbean.attributes.Name,
displayName: displayName,
direction: mbean.attributes.Direction ? mbean.attributes.Direction : '-',
type: typeInfo.type,
status: mbean.attributes[ctrl.statusName],
mbeanName: mbean.mbean.objectName,
profileMBeanName: profile.mbeanName,
profile: profile.name
});
});
}
});
ctrl.items = items;
ctrl.viewedItems = items;
let filters = ctrl.toolbarConfig.filterConfig.appliedFilters;
if (filters.length > 0) {
filterChange(filters);
} else {
ctrl.toolbarConfig.filterConfig.resultsCount = items.length;
}
});
}
ctrl.showModal = function(mode, item) {
let runtimeType = Entaxy.RUNTIME_TYPE.CONNECTOR;
if (mode === Entaxy.MODAL_MODES.ADD) {
let resolve = {
mode: () => mode,
itemType: () => ctrl.itemName,
profiles: () => ctrl.profiles
};
entaxyService.openAddItemModalAndProcessResults(resolve, runtimeType);
} else {
entaxyService.openEditItemModalAndProcessResults(item, ctrl.itemName, runtimeType, mode);
}
}
ctrl.showAddLegacyConnectorModal = function() {
let resolve = {
profiles: () => ctrl.profiles
};
entaxyLegacyConnectorService.openAddLegacyConnectorModal(resolve).then(connectorArgs => {
addLegacyConnector(connectorArgs);
});
}
function addLegacyConnector(connectorArgs) {
let args = entaxyLegacyConnectorService.getArguments(connectorArgs);
let mbeanName = connectorArgs.profile.mbeanName;
operationsService.executeOperation(mbeanName, { name: 'addConnector' }, args)
.then(result => {
Entaxy.notificationSuccess(result);
}).catch(error => {
Entaxy.notificationError(error);
});
}
$scope.$on(Jmx.TreeEvent.Updated, () => {
populateTable();
});
function checkAndProcess(action, item) {
entaxyService.readObjectClusterState(item.mbeanName).then(objectClusterState => {
if (objectClusterState === Entaxy.OBJECT_CLUSTER_STATE.LOCAL) {
Entaxy.notificationInfo('Local ' + ctrl.itemName.toLowerCase() + ' cannot be ' +
action.name.toLowerCase() +
(action.name.toLowerCase() === Entaxy.OPERATION_TYPE.STOP ? 'ped' : 'ed'));
} else if (objectClusterState === Entaxy.OBJECT_CLUSTER_STATE.NON_CLUSTERED) {
Entaxy.notificationInfo(Entaxy.NON_CLUSTERED_MESSAGE.OPERATIONS);
} else {
switch (action.name.toLowerCase()) {
case Entaxy.OPERATION_TYPE.START:
startItem(action, item);
return;
case Entaxy.OPERATION_TYPE.STOP:
stopItem(action, item);
return;
case Entaxy.OPERATION_TYPE.UNINSTALL:
uninstallItem(action, item);
return;
}
}
}).catch(e => Entaxy.notificationError(e));
}
function startItem(action, item) {
if (item.status !== 'Active') {
entaxyAttributesCacheService.setToUpdate(item.mbeanName);
entaxyService.processTableOperation(Entaxy.OPERATION_TYPE.START,
item.name, Entaxy.RUNTIME_TYPE.CONNECTOR, item.displayName);
} else {
Entaxy.notificationInfo(ctrl.itemName + ' has been already started');
}
}
function stopItem(action, item) {
if (item.status !== 'Resolved') {
entaxyAttributesCacheService.setToUpdate(item.mbeanName);
entaxyService.processTableOperation(Entaxy.OPERATION_TYPE.STOP,
item.name, Entaxy.RUNTIME_TYPE.CONNECTOR, item.displayName);
} else {
Entaxy.notificationInfo(ctrl.itemName + ' has been already stopped');
}
}
function uninstallItem(action, item) {
let title = 'Confirm Uninstalling';
let message = 'Do you want to uninstall ' + ctrl.itemName.toLowerCase() + ' ' + item.displayName + '?';
entaxyService.openConfirmationWindow(title, message).then(() => {
entaxyService.processTableOperation(Entaxy.OPERATION_TYPE.UNINSTALL,
item.name, Entaxy.RUNTIME_TYPE.CONNECTOR, item.displayName);
entaxyAttributesCacheService.removeFromCache(item.mbeanName);
});
}
ctrl.dismissAlert = () => ctrl.alert = null;
}
EntaxyAllConnectorsTableController.$inject = ['$q', 'workspace', '$scope', 'operationsService', 'jolokia',
'jolokiaService', 'entaxyService', 'entaxyLegacyConnectorService', 'entaxyAttributesCacheService'];
})(Entaxy || (Entaxy = {}));

View File

@ -0,0 +1,130 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-management-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var Entaxy;
(function (Entaxy) {
Entaxy._module.component('entaxyConfigProperties', {
template:
`
<h2>
Configuration Properties
</h2>
<pf-toolbar class="entaxy-toolbar" config="$ctrl.toolbarConfig"></pf-toolbar>
<pf-table-view config="$ctrl.tableConfig"
columns="$ctrl.tableColumns"
page-config="$ctrl.pageConfig"
items="$ctrl.viewedItems">
</pf-table-view>
`,
controller: EntaxyConfigPropertiesController
})
.name;
function EntaxyConfigPropertiesController(workspace, $location, $scope, $q, jolokia, jolokiaService, operationsService,
entaxyService) {
'ngInject';
let ctrl = this;
ctrl.tableConfig = {
selectionMatchProp: 'displayName',
showCheckboxes: false
};
ctrl.toolbarConfig = {
filterConfig: {
fields: [
{
id: 'displayName',
title: 'Name',
placeholder: 'Filter by Name...',
filterType: 'text'
}
],
appliedFilters: [],
onFilterChange: filterChange
},
isTableView: true
};
ctrl.tableColumns = [
{ header: 'Property', itemField: 'name' },
{ header: 'Name', itemField: 'displayName' },
{ header: 'Type', itemField: 'type' },
{ header: 'Value', itemField: 'value' }
];
ctrl.pageConfig = Entaxy.getStandardPageConfig();
function filterChange(filters) {
ctrl.viewedItems = Entaxy.applyFilters(ctrl.items, filters, matchesFilter);
ctrl.toolbarConfig.filterConfig.resultsCount = ctrl.viewedItems.length;
};
function matchesFilter(item, filter) {
return item.displayName.match(filter.value) !== null;
};
ctrl.items = [];
ctrl.viewedItems = [];
ctrl.$onInit = function() {
populateTable();
}
function populateTable() {
let items = [];
let selectedMbeanName = workspace.getSelectedMBeanName();
entaxyService.readConfiguration(selectedMbeanName).then(config => {
let itemKeys = Object.keys(config.properties);
let configHint = JSON.parse(Entaxy.base64ToString(config.properties.__entaxy_config_hint));
itemKeys.forEach(key => {
let fieldDescription = configHint.fields[key];
if (!fieldDescription.isInternal) {
items.push({
name: key,
displayName: fieldDescription.displayName,
type: fieldDescription.type,
value: config.properties[key]
});
}
});
ctrl.items = items;
ctrl.viewedItems = items;
ctrl.toolbarConfig.filterConfig.resultsCount = items.length;
});
}
}
EntaxyConfigPropertiesController.$inject = ['workspace', '$location', '$scope', '$q', 'jolokia', 'jolokiaService',
'operationsService', 'entaxyService'];
})(Entaxy || (Entaxy = {}));

View File

@ -0,0 +1,49 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-management-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var Entaxy;
(function (Entaxy) {
Entaxy._module.component('entaxyConnections', {
bindings: {
pageTitle: '@'
},
template:
`
<h2>
{{$ctrl.pageTitle}}
</h2>
<entaxy-table runtime-type="{{$ctrl.runtimeType}}" status-name="Status" object-name="name"></entaxy-table>
`,
controller: EntaxyConnectionsController
})
.name;
function EntaxyConnectionsController() {
let ctrl = this;
ctrl.runtimeType = Entaxy.RUNTIME_TYPE.CONNECTION;
}
})(Entaxy || (Entaxy = {}));

View File

@ -0,0 +1,99 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-management-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var Entaxy;
(function (Entaxy) {
Entaxy._module
.component('entaxyConnectors', {
bindings: {
pageTitle: '@'
},
template:
`
<h2>
{{$ctrl.pageTitle}}
</h2>
<entaxy-table runtime-type="{{$ctrl.runtimeType}}"
status-name="BundleState" object-name="systemName"
is-parent-dependent="true" skip-location-update="true"
population-parent-mbean-name="$ctrl.populationParentMbeanName"></entaxy-table>
`,
controller: EntaxyConnectorsController
})
.name;
function EntaxyConnectorsController(workspace, operationsService, jolokia, entaxyLegacyConnectorService) {
'ngInject';
let ctrl = this;
ctrl.runtimeType = Entaxy.RUNTIME_TYPE.CONNECTOR;
ctrl.workspace = workspace;
let primaryActions = [ { name: 'Add Legacy Connector', actionFn: () => ctrl.showAddConnectorModal() } ];
ctrl.config = {
primaryActions: primaryActions,
isTableUpdateNeeded: true
}
ctrl.$onInit = function () {
let selectedMbean = workspace.getSelectedMBean();
ctrl.populationParentMbeanName = selectedMbean.objectName ?
selectedMbean.objectName : selectedMbean.parent.objectName;
}
ctrl.showAddConnectorModal = function() {
let parentMBeanName = ctrl.populationParentMbeanName ?
ctrl.populationParentMbeanName : workspace.getSelectedMBeanName();
let resolve = {
profileName: () => jolokia.getAttribute(parentMBeanName, 'Name')
};
entaxyLegacyConnectorService.openAddLegacyConnectorModal(resolve).then(connectorArgs => {
addConnector(connectorArgs);
});
}
function addConnector(connectorArgs) {
let args = entaxyLegacyConnectorService.getArguments(connectorArgs);
let mbeanName = ctrl.populationParentMbeanName ?
ctrl.populationParentMbeanName : workspace.getSelectedMBeanName();
operationsService.executeOperation(mbeanName, { name: 'addConnector' }, args)
.then(result => {
Entaxy.notificationSuccess(result);
}).catch(error => {
Entaxy.notificationError(error);
});
}
ctrl.dismissAlert = () => ctrl.alert = null;
}
EntaxyConnectorsController.$inject = ['workspace', 'operationsService', 'jolokia', 'entaxyLegacyConnectorService'];
})(Entaxy || (Entaxy = {}));

View File

@ -0,0 +1,49 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-management-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var Entaxy;
(function (Entaxy) {
Entaxy._module.component('entaxyKeyStores', {
bindings: {
pageTitle: '@'
},
template:
`
<h2>
{{$ctrl.pageTitle}}
</h2>
<entaxy-table runtime-type="{{$ctrl.runtimeType}}" status-name="BundleState" object-name="systemName">
</entaxy-table>
`,
controller: EntaxyKeyStoresController
})
.name;
function EntaxyKeyStoresController() {
let ctrl = this;
ctrl.runtimeType = Entaxy.RUNTIME_TYPE_SECURITY.KEY_STORE;
}
})(Entaxy || (Entaxy = {}));

View File

@ -0,0 +1,61 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-management-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var Entaxy;
(function (Entaxy) {
Entaxy._module.component('entaxyOperationAffectedTable', {
bindings: {
items: '<'
},
template:
`
<pf-table-view config="$ctrl.tableConfig"
columns="$ctrl.tableColumns"
items="$ctrl.items">
</pf-table-view>
`,
controller: EntaxyOperationAffectedTableController
})
.name;
function EntaxyOperationAffectedTableController() {
'ngInject';
let ctrl = this;
ctrl.tableConfig = {
selectionMatchProp: 'objectId',
showCheckboxes: false
};
ctrl.tableColumns = [
{ header: 'Object', itemField: 'objectId' },
{ header: 'Operation', itemField: 'action' }
];
}
EntaxyOperationAffectedTableController.$inject = [];
})(Entaxy || (Entaxy = {}));

View File

@ -0,0 +1,51 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-management-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var Entaxy;
(function (Entaxy) {
Entaxy._module
.component('entaxyProfiles', {
bindings: {
pageTitle: '@'
},
template:
`
<h2>
{{$ctrl.pageTitle}}
</h2>
<entaxy-table runtime-type="{{$ctrl.runtimeType}}" status-name="BundleState" object-name="systemName">
</entaxy-table>
`,
controller: EntaxyProfilesController
})
.name;
function EntaxyProfilesController() {
let ctrl = this;
ctrl.runtimeType = Entaxy.RUNTIME_TYPE.PROFILE;
}
})(Entaxy || (Entaxy = {}));

View File

@ -0,0 +1,49 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-management-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var Entaxy;
(function (Entaxy) {
Entaxy._module.component('entaxyRealms', {
bindings: {
pageTitle: '@'
},
template:
`
<h2>
{{$ctrl.pageTitle}}
</h2>
<entaxy-table runtime-type="{{$ctrl.runtimeType}}" status-name="BundleState" object-name="systemName">
</entaxy-table>
`,
controller: EntaxyRealmsController
})
.name;
function EntaxyRealmsController() {
let ctrl = this;
ctrl.runtimeType = Entaxy.RUNTIME_TYPE_SECURITY.JAAS_REALM;
}
})(Entaxy || (Entaxy = {}));

View File

@ -0,0 +1,51 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-management-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var Entaxy;
(function (Entaxy) {
Entaxy._module
.component('entaxyRepositories', {
bindings: {
pageTitle: '@'
},
template:
`
<h2>
{{$ctrl.pageTitle}}
</h2>
<entaxy-table runtime-type="{{$ctrl.runtimeType}}" status-name="BundleState" object-name="systemName">
</entaxy-table>
`,
controller: EntaxyRepositoriesController
})
.name;
function EntaxyRepositoriesController() {
let ctrl = this;
ctrl.runtimeType = Entaxy.RUNTIME_TYPE.REPOSITORY;
}
})(Entaxy || (Entaxy = {}));

View File

@ -0,0 +1,50 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-management-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var Entaxy;
(function (Entaxy) {
Entaxy._module.component('entaxyRouteLibraries', {
bindings: {
pageTitle: '@'
},
template:
`
<h2>
{{$ctrl.pageTitle}}
</h2>
<entaxy-table runtime-type="{{$ctrl.runtimeType}}" status-name="BundleState" object-name="systemName">
</entaxy-table>
`,
controller: EntaxyRouteLibrariesController
})
.name;
function EntaxyRouteLibrariesController() {
let ctrl = this;
ctrl.runtimeType = Entaxy.RUNTIME_TYPE.ROUTE_LIBRARY;
}
})(Entaxy || (Entaxy = {}));

View File

@ -0,0 +1,43 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-management-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var Entaxy;
(function (Entaxy) {
Entaxy._module.component('entaxyRoutes', {
bindings: {
pageTitle: '@'
},
template:
`
<h2>
{{$ctrl.pageTitle}}
</h2>
<entaxy-routes-table></entaxy-routes-table>
`
})
.name;
})(Entaxy || (Entaxy = {}));

View File

@ -0,0 +1,366 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-management-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var Entaxy;
(function (Entaxy) {
Entaxy._module.component('entaxyRoutesTable', {
template:
`
<pf-toolbar class="entaxy-toolbar" config="$ctrl.toolbarConfig"></pf-toolbar>
<pf-table-view config="$ctrl.tableConfig"
columns="$ctrl.tableColumns"
action-buttons="$ctrl.tableActionButtons"
page-config="$ctrl.pageConfig"
items="$ctrl.viewedItems"
ng-if="$ctrl.ready">
</pf-table-view>
`,
controller: EntaxyRoutesTableController
})
.name;
function EntaxyRoutesTableController(workspace, $location, $scope, $uibModal, entaxyService,
entaxyAttributesCacheService, entaxyPrivateObjectsCacheService) {
'ngInject';
let ctrl = this;
ctrl.workspace = workspace;
const STATUS = {
NEW: 'New',
TO_REMOVAL: 'To Removal'
};
let filterValues = Entaxy.getAllBundleStates();
filterValues.push(STATUS.NEW);
filterValues.push(STATUS.TO_REMOVAL);
ctrl.tableConfig = {
selectionMatchProp: 'displayName',
showCheckboxes: false
};
ctrl.toolbarConfig = {
filterConfig: {
fields: [
{
id: 'displayName',
title: 'Name',
placeholder: 'Filter by Name...',
filterType: 'text'
},
{
id: 'status',
title: 'Status',
placeholder: 'Filter by Status...',
filterType: 'select',
filterValues: filterValues
}
],
appliedFilters: [],
onFilterChange: filterChange
},
isTableView: true
};
ctrl.tableColumns = [
{ header: 'Name', itemField: 'displayName' },
{ header: 'Status', itemField: 'status' }
];
ctrl.pageConfig = Entaxy.getStandardPageConfig();
function filterChange(filters) {
ctrl.viewedItems = Entaxy.applyFilters(ctrl.items, filters, matchesFilter);
ctrl.toolbarConfig.filterConfig.resultsCount = ctrl.viewedItems.length;
}
function matchesFilter(item, filter) {
let match = true;
if (filter.id === 'displayName') {
match = item.displayName.toLowerCase().match(filter.value.toLowerCase()) !== null;
} else if (filter.id === 'status') {
match = item.status.match(filter.value) !== null;
}
return match;
}
ctrl.items = [];
ctrl.viewedItems = [];
ctrl.$onInit = function() {
ctrl.runtimeType = Entaxy.RUNTIME_TYPE.ROUTE;
populateTable();
ctrl.itemType = Entaxy.getItemTypeFromRuntimeType(ctrl.runtimeType);
populateActionButtons();
}
function populateActionButtons() {
let selectedMbean = workspace.getSelectedMBean();
let ownerMbean = selectedMbean.parent;
entaxyService.readExtendedData(ownerMbean.objectName)
.then(result => {
let extendedData = JSON.parse(result);
if (!extendedData.applications) {
let primaryActions = [ { name: 'Add ' + ctrl.itemType, actionFn: () => ctrl.showModal() } ];
ctrl.toolbarConfig.actionsConfig = {
primaryActions: primaryActions
};
ctrl.tableActionButtons = [
{ name: 'Remove', title: 'Remove ' + ctrl.itemType, actionFn: removeItem },
{ name: 'Restore', title: 'Restore ' + ctrl.itemType, actionFn: restoreItem }
];
}
ctrl.ready = true;
});
}
function populateTable() {
let selectedMBean = workspace.getSelectedMBean();
if (selectedMBean && selectedMBean.isFolder) {
let items = [];
let children = selectedMBean.children;
if (children && children.length > 0) {
let mbeans = [];
children.forEach(child => {
if (child.objectName) {
let attributes = entaxyAttributesCacheService.getAttributes(child.objectName);
if (attributes.RuntimeType === ctrl.runtimeType) {
mbeans.push({ mbean: child, attributes: attributes });
}
}
});
items = createItemsFromMbeans(mbeans);
}
if (entaxyPrivateObjectsCacheService.hasAddedChildren(selectedMBean.objectName)) {
items = items.concat(createItemsFromAddedObjectsInfo(selectedMBean.objectName));
}
ctrl.items = items;
filterChange(ctrl.toolbarConfig.filterConfig.appliedFilters);
}
}
function createItemsFromMbeans(mbeans) {
let items = [];
mbeans.forEach((mbean) => {
let displayName = mbean.attributes.DisplayName &&
mbean.attributes.DisplayName.trim().length > 0 ?
mbean.attributes.DisplayName : mbean.attributes.Name;
let changedObjectInfo = entaxyPrivateObjectsCacheService
.getChangedObjectInfo(mbean.attributes.ObjectFullId);
items.push({
id: mbean.attributes.Name,
routeId: mbean.attributes.RouteId,
displayName: displayName,
status: changedObjectInfo && changedObjectInfo.toRemoval ?
mbean.attributes.BundleState + ' [' + STATUS.TO_REMOVAL + ']' :
mbean.attributes.BundleState,
mbeanName: mbean.mbean.objectName,
objectFullId: mbean.attributes.ObjectFullId,
toRemoval: changedObjectInfo && changedObjectInfo.toRemoval
});
});
return items;
}
function createItemsFromAddedObjectsInfo(selectedMBeanMame) {
let items = [];
entaxyPrivateObjectsCacheService.getAddedObjectsInfo(selectedMBeanMame).forEach(addedObject => {
items.push({
id: addedObject.ui.id,
routeId: addedObject.properties.routeId,
displayName: addedObject.properties.displayName ?
addedObject.properties.displayName : addedObject.ui.id,
status: addedObject.toRemoval ? STATUS.NEW + ' [' + STATUS.TO_REMOVAL + ']' : STATUS.NEW,
added: true,
toRemoval: addedObject.toRemoval
});
});
return items;
}
ctrl.showModal = function() {
let selectedMbeanName = workspace.getSelectedMBeanName();
let attributes = entaxyAttributesCacheService.getAttributes(selectedMbeanName);
let ownerRuntimeType = attributes.ObjectType;
let ownerFactoryId = attributes.FactoryId;
let factoryMbean = entaxyService.getFolderByTitle(ownerRuntimeType).get(ownerFactoryId);
entaxyService.getFields(factoryMbean.objectName).then(result => {
let fields = JSON.parse(result);
let routesField = fields.find(field => field.name === 'routes');
let factoryFilter = routesField && routesField.itemFactory ?
routesField.itemFactory.filter : undefined;
entaxyService.getFactoriesByFilterSearch(factoryFilter, true).then(factories => {
let typeInfo = routesField['@TYPEINFO'];
let validation = typeInfo ? typeInfo.validation : undefined;
let checkUniqueness = validation && validation.rules && validation.rules.checkUniqueness ?
validation.rules.checkUniqueness : undefined;
let checkUniquenessFields = {};
if (checkUniqueness) {
checkUniqueness.fields.forEach(field => {
checkUniquenessFields[field] = [];
if (ctrl.items) {
ctrl.items.forEach(item => {
if (item[field]) {
checkUniquenessFields[field].push(item[field]);
}
});
}
});
}
let itemTypes = typeInfo && typeInfo.privateObjectTypes ?
typeInfo.privateObjectTypes.map(type => type.displayName).join(' or ') : 'Route';
$uibModal.open({
component: 'entaxyModal',
resolve: {
mode: () => Entaxy.MODAL_MODES.ADD,
itemType: () => itemTypes,
factories: () => factories,
returnFormFields: () => true,
checkUniquenessParentFields: () => checkUniquenessFields
},
size: 'xl',
backdrop: 'static',
windowTopClass: 'modal-top-margin-override'
})
.result.then(formFields => {
// object full id of route-container actually has object full id of its owner
let ownerFullId = attributes.ObjectFullId;
addItem(formFields, routesField, factories, ownerFullId, typeInfo.useAsIdentifier);
},
reason => {
if (reason) {
Entaxy.notificationError(reason);
}
});
});
});
}
function addItem(formFields, routesField, factories, ownerFullId, identifierFieldName) {
let args = entaxyService.getArguments(formFields, factories);
let objectId = args.fields.find(field => field.name === 'objectId').value;
let argFields = args.fields.filter(field => field.name !== 'objectId');
let properties = argFields.reduce((obj, cur) => ({ ...obj, [cur.name] : cur.value }), {});
if (!identifierFieldName) {
identifierFieldName = 'routeId';
}
let routeType = args.factoryId.attributes['typeinfo.routeType'];
let itemInfo = {
objectId: objectId,
factoryId: args.factoryId.name,
scope: routesField.itemScope,
type: routesField.itemType,
properties: properties,
ui: {
id: properties[identifierFieldName],
identifierFieldName: identifierFieldName,
formFields: formFields,
owner: ownerFullId,
routeType: routeType
}
};
let selectedMbean = workspace.getSelectedMBean();
entaxyPrivateObjectsCacheService.addNew(selectedMbean, itemInfo);
workspace.loadTree();
changeLocation(itemInfo.ui.id);
}
function changeLocation(itemName) {
let currentLocation = $location.search();
$location.search('nid', currentLocation.nid + '-' + itemName);
}
$scope.$on(Jmx.TreeEvent.Updated, () => {
populateTable();
});
function removeItem(action, item) {
if (!item.toRemoval) {
let selectedMbean = workspace.getSelectedMBean();
if (item.added) {
entaxyPrivateObjectsCacheService.setAddedObjectToRemoval(selectedMbean.objectName, item.id);
} else {
entaxyService.readConfiguration(item.mbeanName).then(config => {
entaxyPrivateObjectsCacheService.setObjectToRemoval(item.objectFullId, item.mbeanName, config);
});
}
workspace.loadTree();
Entaxy.notificationSuccess('Operation Succeeded');
} else {
Entaxy.notificationInfo(ctrl.itemType + ' has been already set to removal');
}
}
function restoreItem (action, item) {
if (item.toRemoval) {
if (item.added) {
let selectedMbeanName = workspace.getSelectedMBeanName();
entaxyPrivateObjectsCacheService.restoreAddedObject(selectedMbeanName, item.id);
} else {
entaxyPrivateObjectsCacheService.restoreObject(item.objectFullId);
}
workspace.loadTree();
Entaxy.notificationSuccess('Operation Succeeded');
} else {
Entaxy.notificationInfo(ctrl.itemType + ' has been already restored');
}
}
ctrl.dismissAlert = () => ctrl.alert = null;
}
EntaxyRoutesTableController.$inject = ['workspace', '$location', '$scope', '$uibModal', 'entaxyService',
'entaxyAttributesCacheService', 'entaxyPrivateObjectsCacheService'];
})(Entaxy || (Entaxy = {}));

View File

@ -0,0 +1,51 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-management-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var Entaxy;
(function (Entaxy) {
Entaxy._module
.component('entaxyServices', {
bindings: {
pageTitle: '@'
},
template:
`
<h2>
{{$ctrl.pageTitle}}
</h2>
<entaxy-table runtime-type="{{$ctrl.runtimeType}}" status-name="BundleState" object-name="systemName">
</entaxy-table>
`,
controller: EntaxyServicesController
})
.name;
function EntaxyServicesController() {
let ctrl = this;
ctrl.runtimeType = Entaxy.RUNTIME_TYPE.SERVICE;
}
})(Entaxy || (Entaxy = {}));

View File

@ -0,0 +1,306 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-management-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var Entaxy;
(function (Entaxy) {
Entaxy._module
.component('entaxyTable', {
bindings: {
runtimeType: '@',
statusName: '@',
objectName: '@',
isParentDependent: '<',
extraPrimaryActionsConfig: '<',
populationParentMbeanName: '<',
skipLocationUpdate: '<'
},
template:
`
<pf-toolbar class="entaxy-toolbar" config="$ctrl.toolbarConfig"></pf-toolbar>
<pf-table-view config="$ctrl.tableConfig"
columns="$ctrl.tableColumns"
action-buttons="$ctrl.tableActionButtons"
menu-actions="$ctrl.menuActions"
page-config="$ctrl.pageConfig"
items="$ctrl.viewedItems">
</pf-table-view>
`,
controller: EntaxyTableController
})
.name;
function EntaxyTableController(workspace, $location, $scope, $q, jolokia, jolokiaService, operationsService,
entaxyService, entaxyAttributesCacheService) {
'ngInject';
var ctrl = this;
ctrl.workspace = workspace;
let filterValues = Entaxy.getAllBundleStates();
ctrl.tableConfig = {
selectionMatchProp: 'displayName',
showCheckboxes: false
};
ctrl.toolbarConfig = {
filterConfig: {
fields: [
{
id: 'displayName',
title: 'Name',
placeholder: 'Filter by Name...',
filterType: 'text'
},
{
id: 'status',
title: 'Status',
placeholder: 'Filter by Status...',
filterType: 'select',
filterValues: filterValues
}
],
appliedFilters: [],
onFilterChange: filterChange
},
isTableView: true
};
ctrl.tableColumns = [
{ header: 'Name', itemField: 'displayName' },
{ header: 'Status', itemField: 'status' }
];
ctrl.pageConfig = Entaxy.getStandardPageConfig();
function filterChange(filters) {
ctrl.viewedItems = Entaxy.applyFilters(ctrl.items, filters, matchesFilter);
ctrl.toolbarConfig.filterConfig.resultsCount = ctrl.viewedItems.length;
}
function matchesFilter(item, filter) {
let match = true;
if (filter.id === 'displayName') {
match = item.displayName.toLowerCase().match(filter.value.toLowerCase()) !== null;
} else if (filter.id === 'status') {
match = item.status === filter.value;
}
return match;
}
ctrl.items = [];
ctrl.viewedItems = [];
ctrl.$onInit = function() {
populateTable();
ctrl.itemType = Entaxy.getItemTypeFromRuntimeType(ctrl.runtimeType);
let primaryActions = [ { name: 'Add ' + ctrl.itemType, actionFn: () => ctrl.showModal(Entaxy.MODAL_MODES.ADD) } ];
if (ctrl.extraPrimaryActionsConfig) {
let extraPrimaryActions = ctrl.extraPrimaryActionsConfig.primaryActions;
primaryActions = primaryActions.concat(extraPrimaryActions);
if (ctrl.extraPrimaryActionsConfig.isTableUpdateNeeded) {
ctrl.extraPrimaryActionsConfig.updateTableFn = populateTable;
}
}
ctrl.toolbarConfig.actionsConfig = {
primaryActions: primaryActions
};
ctrl.tableActionButtons = [
{ name: 'Start', title: 'Start ' + ctrl.itemType, actionFn: checkAndProcess },
{ name: 'Stop', title: 'Stop ' + ctrl.itemType, actionFn: checkAndProcess },
{ name: 'Edit', title: 'Edit ' + ctrl.itemType + ' Properties', actionFn: showPropertiesModal }
];
ctrl.menuActions = [
{ name: 'Uninstall', title: 'Uninstall ' + ctrl.itemType, actionFn: checkAndProcess },
{ name: 'View Properties', title: 'View ' + ctrl.itemType + ' Properties', actionFn: showPropertiesModal }
];
}
function showPropertiesModal(action, item) {
if (action.name === 'View Properties') {
ctrl.showModal(Entaxy.MODAL_MODES.VIEW, item);
} else if (action.name === 'Edit') {
entaxyService.readObjectClusterState(item.mbeanName).then(objectClusterState => {
if (objectClusterState === Entaxy.OBJECT_CLUSTER_STATE.NON_CLUSTERED) {
Entaxy.notificationInfo(Entaxy.NON_CLUSTERED_MESSAGE.OPERATIONS);
} else {
item.isLocal = objectClusterState === Entaxy.OBJECT_CLUSTER_STATE.LOCAL;
ctrl.showModal(Entaxy.MODAL_MODES.EDIT, item);
}
}).catch(e => Entaxy.notificationError(e));
}
}
function populateTable() {
let items = [];
let selectedMBean = ctrl.populationParentMbeanName ?
entaxyService.getDomainFolder()
.findDescendant(child => child.objectName === ctrl.populationParentMbeanName) :
workspace.getSelectedMBean();
if (selectedMBean && selectedMBean.isFolder) {
entaxyService.getAllChildMBeansByRuntimeType(selectedMBean, ctrl.runtimeType).then((mbeans) => {
mbeans.forEach((mbean) => {
let displayName = mbean.attributes.DisplayName &&
mbean.attributes.DisplayName.trim().length > 0 ?
mbean.attributes.DisplayName : mbean.attributes.Name;
items.push({
name: mbean.attributes.Name,
displayName: displayName,
status: mbean.attributes[ctrl.statusName],
mbeanName: mbean.mbean.objectName
});
});
ctrl.items = items;
ctrl.viewedItems = items;
let filters = ctrl.toolbarConfig.filterConfig.appliedFilters;
if (filters.length > 0) {
filterChange(filters);
} else {
ctrl.toolbarConfig.filterConfig.resultsCount = items.length;
}
});
}
}
ctrl.showModal = function(mode, item) {
if (mode === Entaxy.MODAL_MODES.ADD) {
let parentMBeanName = ctrl.populationParentMbeanName ?
ctrl.populationParentMbeanName : workspace.getSelectedMBeanName();
let parentName = ctrl.isParentDependent === true ?
jolokia.getAttribute(parentMBeanName, 'Name') : undefined;
let resolve = {
mode: () => mode,
itemType: () => ctrl.itemType,
parentName: () => parentName
};
entaxyService.openAddItemModalAndProcessResults(resolve, ctrl.runtimeType, updateLocation);
} else {
entaxyService.openEditItemModalAndProcessResults(item, ctrl.itemType, ctrl.runtimeType, mode);
}
}
function updateLocation(properties, objectId) {
if (!ctrl.skipLocationUpdate) {
let itemName =
ctrl.runtimeType === Entaxy.RUNTIME_TYPE.REPOSITORY ||
ctrl.runtimeType === Entaxy.RUNTIME_TYPE.ROUTE_LIBRARY ?
objectId + '_' + ctrl.runtimeType :
properties[ctrl.objectName] ? properties[ctrl.objectName] : objectId;
changeLocation(itemName);
}
}
function changeLocation(itemName) {
let currentLocation = $location.search();
$location.search('nid', currentLocation.nid + '-' + itemName);
}
$scope.$on(Jmx.TreeEvent.Updated, () => {
populateTable();
});
function checkAndProcess(action, item) {
entaxyService.readObjectClusterState(item.mbeanName).then(objectClusterState => {
if (objectClusterState === Entaxy.OBJECT_CLUSTER_STATE.LOCAL) {
Entaxy.notificationInfo('Local ' + ctrl.itemType.toLowerCase() + ' cannot be ' +
action.name.toLowerCase() +
(action.name.toLowerCase() === Entaxy.OPERATION_TYPE.STOP ? 'ped' : 'ed'));
} else if (objectClusterState === Entaxy.OBJECT_CLUSTER_STATE.NON_CLUSTERED) {
Entaxy.notificationInfo(Entaxy.NON_CLUSTERED_MESSAGE.OPERATIONS);
} else {
switch (action.name.toLowerCase()) {
case Entaxy.OPERATION_TYPE.START:
startItem(action, item);
return;
case Entaxy.OPERATION_TYPE.STOP:
stopItem(action, item);
return;
case Entaxy.OPERATION_TYPE.UNINSTALL:
uninstallItem(action, item);
return;
}
}
}).catch(e => Entaxy.notificationError(e));
}
function startItem(action, item) {
if (item.status !== 'Active') {
entaxyAttributesCacheService.setToUpdate(item.mbeanName);
entaxyService.processTableOperation(Entaxy.OPERATION_TYPE.START,
item.name, ctrl.runtimeType, item.displayName);
} else {
Entaxy.notificationInfo(ctrl.itemType + ' has been already started');
}
}
function stopItem(action, item) {
if (item.status !== 'Resolved') {
entaxyAttributesCacheService.setToUpdate(item.mbeanName);
entaxyService.processTableOperation(Entaxy.OPERATION_TYPE.STOP,
item.name, ctrl.runtimeType, item.displayName);
} else {
Entaxy.notificationInfo(ctrl.itemType + ' has been already stopped');
}
}
function uninstallItem(action, item) {
let title = 'Confirm Uninstalling';
let message = 'Do you want to uninstall ' + ctrl.itemType.toLowerCase() + ' ' + item.displayName + '?';
entaxyService.openConfirmationWindow(title, message).then(() => {
let selectedFolder = entaxyService.getDomainFolder()
.findDescendant(child => child.objectName === item.mbeanName);
let children = Entaxy.getChildrenRecursive(selectedFolder);
entaxyAttributesCacheService.removeFromCache(item.mbeanName);
if (children) {
children.forEach(child => entaxyAttributesCacheService.removeFromCache(child.objectName));
}
entaxyService.processTableOperation(Entaxy.OPERATION_TYPE.UNINSTALL,
item.name, ctrl.runtimeType, item.displayName);
});
}
ctrl.dismissAlert = () => ctrl.alert = null;
}
EntaxyTableController.$inject = ['workspace', '$location', '$scope', '$q', 'jolokia', 'jolokiaService',
'operationsService', 'entaxyService', 'entaxyAttributesCacheService'];
})(Entaxy || (Entaxy = {}));

View File

@ -0,0 +1,49 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-management-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var Entaxy;
(function (Entaxy) {
Entaxy._module.component('entaxyVaults', {
bindings: {
pageTitle: '@'
},
template:
`
<h2>
{{$ctrl.pageTitle}}
</h2>
<entaxy-table runtime-type="{{$ctrl.runtimeType}}" status-name="BundleState" object-name="systemName">
</entaxy-table>
`,
controller: EntaxyVaultsController
})
.name;
function EntaxyVaultsController() {
let ctrl = this;
ctrl.runtimeType = Entaxy.RUNTIME_TYPE_SECURITY.VAULT;
}
})(Entaxy || (Entaxy = {}));

View File

@ -0,0 +1,110 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-management-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var Entaxy;
(function (Entaxy) {
Entaxy._module.component('entaxyAssociatedProfileSelect', {
bindings: {
username: '<'
},
template:
`
<entaxy-select-from-enum id="{{$ctrl.formField.name}}" values="$ctrl.formField.values"
model="$ctrl.formField.value" readonly="$ctrl.formField.readOnly"
is-empty-included="true" empty-option-name="'--No Profile--'"></entaxy-select-from-enum>
`,
controller: EntaxyAssociatedProfileSelectController
})
.name;
function EntaxyAssociatedProfileSelectController(workspace, operationsService, entaxyService, $scope) {
'ngInject';
let ctrl = this;
let selectedMbeanName = workspace.getSelectedMBeanName();
ctrl.$onInit = function() {
entaxyService.getProfiles().then(profiles => {
ctrl.formField = {
readOnly: true,
values: profiles.sort(Entaxy.compareBy('name')).map(profile => profile.name)
}
});
}
$scope.$watch('$ctrl.username', function (newValue, oldValue) {
if (newValue) {
getAssociatedProfile();
}
})
function getAssociatedProfile() {
operationsService
.executeOperation(selectedMbeanName, { name: 'getAssociatedProfile' }, [ ctrl.username ])
.then(profileName => {
if (profileName === 'Empty string') {
ctrl.formField.value = undefined;
ctrl.associatedProfile = undefined;
ctrl.formField.readOnly = false;
} else {
entaxyService.getProfiles().then(profiles => {
let profile = profiles.find(profile => profile.name === profileName);
if (profile) {
ctrl.formField.value = profileName;
ctrl.associatedProfile = profileName;
} else {
Entaxy.notificationError('Associated profile ' + profileName + ' not found');
}
ctrl.formField.readOnly = false;
});
}
});
}
$scope.$watch('$ctrl.formField.value', function (newValue) {
if (newValue !== ctrl.associatedProfile) {
ctrl.associatedProfile = newValue;
associateProfile();
}
})
function associateProfile() {
let parameters = [ ctrl.username, ctrl.associatedProfile ];
operationsService
.executeOperation(selectedMbeanName, { name: 'associateProfile' }, parameters)
.then(() => {
Entaxy.notificationSuccess('Profile ' + ctrl.associatedProfile +
' was successfully associated with user ' + ctrl.username);
})
.catch(error => {
Entaxy.notificationError('An error occurred while associating profile ' + ctrl.associatedProfile +
' to user ' + ctrl.username);
Entaxy.log.error(error);
})
}
}
EntaxyAssociatedProfileSelectController.$inject = ['workspace', 'operationsService', 'entaxyService', '$scope'];
})(Entaxy || (Entaxy = {}));

View File

@ -0,0 +1,210 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-management-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var Entaxy;
(function (Entaxy) {
Entaxy._module.component('entaxyGroupsAndRolesList', {
bindings: {
username: '<',
reloadFn: '<'
},
template:
`
<entaxy-expandable-list items="$ctrl.items" action-buttons="$ctrl.actionButtons" use-toolbar="true"
toolbar-action-buttons="$ctrl.toolbarActionButtons"
enable-toolbar-action-buttons="$ctrl.username ? true : false"
empty-state-config="$ctrl.emptyStateConfig">
</entaxy-expandable-list>
`,
controller: EntaxyGroupsAndRolesListController
})
.name;
function EntaxyGroupsAndRolesListController(workspace, operationsService, entaxyService, $q, $scope, $uibModal) {
'ngInject';
let ctrl = this;
let selectedMbeanName = workspace.getSelectedMBeanName();
let ITEM_TYPES = {
ROLE: 'Role',
GROUP: 'Group'
}
ctrl.toolbarActionButtons = [
{ name: 'Add Group', actionFn: () => showAddGroupModal(), isDisabled: ctrl.username ? false : true },
{ name: 'Add Role', actionFn: () => showAddRoleModal(), isDisabled: ctrl.username ? false : true }
];
ctrl.emptyStateConfig = {
title: 'There is no selected user'
};
ctrl.actionButtons = [{
name: 'Delete',
actionFn: deleteRoleOrGroup
}];
$scope.$watch('$ctrl.username', function (newValue, oldValue) {
if (newValue) {
populateItems();
} else {
ctrl.items = [];
}
})
function populateItems() {
let promises = [];
promises.push(listRolesOrGroups(ctrl.username, 'listRolesForUser'));
promises.push(listRolesOrGroups(ctrl.username, 'listGroupsForUser'));
promises.push(operationsService.executeOperation(selectedMbeanName, { name: 'listGroups'}, []));
$q.all(promises).then(result => {
let roles = JSON.parse(result[0]);
ctrl.roles = JSON.parse(result[0]).map(role => role.name);
let items = [];
let userGroups = JSON.parse(result[1]);
let allGroups = JSON.parse(result[2]);
userGroups.forEach(group => {
let groupWithRoles = allGroups.find(groupWithRoles => group.name === groupWithRoles.name);
groupWithRoles.roles = groupWithRoles.roles.split(',').sort(Entaxy.compare());
groupWithRoles.isGroup = true;
roles = roles.filter(role => !groupWithRoles.roles.includes(role.name));
items.push(groupWithRoles);
});
items.push(...roles);
items.map(item => {
item.displayName = item.name;
if (item.roles) {
item.sublist = item.roles.map(role => {
return {
displayName: role,
typeIcon: 'pf pficon-user',
disableRowExpansion: true
};
});
} else {
item.disableRowExpansion = true;
}
item.typeIcon = item.isGroup ? 'pf pficon-users' : 'pf pficon-user';
return item;
});
ctrl.items = items.sort(Entaxy.compareBy('displayName'));
});
}
function listRolesOrGroups(username, operationName) {
return operationsService.executeOperation(selectedMbeanName, { name: operationName }, [ username ]);
}
function showAddRoleModal() {
openUserManagementModalAndProcess(ITEM_TYPES.ROLE);
}
function showAddGroupModal() {
operationsService.executeOperation(selectedMbeanName, {name: 'listGroups'}, [])
.then(list => {
let items = JSON.parse(list);
let values = items
.filter(item => !includesGroup(item.name))
.map(item => item.name)
.sort(Entaxy.compare());
openUserManagementModalAndProcess(ITEM_TYPES.GROUP, values);
});
}
function openUserManagementModalAndProcess(itemType, values) {
if (itemType === ITEM_TYPES.GROUP && values.length === 0) {
Entaxy.notificationInfo('There are no groups that can be added');
return;
}
$uibModal.open({
component: 'entaxyUserManagementModal',
resolve: {
modalTitle: () => 'Add ' + itemType + ' to ' + ctrl.username,
formFields: () => getFormFields(itemType, values)
},
backdrop: 'static'
}).result.then((args) => {
entaxyService.processUserManagementOperation('add' + itemType, args, populateItems);
}, reason => {
if (reason) {
Entaxy.notificationError(reason);
}
});
}
function getFormFields(itemType, values) {
let formFields = [
{
label: 'Username',
name: 'username',
type: 'text',
required: true,
value: ctrl.username,
readOnly: true
},
{
label: itemType + ' Name',
name: Entaxy.uncapitalize(itemType),
type: 'text',
required: true,
enum: itemType === ITEM_TYPES.GROUP ? true : false,
values: itemType === ITEM_TYPES.GROUP ? values : undefined,
validation: itemType === ITEM_TYPES.ROLE ? {
checkUniqueness: true,
values: ctrl.roles
} : undefined
}
];
return formFields;
}
function includesGroup(itemName) {
let item = ctrl.items.find(item => item.name === itemName);
return item && item.isGroup;
}
function deleteRoleOrGroup(action, item) {
let operationName = item.isGroup ? 'deleteGroup' : 'deleteRole';
let postProcessFn = item.isGroup ? ctrl.reloadFn : populateItems;
entaxyService.processUserManagementOperation(operationName, [ ctrl.username, item.name ], postProcessFn);
}
}
EntaxyGroupsAndRolesListController.$inject = ['workspace', 'operationsService', 'entaxyService', '$q', '$scope',
'$uibModal'];
})(Entaxy || (Entaxy = {}));

View File

@ -0,0 +1,226 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-management-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var Entaxy;
(function (Entaxy) {
Entaxy._module.component('entaxyGroupsTable', {
bindings: {
reloadFn: '<'
},
template:
`
<pf-toolbar class="entaxy-toolbar" config="$ctrl.toolbarConfig"></pf-toolbar>
<pf-table-view config="$ctrl.tableConfig"
columns="$ctrl.tableColumns"
action-buttons="$ctrl.tableActionButtons"
page-config="$ctrl.pageConfig"
items="$ctrl.viewedItems">
</pf-table-view>
`,
controller: EntaxyGroupsTableController
})
.name;
function EntaxyGroupsTableController(workspace, operationsService, entaxyService, $uibModal) {
'ngInject';
let ctrl = this;
let selectedMbeanName = workspace.getSelectedMBeanName();
let delimeter = ', ';
ctrl.tableConfig = {
selectionMatchProp: 'name',
showCheckboxes: false
};
ctrl.toolbarConfig = {
filterConfig: {
fields: [
{
id: 'name',
title: 'Group',
placeholder: 'Filter by Group...',
filterType: 'text'
},
{
id: 'roles',
title: 'Roles',
placeholder: 'Filter by Roles...',
filterType: 'text'
}
],
appliedFilters: [],
onFilterChange: filterChange
},
isTableView: true
};
ctrl.tableColumns = [
{ header: 'Group', itemField: 'name' },
{ header: 'Roles', itemField: 'roles' }
];
ctrl.pageConfig = Entaxy.getStandardPageConfig();
function filterChange(filters) {
ctrl.viewedItems = Entaxy.applyFilters(ctrl.items, filters, matchesFilter);
ctrl.toolbarConfig.filterConfig.resultsCount = ctrl.viewedItems.length;
};
function matchesFilter(item, filter) {
let match = true;
if (filter.id === 'name') {
match = item.name.match(filter.value) !== null;
} else if (filter.id === 'roles') {
match = item.roles.match(filter.value) !== null;
}
return match;
};
ctrl.items = [];
ctrl.viewedItems = [];
ctrl.$onInit = function() {
populateTable();
let primaryActions = [ { name: 'Create Group', actionFn: () => showCreateGroupModal() } ];
ctrl.toolbarConfig.actionsConfig = {
primaryActions: primaryActions
};
ctrl.tableActionButtons = [
{ name: 'Add Role', title: 'Add Role', actionFn: addRole },
{ name: 'Delete Role', title: 'Delete Role', actionFn: deleteRole }
];
}
function populateTable() {
operationsService.executeOperation(selectedMbeanName, { name: 'listGroups' }, [])
.then(list => {
ctrl.items = JSON.parse(list).map(item => {
item.roles = item.roles.replaceAll(',', delimeter);
return item;
});
ctrl.viewedItems = ctrl.items;
let filters = ctrl.toolbarConfig.filterConfig.appliedFilters;
if (filters.length > 0) {
filterChange(filters);
} else {
ctrl.toolbarConfig.filterConfig.resultsCount = ctrl.items.length;
}
})
}
function showCreateGroupModal() {
let resolve = {
modalTitle: () => 'Create Group',
formFields: () => [
{
label: 'Group Name',
name: 'group',
type: 'text',
required: true
}
]
};
openModalAndProcessResults(resolve, 'createGroup');
}
function addRole(action, item) {
let resolve = {
modalTitle: () => 'Add Role to Group ' + item.name,
formFields: () => [
{
label: 'Group Name',
name: 'group',
type: 'text',
required: true,
value: item.name,
readOnly: true
},
{
label: 'Role Name',
name: 'role',
type: 'text',
required: true,
validation: {
checkUniqueness: true,
values: item.roles.split(delimeter)
}
}
]
};
openModalAndProcessResults(resolve, 'addGroupRole');
}
function deleteRole(action, item) {
let roles = item.roles.split(delimeter);
roles.shift();
if (roles.length > 0) {
let resolve = {
modalTitle: () => 'Delete Role from Group ' + item.name,
formFields: () => [
{
name: 'group',
type: 'text',
required: true,
value: item.name,
isHidden: true
},
{
label: 'Role Name',
name: 'role',
type: 'text',
required: true,
enum: true,
values: roles.sort(Entaxy.compare())
}
]
};
openModalAndProcessResults(resolve, 'deleteGroupRole');
} else {
Entaxy.notificationInfo('Group ' + item.name + ' doesn\'t have roles that can be deleted');
}
}
function openModalAndProcessResults(resolve, operationName) {
$uibModal.open({
component: 'entaxyUserManagementModal',
resolve: resolve,
backdrop: 'static'
}).result.then((args) => {
entaxyService.processUserManagementOperation(operationName, args, ctrl.reloadFn);
}, reason => {
if (reason) {
Entaxy.notificationError(reason);
}
});
}
}
EntaxyGroupsTableController.$inject = ['workspace', 'operationsService', 'entaxyService', '$uibModal'];
})(Entaxy || (Entaxy = {}));

View File

@ -0,0 +1,68 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-management-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var Entaxy;
(function (Entaxy) {
Entaxy._module.component('entaxyUserManagement', {
template:
`
<entaxy-users change-selection="$ctrl.changeSelection" selected-username="$ctrl.selectedUsername"
reload-fn="$ctrl.reload"></entaxy-users>
<h2>Groups</h2>
<entaxy-groups-table reload-fn="$ctrl.reload"></entaxy-groups-table>
`,
controller: EntaxyUserManagementController
})
.name;
function EntaxyUserManagementController($cookies, $route) {
'ngInject';
let ctrl = this;
const SELECTED_USER_KEY = 'selectedUser';
ctrl.$onInit = function () {
let selectedUser = $cookies.getObject(SELECTED_USER_KEY);
if (selectedUser) {
ctrl.selectedUsername = selectedUser;
$cookies.remove(SELECTED_USER_KEY);
}
}
ctrl.changeSelection = function (itemName) {
ctrl.selectedUsername = itemName;
}
ctrl.reload = function (username) {
if (ctrl.selectedUsername !== username) {
$cookies.putObject(SELECTED_USER_KEY, ctrl.selectedUsername);
}
$route.reload();
}
}
EntaxyUserManagementController.$inject = ['$cookies', '$route'];
})(Entaxy || (Entaxy = {}));

View File

@ -0,0 +1,133 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-management-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var Entaxy;
(function (Entaxy) {
Entaxy._module.component('entaxyUserManagementModal', {
bindings: {
modalInstance: '<',
resolve: '<'
},
template:
`
<div class="entaxy-modal-container simple-modal-content">
<div class="modal-header">
<button type="button" class="close" aria-label="Close" ng-click="$ctrl.cancel()">
<span class="pficon pficon-close" aria-hidden="true"></span>
</button>
<h4 class="modal-title">{{$ctrl.resolve.modalTitle}}</h4>
</div>
<div class="modal-body">
<form name="entaxyObjectForm" class="form-horizontal">
<div class="form-group" ng-repeat="formField in $ctrl.formFields"
ng-class="{'has-error': $ctrl.errors[formField.name]}" ng-if="!formField.isHidden">
<div class="col-sm-3 label-col">
<label class="control-label" ng-class="{'required-pf': formField.required}" for="{{formField.name}}">
{{formField.label}}
</label>
<button type="button" class="btn btn-link label-description-popover"
popover-placement="auto top-left" popover-trigger="'outsideClick'"
uib-popover="{{formField.description}}" ng-if="formField.description">
<span class="pficon pficon-help"></span>
</button>
</div>
<div class="col-sm-8">
<input type="{{formField.type}}" id="{{formField.name}}" class="form-control"
ng-model="formField.value" ng-readonly="formField.readOnly"
ng-if="!formField.enum && formField.type !== 'password' && formField.type !== 'textarea'">
<entaxy-password-input id="{{formField.name}}" name="formField.name" model="formField.value"
confirmation-model="formField.confirmationValue" readonly="formField.readOnly"
ng-if="formField.type === 'password'" errors="$ctrl.errors"></entaxy-password-input>
<entaxy-select-from-enum id="{{formField.name}}" values="formField.values"
model="formField.value" readonly="formField.readOnly" is-empty-included="false"
ng-if="formField.enum"></entaxy-select-from-enum>
<textarea type="{{formField.type}}" id="{{formField.name}}" class="form-control"
ng-model="formField.value" ng-readonly="formField.readOnly"
ng-if="formField.type === 'textarea'"/>
<span class="help-block" ng-show="$ctrl.errors[formField.name]">
{{$ctrl.errors[formField.name]}}
</span>
</div>
</div>
</form>
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary" ng-click="$ctrl.save()">Save</button>
</div>
</div>
`,
controller: entaxyUserManagementModalController
})
.name;
function entaxyUserManagementModalController($uibModal) {
'ngInject';
let ctrl = this;
ctrl.$onInit = function() {
ctrl.formFields = ctrl.resolve.formFields;
if (!ctrl.formFields || ctrl.formFields.length === 0) {
ctrl.cancel('Fields can not be found');
}
}
ctrl.cancel = function(reason) {
ctrl.modalInstance.dismiss(reason);
}
ctrl.save = function() {
ctrl.errors = validate();
if (Object.keys(ctrl.errors).length === 0) {
let args = ctrl.formFields.map(formField => formField.value);
ctrl.modalInstance.close(args);
}
}
function validate() {
let errors = {};
ctrl.formFields.forEach(formField => {
if (formField.type === 'password' && ctrl.errors && ctrl.errors[formField.name]) {
errors[formField.name] = ctrl.errors[formField.name];
}
if (!errors[formField.name] && formField.required
&& (!formField.value || formField.value.trim().length === 0)) {
errors[formField.name] = Entaxy.ERROR_MESSAGE.EMPTY;
}
if (!errors[formField.name] && formField.validation && formField.validation.checkUniqueness
&& formField.validation.values.includes(formField.value)) {
errors[formField.name] = Entaxy.ERROR_MESSAGE.UNIQUE;
}
});
return errors;
}
}
entaxyUserManagementModalController.$inject = ['$uibModal'];
})(Entaxy || (Entaxy = {}));

View File

@ -0,0 +1,62 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-management-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var Entaxy;
(function (Entaxy) {
Entaxy._module.component('entaxyUsers', {
bindings: {
changeSelection: '<',
selectedUsername: '<',
reloadFn: '<'
},
template:
`
<div class="entaxy-users-container">
<div class="entaxy-users-table-container">
<h2>Users</h2>
<entaxy-users-table change-selection="$ctrl.changeSelection" reload-fn="$ctrl.reloadFn">
</entaxy-users-table>
</div>
<div class="entaxy-user-details-container">
<h2>
User Details
<span ng-if="$ctrl.selectedUsername">for {{$ctrl.selectedUsername}}</span>
</h2>
<label>Associated Profile</label>
<entaxy-associated-profile-select username="$ctrl.selectedUsername">
</entaxy-associated-profile-select>
<label>Groups and Roles</label>
<entaxy-groups-and-roles-list username="$ctrl.selectedUsername" reload-fn="$ctrl.reloadFn">
</entaxy-groups-and-roles-list>
</div>
</div>
`
})
.name;
})(Entaxy || (Entaxy = {}));

View File

@ -0,0 +1,178 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-management-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var Entaxy;
(function (Entaxy) {
Entaxy._module.component('entaxyUsersTable', {
bindings: {
changeSelection: '<',
reloadFn: '<'
},
template:
`
<pf-toolbar class="entaxy-toolbar" config="$ctrl.toolbarConfig"></pf-toolbar>
<pf-table-view config="$ctrl.tableConfig"
columns="$ctrl.tableColumns"
action-buttons="$ctrl.tableActionButtons"
page-config="$ctrl.pageConfig"
items="$ctrl.viewedItems">
</pf-table-view>
`,
controller: EntaxyUsersTableController
})
.name;
function EntaxyUsersTableController(workspace, operationsService, entaxyService, $uibModal, $templateCache) {
'ngInject';
let ctrl = this;
let selectedMbeanName = workspace.getSelectedMBeanName();
ctrl.tableConfig = {
selectionMatchProp: 'name',
showCheckboxes: false
};
ctrl.toolbarConfig = {
filterConfig: {
fields: [
{
id: 'name',
title: 'Name',
placeholder: 'Filter by Name...',
filterType: 'text'
}
],
appliedFilters: [],
onFilterChange: filterChange
},
isTableView: true
};
ctrl.tableColumns = [
{
header: 'Name',
itemField: 'name',
htmlTemplate: 'users-table/name-template.html',
colActionFn: (itemName) => ctrl.changeSelection(itemName)
}
];
$templateCache.put(
'users-table/name-template.html',
'<a href="" ng-click="$ctrl.handleColAction(key, value)">{{value}}</a>'
);
ctrl.pageConfig = Entaxy.getStandardPageConfig();
function filterChange(filters) {
ctrl.viewedItems = Entaxy.applyFilters(ctrl.items, filters, matchesFilter);
ctrl.toolbarConfig.filterConfig.resultsCount = ctrl.viewedItems.length;
};
function matchesFilter(item, filter) {
let match = true;
if (filter.id === 'name') {
match = item.name.toLowerCase().match(filter.value.toLowerCase()) !== null;
}
return match;
};
ctrl.items = [];
ctrl.viewedItems = [];
ctrl.$onInit = function() {
populateTable();
let primaryActions = [ { name: 'Add User', actionFn: () => showAddUserModal() } ];
ctrl.toolbarConfig.actionsConfig = {
primaryActions: primaryActions
};
ctrl.tableActionButtons = [
{ name: 'Delete', title: 'Delete User', actionFn: deleteUser }
];
}
function populateTable() {
operationsService.executeOperation(selectedMbeanName, { name: 'listUsers' }, [])
.then(list => {
ctrl.items = JSON.parse(list);
ctrl.viewedItems = ctrl.items;
let filters = ctrl.toolbarConfig.filterConfig.appliedFilters;
if (filters.length > 0) {
filterChange(filters);
} else {
ctrl.toolbarConfig.filterConfig.resultsCount = ctrl.items.length;
}
})
}
function showAddUserModal() {
$uibModal.open({
component: 'entaxyUserManagementModal',
resolve: {
modalTitle: () => 'Add User',
formFields: () => [
{
label: 'Username',
name: 'username',
type: 'text',
required: true
},
{
label: 'Password',
name: 'password',
type: 'password',
required: true
}
]
},
backdrop: 'static'
}).result.then((args) => {
entaxyService.processUserManagementOperation('addUser', args, populateTable);
},
reason => {
if (reason) {
Entaxy.notificationError(reason);
}
});
}
function deleteUser(action, item) {
ctrl.deletedUsername = item.name;
entaxyService.processUserManagementOperation('deleteUser', [ item.name ], reload);
}
function reload() {
ctrl.reloadFn(ctrl.deletedUsername);
}
}
EntaxyUsersTableController.$inject = ['workspace', 'operationsService', 'entaxyService', '$uibModal',
'$templateCache'];
})(Entaxy || (Entaxy = {}));

View File

@ -0,0 +1,73 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-management-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var Entaxy;
(function (Entaxy) {
Entaxy._module.factory('entaxyAttributesCacheService', ['jolokia',
function(jolokia) {
let attributesCache = {};
return {
getAttributes: function (mbeanName) {
return getAttributes(mbeanName);
},
setToUpdate: function (mbeanName) {
return setToUpdate(mbeanName);
},
removeFromCache: function (mbeanName) {
return removeFromCache(mbeanName);
}
};
function getAttributes(mbeanName) {
let attributesCacheItem = attributesCache[mbeanName];
if (attributesCacheItem) {
if (attributesCacheItem.toUpdate) {
let attributes = jolokia.getAttribute(mbeanName);
attributesCacheItem.attributes = attributes;
attributesCacheItem.toUpdate = false;
}
return attributesCacheItem.attributes;
} else {
let attributes = jolokia.getAttribute(mbeanName);
attributesCache[mbeanName] = { attributes: attributes };
return attributes;
}
}
function setToUpdate(mbeanName) {
let attributesCacheItem = attributesCache[mbeanName];
if (attributesCacheItem) {
attributesCacheItem.toUpdate = true;
}
}
function removeFromCache(mbeanName) {
delete attributesCache[mbeanName];
}
}
])
})(Entaxy || (Entaxy = {}));

View File

@ -0,0 +1,233 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-management-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var Entaxy;
(function (Entaxy) {
Entaxy._module.factory('entaxyPrivateObjectsCacheService', ['workspace', 'entaxyAttributesCacheService',
function(workspace, entaxyAttributesCacheService) {
let changedObjectsInfo = {};
let changedMbeanNames = {};
let addedObjectsInfo = {};
return {
addChanges: function (privateObjectMbean, id, owner, config) {
return addChanges(privateObjectMbean, id, owner, config);
},
isChanged: function (mbeanName) {
return isChanged(mbeanName);
},
isOwnerChanged: function (privateObjectMbean, owner) {
return isOwnerChanged(privateObjectMbean, owner);
},
getChangedObjectInfo: function (id) {
return getChangedObjectInfo(id);
},
getChangedObjectConfig: function (id) {
return getChangedObjectConfig(id);
},
setObjectToRemoval: function (id, privateObjectMbeanName, config) {
return setObjectToRemoval(id, privateObjectMbeanName, config);
},
isObjectSetToRemoval: function (id) {
return isObjectSetToRemoval(id);
},
restoreObject: function (id) {
return restoreObject(id);
},
addNew: function (parentMbean, privateObjectInfo) {
return addNew(parentMbean, privateObjectInfo);
},
hasAddedChildren: function (parentMbeanName) {
return hasAddedChildren(parentMbeanName);
},
getAddedObjectsInfo: function (parentMbeanName) {
return getAddedObjectsInfo(parentMbeanName);
},
setAddedObjectToRemoval: function (parentMbeanName, id) {
return setAddedObjectToRemoval(parentMbeanName, id);
},
isAddedObjectSetToRemoval: function (parentMbeanName, id) {
return isAddedObjectSetToRemoval(parentMbeanName, id);
},
restoreAddedObject: function (parentMbeanName, id) {
return restoreAddedObject(parentMbeanName, id);
},
removeFromCache: function (owner) {
return removeFromCache(owner);
},
findOwnerMbean(descendantMbean, owner) {
return findOwnerMbean(descendantMbean, owner);
}
};
function addChanges(privateObjectMbean, id, owner, config) {
setChangedMbeanNamesAndUpdateTree(privateObjectMbean, owner);
setChangedObjectInfo(id, owner, config);
}
function setChangedMbeanNamesAndUpdateTree(privateObjectMbean, owner) {
if (!changedMbeanNames[owner]) {
let ownerMbean = findOwnerMbean(privateObjectMbean, owner);
changedMbeanNames[owner] = [ ownerMbean.objectName, privateObjectMbean.objectName ];
workspace.loadTree();
} else {
if (!changedMbeanNames[owner].includes(privateObjectMbean.objectName)) {
changedMbeanNames[owner].push(privateObjectMbean.objectName);
workspace.loadTree();
}
}
}
function setChangedObjectInfo(id, owner, config) {
changedObjectsInfo[id] = {
owner: owner,
config: config
}
}
function isChanged(mbeanName) {
return Object.values(changedMbeanNames).flat().includes(mbeanName);
}
function isOwnerChanged(privateObjectMbean, owner) {
let ownerMbean = findOwnerMbean(privateObjectMbean, owner);
return isChanged(ownerMbean.objectName);
}
function getChangedObjectInfo(id) {
return changedObjectsInfo[id];
}
function getChangedObjectConfig(id) {
let object = getChangedObjectInfo(id);
return object ? object.config : null;
}
function setObjectToRemoval(id, privateObjectMbeanName, config) {
if (changedObjectsInfo[id]) {
changedObjectsInfo[id].toRemoval = true;
} else {
let selectedMbean = workspace.getSelectedMBean();
let privateObjectMbean = selectedMbean
.findDescendant(child => child.objectName === privateObjectMbeanName);
let attributes = entaxyAttributesCacheService.getAttributes(privateObjectMbeanName);
addChanges(privateObjectMbean, id, attributes.Owner, config);
changedObjectsInfo[id].toRemoval = true;
}
}
function isObjectSetToRemoval(id) {
let object = getChangedObjectInfo(id);
return object ? object.toRemoval : undefined;
}
function restoreObject(id) {
if (changedObjectsInfo[id]) {
delete changedObjectsInfo[id].toRemoval;
}
}
function addNew(parentMbean, privateObjectInfo) {
let parentMbeanName = parentMbean.objectName;
if (!addedObjectsInfo[parentMbeanName]) {
addedObjectsInfo[parentMbeanName] = [ privateObjectInfo ];
} else {
addedObjectsInfo[parentMbeanName].push(privateObjectInfo);
}
let owner = privateObjectInfo.ui.owner;
let ownerMbean = findOwnerMbean(parentMbean, owner);
if (!changedMbeanNames[owner]) {
changedMbeanNames[owner] = [ownerMbean.objectName];
}
}
function hasAddedChildren(parentMbeanName) {
return addedObjectsInfo[parentMbeanName] ? true : false;
}
function getAddedObjectsInfo(parentMbeanName) {
return addedObjectsInfo[parentMbeanName];
}
function setAddedObjectToRemoval(parentMbeanName, id) {
if (addedObjectsInfo[parentMbeanName]) {
let objectToRemoval = addedObjectsInfo[parentMbeanName]
.find(privateObjInfo => privateObjInfo.ui.id === id);
objectToRemoval.toRemoval = true;
}
}
function isAddedObjectSetToRemoval(parentMbeanName, id) {
if (addedObjectsInfo[parentMbeanName]) {
let objectToRemoval = addedObjectsInfo[parentMbeanName]
.find(privateObjInfo => privateObjInfo.ui.id === id);
return objectToRemoval.toRemoval;
}
}
function restoreAddedObject(parentMbeanName, id) {
if (addedObjectsInfo[parentMbeanName]) {
let objectToRestore = addedObjectsInfo[parentMbeanName]
.find(privateObjInfo => privateObjInfo.ui.id === id);
delete objectToRestore.toRemoval;
}
}
function removeFromCache(owner) {
delete changedMbeanNames[owner];
removeAddedByOwner(owner);
removeByOwner(owner);
}
function removeAddedByOwner(owner) {
addedObjectsInfo = Object.fromEntries(Object.entries(addedObjectsInfo)
.filter(([key, value]) => value && value.length > 0 ? value[0].ui.owner !== owner : false));
}
function removeByOwner(owner) {
changedObjectsInfo = Object.fromEntries(Object.entries(changedObjectsInfo)
.filter(([key, value]) => value.owner !== owner));
}
function findOwnerMbean(descendantMbean, owner) {
return descendantMbean.findAncestor(mbean => {
if (mbean.objectName) {
let attributes = entaxyAttributesCacheService.getAttributes(mbean.objectName);
return attributes.Id === owner;
}
});
}
}
])
})(Entaxy || (Entaxy = {}));

View File

@ -0,0 +1,157 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-management-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var Entaxy;
(function (Entaxy) {
Entaxy._module.factory('entaxyProfileDiagramService', ['entaxyAttributesCacheService',
function(entaxyAttributesCacheService) {
let changes = {};
let isDirty = false;
let isProfileChanged = false;
let isDefaultRouteChanged = false;
return {
createChangesConfig: function (mbeanName, objectId, args, configurableOnly, connector) {
return createChangesConfig(mbeanName, objectId, args, configurableOnly, connector);
},
setChanges: function (mbeanName, changesConfig) {
return setChanges(mbeanName, changesConfig)
},
hasChanges: function (mbeanName) {
return hasChanges(mbeanName);
},
getChanges: function (mbeanName) {
return getChanges(mbeanName);
},
getArgs: function (mbeanName) {
return getArgs(mbeanName);
},
hasType: function (mbeanName, type) {
return hasType(mbeanName, type);
},
setProfileChanged: function () {
isProfileChanged = true;
},
isProfileChanged: function () {
return isProfileChanged;
},
setDefaultRouteChanged: function () {
isDefaultRouteChanged = true;
},
isDefaultRouteChanged: function () {
return isDefaultRouteChanged;
},
setConnectorChanged: function (mbeanName, isChanged) {
return setConnectorChanged(mbeanName, isChanged);
},
isConnectorChanged: function (mbeanName) {
return isConnectorChanged(mbeanName);
},
resetChanges: function (objectId) {
return resetChanges(objectId);
},
isDirty: function () {
return isDirty;
},
setDirty: function () {
isDirty = true;
},
clear: function () {
changes = {};
isDirty = false;
isProfileChanged = false;
isDefaultRouteChanged = false;
}
};
function createChangesConfig(mbeanName, objectId, args, configurableOnly, connector) {
let attributes = entaxyAttributesCacheService.getAttributes(mbeanName);
return {
objectId: objectId,
type: attributes.RuntimeType,
args: args,
configurableOnly: configurableOnly,
connector: connector
};
}
function setChanges(mbeanName, changesConfig) {
changes[mbeanName] = changesConfig;
}
function hasChanges(mbeanName) {
return changes[mbeanName] ? true : false;
}
function getChanges(mbeanName) {
return changes[mbeanName];
}
function getArgs(mbeanName) {
return hasChanges(mbeanName) ? changes[mbeanName].args : null;
}
function hasType(mbeanName, type) {
return hasChanges(mbeanName) && changes[mbeanName].type === type;
}
function setConnectorChanged(mbeanName, isChanged) {
if (hasChanges(mbeanName) && changes[mbeanName].connector) {
changes[mbeanName].connector.isChanged = isChanged;
}
}
function isConnectorChanged(mbeanName) {
return changes[mbeanName] && changes[mbeanName].connector && changes[mbeanName].connector.isChanged;
}
function resetChanges(objectId) {
let hasChangedConnectors = false;
let mbeanNameToRemove;
Object.keys(changes).forEach(mbeanName => {
if (changes[mbeanName].objectId === objectId) {
if (changes[mbeanName].type === Entaxy.RUNTIME_TYPE.PROFILE) {
isProfileChanged = false;
} else if (changes[mbeanName].type === Entaxy.RUNTIME_TYPE.DEFAULT_ROUTE) {
isDefaultRouteChanged = false;
} else if (changes[mbeanName].type === Entaxy.RUNTIME_TYPE.CONNECTOR) {
setConnectorChanged(mbeanName, false);
}
mbeanNameToRemove = mbeanName;
} else {
if (changes[mbeanName].type === Entaxy.RUNTIME_TYPE.CONNECTOR &&
changes[mbeanName].connector && changes[mbeanName].connector.isChanged) {
hasChangedConnectors = true;
}
}
});
isDirty = hasChangedConnectors || isProfileChanged || isDefaultRouteChanged;
delete changes[mbeanNameToRemove];
}
}
])
})(Entaxy || (Entaxy = {}));

View File

@ -0,0 +1,225 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-management-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var Entaxy;
(function (Entaxy) {
Entaxy._module.factory('entaxyResourcesService', ['workspace', 'operationsService', '$q', '$uibModal', 'restService',
function(workspace, operationsService, $q, $uibModal, restService) {
const resourceMbean = getDomainFolder().findDescendant(child =>
child.objectName && child.objectName.endsWith('category=resource'));
return {
getProviderMbean: function (protocol) {
return getProviderMbean(protocol);
},
getResource: function (location) {
return getResource(location);
},
getResourceMetadata: function (location) {
return getResourceMetadata(location);
},
getResourcesInfo: function (providerMBeanName, path) {
return getResourcesInfo(providerMBeanName, path);
},
pasteResource: function (providerMBeanName, fromPath, fullToPath) {
return pasteResource(providerMBeanName, fromPath, fullToPath);
},
removeResource: function (providerMBeanName, path) {
return removeResource(providerMBeanName, path);
},
downloadResource: function (providerMBeanName, path) {
return downloadResource(providerMBeanName, path);
},
uploadFile: function (file, protocol, path) {
return uploadFile(file, protocol, path);
},
getPath: function (crumbs) {
return getPath(crumbs);
},
addFolder: function (items, clientFolders, crumbs) {
return addFolder(items, clientFolders, crumbs);
},
createFolder: function (name, crumbs) {
return createFolder(name, crumbs);
},
getClientFoldersToAdd: function (clientFolders, items, crumbs) {
return getClientFoldersToAdd(clientFolders, items, crumbs);
}
};
function getDomainFolder() {
let entaxyJmxDomain = localStorage['entaxyJmxDomain'] || "ru.entaxy.esb";
return workspace.tree.get(entaxyJmxDomain);
}
function getProviderMbean(protocol) {
return getDomainFolder().findDescendant(child =>
child.objectName && child.objectName.endsWith('provider=' + protocol));
}
function getResource(location) {
return executeOperationOnResourceMbean('getResource', [location]);
}
function getResourceMetadata(location) {
return executeOperationOnResourceMbean('getResourceMetadata', [location]);
}
function executeOperationOnResourceMbean(operationName, properties) {
let resourceObjectName = resourceMbean ? resourceMbean.objectName : undefined;
if (resourceObjectName) {
return operationsService.executeOperation(
resourceObjectName,
{ name: operationName },
properties
);
}
}
function getResourcesInfo(providerMBeanName, path) {
return $q(function (resolve) {
operationsService.executeOperation(providerMBeanName, { name: 'getResourcesInfo' }, [ path ])
.then((result) => {
let items = JSON.parse(result);
items.forEach(item => {
if (item.metadata) {
Object.keys(item.metadata).forEach(section => {
item.metadata[section] = JSON.parse(item.metadata[section]);
if (item.metadata[section].error && !item.error) {
let error = item.metadata[section].error;
item.error = error.message && error.message.length > 0 ?
error.message : error.exception;
}
});
}
});
resolve(items);
})
.catch((error) => {
Entaxy.log.error(error);
Entaxy.notificationError('An error occurred while getting resources.');
});
});
}
function pasteResource(providerMBeanName, fromPath, fullToPath) {
return operationsService
.executeOperation(providerMBeanName, { name: 'pasteResource' }, [ fromPath, fullToPath ]);
}
function removeResource(providerMBeanName, path) {
return operationsService.executeOperation(providerMBeanName, { name: 'removeResource' }, [ path ]);
}
function downloadResource(providerMBeanName, path) {
return operationsService.executeOperation(providerMBeanName, { name: 'downloadResource' }, [ path ]);
}
function uploadFile(file, protocol, path) {
if (!file) {
return;
}
let fd = new FormData();
fd.append('file', file);
fd.append('protocol', protocol);
fd.append('path', path);
return restService.post('/cxf/file-upload/upload/resource', fd);
}
function getPath(crumbs) {
let path = '';
if (crumbs && crumbs.length > 0) {
path = crumbs.join('/');
}
return path;
}
function addFolder(items, clientFolders, crumbs) {
$uibModal.open({
component: 'entaxySimpleResourceNameInputModal',
resolve: {
title: () => 'Set folder name',
names: () => items.filter((item) => item.isFolder).map((item) => item.name),
type: () => 'Folder'
},
size: 'sm-custom',
backdrop: 'static',
windowTopClass: 'modal-top-margin-center-override'
})
.result.then(name => {
let newFolder = createFolder(name, crumbs);
items.push(newFolder);
items = items.sort(Entaxy.compareBy('name')).sort((a, b) => b.isFolder - a.isFolder);
clientFolders.push(newFolder);
});
}
function createFolder(name, crumbs) {
return {
name: name,
isFolder: true,
crumbs: Entaxy.deepCopy(crumbs)
};
}
function getClientFoldersToAdd(clientFolders, items, crumbs) {
let foldersToAdd = [];
if (clientFolders.length > 0) {
clientFolders = clientFolders.filter((folder) => {
let isSaved = true;
if (folder.crumbs.length == crumbs.length && (folder.crumbs.length == 0 ||
(folder.crumbs.length > 0 && folder.crumbs[folder.crumbs.length - 1] ===
crumbs[crumbs.length - 1]))) {
items.forEach((item) => {
if (item.isFolder && item.name === folder.name) {
isSaved = false;
}
});
if (isSaved) {
foldersToAdd.push(folder);
}
}
return isSaved;
});
}
return foldersToAdd;
}
}
])
})(Entaxy || (Entaxy = {}));

View File

@ -0,0 +1,56 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-management-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var Entaxy;
(function (Entaxy) {
Entaxy._module.factory('restService', ['$q', '$http',
function($q, $http) {
return {
post: function (url, data) {
return post(url, data);
}
};
function post(url, data) {
var deferred = $q.defer();
$http({
method: 'POST',
url: url,
data: data,
transformRequest: angular.identity,
headers: {'Content-Type': undefined}
}).then(function(response) {
deferred.resolve(response);
}, function(response) {
deferred.reject(response);
}).catch(function(fallback) {
Entaxy.log.error(fallback);
});
return deferred.promise;
};
}
]);
})(Entaxy || (Entaxy = {}));