graflow: subflow reference nodes & exit subflow
This commit is contained in:
@@ -48,6 +48,21 @@
|
||||
.bzgf-node [data-id="out2"]{ top: 25%; }
|
||||
.bzgf-node [data-id="out3"]{ top: 75%; }
|
||||
|
||||
.bzgf-node[data-nodetype="refnodein"], .bzgf-node[data-nodetype="refnodeout"] {
|
||||
width:3em;
|
||||
height:3em;
|
||||
padding: 2px;
|
||||
}
|
||||
.bzgf-node[data-nodetype="refnodein"] .body, .bzgf-node[data-nodetype="refnodeout"] .body{
|
||||
border-radius: 50%;
|
||||
width: 3em;
|
||||
height: 3em;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.bzgf-node[data-nodetype="refnodein"] .body{ background: #0F0; }
|
||||
.bzgf-node[data-nodetype="refnodeout"] .body{ background: #FF0; }
|
||||
|
||||
.bzgf-wire{ stroke: var(--eicui-base-color-info); stroke-width: 4px; stroke-dasharray: 10,5; }
|
||||
</style>
|
||||
@@ -66,7 +81,18 @@
|
||||
<div class="port" data-type="out" data-id="out2" data-direction="e"></div>
|
||||
<div class="port" data-type="out" data-id="out3" data-direction="e"></div>
|
||||
</div>
|
||||
|
||||
|
||||
</template>
|
||||
|
||||
<template>
|
||||
<div class="bzgf-node" data-nodetype="refnodein">
|
||||
<div class="body">{parentport}</div>
|
||||
<div class="port" data-type="out" data-id="out1" data-direction="e"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template>
|
||||
<div class="bzgf-node" data-nodetype="refnodeout">
|
||||
<div class="body">{parentport}</div>
|
||||
<div class="port" data-type="in" data-id="in1" data-direction="w"></div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -96,6 +96,12 @@
|
||||
.bzgf-node[data-nodetype="input"] .title,
|
||||
.bzgf-node[data-nodetype="console"] .title{ background: #555; }
|
||||
|
||||
.bzgf-node[data-nodetype="refnodein"] .body, .bzgf-node[data-nodetype="refnodeout"] body{
|
||||
border-radius: 50%;
|
||||
}
|
||||
.bzgf-node[data-nodetype="refnodein"] .body{ background: #0F0; }
|
||||
.bzgf-node[data-nodetype="refnodeout"] .body{ background: #FF0; }
|
||||
|
||||
.bzgf-wire{ stroke: #0AF; stroke-width: 2; }
|
||||
</style>
|
||||
|
||||
@@ -170,4 +176,16 @@
|
||||
<label>Value:</label><input name="value" type="text" value="1">
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template>
|
||||
<div class="bzgf-node" data-nodetype="refnodein">
|
||||
<div class="body">{parentport}</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template>
|
||||
<div class="bzgf-node" data-nodetype="refnodeout">
|
||||
<div class="body">{parentport}</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -55,6 +55,9 @@
|
||||
<script>
|
||||
window.addEventListener('load',()=>{
|
||||
const grflw1 = document.querySelector('bz-graflow.compunet')
|
||||
grflw1.addEventListener('subflowLoaded',
|
||||
(evt) => { evt.target.querySelector('.demooptions').style.display = 'none'; }
|
||||
)
|
||||
document.querySelector('[data-trigger="onAutoplace1H"]').addEventListener('click',
|
||||
(evt) => { grflw1.autoPlace('horizontal', 80, 30, 1000, document.querySelector('[data-id="compunet"]').value) }
|
||||
)
|
||||
|
||||
@@ -9,8 +9,16 @@
|
||||
{ "nodeType": "inc",
|
||||
"subflow": "/app/assets/json/bzGraflow/testFlowEic.json",
|
||||
"portLinks": [
|
||||
{ "parentPort": ["in1"], "subflowPort": ["inp1"] },
|
||||
{ "parentPort": ["out1"], "subflowPort": ["out1"] }
|
||||
{ "refNodeType": "refnodein", "refnodePort": "out1",
|
||||
"parentPort": "in1",
|
||||
"subflowNode":"aze2", "subflowPort": "in1",
|
||||
"direction": "in"
|
||||
},
|
||||
{ "refNodeType": "refnodeout", "refnodePort": "in1",
|
||||
"parentPort": "out1",
|
||||
"subflowNode":"aze5", "subflowPort": "out1",
|
||||
"direction": "out"
|
||||
}
|
||||
],
|
||||
"id": "aze2",
|
||||
"coords": { "x": 220, "y": 10}
|
||||
|
||||
Binary file not shown.
+1982
-182
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 123 KiB After Width: | Height: | Size: 1.3 MiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 123 KiB |
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
@@ -0,0 +1,618 @@
|
||||
@font-face {
|
||||
font-family: 'glyphs';
|
||||
src: url('/app/assets/styles/fonts/glyphs.eot');
|
||||
src: url('/app/assets/styles/fonts/glyphs.eot') format('embedded-opentype'),
|
||||
url('/app/assets/styles/fonts/glyphs.ttf') format('truetype'),
|
||||
url('/app/assets/styles/fonts/glyphs.woff') format('woff'),
|
||||
url('/app/assets/styles/fonts/glyphs.svg') format('svg');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-display: block;
|
||||
}
|
||||
|
||||
[class^="icon-"], [class*=" icon-"] {
|
||||
/* use !important to prevent issues with browser extensions that change fonts */
|
||||
font-family: 'glyphs' !important;
|
||||
speak: never;
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
font-variant: normal;
|
||||
text-transform: none;
|
||||
line-height: 1;
|
||||
|
||||
/* Better Font Rendering =========== */
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
span[class*="icon-"][primary]:before { color: var(--app-color-primary); }
|
||||
span[class*="icon-"][secondary] { color: var(--app-color-secondary); }
|
||||
span[class*="icon-"][success] { color: var(--app-color-success); }
|
||||
span[class*="icon-"][danger] { color: var(--app-color-danger); }
|
||||
span[class*="icon-"][warning] { color: var(--app-color-warning); }
|
||||
span[class*="icon-"][accent] { color: var(--app-color-accent); }
|
||||
span[class*="icon-"][info] { color: var(--app-color-info); }
|
||||
|
||||
[class*="icon-"][xxsmall] { font-size: var(--eicui-base-icon-size-2xs); }
|
||||
[class*="icon-"][xsmall] { font-size: var(--eicui-base-icon-size-xs) !important; }
|
||||
[class*="icon-"][small] { font-size: var(--eicui-base-icon-size-s) !important; }
|
||||
[class*="icon-"][medium] { font-size: var(--eicui-base-icon-size-m) !important; }
|
||||
[class*="icon-"][large] { font-size: var(--eicui-base-icon-size-l) !important; }
|
||||
[class*="icon-"][xlarge] { font-size: var(--eicui-base-icon-size-xl) !important; }
|
||||
[class*="icon-"][xxlarge] { font-size: var(--eicui-base-icon-size-2xl); }
|
||||
[class*="icon-"][xxxlarge] { font-size: var(--eicui-base-icon-size-3xl); }
|
||||
[class*="icon-"][xxxxlarge] { font-size: var(--eicui-base-icon-size-4xl); }
|
||||
|
||||
@keyframes spin {
|
||||
0% { transform: rotate(0deg) ; }
|
||||
100% { transform: rotate(360deg) ; }
|
||||
}
|
||||
|
||||
@keyframes uturn {
|
||||
0% { transform: rotate(-180deg) ; }
|
||||
100% { transform: rotate(0deg) ; }
|
||||
}
|
||||
@keyframes uturn-ccw {
|
||||
0% { transform: rotate(180deg) ; }
|
||||
100% { transform: rotate(0deg) ; }
|
||||
}
|
||||
|
||||
.spin { animation: spin 1s infinite linear; }
|
||||
.arrow-expand:before {
|
||||
content: "\f106" !important;
|
||||
animation: uturn-ccw 0.3s 1 linear;
|
||||
}
|
||||
.arrow-collapse:before {
|
||||
content: "\f107" !important;
|
||||
animation: uturn 0.3s 1 normal linear;
|
||||
}
|
||||
|
||||
.icon-backward1:before {
|
||||
content: "\e905";
|
||||
}
|
||||
.icon-backward-step:before {
|
||||
content: "\e943";
|
||||
}
|
||||
.icon-fast-forward:before {
|
||||
content: "\e944";
|
||||
}
|
||||
.icon-pause2:before {
|
||||
content: "\e945";
|
||||
}
|
||||
.icon-play1:before {
|
||||
content: "\e946";
|
||||
}
|
||||
.icon-target1:before {
|
||||
content: "\e948";
|
||||
}
|
||||
.icon-usb:before {
|
||||
content: "\e949";
|
||||
}
|
||||
.icon-video-camera1:before {
|
||||
content: "\e94a";
|
||||
}
|
||||
.icon-price-tag:before {
|
||||
content: "\e93c";
|
||||
}
|
||||
.icon-align-center:before {
|
||||
content: "\e933";
|
||||
}
|
||||
.icon-align-left:before {
|
||||
content: "\e934";
|
||||
}
|
||||
.icon-align-right:before {
|
||||
content: "\e935";
|
||||
}
|
||||
.icon-format-color:before {
|
||||
content: "\e93b";
|
||||
}
|
||||
.icon-format-bold:before {
|
||||
content: "\e936";
|
||||
}
|
||||
.icon-font-size-down:before {
|
||||
content: "\e937";
|
||||
}
|
||||
.icon-format-underline:before {
|
||||
content: "\e939";
|
||||
}
|
||||
.icon-big-bullet:before {
|
||||
content: "\e928";
|
||||
}
|
||||
.icon-code:before {
|
||||
content: "\e92b";
|
||||
}
|
||||
.icon-check-rounded:before {
|
||||
content: "\e91f";
|
||||
}
|
||||
.icon-dashboard:before {
|
||||
content: "\e92a";
|
||||
}
|
||||
.icon-more:before {
|
||||
content: "\e923";
|
||||
}
|
||||
.icon-locked:before {
|
||||
content: "\e925";
|
||||
}
|
||||
.icon-unlocked:before {
|
||||
content: "\e926";
|
||||
}
|
||||
.icon-menu:before {
|
||||
content: "\e920";
|
||||
}
|
||||
.icon-reply:before {
|
||||
content: "\e921";
|
||||
}
|
||||
.icon-back:before {
|
||||
content: "\e921";
|
||||
}
|
||||
.icon-link-ext:before {
|
||||
content: "\e922";
|
||||
}
|
||||
.icon-share:before {
|
||||
content: "\e929";
|
||||
}
|
||||
.icon-workflow:before {
|
||||
content: "\e929";
|
||||
}
|
||||
.icon-health:before {
|
||||
content: "\e927";
|
||||
}
|
||||
.icon-copy:before {
|
||||
content: "\e915";
|
||||
}
|
||||
.icon-filter:before {
|
||||
content: "\e91c";
|
||||
}
|
||||
.icon-deny:before {
|
||||
content: "\e906";
|
||||
}
|
||||
.icon-home:before {
|
||||
content: "\e91d";
|
||||
}
|
||||
.icon-pause1:before {
|
||||
content: "\e916";
|
||||
}
|
||||
.icon-market:before {
|
||||
content: "\e914";
|
||||
}
|
||||
.icon-thumbs-down:before {
|
||||
content: "\e90b";
|
||||
}
|
||||
.icon-thumbs-up:before {
|
||||
content: "\e90c";
|
||||
}
|
||||
.icon-trash:before {
|
||||
content: "\e91e";
|
||||
}
|
||||
.icon-bolt:before {
|
||||
content: "\e901";
|
||||
}
|
||||
.icon-check:before {
|
||||
content: "\e902";
|
||||
}
|
||||
.icon-cancel:before {
|
||||
content: "\e907";
|
||||
}
|
||||
.icon-close:before {
|
||||
content: "\e908";
|
||||
}
|
||||
.icon-download:before {
|
||||
content: "\e903";
|
||||
}
|
||||
.icon-envelope:before {
|
||||
content: "\e909";
|
||||
}
|
||||
.icon-company:before {
|
||||
content: "\e90a";
|
||||
}
|
||||
.icon-servers:before {
|
||||
content: "\e904";
|
||||
}
|
||||
.icon-cabinet:before {
|
||||
content: "\e94b";
|
||||
}
|
||||
.icon-cabinet1:before {
|
||||
content: "\e94c";
|
||||
}
|
||||
.icon-camera1:before {
|
||||
content: "\e94e";
|
||||
}
|
||||
.icon-camera2:before {
|
||||
content: "\e94f";
|
||||
}
|
||||
.icon-film1:before {
|
||||
content: "\e950";
|
||||
}
|
||||
.icon-chronometer:before {
|
||||
content: "\e951";
|
||||
}
|
||||
.icon-chart:before {
|
||||
content: "\e952";
|
||||
}
|
||||
.icon-lab:before {
|
||||
content: "\e953";
|
||||
}
|
||||
.icon-satellite:before {
|
||||
content: "\e954";
|
||||
}
|
||||
.icon-spaceinvaders:before {
|
||||
content: "\e955";
|
||||
}
|
||||
.icon-bomb:before {
|
||||
content: "\e957";
|
||||
}
|
||||
.icon-tools:before {
|
||||
content: "\e958";
|
||||
}
|
||||
.icon-bus:before {
|
||||
content: "\e959";
|
||||
}
|
||||
.icon-stop2:before {
|
||||
content: "\e95a";
|
||||
}
|
||||
.icon-atom:before {
|
||||
content: "\e95b";
|
||||
}
|
||||
.icon-globe:before {
|
||||
content: "\e95c";
|
||||
}
|
||||
.icon-globe1:before {
|
||||
content: "\e95d";
|
||||
}
|
||||
.icon-grid:before {
|
||||
content: "\e95e";
|
||||
}
|
||||
.icon-flag:before {
|
||||
content: "\e95f";
|
||||
}
|
||||
.icon-lock:before {
|
||||
content: "\e960";
|
||||
}
|
||||
.icon-unlocked1:before {
|
||||
content: "\e961";
|
||||
}
|
||||
.icon-camera3:before {
|
||||
content: "\e962";
|
||||
}
|
||||
.icon-calculator:before {
|
||||
content: "\e963";
|
||||
}
|
||||
.icon-diamond:before {
|
||||
content: "\e965";
|
||||
}
|
||||
.icon-atom1:before {
|
||||
content: "\e966";
|
||||
}
|
||||
.icon-syringe:before {
|
||||
content: "\e967";
|
||||
}
|
||||
.icon-health1:before {
|
||||
content: "\e968";
|
||||
}
|
||||
.icon-pill:before {
|
||||
content: "\e969";
|
||||
}
|
||||
.icon-lab1:before {
|
||||
content: "\e96a";
|
||||
}
|
||||
.icon-graph:before {
|
||||
content: "\e96b";
|
||||
}
|
||||
.icon-review:before {
|
||||
content: "\e917";
|
||||
}
|
||||
.icon-correction:before {
|
||||
content: "\e918";
|
||||
}
|
||||
.icon-mediation:before {
|
||||
content: "\e919";
|
||||
}
|
||||
.icon-writing:before {
|
||||
content: "\e91b";
|
||||
}
|
||||
.icon-snapshot:before {
|
||||
content: "\e92d";
|
||||
}
|
||||
.icon-toc:before {
|
||||
content: "\e92e";
|
||||
}
|
||||
.icon-folder:before {
|
||||
content: "\e92f";
|
||||
}
|
||||
.icon-folder-open:before {
|
||||
content: "\e930";
|
||||
}
|
||||
.icon-folder-add:before {
|
||||
content: "\e931";
|
||||
}
|
||||
.icon-folder-remove:before {
|
||||
content: "\e932";
|
||||
}
|
||||
.icon-qrcode:before {
|
||||
content: "\e938";
|
||||
}
|
||||
.icon-chat:before {
|
||||
content: "\e96c";
|
||||
}
|
||||
.icon-bug:before {
|
||||
content: "\e999";
|
||||
}
|
||||
.icon-font-size-up:before {
|
||||
content: "\ea61";
|
||||
}
|
||||
.icon-format-italic:before {
|
||||
content: "\ea64";
|
||||
}
|
||||
.icon-stop:before {
|
||||
content: "\e92c";
|
||||
}
|
||||
.icon-play:before {
|
||||
content: "\e900";
|
||||
}
|
||||
.icon-history:before {
|
||||
content: "\e94d";
|
||||
}
|
||||
.icon-spinner:before {
|
||||
content: "\e981";
|
||||
}
|
||||
.icon-cog:before {
|
||||
content: "\e994";
|
||||
}
|
||||
.icon-star-empty:before {
|
||||
content: "\e9d7";
|
||||
}
|
||||
.icon-star-half:before {
|
||||
content: "\e9d8";
|
||||
}
|
||||
.icon-star-full:before {
|
||||
content: "\e9d9";
|
||||
}
|
||||
.icon-heart:before {
|
||||
content: "\e9da";
|
||||
}
|
||||
.icon-pdf:before {
|
||||
content: "\eadf";
|
||||
}
|
||||
.icon-pen:before {
|
||||
content: "\e910";
|
||||
}
|
||||
.icon-coaching:before {
|
||||
content: "\e91a";
|
||||
}
|
||||
.icon-cart:before {
|
||||
content: "\e93a";
|
||||
}
|
||||
.icon-phone:before {
|
||||
content: "\e942";
|
||||
}
|
||||
.icon-hour-glass:before {
|
||||
content: "\e90f";
|
||||
}
|
||||
.icon-refresh:before {
|
||||
content: "\e984";
|
||||
}
|
||||
.icon-complaint:before {
|
||||
content: "\e9a8";
|
||||
}
|
||||
.icon-evaluation:before {
|
||||
content: "\e9b8";
|
||||
}
|
||||
.icon-link:before {
|
||||
content: "\e9cb";
|
||||
}
|
||||
.icon-loop:before {
|
||||
content: "\ea2d";
|
||||
}
|
||||
.icon-image:before {
|
||||
content: "\e90d";
|
||||
}
|
||||
.icon-new:before {
|
||||
content: "\e924";
|
||||
}
|
||||
.icon-map:before {
|
||||
content: "\e947";
|
||||
}
|
||||
.icon-pin:before {
|
||||
content: "\e947";
|
||||
}
|
||||
.icon-user-check:before {
|
||||
content: "\e975";
|
||||
}
|
||||
.icon-cogs:before {
|
||||
content: "\e995";
|
||||
}
|
||||
.icon-bin:before {
|
||||
content: "\e9ac";
|
||||
}
|
||||
.icon-attachment:before {
|
||||
content: "\e9cd";
|
||||
}
|
||||
.icon-xls:before {
|
||||
content: "\eae2";
|
||||
}
|
||||
.icon-paint-format:before {
|
||||
content: "\e93d";
|
||||
}
|
||||
.icon-camera:before {
|
||||
content: "\e93e";
|
||||
}
|
||||
.icon-film:before {
|
||||
content: "\e93f";
|
||||
}
|
||||
.icon-video-camera:before {
|
||||
content: "\e940";
|
||||
}
|
||||
.icon-stack:before {
|
||||
content: "\e941";
|
||||
}
|
||||
.icon-display:before {
|
||||
content: "\e956";
|
||||
}
|
||||
.icon-database:before {
|
||||
content: "\e964";
|
||||
}
|
||||
.icon-target:before {
|
||||
content: "\e9b3";
|
||||
}
|
||||
.icon-tree:before {
|
||||
content: "\e9bc";
|
||||
}
|
||||
.icon-play2:before {
|
||||
content: "\ea15";
|
||||
}
|
||||
.icon-pause:before {
|
||||
content: "\ea16";
|
||||
}
|
||||
.icon-stop1:before {
|
||||
content: "\ea17";
|
||||
}
|
||||
.icon-previous:before {
|
||||
content: "\ea18";
|
||||
}
|
||||
.icon-next:before {
|
||||
content: "\ea19";
|
||||
}
|
||||
.icon-backward:before {
|
||||
content: "\ea1a";
|
||||
}
|
||||
.icon-forward2:before {
|
||||
content: "\ea1b";
|
||||
}
|
||||
.icon-embed:before {
|
||||
content: "\ea7f";
|
||||
}
|
||||
.icon-steam:before {
|
||||
content: "\eaac";
|
||||
}
|
||||
.icon-dropbox:before {
|
||||
content: "\eaae";
|
||||
}
|
||||
.icon-tux:before {
|
||||
content: "\eabd";
|
||||
}
|
||||
.icon-codepen:before {
|
||||
content: "\eae8";
|
||||
}
|
||||
.icon-sort-asc:before {
|
||||
content: "\e911";
|
||||
}
|
||||
.icon-sort-desc:before {
|
||||
content: "\e912";
|
||||
}
|
||||
.icon-unsorted:before {
|
||||
content: "\e913";
|
||||
}
|
||||
.icon-help:before {
|
||||
content: "\e90e";
|
||||
}
|
||||
.icon-plus:before {
|
||||
content: "\f067";
|
||||
}
|
||||
.icon-search:before {
|
||||
content: "\f002";
|
||||
}
|
||||
.icon-user:before {
|
||||
content: "\f007";
|
||||
}
|
||||
.icon-logoff:before {
|
||||
content: "\f011";
|
||||
}
|
||||
.icon-edit:before {
|
||||
content: "\f040";
|
||||
}
|
||||
.icon-checked:before {
|
||||
content: "\f046";
|
||||
}
|
||||
.icon-info:before {
|
||||
content: "\f05a";
|
||||
}
|
||||
.icon-expand:before {
|
||||
content: "\f065";
|
||||
}
|
||||
.icon-warning:before {
|
||||
content: "\f071";
|
||||
}
|
||||
.icon-calendar:before {
|
||||
content: "\f073";
|
||||
}
|
||||
.icon-comment:before {
|
||||
content: "\f075";
|
||||
}
|
||||
.icon-twitter:before {
|
||||
content: "\f081";
|
||||
}
|
||||
.icon-facebook:before {
|
||||
content: "\f082";
|
||||
}
|
||||
.icon-square-o:before {
|
||||
content: "\f096";
|
||||
}
|
||||
.icon-website:before {
|
||||
content: "\f0ac";
|
||||
}
|
||||
.icon-users:before {
|
||||
content: "\f0c0";
|
||||
}
|
||||
.icon-list-ul:before {
|
||||
content: "\f0ca";
|
||||
}
|
||||
.icon-table:before {
|
||||
content: "\f0ce";
|
||||
}
|
||||
.icon-exchange:before {
|
||||
content: "\f0ec";
|
||||
}
|
||||
.icon-alert:before {
|
||||
content: "\f0f3";
|
||||
}
|
||||
.icon-chevron-left:before {
|
||||
content: "\f100";
|
||||
}
|
||||
.icon-chevron-right:before {
|
||||
content: "\f101";
|
||||
}
|
||||
.icon-angle-left:before {
|
||||
content: "\f104";
|
||||
}
|
||||
.icon-angle-right:before {
|
||||
content: "\f105";
|
||||
}
|
||||
.icon-angle-up:before {
|
||||
content: "\f106";
|
||||
}
|
||||
.icon-angle-down:before {
|
||||
content: "\f107";
|
||||
}
|
||||
.icon-zip:before {
|
||||
content: "\f1c6";
|
||||
}
|
||||
.icon-send:before {
|
||||
content: "\f1d8";
|
||||
}
|
||||
.icon-preview:before {
|
||||
content: "\f1e5";
|
||||
}
|
||||
.icon-stats:before {
|
||||
content: "\f200";
|
||||
}
|
||||
.icon-toggle-off:before {
|
||||
content: "\f204";
|
||||
}
|
||||
.icon-toggle-on:before {
|
||||
content: "\f205";
|
||||
}
|
||||
.icon-user-add:before {
|
||||
content: "\f234";
|
||||
}
|
||||
.icon-calendar-plus:before {
|
||||
content: "\f271";
|
||||
}
|
||||
.icon-calendar-minus:before {
|
||||
content: "\f272";
|
||||
}
|
||||
.icon-calendar-failed:before {
|
||||
content: "\f273";
|
||||
}
|
||||
.icon-calendar-check:before {
|
||||
content: "\f274";
|
||||
}
|
||||
+2699
-548
File diff suppressed because it is too large
Load Diff
Vendored
+138
-27
@@ -18,6 +18,11 @@ class BZgraflow extends Buildoz{
|
||||
e: { x: 1, y: 0 },
|
||||
w: { x: -1, y: 0 },
|
||||
}
|
||||
btnIcons = {
|
||||
zoomin:'M992.262 88.604l-242.552 206.294c-25.074 22.566-51.89 32.926-73.552 31.926 57.256 67.068 91.842 154.078 91.842 249.176 0 212.078-171.922 384-384 384-212.076 0-384-171.922-384-384s171.922-384 384-384c95.098 0 182.108 34.586 249.176 91.844-1-21.662 9.36-48.478 31.926-73.552l206.294-242.552c35.322-39.246 93.022-42.554 128.22-7.356s31.892 92.898-7.354 128.22zM384 320c-141.384 0-256 114.616-256 256s114.616 256 256 256 256-114.616 256-256-114.614-256-256-256zM448 768h-128v-128h-128v-128h128v-128h128v128h128v128h-128z',
|
||||
zoomout:'M992.262 88.604l-242.552 206.294c-25.074 22.566-51.89 32.926-73.552 31.926 57.256 67.068 91.842 154.078 91.842 249.176 0 212.078-171.922 384-384 384-212.076 0-384-171.922-384-384s171.922-384 384-384c95.098 0 182.108 34.586 249.176 91.844-1-21.662 9.36-48.478 31.926-73.552l206.294-242.552c35.322-39.246 93.022-42.554 128.22-7.356s31.892 92.898-7.354 128.22zM384 320c-141.384 0-256 114.616-256 256s114.616 256 256 256 256-114.616 256-256-114.614-256-256-256zM320 380v384h128V448z',
|
||||
}
|
||||
|
||||
static _loadedNodeStyles = new Set() // Allow multi instances or re-loadNodes, but avoid reinjecting same styles !
|
||||
|
||||
constructor(){
|
||||
@@ -28,6 +33,10 @@ class BZgraflow extends Buildoz{
|
||||
this.arrowDefs = null
|
||||
}
|
||||
|
||||
addIcon(el, name) {
|
||||
el.innerHTML = `<svg viewBox="0 0 1024 1024" width="20" height="20" fill="#000000"><g transform="rotate(90 512 512)"><path d="${this.btnIcons[name]}"/></g></svg>`
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
super.connectedCallback()
|
||||
const flowUrl = this.getBZAttribute('flow')
|
||||
@@ -45,7 +54,7 @@ class BZgraflow extends Buildoz{
|
||||
const style = document.createElement('style')
|
||||
//TODO kick this wart somewhere under a carpet
|
||||
style.textContent = `
|
||||
@import '/app/assets/styles/icons.css';
|
||||
/*@import '/app/assets/styles/icons.css';*/
|
||||
.bzgf-wires-container,
|
||||
.bzgf-nodes-container{ position: absolute; inset: 0; width: 100%; height: 100%; }
|
||||
.bzgf-nodes-container .bzgf-node{ position:absolute; }
|
||||
@@ -57,13 +66,20 @@ class BZgraflow extends Buildoz{
|
||||
border-style: none;
|
||||
}
|
||||
.bzgf-nodes-container button.bzgf-zoom-in{
|
||||
width: 2em;
|
||||
height: 2em;
|
||||
z-index: 999;
|
||||
position: absolute;
|
||||
top: -1em;
|
||||
top: -0.5em;
|
||||
right: -1em;
|
||||
color: #A00;
|
||||
color: black;
|
||||
width: 2em;
|
||||
height: 2em;
|
||||
padding: 0;
|
||||
}
|
||||
bz-graflow button.bzgf-zoom-out{
|
||||
z-index: 999;
|
||||
position: absolute;
|
||||
left: 5px;
|
||||
top: 5px;
|
||||
}
|
||||
`
|
||||
this.mainContainer.appendChild(style)
|
||||
@@ -102,6 +118,11 @@ class BZgraflow extends Buildoz{
|
||||
await this.loadNodes(flowObj.nodesFile)
|
||||
this.flow = flowObj.flow
|
||||
this.refresh()
|
||||
this.dispatchEvent(new CustomEvent('flowLoaded', {
|
||||
detail: { url },
|
||||
bubbles: true,
|
||||
composed: true,
|
||||
}))
|
||||
}
|
||||
|
||||
async loadNodes(url) {
|
||||
@@ -135,6 +156,11 @@ class BZgraflow extends Buildoz{
|
||||
// In isolated (shadow DOM) mode, styles must be injected per instance.
|
||||
if(!isIsolated) BZgraflow._loadedNodeStyles.add(url)
|
||||
}
|
||||
this.dispatchEvent(new CustomEvent('nodesLoaded', {
|
||||
detail: { url },
|
||||
bubbles: true,
|
||||
composed: true,
|
||||
}))
|
||||
}
|
||||
|
||||
addNode(node){
|
||||
@@ -153,17 +179,21 @@ class BZgraflow extends Buildoz{
|
||||
this.stagedNodes[id].ports = Object.fromEntries(Array.from(portEls).map(item => ([item.dataset.id, { ...item.dataset, el:item }])))
|
||||
if(node.subflow) {
|
||||
const btnEnterSubflow = document.createElement('button')
|
||||
btnEnterSubflow.classList.add('bzgf-zoom-in', 'icon-copy')
|
||||
btnEnterSubflow.classList.add('bzgf-zoom-in')
|
||||
this.addIcon(btnEnterSubflow, 'zoomin')
|
||||
btnEnterSubflow.addEventListener('click', () => {
|
||||
this.EnterSubflow(id)
|
||||
this.enterSubflow(id)
|
||||
})
|
||||
this.stagedNodes[id].appendChild(btnEnterSubflow)
|
||||
}
|
||||
this.nodesContainer.append(this.stagedNodes[id])
|
||||
if(!this.flow.nodes.find(n => n.id === id)) {
|
||||
this.flow.nodes.push(node)
|
||||
}
|
||||
return(this.stagedNodes[id])
|
||||
}
|
||||
|
||||
EnterSubflow(id){
|
||||
enterSubflow(id){
|
||||
const nodeEl = this.stagedNodes[id]
|
||||
if(!nodeEl) return
|
||||
|
||||
@@ -178,14 +208,45 @@ class BZgraflow extends Buildoz{
|
||||
const childEl = document.createElement('bz-graflow')
|
||||
childEl.setAttribute('flow', flowUrl)
|
||||
childEl.setAttribute('tension', this.getBZAttribute('tension') || '60')
|
||||
// Remember which node we "came from" so exitSubflow() can animate back to it.
|
||||
childEl.dataset.enterNodeId = id
|
||||
// Match the clicked node's border so the transition feels like we're "expanding" it.
|
||||
const nodeStyle = getComputedStyle(nodeEl)
|
||||
childEl.style.border = nodeStyle.border
|
||||
childEl.style.borderRadius = nodeStyle.borderRadius
|
||||
childEl.style.backgroundColor = nodeStyle.backgroundColor
|
||||
|
||||
const btnExitSubflow = document.createElement('button')
|
||||
btnExitSubflow.classList.add('bzgf-zoom-out')
|
||||
this.addIcon(btnExitSubflow, 'zoomout')
|
||||
btnExitSubflow.addEventListener('click', () => {
|
||||
this.exitSubflow(childEl)
|
||||
})
|
||||
childEl.appendChild(btnExitSubflow)
|
||||
// Put the child in the exact same viewport rect as the parent (fixed overlay)
|
||||
this.Invade(this, childEl)
|
||||
this.invade(this, childEl)
|
||||
|
||||
childEl.addEventListener('flowLoaded', (e) => {
|
||||
for(const portLink of flowNode.portLinks){
|
||||
const nid = crypto.randomUUID()
|
||||
childEl.addNode({
|
||||
"nodeType": portLink.refNodeType,
|
||||
"id": nid,
|
||||
"markup": { "parentport": portLink.parentPort }
|
||||
})
|
||||
if(portLink.direction=='in') {
|
||||
childEl.addWire({
|
||||
"from": [nid, portLink.refnodePort],
|
||||
"to": [portLink.subflowNode, portLink.subflowPort]
|
||||
})
|
||||
} else if(portLink.direction=='out') {
|
||||
childEl.addWire({
|
||||
"from": [portLink.subflowNode, portLink.subflowPort],
|
||||
"to": [nid, portLink.refnodePort]
|
||||
})
|
||||
}
|
||||
}
|
||||
childEl.autoPlace('horizontal', 60, 60)
|
||||
})
|
||||
|
||||
// Fade out the current (host) graflow while the child scales up
|
||||
this.hostContainer.style.opacity = '1'
|
||||
@@ -220,10 +281,15 @@ class BZgraflow extends Buildoz{
|
||||
childEl.addEventListener('transitionend', (e) => {
|
||||
if(e.propertyName !== 'transform') return
|
||||
this.hostContainer.style.visibility = 'hidden'
|
||||
this.dispatchEvent(new CustomEvent('subflowLoaded', {
|
||||
detail: { flowUrl },
|
||||
bubbles: true,
|
||||
composed: true,
|
||||
}))
|
||||
}, { once:true })
|
||||
}
|
||||
|
||||
Invade(oldEl, newEl){
|
||||
invade(oldEl, newEl){
|
||||
const r = oldEl.getBoundingClientRect()
|
||||
newEl.style.position = 'fixed'
|
||||
newEl.style.left = r.left + 'px'
|
||||
@@ -234,14 +300,58 @@ class BZgraflow extends Buildoz{
|
||||
oldEl.appendChild(newEl)
|
||||
}
|
||||
|
||||
Evade(oldEl, newEl){
|
||||
oldEl.style.visibility = 'visible'
|
||||
oldEl.style.position = 'absolute'
|
||||
oldEl.style.left = '0'
|
||||
oldEl.style.top = '0'
|
||||
oldEl.style.width = '0'
|
||||
oldEl.style.height = '0'
|
||||
newEl.parentNode.removeChild(newEl)
|
||||
exitSubflow(childEl){
|
||||
if(!childEl) return
|
||||
|
||||
const enterNodeId = childEl.dataset?.enterNodeId
|
||||
const nodeEl = enterNodeId ? this.stagedNodes?.[enterNodeId] : null
|
||||
if(!nodeEl){
|
||||
// Fallback: no context => just restore parent & remove child
|
||||
this.hostContainer.style.opacity = '1'
|
||||
this.hostContainer.style.visibility = 'visible'
|
||||
if(childEl.parentNode === this) this.removeChild(childEl)
|
||||
return
|
||||
}
|
||||
|
||||
// Compute target transform from full-size back to node rect (inverse of EnterSubflow)
|
||||
const nodeBB = nodeEl.getBoundingClientRect()
|
||||
const parentBB = this.getBoundingClientRect()
|
||||
const sx0 = nodeBB.width / parentBB.width
|
||||
const sy0 = nodeBB.height / parentBB.height
|
||||
const tx0 = nodeBB.left - parentBB.left
|
||||
const ty0 = nodeBB.top - parentBB.top
|
||||
|
||||
// Try to match duration to the child's transform transition (default 1000ms)
|
||||
const transitionStr = childEl.style.transition || ''
|
||||
const msMatch = transitionStr.match(/(\d+(?:\.\d+)?)ms/)
|
||||
const durMs = msMatch ? parseFloat(msMatch[1]) : 1000
|
||||
|
||||
// Ensure parent is visible but faded-in during the shrink animation
|
||||
this.hostContainer.style.visibility = 'visible'
|
||||
this.hostContainer.style.opacity = '0'
|
||||
this.hostContainer.style.transition = `opacity ${durMs}ms ease-in-out`
|
||||
|
||||
// Ensure child animates (it should already have the transform transition set)
|
||||
childEl.style.transition = `transform ${durMs}ms ease-in-out`
|
||||
childEl.getBoundingClientRect() // flush
|
||||
|
||||
requestAnimationFrame(() => {
|
||||
// Shrink/move the child back into the original node
|
||||
childEl.style.setProperty('--tx', tx0 + 'px')
|
||||
childEl.style.setProperty('--ty', ty0 + 'px')
|
||||
childEl.style.setProperty('--sx', sx0)
|
||||
childEl.style.setProperty('--sy', sy0)
|
||||
// Fade the parent back in
|
||||
this.hostContainer.style.opacity = '1'
|
||||
})
|
||||
|
||||
childEl.addEventListener('transitionend', (e) => {
|
||||
if(e.propertyName !== 'transform') return
|
||||
if(childEl.parentNode === this) this.removeChild(childEl)
|
||||
// Cleanup: ensure parent is fully visible and no longer hidden
|
||||
this.hostContainer.style.opacity = '1'
|
||||
this.hostContainer.style.visibility = 'visible'
|
||||
}, { once:true })
|
||||
}
|
||||
|
||||
addFakeNode(nid, x, y, w, h){
|
||||
@@ -269,10 +379,12 @@ class BZgraflow extends Buildoz{
|
||||
this.stagedWires[id].classList.add('bzgf-wire')
|
||||
this.stagedWires[id].dataset.id = id
|
||||
this.wiresContainer.append(this.stagedWires[id])
|
||||
if(!this.flow.links.find(l => l.from[0] === idNode1 && l.from[1] === idPort1 && l.to[0] === idNode2 && l.to[1] === idPort2)) {
|
||||
this.flow.links.push(link)
|
||||
}
|
||||
return(this.stagedWires[id])
|
||||
}
|
||||
|
||||
|
||||
clear(){
|
||||
this.nodesContainer.innerHTML = ''
|
||||
this.wiresContainer.innerHTML = ''
|
||||
@@ -670,15 +782,14 @@ class BZgraflow extends Buildoz{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
getLink(nid1, nid2){
|
||||
const real = this.flow.links.find(item => ((item.from[0]==nid1) && (item.to[0]==nid2)))
|
||||
if(real) return(real)
|
||||
const v = this._virtualLinks?.get(`${nid1}__${nid2}`)
|
||||
if(v) return(v)
|
||||
return(null)
|
||||
let lnk = null
|
||||
lnk = this.flow.links.find(item => ((item.from[0]==nid1) && (item.to[0]==nid2)))
|
||||
if(!lnk) {
|
||||
lnk = this._virtualLinks?.get(`${nid1}__${nid2}`)
|
||||
}
|
||||
return(lnk)
|
||||
}
|
||||
|
||||
buildGraphStructures(nodes, links, includeLinkIndexes = false) {
|
||||
|
||||
Reference in New Issue
Block a user