add snackbars

This commit is contained in:
rubikscraft
2022-03-01 21:51:21 +01:00
parent 8b08ad1dbe
commit 05c0ad0e28
14 changed files with 117 additions and 34 deletions

View File

@@ -1,5 +1,7 @@
import { Component, Input } from '@angular/core'; import { Component, Input } from '@angular/core';
import { MatSnackBar } from '@angular/material/snack-bar'; import { MatSnackBar } from '@angular/material/snack-bar';
import { SnackBarType } from 'src/app/models/snack-bar-type';
import { UtilService } from 'src/app/util/util.service';
@Component({ @Component({
selector: 'copy-field', selector: 'copy-field',
@@ -11,11 +13,18 @@ export class CopyFieldComponent {
@Input() label: string = 'Loading...'; @Input() label: string = 'Loading...';
@Input() value: string = 'Loading...'; @Input() value: string = 'Loading...';
constructor(private snackBar: MatSnackBar) {} constructor(private utilService: UtilService) {}
public copy() { public copy() {
try {
navigator.clipboard.writeText(this.value); navigator.clipboard.writeText(this.value);
} catch (e) {
return this.utilService.showSnackBar(
'Copying to clipboard failed',
SnackBarType.Error
);
}
this.snackBar.open(`Copied ${this.label}!`); this.utilService.showSnackBar(`Copied ${this.label}!`, SnackBarType.Info);
} }
} }

View File

@@ -4,7 +4,7 @@ import { CopyFieldComponent } from './copy-field.component';
import { MatInputModule } from '@angular/material/input'; import { MatInputModule } from '@angular/material/input';
import { MatIconModule } from '@angular/material/icon'; import { MatIconModule } from '@angular/material/icon';
import { MatButtonModule } from '@angular/material/button'; import { MatButtonModule } from '@angular/material/button';
import { MatSnackBarModule } from '@angular/material/snack-bar'; import { UtilModule } from 'src/app/util/util.module';
@NgModule({ @NgModule({
declarations: [CopyFieldComponent], declarations: [CopyFieldComponent],
imports: [ imports: [
@@ -12,7 +12,7 @@ import { MatSnackBarModule } from '@angular/material/snack-bar';
MatInputModule, MatInputModule,
MatIconModule, MatIconModule,
MatButtonModule, MatButtonModule,
MatSnackBarModule, UtilModule,
], ],
exports: [CopyFieldComponent], exports: [CopyFieldComponent],
}) })

View File

@@ -0,0 +1,7 @@
export enum SnackBarType {
Success = 'snack-success',
Error = 'snack-error',
Warning = 'snack-warning',
Info = 'snack-info',
Default = 'snack-default',
}

View File

@@ -2,10 +2,6 @@ import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router'; import { RouterModule, Routes } from '@angular/router';
import { UploadComponent } from '../routes/upload/upload.component'; import { UploadComponent } from '../routes/upload/upload.component';
import { NgxDropzoneModule } from 'ngx-dropzone'; import { NgxDropzoneModule } from 'ngx-dropzone';
import {
MatSnackBarModule,
MAT_SNACK_BAR_DEFAULT_OPTIONS,
} from '@angular/material/snack-bar';
import { ProcessingComponent } from '../routes/processing/processing.component'; import { ProcessingComponent } from '../routes/processing/processing.component';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { ApiModule } from '../api/api.module'; import { ApiModule } from '../api/api.module';
@@ -14,6 +10,7 @@ import { PageNotFoundComponent } from '../components/pagenotfound/pagenotfound.c
import { ViewComponent } from '../routes/view/view.component'; import { ViewComponent } from '../routes/view/view.component';
import { CopyFieldModule } from '../components/copy-field/copy-field.module'; import { CopyFieldModule } from '../components/copy-field/copy-field.module';
import { MatButtonModule } from '@angular/material/button'; import { MatButtonModule } from '@angular/material/button';
import { UtilModule } from '../util/util.module';
const routes: Routes = [ const routes: Routes = [
{ path: '', component: UploadComponent }, { path: '', component: UploadComponent },
@@ -28,7 +25,7 @@ const routes: Routes = [
@NgModule({ @NgModule({
imports: [ imports: [
NgxDropzoneModule, NgxDropzoneModule,
MatSnackBarModule, UtilModule,
MatProgressSpinnerModule, MatProgressSpinnerModule,
MatButtonModule, MatButtonModule,
PageNotFoundModule, PageNotFoundModule,
@@ -37,16 +34,6 @@ const routes: Routes = [
RouterModule.forRoot(routes), RouterModule.forRoot(routes),
], ],
declarations: [UploadComponent, ProcessingComponent, ViewComponent], declarations: [UploadComponent, ProcessingComponent, ViewComponent],
providers: [
{
provide: MAT_SNACK_BAR_DEFAULT_OPTIONS,
useValue: {
duration: 2500,
horizontalPosition: 'left',
panelClass: ['mat-toolbar', 'mat-primary'],
},
},
],
exports: [RouterModule], exports: [RouterModule],
}) })
export class AppRouterModule {} export class AppRouterModule {}

View File

@@ -3,27 +3,30 @@ import { Router } from '@angular/router';
import { ProcessingViewMetadata } from 'src/app/models/processing-view-metadata'; import { ProcessingViewMetadata } from 'src/app/models/processing-view-metadata';
import { ImageService } from 'src/app/api/image.service'; import { ImageService } from 'src/app/api/image.service';
import { HasFailed } from 'picsur-shared/dist/types'; import { HasFailed } from 'picsur-shared/dist/types';
import { UtilService } from 'src/app/util/util.service';
@Component({ @Component({
templateUrl: './processing.component.html', templateUrl: './processing.component.html',
styleUrls: ['./processing.component.scss'], styleUrls: ['./processing.component.scss'],
}) })
export class ProcessingComponent implements OnInit { export class ProcessingComponent implements OnInit {
constructor(private router: Router, private imageService: ImageService) {} constructor(
private router: Router,
private imageService: ImageService,
private utilService: UtilService
) {}
async ngOnInit() { async ngOnInit() {
const state = history.state as ProcessingViewMetadata; const state = history.state as ProcessingViewMetadata;
if (!state) { if (!state) {
this.router.navigate(['/'], { replaceUrl: true }); return this.utilService.quitError('Error');
return;
} }
history.replaceState(null, ''); history.replaceState(null, '');
const hash = await this.imageService.UploadImage(state.imageFile); const hash = await this.imageService.UploadImage(state.imageFile);
if (HasFailed(hash)) { if (HasFailed(hash)) {
this.router.navigate(['/'], { replaceUrl: true }); return this.utilService.quitError(hash.getReason());
return;
} }
this.router.navigate([`/view/`, hash], { replaceUrl: true }); this.router.navigate([`/view/`, hash], { replaceUrl: true });

View File

@@ -2,6 +2,7 @@ import { Component, OnInit } from '@angular/core';
import { MatSnackBar } from '@angular/material/snack-bar'; import { MatSnackBar } from '@angular/material/snack-bar';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { NgxDropzoneChangeEvent } from 'ngx-dropzone'; import { NgxDropzoneChangeEvent } from 'ngx-dropzone';
import { UtilService } from 'src/app/util/util.service';
import { ProcessingViewMetadata } from '../../models/processing-view-metadata'; import { ProcessingViewMetadata } from '../../models/processing-view-metadata';
@Component({ @Component({
@@ -9,10 +10,10 @@ import { ProcessingViewMetadata } from '../../models/processing-view-metadata';
styleUrls: ['./upload.component.scss'], styleUrls: ['./upload.component.scss'],
}) })
export class UploadComponent { export class UploadComponent {
constructor(private snackBar: MatSnackBar, private router: Router) {} constructor(private utilService: UtilService, private router: Router) {}
onSelect(event: NgxDropzoneChangeEvent) { onSelect(event: NgxDropzoneChangeEvent) {
if (event.addedFiles.length > 1) { if (event.addedFiles.length > 1) {
this.snackBar.open( this.utilService.showSnackBar(
'You uploaded multiple images, only one has been uploaded' 'You uploaded multiple images, only one has been uploaded'
); );
} }

View File

@@ -1,9 +1,10 @@
.uploadedimage { .uploadedimage {
max-width: 100%;
border-radius: 20px; border-radius: 20px;
} }
.content-border { .content-border {
padding: 2rem; padding: 1rem;
} }

View File

@@ -5,6 +5,7 @@ import { isHash } from 'class-validator';
import { HasFailed } from 'picsur-shared/dist/types'; import { HasFailed } from 'picsur-shared/dist/types';
import { ImageService } from 'src/app/api/image.service'; import { ImageService } from 'src/app/api/image.service';
import { ImageLinks } from 'picsur-shared/dist/dto/imagelinks.dto'; import { ImageLinks } from 'picsur-shared/dist/dto/imagelinks.dto';
import { UtilService } from 'src/app/util/util.service';
@Component({ @Component({
selector: 'app-view', selector: 'app-view',
@@ -15,7 +16,8 @@ export class ViewComponent implements OnInit {
constructor( constructor(
private route: ActivatedRoute, private route: ActivatedRoute,
private router: Router, private router: Router,
private imageService: ImageService private imageService: ImageService,
private utilService: UtilService
) {} ) {}
public imageUrl: string; public imageUrl: string;
@@ -25,14 +27,12 @@ export class ViewComponent implements OnInit {
const params = this.route.snapshot.paramMap; const params = this.route.snapshot.paramMap;
const hash = params.get('hash') ?? ''; const hash = params.get('hash') ?? '';
if (!isHash(hash, 'sha256')) { if (!isHash(hash, 'sha256')) {
this.router.navigate(['/'], { replaceUrl: true }); return this.utilService.quitError('Invalid image link');
return;
} }
const imageMeta = await this.imageService.GetImageMeta(hash); const imageMeta = await this.imageService.GetImageMeta(hash);
if (HasFailed(imageMeta)) { if (HasFailed(imageMeta)) {
this.router.navigate(['/'], { replaceUrl: true }); return this.utilService.quitError(imageMeta.getReason());
return;
} }
this.imageUrl = this.imageService.GetImageURL(hash); this.imageUrl = this.imageService.GetImageURL(hash);

View File

@@ -0,0 +1,24 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { UtilService } from './util.service';
import {
MatSnackBarModule,
MAT_SNACK_BAR_DEFAULT_OPTIONS,
} from '@angular/material/snack-bar';
import { RouterModule } from '@angular/router';
@NgModule({
declarations: [],
providers: [
UtilService,
{
provide: MAT_SNACK_BAR_DEFAULT_OPTIONS,
useValue: {
duration: 4000,
horizontalPosition: 'left',
},
},
],
imports: [CommonModule, MatSnackBarModule, RouterModule],
})
export class UtilModule {}

View File

@@ -0,0 +1,25 @@
import { Injectable } from '@angular/core';
import { MatSnackBar } from '@angular/material/snack-bar';
import { Router } from '@angular/router';
import { SnackBarType } from '../models/snack-bar-type';
@Injectable({
providedIn: 'root',
})
export class UtilService {
constructor(private snackBar: MatSnackBar, private router: Router) {}
public quitError(message: string) {
this.showSnackBar(message, SnackBarType.Error);
this.router.navigate(['/']);
}
public showSnackBar(
message: string,
type: SnackBarType = SnackBarType.Default
) {
this.snackBar.open(message, '', {
panelClass: ['mat-toolbar', 'snackbar', type],
});
}
}

View File

@@ -0,0 +1,2 @@
@import "./personal.scss";
@import "./snackbar.scss";

View File

@@ -0,0 +1,24 @@
.snackbar {
background: #272727;
color: white;
&.snack-success {
background: #4d9a51;
}
&.snack-error {
background: #d74545;
}
&.snack-warning {
background: #f68a1c;
}
&.snack-info {
background: #1d95d6;
}
&.snack-default {
background: #272727;
}
}

View File

@@ -281,4 +281,4 @@ html {
transition: 0.2s; transition: 0.2s;
} }
@import "./styles.personal"; @import "./scss";