fix: improve diagram node readability and add UI to SonarQube scan
All checks were successful
CI / build (push) Successful in 1m8s
CI / cleanup-branch (push) Has been skipped
CI / docker (push) Successful in 1m0s
CI / deploy (push) Successful in 41s
CI / deploy-feature (push) Has been skipped

- Increase node width (160→220), height (40→50), spacing (90→120)
- Use SVG clipPath for text instead of character-count truncation
- Add UI sources, ESLint report, and sonar-scanner CLI to SonarQube workflow

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
hsiegeln
2026-03-28 17:16:36 +01:00
parent 27249c2440
commit 459f4d2e0c
3 changed files with 51 additions and 17 deletions

View File

@@ -42,16 +42,43 @@ jobs:
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
restore-keys: ${{ runner.os }}-maven-
- name: Build and Test with coverage
- name: Build and Test Java
run: mvn clean verify -DskipITs -U --batch-mode
- name: Install UI dependencies
working-directory: ui
run: |
echo '//gitea.siegeln.net/api/packages/cameleer/npm/:_authToken=${REGISTRY_TOKEN}' >> .npmrc
npm ci
env:
REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }}
- name: Lint UI
working-directory: ui
run: npm run lint -- --format json --output-file eslint-report.json || true
- name: Install sonar-scanner
run: |
SONAR_SCANNER_VERSION=6.2.1.4610
curl -sSLo sonar-scanner.zip "https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-${SONAR_SCANNER_VERSION}-linux-x64.zip"
unzip -q sonar-scanner.zip
ln -s "$(pwd)/sonar-scanner-${SONAR_SCANNER_VERSION}-linux-x64/bin/sonar-scanner" /usr/local/bin/sonar-scanner
- name: SonarQube Analysis
run: |
mvn sonar:sonar --batch-mode \
sonar-scanner \
-Dsonar.host.url="$SONAR_HOST_URL" \
-Dsonar.token="$SONAR_TOKEN" \
-Dsonar.projectKey=cameleer3-server \
-Dsonar.projectName="Cameleer3 Server"
-Dsonar.projectName="Cameleer3 Server" \
-Dsonar.sources=cameleer3-server-core/src/main/java,cameleer3-server-app/src/main/java,ui/src \
-Dsonar.tests=cameleer3-server-core/src/test/java,cameleer3-server-app/src/test/java \
-Dsonar.java.binaries=cameleer3-server-core/target/classes,cameleer3-server-app/target/classes \
-Dsonar.java.test.binaries=cameleer3-server-core/target/test-classes,cameleer3-server-app/target/test-classes \
-Dsonar.java.libraries="$HOME/.m2/repository/**/*.jar" \
-Dsonar.typescript.eslint.reportPaths=ui/eslint-report.json \
-Dsonar.eslint.reportPaths=ui/eslint-report.json \
-Dsonar.exclusions="ui/node_modules/**,ui/dist/**,**/target/**"
env:
SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}

View File

@@ -53,12 +53,12 @@ public class ElkDiagramRenderer implements DiagramRenderer {
}
private static final int PADDING = 20;
private static final int NODE_HEIGHT = 40;
private static final int NODE_WIDTH = 160;
private static final int NODE_HEIGHT = 50;
private static final int NODE_WIDTH = 220;
private static final int COMPOUND_TOP_PADDING = 30;
private static final int COMPOUND_SIDE_PADDING = 10;
private static final int CORNER_RADIUS = 8;
private static final double NODE_SPACING = 90.0;
private static final double NODE_SPACING = 120.0;
private static final double EDGE_SPACING = 20.0;
// Blue: endpoints

View File

@@ -5,6 +5,8 @@ import { colorForType, iconForType } from './node-colors';
import { ConfigBadge } from './ConfigBadge';
const TOP_BAR_HEIGHT = 6;
const TEXT_LEFT = 32;
const TEXT_RIGHT_PAD = 24;
const CORNER_RADIUS = 4;
interface DiagramNodeProps {
@@ -109,22 +111,27 @@ export function DiagramNode({
<rect x={0} y={0} width={w} height={TOP_BAR_HEIGHT} rx={CORNER_RADIUS} fill={topBarColor} />
<rect x={CORNER_RADIUS} y={0} width={w - CORNER_RADIUS * 2} height={TOP_BAR_HEIGHT} fill={topBarColor} />
{/* Clip path for text area */}
<clipPath id={`clip-${node.id}`}>
<rect x={TEXT_LEFT} y={TOP_BAR_HEIGHT} width={w - TEXT_LEFT - TEXT_RIGHT_PAD} height={h - TOP_BAR_HEIGHT} />
</clipPath>
{/* Icon */}
<text x={14} y={h / 2 + 6} fill={statusColor ?? color} fontSize={14}>
<text x={14} y={h / 2 + 4} fill={statusColor ?? color} fontSize={14}>
{icon}
</text>
{/* Type name */}
<text x={32} y={h / 2 + 1} fill={labelColor} fontSize={11} fontWeight={600}>
{typeName}
</text>
{/* Detail label (truncated) */}
{detail && detail !== typeName && (
<text x={32} y={h / 2 + 14} fill={isFailed ? '#C0392B' : '#5C5347'} fontSize={10}>
{detail.length > 22 ? detail.slice(0, 20) + '...' : detail}
{/* Type name + detail (clipped to available width) */}
<g clipPath={`url(#clip-${node.id})`}>
<text x={TEXT_LEFT} y={h / 2 - 1} fill={labelColor} fontSize={11} fontWeight={600}>
{typeName}
</text>
)}
{detail && detail !== typeName && (
<text x={TEXT_LEFT} y={h / 2 + 12} fill={isFailed ? '#C0392B' : '#5C5347'} fontSize={10}>
{detail}
</text>
)}
</g>
{/* Config badges */}
{config && <ConfigBadge nodeWidth={w} config={config} />}