Skip to content

Commit b13c7e0

Browse files
authored
Added icons for javalistener, messagestorelistener, ftpfilesystemlistener and exchangemaillistener (#119)
1 parent 47e6f96 commit b13c7e0

6 files changed

Lines changed: 67 additions & 13 deletions

File tree

src/main/frontend/app/routes/builder/builder-files-data-provider.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import type { Disposable, TreeDataProvider, TreeItem, TreeItemIndex } from 'react-complex-tree'
2+
import type { ConfigWithAdapters } from '~/routes/builder/builder-structure';
23

3-
interface ConfigWithAdapters {
4+
export interface AdapterNodeData {
5+
adapterName: string
46
configName: string
5-
adapterNames: string[]
7+
listenerName: string | null
68
}
79

810
export default class BuilderFilesDataProvider implements TreeDataProvider {
@@ -59,18 +61,18 @@ export default class BuilderFilesDataProvider implements TreeDataProvider {
5961
}
6062

6163
// Config folders and adapters
62-
for (const { configName, adapterNames } of configs) {
64+
for (const { configName, adapters } of configs) {
6365
newData[configName] = {
6466
index: configName,
6567
data: configName,
66-
children: adapterNames, // only matching adapters
68+
children: adapters.map((a) => a.adapterName),
6769
isFolder: true,
6870
}
6971

70-
for (const adapterName of adapterNames) {
72+
for (const { adapterName, listenerName } of adapters) {
7173
newData[adapterName] = {
7274
index: adapterName,
73-
data: { adapterName, configName },
75+
data: { adapterName, configName, listenerName } satisfies AdapterNodeData,
7476
isFolder: false,
7577
}
7678
}

src/main/frontend/app/routes/builder/builder-structure.tsx

Lines changed: 41 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1-
import { type JSX, useEffect, useRef, useState } from 'react'
2-
import { getAdapterNamesFromConfiguration } from '~/routes/builder/xml-to-json-parser'
1+
import React, { type JSX, useEffect, useRef, useState } from 'react'
2+
import { getAdapterListenerType, getAdapterNamesFromConfiguration } from '~/routes/builder/xml-to-json-parser'
33
import useTabStore from '~/stores/tab-store'
44
import Search from '~/components/search/search'
55
import FolderIcon from '/icons/solar/Folder.svg?react'
66
import FolderOpenIcon from '/icons/solar/Folder Open.svg?react'
77
import CodeIcon from '/icons/solar/Code.svg?react'
8+
import JavaIcon from '/icons/solar/Cup Hot.svg?react'
9+
import MessageIcon from '/icons/solar/Chat Dots.svg?react'
10+
import MailIcon from '/icons/solar/Mailbox.svg?react'
811
import 'react-complex-tree/lib/style-modern.css'
912
import AltArrowRightIcon from '/icons/solar/Alt Arrow Right.svg?react'
1013
import AltArrowDownIcon from '/icons/solar/Alt Arrow Down.svg?react'
@@ -16,15 +19,18 @@ import {
1619
type TreeRef,
1720
UncontrolledTreeEnvironment,
1821
} from 'react-complex-tree'
19-
import BuilderFilesDataProvider from '~/routes/builder/builder-files-data-provider'
22+
import BuilderFilesDataProvider, { type AdapterNodeData } from '~/routes/builder/builder-files-data-provider'
2023
import { useProjectStore } from '~/stores/project-store'
2124
import { Link } from 'react-router'
2225
import { useTreeStore } from '~/stores/tree-store'
2326
import { useShallow } from 'zustand/react/shallow'
2427

2528
export interface ConfigWithAdapters {
2629
configName: string
27-
adapterNames: string[]
30+
adapters: {
31+
adapterName: string
32+
listenerName: string | null
33+
}[]
2834
}
2935

3036
const TREE_ID = 'builder-files-tree'
@@ -68,16 +74,27 @@ export default function BuilderStructure() {
6874
const loaded: ConfigWithAdapters[] = await Promise.all(
6975
configurationNames.map(async (configName) => {
7076
const adapterNames = await getAdapterNamesFromConfiguration(configName)
71-
return { configName, adapterNames }
77+
78+
// Fetch listener name for each adapter
79+
const adapters = await Promise.all(
80+
adapterNames.map(async (adapterName) => {
81+
const listenerName = await getAdapterListenerType(configName, adapterName)
82+
return { adapterName, listenerName }
83+
}),
84+
)
85+
86+
return { configName, adapters }
7287
}),
7388
)
89+
7490
setConfigs(loaded)
7591
} catch (error) {
7692
console.error('Failed to load adapter names:', error)
7793
} finally {
7894
setIsLoading(false)
7995
}
8096
}
97+
8198
loadAdapters()
8299
}, [configurationNames])
83100

@@ -157,10 +174,13 @@ export default function BuilderStructure() {
157174
item: TreeItem<unknown>
158175
context: TreeItemRenderContext
159176
}) => {
160-
const Icon = (item.isFolder && (context.isExpanded ? FolderOpenIcon : FolderIcon)) || CodeIcon
161-
162177
const searchLower = searchTerm.toLowerCase()
163178
const titleLower = title.toLowerCase()
179+
const listenerType =
180+
!item.isFolder && typeof item.data === 'object' && item.data && 'listenerName' in item.data
181+
? (item.data as { listenerName: string | null }).listenerName
182+
: null
183+
const Icon = item.isFolder ? (context.isExpanded ? FolderOpenIcon : FolderIcon) : getListenerIcon(listenerType)
164184

165185
// Highlight only the substring(s) that match the search term
166186
let highlightedTitle: JSX.Element | string = title
@@ -190,6 +210,20 @@ export default function BuilderStructure() {
190210
)
191211
}
192212

213+
function getListenerIcon(listenerType: string | null) {
214+
if (!listenerType) return CodeIcon
215+
216+
// TODO: Add more icons for more important listener types
217+
const listenerIconMap: Record<string, React.FC<React.SVGProps<SVGSVGElement>>> = {
218+
JavaListener: JavaIcon,
219+
MessageStoreListener: MessageIcon,
220+
FtpFileSystemListener: FolderIcon,
221+
ExchangeMailListener: MailIcon,
222+
}
223+
224+
return listenerIconMap[listenerType] ?? CodeIcon
225+
}
226+
193227
return (
194228
<>
195229
<Search onChange={(event) => setSearchTerm(event.target.value)} />

src/main/frontend/app/routes/builder/xml-to-json-parser.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,21 @@ export async function getAdapterFromConfiguration(filename: string, adapterName:
6565
return null
6666
}
6767

68+
export async function getAdapterListenerType(filename: string, adapterName: string): Promise<string | null> {
69+
const adapterElement = await getAdapterFromConfiguration(filename, adapterName)
70+
if (!adapterElement) return null
71+
// Look through all child elements inside the adapter
72+
const children = adapterElement.querySelectorAll('*')
73+
for (const child of children) {
74+
if (child.tagName.includes('Listener')) {
75+
return child.tagName // Return the tag name, e.g., "JavaListener"
76+
}
77+
}
78+
79+
// No listener element found
80+
return null
81+
}
82+
6883
export async function convertAdapterXmlToJson(adapter: Element) {
6984
const nodes = convertAdapterToFlowNodes(adapter)
7085
const adapterJson = { nodes: nodes, edges: extractEdgesFromAdapter(adapter, nodes) }
Lines changed: 1 addition & 0 deletions
Loading
Lines changed: 1 addition & 0 deletions
Loading
Lines changed: 1 addition & 0 deletions
Loading

0 commit comments

Comments
 (0)