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 <ma...@talismancloud.io>
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

Reply via email to