mirror of
https://github.com/openobserve/openobserve.git
synced 2026-11-06 00:09:22 +00:00
### **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> </dd></td> <td><a href="https://github.com/openobserve/openobserve/pull/8026/files#diff-c06c96ba750be6fc82f517a53ba809efff8aa619aba203b871d4d2aeb7f64f60">+78/-76</a> </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> </dd></td> <td><a href="https://github.com/openobserve/openobserve/pull/8026/files#diff-ba91340f65190fae07746a2877b42357f3c4b10eb9969e7fc6fe393655bc8752">+1/-1</a> </td> </tr> <tr> <td><strong>AddDestination.vue</strong><dd><code>Remove unused Vue APIs and service import</code> </dd></td> <td><a href="https://github.com/openobserve/openobserve/pull/8026/files#diff-61b295458e13049a538f5014124855d58dce664dfbd644b57a964a37a07b7a3f">+0/-4</a> </td> </tr> <tr> <td><strong>AddTemplate.vue</strong><dd><code>Trim unused Vue composition imports</code> </dd></td> <td><a href="https://github.com/openobserve/openobserve/pull/8026/files#diff-2508a43827e6b35c07f3222deebd9945101ca6bc32b9dc592e6253ab99908bba">+0/-4</a> </td> </tr> <tr> <td><strong>AlertsContainer.vue</strong><dd><code>Simplify imports to only computed</code> </dd></td> <td><a href="https://github.com/openobserve/openobserve/pull/8026/files#diff-39b487d54970cff4a1ccdfbb49a4ccb38f7131bb9d30944ce1c6e86d3f818148">+1/-1</a> </td> </tr> <tr> <td><strong>FieldsInput.vue</strong><dd><code>Remove unused defineProps from imports</code> </dd></td> <td><a href="https://github.com/openobserve/openobserve/pull/8026/files#diff-a2dcba327fb56cd4cb52efb06fccc256a71fd8a551b826c6c94e71dad75524f5">+1/-1</a> </td> </tr> <tr> <td><strong>FilterCondition.vue</strong><dd><code>Drop unused defineProps import</code> </dd></td> <td><a href="https://github.com/openobserve/openobserve/pull/8026/files#diff-53916e2402d0ee094fcd63f0ec0c99ceffde4fa042f9001203d2e2e1b7709e10">+1/-1</a> </td> </tr> <tr> <td><strong>VariablesInput.vue</strong><dd><code>Remove unused defineProps import line</code> </dd></td> <td><a href="https://github.com/openobserve/openobserve/pull/8026/files#diff-23a647aa1acfc95bc726629f0daa54005e3da1ed5b16482ceccef0649f680a74">+0/-1</a> </td> </tr> <tr> <td><strong>AddCipherKey.vue</strong><dd><code>Remove unused defineEmits from imports</code> </dd></td> <td><a href="https://github.com/openobserve/openobserve/pull/8026/files#diff-ff5ae3a9b070fe2b3650f177ced0d87e9449ae7375a0b117ee299238293df110">+1/-1</a> </td> </tr> <tr> <td><strong>AppTabs.vue</strong><dd><code>Remove unused defineProps from import</code> </dd></td> <td><a href="https://github.com/openobserve/openobserve/pull/8026/files#diff-f69ae88c0f2018ea808724a0eaee5bd008fd1608c52f7ca20215fc6033f00573">+1/-1</a> </td> </tr> <tr> <td><strong>FunctionsToolbar.vue</strong><dd><code>Prune unused composition API imports</code> </dd></td> <td><a href="https://github.com/openobserve/openobserve/pull/8026/files#diff-8283d2ff9c4a66b4b59eac306672aca2d54655a462e2ddb88e14e039d79dcdaf">+0/-4</a> </td> </tr> <tr> <td><strong>EntityPermissionTable.vue</strong><dd><code>Remove unused defineEmits/defineProps imports</code> </dd></td> <td><a href="https://github.com/openobserve/openobserve/pull/8026/files#diff-07b373cc19e7893c8a8a29f5e6d10b8c74d15d6ad3a4d04f5c06b55d0d8de395">+1/-2</a> </td> </tr> <tr> <td><strong>PermissionsTable.vue</strong><dd><code>Remove unused defineEmits import</code> </dd></td> <td><a href="https://github.com/openobserve/openobserve/pull/8026/files#diff-609d4d7245b7309cf30cc45c22c996c6b068ebc042a9673e75ee3bbd2aa00a2a">+0/-1</a> </td> </tr> <tr> <td><strong>AssociateFunction.vue</strong><dd><code>Remove unused emits and lifecycle imports</code> </dd></td> <td><a href="https://github.com/openobserve/openobserve/pull/8026/files#diff-24a5b2df69327a6477227ea674939dea19dd6d393b4bfcf807089d71e6391152">+0/-2</a> </td> </tr> <tr> <td><strong>ExternalDestination.vue</strong><dd><code>Remove unused Vue/imports and reactive</code> </dd></td> <td><a href="https://github.com/openobserve/openobserve/pull/8026/files#diff-7ed6a9ef676d7d6db5440d4157512f731bad58716c351ca39015125a8a9d2df5">+0/-3</a> </td> </tr> <tr> <td><strong>Stream.vue</strong><dd><code>Drop unused imports and services</code> </dd></td> <td><a href="https://github.com/openobserve/openobserve/pull/8026/files#diff-1a17ced9dc89022502cab0a6f9b97b413c2a2c4f8219733d063fc0180d361739">+1/-2</a> </td> </tr> <tr> <td><strong>PipelineEditor.vue</strong><dd><code>Remove unused defineEmits import</code> </dd></td> <td><a href="https://github.com/openobserve/openobserve/pull/8026/files#diff-68c21f647336067eb79737ce9aca2d49632f2fa1c0878bcfdae55607e3473a15">+0/-1</a> </td> </tr> <tr> <td><strong>StreamSelection.vue</strong><dd><code>Remove unused defineEmits import</code> </dd></td> <td><a href="https://github.com/openobserve/openobserve/pull/8026/files#diff-461440be35cc15b6b78700c8a61747ea9fb601a750af5292fa2d04b6fc96d595">+1/-1</a> </td> </tr> <tr> <td><strong>TenstackTable.vue</strong><dd><code>Remove unused defineEmits import</code> </dd></td> <td><a href="https://github.com/openobserve/openobserve/pull/8026/files#diff-bc3c669f5ab65a42ae378df1f7d6b35014c9c220790bdcc72b47f55d1385dc22">+0/-1</a> </td> </tr> <tr> <td><strong>CellActions.vue</strong><dd><code>Remove unused imports and helpers</code> </dd></td> <td><a href="https://github.com/openobserve/openobserve/pull/8026/files#diff-de54e5b8cd9503c53f3f802ac7bc7e3d25846f1657c77cd99534d9f60673992e">+1/-2</a> </td> </tr> <tr> <td><strong>CustomNode.vue</strong><dd><code>Remove unused refs and image vars</code> </dd></td> <td><a href="https://github.com/openobserve/openobserve/pull/8026/files#diff-b9d83cd503b6d3470b238accaaea0b4decf567add8ad4727c63c9e583725f408">+1/-5</a> </td> </tr> <tr> <td><strong>AdvancedValuesFilter.vue</strong><dd><code>Remove unused defineEmits import</code> </dd></td> <td><a href="https://github.com/openobserve/openobserve/pull/8026/files#diff-19f84276e3e0eebf0af0707cc9480e2dd7434c8e77be13456a1c0607860af3b2">+1/-1</a> </td> </tr> </table></details></td></tr></tr></tbody></table> </details> ___
804 lines
23 KiB
Vue
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>
|