Browse Source

Merge branch 'feature/mapper-integration'

master
Quildra 2 years ago
parent
commit
9b439ab4ab
  1. 12
      package-lock.json
  2. 2
      packages/bridge-ui/package.json
  3. 14
      packages/bridge-ui/src/app/components/race-details/race-details.component.html
  4. 34
      packages/bridge-ui/src/app/components/race-details/race-details.component.ts
  5. 2
      packages/bridge-ui/src/app/components/season-card/season-card.component.html
  6. 10
      packages/bridge-ui/src/app/components/season-card/season-card.component.ts
  7. 4
      packages/bridge-ui/src/app/components/season-standings/season-standings.component.html
  8. 20
      packages/bridge-ui/src/app/components/season-standings/season-standings.component.ts
  9. 37
      packages/bridge-ui/src/app/models/race.model.ts
  10. 21
      packages/bridge-ui/src/app/models/raceEntry.model.ts
  11. 28
      packages/bridge-ui/src/app/models/racer.model.ts
  12. 12
      packages/bridge-ui/src/app/models/season-standing.model.ts
  13. 27
      packages/bridge-ui/src/app/models/season.model.ts
  14. 51
      packages/bridge-ui/src/app/models/user.model.ts
  15. 4
      packages/bridge-ui/src/app/pages/user/user.component.html
  16. 3
      packages/bridge-ui/src/app/pages/user/user.component.ts
  17. 65
      packages/bridge-ui/src/app/services/race-result.service.ts
  18. 18
      packages/bridge-ui/src/app/services/racers.service.ts
  19. 23
      packages/bridge-ui/src/app/services/races.service.ts
  20. 49
      packages/bridge-ui/src/app/services/seasons.service.ts
  21. 2
      packages/bridge-ui/src/app/services/server-side-events.service.ts
  22. 18
      packages/bridge-ui/src/app/services/users.service.ts
  23. 15
      packages/bridge-ui/src/app/services/utils.service.ts
  24. 1
      packages/bridge-ui/src/main.ts

12
package-lock.json

@ -9474,6 +9474,11 @@
"integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==",
"dev": true
},
"node_modules/class-transformer": {
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/class-transformer/-/class-transformer-0.5.1.tgz",
"integrity": "sha512-SQa1Ws6hUbfC98vKGxZH3KFY0Y1lm5Zm0SY8XX9zbK7FJCyVEac3ATW0RIpwzW+oOfmHE5PMPufDG9hCfoEOMw=="
},
"node_modules/clean-stack": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
@ -24018,9 +24023,11 @@
"@angular/router": "^17.0.0",
"@auth0/auth0-angular": "^2.2.1",
"bridge-shared": "^1.0.0",
"class-transformer": "^0.5.1",
"eventemitter3": "^5.0.1",
"jwt-decode": "^4.0.0",
"mat-icon-button-sizes": "^1.0.6",
"reflect-metadata": "^0.2.1",
"rxjs": "~7.8.0",
"tslib": "^2.3.0",
"zone.js": "~0.14.2"
@ -24044,6 +24051,11 @@
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz",
"integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA=="
},
"packages/bridge-ui/node_modules/reflect-metadata": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.1.tgz",
"integrity": "sha512-i5lLI6iw9AU3Uu4szRNPPEkomnkjRTaVt9hy/bn5g/oSzekBSMeLZblcjP74AW0vBabqERLLIrz+gR8QYR54Tw=="
}
}
}

2
packages/bridge-ui/package.json

@ -22,9 +22,11 @@
"@angular/router": "^17.0.0",
"@auth0/auth0-angular": "^2.2.1",
"bridge-shared": "^1.0.0",
"class-transformer": "^0.5.1",
"eventemitter3": "^5.0.1",
"jwt-decode": "^4.0.0",
"mat-icon-button-sizes": "^1.0.6",
"reflect-metadata": "^0.2.1",
"rxjs": "~7.8.0",
"tslib": "^2.3.0",
"zone.js": "~0.14.2"

14
packages/bridge-ui/src/app/components/race-details/race-details.component.html

@ -38,10 +38,10 @@
}
</div>
<div class="race-times">
<div><img class="inline-medal" src="/assets/medal_author.png"/><p>Author: {{formatMilliseconds(race.authorTime)}}</p></div>
<div><img class="inline-medal" src="/assets/medal_gold.png"/><p>Gold: {{formatMilliseconds(race.goldTime)}}</p></div>
<div><img class="inline-medal" src="/assets/medal_silver.png"/><p>Silver: {{formatMilliseconds(race.silverTime)}}</p></div>
<div><img class="inline-medal" src="/assets/medal_bronze.png"/><p>Bronze: {{formatMilliseconds(race.bronzeTime)}}</p></div>
<div><img class="inline-medal" src="/assets/medal_author.png"/><p>Author: {{utilsService.formatMilliseconds(race.authorTime)}}</p></div>
<div><img class="inline-medal" src="/assets/medal_gold.png"/><p>Gold: {{utilsService.formatMilliseconds(race.goldTime)}}</p></div>
<div><img class="inline-medal" src="/assets/medal_silver.png"/><p>Silver: {{utilsService.formatMilliseconds(race.silverTime)}}</p></div>
<div><img class="inline-medal" src="/assets/medal_bronze.png"/><p>Bronze: {{utilsService.formatMilliseconds(race.bronzeTime)}}</p></div>
</div>
</div>
<br/>
@ -62,10 +62,10 @@
<th mat-header-cell *matHeaderCellDef>Name </th>
<td mat-cell *matCellDef="let element">
@if(element.racer.user) {
<a class="user-link" [routerLink]="['/user/'+getUserId(element.racer)]">{{getRacerName(element.racer)}}</a>
<a class="user-link" [routerLink]="['/user/'+element.racer.user.getUserId()]">{{element.racer.getName()}}</a>
}
@else {
{{getRacerName(element.racer)}}
{{element.racer.getName()}}
}
</td>
</ng-container>
@ -73,7 +73,7 @@
<!-- Weight Column -->
<ng-container matColumnDef="runTime">
<th mat-header-cell *matHeaderCellDef>Time </th>
<td mat-cell *matCellDef="let element"> {{formatMilliseconds(element.time)}} </td>
<td mat-cell *matCellDef="let element"> {{utilsService.formatMilliseconds(element.time)}} </td>
</ng-container>
<ng-container matColumnDef="ghost">

34
packages/bridge-ui/src/app/components/race-details/race-details.component.ts

@ -14,6 +14,8 @@ import { Race } from '../../models/race.model';
import { Racer } from '../../models/racer.model';
import { RaceEntry } from '../../models/raceEntry.model';
import { ServerSideEventsService } from '../../services/server-side-events.service';
import { UtilsService } from '../../services/utils.service';
@Component({
selector: 'app-race-details',
@ -75,7 +77,8 @@ export class RaceDetailsComponent implements AfterViewInit {
constructor(
private raceResultService: RaceResultService,
private racesService: RacesService,
private sseService: ServerSideEventsService
private sseService: ServerSideEventsService,
public utilsService: UtilsService
)
{}
@ -143,35 +146,6 @@ export class RaceDetailsComponent implements AfterViewInit {
}
}
formatMilliseconds(milliseconds: number)
{
const minutes = Math.floor(milliseconds / (1000 * 60));
const seconds = Math.floor((milliseconds % (1000 * 60)) / 1000);
const remainingMilliseconds = milliseconds % 1000;
return `${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}:${String(remainingMilliseconds).padStart(3, '0')}`;
}
getRacerName(racer: any): string {
if( racer != undefined) {
if( racer.name == undefined || racer.name == "" ) {
return racer.gameHandle;
}
return racer.name + " (" + racer.gameHandle + ")"
}
return ""
}
getUserId(racer: any): string {
if( racer != undefined && racer.user != undefined) {
return racer.user.auth0id.replace("auth0|", "");
}
return ""
}
timeToMedal(time: number) {
if( this.race == undefined) { return "" }
if( time < this.race.authorTime ) { return "assets/medal_author.png"; }

2
packages/bridge-ui/src/app/components/season-card/season-card.component.html

@ -5,7 +5,7 @@
<mat-card-subtitle>{{season.subTitle}}</mat-card-subtitle>
<div class="docs-guide-card-divider"></div>
<mat-card-content class="mat-mdc-card-content docs-guide-card-summary">
<p>Start Date: {{getStartingDate()}}</p>
<p>Start Date: {{season.getStartingDate()}}</p>
<p>Number of Races: {{season.races.length}}</p>
@if(usersService.canEditSeasons()) {
<button mat-mini-fab color="accent" aria-label="Edit">

10
packages/bridge-ui/src/app/components/season-card/season-card.component.ts

@ -29,16 +29,6 @@ export class SeasonCardComponent {
public usersService: UsersService,
) {}
getStartingDate() {
if(this.season != undefined) {
let date = new Date(0);
date.setUTCSeconds(Number(this.season.startingDate));
return date.toUTCString();
}
return "";
}
deleteSeason(id: string) {
}

4
packages/bridge-ui/src/app/components/season-standings/season-standings.component.html

@ -10,10 +10,10 @@
<th mat-header-cell *matHeaderCellDef>Name </th>
<td mat-cell *matCellDef="let element">
@if(element.racer.user) {
<a class="user-link" [routerLink]="['/user/'+getUserId(element.racer)]">{{getRacerName(element.racer)}}</a>
<a class="user-link" [routerLink]="['/user/'+element.racer.user.getUserId()]">{{element.racer.getName()}}</a>
}
@else {
{{getRacerName(element.racer)}}
{{element.racer.getName()}}
}
</td>
</ng-container>

20
packages/bridge-ui/src/app/components/season-standings/season-standings.component.ts

@ -95,24 +95,4 @@ export class SeasonStandingsComponent {
this.sortStandings(sorted);
}
getRacerName(racer: any): string {
if( racer != undefined) {
if( racer.name == undefined || racer.name == "" ) {
return racer.gameHandle;
}
return racer.name + " (" + racer.gameHandle + ")"
}
return ""
}
getUserId(racer: any): string {
if( racer != undefined && racer.user != undefined) {
return racer.user.auth0id.replace("auth0|", "");
}
return ""
}
}

37
packages/bridge-ui/src/app/models/race.model.ts

@ -1,14 +1,49 @@
export class Race{
import { Expose, Type } from 'class-transformer';
import { RaceEntry } from './raceEntry.model';
import { Season } from './season.model';
export class Race {
@Expose()
id: string = "";
@Expose()
mapName: string = "";
@Expose()
mapURL: string = "";
@Expose()
mapUID: string = "";
@Expose()
mapImgUrl: string = "";
@Expose()
authorTime: number = 0;
@Expose()
goldTime: number = 0;
@Expose()
silverTime: number = 0;
@Expose()
bronzeTime: number = 0;
@Expose()
startDate: Date = new Date(0);
@Expose()
endDate: Date = new Date(0);
@Expose()
racers: string[] = [];
@Expose()
@Type(() => RaceEntry)
results: RaceEntry[] = [];
@Expose()
@Type(() => Season)
season: Season | null = null;
}

21
packages/bridge-ui/src/app/models/raceEntry.model.ts

@ -1,7 +1,22 @@
import { Expose, Type } from 'class-transformer';
import { Race } from './race.model';
import { Racer } from './racer.model';
export class RaceEntry {
id: string = "";
race_id: string = "";
racer_id: string = "";
@Expose()
id: number = -1;
@Expose()
@Type(() => Race)
race: Race | null = null;
@Expose()
@Type(() => Racer)
racer: Racer | null = null;
@Expose()
replayPath: string = "";
@Expose()
time: number = 0;
}

28
packages/bridge-ui/src/app/models/racer.model.ts

@ -1,5 +1,33 @@
import { Expose, Type } from 'class-transformer';
import { User } from './user.model';
import { RaceEntry } from './raceEntry.model';
export class Racer {
@Expose()
id: string = "";
@Expose()
name: string = "";
@Expose()
gameHandle: string = "";
@Expose()
results: RaceEntry[] = [];
@Expose()
@Type(() => User)
user: User | null = null;
getName(): string {
let name = ""
name += this.gameHandle
if(this.user) {
name += " (" + this.user.getUserRealName() + ")";
}
return name;
}
}

12
packages/bridge-ui/src/app/models/season-standing.model.ts

@ -1,6 +1,16 @@
import { Expose, Type } from 'class-transformer';
import { Racer } from "./racer.model";
import { Season } from './season.model';
export class SeasonStanding {
racer?: Racer;
@Expose()
@Type(() => Season)
season: Season | null = null;
@Expose()
@Type(() => Racer)
racer: Racer | null = null;;
@Expose()
points: number = 0;
}

27
packages/bridge-ui/src/app/models/season.model.ts

@ -1,12 +1,35 @@
import { Expose, Type } from 'class-transformer';
import { Race } from "./race.model";
import { SeasonStanding } from "./season-standing.model";
import { Racer } from './racer.model';
export class Season {
@Expose()
id: string = "0";
@Expose()
title: string = "";
@Expose()
subTitle: string = "";
startingDate: Date = new Date(Date.now());
@Expose()
@Type(() => Date)
startingDate: Date = new Date(0);
@Expose()
@Type(() => Race)
races: Race[] = [];
racers: string[] = [];
@Expose()
@Type(() => Racer)
racers: Racer[] = [];
@Expose()
@Type(() => SeasonStanding)
standings: SeasonStanding[] = [];
getStartingDate() {
return this.startingDate.toUTCString();
}
}

51
packages/bridge-ui/src/app/models/user.model.ts

@ -0,0 +1,51 @@
import { Expose, Type } from 'class-transformer';
import { Racer } from './racer.model';
export class User {
@Expose()
auth0id: string = "";
@Expose()
nickname: string = "";
@Expose()
email: string = "";
@Expose()
picture: string = "";
@Expose()
realName: string = "";
@Expose()
lastLogin: Date | null = null;
@Expose({ name: 'racer' })
@Type(() => Racer)
racer: Racer | null = null;
getUserName() : string {
return this.nickname;
}
getUserId() : string {
return this.auth0id.replace("auth0|", "") || "";
}
compareId(otherId: string) {
let other = otherId.replace("auth0|", "")
return this.getUserId() == other;
}
getUserPicture() : string {
return this.picture || "";
}
getUserEmail() : string {
return this.email || "";
}
getUserRealName() : string {
return this.realName || "??? ???";
}
}

4
packages/bridge-ui/src/app/pages/user/user.component.html

@ -18,7 +18,7 @@
<mat-card>
<mat-card-header>
@if(!user.racer) {
@if(!user || !user.racer) {
<mat-card-title>Claim your racer</mat-card-title>
}
@else {
@ -28,7 +28,7 @@
<mat-card-content>
</mat-card-content>
@if(!user.racer) {
@if(!user || !user.racer) {
<mat-card-actions>
<button mat-button color="accent" (click)="openClaimRacerDialog()">Claim</button>
</mat-card-actions>

3
packages/bridge-ui/src/app/pages/user/user.component.ts

@ -9,6 +9,7 @@ import { MatDialog } from '@angular/material/dialog';
import { UsersService } from '../../services/users.service';
import { ClaimRacerDialogComponent } from '../../components/claim-racer-dialog/claim-racer-dialog.component';
import { ActivatedRoute } from '@angular/router';
import { User } from '../../models/user.model';
@Component({
@ -26,7 +27,7 @@ import { ActivatedRoute } from '@angular/router';
export class UserComponent {
public userId: string = "";
public user: any = null;
public user: User | undefined | null = null;
constructor(
public usersService: UsersService,

65
packages/bridge-ui/src/app/services/race-result.service.ts

@ -16,71 +16,6 @@ export class RaceResultService {
) {
}
/*
getAllRacers(): Observable<Array<Racer>> {
return this.httpClient.get<Array<Racer>>("assets/racers.json");
}
getRacer(id: string): Observable<Racer | undefined> {
let promise = new Promise<Racer|undefined>((resolve, reject) => {
this.httpClient.get<Array<Racer>>("assets/racers.json").subscribe(data => {
for(let racer of data) {
if(racer.id == id) {
resolve(racer);
}
}
reject(undefined);
});
});
return from(promise);
}
*/
getRaceResultsForRacer(racerId: string): Observable<RaceEntry[]> {
let promise = new Promise<RaceEntry[]>((resolve, reject) => {
this.httpClient.get<Array<RaceEntry>>("assets/raceEntry.json").subscribe(data => {
let results: RaceEntry[] = [];
for(let result of data) {
if(result.racer_id == racerId) {
results.push(result);
}
}
resolve(results);
});
});
return from(promise);
}
getRaceResultsForRace(raceId: string): Observable<RaceEntry[]> {
let promise = new Promise<RaceEntry[]>((resolve, reject) => {
this.httpClient.get<Array<RaceEntry>>("assets/raceEntry.json").subscribe(data => {
let results: RaceEntry[] = [];
for(let result of data) {
if(result.race_id == raceId) {
results.push(result);
}
}
resolve(results);
});
});
return from(promise);
}
getRaceResultsForRacerInRace(racerId: string, raceId: string): Observable<RaceEntry[]> {
let promise = new Promise<RaceEntry[]>((resolve, reject) => {
this.httpClient.get<Array<RaceEntry>>("assets/raceEntry.json").subscribe(data => {
let results: RaceEntry[] = [];
for(let result of data) {
if(result.race_id == raceId && result.racer_id == racerId) {
results.push(result);
}
}
resolve(results);
});
});
return from(promise);
}
getGhost(raceResultId: string) {
const httpOptions = {
responseType: 'blob' as 'json'

18
packages/bridge-ui/src/app/services/racers.service.ts

@ -12,22 +12,4 @@ export class RacersService {
constructor(private httpClient: HttpClient) {
}
getAllRacers(): Observable<Array<Racer>> {
return this.httpClient.get<Array<Racer>>("assets/racers.json");
}
getRacer(id: string): Observable<Racer | undefined> {
let promise = new Promise<Racer|undefined>((resolve, reject) => {
this.httpClient.get<Array<Racer>>("assets/racers.json").subscribe(data => {
for(let racer of data) {
if(racer.id == id) {
resolve(racer);
}
}
reject(undefined);
});
});
return from(promise);
}
}

23
packages/bridge-ui/src/app/services/races.service.ts

@ -1,9 +1,11 @@
import { Injectable } from '@angular/core';
import { HttpClient } from "@angular/common/http";
import { Observable, from } from "rxjs";
import { plainToClass } from 'class-transformer';
import { Race } from '../models/race.model';
import { ServerEndpointService } from './server-endpoint.service';
import { RaceEntry } from '../models/raceEntry.model';
@Injectable({
providedIn: 'root'
@ -16,16 +18,19 @@ export class RacesService {
) {
}
getAllRaces(): Observable<Array<Race>> {
return this.httpClient.get<Array<Race>>("assets/races.json");
}
getRace(id: string) {
return this.httpClient.get(this.serverEndpointService.getCurrentEndpoint()+"races/"+id);
}
getRaceResults(id: string) {
return this.httpClient.get(this.serverEndpointService.getCurrentEndpoint()+"races/"+id+"/results");
//return this.httpClient.get(this.serverEndpointService.getCurrentEndpoint()+"races/"+id);
throw new Error();
}
getRaceResults(id: string): Observable<Array<RaceEntry>> {
let promise = new Promise<Array<RaceEntry>>((resolve, reject) =>{
this.httpClient.get<Array<RaceEntry>>(this.serverEndpointService.getCurrentEndpoint()+"races/"+id+"/results").subscribe(data => {
let _raceEntries = plainToClass(RaceEntry, data, { excludeExtraneousValues: true, enableCircularCheck: true });
resolve(_raceEntries);
});
});
return from(promise);
}
getMapInfo(mapUID: string) {

49
packages/bridge-ui/src/app/services/seasons.service.ts

@ -2,6 +2,8 @@ import { Injectable } from '@angular/core';
import { HttpClient } from "@angular/common/http";
import { Observable, from } from "rxjs";
import { plainToClass } from 'class-transformer';
import { Season } from '../models/season.model';
import { ServerEndpointService } from './server-endpoint.service';
@ -20,60 +22,21 @@ export class SeasonsService {
)
{}
private convertToClientSeason(data: any): Season {
let _season = new Season();
_season.id = data.id.toString();
_season.title = data.title;
_season.subTitle = data.subTitle;
_season.startingDate = new Date(data.startingDate);
_season.racers = [];
_season.races = data.races;
_season.standings = data.standings;
console.log(_season);
return _season;
}
getAllSeasons(): Observable<Array<Season>> {
if(this.useTestData) {
return this.httpClient.get<Array<Season>>("assets/Seasons.json");
}
let promise = new Promise<Array<Season>>((resolve, reject) =>{
this.httpClient.get<Array<Season>>(this.serverEndpointService.getCurrentEndpoint()+"seasons/").subscribe(data => {
let seasons: Season[] = [];
for(let server_season of data) {
let _season = this.convertToClientSeason(server_season);
seasons.push(_season)
console.log(_season)
console.log(server_season)
}
resolve(seasons);
//reject(undefined);
let _seasons = plainToClass(Season, data, { excludeExtraneousValues: true, enableCircularCheck: true });
resolve(_seasons);
});
});
return from(promise);
}
getSeason(id: string): Observable<Season | undefined> {
if(this.useTestData) {
let promise = new Promise<Season|undefined>((resolve, reject) =>{
this.httpClient.get<Array<Season>>("assets/Seasons.json").subscribe(data => {
for(let season of data) {
if(season.id.toString() == id) {
resolve(season);
}
}
reject(undefined);
});
});
return from(promise);
}
let promise = new Promise<Season|undefined>((resolve, reject) =>{
this.httpClient.get<Array<Season>>(this.serverEndpointService.getCurrentEndpoint()+"seasons/"+id).subscribe(data => {
let _season = this.convertToClientSeason(data);
console.log(data);
console.log(_season);
let _seasons = plainToClass(Season, data, { excludeExtraneousValues: true, enableCircularCheck: true });
let _season = _seasons instanceof Season ? _seasons : _seasons[0]
resolve(_season);
});
});

2
packages/bridge-ui/src/app/services/server-side-events.service.ts

@ -1,6 +1,6 @@
import { Injectable } from '@angular/core';
import { ServerEndpointService } from './server-endpoint.service';
//var EventEmitter2 = require('eventemitter2');
import { EventEmitter } from 'eventemitter3';
@Injectable({

18
packages/bridge-ui/src/app/services/users.service.ts

@ -1,10 +1,13 @@
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { AuthService, User } from '@auth0/auth0-angular';
import { AuthService } from '@auth0/auth0-angular';
import { Observable, from } from "rxjs";
import * as jwt_decode from 'jwt-decode';
import { plainToClass, plainToInstance } from 'class-transformer';
import { ServerEndpointService } from './server-endpoint.service';
import { User } from '../models/user.model';
@Injectable({
providedIn: 'root'
@ -13,7 +16,7 @@ export class UsersService {
isAuthenticated = false;
permissions: string[] = [];
localUser: User | null | undefined = null;
localUser: any | null | undefined = null;
additionalInfo : any = null;
constructor(
@ -52,13 +55,12 @@ export class UsersService {
}
getUserdetails(id: string) {
let promise = new Promise<any|undefined>((resolve, reject) => {
let promise = new Promise<User|undefined>((resolve, reject) => {
this.httpClient.get<Array<any>>(this.serverEndpointService.getCurrentEndpoint()+"users/"+"auth0|"+id).subscribe(data => {
let _season = data; //this.convertToClientSeason(data);
console.log(data);
console.log(_season);
resolve(_season);
this.httpClient.get(this.serverEndpointService.getCurrentEndpoint()+"users/"+"auth0|"+id).subscribe(data => {
let user = plainToClass(User, data, { excludeExtraneousValues: true, enableCircularCheck: true });
let val = user instanceof User ? user : user[0]
resolve(val);
});
});
return from(promise);

15
packages/bridge-ui/src/app/services/utils.service.ts

@ -0,0 +1,15 @@
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root',
})
export class UtilsService {
formatMilliseconds(milliseconds: number)
{
const minutes = Math.floor(milliseconds / (1000 * 60));
const seconds = Math.floor((milliseconds % (1000 * 60)) / 1000);
const remainingMilliseconds = milliseconds % 1000;
return `${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}:${String(remainingMilliseconds).padStart(3, '0')}`;
}
}

1
packages/bridge-ui/src/main.ts

@ -1,4 +1,5 @@
import { bootstrapApplication } from '@angular/platform-browser';
import 'reflect-metadata';
import { appConfig } from './app/app.config';
import { AppComponent } from './app/app.component';

Loading…
Cancel
Save