release version 1.10.0

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

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

@ -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.10.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 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
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 - 2024 EmDev LLC
==========
You may not use this file except in accordance with the License Terms of the Copyright
Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
rights to the Software and any copies are the property of the Copyright Holder. Unless
it is explicitly allowed the Copyright Holder, the User is prohibited from using the
Software for commercial purposes to provide services to third parties.
The Copyright Holder hereby declares that the Software is provided on an "AS IS".
Under no circumstances does the Copyright Holder guarantee or promise that the
Software provided by him will be suitable or not suitable for the specific purposes
of the User, that the Software will meet all commercial and personal subjective
expectations of the User, that the Software will work properly, without technical
errors, quickly and uninterruptedly.
Under no circumstances shall the Copyright Holder or its Affiliates is not liable
to the User for any direct or indirect losses of the User, his expenses or actual
damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
or damage to data, property, etc.
~~~~~~/licensing~~~~~~
-->
<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,191 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-cicd-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var 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,
values: workspace.selection.children.map(revision => revision.title.split(' ')[0])
}
];
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) {
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 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var 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,149 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-cicd-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var 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
}
];
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 () {
$uibModal.open({
component: 'entaxyCiCdSimpleFieldsModal',
resolve: {
modalTitle: () => 'Import Application From File',
formFields: () => getFormFields(false)
},
backdrop: 'static'
})
.result.then(args => {
importFromFile(args);
},
reason => {
if (reason) {
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]);
}
}
ctrl.importFromRepository = function () {
$uibModal.open({
component: 'entaxyCiCdSimpleFieldsModal',
resolve: {
modalTitle: () => 'Import Application From Repository',
formFields: () => getFormFields(true)
},
backdrop: 'static'
})
.result.then(args => {
processOperation('importFromRepository', args);
},
reason => {
if (reason) {
Entaxy.notificationError(reason);
}
});
}
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,282 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-cicd-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var 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) {
'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() {
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 }), {});
}
}
}
EntaxyCICDConfigurationController.$inject = ['workspace', '$scope', '$location', 'entaxyCICDService',
'entaxyService'];
})(EntaxyCICD || (EntaxyCICD = {}));

View File

@ -0,0 +1,189 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-cicd-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var 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 = EntaxyCICD.createTableFromCopyConfigurationLocalValuesResult(result);
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 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var 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 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var 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 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var 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 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var 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 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var 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 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var 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 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var 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,169 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-cicd-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var 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,
values: JSON.parse(result)
}
];
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) {
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 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var 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 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var 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,427 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-cicd-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var 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>';
}
}
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() }
];
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) {
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.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 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var 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,189 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-cicd-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var 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',
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'
}
}
}
];
}
ctrl.addVersionFromScratch = function () {
openCreateVersionModal(getFormFields());
}
ctrl.addVersionFromExistent = function () {
let formFields = getFormFields();
formFields.push({
label: 'Prototype Version',
name: 'prototypeVersion',
enum: 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) {
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,136 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-cicd-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var 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) {
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'
}
}
},
{
name: 'group',
label: 'Group',
type: 'text'
},
{
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,243 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-cicd-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var 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',
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'
}
}
}
];
}
ctrl.addVersionFromScratch = function () {
openCreateVersionModal(getFormFields());
}
ctrl.addVersionFromExistent = function () {
let formFields = getFormFields();
formFields.push({
label: 'Prototype Version',
name: 'prototypeVersion',
enum: 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) {
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 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var 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,134 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-management-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var 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">
<entaxy-select-from-enum id="{{formField.name}}" values="formField.values"
model="formField.value" readonly="formField.readOnly" is-empty-included="false"
ng-if="formField.enum"></entaxy-select-from-enum>
<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($uibModal) {
'ngInject';
let ctrl = this;
ctrl.$onInit = function() {
ctrl.formFields = ctrl.resolve.formFields;
if (!ctrl.formFields || ctrl.formFields.length === 0) {
ctrl.cancel('Fields can not be found');
}
}
ctrl.cancel = function(reason) {
ctrl.modalInstance.dismiss(reason);
}
ctrl.save = function() {
ctrl.errors = validate();
if (Object.keys(ctrl.errors).length === 0) {
let args = ctrl.formFields.map(formField => formField.value);
ctrl.modalInstance.close(args);
}
}
function validate() {
let errors = {};
ctrl.formFields.forEach(formField => {
if (formField.required && (!formField.value ||
(!formField.resource && formField.value.trim().length === 0))) {
errors[formField.name] = Entaxy.ERROR_MESSAGE.EMPTY;
}
if (!errors[formField.name] && formField.validation &&
formField.validation.content && formField.validation.content.regex) {
let regex = new RegExp(formField.validation.content.regex);
if (!formField.value.match(regex)) {
errors[formField.name] = formField.validation.content.errorMessage ?
formField.validation.content.errorMessage : 'Value contains invalid characters';
}
}
if (!errors[formField.name] && formField.validation && formField.validation.checkUniqueness
&& formField.validation.values.includes(formField.value)) {
errors[formField.name] = Entaxy.ERROR_MESSAGE.UNIQUE;
}
});
return errors;
}
}
entaxyCICDSimpleFieldsModalController.$inject = ['$uibModal'];
})(EntaxyCICD || (EntaxyCICD = {}));

View File

@ -0,0 +1,263 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-cicd-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var 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,173 @@
/*-
* ~~~~~~licensing~~~~~~
* entaxy-cicd-plugin
* ==========
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
var 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"></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;
function createTableFromCopyConfigurationLocalValuesResult(result) {
let tableHtml = `<table class="entaxy-result-table">`;
tableHtml += `
<tr>
<th>Configuration Id</th>
<th>Status</th>
</tr>
`;
result.forEach(res => {
let iconName = res.failed ? 'error-circle-o' : 'ok';
tableHtml += `<tr><td style="padding-right: 5px;">` + res.id +
`</td><td><span class="pficon pficon-${iconName}"></span></td></tr>`;
});
tableHtml += `</table>`;
return tableHtml;
}
EntaxyCICD.createTableFromCopyConfigurationLocalValuesResult = createTableFromCopyConfigurationLocalValuesResult;
})(EntaxyCICD || (EntaxyCICD = {}));

View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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