mirror of
https://github.com/TomasiDeveloping/PlayerManagement.git
synced 2026-04-16 09:12:20 +00:00
0.5.0-beta: Player vs duel bar chart implemented, add tooltips
This commit is contained in:
parent
9ba4189a0d
commit
f414b60e5e
@ -3,7 +3,6 @@ using Application.Errors;
|
|||||||
using Application.Interfaces;
|
using Application.Interfaces;
|
||||||
using Asp.Versioning;
|
using Asp.Versioning;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Http;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
namespace Api.Controllers.v1
|
namespace Api.Controllers.v1
|
||||||
@ -36,5 +35,25 @@ namespace Api.Controllers.v1
|
|||||||
return StatusCode(StatusCodes.Status500InternalServerError);
|
return StatusCode(StatusCodes.Status500InternalServerError);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpGet("Player/{playerId:guid}")]
|
||||||
|
public async Task<ActionResult<List<VsDuelParticipantDetailDto>>> GetPlayerVsDuelParticipants(Guid playerId, [FromQuery] int last,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var numberOfParticipationResult =
|
||||||
|
await vsDuelParticipantRepository.GetVsDuelParticipantDetailsAsync(playerId, last,
|
||||||
|
cancellationToken);
|
||||||
|
return numberOfParticipationResult.IsFailure
|
||||||
|
? BadRequest(numberOfParticipationResult.Error)
|
||||||
|
: Ok(numberOfParticipationResult.Value);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
logger.LogError(e, e.Message);
|
||||||
|
return StatusCode(StatusCodes.Status500InternalServerError);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,10 @@
|
|||||||
|
namespace Application.DataTransferObjects.VsDuelParticipant;
|
||||||
|
|
||||||
|
public class VsDuelParticipantDetailDto
|
||||||
|
{
|
||||||
|
public Guid PlayerId { get; set; }
|
||||||
|
|
||||||
|
public DateTime EventDate { get; set; }
|
||||||
|
|
||||||
|
public long WeeklyPoints { get; set; }
|
||||||
|
}
|
||||||
@ -6,4 +6,7 @@ namespace Application.Interfaces;
|
|||||||
public interface IVsDuelParticipantRepository
|
public interface IVsDuelParticipantRepository
|
||||||
{
|
{
|
||||||
Task<Result<VsDuelParticipantDto>> UpdateVsDuelParticipant(VsDuelParticipantDto vsDuelParticipantDto, CancellationToken cancellationToken);
|
Task<Result<VsDuelParticipantDto>> UpdateVsDuelParticipant(VsDuelParticipantDto vsDuelParticipantDto, CancellationToken cancellationToken);
|
||||||
|
|
||||||
|
Task<Result<List<VsDuelParticipantDetailDto>>> GetVsDuelParticipantDetailsAsync(Guid playerId, int last,
|
||||||
|
CancellationToken cancellationToken);
|
||||||
}
|
}
|
||||||
@ -12,5 +12,8 @@ public class VsDuelParticipantProfile : Profile
|
|||||||
.ForMember(des => des.PlayerName, opt => opt.MapFrom(src => src.Player.PlayerName));
|
.ForMember(des => des.PlayerName, opt => opt.MapFrom(src => src.Player.PlayerName));
|
||||||
|
|
||||||
CreateMap<VsDuelParticipantDto, VsDuelParticipant>();
|
CreateMap<VsDuelParticipantDto, VsDuelParticipant>();
|
||||||
|
|
||||||
|
CreateMap<VsDuelParticipant, VsDuelParticipantDetailDto>()
|
||||||
|
.ForMember(des => des.EventDate, opt => opt.MapFrom(src => src.VsDuel.EventDate));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3,6 +3,7 @@ using Application.DataTransferObjects.VsDuelParticipant;
|
|||||||
using Application.Errors;
|
using Application.Errors;
|
||||||
using Application.Interfaces;
|
using Application.Interfaces;
|
||||||
using AutoMapper;
|
using AutoMapper;
|
||||||
|
using AutoMapper.QueryableExtensions;
|
||||||
using Database;
|
using Database;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
@ -31,4 +32,17 @@ public class VsDuelParticipantRepository(ApplicationContext context, IMapper map
|
|||||||
return Result.Failure<VsDuelParticipantDto>(GeneralErrors.DatabaseError);
|
return Result.Failure<VsDuelParticipantDto>(GeneralErrors.DatabaseError);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<Result<List<VsDuelParticipantDetailDto>>> GetVsDuelParticipantDetailsAsync(Guid playerId, int last, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var vsDuelPlayersParticipants = await context.VsDuelParticipants
|
||||||
|
.ProjectTo<VsDuelParticipantDetailDto>(mapper.ConfigurationProvider)
|
||||||
|
.AsNoTracking()
|
||||||
|
.OrderByDescending(e => e.EventDate)
|
||||||
|
.Where(e => e.PlayerId == playerId)
|
||||||
|
.Take(last)
|
||||||
|
.ToListAsync(cancellationToken);
|
||||||
|
|
||||||
|
return Result.Success(vsDuelPlayersParticipants);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -13,6 +13,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Application", "Application\
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{54A90642-561A-4BB1-A94E-469ADEE60C69}") = "Ui", "Ui\Ui.esproj", "{77168004-AF1E-4F51-A096-E8E8BF18A37A}"
|
Project("{54A90642-561A-4BB1-A94E-469ADEE60C69}") = "Ui", "Ui\Ui.esproj", "{77168004-AF1E-4F51-A096-E8E8BF18A37A}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Projektmappenelemente", "Projektmappenelemente", "{E8BE2EF5-0D8D-4D68-9979-0680938F26DF}"
|
||||||
|
ProjectSection(SolutionItems) = preProject
|
||||||
|
README.md = README.md
|
||||||
|
EndProjectSection
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
|||||||
97
README.md
97
README.md
@ -1 +1,96 @@
|
|||||||
# PlayerManagement
|
# PlayerManagement
|
||||||
|
## Changelog
|
||||||
|
|
||||||
|
All notable changes to this project are documented here.
|
||||||
|
This project is currently in the **Beta Phase**.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **[0.5.0-beta]** - *2025-01-21*
|
||||||
|
#### ✨ Added
|
||||||
|
- **Player VS Duel**: In the player detail view, the VS points can now be viewed as a bar chart.
|
||||||
|
|
||||||
|
#### 🛠️ Fixed
|
||||||
|
- *(N/A)*
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **[0.4.1-beta]** - *2025-01-21*
|
||||||
|
#### ✨ Added
|
||||||
|
- **Excel Import**: Players can now be imported via Excel.
|
||||||
|
|
||||||
|
#### 🛠️ Fixed
|
||||||
|
- **Week Pipe Logic**: Corrected calculation logic for weekly processing.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **[0.4.0-beta]** - *2025-01-20*
|
||||||
|
#### ✨ Added
|
||||||
|
- **Player Dismissal Page**: A new GUI page was added for dismissing players.
|
||||||
|
|
||||||
|
#### 🛠️ Fixed
|
||||||
|
- *(N/A)*
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **[0.3.6-beta]** - *2025-01-16*
|
||||||
|
#### ✨ Added
|
||||||
|
- **Player Dismissal Function**: Core dismissal functionality implemented.
|
||||||
|
|
||||||
|
#### 🛠️ Fixed
|
||||||
|
- *(N/A)*
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **[0.3.5-beta]** - *2025-01-09*
|
||||||
|
#### ✨ Added
|
||||||
|
- *(N/A)*
|
||||||
|
|
||||||
|
#### 🛠️ Fixed
|
||||||
|
- **MVP Formula**: Corrected MVP calculation formula.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **[0.3.4-beta]** - *2025-01-07*
|
||||||
|
#### ✨ Added
|
||||||
|
- **Alliance MVP Calculation**: Implemented MVP calculation for alliances with API endpoint support.
|
||||||
|
|
||||||
|
#### 🛠️ Fixed
|
||||||
|
- *(N/A)*
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **[0.3.3-beta]** - *2024-12-17*
|
||||||
|
#### ✨ Added
|
||||||
|
- **Custom Event**: Introduced custom event functionality.
|
||||||
|
|
||||||
|
#### 🛠️ Fixed
|
||||||
|
- *(N/A)*
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **[0.3.2-beta]** - *2024-12-03*
|
||||||
|
#### ✨ Added
|
||||||
|
- **Event Progress**: "In Progress" status added to events.
|
||||||
|
- **League Details in VS Duel**: Added league tiers (e.g., Silver, Gold, Diamond).
|
||||||
|
|
||||||
|
#### 🛠️ Fixed
|
||||||
|
- *(N/A)*
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **[0.3.1-beta]** - *2024-11-28*
|
||||||
|
#### ✨ Added
|
||||||
|
- **Zombie Siege Event**: Introduced a new Zombie Siege event.
|
||||||
|
|
||||||
|
#### 🛠️ Fixed
|
||||||
|
- *(N/A)*
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **[0.3.0-beta]** - *2024-11-26*
|
||||||
|
#### ✨ Added
|
||||||
|
- **Initial Beta Release**: Core features introduced in the first beta release.
|
||||||
|
|
||||||
|
#### 🛠️ Fixed
|
||||||
|
- *(N/A in the initial release)*
|
||||||
|
|||||||
36
Ui/package-lock.json
generated
36
Ui/package-lock.json
generated
@ -20,6 +20,7 @@
|
|||||||
"@ng-bootstrap/ng-bootstrap": "^17.0.1",
|
"@ng-bootstrap/ng-bootstrap": "^17.0.1",
|
||||||
"@popperjs/core": "^2.11.8",
|
"@popperjs/core": "^2.11.8",
|
||||||
"@sweetalert2/theme-dark": "^5.0.18",
|
"@sweetalert2/theme-dark": "^5.0.18",
|
||||||
|
"ag-charts-angular": "^11.0.4",
|
||||||
"bootstrap": "^5.3.2",
|
"bootstrap": "^5.3.2",
|
||||||
"bootstrap-icons": "^1.11.3",
|
"bootstrap-icons": "^1.11.3",
|
||||||
"bootswatch": "^5.3.3",
|
"bootswatch": "^5.3.3",
|
||||||
@ -5226,6 +5227,41 @@
|
|||||||
"node": ">=8.9.0"
|
"node": ">=8.9.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/ag-charts-angular": {
|
||||||
|
"version": "11.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/ag-charts-angular/-/ag-charts-angular-11.0.4.tgz",
|
||||||
|
"integrity": "sha512-1D9xEky6RcwJ49SLGScrVyJNOIy+wH32CaEY4JTdS36QqgFcOVwm5QTiMf/zTa+Qsbz4HfRVBkYpBQuMR0s2Cw==",
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.3.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@angular/common": "^17.0.0 || ^18.0.0 || ^19.0.0",
|
||||||
|
"@angular/core": "^17.0.0 || ^18.0.0 || ^19.0.0",
|
||||||
|
"ag-charts-community": "11.0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/ag-charts-community": {
|
||||||
|
"version": "11.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/ag-charts-community/-/ag-charts-community-11.0.4.tgz",
|
||||||
|
"integrity": "sha512-TFShWfZaA1yJ/hb3jwtNAqBG2Qy9VvoQ9mWLr29ilT6+2R2e30RSk2oH7FAQ2l5nS1367dRf137Td9tUTTuVLg==",
|
||||||
|
"peer": true,
|
||||||
|
"dependencies": {
|
||||||
|
"ag-charts-locale": "11.0.4",
|
||||||
|
"ag-charts-types": "11.0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/ag-charts-locale": {
|
||||||
|
"version": "11.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/ag-charts-locale/-/ag-charts-locale-11.0.4.tgz",
|
||||||
|
"integrity": "sha512-xCQA8CtcUyqU4qYg7u9oUQ+SghIsWAQvY60Bu0ghJJ/bDeW8+ptEU0ogBapuDqfb9B9kqWKgASxbX6diqb+HVQ==",
|
||||||
|
"peer": true
|
||||||
|
},
|
||||||
|
"node_modules/ag-charts-types": {
|
||||||
|
"version": "11.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/ag-charts-types/-/ag-charts-types-11.0.4.tgz",
|
||||||
|
"integrity": "sha512-K/Mi7FXvSCoABLSrqQ70k1QrIL5R6RNCt2NAppOxMEir+DVFPqKZtghruobc2MGVUUKkT9MCn6Dun+fL6yZjfA==",
|
||||||
|
"peer": true
|
||||||
|
},
|
||||||
"node_modules/agent-base": {
|
"node_modules/agent-base": {
|
||||||
"version": "7.1.1",
|
"version": "7.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz",
|
||||||
|
|||||||
@ -22,6 +22,7 @@
|
|||||||
"@ng-bootstrap/ng-bootstrap": "^17.0.1",
|
"@ng-bootstrap/ng-bootstrap": "^17.0.1",
|
||||||
"@popperjs/core": "^2.11.8",
|
"@popperjs/core": "^2.11.8",
|
||||||
"@sweetalert2/theme-dark": "^5.0.18",
|
"@sweetalert2/theme-dark": "^5.0.18",
|
||||||
|
"ag-charts-angular": "^11.0.4",
|
||||||
"bootstrap": "^5.3.2",
|
"bootstrap": "^5.3.2",
|
||||||
"bootstrap-icons": "^1.11.3",
|
"bootstrap-icons": "^1.11.3",
|
||||||
"bootswatch": "^5.3.3",
|
"bootswatch": "^5.3.3",
|
||||||
|
|||||||
@ -27,7 +27,6 @@ import {jwtInterceptor} from "./interceptors/jwt.interceptor";
|
|||||||
import { PlayerNoteModalComponent } from './modals/player-note-modal/player-note-modal.component';
|
import { PlayerNoteModalComponent } from './modals/player-note-modal/player-note-modal.component';
|
||||||
import { PlayerAdmonitionModalComponent } from './modals/player-admonition-modal/player-admonition-modal.component';
|
import { PlayerAdmonitionModalComponent } from './modals/player-admonition-modal/player-admonition-modal.component';
|
||||||
import { PlayerInfoMarshalGuardComponent } from './pages/player-information/player-info-marshal-guard/player-info-marshal-guard.component';
|
import { PlayerInfoMarshalGuardComponent } from './pages/player-information/player-info-marshal-guard/player-info-marshal-guard.component';
|
||||||
import { PlayerInfoVsDuelComponent } from './pages/player-information/player-info-vs-duel/player-info-vs-duel.component';
|
|
||||||
import { WeekPipe } from './helpers/week.pipe';
|
import { WeekPipe } from './helpers/week.pipe';
|
||||||
import { PlayerInfoDesertStormComponent } from './pages/player-information/player-info-desert-storm/player-info-desert-storm.component';
|
import { PlayerInfoDesertStormComponent } from './pages/player-information/player-info-desert-storm/player-info-desert-storm.component';
|
||||||
import { PlayerInfoCustomEventComponent } from './pages/player-information/player-info-custom-event/player-info-custom-event.component';
|
import { PlayerInfoCustomEventComponent } from './pages/player-information/player-info-custom-event/player-info-custom-event.component';
|
||||||
@ -55,6 +54,8 @@ import { CustomEventDetailComponent } from './pages/custom-event/custom-event-de
|
|||||||
import { DismissPlayerComponent } from './pages/dismiss-player/dismiss-player.component';
|
import { DismissPlayerComponent } from './pages/dismiss-player/dismiss-player.component';
|
||||||
import { PlayerDismissInformationModalComponent } from './modals/player-dismiss-information-modal/player-dismiss-information-modal.component';
|
import { PlayerDismissInformationModalComponent } from './modals/player-dismiss-information-modal/player-dismiss-information-modal.component';
|
||||||
import { PlayerExcelImportModalComponent } from './modals/player-excel-import-modal/player-excel-import-modal.component';
|
import { PlayerExcelImportModalComponent } from './modals/player-excel-import-modal/player-excel-import-modal.component';
|
||||||
|
import {AgCharts} from "ag-charts-angular";
|
||||||
|
import {PlayerInfoVsDuelComponent} from "./pages/player-information/player-info-vs-duel/player-info-vs-duel.component";
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
@ -73,10 +74,10 @@ import { PlayerExcelImportModalComponent } from './modals/player-excel-import-mo
|
|||||||
PlayerNoteModalComponent,
|
PlayerNoteModalComponent,
|
||||||
PlayerAdmonitionModalComponent,
|
PlayerAdmonitionModalComponent,
|
||||||
PlayerInfoMarshalGuardComponent,
|
PlayerInfoMarshalGuardComponent,
|
||||||
PlayerInfoVsDuelComponent,
|
|
||||||
WeekPipe,
|
WeekPipe,
|
||||||
PlayerInfoDesertStormComponent,
|
PlayerInfoDesertStormComponent,
|
||||||
PlayerInfoCustomEventComponent,
|
PlayerInfoCustomEventComponent,
|
||||||
|
PlayerInfoVsDuelComponent,
|
||||||
VsDuelCreateModalComponent,
|
VsDuelCreateModalComponent,
|
||||||
VsDuelDetailComponent,
|
VsDuelDetailComponent,
|
||||||
VsDuelEditComponent,
|
VsDuelEditComponent,
|
||||||
@ -119,7 +120,8 @@ import { PlayerExcelImportModalComponent } from './modals/player-excel-import-mo
|
|||||||
config: {
|
config: {
|
||||||
tokenGetter: () => localStorage.getItem(''),
|
tokenGetter: () => localStorage.getItem(''),
|
||||||
}
|
}
|
||||||
})
|
}),
|
||||||
|
AgCharts
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
provideHttpClient(withInterceptors([spinnerInterceptor, jwtInterceptor]))
|
provideHttpClient(withInterceptors([spinnerInterceptor, jwtInterceptor]))
|
||||||
|
|||||||
@ -5,3 +5,9 @@ export interface VsDuelParticipantModel {
|
|||||||
weeklyPoints: number;
|
weeklyPoints: number;
|
||||||
playerName: string;
|
playerName: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface VsDuelParticipantDetailModel {
|
||||||
|
playerId: string;
|
||||||
|
eventDate: Date;
|
||||||
|
weeklyPoints: number;
|
||||||
|
}
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
<a class="navbar-brand" routerLink="/">{{loggedInUser.allianceName}}</a>
|
<a class="navbar-brand" routerLink="/">{{loggedInUser.allianceName}}</a>
|
||||||
|
|
||||||
<!-- Displaying the application version -->
|
<!-- Displaying the application version -->
|
||||||
<span class="version">v.{{version}}</span>
|
<span ngbTooltip="Changelog" placement="auto" (click)="onVersion()" class="version">v.{{version}}</span>
|
||||||
|
|
||||||
<!-- Toggle button for collapsed navigation on smaller screens -->
|
<!-- Toggle button for collapsed navigation on smaller screens -->
|
||||||
<button (click)="isShown = !isShown" aria-controls="navbar" aria-expanded="false" aria-label="Toggle navigation"
|
<button (click)="isShown = !isShown" aria-controls="navbar" aria-expanded="false" aria-label="Toggle navigation"
|
||||||
|
|||||||
@ -41,4 +41,8 @@ export class NavigationComponent implements OnInit, OnDestroy {
|
|||||||
this._authStateChange$.unsubscribe();
|
this._authStateChange$.unsubscribe();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onVersion() {
|
||||||
|
window.open('https://github.com/TomasiDeveloping/PlayerManagement', '_blank');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -98,8 +98,8 @@
|
|||||||
<td>{{user.role}}</td>
|
<td>{{user.role}}</td>
|
||||||
<td>
|
<td>
|
||||||
<div class="d-flex justify-content-around">
|
<div class="d-flex justify-content-around">
|
||||||
<i (click)="onEditUser(user)" class="bi custom-edit-icon bi-pencil-fill"></i>
|
<i ngbTooltip="Edit" placement="auto" (click)="onEditUser(user)" class="bi custom-edit-icon bi-pencil-fill"></i>
|
||||||
<i (click)="onDeleteUser(user)" class="bi custom-delete-icon bi-trash3"></i>
|
<i ngbTooltip="Delete" placement="auto" (click)="onDeleteUser(user)" class="bi custom-delete-icon bi-trash3"></i>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@ -135,9 +135,9 @@
|
|||||||
<td>{{customEvent.createdBy}}</td>
|
<td>{{customEvent.createdBy}}</td>
|
||||||
<td>
|
<td>
|
||||||
<div class="d-flex gap-3 justify-content-around">
|
<div class="d-flex gap-3 justify-content-around">
|
||||||
<i (click)="onGoToCustomEventDetail(customEvent)" class="bi custom-info-icon bi-info-circle-fill"></i>
|
<i ngbTooltip="Show details" placement="auto" (click)="onGoToCustomEventDetail(customEvent)" class="bi custom-info-icon bi-info-circle-fill"></i>
|
||||||
<i (click)="onEditCustomEvent(customEvent)" class="bi custom-edit-icon bi-pencil-fill"></i>
|
<i ngbTooltip="Edit" placement="auto" (click)="onEditCustomEvent(customEvent)" class="bi custom-edit-icon bi-pencil-fill"></i>
|
||||||
<i (click)="onDeleteCustomEvent(customEvent)" class="bi custom-delete-icon bi-trash3"></i>
|
<i ngbTooltip="Delete" placement="auto" (click)="onDeleteCustomEvent(customEvent)" class="bi custom-delete-icon bi-trash3"></i>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@ -143,9 +143,9 @@
|
|||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div class="d-flex gap-3 justify-content-around">
|
<div class="d-flex gap-3 justify-content-around">
|
||||||
<i (click)="onDesertStormDetail(desertStorm)" class="bi custom-info-icon bi-info-circle-fill"></i>
|
<i ngbTooltip="Show details" placement="auto" (click)="onDesertStormDetail(desertStorm)" class="bi custom-info-icon bi-info-circle-fill"></i>
|
||||||
<i (click)="onEditDesertStorm(desertStorm)" class="bi custom-edit-icon bi-pencil-fill"></i>
|
<i ngbTooltip="Edit" placement="auto" (click)="onEditDesertStorm(desertStorm)" class="bi custom-edit-icon bi-pencil-fill"></i>
|
||||||
<i (click)="onDeleteDesertStorm(desertStorm)" class="bi custom-delete-icon bi-trash3"></i>
|
<i ngbTooltip="Delete" placement="auto" (click)="onDeleteDesertStorm(desertStorm)" class="bi custom-delete-icon bi-trash3"></i>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@ -22,9 +22,9 @@
|
|||||||
<td>{{player.dismissalReason}}</td>
|
<td>{{player.dismissalReason}}</td>
|
||||||
<td>
|
<td>
|
||||||
<div class="d-flex gap-3 justify-content-around">
|
<div class="d-flex gap-3 justify-content-around">
|
||||||
<i (click)="onPlayerInformation(player)" class="bi custom-info-icon bi-info-circle-fill"></i>
|
<i ngbTooltip="Show information" placement="auto" (click)="onPlayerInformation(player)" class="bi custom-info-icon bi-info-circle-fill"></i>
|
||||||
<i (click)="onReactivePlayer(player)" class="bi custom-edit-icon bi-bootstrap-reboot"></i>
|
<i ngbTooltip="Rejoining" placement="auto" (click)="onReactivePlayer(player)" class="bi custom-edit-icon bi-bootstrap-reboot"></i>
|
||||||
<i (click)="onDeletePlayer(player)" class="bi custom-delete-icon bi bi-trash3"></i>
|
<i ngbTooltip="Delete" placement="auto" (click)="onDeletePlayer(player)" class="bi custom-delete-icon bi bi-trash3"></i>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@ -110,9 +110,9 @@
|
|||||||
<td>{{marshalGuard.createdBy}}</td>
|
<td>{{marshalGuard.createdBy}}</td>
|
||||||
<td>
|
<td>
|
||||||
<div class="d-flex gap-3 justify-content-around">
|
<div class="d-flex gap-3 justify-content-around">
|
||||||
<i (click)="onGoToMarshalGuardDetail(marshalGuard)" class="bi custom-info-icon bi-info-circle-fill"></i>
|
<i ngbTooltip="Show details" placement="auto" (click)="onGoToMarshalGuardDetail(marshalGuard)" class="bi custom-info-icon bi-info-circle-fill"></i>
|
||||||
<i (click)="onEditMarshalGuard(marshalGuard)" class="bi custom-edit-icon bi-pencil-fill"></i>
|
<i ngbTooltip="Edit" placement="auto" (click)="onEditMarshalGuard(marshalGuard)" class="bi custom-edit-icon bi-pencil-fill"></i>
|
||||||
<i (click)="onDeleteMarshalGuard(marshalGuard)" class="bi custom-delete-icon bi-trash3"></i>
|
<i ngbTooltip="Delete" placement="auto" (click)="onDeleteMarshalGuard(marshalGuard)" class="bi custom-delete-icon bi-trash3"></i>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@ -0,0 +1,3 @@
|
|||||||
|
ag-charts {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
@ -1 +1,21 @@
|
|||||||
<app-under-development></app-under-development>
|
<div>
|
||||||
|
<form class="d-flex gap-2 align-items-center justify-content-center mb-3">
|
||||||
|
<div>
|
||||||
|
<label for="inputField" class="col-form-label">Last:</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<input [ngModelOptions]="{standalone: true}" type="number" id="inputField" class="form-control" placeholder="Input"
|
||||||
|
[(ngModel)]="numberOfLoadVsDuels">
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<button (click)="onReloadVsDuels()" type="submit"
|
||||||
|
class="btn btn-primary">{{ vsDuelsLoaded ? 'Reload' : 'load' }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
@if (vsDuelsLoaded) {
|
||||||
|
<ag-charts [options]="options"></ag-charts>
|
||||||
|
}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|||||||
@ -1,10 +1,92 @@
|
|||||||
import {Component} from '@angular/core';
|
import {Component, inject, Input} from '@angular/core';
|
||||||
|
import { AgChartOptions } from "ag-charts-community";
|
||||||
|
import {DatePipe} from "@angular/common";
|
||||||
|
import {VsDuelParticipantService} from "../../../services/vs-duel-participant.service";
|
||||||
|
import {ToastrService} from "ngx-toastr";
|
||||||
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-player-info-vs-duel',
|
selector: 'app-player-info-vs-duel',
|
||||||
templateUrl: './player-info-vs-duel.component.html',
|
templateUrl: './player-info-vs-duel.component.html',
|
||||||
styleUrl: './player-info-vs-duel.component.css'
|
styleUrl: './player-info-vs-duel.component.css',
|
||||||
|
providers: [DatePipe]
|
||||||
})
|
})
|
||||||
export class PlayerInfoVsDuelComponent {
|
export class PlayerInfoVsDuelComponent {
|
||||||
|
|
||||||
|
@Input({required: true}) playerId!: string;
|
||||||
|
|
||||||
|
private readonly _vsDuelParticipantsService: VsDuelParticipantService = inject(VsDuelParticipantService);
|
||||||
|
private readonly _datePipe: DatePipe = inject(DatePipe);
|
||||||
|
private readonly _toastr: ToastrService = inject(ToastrService);
|
||||||
|
|
||||||
|
numberOfLoadVsDuels: number = 10;
|
||||||
|
vsDuelsLoaded: boolean = false;
|
||||||
|
|
||||||
|
|
||||||
|
options: AgChartOptions = {
|
||||||
|
title: {
|
||||||
|
text: 'Weekly Points'
|
||||||
|
},
|
||||||
|
data: [],
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
type: 'bar',
|
||||||
|
xKey: 'date',
|
||||||
|
xName: 'Date',
|
||||||
|
yKey: 'points',
|
||||||
|
yName: 'Weekly Points',
|
||||||
|
stacked: false,
|
||||||
|
fill: 'blue'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
axes: [
|
||||||
|
{
|
||||||
|
type: 'number',
|
||||||
|
position: 'left',
|
||||||
|
label: {
|
||||||
|
formatter: (params: any) => {
|
||||||
|
return params.value.toLocaleString('en-US')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'category',
|
||||||
|
position: 'bottom',
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
getData(take: number) {
|
||||||
|
const chartData: {date: string, points: number}[] = [];
|
||||||
|
this._vsDuelParticipantsService.getVsDuelParticipantsDetail(this.playerId, take).subscribe({
|
||||||
|
next: ((response) => {
|
||||||
|
if (response) {
|
||||||
|
this.vsDuelsLoaded = true;
|
||||||
|
if (response.length < take) {
|
||||||
|
this._toastr.info('Fewer vs duels were held than wanted to be loaded');
|
||||||
|
this.numberOfLoadVsDuels = response.length;
|
||||||
|
}
|
||||||
|
response.forEach(player => {
|
||||||
|
const data: {date: string, points: number} = {
|
||||||
|
date: this._datePipe.transform(player.eventDate, 'dd.MM.yyyy')!,
|
||||||
|
points: player.weeklyPoints
|
||||||
|
};
|
||||||
|
chartData.push(data)
|
||||||
|
})
|
||||||
|
this.options = {
|
||||||
|
...this.options,
|
||||||
|
data: chartData.reverse()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
error: error => {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
onReloadVsDuels() {
|
||||||
|
this.getData(this.numberOfLoadVsDuels);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -59,7 +59,7 @@
|
|||||||
</h2>
|
</h2>
|
||||||
<div ngbAccordionCollapse>
|
<div ngbAccordionCollapse>
|
||||||
<div ngbAccordionBody>
|
<div ngbAccordionBody>
|
||||||
<app-player-info-vs-duel></app-player-info-vs-duel>
|
<app-player-info-vs-duel [playerId]="playerId"></app-player-info-vs-duel>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -58,7 +58,7 @@
|
|||||||
{{player.playerName}}
|
{{player.playerName}}
|
||||||
</div>
|
</div>
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<i (click)="onGoToPlayerInformation(player)" class="bi custom-info-icon bi-info-circle-fill"></i>
|
<i ngbTooltip="Show information" placement="auto" (click)="onGoToPlayerInformation(player)" class="bi custom-info-icon bi-info-circle-fill"></i>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
@ -66,8 +66,8 @@
|
|||||||
<td>{{player.rankName}}</td>
|
<td>{{player.rankName}}</td>
|
||||||
<td>
|
<td>
|
||||||
<div class="d-flex gap-3 justify-content-around">
|
<div class="d-flex gap-3 justify-content-around">
|
||||||
<i (click)="onEditPlayer(player)" class="bi custom-edit-icon bi-pencil-fill"></i>
|
<i ngbTooltip="Edit" placement="auto" (click)="onEditPlayer(player)" class="bi custom-edit-icon bi-pencil-fill"></i>
|
||||||
<i (click)="onDismissPlayer(player)" class="bi custom-delete-icon bi-person-dash"></i>
|
<i ngbTooltip="Dismiss" placement="auto" (click)="onDismissPlayer(player)" class="bi custom-delete-icon bi-person-dash"></i>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@ -64,9 +64,9 @@
|
|||||||
}</td>
|
}</td>
|
||||||
<td>
|
<td>
|
||||||
<div class="d-flex gap-3 justify-content-around">
|
<div class="d-flex gap-3 justify-content-around">
|
||||||
<i (click)="onGoToVsDuelInformation(vsDuel)" class="bi custom-info-icon bi-info-circle-fill"></i>
|
<i ngbTooltip="Show details" placement="auto" (click)="onGoToVsDuelInformation(vsDuel)" class="bi custom-info-icon bi-info-circle-fill"></i>
|
||||||
<i (click)="onEditVsDuel(vsDuel)" class="bi custom-edit-icon bi-pencil-fill"></i>
|
<i ngbTooltip="Edit" placement="auto" (click)="onEditVsDuel(vsDuel)" class="bi custom-edit-icon bi-pencil-fill"></i>
|
||||||
<i (click)="onDeleteVsDuel(vsDuel)" class="bi custom-delete-icon bi-trash3"></i>
|
<i ngbTooltip="Delete" placement="auto" (click)="onDeleteVsDuel(vsDuel)" class="bi custom-delete-icon bi-trash3"></i>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@ -92,9 +92,9 @@
|
|||||||
<td>{{zombieSiege.createdBy}}</td>
|
<td>{{zombieSiege.createdBy}}</td>
|
||||||
<td>
|
<td>
|
||||||
<div class="d-flex gap-3 justify-content-around">
|
<div class="d-flex gap-3 justify-content-around">
|
||||||
<i (click)="onGoToZombieSiegeDetail(zombieSiege)" class="bi custom-info-icon bi-info-circle-fill"></i>
|
<i ngbTooltip="Show details" placement="auto" (click)="onGoToZombieSiegeDetail(zombieSiege)" class="bi custom-info-icon bi-info-circle-fill"></i>
|
||||||
<i (click)="onEditZombieSiege(zombieSiege)" class="bi custom-edit-icon bi-pencil-fill"></i>
|
<i ngbTooltip="Edit" placement="auto" (click)="onEditZombieSiege(zombieSiege)" class="bi custom-edit-icon bi-pencil-fill"></i>
|
||||||
<i (click)="onDeleteZombieSiege(zombieSiege)" class="bi custom-delete-icon bi-trash3"></i>
|
<i ngbTooltip="Delete" placement="auto" (click)="onDeleteZombieSiege(zombieSiege)" class="bi custom-delete-icon bi-trash3"></i>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@ -1,8 +1,9 @@
|
|||||||
import {inject, Injectable} from '@angular/core';
|
import {inject, Injectable} from '@angular/core';
|
||||||
import {environment} from "../../environments/environment";
|
import {environment} from "../../environments/environment";
|
||||||
import {HttpClient} from "@angular/common/http";
|
import {HttpClient, HttpParams} from "@angular/common/http";
|
||||||
import {VsDuelParticipantModel} from "../models/vsDuelParticipant.model";
|
import {VsDuelParticipantDetailModel, VsDuelParticipantModel} from "../models/vsDuelParticipant.model";
|
||||||
import {Observable} from "rxjs";
|
import {Observable} from "rxjs";
|
||||||
|
import {MarshalGuardParticipantModel} from "../models/marshalGuardParticipant.model";
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
@ -12,6 +13,13 @@ export class VsDuelParticipantService {
|
|||||||
private readonly _serviceUrl = environment.apiBaseUrl + 'VsDuelParticipants/';
|
private readonly _serviceUrl = environment.apiBaseUrl + 'VsDuelParticipants/';
|
||||||
private readonly _httpClient: HttpClient = inject(HttpClient);
|
private readonly _httpClient: HttpClient = inject(HttpClient);
|
||||||
|
|
||||||
|
|
||||||
|
getVsDuelParticipantsDetail(playerId: string, last: number): Observable<VsDuelParticipantDetailModel[]> {
|
||||||
|
let params = new HttpParams();
|
||||||
|
params = params.append('last', last);
|
||||||
|
return this._httpClient.get<VsDuelParticipantDetailModel[]>(this._serviceUrl + 'Player/' + playerId, {params: params});
|
||||||
|
}
|
||||||
|
|
||||||
updateVsDuelParticipant(vsDuelParticipantId: string, vsDuelParticipant: VsDuelParticipantModel): Observable<VsDuelParticipantModel> {
|
updateVsDuelParticipant(vsDuelParticipantId: string, vsDuelParticipant: VsDuelParticipantModel): Observable<VsDuelParticipantModel> {
|
||||||
return this._httpClient.put<VsDuelParticipantModel>(this._serviceUrl + vsDuelParticipantId, vsDuelParticipant);
|
return this._httpClient.put<VsDuelParticipantModel>(this._serviceUrl + vsDuelParticipantId, vsDuelParticipant);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user