Browse Source

ахуенный поиск отвечаю

master
gsd 2 months ago
parent
commit
99f68f047f
  1. 4
      src/app/app.module.ts
  2. 7
      src/app/entities/search/ISearchFilter.ts
  3. 15
      src/app/entities/search/MessageSearchFilter.ts
  4. 38
      src/app/entities/search/SearchFilter.ts
  5. 43
      src/app/pages/internal-components/abstract-search-table.component.ts
  6. 51
      src/app/pages/messages-page/messages-page.component.html
  7. 18
      src/app/pages/messages-page/messages-page.component.scss
  8. 23
      src/app/pages/messages-page/messages-page.component.ts

4
src/app/app.module.ts

@ -41,6 +41,7 @@ import {RussianPaginatorIntl} from "./utils/RussianPaginatorIntl";
import {MatSelectModule} from "@angular/material/select"; import {MatSelectModule} from "@angular/material/select";
import {MatDatepickerModule} from "@angular/material/datepicker"; import {MatDatepickerModule} from "@angular/material/datepicker";
import {MatNativeDateModule} from "@angular/material/core"; import {MatNativeDateModule} from "@angular/material/core";
import {MatProgressSpinnerModule} from "@angular/material/progress-spinner";
registerLocaleData(localeRu, "ru") registerLocaleData(localeRu, "ru")
@ -81,7 +82,8 @@ registerLocaleData(localeRu, "ru")
MatSortModule, MatSortModule,
MatSelectModule, MatSelectModule,
MatDatepickerModule, MatDatepickerModule,
MatNativeDateModule MatNativeDateModule,
MatProgressSpinnerModule
], ],
providers: [ providers: [
{provide: LOCALE_ID, useValue: 'ru' }, {provide: LOCALE_ID, useValue: 'ru' },

7
src/app/entities/search/ISearchFilter.ts

@ -0,0 +1,7 @@
import {ParamMap} from "@angular/router";
import {MatPaginator} from "@angular/material/paginator";
export interface ISearchFilter {
createQuery(paginator:MatPaginator|undefined): {[param: string]: any};
fromQuery(param: ParamMap,paginator:MatPaginator|undefined):void;
}

15
src/app/entities/search/MessageSearchFilter.ts

@ -1,5 +1,20 @@
import {SearchFilter} from "./SearchFilter"; import {SearchFilter} from "./SearchFilter";
import {ParamMap} from "@angular/router";
import {MatPaginator} from "@angular/material/paginator";
export class MessageSearchFilter extends SearchFilter { export class MessageSearchFilter extends SearchFilter {
message: string | null = null; message: string | null = null;
override createQuery(paginator:MatPaginator|undefined): { [p: string]: any } {
let q:{[param: string]: any} = super.createQuery(paginator);
q["message"] = this.message;
return q;
}
override fromQuery(param: ParamMap,paginator:MatPaginator|undefined) {
try {if (param.get("message")) { // @ts-ignore
this.message = param.get("message");}}catch (e) {}
super.fromQuery(param, paginator);
}
} }

38
src/app/entities/search/SearchFilter.ts

@ -1,7 +1,43 @@
export class SearchFilter { import {ISearchFilter} from "./ISearchFilter";
import {ParamMap} from "@angular/router";
import {MatPaginator} from "@angular/material/paginator";
export class SearchFilter implements ISearchFilter {
accounts: string[]|null = null; accounts: string[]|null = null;
begin: Date | null = null; begin: Date | null = null;
end: Date | null = null; end: Date | null = null;
serverId : string | null = null; serverId : string | null = null;
updated: boolean = false; updated: boolean = false;
createQuery(paginator:MatPaginator|undefined):{[param: string]: any} {
let q: {[param: string]: any} = {};
q["accounts"] = this.accounts?this.accounts.join(","):null;
q["begin"] = this.begin?this.begin.getTime():null;
q["end"] = this.end?this.end.getTime():null;
q["serverId"] = this.serverId;
q["page"] = paginator?paginator.pageIndex:null;
q["size"] = paginator?paginator.pageSize:null;
console.log(q);
return q;
}
fromQuery(param: ParamMap, paginator:MatPaginator|undefined): void {
try {if (param.has("accounts")) { // @ts-ignore
this.accounts = param.get("accounts")?.split(",");}} catch (e) {}
try {if (param.has("begin")) {// @ts-ignore
this.begin = new Date(param.get("begin")*1);}} catch (e) {}
try {if (param.get("end")) { // @ts-ignore
this.end = new Date(param.get("end")*1);}}catch (e) {}
try {if (param.get("serverId")) { // @ts-ignore
this.serverId = param.get("serverId");}}catch (e) {}
try {if (param.get("page") && paginator) { // @ts-ignore
paginator.pageIndex = param.get("page")*1;}}catch (e) {}
try {if (param.get("size") && paginator) { // @ts-ignore
paginator.pageSize = param.get("size")*1;}}catch (e) {}
}
} }

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

@ -6,23 +6,37 @@ import {merge, switchMap} from "rxjs";
import {MatSort} from "@angular/material/sort"; import {MatSort} from "@angular/material/sort";
import {SearchFilter} from "../../entities/search/SearchFilter"; import {SearchFilter} from "../../entities/search/SearchFilter";
import {ServerService} from "../../services/server.service"; import {ServerService} from "../../services/server.service";
import {ActivatedRoute, Router} from "@angular/router";
@Component({template: ''}) @Component({template: ''})
export abstract class AbstractSearchTable<T,U extends SearchFilter> implements AfterViewInit { export abstract class AbstractSearchTable<T,U extends SearchFilter> implements AfterViewInit {
dataSource: MatTableDataSource<T>; dataSource: MatTableDataSource<T>;
filter: U = new SearchFilter() as U; filter: U;
@ViewChild(MatPaginator) paginator: MatPaginator | undefined; @ViewChild(MatPaginator) paginator: MatPaginator | undefined;
@ViewChild(MatSort) sort: MatSort | undefined; @ViewChild(MatSort) sort: MatSort | undefined;
serverList: {name: string, server_id: string }[] = [] serverList: {name: string, server_id: string }[] = [];
loading: boolean = false;
err: boolean = false;
protected constructor(protected serverService: ServerService) {
protected constructor(protected serverService: ServerService,
protected route: ActivatedRoute,
protected router: Router) {
this.filter = new SearchFilter() as U;
this.dataSource = new MatTableDataSource<T>(); this.dataSource = new MatTableDataSource<T>();
} }
public updateData() {} public updateData() {
this.router.navigate([], {
relativeTo: this.route,
queryParams: this.filter.createQuery(this.paginator),
queryParamsHandling: "merge"
})
}
ngAfterViewInit(): void { ngAfterViewInit(): void {
this.filter.fromQuery(this.route.snapshot.queryParamMap, this.paginator);
this.updateData(); this.updateData();
this.serverService.getStats("servers").subscribe( this.serverService.getStats("servers").subscribe(
(res) => { (res) => {
@ -35,6 +49,12 @@ export abstract class AbstractSearchTable<T,U extends SearchFilter> implements A
) )
} }
changeAccountToSearch(prev: string, name: any) {
this.removeAccountFromSearch(prev);
this.addAccountToSearch(name.target.value);
this.filter.updated = true;
}
addAccountToSearch(name: string) { addAccountToSearch(name: string) {
if (this.filter.accounts == null) if (this.filter.accounts == null)
this.filter.accounts = []; this.filter.accounts = [];
@ -70,15 +90,14 @@ export abstract class AbstractSearchTable<T,U extends SearchFilter> implements A
} }
} }
addBeginTimeToSearch(custom_date: number|null = null) { addBeginTimeToSearch(custom_date: any = null) {
if (custom_date == null) { if (custom_date == null) {
const d: Date = new Date(); const d: Date = new Date();
d.setUTCHours(0, 0, 0, 0); d.setUTCHours(0, 0, 0, 0);
this.filter.begin = d; this.filter.begin = d;
} }
if (typeof custom_date == "number") { else this.filter.begin = new Date(custom_date);
this.filter.begin = new Date(custom_date);
}
this.filter.updated = true; this.filter.updated = true;
} }
@ -93,9 +112,7 @@ export abstract class AbstractSearchTable<T,U extends SearchFilter> implements A
d.setUTCHours(23, 59, 59, 999); d.setUTCHours(23, 59, 59, 999);
this.filter.end = d; this.filter.end = d;
} }
if (typeof custom_date == "number") { else this.filter.end = new Date(custom_date);
this.filter.end = new Date(custom_date);
}
this.filter.updated = true; this.filter.updated = true;
} }
@ -103,4 +120,8 @@ export abstract class AbstractSearchTable<T,U extends SearchFilter> implements A
this.filter.end = null; this.filter.end = null;
this.filter.updated = true; this.filter.updated = true;
} }
filterChanges(event:any) {
this.filter.updated = true;
}
} }

51
src/app/pages/messages-page/messages-page.component.html

@ -11,32 +11,45 @@
<mat-chip-list> <mat-chip-list>
<mat-chip [matMenuTriggerFor]="addFilter">Искать по...</mat-chip> <mat-chip [matMenuTriggerFor]="addFilter">Искать по...</mat-chip>
<mat-menu #addFilter> <mat-menu #addFilter>
<button mat-menu-item>Имени</button> <button mat-menu-item (click)="addAccountToSearch('')">Профилю</button>
<button mat-menu-item [matMenuTriggerFor]="timeSelect">Времени</button> <button mat-menu-item [matMenuTriggerFor]="timeSelect">Времени</button>
<button mat-menu-item (click)="addServerToSearch()">Серверу</button> <button mat-menu-item (click)="addServerToSearch()">Серверу</button>
<button mat-menu-item>Содержимому</button> <button mat-menu-item (click)="addMessageToSearch('')">Содержимому</button>
</mat-menu> </mat-menu>
<mat-menu #timeSelect> <mat-menu #timeSelect>
<button mat-menu-item (click)="addEndTimeToSearch()">До ...</button> <button mat-menu-item (click)="addEndTimeToSearch()">До ...</button>
<button mat-menu-item (click)="addBeginTimeToSearch()">После ...</button> <button mat-menu-item (click)="addBeginTimeToSearch()">После ...</button>
</mat-menu> </mat-menu>
<mat-chip *ngIf="filter.updated" (click)="getMessages()">Обновить</mat-chip> <mat-chip *ngIf="filter.updated" (click)="updateData()">Обновить</mat-chip>
<div *ngIf="filter.accounts != null">
<mat-chip <mat-chip
*ngFor="let acId of filter.accounts" *ngFor="let acId of filter.accounts"
(removed)="removeAccountFromSearch(acId)">{{acId}} (removed)="removeAccountFromSearch(acId)"
[matMenuTriggerFor]="profileSearch">Профиль: {{acId}}
<button matChipRemove> <button matChipRemove>
<mat-icon>cancel</mat-icon> <mat-icon>cancel</mat-icon>
</button> </button>
<mat-menu #profileSearch>
<mat-form-field appearance="fill" (click)="$event.stopPropagation()">
<mat-label>Ссылка, имя, все что угодно</mat-label>
<input matInput placeholder="отдыхаем" [ngModel]="acId" (change)="changeAccountToSearch(acId, $event)">
</mat-form-field>
</mat-menu>
</mat-chip> </mat-chip>
</div>
<mat-chip <mat-chip
*ngIf="filter.message!=null" *ngIf="filter.message!=null"
(removed)="removeMessageFromSearch()">Сообщение содержит: {{filter.message}} (removed)="removeMessageFromSearch()" [matMenuTriggerFor]="contentSearch">Сообщение содержит: {{filter.message}}
<button matChipRemove> <button matChipRemove>
<mat-icon>cancel</mat-icon> <mat-icon>cancel</mat-icon>
</button> </button>
<mat-menu #contentSearch>
<mat-form-field appearance="fill" (click)="$event.stopPropagation()">
<mat-label>Сообщение содержит...</mat-label>
<input matInput placeholder="люблю россию и путина" [ngModel]="filter.message" (ngModelChange)="addMessageToSearch($event)">
</mat-form-field>
</mat-menu>
</mat-chip> </mat-chip>
<mat-chip *ngIf="filter.serverId!=null" <mat-chip *ngIf="filter.serverId!=null"
@ -62,7 +75,9 @@
<mat-form-field appearance="fill" <mat-form-field appearance="fill"
(click)="$event.stopPropagation()"> (click)="$event.stopPropagation()">
<mat-label>Дата после</mat-label> <mat-label>Дата после</mat-label>
<input matInput type="datetime-local" [(ngModel)]="filter.begin"> <input matInput type="datetime-local"
[(ngModel)]="filter.begin"
(ngModelChange)="addBeginTimeToSearch($event)">
</mat-form-field> </mat-form-field>
</mat-menu> </mat-menu>
</mat-chip> </mat-chip>
@ -79,21 +94,30 @@
<mat-form-field appearance="fill" <mat-form-field appearance="fill"
(click)="$event.stopPropagation()"> (click)="$event.stopPropagation()">
<mat-label>Дата после</mat-label> <mat-label>Дата после</mat-label>
<input matInput type="datetime-local" [(ngModel)]="filter.end"> <input matInput type="datetime-local"
[(ngModel)]="filter.end"
(ngModelChange)="addEndTimeToSearch($event)">
</mat-form-field> </mat-form-field>
</mat-menu> </mat-menu>
</mat-chip> </mat-chip>
</mat-chip-list> </mat-chip-list>
</div> </div>
<div>
<div class="loading-shade"
*ngIf="loading || err">
<mat-spinner *ngIf="loading"></mat-spinner>
<div class="err" *ngIf="err">
Слишком много запросов или сервер не отвечает, обнови страницу.
</div>
</div>
<table mat-table [dataSource]="dataSource" style="width: 100%"> <table mat-table [dataSource]="dataSource" style="width: 100%">
<ng-container matColumnDef="account_name"> <ng-container matColumnDef="account_name">
<th mat-header-cell *matHeaderCellDef> Игрок </th> <th mat-header-cell *matHeaderCellDef> Игрок </th>
<td mat-cell *matCellDef="let row" [matMenuTriggerFor]="accountMenu"> {{row.account_name}} <td mat-cell *matCellDef="let row" [matMenuTriggerFor]="accountMenu"> {{row.account_name}}
<mat-menu #accountMenu> <mat-menu #accountMenu>
<button mat-menu-item (click)="addAccountToSearch(row.account_name)">Добавить в поиск</button> <button mat-menu-item (click)="addAccountToSearch(row.account_name)">Добавить в поиск</button>
<button mat-menu-item (click)="searchPlayer(row.account_name)">Открыть профиль</button> <button mat-menu-item (click)="searchPlayer(row.account_id)">Открыть профиль</button>
</mat-menu></td> </mat-menu></td>
</ng-container> </ng-container>
@ -128,16 +152,19 @@
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr> <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
<!-- Row shown when there is no matching data. --> <!-- Row shown when there is no matching data. -->
<div *ngIf="!loading">
<tr class="mat-row" *matNoDataRow> <tr class="mat-row" *matNoDataRow>
<td class="mat-cell" colspan="4">Нет сообщений</td> <td class="mat-cell" colspan="4">Нет сообщений</td>
</tr> </tr>
</div>
</table> </table>
<mat-paginator <mat-paginator
[pageSizeOptions]="[5, 10, 25, 100]" [pageSizeOptions]="[5, 10, 25, 100]"
[pageSize]="10" [pageSize]="10"
(page)="getMessages()" (page)="updateData()"
></mat-paginator> ></mat-paginator>
</div> </div>
</div> </div>
</div>
</div> </div>

18
src/app/pages/messages-page/messages-page.component.scss

@ -5,3 +5,21 @@
::ng-deep .mat-form-field-underline { ::ng-deep .mat-form-field-underline {
display: none; display: none;
} }
.loading-shade {
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
background: rgba(0, 0, 0, 0.15);
z-index: 1;
display: flex;
align-items: center;
justify-content: center;
}
.err {
max-width: 360px;
text-align: center;
}

23
src/app/pages/messages-page/messages-page.component.ts

@ -10,7 +10,7 @@ import {SearchFilter} from "../../entities/search/SearchFilter";
import {ServerService} from "../../services/server.service"; import {ServerService} from "../../services/server.service";
import {MessageSearchFilter} from "../../entities/search/MessageSearchFilter"; import {MessageSearchFilter} from "../../entities/search/MessageSearchFilter";
import {PlayerService} from "../../services/player.service"; import {PlayerService} from "../../services/player.service";
import {Router} from "@angular/router"; import {ActivatedRoute, Router} from "@angular/router";
@Component({ @Component({
selector: 'app-messages-page', selector: 'app-messages-page',
@ -25,26 +25,30 @@ export class MessagesPageComponent extends AbstractSearchTable<Message, MessageS
private messageService: MessageService, private messageService: MessageService,
protected override serverService: ServerService, protected override serverService: ServerService,
private playerService: PlayerService, private playerService: PlayerService,
private router: Router) { protected override router: Router,
super(serverService); protected override route: ActivatedRoute) {
super(serverService, route, router);
super.filter = new MessageSearchFilter(); super.filter = new MessageSearchFilter();
} }
getMessages(): boolean { private getMessages(): boolean {
this.filter.updated = false; this.filter.updated = false;
this.loading = true;
this.messageService.getMessages(this.filter, this.paginator).subscribe( this.messageService.getMessages(this.filter, this.paginator).subscribe(
(res) => { (res) => {
this.dataSource = new MatTableDataSource<Message>(res.data); this.dataSource = new MatTableDataSource<Message>(res.data);
} this.err = false;
}, (e) => this.err = true, () => this.loading = false
) )
return true; return true;
} }
override updateData() { override updateData() {
super.updateData();
this.getMessages(); this.getMessages();
} }
addMessageToSearch(name: string) { addMessageToSearch(name: any) {
this.filter.message = name; this.filter.message = name;
this.filter.updated = true; this.filter.updated = true;
} }
@ -54,15 +58,12 @@ export class MessagesPageComponent extends AbstractSearchTable<Message, MessageS
this.filter.updated = true; this.filter.updated = true;
} }
searchPlayer(search: string) { searchPlayer(account_id: number) {
if (search.length == 0) {
return;
}
if (!this.authService.isAuth()) { if (!this.authService.isAuth()) {
return; return;
} }
this.playerService.searchProfile(search).subscribe( this.playerService.searchProfile(`[U:1:${account_id}]`).subscribe(
(res) => { (res) => {
if (res.steam64 != null) if (res.steam64 != null)
this.router.navigate(['profile', res.steam64]) this.router.navigate(['profile', res.steam64])

Loading…
Cancel
Save