1.2.0 #406
| @@ -32,7 +32,7 @@ class UserWarningsRepositoryService(UserWarningsRepositoryABC): | ||||
|     def _from_result(self, sql_result: tuple) -> UserWarnings: | ||||
|         user = self._users.get_user_by_id(self._get_value_from_result(sql_result[2])) | ||||
|         author = None | ||||
|         author_id = self._get_value_from_result(sql_result[2]) | ||||
|         author_id = self._get_value_from_result(sql_result[3]) | ||||
|         if author_id is not None: | ||||
|             author = self._users.get_user_by_id(author_id) | ||||
|  | ||||
|   | ||||
| @@ -63,4 +63,5 @@ input UserInput { | ||||
|     id: ID | ||||
|     xp: Int | ||||
|     levelId: ID | ||||
|     userWarnings: [UserWarningInput] | ||||
| } | ||||
| @@ -24,4 +24,11 @@ type UserWarningHistory implements HistoryTableQuery { | ||||
| input UserWarningFilter { | ||||
|     id: ID | ||||
|     user: UserFilter | ||||
| } | ||||
|  | ||||
| input UserWarningInput { | ||||
|     id: ID | ||||
|     user: ID | ||||
|     description: String | ||||
|     author: ID | ||||
| } | ||||
| @@ -139,6 +139,7 @@ class ServerConfigMutation(QueryABC): | ||||
|             self._update_team_role_ids(server_config) | ||||
|  | ||||
|         self._db.save_changes() | ||||
|         self._bot.loop.create_task(self._config_service.reload_server_config(server_config.server)) | ||||
|         return server_config | ||||
|  | ||||
|     def _update_afk_channel_ids(self, new_config: ServerConfig): | ||||
| @@ -178,5 +179,3 @@ class ServerConfigMutation(QueryABC): | ||||
|                 continue | ||||
|  | ||||
|             self._server_configs.add_server_team_role_id_config(role_id) | ||||
|  | ||||
|         self._bot.loop.create_task(self._config_service.reload_server_config(new_config.server)) | ||||
|   | ||||
| @@ -4,8 +4,11 @@ from cpl_discord.service import DiscordBotServiceABC | ||||
| from bot_data.abc.level_repository_abc import LevelRepositoryABC | ||||
| from bot_data.abc.server_repository_abc import ServerRepositoryABC | ||||
| from bot_data.abc.user_repository_abc import UserRepositoryABC | ||||
| from bot_data.abc.user_warnings_repository_abc import UserWarningsRepositoryABC | ||||
| from bot_data.model.user import User | ||||
| from bot_data.model.user_role_enum import UserRoleEnum | ||||
| from bot_graphql.abc.query_abc import QueryABC | ||||
| from modules.base.service.user_warnings_service import UserWarningsService | ||||
| from modules.level.service.level_service import LevelService | ||||
| from modules.permission.service.permission_service import PermissionService | ||||
|  | ||||
| @@ -20,6 +23,8 @@ class UserMutation(QueryABC): | ||||
|         permissions: PermissionService, | ||||
|         levels: LevelRepositoryABC, | ||||
|         level_service: LevelService, | ||||
|         user_warnings: UserWarningsRepositoryABC, | ||||
|         user_warning_service: UserWarningsService, | ||||
|     ): | ||||
|         QueryABC.__init__(self, "UserMutation") | ||||
|  | ||||
| @@ -30,6 +35,8 @@ class UserMutation(QueryABC): | ||||
|         self._permissions = permissions | ||||
|         self._levels = levels | ||||
|         self._level_service = level_service | ||||
|         self._user_warnings = user_warnings | ||||
|         self._user_warning_service = user_warning_service | ||||
|  | ||||
|         self.set_field("updateUser", self.resolve_update_user) | ||||
|  | ||||
| @@ -45,9 +52,28 @@ class UserMutation(QueryABC): | ||||
|  | ||||
|         user.xp = new_xp if new_xp is not None else input["xp"] if "xp" in input else user.xp | ||||
|  | ||||
|         if "userWarnings" in input: | ||||
|             self._update_user_warning(user, input["userWarnings"]) | ||||
|  | ||||
|         self._users.update_user(user) | ||||
|         self._db.save_changes() | ||||
|         self._bot.loop.create_task(self._level_service.set_level(user)) | ||||
|  | ||||
|         user = self._users.get_user_by_id(input["id"]) | ||||
|         return user | ||||
|  | ||||
|     def _update_user_warning(self, user: User, new_warnings: dict): | ||||
|         old_warnings = self._user_warnings.get_user_warnings_by_user_id(user.id) | ||||
|         for warning in old_warnings: | ||||
|             if warning.id in [int(x["id"]) if "id" in x else None for x in new_warnings]: | ||||
|                 continue | ||||
|  | ||||
|             self._user_warning_service.remove_warnings(warning.id) | ||||
|  | ||||
|         for warning in new_warnings: | ||||
|             if "id" in warning and int(warning["id"]) in old_warnings.select(lambda x: x.id): | ||||
|                 continue | ||||
|  | ||||
|             member = self._bot.get_guild(user.server.discord_id).get_member(user.discord_id) | ||||
|             author = self._users.get_user_by_id(int(warning["author"])) | ||||
|             self._user_warning_service.add_warnings(member, warning["description"], author.discord_id) | ||||
|   | ||||
| @@ -400,7 +400,7 @@ class UserGroup(DiscordCommandABC): | ||||
|     async def add(self, ctx: Context, member: discord.Member, description: str): | ||||
|         self._logger.debug(__name__, f"Received command user warning add {ctx}:{member},{description}") | ||||
|         try: | ||||
|             await self._user_warnings_service.add_warnings(member, description, ctx.author.id) | ||||
|             await self._user_warnings_service.add_warnings_async(member, description, ctx.author.id) | ||||
|             await self._message_service.send_ctx_msg(ctx, self._t.transform("modules.base.warnings.add.success")) | ||||
|         except Exception as e: | ||||
|             self._logger.error(__name__, f"Adding user warning failed", e) | ||||
| @@ -414,7 +414,7 @@ class UserGroup(DiscordCommandABC): | ||||
|     async def remove(self, ctx: Context, warning_id: int): | ||||
|         self._logger.debug(__name__, f"Received command user warning remove {ctx}:{warning_id}") | ||||
|         try: | ||||
|             await self._user_warnings_service.remove_warnings(warning_id) | ||||
|             await self._user_warnings_service.remove_warnings_async(warning_id) | ||||
|             await self._message_service.send_ctx_msg(ctx, self._t.transform("modules.base.warnings.remove.success")) | ||||
|         except Exception as e: | ||||
|             self._logger.error(__name__, f"Removing user warning failed", e) | ||||
|   | ||||
| @@ -108,7 +108,15 @@ class UserWarningsService: | ||||
|             await self.notify_team(member, self._t.transform("modules.base.warnings.kick").format(member.mention)) | ||||
|             await member.kick() | ||||
|  | ||||
|     async def add_warnings(self, member: discord.Member, description: str, author_id: int = None): | ||||
|     async def _notify_after_add(self, member: discord.Member, warning: UserWarnings): | ||||
|         server = self._servers.get_server_by_discord_id(member.guild.id) | ||||
|         user = self._users.get_user_by_discord_id_and_server_id(member.id, server.id) | ||||
|  | ||||
|         await self.notify_user(member, self._t.transform("modules.base.warnings.warned").format(warning.description)) | ||||
|         await self.notify_team(member, warning.description) | ||||
|         await self.check_for_warnings(member, user) | ||||
|  | ||||
|     def _add_warnings(self, member: discord.Member, description: str, author_id: int = None): | ||||
|         server = self._servers.get_server_by_discord_id(member.guild.id) | ||||
|         user = self._users.get_user_by_discord_id_and_server_id(member.id, server.id) | ||||
|  | ||||
| @@ -119,17 +127,32 @@ class UserWarningsService: | ||||
|         warning = UserWarnings(description, user, author) | ||||
|         self._warnings.add_user_warnings(warning) | ||||
|         self._db.save_changes() | ||||
|         await self.notify_user(member, self._t.transform("modules.base.warnings.warned").format(warning.description)) | ||||
|         await self.notify_team(member, warning.description) | ||||
|         await self.check_for_warnings(member, user) | ||||
|         return warning | ||||
|  | ||||
|     async def remove_warnings(self, id: int): | ||||
|     def add_warnings(self, member: discord.Member, description: str, author_id: int = None): | ||||
|         warning = self._add_warnings(member, description, author_id) | ||||
|         self._bot.loop.create_task(self._notify_after_add(member, warning)) | ||||
|  | ||||
|     async def add_warnings_async(self, member: discord.Member, description: str, author_id: int = None): | ||||
|         warning = self._add_warnings(member, description, author_id) | ||||
|         await self._notify_after_add(member, warning) | ||||
|  | ||||
|     async def _notify_after_remove(self, warning: UserWarnings): | ||||
|         guild = self._bot.get_guild(warning.user.server.discord_id) | ||||
|         member = guild.get_member(warning.user.discord_id) | ||||
|         await self.notify_user(member, self._t.transform("modules.base.warnings.removed").format(warning.description)) | ||||
|         await self.notify_team(member, warning.description, removed=True) | ||||
|  | ||||
|     def _remove_warnings(self, id: int): | ||||
|         warning = self._warnings.get_user_warnings_by_id(id) | ||||
|         self._warnings.delete_user_warnings(warning) | ||||
|         self._db.save_changes() | ||||
|         return warning | ||||
|  | ||||
|         guild = self._bot.get_guild(warning.user.server.discord_id) | ||||
|         member = guild.get_member(warning.user.discord_id) | ||||
|     def remove_warnings(self, id: int): | ||||
|         warning = self._remove_warnings(id) | ||||
|         self._bot.loop.create_task(self._notify_after_remove(warning)) | ||||
|  | ||||
|         await self.notify_user(member, self._t.transform("modules.base.warnings.removed").format(warning.description)) | ||||
|         await self.notify_team(member, warning.description, removed=True) | ||||
|     async def remove_warnings_async(self, id: int): | ||||
|         warning = self._remove_warnings(id) | ||||
|         await self._notify_after_remove(warning) | ||||
|   | ||||
| @@ -1,8 +1,8 @@ | ||||
| export class Mutations { | ||||
|   static updateUser = ` | ||||
|     mutation updateUser($id: ID, $xp: Int, $levelId: ID) { | ||||
|     mutation updateUser($id: ID, $xp: Int, $levelId: ID, $userWarnings: [UserWarningInput]) { | ||||
|       user { | ||||
|         updateUser(input: { id: $id, xp: $xp, levelId: $levelId }) { | ||||
|         updateUser(input: { id: $id, xp: $xp, levelId: $levelId, userWarnings: $userWarnings }) { | ||||
|           id | ||||
|           name | ||||
|           xp | ||||
| @@ -10,6 +10,10 @@ export class Mutations { | ||||
|             id | ||||
|             name | ||||
|           } | ||||
|           userWarnings { | ||||
|             id | ||||
|             description | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     } | ||||
| @@ -314,4 +318,50 @@ export class Mutations { | ||||
|       } | ||||
|     } | ||||
|   `; | ||||
|  | ||||
|  | ||||
|  | ||||
|   static createUserWarning = ` | ||||
|     mutation createUserWarning($name: String, $description: String, $attribute: String, $operator: String, $value: String, $serverId: ID) { | ||||
|       userWarning { | ||||
|         createUserWarning(input: { name: $name, description: $description, attribute: $attribute, operator: $operator, value: $value, serverId: $serverId}) { | ||||
|           id | ||||
|           name | ||||
|           description | ||||
|           attribute | ||||
|           operator | ||||
|           value | ||||
|           server { | ||||
|             id | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   `; | ||||
|  | ||||
|   static updateUserWarning = ` | ||||
|     mutation updateUserWarning($id: ID, $name: String, $description: String, $attribute: String, $operator: String, $value: String) { | ||||
|       userWarning { | ||||
|         updateUserWarning(input: { id: $id, name: $name, description: $description, attribute: $attribute, operator: $operator, value: $value}) { | ||||
|           id | ||||
|           name | ||||
|           description | ||||
|           attribute | ||||
|           operator | ||||
|           value | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   `; | ||||
|  | ||||
|   static deleteUserWarning = ` | ||||
|     mutation deleteUserWarning($id: ID) { | ||||
|       userWarning { | ||||
|         deleteUserWarning(id: $id) { | ||||
|           id | ||||
|           name | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   `; | ||||
| } | ||||
|   | ||||
| @@ -360,6 +360,10 @@ export class Queries { | ||||
|         userWarningCount | ||||
|         userWarnings { | ||||
|           id | ||||
|           user { | ||||
|             id | ||||
|             name | ||||
|           } | ||||
|           description | ||||
|           author { | ||||
|             id | ||||
|   | ||||
| @@ -6,6 +6,7 @@ import { Achievement } from "../data/achievement.model"; | ||||
| import { TechnicianConfig } from "../config/technician-config.model"; | ||||
| import { ServerConfig } from "../config/server-config.model"; | ||||
| import { ShortRoleName } from "../data/short_role_name.model"; | ||||
| import { UserWarning } from "../data/user_warning.model"; | ||||
|  | ||||
| export interface GraphQLResult { | ||||
|   data: { | ||||
| @@ -77,3 +78,11 @@ export interface ShortRoleNameMutationResult { | ||||
|     deleteShortRoleName?: ShortRoleName | ||||
|   }; | ||||
| } | ||||
|  | ||||
| export interface UserWarningMutationResult { | ||||
|   userWarning: { | ||||
|     createUserWarning?: UserWarning | ||||
|     updateUserWarning?: UserWarning | ||||
|     deleteUserWarning?: UserWarning | ||||
|   }; | ||||
| } | ||||
|   | ||||
| @@ -135,10 +135,10 @@ | ||||
|             <td> | ||||
|               <p-cellEditor> | ||||
|                 <ng-template pTemplate="input"> | ||||
|                   {{value.author.name}} | ||||
|                   {{value.author?.name}} | ||||
|                 </ng-template> | ||||
|                 <ng-template pTemplate="output"> | ||||
|                   {{value.author.name}} | ||||
|                   {{value.author?.name}} | ||||
|                 </ng-template> | ||||
|               </p-cellEditor> | ||||
|             </td> | ||||
| @@ -262,5 +262,12 @@ | ||||
|         </div> | ||||
|       </div> | ||||
|     </p-panel> | ||||
|  | ||||
|     <div class="content-divider"></div> | ||||
|  | ||||
|     <div class="content-row"> | ||||
|       <button pButton icon="pi pi-save" label="{{'common.save' | translate}}" class="btn login-form-submit-btn" | ||||
|               (click)="updateUser()"></button> | ||||
|     </div> | ||||
|   </div> | ||||
| </div> | ||||
|   | ||||
| @@ -10,9 +10,13 @@ import { AuthService } from "src/app/services/auth/auth.service"; | ||||
| import { ToastService } from "src/app/services/toast/toast.service"; | ||||
| import { TranslateService } from "@ngx-translate/core"; | ||||
| import { Server } from "../../../../models/data/server.model"; | ||||
| import { forkJoin, Subject } from "rxjs"; | ||||
| import { takeUntil } from "rxjs/operators"; | ||||
| import { forkJoin, Subject, throwError } from "rxjs"; | ||||
| import { catchError, takeUntil } from "rxjs/operators"; | ||||
| import { Table } from "primeng/table"; | ||||
| import { UserWarning } from "../../../../models/data/user_warning.model"; | ||||
| import { LevelMutationResult, UpdateUserMutationResult, UserWarningMutationResult } from "../../../../models/graphql/result.model"; | ||||
| import { Mutations } from "../../../../models/graphql/mutations.model"; | ||||
| import { ConfirmationDialogService } from "../../../../services/confirmation-dialog/confirmation-dialog.service"; | ||||
|  | ||||
| @Component({ | ||||
|   selector: "app-profile", | ||||
| @@ -23,6 +27,10 @@ export class ProfileComponent implements OnInit, OnDestroy { | ||||
|  | ||||
|   user: User = { createdAt: "", modifiedAt: "" }; | ||||
|   private server: Server = {}; | ||||
|   private author?: UserDTO; | ||||
|   private clonedUserWarnings: UserWarning[] = []; | ||||
|   public isEditingNewUserWarning: boolean = false; | ||||
|   public isEditing: boolean = false; | ||||
|  | ||||
|   private unsubscriber = new Subject<void>(); | ||||
|  | ||||
| @@ -33,11 +41,16 @@ export class ProfileComponent implements OnInit, OnDestroy { | ||||
|     private data: DataService, | ||||
|     private auth: AuthService, | ||||
|     private toast: ToastService, | ||||
|     private translate: TranslateService | ||||
|     private translate: TranslateService, | ||||
|     private toastService: ToastService | ||||
|   ) { | ||||
|   } | ||||
|  | ||||
|   public ngOnInit(): void { | ||||
|     this.loadProfile(); | ||||
|   } | ||||
|  | ||||
|   private loadProfile() { | ||||
|     this.route.params.pipe(takeUntil(this.unsubscriber)).subscribe(params => { | ||||
|       this.data.getServerFromRoute(this.route).then(async (server) => { | ||||
|         if (!params["memberId"] || params["memberId"] == "undefined") { | ||||
| @@ -55,6 +68,7 @@ export class ProfileComponent implements OnInit, OnDestroy { | ||||
|           await this.router.navigate(["/server", server.id]); | ||||
|           return; | ||||
|         } | ||||
|         this.author = user; | ||||
|  | ||||
|         this.data.query<UserListQuery>(Queries.userProfile, { | ||||
|             serverId: this.server.id, | ||||
| @@ -85,6 +99,32 @@ export class ProfileComponent implements OnInit, OnDestroy { | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   public updateUser() { | ||||
|     this.spinner.showSpinner(); | ||||
|     this.spinner.showSpinner(); | ||||
|     this.data.mutation<UpdateUserMutationResult>(Mutations.updateUser, { | ||||
|         id: this.user.id, | ||||
|         xp: this.user.xp, | ||||
|         levelId: this.user.level?.id, | ||||
|         userWarnings: this.user.userWarnings?.map(userWarning => { | ||||
|           return { | ||||
|             id: userWarning.id, | ||||
|             user: userWarning.user?.id ?? this.user.id, | ||||
|             description: userWarning.description, | ||||
|             author: userWarning.author?.id ?? this.author?.id | ||||
|           } | ||||
|         }) | ||||
|       } | ||||
|     ).pipe(catchError(err => { | ||||
|       this.spinner.hideSpinner(); | ||||
|       return throwError(err); | ||||
|     })).subscribe(_ => { | ||||
|       this.spinner.hideSpinner(); | ||||
|       this.toastService.success(this.translate.instant("view.server.members.message.user_changed"), this.translate.instant("view.server.members.message.user_changed_d", { name: this.user.name })); | ||||
|       this.loadProfile(); | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   public ngOnDestroy(): void { | ||||
|     this.unsubscriber.next(); | ||||
|     this.unsubscriber.complete(); | ||||
| @@ -141,16 +181,42 @@ export class ProfileComponent implements OnInit, OnDestroy { | ||||
|   } | ||||
|  | ||||
|   addNewUserWarning(table: Table) { | ||||
|     const newWarning: UserWarning = { | ||||
|       description: "", | ||||
|       user: this.user | ||||
|     }; | ||||
|  | ||||
|     this.user.userWarnings = [newWarning, ...this.user.userWarnings ?? []]; | ||||
|  | ||||
|     table.initRowEdit(newWarning); | ||||
|  | ||||
|     const index = this.user.userWarnings.findIndex(l => l.id == newWarning.id); | ||||
|     this.onRowEditInit(table, newWarning, index); | ||||
|  | ||||
|     this.isEditingNewUserWarning = true; | ||||
|   } | ||||
|  | ||||
|   public onRowEditInit(table: Table, user: User, index: number): void { | ||||
|     this.clonedUserWarnings[index] = { ...user }; | ||||
|   } | ||||
|  | ||||
|   deleteUserWarning(index: number) { | ||||
|     this.user.userWarnings?.splice(index, 1); | ||||
|   } | ||||
|  | ||||
|   editSaveUserWarning(value: any, index: number) { | ||||
|     this.isEditingNewUserWarning = false; | ||||
|     if (!value.value || !this.user.userWarnings || this.user.userWarnings[index] == this.clonedUserWarnings[index]) { | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|     delete this.clonedUserWarnings[index]; | ||||
|   } | ||||
|  | ||||
|   editCancelUserWarning(index: number) { | ||||
|     if (this.user.userWarnings) { | ||||
|       this.user.userWarnings[index] = this.clonedUserWarnings[index]; | ||||
|     } | ||||
|     delete this.clonedUserWarnings[index]; | ||||
|   } | ||||
|  | ||||
|   protected readonly visualViewport = visualViewport; | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user