Permalink
Browse files

Add loading screen

  • Loading branch information...
nezhar committed Nov 4, 2018
1 parent 3c5f4bb commit 3f4765f09aacc79669b117870cafbcc968e346a1
@@ -5,3 +5,5 @@
<ng-template #snippetsApp style="min-width: 1024px;">
<app-base></app-base>
</ng-template>
<app-loading-screen></app-loading-screen>
@@ -54,6 +54,8 @@ import { TeamMemberDeleteModalComponent } from './components/team-member-delete-
import { LabelDeleteModalComponent } from './components/label-delete-modal/label-delete-modal.component';
import { BaseComponent } from './layout/base/base.component';
import { BootstrapSwitchComponent } from './components/bootstrap-switch/bootstrap-switch.component';
import { LoadingScreenComponent } from './components/loading-screen/loading-screen.component';
import { LoadingScreenInterceptor } from "./helpers/loading.interceptor";
library.add(
fas.faCoffee,
@@ -102,6 +104,7 @@ library.add(
LabelDeleteModalComponent,
BaseComponent,
BootstrapSwitchComponent,
LoadingScreenComponent,
],
entryComponents: [
SnippetModalComponent,
@@ -136,6 +139,11 @@ library.add(
provide: HTTP_INTERCEPTORS,
useClass: JwtInterceptor,
multi: true
},
{
provide: HTTP_INTERCEPTORS,
useClass: LoadingScreenInterceptor,
multi: true
}
],
bootstrap: [AppComponent]
@@ -0,0 +1,22 @@
<div class="loading-screen-wrapper" *ngIf="loading">
<div class="loading-screen-icon">
<div class="blobs">
<div class="blob-center"></div>
<div class="blob"></div>
<div class="blob"></div>
<div class="blob"></div>
<div class="blob"></div>
<div class="blob"></div>
<div class="blob"></div>
</div>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<defs>
<filter id="goo">
<feGaussianBlur in="SourceGraphic" stdDeviation="10" result="blur"/>
<feColorMatrix in="blur" mode="matrix" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 18 -7" result="goo"/>
<feBlend in="SourceGraphic" in2="goo"/>
</filter>
</defs>
</svg>
</div>
</div>
@@ -0,0 +1,156 @@
.loading-screen-wrapper {
z-index: 100000;
position: absolute;
background-color: rgba(255, 255, 255, 0.6);
width: 100%;
height: 100%;
display: block;
}
.loading-screen-icon {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
/**
Loader: https://codepen.io/eliortabeka/pen/EXJyPP
*/
svg {
display: none;
}
$bolb-color: #475158;
// Loader
.blobs {
filter: url(#goo);
width: 300px;
height: 300px;
position: relative;
overflow: hidden;
border-radius: 70px;
transform-style: preserve-3d;
// Blob center item
.blob-center {
transform-style: preserve-3d;
position: absolute;
background: $bolb-color;
top: 50%;
left: 50%;
width: 30px;
height: 30px;
transform-origin: left top;
transform: scale(.9) translate(-50%, -50%);
animation: blob-grow
linear
3.4s
infinite;
border-radius: 50%;
box-shadow: 0 -10px 40px -5px $bolb-color;
}
}
// Blob item
.blob {
position: absolute;
background: $bolb-color;
top: 50%;
left: 50%;
width: 30px;
height: 30px;
border-radius: 50%;
animation: blobs
ease-out
3.4s
infinite;
transform: scale(.9) translate(-50%, -50%);
transform-origin: center top;
opacity: 0;
// Set animation delay for each of type
@for $i from 1 to 6 {
&:nth-child(#{$i}) {
animation-delay: $i * 0.2 + s;
}
}
}
// Keyframes variables
$left: calc(-330px - 50%);
$right: calc(330px - 50%);
// Keyframes
@keyframes blobs {
0% {
opacity: 0;
transform: scale(0) translate($left, -50%);
}
1% {
opacity: 1;
}
35%,65% {
opacity: 1;
transform: scale(.9) translate(-50%, -50%);
}
99% {
opacity: 1;
}
100% {
opacity: 0;
transform: scale(0) translate($right, -50%);
}
}
@keyframes blob-grow {
0%, 39% {
transform: scale(0) translate(-50%, -50%);
}
40%, 42% {
transform: scale(1, .9) translate(-50%, -50%);
}
43%, 44% {
transform: scale(1.2, 1.1) translate(-50%, -50%);
}
45%, 46% {
transform: scale(1.3, 1.2) translate(-50%, -50%);
}
47%, 48% {
transform: scale(1.4, 1.3) translate(-50%, -50%);
}
52%{
transform: scale(1.5, 1.4) translate(-50%, -50%);
}
54% {
transform: scale(1.7, 1.6) translate(-50%, -50%);
}
58% {
transform: scale(1.8, 1.7) translate(-50%, -50%);
}
68%, 70% {
transform: scale(1.7, 1.5) translate(-50%, -50%);
}
78% {
transform: scale(1.6, 1.4) translate(-50%, -50%);
}
80%, 81% {
transform: scale(1.5, 1.4) translate(-50%, -50%);
}
82%, 83% {
transform: scale(1.4, 1.3) translate(-50%, -50%);
}
84%, 85% {
transform: scale(1.3, 1.2) translate(-50%, -50%);
}
86%, 87% {
transform: scale(1.2, 1.1) translate(-50%, -50%);
}
90%, 91% {
transform: scale(1, .9) translate(-50%, -50%);
}
92%, 100% {
transform: scale(0) translate(-50%, -50%);
}
}
@@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { LoadingScreenComponent } from './loading-screen.component';
describe('LoadingScreenComponent', () => {
let component: LoadingScreenComponent;
let fixture: ComponentFixture<LoadingScreenComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ LoadingScreenComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(LoadingScreenComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -0,0 +1,31 @@
import { Component, OnDestroy, OnInit } from '@angular/core';
import { LoadingScreenService } from "../../services/loading-screen/loading-screen.service";
import { Subscription } from "rxjs";
import { debounceTime } from "rxjs/operators";
@Component({
selector: 'app-loading-screen',
templateUrl: './loading-screen.component.html',
styleUrls: ['./loading-screen.component.scss']
})
export class LoadingScreenComponent implements OnInit, OnDestroy {
loading: boolean = false;
loadingSubscription: Subscription;
constructor(private loadingScreenService: LoadingScreenService) {
}
ngOnInit() {
this.loadingSubscription = this.loadingScreenService.loadingStatus.pipe(
debounceTime(200)
).subscribe((value) => {
this.loading = value;
});
}
ngOnDestroy() {
this.loadingSubscription.unsubscribe();
}
}
@@ -0,0 +1,51 @@
import { Injectable } from "@angular/core";
import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from "@angular/common/http";
import { Observable } from "rxjs";
import { LoadingScreenService } from "../services/loading-screen/loading-screen.service";
import { finalize } from "rxjs/operators";
@Injectable()
export class LoadingScreenInterceptor implements HttpInterceptor {
activeRequests: number = 0;
/**
* URLs for which the loading screen should not be enabled
*/
skippUrls = [
'/authrefresh',
];
constructor(private loadingScreenService: LoadingScreenService) {
}
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
let displayLoadingScreen = true;
for (const skippUrl of this.skippUrls) {
if (new RegExp(skippUrl).test(request.url)) {
displayLoadingScreen = false;
break;
}
}
if (displayLoadingScreen) {
if (this.activeRequests === 0) {
this.loadingScreenService.startLoading();
}
this.activeRequests++;
return next.handle(request).pipe(
finalize(() => {
this.activeRequests--;
if (this.activeRequests === 0) {
this.loadingScreenService.stopLoading();
}
})
)
} else {
return next.handle(request);
}
};
}
@@ -0,0 +1,12 @@
import { TestBed } from '@angular/core/testing';
import { LoadingScreenService } from './loading-screen.service';
describe('LoadingScreenService', () => {
beforeEach(() => TestBed.configureTestingModule({}));
it('should be created', () => {
const service: LoadingScreenService = TestBed.get(LoadingScreenService);
expect(service).toBeTruthy();
});
});
@@ -0,0 +1,28 @@
import { Injectable } from '@angular/core';
import { Subject } from "rxjs";
@Injectable({
providedIn: 'root'
})
export class LoadingScreenService {
private _loading: boolean = false;
loadingStatus: Subject = new Subject();
get loading():boolean {
return this._loading;
}
set loading(value) {
this._loading = value;
this.loadingStatus.next(value);
}
startLoading() {
this.loading = true;
}
stopLoading() {
this.loading = false;
}
}
@@ -15,6 +15,7 @@ import { AuthResource } from "./resources/auth.resource";
import { ActiveScopeService } from "./navigation/activeScope.service";
import { UserTeamResource } from "./resources/userteam.resource";
import { SnippetLabelResource } from "./resources/snippetlabel.resource";
import { LoadingScreenService } from "./loading-screen/loading-screen.service";
@NgModule({

0 comments on commit 3f4765f

Please sign in to comment.