Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,9 @@ <h2>Nothing to show</h2>
<b>Dependencies</b>
</mat-panel-title>
</mat-expansion-panel-header>
<app-dependency-graph [activityName]="showActivityDetails?.name || ''">
<app-dependency-graph
[activityName]="showActivityDetails?.name || ''"
(activityClicked)="onDependencyClicked($event)">
</app-dependency-graph>
</mat-expansion-panel>

Expand Down Expand Up @@ -248,9 +250,7 @@ <h2>Nothing to show</h2>
(closed)="onPanelClosed(activity)">
<mat-expansion-panel-header>
<mat-panel-title>
<button
class="title-button"
(click)="openActivityDetails(showActivityCard.dimension, activity['name'])">
<button class="title-button" (click)="openActivityDetails(activity['uuid'])">
{{ activity['name'] }}
</button>
</mat-panel-title>
Expand Down
92 changes: 80 additions & 12 deletions src/app/pages/circular-heatmap/circular-heatmap.component.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import { Component, OnInit } from '@angular/core';
import { Component, OnInit, OnDestroy } from '@angular/core';
import { equalArray } from 'src/app/util/util';
import { LoaderService } from 'src/app/service/loader/data-loader.service';
import * as d3 from 'd3';
import { Router } from '@angular/router';
import { Router, ActivatedRoute } from '@angular/router';
import { Location } from '@angular/common';
import { MatChip } from '@angular/material/chips';
import { Subject } from 'rxjs';
import { takeUntil, distinctUntilChanged } from 'rxjs/operators';
import * as md from 'markdown-it';
import {
ModalMessageComponent,
Expand All @@ -22,7 +25,7 @@ import { ThemeService } from '../../service/theme.service';
templateUrl: './circular-heatmap.component.html',
styleUrls: ['./circular-heatmap.component.css'],
})
export class CircularHeatmapComponent implements OnInit {
export class CircularHeatmapComponent implements OnInit, OnDestroy {
Routing: string = '/activity-description';
markdown: md = md();
maxLevelOfMaturity: number = -1;
Expand Down Expand Up @@ -52,10 +55,15 @@ export class CircularHeatmapComponent implements OnInit {
theme: string;
theme_colors!: Record<string, string>;

private destroy$ = new Subject<void>();

constructor(
private loader: LoaderService,
private sectorService: SectorService,
private themeService: ThemeService,
private router: Router,
private route: ActivatedRoute,
private location: Location,
public modal: ModalMessageComponent
) {
this.theme = this.themeService.getTheme();
Expand Down Expand Up @@ -110,6 +118,9 @@ export class CircularHeatmapComponent implements OnInit {
// For now, just draw the sectors (no activities yet)
this.loadCircularHeatMap('#chart', this.allSectors, this.dimensionLabels, this.maxLevel);
console.log(`${perfNow()}: Page loaded: Circular Heatmap`);

// Check if there's a URL fragment and open the corresponding activity
this.checkUrlFragmentForActivity();
})
.catch(err => {
this.displayMessage(new DialogInfo(err.message, 'An error occurred'));
Expand All @@ -119,7 +130,7 @@ export class CircularHeatmapComponent implements OnInit {
});
});
// Reactively handle theme changes (if user toggles later)
this.themeService.theme$.subscribe((theme: string) => {
this.themeService.theme$.pipe(takeUntil(this.destroy$)).subscribe((theme: string) => {
const css = getComputedStyle(document.body);
this.theme_colors = {
background: css.getPropertyValue('--heatmap-background').trim(),
Expand All @@ -133,6 +144,22 @@ export class CircularHeatmapComponent implements OnInit {
});
}

ngOnDestroy(): void {
this.destroy$.next();
this.destroy$.complete();
}

checkUrlFragmentForActivity() {
// Check if there's a URL fragment that might be an activity UUID
this.route.fragment
.pipe(takeUntil(this.destroy$), distinctUntilChanged())
.subscribe(fragment => {
if (fragment && this.dataStore) {
this.navigateToActivityByUuid(fragment);
}
});
}
Comment thread
vbakke marked this conversation as resolved.

displayMessage(dialogInfo: DialogInfo) {
this.modal.openDialog(dialogInfo);
}
Expand Down Expand Up @@ -237,6 +264,14 @@ export class CircularHeatmapComponent implements OnInit {
return this.sectorService.getSectorProgress(sector.activities);
}

onDependencyClicked(activityName: string) {
console.log(`${perfNow()}: Heat: Dependency clicked: '${activityName}'`);
const activity = this.dataStore?.activityStore?.getActivityByName(activityName);
if (activity?.uuid) {
this.navigateToActivityByUuid(activity.uuid);
}
Comment thread
vbakke marked this conversation as resolved.
}

loadCircularHeatMap(
dom_element_to_append_to: string,
dataset: any,
Expand Down Expand Up @@ -540,38 +575,71 @@ export class CircularHeatmapComponent implements OnInit {
console.log(`${perfNow()}: Heat: Card Panel closed: '${activity.name}'`);
}

openActivityDetails(dimension: string, activityName: string) {
openActivityDetails(uuid: string) {
// Find the activity in the selected sector
console.log(`${perfNow()}: Heat: Open Overlay: '${activityName}'`);
if (!this.dataStore) {
console.error(`Data store is not initialized. Cannot open activity ${activityName}`);
if (!this.dataStore || !this.dataStore.activityStore) {
console.error(`Data store is not initialized. Cannot open activity ${uuid}`);
return;
}
if (!this.showActivityCard || !this.showActivityCard.activities) {
this.showOverlay = true;
return;
}
const activity = this.showActivityCard.activities.find(
(a: any) => a.activityName === activityName || a.name === activityName
);

const activity: Activity = this.dataStore.activityStore.getActivityByUuid(uuid);
if (!activity) {
this.showOverlay = true;
return;
}

// Prepare navigationExtras and details
/* eslint-disable */
console.log(`${perfNow()}: Heat: Open Overlay: '${activity.name}'`);
this.showActivityDetails = activity;
this.KnowledgeLabel = this.dataStore.getMetaString('knowledgeLabels', activity.difficultyOfImplementation.knowledge);
this.TimeLabel = this.dataStore.getMetaString('labels', activity.difficultyOfImplementation.time);
this.ResourceLabel = this.dataStore.getMetaString('labels', activity.difficultyOfImplementation.resources);
this.UsefulnessLabel = this.dataStore.getMetaString('labels', activity.usefulness);
this.showOverlay = true;

// Update URL with activity UUID as fragment
if (activity.uuid) {
this.router.navigate([], {
relativeTo: this.route,
fragment: activity.uuid,
queryParamsHandling: 'preserve'
});
}
/* eslint-enable */
}

navigateToActivityByUuid(uuid: string) {
console.log(`${perfNow()}: Heat: Attempting to open activity with UUID: ${uuid}`);
if (!this.dataStore || !this.dataStore.activityStore) {
console.error('Data store is not initialized. Cannot open activity by UUID');
return;
}
const activity: Activity = this.dataStore.activityStore.getActivityByUuid(uuid);
const sector = this.allSectors.find(s => s.activities.some(a => a.uuid === uuid));
if (activity && sector) {
this.selectedSector = sector;
this.showActivityCard = sector;
this.openActivityDetails(activity.uuid);
} else {
// Only close the overlay, do not update the URL
this.showOverlay = false;
console.warn(`Heat: Activity with UUID ${uuid} not found.`);
}
}

closeOverlay() {
// Clear the URL fragment when closing overlay
this.router.navigate([], {
relativeTo: this.route,
fragment: undefined,
queryParamsHandling: 'preserve',
});
this.showOverlay = false;
// console.log(`${perfNow()}: Heat: Close Overlay: '${this.old_activityDetails.name}'`);
}

toggleFilters() {
Expand Down
2 changes: 1 addition & 1 deletion src/assets/Markdown Files/TODO-v4.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
- Teams: Bug: Editing name, pushes the item last
- Teams: Allow editing dates for progress stages
### Heatmap:
- Heatmap: Add #uuid to URL, and allow navigation on clicks in dependencies
- Heatmap: Fix: asterisk marks when modified
- ViewController needs to know about changes vs temp storage
- Heatmap: Bug: Clicking on grey sector leaves cursor on that sector
Expand Down Expand Up @@ -69,6 +68,7 @@
- Meta.yaml: Allow admins to customize the terms 'Team' and 'Group' (e.g. to 'App' and 'Portfolio')

# Done
- Heatmap: Add #uuid to URL, and allow navigation on clicks in dependencies
- Dependency: Make connecting nodes clickable for navigation
- Dependency: Handle dependsOn uuid, not just name
- Matrix: Dependency graph: Render in center of page
Expand Down