Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

72 task investigate cluster visualizations #76

Merged
merged 11 commits into from
Feb 19, 2025
543 changes: 541 additions & 2 deletions App/Frontend/package-lock.json

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions App/Frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"private": true,
"dependencies": {
"@angular/animations": "^19.1.0",
"@angular/cdk": "^19.1.4",
"@angular/common": "^19.1.0",
"@angular/compiler": "^19.1.0",
"@angular/core": "^19.1.0",
Expand All @@ -22,6 +23,7 @@
"@ngx-translate/http-loader": "^16.0.1",
"@swimlane/ngx-charts": "^22.0.0-alpha.0",
"animejs": "^3.2.2",
"d3": "^7.9.0",
"rxjs": "~7.8.0",
"tslib": "^2.3.0",
"zone.js": "~0.15.0"
Expand All @@ -31,6 +33,7 @@
"@angular/cli": "^19.1.5",
"@angular/compiler-cli": "^19.1.0",
"@types/animejs": "^3.1.13",
"@types/d3": "^7.4.3",
"@types/jasmine": "~5.1.0",
"jasmine-core": "~5.5.0",
"karma": "~6.4.0",
Expand Down
2 changes: 2 additions & 0 deletions App/Frontend/src/app/app.routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { LoginComponent } from './login/login.component';
import { DashboardComponent } from './dashboard/dashboard.component';
import { SearchComponent } from './search/search.component';
import { AddComponent } from "./add/add.component";
import {SpiderWebComponent} from "./spider-web/spider-web.component";
import { NotFoundComponent } from './notfound/notfound.component';

export const routes: Routes = [
Expand All @@ -16,5 +17,6 @@ export const routes: Routes = [
{ path: 'dashboard', component: DashboardComponent, data: { title: 'K10s - Dashboard' } },
{ path: 'search', component: SearchComponent, data: { title: 'K10s - Search' } },
{ path: 'add', component: AddComponent, data: { title: 'K10s - Add' } },
{ path: 'spiderweb', component: SpiderWebComponent, data: { title: 'K10s - Testing' } },
{ path: '**', component: NotFoundComponent, data: { title: 'K10s - Not Found' } }
];
2 changes: 2 additions & 0 deletions App/Frontend/src/app/dashboard/dashboard.component.css
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@
box-shadow: 2px 0 5px var(--shadow);
width: 100%;
position: relative;
pointer-events: none;
}

.dashboard-fullscreen-button {
Expand All @@ -118,6 +119,7 @@
fill: var(--secondary);
width: 20px;
height: 20px;
pointer-events: auto;
}

.dashboard-fullscreen-button:hover {
Expand Down
6 changes: 4 additions & 2 deletions App/Frontend/src/app/dashboard/dashboard.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,10 @@ <h2>{{ 'DASHBOARD.DISK' | translate }}</h2>
<app-nav class="nav" id="nav"></app-nav>
<main class="dashboard-main" id="dashboard-main" #dashboardMain>
<section class="dashboard-title" id="dashboard-title" #dashboardTitle>K10s</section>
<section class="dashboard-main-section">
<article class="cursor-move" id="dashboard-main-chart"></article> <!-- TODO -->
<section class="dashboard-main-section" >
<article class="cursor-move" id="dashboard-main-chart">
<app-spider-web class="spider-web" id="spider-web"></app-spider-web>
</article>
</section>
<section class="dashboard-fullscreen-button cursor-pointer" id="dashboard-fullscreen-button">
<svg class="cursor-pointer" viewBox="0 0 16 16">
Expand Down
4 changes: 2 additions & 2 deletions App/Frontend/src/app/dashboard/dashboard.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,13 @@ import { StatsService } from "../services/stats.service";
import { ByteFormatPipe } from "../byte-format.pipe";
import { Color, NgxChartsModule, ScaleType } from "@swimlane/ngx-charts";
import { LoadingComponent } from "../loading/loading.component";
import { SpiderWebComponent } from "../spider-web/spider-web.component";

@Component({
selector: 'app-dashboard',
templateUrl: './dashboard.component.html',
styleUrls: ['./dashboard.component.css'],
imports: [NavComponent, FooterComponent, TranslatePipe, ByteFormatPipe, NgxChartsModule, LoadingComponent],
imports: [NavComponent, FooterComponent, TranslatePipe, ByteFormatPipe, NgxChartsModule, SpiderWebComponent, LoadingComponent],
standalone: true
})

Expand Down Expand Up @@ -94,7 +95,6 @@ export class DashboardComponent implements AfterViewInit {
this.loading = true;
this.usageService.getStats().subscribe({
next: (data) => {
console.log(data);
this.usage = data;
this.updateChartData();
this.loading = false;
Expand Down
15 changes: 15 additions & 0 deletions App/Frontend/src/app/spider-web/spider-web.component.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/**********************************/
/* @since 01/01/2025 */
/* @author K10s Open Source Team */
/**********************************/

.spider-web-container {
position: relative;
height: 600px;
overflow: hidden;

}

canvas {
pointer-events: auto;
}
5 changes: 5 additions & 0 deletions App/Frontend/src/app/spider-web/spider-web.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<!--Author K10s Open Source Team-->

<div class="spider-web-container">
<canvas #canvas></canvas>
</div>
123 changes: 123 additions & 0 deletions App/Frontend/src/app/spider-web/spider-web.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
/**********************************/
/* @since 01/01/2025 */
/* @author K10s Open Source Team */
/**********************************/
import { Component, OnInit, ViewChild, ElementRef } from '@angular/core';

interface Node {
id: number;
x: number;
y: number;
radius: number;
}

@Component({
selector: 'app-spider-web',
templateUrl: './spider-web.component.html',
standalone: true,
styleUrls: ['./spider-web.component.css']
})
export class SpiderWebComponent implements OnInit {
@ViewChild('canvas', { static: true }) canvasRef!: ElementRef;
private ctx!: CanvasRenderingContext2D;
private nodes: Node[] = [];
private connections: { from: number, to: number }[] = [];
private isDragging = false;
private draggedNode: Node | null = null;
private offsetX = 0;
private offsetY = 0;

ngOnInit(): void {
this.initializeCanvas();
this.createNodes();
this.drawWeb();
this.addEventListeners();
}

initializeCanvas() {
const canvas = this.canvasRef.nativeElement;
this.ctx = canvas.getContext('2d')!;
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}

createNodes() { //todo echt ophalen
for (let i = 0; i < 10; i++) {
this.nodes.push({
id: i,
x: Math.random() * window.innerWidth,
y: Math.random() * window.innerHeight,
radius: 40
});
}

for (let i = 0; i < this.nodes.length; i++) {
for (let j = i + 1; j < this.nodes.length; j++) {
if (Math.random() > 0.5) {
this.connections.push({ from: i, to: j });
}
}
}
}

drawWeb() {
this.ctx.clearRect(0, 0, window.innerWidth, window.innerHeight);

const rootStyles = getComputedStyle(document.documentElement);
const primary = rootStyles.getPropertyValue('--primary').trim();
const statusBlue = rootStyles.getPropertyValue('--status-blue').trim();
const statusGrey = rootStyles.getPropertyValue('--status-grey').trim();

this.connections.forEach(connection => {
const fromNode = this.nodes[connection.from];
const toNode = this.nodes[connection.to];
this.ctx.beginPath();
this.ctx.moveTo(fromNode.x, fromNode.y);
this.ctx.lineTo(toNode.x, toNode.y);
this.ctx.strokeStyle = statusGrey;
this.ctx.lineWidth = 1;
this.ctx.stroke();
});

this.nodes.forEach(node => {
this.ctx.beginPath();
this.ctx.arc(node.x, node.y, node.radius, 0, Math.PI * 2);
this.ctx.fillStyle = primary;
this.ctx.fill();
this.ctx.strokeStyle = statusBlue;
this.ctx.stroke();
});
}

addEventListeners() {
const canvas = this.canvasRef.nativeElement;

canvas.addEventListener('mousedown', (event: MouseEvent) => {
const mouseX = event.clientX;
const mouseY = event.clientY;

this.draggedNode = this.nodes.find(node =>
Math.sqrt(Math.pow(node.x - mouseX, 2) + Math.pow(node.y - mouseY, 2)) < node.radius
) || null;

if (this.draggedNode) {
this.isDragging = true;
this.offsetX = mouseX - this.draggedNode.x;
this.offsetY = mouseY - this.draggedNode.y;
}
});

canvas.addEventListener('mousemove', (event: MouseEvent) => {
if (this.isDragging && this.draggedNode) {
this.draggedNode.x = event.clientX - this.offsetX;
this.draggedNode.y = event.clientY - this.offsetY;
this.drawWeb();
}
});

canvas.addEventListener('mouseup', () => {
this.isDragging = false;
this.draggedNode = null;
});
}
}
Loading