staging into master #426
							
								
								
									
										43
									
								
								kdb-bot/src/bot_data/model/user_warnings_history.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								kdb-bot/src/bot_data/model/user_warnings_history.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,43 @@ | ||||
| from typing import Optional | ||||
|  | ||||
| from bot_data.abc.history_table_abc import HistoryTableABC | ||||
|  | ||||
|  | ||||
| # had to name it UserWarnings instead of UserWarning because UserWarning is a builtin class | ||||
| class UserWarningsHistory(HistoryTableABC): | ||||
|     def __init__( | ||||
|         self, | ||||
|         description: str, | ||||
|         user: int, | ||||
|         author: Optional[int], | ||||
|         deleted: bool, | ||||
|         date_from: str, | ||||
|         date_to: str, | ||||
|         id=0, | ||||
|     ): | ||||
|         HistoryTableABC.__init__(self) | ||||
|  | ||||
|         self._id = id | ||||
|         self._description = description | ||||
|         self._user = user | ||||
|         self._author = author | ||||
|  | ||||
|         self._deleted = deleted | ||||
|         self._date_from = date_from | ||||
|         self._date_to = date_to | ||||
|  | ||||
|     @property | ||||
|     def id(self) -> int: | ||||
|         return self._id | ||||
|  | ||||
|     @property | ||||
|     def description(self) -> str: | ||||
|         return self._description | ||||
|  | ||||
|     @property | ||||
|     def user(self) -> int: | ||||
|         return self._user | ||||
|  | ||||
|     @property | ||||
|     def author(self) -> Optional[int]: | ||||
|         return self._author | ||||
| @@ -1,3 +1,4 @@ | ||||
| from cpl_core.dependency_injection import ServiceProviderABC | ||||
| from cpl_query.extension import List | ||||
|  | ||||
| from bot_data.model.user import User | ||||
| @@ -5,9 +6,14 @@ from bot_graphql.abc.filter_abc import FilterABC | ||||
|  | ||||
|  | ||||
| class AchievementFilter(FilterABC): | ||||
|     def __init__(self): | ||||
|     def __init__( | ||||
|         self, | ||||
|         services: ServiceProviderABC, | ||||
|     ): | ||||
|         FilterABC.__init__(self) | ||||
|  | ||||
|         self._services = services | ||||
|  | ||||
|         self._id = None | ||||
|         self._name = None | ||||
|         self._description = None | ||||
|   | ||||
							
								
								
									
										56
									
								
								kdb-bot/src/bot_graphql/filter/user_warning_filter.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								kdb-bot/src/bot_graphql/filter/user_warning_filter.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,56 @@ | ||||
| from cpl_core.dependency_injection import ServiceProviderABC | ||||
| from cpl_query.extension import List | ||||
|  | ||||
| from bot_data.model.user_warnings import UserWarnings | ||||
| from bot_graphql.abc.filter_abc import FilterABC | ||||
|  | ||||
|  | ||||
| class UserWarningFilter(FilterABC): | ||||
|     def __init__( | ||||
|         self, | ||||
|         services: ServiceProviderABC, | ||||
|     ): | ||||
|         FilterABC.__init__(self) | ||||
|  | ||||
|         self._services = services | ||||
|  | ||||
|         self._id = None | ||||
|         self._user = None | ||||
|         self._description = None | ||||
|         self._author = None | ||||
|  | ||||
|     def from_dict(self, values: dict): | ||||
|         if "id" in values: | ||||
|             self._id = int(values["id"]) | ||||
|  | ||||
|         if "user" in values: | ||||
|             from bot_graphql.filter.user_filter import UserFilter | ||||
|  | ||||
|             self._user: UserFilter = self._services.get_service(UserFilter) | ||||
|             self._user.from_dict(values["user"]) | ||||
|  | ||||
|         if "description" in values: | ||||
|             self._description = values["description"] | ||||
|  | ||||
|         if "author" in values: | ||||
|             from bot_graphql.filter.user_filter import UserFilter | ||||
|  | ||||
|             self._author: UserFilter = self._services.get_service(UserFilter) | ||||
|             self._author.from_dict(values["author"]) | ||||
|  | ||||
|     def filter(self, query: List[UserWarnings]) -> List[UserWarnings]: | ||||
|         if self._id is not None: | ||||
|             query = query.where(lambda x: x.id == self._id) | ||||
|  | ||||
|         if self._user is not None: | ||||
|             users = self._user.filter(query.select(lambda x: x.user)).select(lambda x: x.id) | ||||
|             query = query.where(lambda x: x.id in users) | ||||
|  | ||||
|         if self._description is not None: | ||||
|             query = query.where(lambda x: x.description == self._description or self._description in x.description) | ||||
|  | ||||
|         if self._author is not None: | ||||
|             users = self._author.filter(query.select(lambda x: x.author)).select(lambda x: x.id) | ||||
|             query = query.where(lambda x: x.id in users) | ||||
|  | ||||
|         return query | ||||
| @@ -41,6 +41,9 @@ type Query { | ||||
|     shortRoleNames(filter: ShortRoleNameFilter, page: Page, sort: Sort): [ShortRoleName] | ||||
|     shortRoleNamePositions: [String] | ||||
|  | ||||
|     userWarningCount: Int | ||||
|     userWarnings(filter: UserWarningFilter, page: Page, sort: Sort): [UserWarning] | ||||
|  | ||||
|     technicianConfig: TechnicianConfig | ||||
|     possibleFeatureFlags: [String] | ||||
|     discord: Discord | ||||
|   | ||||
| @@ -20,6 +20,9 @@ type User implements TableWithHistoryQuery { | ||||
|     achievementCount: Int | ||||
|     achievements(filter: AchievementFilter, page: Page, sort: Sort): [Achievement] | ||||
|  | ||||
|     userWarningCount: Int | ||||
|     userWarnings(filter: UserWarningFilter, page: Page, sort: Sort): [UserWarning] | ||||
|  | ||||
|     server: Server | ||||
|     leftServer: Boolean | ||||
|  | ||||
|   | ||||
							
								
								
									
										27
									
								
								kdb-bot/src/bot_graphql/graphql/userWarning.gql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								kdb-bot/src/bot_graphql/graphql/userWarning.gql
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | ||||
| type UserWarning implements TableWithHistoryQuery { | ||||
|     id: ID | ||||
|     user: User | ||||
|     description: String | ||||
|     author: User | ||||
|  | ||||
|     createdAt: String | ||||
|     modifiedAt: String | ||||
|  | ||||
|     history: [UserWarningHistory] | ||||
| } | ||||
|  | ||||
| type UserWarningHistory implements HistoryTableQuery { | ||||
|     id: ID | ||||
|     user: ID | ||||
|     description: String | ||||
|     author: ID | ||||
|  | ||||
|     deleted: Boolean | ||||
|     dateFrom: String | ||||
|     dateTo: String | ||||
| } | ||||
|  | ||||
| input UserWarningFilter { | ||||
|     id: ID | ||||
|     user: UserFilter | ||||
| } | ||||
| @@ -18,6 +18,7 @@ from bot_graphql.filter.user_filter import UserFilter | ||||
| from bot_graphql.filter.user_joined_game_server_filter import UserJoinedGameServerFilter | ||||
| from bot_graphql.filter.user_joined_server_filter import UserJoinedServerFilter | ||||
| from bot_graphql.filter.user_joined_voice_channel_filter import UserJoinedVoiceChannelFilter | ||||
| from bot_graphql.filter.user_warning_filter import UserWarningFilter | ||||
| from bot_graphql.graphql_service import GraphQLService | ||||
| from bot_graphql.mutation import Mutation | ||||
| from bot_graphql.mutations.achievement_mutation import AchievementMutation | ||||
| @@ -66,6 +67,8 @@ from bot_graphql.queries.user_joined_server_query import UserJoinedServerQuery | ||||
| from bot_graphql.queries.user_joined_voice_channel_history_query import UserJoinedVoiceChannelHistoryQuery | ||||
| from bot_graphql.queries.user_joined_voice_channel_query import UserJoinedVoiceChannelQuery | ||||
| from bot_graphql.queries.user_query import UserQuery | ||||
| from bot_graphql.queries.user_warning_history_query import UserWarningHistoryQuery | ||||
| from bot_graphql.queries.user_warning_query import UserWarningQuery | ||||
| from bot_graphql.query import Query | ||||
| from bot_graphql.schema import Schema | ||||
|  | ||||
| @@ -115,6 +118,8 @@ class GraphQLModule(ModuleABC): | ||||
|         services.add_transient(QueryABC, UserJoinedGameServerQuery) | ||||
|         services.add_transient(QueryABC, ShortRoleNameHistoryQuery) | ||||
|         services.add_transient(QueryABC, ShortRoleNameQuery) | ||||
|         services.add_transient(QueryABC, UserWarningHistoryQuery) | ||||
|         services.add_transient(QueryABC, UserWarningQuery) | ||||
|  | ||||
|         services.add_transient(QueryABC, DiscordQuery) | ||||
|         services.add_transient(QueryABC, GuildQuery) | ||||
| @@ -135,6 +140,7 @@ class GraphQLModule(ModuleABC): | ||||
|         services.add_transient(FilterABC, UserJoinedVoiceChannelFilter) | ||||
|         services.add_transient(FilterABC, UserJoinedGameServerFilter) | ||||
|         services.add_transient(FilterABC, ShortRoleNameFilter) | ||||
|         services.add_transient(FilterABC, UserWarningFilter) | ||||
|  | ||||
|         # mutations | ||||
|         services.add_transient(QueryABC, AutoRoleMutation) | ||||
|   | ||||
| @@ -6,6 +6,7 @@ from bot_data.abc.achievement_repository_abc import AchievementRepositoryABC | ||||
| from bot_data.abc.user_joined_game_server_repository_abc import UserJoinedGameServerRepositoryABC | ||||
| from bot_data.abc.user_joined_server_repository_abc import UserJoinedServerRepositoryABC | ||||
| from bot_data.abc.user_joined_voice_channel_repository_abc import UserJoinedVoiceChannelRepositoryABC | ||||
| from bot_data.abc.user_warnings_repository_abc import UserWarningsRepositoryABC | ||||
| from bot_data.model.user import User | ||||
| from bot_data.model.user_history import UserHistory | ||||
| from bot_graphql.abc.data_query_with_history_abc import DataQueryWithHistoryABC | ||||
| @@ -13,6 +14,7 @@ from bot_graphql.filter.achievement_filter import AchievementFilter | ||||
| from bot_graphql.filter.user_joined_game_server_filter import UserJoinedGameServerFilter | ||||
| from bot_graphql.filter.user_joined_server_filter import UserJoinedServerFilter | ||||
| from bot_graphql.filter.user_joined_voice_channel_filter import UserJoinedVoiceChannelFilter | ||||
| from bot_graphql.filter.user_warning_filter import UserWarningFilter | ||||
| from modules.level.service.level_service import LevelService | ||||
| from modules.permission.abc.permission_service_abc import PermissionServiceABC | ||||
|  | ||||
| @@ -29,6 +31,7 @@ class UserQuery(DataQueryWithHistoryABC): | ||||
|         user_joined_game_server: UserJoinedGameServerRepositoryABC, | ||||
|         permissions: PermissionServiceABC, | ||||
|         achievements: AchievementRepositoryABC, | ||||
|         user_warnings: UserWarningsRepositoryABC, | ||||
|     ): | ||||
|         DataQueryWithHistoryABC.__init__(self, "User", "UsersHistory", UserHistory, db) | ||||
|  | ||||
| @@ -67,6 +70,9 @@ class UserQuery(DataQueryWithHistoryABC): | ||||
|         self.add_collection( | ||||
|             "achievement", lambda user, *_: achievements.get_achievements_by_user_id(user.id), AchievementFilter | ||||
|         ) | ||||
|         self.add_collection( | ||||
|             "userWarning", lambda user, *_: user_warnings.get_user_warnings_by_user_id(user.id), UserWarningFilter | ||||
|         ) | ||||
|  | ||||
|         self.set_field("server", self.resolve_server) | ||||
|         self.set_field("leftServer", self.resolve_left_server) | ||||
|   | ||||
| @@ -0,0 +1,11 @@ | ||||
| from bot_graphql.abc.history_query_abc import HistoryQueryABC | ||||
|  | ||||
|  | ||||
| class UserWarningHistoryQuery(HistoryQueryABC): | ||||
|     def __init__(self): | ||||
|         HistoryQueryABC.__init__(self, "UserWarning") | ||||
|  | ||||
|         self.set_field("id", lambda x, *_: x.id) | ||||
|         self.set_field("user", lambda x, *_: x.user) | ||||
|         self.set_field("description", lambda x, *_: x.description) | ||||
|         self.set_field("author", lambda x, *_: x.author) | ||||
							
								
								
									
										17
									
								
								kdb-bot/src/bot_graphql/queries/user_warning_query.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								kdb-bot/src/bot_graphql/queries/user_warning_query.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | ||||
| from cpl_core.database.context import DatabaseContextABC | ||||
|  | ||||
| from bot_data.model.user_warnings_history import UserWarningsHistory | ||||
| from bot_graphql.abc.data_query_with_history_abc import DataQueryWithHistoryABC | ||||
|  | ||||
|  | ||||
| class UserWarningQuery(DataQueryWithHistoryABC): | ||||
|     def __init__( | ||||
|         self, | ||||
|         db: DatabaseContextABC, | ||||
|     ): | ||||
|         DataQueryWithHistoryABC.__init__(self, "UserWarning", "UserWarningsHistory", UserWarningsHistory, db) | ||||
|  | ||||
|         self.set_field("id", lambda x, *_: x.id) | ||||
|         self.set_field("user", lambda x, *_: x.user) | ||||
|         self.set_field("description", lambda x, *_: x.description) | ||||
|         self.set_field("author", lambda x, *_: x.author) | ||||
| @@ -15,6 +15,7 @@ from bot_data.abc.user_joined_game_server_repository_abc import UserJoinedGameSe | ||||
| from bot_data.abc.user_joined_server_repository_abc import UserJoinedServerRepositoryABC | ||||
| from bot_data.abc.user_joined_voice_channel_repository_abc import UserJoinedVoiceChannelRepositoryABC | ||||
| from bot_data.abc.user_repository_abc import UserRepositoryABC | ||||
| from bot_data.abc.user_warnings_repository_abc import UserWarningsRepositoryABC | ||||
| from bot_data.model.short_role_name_position_enum import ShortRoleNamePositionEnum | ||||
| from bot_graphql.abc.query_abc import QueryABC | ||||
| from bot_graphql.filter.achievement_filter import AchievementFilter | ||||
| @@ -28,6 +29,7 @@ from bot_graphql.filter.user_filter import UserFilter | ||||
| from bot_graphql.filter.user_joined_game_server_filter import UserJoinedGameServerFilter | ||||
| from bot_graphql.filter.user_joined_server_filter import UserJoinedServerFilter | ||||
| from bot_graphql.filter.user_joined_voice_channel_filter import UserJoinedVoiceChannelFilter | ||||
| from bot_graphql.filter.user_warning_filter import UserWarningFilter | ||||
| from bot_graphql.model.discord import Discord | ||||
| from modules.achievements.achievement_service import AchievementService | ||||
|  | ||||
| @@ -48,6 +50,7 @@ class Query(QueryABC): | ||||
|         users: UserRepositoryABC, | ||||
|         achievements: AchievementRepositoryABC, | ||||
|         short_role_names: ShortRoleNameRepositoryABC, | ||||
|         user_warnings: UserWarningsRepositoryABC, | ||||
|         achievement_service: AchievementService, | ||||
|         technician_config: TechnicianConfigRepositoryABC, | ||||
|     ): | ||||
| @@ -76,11 +79,13 @@ class Query(QueryABC): | ||||
|         self.add_collection("user", lambda *_: users.get_users(), UserFilter) | ||||
|         self.add_collection("achievement", lambda *_: achievements.get_achievements(), AchievementFilter) | ||||
|         self.add_collection("shortRoleName", lambda *_: short_role_names.get_short_role_names(), ShortRoleNameFilter) | ||||
|         self.add_collection("userWarning", lambda *_: user_warnings.get_user_warnings(), UserWarningFilter) | ||||
|  | ||||
|         self.set_field("technicianConfig", lambda *_: technician_config.get_technician_config()) | ||||
|  | ||||
|         self.set_field("achievementAttributes", lambda *_: achievement_service.get_attributes()) | ||||
|         self.set_field("achievementOperators", lambda *_: achievement_service.get_operators()) | ||||
|         self.set_field("shortRoleNamePositions", lambda *_: [x.value for x in ShortRoleNamePositionEnum]) | ||||
|  | ||||
|         self.set_field("possibleFeatureFlags", lambda *_: [e.value for e in FeatureFlagsEnum]) | ||||
|         self.set_field("discord", lambda *_: Discord(bot.guilds, List(any).extend(bot.users))) | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| { | ||||
|     "name": "kdb-web", | ||||
|     "version": "1.1.10", | ||||
|     "version": "1.1.dev402", | ||||
|     "scripts": { | ||||
|         "ng": "ng", | ||||
|         "update-version": "ts-node update-version.ts", | ||||
| @@ -51,4 +51,4 @@ | ||||
|         "tslib": "^2.4.1", | ||||
|         "typescript": "~4.9.5" | ||||
|     } | ||||
| } | ||||
| } | ||||
| @@ -5,6 +5,7 @@ import { UserJoinedServer } from "./user_joined_server.model"; | ||||
| import { UserJoinedVoiceChannel } from "./user_joined_voice_channel.model"; | ||||
| import { UserJoinedGameServer } from "./user_joined_game_server.model"; | ||||
| import { Achievement } from "./achievement.model"; | ||||
| import { UserWarning } from "./user_warning.model"; | ||||
|  | ||||
| export interface User extends DataWithHistory { | ||||
|   id?: number; | ||||
| @@ -29,6 +30,9 @@ export interface User extends DataWithHistory { | ||||
|  | ||||
|   achievementCount?: number; | ||||
|   achievements?: Achievement[]; | ||||
|  | ||||
|   userWarningCount?: number; | ||||
|   userWarnings?: UserWarning[]; | ||||
| } | ||||
|  | ||||
| export interface UserFilter { | ||||
|   | ||||
							
								
								
									
										16
									
								
								kdb-web/src/app/models/data/user_warning.model.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								kdb-web/src/app/models/data/user_warning.model.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | ||||
| import { DataWithHistory } from "./data.model"; | ||||
| import { User, UserFilter } from "./user.model"; | ||||
|  | ||||
| export interface UserWarning extends DataWithHistory { | ||||
|   id?: number; | ||||
|   user?: User; | ||||
|   description?: string; | ||||
|   author?: User; | ||||
| } | ||||
|  | ||||
| export interface UserWarningFilter { | ||||
|   id?: number; | ||||
|   user?: UserFilter; | ||||
|   description?: string; | ||||
|   author?: UserFilter; | ||||
| } | ||||
| @@ -208,7 +208,7 @@ export class Queries { | ||||
|     query { | ||||
|       shortRoleNamePositions | ||||
|     } | ||||
|   ` | ||||
|   `; | ||||
|  | ||||
|   static shortRoleNameQuery = ` | ||||
|     query ShortRoleNameList($serverId: ID, $filter: ShortRoleNameFilter, $page: Page, $sort: Sort) { | ||||
| @@ -279,58 +279,94 @@ export class Queries { | ||||
|  | ||||
|   static userProfile = ` | ||||
|     query UserProfile($serverId: ID, $userId: ID, $page: Page, $sort: Sort) { | ||||
|       servers(filter: {id: $serverId}) { | ||||
|         userCount | ||||
|         users(filter: {id: $userId}, page: $page, sort: $sort) { | ||||
|       userCount | ||||
|       users(filter: {server: {id: $serverId}, id: $userId}, page: $page, sort: $sort) { | ||||
|         id | ||||
|         discordId | ||||
|         name | ||||
|         xp | ||||
|         ontime | ||||
|         level { | ||||
|           id | ||||
|           discordId | ||||
|           name | ||||
|           xp | ||||
|           ontime | ||||
|           level { | ||||
|         } | ||||
|         leftServer | ||||
|         server { | ||||
|           id | ||||
|           name | ||||
|         } | ||||
|  | ||||
|         joinedServerCount | ||||
|         joinedServers { | ||||
|           id | ||||
|           joinedOn | ||||
|           leavedOn | ||||
|         } | ||||
|  | ||||
|         createdAt | ||||
|         modifiedAt | ||||
|       } | ||||
|     } | ||||
|   `; | ||||
|  | ||||
|   static userProfileAchievements = ` | ||||
|     query UserProfile($serverId: ID, $userId: ID, $page: Page, $sort: Sort) { | ||||
|       users(filter: {server: {id: $serverId}, id: $userId}, page: $page, sort: $sort) { | ||||
|         achievementCount | ||||
|         achievements { | ||||
|           id | ||||
|           name | ||||
|           description | ||||
|           createdAt | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   `; | ||||
|  | ||||
|   static userProfileVoiceChannelJoins = ` | ||||
|     query UserProfile($serverId: ID, $userId: ID, $page: Page, $sort: Sort) { | ||||
|       users(filter: {server: {id: $serverId}, id: $userId}, page: $page, sort: $sort) { | ||||
|         joinedVoiceChannelCount | ||||
|         joinedVoiceChannels { | ||||
|           id | ||||
|           channelId | ||||
|           channelName | ||||
|           time | ||||
|           joinedOn | ||||
|           leavedOn | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   `; | ||||
|  | ||||
|   static userProfileGameserverJoins = ` | ||||
|     query UserProfile($serverId: ID, $userId: ID, $page: Page, $sort: Sort) { | ||||
|       users(filter: {server: {id: $serverId}, id: $userId}, page: $page, sort: $sort) { | ||||
|         userJoinedGameServerCount | ||||
|         userJoinedGameServers { | ||||
|           id | ||||
|           gameServer | ||||
|           time | ||||
|           joinedOn | ||||
|           leavedOn | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   `; | ||||
|  | ||||
|   static userProfileWarnings = ` | ||||
|     query UserProfile($serverId: ID, $userId: ID, $page: Page, $sort: Sort) { | ||||
|       users(filter: {server: {id: $serverId}, id: $userId}, page: $page, sort: $sort) { | ||||
|         userWarningCount | ||||
|         userWarnings { | ||||
|           id | ||||
|           description | ||||
|           author { | ||||
|             id | ||||
|             name | ||||
|           } | ||||
|           leftServer | ||||
|           server { | ||||
|             id | ||||
|             name | ||||
|           } | ||||
|  | ||||
|           joinedServerCount | ||||
|           joinedServers { | ||||
|             id | ||||
|             joinedOn | ||||
|             leavedOn | ||||
|           } | ||||
|  | ||||
|           joinedVoiceChannelCount | ||||
|           joinedVoiceChannels { | ||||
|             id | ||||
|             channelId | ||||
|             channelName | ||||
|             time | ||||
|             joinedOn | ||||
|             leavedOn | ||||
|           } | ||||
|  | ||||
|           userJoinedGameServerCount | ||||
|           userJoinedGameServers { | ||||
|             id | ||||
|             gameServer | ||||
|             time | ||||
|             joinedOn | ||||
|             leavedOn | ||||
|           } | ||||
|  | ||||
|           achievements { | ||||
|             id | ||||
|             name | ||||
|             createdAt | ||||
|           } | ||||
|  | ||||
|           createdAt | ||||
|           modifiedAt | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   | ||||
| @@ -8,6 +8,7 @@ import { TechnicianConfig } from "../config/technician-config.model"; | ||||
| import { ServerConfig } from "../config/server-config.model"; | ||||
| import { ShortRoleName } from "../data/short_role_name.model"; | ||||
| import { FeatureFlag } from "../config/feature-flags.model"; | ||||
| import { UserWarning } from "../data/user_warning.model"; | ||||
|  | ||||
| export interface Query { | ||||
|   serverCount: number; | ||||
| @@ -31,6 +32,11 @@ export interface UserListQuery { | ||||
|   users: User[]; | ||||
| } | ||||
|  | ||||
| export interface UserWarningQuery { | ||||
|   userWarningCount: number; | ||||
|   userWarnings: UserWarning[]; | ||||
| } | ||||
|  | ||||
| export interface GameServerListQuery { | ||||
|   gameServerCount: number; | ||||
|   gameServers: GameServer[]; | ||||
|   | ||||
| @@ -76,9 +76,103 @@ | ||||
|       </div> | ||||
|     </div> | ||||
|  | ||||
|     <div> | ||||
|       <div class="content-divider"></div> | ||||
|       <p-table #dt [value]="(user.userWarnings ?? [])" [responsive]="true" responsiveLayout="stack" [breakpoint]="'720px'" dataKey="id" editMode="row"> | ||||
|         <ng-template pTemplate="caption"> | ||||
|           <div class="table-caption"> | ||||
|             <div class="table-caption-table-info"> | ||||
|               <div class="table-caption-text"> | ||||
|                 <h3>{{'common.user_warnings' | translate}}</h3> | ||||
|               </div> | ||||
|             </div> | ||||
|             <div class="table-caption-btn-wrapper btn-wrapper"> | ||||
|               <button pButton label="{{'common.add' | translate}}" class="icon-btn btn" | ||||
|                       icon="pi pi-plus" (click)="addNewUserWarning(dt)"> | ||||
|               </button> | ||||
|             </div> | ||||
|           </div> | ||||
|         </ng-template> | ||||
|         <ng-template pTemplate="header"> | ||||
|           <tr> | ||||
|             <th> | ||||
|               <div class="table-header-label"> | ||||
|                 <div class="table-header-text">{{'common.description' | translate}}</div> | ||||
|               </div> | ||||
|             </th> | ||||
|  | ||||
|             <th> | ||||
|               <div class="table-header-label"> | ||||
|                 <div class="table-header-text">{{'common.author' | translate}}</div> | ||||
|               </div> | ||||
|             </th> | ||||
|  | ||||
|             <th> | ||||
|               <div class="table-header-label"> | ||||
|                 <div class="table-header-text">{{'common.created_at' | translate}}</div> | ||||
|               </div> | ||||
|             </th> | ||||
|  | ||||
|             <th class="table-header-actions"> | ||||
|               <div class="table-header-label"> | ||||
|                 <div class="table-header-text">{{'common.actions' | translate}}</div> | ||||
|               </div> | ||||
|             </th> | ||||
|           </tr> | ||||
|         </ng-template> | ||||
|         <ng-template pTemplate="body" let-value let-editing="editing" let-ri="rowIndex"> | ||||
|           <tr [pEditableRow]="value"> | ||||
|             <td> | ||||
|               <p-cellEditor> | ||||
|                 <ng-template pTemplate="input"> | ||||
|                   <input class="table-edit-input" pInputText type="text" [(ngModel)]="value.description"> | ||||
|                 </ng-template> | ||||
|                 <ng-template pTemplate="output"> | ||||
|                   {{value.description}} | ||||
|                 </ng-template> | ||||
|               </p-cellEditor> | ||||
|             </td> | ||||
|             <td> | ||||
|               <p-cellEditor> | ||||
|                 <ng-template pTemplate="input"> | ||||
|                   {{value.author.name}} | ||||
|                 </ng-template> | ||||
|                 <ng-template pTemplate="output"> | ||||
|                   {{value.author.name}} | ||||
|                 </ng-template> | ||||
|               </p-cellEditor> | ||||
|             </td> | ||||
|  | ||||
|             <td> | ||||
|               <span class="p-column-title">{{'common.created_at' | translate}}:</span> | ||||
|               <p-cellEditor> | ||||
|                 <ng-template pTemplate="input"> | ||||
|                   {{value.createdAt | date:'dd.MM.yy HH:mm'}} | ||||
|                 </ng-template> | ||||
|                 <ng-template pTemplate="output"> | ||||
|                   {{value.createdAt | date:'dd.MM.yy HH:mm'}} | ||||
|                 </ng-template> | ||||
|               </p-cellEditor> | ||||
|             </td> | ||||
|             <td> | ||||
|               <div class="btn-wrapper"> | ||||
|                 <button *ngIf="!editing" pButton type="button" class="btn danger-icon-btn" icon="pi pi-trash" (click)="deleteUserWarning(ri)"></button> | ||||
|  | ||||
|                 <button *ngIf="editing" pButton type="button" pSaveEditableRow class="btn icon-btn" icon="pi pi-check" (click)="editSaveUserWarning(value, ri)"></button> | ||||
|                 <button *ngIf="editing" pButton type="button" pCancelEditableRow class="btn danger-icon-btn" icon="pi pi-times" | ||||
|                         (click)="editCancelUserWarning(ri)"></button> | ||||
|               </div> | ||||
|             </td> | ||||
|           </tr> | ||||
|         </ng-template> | ||||
|       </p-table> | ||||
|       <br> | ||||
|     </div> | ||||
|  | ||||
|     <div class="content-divider"></div> | ||||
|  | ||||
|     <p-panel header="{{'view.server.profile.achievements.header' | translate}}" [toggleable]="true"> | ||||
|     <p-panel header="{{'view.server.profile.achievements.header' | translate}}" [toggleable]="true" [collapsed]="true" | ||||
|              (onBeforeToggle)="onBeforeToggle($event.event, $event.collapsed)"> | ||||
|       <div *ngFor="let achievement of user.achievements;"> | ||||
|         <div class="content-row"> | ||||
|           <div class="content-column"> | ||||
| @@ -86,6 +180,11 @@ | ||||
|             <div class="content-data-value">{{achievement.name}}</div> | ||||
|           </div> | ||||
|  | ||||
|           <div class="content-column"> | ||||
|             <div class="content-data-name">{{'common.description' | translate}}:</div> | ||||
|             <div class="content-data-value">{{achievement.description}}</div> | ||||
|           </div> | ||||
|  | ||||
|           <div class="content-column"> | ||||
|             <div class="content-data-name">{{'view.server.profile.achievements.time' | translate}}:</div> | ||||
|             <div class="content-data-value">{{achievement.createdAt | date:'dd.MM.yyyy HH:mm:ss'}}</div> | ||||
| @@ -94,7 +193,8 @@ | ||||
|       </div> | ||||
|     </p-panel> | ||||
|  | ||||
|     <p-panel header="{{'view.server.profile.joined_voice_channel.header' | translate}}" [toggleable]="true"> | ||||
|     <p-panel header="{{'view.server.profile.joined_voice_channel.header' | translate}}" [toggleable]="true" [collapsed]="true" | ||||
|              (onBeforeToggle)="onBeforeToggle($event.event, $event.collapsed)"> | ||||
|       <div *ngFor="let join of user.joinedVoiceChannels;"> | ||||
|         <div class="content-row"> | ||||
|           <div class="content-column"> | ||||
| @@ -120,7 +220,8 @@ | ||||
|       </div> | ||||
|     </p-panel> | ||||
|  | ||||
|     <p-panel header="{{'view.server.profile.joined_game_server.header' | translate}}" [toggleable]="true"> | ||||
|     <p-panel header="{{'view.server.profile.joined_game_server.header' | translate}}" [toggleable]="true" [collapsed]="true" | ||||
|              (onBeforeToggle)="onBeforeToggle($event.event, $event.collapsed)"> | ||||
|       <div *ngFor="let join of user.userJoinedGameServers;"> | ||||
|         <div class="content-row"> | ||||
|           <div class="content-column"> | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| import { Component, OnDestroy, OnInit } from "@angular/core"; | ||||
| import { ActivatedRoute, Router } from "@angular/router"; | ||||
| import { Queries } from "../../../../models/graphql/queries.model"; | ||||
| import { UserListQuery } from "../../../../models/graphql/query.model"; | ||||
| import { UserListQuery, UserWarningQuery } 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"; | ||||
| @@ -10,8 +10,9 @@ 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 { Subject } from "rxjs"; | ||||
| import { forkJoin, Subject } from "rxjs"; | ||||
| import { takeUntil } from "rxjs/operators"; | ||||
| import { Table } from "primeng/table"; | ||||
|  | ||||
| @Component({ | ||||
|   selector: "app-profile", | ||||
| @@ -58,16 +59,27 @@ export class ProfileComponent implements OnInit, OnDestroy { | ||||
|         this.data.query<UserListQuery>(Queries.userProfile, { | ||||
|             serverId: this.server.id, | ||||
|             userId: params["memberId"] | ||||
|           }, | ||||
|           (x: { servers: Server[] }) => { | ||||
|             return x.servers[0]; | ||||
|           } | ||||
|         ).subscribe(users => { | ||||
|           if (!users.users[0]) { | ||||
|             this.router.navigate([`/server/${server.id}`]); | ||||
|           } | ||||
|           this.user = users.users[0]; | ||||
|           this.spinner.hideSpinner(); | ||||
|  | ||||
|           this.data.query<UserWarningQuery>(Queries.userProfileWarnings, { | ||||
|               serverId: this.server.id, | ||||
|               userId: this.user.id | ||||
|             }, | ||||
|             (data: UserListQuery) => { | ||||
|               return data.users[0]; | ||||
|             } | ||||
|           ).subscribe(result => { | ||||
|             this.user.userWarningCount = result.userWarningCount; | ||||
|             this.user.userWarnings = result.userWarnings; | ||||
|             console.log(result); | ||||
|  | ||||
|             this.spinner.hideSpinner(); | ||||
|           }); | ||||
|         }); | ||||
|       }); | ||||
|     }); | ||||
| @@ -77,4 +89,68 @@ export class ProfileComponent implements OnInit, OnDestroy { | ||||
|     this.unsubscriber.next(); | ||||
|     this.unsubscriber.complete(); | ||||
|   } | ||||
|  | ||||
|   public onBeforeToggle(event: Event, collapsed: boolean) { | ||||
|     const filterUser = (x: { users: User[] }) => { | ||||
|       const users = x.users ?? []; | ||||
|       return users[0]; | ||||
|     }; | ||||
|  | ||||
|     if (collapsed) { | ||||
|       this.spinner.showSpinner(); | ||||
|       forkJoin([ | ||||
|         this.data.query<User>(Queries.userProfileAchievements, { | ||||
|             serverId: this.server.id, | ||||
|             userId: this.user.id | ||||
|           }, | ||||
|           filterUser | ||||
|         ), | ||||
|         this.data.query<User>(Queries.userProfileVoiceChannelJoins, { | ||||
|             serverId: this.server.id, | ||||
|             userId: this.user.id | ||||
|           }, | ||||
|           filterUser | ||||
|         ), | ||||
|         this.data.query<User>(Queries.userProfileGameserverJoins, { | ||||
|             serverId: this.server.id, | ||||
|             userId: this.user.id | ||||
|           }, | ||||
|           filterUser | ||||
|         ) | ||||
|       ]).subscribe(data => { | ||||
|         this.user.achievementCount = data[0].achievementCount; | ||||
|         this.user.achievements = data[0].achievements; | ||||
|  | ||||
|         this.user.joinedVoiceChannelCount = data[1].joinedVoiceChannelCount; | ||||
|         this.user.joinedVoiceChannels = data[1].joinedVoiceChannels; | ||||
|  | ||||
|         this.user.userJoinedGameServerCount = data[2].userJoinedGameServerCount; | ||||
|         this.user.userJoinedGameServers = data[2].userJoinedGameServers; | ||||
|         this.spinner.hideSpinner(); | ||||
|       }); | ||||
|       return; | ||||
|     } | ||||
|     this.user.achievementCount = 0; | ||||
|     this.user.achievements = []; | ||||
|  | ||||
|     this.user.userJoinedGameServerCount = 0; | ||||
|     this.user.userJoinedGameServers = []; | ||||
|  | ||||
|     this.user.joinedVoiceChannelCount = 0; | ||||
|     this.user.joinedVoiceChannels = []; | ||||
|   } | ||||
|  | ||||
|   addNewUserWarning(table: Table) { | ||||
|   } | ||||
|  | ||||
|   deleteUserWarning(index: number) { | ||||
|   } | ||||
|  | ||||
|   editSaveUserWarning(value: any, index: number) { | ||||
|   } | ||||
|  | ||||
|   editCancelUserWarning(index: number) { | ||||
|   } | ||||
|  | ||||
|   protected readonly visualViewport = visualViewport; | ||||
| } | ||||
|   | ||||
| @@ -1,12 +1,11 @@ | ||||
| import { NgModule } from '@angular/core'; | ||||
| import { CommonModule } from '@angular/common'; | ||||
| import { ServerDashboardComponent } from './server-dashboard/server-dashboard.component'; | ||||
| import { ServerRoutingModule } from './server-routing.module'; | ||||
| import { SharedModule } from '../../shared/shared.module'; | ||||
| import { ProfileComponent } from './profile/profile.component'; | ||||
| import { MembersComponent } from './members/members.component'; | ||||
| import { ClientComponent } from './server-dashboard/components/client/client.component'; | ||||
|  | ||||
| import { NgModule } from "@angular/core"; | ||||
| import { CommonModule } from "@angular/common"; | ||||
| import { ServerDashboardComponent } from "./server-dashboard/server-dashboard.component"; | ||||
| import { ServerRoutingModule } from "./server-routing.module"; | ||||
| import { SharedModule } from "../../shared/shared.module"; | ||||
| import { ProfileComponent } from "./profile/profile.component"; | ||||
| import { MembersComponent } from "./members/members.component"; | ||||
| import { ClientComponent } from "./server-dashboard/components/client/client.component"; | ||||
|  | ||||
|  | ||||
| @NgModule({ | ||||
|   | ||||
| @@ -194,7 +194,6 @@ export class SidebarService { | ||||
|       let user: UserDTO | null = authUser?.users?.find(u => u.server == this.server?.id) ?? null; | ||||
|       let isTechnician = (authUser?.users?.map(u => u.isTechnician).filter(u => u) ?? []).length > 0; | ||||
|       let isTechnicianAndFullAccessActive = this.hasFeature("TechnicianFullAccess") && isTechnician; | ||||
|       console.log(this.hasFeature("TechnicianFullAccess")) | ||||
|  | ||||
|       if (build || this.menuItems$.value.length == 0) { | ||||
|         await this.buildMenu(user, hasPermission, isTechnician); | ||||
|   | ||||
| @@ -122,6 +122,8 @@ | ||||
|     } | ||||
|   }, | ||||
|   "common": { | ||||
|     "user_warnings": "Verwarnungen", | ||||
|     "author": "Autor", | ||||
|     "404": "404 - Der Eintrag konnte nicht gefunden werden", | ||||
|     "actions": "Aktionen", | ||||
|     "active": "Aktiv", | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| { | ||||
|   "WebVersion": { | ||||
|     "Major": "1", | ||||
|     "Minor": "1", | ||||
|     "Micro": "10" | ||||
|   } | ||||
| } | ||||
|     "WebVersion": { | ||||
|         "Major": "1", | ||||
|         "Minor": "1", | ||||
|         "Micro": "dev402" | ||||
|     } | ||||
| } | ||||
| @@ -201,10 +201,10 @@ header { | ||||
|  | ||||
|               font-size: 18px; | ||||
|             } | ||||
|           } | ||||
|  | ||||
|             .content-divider { | ||||
|               margin: 5px 0; | ||||
|             } | ||||
|           .content-divider { | ||||
|             margin: 10px 0; | ||||
|           } | ||||
|  | ||||
|           p-panel { | ||||
| @@ -493,7 +493,7 @@ header { | ||||
|   } | ||||
|  | ||||
|   .content-divider { | ||||
|     margin: 5px 0; | ||||
|     margin: 10px 0; | ||||
|   } | ||||
|  | ||||
|   .content-input-field { | ||||
|   | ||||
| @@ -20,7 +20,8 @@ | ||||
|   background-color: $primaryBackgroundColor; | ||||
|  | ||||
|   h1, | ||||
|   h2 { | ||||
|   h2, | ||||
|   h3 { | ||||
|     color: $primaryHeaderColor; | ||||
|   } | ||||
|  | ||||
|   | ||||
| @@ -20,7 +20,8 @@ | ||||
|   background-color: $primaryBackgroundColor; | ||||
|  | ||||
|   h1, | ||||
|   h2 { | ||||
|   h2, | ||||
|   h3 { | ||||
|     color: $primaryHeaderColor; | ||||
|   } | ||||
|  | ||||
|   | ||||
| @@ -21,7 +21,8 @@ | ||||
|  | ||||
|  | ||||
|   h1, | ||||
|   h2 { | ||||
|   h2, | ||||
|   h3 { | ||||
|     color: $primaryHeaderColor; | ||||
|   } | ||||
|  | ||||
|   | ||||
| @@ -20,7 +20,8 @@ | ||||
|   background-color: $primaryBackgroundColor; | ||||
|  | ||||
|   h1, | ||||
|   h2 { | ||||
|   h2, | ||||
|   h3 { | ||||
|     color: $primaryHeaderColor; | ||||
|   } | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user