diff --git a/src/app/app.component.html b/src/app/app.component.html index 319b11d..cbf22d7 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -1,7 +1,8 @@
- -
- - -
+ + +
+ + +
\ No newline at end of file diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 9f30793..9c7b79e 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -1,4 +1,5 @@ import { Component } from '@angular/core'; +import { LoaderService } from './services/loader.service'; @Component({ selector: 'app-root', @@ -6,5 +7,5 @@ import { Component } from '@angular/core'; styleUrls: ['./app.component.scss'] }) export class AppComponent { - title = 'my-portfolio'; + constructor(public loaderSvc: LoaderService) {} } diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 8270401..3784c61 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -1,6 +1,6 @@ import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; -import { HTTP_INTERCEPTORS, HttpClientModule } from '@angular/common/http'; +import { HttpClientModule } from '@angular/common/http'; import { AppComponent } from './app.component'; import { ContactSidebarComponent } from './contact-sidebar/contact-sidebar.component'; @@ -11,12 +11,13 @@ import { ProjectsComponent } from './projects/projects.component'; import { BlogComponent } from './blog/blog.component'; import { ContactComponent } from './contact/contact.component'; import { AppRoutingModule } from './app-routing.module'; -import { AuthInterceptor } from './http-interceptors/auth.interceptor'; import { httpInterceptorProviders } from './http-interceptors'; +import { SpinnerComponent } from './spinner/spinner.component'; @NgModule({ declarations: [ AppComponent, + SpinnerComponent, ContactSidebarComponent, NavbarComponent, AboutComponent, diff --git a/src/app/http-interceptors/index.ts b/src/app/http-interceptors/index.ts index b5e66cd..ababa5a 100644 --- a/src/app/http-interceptors/index.ts +++ b/src/app/http-interceptors/index.ts @@ -1,7 +1,9 @@ import { HTTP_INTERCEPTORS } from "@angular/common/http"; import { AuthInterceptor } from "./auth.interceptor"; +import { LoadingInterceptor } from "./loading.interceptor"; export const httpInterceptorProviders = [ - {provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true} + {provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true}, + {provide: HTTP_INTERCEPTORS, useClass: LoadingInterceptor, multi: true} ] \ No newline at end of file diff --git a/src/app/http-interceptors/loading.interceptor.ts b/src/app/http-interceptors/loading.interceptor.ts new file mode 100644 index 0000000..470744d --- /dev/null +++ b/src/app/http-interceptors/loading.interceptor.ts @@ -0,0 +1,27 @@ +import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from "@angular/common/http"; +import { Injectable } from "@angular/core"; +import { Observable, finalize } from "rxjs"; +import { LoaderService } from "../services/loader.service"; + +@Injectable() +export class LoadingInterceptor implements HttpInterceptor { + + private totalRequests: number = 0; + + constructor(private loadingSvc: LoaderService) { } + + intercept(req: HttpRequest, next: HttpHandler): Observable> { + this.totalRequests++; + this.loadingSvc.setLoading(true); + return next.handle(req).pipe( + finalize( + () => { + this.totalRequests--; + if (this.totalRequests == 0) { + this.loadingSvc.setLoading(false); + } + } + ) + ); + } +} \ No newline at end of file diff --git a/src/app/services/loader.service.spec.ts b/src/app/services/loader.service.spec.ts new file mode 100644 index 0000000..aef6961 --- /dev/null +++ b/src/app/services/loader.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { LoaderService } from './loader.service'; + +describe('LoaderService', () => { + let service: LoaderService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(LoaderService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/app/services/loader.service.ts b/src/app/services/loader.service.ts new file mode 100644 index 0000000..ec2d0ca --- /dev/null +++ b/src/app/services/loader.service.ts @@ -0,0 +1,16 @@ +import { Injectable } from '@angular/core'; + +@Injectable({ + providedIn: 'root' +}) +export class LoaderService { + private loading: boolean = false; + + setLoading(loading: boolean){ + this.loading = loading; + } + + getLoading(): boolean{ + return this.loading; + } +} diff --git a/src/app/spinner/spinner.component.html b/src/app/spinner/spinner.component.html new file mode 100644 index 0000000..d1bd03e --- /dev/null +++ b/src/app/spinner/spinner.component.html @@ -0,0 +1,3 @@ +
+
+
\ No newline at end of file diff --git a/src/app/spinner/spinner.component.scss b/src/app/spinner/spinner.component.scss new file mode 100644 index 0000000..c4bb107 --- /dev/null +++ b/src/app/spinner/spinner.component.scss @@ -0,0 +1,65 @@ +.cssload-container { + position: fixed; + width: 100%; + left: 0; + right: 0; + top: 0; + bottom: 0; + background-color: rgba(0, 0, 0, 0.7); + z-index: 9999; +} + +.cssload-speeding-wheel { + content: ""; + display: block; + position: absolute; + left: 48%; + top: 40%; + width: 63px; + height: 63px; + margin: 0 auto; + border: 4px solid hsl(45, 54%, 58%); + border-radius: 50%; + border-left-color: transparent; + border-right-color: transparent; + animation: cssload-spin 500ms infinite linear; + -o-animation: cssload-spin 500ms infinite linear; + -ms-animation: cssload-spin 500ms infinite linear; + -webkit-animation: cssload-spin 500ms infinite linear; + -moz-animation: cssload-spin 500ms infinite linear; +} + +@keyframes cssload-spin { + 100% { + transform: rotate(360deg); + transform: rotate(360deg); + } +} + +@-o-keyframes cssload-spin { + 100% { + -o-transform: rotate(360deg); + transform: rotate(360deg); + } +} + +@-ms-keyframes cssload-spin { + 100% { + -ms-transform: rotate(360deg); + transform: rotate(360deg); + } +} + +@-webkit-keyframes cssload-spin { + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} + +@-moz-keyframes cssload-spin { + 100% { + -moz-transform: rotate(360deg); + transform: rotate(360deg); + } +} \ No newline at end of file diff --git a/src/app/spinner/spinner.component.spec.ts b/src/app/spinner/spinner.component.spec.ts new file mode 100644 index 0000000..5e92051 --- /dev/null +++ b/src/app/spinner/spinner.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SpinnerComponent } from './spinner.component'; + +describe('SpinnerComponent', () => { + let component: SpinnerComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [SpinnerComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(SpinnerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/spinner/spinner.component.ts b/src/app/spinner/spinner.component.ts new file mode 100644 index 0000000..cfdbecf --- /dev/null +++ b/src/app/spinner/spinner.component.ts @@ -0,0 +1,14 @@ +import { Component, ViewEncapsulation } from '@angular/core'; +import { LoaderService } from '../services/loader.service'; + +@Component({ + selector: 'app-spinner', + templateUrl: './spinner.component.html', + styleUrl: './spinner.component.scss', + encapsulation: ViewEncapsulation.ShadowDom +}) +export class SpinnerComponent { + + constructor(public loader: LoaderService) { + } +}