release version 1.11.0

This commit is contained in:
2025-07-10 23:47:05 +03:00
parent 5cb6857fa1
commit 8dd9cf9cf2
3082 changed files with 278464 additions and 1833 deletions

View File

@@ -0,0 +1,193 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-cicd-plugin
* ==========
* Copyright (C) 2020 - 2025 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 EntaxyCICD;
(function (EntaxyCICD) {
EntaxyCICD._module.component('entaxyCiCdApplication', {
template:
`
<div class="entaxy-cicd-zero-revision-note" ng-if="$ctrl.isRevisionSelected && $ctrl.revision === '0'">
<entaxy-form-field-extra-info type="'info'" message="$ctrl.zeroRevisionNote"></entaxy-form-field-extra-info>
</div>
<div ng-if="$ctrl.versions || $ctrl.isVersionSelected || $ctrl.isRevisionSelected"
class="entaxy-cicd-header-container">
<div class="entaxy-cicd-title-with-info-container">
<span class="first" ng-class="{'lead': !$ctrl.isVersionSelected && !$ctrl.isRevisionSelected}">
Application: {{$ctrl.application}}
</span>
<span ng-class="{'lead': $ctrl.isVersionSelected}"
ng-if="$ctrl.isVersionSelected || $ctrl.isRevisionSelected">
Version: {{$ctrl.version}}
</span>
<div ng-if="!$ctrl.isVersionSelected && !$ctrl.isRevisionSelected">
<span>Version:</span>
<entaxy-select-from-enum values="$ctrl.versions" model="$ctrl.version"
is-empty-included="false"></entaxy-select-from-enum>
</div>
<span ng-if="$ctrl.isVersionSelected">
Last Revision: {{$ctrl.lastRevision}}
</span>
<span ng-if="$ctrl.isVersionSelected">
Installed Revision: {{$ctrl.installedRevision}}
</span>
<span class="lead" ng-if="$ctrl.isRevisionSelected">
Revision: {{$ctrl.revision}}
</span>
<span ng-if="$ctrl.isRevisionSelected">
Revision Status: {{$ctrl.revisionStatus}}
</span>
</div>
<div ng-if="$ctrl.isRevisionSelected" class="entaxy-cicd-header-buttons-container">
<entaxy-ci-cd-application-management-buttons storage="$ctrl.storage" application="$ctrl.application"
version="$ctrl.version" revision="$ctrl.revision" revision-status="$ctrl.revisionStatus">
</entaxy-ci-cd-application-management-buttons>
</div>
<div class="dropdown primary-action entaxy-cicd-header-buttons-container"
uib-dropdown ng-if="$ctrl.isVersionSelected">
<button class="dropdown-toggle" uib-dropdown-toggle type="button">
Add Revision
<span class="caret"></span>
</button>
<ul class="dropdown-menu dropdown-menu-right">
<li role="menuitem" ng-click="$ctrl.addRevision()">
<a class="secondary-action">Add Revision</a>
</li>
<li role="menuitem" ng-click="$ctrl.addRevisionFromExistent()">
<a class="secondary-action">Add Revision From Existent</a>
</li>
</ul>
</div>
</div>
<div class="entaxy-cicd-content-container">
<h2 class="first">
Items
</h2>
<entaxy-ci-cd-application-items version="$ctrl.version"></entaxy-ci-cd-application-items>
<h2>
Requirements
</h2>
<entaxy-ci-cd-requirements version="$ctrl.version" type="Application"></entaxy-ci-cd-requirements>
</div>
`,
controller: EntaxyCICDApplicationController
})
.name;
function EntaxyCICDApplicationController(workspace, $uibModal, entaxyCICDService) {
'ngInject';
let ctrl = this;
ctrl.zeroRevisionNote = 'Revision 0 cannot be configured';
ctrl.$onInit = function() {
ctrl.storage = EntaxyCICD.getStorage(workspace.selection);
ctrl.application = EntaxyCICD.getProjectOrApplication(workspace.selection);
ctrl.isVersionSelected = EntaxyCICD.isVersion(workspace.selection);
ctrl.isRevisionSelected = EntaxyCICD.isRevision(workspace.selection);
if (ctrl.isVersionSelected || ctrl.isRevisionSelected) {
ctrl.version = EntaxyCICD.getVersion(workspace.selection);
if (ctrl.isRevisionSelected) {
let revisionInfo = EntaxyCICD.getRevisionInfo(workspace.selection);
ctrl.revision = revisionInfo.revision;
ctrl.revisionStatus = revisionInfo.revisionStatus;
} else {
entaxyCICDService.executeOperation('readApplicationVersionLastAndInstalledRevision',
[ctrl.storage, ctrl.application, ctrl.version])
.then(result => {
let revisionsInfo = JSON.parse(result);
ctrl.lastRevision = revisionsInfo.lastRevision;
ctrl.installedRevision = revisionsInfo.installedRevision;
});
}
} else {
populateVersions();
}
}
function populateVersions() {
ctrl.versions = EntaxyCICD.getVersions(workspace.selection);
if (ctrl.versions.length > 0) {
ctrl.version = ctrl.versions[ctrl.versions.length - 1];
}
}
ctrl.addRevision = function () {
createRevision(-1);
}
ctrl.addRevisionFromExistent = function () {
let formFields = [
{
label: 'Prototype Revision',
name: 'prototypeRevision',
enum: true,
required: true,
values: workspace.selection.children.map(revision => revision.title.split(' ')[0]),
setFocused: true
}
];
openCreateRevisionModal(formFields);
}
function openCreateRevisionModal(formFields) {
$uibModal.open({
component: 'entaxyCiCdSimpleFieldsModal',
resolve: {
modalTitle: () => 'Create Revision',
formFields: () => formFields
},
backdrop: 'static'
}).result.then((args) => {
createRevision(...args);
}, reason => {
if (reason && reason !== Entaxy.MODAL_CANCEL_REASON.ESCAPE_KEY_PRESS) {
Entaxy.notificationError(reason);
}
});
}
function createRevision(prototypeRevision) {
entaxyCICDService.executeOperation('createRevision',
[ctrl.storage, ctrl.application, ctrl.version, prototypeRevision])
.then(result => {
Entaxy.notificationSuccess(result);
entaxyCICDService.treeUpdated();
}).catch(error => {
Entaxy.notificationError(error);
});
}
}
EntaxyCICDApplicationController.$inject = ['workspace', '$uibModal', 'entaxyCICDService'];
})(EntaxyCICD || (EntaxyCICD = {}));

View File

@@ -0,0 +1,108 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-cicd-plugin
* ==========
* Copyright (C) 2020 - 2025 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 EntaxyCICD;
(function (EntaxyCICD) {
EntaxyCICD._module.component('entaxyCiCdApplicationManagementButtons', {
bindings: {
storage: '<',
application: '<',
version: '<',
revision: '<',
revisionStatus: '<',
isConfigurationDirty: '<'
},
template:
`
<button type="button" ng-click="$ctrl.configure()"
ng-if="!$ctrl.isInstalled && !$ctrl.isUninstalled">Configure</button>
<button type="button" ng-click="$ctrl.deploy()"
ng-if="!$ctrl.isInstalled && !$ctrl.isUninstalled">Deploy</button>
<button type="button" ng-click="$ctrl.install()" ng-if="!$ctrl.isInstalled">Install</button>
<button type="button" ng-click="$ctrl.uninstall()" ng-if="$ctrl.isInstalled">Uninstall</button>
`,
controller: EntaxyCICDApplicationManagementButtonsController
})
.name;
function EntaxyCICDApplicationManagementButtonsController(workspace, entaxyCICDService) {
'ngInject';
let ctrl = this;
ctrl.$onInit = function() {
ctrl.isConfigured = ctrl.revisionStatus === EntaxyCICD.REVISION_STATUS.CONFIGURED;
ctrl.isDeployed = ctrl.revisionStatus === EntaxyCICD.REVISION_STATUS.DEPLOYED;
ctrl.isInstalled = ctrl.revisionStatus === EntaxyCICD.REVISION_STATUS.INSTALLED;
ctrl.isUninstalled = ctrl.revisionStatus === EntaxyCICD.REVISION_STATUS.UNINSTALLED;
}
const OPERATION_TYPE = {
CONFIGURE: 'configure',
DEPLOY: 'deploy',
INSTALL: 'install',
UNINSTALL: 'uninstall'
}
ctrl.configure = function () {
processOperation(OPERATION_TYPE.CONFIGURE);
}
ctrl.deploy = function () {
processOperation(OPERATION_TYPE.DEPLOY);
}
ctrl.install = function () {
processOperation(OPERATION_TYPE.INSTALL);
}
ctrl.uninstall = function () {
processOperation(OPERATION_TYPE.UNINSTALL);
}
function processOperation(operationType) {
if (!ctrl.isConfigurationDirty || confirm(Entaxy.CONFIRMATION.UNSAVED_CHANGES)) {
entaxyCICDService.executeOperation(operationType + 'Revision',
[ctrl.storage, ctrl.application, ctrl.version, ctrl.revision])
.then(result => {
let message =
operationType === OPERATION_TYPE.INSTALL || operationType === OPERATION_TYPE.UNINSTALL ?
EntaxyCICD.capitalize(operationType) + 'ation started successfully. ' +
'<b>Please notice that operation may take some time.</b>' : result;
Entaxy.notification(Entaxy.NOTIFICATION_TYPE.SUCCESS, message,
Entaxy.configuration[Entaxy.CONFIGURATION_KEYS.NOTIFICATION_TIMEOUT_SUCCESS]);
entaxyCICDService.treeUpdated();
}).catch(error => {
Entaxy.notificationError(error);
EntaxyCICD.log.error(error);
});
}
}
}
EntaxyCICDApplicationManagementButtonsController.$inject = ['workspace', 'entaxyCICDService'];
})(EntaxyCICD || (EntaxyCICD = {}));

View File

@@ -0,0 +1,143 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-cicd-plugin
* ==========
* Copyright (C) 2020 - 2025 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 EntaxyCICD;
(function (EntaxyCICD) {
EntaxyCICD._module.component('entaxyCiCdApplications', {
template:
`
<div class="entaxy-cicd-content-with-title-container">
<h2>
Applications
</h2>
<entaxy-ci-cd-applications-table type="Application"
import-from-file="$ctrl.importFromFile" import-from-repository="$ctrl.importFromRepository">
</entaxy-ci-cd-applications-table>
</div>
`,
controller: EntaxyCICDApplicationsController
})
.name;
function EntaxyCICDApplicationsController(workspace, $uibModal, entaxyCICDService) {
'ngInject';
let ctrl = this;
const isStorageSelected = EntaxyCICD.isStorage(workspace.selection);
ctrl.$onInit = function() {
}
function getFormFields(isFromRepository) {
let formFields = [
{
name: 'storage',
label: 'Storage',
type: 'string',
value: isStorageSelected ? workspace.selection.title : undefined,
enum: isStorageSelected ? undefined : true,
values: isStorageSelected ? undefined : workspace.selection.children.map(child => child.title),
required: true,
readOnly: isStorageSelected ? true : undefined,
setFocused: true
}
];
if (isFromRepository) {
formFields.push({
name: 'mavenUrl',
label: 'Maven Url',
type: 'string',
required: true
});
} else {
formFields.push({
name: 'file',
label: 'File',
resource: true,
required: true
});
}
return formFields;
}
ctrl.importFromFile = function () {
openModalAndProcessResults(false);
}
ctrl.importFromRepository = function () {
openModalAndProcessResults(true);
}
function openModalAndProcessResults(isFromRepository) {
$uibModal.open({
component: 'entaxyCiCdSimpleFieldsModal',
resolve: {
modalTitle: () => 'Import Application From ' + (isFromRepository ? 'Repository' : 'File'),
formFields: () => getFormFields(isFromRepository)
},
backdrop: 'static'
})
.result.then(args => {
if (isFromRepository) {
processOperation('importFromRepository', args);
} else {
importFromFile(args);
}
},
reason => {
if (reason && reason !== Entaxy.MODAL_CANCEL_REASON.ESCAPE_KEY_PRESS) {
Entaxy.notificationError(reason);
}
});
}
function importFromFile(args) {
let file = args[1];
const reader = new FileReader();
reader.readAsBinaryString(file);
reader.onloadend = function () {
const base64String = btoa(reader.result);
processOperation('importFromBase64String', [args[0], base64String]);
}
}
function processOperation(operationName, properties) {
entaxyCICDService.executeOperation(operationName, properties)
.then(result => {
Entaxy.notificationSuccess(result);
entaxyCICDService.treeUpdated();
})
.catch(error => {
Entaxy.notificationError(error);
EntaxyCICD.log.error(error);
});
}
}
EntaxyCICDApplicationsController.$inject = ['workspace', '$uibModal', 'entaxyCICDService'];
})(EntaxyCICD || (EntaxyCICD = {}));

View File

@@ -0,0 +1,297 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-cicd-plugin
* ==========
* Copyright (C) 2020 - 2025 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 EntaxyCICD;
(function (EntaxyCICD) {
EntaxyCICD._module.component('entaxyCiCdConfiguration', {
bindings: {
configurationId: '<',
configured: '<',
isDirty: '='
},
template:
`
<div class="entaxy-cicd-header-container">
<h2>
Configuration: {{$ctrl.configurationId}}
</h2>
</div>
<div class="entaxy-cicd-subtitle-info-container">
<span>Configured Id: {{$ctrl.configuredId}}</span>
<span>Configured Type: {{$ctrl.configuredType}}</span>
</div>
<pf-toolbar class="entaxy-toolbar" config="$ctrl.toolbarConfig"></pf-toolbar>
<form name="entaxyObjectForm" class="form-horizontal">
<div class="entaxy-table-with-inputs" ng-if="$ctrl.viewedItems && $ctrl.viewedItems.length > 0">
<table datatable="ng" dt-options="$ctrl.dtOptions"
class="table-view-container table table-striped table-bordered table-hover dataTable no-footer">
<thead>
<tr role="row">
<th>Name</th>
<th>Display Name</th>
<th>Imported Value</th>
<th>Local Value</th>
</tr>
</thead>
<tbody>
<tr role="row" ng-repeat="field in $ctrl.viewedItems">
<td ng-class="{'red': field.isRed, 'green': field.isGreen, 'bold': field.importedValue !== field.originValue}">
{{ field.name }}
</td>
<td>{{ field.displayName }}</td>
<td class="field-input-cell" ng-class="{'field-input-checkbox-cell': field.type === 'checkbox'}"
ng-if="$ctrl.configured">
<input type="{{field.type}}" ng-class="{'form-control': field.type !== 'checkbox'}"
ng-model="field.importedValue" ng-change="$ctrl.checkDirtiness()"/>
</td>
<td ng-if="!$ctrl.configured">{{ field.importedValue }}</td>
<td>{{ field.localValue }}</td>
</tr>
</tbody>
</table>
</div>
</form>
<pf-empty-state ng-if="!$ctrl.viewedItems || $ctrl.viewedItems.length == 0"></pf-empty-state>
`,
controller: EntaxyCICDConfigurationController
})
.name;
function EntaxyCICDConfigurationController(workspace, $scope, $location, entaxyCICDService, entaxyService,
entaxyHotkeysService) {
'ngInject';
let ctrl = this;
ctrl.dtOptions = {
autoWidth: false,
destroy: true,
order: [[0, "asc"]],
dom: "t",
paging: false
};
ctrl.toolbarConfig = {
filterConfig: {
fields: [
{
id: 'displayName',
title: 'Display Name',
placeholder: 'Filter by Display Name...',
filterType: 'text'
},
{
id: 'name',
title: 'Name',
placeholder: 'Filter by Name...',
filterType: 'text'
}
],
inlineResults: true,
appliedFilters: [],
onFilterChange: filterChange
},
isTableView: true
};
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;
} else if (filter.id === 'displayName') {
match = item.displayName.toLowerCase().match(filter.value.toLowerCase()) !== null;
}
return match;
};
ctrl.checkDirtiness = function () {
if ($scope.entaxyObjectForm.$dirty) {
let isDirty = false;
for (let i = 0; i < ctrl.items.length; i++) {
if (ctrl.items[i].importedValue !== ctrl.items[i].originValue) {
isDirty = true;
break;
}
}
if (!isDirty) {
$scope.entaxyObjectForm.$setPristine();
}
}
}
setTimeout( function () {
ctrl.activeTabIndex = entaxyService.getActiveTabIndex();
});
$scope.$on("$locationChangeStart", function(event) {
if ($scope.entaxyObjectForm.$dirty && !confirm(Entaxy.CONFIRMATION.UNSAVED_CHANGES)) {
event.preventDefault();
ctrl.isTreeOrTabSelectionUpdateNeeded = true;
}
});
$scope.$watch('$ctrl.isTreeOrTabSelectionUpdateNeeded', function (newValue) {
if (newValue) {
setTimeout(function () {
entaxyService.updateTabSelection(ctrl.activeTabIndex);
});
Jmx.updateTreeSelectionFromURL($location, $(entaxyCICDTreeElementId));
ctrl.isTreeOrTabSelectionUpdateNeeded = false;
}
});
ctrl.$onInit = function() {
entaxyHotkeysService.setHotkeys($scope, getHotkeysConfigs());
if (ctrl.configured) {
let primaryActions = [
{ name: 'Clear Changes', actionFn: clearChanges },
{ name: 'Copy Local Values', actionFn: useLocalValues },
{ name: 'Save Changes', actionFn: save }
];
ctrl.toolbarConfig.actionsConfig = {
primaryActions: primaryActions
};
}
}
const storage = EntaxyCICD.getStorage(workspace.selection);
const application = EntaxyCICD.getProjectOrApplication(workspace.selection);
const version = EntaxyCICD.getVersion(workspace.selection);
const revision = workspace.selection.title.split(' ')[0];
$scope.$watch('entaxyObjectForm.$dirty', function () {
ctrl.isDirty = $scope.entaxyObjectForm.$dirty;
});
$scope.$watch('$ctrl.configurationId', function () {
$scope.entaxyObjectForm.$setPristine();
populateTable();
});
function populateTable() {
entaxyCICDService.executeOperation('readRevisionConfiguration',
[storage, application, version, revision, ctrl.configurationId])
.then(result => {
let config = JSON.parse(result);
ctrl.configuredId = config.id;
ctrl.configuredType = config.type;
let fields = config.fields;
ctrl.items = fields.length === 0 ? [] : fields.map(field => {
field.type = Entaxy.convertToHtmlInputType(field.type);
if (field.importedValue === "" || field.importedValue === null) {
field.isRed = true;
} else if (field.localValue === "" || field.localValue === null) {
field.isGreen = true;
}
if (field.type === 'number') {
field.importedValue = field.importedValue !== null ? JSON.parse(field.importedValue) : null;
}
field.originValue = field.importedValue;
return field;
});
filterChange(ctrl.toolbarConfig.filterConfig.appliedFilters);
}).catch(error => {
Entaxy.notificationError('Can not read configuration: ' + error);
EntaxyCICD.log.error(error);
});
}
function clearChanges() {
if ($scope.entaxyObjectForm.$dirty) {
ctrl.items = ctrl.items.map(item => {
item.importedValue = item.originValue;
return item;
});
filterChange(ctrl.toolbarConfig.filterConfig.appliedFilters);
$scope.entaxyObjectForm.$setPristine();
}
}
function useLocalValues() {
ctrl.items = ctrl.items.map(item => {
item.importedValue = item.localValue;
return item;
});
if (!$scope.entaxyObjectForm.$dirty) {
$scope.entaxyObjectForm.$setDirty();
} else {
ctrl.checkDirtiness();
}
}
function save() {
if ($scope.entaxyObjectForm.$dirty) {
let properties = getProperties();
entaxyCICDService.executeOperation('saveRevisionConfiguration',
[storage, application, version, revision, ctrl.configurationId, properties])
.then(result => {
Entaxy.notificationSuccess(result);
$scope.entaxyObjectForm.$setPristine();
populateTable();
}).catch(error => {
Entaxy.notificationError(error);
EntaxyCICD.log.error(error);
});
}
}
function getProperties() {
let filteredFields = ctrl.items.filter(field => field.importedValue !== field.originValue);
if (filteredFields && filteredFields.length > 0) {
return filteredFields.reduce((obj, cur) => ({ ...obj, [cur.name] : cur.importedValue }), {});
}
}
function getHotkeysConfigs() {
return [
{
...Entaxy.getSaveHotkeyDescription(),
callback: function (event) {
event.preventDefault();
save();
}
}
];
}
}
EntaxyCICDConfigurationController.$inject = ['workspace', '$scope', '$location', 'entaxyCICDService',
'entaxyService', 'entaxyHotkeysService'];
})(EntaxyCICD || (EntaxyCICD = {}));

View File

@@ -0,0 +1,189 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-cicd-plugin
* ==========
* Copyright (C) 2020 - 2025 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 EntaxyCICD;
(function (EntaxyCICD) {
EntaxyCICD._module.component('entaxyCiCdConfigurations', {
bindings: {
changeSelection: '<',
configured: '<'
},
template:
`
<pf-toolbar class="entaxy-toolbar" config="$ctrl.toolbarConfig"></pf-toolbar>
<div class="entaxy-cicd-objects-table-container">
<pf-table-view config="$ctrl.tableConfig"
columns="$ctrl.tableColumns"
items="$ctrl.viewedItems">
</pf-table-view>
</div>
`,
controller: EntaxyCICDConfigurationsController
})
.name;
function EntaxyCICDConfigurationsController(workspace, $q, entaxyCICDService, $templateCache, $route) {
'ngInject';
let ctrl = this;
ctrl.tableConfig = {
selectionMatchProp: 'id'
};
function changeSelected(item) {
if (ctrl.selected[item.id]) {
delete ctrl.selected[item.id];
} else {
ctrl.selected[item.id] = item;
}
}
ctrl.toolbarConfig = {
filterConfig: {
fields: [
{
id: 'id',
title: 'Id',
placeholder: 'Filter by Id...',
filterType: 'text'
}
],
inlineResults: true,
appliedFilters: [],
onFilterChange: filterChange
},
isTableView: true
};
ctrl.tableColumns = [
{
header: 'Id',
itemField: 'id',
htmlTemplate: 'configurations/id.html',
colActionFn: (configurationId) => ctrl.changeSelection(configurationId)
},
{ header: 'Location', itemField: 'location' }
];
$templateCache.put(
'configurations/id.html',
'<a href="" ng-click="$ctrl.handleColAction(key, value)">{{value}}</a>'
);
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 === 'id') {
match = item.id.toLowerCase().match(filter.value.toLowerCase()) !== null;
}
return match;
};
ctrl.items = [];
ctrl.viewedItems = [];
ctrl.$onInit = function() {
ctrl.tableConfig.showCheckboxes = ctrl.configured;
if (ctrl.configured) {
ctrl.selected = {};
ctrl.tableConfig.onCheckBoxChange = (item) => changeSelected(item);
let primaryActions = [
{name: 'Set Local Values', actionFn: useLocalValues}
];
ctrl.toolbarConfig.actionsConfig = {
primaryActions: primaryActions
};
}
ctrl.storage = EntaxyCICD.getStorage(workspace.selection);
ctrl.application = EntaxyCICD.getProjectOrApplication(workspace.selection);
ctrl.version = EntaxyCICD.getVersion(workspace.selection);
ctrl.revision = workspace.selection.title.split(' ')[0];
populateTable();
}
function populateTable() {
entaxyCICDService.executeOperation('listRevisionConfigurations',
[ctrl.storage, ctrl.application, ctrl.version, ctrl.revision])
.then(result => {
let items = JSON.parse(result);
ctrl.items = items;
filterChange(ctrl.toolbarConfig.filterConfig.appliedFilters);
});
}
function useLocalValues() {
let selectedIds = Object.keys(ctrl.selected);
if (selectedIds.length > 0) {
let promises = [];
let failedIds = [];
selectedIds.forEach(id => {
promises.push(
entaxyCICDService.executeOperation('fillInRevisionConfigurationWithLocalValues',
[ctrl.storage, ctrl.application, ctrl.version, ctrl.revision, id])
.catch(error => {
failedIds.push(id);
EntaxyCICD.log.error(error);
})
);
});
$q.all(promises).then(result => {
if (failedIds.length > 0) {
let result = selectedIds.map(id => {
return {
id: id,
failed: failedIds.includes(id)
};
});
let tableHtml = Entaxy.createStatusResultTable(result, 'Configuration Id');
let mainMessage = 'Some configurations were skipped ' +
'while setting local values due to errors that have occurred';
Entaxy.notificationWithDetails(Entaxy.NOTIFICATION_TYPE.WARNING, mainMessage, tableHtml,
Entaxy.configuration[Entaxy.CONFIGURATION_KEYS.NOTIFICATION_TIMEOUT_TABLE]);
} else {
Entaxy.notificationSuccess('Values of selected configurations were successfully ' +
'set to values of local configurations');
}
$route.reload();
}).catch(error => {
Entaxy.notificationError(error);
EntaxyCICD.log.error(error);
});
}
}
}
EntaxyCICDConfigurationsController.$inject = ['workspace', '$q', 'entaxyCICDService', '$templateCache', '$route'];
})(EntaxyCICD || (EntaxyCICD = {}));

View File

@@ -0,0 +1,151 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-cicd-plugin
* ==========
* Copyright (C) 2020 - 2025 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 EntaxyCICD;
(function (EntaxyCICD) {
EntaxyCICD._module.component('entaxyCiCdApplicationItems', {
bindings: {
version: '<'
},
template:
`
<pf-toolbar class="entaxy-toolbar" config="$ctrl.toolbarConfig"></pf-toolbar>
<pf-table-view class="entaxy-cicd-table"
config="$ctrl.tableConfig"
columns="$ctrl.tableColumns"
page-config="$ctrl.pageConfig"
items="$ctrl.viewedItems">
</pf-table-view>
`,
controller: EntaxyCICDApplicationItemsController
})
.name;
function EntaxyCICDApplicationItemsController(workspace, $scope, entaxyCICDService) {
'ngInject';
let ctrl = this;
ctrl.tableConfig = {
selectionMatchProp: 'id',
showCheckboxes: false
};
ctrl.toolbarConfig = {
filterConfig: {
fields: [
{
id: 'id',
title: 'Id',
placeholder: 'Filter by Id...',
filterType: 'text'
},
{
id: 'type',
title: 'Type',
placeholder: 'Filter by Type...',
filterType: 'select',
filterValues: []
},
{
id: 'revisionable',
title: 'Revisionable',
placeholder: 'Filter by Revisionable...',
filterType: 'select',
filterValues: ['yes', 'no']
},
{
id: 'editable',
title: 'Editable',
placeholder: 'Filter by Editable...',
filterType: 'select',
filterValues: ['yes', 'no']
}
],
inlineResults: true,
appliedFilters: [],
onFilterChange: filterChange
},
isTableView: true
};
ctrl.tableColumns = [
{ header: 'Id', itemField: 'id' },
{ header: 'Type', itemField: 'type' },
{ header: 'Revisionable', itemField: 'revisionable',
templateFn: (value) => EntaxyCICD.getStatusTemplate(value) },
{ header: 'Editable', itemField: 'editable',
templateFn: (value) => EntaxyCICD.getStatusTemplate(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) {
let match = true;
if (filter.id === 'id') {
match = item.id.toLowerCase().match(filter.value.toLowerCase()) !== null;
} else if (filter.id === 'type') {
match = item.type === filter.value;
} else if (filter.id === 'revisionable') {
match = filter.value === 'yes' ? item.revisionable === true : item.revisionable === false;
} else if (filter.id === 'editable') {
match = filter.value === 'yes' ? item.editable === true : item.editable === false;
}
return match;
};
ctrl.items = [];
ctrl.viewedItems = [];
ctrl.$onInit = function() {
entaxyCICDService.setTypesToFilterConfig(ctrl.toolbarConfig.filterConfig.fields);
}
$scope.$watch('$ctrl.version', function () {
populateTable();
});
function populateTable() {
const storage = EntaxyCICD.getStorage(workspace.selection);
const application = EntaxyCICD.getProjectOrApplication(workspace.selection);
entaxyCICDService.executeOperation('listApplicationItems', [storage, application, ctrl.version])
.then(result => {
let items = JSON.parse(result);
ctrl.items = items;
filterChange(ctrl.toolbarConfig.filterConfig.appliedFilters);
});
}
}
EntaxyCICDApplicationItemsController.$inject = ['workspace', '$scope', 'entaxyCICDService'];
})(EntaxyCICD || (EntaxyCICD = {}));

View File

@@ -0,0 +1,95 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-cicd-plugin
* ==========
* Copyright (C) 2020 - 2025 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 EntaxyCICD;
(function (EntaxyCICD) {
EntaxyCICD._module.component('entaxyCiCdRevision', {
template:
`
<div class="entaxy-cicd-zero-revision-note" ng-if="$ctrl.revision === '0'">
<entaxy-form-field-extra-info type="'info'" message="$ctrl.zeroRevisionNote"></entaxy-form-field-extra-info>
</div>
<div class="entaxy-cicd-header-container">
<div class="entaxy-cicd-title-with-info-container">
<span class="first">Application: {{$ctrl.application}}</span>
<span>Version: {{$ctrl.version}}</span>
<span class="lead">Revision: {{$ctrl.revision}}</span>
<span>Revision Status: {{$ctrl.revisionStatus}}</span>
</div>
<div class="entaxy-cicd-header-buttons-container">
<entaxy-ci-cd-application-management-buttons storage="$ctrl.storage" application="$ctrl.application"
version="$ctrl.version" revision="$ctrl.revision" revision-status="$ctrl.revisionStatus"
is-configuration-dirty="$ctrl.isConfigurationDirty">
</entaxy-ci-cd-application-management-buttons>
</div>
</div>
<div class="entaxy-cicd-content-container">
<h2 class="first">
Configurations
</h2>
<entaxy-ci-cd-configurations change-selection="$ctrl.changeSelection"
configured="$ctrl.isConfigured"></entaxy-ci-cd-configurations>
<div class="entaxy-cicd-configuration-container" ng-if="$ctrl.configuration">
<entaxy-ci-cd-configuration configuration-id="$ctrl.configuration"
configured="$ctrl.isConfigured" is-dirty="$ctrl.isConfigurationDirty"></entaxy-ci-cd-configuration>
</div>
</div>
`,
controller: EntaxyCICDRevisionController
})
.name;
function EntaxyCICDRevisionController(workspace) {
'ngInject';
let ctrl = this;
ctrl.zeroRevisionNote = 'Revision 0 cannot be configured';
ctrl.$onInit = function() {
ctrl.storage = EntaxyCICD.getStorage(workspace.selection);
ctrl.application = EntaxyCICD.getProjectOrApplication(workspace.selection);
ctrl.version = EntaxyCICD.getVersion(workspace.selection);
let revisionInfo = EntaxyCICD.getRevisionInfo(workspace.selection);
ctrl.revision = revisionInfo.revision;
ctrl.revisionStatus = revisionInfo.revisionStatus;
ctrl.isConfigured = ctrl.revisionStatus === EntaxyCICD.REVISION_STATUS.CONFIGURED;
}
ctrl.changeSelection = function (configurationId) {
if (!ctrl.isConfigurationDirty || confirm(Entaxy.CONFIRMATION.UNSAVED_CHANGES)) {
ctrl.configuration = configurationId;
}
}
}
EntaxyCICDRevisionController.$inject = ['workspace'];
})(EntaxyCICD || (EntaxyCICD = {}));

View File

@@ -0,0 +1,181 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-cicd-plugin
* ==========
* Copyright (C) 2020 - 2025 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 EntaxyCICD;
(function (EntaxyCICD) {
EntaxyCICD._module.component('entaxyCiCdVersionsRevisionsInfo', {
template:
`
<div class="entaxy-cicd-content-with-title-container">
<h2>Versions & Revisions</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>
</div>
`,
controller: EntaxyCICDVersionsRevisionsInfoController
})
.name;
function EntaxyCICDVersionsRevisionsInfoController(workspace, entaxyCICDService, $q, $templateCache, $location) {
'ngInject';
let ctrl = this;
ctrl.tableConfig = {
selectionMatchProp: 'version',
showCheckboxes: false
};
ctrl.toolbarConfig = {
filterConfig: {
fields: [
{
id: 'version',
title: 'Version',
placeholder: 'Filter by Version...',
filterType: 'text'
},
{
id: 'installedRevision',
title: 'Installed Revision Presence',
placeholder: 'Filter by Installed Revision Presence...',
filterType: 'select',
filterValues: ['present', 'not present']
}
],
inlineResults: true,
appliedFilters: [],
onFilterChange: filterChange
},
isTableView: true
};
ctrl.tableColumns = [
{
header: 'Version',
itemField: 'version',
htmlTemplate: 'application/version.html',
colActionFn: (version) => ctrl.changeLocation(version)
},
{ header: 'Last Revision', itemField: 'lastRevision' },
{ header: 'Installed Revision', itemField: 'installedRevision' }
];
$templateCache.put(
'application/version.html',
'<a href="" ng-click="$ctrl.handleColAction(key, value)">{{value}}</a>'
);
ctrl.changeLocation = function (version) {
let nid = $location.search().nid;
$location.search('nid', nid + '-' + version);
}
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 === 'version') {
match = item.version.match(filter.value) !== null;
} else if (filter.id === 'installedRevision') {
match = filter.value === 'present' ? item.installedRevision !== '-' : item.installedRevision === '-';
}
return match;
};
ctrl.items = [];
ctrl.viewedItems = [];
ctrl.$onInit = function() {
ctrl.storage = EntaxyCICD.getStorage(workspace.selection);
ctrl.tableActionButtons = [
{ name: 'Remove Version', title: 'Remove Version', actionFn: removeVersion }
];
populateTable();
}
function populateTable() {
const applicationFolder = workspace.selection;
let items = [];
let promises = [];
if (applicationFolder.children && applicationFolder.children.length > 0) {
applicationFolder.children.forEach(versionFolder => {
promises.push(
entaxyCICDService.executeOperation('readApplicationVersionLastAndInstalledRevision',
[ctrl.storage, applicationFolder.title, versionFolder.title])
.then(result => {
let revisionsInfo = JSON.parse(result);
items.push({
version: versionFolder.title,
lastRevision: revisionsInfo.lastRevision,
installedRevision: revisionsInfo.installedRevision
});
})
);
});
}
$q.all(promises).then(() => {
ctrl.items = items;
filterChange(ctrl.toolbarConfig.filterConfig.appliedFilters);
});
}
function removeVersion(action, item) {
let application = workspace.selection.title;
if (ctrl.items.length > 1) {
let properties = [ctrl.storage, application, item.version];
entaxyCICDService.removeItemWithConfirmation(EntaxyCICD.ITEM_TYPE.VERSION, item.version, properties);
} else {
let properties = [ctrl.storage, application];
let message = 'Removing the last version of the application will lead to removing the application. ' +
'Do you want to proceed?';
entaxyCICDService.removeItemWithConfirmation(EntaxyCICD.ITEM_TYPE.APPLICATION, null, properties,
false, message);
}
}
}
EntaxyCICDVersionsRevisionsInfoController.$inject = ['workspace', 'entaxyCICDService', '$q', '$templateCache',
'$location'];
})(EntaxyCICD || (EntaxyCICD = {}));

View File

@@ -0,0 +1,280 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-cicd-plugin
* ==========
* Copyright (C) 2020 - 2025 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 EntaxyCICD;
(function (EntaxyCICD) {
EntaxyCICD._module.component('entaxyCiCdApplicationsTable', {
bindings: {
type: '@',
importFromFile: '<',
importFromRepository: '<',
createProject: '<'
},
template:
`
<pf-toolbar class="entaxy-toolbar" config="$ctrl.toolbarConfig">
<actions>
<span class="dropdown primary-action" uib-dropdown>
<button class="btn btn-default dropdown-toggle" uib-dropdown-toggle type="button">
Import
<span class="caret"></span>
</button>
<ul class="dropdown-menu">
<li role="menuitem" ng-click="$ctrl.importFromFile()">
<a class="secondary-action">Import From File</a>
</li>
<li role="menuitem" ng-click="$ctrl.importFromRepository()">
<a class="secondary-action">Import From Repository</a>
</li>
</ul>
</span>
</actions>
</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: EntaxyCICDApplicationsTableController
})
.name;
function EntaxyCICDApplicationsTableController(workspace, $uibModal, entaxyCICDService, $templateCache, $location) {
'ngInject';
let ctrl = this;
const isStorageSelected = EntaxyCICD.isStorage(workspace.selection);
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: 'applications/table/name.html',
colActionFn: (name) => ctrl.changeLocation(name)
}
];
$templateCache.put(
'applications/table/name.html',
'<a href="" ng-click="$ctrl.handleColAction(key, value)">{{value}}</a>'
);
ctrl.changeLocation = function (name) {
let nid = $location.search().nid;
if (isStorageSelected) {
$location.search('nid', nid + '-' + name);
} else {
let item = ctrl.viewedItems.find(viewedItem => viewedItem.name === name);
$location.search('nid', [nid, item.storage, name].join('-'));
}
}
if (!isStorageSelected) {
ctrl.tableColumns.push({ header: 'Storage', itemField: 'storage' });
ctrl.toolbarConfig.filterConfig.fields.push({
id: 'storage',
title: 'Storage',
placeholder: 'Filter by Storage...',
filterType: 'select',
filterValues: EntaxyCICD.getStorages(workspace.selection)
});
}
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;
} else if (filter.id === 'storage') {
match = item.storage === filter.value;
}
return match;
};
ctrl.items = [];
ctrl.viewedItems = [];
ctrl.$onInit = function() {
populateTable();
if (ctrl.type === EntaxyCICD.ITEM_TYPE.APPLICATION) {
ctrl.toolbarConfig.actionsConfig = {
actionsInclude: true
};
ctrl.tableColumns.push({
header: 'Versions & Revisions',
itemField: 'versionsRevisionsInfo',
templateFn: (value) => getVersionsRevisionsColumnTemplate(value)
});
} else if (ctrl.type === EntaxyCICD.ITEM_TYPE.PROJECT) {
let primaryActions = [{name: 'Create ' + ctrl.type, actionFn: () => ctrl.createProject(ctrl.items)}];
ctrl.toolbarConfig.actionsConfig = {
primaryActions: primaryActions
};
}
ctrl.tableActionButtons = [
{ name: 'Remove', title: 'Remove ' + ctrl.type, actionFn: removeItem }
];
}
function getVersionsRevisionsColumnTemplate(value) {
const DIV = {
OPEN: '<div>',
CLOSE: '</div>'
};
const CLASS_INSTALLED = 'class="entaxy-cicd-installed"';
function insert(string, index, substring) {
return string.slice(0, index) + substring + string.slice(index);
}
const spanOpen = '<span data-toggle="tooltip" title="">';
const SPAN = {
OPEN: {
VERSION: insert(spanOpen, -2, 'Version'),
LAST_REVISION: insert(spanOpen, -2, 'Last Revision'),
INSTALLED_REVISION: insert(spanOpen, -2, 'Installed Revision')
},
CLOSE: '</span>'
};
let result = DIV.OPEN;
value = value.sort(Entaxy.compareBy('version'));
value.forEach(item => {
const versionOpeningSpan = item.installedRevision !== '-' ?
insert(SPAN.OPEN.VERSION, 5, ' ' + CLASS_INSTALLED) :
SPAN.OPEN.VERSION;
const revisionOpeningSpan = item.installedRevision !== '-' ?
insert(SPAN.OPEN.INSTALLED_REVISION, 5, ' ' + CLASS_INSTALLED) :
SPAN.OPEN.INSTALLED_REVISION;
result = result +
DIV.OPEN +
versionOpeningSpan + item.version + SPAN.CLOSE +
SPAN.OPEN.LAST_REVISION + item.lastRevision + SPAN.CLOSE +
revisionOpeningSpan + item.installedRevision + SPAN.CLOSE +
DIV.CLOSE;
});
return result + DIV.CLOSE;
}
function populateTable() {
let items = [];
if (isStorageSelected) {
items = getItemsFromChildren(workspace.selection);
} else {
let storages = workspace.selection.children;
if (storages && storages.length > 0) {
storages.forEach(storage => {
items = getItemsFromChildren(storage);
});
}
}
if (ctrl.type === EntaxyCICD.ITEM_TYPE.APPLICATION) {
items.forEach(item => {
if (item.versions) {
item.versionsRevisionsInfo = [];
item.versions.forEach(version => {
entaxyCICDService.executeOperation('readApplicationVersionLastAndInstalledRevision',
[item.storage, item.name, version])
.then(result => {
let revisionsInfo = JSON.parse(result);
item.versionsRevisionsInfo.push({
version: version,
lastRevision: revisionsInfo.lastRevision,
installedRevision: revisionsInfo.installedRevision
});
});
});
}
});
}
ctrl.items = items;
filterChange(ctrl.toolbarConfig.filterConfig.appliedFilters);
}
function getItemsFromChildren(selection) {
let items = [];
if (selection.children && selection.children.length > 0) {
selection.children.forEach(item => {
items.push({
name: item.title,
storage: selection.title,
versions: ctrl.type === EntaxyCICD.ITEM_TYPE.APPLICATION
&& item.children && item.children.length > 0 ?
item.children.map(child => child.title) : undefined
});
});
}
return items;
}
function removeItem(action, item) {
let properties = [item.storage, item.name];
entaxyCICDService.removeItemWithConfirmation(ctrl.type, item.name, properties, true);
}
}
EntaxyCICDApplicationsTableController.$inject = ['workspace', '$uibModal', 'entaxyCICDService',
'$templateCache', '$location'];
})(EntaxyCICD || (EntaxyCICD = {}));

View File

@@ -0,0 +1,51 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-cicd-plugin
* ==========
* Copyright (C) 2020 - 2025 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 EntaxyCICD;
(function (EntaxyCICD) {
EntaxyCICD._module.component('entaxyCiCdContents', {
template:
`
<div class="contents" ng-view ng-if="$ctrl.isReady" style="padding: 0 !important;"></div>
`,
controller: EntaxyCICDContentsController
})
.name;
function EntaxyCICDContentsController($scope, $route) {
'ngInject';
let ctrl = this;
ctrl.isReady = false;
$scope.$on('jmxTreeClicked', function () {
ctrl.isReady = true;
$route.reload();
});
}
EntaxyCICDContentsController.$inject = ['$scope', '$route'];
})(EntaxyCICD || (EntaxyCICD = {}));

View File

@@ -0,0 +1,237 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-cicd-plugin
* ==========
* Copyright (C) 2020 - 2025 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 EntaxyCICD;
(function (EntaxyCICD) {
EntaxyCICD.log.debug("loading navigation");
EntaxyCICD._module
.config(configureRoutes)
.component('entaxyCiCdNavigation', {
template: `<hawtio-tabs tabs="$ctrl.tabs" on-change="$ctrl.goto(tab)"></hawtio-tabs>`,
controller: EntaxyCICDNavigationController
})
.name;
EntaxyCICD.log.debug("loaded navigation " + EntaxyCICD.navigationModule);
function EntaxyCICDNavigationController($scope, $location, workspace, localStorage, jolokia, $rootScope) {
'ngInject';
let ctrl = this;
this.$location = $location;
let selected = workspace.selection;
entaxyCICDJmxDomain = localStorage['entaxyCICDJmxDomain'] || "ru.entaxy.cicd";
$scope.$on('jmxTreeClicked', function (event, selectedNode) {
ctrl.tabs = getTabs();
let tab;
if (!selected) {
selected = selectedNode;
tab = _.find(ctrl.tabs, { path: ctrl.$location.path() });
if (!tab) {
tab = ctrl.tabs[0];
}
} else {
if (JSON.stringify(selected.folderNames) !== JSON.stringify(selectedNode.folderNames)) {
selected = selectedNode;
tab = ctrl.tabs[0];
} else {
tab = _.find(ctrl.tabs, {path: ctrl.$location.path()});
if (!tab) {
tab = ctrl.tabs[0];
}
}
}
ctrl.$location.path(tab.path);
});
EntaxyCICDNavigationController.prototype.$onInit = function () {
if (!workspace.selection) {
this.tabs = [];
} else {
this.tabs = getTabs();
}
};
EntaxyCICDNavigationController.prototype.goto = function (tab) {
this.$location.path(tab.path);
};
function getTabs() {
var tabs = [];
var enabledRoutes = Object.keys(TAB_CONFIG)
.map(function (config) { return TAB_CONFIG[config].route; })
.filter(function (route) { return _.startsWith(route, '/entaxy-cicd'); });
if (enabledRoutes.length > 0) {
if (workspace.getSelectedMBeanName()) {
if (workspace.hasDomainAndProperties(entaxyCICDJmxDomain, { module: 'projects' })) {
tabs.push(new Nav.HawtioTab(TAB_CONFIG.projects.title, TAB_CONFIG.projects.route));
} else if (workspace.hasDomainAndProperties(entaxyCICDJmxDomain, { module: 'applications' })) {
tabs.push(new Nav.HawtioTab(TAB_CONFIG.applications.title, TAB_CONFIG.applications.route));
}
} else if (shouldShowProjectsTab()) {
tabs.push(new Nav.HawtioTab(TAB_CONFIG.projects.title, TAB_CONFIG.projects.route));
} else if (shouldShowVersionsTab()) {
tabs.push(new Nav.HawtioTab(TAB_CONFIG.projectVersions.title, TAB_CONFIG.projectVersions.route));
tabs.push(new Nav.HawtioTab(TAB_CONFIG.project.title, TAB_CONFIG.project.route));
} else if (shouldShowProjectTab()) {
tabs.push(new Nav.HawtioTab(TAB_CONFIG.project.title, TAB_CONFIG.project.route));
} else if (shouldShowBuildInfoTabs()) {
tabs.push(new Nav.HawtioTab(TAB_CONFIG.buildInfoItems.title, TAB_CONFIG.buildInfoItems.route));
tabs.push(new Nav.HawtioTab(TAB_CONFIG.buildInfoRequirements.title, TAB_CONFIG.buildInfoRequirements.route));
tabs.push(new Nav.HawtioTab(TAB_CONFIG.buildInfoComponents.title, TAB_CONFIG.buildInfoComponents.route));
} else if (shouldShowApplicationsTab()) {
tabs.push(new Nav.HawtioTab(TAB_CONFIG.applications.title, TAB_CONFIG.applications.route));
} else if (shouldShowVersionsRevisionsTab()) {
tabs.push(new Nav.HawtioTab(TAB_CONFIG.versionsRevisionsInfo.title, TAB_CONFIG.versionsRevisionsInfo.route));
tabs.push(new Nav.HawtioTab(TAB_CONFIG.application.title, TAB_CONFIG.application.route));
} else if (shouldShowApplicationTab()) {
tabs.push(new Nav.HawtioTab(TAB_CONFIG.application.title, TAB_CONFIG.application.route));
} else if (shouldShowRevisionTab()) {
tabs.push(new Nav.HawtioTab(TAB_CONFIG.revision.title, TAB_CONFIG.revision.route));
tabs.push(new Nav.HawtioTab(TAB_CONFIG.application.title, TAB_CONFIG.application.route));
}
}
return tabs;
}
function shouldShowProjectsTab() {
let selectionFolderNames = workspace.selection.folderNames;
return selectionFolderNames[1] === 'projects' &&
(selectionFolderNames.length === 2 || selectionFolderNames.length === 3);
}
function shouldShowVersionsTab() {
let selectionFolderNames = workspace.selection.folderNames;
return selectionFolderNames[1] === 'projects' && selectionFolderNames.length === 4;
}
function shouldShowProjectTab() {
let selectionFolderNames = workspace.selection.folderNames;
return selectionFolderNames[1] === 'projects' &&
(selectionFolderNames.length === 4 || selectionFolderNames.length === 5);
}
function shouldShowBuildInfoTabs() {
let selectionFolderNames = workspace.selection.folderNames;
return selectionFolderNames[1] === 'projects' && selectionFolderNames.length === 6;
}
function shouldShowApplicationsTab() {
let selectionFolderNames = workspace.selection.folderNames;
return selectionFolderNames[1] === 'applications' &&
(selectionFolderNames.length === 2 || selectionFolderNames.length === 3);
}
function shouldShowApplicationTab() {
let selectionFolderNames = workspace.selection.folderNames;
return selectionFolderNames[1] === 'applications' && selectionFolderNames.length === 5;
}
function shouldShowVersionsRevisionsTab() {
let selectionFolderNames = workspace.selection.folderNames;
return selectionFolderNames[1] === 'applications' && selectionFolderNames.length === 4;
}
function shouldShowRevisionTab() {
let selectionFolderNames = workspace.selection.folderNames;
return selectionFolderNames[1] === 'applications' && selectionFolderNames.length === 6;
}
// global event for entaxy extras
$rootScope.$emit('entaxyCiCdNavigationInited', $scope);
}
EntaxyCICDNavigationController.$inject = ['$scope', '$location', 'workspace', 'localStorage', 'jolokia', '$rootScope']
function configureRoutes($routeProvider) {
$routeProvider.
when(TAB_CONFIG.projects.route,
{ template: '<entaxy-ci-cd-projects></entaxy-ci-cd-projects>' }).
when(TAB_CONFIG.projectVersions.route,
{ template: '<entaxy-ci-cd-project-versions></entaxy-ci-cd-project-versions>' }).
when(TAB_CONFIG.project.route,
{ template: '<entaxy-ci-cd-project></entaxy-ci-cd-project>' }).
when(TAB_CONFIG.buildInfoItems.route,
{ template: '<entaxy-ci-cd-build-info type="Items"></entaxy-ci-cd-build-info>' }).
when(TAB_CONFIG.buildInfoRequirements.route,
{ template: '<entaxy-ci-cd-build-info type="Requirements"></entaxy-ci-cd-build-info>' }).
when(TAB_CONFIG.buildInfoComponents.route,
{ template: '<entaxy-ci-cd-build-info type="Components"></entaxy-ci-cd-build-info>' }).
when(TAB_CONFIG.applications.route,
{ template: '<entaxy-ci-cd-applications></entaxy-ci-cd-applications>' }).
when(TAB_CONFIG.application.route,
{ template: '<entaxy-ci-cd-application></entaxy-ci-cd-application>' }).
when(TAB_CONFIG.versionsRevisionsInfo.route,
{ template: '<entaxy-ci-cd-versions-revisions-info></entaxy-ci-cd-versions-revisions-info>' }).
when(TAB_CONFIG.revision.route,
{ template: '<entaxy-ci-cd-revision></entaxy-ci-cd-revision>' });
}
configureRoutes.$inject = ['$routeProvider'];
})(EntaxyCICD || (EntaxyCICD = {}));
let TAB_CONFIG = {
projects: {
title: 'Projects',
route: '/entaxy-cicd/projects'
},
project: {
title: 'Project',
route: '/entaxy-cicd/project'
},
projectVersions: {
title: 'Versions',
route: '/entaxy-cicd/project/versions'
},
buildInfoItems: {
title: 'Items',
route: '/entaxy-cicd/project/build-info/items'
},
buildInfoRequirements: {
title: 'Requirements',
route: '/entaxy-cicd/project/build-info/requirements'
},
buildInfoComponents: {
title: 'Components',
route: '/entaxy-cicd/project/build-info/components'
},
applications: {
title: 'Applications',
route: '/entaxy-cicd/applications'
},
application: {
title: 'Application',
route: '/entaxy-cicd/application'
},
versionsRevisionsInfo: {
title: 'Versions & Revisions',
route: '/entaxy-cicd/application/versions-revisions-info'
},
revision: {
title: 'Revision',
route: '/entaxy-cicd/application/revision'
}
};

View File

@@ -0,0 +1,110 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-cicd-plugin
* ==========
* Copyright (C) 2020 - 2025 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 EntaxyCICD;
(function (EntaxyCICD) {
EntaxyCICD._module.component('entaxyCiCdAddObjectsModal', {
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">
<div ng-if="$ctrl.resolve.objects">
<div class="add-objects-message-container">
{{$ctrl.message}}
</div>
<entaxy-expandable-list items="$ctrl.resolve.objects" use-toolbar="false" show-select-box="true"
on-check-box-change-fn="$ctrl.changeSelected">
</entaxy-expandable-list>
</div>
<entaxy-ci-cd-objects-select change-selected="$ctrl.changeSelected" ng-if="!$ctrl.resolve.objects"
excluded-object-ids="$ctrl.resolve.excludedObjectIds"></entaxy-ci-cd-objects-select>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" ng-click="$ctrl.cancel()"
ng-if="$ctrl.includeSkip">Skip</button>
<button type="submit" class="btn btn-primary" ng-click="$ctrl.save()">Add</button>
</div>
</div>
`,
controller: entaxyCICDAddObjectsModalController
})
.name;
function entaxyCICDAddObjectsModalController() {
let ctrl = this;
ctrl.$onInit = function() {
ctrl.modalTitle = 'Add Objects to the Project: ' + ctrl.resolve.project;
ctrl.selected = {};
if (ctrl.resolve.objects) {
ctrl.message = 'You may also want to add optional related objects:';
ctrl.includeSkip = true;
}
}
ctrl.changeSelected = function (item) {
if (ctrl.resolve.objects) {
if (item.relatedTo && item.relatedTo.length > 1) {
let relatedToExcludeParent = item.relatedTo.filter(objectId => objectId !== item.parent);
relatedToExcludeParent.forEach(objectId => {
let object = ctrl.resolve.objects.find(it => it.name === objectId);
let relatedObject = object.sublist.find(it => it.name === item.name);
relatedObject.selected = item.selected;
});
}
}
if (ctrl.selected[item.fullId]) {
delete ctrl.selected[item.fullId];
} else {
ctrl.selected[item.fullId] = item;
}
}
ctrl.save = function () {
ctrl.modalInstance.close(ctrl.selected);
}
ctrl.cancel = function(reason) {
ctrl.modalInstance.dismiss(reason);
}
}
})(EntaxyCICD || (EntaxyCICD = {}));

View File

@@ -0,0 +1,171 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-cicd-plugin
* ==========
* Copyright (C) 2020 - 2025 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 EntaxyCICD;
(function (EntaxyCICD) {
EntaxyCICD._module.component('entaxyCiCdBuildInfo', {
bindings: {
type: '@'
},
template:
`
<div class="entaxy-cicd-header-container">
<div class="entaxy-cicd-title-with-info-container">
<span class="first lead">Build</span>
<span>Project: {{$ctrl.project}}</span>
<span>Version: {{$ctrl.version}}</span>
<div ng-if="$ctrl.mavenUrl">
<span>Maven URL: {{$ctrl.mavenUrl}}</span>
<entaxy-copy-to-clipboard-button title="Copy maven URL to clipboard"
text-to-copy="$ctrl.mavenUrl"></entaxy-copy-to-clipboard-button>
</div>
</div>
<div class="entaxy-cicd-header-buttons-container">
<div class="btn-group" uib-dropdown>
<button id="single-button" type="button" uib-dropdown-toggle ng-disabled="disabled">
Export
<span class="caret"></span>
</button>
<ul class="dropdown-menu dropdown-menu-right" uib-dropdown-menu
role="menu" aria-labelledby="single-button">
<li role="menuitem"><a ng-click="$ctrl.exportToFile()">Export To File</a></li>
<li role="menuitem"><a ng-click="$ctrl.exportToRepository()">Export To Repository</a></li>
</ul>
</div>
</div>
</div>
<div class="entaxy-cicd-content-container">
<h2 class="first">
{{ $ctrl.type }}
</h2>
<entaxy-ci-cd-project-items ng-if="$ctrl.isItems()"></entaxy-ci-cd-project-items>
<entaxy-ci-cd-requirements ng-if="$ctrl.isRequirements()"
version="$ctrl.version" type="BuiltProject"></entaxy-ci-cd-requirements>
<entaxy-ci-cd-project-components ng-if="$ctrl.isComponents()"></entaxy-ci-cd-project-components>
</div>
`,
controller: entaxyCICDBuildInfoController
})
.name;
function entaxyCICDBuildInfoController(workspace, entaxyCICDService, entaxyService, $uibModal) {
'ngInject';
let ctrl = this;
const storage = EntaxyCICD.getStorage(workspace.selection);
const TYPE = {
ITEMS: 'Items',
REQUIREMENTS: 'Requirements',
COMPONENTS: 'Components'
}
ctrl.isItems = function () {
return ctrl.type === TYPE.ITEMS;
}
ctrl.isRequirements = function () {
return ctrl.type === TYPE.REQUIREMENTS;
}
ctrl.isComponents = function () {
return ctrl.type === TYPE.COMPONENTS;
}
ctrl.$onInit = function() {
ctrl.project = EntaxyCICD.getProjectOrApplication(workspace.selection);
ctrl.version = EntaxyCICD.getVersion(workspace.selection);
entaxyCICDService.executeOperation('readMavenUrl', [storage, ctrl.project, ctrl.version])
.then(result => {
ctrl.mavenUrl = result;
});
}
ctrl.exportToFile = function () {
entaxyCICDService.executeOperation('exportToFile', [storage, ctrl.project, ctrl.version])
.then(result => {
let fileName = ctrl.project + '-' + ctrl.version + '.jar';
entaxyService.downloadFileFromBase64StringContent(result, fileName);
}).catch(error => {
Entaxy.notificationError(error);
EntaxyCICD.log.error(error);
});
}
ctrl.exportToRepository = function () {
entaxyCICDService.executeOperation('listRepositories', [])
.then(result => {
let formFields = [
{
label: 'Repository',
name: 'repository',
enum: true,
required: true,
values: JSON.parse(result),
setFocused: true
}
];
showExportModal(formFields);
}).catch(error => {
Entaxy.notificationError(error);
});
}
function showExportModal(formFields) {
$uibModal.open({
component: 'entaxyCiCdSimpleFieldsModal',
resolve: {
modalTitle: () => 'Export Project To Repository',
formFields: () => formFields
},
backdrop: 'static'
}).result.then((args) => {
exportToRepository(args[0]);
}, reason => {
if (reason && reason !== Entaxy.MODAL_CANCEL_REASON.ESCAPE_KEY_PRESS) {
Entaxy.notificationError(reason);
}
});
}
function exportToRepository(repository) {
entaxyCICDService.executeOperation('exportToRepository',
[storage, ctrl.project, ctrl.version, repository])
.then(result => {
Entaxy.notificationSuccess(result);
}).catch(error => {
Entaxy.notificationError(error);
EntaxyCICD.log.error(error);
});
}
}
entaxyCICDBuildInfoController.$inject = ['workspace', 'entaxyCICDService', 'entaxyService', '$uibModal'];
})(EntaxyCICD || (EntaxyCICD = {}));

View File

@@ -0,0 +1,126 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-cicd-plugin
* ==========
* Copyright (C) 2020 - 2025 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 EntaxyCICD;
(function (EntaxyCICD) {
EntaxyCICD._module.component('entaxyCiCdProjectComponents', {
template:
`
<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: EntaxyCICDProjectComponentsController
})
.name;
function EntaxyCICDProjectComponentsController(workspace, entaxyCICDService) {
'ngInject';
let ctrl = this;
ctrl.tableConfig = {
selectionMatchProp: 'id',
showCheckboxes: false
};
ctrl.toolbarConfig = {
filterConfig: {
fields: [
{
id: 'id',
title: 'Id',
placeholder: 'Filter by Id...',
filterType: 'text'
},
{
id: 'type',
title: 'Type',
placeholder: 'Filter by Type...',
filterType: 'select',
filterValues: []
}
],
inlineResults: true,
appliedFilters: [],
onFilterChange: filterChange
},
isTableView: true
};
ctrl.tableColumns = [
{ header: 'Id', itemField: 'id' },
{ header: 'Type', itemField: 'type' },
{ header: 'Priority', itemField: 'priority' }
];
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 === 'id') {
match = item.id.match(filter.value) !== null;
} else if (filter.id === 'type') {
match = item.type === filter.value;
}
return match;
};
ctrl.items = [];
ctrl.viewedItems = [];
ctrl.$onInit = function() {
entaxyCICDService.setTypesToFilterConfig(ctrl.toolbarConfig.filterConfig.fields);
populateTable();
}
function populateTable() {
const storage = EntaxyCICD.getStorage(workspace.selection);
const project = EntaxyCICD.getProjectOrApplication(workspace.selection);
const version = EntaxyCICD.getVersion(workspace.selection);
entaxyCICDService.executeOperation('listBuiltProjectComponents', [storage, project, version])
.then(result => {
let items = JSON.parse(result);
ctrl.items = items;
filterChange(ctrl.toolbarConfig.filterConfig.appliedFilters);
});
}
}
EntaxyCICDProjectComponentsController.$inject = ['workspace', 'entaxyCICDService'];
})(EntaxyCICD || (EntaxyCICD = {}));

View File

@@ -0,0 +1,126 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-cicd-plugin
* ==========
* Copyright (C) 2020 - 2025 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 EntaxyCICD;
(function (EntaxyCICD) {
EntaxyCICD._module.component('entaxyCiCdProjectItems', {
template:
`
<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: EntaxyCICDProjectItemsController
})
.name;
function EntaxyCICDProjectItemsController(workspace, entaxyCICDService) {
'ngInject';
let ctrl = this;
ctrl.tableConfig = {
selectionMatchProp: 'id',
showCheckboxes: false
};
ctrl.toolbarConfig = {
filterConfig: {
fields: [
{
id: 'id',
title: 'Id',
placeholder: 'Filter by Id...',
filterType: 'text'
},
{
id: 'type',
title: 'Type',
placeholder: 'Filter by Type...',
filterType: 'select',
filterValues: []
}
],
inlineResults: true,
appliedFilters: [],
onFilterChange: filterChange
},
isTableView: true
};
ctrl.tableColumns = [
{ header: 'Id', itemField: 'id' },
{ header: 'Type', itemField: 'type' },
{ header: 'Component', itemField: 'component' }
];
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 === 'id') {
match = item.id.match(filter.value) !== null;
} else if (filter.id === 'type') {
match = item.type === filter.value;
}
return match;
};
ctrl.items = [];
ctrl.viewedItems = [];
ctrl.$onInit = function() {
entaxyCICDService.setTypesToFilterConfig(ctrl.toolbarConfig.filterConfig.fields);
populateTable();
}
function populateTable() {
const storage = EntaxyCICD.getStorage(workspace.selection);
const project = EntaxyCICD.getProjectOrApplication(workspace.selection);
const version = EntaxyCICD.getVersion(workspace.selection);
entaxyCICDService.executeOperation('listBuiltProjectItems', [storage, project, version])
.then(result => {
let items = JSON.parse(result);
ctrl.items = items;
filterChange(ctrl.toolbarConfig.filterConfig.appliedFilters);
});
}
}
EntaxyCICDProjectItemsController.$inject = ['workspace', 'entaxyCICDService'];
})(EntaxyCICD || (EntaxyCICD = {}));

View File

@@ -0,0 +1,489 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-cicd-plugin
* ==========
* Copyright (C) 2020 - 2025 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 EntaxyCICD;
(function (EntaxyCICD) {
EntaxyCICD._module.component('entaxyCiCdObjects', {
bindings: {
storage: '<',
project: '<',
version: '<'
},
template:
`
<pf-toolbar class="entaxy-toolbar" config="$ctrl.toolbarConfig">
<actions>
<button type="button" class="btn btn-default" ng-repeat="action in $ctrl.actions"
ng-click="action.actionFn()">
{{action.name}}
</button>
</actions>
</pf-toolbar>
<div class="entaxy-cicd-objects-table-container">
<pf-table-view class="entaxy-cicd-table"
config="$ctrl.tableConfig"
columns="$ctrl.tableColumns"
dt-options="$ctrl.dtOptions"
items="$ctrl.viewedItems">
</pf-table-view>
</div>
`,
controller: EntaxyCICDObjectsController
})
.name;
function EntaxyCICDObjectsController(workspace, $scope, $uibModal, entaxyCICDService, $q, $route) {
'ngInject';
let ctrl = this;
ctrl.tableConfig = {
selectionMatchProp: 'id',
onCheckBoxChange: (item) => changeSelected(item)
};
function changeSelected(item) {
if (ctrl.selected[item.id]) {
delete ctrl.selected[item.id];
} else {
ctrl.selected[item.id] = item;
}
}
ctrl.toolbarConfig = {
filterConfig: {
fields: [
{
id: 'displayName',
title: 'Id / Name',
placeholder: 'Filter by Id or Name...',
filterType: 'text'
},
{
id: 'type',
title: 'Type',
placeholder: 'Filter by Type...',
filterType: 'select',
filterValues: []
},
{
id: 'status',
title: 'Status',
placeholder: 'Filter by Status...',
filterType: 'select',
filterValues: []
},
{
id: 'scope',
title: 'Scope',
placeholder: 'Filter by Scope...',
filterType: 'select',
filterValues: []
},
{
id: 'required',
title: 'Required',
placeholder: 'Filter by Required...',
filterType: 'select',
filterValues: ['yes', 'no']
},
{
id: 'ignored',
title: 'Ignored',
placeholder: 'Filter by Ignored...',
filterType: 'select',
filterValues: ['yes', 'no']
}
],
appliedFilters: [],
onFilterChange: filterChange
},
isTableView: true
};
ctrl.tableColumns = [
{ header: 'Status', itemField: 'status', templateFn: (value) => getObjectStatusTemplate(value) },
{ header: 'Id / Name', itemField: 'displayName' },
{ header: 'Type', itemField: 'type' },
{ header: 'Scope', itemField: 'scope' },
{ header: 'Required', itemField: 'required',
templateFn: (value) => EntaxyCICD.getStatusTemplate(value) },
{ header: 'Ignored', itemField: 'ignored',
templateFn: (value) => EntaxyCICD.getStatusTemplate(value) },
{ header: 'Id', itemField: 'id' }
];
function getObjectStatusTemplate(value) {
switch (value) {
case 'INCLUDED':
return '<span class="pficon pficon-ok" data-toggle="tooltip" title="Included"></span>';
case 'IGNORED':
return '<span class="pficon pficon-arrow" data-toggle="tooltip" title="Ignored"></span>';
case 'REQUIRED':
return '<span class="pficon pficon-warning-triangle-o" data-toggle="tooltip" title="Required"></span>';
case 'GHOST':
return '<span class="pficon pficon-unknowm" data-toggle="tooltip" title="Ghost"></span>';
case 'DELETED':
return '<span class="pficon pficon-error-circle-o" data-toggle="tooltip" title="Deleted"></span>';
}
}
ctrl.dtOptions = {
order: [[1, "desc"]],
columnDefs: [
{ "targets": [0], "sortable": false },
{ "targets": [7], "class": "hide" }
]
};
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 === 'status') {
match = item.status === filter.value;
} else if (filter.id === 'displayName') {
match = item.displayName.toLowerCase().match(filter.value.toLowerCase()) !== null;
} else if (filter.id === 'type') {
match = item.type === filter.value;
} else if (filter.id === 'scope') {
match = item.scope === filter.value;
} else if (filter.id === 'required') {
match = filter.value === 'yes' ? item.required === true : item.required === false;
} else if (filter.id === 'ignored') {
match = filter.value === 'yes' ? item.ignored === true : item.ignored === false;
}
return match;
};
ctrl.items = [];
ctrl.viewedItems = [];
ctrl.$onInit = function() {
ctrl.selected = {};
let primaryActions = [
{ name: 'Add Objects', actionFn: () => ctrl.showAddObjectsModal() },
{ name: 'Add Resources', actionFn: () => ctrl.showAddResourcesModal() }
];
ctrl.toolbarConfig.actionsConfig = {
primaryActions: primaryActions,
actionsInclude: true
};
ctrl.actions = [
{ name: 'Include Selected', actionFn: ctrl.includeSelected },
{ name: 'Ignore Selected', actionFn: ctrl.ignoreSelected },
{ name: 'Remove Selected', actionFn: ctrl.removeSelected },
{ name: 'Add Related', actionFn: ctrl.addRelatedObjects }
];
entaxyCICDService.setTypesToFilterConfig(ctrl.toolbarConfig.filterConfig.fields);
entaxyCICDService.setScopesToFilterConfig(ctrl.toolbarConfig.filterConfig.fields);
let filterConfigFieldStatus = ctrl.toolbarConfig.filterConfig.fields.find(field => field.id === 'status');
entaxyCICDService.executeOperation('readProjectItemStatuses', [])
.then(result => {
filterConfigFieldStatus.filterValues = JSON.parse(result);
});
}
$scope.$watch('$ctrl.version', function () {
populateTable();
});
function populateTable() {
ctrl.selected = {};
entaxyCICDService.executeOperation('listProjectItems', [ctrl.storage, ctrl.project, ctrl.version])
.then(result => {
let items = JSON.parse(result);
ctrl.items = items.map(item => {
if (!item.displayName || item.displayName.trim().length == 0) {
item.displayName = item.id;
}
return item;
});
filterChange(ctrl.toolbarConfig.filterConfig.appliedFilters);
});
}
ctrl.showAddObjectsModal = function (objects) {
$uibModal.open({
component: 'entaxyCiCdAddObjectsModal',
resolve: {
project: () => ctrl.project,
objects: () => objects,
excludedObjectIds: () => ctrl.items.length > 0 ? ctrl.items.map(item => item.id) : []
},
size: 'xl',
backdrop: 'static'
})
.result.then(objectsMap => {
addObjects(objectsMap);
},
reason => {
if (reason && reason !== Entaxy.MODAL_CANCEL_REASON.ESCAPE_KEY_PRESS) {
Entaxy.notificationError(reason);
}
});
}
function addObjects(objectsMap) {
let objectsIds = Object.keys(objectsMap);
if (objectsIds.length > 0) {
let promises = [];
objectsIds.forEach(objectId => {
promises.push(
entaxyCICDService.executeOperation('addObject',
[ctrl.storage, ctrl.project, ctrl.version, objectId])
);
});
$q.all(promises).then(result => {
addRelatedObjects(objectsMap, objectsIds, result);
Entaxy.notificationSuccess('Operation Succeeded');
populateTable();
}).catch(error => {
Entaxy.notificationError(error);
});
}
}
function addRelatedObjects(objectsMap, objectsIds, result, showNotification) {
let objectsTree = [];
let relations = {};
let addedItems = ctrl.items.length > 0 ? ctrl.items.map(item => item.id) : [];
for (let i = 0; i < objectsIds.length; i++) {
let relatedObjects = JSON.parse(result[i]);
if (relatedObjects.length > 0) {
let objectsToAdd = relatedObjects.filter(object =>
!objectsIds.includes(object.fullId) && !addedItems.includes(object.fullId));
if (objectsToAdd.length > 0) {
let sublist = objectsToAdd.map(object => {
addRelation(relations, object.fullId, objectsIds[i]);
return {
name: object.fullId,
fullId: object.fullId,
displayName: object.displayName,
additionalInfo: object.type,
parent: objectsIds[i],
disableRowExpansion: true
};
});
objectsTree.push({
name: objectsIds[i],
displayName: objectsMap[objectsIds[i]].displayName,
additionalInfo: objectsMap[objectsIds[i]].type,
isExpanded: true,
sublist: sublist.sort(Entaxy.compareBy('displayName'))
});
}
}
}
if (objectsTree.length > 0) {
setRelated(relations, objectsTree);
ctrl.showAddObjectsModal(objectsTree);
} else {
if (showNotification) {
Entaxy.notificationInfo('There are no related objects that are not included');
}
}
}
function addRelation(relations, relatedObjectId, objectId) {
if (relations[relatedObjectId]) {
relations[relatedObjectId].push(objectId);
} else {
relations[relatedObjectId] = [objectId];
}
}
function setRelated(relations, objectsTree) {
Object.keys(relations).forEach(key => {
if (relations[key].length > 1) {
relations[key].forEach(objectId => {
let object = objectsTree.find(object => object.name === objectId);
let relatedObject = object.sublist.find(object => object.name === key);
relatedObject.relatedTo = relations[key];
})
}
});
}
ctrl.addRelatedObjects = function () {
let objectsIds = Object.keys(ctrl.selected);
if (objectsIds.length == 0) {
Entaxy.notificationInfo('At least one item should be selected');
return;
}
let objectsMap = {};
let promises = [];
objectsIds.forEach(objectId => {
if (ctrl.selected[objectId].type === 'OBJECT') {
objectsMap[objectId] = {
displayName: ctrl.selected[objectId].displayName,
type: ctrl.selected[objectId].runtimeType
};
promises.push(
entaxyCICDService.executeOperation('getRelatedObjects', [objectId])
);
}
});
if (promises.length > 0) {
$q.all(promises).then(result => {
addRelatedObjects(objectsMap, Object.keys(objectsMap), result, true);
}).catch(error => {
Entaxy.notificationError(error);
});
} else {
Entaxy.notificationInfo('Selected items should have OBJECT type');
}
}
ctrl.showAddResourcesModal = function () {
$uibModal.open({
component: 'entaxyResourceViewerModal',
resolve: {
config: {
resourceProvider: 'schemas',
folderSelectionEnabled: true,
multipleSelectionEnabled: true,
providersSelectionEnabled: true
}
},
size: 'xl',
backdrop: 'static'
})
.result.then(locations => {
addResources(locations);
},
reason => {
if (reason && reason !== Entaxy.MODAL_CANCEL_REASON.ESCAPE_KEY_PRESS) {
Entaxy.notificationError(reason);
}
});
}
function addResources(locations) {
let promises = [];
let failedResources = [];
locations.forEach(location => {
promises.push(
entaxyCICDService.executeOperation('addResource',
[ctrl.storage, ctrl.project, ctrl.version, location])
.catch(error => {
failedResources.push(location);
EntaxyCICD.log.error(error);
})
);
});
$q.all(promises).then(result => {
if (failedResources.length > 0) {
let result = locations.map(location => {
return {
id: location,
failed: failedResources.includes(location)
};
});
let tableHtml = Entaxy.createStatusResultTable(result, 'Location');
let mainMessage = 'Errors occurred while adding resources';
Entaxy.notificationWithDetails(Entaxy.NOTIFICATION_TYPE.WARNING, mainMessage, tableHtml,
Entaxy.configuration[Entaxy.CONFIGURATION_KEYS.NOTIFICATION_TIMEOUT_TABLE]);
} else {
Entaxy.notificationSuccess('Operation Succeeded');
}
$route.reload();
}).catch(error => {
Entaxy.notificationError(error);
EntaxyCICD.log.error(error);
});
}
ctrl.includeSelected = function () {
processOperationSelected('addItem', 'Selected items were successfully included into the project');
}
ctrl.ignoreSelected = function () {
processOperationSelected('ignoreItem', 'Selected items were successfully ignored from the project');
}
ctrl.removeSelected = function () {
const operationName = 'removeItems';
const successMessage = 'Selected items were successfully removed from the project';
let selectedIds = Object.keys(ctrl.selected);
if (selectedIds.length > 0) {
entaxyCICDService
.executeOperation(operationName, [ctrl.storage, ctrl.project, ctrl.version, selectedIds])
.then(result => {
let unremovedItems = JSON.parse(result);
if (unremovedItems && Object.keys(unremovedItems).length > 0) {
let message = 'There are items that cannot be removed ' +
'since they are required by some of remaining items';
let table = EntaxyCICD.createTableFromUnremovedItems(unremovedItems);
Entaxy.notificationWithDetails(Entaxy.NOTIFICATION_TYPE.INFO, message, table, 30000);
} else {
Entaxy.notificationSuccess(successMessage);
}
$route.reload();
}).catch(error => {
Entaxy.notificationError(error);
EntaxyCICD.log.error(error);
});
}
}
function processOperationSelected(operationName, successMessage) {
let selectedIds = Object.keys(ctrl.selected);
if (selectedIds.length > 0) {
let promises = [];
selectedIds.forEach(id => {
promises.push(
entaxyCICDService.executeOperation(operationName,
[ctrl.storage, ctrl.project, ctrl.version, id])
);
});
$q.all(promises).then(result => {
Entaxy.notificationSuccess(successMessage ? successMessage : 'Operation succeeded');
$route.reload();
}).catch(error => {
Entaxy.notificationError(error);
EntaxyCICD.log.error(error);
});
}
}
}
EntaxyCICDObjectsController.$inject = ['workspace', '$scope', '$uibModal', 'entaxyCICDService', '$q', '$route'];
})(EntaxyCICD || (EntaxyCICD = {}));

View File

@@ -0,0 +1,127 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-cicd-plugin
* ==========
* Copyright (C) 2020 - 2025 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 EntaxyCICD;
(function (EntaxyCICD) {
EntaxyCICD._module.component('entaxyCiCdObjectsSelect', {
bindings: {
changeSelected: '<',
excludedObjectIds: '<'
},
template:
`
<pf-toolbar class="entaxy-toolbar" config="$ctrl.toolbarConfig"></pf-toolbar>
<div class="entaxy-cicd-objects-table-container">
<pf-table-view config="$ctrl.tableConfig"
columns="$ctrl.tableColumns"
dt-options="$ctrl.dtOptions"
items="$ctrl.viewedItems">
</pf-table-view>
</div>
`,
controller: EntaxyCICDObjectsSelectController
})
.name;
function EntaxyCICDObjectsSelectController(workspace, entaxyCICDService) {
'ngInject';
let ctrl = this;
ctrl.tableConfig = {
selectionMatchProp: 'fullId',
onCheckBoxChange: (item) => ctrl.changeSelected(item)
};
ctrl.toolbarConfig = {
filterConfig: {
fields: [
{
id: 'displayName',
title: 'Name',
placeholder: 'Filter by Name...',
filterType: 'text'
},
{
id: 'type',
title: 'Type',
placeholder: 'Filter by Type...',
filterType: 'text'
}
],
appliedFilters: [],
onFilterChange: filterChange
},
isTableView: true
};
ctrl.tableColumns = [
{ header: 'Name', itemField: 'displayName' },
{ header: 'Type', itemField: 'type' },
{ header: 'Full Id', itemField: 'fullId' }
];
ctrl.dtOptions = {
columnDefs: [
{ "targets": [0], "sortable": false },
{ "targets": [3], "class": "hide" }
]
};
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 === 'type') {
match = item.type.toLowerCase().match(filter.value.toLowerCase()) !== null;
}
return match;
};
ctrl.items = [];
ctrl.viewedItems = [];
ctrl.$onInit = function() {
populateTable();
}
function populateTable() {
entaxyCICDService.executeOperation('listObjects', [])
.then(result => {
let items = JSON.parse(result);
ctrl.items = items.filter(item => !ctrl.excludedObjectIds.includes(item.fullId));
filterChange(ctrl.toolbarConfig.filterConfig.appliedFilters);
});
}
}
EntaxyCICDObjectsSelectController.$inject = ['workspace', 'entaxyCICDService'];
})(EntaxyCICD || (EntaxyCICD = {}));

View File

@@ -0,0 +1,192 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-cicd-plugin
* ==========
* Copyright (C) 2020 - 2025 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 EntaxyCICD;
(function (EntaxyCICD) {
EntaxyCICD._module.component('entaxyCiCdProject', {
template:
`
<div ng-if="$ctrl.versions || $ctrl.isVersionSelected">
<div class="entaxy-cicd-header-container">
<div class="entaxy-cicd-title-with-info-container">
<span class="first" ng-class="{'lead': !$ctrl.isVersionSelected}">Project: {{$ctrl.project}}</span>
<span class="lead" ng-if="$ctrl.isVersionSelected">Version: {{$ctrl.version}}</span>
<div ng-if="!$ctrl.isVersionSelected">
<span>Version:</span>
<entaxy-select-from-enum values="$ctrl.versions" model="$ctrl.version"
is-empty-included="false"></entaxy-select-from-enum>
<div class="btn-group" uib-dropdown>
<button id="single-button" type="button" uib-dropdown-toggle ng-disabled="disabled">
Add Version
<span class="caret"></span>
</button>
<ul class="dropdown-menu" uib-dropdown-menu role="menu" aria-labelledby="single-button">
<li role="menuitem"><a ng-click="$ctrl.addVersionFromScratch()">Add Version From Scratch</a></li>
<li role="menuitem"><a ng-click="$ctrl.addVersionFromExistent()">Add Version From Existent</a></li>
</ul>
</div>
</div>
</div>
<div class="entaxy-cicd-header-buttons-container">
<button type="button" ng-click="$ctrl.commit()">Commit</button>
<button type="button" ng-click="$ctrl.build()">Build</button>
</div>
</div>
<div class="entaxy-cicd-content-container">
<entaxy-ci-cd-objects storage="$ctrl.storage" project="$ctrl.project" version="$ctrl.version"
ng-if="$ctrl.version"></entaxy-ci-cd-objects>
</div>
</div>
`,
controller: entaxyCICDProjectController
})
.name;
function entaxyCICDProjectController(workspace, entaxyCICDService, $uibModal) {
'ngInject';
let ctrl = this;
ctrl.$onInit = function() {
ctrl.storage = EntaxyCICD.getStorage(workspace.selection);
ctrl.project = EntaxyCICD.getProjectOrApplication(workspace.selection);
ctrl.isVersionSelected = EntaxyCICD.isVersion(workspace.selection);
if (ctrl.isVersionSelected) {
ctrl.version = workspace.selection.title;
} else {
populateVersions();
}
}
function populateVersions() {
ctrl.versions = EntaxyCICD.getVersions(workspace.selection);
if (ctrl.versions.length > 0) {
ctrl.version = ctrl.versions[ctrl.versions.length - 1];
}
}
function getFormFields() {
return [
{
label: 'Current Version',
name: 'currentVersion',
type: 'text',
value: ctrl.version,
readOnly: true
},
{
label: 'Created Version',
name: 'createdVersion',
type: 'text',
required: true,
validation: {
checkUniqueness: true,
values: ctrl.versions,
content: {
regex: '^([1-9][0-9]*|0)\\.([1-9][0-9]*|0)\\.([1-9][0-9]*|0)$',
errorMessage: 'Value must match the pattern: X.X.X, where X represents a number'
}
},
setFocused: true
}
];
}
ctrl.addVersionFromScratch = function () {
openCreateVersionModal(getFormFields());
}
ctrl.addVersionFromExistent = function () {
let formFields = getFormFields();
formFields.push({
label: 'Prototype Version',
name: 'prototypeVersion',
enum: true,
required: true,
values: ctrl.versions,
value: ctrl.version
});
openCreateVersionModal(formFields);
}
function openCreateVersionModal(formFields) {
$uibModal.open({
component: 'entaxyCiCdSimpleFieldsModal',
resolve: {
modalTitle: () => 'Create Version',
formFields: () => formFields
},
backdrop: 'static'
}).result.then((args) => {
args.shift();
createVersion(...args);
}, reason => {
if (reason && reason !== Entaxy.MODAL_CANCEL_REASON.ESCAPE_KEY_PRESS) {
Entaxy.notificationError(reason);
}
});
}
function createVersion(createdVersion, prototypeVersion) {
entaxyCICDService.executeOperation('createVersion',
[ctrl.storage, ctrl.project, createdVersion, prototypeVersion])
.then(result => {
Entaxy.notificationSuccess(result);
entaxyCICDService.treeUpdated();
}).catch(error => {
Entaxy.notificationError(error);
EntaxyCICD.log.error(error);
});
}
ctrl.commit = function () {
processOperation('saveProjectVersion');
}
ctrl.build = function () {
processOperation('buildProjectVersion');
}
function processOperation(operationName) {
entaxyCICDService.executeOperation(operationName, [ctrl.storage, ctrl.project, ctrl.version])
.then(result => {
Entaxy.notificationSuccess(result);
if (operationName === 'buildProjectVersion') {
workspace.jmxTreeUpdated();
}
}).catch(error => {
Entaxy.notificationError(error);
EntaxyCICD.log.error(error);
});
}
}
entaxyCICDProjectController.$inject = ['workspace', 'entaxyCICDService', '$uibModal'];
})(EntaxyCICD || (EntaxyCICD = {}));

View File

@@ -0,0 +1,146 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-cicd-plugin
* ==========
* Copyright (C) 2020 - 2025 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 EntaxyCICD;
(function (EntaxyCICD) {
EntaxyCICD._module.component('entaxyCiCdProjects', {
template:
`
<div class="entaxy-cicd-content-with-title-container">
<h2>
Projects
</h2>
<entaxy-ci-cd-applications-table type="Project" create-project="$ctrl.showCreateProjectModal">
</entaxy-ci-cd-applications-table>
</div>
`,
controller: EntaxyCICDProjectsController
})
.name;
function EntaxyCICDProjectsController(workspace, $uibModal, entaxyCICDService, $scope, $route) {
'ngInject';
let ctrl = this;
const isStorageSelected = EntaxyCICD.isStorage(workspace.selection);
ctrl.$onInit = function() {
}
ctrl.showCreateProjectModal = function(items) {
$uibModal.open({
component: 'entaxyCiCdSimpleFieldsModal',
resolve: {
modalTitle: () => 'Create Project',
formFields: () => getFormFields(items)
},
backdrop: 'static'
})
.result.then(args => {
createProject(args);
},
reason => {
if (reason && reason !== Entaxy.MODAL_CANCEL_REASON.ESCAPE_KEY_PRESS) {
Entaxy.notificationError(reason);
}
});
}
function getFormFields(items) {
return [
{
name: 'name',
label: 'Name',
type: 'text',
required: true,
validation: {
checkUniqueness: true,
values: items.map(project => project.name),
content: {
regex: '^[a-zA-Z0-9-_]+$',
errorMessage: 'Value must contain only latin letters, numbers, hyphens and underscores'
},
length: {
min: 3
}
},
setFocused: true
},
{
name: 'group',
label: 'Group',
type: 'text',
validation: {
content: {
regex: '^[a-zA-Z0-9-_]*$',
errorMessage: 'Value must contain only latin letters, numbers, hyphens and underscores'
}
},
},
{
name: 'storage',
label: 'Storage',
type: 'string',
value: isStorageSelected ? workspace.selection.title : undefined,
enum: isStorageSelected ? undefined : true,
values: isStorageSelected ? undefined : workspace.selection.children.map(child => child.title),
required: true,
readOnly: isStorageSelected ? true : undefined
},
{
name: 'version',
label: 'Version',
type: 'string',
value: '1.0.0',
required: true,
validation: {
content: {
regex: '^([1-9][0-9]*|0)\.([1-9][0-9]*|0)\.([1-9][0-9]*|0)$',
errorMessage: 'Value must match the pattern: X.X.X, where X represents the number'
}
}
}
];
}
function createProject(args) {
let projectName = args[1] ? args[1] + '/' + args[0] : args[0];
entaxyCICDService.executeOperation('createProject', [projectName, args[2], args[3]])
.then(result => {
Entaxy.notificationSuccess(result);
entaxyCICDService.treeUpdated();
})
.catch(error => {
Entaxy.notificationError(error);
EntaxyCICD.log.error(error);
});
}
}
EntaxyCICDProjectsController.$inject = ['workspace', '$uibModal', 'entaxyCICDService', '$scope', '$route'];
})(EntaxyCICD || (EntaxyCICD = {}));

View File

@@ -0,0 +1,246 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-cicd-plugin
* ==========
* Copyright (C) 2020 - 2025 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 EntaxyCICD;
(function (EntaxyCICD) {
EntaxyCICD._module.component('entaxyCiCdProjectVersions', {
template:
`
<div class="entaxy-cicd-content-with-title-container">
<h2>{{$ctrl.title}}</h2>
<pf-toolbar class="entaxy-toolbar" config="$ctrl.toolbarConfig">
<actions>
<span class="dropdown primary-action" uib-dropdown>
<button class="dropdown-toggle" uib-dropdown-toggle type="button">
Add Version
<span class="caret"></span>
</button>
<ul class="dropdown-menu">
<li role="menuitem" ng-click="$ctrl.addVersionFromScratch()">
<a class="secondary-action">Add Version From Scratch</a>
</li>
<li role="menuitem" ng-click="$ctrl.addVersionFromExistent()">
<a class="secondary-action">Add Version From Existent</a>
</li>
</ul>
</span>
</actions>
</pf-toolbar>
<pf-table-view class="entaxy-cicd-table"
config="$ctrl.tableConfig"
columns="$ctrl.tableColumns"
action-buttons="$ctrl.tableActionButtons"
page-config="$ctrl.pageConfig"
items="$ctrl.viewedItems">
</pf-table-view>
</div>
`,
controller: entaxyCICDProjectVersionsController
})
.name;
function entaxyCICDProjectVersionsController($scope, workspace, entaxyCICDService, $uibModal, $templateCache,
$location) {
'ngInject';
let ctrl = this;
ctrl.tableConfig = {
selectionMatchProp: 'name',
showCheckboxes: false
};
ctrl.toolbarConfig = {
filterConfig: {
fields: [
{
id: 'name',
title: 'Name',
placeholder: 'Filter by Name...',
filterType: 'text'
},
{
id: 'isBuilt',
title: 'Build Available',
placeholder: 'Filter by Built Availability...',
filterType: 'select',
filterValues: ['yes', 'no']
}
],
appliedFilters: [],
onFilterChange: filterChange
},
actionsConfig: {
actionsInclude: true
},
isTableView: true
};
ctrl.tableColumns = [
{
header: 'Name',
itemField: 'name',
htmlTemplate: 'project/version/name.html',
colActionFn: (name) => ctrl.changeLocation(name)
},
{ header: 'Build Available', itemField: 'isBuilt',
templateFn: (value) => EntaxyCICD.getStatusTemplate(value) }
];
$templateCache.put(
'project/version/name.html',
'<a href="" ng-click="$ctrl.handleColAction(key, value)">{{value}}</a>'
);
ctrl.changeLocation = function (name) {
let nid = $location.search().nid;
$location.search('nid', nid + '-' + 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;
} else if (filter.id === 'isBuilt') {
match = filter.value === 'yes' ? item.isBuilt === true : item.isBuilt === false;
}
return match;
};
ctrl.$onInit = function() {
ctrl.storage = EntaxyCICD.getStorage(workspace.selection);
ctrl.project = workspace.selection.title;
ctrl.title = 'Versions';
ctrl.tableActionButtons = [
{ name: 'Remove', title: 'Remove Version', actionFn: removeVersion }
];
populateTable();
}
ctrl.items = [];
ctrl.viewedItems = [];
function populateTable() {
let selectedProject = workspace.selection;
if (selectedProject.children && selectedProject.children.length > 0) {
let versions = [];
selectedProject.children.forEach(version => {
versions.push({
name: version.title,
isBuilt: version.children && version.children.length === 1 ? true : false
});
});
ctrl.items = versions;
filterChange(ctrl.toolbarConfig.filterConfig.appliedFilters);
}
}
function getFormFields() {
return [
{
label: 'Created Version',
name: 'createdVersion',
type: 'text',
required: true,
validation: {
checkUniqueness: true,
values: ctrl.items.map(version => version.name),
content: {
regex: '^([1-9][0-9]*|0)\\.([1-9][0-9]*|0)\\.([1-9][0-9]*|0)$',
errorMessage: 'Value must match the pattern: X.X.X, where X represents a number'
}
},
setFocused: true
}
];
}
ctrl.addVersionFromScratch = function () {
openCreateVersionModal(getFormFields());
}
ctrl.addVersionFromExistent = function () {
let formFields = getFormFields();
formFields.push({
label: 'Prototype Version',
name: 'prototypeVersion',
enum: true,
required: true,
values: ctrl.items.map(version => version.name)
});
openCreateVersionModal(formFields);
}
function openCreateVersionModal(formFields) {
$uibModal.open({
component: 'entaxyCiCdSimpleFieldsModal',
resolve: {
modalTitle: () => 'Create Version',
formFields: () => formFields
},
backdrop: 'static'
}).result.then((args) => {
createVersion(...args);
}, reason => {
if (reason && reason !== Entaxy.MODAL_CANCEL_REASON.ESCAPE_KEY_PRESS) {
Entaxy.notificationError(reason);
}
});
}
function createVersion(createdVersion, prototypeVersion) {
entaxyCICDService.executeOperation('createVersion',
[ctrl.storage, ctrl.project, createdVersion, prototypeVersion])
.then(result => {
Entaxy.notificationSuccess(result);
entaxyCICDService.treeUpdated();
}).catch(error => {
Entaxy.notificationError(error);
EntaxyCICD.log.error(error);
});
}
function removeVersion(action, item) {
let properties = [ctrl.storage, ctrl.project, item.name];
entaxyCICDService.removeItemWithConfirmation(EntaxyCICD.ITEM_TYPE.VERSION, item.name, properties);
}
}
entaxyCICDProjectVersionsController.$inject = ['$scope', 'workspace', 'entaxyCICDService', '$uibModal',
'$templateCache', '$location'];
})(EntaxyCICD || (EntaxyCICD = {}));

View File

@@ -0,0 +1,153 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-cicd-plugin
* ==========
* Copyright (C) 2020 - 2025 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 EntaxyCICD;
(function (EntaxyCICD) {
EntaxyCICD._module.component('entaxyCiCdRequirements', {
bindings: {
version: '<',
type: '@'
},
template:
`
<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: EntaxyCICDRequirementsController
})
.name;
function EntaxyCICDRequirementsController(workspace, $scope, $uibModal, entaxyCICDService) {
'ngInject';
let ctrl = this;
ctrl.tableConfig = {
selectionMatchProp: 'id',
showCheckboxes: false
};
ctrl.toolbarConfig = {
filterConfig: {
fields: [
{
id: 'id',
title: 'Id',
placeholder: 'Filter by Id...',
filterType: 'text'
},
{
id: 'type',
title: 'Type',
placeholder: 'Filter by Type...',
filterType: 'select',
filterValues: []
},
{
id: 'scope',
title: 'Scope',
placeholder: 'Filter by Scope...',
filterType: 'select',
filterValues: []
},
{
id: 'status',
title: 'Status',
placeholder: 'Filter by Status...',
filterType: 'select',
filterValues: ['yes', 'no']
}
],
inlineResults: true,
appliedFilters: [],
onFilterChange: filterChange
},
isTableView: true
};
ctrl.tableColumns = [
{ header: 'Id', itemField: 'id' },
{ header: 'Type', itemField: 'type' },
{ header: 'Scope', itemField: 'scope' },
{ header: 'Status', itemField: 'status', templateFn: (value) => EntaxyCICD.getStatusTemplate(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) {
let match = true;
if (filter.id === 'id') {
match = item.id.toLowerCase().match(filter.value.toLowerCase()) !== null;
} else if (filter.id === 'type') {
match = item.type === filter.value;
} else if (filter.id === 'scope') {
match = item.scope === filter.value;
} else if (filter.id === 'status') {
match = filter.value === 'yes' ? item.status === true : item.status === false;
}
return match;
};
ctrl.items = [];
ctrl.viewedItems = [];
ctrl.$onInit = function() {
entaxyCICDService.setTypesToFilterConfig(ctrl.toolbarConfig.filterConfig.fields);
entaxyCICDService.setScopesToFilterConfig(ctrl.toolbarConfig.filterConfig.fields);
}
$scope.$watch('$ctrl.version', function () {
populateTable();
});
function populateTable() {
const storage = EntaxyCICD.getStorage(workspace.selection);
const application = EntaxyCICD.getProjectOrApplication(workspace.selection);
let operationName = 'list' + ctrl.type + 'Requirements';
entaxyCICDService.executeOperation(operationName, [storage, application, ctrl.version])
.then(result => {
let items = JSON.parse(result);
ctrl.items = items;
filterChange(ctrl.toolbarConfig.filterConfig.appliedFilters);
});
}
}
EntaxyCICDRequirementsController.$inject = ['workspace', '$scope', '$uibModal', 'entaxyCICDService'];
})(EntaxyCICD || (EntaxyCICD = {}));

View File

@@ -0,0 +1,147 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-management-plugin
* ==========
* Copyright (C) 2020 - 2025 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 EntaxyCICD;
(function (EntaxyCICD) {
EntaxyCICD._module.component('entaxyCiCdSimpleFieldsModal', {
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.resource" set-focused="formField.setFocused">
<entaxy-select-from-enum id="{{formField.name}}" values="formField.values"
model="formField.value" readonly="formField.readOnly" is-empty-included="false"
ng-if="formField.enum" set-focused="formField.setFocused"></entaxy-select-from-enum>
<entaxy-resource-input id="{{formField.name}}" name="{{formField.name}}" model="formField.value"
ng-if="formField.resource"></entaxy-resource-input>
<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: entaxyCICDSimpleFieldsModalController
})
.name;
function entaxyCICDSimpleFieldsModalController($scope, $uibModal, entaxyService, entaxyHotkeysService) {
'ngInject';
let ctrl = this;
ctrl.$onInit = function() {
entaxyHotkeysService.setHotkeys($scope, getHotkeysConfigs());
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.required && (formField.value === undefined ||
(!formField.resource && formField.value.trim().length === 0))) {
errors[formField.name] = Entaxy.ERROR_MESSAGE.EMPTY;
}
if (!errors[formField.name] && formField.validation) {
let validation = { ...formField.validation };
delete validation.checkUniqueness;
delete validation.values;
entaxyService.validateByRules(formField, validation, errors);
}
if (!errors[formField.name] && formField.validation && formField.validation.checkUniqueness
&& formField.validation.values.includes(formField.value)) {
errors[formField.name] = Entaxy.ERROR_MESSAGE.UNIQUE;
}
});
return errors;
}
function getHotkeysConfigs() {
return [
{
...Entaxy.getSaveHotkeyDescription(),
callback: function (event) {
event.preventDefault();
ctrl.save();
}
}
];
}
}
entaxyCICDSimpleFieldsModalController.$inject = ['$scope', '$uibModal', 'entaxyService', 'entaxyHotkeysService'];
})(EntaxyCICD || (EntaxyCICD = {}));

View File

@@ -0,0 +1,263 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-cicd-plugin
* ==========
* Copyright (C) 2020 - 2025 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 EntaxyCICD;
(function (EntaxyCICD) {
EntaxyCICD._module.component('entaxyCiCdTreeHeader', {
template:
`
<div class="tree-nav-sidebar-header">
<form role="form" class="search-pf has-button">
<div class="form-group has-clear">
<div class="search-pf-input-group">
<label for="input-search" class="sr-only">Search Tree:</label>
<input id="input-search" type="search" class="form-control" placeholder="Search tree:"
ng-model="$ctrl.filter">
<button type="button" class="clear" aria-hidden="true"
ng-hide="$ctrl.filter.length === 0"
ng-click="$ctrl.filter = ''">
<span class="pficon pficon-close"></span>
</button>
</div>
</div>
<div class="form-group tree-nav-buttons">
<span class="badge" ng-class="{positive: $ctrl.result.length > 0}"
ng-show="$ctrl.filter.length > 0">
{{$ctrl.result.length}}
</span>
<i class="fa fa-plus-square-o" title="Expand All" ng-click="$ctrl.expandAll()"></i>
<i class="fa fa-minus-square-o" title="Collapse All" ng-click="$ctrl.contractAll()"></i>
</div>
</form>
</div>
`,
controller: EntaxyCICDTreeHeaderController
}).component('entaxyCiCdTree', {
template:
`
<div class="tree-nav-sidebar-content">
<div id="entaxycicdtree" class="treeview-pf-hover treeview-pf-select"></div>
</div>
`,
controller: EntaxyCICDTreeController
})
.name;
entaxyCICDTreeElementId = '#entaxycicdtree';
EntaxyCICD.log.debug("loaded tree" + EntaxyCICD.treeModule);
function EntaxyCICDTreeHeaderController($scope, $element) {
'ngInject';
EntaxyCICD.log.debug("EntaxyCICDTreeHeaderController ");
this.$scope = $scope;
this.$element = $element;
this.filter = '';
this.result = [];
// it's not possible to declare classes to the component host tag in AngularJS
$element.addClass('tree-nav-sidebar-header');
EntaxyCICDTreeHeaderController.prototype.$onInit = function () {
EntaxyCICD.log.debug("EntaxyCICDTreeHeaderController init");
var _this = this;
this.$scope.$watch(angular.bind(this, function () { return _this.filter; }), function (filter, previous) {
if (filter !== previous) {
_this.search(filter);
}
});
};
EntaxyCICDTreeHeaderController.prototype.search = function (filter) {
EntaxyCICD.log.debug("EntaxyCICDTreeHeaderController search");
var _this = this;
var doSearch = function (filter) {
var result = _this.tree().search(filter, {
ignoreCase: true,
exactMatch: false,
revealResults: true
});
_this.result.length = 0;
(_a = _this.result).push.apply(_a, result);
Core.$apply(_this.$scope);
var _a;
};
_.debounce(doSearch, 300, { leading: false, trailing: true })(filter);
};
EntaxyCICDTreeHeaderController.prototype.tree = function () {
EntaxyCICD.log.debug("EntaxyCICDTreeHeaderController tree");
return $(entaxyCICDTreeElementId).treeview(true);
};
EntaxyCICDTreeHeaderController.prototype.expandAll = function () {
EntaxyCICD.log.debug("EntaxyCICDTreeHeaderController expand");
return this.tree()
.expandNode(this.tree().getNodes(), { levels: HawtioTree.getMaxTreeLevel(this.tree()), silent: true });
};
EntaxyCICDTreeHeaderController.prototype.contractAll = function () {
EntaxyCICD.log.debug("EntaxyCICDTreeHeaderController contract");
return this.tree()
.collapseNode(this.tree().getNodes(), { ignoreChildren: true, silent: true });
};
}
EntaxyCICDTreeHeaderController.$inject = ['$scope', '$element'];
function EntaxyCICDTreeController($scope, $location, workspace, $element, operationsService, $q) {
'ngInject';
this.$scope = $scope;
this.$location = $location;
this.workspace = workspace;
this.$element = $element;
// it's not possible to declare classes to the component host tag in AngularJS
$element.addClass('tree-nav-sidebar-content');
EntaxyCICD.log.debug("EntaxyCICDTreeController ");
var entaxyCICDJmxDomain = localStorage['entaxyCICDJmxDomain'] || "ru.entaxy.cicd";
EntaxyCICDTreeController.prototype.$onInit = function () {
EntaxyCICD.log.debug("EntaxyCICDTreeController onInit");
var _this = this;
this.$scope.$on('$destroy', function () { return _this.removeTree(); });
this.$scope.$on('$routeChangeStart', function () {
return Jmx.updateTreeSelectionFromURL(_this.$location, $(entaxyCICDTreeElementId));
});
this.$scope.$on('jmxTreeUpdated', function (event, opts) {
let updateSelectionNode = opts ? opts.updateSelectionNode : false;
return _this.populateTree(updateSelectionNode);
});
this.populateTree();
};
EntaxyCICDTreeController.prototype.updateSelectionFromURL = function () {
Jmx.updateTreeSelectionFromURLAndAutoSelect(this.$location, $(entaxyCICDTreeElementId), null, true);
};
EntaxyCICDTreeController.prototype.populateTree = function (updateSelectionNode) {
let tree = this.workspace.tree;
if (tree) {
let domain = tree.get(entaxyCICDJmxDomain);
if (domain && domain.children && domain.children.length > 0) {
let promises = [];
domain.children.forEach(child => {
child.class = createClassName(child.title);
promises.push(
operationsService.executeOperation(child.objectName, {name: 'readAsTree'}, [])
.then(result => {
let nodes = JSON.parse(result);
let folderNames = child.key.split('-');
folderNames.shift();
let cicdTree = createTree(nodes, child.key, folderNames);
cicdTree.forEach(cicdChild => {
cicdChild.parent = child;
});
child.children = cicdTree;
})
);
});
$q.all(promises).then(() => {
this.removeTree();
Jmx.enableTree(this.$scope, this.$location, this.workspace,
$(entaxyCICDTreeElementId), domain.children);
this.updateSelectionFromURL();
if (updateSelectionNode) {
workspace.updateSelectionNode(workspace.selection);
}
});
}
}
};
function createTree(children, keyPrefix, folderNames) {
let folders = [];
if (children && children.length > 0) {
children.forEach(child => {
let folder = new Jmx.Folder(child.title);
let index = child.title.indexOf('[');
if (index > 0) {
folder.key = keyPrefix + '-' + child.title.slice(0, index - 1).toLowerCase();
} else {
folder.key = keyPrefix + '-' + child.title.toLowerCase();
}
let folderNamesCopy = folderNames.map(folderName => folderName);
folderNamesCopy.push(index > 0 ? child.title.slice(0, index - 1) : child.title);
folder.folderNames = folderNamesCopy;
addClass(folder);
folder.tooltip = folder.title;
folder.domain = entaxyCICDJmxDomain;
folder.children = createTree(child.children, folder.key, folderNamesCopy);
if (folder.children && folder.children.length > 0) {
folder.children.forEach(child => {
child.parent = folder;
})
}
folder.sortChildren();
folders.push(folder);
});
}
return folders;
}
function addClass(folder) {
switch (folder.folderNames.length) {
case 3:
folder.class = createClassName('storages');
break;
case 4:
folder.class = createClassName(folder.folderNames[1]);
break;
case 5:
folder.class = createClassName('versions');
break;
case 6:
folder.class = createClassName(folder.folderNames[1] === 'applications' ?
'revisions' : 'build-info');
break;
}
}
function createClassName(folderName) {
return 'entaxy-cicd-' + folderName + '-icon';
}
EntaxyCICDTreeController.prototype.removeTree = function () {
var tree = $(entaxyCICDTreeElementId).treeview(true);
// There is no exposed API to check whether the tree has already been initialized,
// so let's just check if the methods are present
if (tree.clearSearch) {
tree.clearSearch();
// Bootstrap tree view leaks the node elements into the data structure
// so let's clean this up when the user leaves the view
var cleanTreeFolder_1 = function (node) {
delete node['$el'];
if (node.nodes)
node.nodes.forEach(cleanTreeFolder_1);
};
cleanTreeFolder_1(this.workspace.tree);
// Then call the tree clean-up method
tree.remove();
}
}
}
EntaxyCICDTreeController.$inject = ['$scope', '$location', 'workspace', '$element', 'operationsService', '$q'];
})(EntaxyCICD || (EntaxyCICD = {}));

View File

@@ -0,0 +1,155 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-cicd-plugin
* ==========
* Copyright (C) 2020 - 2025 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 EntaxyCICD;
(function (EntaxyCICD) {
const REVISION_STATUS = {
CONFIGURED: 'CONFIGURED',
DEPLOYED: 'DEPLOYED',
INSTALLED: 'INSTALLED',
UNINSTALLED: 'UNINSTALLED'
}
EntaxyCICD.REVISION_STATUS = REVISION_STATUS;
const ITEM_TYPE = {
APPLICATION: 'Application',
PROJECT: 'Project',
VERSION: 'Version'
}
EntaxyCICD.ITEM_TYPE = ITEM_TYPE;
function isStorage(selection) {
return selection.folderNames && selection.folderNames.length === 3;
}
EntaxyCICD.isStorage = isStorage;
function getStorage(selection) {
if (selection.folderNames) {
switch (selection.folderNames.length) {
case 3:
return selection.title;
case 4:
return selection.parent.title;
case 5:
return selection.parent.parent.title;
case 6:
return selection.parent.parent.parent.title;
}
}
}
EntaxyCICD.getStorage = getStorage;
function getStorages(selection) {
return selection.children && selection.children.length > 0 ? selection.children.map(child => child.title) : [];
}
EntaxyCICD.getStorages = getStorages;
function getProjectOrApplication(selection) {
if (selection.folderNames) {
switch (selection.folderNames.length) {
case 4:
return selection.title;
case 5:
return selection.parent.title;
case 6:
return selection.parent.parent.title;
}
}
}
EntaxyCICD.getProjectOrApplication = getProjectOrApplication;
function isVersion(selection) {
return selection.folderNames && selection.folderNames.length === 5;
}
EntaxyCICD.isVersion = isVersion;
function getVersion(selection) {
if (selection.folderNames) {
switch (selection.folderNames.length) {
case 5:
return selection.title;
case 6:
return selection.parent.title;
}
}
}
EntaxyCICD.getVersion = getVersion;
function getVersions(selection) {
return selection.children && selection.children.length > 0 ? selection.children.map(child => child.title) : [];
}
EntaxyCICD.getVersions = getVersions;
function isRevision(selection) {
return selection.folderNames && selection.folderNames.length === 6;
}
EntaxyCICD.isRevision = isRevision;
function getRevisionInfo(selection) {
let splitTitle = selection.title.split(' ');
return {
revision: splitTitle[0],
revisionStatus: splitTitle[1].replace(/\[|]/g, '')
};
}
EntaxyCICD.getRevisionInfo = getRevisionInfo;
function getStatusTemplate(value) {
if (value) {
return '<span class="pficon pficon-ok"></span>'
} else {
return '<span class="pficon pficon-error-circle-o blue"></span>';
}
}
EntaxyCICD.getStatusTemplate = getStatusTemplate;
function capitalize(string) {
return string.charAt(0).toUpperCase() + string.slice(1);
}
EntaxyCICD.capitalize = capitalize;
function createTableFromUnremovedItems(unremovedItemsInfo) {
let tableHtml = `<table class="entaxy-cicd-unremoved-info-table">`;
tableHtml += `
<tr>
<th>Item</th>
<th>Required By</th>
</tr>
`;
Object.entries(unremovedItemsInfo).forEach(([itemId, listRequiredBy]) => {
tableHtml += `<tr><td>` + itemId + `</td><td>`;
listRequiredBy.forEach(requiredBy => {
tableHtml += requiredBy + '\n';
});
tableHtml += `</td></tr>`;
});
tableHtml += `</table>`;
return tableHtml;
}
EntaxyCICD.createTableFromUnremovedItems = createTableFromUnremovedItems;
})(EntaxyCICD || (EntaxyCICD = {}));

View File

@@ -0,0 +1,93 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-management-plugin
* ==========
* Copyright (C) 2020 - 2025 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~~~~~~
*/
/**
* The main entry point for the Simple module
*/
var EntaxyCICD = (function (EntaxyCICD) {
/**
* The name of this plugin
*/
EntaxyCICD.pluginName = 'entaxy-cicd';
/**
* This plugin's logger instance
*/
EntaxyCICD.log = Logger.get('entaxy-cicd');
/**
* The top level path of this plugin on the server
*/
EntaxyCICD.contextPath = "/entaxy-cicd/";
EntaxyCICD.log.info("loading entaxy cicd plugin")
EntaxyCICD._module = angular.module(EntaxyCICD.pluginName, [
'angularResizable'
])
.component('entaxyCiCd', {
template:
`
<div class="tree-nav-layout">
<div class="sidebar-pf sidebar-pf-left" resizable r-directions="['right']">
<entaxy-ci-cd-tree-header></entaxy-ci-cd-tree-header>
<entaxy-ci-cd-tree></entaxy-ci-cd-tree>
</div>
<div class="tree-nav-main">
<entaxy-ci-cd-navigation></entaxy-ci-cd-navigation>
<entaxy-ci-cd-contents></entaxy-ci-cd-contents>
</div>
</div>
`
})
.run(configurePlugin);
function configurePlugin(mainNavService, workspace, helpRegistry, preferencesRegistry, localStorage) {
var entaxyCICDJmxDomain = localStorage['entaxyCICDJmxDomain'] || "ru.entaxy.cicd";
mainNavService.addItem({
title: 'Entaxy CI/CD',
basePath: '/entaxy-cicd',
template: '<entaxy-ci-cd></entaxy-ci-cd>',
isValid: function () { return workspace.treeContainsDomainAndProperties(entaxyCICDJmxDomain); },
rank: 2
});
// clean up local storage upon logout
/* preLogoutTasks.addTask('CleanupArtemisCredentials', function () {
Artemis.log.debug("Clean up Artemis credentials in local storage");
localStorage.removeItem('artemisUserName');
localStorage.removeItem('artemisPassword');
}); */
}
configurePlugin.$inject = ['mainNavService', 'workspace', 'helpRegistry', 'preferencesRegistry', 'localStorage'];
return EntaxyCICD;
})(EntaxyCICD || {});
// tell the Hawtio plugin loader about our plugin so it can be
// bootstrapped with the rest of AngularJS
hawtioPluginLoader.addModule(EntaxyCICD.pluginName);

View File

@@ -0,0 +1,125 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-cicd-plugin
* ==========
* Copyright (C) 2020 - 2025 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 EntaxyCICD;
(function (EntaxyCICD) {
EntaxyCICD._module.factory('entaxyCICDService', ['$q', 'workspace', 'jolokia', 'jolokiaService', 'operationsService',
'$uibModal', 'entaxyService',
function($q, workspace, jolokia, jolokiaService, operationsService, $uibModal, entaxyService) {
const entaxyCICDJmxDomain = localStorage['entaxyCICDJmxDomain'] || "ru.entaxy.cicd";
return {
executeOperation: function (operationName, properties) {
return executeOperation(operationName, properties);
},
treeUpdated: function () {
return treeUpdated();
},
setTypesToFilterConfig: function (filterFields) {
return setValuesToFilterConfig(filterFields, 'type', 'readApplicationItemTypes');
},
setScopesToFilterConfig: function (filterFields) {
return setValuesToFilterConfig(filterFields, 'scope', 'readApplicationItemScopes');
},
removeItemWithConfirmation: function (itemType, itemName, properties, updateSelectionNode, message) {
return removeItemWithConfirmation(itemType, itemName, properties, updateSelectionNode, message);
}
};
function executeOperation(operationName, properties) {
let mbeanName = getCICDMBeanName();
let operation = { name : operationName };
if (mbeanName) {
return operationsService.executeOperation(mbeanName, operation, properties);
} else {
return $q.reject("Cannot find mbean for CI/CD");
}
}
function treeUpdated () {
let rootScope = workspace.$rootScope;
if (rootScope) {
Core.$apply(rootScope);
rootScope.$broadcast(Jmx.TreeEvent.Updated, { updateSelectionNode: true });
}
}
function setValuesToFilterConfig(filterFields, fieldId, operationName) {
let mbean = workspace.findMBeanWithProperties(entaxyCICDJmxDomain, { module: 'applications' });
let operation = { name: operationName };
operationsService.executeOperation(mbean.objectName, operation, [])
.then(result => {
let toolbarConfigTypeField = filterFields.find(field => field.id === fieldId);
toolbarConfigTypeField.filterValues = JSON.parse(result);
});
}
function removeItemWithConfirmation(itemType, itemName, properties, updateSelectionNode, message) {
let title = 'Confirm Removing';
if (!message) {
message = 'Do you want to remove the ' + itemType.toLowerCase() + ' ' + itemName + '?';
}
entaxyService.openConfirmationWindow(title, message).then(() => {
executeOperation('remove' + itemType, properties)
.then(result => {
Entaxy.notificationSuccess(result);
if (updateSelectionNode) {
treeUpdated();
} else {
workspace.jmxTreeUpdated();
}
})
.catch(error => {
Entaxy.notificationError(error);
EntaxyCICD.log.error(error);
});
});
}
function getCICDMBeanName() {
if (!workspace.hasDomainAndProperties(entaxyCICDJmxDomain)) {
return;
}
let tree = workspace.tree;
if (tree) {
let domain = tree.get(entaxyCICDJmxDomain);
if (domain && domain.children) {
for (let i = 0; i < domain.children.length; i++) {
if (domain.children[i].folderNames[1] === workspace.selection.folderNames[1]) {
return domain.children[i].objectName;
}
}
}
}
}
}
])
})(EntaxyCICD || (EntaxyCICD = {}));