1.0.0 #253
| @@ -86,6 +86,17 @@ class User(TableABC): | ||||
|     def server(self) -> Optional[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 | ||||
|     def get_select_all_string() -> str: | ||||
|         return str( | ||||
|   | ||||
| @@ -31,7 +31,9 @@ class ServerFilter(FilterABC): | ||||
|             query = query.where(lambda x: x.id == self._id) | ||||
|  | ||||
|         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: | ||||
|  | ||||
|   | ||||
| @@ -73,7 +73,7 @@ class UserFilter(FilterABC): | ||||
|  | ||||
|     def filter(self, query: List[User]) -> List[User]: | ||||
|         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: | ||||
|             query = query.where( | ||||
|   | ||||
| @@ -91,5 +91,6 @@ class UserQuery(DataQueryABC): | ||||
|     def resolve_server(user: User, *_): | ||||
|         return user.server | ||||
|  | ||||
|     def resolve_left_server(self, user: User, *_): | ||||
|         return self._ujs.find_active_user_joined_server_by_user_id(user.id) is None | ||||
|     @staticmethod | ||||
|     def resolve_left_server(user: User, *_): | ||||
|         return user.left_server | ||||
|   | ||||
| @@ -24,5 +24,5 @@ export interface UserDTO { | ||||
|   modifiedAt: string; | ||||
|   isTechnician: boolean; | ||||
|   isAdmin: boolean; | ||||
|   IsModerator: boolean; | ||||
|   isModerator: boolean; | ||||
| } | ||||
|   | ||||
| @@ -61,6 +61,13 @@ | ||||
|             </div> | ||||
|           </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"> | ||||
|             <div class="table-header-label"> | ||||
|               <div class="table-header-text">{{'view.server.members.headers.level' | translate}}</div> | ||||
| @@ -92,6 +99,11 @@ | ||||
|           </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> | ||||
|             <form [formGroup]="filterForm"> | ||||
|               <p-dropdown formControlName="level" [options]="levels" placeholder="{{'view.server.members.headers.level' | translate}}"></p-dropdown> | ||||
| @@ -153,6 +165,16 @@ | ||||
|               </ng-template> | ||||
|             </p-cellEditor> | ||||
|           </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> | ||||
|             <p-cellEditor> | ||||
|               <ng-template pTemplate="input"> | ||||
| @@ -167,6 +189,7 @@ | ||||
|             <div class="btn-wrapper"> | ||||
|               <button *ngIf="!editing" pButton pInitEditableRow class="btn icon-btn" icon="pi pi-pencil" | ||||
|                       (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" | ||||
|                       icon="pi pi-check-circle" (click)="onRowEditSave(dt, member, ri)"></button> | ||||
|   | ||||
| @@ -29,6 +29,10 @@ export class MembersComponent { | ||||
|   members!: User[]; | ||||
|   // levelsFilter!: 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; | ||||
|  | ||||
|   clonedUsers: { [s: string]: User; } = {}; | ||||
| @@ -60,12 +64,11 @@ export class MembersComponent { | ||||
|     id: FormControl<number | null>, | ||||
|     discordId: FormControl<number | null>, | ||||
|     name: FormControl<string | null>, | ||||
|     leftServer: FormControl<boolean | null>, | ||||
|     level: FormControl<number | null> | ||||
|   }>; | ||||
|  | ||||
|   filter: UserFilter = { | ||||
|     leftServer: false | ||||
|   }; | ||||
|   filter: UserFilter = {}; | ||||
|   page: Page = { | ||||
|     pageSize: undefined, | ||||
|     pageIndex: undefined | ||||
| @@ -86,7 +89,7 @@ export class MembersComponent { | ||||
|     private translate: TranslateService, | ||||
|     private data: DataService, | ||||
|     private sidebar: SidebarService, | ||||
|     private route: ActivatedRoute, | ||||
|     private route: ActivatedRoute | ||||
|   ) { | ||||
|   } | ||||
|  | ||||
| @@ -110,12 +113,26 @@ export class MembersComponent { | ||||
|     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() { | ||||
|     this.filterForm = this.fb.group({ | ||||
|       id: new FormControl<number | null>(null), | ||||
|       discordId: new FormControl<number | null>(null), | ||||
|       name: [""], | ||||
|       level: new FormControl<number | null>(null) | ||||
|       leftServer: new FormControl<boolean | null>(null), | ||||
|       level: new FormControl<number | null>(null), | ||||
|     }); | ||||
|  | ||||
|     this.filterForm.valueChanges.pipe( | ||||
| @@ -139,6 +156,12 @@ export class MembersComponent { | ||||
|         this.filter.name = undefined; | ||||
|       } | ||||
|  | ||||
|       if (changes.leftServer !== undefined && changes.leftServer !== null) { | ||||
|         this.filter.leftServer = changes.leftServer; | ||||
|       } else { | ||||
|         this.filter.leftServer = undefined; | ||||
|       } | ||||
|  | ||||
|       if (changes.level) { | ||||
|         this.filter.level = { | ||||
|           id: changes.level | ||||
| @@ -157,25 +180,12 @@ 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) { | ||||
|     this.page.pageSize = event.rows ?? 0; | ||||
|     if (event.first != null && event.rows != null) | ||||
|       this.page.pageIndex = event.first / event.rows; | ||||
|     this.sort.sortColumn = event.sortField ?? undefined; | ||||
|     this.sort.sortDirection = event.sortOrder === 1 ? SortDirection.ASC : event.sortOrder === -1 ? SortDirection.DESC: SortDirection.ASC; | ||||
|     this.sort.sortDirection = event.sortOrder === 1 ? SortDirection.ASC : event.sortOrder === -1 ? SortDirection.DESC : SortDirection.ASC; | ||||
|  | ||||
|     this.loadNextPage(); | ||||
|   } | ||||
|   | ||||
| @@ -5,6 +5,11 @@ import { UserListQuery } from "../../../../models/graphql/query.model"; | ||||
| import { SpinnerService } from "../../../../services/spinner/spinner.service"; | ||||
| import { DataService } from "../../../../services/data/data.service"; | ||||
| 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({ | ||||
|   selector: "app-profile", | ||||
| @@ -19,11 +24,15 @@ export class ProfileComponent implements OnInit { | ||||
|     private route: ActivatedRoute, | ||||
|     private router: Router, | ||||
|     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.spinner.showSpinner(); | ||||
| @@ -33,10 +42,18 @@ export class ProfileComponent implements OnInit { | ||||
|       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, { | ||||
|         filter: { | ||||
|           id: this.route.snapshot.params["memberId"], | ||||
|           leftServer: false | ||||
|           id: this.route.snapshot.params["memberId"] | ||||
|         } | ||||
|       }, | ||||
|       function(data: UserListQuery) { | ||||
| @@ -44,7 +61,6 @@ export class ProfileComponent implements OnInit { | ||||
|       } | ||||
|     ).subscribe(user => { | ||||
|       this.user = user; | ||||
|       console.log(this.user); | ||||
|       this.spinner.hideSpinner(); | ||||
|     }); | ||||
|   } | ||||
|   | ||||
| @@ -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> { | ||||
|     return this.http | ||||
|       .post<{ data: T }>(`${this.appsettings.getApiURL()}/api/graphql`, { | ||||
|   | ||||
| @@ -114,7 +114,7 @@ export class SidebarService { | ||||
|  | ||||
|       if (this.server$.value) { | ||||
|         this.serverMenu.visible = true; | ||||
|         this.serverMembers.visible = !!user?.isAdmin; | ||||
|         this.serverMembers.visible = !!user?.isModerator; | ||||
|       } else { | ||||
|         this.serverMenu.visible = false; | ||||
|       } | ||||
|   | ||||
| @@ -182,7 +182,9 @@ | ||||
|           "time": "Zeit", | ||||
|           "joined_at": "Beigetreten am", | ||||
|           "leaved_at": "Verlassen am" | ||||
|         } | ||||
|         }, | ||||
|         "permission_denied": "Zugriff Verweigert!", | ||||
|         "permission_denied_d": "Du musst Moderator sein, um andere Profile sehen zu können!" | ||||
|       }, | ||||
|       "members": { | ||||
|         "header": "Mitglieder", | ||||
| @@ -196,6 +198,7 @@ | ||||
|           "name": "Name", | ||||
|           "xp": "XP", | ||||
|           "ontime": "Ontime", | ||||
|           "left_server": "Aktiv", | ||||
|           "level": "Level", | ||||
|           "actions": "Aktionen" | ||||
|         }, | ||||
|   | ||||
		Reference in New Issue
	
	Block a user