This is an automated email from the ASF dual-hosted git repository.
marat pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-karavan.git
The following commit(s) were added to refs/heads/main by this push:
new e2c3b49e Fix #1155
e2c3b49e is described below
commit e2c3b49e51001e3da51043d914b0a36c532787e7
Author: Marat Gubaidullin <[email protected]>
AuthorDate: Thu Feb 29 21:16:08 2024 -0500
Fix #1155
---
.../main/webui/src/designer/route/DslSelector.tsx | 18 +-
.../src/project/trace/RunnerInfoTraceMessage.tsx | 190 +++++++++++++++++++++
.../src/project/trace/RunnerInfoTraceModal.tsx | 72 ++++----
.../src/project/trace/RunnerInfoTraceNode.tsx | 76 ---------
.../src/main/webui/src/project/trace/trace.css | 43 +++++
5 files changed, 273 insertions(+), 126 deletions(-)
diff --git a/karavan-app/src/main/webui/src/designer/route/DslSelector.tsx
b/karavan-app/src/main/webui/src/designer/route/DslSelector.tsx
index 14a4bb2b..68e62e22 100644
--- a/karavan-app/src/main/webui/src/designer/route/DslSelector.tsx
+++ b/karavan-app/src/main/webui/src/designer/route/DslSelector.tsx
@@ -68,7 +68,7 @@ export function DslSelector (props: Props) {
function searchInput() {
return (
<Flex className="search">
- {selectorTabIndex === 'kamelet' && <FlexItem>
+ {selectorTabIndex === 'kamelet' && <FlexItem>
<Switch
label="Custom only"
id="switch"
@@ -84,7 +84,7 @@ export function DslSelector (props: Props) {
</Flex>
)
}
-
+
function getCard(dsl: DslMetaModel, index: number) {
const labels = dsl.labels !== undefined ?
dsl.labels.split(",").filter(label => label !== 'eip') : [];
const isCustom = KameletApi.getCustomKameletNames().includes(dsl.name);
@@ -96,7 +96,7 @@ export function DslSelector (props: Props) {
{['kamelet',
'component'].includes(dsl.navigation.toLowerCase()) &&
<Badge isRead className="version
labels">{dsl.version}</Badge>
}
- {isCustom && <Badge className="custom">custom</Badge>}
+ {isCustom && <Badge className="custom">custom</Badge>}
</CardHeader>
<CardHeader>
{CamelUi.getIconForDsl(dsl)}
@@ -149,9 +149,9 @@ export function DslSelector (props: Props) {
const eipElements = CamelUi.getSelectorModelsForParentFiltered(parentDsl,
'eip', showSteps);
const componentElements =
CamelUi.getSelectorModelsForParentFiltered(parentDsl, 'component', showSteps)
- .filter(dsl =>
(!blockedComponents.includes(dsl.uri || dsl.name)));
+ .filter(dsl => (!blockedComponents.includes(dsl.uri || dsl.name)));
let kameletElements =
CamelUi.getSelectorModelsForParentFiltered(parentDsl, 'kamelet', showSteps)
- .filter(dsl =>
(!blockedKamelets.includes(dsl.name)));
+ .filter(dsl => (!blockedKamelets.includes(dsl.name)));
if (customOnly) kameletElements = kameletElements.filter(k =>
KameletApi.getCustomKameletNames().includes(k.name));
const filteredEipElements = filterElements(eipElements);
@@ -188,14 +188,14 @@ export function DslSelector (props: Props) {
}
{filteredKameletElements?.length > 0 &&
<Tab eventKey={'kamelet'} key={"tab-kamelet"}
- title={
- <TabTitleText>{`Kamelets
(${filteredKameletElements?.length})`}</TabTitleText>}>
+ title={
+ <TabTitleText>{`Kamelets
(${filteredKameletElements?.length})`}</TabTitleText>}>
</Tab>
}
{filteredComponentElements?.length > 0 &&
<Tab eventKey={'component'}
key={'tab-component'}
- title={
- <TabTitleText>{`Components
(${filteredComponentElements?.length})`}</TabTitleText>}>
+ title={
+ <TabTitleText>{`Components
(${filteredComponentElements?.length})`}</TabTitleText>}>
</Tab>
}
</Tabs>
diff --git
a/karavan-app/src/main/webui/src/project/trace/RunnerInfoTraceMessage.tsx
b/karavan-app/src/main/webui/src/project/trace/RunnerInfoTraceMessage.tsx
new file mode 100644
index 00000000..7eae1020
--- /dev/null
+++ b/karavan-app/src/main/webui/src/project/trace/RunnerInfoTraceMessage.tsx
@@ -0,0 +1,190 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import React, {useEffect, useState} from 'react';
+import {
+ CodeBlock,
+ CodeBlockCode,
+ DataList,
+ DataListCell,
+ DataListItem,
+ DataListItemCells,
+ DataListItemRow,
+ DataListWrapModifier,
+ DescriptionList,
+ DescriptionListDescription,
+ DescriptionListGroup,
+ DescriptionListTerm, Flex,
+ Panel,
+ PanelHeader,
+ PanelMain,
+ PanelMainBody, Tab,
+ Tabs, TabTitleText, Text, TextContent, TextVariants
+} from '@patternfly/react-core';
+import '../../designer/karavan.css';
+import {Caption, Table, Tbody, Td, Th, Thead, Tr} from
"@patternfly/react-table";
+
+interface Props {
+ trace: any
+}
+
+export function RunnerInfoTraceMessage (props: Props) {
+
+ const [tab, setTab] = useState<string | number>('variables');
+ const [variableName, setVariableName] = useState<string | number>();
+
+ const type = props.trace?.message?.body?.type;
+ const headers: any[] = [...props.trace?.message?.headers];
+ const properties: any[] = [...props.trace?.message?.exchangeProperties];
+ const variables: any[] = props.trace?.message?.exchangeVariables ?
[...props.trace?.message?.exchangeVariables] : [];
+ const body = props.trace?.message?.body?.value;
+ const variable = variables.filter(v => v.key === variableName)?.at(0);
+
+ useEffect(()=> {
+ console.log(variableName)
+ }, [variableName])
+
+ function getBody() {
+ return (
+ <CodeBlock title="Body">
+ <CodeBlockCode id="code-content">{body}</CodeBlockCode>
+ </CodeBlock>
+ )
+ }
+
+ function getVariableValue() {
+ if (variable?.value !== undefined) {
+ const isObject = variable?.value instanceof Object;
+ return (
+ <CodeBlock title="Body">
+ <CodeBlockCode id="code-content">{isObject ?
JSON.stringify(variable.value) : variable.value}</CodeBlockCode>
+ </CodeBlock>
+ )
+ }
+ }
+
+ function getVariableType() {
+ if (variable?.value !== undefined) {
+ return (
+ <TextContent className="title">
+ <Flex gap={{default: "gap"}}>
+ <Text component={TextVariants.p}>Type:</Text>
+ <Text
component={TextVariants.h6}>{variable.type}</Text>
+ </Flex>
+ </TextContent>
+ )
+ }
+ }
+
+ function getHeaders() {
+ return (
+ <Table aria-label="Simple table" variant={'compact'}
borders={true} className='table'>
+ <Caption>Exchange message headers</Caption>
+ <Thead>
+ <Tr>
+ <Th>Key</Th>
+ <Th>Type</Th>
+ <Th>Value</Th>
+ </Tr>
+ </Thead>
+ <Tbody>
+ {headers.map((header: any, index: number) => (
+ <Tr key={header[0] + "-" + index}>
+ <Td dataLabel={'key'}>{header.key}</Td>
+ <Td dataLabel={'type'}>{header.type}</Td>
+ <Td dataLabel={'value'}>{header.value}</Td>
+ </Tr>
+ ))}
+ </Tbody>
+ </Table>
+ )
+ }
+
+ function getProperties() {
+ return (
+ <Table aria-label="Simple table" variant={'compact'}
borders={true} className='table'>
+ <Caption>Exchange message properties</Caption>
+ <Thead>
+ <Tr>
+ <Th>Key</Th>
+ <Th>Type</Th>
+ <Th>Value</Th>
+ </Tr>
+ </Thead>
+ <Tbody>
+ {properties.map((header: any, index: number) => (
+ <Tr key={header[0] + "-" + index}>
+ <Td dataLabel={'key'}>{header.key}</Td>
+ <Td dataLabel={'type'}>{header.type}</Td>
+ <Td dataLabel={'value'}>{header.value}</Td>
+ </Tr>
+ ))}
+ </Tbody>
+ </Table>
+ )
+ }
+
+ return (
+ <div className="panel2">
+ <TextContent className="title">
+ <Text component={TextVariants.h3}>Message</Text>
+ </TextContent>
+ <Tabs activeKey={tab} onSelect={(event, eventKey) =>
setTab(eventKey)}>
+ <Tab eventKey={'variables'}
title={<TabTitleText>Variables</TabTitleText>}/>
+ <Tab eventKey={'body'}
title={<TabTitleText>Body</TabTitleText>}/>
+ <Tab eventKey={'headers'}
title={<TabTitleText>Headers</TabTitleText>}/>
+ <Tab eventKey={'properties'}
title={<TabTitleText>Properties</TabTitleText>}/>
+ </Tabs>
+ {tab === 'variables' && variables.length > 0 &&
+ <>
+ <Tabs activeKey={variableName} onSelect={(event, eventKey) =>
setVariableName(eventKey)}>
+ {variables.map(v => (<Tab eventKey={v.key}
title={<TabTitleText>{v.key}</TabTitleText>}/>))}
+ </Tabs>
+ {getVariableType()}
+ </>
+ }
+ <div className="scrollable">
+ {tab === 'variables' && getVariableValue()}
+ {tab === 'body' && getBody()}
+ {tab === 'headers' && getHeaders()}
+ {tab === 'properties' && getProperties()}
+ </div>
+ </div>
+ // <Panel isScrollable>
+ // <PanelMain tabIndex={0}>
+ // <PanelHeader>
+ // <DescriptionList isHorizontal>
+ // <DescriptionListGroup>
+ //
<DescriptionListTerm>Headers</DescriptionListTerm>
+ // </DescriptionListGroup>
+
+ // <DescriptionListGroup>
+ //
<DescriptionListTerm>Body</DescriptionListTerm>
+ // <DescriptionListDescription>
+ // {type}
+ // </DescriptionListDescription>
+ // </DescriptionListGroup>
+ // </DescriptionList>
+ // </PanelHeader>
+ // <PanelMainBody style={{padding: "0"}}>
+ // <CodeBlock title="Body">
+ // <CodeBlockCode
id="code-content">{body}</CodeBlockCode>
+ // </CodeBlock>
+ // </PanelMainBody>
+ // </PanelMain>
+ // </Panel>
+ );
+}
diff --git
a/karavan-app/src/main/webui/src/project/trace/RunnerInfoTraceModal.tsx
b/karavan-app/src/main/webui/src/project/trace/RunnerInfoTraceModal.tsx
index af950b60..862e1fbd 100644
--- a/karavan-app/src/main/webui/src/project/trace/RunnerInfoTraceModal.tsx
+++ b/karavan-app/src/main/webui/src/project/trace/RunnerInfoTraceModal.tsx
@@ -16,12 +16,14 @@
*/
import React, {useState} from 'react';
import {
- Flex, FlexItem,
- Modal, ModalVariant, DescriptionListGroup, DescriptionListTerm,
DescriptionList, Button
+ Modal,
+ ModalVariant,
+ JumpLinksItem,
+ JumpLinks,
+ TextContent, TextVariants, Text
} from '@patternfly/react-core';
-import '../../designer/karavan.css';
-import {RunnerInfoTraceNode} from "./RunnerInfoTraceNode";
-import ArrowRightIcon from
"@patternfly/react-icons/dist/esm/icons/arrow-right-icon";
+import './trace.css';
+import {RunnerInfoTraceMessage} from "./RunnerInfoTraceMessage";
interface Props {
exchangeId: string
@@ -34,49 +36,37 @@ export function RunnerInfoTraceModal (props: Props) {
const [activeNode, setActiveNode] = useState(props.nodes.at(0));
- function getComponent(node: any): any {
- return {name: node.nodeId, component: (<p>Step 1 content</p>) }
- }
-
- function getRoutes(): any[] {
- return Array.from(new Set((props.nodes).map((item: any) =>
item?.routeId)));
- }
-
return (
<Modal
title={"Exchange: " + props.exchangeId}
+ width={"90%"}
+ className="trace-modal"
variant={ModalVariant.large}
isOpen={props.isOpen}
onClose={() => props.onClose()}
- actions={[
- ]}
+ actions={[]}
>
- <Flex direction={{default: "row"}}
justifyContent={{default:"justifyContentSpaceBetween"}}>
- <FlexItem flex={{default: "flex_1"}}>
- <DescriptionList>
- <DescriptionListGroup>
- <DescriptionListTerm>Nodes</DescriptionListTerm>
- </DescriptionListGroup>
- </DescriptionList>
- {props.nodes.map((node: any, index: number) => (
- <FlexItem key={node.uid + "-" + index}>
- <Button variant={node.uid === activeNode.uid ?
"secondary" : "link"}
- icon={node.nodeId === undefined ?
<ArrowRightIcon/> : undefined}
- onClick={event => {setActiveNode(node)}}>
- {node.nodeId ? node.nodeId : node.routeId}
- </Button>
- </FlexItem>
- ))}
- </FlexItem>
- <FlexItem flex={{default: "flex_3"}}>
- <DescriptionList>
- <DescriptionListGroup>
- <DescriptionListTerm>Exchange</DescriptionListTerm>
- </DescriptionListGroup>
- </DescriptionList>
- <RunnerInfoTraceNode trace={activeNode} />
- </FlexItem>
- </Flex>
+ <div className="container">
+ <div className="panel1">
+ <TextContent className="title">
+ <Text component={TextVariants.h3}>Nodes</Text>
+ </TextContent>
+ <div className="scrollable">
+ <JumpLinks isVertical>
+ {[...props.nodes].map((node: any, index: number)
=> (
+ <JumpLinksItem key={node.uid + "-" + index}
+ isActive={node.uid ===
activeNode.uid}
+ onClick={_ =>
{setActiveNode(node)}}>
+ {node.nodeId ? node.nodeId : node.routeId}
+ </JumpLinksItem>
+ ))}
+ {/*{Array.from(Array(100).keys())*/}
+ {/* .map(_ => (<JumpLinksItem>Inactive
section</JumpLinksItem>))}*/}
+ </JumpLinks>
+ </div>
+ </div>
+ <RunnerInfoTraceMessage trace={activeNode}/>
+ </div>
</Modal>
);
}
diff --git
a/karavan-app/src/main/webui/src/project/trace/RunnerInfoTraceNode.tsx
b/karavan-app/src/main/webui/src/project/trace/RunnerInfoTraceNode.tsx
deleted file mode 100644
index 73181663..00000000
--- a/karavan-app/src/main/webui/src/project/trace/RunnerInfoTraceNode.tsx
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-import React from 'react';
-import {
- CodeBlock, CodeBlockCode, DataList, DataListCell, DataListItem,
DataListItemCells, DataListItemRow, DataListWrapModifier,
- DescriptionList,
- DescriptionListDescription,
- DescriptionListGroup,
- DescriptionListTerm, Panel, PanelHeader, PanelMain, PanelMainBody
-} from '@patternfly/react-core';
-import '../../designer/karavan.css';
-
-interface Props {
- trace: any
-}
-
-export function RunnerInfoTraceNode (props: Props) {
-
- const type = props.trace?.message?.body?.type;
- const body = props.trace?.message?.body?.value;
- const headers: any[] = [...props.trace?.message?.headers];
- return (
- <Panel isScrollable>
- <PanelMain tabIndex={0}>
- <PanelHeader>
- <DescriptionList isHorizontal>
- <DescriptionListGroup>
-
<DescriptionListTerm>Headers</DescriptionListTerm>
- </DescriptionListGroup>
- <DataList aria-label="Compact data list example"
isCompact>
- {headers.map((header: any, index: number) => (
- <DataListItem key={header[0] + "-" +
index} aria-labelledby="compact-item1">
- <DataListItemRow>
- <DataListItemCells
- dataListCells={[
- <DataListCell key="uid"
>{header.key}</DataListCell>,
- <DataListCell
key="type">{header.type}</DataListCell>,
- <DataListCell
key="routeId" wrapModifier={DataListWrapModifier.truncate}>
- {header.value}
- </DataListCell>,
- ]}
- />
- </DataListItemRow>
- </DataListItem>))}
- </DataList>
- <DescriptionListGroup>
- <DescriptionListTerm>Body</DescriptionListTerm>
- <DescriptionListDescription>
- {type}
- </DescriptionListDescription>
- </DescriptionListGroup>
- </DescriptionList>
- </PanelHeader>
- <PanelMainBody style={{padding: "0"}}>
- <CodeBlock title="Body">
- <CodeBlockCode
id="code-content">{body}</CodeBlockCode>
- </CodeBlock>
- </PanelMainBody>
- </PanelMain>
- </Panel>
- );
-}
diff --git a/karavan-app/src/main/webui/src/project/trace/trace.css
b/karavan-app/src/main/webui/src/project/trace/trace.css
new file mode 100644
index 00000000..401585ee
--- /dev/null
+++ b/karavan-app/src/main/webui/src/project/trace/trace.css
@@ -0,0 +1,43 @@
+.trace-modal {
+ height: 90%;
+}
+
+.trace-no-padding {
+ padding: 0;
+}
+
+.trace-padding-bottom-only {
+ padding: 0 0 var(--pf-v5-c-panel__header--PaddingBottom) 0;
+}
+
+.trace-modal .pf-v5-c-modal-box__body {
+ display: flex;
+}
+
+.trace-modal .container {
+ display: flex;
+ padding: 0;
+ flex: 1;
+}
+
+.trace-modal .panel1 {
+ flex: 1;
+ padding: 10px;
+}
+
+.trace-modal .panel1 .scrollable,
+.trace-modal .panel2 .scrollable {
+ overflow-y: auto;
+ height: 95%;
+ padding-top: 10px;
+}
+
+.trace-modal .panel2 {
+ flex: 4;
+ padding: 10px;
+}
+
+/*.trace-modal .panel2 .pf-v5-c-tab-content {*/
+/* overflow-y: auto;*/
+/* height: 100%;*/
+/*}*/
\ No newline at end of file