release version 1.10.0
After Width: | Height: | Size: 800 B |
After Width: | Height: | Size: 864 B |
After Width: | Height: | Size: 923 B |
After Width: | Height: | Size: 892 B |
After Width: | Height: | Size: 758 B |
After Width: | Height: | Size: 811 B |
After Width: | Height: | Size: 392 B |
After Width: | Height: | Size: 745 B |
After Width: | Height: | Size: 646 B |
After Width: | Height: | Size: 645 B |
After Width: | Height: | Size: 758 B |
After Width: | Height: | Size: 636 B |
After Width: | Height: | Size: 576 B |
After Width: | Height: | Size: 609 B |
After Width: | Height: | Size: 739 B |
175
ui/entaxy-hawtio/entaxy-cicd-plugin/LICENSE.txt
Normal 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. Если какое-либо положение настоящей Лицензии будет признано судом недействительным,
|
||||
остальные положения будут продолжать своё действие, а Пользователь будет обязан продолжать
|
||||
исполнять свои обязанности в соответствии с этими положениями.
|
253
ui/entaxy-hawtio/entaxy-cicd-plugin/pom.xml
Normal 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>
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
@ -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>
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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'
|
||||
}
|
||||
};
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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);
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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 = {}));
|
@ -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 = {}));
|