diff --git a/.gitea/workflows/sonarqube.yml b/.gitea/workflows/sonarqube.yml new file mode 100644 index 00000000..8bf969a4 --- /dev/null +++ b/.gitea/workflows/sonarqube.yml @@ -0,0 +1,57 @@ +name: SonarQube + +on: + schedule: + - cron: '0 2 * * *' + workflow_dispatch: + +jobs: + sonarqube: + runs-on: ubuntu-latest + container: + image: gitea.siegeln.net/cameleer/cameleer-build:1 + credentials: + username: cameleer + password: ${{ secrets.REGISTRY_TOKEN }} + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Configure Gitea Maven Registry + run: | + mkdir -p ~/.m2 + cat > ~/.m2/settings.xml << 'SETTINGS' + + + + gitea + cameleer + ${env.REGISTRY_TOKEN} + + + + SETTINGS + env: + REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }} + + - name: Cache Maven dependencies + uses: actions/cache@v4 + with: + path: ~/.m2/repository + key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} + restore-keys: ${{ runner.os }}-maven- + + - name: Build and Test with coverage + run: mvn clean verify -DskipITs -U --batch-mode + + - name: SonarQube Analysis + run: | + mvn sonar:sonar --batch-mode \ + -Dsonar.host.url="$SONAR_HOST_URL" \ + -Dsonar.token="$SONAR_TOKEN" \ + -Dsonar.projectKey=cameleer3-server \ + -Dsonar.projectName="Cameleer3 Server" + env: + SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }} + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} diff --git a/ui/package-lock.json b/ui/package-lock.json index 04b06ad0..6af50a71 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -8,7 +8,7 @@ "name": "ui", "version": "0.0.0", "dependencies": { - "@cameleer/design-system": "^0.1.18", + "@cameleer/design-system": "^0.1.19", "@tanstack/react-query": "^5.90.21", "lucide-react": "^1.7.0", "openapi-fetch": "^0.17.0", @@ -277,9 +277,9 @@ } }, "node_modules/@cameleer/design-system": { - "version": "0.1.18", - "resolved": "https://gitea.siegeln.net/api/packages/cameleer/npm/%40cameleer%2Fdesign-system/-/0.1.18/design-system-0.1.18.tgz", - "integrity": "sha512-uvGr4PFw6Eya+h9DSD0wBnzjIXhZpcndR2dDJX2tMvQqgy+32WTTTQ8BZZWZjOKLSv63UpBN/fwVSXtkA4dnqA==", + "version": "0.1.19", + "resolved": "https://gitea.siegeln.net/api/packages/cameleer/npm/%40cameleer%2Fdesign-system/-/0.1.19/design-system-0.1.19.tgz", + "integrity": "sha512-YpYJysWycqRiTMco3Fco8AIatJz/IU7EecTmUQLUrkcBUGfHOWzCTMYm47jRvNAjQrANoanYnXPKXRHg91NS2w==", "dependencies": { "lucide-react": "^1.7.0", "react": "^19.0.0", diff --git a/ui/package.json b/ui/package.json index e0ae3b77..b5168f69 100644 --- a/ui/package.json +++ b/ui/package.json @@ -14,7 +14,7 @@ "generate-api:live": "curl -s http://localhost:8081/api/v1/api-docs -o src/api/openapi.json && openapi-typescript src/api/openapi.json -o src/api/schema.d.ts" }, "dependencies": { - "@cameleer/design-system": "^0.1.18", + "@cameleer/design-system": "^0.1.19", "@tanstack/react-query": "^5.90.21", "lucide-react": "^1.7.0", "openapi-fetch": "^0.17.0", diff --git a/ui/src/components/ExecutionDiagram/ExecutionDiagram.module.css b/ui/src/components/ExecutionDiagram/ExecutionDiagram.module.css index b2e62406..550e4d1f 100644 --- a/ui/src/components/ExecutionDiagram/ExecutionDiagram.module.css +++ b/ui/src/components/ExecutionDiagram/ExecutionDiagram.module.css @@ -447,6 +447,11 @@ overflow-y: auto; } +.errorStackWrap pre { + max-height: 50vh; + overflow-y: auto; +} + .errorStackLabel { font-size: 10px; font-weight: 600; diff --git a/ui/src/components/ExecutionDiagram/tabs/ErrorTab.tsx b/ui/src/components/ExecutionDiagram/tabs/ErrorTab.tsx index 2a8630c9..cde66434 100644 --- a/ui/src/components/ExecutionDiagram/tabs/ErrorTab.tsx +++ b/ui/src/components/ExecutionDiagram/tabs/ErrorTab.tsx @@ -38,7 +38,9 @@ export function ErrorTab({ processor, executionDetail }: ErrorTabProps) { {errorStackTrace && ( <>
Stack Trace
- +
+ +
)} diff --git a/ui/src/components/LayoutShell.tsx b/ui/src/components/LayoutShell.tsx index e860216e..44b9ef99 100644 --- a/ui/src/components/LayoutShell.tsx +++ b/ui/src/components/LayoutShell.tsx @@ -222,36 +222,31 @@ function LayoutContent() { navigate(`${baseParts.join('/')}?text=${encodeURIComponent(query)}`); }, [navigate, scope.appId, scope.routeId]); - // Intercept Sidebar's internal navigation to re-route through current tab - const handleSidebarClick = useCallback((e: React.MouseEvent) => { - const anchor = (e.target as HTMLElement).closest('a[href]'); - if (!anchor) return; - const href = anchor.getAttribute('href') || ''; - - // Intercept /apps/:appId and /apps/:appId/:routeId links - const appMatch = href.match(/^\/apps\/([^/]+)(?:\/(.+))?$/); + // Translate Sidebar's internal paths to our URL structure + const handleSidebarNavigate = useCallback((path: string) => { + // /apps/:appId and /apps/:appId/:routeId → current tab + const appMatch = path.match(/^\/apps\/([^/]+)(?:\/(.+))?$/); if (appMatch) { - e.preventDefault(); const [, sAppId, sRouteId] = appMatch; navigate(sRouteId ? `/${scope.tab}/${sAppId}/${sRouteId}` : `/${scope.tab}/${sAppId}`); return; } - // Intercept /agents/* links — redirect to runtime tab - const agentMatch = href.match(/^\/agents\/([^/]+)(?:\/(.+))?$/); + // /agents/:appId/:instanceId → runtime tab + const agentMatch = path.match(/^\/agents\/([^/]+)(?:\/(.+))?$/); if (agentMatch) { - e.preventDefault(); const [, sAppId, sInstanceId] = agentMatch; navigate(sInstanceId ? `/runtime/${sAppId}/${sInstanceId}` : `/runtime/${sAppId}`); + return; } + + navigate(path); }, [navigate, scope.tab]); return ( - - + } > - {/* Scrollable content */} -
- {/* Exchanges table */} -
-
- - {textFilter ? ( - <> - - Search: “{textFilter}” - - - ) : 'Recent Exchanges'} - -
- - {rows.length.toLocaleString()} of {(searchResult?.total ?? 0).toLocaleString()} exchanges - - {!textFilter && } -
-
- -
- - row.errorMessage ? ( -
- -
-
{row.errorMessage}
-
Click to view full stack trace
-
-
- ) : null - } - /> -
+
+
+ + {textFilter ? ( + <> + + Search: “{textFilter}” + + + ) : 'Recent Exchanges'} + +
+ + {rows.length.toLocaleString()} of {(searchResult?.total ?? 0).toLocaleString()} exchanges + + {!textFilter && }
- + + + row.errorMessage ? ( +
+ +
+
{row.errorMessage}
+
Click to view full stack trace
+
+
+ ) : null + } + /> +
) } diff --git a/ui/src/pages/Exchanges/ExchangesPage.module.css b/ui/src/pages/Exchanges/ExchangesPage.module.css index 3c545469..dac174db 100644 --- a/ui/src/pages/Exchanges/ExchangesPage.module.css +++ b/ui/src/pages/Exchanges/ExchangesPage.module.css @@ -5,7 +5,9 @@ } .leftPanel { - overflow: auto; + display: flex; + flex-direction: column; + overflow: hidden; height: 100%; flex-shrink: 0; }