From f6c0cb1ca1d5c6154ffb8009759742adcf4bf239 Mon Sep 17 00:00:00 2001 From: Vitor Hideyoshi Nakazone Batista Date: Thu, 28 Dec 2023 02:59:32 -0300 Subject: [PATCH 01/12] Minor Fixes in Home Page --- .gitignore | 1 + src/app/app.module.ts | 1 - src/app/home/stack-slider/stack-card/stack-card.component.css | 4 ++++ 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 4fcb0ba..32953f9 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,7 @@ yarn-error.log .project .classpath .c9/ +.nx/ *.launch .settings/ *.sublime-workspace diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 1ee9eb6..9d85a39 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -4,7 +4,6 @@ import { BrowserModule } from '@angular/platform-browser'; import { AppComponent } from './app.component'; import { HeaderModule } from './header/header.module'; import { SharedModule } from './shared/shared.module'; -import { HomeComponent } from './home/home.component'; import { AppRouterModule } from './app-router.module'; import { FontAwesomeModule } from '@fortawesome/angular-fontawesome'; import { AppServiceWorkerModule } from './app-service-worker.module'; diff --git a/src/app/home/stack-slider/stack-card/stack-card.component.css b/src/app/home/stack-slider/stack-card/stack-card.component.css index b3c5ebb..1b71ed7 100644 --- a/src/app/home/stack-slider/stack-card/stack-card.component.css +++ b/src/app/home/stack-slider/stack-card/stack-card.component.css @@ -14,6 +14,10 @@ display: flex; align-items: center; } +.stack-card-image::selection, +.stack-card-image *::selection { + background: transparent; +} .stack-card-body { padding: 10px; From 12e8aadf7b9fff49cc4754e82a02a78dd24ad24e Mon Sep 17 00:00:00 2001 From: Vitor Hideyoshi Nakazone Batista Date: Thu, 28 Dec 2023 21:28:36 -0300 Subject: [PATCH 02/12] Initial Implementation of Project Cards --- src/app/app-router.module.ts | 5 ++ src/app/app.module.ts | 2 + src/app/header/header.component.ts | 8 +- .../project-card/project-card.component.css | 74 ++++++++++++++++++ .../project-card/project-card.component.html | 41 ++++++++++ .../project-card.component.spec.ts | 21 +++++ .../project-card/project-card.component.ts | 33 ++++++++ src/app/projects/projects.component.css | 8 ++ src/app/projects/projects.component.html | 6 ++ src/app/projects/projects.component.spec.ts | 21 +++++ src/app/projects/projects.component.ts | 27 +++++++ src/app/projects/projects.module.ts | 21 +++++ src/app/shared/auth/auth.service.ts | 4 - .../github-service/github.service.spec.ts | 16 ++++ .../shared/github-service/github.service.ts | 78 +++++++++++++++++++ src/app/shared/model/project/project.model.ts | 17 ++++ src/environments/environment.prod.ts | 1 + src/environments/environment.ts | 1 + 18 files changed, 376 insertions(+), 8 deletions(-) create mode 100644 src/app/projects/project-card/project-card.component.css create mode 100644 src/app/projects/project-card/project-card.component.html create mode 100644 src/app/projects/project-card/project-card.component.spec.ts create mode 100644 src/app/projects/project-card/project-card.component.ts create mode 100644 src/app/projects/projects.component.css create mode 100644 src/app/projects/projects.component.html create mode 100644 src/app/projects/projects.component.spec.ts create mode 100644 src/app/projects/projects.component.ts create mode 100644 src/app/projects/projects.module.ts create mode 100644 src/app/shared/github-service/github.service.spec.ts create mode 100644 src/app/shared/github-service/github.service.ts create mode 100644 src/app/shared/model/project/project.model.ts diff --git a/src/app/app-router.module.ts b/src/app/app-router.module.ts index 43d8625..c05a30d 100644 --- a/src/app/app-router.module.ts +++ b/src/app/app-router.module.ts @@ -3,6 +3,7 @@ import { CommonModule } from '@angular/common'; import { RouterModule, Routes } from '@angular/router'; import { HomeComponent } from './home/home.component'; import { CallbackComponent } from './header/header-popup/callback/callback.component'; +import {ProjectsComponent} from "./projects/projects.component"; const routes: Routes = [ { @@ -14,6 +15,10 @@ const routes: Routes = [ path: 'home', component: HomeComponent, }, + { + path: 'projects', + component: ProjectsComponent, + }, { path: 'callback', component: CallbackComponent, diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 9d85a39..98c88c1 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -11,6 +11,7 @@ import { ServiceWorkerModule } from '@angular/service-worker'; import { environment } from '../environments/environment'; import { FooterComponent } from './footer/footer.component'; import {HomeModule} from "./home/home.module"; +import {ProjectsModule} from "./projects/projects.module"; @NgModule({ declarations: [AppComponent, FooterComponent], @@ -18,6 +19,7 @@ import {HomeModule} from "./home/home.module"; BrowserModule, HeaderModule, HomeModule, + ProjectsModule, AppRouterModule, AppServiceWorkerModule, SharedModule, diff --git a/src/app/header/header.component.ts b/src/app/header/header.component.ts index 4f75f3f..c13684f 100644 --- a/src/app/header/header.component.ts +++ b/src/app/header/header.component.ts @@ -25,7 +25,7 @@ import { MyProfileComponent } from './header-popup/my-profile/my-profile.compone export class HeaderComponent implements OnInit, OnDestroy { pages: { name: string; route: string }[] = [ { name: 'Home', route: '/home' }, - { name: 'Projects', route: '/home' }, + { name: 'Projects', route: '/projects' }, { name: 'Contact', route: '/home' }, ]; @@ -38,13 +38,13 @@ export class HeaderComponent implements OnInit, OnDestroy { userSliderStatus: boolean = false; @ViewChild('profileBtn') - profileBtnElementRef!: ElementRef; + profileBtnElementRef!: ElementRef; @ViewChild('profileDropdown') - profileDropdownElementRef!: ElementRef; + profileDropdownElementRef!: ElementRef; @ViewChild('user') - userElementRef!: ElementRef; + userElementRef!: ElementRef; loggedUser!: User | null; diff --git a/src/app/projects/project-card/project-card.component.css b/src/app/projects/project-card/project-card.component.css new file mode 100644 index 0000000..12d44ca --- /dev/null +++ b/src/app/projects/project-card/project-card.component.css @@ -0,0 +1,74 @@ +.card .inverse-card-image { + flex-direction: row-reverse; +} + +.card .card-content { + height: 350px; + width: 100%; + padding: 40px; + display: flex; + flex-direction: column; + justify-content: space-around; +} +.card .card-content > * { + margin: 10px; +} + +.card .card-content .card-content-h { + width: 80%; +} + +.card .card-content .card-title { + font-size: 2rem; + font-weight: 500; + justify-content: left; +} +.card .card-content .card-text { + font-size: 1.2rem; + font-weight: 300; +} + + +.card .card-content .card-content-f { + display: flex; + 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; + justify-content: space-around; +} + + +.stat-item { + margin: 5px 0px 5px 0px; + display: flex; + flex-direction: row; + align-items: start; + align-content: start; +} +.stat-item .stat-icon { + margin: 0px 15px 0px 0px; + width: 20px; + height: 20px; + font-size: 1rem; + + display: flex; +} +.stat-item span { + font-size: 1rem; + font-weight: 300; + margin: 0; + justify-content: left; +} + +.stats-inline { + margin: 0; + width: 100%; + flex-direction: row !important; +} diff --git a/src/app/projects/project-card/project-card.component.html b/src/app/projects/project-card/project-card.component.html new file mode 100644 index 0000000..02af6f7 --- /dev/null +++ b/src/app/projects/project-card/project-card.component.html @@ -0,0 +1,41 @@ +
+
+
+

+ {{project.name}} +

+

{{project.description}}

+
+
+
+

Language: {{project.languages}}

+
+
+
+
+ +
+ {{project.license}} +
+
+
+ +
+ {{project.stars}} +
+
+
+ +
+ {{project.forks}} +
+
+
+ +
+ {{project.watchers}} +
+
+
+
+
diff --git a/src/app/projects/project-card/project-card.component.spec.ts b/src/app/projects/project-card/project-card.component.spec.ts new file mode 100644 index 0000000..74de6b1 --- /dev/null +++ b/src/app/projects/project-card/project-card.component.spec.ts @@ -0,0 +1,21 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ProjectCardComponent } from './project-card.component'; + +describe('ProjectCardComponent', () => { + let component: ProjectCardComponent; + let fixture: ComponentFixture; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [ProjectCardComponent] + }); + fixture = TestBed.createComponent(ProjectCardComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/projects/project-card/project-card.component.ts b/src/app/projects/project-card/project-card.component.ts new file mode 100644 index 0000000..eb7f79d --- /dev/null +++ b/src/app/projects/project-card/project-card.component.ts @@ -0,0 +1,33 @@ +import {Component, Input} from '@angular/core'; +import { faCodeFork, faEye, faStar } from '@fortawesome/free-solid-svg-icons'; +import {Project} from "../../shared/model/project/project.model"; +import {faScaleBalanced} from "@fortawesome/free-solid-svg-icons/faScaleBalanced"; + +@Component({ + selector: 'app-project-card', + templateUrl: './project-card.component.html', + styleUrls: ['./project-card.component.css'] +}) +export class ProjectCardComponent { + @Input() inverted: boolean = false; + + @Input() project!: Project; + + // Stats Icons Definitions + faLicense = faScaleBalanced; + + faStars = faStar; + + faCodeFork = faCodeFork; + + faEye = faEye; + + get hasLicense(): boolean { + return this.project.license !== undefined; + } + + get hasLanguage(): boolean { + return this.project.languages !== undefined && + this.project.languages?.length > 0; + } +} diff --git a/src/app/projects/projects.component.css b/src/app/projects/projects.component.css new file mode 100644 index 0000000..fc35c46 --- /dev/null +++ b/src/app/projects/projects.component.css @@ -0,0 +1,8 @@ +app-project-card { + display: flex; + flex-direction: column; + margin-top: 25px; +} +app-project-card:last-child { + margin-bottom: 25px; +} diff --git a/src/app/projects/projects.component.html b/src/app/projects/projects.component.html new file mode 100644 index 0000000..6604b95 --- /dev/null +++ b/src/app/projects/projects.component.html @@ -0,0 +1,6 @@ +
+
+ + +
+
diff --git a/src/app/projects/projects.component.spec.ts b/src/app/projects/projects.component.spec.ts new file mode 100644 index 0000000..d396b2d --- /dev/null +++ b/src/app/projects/projects.component.spec.ts @@ -0,0 +1,21 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ProjectsComponent } from './projects.component'; + +describe('ProjectsComponent', () => { + let component: ProjectsComponent; + let fixture: ComponentFixture; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [ProjectsComponent] + }); + fixture = TestBed.createComponent(ProjectsComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/projects/projects.component.ts b/src/app/projects/projects.component.ts new file mode 100644 index 0000000..23da837 --- /dev/null +++ b/src/app/projects/projects.component.ts @@ -0,0 +1,27 @@ +import {Component, OnInit} from '@angular/core'; +import {GithubService} from "../shared/github-service/github.service"; +import {Project} from "../shared/model/project/project.model"; + +@Component({ + selector: 'app-projects', + templateUrl: './projects.component.html', + styleUrls: ['./projects.component.css'] +}) +export class ProjectsComponent implements OnInit { + projects!: Project[]; + + constructor(private githubService: GithubService) { + } + + ngOnInit(): void { + this.projects = []; + this.githubService.getProjects().subscribe((project: Project) => { + this.projects.push(project); + }); + } + + identifyProject(index: number, project: Project) { + return project.name; + } + +} diff --git a/src/app/projects/projects.module.ts b/src/app/projects/projects.module.ts new file mode 100644 index 0000000..665f97d --- /dev/null +++ b/src/app/projects/projects.module.ts @@ -0,0 +1,21 @@ +import {NgModule} from "@angular/core"; +import {ProjectsComponent} from "./projects.component"; +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"; + +@NgModule({ + declarations: [ + ProjectsComponent, + ProjectCardComponent + ], + imports: [ + CommonModule, + NgOptimizedImage, + MatIconModule, + FontAwesomeModule + ], + exports: [] +}) +export class ProjectsModule { } diff --git a/src/app/shared/auth/auth.service.ts b/src/app/shared/auth/auth.service.ts index b3aedae..678376b 100644 --- a/src/app/shared/auth/auth.service.ts +++ b/src/app/shared/auth/auth.service.ts @@ -2,19 +2,15 @@ import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { first, - firstValueFrom, map, Observable, of, Subject, - take, - tap, } from 'rxjs'; import { catchError } from 'rxjs/operators'; import { environment } from 'src/environments/environment'; import { HttpError } from '../model/httpError/httpError.model'; import { User } from '../model/user/user.model'; -import * as http from 'http'; @Injectable({ providedIn: 'root', diff --git a/src/app/shared/github-service/github.service.spec.ts b/src/app/shared/github-service/github.service.spec.ts new file mode 100644 index 0000000..bcef5d4 --- /dev/null +++ b/src/app/shared/github-service/github.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { GithubServiceService } from './github.service'; + +describe('GithubServiceService', () => { + let service: GithubServiceService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(GithubServiceService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/app/shared/github-service/github.service.ts b/src/app/shared/github-service/github.service.ts new file mode 100644 index 0000000..5905cea --- /dev/null +++ b/src/app/shared/github-service/github.service.ts @@ -0,0 +1,78 @@ +import { Injectable } from '@angular/core'; +import {Language, Project} from "../model/project/project.model"; +import {HttpClient} from "@angular/common/http"; +import { + map, mergeMap, + Observable, + pipe, switchMap, take +} from 'rxjs'; +import { environment } from 'src/environments/environment'; + +@Injectable({ + providedIn: 'root' +}) +export class GithubService { + + GITHUB_API_URL = 'https://api.github.com'; + + GITHUB_USER = environment.githubUser; + + constructor(private http: HttpClient) { } + + getProjects(): Observable { + return this.http.get(this.apiReposString()).pipe( + map((projects: any) => { + return projects.map((project: any) => { + return { + name: project.name, + description: project.description, + license: project.license?.key, + link: project.html_url, + + stars: project.stargazers_count, + forks: project.forks_count, + watchers: project.watchers_count + } as Project; + }).filter((project: Project) => { + return project.name !== this.GITHUB_USER; + }); + }), + switchMap((projects: Project[]) => { + return new Observable((observer) => { + projects.forEach((project: Project, index: number) => { + this.getProjectLanguage(project).subscribe((languages: Language[]) => { + project.languages = languages; + observer.next(project); + }); + }); + }); + }) + ) + } + + private getProjectLanguage(project: Project): Observable { + return this.http.get(this.apiRepoLanguagesString(project.name)).pipe( + map((languages: any) => { + let totalBytes = 0; + Object.keys(languages).forEach((language: string) => { + totalBytes += languages[language]; + }); + + return Object.keys(languages).map((language: string) => { + return { + name: language, + percentage: (languages[language]/totalBytes)*100 + } as Language; + }); + }) + ); + } + + private apiReposString() { + return `${this.GITHUB_API_URL}/users/${this.GITHUB_USER}/repos`; + } + + private apiRepoLanguagesString(repoName: string) { + return `${this.GITHUB_API_URL}/repos/${this.GITHUB_USER}/${repoName}/languages`; + } +} diff --git a/src/app/shared/model/project/project.model.ts b/src/app/shared/model/project/project.model.ts new file mode 100644 index 0000000..8fd9c7b --- /dev/null +++ b/src/app/shared/model/project/project.model.ts @@ -0,0 +1,17 @@ +export type Language = { + name: string; + percentage: number; +} + +export type Project = { + name: string; + description: string; + link: string; + + license?: string; + languages?: Language[]; + + stars: number; + forks: number; + watchers: number; +} diff --git a/src/environments/environment.prod.ts b/src/environments/environment.prod.ts index d1643c6..adff1c3 100644 --- a/src/environments/environment.prod.ts +++ b/src/environments/environment.prod.ts @@ -2,4 +2,5 @@ export const environment = { production: true, backendPath: (window)['env']['BACKEND_URL'], backendOAuthPath: (window)['env']['BACKEND_OAUTH_URL'], + githubUser: (window)['env']['GITHUB_USER'], }; diff --git a/src/environments/environment.ts b/src/environments/environment.ts index 6e0d313..bdf5548 100644 --- a/src/environments/environment.ts +++ b/src/environments/environment.ts @@ -6,6 +6,7 @@ export const environment = { production: false, backendPath: 'http://localhost:8070', backendOAuthPath: 'http://localhost:8070', + githubUser: 'HideyoshiNakazone', }; /* From f4f11a8a05171a174e891dbae7db69e87f3ba0bf Mon Sep 17 00:00:00 2001 From: Vitor Hideyoshi Nakazone Batista Date: Thu, 28 Dec 2023 22:34:36 -0300 Subject: [PATCH 03/12] Initial Language Graph Implementation --- package-lock.json | 118 ++++++++++++++++++ package.json | 2 + .../project-card/project-card.component.css | 26 +++- .../project-card/project-card.component.html | 14 ++- .../project-card/project-card.component.ts | 70 ++++++++++- src/app/projects/projects.module.ts | 4 +- .../shared/github-service/github.service.ts | 27 +++- src/app/shared/model/project/project.model.ts | 1 + src/assets/env.sample.js | 1 + 9 files changed, 249 insertions(+), 14 deletions(-) diff --git a/package-lock.json b/package-lock.json index c9e31e2..b343608 100644 --- a/package-lock.json +++ b/package-lock.json @@ -25,12 +25,14 @@ "@fortawesome/free-regular-svg-icons": "^6.1.1", "@fortawesome/free-solid-svg-icons": "^6.1.1", "@glidejs/glide": "^3.6.0", + "apexcharts": "^3.45.1", "bootstrap": "^4.6.2", "cookieconsent": "^3.1.1", "cors": "^2.8.5", "envsub": "^4.1.0", "express": "^4.18.1", "jquery": "^3.6.0", + "ng-apexcharts": "^1.8.0", "ngx-cookie-service": "^16.0.1", "ngx-cookieconsent": "^4.0.2", "ngx-glide": "^16.0.0", @@ -5440,6 +5442,11 @@ "node": ">=14.15.0" } }, + "node_modules/@yr/monotone-cubic-spline": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@yr/monotone-cubic-spline/-/monotone-cubic-spline-1.0.3.tgz", + "integrity": "sha512-FQXkOta0XBSUPHndIKON2Y9JeQz5ZeMqLYZVVK93FliNBFm7LNMIZmY6FrMEB9XPcDbE2bekMbZD6kzDkxwYjA==" + }, "node_modules/@zkochan/js-yaml": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/@zkochan/js-yaml/-/js-yaml-0.0.6.tgz", @@ -5722,6 +5729,20 @@ "node": ">= 8" } }, + "node_modules/apexcharts": { + "version": "3.45.1", + "resolved": "https://registry.npmjs.org/apexcharts/-/apexcharts-3.45.1.tgz", + "integrity": "sha512-pPjj/SA6dfPvR/IKRZF0STdfBGpBh3WRt7K0DFuW9P8erypYkX17EHu3/molPRfo2zSiQwTVpshHC5ncysqfkA==", + "dependencies": { + "@yr/monotone-cubic-spline": "^1.0.3", + "svg.draggable.js": "^2.2.2", + "svg.easing.js": "^2.0.0", + "svg.filter.js": "^2.0.2", + "svg.pathmorphing.js": "^0.1.3", + "svg.resize.js": "^1.4.3", + "svg.select.js": "^3.0.1" + } + }, "node_modules/aproba": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", @@ -12063,6 +12084,20 @@ "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" }, + "node_modules/ng-apexcharts": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/ng-apexcharts/-/ng-apexcharts-1.8.0.tgz", + "integrity": "sha512-NwJuMLHoLm52LSzM08RXV6oOOTyUYREAV53WHVGs+L2qi8UWbxCz19hX0kk+F/xFLEhhuiLegO3T1v30jLbKSQ==", + "dependencies": { + "tslib": "^2.0.0" + }, + "peerDependencies": { + "@angular/common": ">=13.0.0", + "@angular/core": ">=13.0.0", + "apexcharts": "^3.41.0", + "rxjs": "^6.5.3 || ^7.4.0" + } + }, "node_modules/ngx-cookie-service": { "version": "16.0.1", "resolved": "https://registry.npmjs.org/ngx-cookie-service/-/ngx-cookie-service-16.0.1.tgz", @@ -15233,6 +15268,89 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/svg.draggable.js": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/svg.draggable.js/-/svg.draggable.js-2.2.2.tgz", + "integrity": "sha512-JzNHBc2fLQMzYCZ90KZHN2ohXL0BQJGQimK1kGk6AvSeibuKcIdDX9Kr0dT9+UJ5O8nYA0RB839Lhvk4CY4MZw==", + "dependencies": { + "svg.js": "^2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/svg.easing.js": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/svg.easing.js/-/svg.easing.js-2.0.0.tgz", + "integrity": "sha512-//ctPdJMGy22YoYGV+3HEfHbm6/69LJUTAqI2/5qBvaNHZ9uUFVC82B0Pl299HzgH13rKrBgi4+XyXXyVWWthA==", + "dependencies": { + "svg.js": ">=2.3.x" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/svg.filter.js": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/svg.filter.js/-/svg.filter.js-2.0.2.tgz", + "integrity": "sha512-xkGBwU+dKBzqg5PtilaTb0EYPqPfJ9Q6saVldX+5vCRy31P6TlRCP3U9NxH3HEufkKkpNgdTLBJnmhDHeTqAkw==", + "dependencies": { + "svg.js": "^2.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/svg.js": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/svg.js/-/svg.js-2.7.1.tgz", + "integrity": "sha512-ycbxpizEQktk3FYvn/8BH+6/EuWXg7ZpQREJvgacqn46gIddG24tNNe4Son6omdXCnSOaApnpZw6MPCBA1dODA==" + }, + "node_modules/svg.pathmorphing.js": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/svg.pathmorphing.js/-/svg.pathmorphing.js-0.1.3.tgz", + "integrity": "sha512-49HWI9X4XQR/JG1qXkSDV8xViuTLIWm/B/7YuQELV5KMOPtXjiwH4XPJvr/ghEDibmLQ9Oc22dpWpG0vUDDNww==", + "dependencies": { + "svg.js": "^2.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/svg.resize.js": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/svg.resize.js/-/svg.resize.js-1.4.3.tgz", + "integrity": "sha512-9k5sXJuPKp+mVzXNvxz7U0uC9oVMQrrf7cFsETznzUDDm0x8+77dtZkWdMfRlmbkEEYvUn9btKuZ3n41oNA+uw==", + "dependencies": { + "svg.js": "^2.6.5", + "svg.select.js": "^2.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/svg.resize.js/node_modules/svg.select.js": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/svg.select.js/-/svg.select.js-2.1.2.tgz", + "integrity": "sha512-tH6ABEyJsAOVAhwcCjF8mw4crjXSI1aa7j2VQR8ZuJ37H2MBUbyeqYr5nEO7sSN3cy9AR9DUwNg0t/962HlDbQ==", + "dependencies": { + "svg.js": "^2.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/svg.select.js": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/svg.select.js/-/svg.select.js-3.0.1.tgz", + "integrity": "sha512-h5IS/hKkuVCbKSieR9uQCj9w+zLHoPh+ce19bBYyqF53g6mnPB8sAtIbe1s9dh2S2fCmYX2xel1Ln3PJBbK4kw==", + "dependencies": { + "svg.js": "^2.6.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/symbol-observable": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-4.0.0.tgz", diff --git a/package.json b/package.json index 0b5c8bd..2646c9c 100644 --- a/package.json +++ b/package.json @@ -33,12 +33,14 @@ "@fortawesome/free-regular-svg-icons": "^6.1.1", "@fortawesome/free-solid-svg-icons": "^6.1.1", "@glidejs/glide": "^3.6.0", + "apexcharts": "^3.45.1", "bootstrap": "^4.6.2", "cookieconsent": "^3.1.1", "cors": "^2.8.5", "envsub": "^4.1.0", "express": "^4.18.1", "jquery": "^3.6.0", + "ng-apexcharts": "^1.8.0", "ngx-cookie-service": "^16.0.1", "ngx-cookieconsent": "^4.0.2", "ngx-glide": "^16.0.0", diff --git a/src/app/projects/project-card/project-card.component.css b/src/app/projects/project-card/project-card.component.css index 12d44ca..baeaaeb 100644 --- a/src/app/projects/project-card/project-card.component.css +++ b/src/app/projects/project-card/project-card.component.css @@ -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; + } +} diff --git a/src/app/projects/project-card/project-card.component.html b/src/app/projects/project-card/project-card.component.html index 02af6f7..5877570 100644 --- a/src/app/projects/project-card/project-card.component.html +++ b/src/app/projects/project-card/project-card.component.html @@ -7,10 +7,18 @@

{{project.description}}

-
-

Language: {{project.languages}}

+
+ +
-
+
diff --git a/src/app/projects/project-card/project-card.component.ts b/src/app/projects/project-card/project-card.component.ts index eb7f79d..9f32f85 100644 --- a/src/app/projects/project-card/project-card.component.ts +++ b/src/app/projects/project-card/project-card.component.ts @@ -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 + } + }; + } } diff --git a/src/app/projects/projects.module.ts b/src/app/projects/projects.module.ts index 665f97d..25c2b8f 100644 --- a/src/app/projects/projects.module.ts +++ b/src/app/projects/projects.module.ts @@ -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: [] }) diff --git a/src/app/shared/github-service/github.service.ts b/src/app/shared/github-service/github.service.ts index 5905cea..568cffa 100644 --- a/src/app/shared/github-service/github.service.ts +++ b/src/app/shared/github-service/github.service.ts @@ -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; + + constructor(private http: HttpClient) { + this.getLanguageColor().subscribe((colors: Map) => { + this.colors = colors; + }); + } getProjects(): Observable { 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> { + return this.http.get(this.GITHUB_API_COLORS).pipe( + map((colors: any) => { + const colorMap = new Map(); + 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`; } diff --git a/src/app/shared/model/project/project.model.ts b/src/app/shared/model/project/project.model.ts index 8fd9c7b..af47098 100644 --- a/src/app/shared/model/project/project.model.ts +++ b/src/app/shared/model/project/project.model.ts @@ -1,5 +1,6 @@ export type Language = { name: string; + color: string; percentage: number; } diff --git a/src/assets/env.sample.js b/src/assets/env.sample.js index ac046df..151211c 100644 --- a/src/assets/env.sample.js +++ b/src/assets/env.sample.js @@ -4,4 +4,5 @@ // Environment variables window["env"]["BACKEND_URL"] = "${BACKEND_URL}"; window["env"]["BACKEND_OAUTH_URL"] = "${BACKEND_OAUTH_URL}"; + window["env"]["GITHUB_USER"] = "${GITHUB_USER}"; })(this); From 0c52a4ec1ff33d3400d8630e91e442eea91badf3 Mon Sep 17 00:00:00 2001 From: Vitor Hideyoshi Nakazone Batista Date: Thu, 28 Dec 2023 23:41:23 -0300 Subject: [PATCH 04/12] Changes Graph to Donut --- src/app/projects/project-card/project-card.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/projects/project-card/project-card.component.ts b/src/app/projects/project-card/project-card.component.ts index 9f32f85..066d525 100644 --- a/src/app/projects/project-card/project-card.component.ts +++ b/src/app/projects/project-card/project-card.component.ts @@ -68,7 +68,7 @@ export class ProjectCardComponent implements OnInit { colors: languages.map(value => value.color), chart: { width: 380, - type: "pie" + type: "donut" }, labels: languages.map(value => value.name), responsive: [ From 250720de1e1d29ba2299e1da26e33c3410bc1408 Mon Sep 17 00:00:00 2001 From: Vitor Hideyoshi Nakazone Batista Date: Thu, 28 Dec 2023 23:48:45 -0300 Subject: [PATCH 05/12] Better Project Card Styling --- .../projects/project-card/project-card.component.css | 12 +++++++++--- .../projects/project-card/project-card.component.ts | 1 + 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/app/projects/project-card/project-card.component.css b/src/app/projects/project-card/project-card.component.css index baeaaeb..b600656 100644 --- a/src/app/projects/project-card/project-card.component.css +++ b/src/app/projects/project-card/project-card.component.css @@ -17,14 +17,18 @@ width: 80%; } -.card .card-content .card-title { +.card .card-content .card-title a { font-size: 2rem; - font-weight: 500; + font-weight: 600; justify-content: left; + color: #767676; + text-decoration: none; } + .card .card-content .card-text { font-size: 1.2rem; - font-weight: 300; + font-weight: 400; + color: #919294; } @@ -46,6 +50,8 @@ flex-direction: row; align-items: start; align-content: start; + + color: #919294; } .stat-item .stat-icon { margin: 0px 15px 0px 0px; diff --git a/src/app/projects/project-card/project-card.component.ts b/src/app/projects/project-card/project-card.component.ts index 066d525..85406af 100644 --- a/src/app/projects/project-card/project-card.component.ts +++ b/src/app/projects/project-card/project-card.component.ts @@ -87,6 +87,7 @@ export class ProjectCardComponent implements OnInit { plotOptions: { pie: { expandOnClick: true, + } }, dataLabels: { From c1b8b651e05217f49d7b4e1052f3527cc3e32649 Mon Sep 17 00:00:00 2001 From: Vitor Hideyoshi Nakazone Batista Date: Thu, 28 Dec 2023 23:52:40 -0300 Subject: [PATCH 06/12] Better Responsiveness --- .../project-card/project-card.component.css | 2 +- .../project-card/project-card.component.html | 4 +-- .../project-card/project-card.component.ts | 30 +++++++++++++++---- 3 files changed, 27 insertions(+), 9 deletions(-) diff --git a/src/app/projects/project-card/project-card.component.css b/src/app/projects/project-card/project-card.component.css index b600656..23fc3c6 100644 --- a/src/app/projects/project-card/project-card.component.css +++ b/src/app/projects/project-card/project-card.component.css @@ -81,7 +81,7 @@ } /* COMPUTER FORMAT */ -@media only screen and (min-width: 712px) { +@media only screen and (min-width: 770px) { .card-languages { margin: 0; } diff --git a/src/app/projects/project-card/project-card.component.html b/src/app/projects/project-card/project-card.component.html index 5877570..668f584 100644 --- a/src/app/projects/project-card/project-card.component.html +++ b/src/app/projects/project-card/project-card.component.html @@ -7,7 +7,7 @@

{{project.description}}

-
+
-
+
diff --git a/src/app/projects/project-card/project-card.component.ts b/src/app/projects/project-card/project-card.component.ts index 85406af..b92f5ce 100644 --- a/src/app/projects/project-card/project-card.component.ts +++ b/src/app/projects/project-card/project-card.component.ts @@ -1,4 +1,4 @@ -import {Component, Input, OnInit, ViewChild} from '@angular/core'; +import {Component, HostListener, Input, OnInit, ViewChild} from '@angular/core'; import { faCodeFork, faEye, faStar } from '@fortawesome/free-solid-svg-icons'; import {Language, Project} from "../../shared/model/project/project.model"; import {faScaleBalanced} from "@fortawesome/free-solid-svg-icons/faScaleBalanced"; @@ -46,13 +46,28 @@ export class ProjectCardComponent implements OnInit { faEye = faEye; + private windowResizeTimeout: any; + ngOnInit() { if (!!this.project.languages) { - this.chartOptions = this.generateChart(this.project.languages); + const windowWidth = window.innerWidth; + this.chartOptions = this.generateChart(this.project.languages, windowWidth); } } + @HostListener('window:resize', ['$event']) + getScreenSize(event: Event) { + clearTimeout(this.windowResizeTimeout); + + this.windowResizeTimeout = setTimeout(() => { + if (!this.project.languages) return; + this.chartOptions = this.generateChart( + this.project.languages, window.innerWidth + ); + }, 100); + } + get hasLicense(): boolean { return this.project.license !== undefined; } @@ -62,7 +77,10 @@ export class ProjectCardComponent implements OnInit { this.project.languages?.length > 0; } - private generateChart(languages: Language[]): ChartOptions { + private generateChart(languages: Language[], windowWidth: number): ChartOptions { + const responsiveWindowWidth = windowWidth >= 530 ? + 300 : (windowWidth*.8 - 80); + return { series: languages.map(value => value.percentage), colors: languages.map(value => value.color), @@ -73,10 +91,10 @@ export class ProjectCardComponent implements OnInit { labels: languages.map(value => value.name), responsive: [ { - breakpoint: 480, + breakpoint: 530, options: { chart: { - width: 300 + width: responsiveWindowWidth }, legend: { position: "bottom" @@ -87,7 +105,7 @@ export class ProjectCardComponent implements OnInit { plotOptions: { pie: { expandOnClick: true, - + } }, dataLabels: { From 04ab3446df9e4319ef7f5904a0c4a08dc4c08963 Mon Sep 17 00:00:00 2001 From: Vitor Hideyoshi Nakazone Batista Date: Fri, 29 Dec 2023 01:50:04 -0300 Subject: [PATCH 07/12] Implements LocalStorage to Limit GithubAPI Calls --- .../shared/github-service/github.service.ts | 56 ++++++++++++++++++- 1 file changed, 54 insertions(+), 2 deletions(-) diff --git a/src/app/shared/github-service/github.service.ts b/src/app/shared/github-service/github.service.ts index 568cffa..90ba7d7 100644 --- a/src/app/shared/github-service/github.service.ts +++ b/src/app/shared/github-service/github.service.ts @@ -4,7 +4,7 @@ import {HttpClient} from "@angular/common/http"; import { map, mergeMap, Observable, - pipe, switchMap, take + pipe, switchMap, take, tap } from 'rxjs'; import { environment } from 'src/environments/environment'; @@ -28,6 +28,57 @@ export class GithubService { } getProjects(): Observable { + if (this.isLocalStorageValid()) { + console.log('Fetching projects from local storage') + return this.getProjectsFromLocalStorage(); + } + + console.log('Fetching projects from Github API') + return this.getProjectsFromGithub() + } + + private isLocalStorageValid(): boolean { + const projects = localStorage.getItem('github-projects'); + let status = !!projects + + if (!status) { + return false; + } + + const timestamp = localStorage.getItem('github-projects-timestamp'); + if (timestamp) { + const diff = new Date().getTime() - parseInt(timestamp); + status = diff < 86400000; + } else { + status = false; + } + + return status; + } + + private saveProjectsToLocalStorage(project: Project) { + const p = localStorage.getItem('github-projects'); + if (p) { + const projects = JSON.parse(p); + projects.push(project); + localStorage.setItem('github-projects', JSON.stringify(projects)); + } else { + localStorage.setItem('github-projects', JSON.stringify([project])); + } + + localStorage.setItem('github-projects-timestamp', new Date().getTime().toString()); + } + + private getProjectsFromLocalStorage(): Observable { + const projects = localStorage.getItem('github-projects') || '[]'; + return new Observable((observer) => { + JSON.parse(projects).forEach((project: Project) => { + observer.next(project); + }); + }); + } + + private getProjectsFromGithub(): Observable { return this.http.get(this.apiReposString()).pipe( map((projects: any) => { return projects.map((project: any) => { @@ -54,7 +105,8 @@ export class GithubService { }); }); }); - }) + }), + tap((project: Project) => this.saveProjectsToLocalStorage(project)) ) } From 139b20984c248b2db318f297de8fb06f5f461abc Mon Sep 17 00:00:00 2001 From: Vitor Hideyoshi Nakazone Batista Date: Fri, 29 Dec 2023 03:22:00 -0300 Subject: [PATCH 08/12] Adds Github Actions to Clean Vercel Deployments --- .github/workflows/vercel-cleanup-pr.yml | 27 +++++++++++++++ .../vercel-cleanup-previous-preview.yml | 33 +++++++++++++++++++ .gitignore | 2 ++ 3 files changed, 62 insertions(+) create mode 100644 .github/workflows/vercel-cleanup-pr.yml create mode 100644 .github/workflows/vercel-cleanup-previous-preview.yml diff --git a/.github/workflows/vercel-cleanup-pr.yml b/.github/workflows/vercel-cleanup-pr.yml new file mode 100644 index 0000000..2138d0c --- /dev/null +++ b/.github/workflows/vercel-cleanup-pr.yml @@ -0,0 +1,27 @@ +name: vercel-cleanup-pr + +on: + pull_request: + types: [closed] + +env: + VERCEL_CLI_TOKEN: ${{ secrets.VERCEL_CLI_TOKEN }} + VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }} + GITHUB_PR_ID: ${{github.event.pull_request.number}} + +jobs: + cleanup: + runs-on: ubuntu-latest + steps: + - name: Cleanup Vercel Deployments + run: | + closed_deployments=$(curl "https://api.vercel.com/v6/deployments?projectId=$VERCEL_PROJECT_ID" \ + -H "Accept: application/json" \ + -H "Authorization: Bearer ${VERCEL_CLI_TOKEN}" | jq -r ".deployments[] | select(.meta.githubPrId == \"${GITHUB_PR_ID}\") | .uid") + for deployment in $closed_deployments; do + echo "Deleting Deployment: $deployment" + curl "https://api.vercel.com/v6/now/deployments/$deployment" \ + -X DELETE \ + -H "Authorization: Bearer ${VERCEL_CLI_TOKEN}" + done + diff --git a/.github/workflows/vercel-cleanup-previous-preview.yml b/.github/workflows/vercel-cleanup-previous-preview.yml new file mode 100644 index 0000000..1df8114 --- /dev/null +++ b/.github/workflows/vercel-cleanup-previous-preview.yml @@ -0,0 +1,33 @@ +name: vercel-cleanup-preview + +on: + push: + branches: + - '*' + - '!main' + - '!devel' + +env: + VERCEL_CLI_TOKEN: ${{ secrets.VERCEL_CLI_TOKEN }} + VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }} + GIT_PREVIOS_COMMIT: ${{github.event.before}} + + +jobs: + cleanup: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Cleanup Vercel Deployments + run: | + + invalid_deployments=$(curl "https://api.vercel.com/v6/deployments?projectId=$VERCEL_PROJECT_ID" \ + -H "Accept: application/json" \ + -H "Authorization: Bearer ${VERCEL_CLI_TOKEN}" | jq -r ".deployments[] | select(.meta.githubCommitSha == \"${GIT_PREVIOS_COMMIT}\") | .uid") + + for deployment in $invalid_deployments; do + echo "Deleting Deployment: $deployment" + curl "https://api.vercel.com/v6/now/deployments/$deployment" \ + -X DELETE \ + -H "Authorization: Bearer ${VERCEL_CLI_TOKEN}" + done diff --git a/.gitignore b/.gitignore index 32953f9..d04aabd 100644 --- a/.gitignore +++ b/.gitignore @@ -46,3 +46,5 @@ Thumbs.db src/assets/env.js .env + +.secret From c1a10e63ae15f1679c68362c3d3578c126ef95b4 Mon Sep 17 00:00:00 2001 From: Vitor Hideyoshi Nakazone Batista Date: Fri, 29 Dec 2023 03:41:28 -0300 Subject: [PATCH 09/12] Empty Commit From 24947365a9f7d7b589faea2e618985f0e9d61a92 Mon Sep 17 00:00:00 2001 From: Vitor Hideyoshi Nakazone Batista Date: Fri, 29 Dec 2023 03:50:01 -0300 Subject: [PATCH 10/12] Fixes PR Cleanup --- .github/workflows/vercel-cleanup-pr.yml | 10 +++++----- .github/workflows/vercel-cleanup-previous-preview.yml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/vercel-cleanup-pr.yml b/.github/workflows/vercel-cleanup-pr.yml index 2138d0c..173a9a9 100644 --- a/.github/workflows/vercel-cleanup-pr.yml +++ b/.github/workflows/vercel-cleanup-pr.yml @@ -2,12 +2,11 @@ name: vercel-cleanup-pr on: pull_request: - types: [closed] env: VERCEL_CLI_TOKEN: ${{ secrets.VERCEL_CLI_TOKEN }} VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }} - GITHUB_PR_ID: ${{github.event.pull_request.number}} + GITHUB_PR_ID: ${{ github.event.number }} jobs: cleanup: @@ -18,10 +17,11 @@ jobs: closed_deployments=$(curl "https://api.vercel.com/v6/deployments?projectId=$VERCEL_PROJECT_ID" \ -H "Accept: application/json" \ -H "Authorization: Bearer ${VERCEL_CLI_TOKEN}" | jq -r ".deployments[] | select(.meta.githubPrId == \"${GITHUB_PR_ID}\") | .uid") + echo "PR: $GITHUB_PR_ID" for deployment in $closed_deployments; do echo "Deleting Deployment: $deployment" - curl "https://api.vercel.com/v6/now/deployments/$deployment" \ - -X DELETE \ - -H "Authorization: Bearer ${VERCEL_CLI_TOKEN}" + # curl "https://api.vercel.com/v6/now/deployments/$deployment" \ + # -X DELETE \ + # -H "Authorization: Bearer ${VERCEL_CLI_TOKEN}" done diff --git a/.github/workflows/vercel-cleanup-previous-preview.yml b/.github/workflows/vercel-cleanup-previous-preview.yml index 1df8114..0906850 100644 --- a/.github/workflows/vercel-cleanup-previous-preview.yml +++ b/.github/workflows/vercel-cleanup-previous-preview.yml @@ -10,7 +10,7 @@ on: env: VERCEL_CLI_TOKEN: ${{ secrets.VERCEL_CLI_TOKEN }} VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }} - GIT_PREVIOS_COMMIT: ${{github.event.before}} + GIT_PREVIOS_COMMIT: ${{ github.event.before }} jobs: From a08bd120b76d153d9555aa799000190e7d336642 Mon Sep 17 00:00:00 2001 From: Vitor Hideyoshi Nakazone Batista Date: Fri, 29 Dec 2023 03:51:38 -0300 Subject: [PATCH 11/12] Final Adjustment --- .github/workflows/vercel-cleanup-pr.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/vercel-cleanup-pr.yml b/.github/workflows/vercel-cleanup-pr.yml index 173a9a9..082202f 100644 --- a/.github/workflows/vercel-cleanup-pr.yml +++ b/.github/workflows/vercel-cleanup-pr.yml @@ -2,6 +2,7 @@ name: vercel-cleanup-pr on: pull_request: + types: [closed] env: VERCEL_CLI_TOKEN: ${{ secrets.VERCEL_CLI_TOKEN }} @@ -17,11 +18,10 @@ jobs: closed_deployments=$(curl "https://api.vercel.com/v6/deployments?projectId=$VERCEL_PROJECT_ID" \ -H "Accept: application/json" \ -H "Authorization: Bearer ${VERCEL_CLI_TOKEN}" | jq -r ".deployments[] | select(.meta.githubPrId == \"${GITHUB_PR_ID}\") | .uid") - echo "PR: $GITHUB_PR_ID" for deployment in $closed_deployments; do echo "Deleting Deployment: $deployment" - # curl "https://api.vercel.com/v6/now/deployments/$deployment" \ - # -X DELETE \ - # -H "Authorization: Bearer ${VERCEL_CLI_TOKEN}" + curl "https://api.vercel.com/v6/now/deployments/$deployment" \ + -X DELETE \ + -H "Authorization: Bearer ${VERCEL_CLI_TOKEN}" done From c84557611c418c814180a157d960ccee81555bb0 Mon Sep 17 00:00:00 2001 From: Vitor Hideyoshi Nakazone Batista Date: Fri, 29 Dec 2023 04:48:18 -0300 Subject: [PATCH 12/12] Implements Lazy Loading --- src/app/app-router.module.ts | 7 +++---- src/app/app.component.ts | 2 +- src/app/app.module.ts | 4 ---- .../header-dropdown.component.ts | 16 +++++++------- .../callback/callback.component.ts | 20 +++++++++--------- .../header-popup/login/login.component.ts | 8 +++---- .../my-profile/my-profile.component.ts | 10 ++++----- .../profile-picture-picker.component.ts | 4 ++-- .../header-popup/signup/signup.component.ts | 8 +++---- .../nav-slider/nav-slider.component.ts | 6 +++--- .../user-slider/user-slider.component.ts | 10 ++++----- src/app/header/header.component.ts | 2 +- src/app/home/home-router.module.ts | 18 ++++++++++++++++ src/app/home/home.module.ts | 4 +++- .../project-card.component.spec.ts | 21 ------------------- .../project-card/project-card.component.ts | 4 +--- src/app/projects/projects-router.module.ts | 18 ++++++++++++++++ src/app/projects/projects.component.spec.ts | 21 ------------------- src/app/projects/projects.component.ts | 2 +- src/app/projects/projects.module.ts | 4 +++- .../github-service/github.service.spec.ts | 16 -------------- .../shared/{auth => service}/auth.service.ts | 0 .../github.service.ts | 0 23 files changed, 90 insertions(+), 115 deletions(-) create mode 100644 src/app/home/home-router.module.ts delete mode 100644 src/app/projects/project-card/project-card.component.spec.ts create mode 100644 src/app/projects/projects-router.module.ts delete mode 100644 src/app/projects/projects.component.spec.ts delete mode 100644 src/app/shared/github-service/github.service.spec.ts rename src/app/shared/{auth => service}/auth.service.ts (100%) rename src/app/shared/{github-service => service}/github.service.ts (100%) diff --git a/src/app/app-router.module.ts b/src/app/app-router.module.ts index c05a30d..1f099fc 100644 --- a/src/app/app-router.module.ts +++ b/src/app/app-router.module.ts @@ -1,9 +1,8 @@ import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { RouterModule, Routes } from '@angular/router'; -import { HomeComponent } from './home/home.component'; import { CallbackComponent } from './header/header-popup/callback/callback.component'; -import {ProjectsComponent} from "./projects/projects.component"; + const routes: Routes = [ { @@ -13,11 +12,11 @@ const routes: Routes = [ }, { path: 'home', - component: HomeComponent, + loadChildren: () => import('./home/home.module').then(mod => mod.HomeModule), }, { path: 'projects', - component: ProjectsComponent, + loadChildren: () => import('./projects/projects.module').then(mod => mod.ProjectsModule), }, { path: 'callback', diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 2b4186e..66f2d6e 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -1,5 +1,5 @@ import { Component, OnDestroy, OnInit } from '@angular/core'; -import { AuthService } from './shared/auth/auth.service'; +import { AuthService } from './shared/service/auth.service'; import { UpdateService } from './shared/service-worker/update.service'; import { NgcCookieConsentService, diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 98c88c1..3c70d55 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -10,16 +10,12 @@ import { AppServiceWorkerModule } from './app-service-worker.module'; import { ServiceWorkerModule } from '@angular/service-worker'; import { environment } from '../environments/environment'; import { FooterComponent } from './footer/footer.component'; -import {HomeModule} from "./home/home.module"; -import {ProjectsModule} from "./projects/projects.module"; @NgModule({ declarations: [AppComponent, FooterComponent], imports: [ BrowserModule, HeaderModule, - HomeModule, - ProjectsModule, AppRouterModule, AppServiceWorkerModule, SharedModule, diff --git a/src/app/header/header-dropdown/header-dropdown.component.ts b/src/app/header/header-dropdown/header-dropdown.component.ts index 2812b9b..55aac63 100644 --- a/src/app/header/header-dropdown/header-dropdown.component.ts +++ b/src/app/header/header-dropdown/header-dropdown.component.ts @@ -22,7 +22,7 @@ import { faUser, } from '@fortawesome/free-solid-svg-icons'; import { Subscription } from 'rxjs'; -import { AuthService } from 'src/app/shared/auth/auth.service'; +import { AuthService } from 'src/app/shared/service/auth.service'; import { User } from '../../shared/model/user/user.model'; import UserChecker from '../../shared/model/user/user.checker'; import { HelpComponent } from '../header-popup/help/help.component'; @@ -96,25 +96,25 @@ export class HeaderDropdownComponent implements OnInit, OnDestroy { private userSubscription!: Subscription; @Input() - state: boolean = false; + state: boolean = false; @Input() - ignoreClickOutside!: HTMLDivElement[]; + ignoreClickOutside!: HTMLDivElement[]; @Output() - clickOutside = new EventEmitter(); + clickOutside = new EventEmitter(); @Output() - loginPopupState: EventEmitter = new EventEmitter(); + loginPopupState: EventEmitter = new EventEmitter(); @Output() - signupPopupState: EventEmitter = new EventEmitter(); + signupPopupState: EventEmitter = new EventEmitter(); @Output() - helpPopupState: EventEmitter = new EventEmitter(); + helpPopupState: EventEmitter = new EventEmitter(); @Output() - myProfilePopupState: EventEmitter = new EventEmitter(); + myProfilePopupState: EventEmitter = new EventEmitter(); constructor( private viewContainerRef: ViewContainerRef, diff --git a/src/app/header/header-popup/callback/callback.component.ts b/src/app/header/header-popup/callback/callback.component.ts index 18bc37f..3a81d79 100644 --- a/src/app/header/header-popup/callback/callback.component.ts +++ b/src/app/header/header-popup/callback/callback.component.ts @@ -1,6 +1,6 @@ import { ActivatedRoute, Router } from '@angular/router'; import { Component, OnInit } from '@angular/core'; -import { AuthService } from 'src/app/shared/auth/auth.service'; +import { AuthService } from 'src/app/shared/service/auth.service'; @Component({ selector: 'app-callback', @@ -19,15 +19,15 @@ export class CallbackComponent implements OnInit { let auth: 'google' | 'github' = p['auth']; switch (auth) { - case 'github': - this.authService.loginGithubUser(p); - break; - case 'google': - this.authService.loginGoogleUser(p); - break; - default: - console.log(`Unimplemented auth: ${auth}`); - break; + case 'github': + this.authService.loginGithubUser(p); + break; + case 'google': + this.authService.loginGoogleUser(p); + break; + default: + console.log(`Unimplemented auth: ${auth}`); + break; } this.router.navigate(['/home']); diff --git a/src/app/header/header-popup/login/login.component.ts b/src/app/header/header-popup/login/login.component.ts index f96873e..a6a1baa 100644 --- a/src/app/header/header-popup/login/login.component.ts +++ b/src/app/header/header-popup/login/login.component.ts @@ -13,7 +13,7 @@ import { MatIconRegistry } from '@angular/material/icon'; import { DomSanitizer } from '@angular/platform-browser'; import { faLock, faUser } from '@fortawesome/free-solid-svg-icons'; import { Subscription } from 'rxjs'; -import { AuthService } from 'src/app/shared/auth/auth.service'; +import { AuthService } from 'src/app/shared/service/auth.service'; import { HttpError } from 'src/app/shared/model/httpError/httpError.model'; import HttpErrorChecker from 'src/app/shared/model/httpError/httpErrorChecker'; import UserChecker from 'src/app/shared/model/user/user.checker'; @@ -99,13 +99,13 @@ const GITHUB_LOGO_SVG = 'assets/img/providers/github.svg'; }) export class LoginComponent implements OnInit, AfterViewInit, OnDestroy { @Input() - state: boolean = false; + state: boolean = false; @Input() - ignoreClickOutside!: HTMLDivElement[]; + ignoreClickOutside!: HTMLDivElement[]; @Output() - stateChange = new EventEmitter(); + stateChange = new EventEmitter(); loginForm!: FormGroup; diff --git a/src/app/header/header-popup/my-profile/my-profile.component.ts b/src/app/header/header-popup/my-profile/my-profile.component.ts index ee46287..fe3bdf0 100644 --- a/src/app/header/header-popup/my-profile/my-profile.component.ts +++ b/src/app/header/header-popup/my-profile/my-profile.component.ts @@ -6,7 +6,7 @@ import { OnInit, Output, } from '@angular/core'; -import { AuthService } from '../../../shared/auth/auth.service'; +import { AuthService } from '../../../shared/service/auth.service'; import { User } from '../../../shared/model/user/user.model'; import { animate, @@ -88,16 +88,16 @@ import { faFileUpload } from '@fortawesome/free-solid-svg-icons'; }) export class MyProfileComponent implements OnInit { @Input() - state: boolean = false; + state: boolean = false; @Input() - user!: User | null; + user!: User | null; @Input() - ignoreClickOutside!: HTMLDivElement[]; + ignoreClickOutside!: HTMLDivElement[]; @Output() - stateChange = new EventEmitter(); + stateChange = new EventEmitter(); alterForm!: FormGroup; diff --git a/src/app/header/header-popup/my-profile/profile-picture-picker/profile-picture-picker.component.ts b/src/app/header/header-popup/my-profile/profile-picture-picker/profile-picture-picker.component.ts index e211ac5..62e89e2 100644 --- a/src/app/header/header-popup/my-profile/profile-picture-picker/profile-picture-picker.component.ts +++ b/src/app/header/header-popup/my-profile/profile-picture-picker/profile-picture-picker.component.ts @@ -1,5 +1,5 @@ import { Component, EventEmitter, Output } from '@angular/core'; -import { AuthService } from '../../../../shared/auth/auth.service'; +import { AuthService } from '../../../../shared/service/auth.service'; @Component({ selector: 'app-profile-picture-picker', @@ -8,7 +8,7 @@ import { AuthService } from '../../../../shared/auth/auth.service'; }) export class ProfilePicturePickerComponent { @Output() - imageSent = new EventEmitter(); + imageSent = new EventEmitter(); private profilePicture!: File; diff --git a/src/app/header/header-popup/signup/signup.component.ts b/src/app/header/header-popup/signup/signup.component.ts index 6c041b3..3430aca 100644 --- a/src/app/header/header-popup/signup/signup.component.ts +++ b/src/app/header/header-popup/signup/signup.component.ts @@ -9,7 +9,7 @@ import { faUser, } from '@fortawesome/free-solid-svg-icons'; import { Subscription } from 'rxjs'; -import { AuthService } from 'src/app/shared/auth/auth.service'; +import { AuthService } from 'src/app/shared/service/auth.service'; import { HttpError } from 'src/app/shared/model/httpError/httpError.model'; import HttpErrorChecker from 'src/app/shared/model/httpError/httpErrorChecker'; import UserChecker from 'src/app/shared/model/user/user.checker'; @@ -90,13 +90,13 @@ const GITHUB_LOGO_SVG = 'assets/img/providers/github.svg'; }) export class SignupComponent implements OnInit { @Input() - state: boolean = false; + state: boolean = false; @Input() - ignoreClickOutside!: HTMLDivElement[]; + ignoreClickOutside!: HTMLDivElement[]; @Output() - stateChange = new EventEmitter(); + stateChange = new EventEmitter(); signupForm!: FormGroup; diff --git a/src/app/header/header-slider/nav-slider/nav-slider.component.ts b/src/app/header/header-slider/nav-slider/nav-slider.component.ts index b2b65c9..3154012 100644 --- a/src/app/header/header-slider/nav-slider/nav-slider.component.ts +++ b/src/app/header/header-slider/nav-slider/nav-slider.component.ts @@ -10,7 +10,7 @@ import { faUser } from '@fortawesome/free-solid-svg-icons'; import { SliderItemComponent } from 'src/app/shared/components/slider-item/slider-item.component'; import UserChecker from '../../../shared/model/user/user.checker'; import { User } from '../../../shared/model/user/user.model'; -import { AuthService } from '../../../shared/auth/auth.service'; +import { AuthService } from '../../../shared/service/auth.service'; import { Subscription } from 'rxjs'; @Component({ @@ -25,14 +25,14 @@ export class NavSliderComponent userIcon = faUser; @Input() - pages!: { name: string; route: string }[]; + pages!: { name: string; route: string }[]; loggedUser!: User | null; private userSubscription!: Subscription; @Output() - profileButtonClicked = new EventEmitter(); + profileButtonClicked = new EventEmitter(); constructor(private authService: AuthService) { super(); diff --git a/src/app/header/header-slider/user-slider/user-slider.component.ts b/src/app/header/header-slider/user-slider/user-slider.component.ts index f97c412..9da3b36 100644 --- a/src/app/header/header-slider/user-slider/user-slider.component.ts +++ b/src/app/header/header-slider/user-slider/user-slider.component.ts @@ -1,6 +1,6 @@ import { Component, EventEmitter, OnInit, Output } from '@angular/core'; import { Subscription } from 'rxjs'; -import { AuthService } from 'src/app/shared/auth/auth.service'; +import { AuthService } from 'src/app/shared/service/auth.service'; import { SliderItemComponent } from 'src/app/shared/components/slider-item/slider-item.component'; import UserChecker from 'src/app/shared/model/user/user.checker'; import { User } from 'src/app/shared/model/user/user.model'; @@ -52,16 +52,16 @@ export class UserSliderComponent extends SliderItemComponent implements OnInit { authSubscription!: Subscription; @Output() - loginPopupState: EventEmitter = new EventEmitter(); + loginPopupState: EventEmitter = new EventEmitter(); @Output() - signupPopupState: EventEmitter = new EventEmitter(); + signupPopupState: EventEmitter = new EventEmitter(); @Output() - helpPopupState: EventEmitter = new EventEmitter(); + helpPopupState: EventEmitter = new EventEmitter(); @Output() - myProfilePopupState: EventEmitter = new EventEmitter(); + myProfilePopupState: EventEmitter = new EventEmitter(); constructor(private authService: AuthService) { super(); diff --git a/src/app/header/header.component.ts b/src/app/header/header.component.ts index c13684f..e9f0b64 100644 --- a/src/app/header/header.component.ts +++ b/src/app/header/header.component.ts @@ -10,7 +10,7 @@ import { import { faUser } from '@fortawesome/free-solid-svg-icons'; import { LoginComponent } from './header-popup/login/login.component'; import { SignupComponent } from './header-popup/signup/signup.component'; -import { AuthService } from '../shared/auth/auth.service'; +import { AuthService } from '../shared/service/auth.service'; import UserChecker from '../shared/model/user/user.checker'; import { User } from '../shared/model/user/user.model'; import { Subscription } from 'rxjs'; diff --git a/src/app/home/home-router.module.ts b/src/app/home/home-router.module.ts new file mode 100644 index 0000000..7cfc348 --- /dev/null +++ b/src/app/home/home-router.module.ts @@ -0,0 +1,18 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { RouterModule, Routes } from '@angular/router'; +import {HomeComponent} from "./home.component"; + +const routes: Routes = [ + { + path: '', + component: HomeComponent, + }, +]; + +@NgModule({ + declarations: [], + imports: [CommonModule, RouterModule.forChild(routes)], + exports: [RouterModule], +}) +export class HomeRouterModule {} diff --git a/src/app/home/home.module.ts b/src/app/home/home.module.ts index 2bfa1be..96d951b 100644 --- a/src/app/home/home.module.ts +++ b/src/app/home/home.module.ts @@ -4,6 +4,7 @@ import {HomeComponent} from "./home.component"; import {StackSliderComponent} from "./stack-slider/stack-slider.component"; import {StackCardComponent} from "./stack-slider/stack-card/stack-card.component"; import {NgxGlideComponent} from "ngx-glide"; +import {HomeRouterModule} from "./home-router.module"; @@ -16,7 +17,8 @@ import {NgxGlideComponent} from "ngx-glide"; imports: [ CommonModule, NgxGlideComponent, - NgOptimizedImage + NgOptimizedImage, + HomeRouterModule ] }) export class HomeModule { } diff --git a/src/app/projects/project-card/project-card.component.spec.ts b/src/app/projects/project-card/project-card.component.spec.ts deleted file mode 100644 index 74de6b1..0000000 --- a/src/app/projects/project-card/project-card.component.spec.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; - -import { ProjectCardComponent } from './project-card.component'; - -describe('ProjectCardComponent', () => { - let component: ProjectCardComponent; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - declarations: [ProjectCardComponent] - }); - fixture = TestBed.createComponent(ProjectCardComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/src/app/projects/project-card/project-card.component.ts b/src/app/projects/project-card/project-card.component.ts index b92f5ce..45b5ad3 100644 --- a/src/app/projects/project-card/project-card.component.ts +++ b/src/app/projects/project-card/project-card.component.ts @@ -1,9 +1,7 @@ import {Component, HostListener, Input, OnInit, ViewChild} from '@angular/core'; -import { faCodeFork, faEye, faStar } from '@fortawesome/free-solid-svg-icons'; +import {faCodeFork, faEye, faScaleBalanced, faStar} from '@fortawesome/free-solid-svg-icons'; import {Language, Project} from "../../shared/model/project/project.model"; -import {faScaleBalanced} from "@fortawesome/free-solid-svg-icons/faScaleBalanced"; import { - ApexAnnotations, ApexChart, ApexDataLabels, ApexNonAxisChartSeries, ApexPlotOptions, diff --git a/src/app/projects/projects-router.module.ts b/src/app/projects/projects-router.module.ts new file mode 100644 index 0000000..6f01310 --- /dev/null +++ b/src/app/projects/projects-router.module.ts @@ -0,0 +1,18 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { RouterModule, Routes } from '@angular/router'; +import {ProjectsComponent} from "./projects.component"; + +const routes: Routes = [ + { + path: '', + component: ProjectsComponent + }, +]; + +@NgModule({ + declarations: [], + imports: [CommonModule, RouterModule.forChild(routes)], + exports: [RouterModule], +}) +export class ProjectsRouterModule {} diff --git a/src/app/projects/projects.component.spec.ts b/src/app/projects/projects.component.spec.ts deleted file mode 100644 index d396b2d..0000000 --- a/src/app/projects/projects.component.spec.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; - -import { ProjectsComponent } from './projects.component'; - -describe('ProjectsComponent', () => { - let component: ProjectsComponent; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - declarations: [ProjectsComponent] - }); - fixture = TestBed.createComponent(ProjectsComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/src/app/projects/projects.component.ts b/src/app/projects/projects.component.ts index 23da837..2412c35 100644 --- a/src/app/projects/projects.component.ts +++ b/src/app/projects/projects.component.ts @@ -1,5 +1,5 @@ import {Component, OnInit} from '@angular/core'; -import {GithubService} from "../shared/github-service/github.service"; +import {GithubService} from "../shared/service/github.service"; import {Project} from "../shared/model/project/project.model"; @Component({ diff --git a/src/app/projects/projects.module.ts b/src/app/projects/projects.module.ts index 25c2b8f..15b5a90 100644 --- a/src/app/projects/projects.module.ts +++ b/src/app/projects/projects.module.ts @@ -5,6 +5,7 @@ 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"; +import {ProjectsRouterModule} from "./projects-router.module"; @NgModule({ declarations: [ @@ -16,7 +17,8 @@ import {NgApexchartsModule} from "ng-apexcharts"; NgOptimizedImage, MatIconModule, FontAwesomeModule, - NgApexchartsModule + NgApexchartsModule, + ProjectsRouterModule ], exports: [] }) diff --git a/src/app/shared/github-service/github.service.spec.ts b/src/app/shared/github-service/github.service.spec.ts deleted file mode 100644 index bcef5d4..0000000 --- a/src/app/shared/github-service/github.service.spec.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { TestBed } from '@angular/core/testing'; - -import { GithubServiceService } from './github.service'; - -describe('GithubServiceService', () => { - let service: GithubServiceService; - - beforeEach(() => { - TestBed.configureTestingModule({}); - service = TestBed.inject(GithubServiceService); - }); - - it('should be created', () => { - expect(service).toBeTruthy(); - }); -}); diff --git a/src/app/shared/auth/auth.service.ts b/src/app/shared/service/auth.service.ts similarity index 100% rename from src/app/shared/auth/auth.service.ts rename to src/app/shared/service/auth.service.ts diff --git a/src/app/shared/github-service/github.service.ts b/src/app/shared/service/github.service.ts similarity index 100% rename from src/app/shared/github-service/github.service.ts rename to src/app/shared/service/github.service.ts