diff --git a/src/app.constants.ts b/src/app.constants.ts index 22ea441..c177038 100644 --- a/src/app.constants.ts +++ b/src/app.constants.ts @@ -1,4 +1,4 @@ export const API_URL = 'http://127.0.0.1:3000'; -//export const WEBSOCK_URL = 'http://127.0.0.1:3000'; +export const WEBSOCK_URL = 'http://127.0.0.1:3000'; // export const API_URL = 'https://thanksgiving2023.ngweb.io/api'; - export const WEBSOCK_URL = "https://thanksgiving2023.ngweb.io/" + //export const WEBSOCK_URL = "https://thanksgiving2023.ngweb.io/" diff --git a/src/app/admin/admin-main/admin-main.component.html b/src/app/admin/admin-main/admin-main.component.html new file mode 100644 index 0000000..8ef7813 --- /dev/null +++ b/src/app/admin/admin-main/admin-main.component.html @@ -0,0 +1,6 @@ +
+

Game state

+ + +
+ diff --git a/src/app/admin/admin-main/admin-main.component.scss b/src/app/admin/admin-main/admin-main.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/admin/admin-main/admin-main.component.spec.ts b/src/app/admin/admin-main/admin-main.component.spec.ts new file mode 100644 index 0000000..04075ad --- /dev/null +++ b/src/app/admin/admin-main/admin-main.component.spec.ts @@ -0,0 +1,21 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { AdminMainComponent } from './admin-main.component'; + +describe('AdminMainComponent', () => { + let component: AdminMainComponent; + let fixture: ComponentFixture; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [AdminMainComponent] + }); + fixture = TestBed.createComponent(AdminMainComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/admin/admin-main/admin-main.component.ts b/src/app/admin/admin-main/admin-main.component.ts new file mode 100644 index 0000000..719d3cc --- /dev/null +++ b/src/app/admin/admin-main/admin-main.component.ts @@ -0,0 +1,10 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'app-admin-main', + templateUrl: './admin-main.component.html', + styleUrls: ['./admin-main.component.scss'] +}) +export class AdminMainComponent { + +} diff --git a/src/app/admin/admin-routing.module.ts b/src/app/admin/admin-routing.module.ts index 261ed5a..39b798c 100644 --- a/src/app/admin/admin-routing.module.ts +++ b/src/app/admin/admin-routing.module.ts @@ -2,6 +2,8 @@ import { NgModule } from "@angular/core"; import { ActivatedRouteSnapshot, RouterModule, RouterStateSnapshot, Routes, UrlTree } from "@angular/router"; import { HomeComponent } from "./home/home.component"; import { Observable, of } from "rxjs"; +import {ConfigurationComponent} from "./configuration/configuration.component"; +import {AdminMainComponent} from "./admin-main/admin-main.component"; export class AdminGuard { @@ -10,6 +12,9 @@ export class AdminGuard { } canDeactivate(component: HomeComponent, currentRoute: ActivatedRouteSnapshot, currentState: RouterStateSnapshot, nextState?: RouterStateSnapshot): Observable | Promise | boolean | UrlTree { + if(nextState?.url.indexOf('admin') !== -1){ + return of(true); + } return of(false); } @@ -21,7 +26,19 @@ const routes: Routes = [ path: '', component: HomeComponent, canDeactivate: [AdminGuard], - } + children: [ + { + path:'', + component: AdminMainComponent, + canDeactivate: [AdminGuard], + }, + { + path: 'configuration', + component: ConfigurationComponent, + canDeactivate: [AdminGuard], + }] + }, + ] @NgModule({ diff --git a/src/app/admin/admin.module.ts b/src/app/admin/admin.module.ts index b3b35a4..f1c9840 100644 --- a/src/app/admin/admin.module.ts +++ b/src/app/admin/admin.module.ts @@ -3,9 +3,12 @@ import { CommonModule } from '@angular/common'; import { HomeComponent } from './home/home.component'; import { AdminRoutingModule } from "./admin-routing.module"; import { MainActionsComponent } from './components/main-actions/main-actions.component'; -import { AppModule } from "../app.module"; import { SharedModule } from "../shared/shared.module"; import { QueueActionsComponent } from './components/queue-actions/queue-actions.component'; +import { ConfigurationComponent } from './configuration/configuration.component'; +import { AdminNavComponent } from './components/admin-nav/admin-nav.component'; +import { AdminMainComponent } from './admin-main/admin-main.component'; +import { FeatureflagsComponent } from './components/featureflags/featureflags.component'; @@ -13,7 +16,11 @@ import { QueueActionsComponent } from './components/queue-actions/queue-actions. declarations: [ HomeComponent, MainActionsComponent, - QueueActionsComponent + QueueActionsComponent, + ConfigurationComponent, + AdminNavComponent, + AdminMainComponent, + FeatureflagsComponent, ], imports: [ CommonModule, AdminRoutingModule, SharedModule, diff --git a/src/app/admin/components/admin-nav/admin-nav.component.html b/src/app/admin/components/admin-nav/admin-nav.component.html new file mode 100644 index 0000000..d882c6e --- /dev/null +++ b/src/app/admin/components/admin-nav/admin-nav.component.html @@ -0,0 +1,3 @@ + +Main +Config diff --git a/src/app/admin/components/admin-nav/admin-nav.component.scss b/src/app/admin/components/admin-nav/admin-nav.component.scss new file mode 100644 index 0000000..cf1a774 --- /dev/null +++ b/src/app/admin/components/admin-nav/admin-nav.component.scss @@ -0,0 +1,4 @@ +a:link, a:active, a:visited { + color: white; + padding: 3px; +} diff --git a/src/app/admin/components/admin-nav/admin-nav.component.spec.ts b/src/app/admin/components/admin-nav/admin-nav.component.spec.ts new file mode 100644 index 0000000..9c03deb --- /dev/null +++ b/src/app/admin/components/admin-nav/admin-nav.component.spec.ts @@ -0,0 +1,21 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { AdminNavComponent } from './admin-nav.component'; + +describe('AdminNavComponent', () => { + let component: AdminNavComponent; + let fixture: ComponentFixture; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [AdminNavComponent] + }); + fixture = TestBed.createComponent(AdminNavComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/admin/components/admin-nav/admin-nav.component.ts b/src/app/admin/components/admin-nav/admin-nav.component.ts new file mode 100644 index 0000000..3b237d2 --- /dev/null +++ b/src/app/admin/components/admin-nav/admin-nav.component.ts @@ -0,0 +1,10 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'app-admin-nav', + templateUrl: './admin-nav.component.html', + styleUrls: ['./admin-nav.component.scss'] +}) +export class AdminNavComponent { + +} diff --git a/src/app/admin/components/featureflags/featureflags.component.html b/src/app/admin/components/featureflags/featureflags.component.html new file mode 100644 index 0000000..59b6e70 --- /dev/null +++ b/src/app/admin/components/featureflags/featureflags.component.html @@ -0,0 +1,7 @@ +
+
+ + +
+ +
\ No newline at end of file diff --git a/src/app/admin/components/featureflags/featureflags.component.scss b/src/app/admin/components/featureflags/featureflags.component.scss new file mode 100644 index 0000000..1aa47e8 --- /dev/null +++ b/src/app/admin/components/featureflags/featureflags.component.scss @@ -0,0 +1,8 @@ +.featureflags { + .form-group { + margin-left: 5px; + } + label { + margin-left: 3px; + } +} \ No newline at end of file diff --git a/src/app/admin/components/featureflags/featureflags.component.spec.ts b/src/app/admin/components/featureflags/featureflags.component.spec.ts new file mode 100644 index 0000000..2d31e29 --- /dev/null +++ b/src/app/admin/components/featureflags/featureflags.component.spec.ts @@ -0,0 +1,21 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { FeatureflagsComponent } from './featureflags.component'; + +describe('FeatureflagsComponent', () => { + let component: FeatureflagsComponent; + let fixture: ComponentFixture; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [FeatureflagsComponent] + }); + fixture = TestBed.createComponent(FeatureflagsComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/admin/components/featureflags/featureflags.component.ts b/src/app/admin/components/featureflags/featureflags.component.ts new file mode 100644 index 0000000..ff30782 --- /dev/null +++ b/src/app/admin/components/featureflags/featureflags.component.ts @@ -0,0 +1,50 @@ +import {Component, OnDestroy, OnInit} from '@angular/core'; +import {ApiService, FeatureFlagStateDto} from "../../../services/api.service"; +import {FeatureFlagList} from "../../../shared/featureflags"; +import {takeUntil} from "rxjs/operators"; +import {Subject} from "rxjs"; +import {EventService} from "../../../services/event.service"; + +@Component({ + selector: 'app-featureflags', + templateUrl: './featureflags.component.html', + styleUrls: ['./featureflags.component.scss'] +}) +export class FeatureflagsComponent implements OnInit, OnDestroy { + destroyed$ = new Subject(); + public features: FeatureFlagStateDto[] = []; + constructor(private apiService: ApiService, private eventService: EventService) { + } + + ngOnDestroy(): void { + this.destroyed$.complete(); + } + ngOnInit(): void { + this.eventService.featureFlagChanged.pipe(takeUntil(this.destroyed$)).subscribe(result => this.loadFeatureFlags()); + this.loadFeatureFlags(); + } + private loadFeatureFlags() { + + FeatureFlagList.FeatureFlags.map((featureFlag) => { + this.apiService.getFeatureFlagState(featureFlag).pipe(takeUntil(this.destroyed$)).subscribe((result) => { + if(!this.features.find((x) => x.name === result.name)) { + this.features.push(result); + } else { + const index = this.features.findIndex((x) => x.name === result.name); + this.features[index] = result; + } + }); + }) + } + + setFeatureFlag(name: string) { + const ff = this.features.find((featureFlag) => featureFlag.name === name); + let newState = false; + if(ff) { + newState = !ff.state; + } + this.apiService.setFeatureFlagState(name, newState).pipe(takeUntil(this.destroyed$)).subscribe((result) => { + this.loadFeatureFlags(); + }); + } +} diff --git a/src/app/admin/configuration/configuration.component.html b/src/app/admin/configuration/configuration.component.html new file mode 100644 index 0000000..efab6d3 --- /dev/null +++ b/src/app/admin/configuration/configuration.component.html @@ -0,0 +1,4 @@ +
+

FeatureFlags

+ +
diff --git a/src/app/admin/configuration/configuration.component.scss b/src/app/admin/configuration/configuration.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/admin/configuration/configuration.component.spec.ts b/src/app/admin/configuration/configuration.component.spec.ts new file mode 100644 index 0000000..f9a950d --- /dev/null +++ b/src/app/admin/configuration/configuration.component.spec.ts @@ -0,0 +1,21 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ConfigurationComponent } from './configuration.component'; + +describe('ConfigurationComponent', () => { + let component: ConfigurationComponent; + let fixture: ComponentFixture; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [ConfigurationComponent] + }); + fixture = TestBed.createComponent(ConfigurationComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/admin/configuration/configuration.component.ts b/src/app/admin/configuration/configuration.component.ts new file mode 100644 index 0000000..56d6668 --- /dev/null +++ b/src/app/admin/configuration/configuration.component.ts @@ -0,0 +1,10 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'app-configuration', + templateUrl: './configuration.component.html', + styleUrls: ['./configuration.component.scss'] +}) +export class ConfigurationComponent { + +} diff --git a/src/app/admin/home/home.component.html b/src/app/admin/home/home.component.html index 53771d1..2dd4ab4 100644 --- a/src/app/admin/home/home.component.html +++ b/src/app/admin/home/home.component.html @@ -1,8 +1,9 @@ -
- - - - - - -
+ + +
+

Queue

+ + +
diff --git a/src/app/admin/home/home.component.scss b/src/app/admin/home/home.component.scss index e69de29..5e69929 100644 --- a/src/app/admin/home/home.component.scss +++ b/src/app/admin/home/home.component.scss @@ -0,0 +1,5 @@ +@import "../../../styles"; +.nav { + background-color: $thg_orange; + +} \ No newline at end of file diff --git a/src/app/components/participant-item/participant-item.component.scss b/src/app/components/participant-item/participant-item.component.scss index dba52f1..2b4119d 100644 --- a/src/app/components/participant-item/participant-item.component.scss +++ b/src/app/components/participant-item/participant-item.component.scss @@ -1,8 +1,8 @@ @import "../../../styles.scss"; @import url('https://fonts.googleapis.com/css2?family=Pacifico&display=swap'); .card { - min-width: 150px; - max-width: 150px; + min-width: 140px; + max-width: 140px; min-height: 230px; border: 0px solid #c2c2c2; background: rgb(255,166,1); @@ -14,7 +14,7 @@ figure { border-radius:100%; display:inline-block; - margin-bottom: 15px; + margin-bottom: 5px; margin-left: auto; margin-right: auto; } diff --git a/src/app/components/participants/participants.component.html b/src/app/components/participants/participants.component.html index 24fe064..f59a88c 100644 --- a/src/app/components/participants/participants.component.html +++ b/src/app/components/participants/participants.component.html @@ -1,10 +1,9 @@
-
+
-
diff --git a/src/app/services/api.service.ts b/src/app/services/api.service.ts index 29341ec..861e621 100644 --- a/src/app/services/api.service.ts +++ b/src/app/services/api.service.ts @@ -11,6 +11,11 @@ import { PenaltyDto } from "../../types/penalty.dto"; import { PrizeDto } from "../../types/prize.dto"; import {QuestionresultsDto} from "../../types/questionresults.dto"; +export interface FeatureFlagStateDto { + name: string; + state: boolean; +} + @Injectable({ providedIn: 'root' }) @@ -94,4 +99,12 @@ export class ApiService { getQuestionResults() { return this.httpClient.get(`${API_URL}/quiz/question-results`) } + + getFeatureFlagState(feature: string) { + return this.httpClient.get(`${API_URL}/featureflag/${feature}`); + } + + setFeatureFlagState(feature: string, state: boolean) { + return this.httpClient.post(`${API_URL}/featureflag`, { name: feature, state: state }); + } } diff --git a/src/app/services/event.service.ts b/src/app/services/event.service.ts index 261b0e5..9e3ebd3 100644 --- a/src/app/services/event.service.ts +++ b/src/app/services/event.service.ts @@ -31,6 +31,7 @@ export class EventService { public gameResumed = new EventEmitter>(); public notificationEvent = new EventEmitter>(); public userPropertyChanged = new EventEmitter>(); + public featureFlagChanged = new EventEmitter>(); constructor() { } public emit(event: ServerEvent) { @@ -81,6 +82,9 @@ export class EventService { case "user_property_changed": this.userPropertyChanged.emit(event as ServerEvent); break; + case "feature_flag_changed": + this.featureFlagChanged.emit(event); + break; } } } diff --git a/src/app/shared/featureflags.ts b/src/app/shared/featureflags.ts new file mode 100644 index 0000000..5c86195 --- /dev/null +++ b/src/app/shared/featureflags.ts @@ -0,0 +1,3 @@ +export class FeatureFlagList { + static readonly FeatureFlags: string[] = ["EnableEndgamePoints"]; +} \ No newline at end of file diff --git a/src/types/server-event.ts b/src/types/server-event.ts index d2b705f..ca4c376 100644 --- a/src/types/server-event.ts +++ b/src/types/server-event.ts @@ -87,5 +87,6 @@ export interface ServerEvent { | 'game_resumed' | 'notification' | 'user_property_changed' + | 'feature_flag_changed' data: T }