Browse Source

fixes 2

master
gsd 2 months ago
parent
commit
72fbb3628a
  1. 6
      src/app/app.module.ts
  2. 11
      src/app/pages/banlist-page/banlist-search-table.ts
  3. 7
      src/app/pages/internal-components/abstract-search-table.component.ts
  4. 249
      src/app/pages/internal-components/dialogs/simple-action-dialog.component.ts
  5. 29
      src/app/pages/profile-page/profile-page.component.html
  6. 33
      src/app/pages/servers-page/servers-page.component.html
  7. 6
      src/app/pages/servers-page/servers-page.component.ts
  8. 30
      src/app/services/action.service.ts
  9. 2
      src/app/services/auth.service.ts
  10. 8
      src/styles.scss

6
src/app/app.module.ts

@ -80,6 +80,8 @@ import { FilesPageComponent } from './admin-pages/files-page/files-page.componen
import {FilesSearchTable} from "./admin-pages/files-page/FilesSearchTable";
import {FilesUploader} from "./admin-pages/files-page/FilesUploader";
import {AuthDialogRequest} from "./pages/internal-components/dialogs/AuthDialogRequest";
import {SimpleActionDialog} from "./pages/internal-components/dialogs/simple-action-dialog.component";
import {MatTooltipModule} from "@angular/material/tooltip";
registerLocaleData(localeRu, "ru")
@ -122,6 +124,7 @@ registerLocaleData(localeRu, "ru")
VipFreeDialog,
VipPromocodeDialog,
AuthDialogRequest,
SimpleActionDialog,
DowngamePageComponent,
StatisticPageComponent,
AboutPageComponent,
@ -161,7 +164,8 @@ registerLocaleData(localeRu, "ru")
MatProgressSpinnerModule,
MatDialogModule,
MatStepperModule,
MatCheckboxModule
MatCheckboxModule,
MatTooltipModule
],
providers: [
{provide: LOCALE_ID, useValue: 'ru' },

11
src/app/pages/banlist-page/banlist-search-table.ts

@ -11,6 +11,7 @@ import {MatDialog} from "@angular/material/dialog";
import {MatTableDataSource} from "@angular/material/table";
import {BanViewDialog} from "../internal-components/dialogs/BanViewDialog";
import {AuthDialogRequest} from "../internal-components/dialogs/AuthDialogRequest";
import {ActionService} from "../../services/action.service";
@Component({
selector: "app-banlist-search-table",
@ -99,11 +100,8 @@ import {AuthDialogRequest} from "../internal-components/dialogs/AuthDialogReques
<ng-container matColumnDef="action">
<th mat-header-cell *matHeaderCellDef> Действие </th>
<td mat-cell *matCellDef="let row">
<mat-icon [matMenuTriggerFor]="actionMenu" style="cursor: pointer">view_headline</mat-icon>
<mat-menu #actionMenu>
<button mat-menu-item (click)="openBanDialog(row)">Подробнее</button>
<button mat-menu-item *ngIf="row.active==true&&authService.isModerator()">Разбанить</button>
</mat-menu>
<mat-icon style="cursor: pointer" matTooltip="Подробнее" (click)="openBanDialog(row)">remove_red_eye</mat-icon>
<mat-icon style="cursor: pointer" matTooltip="Разбанить" *ngIf="row.active==true&&authService.isModerator()" (click)="actionService.simpleActionWithSearch(row.steam_id, 'unban')">lock_open</mat-icon>
</td>
</ng-container>
@ -135,7 +133,8 @@ export class BanlistSearchTable extends AbstractSearchTable<Ban, BanSearchFilter
protected override router: Router,
protected override route: ActivatedRoute,
private banService: BanService,
private dialog: MatDialog) {
private dialog: MatDialog,
public actionService: ActionService) {
super(authService, serverService, playerService, route, router);
super.filter = new BanSearchFilter();
}

7
src/app/pages/internal-components/abstract-search-table.component.ts

@ -26,7 +26,7 @@ export abstract class AbstractSearchTable<T,U extends SearchFilter> implements A
@Input("account_id")
//[U:1:%s]
account_id: number | null = null;
account_id: string | number | null = null;
@Input("use_query")
use_query: boolean = true;
@ -55,7 +55,10 @@ export abstract class AbstractSearchTable<T,U extends SearchFilter> implements A
if (this.account_id == null || !this.use_query)
this.filter.fromQuery(this.route.snapshot.queryParamMap, this.paginator);
else
this.filter.addAccountToSearch(`[U:1:${this.account_id}]`);
if (typeof this.account_id == 'number')
this.filter.addAccountToSearch(`[U:1:${this.account_id}]`);
else
this.filter.addAccountToSearch(this.account_id);
this.updateData();
this.serverService.servers.subscribe(

249
src/app/pages/internal-components/dialogs/simple-action-dialog.component.ts

@ -0,0 +1,249 @@
import {Component, Inject, Input} from "@angular/core";
import {MAT_DIALOG_DATA} from "@angular/material/dialog";
import {HttpClient} from "@angular/common/http";
import {Player} from "../../../entities/servers/Player";
import {map} from "rxjs";
import {SteamIDs} from "../../../entities/profile/SteamIDs";
@Component({
selector: 'app-report-create-dialog',
template: `
<div [ngSwitch]="data.mode">
<div *ngSwitchDefault>
<h1 mat-dialog-title style="color: black">Что-то пошло не так</h1>
<mat-dialog-content>
<p>Не выбран режим работы окна</p>
</mat-dialog-content>
<mat-dialog-actions>
<button mat-button mat-raised-button mat-dialog-close="true" style="width: 100%">Закрыть</button>
</mat-dialog-actions>
</div>
<div *ngSwitchCase="'report'">
<h1 mat-dialog-title style="color: black">Создать жалобу</h1>
<mat-dialog-content>
<p>{{response}}</p>
<mat-form-field style="width: 100%" appearance="fill">
<mat-label>Причина тряски</mat-label>
<input matInput placeholder="Путис" [(ngModel)]="text" [disabled]="loading">
</mat-form-field>
<button
[disabled]="text.length<1 || loading"
mat-button
mat-raised-button
style="width: 100%"
(click)="sendReport()">Пожаловаться</button>
</mat-dialog-content>
<mat-dialog-actions>
<button mat-button mat-raised-button mat-dialog-close="true" style="width: 100%">Закрыть</button>
</mat-dialog-actions>
</div>
<div *ngSwitchCase="'ban'">
<h1 mat-dialog-title style="color: black">Бан</h1>
<mat-dialog-content>
<p>{{response}}</p>
<mat-form-field style="width: 100%" appearance="fill">
<mat-label>Причина бана</mat-label>
<input matInput placeholder="Хохол" [(ngModel)]="text" [disabled]="loading">
</mat-form-field>
<mat-form-field style="width: 100%" appearance="fill">
<mat-label>Длительность бана в минутах, 0 - навсегда</mat-label>
<input matInput placeholder="0" type="number" [(ngModel)]="number" [disabled]="loading">
</mat-form-field>
<button
[disabled]="text.length<1 || loading"
mat-button
mat-raised-button
style="width: 100%"
(click)="sendBan()">Забанить</button>
</mat-dialog-content>
<mat-dialog-actions>
<button mat-button mat-raised-button mat-dialog-close="true" style="width: 100%">Закрыть</button>
</mat-dialog-actions>
</div>
<div *ngSwitchCase="'kick'">
<h1 mat-dialog-title style="color: black">Кикаем игрока</h1>
<mat-dialog-content>
<p>{{response}}</p>
<mat-form-field style="width: 100%" appearance="fill">
<mat-label>Причина кика</mat-label>
<input matInput placeholder="Мешает какать" [(ngModel)]="text" [disabled]="loading">
</mat-form-field>
<button
[disabled]="text.length<1 || loading"
mat-button
mat-raised-button
style="width: 100%"
(click)="sendKick()">Кикнуть</button>
</mat-dialog-content>
<mat-dialog-actions>
<button mat-button mat-raised-button mat-dialog-close="true" style="width: 100%">Закрыть</button>
</mat-dialog-actions>
</div>
<div *ngSwitchCase="'mute'">
<h1 mat-dialog-title style="color: black">Выключаем микрофон</h1>
<mat-dialog-content>
<p [style]="response == 'Введи причину, чем она понятнее тем лучше'?'display: none':''">{{response}}</p>
<button
[disabled]="loading"
mat-button
mat-raised-button
style="width: 100%"
(click)="sendMute()">Выключить микрофон</button>
</mat-dialog-content>
<mat-dialog-actions>
<button mat-button mat-raised-button mat-dialog-close="true" style="width: 100%">Закрыть</button>
</mat-dialog-actions>
</div>
<div *ngSwitchCase="'unban'">
<h1 mat-dialog-title style="color: black">Разбанить игрока</h1>
<mat-dialog-content>
<p [style]="response == 'Введи причину, чем она понятнее тем лучше'?'display: none':''">{{response}}</p>
<button
[disabled]="loading"
mat-button
mat-raised-button
style="width: 100%"
(click)="sendUnban()">Разбанить</button>
</mat-dialog-content>
<mat-dialog-actions>
<button mat-button mat-raised-button mat-dialog-close="true" style="width: 100%">Закрыть</button>
</mat-dialog-actions>
</div>
</div>
`
})
export class SimpleActionDialog {
text: string = "";
number: number = 0;
response: string = "Введи причину, чем она понятнее тем лучше";
loading: boolean = false;
constructor(@Inject(MAT_DIALOG_DATA) public data: {
steamIds: SteamIDs,
mode: string
},
private http: HttpClient) {}
sendReport() {
this.response = 'Отправляем....'
this.loading = true;
this.http.post(`api/profile/current/report?steam64=${this.data.steamIds.steam64}&text=${this.text}`, {})
.pipe(map(res => Number.parseInt(`${res}`)))
.subscribe(
(res) => {
if (res > 0) this.response = 'Репорт успешно отослан'
else if (res < 0) this.response = `Перед другим репортом нужно подождать ${res*-1} секунд`;
else this.response = 'Произошла ошибка, нельзя опубликовать жалобу';
this.loading = false;
},
(error) => {
if (error.status == 406) this.response = 'Ты в бане, жалобу отправить нельзя!'
else this.response = 'Неизвестная ошибка, терпи...';
this.loading = false;
})
}
sendKick() {
this.response = "Кикаем...";
this.loading = true;
this.http.post(`api/admin/kick?steam64=${this.data.steamIds.steam64}`, {})
.subscribe(
(res) => {
this.loading = false;
this.response = 'Успешно кикнут';
}, (err) => {
switch (err.status) {
case 404: {
this.response = "Такого игрока уже нет на сервере";
break;
}
default: {
this.response = "Неизвестная ошибка, ты новичек??";
break;
}
}
this.loading = false;
}
)
}
sendMute() {
this.response = "Выключаем микрофон...";
this.loading = true;
this.http.post(`api/admin/mute?steam64=${this.data.steamIds.steam64}`, {})
.subscribe(
(res) => {
this.loading = false;
this.response = 'Успешно выключен микрофон';
}, (err) => {
switch (err.status) {
case 404: {
this.response = "Такого игрока уже нет на сервере";
break;
}
default: {
this.response = "Неизвестная ошибка, ты новичек??";
break;
}
}
this.loading = false;
}
)
}
sendUnban() {
this.response = "Пробуем разбанить";
this.loading = true;
this.http.delete(`api/admin/ban?steam64=${this.data.steamIds.steam64}`, {})
.subscribe(
(res) => {
this.loading = false;
this.response = 'Успешно разбанил';
}, (err) => {
switch (err.status) {
case 404: {
this.response = "А такого бана нет";
break;
}
default: {
this.response = "Неизвестная ошибка, ты новичек??";
break;
}
}
this.loading = false;
}
)
}
sendBan() {
this.response = "Баним...";
this.loading = true;
this.http.post(`api/admin/ban?steam64=${this.data.steamIds.steam64}&ban_length=${this.number}&ban_reason=${this.text}`, {})
.subscribe(
(res) => {
this.loading = false;
},
(err) => {
switch (err.status) {
case 201: {
this.response = 'Успешно забанен!';
break;
}
case 202: {
this.response = 'Уже в бане, нельзя забанить повторно';
break;
}
case 406: {
this.response = 'Чел... Он слишком крут для тебя';
break;
}
default: {
this.response = 'Неизвестная ошибка, ты новичек??';
break;
}
}
this.loading = false;
}
)
}
}

29
src/app/pages/profile-page/profile-page.component.html

@ -3,9 +3,9 @@
<h1>Профиль</h1>
<h3>Здесь можно увидеть профиль игрока на наших серверах с подробной информации о нем</h3>
</div>
<div *ngIf="loading == false && profile != null && profile.steam_data != null">
<h1>{{profile.steam_data.nickname}}</h1>
<h3>Открыть профиль в стиме</h3>
<div *ngIf="loading == false && profile != null">
<h1>{{profile.steam_data != null?profile.steam_data.nickname:'Просмотр профиля'}}</h1>
<h3 (click)="profile.steamids != null ? actionService.goToUrlViaTab(profile.steamids.community_url) : null">Открыть профиль в стиме</h3>
</div>
<div *ngIf="loading == true">
<h1>Загрузка данных о профиле</h1>
@ -23,16 +23,19 @@
<mat-card-title *ngIf="profile.steam_data != null">{{profile.steam_data.nickname}}</mat-card-title>
<mat-card-subtitle>
<div>
<p *ngIf="profile.steamids != null">Steam64: {{profile.steamids.steam64}}</p>
<p *ngIf="profile.steamids != null">Steam3: {{profile.steamids.steam3}}</p>
<p *ngIf="profile.steamids != null">Steam2: {{profile.steamids.steam2}}</p>
<p *ngIf="profile.steamids != null" style="cursor: pointer" (click)="actionService.copyToClipboard(profile.steamids.steam64, true)">Steam64: {{profile.steamids.steam64}}</p>
<p *ngIf="profile.steamids != null" style="cursor: pointer" (click)="actionService.copyToClipboard(profile.steamids.steam3, true)">Steam3: {{profile.steamids.steam3}}</p>
<p *ngIf="profile.steamids != null" style="cursor: pointer" (click)="actionService.copyToClipboard(profile.steamids.steam2, true)">Steam2: {{profile.steamids.steam2}}</p>
</div>
</mat-card-subtitle>
<img *ngIf="profile != null && profile.steam_data != null" mat-card-sm-image [src]="profile.steam_data.avatar" >
</mat-card-title-group><mat-divider inset></mat-divider>
<mat-card-actions>
<button mat-button>Открыть Steam</button>
<button mat-button>Купить VIP</button>
</mat-card-title-group>
<mat-divider *ngIf="authService.isModerator() && profile.steamids && authService.steamIds && authService.steamIds.steam64 != profile.steamids.steam64" inset></mat-divider>
<mat-card-actions *ngIf="authService.isModerator() && profile.steamids && authService.steamIds && authService.steamIds.steam64 != profile.steamids.steam64">
<button mat-button *ngIf="profile.play_on != null" (click)="actionService.simpleAction(profile.steamids, 'kick')">Кикнуть</button>
<button mat-button *ngIf="profile.play_on != null" (click)="actionService.simpleAction(profile.steamids, 'mute')">Замьютить</button>
<button mat-button *ngIf="profile.ban == null" (click)="actionService.simpleAction(profile.steamids, 'ban')">Забанить</button>
<button mat-button *ngIf="profile.ban != null" (click)="actionService.simpleAction(profile.steamids, 'unban')">Разбанить</button>
</mat-card-actions>
</mat-card>
<mat-card *ngIf="profile.permition != null">
@ -131,15 +134,13 @@
</mat-expansion-panel-header>
<app-donate-search-table #appdonatesearchtable [lazy]="true" [account_id]="profile.steamids.account_id"></app-donate-search-table>
</mat-expansion-panel>
<mat-expansion-panel hideToggle>
<mat-expansion-panel hideToggle *ngIf="profile!=null && profile.steamids!=null" (click)="appreportsearchtable.lazyInit()">
<mat-expansion-panel-header>
<mat-panel-title>
Репорты с участием игрока
</mat-panel-title>
</mat-expansion-panel-header>
<div>
<p>Табличку с репортом</p>
</div>
<app-report-search-table #appreportsearchtable [lazy]="true" [account_id]="profile.steamids.steam2"></app-report-search-table>
</mat-expansion-panel>
<mat-expansion-panel hideToggle *ngIf="profile!=null && profile.steamids!=null" (click)="appmessagesearch.lazyInit()">
<mat-expansion-panel-header>

33
src/app/pages/servers-page/servers-page.component.html

@ -5,6 +5,11 @@
<div class="content-in-center">
<div class="content-in-border">
<div *ngIf="!serversExists()">
<h3 style="color: black">Подгрузка серверов</h3>
<mat-progress-bar mode="indeterminate"></mat-progress-bar>
</div>
<mat-accordion>
<mat-expansion-panel hideToggle *ngFor="let server of servers | keyvalue: playerCountOrder">
<mat-expansion-panel-header>
@ -52,18 +57,18 @@
<mat-card-subtitle>Текущая карта</mat-card-subtitle>
</mat-card>
<mat-card
style="cursor: pointer"
class="clickable"
(click)="actionService.goToUrlViaTab('steam://connect/'+server.value.ip)">
<mat-card-title>Подключиться</mat-card-title>
<mat-card-subtitle>через Steam</mat-card-subtitle>
</mat-card>
<mat-card
style="cursor: pointer"
class="clickable"
(click)="actionService.copyToClipboard('connect ' + server.value.ip) && actionService.showSnack('Команда для подключения через консоль скопирована в буфер обмена')">
<mat-card-title>Адрес сервера</mat-card-title>
<mat-card-subtitle>{{server.value.ip}}</mat-card-subtitle>
</mat-card>
<mat-card *ngIf="server.value.workshop != ''" style="cursor: pointer" (click)="actionService.goToUrlViaTab(server.value.workshop)">
<mat-card *ngIf="server.value.workshop != ''" class="clickable" (click)="actionService.goToUrlViaTab(server.value.workshop)">
<mat-card-title>Скачать карту</mat-card-title>
<mat-card-subtitle>из воркшопа</mat-card-subtitle>
</mat-card>
@ -124,36 +129,36 @@
<div class="container responsive-grid-250">
<mat-card>
<mat-card-content>
<p *ngIf="player.steam.steam2" style="cursor: pointer" (click)="actionService.copyToClipboard(player.steam.steam2) && actionService.showSnack('Скопировано в буфер обмена')">{{player.steam.steam2}}</p>
<p *ngIf="player.steam.steam3" style="cursor: pointer" (click)="actionService.copyToClipboard(player.steam.steam3) && actionService.showSnack('Скопировано в буфер обмена')">{{player.steam.steam3}}</p>
<p *ngIf="player.steam.steam64" style="cursor: pointer" (click)="actionService.copyToClipboard(player.steam.steam64) && actionService.showSnack('Скопировано в буфер обмена')">{{player.steam.steam64}}</p>
<p *ngIf="player.steam.steam2" class="clickable" (click)="actionService.copyToClipboard(player.steam.steam2, true)">{{player.steam.steam2}}</p>
<p *ngIf="player.steam.steam3" class="clickable" (click)="actionService.copyToClipboard(player.steam.steam3, true)">{{player.steam.steam3}}</p>
<p *ngIf="player.steam.steam64" class="clickable" (click)="actionService.copyToClipboard(player.steam.steam64, true)">{{player.steam.steam64}}</p>
</mat-card-content>
</mat-card>
<mat-card style="cursor: pointer"
<mat-card class="clickable"
*ngIf="player.steam.steam64 != null"
(click)="authService.isAuth()?actionService.goToUrlViaRouter(['profile', player.steam.steam64]):actionService.showSnack('Сначала нужно войти на сайте')">
<mat-card-title>Открыть профиль</mat-card-title>
<mat-card-subtitle>на сайте</mat-card-subtitle>
</mat-card>
<mat-card style="cursor: pointer"
<mat-card class="clickable"
(click)="actionService.goToUrlViaTab(player.steam.community_url)">
<mat-card-title >Открыть профиль</mat-card-title>
<mat-card-subtitle>в стиме</mat-card-subtitle>
</mat-card>
<mat-card style="cursor: pointer"
(click)="authService.isAuth()?null:actionService.showSnack('Сначала нужно войти на сайте')">
<mat-card class="clickable"
(click)="authService.isAuth()?actionService.simpleAction(player.steam, 'report'):actionService.showSnack('Сначала нужно войти на сайте')">
<mat-card-title>Пожаловаться</mat-card-title>
<mat-card-subtitle>на игрока который играет</mat-card-subtitle>
</mat-card>
</div>
<div class="container responsive-grid-300">
<mat-card>
<div class="container responsive-grid-300" *ngIf="authService.isModerator()">
<mat-card class="clickable" (click)="actionService.simpleAction(player.steam, 'ban')">
<mat-card-title>Забанить</mat-card-title>
</mat-card>
<mat-card>
<mat-card class="clickable" (click)="actionService.simpleAction(player.steam, 'kick')">
<mat-card-title>Кикнуть</mat-card-title>
</mat-card>
<mat-card>
<mat-card class="clickable" (click)="actionService.simpleAction(player.steam, 'mute')">
<mat-card-title>Кинуть в мут</mat-card-title>
</mat-card>
</div>

6
src/app/pages/servers-page/servers-page.component.ts

@ -5,6 +5,9 @@ import {KeyValue} from "@angular/common";
import {ActionService} from "../../services/action.service";
import {Tf2dataService} from "../../services/tf2data.service";
import {AuthService} from "../../services/auth.service";
import {Player} from "../../entities/servers/Player";
import {MatDialog} from "@angular/material/dialog";
import {SimpleActionDialog} from "../internal-components/dialogs/simple-action-dialog.component";
@Component({
selector: 'app-servers-page',
@ -62,4 +65,7 @@ export class ServersPageComponent implements OnInit {
return name.split("workshop/").pop().split(".ugc").shift()
}
serversExists():boolean {
return Object.keys(this.servers).length > 0;
}
}

30
src/app/services/action.service.ts

@ -1,6 +1,11 @@
import { Injectable } from '@angular/core';
import {MatSnackBar, MatSnackBarRef} from "@angular/material/snack-bar";
import {Router} from "@angular/router";
import {Player} from "../entities/servers/Player";
import {SimpleActionDialog} from "../pages/internal-components/dialogs/simple-action-dialog.component";
import {MatDialog} from "@angular/material/dialog";
import {SteamIDs} from "../entities/profile/SteamIDs";
import {PlayerService} from "./player.service";
@Injectable({
providedIn: 'root'
@ -8,10 +13,17 @@ import {Router} from "@angular/router";
export class ActionService {
constructor(private snack: MatSnackBar,
private router: Router) { }
private router: Router,
private dialog: MatDialog,
private playerService: PlayerService) { }
public copyToClipboard(text:string|null, show_snack: boolean = false):boolean {
if (text != null)
navigator.clipboard.writeText(text);
if (show_snack)
this.showSnack('Скопировано в буфер обмена');
public copyToClipboard(text:string):boolean {
navigator.clipboard.writeText(text);
return true;
}
@ -31,4 +43,16 @@ export class ActionService {
window.open(url, "_blank");
return true;
}
//todo abst
simpleAction(steamIds: SteamIDs|null, mode: 'report'|'ban'|'kick'|'mute'|'unban') {
if (steamIds != null)
this.dialog.open(SimpleActionDialog, {data:{steamIds, mode}, minWidth:'500px'});
}
simpleActionWithSearch(steam: string, mode:string) {
this.playerService.searchProfile(steam).subscribe(
(steamIds) => this.dialog.open(SimpleActionDialog, {data:{steamIds, mode}, minWidth:'500px'})
);
}
}

2
src/app/services/auth.service.ts

@ -54,7 +54,7 @@ export class AuthService {
login() {
sessionStorage.removeItem(AuthService.KEY);
window.open(`api/auth/login?subdomain=${location.hostname.split(".").shift()}`)
window.open(`api/auth/login?subdomain=${location.hostname.split(".").shift()}`, "_self")
}
logout() {

8
src/styles.scss

@ -393,3 +393,11 @@ span {
.mat-dialog-content {
padding-bottom: 1% !important;
}
.clickable {
cursor: pointer
}
mat-card + .clickable:hover {
background: linear-gradient(to top, #f2a998, #e65e11);;
}

Loading…
Cancel
Save