Added leftServer handling to members list #130

This commit is contained in:
Sven Heidemann 2023-02-18 12:14:04 +01:00
parent afff27b273
commit 7d67b08ce6
11 changed files with 97 additions and 43 deletions

View File

@ -86,6 +86,17 @@ class User(TableABC):
def server(self) -> Optional[Server]: def server(self) -> Optional[Server]:
return self._server return self._server
@property
@ServiceProviderABC.inject
def left_server(
self,
services: ServiceProviderABC,
) -> bool:
from bot_data.abc.user_joined_server_repository_abc import UserJoinedServerRepositoryABC
ujs: UserJoinedServerRepositoryABC = services.get_service(UserJoinedServerRepositoryABC)
return ujs.find_active_user_joined_server_by_user_id(self.id) is None
@staticmethod @staticmethod
def get_select_all_string() -> str: def get_select_all_string() -> str:
return str( return str(

View File

@ -31,7 +31,9 @@ class ServerFilter(FilterABC):
query = query.where(lambda x: x.id == self._id) query = query.where(lambda x: x.id == self._id)
if self._discord_id is not None: if self._discord_id is not None:
query = query.where(lambda x: x.discord_id == self._discord_id) query = query.where(
lambda x: x.discord_id == self._discord_id or str(self._discord_id) in str(x.discord_id)
)
if self._name is not None: if self._name is not None:

View File

@ -73,7 +73,7 @@ class UserFilter(FilterABC):
def filter(self, query: List[User]) -> List[User]: def filter(self, query: List[User]) -> List[User]:
if self._id is not None: if self._id is not None:
query = query.where(lambda x: x.id == self._id or str(self._id) in str(x.id)) query = query.where(lambda x: x.id == self._id)
if self._discord_id is not None: if self._discord_id is not None:
query = query.where( query = query.where(

View File

@ -91,5 +91,6 @@ class UserQuery(DataQueryABC):
def resolve_server(user: User, *_): def resolve_server(user: User, *_):
return user.server return user.server
def resolve_left_server(self, user: User, *_): @staticmethod
return self._ujs.find_active_user_joined_server_by_user_id(user.id) is None def resolve_left_server(user: User, *_):
return user.left_server

View File

@ -24,5 +24,5 @@ export interface UserDTO {
modifiedAt: string; modifiedAt: string;
isTechnician: boolean; isTechnician: boolean;
isAdmin: boolean; isAdmin: boolean;
IsModerator: boolean; isModerator: boolean;
} }

View File

@ -61,6 +61,13 @@
</div> </div>
</th> </th>
<th class="table-header-actions" pSortableColumn="leftServer">
<div class="table-header-label">
<div class="table-header-text">{{'view.server.members.headers.left_server' | translate}}</div>
<p-sortIcon field="leftServer" class="table-header-icon"></p-sortIcon>
</div>
</th>
<th class="table-header-small-dropdown" pSortableColumn="level.name"> <th class="table-header-small-dropdown" pSortableColumn="level.name">
<div class="table-header-label"> <div class="table-header-label">
<div class="table-header-text">{{'view.server.members.headers.level' | translate}}</div> <div class="table-header-text">{{'view.server.members.headers.level' | translate}}</div>
@ -92,6 +99,11 @@
</th> </th>
<th></th> <th></th>
<th></th> <th></th>
<th>
<form [formGroup]="filterForm">
<p-dropdown formControlName="leftServer" [options]="leftServerOptions" placeholder="{{'view.server.members.headers.left_server' | translate}}"></p-dropdown>
</form>
</th>
<th> <th>
<form [formGroup]="filterForm"> <form [formGroup]="filterForm">
<p-dropdown formControlName="level" [options]="levels" placeholder="{{'view.server.members.headers.level' | translate}}"></p-dropdown> <p-dropdown formControlName="level" [options]="levels" placeholder="{{'view.server.members.headers.level' | translate}}"></p-dropdown>
@ -153,6 +165,16 @@
</ng-template> </ng-template>
</p-cellEditor> </p-cellEditor>
</td> </td>
<td>
<p-cellEditor>
<ng-template pTemplate="input">
{{!member.leftServer | bool}}
</ng-template>
<ng-template pTemplate="output">
{{!member.leftServer | bool}}
</ng-template>
</p-cellEditor>
</td>
<td> <td>
<p-cellEditor> <p-cellEditor>
<ng-template pTemplate="input"> <ng-template pTemplate="input">
@ -167,6 +189,7 @@
<div class="btn-wrapper"> <div class="btn-wrapper">
<button *ngIf="!editing" pButton pInitEditableRow class="btn icon-btn" icon="pi pi-pencil" <button *ngIf="!editing" pButton pInitEditableRow class="btn icon-btn" icon="pi pi-pencil"
(click)="onRowEditInit(dt, member, ri)"></button> (click)="onRowEditInit(dt, member, ri)"></button>
<button *ngIf="!editing" pButton pInitEditableRow class="btn icon-btn" icon="pi pi-user" [routerLink]="member.id"></button>
<button *ngIf="editing" pButton pSaveEditableRow class="btn icon-btn" <button *ngIf="editing" pButton pSaveEditableRow class="btn icon-btn"
icon="pi pi-check-circle" (click)="onRowEditSave(dt, member, ri)"></button> icon="pi pi-check-circle" (click)="onRowEditSave(dt, member, ri)"></button>

View File

@ -29,6 +29,10 @@ export class MembersComponent {
members!: User[]; members!: User[];
// levelsFilter!: MenuItem[]; // levelsFilter!: MenuItem[];
levels!: MenuItem[]; levels!: MenuItem[];
leftServerOptions = [
{label: this.translate.instant('common.bool_as_string.true'), value: false},
{label: this.translate.instant('common.bool_as_string.false'), value: true},
];
loading = true; loading = true;
clonedUsers: { [s: string]: User; } = {}; clonedUsers: { [s: string]: User; } = {};
@ -60,12 +64,11 @@ export class MembersComponent {
id: FormControl<number | null>, id: FormControl<number | null>,
discordId: FormControl<number | null>, discordId: FormControl<number | null>,
name: FormControl<string | null>, name: FormControl<string | null>,
leftServer: FormControl<boolean | null>,
level: FormControl<number | null> level: FormControl<number | null>
}>; }>;
filter: UserFilter = { filter: UserFilter = {};
leftServer: false
};
page: Page = { page: Page = {
pageSize: undefined, pageSize: undefined,
pageIndex: undefined pageIndex: undefined
@ -86,7 +89,7 @@ export class MembersComponent {
private translate: TranslateService, private translate: TranslateService,
private data: DataService, private data: DataService,
private sidebar: SidebarService, private sidebar: SidebarService,
private route: ActivatedRoute, private route: ActivatedRoute
) { ) {
} }
@ -110,12 +113,26 @@ export class MembersComponent {
this.loadNextPage(); this.loadNextPage();
} }
loadNextPage() {
this.loading = true;
this.data.query<UserListQuery>(Queries.usersQuery, {
filter: this.filter, page: this.page, sort: this.sort
}
).subscribe(data => {
this.totalRecords = data.userCount;
this.members = data.users;
this.spinner.hideSpinner();
this.loading = false;
});
}
setFilterForm() { setFilterForm() {
this.filterForm = this.fb.group({ this.filterForm = this.fb.group({
id: new FormControl<number | null>(null), id: new FormControl<number | null>(null),
discordId: new FormControl<number | null>(null), discordId: new FormControl<number | null>(null),
name: [""], name: [""],
level: new FormControl<number | null>(null) leftServer: new FormControl<boolean | null>(null),
level: new FormControl<number | null>(null),
}); });
this.filterForm.valueChanges.pipe( this.filterForm.valueChanges.pipe(
@ -139,6 +156,12 @@ export class MembersComponent {
this.filter.name = undefined; this.filter.name = undefined;
} }
if (changes.leftServer !== undefined && changes.leftServer !== null) {
this.filter.leftServer = changes.leftServer;
} else {
this.filter.leftServer = undefined;
}
if (changes.level) { if (changes.level) {
this.filter.level = { this.filter.level = {
id: changes.level id: changes.level
@ -157,19 +180,6 @@ export class MembersComponent {
}); });
} }
loadNextPage() {
this.loading = true;
this.data.query<UserListQuery>(Queries.usersQuery, {
filter: this.filter, page: this.page, sort: this.sort
}
).subscribe(data => {
this.totalRecords = data.userCount;
this.members = data.users;
this.spinner.hideSpinner();
this.loading = false;
});
}
nextPage(event: LazyLoadEvent) { nextPage(event: LazyLoadEvent) {
this.page.pageSize = event.rows ?? 0; this.page.pageSize = event.rows ?? 0;
if (event.first != null && event.rows != null) if (event.first != null && event.rows != null)

View File

@ -5,6 +5,11 @@ import { UserListQuery } from "../../../../models/graphql/query.model";
import { SpinnerService } from "../../../../services/spinner/spinner.service"; import { SpinnerService } from "../../../../services/spinner/spinner.service";
import { DataService } from "../../../../services/data/data.service"; import { DataService } from "../../../../services/data/data.service";
import { User } from "../../../../models/data/user.model"; import { User } from "../../../../models/data/user.model";
import { UserDTO } from "../../../../models/auth/auth-user.dto";
import { AuthService } from "src/app/services/auth/auth.service";
import { SidebarService } from "../../../../services/sidebar/sidebar.service";
import { ToastService } from "src/app/services/toast/toast.service";
import { TranslateService } from "@ngx-translate/core";
@Component({ @Component({
selector: "app-profile", selector: "app-profile",
@ -19,11 +24,15 @@ export class ProfileComponent implements OnInit {
private route: ActivatedRoute, private route: ActivatedRoute,
private router: Router, private router: Router,
private spinner: SpinnerService, private spinner: SpinnerService,
private data: DataService private sidebar: SidebarService,
private data: DataService,
private auth: AuthService,
private toast: ToastService,
private translate: TranslateService
) { ) {
} }
ngOnInit() { async ngOnInit() {
this.data.getServerFromRoute(this.route); this.data.getServerFromRoute(this.route);
this.spinner.showSpinner(); this.spinner.showSpinner();
@ -33,10 +42,18 @@ export class ProfileComponent implements OnInit {
return; return;
} }
let authUser = await this.auth.getLoggedInUser();
let user: UserDTO | null = authUser?.users?.find(u => u.server == this.sidebar.server$.value?.id) ?? null;
if (!user || user?.id != this.route.snapshot.params["memberId"] && !user?.isModerator) {
this.toast.error(this.translate.instant("view.server.profile.permission_denied"), this.translate.instant("view.server.profile.permission_denied_d"));
this.router.navigate(["/server", this.sidebar.server$.value?.id]);
return;
}
this.data.query<User>(Queries.singleUserQuery, { this.data.query<User>(Queries.singleUserQuery, {
filter: { filter: {
id: this.route.snapshot.params["memberId"], id: this.route.snapshot.params["memberId"]
leftServer: false
} }
}, },
function(data: UserListQuery) { function(data: UserListQuery) {
@ -44,7 +61,6 @@ export class ProfileComponent implements OnInit {
} }
).subscribe(user => { ).subscribe(user => {
this.user = user; this.user = user;
console.log(this.user);
this.spinner.hideSpinner(); this.spinner.hideSpinner();
}); });
} }

View File

@ -44,18 +44,6 @@ export class DataService {
}); });
} }
// query(query: string, variables: object = {}): Observable<QueryResult> {
// return this.http.post<QueryResult>(`${this.appsettings.getApiURL()}/api/graphql`,
// JSON.stringify({
// query, variables
// }), {
// headers: new HttpHeaders({
// "Content-Type": "application/json"
// })
// }
// );
// }
public query<T>(query: string, variables?: Variables, f?: Function): Observable<T> { public query<T>(query: string, variables?: Variables, f?: Function): Observable<T> {
return this.http return this.http
.post<{ data: T }>(`${this.appsettings.getApiURL()}/api/graphql`, { .post<{ data: T }>(`${this.appsettings.getApiURL()}/api/graphql`, {

View File

@ -114,7 +114,7 @@ export class SidebarService {
if (this.server$.value) { if (this.server$.value) {
this.serverMenu.visible = true; this.serverMenu.visible = true;
this.serverMembers.visible = !!user?.isAdmin; this.serverMembers.visible = !!user?.isModerator;
} else { } else {
this.serverMenu.visible = false; this.serverMenu.visible = false;
} }

View File

@ -182,7 +182,9 @@
"time": "Zeit", "time": "Zeit",
"joined_at": "Beigetreten am", "joined_at": "Beigetreten am",
"leaved_at": "Verlassen am" "leaved_at": "Verlassen am"
} },
"permission_denied": "Zugriff Verweigert!",
"permission_denied_d": "Du musst Moderator sein, um andere Profile sehen zu können!"
}, },
"members": { "members": {
"header": "Mitglieder", "header": "Mitglieder",
@ -196,6 +198,7 @@
"name": "Name", "name": "Name",
"xp": "XP", "xp": "XP",
"ontime": "Ontime", "ontime": "Ontime",
"left_server": "Aktiv",
"level": "Level", "level": "Level",
"actions": "Aktionen" "actions": "Aktionen"
}, },