release version 1.11.0
This commit is contained in:
@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>ru.entaxy.esb.ui</groupId>
|
||||
<artifactId>entaxy-hawtio</artifactId>
|
||||
<version>1.10.0</version>
|
||||
<version>1.11.0</version>
|
||||
</parent>
|
||||
<groupId>ru.entaxy.esb.ui.hawtio</groupId>
|
||||
<artifactId>entaxy-management-plugin</artifactId>
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* entaxy-management-plugin
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2024 EmDev LLC
|
||||
* Copyright (C) 2020 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
|
@ -3,7 +3,7 @@
|
||||
~~~~~~licensing~~~~~~
|
||||
entaxy-management-plugin
|
||||
==========
|
||||
Copyright (C) 2020 - 2024 EmDev LLC
|
||||
Copyright (C) 2020 - 2025 EmDev LLC
|
||||
==========
|
||||
You may not use this file except in accordance with the License Terms of the Copyright
|
||||
Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* entaxy-management-plugin
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2024 EmDev LLC
|
||||
* Copyright (C) 2020 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* entaxy-management-plugin
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2024 EmDev LLC
|
||||
* Copyright (C) 2020 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
|
314
ui/entaxy-hawtio/entaxy-management-plugin/src/main/webapp/codemirror/mode/freemarker/freemarker.js
vendored
Normal file
314
ui/entaxy-hawtio/entaxy-management-plugin/src/main/webapp/codemirror/mode/freemarker/freemarker.js
vendored
Normal file
@ -0,0 +1,314 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* entaxy-management-plugin
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
|
||||
/**
|
||||
* freemarker
|
||||
*/
|
||||
|
||||
(function(mod) {
|
||||
if (typeof exports == "object" && typeof module == "object" ) // CommonJS
|
||||
mod(require("../../lib/codemirror"));
|
||||
else if (typeof define == "function" && define.amd ) // AMD
|
||||
define([ "../../lib/codemirror" ], mod);
|
||||
else
|
||||
// Plain browser env
|
||||
mod(CodeMirror);
|
||||
})(function(CodeMirror) {
|
||||
"use strict";
|
||||
|
||||
CodeMirror
|
||||
.defineMode("freemarker", function(config) {
|
||||
"use strict";
|
||||
|
||||
// our default settings; check to see if they're overridden
|
||||
var settings = {
|
||||
leftDelimiter : '[', rightDelimiter : ']', tagSyntax : 2
|
||||
// 1 angle_bracket,2 square_bracket
|
||||
};
|
||||
if (config.hasOwnProperty("tagSyntax") ) {
|
||||
if (config.tagSyntax === 1 ) {
|
||||
settings.tagSyntax = 1;
|
||||
settings.leftDelimiter = '<';
|
||||
settings.rightDelimiter = '>';
|
||||
}
|
||||
}
|
||||
|
||||
var keyFunctions = [ "assign", "attempt", "autoesc", "break", "case", "compress", "default", "else",
|
||||
"elseif", "escape", "fallback", "function", "flush", "ftl", "global", "if", "import",
|
||||
"include", "items", "list", "local", "lt", "macro", "nested","noautoesc", "noescape", "noparse", "nt","outputformat",
|
||||
"recover", "recurse", "return", "rt", "sep", "setting", "stop", "switch", "t", "visit" ];
|
||||
var specialVariables = [ "auto_esc" , "caller_template_name", "current_template_name", "data_model", "error", "get_optional_template", "globals", "lang", "locale",
|
||||
"locale_object", "locals", "main", "main_template_name", "namespace", "node", "now",
|
||||
"output_encoding " , "output_format" , "template_name" , "time_zone" , "url_escaping_charset", "vars", "version" ];
|
||||
|
||||
var freemarkerStartTagArray = [ "#", "@" ];
|
||||
|
||||
var freemarkerEndTagArray = [ "/#", "/@", "/>" ];
|
||||
|
||||
var last;
|
||||
var freemarkerMode;
|
||||
var regs = {
|
||||
operatorChars : /[+\-*&%=<>!?:;,|&]/, validIdentifier : /[a-zA-Z0-9_]/, stringChar : /['"]/
|
||||
};
|
||||
|
||||
var helpers = {
|
||||
cont : function(style, lastType, lastFreemarkerMode) {
|
||||
last = lastType;
|
||||
freemarkerMode = lastFreemarkerMode;
|
||||
return style;
|
||||
}, chain : function(stream, state, parser) {
|
||||
state.tokenize = parser;
|
||||
return parser(stream, state);
|
||||
}
|
||||
};
|
||||
|
||||
// our various parsers
|
||||
var parsers = {
|
||||
|
||||
// the main tokenizer
|
||||
tokenizer : function(stream, state) {
|
||||
if (stream.match(settings.leftDelimiter, true) ) {
|
||||
if (stream.match("#--", true) ) {
|
||||
return helpers.chain(stream, state, parsers.inBlock("comment", "--"
|
||||
+ settings.rightDelimiter));
|
||||
} else {
|
||||
for (var i = 0; i < freemarkerStartTagArray.length; i++) {
|
||||
if (stream.match(freemarkerStartTagArray[i], false) ) {
|
||||
state.tokenize = parsers.freemarkerTemplate;
|
||||
if (freemarkerStartTagArray[i] == "@" ) {
|
||||
freemarkerMode = "macro";
|
||||
} else {
|
||||
freemarkerMode = "tag";
|
||||
}
|
||||
last = "startTag";
|
||||
return "tag";
|
||||
}
|
||||
}
|
||||
for (var i = 0; i < freemarkerEndTagArray.length; i++) {
|
||||
if (stream.match(freemarkerEndTagArray[i], false) ) {
|
||||
state.tokenize = parsers.freemarkerTemplate;
|
||||
if (freemarkerEndTagArray[i] == "/@" ) {
|
||||
freemarkerMode = "macro";
|
||||
} else {
|
||||
freemarkerMode = "tag";
|
||||
}
|
||||
last = "endTag";
|
||||
return "tag";
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (stream.match("${", false) ) {
|
||||
state.tokenize = parsers.freemarkerTemplate;
|
||||
last = "startTag";
|
||||
freemarkerMode = "echo";
|
||||
return "keyword";
|
||||
}
|
||||
stream.next();
|
||||
return null;
|
||||
},
|
||||
|
||||
// parsing freemarker content
|
||||
freemarkerTemplate : function(stream, state) {
|
||||
if (stream.match(settings.rightDelimiter, true) ) {
|
||||
state.depth--;
|
||||
if (state.depth <= 0 ) {
|
||||
state.tokenize = parsers.tokenizer;
|
||||
}
|
||||
return helpers.cont("tag", null, null);
|
||||
} else if ("echo" == state.freemarkerMode && stream.match("}", true) ) {
|
||||
state.depth--;
|
||||
if (state.depth <= 0 ) {
|
||||
state.tokenize = parsers.tokenizer;
|
||||
}
|
||||
return helpers.cont("keyword", null, null);
|
||||
}
|
||||
|
||||
if (stream.match(settings.leftDelimiter, true) ) {
|
||||
for (var i = 0; i < freemarkerStartTagArray.length; i++) {
|
||||
if (stream.match(freemarkerStartTagArray[i], false) ) {
|
||||
state.depth++;
|
||||
if (freemarkerStartTagArray[i] == "@" ) {
|
||||
return helpers.cont("tag", "startTag", "macro");
|
||||
} else {
|
||||
return helpers.cont("tag", "startTag", "tag");
|
||||
}
|
||||
}
|
||||
}
|
||||
for (var i = 0; i < freemarkerEndTagArray.length; i++) {
|
||||
if (stream.match(freemarkerEndTagArray[i], false) ) {
|
||||
state.depth++;
|
||||
if (freemarkerEndTagArray[i] == "/@" ) {
|
||||
return helpers.cont("tag", "endTag", "macro");
|
||||
} else {
|
||||
return helpers.cont("tag", "endTag", "tag");
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (stream.match("${", true) ) {
|
||||
state.depth++;
|
||||
return helpers.cont("keyword", "startTag", "echo");
|
||||
}
|
||||
var ch = stream.next();
|
||||
if ("." == ch ) {
|
||||
if("echo" == state.freemarkerMode || "whitespace" == state.last ||"operator"== state.last){
|
||||
for (var i = 0; i < specialVariables.length; i++) {
|
||||
if(stream.match(specialVariables[i],true)){
|
||||
return helpers.cont("keyword", "variable", state.freemarkerMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
if("keyword"==state.last && stream.eatWhile(regs.validIdentifier)){
|
||||
return helpers.cont("keyword", null, state.freemarkerMode);
|
||||
}else{
|
||||
return helpers.cont("operator", "childVariable", state.freemarkerMode);
|
||||
}
|
||||
} else if (regs.stringChar.test(ch) ) {
|
||||
state.tokenize = parsers.inAttribute(ch);
|
||||
return helpers.cont("string", "string", state.freemarkerMode);
|
||||
} else if (regs.operatorChars.test(ch) ) {
|
||||
if ("?" === ch ) {
|
||||
return helpers.cont("operator", "builtin", state.freemarkerMode);
|
||||
} else {
|
||||
return helpers.cont("operator", "operator", state.freemarkerMode);
|
||||
}
|
||||
} else if ("[" == ch || "{" == ch|| "(" == ch ) {
|
||||
return helpers.cont("bracket", "bracket", state.freemarkerMode);
|
||||
} else if ("]" == ch || "}" == ch || ")" == ch ) {
|
||||
return helpers.cont("bracket", "variable", state.freemarkerMode);
|
||||
} else if ("/" == ch ) {
|
||||
return helpers.cont("tag", "endTag", state.freemarkerMode);
|
||||
} else if ("@" == ch && "macro" == state.freemarkerMode ) {
|
||||
stream.eatWhile(regs.validIdentifier)
|
||||
return helpers.cont("keyword", "keyword", state.freemarkerMode);
|
||||
} else if (/\d/.test(ch) ) {
|
||||
stream.eat(/x/i)
|
||||
stream.eatWhile(/\d/);
|
||||
return helpers.cont("number", "number", state.freemarkerMode);
|
||||
} else if("tag" == state.freemarkerMode && "whitespace" == state.last && (stream.match("as",true) || stream.match("in",true)|| stream.match("using",true) )) {
|
||||
return helpers.cont("keyword", "operator", state.freemarkerMode);
|
||||
} else if("tag" == state.freemarkerMode && "whitespace" == state.last && (stream.match("gte",true) || stream.match("lte",true) || stream.match("gt",true) || stream.match("lt",true) )) {
|
||||
return helpers.cont("operator", "operator", state.freemarkerMode);
|
||||
} else {
|
||||
if ("builtin" == state.last ) {
|
||||
stream.eat("?");
|
||||
stream.eatWhile(regs.validIdentifier);
|
||||
return helpers.cont("builtin", "variable", state.freemarkerMode);
|
||||
} else if ("whitespace" == state.last||"bracket" == state.last) {
|
||||
if ("macro" == state.freemarkerMode ) {
|
||||
stream.eatWhile(regs.validIdentifier);
|
||||
return helpers.cont("attribute", "attribute", state.freemarkerMode);
|
||||
} else {
|
||||
stream.eatWhile(regs.validIdentifier);
|
||||
return helpers.cont("variable-2", "variable", state.freemarkerMode);
|
||||
}
|
||||
} else if ("operator" == state.last ) {
|
||||
stream.eatWhile(regs.validIdentifier);
|
||||
return helpers.cont("variable-2", "variable", state.freemarkerMode);
|
||||
} else if ("childVariable" == state.last ) {
|
||||
stream.eatWhile(regs.validIdentifier);
|
||||
return helpers.cont("variable-3", "variable", state.freemarkerMode);
|
||||
} else if (/\s/.test(ch) ) {
|
||||
last = "whitespace";
|
||||
return null;
|
||||
} else if ("string" == state.last ) {
|
||||
stream.eatWhile(regs.validIdentifier);
|
||||
return helpers.cont("attribute", "attribute", state.freemarkerMode);
|
||||
} else {
|
||||
if ("startTag" == state.last || "endTag" == state.last ) {
|
||||
if ("echo" == state.freemarkerMode ) {
|
||||
stream.eatWhile(regs.validIdentifier)
|
||||
return helpers.cont("variable-2", "variable", state.freemarkerMode);
|
||||
}
|
||||
}
|
||||
if ("tag" == state.freemarkerMode ) {
|
||||
var str = "";
|
||||
if (ch != "/" ) {
|
||||
str += ch;
|
||||
}
|
||||
var c = null;
|
||||
while (c = stream.eat(regs.validIdentifier)) {
|
||||
str += c;
|
||||
}
|
||||
for (var i = 0 ; i < keyFunctions.length; i++) {
|
||||
if ("#"+keyFunctions[i] == str ) {
|
||||
return helpers.cont("keyword", "keyword", state.freemarkerMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return helpers.cont("error", "tag", state.freemarkerMode);
|
||||
}
|
||||
},
|
||||
|
||||
inAttribute : function(quote) {
|
||||
return function(stream, state) {
|
||||
var prevChar = null;
|
||||
var currChar = null;
|
||||
while (!stream.eol()) {
|
||||
currChar = stream.peek();
|
||||
if (stream.next() == quote && '\\' !== prevChar ) {
|
||||
state.tokenize = parsers.freemarkerTemplate;
|
||||
break;
|
||||
}
|
||||
prevChar = currChar;
|
||||
}
|
||||
return "string";
|
||||
};
|
||||
},
|
||||
|
||||
inBlock : function(style, terminator) {
|
||||
return function(stream, state) {
|
||||
while (!stream.eol()) {
|
||||
if (stream.match(terminator) ) {
|
||||
state.tokenize = parsers.tokenizer;
|
||||
break;
|
||||
}
|
||||
stream.next();
|
||||
}
|
||||
return style;
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
// the public API for CodeMirror
|
||||
return {
|
||||
startState : function() {
|
||||
return {
|
||||
tokenize : parsers.tokenizer, mode : "freemarker", last : null, freemarkerMode : null,
|
||||
depth : 0
|
||||
};
|
||||
}, token : function(stream, state) {
|
||||
state.last = last;
|
||||
state.freemarkerMode = freemarkerMode;
|
||||
return state.tokenize(stream, state);
|
||||
}, electricChars : ""
|
||||
};
|
||||
});
|
||||
|
||||
CodeMirror.defineMIME("text/freemarker", "freemarker");
|
||||
|
||||
});
|
@ -0,0 +1,229 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* entaxy-management-plugin
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
|
||||
/**
|
||||
* @file freemarkermixed.js
|
||||
*/
|
||||
|
||||
(function(mod) {
|
||||
if (typeof exports == "object" && typeof module == "object" ) // CommonJS
|
||||
mod(require("../../lib/codemirror"), require("../htmlmixed/htmlmixed"), require("../freemarker/freemarker"));
|
||||
else if (typeof define == "function" && define.amd ) // AMD
|
||||
define([ "../../lib/codemirror", "../htmlmixed/htmlmixed", "../freemarker/freemarker" ], mod);
|
||||
else
|
||||
// Plain browser env
|
||||
mod(CodeMirror);
|
||||
})
|
||||
(function(CodeMirror) {
|
||||
"use strict";
|
||||
|
||||
CodeMirror
|
||||
.defineMode("freemarkermixed", function(config) {
|
||||
|
||||
var htmlMixedMode = CodeMirror.getMode(config, "htmlmixed");
|
||||
var freemarkerMode = CodeMirror.getMode(config, "freemarker");
|
||||
|
||||
var settings = {
|
||||
leftDelimiter : '[', rightDelimiter : ']', tagSyntax : 2
|
||||
// 1 angle_bracket,2 square_bracket
|
||||
};
|
||||
|
||||
if (config.hasOwnProperty("tagSyntax") ) {
|
||||
if (config.tagSyntax === 1 ) {
|
||||
settings.tagSyntax = 1;
|
||||
settings.leftDelimiter = '<';
|
||||
settings.rightDelimiter = '>';
|
||||
}
|
||||
}
|
||||
|
||||
var freemarkerFlagArray = ["#","/#","@","/@"];
|
||||
|
||||
function regEsc(str) {
|
||||
return str.replace(/[^\s\w]/g, "\\$&");
|
||||
}
|
||||
|
||||
var regLeftArray=[],htmlHasLeftDelimeterRegArray=[];
|
||||
|
||||
for (var i = 0; i < freemarkerFlagArray.length; i++) {
|
||||
let futureRegExp = ".*" + regEsc(settings.leftDelimiter + freemarkerFlagArray[i]);
|
||||
regLeftArray.push( new RegExp(".*" + regEsc(settings.leftDelimiter + freemarkerFlagArray[i])));
|
||||
htmlHasLeftDelimeterRegArray.push( new RegExp("[^<>]*" + regEsc(settings.leftDelimiter + freemarkerFlagArray[i])));
|
||||
}
|
||||
|
||||
var helpers = {
|
||||
chain : function(stream, state, parser) {
|
||||
state.tokenize = parser;
|
||||
return parser(stream, state);
|
||||
},
|
||||
|
||||
cleanChain : function(stream, state, parser) {
|
||||
state.tokenize = null;
|
||||
state.localState = null;
|
||||
state.localMode = null;
|
||||
return (typeof parser == "string") ? (parser ? parser : null) : parser(stream, state);
|
||||
},
|
||||
|
||||
maybeBackup : function(stream, pat, style) {
|
||||
var cur = stream.current();
|
||||
var close = cur.search(pat) , m;
|
||||
if (close > -1 ) {
|
||||
stream.backUp(cur.length - close);
|
||||
} else if (m = cur.match(/<\/?$/) ) {
|
||||
stream.backUp(cur.length);
|
||||
if (!stream.match(pat, false) ) {
|
||||
stream.match(cur[0]);
|
||||
}
|
||||
}
|
||||
return style;
|
||||
}
|
||||
};
|
||||
|
||||
var parsers = {
|
||||
html : function(stream, state) {
|
||||
if (!state.noparse) {
|
||||
var htmlTagName = state.htmlMixedState.htmlState.context && state.htmlMixedState.htmlState.context.tagName
|
||||
? state.htmlMixedState.htmlState.context.tagName
|
||||
: null;
|
||||
for (var i = 0; i < freemarkerFlagArray.length; i++) {
|
||||
if ( (stream.match(htmlHasLeftDelimeterRegArray[i], false) && htmlTagName === null ) || stream.match(settings.leftDelimiter + freemarkerFlagArray[i], false)) {
|
||||
state.tokenize = parsers.freemarker;
|
||||
state.localMode = freemarkerMode;
|
||||
state.localState = freemarkerMode.startState(htmlMixedMode.indent(state.htmlMixedState, "", ""));
|
||||
return helpers.maybeBackup(stream, regEsc(settings.leftDelimiter) + freemarkerFlagArray[i], freemarkerMode.token(stream, state.localState));
|
||||
} else if (stream.match("${", false)) {
|
||||
state.tokenize = parsers.freemarker;
|
||||
state.localMode = freemarkerMode;
|
||||
state.localState = freemarkerMode.startState(htmlMixedMode.indent(state.htmlMixedState, "", ""));
|
||||
return helpers.maybeBackup(stream, "${", freemarkerMode.token(stream, state.localState));
|
||||
}
|
||||
}
|
||||
}
|
||||
return htmlMixedMode.token(stream, state.htmlMixedState);
|
||||
},
|
||||
|
||||
freemarker : function(stream, state) {
|
||||
if (stream.match(settings.leftDelimiter + "#--", false) ) {
|
||||
return helpers.chain(stream, state, parsers.inBlock("comment", "--"
|
||||
+ settings.rightDelimiter));
|
||||
} else if (stream.match(settings.rightDelimiter, false) ) {
|
||||
stream.eat(settings.rightDelimiter);
|
||||
state.tokenize = parsers.html;
|
||||
state.localMode = htmlMixedMode;
|
||||
state.localState = state.htmlMixedState;
|
||||
return "tag";
|
||||
} else if (stream.match("}", false) ) {
|
||||
stream.eat("}");
|
||||
state.tokenize = parsers.html;
|
||||
state.localMode = htmlMixedMode;
|
||||
state.localState = state.htmlMixedState;
|
||||
return "keyword";
|
||||
}
|
||||
|
||||
return helpers.maybeBackup(stream, regEsc(settings.rightDelimiter), freemarkerMode
|
||||
.token(stream, state.localState));
|
||||
},
|
||||
|
||||
inBlock : function(style, terminator) {
|
||||
return function(stream, state) {
|
||||
while (!stream.eol()) {
|
||||
if (stream.match(terminator) ) {
|
||||
helpers.cleanChain(stream, state, "");
|
||||
break;
|
||||
}
|
||||
stream.next();
|
||||
}
|
||||
return style;
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
startState : function() {
|
||||
var state = htmlMixedMode.startState();
|
||||
return {
|
||||
token : parsers.html, localMode : null, localState : null, htmlMixedState : state,
|
||||
tokenize : null, noparse : false
|
||||
};
|
||||
},
|
||||
|
||||
copyState : function(state) {
|
||||
var local = null , tok = (state.tokenize || state.token);
|
||||
if (state.localState ) {
|
||||
local = CodeMirror
|
||||
.copyState((tok != parsers.html ? freemarkerMode : htmlMixedMode), state.localState);
|
||||
}
|
||||
return {
|
||||
token : state.token, tokenize : state.tokenize, localMode : state.localMode,
|
||||
localState : local,
|
||||
htmlMixedState : CodeMirror.copyState(htmlMixedMode, state.htmlMixedState),
|
||||
noparse : state.noparse
|
||||
};
|
||||
},
|
||||
|
||||
token : function(stream, state) {
|
||||
if (stream.match(settings.leftDelimiter+"#", false) ) {
|
||||
if (!state.noparse && stream.match("#noparse", true)) {
|
||||
state.noparse = true;
|
||||
return "keyword";
|
||||
} else if (state.noparse && stream.match("/#noparse", true)) {
|
||||
state.noparse = false;
|
||||
return "keyword";
|
||||
}
|
||||
}
|
||||
if (state.noparse && state.localState != state.htmlMixedState ) {
|
||||
state.tokenize = parsers.html;
|
||||
state.localMode = htmlMixedMode;
|
||||
state.localState = state.htmlMixedState;
|
||||
}
|
||||
var style = (state.tokenize || state.token)(stream, state);
|
||||
return style;
|
||||
},
|
||||
|
||||
indent : function(state, textAfter) {
|
||||
if (state.localMode == freemarkerMode || (state.noparse && !state.localMode) ) {
|
||||
for (var i = 0; i < regLeftArray.length; i++) {
|
||||
if(regLeftArray[i].test(textAfter)){
|
||||
return CodeMirror.Pass;
|
||||
}
|
||||
}
|
||||
}
|
||||
return htmlMixedMode.indent(state.htmlMixedState, textAfter, "");
|
||||
},
|
||||
|
||||
innerMode : function(state) {
|
||||
return {
|
||||
state : state.localState || state.htmlMixedState,
|
||||
mode : state.localMode || htmlMixedMode
|
||||
};
|
||||
}
|
||||
};
|
||||
}, "htmlmixed", "freemarker");
|
||||
|
||||
CodeMirror.defineMIME("text/freemarker", "freemarkermixed");
|
||||
// vim: et ts=2 sts=2 sw=2
|
||||
|
||||
});
|
File diff suppressed because it is too large
Load Diff
@ -3,7 +3,7 @@
|
||||
~~~~~~licensing~~~~~~
|
||||
entaxy-management-plugin
|
||||
==========
|
||||
Copyright (C) 2020 - 2024 EmDev LLC
|
||||
Copyright (C) 2020 - 2025 EmDev LLC
|
||||
==========
|
||||
You may not use this file except in accordance with the License Terms of the Copyright
|
||||
Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* entaxy-management-plugin
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2024 EmDev LLC
|
||||
* Copyright (C) 2020 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* entaxy-management-plugin
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2024 EmDev LLC
|
||||
* Copyright (C) 2020 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* entaxy-management-plugin
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2024 EmDev LLC
|
||||
* Copyright (C) 2020 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -2,7 +2,7 @@
|
||||
~~~~~~licensing~~~~~~
|
||||
entaxy-management-plugin
|
||||
==========
|
||||
Copyright (C) 2020 - 2024 EmDev LLC
|
||||
Copyright (C) 2020 - 2025 EmDev LLC
|
||||
==========
|
||||
You may not use this file except in accordance with the License Terms of the Copyright
|
||||
Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
|
@ -2,7 +2,7 @@
|
||||
~~~~~~licensing~~~~~~
|
||||
entaxy-management-plugin
|
||||
==========
|
||||
Copyright (C) 2020 - 2024 EmDev LLC
|
||||
Copyright (C) 2020 - 2025 EmDev LLC
|
||||
==========
|
||||
You may not use this file except in accordance with the License Terms of the Copyright
|
||||
Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
|
@ -2,7 +2,7 @@
|
||||
~~~~~~licensing~~~~~~
|
||||
entaxy-management-plugin
|
||||
==========
|
||||
Copyright (C) 2020 - 2024 EmDev LLC
|
||||
Copyright (C) 2020 - 2025 EmDev LLC
|
||||
==========
|
||||
You may not use this file except in accordance with the License Terms of the Copyright
|
||||
Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
|
File diff suppressed because one or more lines are too long
@ -0,0 +1,58 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* entaxy-management-plugin
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
var 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 = {}));
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* entaxy-management-plugin
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2024 EmDev LLC
|
||||
* Copyright (C) 2020 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
|
@ -0,0 +1,163 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* entaxy-management-plugin
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
var 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': '=',
|
||||
'callback': '&contextMenu',
|
||||
'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() {
|
||||
$scope.callback({ $event: event });
|
||||
});
|
||||
|
||||
$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 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
var 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 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
var 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 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
var 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 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
var 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,39 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* entaxy-management-plugin
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
var Entaxy;
|
||||
(function (Entaxy) {
|
||||
Entaxy._module.directive('setFocused', function() {
|
||||
return {
|
||||
link: function (scope, element, attrs) {
|
||||
scope.$watch(attrs.setFocused, function (val) {
|
||||
if (angular.isDefined(val) && val) {
|
||||
setTimeout(function () { element[0].focus(); });
|
||||
}}, true);
|
||||
}
|
||||
};
|
||||
})
|
||||
.name;
|
||||
})(Entaxy || (Entaxy = {}));
|
@ -0,0 +1,62 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* entaxy-atlasmap-plugin
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
var Entaxy;
|
||||
(function (Entaxy) {
|
||||
Entaxy._module.component('entaxyEditor', {
|
||||
bindings: {
|
||||
sourceDoc: '=',
|
||||
mode: '<',
|
||||
readOnly: '<'
|
||||
},
|
||||
template:
|
||||
`
|
||||
<div hawtio-editor="source" mode="$ctrl.mode" output-editor="editor"></div>
|
||||
`,
|
||||
controller: entaxyEditorController
|
||||
})
|
||||
.name;
|
||||
|
||||
function entaxyEditorController($scope) {
|
||||
'ngInject';
|
||||
let ctrl = this;
|
||||
|
||||
ctrl.$onInit = function () {
|
||||
$scope.source = ctrl.sourceDoc;
|
||||
}
|
||||
|
||||
$scope.$watch('source', function (newValue) {
|
||||
ctrl.sourceDoc = newValue;
|
||||
});
|
||||
|
||||
setTimeout(function() {
|
||||
if (ctrl.readOnly === true) {
|
||||
$scope.editor.options.readOnly = true;
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
entaxyEditorController.$inject = ['$scope'];
|
||||
|
||||
})(Entaxy || (Entaxy = {}));
|
@ -0,0 +1,201 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* entaxy-management-plugin
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
var 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 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
var 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 = {}));
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* entaxy-management-plugin
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2024 EmDev LLC
|
||||
* Copyright (C) 2020 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
@ -29,20 +29,21 @@ var Entaxy;
|
||||
.component('entaxyFilePanel', {
|
||||
bindings: {
|
||||
items: '=',
|
||||
selectedItem: '<',
|
||||
selectedItems: '<',
|
||||
view: '<',
|
||||
changeSelectionFn: '<',
|
||||
openFn: '<',
|
||||
resourceContextMenuOptions: '<',
|
||||
admResourceContextMenuOptions: '<',
|
||||
folderContextMenuOptions: '<'
|
||||
},
|
||||
template:
|
||||
`
|
||||
<div class="file-panel no-selection" ng-class="{'tile-theme': $ctrl.view === 'tiles', 'list-theme': $ctrl.view === 'list'}">
|
||||
<div ng-class="{'tile': $ctrl.view === 'tiles', 'list': $ctrl.view === 'list', 'active': $ctrl.selectedItem === item}"
|
||||
ng-repeat="item in $ctrl.items" ng-click="$ctrl.changeSelection(item)" ng-dblclick="$ctrl.open(item)"
|
||||
context-menu item="item"
|
||||
context-menu-options="item.isFolder ? $ctrl.folderContextMenuOptions : $ctrl.resourceContextMenuOptions">
|
||||
<div ng-class="{'tile': $ctrl.view === 'tiles', 'list': $ctrl.view === 'list', 'active': $ctrl.isActive(item)}"
|
||||
ng-repeat="item in $ctrl.items" ng-click="$ctrl.changeSelection($event, item)" ng-dblclick="$ctrl.open(item)"
|
||||
context-menu="$ctrl.considerChangingSelection(item)" item="item"
|
||||
context-menu-options="$ctrl.getContextMenuOptions(item)">
|
||||
<div class="icon">
|
||||
<span ng-class="{'fa fa-folder': item.isFolder, 'fa fa-file': !item.isFolder}"></span>
|
||||
</div>
|
||||
@ -50,7 +51,7 @@ var Entaxy;
|
||||
<span class="pficon pficon-info" data-toggle="tooltip" title="{{item.error}}"></span>
|
||||
</div>
|
||||
<div class="name" ng-class="{'has-error': item.error}" data-toggle="tooltip" title="{{item.name}}">
|
||||
{{ $ctrl.view === 'tiles' ? (item.name | limitTo: 22) : item.name }}{{ ($ctrl.view === 'tiles' && item.name.length > 22) ? '...' : '' }}
|
||||
{{ $ctrl.view === 'tiles' ? (item.name | limitTo: 16) : item.name }}{{ ($ctrl.view === 'tiles' && item.name.length > 16) ? '...' : '' }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="tile empty" ng-if="$ctrl.view === 'tiles'" ng-repeat="item in $ctrl.emptyItems"></div>
|
||||
@ -67,12 +68,33 @@ var Entaxy;
|
||||
ctrl.emptyItems = [{},{},{},{},{},{},{},{}];
|
||||
}
|
||||
|
||||
ctrl.changeSelection = function (item) {
|
||||
ctrl.changeSelectionFn(item);
|
||||
ctrl.isActive = function (item) {
|
||||
return ctrl.selectedItems && ctrl.selectedItems.includes(item);
|
||||
}
|
||||
|
||||
ctrl.considerChangingSelection = function (item) {
|
||||
if (!ctrl.selectedItems.includes(item)) {
|
||||
ctrl.changeSelectionFn(item);
|
||||
}
|
||||
}
|
||||
|
||||
ctrl.changeSelection = function (clickEvent, item) {
|
||||
ctrl.changeSelectionFn(item, clickEvent.ctrlKey);
|
||||
}
|
||||
|
||||
ctrl.open = function (item) {
|
||||
ctrl.openFn(item);
|
||||
}
|
||||
|
||||
ctrl.getContextMenuOptions = function (item) {
|
||||
return item.isFolder ?
|
||||
ctrl.folderContextMenuOptions :
|
||||
isAdm(item) ? ctrl.admResourceContextMenuOptions : ctrl.resourceContextMenuOptions;
|
||||
}
|
||||
|
||||
function isAdm(item) {
|
||||
let splitName = item.name.split('.');
|
||||
return splitName.length > 1 && splitName.pop() === 'adm';
|
||||
}
|
||||
}
|
||||
})(Entaxy || (Entaxy = {}));
|
||||
|
@ -0,0 +1,61 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* entaxy-management-plugin
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
var 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,229 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* entaxy-management-plugin
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
var Entaxy;
|
||||
(function (Entaxy) {
|
||||
Entaxy._module.component('entaxyFormFields', {
|
||||
bindings: {
|
||||
items: '<',
|
||||
setFocusOn: '<',
|
||||
errors: '<',
|
||||
mode: '<',
|
||||
formController: '<',
|
||||
updateFieldsAfterSelectionChangeFn: '<'
|
||||
},
|
||||
template:
|
||||
`
|
||||
<div class="form-group"
|
||||
ng-class="{'has-error': ($ctrl.errors[formField.name] || formField.error) && 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)" ng-keydown="$ctrl.handleEnter($event)"
|
||||
set-focused="$ctrl.setFocusOn === formField.name">
|
||||
<textarea id="{{formField.name}}" class="form-control" ng-model="formField.value"
|
||||
ng-readonly="formField.readOnly" ng-if="$ctrl.isTextarea(formField)"
|
||||
set-focused="$ctrl.setFocusOn === formField.name"></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)"
|
||||
set-focused="$ctrl.setFocusOn === formField.name"></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"
|
||||
set-focused="$ctrl.setFocusOn === formField.name"></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)"
|
||||
set-focused="$ctrl.setFocusOn === formField.name"></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" set-focused="$ctrl.setFocusOn === formField.name"></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)"
|
||||
set-focused="$ctrl.setFocusOn === formField.name"></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"
|
||||
set-focused="$ctrl.setFocusOn === formField.name"></entaxy-map-input>
|
||||
<span class="help-block" ng-show="$ctrl.errors[formField.name] && formField.type !== 'list'">
|
||||
{{$ctrl.errors[formField.name]}}
|
||||
</span>
|
||||
<span class="help-block"
|
||||
ng-show="formField.error && !$ctrl.errors[formField.name] && formField.type !== 'list'">
|
||||
{{formField.error}}
|
||||
</span>
|
||||
</div>
|
||||
<div class="extra-actions" ng-class="{'col-sm-1': !formField.excludeLabel}"
|
||||
ng-if="$ctrl.shouldShowReset(formField)">
|
||||
<span class="pficon pficon-history reset-button" data-toggle="tooltip" title="Reset"
|
||||
ng-click="$ctrl.reset(formField)"></span>
|
||||
</div>
|
||||
</div>
|
||||
`,
|
||||
controller: entaxyFormFieldsController
|
||||
})
|
||||
.name;
|
||||
|
||||
function entaxyFormFieldsController(entaxyService) {
|
||||
'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);
|
||||
}
|
||||
|
||||
ctrl.handleEnter = function (event) {
|
||||
if (event.keyCode == 13) {
|
||||
event.preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
ctrl.shouldShowReset = function (formField) {
|
||||
return ctrl.isXml(formField) && !formField.readOnly && formField.dependsOn;
|
||||
}
|
||||
|
||||
ctrl.reset = function (formField) {
|
||||
let title = 'Confirm Reset';
|
||||
let message = 'Do you want to reset value of ' + formField.label + ' field to its default value?';
|
||||
|
||||
entaxyService.openConfirmationWindow(title, message).then(() => {
|
||||
let definingFormFields = entaxyService.getDefiningFormFields([formField], ctrl.items);
|
||||
entaxyService.computeDependentFormFieldValue(formField, definingFormFields);
|
||||
setDirty();
|
||||
});
|
||||
}
|
||||
|
||||
function setDirty() {
|
||||
if (ctrl.formController && !ctrl.formController.$dirty) {
|
||||
ctrl.formController.$setDirty();
|
||||
}
|
||||
}
|
||||
}
|
||||
entaxyFormFieldsController.$inject = ['entaxyService'];
|
||||
})(Entaxy || (Entaxy = {}));
|
@ -0,0 +1,107 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* entaxy-management-plugin
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
var 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,146 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* entaxy-management-plugin
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
var Entaxy;
|
||||
(function (Entaxy) {
|
||||
Entaxy._module.component('entaxyInnerObjectInput', {
|
||||
bindings: {
|
||||
model: '=',
|
||||
mode: '<',
|
||||
type: '<',
|
||||
objectFactoryFilter: '<',
|
||||
fieldName: '<',
|
||||
readonly: '<',
|
||||
setFocused: '<',
|
||||
formController: '<'
|
||||
},
|
||||
template:
|
||||
`
|
||||
<div class="input-with-button">
|
||||
<input type="text" ng-model="$ctrl.info" ng-class="{'form-control': true}"
|
||||
ng-keydown="$ctrl.handleEnter($event)" tabindex="-1" readonly>
|
||||
<span class="pficon pficon-delete" ng-click="$ctrl.clear()" ng-if="$ctrl.model"></span>
|
||||
<button class="btn-std entaxy-view-resources-form" ng-click="$ctrl.openModal()"
|
||||
ng-if="!$ctrl.readonly || $ctrl.model" set-focused="$ctrl.setFocused">
|
||||
{{$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.handleEnter = function (event) {
|
||||
if (event.keyCode == 13) {
|
||||
event.preventDefault();
|
||||
if (!ctrl.readonly || ctrl.model) {
|
||||
ctrl.openModal();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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,204 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* entaxy-management-plugin
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
var 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, entaxyHotkeysService) {
|
||||
'ngInject';
|
||||
|
||||
let ctrl = this;
|
||||
|
||||
ctrl.$onInit = function() {
|
||||
entaxyHotkeysService.setHotkeys($scope, getHotkeysConfigs());
|
||||
|
||||
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);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function getHotkeysConfigs() {
|
||||
return [
|
||||
{
|
||||
...Entaxy.getSaveHotkeyDescription(),
|
||||
callback: function (event) {
|
||||
event.preventDefault();
|
||||
ctrl.save();
|
||||
}
|
||||
}
|
||||
];
|
||||
}
|
||||
}
|
||||
entaxyInnerObjectInputModalController.$inject = ['$uibModal', '$scope', 'workspace', 'entaxyService', 'entaxyHotkeysService'];
|
||||
|
||||
})(Entaxy || (Entaxy = {}));
|
@ -0,0 +1,61 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* entaxy-management-plugin
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
var Entaxy;
|
||||
(function (Entaxy) {
|
||||
Entaxy._module.component('entaxyInputWithExtension', {
|
||||
bindings: {
|
||||
model: '=',
|
||||
modelWithoutExtension: '=',
|
||||
extension: '<',
|
||||
readonly: '<',
|
||||
setFocused: '<',
|
||||
formController: '<'
|
||||
},
|
||||
template:
|
||||
`
|
||||
<div class="input-with-extension">
|
||||
<input type="text" ng-model="$ctrl.modelWithoutExtension" class="form-control" ng-readonly="$ctrl.readonly"
|
||||
set-focused="$ctrl.setFocused" />
|
||||
<input type="text" ng-model="$ctrl.extension" class="form-control extension-input" tabindex="-1" 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 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
var 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.checkChildrenUniqueness : 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,81 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* entaxy-management-plugin
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
var 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 => {
|
||||
if (!formField.isBackRef && !formField.isHidden) {
|
||||
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,207 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* entaxy-management-plugin
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
var Entaxy;
|
||||
(function (Entaxy) {
|
||||
Entaxy._module.component('entaxyMapInput', {
|
||||
bindings: {
|
||||
model: '=',
|
||||
items: '=',
|
||||
duplicateKeys: '=',
|
||||
hasErrors: '=',
|
||||
readonly: '<',
|
||||
setFocused: '<',
|
||||
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" class="btn-std btn-std-ignore-error" ng-click="$ctrl.remove(field)"
|
||||
data-toggle="tooltip" title="Remove" ng-if="!field.removed">
|
||||
<span class="pficon pficon-delete"></span>
|
||||
</button>
|
||||
<button type="button" class="btn-std btn-std-ignore-error" 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="btn-std entaxy-map-input-add-button"
|
||||
ng-class="{'btn-std-ignore-error': $ctrl.items && $ctrl.items.length > 0}"
|
||||
ng-if="!$ctrl.readonly" ng-click="$ctrl.add()" set-focused="$ctrl.setFocused">
|
||||
<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,111 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* entaxy-management-plugin
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
var Entaxy;
|
||||
(function (Entaxy) {
|
||||
Entaxy._module.component('entaxyPasswordInput', {
|
||||
bindings: {
|
||||
name: '<',
|
||||
model: '=',
|
||||
confirmationModel: '=',
|
||||
ignoreConfirmationValue: '=',
|
||||
readonly: '<',
|
||||
setFocused: '<',
|
||||
errors: '='
|
||||
},
|
||||
template:
|
||||
`
|
||||
<div class="password-input">
|
||||
<input type="{{$ctrl.type}}" class="form-control" ng-model="$ctrl.model" ng-readonly="$ctrl.readonly"
|
||||
autocomplete="new-password" set-focused="$ctrl.setFocused">
|
||||
<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 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
var 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,236 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* entaxy-management-plugin
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
var 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
|
||||
.filter(mbean => mbean.attributes.RuntimeType === ctrl.type));
|
||||
});
|
||||
}).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) {
|
||||
Entaxy.changingFieldValueNotification(ctrl.itemType);
|
||||
}
|
||||
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,119 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* entaxy-management-plugin
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
var Entaxy;
|
||||
(function (Entaxy) {
|
||||
Entaxy._module
|
||||
.component('entaxySelectFromEnum', {
|
||||
bindings: {
|
||||
values: '<',
|
||||
isEmptyIncluded: '<',
|
||||
emptyOptionName: '<',
|
||||
model: '=',
|
||||
readonly: '<',
|
||||
setFocused: '<',
|
||||
multiple: '<',
|
||||
sortNeeded: '<'
|
||||
},
|
||||
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"
|
||||
set-focused="$ctrl.setFocused" />
|
||||
`,
|
||||
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() {
|
||||
let 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 }
|
||||
}) : [];
|
||||
|
||||
ctrl.options = options.length > 1 && ctrl.sortNeeded ?
|
||||
options.sort(Entaxy.compareBy('displayName')) : options;
|
||||
|
||||
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,93 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* entaxy-management-plugin
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
var Entaxy;
|
||||
(function (Entaxy) {
|
||||
Entaxy._module
|
||||
.component('entaxyUrlInput', {
|
||||
bindings: {
|
||||
model: '=',
|
||||
config: '<',
|
||||
readonly: '<',
|
||||
setFocused: '<',
|
||||
formController: '<'
|
||||
},
|
||||
template:
|
||||
`
|
||||
<div class="input-with-button">
|
||||
<input type="text" ng-model="$ctrl.model" ng-class="{'form-control': true}"
|
||||
ng-keydown="$ctrl.handleEnter($event)" tabindex="-1" readonly>
|
||||
<span class="pficon pficon-delete" ng-click="$ctrl.clear()" ng-if="$ctrl.model"></span>
|
||||
<button class="btn-std entaxy-view-resources-form" ng-click="$ctrl.openViewer()" ng-if="!$ctrl.readonly"
|
||||
set-focused="$ctrl.setFocused">
|
||||
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.handleEnter = function (event) {
|
||||
if (event.keyCode == 13) {
|
||||
event.preventDefault();
|
||||
if (!ctrl.readonly) {
|
||||
ctrl.openViewer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ctrl.clear = function () {
|
||||
ctrl.model = undefined;
|
||||
}
|
||||
}
|
||||
entaxyUrlInputController.$inject = ['workspace', '$uibModal'];
|
||||
|
||||
})(Entaxy || (Entaxy = {}));
|
@ -0,0 +1,81 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* entaxy-management-plugin
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
var Entaxy;
|
||||
(function (Entaxy) {
|
||||
Entaxy._module
|
||||
.component('entaxyXml', {
|
||||
bindings: {
|
||||
ngModel: '=',
|
||||
mode: '<',
|
||||
readonly: '<',
|
||||
setFocused: '<',
|
||||
formController: '<'
|
||||
},
|
||||
template:
|
||||
`
|
||||
<button class="btn-std entaxy-xml-form" ng-click="$ctrl.openEditor()" ng-disabled="$ctrl.disabled"
|
||||
set-focused="$ctrl.setFocused">
|
||||
{{$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 = {}));
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* entaxy-management-plugin
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2024 EmDev LLC
|
||||
* Copyright (C) 2020 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
@ -47,7 +47,7 @@ var Entaxy;
|
||||
<form name="entaxyObjectForm" class="form-horizontal">
|
||||
<entaxy-form-fields items="$ctrl.viewedFormFields" errors="$ctrl.errors" mode="$ctrl.mode"
|
||||
update-fields-after-selection-change-fn="$ctrl.updateFieldsAfterSelectionChange"
|
||||
form-controller="entaxyObjectForm"></entaxy-form-fields>
|
||||
form-controller="entaxyObjectForm" set-focus-on="$ctrl.setFocusOn"></entaxy-form-fields>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
@ -105,6 +105,11 @@ var Entaxy;
|
||||
ctrl.change = function(group) {
|
||||
ctrl.viewedFormFields = ctrl.fields.filter((formField) => formField.group === group.name);
|
||||
ctrl.selectedGroup = group;
|
||||
let setFocusOn = ctrl.viewedFormFields
|
||||
.find(formField => !formField.isBackRef && !formField.isHidden && !formField.readOnly);
|
||||
if (setFocusOn) {
|
||||
ctrl.setFocusOn = setFocusOn.name;
|
||||
}
|
||||
}
|
||||
|
||||
ctrl.matchesFilter = function(group, filter) {
|
||||
@ -134,11 +139,15 @@ var Entaxy;
|
||||
if (ctrl.fields && ctrl.fields.length > 1) {
|
||||
ctrl.fields.forEach(formField => {
|
||||
if (formField.ui && formField.ui.displayBlocks) {
|
||||
let managedBy = formField.ui.displayBlocksManagedBy;
|
||||
if (!displayBlocks[managedBy]) {
|
||||
displayBlocks[managedBy] = {};
|
||||
}
|
||||
formField.ui.displayBlocks.forEach(displayBlock => {
|
||||
if (!displayBlocks[displayBlock]) {
|
||||
displayBlocks[displayBlock] = [formField];
|
||||
if (!displayBlocks[managedBy][displayBlock]) {
|
||||
displayBlocks[managedBy][displayBlock] = [formField];
|
||||
} else {
|
||||
displayBlocks[displayBlock].push(formField);
|
||||
displayBlocks[managedBy][displayBlock].push(formField);
|
||||
}
|
||||
});
|
||||
if (!formField.ui.originProperties) {
|
||||
@ -154,37 +163,87 @@ var Entaxy;
|
||||
|
||||
function manageDisplayBlocks() {
|
||||
if (Object.keys(displayBlocks).length > 0) {
|
||||
ctrl.managingFields = ctrl.fields.filter(formField =>
|
||||
formField.ui && formField.ui.manageDisplayBlocksByValue);
|
||||
ctrl.managingFields = getSortedManagingFields();
|
||||
for (let i = 0; i < ctrl.managingFields.length; i++) {
|
||||
$scope.$watch('$ctrl.managingFields[' + i + '].value', function (newValue) {
|
||||
Object.keys(displayBlocks)
|
||||
Object.keys(displayBlocks[ctrl.managingFields[i].name])
|
||||
.filter(displayBlock => displayBlock !== newValue)
|
||||
.forEach(displayBlock => {
|
||||
let fieldsToHide = displayBlocks[displayBlock]
|
||||
let fieldsToHide = displayBlocks[ctrl.managingFields[i].name][displayBlock]
|
||||
.filter(fieldToHide => fieldToHide.group === ctrl.managingFields[i].group);
|
||||
fieldsToHide.forEach(formField => {
|
||||
formField.required = false;
|
||||
formField.isHidden = true;
|
||||
if (!formField.ui.transmitAlways) {
|
||||
formField.ignored = true;
|
||||
}
|
||||
});
|
||||
hideFields(fieldsToHide);
|
||||
});
|
||||
if (displayBlocks[newValue]) {
|
||||
let fieldsToDisplay = displayBlocks[newValue]
|
||||
if (displayBlocks[ctrl.managingFields[i].name][newValue]) {
|
||||
let fieldsToDisplay = displayBlocks[ctrl.managingFields[i].name][newValue]
|
||||
.filter(fieldToDisplay => fieldToDisplay.group === ctrl.managingFields[i].group);
|
||||
fieldsToDisplay.forEach(formField => {
|
||||
formField.required = formField.ui.originProperties.required;
|
||||
formField.isHidden = formField.ui.originProperties.isHidden;
|
||||
delete formField.ignored;
|
||||
});
|
||||
displayFields(fieldsToDisplay);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getSortedManagingFields () {
|
||||
let managingFields = ctrl.fields.filter(formField =>
|
||||
formField.ui && formField.ui.manageDisplayBlocksByValue);
|
||||
let managingTrees = {};
|
||||
let topManagingFields = managingFields.filter(formField => !formField.ui.displayBlocksManagedBy);
|
||||
topManagingFields.forEach(topManagingField => {
|
||||
managingTrees[topManagingField.name] = getManagingTree(topManagingField.name, managingFields);
|
||||
});
|
||||
let sorted = [];
|
||||
sortManagingFields(managingTrees, managingFields, sorted);
|
||||
return sorted;
|
||||
}
|
||||
|
||||
function getManagingTree(topManagingFieldName, managingFields) {
|
||||
let tree = {};
|
||||
managingFields
|
||||
.filter(formField => formField.ui && formField.ui.displayBlocksManagedBy === topManagingFieldName)
|
||||
.forEach(formField => {
|
||||
tree[formField.name] = getManagingTree(formField.name, managingFields);
|
||||
});
|
||||
return tree;
|
||||
}
|
||||
|
||||
function sortManagingFields(managingTrees, managingFields, sorted) {
|
||||
Object.keys(managingTrees)
|
||||
.forEach(managingFieldName => {
|
||||
sorted.unshift(managingFields.find(formField => formField.name === managingFieldName));
|
||||
sortManagingFields(managingTrees[managingFieldName], managingFields, sorted);
|
||||
});
|
||||
}
|
||||
|
||||
function hideFields(fieldsToHide) {
|
||||
fieldsToHide.forEach(formField => {
|
||||
formField.required = false;
|
||||
formField.isHidden = true;
|
||||
if (!formField.ui.transmitAlways) {
|
||||
formField.ignored = true;
|
||||
}
|
||||
if (formField.ui.manageDisplayBlocksByValue) {
|
||||
let extraFieldsToHide = displayBlocks[formField.name][formField.value];
|
||||
if (extraFieldsToHide && extraFieldsToHide.length > 0) {
|
||||
hideFields(extraFieldsToHide);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function displayFields(fieldsToDisplay) {
|
||||
fieldsToDisplay.forEach(formField => {
|
||||
formField.required = formField.ui.originProperties.required;
|
||||
formField.isHidden = formField.ui.originProperties.isHidden;
|
||||
delete formField.ignored;
|
||||
if (formField.ui.manageDisplayBlocksByValue) {
|
||||
let extraFieldsToDisplay = displayBlocks[formField.name][formField.value];
|
||||
if (extraFieldsToDisplay && extraFieldsToDisplay.length > 0) {
|
||||
displayFields(extraFieldsToDisplay);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ctrl.updateFieldsAfterSelectionChange = function (oldItem, newItem) {
|
||||
|
||||
if (oldItem) {
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* entaxy-management-plugin
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2024 EmDev LLC
|
||||
* Copyright (C) 2020 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* entaxy-management-plugin
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2024 EmDev LLC
|
||||
* Copyright (C) 2020 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
|
@ -0,0 +1,214 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* entaxy-management-plugin
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
var 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 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
var 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,156 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* entaxy-atlasmap-plugin
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
var Entaxy;
|
||||
(function (Entaxy) {
|
||||
Entaxy._module.component('entaxyCreateResourceModal', {
|
||||
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="entaxy-create-resource-fields-container">
|
||||
<div class="entaxy-create-resource-name-field-container" ng-class="{'has-error': $ctrl.errors.name}">
|
||||
<label class="control-label required-pf" for="contentName">Name</label>
|
||||
<input type="text" id="contentName" class="form-control" ng-model="$ctrl.name" set-focused="true">
|
||||
</div>
|
||||
<entaxy-select-from-enum id="contentType" ng-class="{'has-error': $ctrl.errors.type}"
|
||||
values="$ctrl.selectValues" model="$ctrl.editorMode"
|
||||
is-empty-included="false" sort-needed="true">
|
||||
</entaxy-select-from-enum>
|
||||
</div>
|
||||
<div class="entaxy-resource-editor-container">
|
||||
<entaxy-editor class="entaxy-editor" ng-class="{'has-error': $ctrl.errors.content}"
|
||||
mode="$ctrl.editorMode" source-doc="$ctrl.source">
|
||||
</entaxy-editor>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="submit" class="btn btn-primary" ng-click="$ctrl.save()">{{$ctrl.btnTitle}}</button>
|
||||
</div>
|
||||
</div>
|
||||
`,
|
||||
controller: entaxyCreateResourceModalController
|
||||
})
|
||||
.name;
|
||||
|
||||
function entaxyCreateResourceModalController($uibModal, $scope, entaxyService, entaxyHotkeysService) {
|
||||
'ngInject';
|
||||
|
||||
let ctrl = this;
|
||||
|
||||
ctrl.$onInit = function() {
|
||||
entaxyHotkeysService.setHotkeys($scope, getHotkeysConfigs());
|
||||
|
||||
ctrl.mode = Entaxy.MODAL_MODES.EDIT;
|
||||
ctrl.modalTitle = ctrl.resolve.modalTitle ? ctrl.resolve.modalTitle : 'Create resource';
|
||||
ctrl.btnTitle = 'Save';
|
||||
ctrl.selectValues = [
|
||||
'xml',
|
||||
{
|
||||
displayValue: 'json',
|
||||
value: { name: 'javascript', json: true }
|
||||
}
|
||||
];
|
||||
if (ctrl.resolve.extraTypes) {
|
||||
ctrl.selectValues = ctrl.selectValues.concat(ctrl.resolve.extraTypes);
|
||||
}
|
||||
ctrl.name = ctrl.resolve.resourceName ? ctrl.resolve.resourceName : '';
|
||||
ctrl.source = '';
|
||||
}
|
||||
|
||||
ctrl.cancel = function(reason) {
|
||||
ctrl.modalInstance.dismiss(reason);
|
||||
}
|
||||
|
||||
ctrl.save = function() {
|
||||
if (validate()) {
|
||||
ctrl.modalInstance.close({
|
||||
name: ctrl.name,
|
||||
text: ctrl.source,
|
||||
type: getType().toUpperCase()
|
||||
});
|
||||
} else {
|
||||
let fieldName = ctrl.errors.name ? 'Name' : 'Content';
|
||||
let message = ctrl.errors.type ?
|
||||
'Selected type should match the content' : fieldName + ' value should not be empty';
|
||||
Entaxy.notificationError(message);
|
||||
}
|
||||
}
|
||||
|
||||
function validate() {
|
||||
ctrl.errors = {};
|
||||
if (!ctrl.name || ctrl.name.trim().length == 0) {
|
||||
ctrl.errors.name = true;
|
||||
return false;
|
||||
}
|
||||
if (angular.isString(ctrl.source) && ctrl.source.trim().length == 0) {
|
||||
ctrl.errors.content = true;
|
||||
}
|
||||
if (!ctrl.errors.content && !isTypeFitContent()) {
|
||||
ctrl.errors.type = true;
|
||||
}
|
||||
return Object.keys(ctrl.errors).length == 0;
|
||||
}
|
||||
|
||||
function getType() {
|
||||
let selectedValue = ctrl.selectValues.find(selectValue => selectValue.value === ctrl.editorMode);
|
||||
return selectedValue !== undefined ? selectedValue.displayValue : ctrl.editorMode;
|
||||
}
|
||||
|
||||
function isTypeFitContent() {
|
||||
if (ctrl.editorMode === 'xml') {
|
||||
return entaxyService.isSupposedlyXml(ctrl.source);
|
||||
} else if (angular.isObject(ctrl.editorMode) && ctrl.editorMode.json) {
|
||||
return entaxyService.isSupposedlyJson(ctrl.source);
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
function getHotkeysConfigs() {
|
||||
return [
|
||||
{
|
||||
...Entaxy.getSaveHotkeyDescription(),
|
||||
callback: function (event) {
|
||||
event.preventDefault();
|
||||
ctrl.save();
|
||||
}
|
||||
}
|
||||
];
|
||||
}
|
||||
}
|
||||
entaxyCreateResourceModalController.$inject = ['$uibModal', '$scope', 'entaxyService', 'entaxyHotkeysService'];
|
||||
|
||||
})(Entaxy || (Entaxy = {}));
|
@ -0,0 +1,188 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* entaxy-management-plugin
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
var Entaxy;
|
||||
(function (Entaxy) {
|
||||
Entaxy._module.component('entaxyEditorModal', {
|
||||
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="syntax-highlighting-container">
|
||||
<label class="control-label" for="syntaxHighlighting">Syntax highlighting</label>
|
||||
<entaxy-select-from-enum id="syntaxHighlighting"
|
||||
values="$ctrl.selectValues" model="$ctrl.editorMode"
|
||||
is-empty-included="false" sort-needed="true"></entaxy-select-from-enum>
|
||||
</div>
|
||||
<div class="entaxy-resource-editor-container">
|
||||
<entaxy-editor class="entaxy-editor" mode="$ctrl.editorMode" source-doc="$ctrl.resourceContent">
|
||||
</entaxy-editor>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<div class="btn-group" uib-dropdown>
|
||||
<button id="split-button" type="button" class="btn btn-primary" ng-click="$ctrl.save(true)">
|
||||
Save
|
||||
</button>
|
||||
<button type="button" class="btn btn-primary" uib-dropdown-toggle>
|
||||
<span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu" uib-dropdown-menu role="menu" aria-labelledby="split-button">
|
||||
<li role="menuitem"><a ng-click="$ctrl.save(false)">Save as...</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`,
|
||||
controller: entaxyEditorModalController
|
||||
})
|
||||
.name;
|
||||
|
||||
function entaxyEditorModalController($uibModal, $scope, entaxyService, entaxyResourcesService, entaxyHotkeysService) {
|
||||
'ngInject';
|
||||
|
||||
let ctrl = this;
|
||||
|
||||
ctrl.$onInit = function() {
|
||||
entaxyHotkeysService.setHotkeys($scope, getHotkeysConfigs());
|
||||
|
||||
let ftlType = {
|
||||
displayValue: 'ftl',
|
||||
value: 'freemarkermixed'
|
||||
};
|
||||
let jsonType = {
|
||||
displayValue: 'json',
|
||||
value: { name: 'javascript', json: true }
|
||||
};
|
||||
ctrl.selectValues = [ ftlType, jsonType, 'xml', 'yaml', 'txt' ];
|
||||
|
||||
ctrl.modalTitle = 'Edit resource: ' + ctrl.resolve.resourceName;
|
||||
ctrl.resourceContent = ctrl.resolve.resourceContent;
|
||||
|
||||
ctrl.editorMode = getEditorMode(ctrl.resolve.extension);
|
||||
}
|
||||
|
||||
function getEditorMode(extension) {
|
||||
switch (extension) {
|
||||
case 'xml':
|
||||
case 'xsd':
|
||||
case 'xsl':
|
||||
case 'xslt':
|
||||
case 'wsdl':
|
||||
return 'xml';
|
||||
case 'json':
|
||||
case 'ftl':
|
||||
return ctrl.selectValues.find(value => value.displayValue === extension).value;
|
||||
case 'yaml':
|
||||
case 'txt':
|
||||
return extension;
|
||||
default:
|
||||
return 'txt';
|
||||
}
|
||||
}
|
||||
|
||||
ctrl.cancel = function(reason) {
|
||||
ctrl.modalInstance.dismiss(reason);
|
||||
}
|
||||
|
||||
ctrl.save = function(writeIntoSource) {
|
||||
if (validate()) {
|
||||
if (writeIntoSource) {
|
||||
ctrl.modalInstance.close({
|
||||
writeIntoSource: writeIntoSource,
|
||||
content: ctrl.resourceContent
|
||||
});
|
||||
} else {
|
||||
entaxyResourcesService.openResourceNameInputModal(
|
||||
{ name: ctrl.resolve.resourceName, isFolder: false },
|
||||
ctrl.resolve.names,
|
||||
true,
|
||||
false)
|
||||
.then((name) => {
|
||||
ctrl.modalInstance.close({
|
||||
writeIntoSource: writeIntoSource,
|
||||
content: ctrl.resourceContent,
|
||||
name: name
|
||||
});
|
||||
});
|
||||
}
|
||||
} else {
|
||||
let message = ctrl.errors.type ? 'Content value is invalid' : 'Content value should not be empty';
|
||||
Entaxy.notificationError(message);
|
||||
}
|
||||
}
|
||||
|
||||
function validate() {
|
||||
ctrl.errors = {};
|
||||
if (angular.isString(ctrl.resourceContent) && ctrl.resourceContent.trim().length > 0 &&
|
||||
!isTypeFitContent()) {
|
||||
ctrl.errors.type = true;
|
||||
}
|
||||
return Object.keys(ctrl.errors).length == 0;
|
||||
}
|
||||
|
||||
function isTypeFitContent() {
|
||||
if (ctrl.resolve.extension === 'xml') {
|
||||
return entaxyService.isSupposedlyXml(ctrl.resourceContent);
|
||||
} else if (ctrl.resolve.extension === 'json') {
|
||||
return entaxyService.isSupposedlyJson(ctrl.resourceContent);
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
function getHotkeysConfigs() {
|
||||
return [
|
||||
{
|
||||
...Entaxy.getSaveHotkeyDescription(),
|
||||
callback: function (event) {
|
||||
event.preventDefault();
|
||||
ctrl.save(true);
|
||||
}
|
||||
},
|
||||
{
|
||||
...Entaxy.getSaveAsHotkeyDescription(),
|
||||
callback: function (event) {
|
||||
event.preventDefault();
|
||||
ctrl.save(false);
|
||||
}
|
||||
}
|
||||
];
|
||||
}
|
||||
}
|
||||
entaxyEditorModalController.$inject = ['$uibModal', '$scope', 'entaxyService', 'entaxyResourcesService',
|
||||
'entaxyHotkeysService'];
|
||||
|
||||
})(Entaxy || (Entaxy = {}));
|
@ -0,0 +1,395 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* entaxy-management-plugin
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
var 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.containers" selected="$ctrl.selectedContainer"
|
||||
change-selection="$ctrl.changeContainerSelection" 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.selectedContainer">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.containers"
|
||||
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.containers"
|
||||
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, entaxyHotkeysService,
|
||||
entaxyPrivateObjectsCacheService, entaxyProfileDiagramService) {
|
||||
'ngInject';
|
||||
|
||||
var ctrl = this;
|
||||
|
||||
ctrl.$onInit = function() {
|
||||
|
||||
ctrl.mode = ctrl.resolve.mode;
|
||||
|
||||
if (!ctrl.mode) {
|
||||
ctrl.cancel('Mode is not defined');
|
||||
}
|
||||
|
||||
entaxyHotkeysService.setHotkeys($scope, getHotkeysConfigs());
|
||||
|
||||
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 containerType = ctrl.resolve.containerType ? ctrl.resolve.containerType : 'Container';
|
||||
|
||||
ctrl.firstStepTitle = ctrl.resolve.firstStepTitle ?
|
||||
ctrl.resolve.firstStepTitle :
|
||||
'Choose ' + containerType.toLowerCase() + ' to attach ' + ctrl.itemType.toLowerCase() + ' to';
|
||||
|
||||
ctrl.secondStepTitle = ctrl.resolve.secondStepTitle ? ctrl.resolve.secondStepTitle : 'Choose factory';
|
||||
|
||||
ctrl.thirdStepTitle = ctrl.resolve.itemName ? ctrl.mode + ' properties for ' + ctrl.resolve.itemName
|
||||
: ctrl.resolve.thirdStepTitle ? ctrl.resolve.thirdStepTitle : 'Fill in fields';
|
||||
|
||||
if (ctrl.mode !== Entaxy.MODAL_MODES.ADD || ctrl.resolve.useTemplate) {
|
||||
ctrl.properties = ctrl.resolve.info.properties;
|
||||
ctrl.configurableOnly = !ctrl.resolve.useTemplate ? ctrl.resolve.info.configurableOnly : false;
|
||||
}
|
||||
|
||||
ctrl.containers = ctrl.resolve.containers;
|
||||
|
||||
ctrl.factories = ctrl.resolve.factories ? ctrl.resolve.factories : null;
|
||||
|
||||
if (!ctrl.factories || ctrl.factories.length === 0) {
|
||||
ctrl.cancel('Factories are not found');
|
||||
} else if (ctrl.factories.length === 1) {
|
||||
ctrl.selectedFactory = ctrl.factories[0];
|
||||
}
|
||||
|
||||
ctrl.factories.sort(Entaxy.compareBy('displayName'));
|
||||
|
||||
if (ctrl.containers) {
|
||||
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.containers && container.value !== ctrl.selectedContainer.name)) {
|
||||
|
||||
ctrl.formFields = [];
|
||||
|
||||
ctrl.formFields.push({
|
||||
label: 'Factory',
|
||||
name: 'factoryId',
|
||||
type: 'text',
|
||||
description: ctrl.selectedFactory.description,
|
||||
value: ctrl.selectedFactory.displayName,
|
||||
originalValue: ctrl.selectedFactory.name,
|
||||
readOnly: true,
|
||||
required: ctrl.mode === Entaxy.MODAL_MODES.VIEW ? false : true,
|
||||
group: 'general'
|
||||
});
|
||||
|
||||
entaxyService.getFields(ctrl.selectedFactory.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.selectedContainer ?
|
||||
ctrl.selectedContainer.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);
|
||||
if (!formField.isBackRef && !formField.isHidden) {
|
||||
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) {
|
||||
Entaxy.changingFieldValueNotification('defining');
|
||||
|
||||
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();
|
||||
if (ctrl.factories.length > 1) {
|
||||
ctrl.step2 = true;
|
||||
} else if (ctrl.factories.length === 1) {
|
||||
ctrl.step1 = true;
|
||||
}
|
||||
ctrl.step3 = false;
|
||||
}
|
||||
}
|
||||
|
||||
function clearWatchers() {
|
||||
if (watchers && watchers.length > 0) {
|
||||
watchers.forEach(watcher => {
|
||||
watcher();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
ctrl.cancel = function(reason) {
|
||||
ctrl.modalInstance.dismiss(reason);
|
||||
}
|
||||
|
||||
ctrl.changeContainerSelection = function(item, isDblClicked) {
|
||||
ctrl.selectedContainer = 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 profileMBeanName = ctrl.selectedContainer ? ctrl.selectedContainer.mbeanName : undefined;
|
||||
|
||||
entaxyService.validateFields(ctrl.formFields, ctrl.selectedFactory,
|
||||
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);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function getHotkeysConfigs() {
|
||||
return [
|
||||
{
|
||||
...Entaxy.getSaveHotkeyDescription(),
|
||||
callback: function (event) {
|
||||
event.preventDefault();
|
||||
if (ctrl.mode === Entaxy.MODAL_MODES.EDIT ||
|
||||
(ctrl.mode === Entaxy.MODAL_MODES.ADD && ctrl.step3)) {
|
||||
ctrl.save();
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
...Entaxy.getBackHotkeyDescription(),
|
||||
callback: function (event) {
|
||||
event.preventDefault();
|
||||
if ((ctrl.step2 && ctrl.containers) ||
|
||||
(ctrl.step3 && (ctrl.factories.length > 1 || ctrl.containers))) {
|
||||
ctrl.back();
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
...Entaxy.getNextHotkeyDescription(),
|
||||
callback: function (event) {
|
||||
event.preventDefault();
|
||||
if ((ctrl.step1 && ctrl.selectedContainer) || (ctrl.step2 && ctrl.selectedFactory)) {
|
||||
ctrl.next();
|
||||
}
|
||||
}
|
||||
}
|
||||
];
|
||||
}
|
||||
}
|
||||
entaxyModalController.$inject = ['$scope', 'entaxyService', 'entaxyHotkeysService',
|
||||
'entaxyPrivateObjectsCacheService', 'entaxyProfileDiagramService'];
|
||||
|
||||
})(Entaxy || (Entaxy = {}));
|
@ -0,0 +1,86 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* entaxy-management-plugin
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
var 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,395 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* entaxy-management-plugin
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
var 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" ng-class="{'entaxy-resource-save-mode': $ctrl.saveMode}">
|
||||
<div class="modal-resources-viewer-container">
|
||||
<div class="modal-resources-viewer-header-container">
|
||||
<div class="provider-selector" ng-if="$ctrl.providers">
|
||||
<span>Provider:</span>
|
||||
<select class="form-control" ng-options="provider for provider in $ctrl.providers"
|
||||
ng-model="$ctrl.newProtocol" ng-change="$ctrl.onProviderSelectionChange()" />
|
||||
</div>
|
||||
<div class="navigation-creation">
|
||||
<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.folderAddingEnabled">
|
||||
<span class="pficon pficon-add-circle-o"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<entaxy-file-panel items="$ctrl.items" selected-items="$ctrl.selectedItems" view="$ctrl.view"
|
||||
change-selection-fn="$ctrl.changeSelection" open-fn="$ctrl.open"></entaxy-file-panel>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer"
|
||||
ng-class="{'has-error': $ctrl.error, 'entaxy-resource-save-mode': $ctrl.saveMode}">
|
||||
<div class="entaxy-resource-save-mode-labelled-field-container" ng-if="$ctrl.saveMode">
|
||||
<label class="control-label">Name</label>
|
||||
<div class="entaxy-resource-save-mode-field-container">
|
||||
<entaxy-input-with-extension model="$ctrl.name" set-focused="true"
|
||||
model-without-extension="$ctrl.nameWithoutExtension" extension="$ctrl.extension">
|
||||
</entaxy-input-with-extension>
|
||||
<span class="help-block" ng-if="$ctrl.error">
|
||||
{{$ctrl.error}}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary" ng-click="$ctrl.save()">{{$ctrl.btnTitle}}</button>
|
||||
</div>
|
||||
</div>
|
||||
`,
|
||||
controller: entaxyResourceViewerModalController
|
||||
})
|
||||
.name;
|
||||
|
||||
function entaxyResourceViewerModalController($uibModal, $scope, hotkeys, entaxyHotkeysService,
|
||||
entaxyResourcesService, entaxyService) {
|
||||
'ngInject';
|
||||
|
||||
let ctrl = this;
|
||||
|
||||
ctrl.$onInit = function() {
|
||||
ctrl.saveMode = ctrl.resolve.config.saveMode;
|
||||
ctrl.btnTitle = ctrl.saveMode ? 'Save' : 'Select';
|
||||
ctrl.modalTitle = ctrl.saveMode ? 'Save Resource' : 'Select Resources';
|
||||
|
||||
if (ctrl.saveMode) {
|
||||
entaxyHotkeysService.setHotkeys($scope, getHotkeysConfigs());
|
||||
} else {
|
||||
hotkeys.pause();
|
||||
}
|
||||
|
||||
ctrl.view = 'tiles';
|
||||
ctrl.protocol = ctrl.resolve.config.resourceProvider;
|
||||
setProviderMbeanName();
|
||||
|
||||
if (ctrl.resolve.config.providersSelectionEnabled) {
|
||||
ctrl.newProtocol = ctrl.protocol;
|
||||
populateProviders();
|
||||
}
|
||||
|
||||
ctrl.filter = ctrl.resolve.config.filter;
|
||||
|
||||
ctrl.folderSelectionEnabled = ctrl.resolve.config.folderSelectionEnabled;
|
||||
ctrl.folderAddingEnabled = ctrl.resolve.config.folderAddingEnabled;
|
||||
ctrl.multipleSelectionEnabled = ctrl.resolve.config.multipleSelectionEnabled;
|
||||
|
||||
if (ctrl.saveMode) {
|
||||
ctrl.extension = ctrl.filter.slice(1);
|
||||
}
|
||||
|
||||
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.saveMode) {
|
||||
let lastPathItem = splitPath[splitPath.length - 1];
|
||||
if (lastPathItem.endsWith(ctrl.extension)) {
|
||||
ctrl.nameWithoutExtension = lastPathItem
|
||||
.substring(0, lastPathItem.lastIndexOf(ctrl.extension));
|
||||
splitPath.pop();
|
||||
}
|
||||
}
|
||||
if (!ctrl.folderSelectionEnabled) {
|
||||
splitPath.pop();
|
||||
}
|
||||
// todo else check if the last item in path is folder or not
|
||||
ctrl.crumbs = splitPath;
|
||||
} else {
|
||||
ctrl.crumbs = [];
|
||||
}
|
||||
} else {
|
||||
ctrl.crumbs = [];
|
||||
}
|
||||
}
|
||||
|
||||
function populateProviders() {
|
||||
entaxyResourcesService.getProviders()
|
||||
.then(result => {
|
||||
ctrl.providers = JSON.parse(result);
|
||||
})
|
||||
.catch(error => {
|
||||
Entaxy.log.error(error);
|
||||
Entaxy.notificationError(error)
|
||||
});
|
||||
}
|
||||
|
||||
function setProviderMbeanName() {
|
||||
let provider = entaxyResourcesService.getProviderMbean(ctrl.protocol);
|
||||
ctrl.providerMBeanName = provider.objectName;
|
||||
}
|
||||
|
||||
ctrl.providerCrumbsCache = {};
|
||||
|
||||
ctrl.onProviderSelectionChange = function () {
|
||||
ctrl.providerCrumbsCache[ctrl.protocol] = ctrl.crumbs;
|
||||
let forceUpdate = entaxyResourcesService.getPath(ctrl.providerCrumbsCache[ctrl.protocol]) ===
|
||||
entaxyResourcesService.getPath(ctrl.providerCrumbsCache[ctrl.newProtocol]);
|
||||
ctrl.protocol = ctrl.newProtocol;
|
||||
setProviderMbeanName();
|
||||
ctrl.crumbs = ctrl.providerCrumbsCache[ctrl.newProtocol] ? ctrl.providerCrumbsCache[ctrl.newProtocol] : [];
|
||||
if (forceUpdate) {
|
||||
onCrumbsUpdated();
|
||||
}
|
||||
}
|
||||
|
||||
$scope.$watchCollection('$ctrl.crumbs', function(newValue, oldValue) {
|
||||
onCrumbsUpdated();
|
||||
});
|
||||
|
||||
function onCrumbsUpdated() {
|
||||
ctrl.selectedItems = [];
|
||||
updateItems();
|
||||
}
|
||||
|
||||
$scope.$watch('$ctrl.name', function () {
|
||||
if (ctrl.saveMode && ctrl.selectedItems.length == 1 && ctrl.name !== ctrl.selectedItems[0].name) {
|
||||
ctrl.selectedItems = [];
|
||||
}
|
||||
});
|
||||
|
||||
ctrl.changeSelection = function (item, isMultiple) {
|
||||
if (!item.error) {
|
||||
if (!isMultiple) {
|
||||
ctrl.selectedItems = [ item ];
|
||||
if (ctrl.saveMode && !item.isFolder) {
|
||||
ctrl.nameWithoutExtension = item.name.substring(0, item.name.lastIndexOf(ctrl.extension));
|
||||
}
|
||||
} else {
|
||||
if (ctrl.multipleSelectionEnabled && ctrl.selectedItems && ctrl.selectedItems.length > 0) {
|
||||
if (ctrl.selectedItems.includes(item)) {
|
||||
ctrl.selectedItems = ctrl.selectedItems.filter(it => it.name !== item.name);
|
||||
} else {
|
||||
ctrl.selectedItems.push(item);
|
||||
}
|
||||
} else {
|
||||
ctrl.selectedItems = [ 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.folderAddingEnabled && 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.saveMode) {
|
||||
if (ctrl.items.find(item => item.name === ctrl.name)) {
|
||||
let title = 'Confirm Saving';
|
||||
let message = 'Resource with name ' + ctrl.name + ' already exists.' +
|
||||
' Do you want to replace it?';
|
||||
entaxyService.openConfirmationWindow(title, message).then(() => {
|
||||
save();
|
||||
});
|
||||
} else {
|
||||
save();
|
||||
}
|
||||
} else {
|
||||
save();
|
||||
}
|
||||
}
|
||||
|
||||
function save() {
|
||||
if (!validate()) {
|
||||
return;
|
||||
}
|
||||
if (ctrl.selectedItems && ctrl.selectedItems.length > 0) {
|
||||
let locations = [];
|
||||
ctrl.selectedItems.forEach(selectedItem => {
|
||||
if (!selectedItem.isFolder || ctrl.folderSelectionEnabled) {
|
||||
let path = entaxyResourcesService.getPath(ctrl.crumbs);
|
||||
let folderLocation = getFolderLocation(path);
|
||||
let separator = path.length > 0 ? '/' : '';
|
||||
let location = folderLocation + separator + selectedItem.name;
|
||||
locations.push(location);
|
||||
}
|
||||
});
|
||||
if (locations.length > 0) {
|
||||
ctrl.modalInstance.close(ctrl.multipleSelectionEnabled ? locations : locations[0]);
|
||||
}
|
||||
} else {
|
||||
if (ctrl.folderSelectionEnabled) {
|
||||
let path = entaxyResourcesService.getPath(ctrl.crumbs);
|
||||
let folderLocation = getFolderLocation(path);
|
||||
if (ctrl.saveMode) {
|
||||
if (!folderLocation.endsWith(ctrl.extension)) {
|
||||
folderLocation += '/' + ctrl.name;
|
||||
}
|
||||
}
|
||||
ctrl.modalInstance.close(ctrl.multipleSelectionEnabled ? [ folderLocation ] : folderLocation);
|
||||
} else {
|
||||
Entaxy.notificationError('There is no selected resource');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getFolderLocation(path) {
|
||||
return ctrl.useShortUrl ? ctrl.protocol + ':' + path : 'entaxy-resource://' + ctrl.protocol + '/' + path;
|
||||
}
|
||||
|
||||
function validate() {
|
||||
ctrl.error = undefined;
|
||||
if (ctrl.saveMode) {
|
||||
if (!ctrl.nameWithoutExtension || ctrl.nameWithoutExtension.trim().length == 0) {
|
||||
ctrl.error = Entaxy.ERROR_MESSAGE.EMPTY;
|
||||
}
|
||||
if (!ctrl.error) {
|
||||
['/', '\\', ':', '*', '?', '<', '>', '|'].forEach((symbol) => {
|
||||
if (ctrl.nameWithoutExtension.indexOf(symbol) >= 0) {
|
||||
ctrl.error = 'Must not include symbols /\\:*?<>|';
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
return ctrl.error ? false : true;
|
||||
}
|
||||
|
||||
$scope.$on('$destroy', function() {
|
||||
if (!ctrl.saveMode) {
|
||||
hotkeys.unpause();
|
||||
}
|
||||
});
|
||||
|
||||
function getHotkeysConfigs() {
|
||||
return [
|
||||
{
|
||||
...Entaxy.getSaveHotkeyDescription(),
|
||||
callback: function (event) {
|
||||
event.preventDefault();
|
||||
ctrl.save();
|
||||
}
|
||||
}
|
||||
];
|
||||
}
|
||||
}
|
||||
entaxyResourceViewerModalController.$inject = ['$uibModal', '$scope', 'hotkeys', 'entaxyHotkeysService',
|
||||
'entaxyResourcesService', 'entaxyService'];
|
||||
|
||||
})(Entaxy || (Entaxy = {}));
|
@ -0,0 +1,137 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* entaxy-management-plugin
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
var 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.getSetName" ng-if="!$ctrl.extension"
|
||||
ng-model-options="{getterSetter: true}" ng-trim="false" set-focused="true">
|
||||
<entaxy-input-with-extension model="$ctrl.name" ng-if="$ctrl.extension" set-focused="true"
|
||||
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($scope, $uibModal, entaxyHotkeysService) {
|
||||
'ngInject';
|
||||
|
||||
let ctrl = this;
|
||||
|
||||
ctrl.$onInit = function() {
|
||||
entaxyHotkeysService.setHotkeys($scope, getHotkeysConfigs());
|
||||
|
||||
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.getSetName = function (newName) {
|
||||
return angular.isDefined(newName) ?
|
||||
(ctrl.name = ctrl.resolve.replaceSpaces ? newName.replace(' ', '_') : newName) : ctrl.name;
|
||||
}
|
||||
|
||||
ctrl.cancel = function(reason) {
|
||||
ctrl.modalInstance.dismiss(reason);
|
||||
}
|
||||
|
||||
ctrl.save = function() {
|
||||
ctrl.error = validate();
|
||||
if (!ctrl.error) {
|
||||
ctrl.modalInstance.close(ctrl.resolve.replaceSpaces ? ctrl.name : ctrl.name.trim());
|
||||
}
|
||||
}
|
||||
|
||||
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 + ' name must be unique';
|
||||
}
|
||||
});
|
||||
return error;
|
||||
}
|
||||
|
||||
function isEmpty(value) {
|
||||
return !value || value.length == 0 || value.trim().length == 0;
|
||||
}
|
||||
|
||||
function getHotkeysConfigs() {
|
||||
return [
|
||||
{
|
||||
...Entaxy.getSaveHotkeyDescription(),
|
||||
callback: function (event) {
|
||||
event.preventDefault();
|
||||
ctrl.save();
|
||||
}
|
||||
}
|
||||
];
|
||||
}
|
||||
}
|
||||
entaxySimpleResourceNameInputModalController.$inject = ['$scope', '$uibModal', 'entaxyHotkeysService'];
|
||||
|
||||
})(Entaxy || (Entaxy = {}));
|
@ -0,0 +1,103 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* entaxy-management-plugin
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
var 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="entaxy-editor-container">
|
||||
<entaxy-xml-editor class="entaxy-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.btnTitle}}</button>
|
||||
</div>
|
||||
</div>
|
||||
`,
|
||||
controller: entaxyXmlModalController
|
||||
})
|
||||
.name;
|
||||
|
||||
function entaxyXmlModalController($uibModal, $scope, entaxyHotkeysService) {
|
||||
'ngInject';
|
||||
|
||||
let ctrl = this;
|
||||
|
||||
ctrl.$onInit = function() {
|
||||
entaxyHotkeysService.setHotkeys($scope, getHotkeysConfigs());
|
||||
|
||||
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');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getHotkeysConfigs() {
|
||||
return [
|
||||
{
|
||||
...Entaxy.getSaveHotkeyDescription(),
|
||||
callback: function (event) {
|
||||
event.preventDefault();
|
||||
ctrl.save();
|
||||
}
|
||||
}
|
||||
];
|
||||
}
|
||||
}
|
||||
entaxyXmlModalController.$inject = ['$uibModal', '$scope', 'entaxyHotkeysService'];
|
||||
|
||||
})(Entaxy || (Entaxy = {}));
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* entaxy-management-plugin
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2024 EmDev LLC
|
||||
* Copyright (C) 2020 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
@ -379,9 +379,12 @@ var Entaxy;
|
||||
when(TAB_CONFIG.routeProperties.route,
|
||||
{ template: '<entaxy-properties item-name="Route"></entaxy-properties>' }).
|
||||
when(TAB_CONFIG.resources.route,
|
||||
{ template: '<entaxy-resources></entaxy-resources>' }).
|
||||
{
|
||||
template: '<entaxy-resources></entaxy-resources>',
|
||||
reloadOnSearch: false
|
||||
}).
|
||||
when(TAB_CONFIG.services.route,
|
||||
{ template: '<entaxy-services page-title="Services"></entaxy-services>' }).
|
||||
{ template: '<entaxy-services page-title="Services and Clients"></entaxy-services>' }).
|
||||
when(TAB_CONFIG.serviceProperties.route,
|
||||
{ template: '<entaxy-properties item-name="Service"></entaxy-properties>' }).
|
||||
when(TAB_CONFIG.realms.route,
|
||||
@ -483,7 +486,7 @@ var TAB_CONFIG = {
|
||||
route: '/entaxy-management/resources'
|
||||
},
|
||||
services: {
|
||||
title: 'Services',
|
||||
title: 'Services and Clients',
|
||||
route: '/entaxy-management/services'
|
||||
},
|
||||
serviceProperties: {
|
||||
|
@ -0,0 +1,57 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* entaxy-management-plugin
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
var Entaxy;
|
||||
(function (Entaxy) {
|
||||
Entaxy._module.component('entaxyConnectorBlock', {
|
||||
transclude: true,
|
||||
bindings: {
|
||||
direction: '<',
|
||||
connector: '<',
|
||||
editConnectorPropertiesFn: '<',
|
||||
saveConnectorFn: '<'
|
||||
},
|
||||
template:
|
||||
`
|
||||
<div class="connector-block" ng-class="{'has-changes': $ctrl.connector.isChanged}"
|
||||
ng-click="$ctrl.editConnectorPropertiesFn($ctrl.connector, $event)">
|
||||
<div class="connector-info">
|
||||
<div class="connector-title-container">
|
||||
<span class="profile-diagram-support-span" ng-if="$ctrl.connector.isChanged"></span>
|
||||
<span class="bold connector-title" data-toggle="tooltip" title="{{$ctrl.connector.displayName}}">
|
||||
{{$ctrl.connector.displayName}}
|
||||
</span>
|
||||
<span class="pficon pficon-save" ng-click="$ctrl.saveConnectorFn($ctrl.connector, $event)"
|
||||
data-toggle="tooltip" title="Save connector changes" ng-if="$ctrl.connector.isChanged"></span>
|
||||
</div>
|
||||
<span class="connector-classifier">{{$ctrl.connector.classifier}}</span>
|
||||
</div>
|
||||
<ng-transclude></ng-transclude>
|
||||
</div>
|
||||
`
|
||||
})
|
||||
.name;
|
||||
|
||||
})(Entaxy || (Entaxy = {}));
|
@ -0,0 +1,148 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* entaxy-management-plugin
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
var 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">
|
||||
<entaxy-normal-connector-block ng-repeat="connector in $ctrl.connectors"
|
||||
ng-if="!connector.isCustom" direction="$ctrl.direction" connector="connector"
|
||||
edit-connector-properties-fn="$ctrl.editConnectorProperties"
|
||||
save-connector-fn="$ctrl.saveConnector"
|
||||
edit-connector-customization-point-fn="$ctrl.editConnectorCustomizationPoint">
|
||||
</entaxy-normal-connector-block>
|
||||
<entaxy-custom-connector-block ng-repeat="connector in $ctrl.connectors"
|
||||
ng-if="connector.isCustom" direction="$ctrl.direction" connector="connector"
|
||||
edit-connector-properties-fn="$ctrl.editConnectorProperties"
|
||||
save-connector-fn="$ctrl.saveConnector"
|
||||
edit-connector-customization-point-fn="$ctrl.editConnectorCustomizationPoint">
|
||||
</entaxy-custom-connector-block>
|
||||
</div>
|
||||
<entaxy-in-flow-block ng-if="$ctrl.isDirectionIn"
|
||||
edit-profile-properties-fn="$ctrl.editProfileProperties"
|
||||
edit-flow-customization-point-fn="$ctrl.editFlowCustomizationPoint"></entaxy-in-flow-block>
|
||||
<entaxy-out-flow-block ng-if="!$ctrl.isDirectionIn"
|
||||
edit-profile-properties-fn="$ctrl.editProfileProperties"
|
||||
edit-flow-customization-point-fn="$ctrl.editFlowCustomizationPoint"></entaxy-out-flow-block>
|
||||
</div>
|
||||
</div>
|
||||
`,
|
||||
controller: entaxyConnectorsWithFlowController
|
||||
})
|
||||
.name;
|
||||
|
||||
function entaxyConnectorsWithFlowController(workspace) {
|
||||
'ngInject';
|
||||
|
||||
let ctrl = this;
|
||||
|
||||
ctrl.$onInit = function() {
|
||||
if (ctrl.direction) {
|
||||
ctrl.isDirectionIn = ctrl.direction === 'in';
|
||||
ctrl.connectorsGroupTitle = '--- ' + ctrl.direction.toUpperCase() + ' ---';
|
||||
} 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';
|
||||
case 'custom-route':
|
||||
return ctrl.isDirectionIn ? 'customInputRoute' : 'customOutputRoute';
|
||||
};
|
||||
}
|
||||
|
||||
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,74 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* entaxy-management-plugin
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
var Entaxy;
|
||||
(function (Entaxy) {
|
||||
Entaxy._module.component('entaxyCustomConnectorBlock', {
|
||||
transclude: true,
|
||||
bindings: {
|
||||
direction: '<',
|
||||
connector: '<',
|
||||
editConnectorPropertiesFn: '<',
|
||||
saveConnectorFn: '<',
|
||||
editConnectorCustomizationPointFn: '<'
|
||||
},
|
||||
template:
|
||||
`
|
||||
<entaxy-connector-block direction="$ctrl.direction" connector="$ctrl.connector"
|
||||
edit-connector-properties-fn="$ctrl.editConnectorPropertiesFn"
|
||||
save-connector-fn="$ctrl.saveConnectorFn">
|
||||
<div class="custom-connector-customization-points-container" ng-if="$ctrl.connector.isCustom">
|
||||
<div id="{{$ctrl.connector.name}}_{{$ctrl.customConnectorCustomizationPoints[0]}}"
|
||||
class="customization-point-block"
|
||||
ng-click="$ctrl.editConnectorCustomizationPointFn($ctrl.connector, $ctrl.customConnectorCustomizationPoints[0], $event)">
|
||||
{{$ctrl.customConnectorCustomizationPoints[0]}}
|
||||
</div>
|
||||
<div id="{{$ctrl.connector.name}}_{{$ctrl.customConnectorCustomizationPoints[1]}}"
|
||||
class="customization-point-block"
|
||||
ng-click="$ctrl.editConnectorCustomizationPointFn($ctrl.connector, $ctrl.customConnectorCustomizationPoints[1], $event)">
|
||||
{{$ctrl.customConnectorCustomizationPoints[1]}}
|
||||
</div>
|
||||
</div>
|
||||
<div id="{{$ctrl.connector.name}}_{{$ctrl.customConnectorCustomizationPoints[2]}}"
|
||||
class="customization-point-block" ng-if="$ctrl.connector.isCustom"
|
||||
ng-click="$ctrl.editConnectorCustomizationPointFn($ctrl.connector, $ctrl.customConnectorCustomizationPoints[2], $event)">
|
||||
{{$ctrl.customConnectorCustomizationPoints[2]}}
|
||||
</div>
|
||||
</entaxy-connector-block>
|
||||
`,
|
||||
controller: entaxyCustomConnectorBlockController
|
||||
})
|
||||
.name;
|
||||
|
||||
function entaxyCustomConnectorBlockController() {
|
||||
let ctrl = this;
|
||||
|
||||
ctrl.$onInit = function() {
|
||||
ctrl.customConnectorCustomizationPoints = ctrl.direction === 'in' ?
|
||||
['custom-route', 'pre-route', 'response'] : ['custom-route', 'pre-output', 'postprocess'];
|
||||
}
|
||||
}
|
||||
|
||||
})(Entaxy || (Entaxy = {}));
|
@ -0,0 +1,49 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* entaxy-management-plugin
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
var 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>
|
||||
`
|
||||
})
|
||||
.name;
|
||||
|
||||
})(Entaxy || (Entaxy = {}));
|
@ -0,0 +1,46 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* entaxy-management-plugin
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
var Entaxy;
|
||||
(function (Entaxy) {
|
||||
Entaxy._module.component('entaxyFlowBlock', {
|
||||
transclude: true,
|
||||
bindings: {
|
||||
direction: '<',
|
||||
flowName: '<',
|
||||
editProfilePropertiesFn: '<'
|
||||
},
|
||||
template:
|
||||
`
|
||||
<div id="{{$ctrl.direction}}-flow-block" class="flow-block"
|
||||
ng-click="$ctrl.editProfilePropertiesFn($ctrl.direction + '-flow', $event)">
|
||||
<span>{{$ctrl.flowName}}</span>
|
||||
<ng-transclude></ng-transclude>
|
||||
</div>
|
||||
`
|
||||
})
|
||||
.name;
|
||||
|
||||
})(Entaxy || (Entaxy = {}));
|
@ -0,0 +1,58 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* entaxy-management-plugin
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
var Entaxy;
|
||||
(function (Entaxy) {
|
||||
Entaxy._module.component('entaxyInFlowBlock', {
|
||||
bindings: {
|
||||
editProfilePropertiesFn: '<',
|
||||
editFlowCustomizationPointFn: '<'
|
||||
},
|
||||
template:
|
||||
`
|
||||
<entaxy-flow-block direction="$ctrl.direction" flow-name="$ctrl.flowName"
|
||||
edit-profile-properties-fn="$ctrl.editProfilePropertiesFn">
|
||||
<div id="{{$ctrl.direction}}-flow_{{customizationPoint}}" class="customization-point-block"
|
||||
ng-repeat="customizationPoint in $ctrl.inFlowCustomizationPoints"
|
||||
ng-click="$ctrl.editFlowCustomizationPointFn(customizationPoint, $event)">
|
||||
{{customizationPoint}}
|
||||
</div>
|
||||
</entaxy-flow-block>
|
||||
`,
|
||||
controller: entaxyInFlowBlockController
|
||||
})
|
||||
.name;
|
||||
|
||||
function entaxyInFlowBlockController() {
|
||||
let ctrl = this;
|
||||
|
||||
ctrl.$onInit = function() {
|
||||
ctrl.direction = 'in';
|
||||
ctrl.flowName = 'IN-FLOW';
|
||||
ctrl.inFlowCustomizationPoints = ['pre-route', 'response'];
|
||||
}
|
||||
}
|
||||
|
||||
})(Entaxy || (Entaxy = {}));
|
@ -0,0 +1,62 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* entaxy-management-plugin
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
var Entaxy;
|
||||
(function (Entaxy) {
|
||||
Entaxy._module.component('entaxyNormalConnectorBlock', {
|
||||
transclude: true,
|
||||
bindings: {
|
||||
direction: '<',
|
||||
connector: '<',
|
||||
editConnectorPropertiesFn: '<',
|
||||
saveConnectorFn: '<',
|
||||
editConnectorCustomizationPointFn: '<'
|
||||
},
|
||||
template:
|
||||
`
|
||||
<entaxy-connector-block direction="$ctrl.direction" connector="$ctrl.connector"
|
||||
edit-connector-properties-fn="$ctrl.editConnectorPropertiesFn"
|
||||
save-connector-fn="$ctrl.saveConnectorFn">
|
||||
<div ng-repeat="customizationPoint in $ctrl.connectorCustomizationPoints"
|
||||
id="{{$ctrl.connector.name}}_{{customizationPoint}}" class="customization-point-block"
|
||||
ng-click="$ctrl.editConnectorCustomizationPointFn($ctrl.connector, customizationPoint, $event)">
|
||||
{{customizationPoint}}
|
||||
</div>
|
||||
</entaxy-connector-block>
|
||||
`,
|
||||
controller: entaxyNormalConnectorBlockController
|
||||
})
|
||||
.name;
|
||||
|
||||
function entaxyNormalConnectorBlockController() {
|
||||
let ctrl = this;
|
||||
|
||||
ctrl.$onInit = function() {
|
||||
ctrl.connectorCustomizationPoints = ctrl.direction === 'in' ?
|
||||
['pre-route', 'response'] : ['pre-output', 'postprocess'];
|
||||
}
|
||||
}
|
||||
|
||||
})(Entaxy || (Entaxy = {}));
|
@ -0,0 +1,73 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* entaxy-management-plugin
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
var Entaxy;
|
||||
(function (Entaxy) {
|
||||
Entaxy._module.component('entaxyOutFlowBlock', {
|
||||
bindings: {
|
||||
editProfilePropertiesFn: '<',
|
||||
editFlowCustomizationPointFn: '<'
|
||||
},
|
||||
template:
|
||||
`
|
||||
<entaxy-flow-block direction="$ctrl.direction" flow-name="$ctrl.flowName"
|
||||
edit-profile-properties-fn="$ctrl.editProfilePropertiesFn">
|
||||
<div class="{{$ctrl.direction}}-flow-customization-points-container">
|
||||
<div id="{{$ctrl.direction}}-flow_{{$ctrl.connectorSelector}}"
|
||||
class="customization-point-block {{$ctrl.connectorSelector}}"
|
||||
ng-click="$ctrl.editFlowCustomizationPointFn($ctrl.connectorSelector, $event)"
|
||||
data-toggle="tooltip" title="{{$ctrl.connectorSelector}}">
|
||||
<span class="{{$ctrl.connectorSelector}}-icon"></span>
|
||||
</div>
|
||||
<div id="{{$ctrl.direction}}-flow_{{$ctrl.preRoute}}"
|
||||
class="customization-point-block {{$ctrl.preRoute}}"
|
||||
ng-click="$ctrl.editFlowCustomizationPointFn($ctrl.preRoute, $event)">
|
||||
{{$ctrl.preRoute}}
|
||||
</div>
|
||||
</div>
|
||||
<div id="{{$ctrl.direction}}-flow_{{$ctrl.postprocess}}"
|
||||
class="customization-point-block"
|
||||
ng-click="$ctrl.editFlowCustomizationPointFn($ctrl.postprocess, $event)">
|
||||
{{$ctrl.postprocess}}
|
||||
</div>
|
||||
</entaxy-flow-block>
|
||||
`,
|
||||
controller: entaxyOutFlowBlockController
|
||||
})
|
||||
.name;
|
||||
|
||||
function entaxyOutFlowBlockController() {
|
||||
let ctrl = this;
|
||||
|
||||
ctrl.$onInit = function() {
|
||||
ctrl.direction = 'out';
|
||||
ctrl.flowName = 'OUT-FLOW';
|
||||
ctrl.connectorSelector = 'connector-selector';
|
||||
ctrl.preRoute = 'pre-route';
|
||||
ctrl.postprocess = 'postprocess';
|
||||
}
|
||||
}
|
||||
|
||||
})(Entaxy || (Entaxy = {}));
|
@ -0,0 +1,713 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* entaxy-management-plugin
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
var Entaxy;
|
||||
(function (Entaxy) {
|
||||
Entaxy._module.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,
|
||||
isCustom: mbean.attributes.ObjectLabel ? // fixme object label is bad attr for this purpose
|
||||
mbean.attributes.ObjectLabel.split(',').includes('custom') : false
|
||||
};
|
||||
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) => {
|
||||
|
||||
if (connector.isCustom) {
|
||||
lines.push(new LeaderLine(
|
||||
LeaderLine.pointAnchor(
|
||||
document.getElementById('source-' + connector.name + '-block'),
|
||||
{x: '100%', y: 11}
|
||||
),
|
||||
document.getElementById(connector.name + '_custom-route'),
|
||||
{color: 'green', size: 2, path: 'straight'}
|
||||
));
|
||||
lines.push(new LeaderLine(
|
||||
document.getElementById(connector.name + '_custom-route'),
|
||||
document.getElementById(connector.name + '_pre-route'),
|
||||
{color: 'green', size: 2, path: 'straight'}
|
||||
));
|
||||
} else {
|
||||
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) => {
|
||||
|
||||
if (connector.isCustom) {
|
||||
lines.push(new LeaderLine(
|
||||
document.getElementById(connector.name + '_custom-route'),
|
||||
LeaderLine.pointAnchor(
|
||||
document.getElementById('target-' + connector.name + '-block'),
|
||||
{x: '100%', y: 11}
|
||||
),
|
||||
{color: 'green', size: 2, path: 'straight'}
|
||||
));
|
||||
lines.push(new LeaderLine(
|
||||
document.getElementById(connector.name + '_pre-output'),
|
||||
document.getElementById(connector.name + '_custom-route'),
|
||||
{color: 'green', size: 2, path: 'straight'}
|
||||
));
|
||||
} else {
|
||||
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,156 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* entaxy-management-plugin
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
var 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.replace(/(<([^>]+)>)/ig, '') :
|
||||
'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 = {}));
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* entaxy-management-plugin
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2024 EmDev LLC
|
||||
* Copyright (C) 2020 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
@ -61,13 +61,14 @@ var Entaxy;
|
||||
})
|
||||
.name;
|
||||
|
||||
function entaxyPropertiesController($scope, workspace, entaxyService, jolokia, $location, $route,
|
||||
function entaxyPropertiesController($scope, workspace, entaxyService, jolokia, $location, $route, entaxyHotkeysService,
|
||||
entaxyAttributesCacheService, entaxyPrivateObjectsCacheService) {
|
||||
'ngInject';
|
||||
|
||||
let ctrl = this;
|
||||
|
||||
ctrl.$onInit = function() {
|
||||
entaxyHotkeysService.setHotkeys($scope, getHotkeysConfigs());
|
||||
|
||||
ctrl.mode = Entaxy.MODAL_MODES.EDIT;
|
||||
|
||||
@ -100,13 +101,19 @@ var Entaxy;
|
||||
ctrl.hasChangedPrivateObjects = true;
|
||||
}
|
||||
|
||||
entaxyService.readObjectClusterState(mbeanName).then(objectClusterState => {
|
||||
if (objectClusterState !== Entaxy.OBJECT_CLUSTER_STATE.NON_CLUSTERED) {
|
||||
ctrl.local = objectClusterState === Entaxy.OBJECT_CLUSTER_STATE.LOCAL;
|
||||
} else {
|
||||
ctrl.mode = Entaxy.MODAL_MODES.VIEW;
|
||||
}
|
||||
}).catch(e => Entaxy.notificationError(e));
|
||||
if (attributes.RuntimeType === Entaxy.RUNTIME_TYPE.CONNECTION && attributes.Platform) {
|
||||
ctrl.mode = Entaxy.MODAL_MODES.VIEW;
|
||||
}
|
||||
|
||||
if (ctrl.mode !== Entaxy.MODAL_MODES.VIEW) {
|
||||
entaxyService.readObjectClusterState(mbeanName).then(objectClusterState => {
|
||||
if (objectClusterState !== Entaxy.OBJECT_CLUSTER_STATE.NON_CLUSTERED) {
|
||||
ctrl.local = objectClusterState === Entaxy.OBJECT_CLUSTER_STATE.LOCAL;
|
||||
} else {
|
||||
ctrl.mode = Entaxy.MODAL_MODES.VIEW;
|
||||
}
|
||||
}).catch(e => Entaxy.notificationError(e));
|
||||
}
|
||||
|
||||
if (!ctrl.itemInfo) {
|
||||
entaxyService.readConfiguration(mbeanName)
|
||||
@ -174,7 +181,9 @@ var Entaxy;
|
||||
ctrl.itemInfo.configurableOnly, ctrl.mode);
|
||||
if (formField) {
|
||||
ctrl.formFields.push(formField);
|
||||
groups.add(formField.group);
|
||||
if (!formField.isBackRef && !formField.isHidden) {
|
||||
groups.add(formField.group);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@ -203,6 +212,8 @@ var Entaxy;
|
||||
}
|
||||
$scope.$watch('$ctrl.definingFormFields[' + i + '].value', function(newValue, oldValue) {
|
||||
if (newValue !== oldValue) {
|
||||
Entaxy.changingFieldValueNotification('defining');
|
||||
|
||||
entaxyService.processDependencies(dependentFormFields,
|
||||
ctrl.definingFormFields,
|
||||
ctrl.definingFormFields[i].name,
|
||||
@ -244,7 +255,7 @@ var Entaxy;
|
||||
}
|
||||
|
||||
function save() {
|
||||
entaxyService.validateFields(ctrl.formFields, ctrl.factories[0], ctrl.itemName)
|
||||
entaxyService.validateFields(ctrl.formFields, ctrl.factories[0])
|
||||
.then(errors => {
|
||||
ctrl.errors = errors;
|
||||
|
||||
@ -284,7 +295,7 @@ var Entaxy;
|
||||
}
|
||||
|
||||
function saveAll() {
|
||||
entaxyService.validateFields(ctrl.formFields, ctrl.factories[0], ctrl.itemName)
|
||||
entaxyService.validateFields(ctrl.formFields, ctrl.factories[0])
|
||||
.then(errors => {
|
||||
ctrl.errors = errors;
|
||||
|
||||
@ -384,8 +395,31 @@ var Entaxy;
|
||||
$scope.$on(Jmx.TreeEvent.Updated, () => {
|
||||
$route.reload();
|
||||
});
|
||||
|
||||
function getHotkeysConfigs() {
|
||||
return [
|
||||
{
|
||||
...Entaxy.getSaveHotkeyDescription(),
|
||||
callback: function (event) {
|
||||
event.preventDefault();
|
||||
if (!ctrl.isReadOnly()) {
|
||||
ctrl.save();
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
...Entaxy.getSaveAllHotkeyDescription(),
|
||||
callback: function(event) {
|
||||
event.preventDefault();
|
||||
if (ctrl.private && !ctrl.isReadOnly() && (ctrl.isOwnerChanged || ctrl.isFormDirty)) {
|
||||
ctrl.saveAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
];
|
||||
}
|
||||
}
|
||||
entaxyPropertiesController.$inject = ['$scope', 'workspace', 'entaxyService', 'jolokia', '$location', '$route',
|
||||
'entaxyAttributesCacheService', 'entaxyPrivateObjectsCacheService'];
|
||||
'entaxyHotkeysService', 'entaxyAttributesCacheService', 'entaxyPrivateObjectsCacheService'];
|
||||
|
||||
})(Entaxy || (Entaxy = {}));
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* entaxy-management-plugin
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2024 EmDev LLC
|
||||
* Copyright (C) 2020 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
@ -61,15 +61,16 @@ var Entaxy;
|
||||
<div class="resources-file-drop-zone" entaxy-file-drop ng-model="$ctrl.file"
|
||||
process-fn="$ctrl.upload($ctrl.file)">
|
||||
<div class="file-panel-container" context-menu context-menu-options="$ctrl.contextMenuOptions">
|
||||
<entaxy-file-panel items="$ctrl.items" selected-item="$ctrl.selectedItem" view="$ctrl.view"
|
||||
<entaxy-file-panel items="$ctrl.items" selected-items="$ctrl.selectedItems" view="$ctrl.view"
|
||||
change-selection-fn="$ctrl.changeSelection" open-fn="$ctrl.open"
|
||||
resource-context-menu-options="$ctrl.resourceContextMenuOptions"
|
||||
adm-resource-context-menu-options="$ctrl.admResourceContextMenuOptions"
|
||||
folder-context-menu-options="$ctrl.folderContextMenuOptions"></entaxy-file-panel>
|
||||
</div>
|
||||
<div class="meta-info" resizable r-directions="['left']"
|
||||
ng-if="$ctrl.selectedItem && $ctrl.selectedItem.metadata">
|
||||
ng-if="$ctrl.selectedItems && $ctrl.selectedItems.length == 1 && $ctrl.selectedItems[0].metadata">
|
||||
<uib-tabset active="$ctrl.activeTab" class="meta-tabs">
|
||||
<uib-tab ng-repeat="(section, info) in $ctrl.selectedItem.metadata track by $index"
|
||||
<uib-tab ng-repeat="(section, info) in $ctrl.selectedItems[0].metadata track by $index"
|
||||
heading="{{section}}">
|
||||
<div class="json-formatter">
|
||||
<json-formatter json="info" open="1"></json-formatter>
|
||||
@ -83,8 +84,8 @@ var Entaxy;
|
||||
})
|
||||
.name;
|
||||
|
||||
function entaxyResourcesController(workspace, $scope, jolokia, entaxyService, entaxyResourcesService,
|
||||
$timeout, $uibModal, $cookies) {
|
||||
function entaxyResourcesController(workspace, $scope, jolokia, entaxyService, entaxyResourcesService, $timeout,
|
||||
$uibModal, $cookies, entaxyHotkeysService, $q, $window, $location, $route) {
|
||||
'ngInject';
|
||||
|
||||
let ctrl = this;
|
||||
@ -98,62 +99,79 @@ var Entaxy;
|
||||
name: 'Create folder',
|
||||
actionFn: createFolder
|
||||
},
|
||||
{
|
||||
name: 'Create resource',
|
||||
actionFn: createResource
|
||||
},
|
||||
{
|
||||
name: 'Upload',
|
||||
actionFn: uploadResource
|
||||
},
|
||||
{
|
||||
name: 'Paste',
|
||||
actionFn: pasteResource
|
||||
actionFn: pasteResources
|
||||
}
|
||||
];
|
||||
|
||||
|
||||
ctrl.resourceContextMenuOptions = [
|
||||
{
|
||||
name: 'Download',
|
||||
actionFn: downloadResource
|
||||
},
|
||||
let commonContextMenuOptions = [
|
||||
{
|
||||
name: 'Copy',
|
||||
actionFn: copyResource
|
||||
actionFn: copyResources
|
||||
},
|
||||
{
|
||||
name: 'Cut',
|
||||
actionFn: cutResource
|
||||
actionFn: cutResources
|
||||
},
|
||||
{
|
||||
name: 'Remove',
|
||||
actionFn: removeResource
|
||||
actionFn: removeResources
|
||||
},
|
||||
{
|
||||
divider: true
|
||||
}
|
||||
].concat(ctrl.contextMenuOptions);
|
||||
];
|
||||
|
||||
ctrl.resourceContextMenuOptions = [
|
||||
{
|
||||
name: 'Download',
|
||||
actionFn: downloadResources
|
||||
}
|
||||
].concat(commonContextMenuOptions).concat(ctrl.contextMenuOptions);
|
||||
|
||||
ctrl.admResourceContextMenuOptions = [
|
||||
{
|
||||
name: 'Open in new tab',
|
||||
actionFn: openTransformationEditorInTab
|
||||
}
|
||||
].concat(ctrl.resourceContextMenuOptions);
|
||||
|
||||
ctrl.folderContextMenuOptions = [
|
||||
{
|
||||
name: 'Paste to folder',
|
||||
actionFn: pasteResourceToFolder
|
||||
},
|
||||
{
|
||||
name: 'Remove',
|
||||
actionFn: removeResource
|
||||
},
|
||||
{
|
||||
divider: true
|
||||
}
|
||||
].concat(ctrl.contextMenuOptions);
|
||||
].concat(commonContextMenuOptions).concat(ctrl.contextMenuOptions);
|
||||
|
||||
ctrl.$onInit = function () {
|
||||
entaxyHotkeysService.setHotkeys($scope, getHotkeysConfigs());
|
||||
|
||||
ctrl.view = 'list';
|
||||
ctrl.protocol = jolokia.getAttribute(selectedMbeanName, 'Protocol');
|
||||
let path = $cookies.getObject(ctrl.protocol);
|
||||
ctrl.crumbs = path ? path.split('/') : [];
|
||||
}
|
||||
|
||||
let locationNid = $location.search() ? $location.search().nid : undefined;
|
||||
$scope.$on('jmxTreeClicked', function () {
|
||||
const currentLocationNid = $location.search() ? $location.search().nid : undefined;
|
||||
if (locationNid !== currentLocationNid) {
|
||||
locationNid = currentLocationNid;
|
||||
$route.reload();
|
||||
}
|
||||
});
|
||||
|
||||
$scope.$watchCollection('$ctrl.crumbs', function() {
|
||||
ctrl.selectedItem = null;
|
||||
ctrl.selectedItems = [];
|
||||
ctrl.location = ctrl.isFullLocationView ? getFullLocation() : getLocation();
|
||||
|
||||
$cookies.putObject(ctrl.protocol, getPath());
|
||||
@ -170,40 +188,179 @@ var Entaxy;
|
||||
ctrl.isFullLocationView = !ctrl.isFullLocationView;
|
||||
}
|
||||
|
||||
ctrl.changeSelection = function (item) {
|
||||
ctrl.selectedItem = item;
|
||||
ctrl.changeSelection = function (item, isMultiple) {
|
||||
if (!isMultiple) {
|
||||
ctrl.selectedItems = [ item ];
|
||||
} else {
|
||||
if (ctrl.selectedItems && ctrl.selectedItems.length > 0) {
|
||||
if (ctrl.selectedItems.includes(item)) {
|
||||
ctrl.selectedItems = ctrl.selectedItems.filter(it => it.name !== item.name);
|
||||
} else {
|
||||
ctrl.selectedItems.push(item);
|
||||
}
|
||||
} else {
|
||||
ctrl.selectedItems = [ item ];
|
||||
}
|
||||
}
|
||||
|
||||
ctrl.location = ctrl.isFullLocationView ? getFullLocation() : getLocation();
|
||||
$timeout(function () {
|
||||
ctrl.activeTab = 0;
|
||||
});
|
||||
}
|
||||
|
||||
function createResource () {
|
||||
entaxyResourcesService.openResourceNameInputModal({ isFolder: false },
|
||||
ctrl.items.map((item) => item.name), false, false)
|
||||
.then((name) => {
|
||||
saveResource(
|
||||
getPath() + '/' + name,
|
||||
'',
|
||||
'Resource ' + name + ' was successfully added',
|
||||
true,
|
||||
name);
|
||||
});
|
||||
}
|
||||
|
||||
ctrl.open = function (item) {
|
||||
if (item.isFolder === true) {
|
||||
ctrl.crumbs.push(item.name);
|
||||
} else {
|
||||
let splitName = item.name.split('.');
|
||||
let extension = splitName.length > 1 ? splitName.pop() : undefined;
|
||||
if (extension === 'adm') {
|
||||
openTransformationEditor(item);
|
||||
} else {
|
||||
openEditor(item, extension);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function updateItems() {
|
||||
function openEditor(item, extension) {
|
||||
let location = getFullLocation();
|
||||
entaxyResourcesService.getResource(location, true).then(resourceContent => {
|
||||
$uibModal.open({
|
||||
component: 'entaxyEditorModal',
|
||||
resolve: {
|
||||
resourceName: () => item.name,
|
||||
resourceContent: () => resourceContent,
|
||||
extension: () => extension,
|
||||
names: () => ctrl.items.map((item) => item.name)
|
||||
},
|
||||
size: 'xl',
|
||||
backdrop: 'static'
|
||||
})
|
||||
.result.then(data => {
|
||||
if (data.writeIntoSource) {
|
||||
saveResource(
|
||||
getLocationWithoutProtocol(),
|
||||
data.content,
|
||||
'Resource ' + item.name + ' was successfully edited',
|
||||
false);
|
||||
} else {
|
||||
let path = getPath();
|
||||
let separator = path.length > 0 ? '/' : '';
|
||||
saveResource(
|
||||
path + separator + data.name,
|
||||
data.content,
|
||||
'Resource ' + data.name + ' was successfully added',
|
||||
true,
|
||||
data.name);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function openTransformationEditor(item) {
|
||||
|
||||
let location = getLocation();
|
||||
$location.search('location', location);
|
||||
|
||||
$uibModal.open({
|
||||
component: 'entaxyAtlasmapConsoleModal',
|
||||
resolve: {
|
||||
resourceName: () => item.name,
|
||||
names: () => ctrl.items.map((item) => item.name),
|
||||
location: () => location
|
||||
},
|
||||
size: 'xxl',
|
||||
backdrop: 'static'
|
||||
}).result
|
||||
.then((newName) => {
|
||||
$location.search('location', null);
|
||||
if (newName) {
|
||||
Entaxy.notificationSuccess('Resource ' + newName + ' was successfully added');
|
||||
updateItems(newName);
|
||||
} else {
|
||||
Entaxy.notificationSuccess('Resource ' + item.name + ' was successfully edited');
|
||||
}
|
||||
})
|
||||
.catch((reason) => {
|
||||
$location.search('location', null);
|
||||
if (reason && reason !== Entaxy.MODAL_CANCEL_REASON.ESCAPE_KEY_PRESS) {
|
||||
Entaxy.notificationError(reason);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function openTransformationEditorInTab() {
|
||||
let currentLocation = $location.absUrl();
|
||||
let finalLocation = currentLocation.substring(0, currentLocation.indexOf('entaxy-management'))
|
||||
.concat('entaxy-transformation?location=').concat(getLocation());
|
||||
$window.open(finalLocation, '_blank');
|
||||
}
|
||||
|
||||
function saveResource(path, content, notificationMessage, isUpdateNeeded, selectAfterSavingByName) {
|
||||
entaxyResourcesService
|
||||
.saveResource(selectedMbeanName, path, content)
|
||||
.then(() => {
|
||||
Entaxy.notificationSuccess(notificationMessage);
|
||||
if (isUpdateNeeded) {
|
||||
updateItems(selectAfterSavingByName);
|
||||
}
|
||||
}).catch(error => {
|
||||
Entaxy.notificationError(error);
|
||||
Entaxy.log.error(error);
|
||||
});
|
||||
}
|
||||
|
||||
function updateItems(selectByName) {
|
||||
let path = getPath();
|
||||
|
||||
entaxyResourcesService.getResourcesInfo(selectedMbeanName, path)
|
||||
.then(originItems => {
|
||||
items = originItems
|
||||
let items = originItems
|
||||
.concat(entaxyResourcesService.getClientFoldersToAdd(clientFolders, originItems, ctrl.crumbs));
|
||||
ctrl.items = items.sort(Entaxy.compareBy('name')).sort((a, b) => b.isFolder - a.isFolder);
|
||||
|
||||
if (selectByName) {
|
||||
let itemToSelect = ctrl.items.find(item => item.name === selectByName);
|
||||
ctrl.changeSelection(itemToSelect);
|
||||
scrollToItem();
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function scrollToItem() {
|
||||
setTimeout(function () {
|
||||
|
||||
let element = ctrl.view === 'tiles' ?
|
||||
document.getElementsByClassName('tile active')[0] :
|
||||
document.getElementsByClassName('list active')[0];
|
||||
|
||||
element.scrollIntoView();
|
||||
});
|
||||
}
|
||||
|
||||
function getPath() {
|
||||
return entaxyResourcesService.getPath(ctrl.crumbs);
|
||||
}
|
||||
|
||||
function getLocationWithoutProtocol(folderSelectionEnabled) {
|
||||
let isItemSelected = ctrl.selectedItem &&
|
||||
(!ctrl.selectedItem.isFolder || (folderSelectionEnabled && ctrl.selectedItem.isFolder));
|
||||
let isItemSelected = ctrl.selectedItems && ctrl.selectedItems.length == 1 &&
|
||||
(!ctrl.selectedItems[0].isFolder || (folderSelectionEnabled && ctrl.selectedItems[0].isFolder));
|
||||
let separator = getPath().length > 0 && isItemSelected ? '/' : '';
|
||||
let selectedItemName = isItemSelected ? ctrl.selectedItem.name : '';
|
||||
let selectedItemName = isItemSelected ? ctrl.selectedItems[0].name : '';
|
||||
return getPath() + separator + selectedItemName;
|
||||
}
|
||||
|
||||
@ -223,48 +380,57 @@ var Entaxy;
|
||||
ctrl.triggerUpload();
|
||||
}
|
||||
|
||||
function downloadResource(item) {
|
||||
function downloadResources() {
|
||||
let path = getLocationWithoutProtocol(true);
|
||||
|
||||
let path = isItemSelected(item) ?
|
||||
getLocationWithoutProtocol(true) :
|
||||
getLocationWithoutProtocol(true) + '/' + item.name;
|
||||
|
||||
entaxyResourcesService.downloadResource(selectedMbeanName, path)
|
||||
.then(result => {
|
||||
entaxyService.downloadFileFromBase64StringContent(result, item.name);
|
||||
}).catch(error => {
|
||||
Entaxy.notificationError(error);
|
||||
Entaxy.log.error(error);
|
||||
ctrl.selectedItems.forEach(item => {
|
||||
let fullPath = ctrl.selectedItems.length > 1 ? path + '/' + item.name : path;
|
||||
entaxyResourcesService.downloadResource(selectedMbeanName, fullPath)
|
||||
.then(result => {
|
||||
entaxyService.downloadFileFromBase64StringContent(result, item.name);
|
||||
}).catch(error => {
|
||||
Entaxy.notificationError(error);
|
||||
Entaxy.log.error(error);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function copyResource(item) {
|
||||
setCopyConfig(item, false);
|
||||
function copyResources() {
|
||||
processCopyCut(false);
|
||||
}
|
||||
|
||||
function cutResource(item) {
|
||||
setCopyConfig(item, true);
|
||||
function cutResources() {
|
||||
processCopyCut(true);
|
||||
}
|
||||
|
||||
function processCopyCut(removeSource) {
|
||||
if (ctrl.selectedItems && ctrl.selectedItems.length > 0) {
|
||||
Entaxy.resourceCopyConfigs = {};
|
||||
ctrl.selectedItems.forEach(item => {
|
||||
setCopyConfig(item, removeSource);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function setCopyConfig(item, removeSource) {
|
||||
Entaxy.resourceCopyConfig.sourceResourcePath = isItemSelected(item) ?
|
||||
let sourceResourcePath = ctrl.selectedItems && ctrl.selectedItems.length == 1 ?
|
||||
getLocation(true) : getLocation(true) + '/' + item.name;
|
||||
Entaxy.resourceCopyConfig.sourceResourceName = item.name;
|
||||
Entaxy.resourceCopyConfig.removeSource = removeSource;
|
||||
Entaxy.resourceCopyConfigs[item.name] = {
|
||||
sourceResourcePath: sourceResourcePath,
|
||||
removeSource: removeSource
|
||||
};
|
||||
}
|
||||
|
||||
function pasteResource() {
|
||||
if (Entaxy.resourceCopyConfig.sourceResourcePath) {
|
||||
function pasteResources() {
|
||||
if (Object.keys(Entaxy.resourceCopyConfigs).length > 0) {
|
||||
let path = getPath();
|
||||
pasteWithUniquenessCheck(ctrl.items, path);
|
||||
}
|
||||
}
|
||||
|
||||
function pasteResourceToFolder(item) {
|
||||
if (Entaxy.resourceCopyConfig.sourceResourcePath) {
|
||||
let path = isItemSelected(item) ?
|
||||
getLocationWithoutProtocol(true) :
|
||||
getLocationWithoutProtocol(true) + '/' + item.name;
|
||||
function pasteResourceToFolder() {
|
||||
if (Object.keys(Entaxy.resourceCopyConfigs).length > 0) {
|
||||
let path = getLocationWithoutProtocol(true);
|
||||
|
||||
entaxyResourcesService.getResourcesInfo(selectedMbeanName, path)
|
||||
.then(items => {
|
||||
@ -278,40 +444,43 @@ var Entaxy;
|
||||
}
|
||||
|
||||
function pasteWithUniquenessCheck(items, path) {
|
||||
|
||||
let copiedDuplicateItem = items.find(item => item.name === Entaxy.resourceCopyConfig.sourceResourceName);
|
||||
if (copiedDuplicateItem && !copiedDuplicateItem.isFolder) {
|
||||
$uibModal.open({
|
||||
component: 'entaxySimpleResourceNameInputModal',
|
||||
resolve: {
|
||||
title: () => 'Change resource name',
|
||||
names: () => items.filter((item) => !item.isFolder).map((item) => item.name),
|
||||
name: () => Entaxy.resourceCopyConfig.sourceResourceName,
|
||||
type: () => 'Resource'
|
||||
},
|
||||
size: 'sm-custom',
|
||||
backdrop: 'static',
|
||||
windowTopClass: 'modal-top-margin-center-override'
|
||||
})
|
||||
.result.then(name => {
|
||||
paste(Entaxy.resourceCopyConfig.sourceResourcePath, path, name);
|
||||
});
|
||||
} else {
|
||||
paste(Entaxy.resourceCopyConfig.sourceResourcePath, path, Entaxy.resourceCopyConfig.sourceResourceName);
|
||||
let copiedDuplicateItems = [];
|
||||
let namesToPaste = Object.keys(Entaxy.resourceCopyConfigs);
|
||||
items.forEach(item => {
|
||||
if (namesToPaste.includes(item.name)) {
|
||||
copiedDuplicateItems.push(item);
|
||||
}
|
||||
});
|
||||
if (copiedDuplicateItems.length > 0) {
|
||||
for (let i = copiedDuplicateItems.length - 1; i >= 0; i--) {
|
||||
renameResourceAndPaste(copiedDuplicateItems[i], path);
|
||||
}
|
||||
}
|
||||
let copiedDuplicateItemsNames = copiedDuplicateItems.map(item => item.name);
|
||||
namesToPaste.filter(name => !copiedDuplicateItemsNames.includes(name)).forEach(name => {
|
||||
paste(Entaxy.resourceCopyConfigs[name].sourceResourcePath, path, name,
|
||||
Entaxy.resourceCopyConfigs[name].removeSource);
|
||||
});
|
||||
}
|
||||
|
||||
function paste(from, to, name) {
|
||||
function renameResourceAndPaste(item, path) {
|
||||
entaxyResourcesService.openResourceNameInputModal(item, ctrl.items.map((item) => item.name), true, false)
|
||||
.then(name => {
|
||||
paste(Entaxy.resourceCopyConfigs[item.name].sourceResourcePath, path, name,
|
||||
Entaxy.resourceCopyConfigs[item.name].removeSource);
|
||||
});
|
||||
}
|
||||
|
||||
function paste(from, to, name, removeSource) {
|
||||
const fullToPath = to + '/' + name;
|
||||
entaxyResourcesService.pasteResource(selectedMbeanName, from, fullToPath)
|
||||
.then(result => {
|
||||
if (Entaxy.resourceCopyConfig.removeSource) {
|
||||
entaxyResourcesService.removeResource(selectedMbeanName,
|
||||
Entaxy.resourceCopyConfig.sourceResourcePath)
|
||||
if (removeSource) {
|
||||
entaxyResourcesService.removeResource(selectedMbeanName, from)
|
||||
.then(result => {
|
||||
Entaxy.resourceCopyConfig.sourceResourcePath = ctrl.protocol + ':' + fullToPath;
|
||||
Entaxy.resourceCopyConfig.sourceResourceName = name;
|
||||
Entaxy.resourceCopyConfig.removeSource = false;
|
||||
let configToRemove = Object.entries(Entaxy.resourceCopyConfigs)
|
||||
.find(([name, config]) => config.sourceResourcePath === from);
|
||||
delete Entaxy.resourceCopyConfigs[configToRemove[0]];
|
||||
updateItems();
|
||||
}).catch(error => {
|
||||
Entaxy.notificationError(error);
|
||||
@ -326,33 +495,50 @@ var Entaxy;
|
||||
});
|
||||
}
|
||||
|
||||
function removeResource(item) {
|
||||
let title = 'Confirm Removing Resource';
|
||||
let resourceType = item.isFolder ? 'folder' : 'resource';
|
||||
let message = 'Do you want to remove ' + resourceType + ' ' + item.name + '?';
|
||||
function removeResources() {
|
||||
if (ctrl.selectedItems && ctrl.selectedItems.length > 0) {
|
||||
removeSelectedResources();
|
||||
}
|
||||
}
|
||||
|
||||
function removeSelectedResources() {
|
||||
let title = 'Confirm Removing Resources';
|
||||
let message = 'Do you want to remove selected resources?';
|
||||
|
||||
entaxyService.openConfirmationWindow(title, message)
|
||||
.then(() => {
|
||||
let path = isItemSelected(item) ?
|
||||
getLocationWithoutProtocol(true) :
|
||||
getLocationWithoutProtocol(true) + '/' + item.name;
|
||||
entaxyResourcesService.removeResource(selectedMbeanName, path)
|
||||
.then((result) => {
|
||||
Entaxy.notificationSuccess('Resource ' + item.name + ' was successfully removed');
|
||||
if (isItemSelected(item)) {
|
||||
ctrl.selectedItem = undefined;
|
||||
let promises = [];
|
||||
let failedResources = [];
|
||||
let path = getLocationWithoutProtocol(true);
|
||||
ctrl.selectedItems.forEach(item => {
|
||||
let fullPath = ctrl.selectedItems.length > 1 ? path + '/' + item.name : path;
|
||||
promises.push(
|
||||
entaxyResourcesService
|
||||
.removeResource(selectedMbeanName, fullPath)
|
||||
.catch((error) => {
|
||||
failedResources.push(fullPath);
|
||||
Entaxy.log.error(error);
|
||||
})
|
||||
);
|
||||
});
|
||||
$q.all(promises).then(result => {
|
||||
if (failedResources.length > 0) {
|
||||
let message = 'Errors occurred while removing resources';
|
||||
Entaxy.notificationError(message);
|
||||
} else {
|
||||
Entaxy.notificationSuccess('Resources were successfully removed');
|
||||
}
|
||||
ctrl.selectedItems = [];
|
||||
updateItems();
|
||||
})
|
||||
.catch((error) => {
|
||||
Entaxy.log.error(error);
|
||||
Entaxy.notificationError('An error occurred while removing resource ' + item.name);
|
||||
}).catch(error => {
|
||||
Entaxy.notificationError(error);
|
||||
EntaxyCICD.log.error(error);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function isItemSelected(item) {
|
||||
return ctrl.selectedItem && ctrl.selectedItem.name === item.name;
|
||||
return ctrl.selectedItems && ctrl.selectedItems.includes(item);
|
||||
}
|
||||
|
||||
ctrl.triggerUpload = function () {
|
||||
@ -375,8 +561,41 @@ var Entaxy;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function getHotkeysConfigs() {
|
||||
return [
|
||||
{
|
||||
...Entaxy.getCopyHotkeyDescription(),
|
||||
callback: function (event) {
|
||||
event.preventDefault();
|
||||
copyResources();
|
||||
}
|
||||
},
|
||||
{
|
||||
...Entaxy.getCutHotkeyDescription(),
|
||||
callback: function(event) {
|
||||
event.preventDefault();
|
||||
cutResources();
|
||||
}
|
||||
},
|
||||
{
|
||||
...Entaxy.getPasteHotkeyDescription(),
|
||||
callback: function(event) {
|
||||
event.preventDefault();
|
||||
pasteResources();
|
||||
}
|
||||
},
|
||||
{
|
||||
...Entaxy.getRemoveHotkeyDescription(),
|
||||
callback: function(event) {
|
||||
event.preventDefault();
|
||||
removeResources();
|
||||
}
|
||||
}
|
||||
];
|
||||
}
|
||||
}
|
||||
entaxyResourcesController.$inject = ['workspace', '$scope', 'jolokia', 'entaxyService', 'entaxyResourcesService',
|
||||
'$timeout', '$uibModal', '$cookies'];
|
||||
'$timeout', '$uibModal', '$cookies', 'entaxyHotkeysService', '$q', '$window', '$location', '$route'];
|
||||
|
||||
})(Entaxy || (Entaxy = {}));
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* entaxy-management-plugin
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2024 EmDev LLC
|
||||
* Copyright (C) 2020 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
@ -49,7 +49,7 @@ var Entaxy;
|
||||
</div>
|
||||
<div ng-if="$ctrl.isContentReady">
|
||||
<div class="xml-route-source-container">
|
||||
<entaxy-xml-editor class="xml-editor" source-doc="$ctrl.xml" read-only="$ctrl.readOnly">
|
||||
<entaxy-xml-editor class="entaxy-editor" source-doc="$ctrl.xml" read-only="$ctrl.readOnly">
|
||||
</entaxy-xml-editor>
|
||||
</div>
|
||||
</div>
|
||||
@ -59,7 +59,7 @@ var Entaxy;
|
||||
})
|
||||
.name;
|
||||
|
||||
function entaxySourceController(workspace, $location, operationsService, $scope,
|
||||
function entaxySourceController(workspace, $location, operationsService, $scope, entaxyHotkeysService,
|
||||
entaxyService, entaxyAttributesCacheService, entaxyPrivateObjectsCacheService) {
|
||||
'ngInject';
|
||||
|
||||
@ -67,6 +67,7 @@ var Entaxy;
|
||||
ctrl.errorMessage = 'Value cannot be empty';
|
||||
|
||||
ctrl.$onInit = function() {
|
||||
entaxyHotkeysService.setHotkeys($scope, getHotkeysConfigs());
|
||||
|
||||
let selectedMbean = workspace.getSelectedMBean();
|
||||
let selectedMbeanName = selectedMbean.objectName;
|
||||
@ -278,8 +279,32 @@ var Entaxy;
|
||||
.isOwnerChanged(workspace.getSelectedMBean(), ctrl.owner);
|
||||
}
|
||||
}
|
||||
|
||||
function getHotkeysConfigs() {
|
||||
return [
|
||||
{
|
||||
...Entaxy.getSaveHotkeyDescription(),
|
||||
callback: function (event) {
|
||||
event.preventDefault();
|
||||
if (ctrl.isContentPresent && !ctrl.readOnly) {
|
||||
ctrl.save();
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
...Entaxy.getSaveAllHotkeyDescription(),
|
||||
callback: function(event) {
|
||||
event.preventDefault();
|
||||
if (ctrl.isContentPresent && !ctrl.readOnly && ctrl.private &&
|
||||
(ctrl.isOwnerChanged || ctrl.isDirty)) {
|
||||
ctrl.saveAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
];
|
||||
}
|
||||
}
|
||||
entaxySourceController.$inject = ['workspace', '$location', 'operationsService', '$scope',
|
||||
entaxySourceController.$inject = ['workspace', '$location', 'operationsService', '$scope', 'entaxyHotkeysService',
|
||||
'entaxyService', 'entaxyAttributesCacheService', 'entaxyPrivateObjectsCacheService'];
|
||||
|
||||
})(Entaxy || (Entaxy = {}));
|
||||
|
@ -0,0 +1,185 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* entaxy-management-plugin
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
var 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,
|
||||
setFocused: 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 && reason !== Entaxy.MODAL_CANCEL_REASON.ESCAPE_KEY_PRESS) {
|
||||
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,364 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* entaxy-management-plugin
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
var 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';
|
||||
const CONTAINER_TYPE_PROFILE = 'Profile';
|
||||
|
||||
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 },
|
||||
{ name: 'Use As Template', title: 'Use As Template', actionFn: addConnectorFromTemplate }
|
||||
];
|
||||
|
||||
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,
|
||||
containerType: () => CONTAINER_TYPE_PROFILE,
|
||||
containers: () => ctrl.profiles
|
||||
};
|
||||
|
||||
entaxyService.openAddItemModalAndProcessResults(resolve, runtimeType);
|
||||
} else {
|
||||
entaxyService.openEditItemModalAndProcessResults(item, ctrl.itemName, runtimeType, mode);
|
||||
}
|
||||
}
|
||||
|
||||
function addConnectorFromTemplate(action, item) {
|
||||
let resolve = {
|
||||
itemType: () => ctrl.itemName,
|
||||
containerType: () => CONTAINER_TYPE_PROFILE,
|
||||
containers: () => ctrl.profiles
|
||||
};
|
||||
entaxyService.openAddItemFromTemplateModalAndProcessResults(resolve, item, Entaxy.RUNTIME_TYPE.CONNECTOR);
|
||||
}
|
||||
|
||||
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 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
var 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 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
var 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 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
var 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 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
var 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 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
var 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 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
var 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 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
var 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 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
var 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 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
var 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 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
var 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 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
var 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.checkChildrenUniqueness : 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 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
var 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,311 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* entaxy-management-plugin
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
var 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') {
|
||||
if (ctrl.runtimeType === Entaxy.RUNTIME_TYPE.CONNECTION && item.isPlatform) {
|
||||
ctrl.showModal(Entaxy.MODAL_MODES.VIEW, item);
|
||||
return;
|
||||
}
|
||||
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,
|
||||
isPlatform: mbean.attributes.Platform
|
||||
});
|
||||
});
|
||||
|
||||
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 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
var 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 = {}));
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* entaxy-management-plugin
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2024 EmDev LLC
|
||||
* Copyright (C) 2020 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
|
@ -0,0 +1,110 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* entaxy-management-plugin
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
var 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,211 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* entaxy-management-plugin
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
var 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 && reason !== Entaxy.MODAL_CANCEL_REASON.ESCAPE_KEY_PRESS) {
|
||||
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,
|
||||
setFocused: itemType === ITEM_TYPES.ROLE ? true : 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,228 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* entaxy-management-plugin
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
var 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,
|
||||
setFocused: 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)
|
||||
},
|
||||
setFocused: true
|
||||
}
|
||||
]
|
||||
};
|
||||
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 && reason !== Entaxy.MODAL_CANCEL_REASON.ESCAPE_KEY_PRESS) {
|
||||
Entaxy.notificationError(reason);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
EntaxyGroupsTableController.$inject = ['workspace', 'operationsService', 'entaxyService', '$uibModal'];
|
||||
|
||||
})(Entaxy || (Entaxy = {}));
|
@ -0,0 +1,68 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* entaxy-management-plugin
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
var 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,149 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* entaxy-management-plugin
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
var 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'"
|
||||
set-focused="formField.setFocused">
|
||||
<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"
|
||||
set-focused="formField.setFocused"></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'" set-focused="formField.setFocused"/>
|
||||
<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($scope, $uibModal, entaxyHotkeysService) {
|
||||
'ngInject';
|
||||
|
||||
let ctrl = this;
|
||||
|
||||
ctrl.$onInit = function() {
|
||||
entaxyHotkeysService.setHotkeys($scope, getHotkeysConfigs());
|
||||
|
||||
ctrl.formFields = ctrl.resolve.formFields;
|
||||
if (!ctrl.formFields || ctrl.formFields.length === 0) {
|
||||
ctrl.cancel('Fields can not be found');
|
||||
}
|
||||
}
|
||||
|
||||
ctrl.cancel = function(reason) {
|
||||
ctrl.modalInstance.dismiss(reason);
|
||||
}
|
||||
|
||||
ctrl.save = function() {
|
||||
ctrl.errors = validate();
|
||||
if (Object.keys(ctrl.errors).length === 0) {
|
||||
let args = ctrl.formFields.map(formField => formField.value);
|
||||
ctrl.modalInstance.close(args);
|
||||
}
|
||||
}
|
||||
|
||||
function validate() {
|
||||
let errors = {};
|
||||
|
||||
ctrl.formFields.forEach(formField => {
|
||||
if (formField.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;
|
||||
}
|
||||
|
||||
function getHotkeysConfigs() {
|
||||
return [
|
||||
{
|
||||
...Entaxy.getSaveHotkeyDescription(),
|
||||
callback: function (event) {
|
||||
event.preventDefault();
|
||||
ctrl.save();
|
||||
}
|
||||
}
|
||||
];
|
||||
}
|
||||
}
|
||||
entaxyUserManagementModalController.$inject = ['$scope', '$uibModal', 'entaxyHotkeysService'];
|
||||
|
||||
})(Entaxy || (Entaxy = {}));
|
@ -0,0 +1,62 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* entaxy-management-plugin
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
var Entaxy;
|
||||
(function (Entaxy) {
|
||||
Entaxy._module.component('entaxyUsers', {
|
||||
bindings: {
|
||||
changeSelection: '<',
|
||||
selectedUsername: '<',
|
||||
reloadFn: '<'
|
||||
},
|
||||
template:
|
||||
`
|
||||
<div class="entaxy-users-container">
|
||||
<div class="entaxy-users-table-container">
|
||||
<h2>Users</h2>
|
||||
<entaxy-users-table change-selection="$ctrl.changeSelection" reload-fn="$ctrl.reloadFn">
|
||||
</entaxy-users-table>
|
||||
</div>
|
||||
|
||||
<div class="entaxy-user-details-container">
|
||||
<h2>
|
||||
User Details
|
||||
<span ng-if="$ctrl.selectedUsername">for {{$ctrl.selectedUsername}}</span>
|
||||
</h2>
|
||||
|
||||
<label>Associated Profile</label>
|
||||
<entaxy-associated-profile-select username="$ctrl.selectedUsername">
|
||||
</entaxy-associated-profile-select>
|
||||
|
||||
<label>Groups and Roles</label>
|
||||
<entaxy-groups-and-roles-list username="$ctrl.selectedUsername" reload-fn="$ctrl.reloadFn">
|
||||
</entaxy-groups-and-roles-list>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
})
|
||||
.name;
|
||||
|
||||
})(Entaxy || (Entaxy = {}));
|
@ -0,0 +1,179 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* entaxy-management-plugin
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
var Entaxy;
|
||||
(function (Entaxy) {
|
||||
Entaxy._module.component('entaxyUsersTable', {
|
||||
bindings: {
|
||||
changeSelection: '<',
|
||||
reloadFn: '<'
|
||||
},
|
||||
template:
|
||||
`
|
||||
<pf-toolbar class="entaxy-toolbar" config="$ctrl.toolbarConfig"></pf-toolbar>
|
||||
<pf-table-view config="$ctrl.tableConfig"
|
||||
columns="$ctrl.tableColumns"
|
||||
action-buttons="$ctrl.tableActionButtons"
|
||||
page-config="$ctrl.pageConfig"
|
||||
items="$ctrl.viewedItems">
|
||||
</pf-table-view>
|
||||
`,
|
||||
controller: EntaxyUsersTableController
|
||||
})
|
||||
.name;
|
||||
|
||||
function EntaxyUsersTableController(workspace, operationsService, entaxyService, $uibModal, $templateCache) {
|
||||
'ngInject';
|
||||
|
||||
let ctrl = this;
|
||||
let selectedMbeanName = workspace.getSelectedMBeanName();
|
||||
|
||||
ctrl.tableConfig = {
|
||||
selectionMatchProp: 'name',
|
||||
showCheckboxes: false
|
||||
};
|
||||
|
||||
ctrl.toolbarConfig = {
|
||||
filterConfig: {
|
||||
fields: [
|
||||
{
|
||||
id: 'name',
|
||||
title: 'Name',
|
||||
placeholder: 'Filter by Name...',
|
||||
filterType: 'text'
|
||||
}
|
||||
],
|
||||
appliedFilters: [],
|
||||
onFilterChange: filterChange
|
||||
},
|
||||
isTableView: true
|
||||
};
|
||||
|
||||
ctrl.tableColumns = [
|
||||
{
|
||||
header: 'Name',
|
||||
itemField: 'name',
|
||||
htmlTemplate: 'users-table/name-template.html',
|
||||
colActionFn: (itemName) => ctrl.changeSelection(itemName)
|
||||
}
|
||||
];
|
||||
|
||||
$templateCache.put(
|
||||
'users-table/name-template.html',
|
||||
'<a href="" ng-click="$ctrl.handleColAction(key, value)">{{value}}</a>'
|
||||
);
|
||||
|
||||
ctrl.pageConfig = Entaxy.getStandardPageConfig();
|
||||
|
||||
function filterChange(filters) {
|
||||
ctrl.viewedItems = Entaxy.applyFilters(ctrl.items, filters, matchesFilter);
|
||||
ctrl.toolbarConfig.filterConfig.resultsCount = ctrl.viewedItems.length;
|
||||
};
|
||||
|
||||
function matchesFilter(item, filter) {
|
||||
let match = true;
|
||||
if (filter.id === 'name') {
|
||||
match = item.name.toLowerCase().match(filter.value.toLowerCase()) !== null;
|
||||
}
|
||||
return match;
|
||||
};
|
||||
|
||||
ctrl.items = [];
|
||||
ctrl.viewedItems = [];
|
||||
|
||||
ctrl.$onInit = function() {
|
||||
populateTable();
|
||||
|
||||
let primaryActions = [ { name: 'Add User', actionFn: () => showAddUserModal() } ];
|
||||
|
||||
ctrl.toolbarConfig.actionsConfig = {
|
||||
primaryActions: primaryActions
|
||||
};
|
||||
|
||||
ctrl.tableActionButtons = [
|
||||
{ name: 'Delete', title: 'Delete User', actionFn: deleteUser }
|
||||
];
|
||||
}
|
||||
|
||||
function populateTable() {
|
||||
operationsService.executeOperation(selectedMbeanName, { name: 'listUsers' }, [])
|
||||
.then(list => {
|
||||
ctrl.items = JSON.parse(list);
|
||||
ctrl.viewedItems = ctrl.items;
|
||||
|
||||
let filters = ctrl.toolbarConfig.filterConfig.appliedFilters;
|
||||
if (filters.length > 0) {
|
||||
filterChange(filters);
|
||||
} else {
|
||||
ctrl.toolbarConfig.filterConfig.resultsCount = ctrl.items.length;
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function showAddUserModal() {
|
||||
$uibModal.open({
|
||||
component: 'entaxyUserManagementModal',
|
||||
resolve: {
|
||||
modalTitle: () => 'Add User',
|
||||
formFields: () => [
|
||||
{
|
||||
label: 'Username',
|
||||
name: 'username',
|
||||
type: 'text',
|
||||
required: true,
|
||||
setFocused: true
|
||||
},
|
||||
{
|
||||
label: 'Password',
|
||||
name: 'password',
|
||||
type: 'password',
|
||||
required: true
|
||||
}
|
||||
]
|
||||
},
|
||||
backdrop: 'static'
|
||||
}).result.then((args) => {
|
||||
entaxyService.processUserManagementOperation('addUser', args, populateTable);
|
||||
},
|
||||
reason => {
|
||||
if (reason && reason !== Entaxy.MODAL_CANCEL_REASON.ESCAPE_KEY_PRESS) {
|
||||
Entaxy.notificationError(reason);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function deleteUser(action, item) {
|
||||
ctrl.deletedUsername = item.name;
|
||||
entaxyService.processUserManagementOperation('deleteUser', [ item.name ], reload);
|
||||
}
|
||||
|
||||
function reload() {
|
||||
ctrl.reloadFn(ctrl.deletedUsername);
|
||||
}
|
||||
}
|
||||
EntaxyUsersTableController.$inject = ['workspace', 'operationsService', 'entaxyService', '$uibModal',
|
||||
'$templateCache'];
|
||||
|
||||
})(Entaxy || (Entaxy = {}));
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* entaxy-management-plugin
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2024 EmDev LLC
|
||||
* Copyright (C) 2020 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* entaxy-management-plugin
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2024 EmDev LLC
|
||||
* Copyright (C) 2020 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
@ -80,12 +80,18 @@ var Entaxy;
|
||||
Entaxy.NON_CLUSTERED_MESSAGE = NON_CLUSTERED_MESSAGE;
|
||||
|
||||
const ERROR_MESSAGE = {
|
||||
INVALID: 'Invalid value',
|
||||
UNIQUE: 'Value must be unique',
|
||||
EMPTY: 'Please fill out this field',
|
||||
PASSWORD_CONFIRMATION: 'Password and confirmation password do not match'
|
||||
}
|
||||
Entaxy.ERROR_MESSAGE = ERROR_MESSAGE;
|
||||
|
||||
const MODAL_CANCEL_REASON = {
|
||||
ESCAPE_KEY_PRESS: 'escape key press'
|
||||
}
|
||||
Entaxy.MODAL_CANCEL_REASON = MODAL_CANCEL_REASON;
|
||||
|
||||
const CONFIRMATION = {
|
||||
UNSAVED_CHANGES: 'You have unsaved changes. Do you want to proceed anyway?'
|
||||
}
|
||||
@ -119,10 +125,8 @@ var Entaxy;
|
||||
}
|
||||
Entaxy.getItemTypeFromRuntimeType = getItemTypeFromRuntimeType;
|
||||
|
||||
let resourceCopyConfig = {
|
||||
removeSource: false
|
||||
}
|
||||
Entaxy.resourceCopyConfig = resourceCopyConfig;
|
||||
let resourceCopyConfigs = {};
|
||||
Entaxy.resourceCopyConfigs = resourceCopyConfigs;
|
||||
|
||||
function deepCopy(object) {
|
||||
return JSON.parse(JSON.stringify(object));
|
||||
@ -327,6 +331,24 @@ var Entaxy;
|
||||
}
|
||||
Entaxy.createTableFromOperationAffectedObjects = createTableFromOperationAffectedObjects;
|
||||
|
||||
function createStatusResultTable(result, header) {
|
||||
let tableHtml = `<table class="entaxy-result-table">`;
|
||||
tableHtml += `
|
||||
<tr>
|
||||
<th>` + header + `</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;
|
||||
}
|
||||
Entaxy.createStatusResultTable = createStatusResultTable;
|
||||
|
||||
function notificationWithDetails(type, mainMessage, message, duration) {
|
||||
let toastHtml = `
|
||||
<div class="toast-pf alert alert-${type} alert-dismissable">
|
||||
@ -439,6 +461,15 @@ var Entaxy;
|
||||
}
|
||||
Entaxy.notificationError = notificationError;
|
||||
|
||||
function changingFieldValueNotification(fieldDescriptor) {
|
||||
Core.notification(Entaxy.NOTIFICATION_TYPE.WARNING,
|
||||
'Changing ' + fieldDescriptor +
|
||||
' 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]);
|
||||
}
|
||||
Entaxy.changingFieldValueNotification = changingFieldValueNotification;
|
||||
|
||||
function setDefaultConfiguration() {
|
||||
Entaxy.configuration = getDefaultConfiguration();
|
||||
}
|
||||
|
@ -0,0 +1,106 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* entaxy-management-plugin
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
* rights to the Software and any copies are the property of the Copyright Holder. Unless
|
||||
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
|
||||
* Software for commercial purposes to provide services to third parties.
|
||||
*
|
||||
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
|
||||
* Under no circumstances does the Copyright Holder guarantee or promise that the
|
||||
* Software provided by him will be suitable or not suitable for the specific purposes
|
||||
* of the User, that the Software will meet all commercial and personal subjective
|
||||
* expectations of the User, that the Software will work properly, without technical
|
||||
* errors, quickly and uninterruptedly.
|
||||
*
|
||||
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
|
||||
* to the User for any direct or indirect losses of the User, his expenses or actual
|
||||
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
|
||||
* or damage to data, property, etc.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
var Entaxy;
|
||||
(function (Entaxy) {
|
||||
|
||||
function getSaveHotkeyDescription() {
|
||||
return {
|
||||
combo: 'ctrl+s',
|
||||
description: 'Saves the current object',
|
||||
allowIn: ['INPUT', 'SELECT', 'TEXTAREA']
|
||||
};
|
||||
}
|
||||
Entaxy.getSaveHotkeyDescription = getSaveHotkeyDescription;
|
||||
|
||||
function getSaveAsHotkeyDescription() {
|
||||
return {
|
||||
combo: 'ctrl+shift+s',
|
||||
description: 'Saves the current object with different name',
|
||||
allowIn: ['INPUT', 'SELECT', 'TEXTAREA']
|
||||
};
|
||||
}
|
||||
Entaxy.getSaveAsHotkeyDescription = getSaveAsHotkeyDescription;
|
||||
|
||||
function getSaveAllHotkeyDescription() {
|
||||
return {
|
||||
combo: 'ctrl+shift+s',
|
||||
description: 'Saves the current and related objects',
|
||||
allowIn: ['INPUT', 'SELECT', 'TEXTAREA']
|
||||
};
|
||||
}
|
||||
Entaxy.getSaveAllHotkeyDescription = getSaveAllHotkeyDescription;
|
||||
|
||||
function getBackHotkeyDescription() {
|
||||
return {
|
||||
combo: 'alt+left',
|
||||
description: 'Moves to the previous step of the modal',
|
||||
allowIn: ['INPUT', 'SELECT', 'TEXTAREA']
|
||||
};
|
||||
}
|
||||
Entaxy.getBackHotkeyDescription = getBackHotkeyDescription;
|
||||
|
||||
function getNextHotkeyDescription() {
|
||||
return {
|
||||
combo: 'alt+right',
|
||||
description: 'Moves to the next step of the modal',
|
||||
allowIn: ['INPUT', 'SELECT', 'TEXTAREA']
|
||||
};
|
||||
}
|
||||
Entaxy.getNextHotkeyDescription = getNextHotkeyDescription;
|
||||
|
||||
function getCopyHotkeyDescription() {
|
||||
return {
|
||||
combo: 'ctrl+c',
|
||||
description: 'Copies the item'
|
||||
};
|
||||
}
|
||||
Entaxy.getCopyHotkeyDescription = getCopyHotkeyDescription;
|
||||
|
||||
function getCutHotkeyDescription() {
|
||||
return {
|
||||
combo: 'ctrl+x',
|
||||
description: 'Cuts the item'
|
||||
};
|
||||
}
|
||||
Entaxy.getCutHotkeyDescription = getCutHotkeyDescription;
|
||||
|
||||
function getPasteHotkeyDescription() {
|
||||
return {
|
||||
combo: 'ctrl+v',
|
||||
description: 'Pastes the item'
|
||||
};
|
||||
}
|
||||
Entaxy.getPasteHotkeyDescription = getPasteHotkeyDescription;
|
||||
|
||||
function getRemoveHotkeyDescription() {
|
||||
return {
|
||||
combo: 'del',
|
||||
description: 'Removes the item'
|
||||
};
|
||||
}
|
||||
Entaxy.getRemoveHotkeyDescription = getRemoveHotkeyDescription;
|
||||
|
||||
})(Entaxy || (Entaxy = {}));
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* entaxy-management-plugin
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2024 EmDev LLC
|
||||
* Copyright (C) 2020 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* entaxy-management-plugin
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2024 EmDev LLC
|
||||
* Copyright (C) 2020 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
@ -47,7 +47,8 @@ var Entaxy = (function (Entaxy) {
|
||||
Entaxy._module = angular.module(Entaxy.pluginName, [
|
||||
'angularResizable',
|
||||
'jsonFormatter',
|
||||
'ui.sortable'
|
||||
'ui.sortable',
|
||||
'cfp.hotkeys'
|
||||
])
|
||||
.component('entaxy', {
|
||||
template:
|
||||
@ -147,7 +148,7 @@ var Entaxy = (function (Entaxy) {
|
||||
});
|
||||
|
||||
angular.forEach(
|
||||
['factories', 'search', 'route-component-libraries',
|
||||
['factories', 'search', 'route-component-libraries', 'data-management',
|
||||
'resource', 'connectors', 'security', 'configs', 'objects'],
|
||||
(folderName) => {
|
||||
addClassRecursive(
|
||||
@ -352,7 +353,8 @@ var Entaxy = (function (Entaxy) {
|
||||
}
|
||||
});
|
||||
});
|
||||
Entaxy.setChildrenToEntaxyTags(topChildrenTags);
|
||||
Entaxy.enrichEntaxyTags(topChildrenTags);
|
||||
Entaxy.enrichCamelTags(topChildrenTags);
|
||||
})
|
||||
.catch(error => Entaxy.log.error(error));
|
||||
}
|
||||
@ -389,12 +391,14 @@ const L10N = {
|
||||
routes: 'Маршруты',
|
||||
bound: 'Связанные',
|
||||
resource: 'Ресурсы',
|
||||
services: 'Сервисы',
|
||||
services: 'Сервисы и Клиенты',
|
||||
security: 'Безопасность',
|
||||
repositories: 'Репозитории',
|
||||
objects: 'Объекты',
|
||||
configs: 'Конфигурации',
|
||||
search: 'Поиск',
|
||||
['route-libraries']: 'Библиотеки маршрутов',
|
||||
['route-component-libraries']: 'Библиотеки компонентов маршрутов'
|
||||
['route-component-libraries']: 'Библиотеки компонентов маршрутов',
|
||||
['data-management']: 'Управление данными',
|
||||
['data-mappers']: 'Маппинг данных'
|
||||
};
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* entaxy-management-plugin
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2024 EmDev LLC
|
||||
* Copyright (C) 2020 - 2025 EmDev LLC
|
||||
* ==========
|
||||
* You may not use this file except in accordance with the License Terms of the Copyright
|
||||
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user