diff --git a/.github/workflows/build-test-scan-push-images.yml b/.github/workflows/build-test-scan-push-images.yml index 4e47fc5..84a9921 100644 --- a/.github/workflows/build-test-scan-push-images.yml +++ b/.github/workflows/build-test-scan-push-images.yml @@ -95,6 +95,7 @@ jobs: image-ref: '${{ env.REGISTRY }}/${{ env.NAMESPACE }}/${{ env.SUB_NAMESPACE }}/${{ matrix.image.name }}:${{ github.sha }}' format: 'sarif' output: 'trivy-results.sarif' + limit-severities-for-sarif: true exit-code: '1' severity: 'CRITICAL,HIGH' diff --git a/frontend/indiestream/src/app/app.component.html b/frontend/indiestream/src/app/app.component.html index e4b6df0..91e85a7 100644 --- a/frontend/indiestream/src/app/app.component.html +++ b/frontend/indiestream/src/app/app.component.html @@ -204,6 +204,8 @@

Hello, {{ title }}

+ + diff --git a/frontend/indiestream/src/app/app.component.spec.ts b/frontend/indiestream/src/app/app.component.spec.ts index 32a0f83..8680c1e 100644 --- a/frontend/indiestream/src/app/app.component.spec.ts +++ b/frontend/indiestream/src/app/app.component.spec.ts @@ -1,10 +1,11 @@ import { TestBed } from '@angular/core/testing'; import { AppComponent } from './app.component'; +import {BrowserAnimationsModule} from "@angular/platform-browser/animations"; describe('AppComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ - imports: [AppComponent], + imports: [AppComponent, BrowserAnimationsModule], }).compileComponents(); }); diff --git a/frontend/indiestream/src/app/app.component.ts b/frontend/indiestream/src/app/app.component.ts index f35e409..56078cf 100644 --- a/frontend/indiestream/src/app/app.component.ts +++ b/frontend/indiestream/src/app/app.component.ts @@ -5,11 +5,12 @@ import { Game } from "./modules/games"; import { CommonModule } from "@angular/common"; import { MatButtonModule } from '@angular/material/button'; import { HttpClientModule } from "@angular/common/http"; +import { GameUploadComponent} from "./components/game-upload/game-upload.component"; @Component({ selector: 'app-root', standalone: true, - imports: [RouterOutlet, CommonModule, MatButtonModule, HttpClientModule], + imports: [RouterOutlet, CommonModule, MatButtonModule, HttpClientModule, GameUploadComponent], templateUrl: './app.component.html', styleUrl: './app.component.scss' }) diff --git a/frontend/indiestream/src/app/app.config.ts b/frontend/indiestream/src/app/app.config.ts index f1c3753..9e293ec 100644 --- a/frontend/indiestream/src/app/app.config.ts +++ b/frontend/indiestream/src/app/app.config.ts @@ -1,10 +1,11 @@ -import { ApplicationConfig } from '@angular/core'; +import {ApplicationConfig, importProvidersFrom} from '@angular/core'; import { provideRouter } from '@angular/router'; import { routes } from './app.routes'; -import {provideHttpClient} from "@angular/common/http"; +import { provideHttpClient } from "@angular/common/http"; import { provideAnimationsAsync } from '@angular/platform-browser/animations/async'; +import {provideAnimations} from "@angular/platform-browser/animations"; export const appConfig: ApplicationConfig = { - providers: [provideRouter(routes), provideHttpClient(), provideAnimationsAsync()] + providers: [provideRouter(routes), provideHttpClient(), provideAnimationsAsync(), provideAnimations()] }; diff --git a/frontend/indiestream/src/app/components/game-upload/game-upload.component.html b/frontend/indiestream/src/app/components/game-upload/game-upload.component.html new file mode 100644 index 0000000..e11cba9 --- /dev/null +++ b/frontend/indiestream/src/app/components/game-upload/game-upload.component.html @@ -0,0 +1,29 @@ +
+
+ + Title of your game + + + + + Chose game + + + +
+
+
+ + +
+ +
+
diff --git a/frontend/indiestream/src/app/components/game-upload/game-upload.component.scss b/frontend/indiestream/src/app/components/game-upload/game-upload.component.scss new file mode 100644 index 0000000..41e0ac7 --- /dev/null +++ b/frontend/indiestream/src/app/components/game-upload/game-upload.component.scss @@ -0,0 +1,20 @@ +.game-upload-container { + display: inline-block; +} + +.input-file { + display: none; +} + +.input-fields { + margin-top: 10px; + margin-bottom: 10px; +} + +.input-title { + margin-right: 10px; +} + +.progress-bar { + margin-bottom: 5px; +} diff --git a/frontend/indiestream/src/app/components/game-upload/game-upload.component.spec.ts b/frontend/indiestream/src/app/components/game-upload/game-upload.component.spec.ts new file mode 100644 index 0000000..06afcec --- /dev/null +++ b/frontend/indiestream/src/app/components/game-upload/game-upload.component.spec.ts @@ -0,0 +1,24 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { GameUploadComponent } from './game-upload.component'; +import {BrowserAnimationsModule} from "@angular/platform-browser/animations"; + +describe('GameUploadComponent', () => { + let component: GameUploadComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [GameUploadComponent, BrowserAnimationsModule] + }) + .compileComponents(); + + fixture = TestBed.createComponent(GameUploadComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/frontend/indiestream/src/app/components/game-upload/game-upload.component.ts b/frontend/indiestream/src/app/components/game-upload/game-upload.component.ts new file mode 100644 index 0000000..969dcdd --- /dev/null +++ b/frontend/indiestream/src/app/components/game-upload/game-upload.component.ts @@ -0,0 +1,71 @@ +import { Component } from '@angular/core'; +import { MatButtonModule } from '@angular/material/button'; +import { MatProgressBar } from "@angular/material/progress-bar"; +import { MatIcon } from "@angular/material/icon"; +import { HttpClientModule, HttpEventType } from "@angular/common/http"; +import {finalize, Subscription} from "rxjs"; +import {NgIf} from "@angular/common"; +import {GamesService} from "../../services/games.service"; +import {MatFormField, MatHint, MatInput, MatLabel, MatSuffix} from "@angular/material/input"; +import {FormBuilder, ReactiveFormsModule, Validators} from "@angular/forms"; + +@Component({ + selector: 'app-game-upload', + standalone: true, + imports: [ + MatButtonModule, + MatProgressBar, + MatIcon, + NgIf, + MatInput, + MatHint, + MatFormField, + MatLabel, + MatSuffix, + ReactiveFormsModule, + HttpClientModule, + ], + templateUrl: './game-upload.component.html', + styleUrl: './game-upload.component.scss' +}) +export class GameUploadComponent { + + uploadProgress: number = 0; + uploadSub: Subscription = new Subscription(); + file_store: FileList = new DataTransfer().files; + gameForm = this.fb.group({ + title: ['', Validators.required], + filename: ['', Validators.required] + }); + + constructor(private gamesService: GamesService, private fb: FormBuilder) {} + + onFileSelected(event: any) { + const file:File = event.target.files[0]; + if (file) { + this.file_store = event.target.files; + this.gameForm.patchValue({ filename: file.name}); + } + } + + onUpload() { + const upload$ = this.gamesService.uploadGame(this.file_store[0]) + .pipe( + finalize(() => this.reset()) + ); + + this.uploadSub = upload$.subscribe(event => { + if (event.type == HttpEventType.UploadProgress && event.total !== undefined) { + this.uploadProgress = Math.round(100 * (event.loaded / event.total)); + } + }) + } + + reset() { + this.uploadProgress = 0; + this.uploadSub.unsubscribe(); + this.uploadSub = new Subscription(); + this.gameForm.reset(); + this.file_store = new DataTransfer().files; + } +} diff --git a/frontend/indiestream/src/app/services/games.service.ts b/frontend/indiestream/src/app/services/games.service.ts index 77d32a9..ef3f400 100644 --- a/frontend/indiestream/src/app/services/games.service.ts +++ b/frontend/indiestream/src/app/services/games.service.ts @@ -1,5 +1,5 @@ import { Injectable } from "@angular/core"; -import { HttpClient } from '@angular/common/http'; +import {HttpClient, HttpEvent} from '@angular/common/http'; import { Games, Game } from '../modules/games'; import { Observable } from "rxjs"; import { environment } from "../environment"; @@ -22,5 +22,12 @@ export class GamesService { deleteGame(id: string): void{ this.http.delete(this.apiUrl + "/games/" + id + "/") } + + uploadGame(file: File): Observable>{ + return this.http.post(this.apiUrl + "/games/", file, { + reportProgress: true, + observe: 'events' + }); + } }