Initial Language Graph Implementation

This commit is contained in:
2023-12-28 22:34:36 -03:00
parent 12e8aadf7b
commit f4f11a8a05
9 changed files with 249 additions and 14 deletions

View File

@@ -3,7 +3,6 @@
}
.card .card-content {
height: 350px;
width: 100%;
padding: 40px;
display: flex;
@@ -34,13 +33,9 @@
justify-content: center;
flex-direction: row;
}
.card .card-content .card-content-f .card-info {
display: flex;
flex-direction: column;
}
.card .card-content .card-content-f .card-stats {
display: flex;
flex-direction: column;
flex-direction: row;
justify-content: space-around;
}
@@ -72,3 +67,22 @@
width: 100%;
flex-direction: row !important;
}
.card-languages {
padding: 0;
margin-top: 25px;
margin-bottom: 25px;
}
/* COMPUTER FORMAT */
@media only screen and (min-width: 712px) {
.card-languages {
margin: 0;
}
.card .card-content .card-content-f .card-stats {
display: flex;
flex-direction: column;
justify-content: space-around;
}
}

View File

@@ -7,10 +7,18 @@
<p class="card-text">{{project.description}}</p>
</div>
<div class="card-content-f row">
<div class="card-info col-9" *ngIf="hasLanguage">
<p >Language: {{project.languages}}</p>
<div class="card-languages col-sm-9" *ngIf="hasLanguage" id="language-chart">
<apx-chart *ngIf="chartOptions !== undefined"
[series]="chartOptions.series"
[colors]="chartOptions.colors"
[chart]="chartOptions.chart"
[labels]="chartOptions.labels"
[responsive]="chartOptions.responsive"
[plotOptions]="chartOptions.plotOptions"
[dataLabels]="chartOptions.dataLabels">
</apx-chart>
</div>
<div class="card-stats" [ngClass]="hasLanguage ? 'col-3' : 'stats-inline'">
<div class="card-stats" [ngClass]="hasLanguage ? 'col-sm-3' : 'stats-inline'">
<div class="stat-item" *ngIf="hasLicense">
<div class="stat-icon">
<fa-icon [icon]="faLicense"></fa-icon>

View File

@@ -1,18 +1,42 @@
import {Component, Input} from '@angular/core';
import {Component, Input, OnInit, ViewChild} from '@angular/core';
import { faCodeFork, faEye, faStar } from '@fortawesome/free-solid-svg-icons';
import {Project} from "../../shared/model/project/project.model";
import {Language, Project} from "../../shared/model/project/project.model";
import {faScaleBalanced} from "@fortawesome/free-solid-svg-icons/faScaleBalanced";
import {
ApexAnnotations,
ApexChart, ApexDataLabels,
ApexNonAxisChartSeries,
ApexPlotOptions,
ApexResponsive,
ChartComponent
} from "ng-apexcharts";
export type ChartOptions = {
series: ApexNonAxisChartSeries;
colors: string[];
chart: ApexChart;
responsive: ApexResponsive[];
labels: string[];
plotOptions: ApexPlotOptions;
dataLabels: ApexDataLabels;
};
@Component({
selector: 'app-project-card',
templateUrl: './project-card.component.html',
styleUrls: ['./project-card.component.css']
})
export class ProjectCardComponent {
export class ProjectCardComponent implements OnInit {
@Input() inverted: boolean = false;
@Input() project!: Project;
@ViewChild('language-chart')
languageChart: ChartComponent | undefined;
chartOptions: ChartOptions | undefined;
// Stats Icons Definitions
faLicense = faScaleBalanced;
@@ -22,6 +46,13 @@ export class ProjectCardComponent {
faEye = faEye;
ngOnInit() {
if (!!this.project.languages) {
this.chartOptions = this.generateChart(this.project.languages);
}
}
get hasLicense(): boolean {
return this.project.license !== undefined;
}
@@ -30,4 +61,37 @@ export class ProjectCardComponent {
return this.project.languages !== undefined &&
this.project.languages?.length > 0;
}
private generateChart(languages: Language[]): ChartOptions {
return {
series: languages.map(value => value.percentage),
colors: languages.map(value => value.color),
chart: {
width: 380,
type: "pie"
},
labels: languages.map(value => value.name),
responsive: [
{
breakpoint: 480,
options: {
chart: {
width: 300
},
legend: {
position: "bottom"
}
}
}
],
plotOptions: {
pie: {
expandOnClick: true,
}
},
dataLabels: {
enabled: false
}
};
}
}

View File

@@ -4,6 +4,7 @@ import {CommonModule, NgOptimizedImage} from "@angular/common";
import { ProjectCardComponent } from './project-card/project-card.component';
import {MatIconModule} from "@angular/material/icon";
import {FontAwesomeModule} from "@fortawesome/angular-fontawesome";
import {NgApexchartsModule} from "ng-apexcharts";
@NgModule({
declarations: [
@@ -14,7 +15,8 @@ import {FontAwesomeModule} from "@fortawesome/angular-fontawesome";
CommonModule,
NgOptimizedImage,
MatIconModule,
FontAwesomeModule
FontAwesomeModule,
NgApexchartsModule
],
exports: []
})

View File

@@ -15,9 +15,17 @@ export class GithubService {
GITHUB_API_URL = 'https://api.github.com';
GITHUB_API_COLORS = 'https://raw.githubusercontent.com/ozh/github-colors/master/colors.json';
GITHUB_USER = environment.githubUser;
constructor(private http: HttpClient) { }
colors!: Map<string, string>;
constructor(private http: HttpClient) {
this.getLanguageColor().subscribe((colors: Map<string, string>) => {
this.colors = colors;
});
}
getProjects(): Observable<Project> {
return this.http.get(this.apiReposString()).pipe(
@@ -61,6 +69,7 @@ export class GithubService {
return Object.keys(languages).map((language: string) => {
return {
name: language,
color: this.colors.get(language) || this.getRandColor(),
percentage: (languages[language]/totalBytes)*100
} as Language;
});
@@ -68,6 +77,22 @@ export class GithubService {
);
}
private getLanguageColor(): Observable<Map<string, string>> {
return this.http.get(this.GITHUB_API_COLORS).pipe(
map((colors: any) => {
const colorMap = new Map<string, string>();
Object.keys(colors).forEach((language: string) => {
colorMap.set(language, colors[language].color);
});
return colorMap;
})
);
}
private getRandColor(): string {
return `#${Math.floor(Math.random()*16777215).toString(16)}`;
}
private apiReposString() {
return `${this.GITHUB_API_URL}/users/${this.GITHUB_USER}/repos`;
}

View File

@@ -1,5 +1,6 @@
export type Language = {
name: string;
color: string;
percentage: number;
}