Skip to content

Commit

Permalink
Merge pull request #361 from COS301-SE-2024/feat/updatedInsights
Browse files Browse the repository at this point in the history
Feat/updated insights
  • Loading branch information
Douglasj02 authored Sep 25, 2024
2 parents 7cc5ace + 033296b commit fcf2bc0
Show file tree
Hide file tree
Showing 7 changed files with 199 additions and 112 deletions.
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
<div class="fixed mb-3 bottom-player" style="width: 98vw; height: 12vh; left:1vw ">
<div class="rounded-md h-full">
<div class="absolute top-0 w-full z-20">
<div #progressContainer [ngClass]="moodComponentClasses[this.moodService.getCurrentMood()]" class="w-full rounded-t-full h-1 hover:cursor-pointer" (click)="updateProgress($event)">
<div #progressContainer class=" bg-gray-300 w-full rounded-t-full h-1 hover:cursor-pointer" (click)="updateProgress($event)">
<div [ngClass]="moodClassesDark[this.moodService.getCurrentMood()]" id="progressBar" class=" h-1 rounded-full" [style.width.%]="trackProgress"></div>
</div>
</div>
<div [ngClass]="moodComponentClasses[this.moodService.getCurrentMood()]" class=" opacity-80 rounded-lg overflow-hidden h-full flex items-center p-4">
<div class="bg-stone-950 opacity-80 rounded-lg overflow-hidden h-full flex items-center p-4">
<div class="flex items-center h-full w-full justify-between">

<div class="flex items-center space-x-5">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,4 @@
/* Add any other properties that change on hover to be neutralized */
}


Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<div class="z-10 w-[45vh]" style="--tw-h: 73.8vh; top: 10.2vh;">
<div class="z-10 w-[45vh] opacity-90" style="--tw-h: 73.8vh; top: 10.2vh;">
<div class="container pl-3 rounded-md h-full">
<div [ngClass]="moodComponentClasses[moodService.getCurrentMood()]" class="rounded-lg overflow-auto h-full flex flex-col justify-between scrollbar-hidden">
<div [ngClass]="moodComponentClasses[moodService.getCurrentMood()]" class=" bg-stone-950 rounded-lg overflow-auto h-full flex flex-col justify-between scrollbar-hidden">
<div class="flex justify-between items-center mb-2 mt-3">
<div class="button-container" [ngClass]="getButtonClasses('suggestions')">
<button class="px-10 text-md font-bold text-white focus:outline-none truncate" (click)="selectOption('suggestions')">Suggestions</button>
Expand Down Expand Up @@ -28,7 +28,7 @@
<div *ngIf="isEchoModalVisible" id="echo-songs" tabindex="-1" aria-hidden="true" class="fixed top-0 right-0 left-0 z-50 flex justify-center items-center w-full h-full bg-black bg-opacity-50">
<div class="relative p-4 w-full max-w-2xl max-h-full">
<!-- Modal content -->
<div class="relative bg-white rounded-lg shadow dark:bg-gray-700">
<div class="relative bg-white rounded-lg shadow dark:bg-gray-950">
<!-- Modal header -->
<div class="flex items-center justify-between p-4 md:p-5 border-b rounded-t dark:border-gray-600">
<h3 class="text-xl font-semibold text-gray-900 dark:text-white">
Expand All @@ -55,4 +55,4 @@ <h3 class="text-xl font-semibold text-gray-900 dark:text-white">
</div>
</div>
</div>
</div>
</div>
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
<div [ngClass]="this.moodComponentClasses[this.moodService.getCurrentMood()]" class="flex items-center mb-5 hover:cursor-pointer bg-default-backgrounddark rounded-lg p-1 group"
<div class="bg-stone-950 flex items-center mb-5 hover:cursor-pointer bg-default-backgrounddark rounded-lg p-1 group"
(click)="playTrack(card.id)">
<!-- Image on the left -->
<div class="mr-4 flex-shrink-0" [style.width]="imgSize">
<img [src]="card?.imageUrl || 'path/to/default-image.jpg'"
alt="Card image"
class="w-1/4 rounded-lg mr-2.5 w-full h-auto"
[style.width]="imgSize"
<img [src]="card?.imageUrl || 'path/to/default-image.jpg'"
alt="Card image"
class="w-1/4 rounded-lg mr-2.5 w-full h-auto"
[style.width]="imgSize"
[style.height]="imgSize">
</div>
<!-- Text on the right -->
<div class="flex-grow">
<!-- First text with icon -->
<div class="flex items-center">
<img *ngIf="card.explicit" src="../../../../assets/images/explicit-dark.png" alt="Explicit Icon" class="w-6 h-6 mr-2">
<h1 class="font-weight: bold;">{{ card.text }}</h1>
<h1 class="font-weight: bold; text-white">{{ card.text }}</h1>
</div>
<!-- Second text (underneath the first text) -->
<p class="font-weight: bold;">{{ card.secondaryText }}</p>
<p class="font-weight: bold; text-white">{{ card.secondaryText }}</p>
</div>
<app-echo-button
[width]="svgSize"
[height]="svgSize"
[width]="svgSize"
[height]="svgSize"
(buttonClick)="onEchoButtonClick($event)"
class="opacity-0 group-hover:opacity-100 transition-opacity duration-300">
</app-echo-button>
</div>
</div>
19 changes: 19 additions & 0 deletions Frontend/src/app/pages/insights/insights.component.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/* Custom Scrollbar Styling */
#center::-webkit-scrollbar {
width: 12px;
}

#center::-webkit-scrollbar-track {
background: #3b3b3b; /* Dark background for the scrollbar track */
border-radius: 10px;
}

#center::-webkit-scrollbar-thumb {
background-color: #7e7e7e; /* Thumb color */
border-radius: 10px;
border: 3px solid #3b3b3b; /* Padding around the scrollbar thumb */
}

#center::-webkit-scrollbar-thumb:hover {
background-color: #b0b0b0; /* Lighter color on hover */
}
64 changes: 55 additions & 9 deletions Frontend/src/app/pages/insights/insights.component.html
Original file line number Diff line number Diff line change
@@ -1,11 +1,57 @@
<div class="w-full h-full">
<canvas class="w-full h-full" id="MyChart"></canvas>
<button [ngClass]="moodComponentClasses[this.moodService.getCurrentMood()]" class="font-medium rounded-lg text-sm px-4 py-2.5 text-center" (click)="nextChartType()">Next</button>
</div>
<div id="center" class=" rounded-xl no-scrollbar border border-stone-950 overflow-y-scroll bg-stone-950 opacity-90 p-4" style="height: 72vh; width: 75vw;">
<h1 class="text-3xl font-bold text-white text-center mb-6">Listening Insights</h1>

<!-- Widgets Grid -->
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6 mb-8">
<div class="bg-stone-900 shadow-lg rounded-lg p-6 text-center">
<h2 class="text-2xl font-semibold text-white">Top Mood</h2>
<p class="text-xl text-gray-300">Joy</p>
</div>
<div class="bg-stone-900 shadow-lg rounded-lg p-6 text-center">
<h2 class="text-2xl font-semibold text-white">Total Listening Time</h2>
<p class="text-xl text-gray-300">42 hrs</p>
</div>
<div class="bg-stone-900 shadow-lg rounded-lg p-6 text-center">
<h2 class="text-2xl font-semibold text-white">Most Listened Artist</h2>
<p class="text-xl text-gray-300">The Weeknd</p>
</div>
<div class="bg-stone-900 shadow-lg rounded-lg p-6 text-center">
<h2 class="text-2xl font-semibold text-white">Most Played Track</h2>
<p class="text-xl text-gray-300">Blinding Lights</p>
</div>
<div class="bg-stone-900 shadow-lg rounded-lg p-6 text-center">
<h2 class="text-2xl font-semibold text-white">Top Genre</h2>
<p class="text-xl text-gray-300">Pop</p>
</div>
<div class="bg-stone-900 shadow-lg rounded-lg p-6 text-center">
<h2 class="text-2xl font-semibold text-white">Average Song Duration</h2>
<p class="text-xl text-gray-300">3 min 45 sec</p>
</div>
<div class="bg-stone-900 shadow-lg rounded-lg p-6 text-center">
<h2 class="text-2xl font-semibold text-white">Most Active Day</h2>
<p class="text-xl text-gray-300">Saturday</p>
</div>
<div class="bg-stone-900 shadow-lg rounded-lg p-6 text-center">
<h2 class="text-2xl font-semibold text-white">Unique Artists Listened</h2>
<p class="text-xl text-gray-300">28</p>
</div>
</div>

<!-- Mood Distribution Chart -->
<div class="bg-stone-950 shadow-lg rounded-lg p-6 mb-8">
<h2 class="text-2xl font-semibold text-white mb-4">Mood Distribution</h2>
<canvas id="MoodChart" class="w-full h-64"></canvas>
</div>

<!-- Listening by Service (Spotify/YouTube) -->
<div class="bg-stone-950 shadow-lg rounded-lg p-6 mb-8">
<h2 class="text-2xl font-semibold text-white mb-4">Listening by Service</h2>
<canvas id="ServiceChart" class="w-full h-64"></canvas>
</div>

<!-- <div *ngIf="screenSize === 'mobile'" class="mobile-layout">
<div [ngClass]="backgroundMoodClasses[this.moodService.getCurrentMood()]" class="min-h-screen grid grid-cols-5 grid-rows-6 gap-4 px-6 py-3 lg:px-8" style="overflow: auto;">
<canvas class="left-1/2 top-1/2 pt-12" id="MyChart" ></canvas>
<!-- Top Genres Chart -->
<div class="bg-stone-950 shadow-lg rounded-lg p-6">
<h2 class="text-2xl font-semibold text-white mb-4">Top Genres</h2>
<canvas id="GenreChart" class="w-full h-64"></canvas>
</div>
<button [ngClass]="moodComponentClasses[this.moodService.getCurrentMood()]" class="font-medium rounded-lg text-sm px-4 py-2.5 text-center" (click)="nextChartType()">Next</button>
</div> -->
</div>
195 changes: 108 additions & 87 deletions Frontend/src/app/pages/insights/insights.component.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { AfterViewInit, AfterViewChecked, Component, Inject, PLATFORM_ID, Input } from "@angular/core";
import { AfterViewInit, AfterViewChecked, Component, Inject, PLATFORM_ID, Input, ElementRef, ViewChild } from "@angular/core";
import { isPlatformBrowser } from "@angular/common";
import Chart, { ChartType } from "chart.js/auto";
import { MoodService } from '../../services/mood-service.service';
Expand All @@ -14,110 +14,131 @@ import { NgClass, NgIf } from '@angular/common';
export class InsightsComponent implements AfterViewInit, AfterViewChecked {
@Input() percentageData: number[] = [25, 5, 30, 40, 10, 15, 20, 25, 30, 10, 15, 5, 20, 5, 5, 15, 10, 10, 25, 10, 20, 15, 10, 5, 20, 15];
public chart: any;
// Chart Variables
public chartTypes: ChartType[] = ["pie", "bar", "line", "doughnut", "radar", "polarArea"];
public currentChartIndex: number = 0;
screenSize?: string;
//Mood Service Variables
currentMood!: string;
moodComponentClasses!:{ [key: string]: string };
backgroundMoodClasses!:{ [key: string]: string };
// Page Variables
public moodComponentClasses!: { [key: string]: string };
private chartInitialized: boolean = false;

// ViewChild sections for smooth scrolling
@ViewChild('widgets', { static: false }) widgetsSection!: ElementRef;
@ViewChild('moodChart', { static: false }) moodChartSection!: ElementRef;
@ViewChild('serviceChart', { static: false }) serviceChartSection!: ElementRef;
@ViewChild('genreChart', { static: false }) genreChartSection!: ElementRef;

constructor(@Inject(PLATFORM_ID) private platformId: Object, public moodService: MoodService) {
this.moodComponentClasses = this.moodService.getComponentMoodClasses();
this.backgroundMoodClasses = this.moodService.getBackgroundMoodClasses();
this.moodComponentClasses = {
'Joy': 'bg-yellow-400 text-black',
'Sadness': 'bg-blue-400 text-white',
'Anger': 'bg-red-400 text-white',
'Love': 'bg-pink-400 text-white',
'Fear': 'bg-gray-400 text-white',
'Optimism': 'bg-green-400 text-white'
};
}

ngAfterViewInit() {
this.chartInitialized = false; // Reset chart initialization flag
};

this.chartInitialized = false;
}

ngAfterViewChecked() {
if (isPlatformBrowser(this.platformId) && !this.chartInitialized) {
const chartCanvas = document.getElementById("MyChart") as HTMLCanvasElement;
if (chartCanvas) {
this.createChart().then(() => {
this.chartInitialized = true; // Set chart initialization flag
}).catch(error => {
});
}
this.initializeCharts();
}
}

createChart(): Promise<void> {
return new Promise((resolve, reject) => {
try {
const chartCanvas = document.getElementById("MyChart") as HTMLCanvasElement;
if (chartCanvas) {
console.log("Canvas element found");
if (this.chart) {
this.chart.destroy();
initializeCharts() {
this.createChart('MoodChart', this.chartTypes[this.currentChartIndex], this.getMoodData());
this.createChart('ServiceChart', 'doughnut', this.getServiceDistributionData());
this.createChart('GenreChart', 'bar', this.getGenreData());
this.chartInitialized = true;
}

createChart(chartId: string, type: ChartType, chartData: any) {
const chartCanvas = document.getElementById(chartId) as HTMLCanvasElement;
if (chartCanvas) {
const existingChart = Chart.getChart(chartId);
if (existingChart) existingChart.destroy();

new Chart(chartCanvas, {
type: type,
data: chartData,
options: {
aspectRatio: 2.5,
responsive: true,
plugins: {
legend: { display: true, position: 'bottom' },
tooltip: { enabled: true }
}
this.chart = new Chart(chartCanvas, {
type: this.chartTypes[this.currentChartIndex],
data: {
labels: [
"Anger", "Annoyance", "Fear", "Excitement", "Amusement", "Admiration",
"Approval", "Caring", "Joy", "Desire", "Curiosity", "Confusion",
"Gratitude", "Surprise", "Disappointment", "Disapproval", "Disgust",
"Embarrassment", "Sadness", "Grief", "Love", "Nervousness", "Optimism",
"Pride", "Realisation", "Relief"
],
datasets: [{
label: "Percentage of recent Moods",
data: this.percentageData,
backgroundColor: [
this.moodService.getRBGAColor("Anger"),
this.moodService.getRBGAColor("Annoyance"),
this.moodService.getRBGAColor("Fear"),
this.moodService.getRBGAColor("Excitement"),
this.moodService.getRBGAColor("Amusement"),
this.moodService.getRBGAColor("Admiration"),
this.moodService.getRBGAColor("Approval"),
this.moodService.getRBGAColor("Caring"),
this.moodService.getRBGAColor("Joy"),
this.moodService.getRBGAColor("Desire"),
this.moodService.getRBGAColor("Curiosity"),
this.moodService.getRBGAColor("Confusion"),
this.moodService.getRBGAColor("Gratitude"),
this.moodService.getRBGAColor("Surprise"),
this.moodService.getRBGAColor("Disappointment"),
this.moodService.getRBGAColor("Disapproval"),
this.moodService.getRBGAColor("Disgust"),
this.moodService.getRBGAColor("Embarrassment"),
this.moodService.getRBGAColor("Sadness"),
this.moodService.getRBGAColor("Grief"),
this.moodService.getRBGAColor("Love"),
this.moodService.getRBGAColor("Nervousness"),
this.moodService.getRBGAColor("Optimism"),
this.moodService.getRBGAColor("Pride"),
this.moodService.getRBGAColor("Realisation"),
this.moodService.getRBGAColor("Relief"),
],
hoverOffset: 4
}]
},
options: {
aspectRatio: 2.5
}
});
resolve();
} else {
reject("Canvas element not found");
}
} catch (error) {
reject(error);
}
});
});
}
}

nextChartType() {
this.currentChartIndex = (this.currentChartIndex + 1) % this.chartTypes.length;
this.createChart().then(() => {
}).catch(error => {
});
this.createChart('MoodChart', this.chartTypes[this.currentChartIndex], this.getMoodData());
}

scrollToSection(section: string) {
let targetSection: ElementRef | undefined;
switch (section) {
case 'widgets':
targetSection = this.widgetsSection;
break;
case 'moodChart':
targetSection = this.moodChartSection;
break;
case 'serviceChart':
targetSection = this.serviceChartSection;
break;
case 'genreChart':
targetSection = this.genreChartSection;
break;
}

if (targetSection) {
targetSection.nativeElement.scrollIntoView({ behavior: 'smooth' });
}
}

getMoodData() {
return {
labels: [
"Joy", "Sadness", "Anger", "Disgust", "Fear", "Surprise", "Love", "Optimism", "Pride", "Relief"
],
datasets: [{
label: 'Mood Distribution',
data: [30, 10, 5, 3, 7, 8, 25, 5, 2, 5],
backgroundColor: [
'#facc15', '#94a3b8', '#ef4444', '#a3e635', '#3b82f6', '#eab308',
'#ec4899', '#10b981', '#fb923c', '#6b7280'
],
hoverOffset: 4
}]
};
}

getServiceDistributionData() {
return {
labels: ['Spotify', 'YouTube'],
datasets: [{
label: 'Listening Distribution',
data: [70, 30],
backgroundColor: ['#1DB954', '#FF0000'],
}]
};
}

getGenreData() {
return {
labels: ['Pop', 'Rock', 'Hip-Hop', 'Electronic', 'Jazz', 'Classical', 'Indie', 'R&B'],
datasets: [{
label: 'Top Genres',
data: [35, 20, 15, 10, 5, 5, 7, 3],
backgroundColor: [
'#f43f5e', '#3b82f6', '#22c55e', '#facc15', '#6366f1', '#8b5cf6', '#f59e0b', '#10b981'
]
}]
};
}
}
}

0 comments on commit fcf2bc0

Please sign in to comment.