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

@ -3,7 +3,7 @@
<parent>
<groupId>ru.entaxy.esb.ui</groupId>
<artifactId>entaxy-hawtio</artifactId>
<version>1.10.0</version>
<version>1.11.0</version>
</parent>
<groupId>ru.entaxy.esb.ui.hawtio</groupId>
<artifactId>artemis-plugin-entaxy</artifactId>

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* artemis-plugin-entaxy
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* 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

View File

@ -3,7 +3,7 @@
~~~~~~licensing~~~~~~
artemis-plugin-entaxy
==========
Copyright (C) 2020 - 2024 EmDev LLC
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

View File

@ -2,7 +2,7 @@
# ~~~~~~licensing~~~~~~
# artemis-plugin-entaxy
# ==========
# Copyright (C) 2020 - 2024 EmDev LLC
# 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

View File

@ -20,7 +20,7 @@
~~~~~~licensing~~~~~~
artemis-plugin-entaxy
==========
Copyright (C) 2020 - 2024 EmDev LLC
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

View File

@ -2,7 +2,7 @@
~~~~~~licensing~~~~~~
artemis-plugin-entaxy
==========
Copyright (C) 2020 - 2024 EmDev LLC
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

View File

@ -2,7 +2,7 @@
~~~~~~licensing~~~~~~
artemis-plugin-entaxy
==========
Copyright (C) 2020 - 2024 EmDev LLC
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

View File

@ -2,7 +2,7 @@
~~~~~~licensing~~~~~~
artemis-plugin-entaxy
==========
Copyright (C) 2020 - 2024 EmDev LLC
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

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* artemis-plugin-entaxy
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* 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

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* artemis-plugin-entaxy
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* 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

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* artemis-plugin-entaxy
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* 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

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* artemis-plugin-entaxy
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* 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

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* artemis-plugin-entaxy
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* 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

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* artemis-plugin-entaxy
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* 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

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* artemis-plugin-entaxy
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* 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

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* artemis-plugin-entaxy
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* 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

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* artemis-plugin-entaxy
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* 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

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* artemis-plugin-entaxy
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* 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

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* artemis-plugin-entaxy
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* 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

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* artemis-plugin-entaxy
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* 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

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* artemis-plugin-entaxy
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* 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

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* artemis-plugin-entaxy
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* 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

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* artemis-plugin-entaxy
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* 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

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* artemis-plugin-entaxy
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* 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

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* artemis-plugin-entaxy
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* 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

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* artemis-plugin-entaxy
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* 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

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* artemis-plugin-entaxy
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* 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

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* artemis-plugin-entaxy
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* 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

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* artemis-plugin-entaxy
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* 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

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* artemis-plugin-entaxy
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* 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

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* artemis-plugin-entaxy
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* 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

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* artemis-plugin-entaxy
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* 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

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* artemis-plugin-entaxy
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* 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

View File

@ -3,7 +3,7 @@
<parent>
<groupId>ru.entaxy.esb.ui</groupId>
<artifactId>entaxy-hawtio</artifactId>
<version>1.10.0</version>
<version>1.11.0</version>
</parent>
<groupId>ru.entaxy.esb.ui.hawtio</groupId>
<artifactId>entaxy-branding-plugin</artifactId>

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* entaxy-branding-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* 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

View File

@ -3,7 +3,7 @@
~~~~~~licensing~~~~~~
entaxy-branding-plugin
==========
Copyright (C) 2020 - 2024 EmDev LLC
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

View File

@ -3,7 +3,7 @@
~~~~~~licensing~~~~~~
entaxy-branding-plugin
==========
Copyright (C) 2020 - 2024 EmDev LLC
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

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* entaxy-branding-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* 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
@ -147,6 +147,10 @@ entaxy-header .pficon.pficon-info:hover {
background: url("../img/icons/cranberry-red/entaxy-route-libraries-icon.png");
}
.entaxy-data-management-icon span.node-icon::before {
background: url("../img/icons/cranberry-red/entaxy-data-management-icon.png");
}
.entaxy-cicd-projects-icon span.node-icon::before {
background: url("../img/icons/cicd/entaxy-cicd-projects-icon.png");
}
@ -195,6 +199,7 @@ entaxy-header .pficon.pficon-info:hover {
.entaxy-search-icon span.node-icon::before,
.entaxy-route-libraries-icon span.node-icon::before,
.entaxy-route-component-libraries-icon span.node-icon::before,
.entaxy-data-management-icon span.node-icon::before,
.entaxy-cicd-projects-icon span.node-icon::before,
.entaxy-cicd-applications-icon span.node-icon::before,
@ -401,9 +406,11 @@ svg text {
.btn-primary.active.focus,
.btn-primary.active:focus,
.btn-primary.active:hover, .btn-primary:active.focus,
.btn-primary.active:hover,
.btn-primary:active.focus,
.btn-primary:active:focus,
.btn-primary:active:hover,
.open .dropdown-toggle.btn-primary,
.open .dropdown-toggle.btn-primary.focus,
.open .dropdown-toggle.btn-primary:focus,
.open .dropdown-toggle.btn-primary:hover {
@ -411,6 +418,10 @@ svg text {
border-color: #B21054;
}
.btn-primary .caret:before {
color: #fff;
}
/*These change the row in a table when hovered over*/
.table-hover>tbody>tr:hover {
background-color: #DF667Bb3;
@ -528,6 +539,16 @@ table.dataTable thead .sorting_asc:before, table.dataTable thead .sorting_desc:b
min-width: 900px;
}
.modal-xxl {
width: 90%;
min-width: 900px;
}
.modal-body-without-header iframe {
width: 100%;
margin: 0;
}
.modal-body-header {
height: 70px;
max-height: 70px;
@ -865,6 +886,20 @@ table.dataTable thead .sorting_asc:before, table.dataTable thead .sorting_desc:b
outline: none;
}
.form-group .extra-actions {
padding-left: 0px;
padding-top: 4px;
margin-left: -10px;
}
.form-group .extra-actions .reset-button {
cursor: pointer;
}
.form-group .extra-actions .reset-button:hover {
color: #DF667B;
}
/*These are for custom forms*/
.entaxy-xml-form {
@ -872,8 +907,37 @@ table.dataTable thead .sorting_asc:before, table.dataTable thead .sorting_desc:b
height: 26px;
}
button[disabled].entaxy-xml-form {
button.btn-std,
.has-error button.btn-std.btn-std-ignore-error {
background-color: #efefef;
border: 1px solid #767676;
border-radius: 2px;
padding: 2px 7px;
}
button.btn-std:hover,
.has-error button.btn-std.btn-std-ignore-error:hover {
background-color: #dfdfdf;
border-color: #535353;
}
.has-error button.btn-std {
background-color: #f3dede;
border: 1px solid #c00;
border-radius: 2px;
padding: 2px 7px;
}
.has-error button.btn-std:hover {
background-color: #f1cece;
border-color: #900;
}
button[disabled].btn-std,
button[disabled].btn-std:hover {
background-color: #efefef;
color: #8b8d8f;
border-color: #d1d1d1;
}
.input-with-button,
@ -1055,11 +1119,45 @@ select.form-control {
}
.modal-resources-viewer-container {
padding: 10px;
padding: 10px 0;
height: inherit;
}
.modal-resources-viewer-container .modal-resources-viewer-header-container {
padding: 0 10px;
}
.modal-resources-viewer-container .file-panel {
height: calc(100% - 17px);
overflow: hidden auto;
padding-right: 0 !important;
padding-left: 5px;
padding-bottom: 20px;
}
.modal-resources-viewer-header-container {
display: flex;
flex-direction: column;
-webkit-flex-direction: column;
}
.modal-resources-viewer-header-container .provider-selector {
display: flex;
}
.modal-resources-viewer-header-container .provider-selector > span {
font-size: 13.5px;
margin-top: 2px;
margin-right: 10px;
}
.modal-resources-viewer-header-container .provider-selector > select {
width: 180px;
margin-bottom: 5px;
}
.modal-resources-viewer-header-container .navigation-creation {
display: flex;
}
.modal-resources-viewer-header-container entaxy-crumbs {
@ -1070,6 +1168,44 @@ entaxy-resource-viewer-modal .modal-body-without-header {
margin-top: 0 !important;
}
.modal-body-without-header.entaxy-resource-save-mode {
height: calc(100vh - 256px);
max-height: calc(100vh - 256px);
}
.modal-footer.entaxy-resource-save-mode {
display: flex;
}
.modal-footer.entaxy-resource-save-mode .entaxy-resource-save-mode-labelled-field-container {
display: flex;
width: 100%;
margin-right: 20px
}
.modal-footer.entaxy-resource-save-mode .entaxy-resource-save-mode-field-container {
display: flex;
flex-direction: column;
width: 100%;
height: 52px;
margin-right: 20px;
}
.modal-footer.entaxy-resource-save-mode .entaxy-resource-save-mode-field-container entaxy-input-with-extension {
width: 100%;
margin-left: 20px;
}
.modal-footer.entaxy-resource-save-mode span.help-block {
text-align: left;
margin-left: 20px;
}
.modal-footer.entaxy-resource-save-mode .btn {
height: 26px;
align-self: end;
}
/* css for resource loading ui */
.highlighted {
@ -1173,6 +1309,7 @@ entaxy-resource-viewer-modal .modal-body-without-header {
.file-panel .tile {
width: 100px;
height: fit-content;
display: flex;
flex-direction: column;
-webkit-flex-direction: column;
@ -1238,6 +1375,8 @@ entaxy-resource-viewer-modal .modal-body-without-header {
display: flex;
flex-direction: row;
-webkit-flex-direction: row;
flex-wrap: wrap;
-webkit-flex-wrap: wrap;
color: #535353;
cursor: pointer;
margin-bottom: 5px;
@ -1823,10 +1962,14 @@ entaxy-connectors-with-flow {
background-color: #D2D2D2;
}
.out-flow-customization-points-container {
.out-flow-customization-points-container,
.custom-connector-customization-points-container {
display: flex;
justify-content: space-between;
width: 150px;
}
.custom-connector-customization-points-container .customization-point-block {
width: 90px !important;
}
.customization-point-block.connector-selector {
@ -1850,11 +1993,13 @@ entaxy-connectors-with-flow {
margin-bottom: 1px;
}
.connector-block .customization-point-block {
.connector-block .customization-point-block,
.custom-connector-customization-points-container {
width: 200px;
}
.flow-block .customization-point-block {
.flow-block .customization-point-block,
.out-flow-customization-points-container {
width: 150px;
}
@ -2552,7 +2697,7 @@ entaxy-ci-cd-configurations .entaxy-cicd-objects-table-container {
}
.entaxy-cicd-table .pficon-arrow:before,
.entaxy-cicd-table .pficon-error-circle-o:before {
.entaxy-cicd-table .pficon-error-circle-o.blue:before {
color: #0000ff;
}
@ -2587,6 +2732,65 @@ entaxy-ci-cd-add-objects-modal entaxy-expandable-list .list-view-pf .list-group-
border-top: 1px solid #d1d1d1;
}
/* atlasmap console */
.entaxy-atlasmap-console {
width: calc(100% + 52px);
height: 100%;
margin: 0 -20px -6px -32px;
overflow: scroll;
border: none;
}
/* atlasmap console modal */
.modal-body-without-header.entaxy-atlasmap-console-modal {
margin: 0;
height: calc(100vh - 170px);
max-height: calc(100vh - 170px);
}
.modal-body-without-header.entaxy-atlasmap-console-modal .entaxy-atlasmap-console-container {
height: 100%;
}
/* atlasmap create instance modal, create resource modal */
.entaxy-resource-editor-container,
.entaxy-create-resource-fields-container {
padding: 0 20px 10px 20px;
}
.entaxy-create-resource-fields-container .entaxy-create-resource-name-field-container {
display: flex;
margin-bottom: 10px;
}
.entaxy-create-resource-fields-container .entaxy-create-resource-name-field-container .control-label {
margin-right: 20px;
}
.entaxy-editor-container .entaxy-editor.has-error .CodeMirror,
.entaxy-resource-editor-container .entaxy-editor.has-error .CodeMirror {
border-color: #c00;
}
/* edit resource modal */
.syntax-highlighting-container {
padding: 0 20px 10px 20px;
display: flex;
}
.syntax-highlighting-container label {
margin-right: 20px;
white-space: nowrap;
}
.syntax-highlighting-container entaxy-select-from-enum {
width: 100%;
}
/*This is the original css from HawtIO 1,leaving as is as somemay be used*/
* {
font-family: "Open Sans";
@ -2739,15 +2943,23 @@ ul.dynatree-container li {
border: 1px solid #d4d4d4;
}
.xml-editor-container {
.entaxy-editor-container {
margin-left: 20px;
margin-right: 20px;
}
.xml-editor-container .editor-autoresize .CodeMirror-scroll {
.entaxy-editor-container .editor-autoresize .CodeMirror-scroll {
height: calc(100vh - 240px);
}
.entaxy-resource-editor-container .editor-autoresize .CodeMirror-scroll {
height: calc(100vh - 276px);
}
entaxy-create-resource-modal .entaxy-resource-editor-container .editor-autoresize .CodeMirror-scroll {
height: calc(100vh - 312px);
}
.xml-route-source-container .editor-autoresize .CodeMirror-scroll {
height: calc(100vh - 320px);
}

View File

@ -3,7 +3,7 @@
~~~~~~licensing~~~~~~
entaxy-branding-plugin
==========
Copyright (C) 2020 - 2024 EmDev LLC
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

View File

@ -3,7 +3,7 @@
~~~~~~licensing~~~~~~
entaxy-branding-plugin
==========
Copyright (C) 2020 - 2024 EmDev LLC
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

Binary file not shown.

After

Width:  |  Height:  |  Size: 800 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 864 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 923 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 892 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 758 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 811 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 745 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 646 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 645 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 609 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 739 B

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* entaxy-branding-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* 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

View File

@ -0,0 +1,175 @@
ЛИЦЕНЗИЯ ОГРАНИЧЕННОГО ПРИМЕНЕНИЯ
Настоящий документ устанавливает для Пользователя условия применения Базовой (некоммерческой)
версии лицензии для пробного использования программного обеспечения ENTAXY, принадлежащего
Правообладателю Обществу с ограниченной ответственностью "ЕМДЕВ" (ОГРН 1057810026658, ИНН
7813313860, юридический адрес: 197022, Россия, г. Санкт-Петербург, ул. Профессора Попова,
д. 23, литера В, помещение 3Н), расположенной в сети Интернет по адресу
https://www.emdev.ru/about (далее - Компания).
Используя или получая доступ к Программному обеспечению, или нажав «Я согласен с Условиями»
(или аналогичную кнопку или флажок) после загрузки или установки Программного обеспечения,
Пользователь выражает свое согласие на обязательность условий и ограничений, изложенных в
настоящем документе, в противном случае, он должен не использовать или не получать доступ
к Программному обеспечению.
1. ТЕРМИНЫ И ОПРЕДЕЛЕНИЯ
a) ПО Программное обеспечение, интеграционная шина «ЭНТАКСИ» (ENTAXY) в любой ее версии
или редакции, исключительные права на которую принадлежат Правообладателю.
b) Правообладатель (Компания) ООО «ЕМДЕВ», ОГРН 1057810026658, ИНН 7813313860, исключительные
права которого подтверждаются Свидетельством о государственной регистрации в Реестре программ
для ЭВМ № 2021610848 от 19.01.2021 года.
c) Пользователь юридическое или физическое лицо, получившее через скачивание с сайта
https://entaxy.ru или иным образом, дистрибутив ПО, пользующееся ПО.
d) ИС интеллектуальная собственность закреплённое законом исключительное право, а также
личные неимущественные права авторов произведений на результат интеллектуальной деятельности.
e) Подписка это коммерческое предложение Правообладателя, состоящее из Лицензии на использование
ПО и доступа к технической поддержке программного обеспечения на срок Подписки. Подписка
включает предоставление Пользователю неисключительного права использования ПО, в том числе
получение обновлений функционала ПО и безопасности ПО, исправление ошибок ПО и получение
патчей с обновлениями и исправлениями программного обеспечения. Подписка приобретается
Пользователем на период времени, указанный в Сертификате. Количество подписок устанавливается
для каждого Пользователя индивидуально в Сертификате.
f) Сертификат документ, выдаваемый Дистрибъютором или Авторизованным партнёром (Партнёром),
подтверждающий факт приобретения физическим или юридическим лицом Подписки на программное
обеспечение в ограниченном объёме и на определённый период времени.
g) Лицензия (простая (неисключительная) совокупность ограниченных прав использования ПО,
предоставленных Пользователю согласно условиям Подписки.
h) Библиотека совокупность подпрограмм и объектов, используемых для разработки программного
обеспечения.
i) Исходный код текст компьютерной программы на каком-либо языке программирования, состоящий
из одного или нескольких файлов, который может быть прочтён человеком.
j) Объектный код файл (часть машинного кода) с промежуточным представлением отдельного модуля
программы, полученный в результате обработки исходного кода, еще не связанный в полную программу.
Это машинный код для одной конкретной библиотеки или модуля, который будет составлять готовый
продукт.
k) Некоммерческое использование индивидуальное личное использование Пользователем программного
обеспечения с целью обучения работе с Программным обеспечением, для оценки или демонстрации
возможностей Программного обеспечения, при котором, Пользователем не извлекается коммерческая
выгода и/или не идёт в доход денежное вознаграждение при использовании Программного обеспечения.
2. ДОПУСТИМЫЕ СПОСОБЫ ИСПОЛЬЗОВАНИЯ ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ
2.1. Правообладатель предоставляет Пользователю ограниченное право использования Программного
обеспечения на условиях простой (неисключительной) лицензии в объёме, ограниченном правом
воспроизведения полной рабочей версии программного обеспечения, новых версий программного обеспечения
в памяти оборудования и его запуска на оборудовании в соответствии со ст. 1280 ГК РФ.
2.2. Право на использование Программного обеспечения, предоставляемое Пользователю, носит
неисключительный характер.
2.3. Пользователю предоставляется всемирная, неисключительная, не подлежащая сублицензированию,
лицензия на ограниченное использование Программного обеспечения.
2.4. Пользователь, имеющий Базовую (некоммерческую) версию лицензии для пробного использования
имеет право приобрести Подписку на программное обеспечение. В этом случае Пользователь обязан
обратиться в службу поддержки Правообладателя по адресу: https://entaxy.ru/ для изменения
вида лицензии с Базовой бесплатной версии на Подписки.
2.5. Срок использования скачанной Пользователем базовой (некоммерческой) версии лицензии для
пробного использования программного обеспечения не ограничен.
2.6. Использование Пользователем настоящего программного обеспечения в целях разработки,
модификации, обновления другого ПО, принадлежащего третьим лицам, а не Правообладателю,
без разрешения Правообладателя не допускается.
3. АВТОРСКОЕ ПРАВО.
3.1. Все авторские права, все права интеллектуальной собственности на Программное обеспечение
и любые его копии принадлежат Правообладателю.
3.2. Все авторские права, все права интеллектуальной собственности в отношении любого контента,
к которому можно получить доступ с помощью Программного обеспечения, является собственностью
соответствующего владельца контента и защищается применимым законодательством об авторском
праве или другими законами и договорами об интеллектуальной собственности.
3.3. Условия использования Программного обеспечения.
Лицензия, предоставленная Пользователю, действительна только в том случае, если Пользователь
придерживается следующих условий:
3.3.1. Принятие уведомлений об авторских правах. Пользователю запрещается удалять или изменять
какие-либо уведомления об авторских правах или лицензиях, которые появляются при использовании
Программного обеспечения или на нем.
3.3.2. Модификация. Пользователю запрещается модифицировать, изменять, декомпилировать,
расшифровывать, дизассемблировать, переводить или реверсировать, перепроектировать
Программное обеспечение.
3.3.3. Распространение. Пользователю запрещается сублицензировать, передавать право использования
ПО или иным образом распространять или предоставлять Программное обеспечение любой третьей стороне.
3.3.4. SaaS. За исключением случаев, когда это разрешено Правообладателем, Пользователю запрещено
использовать Программное обеспечение в коммерческих целях для оказания услуг третьим лицам.
4. ОТВЕТСТВЕННОСТЬ ПРАВООБЛАДАТЕЛЯ ПРИ НАРУШЕНИИ ПОЛЬЗОВАТЕЛЕМ ПРАВ «ИС»
4.1. Правообладатель не несет никаких обязательств в отношении каких-либо претензий к Пользователю
на предмет нарушения последним прав Интеллектуальной собственности, возникших в связи с
использованием Пользователем:
4.1.1. Любых компонентов программного обеспечения с открытым исходным кодом, включенных в
Программное обеспечение;
4.1.2. Любого нарушения правил использования Программного обеспечения, установленного условиями
настоящего соглашения;
4.1.3. Любого использования Программного обеспечения в сочетании с другими ПО, оборудованием,
или данными, не предоставленными Пользователю Правообладателем;
4.1.4. Любого изменения Программного обеспечения любым третьим лицом, а не Правообладателем.
5. НАСТОЯЩИМ ПРАВООБЛАДАТЕЛЬ ЗАЯВЛЯЕТ, ЧТО ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ ПРЕДОСТАВЛЯЕТСЯ ПОЛЬЗОВАТЕЛЮ
ПО ПРИНЦИПУ «AS IS» - «КАК ЕСТЬ». НИ ПРИ КАКИХ ОБСТОЯТЕЛЬСТВАХ ПРАВООБЛАДАТЕЛЬ НЕ ГАРАНТИРУЕТ
И НЕ ОБЕЩАЕТ, ЧТО ПРЕДОСТАВЛЕННОЕ ИМ ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ БУДЕТ ПОДХОДИТЬ ИЛИ НЕ ПОДХОДИТЬ
ДЛЯ КОНКРЕТНЫХ ЦЕЛЕЙ ПОЛЬЗОВАТЕЛЯ, ЧТО ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ БУДЕТ ОТВЕЧАТЬ ВСЕМ КОММЕРЧЕСКИМ
И ЛИЧНЫМ СУБЪЕКТИВНЫМ ОЖИДАНИЯМ ПОЛЬЗОВАТЕЛЯ, ЧТО ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ БУДЕТ РАБОТАТЬ
ИСПРАВНО, БЕЗ ТЕХНИЧЕСКИХ ОШИБОК, БЫСТРО И БЕСПЕРЕБОЙНО.
6. ОГРАНИЧЕНИЕ ОТВЕТСТВЕННОСТИ.
НИ ПРИ КАКИХ ОБСТОЯТЕЛЬСТВАХ ПРАВООБЛАДАТЕЛЬ ИЛИ ЕГО АФФИЛЛИРОВАННЫЕ ЛИЦА НЕ НЕСУТ ПЕРЕД ПОЛЬЗОВАТЕЛЕМ
ОТВЕТСТВЕННОСТИ ЗА ЛЮБЫЕ ПРЯМЫЕ ИЛИ КОСВЕННЫЕ УБЫТКИ ПОЛЬЗОВАТЕЛЯ, ЕГО РАСХОДЫ ИЛИ РЕАЛЬНЫЙ УЩЕРБ,
ВКЛЮЧАЯ, ПОМИМО ПРОЧЕГО, ПРОСТОИ; УТРАТУ БИЗНЕСА; УПУЩЕННУЮ ВЫГОДУ; НЕДОПОЛУЧЕННУЮ ПРИБЫЛЬ;
ПОТЕРЮ ИЛИ ПОВРЕЖДЕНИЕ ДАННЫХ, ИМУЩЕСТВА И ИНОЕ.
ОГРАНИЧЕНИЯ ПРИМЕНЯЮТСЯ НЕЗАВИСИМО ОТ ОСНОВАНИЯ НАСТУПЛЕНИЯ ОТВЕТСТВЕННОСТИ; В ТОМ ЧИСЛЕ ВСЛЕДСТВИЕ
ДЕЙСТВИЯ ИЛИ БЕЗДЕЙСТВИЯ, НЕБРЕЖНОСТИ, УМЫСЛА, ПРЯМОГО ИЛИ КОСВЕННОГО; НЕОСТОРОЖНОСТИ; ЗАБЛУЖДЕНИЯ;
КЛЕВЕТЫ; НАРУШЕНИЯ КОНФИДЕНЦИАЛЬНОСТИ ИЛИ ПРАВА ИНТЕЛЛЕКТУАЛЬНОЙ СОБСТВЕННОСТИ; ИЛИ ЛЮБОЕ ДРУГОЕ
ОСНОВАНИЕ НАСТУПЛЕНИЯ ОТВЕТСТВЕННОСТИ.
7. ОБЯЗАННОСТЬ ПОЛЬЗОВАТЕЛЯ:
Не осуществлять самостоятельно и (или) с привлечением третьих лиц нижеследующие действия
(включая, но не ограничиваясь) по:
-дизассемблированию и (или) декомпилированию (преобразованию объектного кода в исходный код)
Программного обеспечения;
-модификации Программного обеспечения, в том числе вносить изменения в объектный код, исходный
код Программного обеспечения, за исключением тех изменений, которые вносятся средствами,
включёнными в Программное обеспечение и описанными непосредственно в документации к нему;
-созданию условий для использования Программного обеспечения лицами, не имеющими прав на
использование данного Программного обеспечения, включая (но не ограничиваясь) вмешательство
третьих лиц в функционирование Программного обеспечения, предоставление третьим лицам доступа
к исследованию и (или) замене настроек Программного обеспечения, включая его первичную установку;
-распространению Программного обеспечения в целом или в части (включая приложенную к нему документацию).
8. БИБЛИОТЕКА ПО. ИСПОЛЬЗУЕМЫЕ ПРОГРАММНЫЕ СРЕДСТВА.
8.1. Настоящим, Правообладатель заверяет, что Библиотека программного обеспечения состоит из
лицензионных продуктов, используемых на законных основаниях, а
именно https://entaxy.ru/libs/licenses/root-aggregated.deps.
8.2. Любые программные средства, применяемые Пользователем при работе с ПО, должны быть
совместимы с библиотекой ПО, указанной в п.8.1. настоящего соглашения.
8.3. Перечень внешних модулей ПО, указанный в п.8.1 настоящего соглашения, может изменяться
Правообладателем в одностороннем порядке, в зависимости от выпуска релизов программного обеспечения,
содержащих все изменения и дополнения программного обеспечения.
9. ВНЕСЕНИЕ ИЗМЕНЕНИЙ В ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ.
9.1. Программное обеспечение, интеграционная шина «ЭНТАКСИ» (ENTAXY) является свободно распространяемым
программным обеспечением.
9.2. Пользователь имеет право вносить изменения в исходный код программного обеспечения исключительно
с согласия Правообладателя в порядке предложения изменений/правок/дополнений через механизм
«Pull Requests» в открытом репозитории Правообладателя по адресу: https://git.entaxy.ru/entaxy/entaxy-public.
9.3. Любые изменения программного обеспечения, осуществляемые Пользователем без соблюдения условий
пункта 9.2. настоящего документа, являются нарушением авторских и смежных прав Правообладателя,
прав интеллектуальной собственности Правообладателя и влекут применение к Пользователю мер
ответственности в соответствии с условиями настоящей Лицензии, а также применимого законодательства
Российской Федерации.
10. ЗАКЛЮЧИТЕЛЬНЫЕ ПОЛОЖЕНИЯ.
10.1. В случае нарушения Пользователем любого из условий настоящей Лицензии, Правообладатель имеет
право взыскать с Пользователя любые причинённые таким нарушением убытки, реальный ущерб,
недополученную прибыль, упущенную выгоду, а также в случае нарушения Пользователем условий
пункта 9.2 настоящего соглашения, в том числе, взыскать с Пользователя штраф в размере
2 000 000 (Два миллиона) рублей за каждый установленный случай несанкционированного изменения
исходного или объектного кода Программного обеспечения «Энтакси» (Entaxy).
10.2. В рамках исполнения Пользователем обязательств по настоящей Лицензии, применимое
законодательство Российской Федерации.
10.3. Если какое-либо положение настоящей Лицензии будет признано судом недействительным,
остальные положения будут продолжать своё действие, а Пользователь будет обязан продолжать
исполнять свои обязанности в соответствии с этими положениями.

View File

@ -0,0 +1,253 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>ru.entaxy.esb.ui</groupId>
<artifactId>entaxy-hawtio</artifactId>
<version>1.11.0</version>
</parent>
<groupId>ru.entaxy.esb.ui.hawtio</groupId>
<artifactId>entaxy-cicd-plugin</artifactId>
<packaging>war</packaging>
<name>ENTAXY :: UI :: HAWTIO :: ENTAXY CI/CD PLUGIN</name>
<description>ENTAXY :: UI :: HAWTIO :: ENTAXY CI/CD MANAGEMENT</description>
<properties>
<!-- filtered plugin properties, we don't define plugin-scripts here
as we build that dynamically using maven-antrun-plugin below. -->
<!-- plugin-context is what context this plugin will handle requests on
in the application server -->
<plugin-context>/entaxy-cicd</plugin-context>
<!-- plugin-name is the name of our plugin, affects the name used for
the plugin's mbean -->
<plugin-name>entaxy-cicd</plugin-name>
<!-- plugin-domain is currently unused, we just define it to an empty
string -->
<plugin-domain />
<!-- this lets this plugin deploy nicely into karaf, these get used
for the ImportPackage directive for maven-bundle-plugin -->
<bundle.osgi.import.pkg>
javax.management;resolution:=optional,
org.slf4j;resolution:=optional;version="[1.7,2)",
javax.servlet;version="[3.1,4)"
</bundle.osgi.import.pkg>
<webapp-dir>${project.artifactId}-${project.version}</webapp-dir>
<webapp-outdir>${basedir}/target/${webapp-dir}</webapp-outdir>
<schema-outdir>${basedir}/src/main/webapp/lib</schema-outdir>
<appjs-outfile>${webapp-outdir}/app/app.js</appjs-outfile>
<bundle.osgi.remove.headers>Karaf-Commands,Private-Package,Include-Resource</bundle.osgi.remove.headers>
</properties>
<dependencies>
<dependency>
<groupId>io.hawt</groupId>
<artifactId>hawtio-plugin-mbean</artifactId>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- dependency>
<groupId>com.google.errorprone</groupId>
<artifactId>error_prone_core</artifactId>
</dependency -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
</dependency>
</dependencies>
<build>
<!-- we want to ensure src/main/resources/WEB-INF/web.xml is being filtered
so that it picks up all of our javascript files -->
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
<plugins>
<!-- We use maven-antrun-plugin to build up a list of
javascript files for our plugin mbean, this means
it needs to run before the maven-resources-plugin
copies and filters the web.xml, since for this
example we use contextParam settings to configure
our plugin mbean -->
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<version>${maven-antrun-plugin.version}</version>
<executions>
<execution>
<!-- we run this early in the build process before
maven-resources-plugin is run. We're exporting the
plugin-scripts property from here, so we need to
use maven-antrun-plugin 1.6 or up -->
<id>generate-sources</id>
<phase>generate-sources</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target>
<echo>Building plugin javascript file list</echo>
<!-- javascript-files will contain all of the javascript in
our project -->
<fileset id="javascript-files-main" dir="${basedir}/src/main/webapp">
<include name="**/entaxyCICDPlugin.js" />
</fileset>
<fileset id="javascript-files-others" dir="${basedir}/src/main/webapp">
<include name="**/*.js" />
<exclude name="**/entaxyCICDPlugin.js" />
</fileset>
<!-- we need to strip out the top level path which is
our source directory and be sure to change the directory
separators to forward slashes -->
<pathconvert pathsep="," dirsep="/" property="plugin-scripts-main" refid="javascript-files-main">
<map from="${basedir}/src/main/webapp/" to="" />
</pathconvert>
<pathconvert pathsep="," dirsep="/" property="plugin-scripts-others" refid="javascript-files-others">
<map from="${basedir}/src/main/webapp/" to="" />
</pathconvert>
<property name="plugin-scripts" value="${plugin-scripts-main},${plugin-scripts-others}" />
<echo>Files: ${plugin-scripts}</echo>
<!--<replace file="${webapp-outdir}/plugin/js/brandingPlugin.js">
<replacefilter token="@artemis.version@" value="${project.version}" />
</replace>-->
</target>
<!-- this exports plugin-scripts to the maven build, without
this line ${plugin-scripts} in the web.xml file won't be
replaced -->
<exportAntProperties>true</exportAntProperties>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>${maven-resources-plugin.version}</version>
<executions>
<execution>
<!-- defining this maven plugin in the same phase as the
maven-antrun-plugin but *after* we've configured the
maven-antrun-plugin ensures we filter resources *after*
we've discovered the plugin .js files. -->
<id>copy-resources</id>
<phase>generate-sources</phase>
<goals>
<goal>resources</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- maven-bundle-plugin config, needed to make this war
deployable in karaf, defines the context that this bundle
should handle requests on -->
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<executions>
<execution>
<id>bundle-manifest</id>
<phase>process-classes</phase>
<goals>
<goal>manifest</goal>
</goals>
</execution>
</executions>
<configuration>
<manifestLocation>${webapp-outdir}/META-INF</manifestLocation>
<supportedProjectTypes>
<supportedProjectType>jar</supportedProjectType>
<supportedProjectType>bundle</supportedProjectType>
<supportedProjectType>war</supportedProjectType>
</supportedProjectTypes>
<instructions>
<Webapp-Context>${plugin-context}</Webapp-Context>
<Web-ContextPath>${plugin-context}</Web-ContextPath>
<Embed-Directory>WEB-INF/lib</Embed-Directory>
<Embed-Dependency>*;scope=compile|runtime</Embed-Dependency>
<Embed-Transitive>true</Embed-Transitive>
<!-- Export-Package>${osgi.export}</Export-Package -->
<!-- Import-Package>
javax.management;resolution:=optional,
org.slf4j;resolution:=optional;version="[1.7,2)",
javax.servlet;version="[3.1,4)"
</Import-Package -->
<!-- DynamicImport-Package>${osgi.dynamic}</DynamicImport-Package -->
<!-- Private-Package></Private-Package -->
<Bundle-ClassPath>.,WEB-INF/classes</Bundle-ClassPath>
<Bundle-Name>${project.name}</Bundle-Name>
<Bundle-SymbolicName>${project.groupId}.${project.artifactId}</Bundle-SymbolicName>
<Implementation-Title>Entaxy</Implementation-Title>
<Implementation-Version>${project.version}</Implementation-Version>
</instructions>
</configuration>
</plugin>
<!-- We define the maven-war-plugin here and make sure it uses
the manifest file generated by the maven-bundle-plugin. We
also ensure it picks up our filtered web.xml and not the one
in src/main/resources -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<outputFileNameMapping>@{artifactId}@-@{baseVersion}@@{dashClassifier?}@.@{extension}@</outputFileNameMapping>
<packagingExcludes>**/classes/OSGI-INF/**</packagingExcludes>
<failOnMissingWebXml>false</failOnMissingWebXml>
<archive>
<manifestFile>${webapp-outdir}/META-INF/MANIFEST.MF</manifestFile>
</archive>
<webResources>
<resource>
<filtering>true</filtering>
<directory>src/main/resources</directory>
<includes>
<include>**/*.*</include>
</includes>
<excludes>
<exclude>log4j.properties</exclude>
</excludes>
</resource>
<resource>
<filtering>true</filtering>
<directory>src/main/webapp</directory>
<includes>
<include>**/*.*</include>
</includes>
<excludes>
<exclude>log4j.properties</exclude>
</excludes>
</resource>
</webResources>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,80 @@
/*-
* ~~~~~~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~~~~~~
*/
package ru.entaxy.ui.hawtio.cicd;
import io.hawt.web.plugin.HawtioPlugin;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
/**
* The Plugin Context Listener used to load in the plugin
**/
public class PluginContextListener implements ServletContextListener {
private static final Logger LOG = LoggerFactory.getLogger(PluginContextListener.class);
HawtioPlugin plugin = null;
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
ServletContext context = servletContextEvent.getServletContext();
plugin = new HawtioPlugin();
plugin.setContext(context.getContextPath());
plugin.setName(context.getInitParameter("plugin-name"));
plugin.setScripts(context.getInitParameter("plugin-scripts"));
plugin.setDomain(null);
try {
plugin.init();
} catch (Exception e) {
throw createServletException(e);
}
LOG.info("Initialized {} plugin", plugin.getName());
}
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
try {
plugin.destroy();
} catch (Exception e) {
throw createServletException(e);
}
LOG.info("Destroyed {} plugin", plugin.getName());
}
protected RuntimeException createServletException(Exception e) {
return new RuntimeException(e);
}
}

View File

@ -0,0 +1,73 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~~~~~~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~~~~~~
-->
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
version="2.4">
<description>Entaxy HawtIO management plugin</description>
<display-name>entaxy hawt.io management plugin</display-name>
<context-param>
<description>Plugin's path on the server</description>
<param-name>plugin-context</param-name>
<param-value>${plugin-context}</param-value>
</context-param>
<context-param>
<description>Plugin's path on the server</description>
<param-name>plugin-name</param-name>
<param-value>${plugin-name}</param-value>
</context-param>
<context-param>
<description>Plugin's path on the server</description>
<param-name>plugin-domain</param-name>
<param-value>${plugin-domain}</param-value>
</context-param>
<context-param>
<description>Plugin's path on the server</description>
<param-name>plugin-scripts</param-name>
<param-value>${plugin-scripts}</param-value>
</context-param>
<context-param>
<description>Disable listing of directories and files</description>
<param-name>org.eclipse.jetty.servlet.Default.dirAllowed</param-name>
<param-value>false</param-value>
</context-param>
<listener>
<listener-class>ru.entaxy.ui.hawtio.cicd.PluginContextListener</listener-class>
</listener>
</web-app>

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 = {}));

View File

@ -3,7 +3,7 @@
<parent>
<groupId>ru.entaxy.esb.ui</groupId>
<artifactId>entaxy-hawtio</artifactId>
<version>1.10.0</version>
<version>1.11.0</version>
</parent>
<groupId>ru.entaxy.esb.ui.hawtio</groupId>
<artifactId>entaxy-h2-plugin</artifactId>

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* entaxy-management-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* 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

View File

@ -3,7 +3,7 @@
~~~~~~licensing~~~~~~
entaxy-management-plugin
==========
Copyright (C) 2020 - 2024 EmDev LLC
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

View File

@ -3,7 +3,7 @@
~~~~~~licensing~~~~~~
entaxy-management-plugin
==========
Copyright (C) 2020 - 2024 EmDev LLC
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

View File

@ -2,7 +2,7 @@
~~~~~~licensing~~~~~~
entaxy-management-plugin
==========
Copyright (C) 2020 - 2024 EmDev LLC
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

View File

@ -2,7 +2,7 @@
~~~~~~licensing~~~~~~
entaxy-management-plugin
==========
Copyright (C) 2020 - 2024 EmDev LLC
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

View File

@ -2,7 +2,7 @@
~~~~~~licensing~~~~~~
entaxy-management-plugin
==========
Copyright (C) 2020 - 2024 EmDev LLC
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

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* entaxy-h2-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* 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

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* entaxy-management-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* 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

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* entaxy-management-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* 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

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* entaxy-management-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* 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

View File

@ -3,7 +3,7 @@
<parent>
<groupId>ru.entaxy.esb.ui</groupId>
<artifactId>entaxy-hawtio</artifactId>
<version>1.10.0</version>
<version>1.11.0</version>
</parent>
<groupId>ru.entaxy.esb.ui.hawtio</groupId>
<artifactId>entaxy-management-plugin</artifactId>

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* entaxy-management-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* 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

Some files were not shown because too many files have changed in this diff Show More