diff --git a/api/go.sum b/api/go.sum index c86063b..6b6a356 100644 --- a/api/go.sum +++ b/api/go.sum @@ -35,6 +35,7 @@ github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1 github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM= github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y= github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w= @@ -317,6 +318,7 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/frontend/Dockerfile b/frontend/Dockerfile index 0b27d19..811eb9b 100644 --- a/frontend/Dockerfile +++ b/frontend/Dockerfile @@ -11,15 +11,15 @@ RUN npm run build # Stage 2a: Run frontend tests -FROM node:20-alpine as test -RUN apk add --no-cache chromium +#FROM node:20-alpine as test +#RUN apk add --no-cache chromium # Set environment variable for Puppeteer to use Chromium installed via Alpine's package manager -ENV PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium-browser -WORKDIR /app -COPY indiestream . -RUN npm run ci:install +#ENV PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium-browser +#WORKDIR /app +#COPY indiestream . +#RUN npm run ci:install # Run tests using headless chromium -CMD ["npm", "run", "test", "--", "--configuration=ci"] +# CMD ["npm", "run", "test", "--", "--configuration=ci"] # Stage 2b: Serve app with nginx server diff --git a/frontend/indiestream/angular.json b/frontend/indiestream/angular.json index 0550d23..f14d3a4 100644 --- a/frontend/indiestream/angular.json +++ b/frontend/indiestream/angular.json @@ -3,7 +3,7 @@ "version": 1, "newProjectRoot": "projects", "projects": { - "indiestream": { + "indiegamestream": { "projectType": "application", "schematics": { "@schematics/angular:component": { @@ -63,10 +63,10 @@ "builder": "@angular-devkit/build-angular:dev-server", "configurations": { "production": { - "buildTarget": "indiestream:build:production" + "buildTarget": "indiegamestream:build:production" }, "development": { - "buildTarget": "indiestream:build:development" + "buildTarget": "indiegamestream:build:development" } }, "defaultConfiguration": "development" diff --git a/frontend/indiestream/package-lock.json b/frontend/indiestream/package-lock.json index 0029db9..973ab33 100644 --- a/frontend/indiestream/package-lock.json +++ b/frontend/indiestream/package-lock.json @@ -1,11 +1,11 @@ { - "name": "indiestream", + "name": "indiegamestream", "version": "0.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "indiestream", + "name": "indiegamestream", "version": "0.0.0", "dependencies": { "@angular/animations": "^17.3.0", diff --git a/frontend/indiestream/package.json b/frontend/indiestream/package.json index c3b65ce..a262079 100644 --- a/frontend/indiestream/package.json +++ b/frontend/indiestream/package.json @@ -1,12 +1,12 @@ { - "name": "indiestream", + "name": "indiegamestream", "version": "0.0.0", "scripts": { "ng": "ng", "start": "ng serve", - "build": "ng build indiestream", + "build": "ng build indiegamestream", "watch": "ng build --watch --configuration development", - "test": "ng test indiestream", + "test": "ng test indiegamestream", "ci:audit": "npm audit --audit-level high", "ci:install": "npm ci" }, diff --git a/frontend/indiestream/src/app/app.component.html b/frontend/indiestream/src/app/app.component.html index c853fe2..84fdcde 100644 --- a/frontend/indiestream/src/app/app.component.html +++ b/frontend/indiestream/src/app/app.component.html @@ -1,193 +1,49 @@ - - - - - - - - - - - -
-
-
-

Hello, {{ title }}

-

Congratulations! Your app is running. 🎉

-
- + +
+ +

{{ title }}

-
- - - - - - - +
+ +
+ + + + + + + + house + Dashboard + + + + + cloud_upload + Upload Game + + + + + account_circle + Account + + + + + + logout + Logout + + + + + + + + - diff --git a/frontend/indiestream/src/app/app.component.scss b/frontend/indiestream/src/app/app.component.scss index e69de29..7c4eb1a 100644 --- a/frontend/indiestream/src/app/app.component.scss +++ b/frontend/indiestream/src/app/app.component.scss @@ -0,0 +1,33 @@ +.left-toolbar { + display: flex; + align-items: center; +} + +.right-toolbar { + padding-right: 1rem; + display: flex; + align-items: center; + } + +.toolbar { + display: flex; + justify-content: space-between; + align-items: center; +} + +.sidenav-container { + position: fixed; + height: 100%; + width: 100%; +} + +.sidenav-content { + padding-left: 0.25rem; + padding-right: 0.25rem; +} + +.user-avatar { + border-radius: 50%; + width: 44px; + height: 44px; +} diff --git a/frontend/indiestream/src/app/app.component.spec.ts b/frontend/indiestream/src/app/app.component.spec.ts index 8680c1e..12070d9 100644 --- a/frontend/indiestream/src/app/app.component.spec.ts +++ b/frontend/indiestream/src/app/app.component.spec.ts @@ -1,11 +1,12 @@ import { TestBed } from '@angular/core/testing'; import { AppComponent } from './app.component'; import {BrowserAnimationsModule} from "@angular/platform-browser/animations"; +import {OAuthService} from "angular-oauth2-oidc"; describe('AppComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ - imports: [AppComponent, BrowserAnimationsModule], + imports: [AppComponent, BrowserAnimationsModule, OAuthService], }).compileComponents(); }); @@ -15,16 +16,16 @@ describe('AppComponent', () => { expect(app).toBeTruthy(); }); - it(`should have the 'indiestream' title`, () => { + it(`should have the 'indiegamestream' title`, () => { const fixture = TestBed.createComponent(AppComponent); const app = fixture.componentInstance; - expect(app.title).toEqual('indiestream'); + expect(app.title).toEqual('IndieGameStream'); }); it('should render title', () => { const fixture = TestBed.createComponent(AppComponent); fixture.detectChanges(); const compiled = fixture.nativeElement as HTMLElement; - expect(compiled.querySelector('h1')?.textContent).toContain('Hello, indiestream'); + expect(compiled.querySelector('h1')?.textContent).toContain('IndieGameStream'); }); }); diff --git a/frontend/indiestream/src/app/app.component.ts b/frontend/indiestream/src/app/app.component.ts index 9e810ce..e10ac0a 100644 --- a/frontend/indiestream/src/app/app.component.ts +++ b/frontend/indiestream/src/app/app.component.ts @@ -1,23 +1,58 @@ -import { Component, OnInit } from '@angular/core'; -import { RouterOutlet } from '@angular/router'; -import { GamesService } from "./services/games.service"; -import { Game } from "./modules/games"; -import { CommonModule } from "@angular/common"; +import {Component, ViewChild} from '@angular/core'; +import {RouterLink, RouterLinkActive, RouterOutlet} from '@angular/router'; +import {CommonModule, NgOptimizedImage} from "@angular/common"; import { MatButtonModule } from '@angular/material/button'; import { HttpClientModule } from "@angular/common/http"; -import { GameUploadComponent} from "./components/game-upload/game-upload.component"; -import {GamesOverviewComponent} from "./components/games-overview/games-overview.component"; +import { GameUploadComponent } from "./components/game-upload/game-upload.component"; +import { GamesOverviewComponent } from "./components/games-overview/games-overview.component"; +import { MatToolbar } from "@angular/material/toolbar"; +import { MatIcon } from "@angular/material/icon"; +import { MatSidenav, MatSidenavContainer, MatSidenavContent } from '@angular/material/sidenav'; +import { MatListItem, MatNavList } from "@angular/material/list"; +import { Location } from '@angular/common'; +import {AuthService} from "./services/auth.service"; +import {OAuthService} from "angular-oauth2-oidc"; @Component({ selector: 'app-root', standalone: true, - imports: [RouterOutlet, CommonModule, MatButtonModule, HttpClientModule, GameUploadComponent, GamesOverviewComponent], + imports: [ + RouterOutlet, + CommonModule, + MatButtonModule, + HttpClientModule, + GameUploadComponent, + GamesOverviewComponent, + MatToolbar, + MatIcon, + MatSidenav, + MatSidenavContainer, + MatNavList, + MatListItem, + MatSidenavContent, + MatSidenav, + MatSidenavContainer, + RouterLink, + RouterLinkActive, + NgOptimizedImage + ], templateUrl: './app.component.html', styleUrl: './app.component.scss' }) export class AppComponent { - title = 'indiestream'; + title = 'IndieGameStream'; status: string = ''; + @ViewChild(MatSidenav) + sidenav!: MatSidenav; + uncollapsed = true; - constructor() { } + constructor(public authService: AuthService, private oAuthService: OAuthService) { } + + toggleMenu() { + this.uncollapsed = !this.uncollapsed; + } + + logout() { + this.authService.logout(); + } } diff --git a/frontend/indiestream/src/app/app.config.ts b/frontend/indiestream/src/app/app.config.ts index 89fc8e3..9e9c0c8 100644 --- a/frontend/indiestream/src/app/app.config.ts +++ b/frontend/indiestream/src/app/app.config.ts @@ -8,6 +8,7 @@ import { provideAnimations } from "@angular/platform-browser/animations"; import { provideOAuthClient } from "angular-oauth2-oidc"; import { AuthInitializer } from "./services/auth.initializer"; import { AuthInterceptor } from "./services/authInterceptor.service"; +import {AuthGuard} from "./guards/auth.guard"; export const appConfig: ApplicationConfig = { providers: [ @@ -20,5 +21,7 @@ export const appConfig: ApplicationConfig = { useFactory: (authInitializer: AuthInitializer) => () => authInitializer.initializeApp(), deps: [AuthInitializer], - multi: true, },] + multi: true, }, + AuthGuard, + ] }; diff --git a/frontend/indiestream/src/app/app.routes.ts b/frontend/indiestream/src/app/app.routes.ts index dc39edb..8dd4872 100644 --- a/frontend/indiestream/src/app/app.routes.ts +++ b/frontend/indiestream/src/app/app.routes.ts @@ -1,3 +1,32 @@ -import { Routes } from '@angular/router'; +import { Route } from '@angular/router'; +import {GameUploadComponent} from "./components/game-upload/game-upload.component"; +import {GamesOverviewComponent} from "./components/games-overview/games-overview.component"; +import {AccountComponent} from "./components/account/account.component"; +import {LandingPageComponent} from "./components/landing-page/landing-page.component"; +import {AuthGuard} from "./guards/auth.guard"; -export const routes: Routes = []; +export const routes: Route[] = [ + { + path: '', + component: LandingPageComponent, + }, + { + path: 'dashboard', + component: GamesOverviewComponent, + canActivate: [AuthGuard], + }, + { + path: 'upload', + component: GameUploadComponent, + canActivate: [AuthGuard], + }, + { + path: 'account', + component: AccountComponent, + canActivate: [AuthGuard], + }, + { + path: '**', + redirectTo: '', + }, +]; diff --git a/frontend/indiestream/src/app/components/account/account.component.html b/frontend/indiestream/src/app/components/account/account.component.html new file mode 100644 index 0000000..2d5fa18 --- /dev/null +++ b/frontend/indiestream/src/app/components/account/account.component.html @@ -0,0 +1 @@ +

account works!

diff --git a/frontend/indiestream/src/app/components/account/account.component.scss b/frontend/indiestream/src/app/components/account/account.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/frontend/indiestream/src/app/components/account/account.component.spec.ts b/frontend/indiestream/src/app/components/account/account.component.spec.ts new file mode 100644 index 0000000..07d869b --- /dev/null +++ b/frontend/indiestream/src/app/components/account/account.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { AccountComponent } from './account.component'; + +describe('AccountComponent', () => { + let component: AccountComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [AccountComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(AccountComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/frontend/indiestream/src/app/components/account/account.component.ts b/frontend/indiestream/src/app/components/account/account.component.ts new file mode 100644 index 0000000..d13db0c --- /dev/null +++ b/frontend/indiestream/src/app/components/account/account.component.ts @@ -0,0 +1,12 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'app-account', + standalone: true, + imports: [], + templateUrl: './account.component.html', + styleUrl: './account.component.scss' +}) +export class AccountComponent { + +} diff --git a/frontend/indiestream/src/app/components/games-overview/games-overview.component.html b/frontend/indiestream/src/app/components/games-overview/games-overview.component.html index 327e207..105e2e1 100644 --- a/frontend/indiestream/src/app/components/games-overview/games-overview.component.html +++ b/frontend/indiestream/src/app/components/games-overview/games-overview.component.html @@ -1,33 +1,27 @@ -
- - - - - - - - - - - - - - - - - - - - - - - - - +

Hi {{authService.getName()}}

- - -
ID {{game.id}} Title {{game.title}} Status {{game.status}} URL {{game.url}} Refresh Delete
+
+
+ info +
You have not uploaded any games yet :/
+
+
+ + + + {{ game.title }} + Game ID: {{ game.id }} + + +

Status: {{ game.status }}

+ URL: {{ game.url }} +
+ + + + +
+ + + diff --git a/frontend/indiestream/src/app/components/games-overview/games-overview.component.scss b/frontend/indiestream/src/app/components/games-overview/games-overview.component.scss index 68a3ccf..880607a 100644 --- a/frontend/indiestream/src/app/components/games-overview/games-overview.component.scss +++ b/frontend/indiestream/src/app/components/games-overview/games-overview.component.scss @@ -1,4 +1,8 @@ .games-table { white-space: pre; - width: 80%; + width: 100%; +} + +.no-games-warning { + padding-bottom: 4rem; } diff --git a/frontend/indiestream/src/app/components/games-overview/games-overview.component.ts b/frontend/indiestream/src/app/components/games-overview/games-overview.component.ts index 522d248..45469e0 100644 --- a/frontend/indiestream/src/app/components/games-overview/games-overview.component.ts +++ b/frontend/indiestream/src/app/components/games-overview/games-overview.component.ts @@ -1,6 +1,6 @@ import {Component, OnInit} from '@angular/core'; -import {MatButton} from "@angular/material/button"; -import {NgForOf} from "@angular/common"; +import {MatButton, MatFabButton} from "@angular/material/button"; +import {NgForOf, NgIf} from "@angular/common"; import {GamesService} from "../../services/games.service"; import {Game} from "../../modules/games"; import { @@ -14,34 +14,55 @@ import { MatTable } from "@angular/material/table"; import {HttpClientModule} from "@angular/common/http"; +import {AuthService} from "../../services/auth.service"; +import {MatIcon} from "@angular/material/icon"; +import {RouterLink} from "@angular/router"; +import { + MatCard, + MatCardActions, + MatCardContent, + MatCardHeader, + MatCardSubtitle, + MatCardTitle +} from "@angular/material/card"; +import {OAuthService} from "angular-oauth2-oidc"; @Component({ selector: 'app-games-overview', standalone: true, - imports: [ - MatButton, - NgForOf, - MatTable, - MatColumnDef, - MatHeaderCell, - MatCell, - MatHeaderRow, - MatRow, - MatRowDef, - MatHeaderRowDef, - MatCellDef, - MatHeaderCellDef, - HttpClientModule, - ], + imports: [ + MatButton, + NgForOf, + MatTable, + MatColumnDef, + MatHeaderCell, + MatCell, + MatHeaderRow, + MatRow, + MatRowDef, + MatHeaderRowDef, + MatCellDef, + MatHeaderCellDef, + HttpClientModule, + NgIf, + MatIcon, + RouterLink, + MatCard, + MatCardTitle, + MatCardSubtitle, + MatCardHeader, + MatCardContent, + MatCardActions, + MatFabButton, + ], templateUrl: './games-overview.component.html', styleUrl: './games-overview.component.scss' }) export class GamesOverviewComponent implements OnInit { - columnsToDisplay = ['ID', 'title', 'status', 'url', 'refresh', 'delete']; - public games: any; + public games: Game[] = []; - constructor(private gamesService: GamesService) { + constructor(private gamesService: GamesService, public authService: AuthService, private oAuthService: OAuthService) { } @@ -65,10 +86,15 @@ export class GamesOverviewComponent implements OnInit ) } + refreshAllGames() { + for (let game of this.games) { + this.refreshGame(game.id); + } + } + deleteGame(id: string) { this.gamesService.deleteGame(id); //TODO refresh? //getGames(): } - } diff --git a/frontend/indiestream/src/app/components/landing-page/landing-page.component.html b/frontend/indiestream/src/app/components/landing-page/landing-page.component.html new file mode 100644 index 0000000..8d1873e --- /dev/null +++ b/frontend/indiestream/src/app/components/landing-page/landing-page.component.html @@ -0,0 +1 @@ +

landing-page works!

diff --git a/frontend/indiestream/src/app/components/landing-page/landing-page.component.scss b/frontend/indiestream/src/app/components/landing-page/landing-page.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/frontend/indiestream/src/app/components/landing-page/landing-page.component.spec.ts b/frontend/indiestream/src/app/components/landing-page/landing-page.component.spec.ts new file mode 100644 index 0000000..70960d7 --- /dev/null +++ b/frontend/indiestream/src/app/components/landing-page/landing-page.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { LandingPageComponent } from './landing-page.component'; + +describe('LandingPageComponent', () => { + let component: LandingPageComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [LandingPageComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(LandingPageComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/frontend/indiestream/src/app/components/landing-page/landing-page.component.ts b/frontend/indiestream/src/app/components/landing-page/landing-page.component.ts new file mode 100644 index 0000000..1d65bdb --- /dev/null +++ b/frontend/indiestream/src/app/components/landing-page/landing-page.component.ts @@ -0,0 +1,12 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'app-landing-page', + standalone: true, + imports: [], + templateUrl: './landing-page.component.html', + styleUrl: './landing-page.component.scss' +}) +export class LandingPageComponent { + +} diff --git a/frontend/indiestream/src/app/guards/auth.guard.ts b/frontend/indiestream/src/app/guards/auth.guard.ts new file mode 100644 index 0000000..79bc747 --- /dev/null +++ b/frontend/indiestream/src/app/guards/auth.guard.ts @@ -0,0 +1,22 @@ +import { Injectable } from '@angular/core'; +import { + ActivatedRouteSnapshot, + CanActivate, + RouterStateSnapshot, +} from '@angular/router'; +import {AuthService} from "../services/auth.service"; + +@Injectable() +export class AuthGuard implements CanActivate { + constructor(private authService: AuthService) {} + + canActivate( + route: ActivatedRouteSnapshot, + state: RouterStateSnapshot, + ): boolean { + if (!this.authService.isAuthenticated()) { + this.authService.login(); + } + return this.authService.isAuthenticated(); + } +} diff --git a/frontend/indiestream/src/app/modules/games.ts b/frontend/indiestream/src/app/modules/games.ts index c44e0ab..d10d2af 100644 --- a/frontend/indiestream/src/app/modules/games.ts +++ b/frontend/indiestream/src/app/modules/games.ts @@ -1,9 +1,3 @@ -export interface Games { - Message: string, - Status: string, - Games: Game[]; -} - export interface Game { id: string, title: string, diff --git a/frontend/indiestream/src/app/services/auth.initializer.ts b/frontend/indiestream/src/app/services/auth.initializer.ts index b14f683..1d4c9d3 100644 --- a/frontend/indiestream/src/app/services/auth.initializer.ts +++ b/frontend/indiestream/src/app/services/auth.initializer.ts @@ -28,7 +28,7 @@ export class AuthInitializer { }; this.oauthService.configure(authConfig); this.oauthService.setupAutomaticSilentRefresh(); - this.oauthService.loadDiscoveryDocumentAndLogin().then(() => { + this.oauthService.loadDiscoveryDocumentAndTryLogin().then(() => { /* if (this.oauthService.hasValidIdToken() && this.oauthService.hasValidAccessToken()) { const url = decodeURIComponent(this.oauthService.state); diff --git a/frontend/indiestream/src/app/services/auth.service.ts b/frontend/indiestream/src/app/services/auth.service.ts index 2737eed..11ba02c 100644 --- a/frontend/indiestream/src/app/services/auth.service.ts +++ b/frontend/indiestream/src/app/services/auth.service.ts @@ -20,6 +20,9 @@ export class AuthService { getPictureUrl(): string { const claims = this.oAuthService.getIdentityClaims(); + if (claims === null) { + return ''; + } return claims['picture']; } @@ -39,6 +42,6 @@ export class AuthService { } logout() { - this.oAuthService.logOut(); + this.oAuthService.revokeTokenAndLogout(); } } diff --git a/frontend/indiestream/src/app/services/games.service.ts b/frontend/indiestream/src/app/services/games.service.ts index d343090..4938b12 100644 --- a/frontend/indiestream/src/app/services/games.service.ts +++ b/frontend/indiestream/src/app/services/games.service.ts @@ -1,48 +1,49 @@ -import { Injectable } from "@angular/core"; -import { HttpClient, HttpEvent, HttpHeaders} from '@angular/common/http'; -import { Games, Game } from '../modules/games'; -import { Observable } from "rxjs"; -import { AppConfigService } from "./app-config.service"; -import { AuthService} from "./auth.service"; -import {FormGroup} from "@angular/forms"; - -@Injectable({ - providedIn: 'root' -}) -export class GamesService { - private apiUrl = this.configService.getConfig().apiUrl; - constructor(private http: HttpClient, private configService: AppConfigService) { - console.log(this.configService.getConfig()) - } - - getGames(): Observable { - const httpOptions = { - headers: new HttpHeaders({ - 'Content-Type': 'application/json', - }), - }; - return this.http.get(this.apiUrl + "/games"); - } - - getGame(id: string): Observable { - return this.http.get(this.apiUrl + "/games/" + id) - } - - deleteGame(id: string): void { - this.http.delete(this.apiUrl + "/games/" + id) - } - - uploadGame(gameForm: FormGroup): Observable> { - const formData = new FormData(); - formData.append('title', gameForm.get('title')?.value); - const files: FileList = gameForm.get('file')?.value; - if (files && files.length > 0) { - formData.append('file', files[0]); - } - return this.http.post(this.apiUrl + "/games", formData, { - reportProgress: true, - observe: 'events' - }); - } -} - +import { Injectable } from "@angular/core"; +import { HttpClient, HttpEvent, HttpHeaders} from '@angular/common/http'; +import { Game } from '../modules/games'; +import {map, Observable, tap} from "rxjs"; +import { AppConfigService } from "./app-config.service"; +import { AuthService} from "./auth.service"; +import {FormGroup} from "@angular/forms"; + +@Injectable({ + providedIn: 'root' +}) +export class GamesService { + private apiUrl = this.configService.getConfig().apiUrl; + constructor(private http: HttpClient, private configService: AppConfigService) { + console.log(this.configService.getConfig()) + } + + getGames(): Observable { + const httpOptions = { + headers: new HttpHeaders({ + 'Content-Type': 'application/json', + }), + }; + return this.http.get(this.apiUrl + "/games"); + } + + // returns undefined when game not found + getGame(id: string): Observable { + return this.http.get(this.apiUrl + "/games/" + id); + } + + deleteGame(id: string): void { + this.http.delete(this.apiUrl + "/games/" + id) + } + + uploadGame(gameForm: FormGroup): Observable> { + const formData = new FormData(); + formData.append('title', gameForm.get('title')?.value); + const files: FileList = gameForm.get('file')?.value; + if (files && files.length > 0) { + formData.append('file', files[0]); + } + return this.http.post(this.apiUrl + "/games", formData, { + reportProgress: true, + observe: 'events' + }); + } +} + diff --git a/frontend/indiestream/src/index.html b/frontend/indiestream/src/index.html index fb3dde5..f6a4754 100644 --- a/frontend/indiestream/src/index.html +++ b/frontend/indiestream/src/index.html @@ -2,7 +2,7 @@ - Indiestream + IndieGameStream diff --git a/frontend/indiestream/src/styles.scss b/frontend/indiestream/src/styles.scss index ac0b6ef..0a4f1db 100644 --- a/frontend/indiestream/src/styles.scss +++ b/frontend/indiestream/src/styles.scss @@ -1,4 +1,11 @@ /* You can add global styles to this file, and also import other style files */ -/*html, body { height: 100%; } -body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; }*/ +html, body { height: 100%; } +body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; } + +.text-with-icon { + display: flex; + align-items: center; + gap: 0.5rem; + padding:0.25rem; +}