Files
openobserve/web/src/plugins/pipelines/CustomNode.vue
T
Sai Nikhil 5dab735d3e fix: removed unused code and warnings while in dev mode / build (#8026)
### **User description**
1. removed defineProps , defineEmits as they are not required to import
while using <script setup> because they are built in compiler macros
2. removed unused imports 
3. added tbody around tr td inside table which was throwing an error


___

### **PR Type**
Bug fix, Enhancement


___

### **Description**
- Wrap table rows with tbody in DateTime

- Remove unused Vue imports and emits

- Clean up dead code and variables

- Minor formatting and consistency fixes


___

### Diagram Walkthrough


```mermaid
flowchart LR
  A["Vue components"] -- "remove unused imports/defines" --> B["Cleaner scripts"]
  A -- "table rows wrapped with tbody" --> C["Valid HTML structure"]
  C -- "prevents runtime/warning errors" --> D["Stabler UI"]
```



<details> <summary><h3> File Walkthrough</h3></summary>

<table><thead><tr><th></th><th align="left">Relevant
files</th></tr></thead><tbody><tr><td><strong>Bug
fix</strong></td><td><details><summary>1 files</summary><table>
<tr>
<td><strong>DateTime.vue</strong><dd><code>Add tbody wrapper to table
rows</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td>
<td><a
href="https://github.com/openobserve/openobserve/pull/8026/files#diff-c06c96ba750be6fc82f517a53ba809efff8aa619aba203b871d4d2aeb7f64f60">+78/-76</a>&nbsp;
</td>

</tr>

</table></details></td></tr><tr><td><strong>Enhancement</strong></td><td><details><summary>21
files</summary><table>
<tr>
<td><strong>FileItem.vue</strong><dd><code>Drop unused
defineProps/defineEmits imports</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
</dd></td>
<td><a
href="https://github.com/openobserve/openobserve/pull/8026/files#diff-ba91340f65190fae07746a2877b42357f3c4b10eb9969e7fc6fe393655bc8752">+1/-1</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>

<tr>
<td><strong>AddDestination.vue</strong><dd><code>Remove unused Vue APIs
and service import</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
</dd></td>
<td><a
href="https://github.com/openobserve/openobserve/pull/8026/files#diff-61b295458e13049a538f5014124855d58dce664dfbd644b57a964a37a07b7a3f">+0/-4</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>

<tr>
<td><strong>AddTemplate.vue</strong><dd><code>Trim unused Vue
composition imports</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td>
<td><a
href="https://github.com/openobserve/openobserve/pull/8026/files#diff-2508a43827e6b35c07f3222deebd9945101ca6bc32b9dc592e6253ab99908bba">+0/-4</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>

<tr>
<td><strong>AlertsContainer.vue</strong><dd><code>Simplify imports to
only computed</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td>
<td><a
href="https://github.com/openobserve/openobserve/pull/8026/files#diff-39b487d54970cff4a1ccdfbb49a4ccb38f7131bb9d30944ce1c6e86d3f818148">+1/-1</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>

<tr>
<td><strong>FieldsInput.vue</strong><dd><code>Remove unused defineProps
from imports</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; </dd></td>
<td><a
href="https://github.com/openobserve/openobserve/pull/8026/files#diff-a2dcba327fb56cd4cb52efb06fccc256a71fd8a551b826c6c94e71dad75524f5">+1/-1</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>

<tr>
<td><strong>FilterCondition.vue</strong><dd><code>Drop unused
defineProps import</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; </dd></td>
<td><a
href="https://github.com/openobserve/openobserve/pull/8026/files#diff-53916e2402d0ee094fcd63f0ec0c99ceffde4fa042f9001203d2e2e1b7709e10">+1/-1</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>

<tr>
<td><strong>VariablesInput.vue</strong><dd><code>Remove unused
defineProps import line</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; </dd></td>
<td><a
href="https://github.com/openobserve/openobserve/pull/8026/files#diff-23a647aa1acfc95bc726629f0daa54005e3da1ed5b16482ceccef0649f680a74">+0/-1</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>

<tr>
<td><strong>AddCipherKey.vue</strong><dd><code>Remove unused defineEmits
from imports</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; </dd></td>
<td><a
href="https://github.com/openobserve/openobserve/pull/8026/files#diff-ff5ae3a9b070fe2b3650f177ced0d87e9449ae7375a0b117ee299238293df110">+1/-1</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>

<tr>
<td><strong>AppTabs.vue</strong><dd><code>Remove unused defineProps from
import</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; </dd></td>
<td><a
href="https://github.com/openobserve/openobserve/pull/8026/files#diff-f69ae88c0f2018ea808724a0eaee5bd008fd1608c52f7ca20215fc6033f00573">+1/-1</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>

<tr>
<td><strong>FunctionsToolbar.vue</strong><dd><code>Prune unused
composition API imports</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td>
<td><a
href="https://github.com/openobserve/openobserve/pull/8026/files#diff-8283d2ff9c4a66b4b59eac306672aca2d54655a462e2ddb88e14e039d79dcdaf">+0/-4</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>

<tr>
<td><strong>EntityPermissionTable.vue</strong><dd><code>Remove unused
defineEmits/defineProps imports</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td>
<td><a
href="https://github.com/openobserve/openobserve/pull/8026/files#diff-07b373cc19e7893c8a8a29f5e6d10b8c74d15d6ad3a4d04f5c06b55d0d8de395">+1/-2</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>

<tr>
<td><strong>PermissionsTable.vue</strong><dd><code>Remove unused
defineEmits import</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
</dd></td>
<td><a
href="https://github.com/openobserve/openobserve/pull/8026/files#diff-609d4d7245b7309cf30cc45c22c996c6b068ebc042a9673e75ee3bbd2aa00a2a">+0/-1</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>

<tr>
<td><strong>AssociateFunction.vue</strong><dd><code>Remove unused emits
and lifecycle imports</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
</dd></td>
<td><a
href="https://github.com/openobserve/openobserve/pull/8026/files#diff-24a5b2df69327a6477227ea674939dea19dd6d393b4bfcf807089d71e6391152">+0/-2</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>

<tr>
<td><strong>ExternalDestination.vue</strong><dd><code>Remove unused
Vue/imports and reactive</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; </dd></td>
<td><a
href="https://github.com/openobserve/openobserve/pull/8026/files#diff-7ed6a9ef676d7d6db5440d4157512f731bad58716c351ca39015125a8a9d2df5">+0/-3</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>

<tr>
<td><strong>Stream.vue</strong><dd><code>Drop unused imports and
services</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td>
<td><a
href="https://github.com/openobserve/openobserve/pull/8026/files#diff-1a17ced9dc89022502cab0a6f9b97b413c2a2c4f8219733d063fc0180d361739">+1/-2</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>

<tr>
<td><strong>PipelineEditor.vue</strong><dd><code>Remove unused
defineEmits import</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
</dd></td>
<td><a
href="https://github.com/openobserve/openobserve/pull/8026/files#diff-68c21f647336067eb79737ce9aca2d49632f2fa1c0878bcfdae55607e3473a15">+0/-1</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>

<tr>
<td><strong>StreamSelection.vue</strong><dd><code>Remove unused
defineEmits import</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
</dd></td>
<td><a
href="https://github.com/openobserve/openobserve/pull/8026/files#diff-461440be35cc15b6b78700c8a61747ea9fb601a750af5292fa2d04b6fc96d595">+1/-1</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>

<tr>
<td><strong>TenstackTable.vue</strong><dd><code>Remove unused
defineEmits import</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
</dd></td>
<td><a
href="https://github.com/openobserve/openobserve/pull/8026/files#diff-bc3c669f5ab65a42ae378df1f7d6b35014c9c220790bdcc72b47f55d1385dc22">+0/-1</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>

<tr>
<td><strong>CellActions.vue</strong><dd><code>Remove unused imports and
helpers</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td>
<td><a
href="https://github.com/openobserve/openobserve/pull/8026/files#diff-de54e5b8cd9503c53f3f802ac7bc7e3d25846f1657c77cd99534d9f60673992e">+1/-2</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>

<tr>
<td><strong>CustomNode.vue</strong><dd><code>Remove unused refs and
image vars</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td>
<td><a
href="https://github.com/openobserve/openobserve/pull/8026/files#diff-b9d83cd503b6d3470b238accaaea0b4decf567add8ad4727c63c9e583725f408">+1/-5</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>

<tr>
<td><strong>AdvancedValuesFilter.vue</strong><dd><code>Remove unused
defineEmits import</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
</dd></td>
<td><a
href="https://github.com/openobserve/openobserve/pull/8026/files#diff-19f84276e3e0eebf0af0707cc9480e2dd7434c8e77be13456a1c0607860af3b2">+1/-1</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>
</table></details></td></tr></tr></tbody></table>

</details>

___
2025-08-17 14:45:08 +05:30

804 lines
23 KiB
Vue

<!-- Copyright 2023 OpenObserve Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<script setup>
import { Handle } from "@vue-flow/core";
import useDragAndDrop from "./useDnD";
import { ref } from "vue";
import { useI18n } from "vue-i18n";
import ConfirmDialog from "@/components/ConfirmDialog.vue";
import { getImageURL } from "@/utils/zincutils";
import config from "@/aws-exports";
const functionImage = getImageURL("images/pipeline/function.svg");
const streamOutputImage = getImageURL("images/pipeline/outputStream.svg");
const conditionImage = getImageURL("images/pipeline/condition.svg");
const externalOutputImage = getImageURL("images/pipeline/externalOutput.svg");
const props = defineProps({
id: {
type: String,
},
data: {
type: Object,
},
io_type: {
type: String,
},
});
const emit = defineEmits(["delete:node"]);
const { pipelineObj, deletePipelineNode,onDragStart,onDrop } = useDragAndDrop();
const menu = ref(false)
const hanldeMouseOver = () => {
console.log("mouse over")
}
const onFunctionClick = (data,event,id) =>{
pipelineObj.userSelectedNode = data;
const dataToOpen = {
label: "Function",
subtype: "function",
io_type: "default",
icon: "img:" + functionImage,
tooltip: "Function Node",
isSectionHeader: false,
};
pipelineObj.userClickedNode = id;
onDragStart(event,dataToOpen)
onDrop(event,{x:100,y:100});
menu.value = false
}
const onConditionClick = (data,event,id) =>{
data.label = id;
pipelineObj.userSelectedNode = data;
const dataToOpen = {
label: "Condition",
subtype: "condition",
io_type: "default",
icon: "img:" + conditionImage,
tooltip: "Condition Node",
isSectionHeader: false,
}
pipelineObj.userClickedNode = id
onDragStart(event,dataToOpen)
onDrop(event,{x:100,y:100});
menu.value = false
}
const onStreamOutputClick = (data,event,id) =>{
pipelineObj.userSelectedNode = data;
if(!id){
pipelineObj.userClickedNode = data.label;
}
else{
pipelineObj.userClickedNode = id;
}
const dataToOpen =
{
label: "Stream",
subtype: "stream",
io_type: "output",
icon: "img:" + streamOutputImage,
tooltip: "Destination: Stream Node",
isSectionHeader: false,
}
// pipelineObj.userClickedNode = id
onDragStart(event,dataToOpen)
onDrop(event,{x:100,y:100});
menu.value = false
}
const onExternalDestinationClick = (data,event,id) =>{
pipelineObj.userSelectedNode = data;
if(!id){
pipelineObj.userClickedNode = data.label;
}
else{
pipelineObj.userClickedNode = id;
}
const dataToOpen =
{
label: "Remote",
subtype: "remote_stream",
io_type: "output",
icon: "img:" + externalOutputImage,
tooltip: "Destination: Remote Node",
isSectionHeader: false,
}
// pipelineObj.userClickedNode = id
onDragStart(event,dataToOpen)
onDrop(event,{x:100,y:100});
menu.value = false
}
const { t } = useI18n();
const editNode = (id) => {
//from id find the node from pipelineObj.currentSelectedPipelineData.nodes
const fullNode = pipelineObj.currentSelectedPipeline.nodes.find(
(node) => node.id === id
);
pipelineObj.isEditNode = true;
pipelineObj.currentSelectedNodeData = fullNode;
pipelineObj.currentSelectedNodeID = id;
pipelineObj.dialog.name = fullNode.data.node_type;
pipelineObj.dialog.show = true;
};
const deleteNode = (id) => {
openCancelDialog(id);
};
const functionInfo = (data) => {
return pipelineObj.functions[data.name] || null;
}
const confirmDialogMeta = ref({
show: false,
title: "",
message: "",
data: null,
onConfirm: () => {},
});
const openCancelDialog = (id) => {
confirmDialogMeta.value.show = true;
confirmDialogMeta.value.title = t("common.delete");
confirmDialogMeta.value.message = "Are you sure you want to delete node?";
confirmDialogMeta.value.onConfirm = () => {
deletePipelineNode(id);
};
};
const resetConfirmDialog = () => {
confirmDialogMeta.value.show = false;
confirmDialogMeta.value.title = "";
confirmDialogMeta.value.message = "";
confirmDialogMeta.value.onConfirm = () => {};
};
function getIcon(data, ioType) {
const searchTerm = data.node_type;
const node = pipelineObj.nodeTypes.find(
(node) => node.subtype === searchTerm && node.io_type === ioType,
);
return node ? node.icon : undefined;
}
</script>
<template>
<!-- Input Handle (Target) -->
<div class="o2vf_node">
<Handle
v-if="io_type == 'output' || io_type === 'default'"
id="input"
type="target"
:position="'top'"
class="node_handle_custom"
/>
<div
v-if="data.node_type == 'function'"
:class="`o2vf_node_${io_type}`"
class="custom-btn q-pa-none btn-fixed-width"
style="
padding: 5px 2px;
width: fit-content;
display: flex;
align-items: center;
border: none;
cursor: pointer;
"
@mouseover="menu = true"
@mouseleave="menu = false"
>
<q-menu @mouseover="menu = true" @mouseleave="menu = false" v-model="menu" name="myMenu" class="menu-list" anchor="top right" self="top left">
<q-list >
<q-item clickable @click="(event) => onFunctionClick(data, event,id)">
<q-item-section avatar>
<img :src="functionImage" alt="Function" style="width: 30px; height: 30px;">
<q-tooltip anchor="top middle" self="bottom right">Function</q-tooltip>
</q-item-section>
</q-item>
<q-item clickable @click="(event) => onConditionClick(data, event,id)">
<q-item-section avatar>
<img :src="conditionImage" alt="Stream" style="width: 30px; height: 30px;">
<q-tooltip anchor="top middle" self="bottom right">Condition</q-tooltip>
</q-item-section>
</q-item>
<q-item clickable @click="(event) => onStreamOutputClick(data, event,id)">
<q-item-section avatar>
<img :src="streamOutputImage" alt="Output Stream" style="width: 30px; height: 30px;">
<q-tooltip anchor="top middle" self="bottom right">Output</q-tooltip>
</q-item-section>
</q-item>
<q-item
v-if="config.isEnterprise == 'true'"
clickable
@click="(event) => onExternalDestinationClick(data, event, id)"
>
<q-item-section avatar>
<img :src="externalOutputImage" alt="Remote Destination" style="width: 30px; height: 30px;">
<q-tooltip anchor="top middle" self="bottom right">Remote</q-tooltip>
</q-item-section>
</q-item>
<!-- Add more items similarly for other images -->
</q-list>
</q-menu>
<q-tooltip :style="{ maxWidth: '300px', whiteSpace: 'pre-wrap' }">
<div>
<strong>Name:</strong> {{ functionInfo(data).name }}<br />
<strong>Definition:</strong><br />
<div style="border: 1px solid lightgray; padding: 4px; border-radius: 1px ;">
{{ functionInfo(data).function }}
</div>
</div>
</q-tooltip>
<div class="icon-container " style="display: flex; align-items: center">
<!-- Icon -->
<q-icon
:name="getIcon(data, io_type)"
size="1em"
class="q-ma-sm"
/>
</div>
<!-- Separator -->
<q-separator vertical class="q-mr-sm" />
<!-- Label -->
<div class="container">
<div
class="row"
align="left"
style="
text-align: left;
text-wrap: wrap;
width: auto;
text-overflow: ellipsis;
"
>
{{ data.name }}
</div>
<div class="row">
<div style="text-transform: capitalize">
Run
{{
data.after_flatten ? "After Flattening" : "Before Flattening"
}}
</div>
</div>
</div>
<div class="float-right tw-pl-2">
<q-btn
flat
round
dense
icon="edit"
size="0.8em"
@click="editNode(id)"
/>
<q-btn
flat
round
dense
icon="delete"
size="0.8em"
@click="deleteNode(id)"
/>
</div>
</div>
<div
v-if="data.node_type == 'stream'"
:class="`o2vf_node_${io_type}`"
class="custom-btn q-pa-none btn-fixed-width"
style="
width: fit-content;
display: flex;
align-items: center;
border: none;
cursor: pointer;
padding: 5px 2px;
"
@mouseover="menu = true"
@mouseleave="menu = false"
>
<q-menu v-if="io_type == 'input'" @mouseover="menu = true" @mouseleave="menu = false" v-model="menu" name="myMenu" class="menu-list" anchor="top right" self="top left">
<q-list >
<q-item clickable @click="(event) => onFunctionClick(data, event,id)">
<q-item-section avatar>
<img :src="functionImage" alt="Function" style="width: 30px; height: 30px;">
<q-tooltip anchor="top middle" self="bottom right">Function</q-tooltip>
</q-item-section>
</q-item>
<q-item clickable @click="(event) => onConditionClick(data, event,id)">
<q-item-section avatar>
<img :src="conditionImage" alt="Stream" style="width: 30px; height: 30px;">
<q-tooltip anchor="top middle" self="bottom right">Condition</q-tooltip>
</q-item-section>
</q-item>
<q-item clickable @click="(event) => onStreamOutputClick(data, event,id)">
<q-item-section avatar>
<img :src="streamOutputImage" alt="Output Stream" style="width: 30px; height: 30px;">
<q-tooltip anchor="top middle" self="bottom right">Output</q-tooltip>
</q-item-section>
</q-item>
<q-item
v-if="config.isEnterprise == 'true'"
clickable
@click="(event) => onExternalDestinationClick(data, event, id)"
>
<q-item-section avatar>
<img :src="externalOutputImage" alt="Remote Destination" style="width: 30px; height: 30px;">
<q-tooltip anchor="top middle" self="bottom right">Remote</q-tooltip>
</q-item-section>
</q-item>
<!-- Add more items similarly for other images -->
</q-list>
</q-menu>
<div class="icon-container" style="display: flex; align-items: center">
<!-- Icon -->
<q-icon
:name="getIcon(data, io_type)"
size="1em"
class="q-ma-sm"
/>
</div>
<!-- Separator -->
<q-separator vertical class="q-mr-sm" />
<!-- Label -->
<div class="container">
<div
v-if=" data.stream_name && data.stream_name.hasOwnProperty('label')"
class="row"
style="
text-align: left;
text-wrap: wrap;
width: auto;
text-overflow: ellipsis;
"
>
{{ data.stream_type }} - {{ data.stream_name.label }}
</div>
<div
v-else
class="row"
style="
text-align: left;
text-wrap: wrap;
width: auto;
text-overflow: ellipsis;
"
>
{{ data.stream_type }} - {{ data.stream_name }}
</div>
</div>
<div class="float-right tw-pl-2">
<q-btn
flat
round
dense
icon="edit"
size="0.8em"
@click="editNode(id)"
/>
<q-btn
flat
round
dense
icon="delete"
size="0.8em"
@click="deleteNode(id)"
/>
</div>
</div>
<div
v-if="data.node_type == 'remote_stream'"
:class="`o2vf_node_${io_type}`"
class="custom-btn q-pa-none btn-fixed-width"
style="
width: fit-content;
display: flex;
align-items: center;
border: none;
cursor: pointer;
padding: 5px 2px;
"
@mouseover="menu = true"
@mouseleave="menu = false"
>
<q-menu v-if="io_type == 'input'" @mouseover="menu = true" @mouseleave="menu = false" v-model="menu" name="myMenu" class="menu-list" anchor="top right" self="top left">
<q-list >
<q-item clickable @click="(event) => onFunctionClick(data, event,id)">
<q-item-section avatar>
<img :src="functionImage" alt="Function" style="width: 30px; height: 30px;">
<q-tooltip anchor="top middle" self="bottom right">Function</q-tooltip>
</q-item-section>
</q-item>
<q-item clickable @click="(event) => onConditionClick(data, event,id)">
<q-item-section avatar>
<img :src="conditionImage" alt="Stream" style="width: 30px; height: 30px;">
<q-tooltip anchor="top middle" self="bottom right">Condition</q-tooltip>
</q-item-section>
</q-item>
<q-item clickable @click="(event) => onStreamOutputClick(data, event,id)">
<q-item-section avatar>
<img :src="streamOutputImage" alt="Output Stream" style="width: 30px; height: 30px;">
<q-tooltip anchor="top middle" self="bottom right">Output</q-tooltip>
</q-item-section>
</q-item>
<q-item
v-if="config.isEnterprise == 'true'"
clickable
@click="(event) => onExternalDestinationClick(data, event, id)"
>
<q-item-section avatar>
<img :src="externalOutputImage" alt="Remote Destination" style="width: 30px; height: 30px;">
<q-tooltip anchor="top middle" self="bottom right">Remote</q-tooltip>
</q-item-section>
</q-item>
<!-- Add more items similarly for other images -->
</q-list>
</q-menu>
<div class="icon-container" style="display: flex; align-items: center">
<!-- Icon -->
<q-icon
:name="getIcon(data, io_type)"
size="1em"
class="q-ma-sm"
/>
</div>
<!-- Separator -->
<q-separator vertical class="q-mr-sm" />
<!-- Label -->
<div class="container">
<div
class="row"
style="
text-align: left;
text-wrap: wrap;
width: auto;
text-overflow: ellipsis;
"
>
{{ data.destination_name }}
</div>
</div>
<div class="float-right tw-pl-2">
<q-btn
flat
round
dense
icon="edit"
size="0.8em"
@click="editNode(id)"
/>
<q-btn
flat
round
dense
icon="delete"
size="0.8em"
@click="deleteNode(id)"
/>
</div>
</div>
<div
v-if="data.node_type == 'query'"
:class="`o2vf_node_${io_type}`"
class="custom-btn q-pa-none btn-fixed-width"
style="
width: fit-content;
display: flex;
align-items: center;
border: none;
cursor: pointer;
padding: 5px 2px;
"
@mouseover="menu = true"
@mouseleave="menu = false"
>
<q-menu v-model="menu" @mouseover="menu = true" @mouseleave="menu = false" name="myMenu" class="menu-list" anchor="top right" self="top left">
<q-list >
<q-item clickable @click="(event) => onFunctionClick(data, event,id)">
<q-item-section avatar>
<img :src="functionImage" alt="Function" style="width: 30px; height: 30px;">
<q-tooltip anchor="top middle" self="bottom right">Function</q-tooltip>
</q-item-section>
</q-item>
<q-item clickable @click="(event) => onConditionClick(data, event,id)">
<q-item-section avatar>
<img :src="conditionImage" alt="Stream" style="width: 30px; height: 30px;">
<q-tooltip anchor="top middle" self="bottom right">Condition</q-tooltip>
</q-item-section>
</q-item>
<q-item clickable @click="(event) => onStreamOutputClick(data, event,id)">
<q-item-section avatar>
<img :src="streamOutputImage" alt="Output Stream" style="width: 30px; height: 30px;">
<q-tooltip anchor="top middle" self="bottom right">Output</q-tooltip>
</q-item-section>
</q-item>
<q-item
v-if="config.isEnterprise == 'true'"
clickable
@click="(event) => onExternalDestinationClick(data, event, id)"
>
<q-item-section avatar>
<img :src="externalOutputImage" alt="Remote Destination" style="width: 30px; height: 30px;">
<q-tooltip anchor="top middle" self="bottom right">Remote</q-tooltip>
</q-item-section>
</q-item>
<!-- Add more items similarly for other images -->
</q-list>
</q-menu>
<q-tooltip :style="{ maxWidth: '300px', whiteSpace: 'pre-wrap' }">
<div>
<strong>{{ data.query_condition.type == 'sql' ? 'SQL' : 'PromQL' }}:</strong> <pre style="max-width: 200px ; text-wrap: wrap;">{{ data.query_condition.type == 'sql' ? data.query_condition.sql : data.query_condition.promql }}</pre><br />
<strong>Period:</strong> {{ data.trigger_condition.period }}<br />
<strong>Frequency:</strong> {{ data.trigger_condition.frequency }} {{ data.trigger_condition.frequency_type }}<br />
<strong>Operator:</strong> {{ data.trigger_condition.operator }}<br />
<strong>Threshold:</strong> {{ data.trigger_condition.threshold }}<br />
<strong>Cron:</strong> {{ data.trigger_condition.cron || 'None' }}<br />
<strong>Silence:</strong> {{ data.trigger_condition.silence }}
</div>
</q-tooltip>
<div class="icon-container" style="display: flex; align-items: center">
<!-- Icon -->
<q-icon
:name="getIcon(data, io_type)"
size="1em"
class="q-ma-sm"
/>
</div>
<!-- Separator -->
<q-separator vertical class="q-mr-sm" />
<!-- Label -->
<div class="container">
<div
class="row"
style="
text-align: left;
text-wrap: wrap;
width: auto;
text-overflow: ellipsis;
"
>
{{ data.stream_type }} - {{ data.stream_name }}
</div>
</div>
<div class="float-right">
<q-btn
flat
round
dense
icon="edit"
size="0.8em"
@click="editNode(id)"
style="margin-right: 5px"
/>
<q-btn
flat
round
dense
icon="delete"
size="0.8em"
@click="deleteNode(id)"
/>
</div>
</div>
<div
v-if="data.node_type == 'condition'"
:class="`o2vf_node_${io_type}`"
class="custom-btn q-pa-none btn-fixed-width"
style="
width: fit-content;
display: flex;
align-items: center;
border: none;
cursor: pointer;
"
@mouseover="menu = true"
@mouseleave="menu = false"
>
<q-menu v-model="menu" @mouseover="menu = true" @mouseleave="menu = false" name="myMenu" class="menu-list" anchor="top right" self="top left">
<q-list >
<q-item clickable @click="(event) => onFunctionClick(data, event,id)">
<q-item-section avatar>
<img :src="functionImage" alt="Function" style="width: 30px; height: 30px;">
<q-tooltip anchor="top middle" self="bottom right">Function</q-tooltip>
</q-item-section>
</q-item>
<q-item clickable @click="(event) => onConditionClick(data, event,id)">
<q-item-section avatar>
<img :src="conditionImage" alt="Stream" style="width: 30px; height: 30px;">
<q-tooltip anchor="top middle" self="bottom right">Condition</q-tooltip>
</q-item-section>
</q-item>
<q-item class="q-item-output" clickable @click="(event) => onStreamOutputClick(data, event,id)">
<q-item-section avatar>
<img :src="streamOutputImage" alt="Output Stream" style="width: 30px; height: 30px;">
<q-tooltip anchor="top middle" self="bottom right">Output</q-tooltip>
</q-item-section>
</q-item>
<q-item
v-if="config.isEnterprise == 'true'"
clickable
@click="(event) => onExternalDestinationClick(data, event, id)"
>
<q-item-section avatar>
<img :src="externalOutputImage" alt="Remote Destination" style="width: 30px; height: 30px;">
<q-tooltip anchor="top middle" self="bottom right">Remote</q-tooltip>
</q-item-section>
</q-item>
<!-- Add more items similarly for other images -->
</q-list>
</q-menu>
<div class="icon-container" style="display: flex; align-items: center">
<!-- Icon -->
<q-icon
:name="getIcon(data, io_type)"
size="1em"
class="q-ma-sm"
/>
</div>
<!-- Separator -->
<q-separator vertical class="q-mr-sm" />
<!-- Label -->
<div class="container">
<div
style="
text-align: left;
text-wrap: wrap;
width: auto;
text-overflow: ellipsis;
"
>
<div class="column" v-for="(condition, index) in data.conditions" :key="index" style="margin-bottom: 1px;">
{{ condition.column }} {{ condition.operator }} {{ condition.value }}
</div>
</div>
</div>
<div class="float-right">
<q-btn
flat
round
dense
icon="edit"
size="0.8em"
@click="editNode(id)"
style="margin-right: 5px"
/>
<q-btn
flat
round
dense
icon="delete"
size="0.8em"
@click="deleteNode(id)"
/>
</div>
</div>
<Handle
v-if="io_type === 'input' || io_type === 'default'"
id="output"
type="source"
:position="'bottom'"
class="node_handle_custom"
/>
</div>
<confirm-dialog
:title="confirmDialogMeta.title"
:message="confirmDialogMeta.message"
@update:ok="confirmDialogMeta.onConfirm()"
@update:cancel="resetConfirmDialog"
v-model="confirmDialogMeta.show"
/>
</template>
<style lang="scss">
.node_handle_custom{
background-color:#9a9698;
height:10px;
width:30px;
border-radius:4px;
filter: invert(100%);
}
.vue-flow__node-custom {
padding: 10px;
border-radius: 3px;
width: 150px;
font-size: 12px;
text-align: center;
border-width: 1px;
border-style: solid;
color: var(--vf-node-text);
background-color: var(--vf-node-bg);
border-color: var(--vf-node-color);
}
.menu-list{
margin: 0px 10px;
background-color: white;
}
</style>