diff --git a/kdb-bot/src/bot/config b/kdb-bot/src/bot/config index ac704682..84d05a9c 160000 --- a/kdb-bot/src/bot/config +++ b/kdb-bot/src/bot/config @@ -1 +1 @@ -Subproject commit ac7046820f3410f55e779797126d9410c6bcdc9f +Subproject commit 84d05a9c7825ada185c4c0819555fa6b3b0de662 diff --git a/kdb-bot/src/bot_api/model/auth_user_dto.py b/kdb-bot/src/bot_api/model/auth_user_dto.py index 6d80410b..0572fad8 100644 --- a/kdb-bot/src/bot_api/model/auth_user_dto.py +++ b/kdb-bot/src/bot_api/model/auth_user_dto.py @@ -1,7 +1,10 @@ from datetime import datetime from typing import Optional +from cpl_query.extension import List + from bot_api.abc.dto_abc import DtoABC +from bot_api.model.user_dto import UserDTO from bot_data.model.auth_role_enum import AuthRoleEnum @@ -15,6 +18,7 @@ class AuthUserDTO(DtoABC): password: str = None, confirmation_id: Optional[str] = None, auth_role: AuthRoleEnum = None, + users: List[UserDTO] = None, created_at: datetime = None, modified_at: datetime = None, ): @@ -30,6 +34,11 @@ class AuthUserDTO(DtoABC): self._created_at = created_at self._modified_at = modified_at + if users is None: + self._users = List(UserDTO) + else: + self._users = users + @property def id(self) -> int: return self._id @@ -82,6 +91,10 @@ class AuthUserDTO(DtoABC): def auth_role(self, value: AuthRoleEnum): self._auth_role = value + @property + def users(self) -> List[UserDTO]: + return self._users + @property def created_at(self) -> datetime: return self._created_at @@ -98,6 +111,12 @@ class AuthUserDTO(DtoABC): self._password = values["password"] self._is_confirmed = values["isConfirmed"] self._auth_role = AuthRoleEnum(values["authRole"]) + if "users" in values: + self._users = List(UserDTO) + for u in values["users"]: + user = UserDTO() + user.from_dict(u) + self._users.add(user) self._created_at = values["createdAt"] self._modified_at = values["modifiedAt"] @@ -111,6 +130,7 @@ class AuthUserDTO(DtoABC): "password": self._password, "isConfirmed": self._is_confirmed, "authRole": self._auth_role.value, + "users": self._users.select(lambda u: u.to_dict()).to_list(), "createdAt": self._created_at, "modifiedAt": self._modified_at, } diff --git a/kdb-bot/src/bot_api/model/user_dto.py b/kdb-bot/src/bot_api/model/user_dto.py new file mode 100644 index 00000000..c15f1bfe --- /dev/null +++ b/kdb-bot/src/bot_api/model/user_dto.py @@ -0,0 +1,88 @@ +from typing import Optional + +from bot_api.abc.dto_abc import DtoABC +from bot_data.model.server import Server + + +class UserDTO(DtoABC): + def __init__( + self, + id: int = None, + dc_id: int = None, + xp: int = None, + minecraft_id: Optional[str] = None, + server: Optional[Server] = None, + is_technician: Optional[bool] = None, + is_admin: Optional[bool] = None, + is_moderator: Optional[bool] = None, + ): + DtoABC.__init__(self) + + self._user_id = id + self._discord_id = dc_id + self._xp = xp + self._minecraft_id = minecraft_id + self._server = server + + self._is_technician = is_technician + self._is_admin = is_admin + self._is_moderator = is_moderator + + @property + def user_id(self) -> int: + return self._user_id + + @property + def discord_id(self) -> int: + return self._discord_id + + @property + def xp(self) -> int: + return self._xp + + @xp.setter + def xp(self, value: int): + self._xp = value + + @property + def minecraft_id(self) -> Optional[str]: + return self._minecraft_id + + @minecraft_id.setter + def minecraft_id(self, value: str): + self._minecraft_id = value + + @property + def server(self) -> Optional[Server]: + return self._server + + @property + def is_technician(self) -> bool: + return self._is_technician if self._is_technician is not None else False + + @property + def is_admin(self) -> bool: + return self._is_admin if self._is_admin is not None else False + + @property + def is_moderator(self) -> bool: + return self._is_moderator if self._is_moderator is not None else False + + def from_dict(self, values: dict): + self._user_id = values["id"] + self._discord_id = values["dcId"] + self._xp = values["xp"] + self._minecraft_id = values["minecraftId"] + self._server = values["server"] + + def to_dict(self) -> dict: + return { + "id": self._user_id, + "dcId": self._discord_id, + "xp": self._xp, + "minecraftId": self._minecraft_id, + "server": self._server.id, + "isTechnician": self.is_technician, + "isAdmin": self.is_admin, + "isModerator": self.is_moderator, + } diff --git a/kdb-bot/src/bot_api/service/discord_service.py b/kdb-bot/src/bot_api/service/discord_service.py index 4770930a..386b3046 100644 --- a/kdb-bot/src/bot_api/service/discord_service.py +++ b/kdb-bot/src/bot_api/service/discord_service.py @@ -2,7 +2,6 @@ from typing import Optional from cpl_discord.service import DiscordBotServiceABC from cpl_query.extension import List -from flask import jsonify from bot_api.abc.auth_service_abc import AuthServiceABC from bot_api.exception.service_error_code_enum import ServiceErrorCode @@ -10,7 +9,6 @@ from bot_api.exception.service_exception import ServiceException from bot_api.filter.discord.server_select_criteria import ServerSelectCriteria from bot_api.model.discord.server_dto import ServerDTO from bot_api.model.discord.server_filtered_result_dto import ServerFilteredResultDTO -from bot_api.model.error_dto import ErrorDTO from bot_api.transformer.server_transformer import ServerTransformer from bot_data.abc.auth_user_repository_abc import AuthUserRepositoryABC from bot_data.abc.server_repository_abc import ServerRepositoryABC @@ -35,7 +33,7 @@ class DiscordService: self._users = users def _to_dto(self, x: Server) -> Optional[ServerDTO]: - guild = self._bot.get_guild(x.discord_server_id) + guild = self._bot.get_guild(x.discord_id) if guild is None: return ServerTransformer.to_dto(x, "", 0, None) @@ -55,8 +53,8 @@ class DiscordService: if role != AuthRoleEnum.admin: auth_user = self._auth_users.find_auth_user_by_email(token["email"]) if auth_user is not None: - user_ids = auth_user.users.select(lambda x: x.server is not None and x.server.server_id) - servers = servers.where(lambda x: x.server_id in user_ids) + user_ids = auth_user.users.select(lambda x: x.server is not None and x.server.id) + servers = servers.where(lambda x: x.id in user_ids) servers = List(ServerDTO, servers) return servers.select(self._to_dto).where(lambda x: x.name != "") @@ -72,8 +70,8 @@ class DiscordService: if role != AuthRoleEnum.admin: auth_user = self._auth_users.find_auth_user_by_email(token["email"]) if auth_user is not None: - user_ids = auth_user.users.select(lambda x: x.server is not None and x.server.server_id) - filtered_result.result = filtered_result.result.where(lambda x: x.server_id in user_ids) + user_ids = auth_user.users.select(lambda x: x.server is not None and x.server.id) + filtered_result.result = filtered_result.result.where(lambda x: x.id in user_ids) servers: List = filtered_result.result.select(self._to_dto).where(lambda x: x.name != "") result = List(ServerDTO, servers) @@ -87,7 +85,7 @@ class DiscordService: async def get_server_by_id_async(self, id: int) -> ServerDTO: server = self._servers.get_server_by_id(id) - guild = self._bot.get_guild(server.discord_server_id) + guild = self._bot.get_guild(server.discord_id) server_dto = ServerTransformer.to_dto(server, guild.name, guild.member_count, guild.icon) return server_dto diff --git a/kdb-bot/src/bot_api/transformer/auth_user_transformer.py b/kdb-bot/src/bot_api/transformer/auth_user_transformer.py index 0e47ae35..09e6495c 100644 --- a/kdb-bot/src/bot_api/transformer/auth_user_transformer.py +++ b/kdb-bot/src/bot_api/transformer/auth_user_transformer.py @@ -1,9 +1,16 @@ from datetime import datetime +from cpl_core.dependency_injection import ServiceProviderABC +from cpl_discord.service import DiscordBotServiceABC +from cpl_query.extension import List + from bot_api.abc.transformer_abc import TransformerABC from bot_api.model.auth_user_dto import AuthUserDTO +from bot_api.model.user_dto import UserDTO from bot_data.model.auth_role_enum import AuthRoleEnum from bot_data.model.auth_user import AuthUser +from bot_data.model.user import User +from modules.permission.abc.permission_service_abc import PermissionServiceABC class AuthUserTransformer(TransformerABC): @@ -25,7 +32,28 @@ class AuthUserTransformer(TransformerABC): ) @staticmethod - def to_dto(db: AuthUser, password: str = None) -> AuthUserDTO: + @ServiceProviderABC.inject + def _is_technician(user: User, bot: DiscordBotServiceABC, permissions: PermissionServiceABC): + guild = bot.get_guild(user.server.discord_id) + member = guild.get_member(user.discord_id) + return permissions.is_member_technician(member) + + @staticmethod + @ServiceProviderABC.inject + def _is_admin(user: User, bot: DiscordBotServiceABC, permissions: PermissionServiceABC): + guild = bot.get_guild(user.server.discord_id) + member = guild.get_member(user.discord_id) + return permissions.is_member_technician(member) + + @staticmethod + @ServiceProviderABC.inject + def _is_moderator(user: User, bot: DiscordBotServiceABC, permissions: PermissionServiceABC): + guild = bot.get_guild(user.server.discord_id) + member = guild.get_member(user.discord_id) + return permissions.is_member_technician(member) + + @classmethod + def to_dto(cls, db: AuthUser, password: str = None) -> AuthUserDTO: return AuthUserDTO( db.id, db.first_name, @@ -34,6 +62,21 @@ class AuthUserTransformer(TransformerABC): "" if password is None else password, db.confirmation_id, db.auth_role, + List( + UserDTO, + db.users.select( + lambda u: UserDTO( + u.id, + u.discord_id, + u.xp, + u.minecraft_id, + u.server, + cls._is_technician(u), + cls._is_admin(u), + cls._is_moderator(u), + ) + ), + ), db.created_at, db.modified_at, ) diff --git a/kdb-bot/src/bot_api/transformer/server_transformer.py b/kdb-bot/src/bot_api/transformer/server_transformer.py index bc4c5eeb..bffba8e1 100644 --- a/kdb-bot/src/bot_api/transformer/server_transformer.py +++ b/kdb-bot/src/bot_api/transformer/server_transformer.py @@ -15,8 +15,8 @@ class ServerTransformer(TransformerABC): @staticmethod def to_dto(db: Server, name: str, member_count: int, icon_url: Optional[discord.Asset]) -> ServerDTO: return ServerDTO( - db.server_id, - db.discord_server_id, + db.id, + db.discord_id, name, member_count, icon_url.url if icon_url is not None else None, diff --git a/kdb-bot/src/bot_core/service/client_utils_service.py b/kdb-bot/src/bot_core/service/client_utils_service.py index 414b62e2..b0cd36b3 100644 --- a/kdb-bot/src/bot_core/service/client_utils_service.py +++ b/kdb-bot/src/bot_core/service/client_utils_service.py @@ -60,28 +60,28 @@ class ClientUtilsService(ClientUtilsABC): def received_command(self, guild_id: int): server = self._servers.get_server_by_discord_id(guild_id) - client = self._clients.find_client_by_discord_id_and_server_id(self._bot.user.id, server.server_id) + client = self._clients.find_client_by_discord_id_and_server_id(self._bot.user.id, server.id) client.received_command_count += 1 self._clients.update_client(client) self._db.save_changes() def moved_user(self, guild_id: int): server = self._servers.get_server_by_discord_id(guild_id) - client = self._clients.find_client_by_discord_id_and_server_id(self._bot.user.id, server.server_id) + client = self._clients.find_client_by_discord_id_and_server_id(self._bot.user.id, server.id) client.moved_users_count += 1 self._clients.update_client(client) self._db.save_changes() def moved_users(self, guild_id: int, count: int): server = self._servers.get_server_by_discord_id(guild_id) - client = self._clients.find_client_by_discord_id_and_server_id(self._bot.user.id, server.server_id) + client = self._clients.find_client_by_discord_id_and_server_id(self._bot.user.id, server.id) client.moved_users_count += count self._clients.update_client(client) self._db.save_changes() def get_client(self, dc_ic: int, guild_id: int): server = self._servers.get_server_by_discord_id(guild_id) - client = self._clients.find_client_by_discord_id_and_server_id(self._bot.user.id, server.server_id) + client = self._clients.find_client_by_discord_id_and_server_id(self._bot.user.id, server.id) return client async def check_if_bot_is_ready_yet(self) -> bool: @@ -138,7 +138,7 @@ class ClientUtilsService(ClientUtilsABC): ) -> bool: umcph = None try: - umcph = self._umcphs.find_user_message_count_per_hour_by_user_id_and_date(user.user_id, created_at) + umcph = self._umcphs.find_user_message_count_per_hour_by_user_id_and_date(user.id, created_at) if umcph is None: self._umcphs.add_user_message_count_per_hour( UserMessageCountPerHour( @@ -151,7 +151,7 @@ class ClientUtilsService(ClientUtilsABC): self._db.save_changes() - umcph = self._umcphs.get_user_message_count_per_hour_by_user_id_and_date(user.user_id, created_at) + umcph = self._umcphs.get_user_message_count_per_hour_by_user_id_and_date(user.id, created_at) except Exception as e: self._logger.error( __name__, @@ -183,7 +183,7 @@ class ClientUtilsService(ClientUtilsABC): def get_ontime_for_user(self, user: User) -> float: return round( - self._user_joined_voice_channel.get_user_joined_voice_channels_by_user_id(user.user_id) + self._user_joined_voice_channel.get_user_joined_voice_channels_by_user_id(user.id) .where(lambda x: x.leaved_on is not None and x.joined_on is not None) .sum(lambda join: (join.leaved_on - join.joined_on).total_seconds() / 3600), 2, diff --git a/kdb-bot/src/bot_data/model/api_key.py b/kdb-bot/src/bot_data/model/api_key.py index d27037cb..47e2209e 100644 --- a/kdb-bot/src/bot_data/model/api_key.py +++ b/kdb-bot/src/bot_data/model/api_key.py @@ -73,7 +73,7 @@ class ApiKey(TableABC): ) VALUES ( '{self._identifier}', '{self._key}', - {"NULL" if self._creator is None else self._creator.user_id}, + {"NULL" if self._creator is None else self._creator.id}, '{self._created_at}', '{self._modified_at}' ); diff --git a/kdb-bot/src/bot_data/model/auth_user.py b/kdb-bot/src/bot_data/model/auth_user.py index f3a46707..b9675f30 100644 --- a/kdb-bot/src/bot_data/model/auth_user.py +++ b/kdb-bot/src/bot_data/model/auth_user.py @@ -42,6 +42,8 @@ class AuthUser(TableABC): if users is None: self._users = List(User) + else: + self._users = users self._auth_role_id = auth_role @@ -250,10 +252,10 @@ class AuthUser(TableABC): `EMail` = '{self._email}', `Password` = '{self._password}', `PasswordSalt` = '{self._password_salt}', - `RefreshToken` = '{"NULL" if self._refresh_token is None else self._refresh_token}', - `ConfirmationId` = '{"NULL" if self._confirmation_id is None else self._confirmation_id}', - `ForgotPasswordId` = '{"NULL" if self._forgot_password_id is None else self._forgot_password_id}', - `OAuthId` = '{"NULL" if self._oauth_id is None else self._oauth_id}', + `RefreshToken` = '{'null' if self._refresh_token is None else f'{self._refresh_token}'}', + `ConfirmationId` = '{'null' if self._confirmation_id is None else f'{self._confirmation_id}'}', + `ForgotPasswordId` = '{'null' if self._forgot_password_id is None else f'{self._forgot_password_id}'}', + `OAuthId` = '{'null' if self._oauth_id is None else f'{self._oauth_id}'}', `RefreshTokenExpiryTime` = '{self._refresh_token_expire_time.isoformat()}', `AuthRole` = {self._auth_role_id.value}, `LastModifiedAt` = '{self._modified_at}' diff --git a/kdb-bot/src/bot_data/model/auth_user_users_relation.py b/kdb-bot/src/bot_data/model/auth_user_users_relation.py index 1ef7e35d..6d5f7f30 100644 --- a/kdb-bot/src/bot_data/model/auth_user_users_relation.py +++ b/kdb-bot/src/bot_data/model/auth_user_users_relation.py @@ -71,7 +71,7 @@ class AuthUserUsersRelation(TableABC): `AuthUserId`, `UserId`, `CreatedAt`, `LastModifiedAt` ) VALUES ( {self._auth_user.id}, - {self._user.user_id}, + {self._user.id}, '{self._created_at}', '{self._modified_at}' ); @@ -84,10 +84,10 @@ class AuthUserUsersRelation(TableABC): f""" UPDATE `AuthUserUsersRelations` SET `AuthUserId` = '{self._auth_user.id}',, - `UserId` = '{self._user.user_id}' + `UserId` = '{self._user.id}' `LastModifiedAt` = '{self._modified_at}' WHERE `AuthUserId` = {self._auth_user.id} - AND `UserId` = {self._user.user_id}; + AND `UserId` = {self._user.id}; """ ) @@ -97,6 +97,6 @@ class AuthUserUsersRelation(TableABC): f""" DELETE FROM `AuthUserUsersRelations` WHERE `AuthUserId` = {self._auth_user.id} - AND `UserId` = {self._user.user_id}; + AND `UserId` = {self._user.id}; """ ) diff --git a/kdb-bot/src/bot_data/model/auto_role.py b/kdb-bot/src/bot_data/model/auto_role.py index 16287e6e..28ad489d 100644 --- a/kdb-bot/src/bot_data/model/auto_role.py +++ b/kdb-bot/src/bot_data/model/auto_role.py @@ -2,6 +2,8 @@ from datetime import datetime from typing import Optional from cpl_core.database import TableABC +from cpl_core.dependency_injection import ServiceProviderABC +from cpl_discord.service import DiscordBotServiceABC from bot_data.model.server import Server @@ -10,7 +12,7 @@ class AutoRole(TableABC): def __init__( self, server: Optional[Server], - dc_channel_id: int, + channel_id: int, dc_message_id: int, created_at: datetime = None, modified_at: datetime = None, @@ -18,7 +20,7 @@ class AutoRole(TableABC): ): self._auto_role_id = id self._server = server - self._discord_channel_id = dc_channel_id + self._discord_channel_id = channel_id self._discord_message_id = dc_message_id TableABC.__init__(self) @@ -26,7 +28,7 @@ class AutoRole(TableABC): self._modified_at = modified_at if modified_at is not None else self._modified_at @property - def auto_role_id(self) -> int: + def id(self) -> int: return self._auto_role_id @property @@ -41,6 +43,12 @@ class AutoRole(TableABC): def discord_channel_id(self, value: int): self._discord_channel_id = value + @property + @ServiceProviderABC.inject + def discord_channel_name(self, bot: DiscordBotServiceABC) -> str: + channel = bot.get_channel(self.discord_channel_id) + return None if channel is None else channel.name + @property def discord_message_id(self) -> int: return self._discord_message_id @@ -91,7 +99,7 @@ class AutoRole(TableABC): INSERT INTO `AutoRoles` ( `ServerId`, `DiscordChannelId`, `DiscordMessageId`, `CreatedAt`, `LastModifiedAt` ) VALUES ( - {self._server.server_id}, + {self._server.id}, {self._discord_channel_id}, {self._discord_message_id}, '{self._created_at}', @@ -105,7 +113,7 @@ class AutoRole(TableABC): return str( f""" UPDATE `AutoRoles` - SET `ServerId` = {self._server.server_id}, + SET `ServerId` = {self._server.id}, `DiscordChannelId` = {self._discord_channel_id}, `DiscordMessageId` = {self._discord_message_id}, `LastModifiedAt` = '{self._modified_at}' diff --git a/kdb-bot/src/bot_data/model/auto_role_rule.py b/kdb-bot/src/bot_data/model/auto_role_rule.py index f7166637..3630f134 100644 --- a/kdb-bot/src/bot_data/model/auto_role_rule.py +++ b/kdb-bot/src/bot_data/model/auto_role_rule.py @@ -1,6 +1,8 @@ from datetime import datetime from cpl_core.database import TableABC +from cpl_core.dependency_injection import ServiceProviderABC +from cpl_discord.service import DiscordBotServiceABC from bot_data.model.auto_role import AutoRole @@ -25,7 +27,7 @@ class AutoRoleRule(TableABC): self._modified_at = modified_at if modified_at is not None else self._modified_at @property - def auto_role_rule_id(self) -> int: + def id(self) -> int: return self._auto_role_rule_id @property @@ -44,6 +46,12 @@ class AutoRoleRule(TableABC): def role_id(self) -> int: return self._discord_role_id + @property + @ServiceProviderABC.inject + def role_name(self, bot: DiscordBotServiceABC) -> str: + guild = bot.get_guild(self.auto_role.server.discord_id) + return guild.get_role(self.role_id).name + @role_id.setter def role_id(self, value: int): self._discord_role_id = value diff --git a/kdb-bot/src/bot_data/model/client.py b/kdb-bot/src/bot_data/model/client.py index db98caaf..79f5c0fe 100644 --- a/kdb-bot/src/bot_data/model/client.py +++ b/kdb-bot/src/bot_data/model/client.py @@ -1,5 +1,8 @@ from datetime import datetime + from cpl_core.database import TableABC +from cpl_core.dependency_injection import ServiceProviderABC +from cpl_discord.service import DiscordBotServiceABC from bot_data.model.server import Server @@ -32,13 +35,18 @@ class Client(TableABC): self._modified_at = modified_at if modified_at is not None else self._modified_at @property - def client_id(self) -> int: + def id(self) -> int: return self._client_id @property def discord_id(self) -> int: return self._discord_client_id + @property + @ServiceProviderABC.inject + def name(self, bot: DiscordBotServiceABC) -> str: + return bot.user.name + @property def sent_message_count(self) -> int: return self._sent_message_count @@ -154,7 +162,7 @@ class Client(TableABC): {self._deleted_message_count}, {self._received_message_count}, {self._moved_users_count}, - {self._server.server_id}, + {self._server.id}, '{self._created_at}', '{self._modified_at}' ); diff --git a/kdb-bot/src/bot_data/model/known_user.py b/kdb-bot/src/bot_data/model/known_user.py index 3c708f9b..b17a13ce 100644 --- a/kdb-bot/src/bot_data/model/known_user.py +++ b/kdb-bot/src/bot_data/model/known_user.py @@ -19,7 +19,7 @@ class KnownUser(TableABC): self._modified_at = modified_at if modified_at is not None else self._modified_at @property - def known_user_id(self) -> int: + def id(self) -> int: return self._known_user_id @property diff --git a/kdb-bot/src/bot_data/model/level.py b/kdb-bot/src/bot_data/model/level.py index fbea3634..b47f6fd4 100644 --- a/kdb-bot/src/bot_data/model/level.py +++ b/kdb-bot/src/bot_data/model/level.py @@ -1,5 +1,6 @@ from datetime import datetime from typing import Optional + from cpl_core.database import TableABC from bot_data.model.server import Server @@ -114,7 +115,7 @@ class Level(TableABC): '{self._color}', {self._min_xp}, {self._permissions}, - {self._server.server_id}, + {self._server.id}, '{self._created_at}', '{self._modified_at}' ); diff --git a/kdb-bot/src/bot_data/model/server.py b/kdb-bot/src/bot_data/model/server.py index 4f22ec1c..e2412295 100644 --- a/kdb-bot/src/bot_data/model/server.py +++ b/kdb-bot/src/bot_data/model/server.py @@ -1,7 +1,8 @@ from datetime import datetime -from typing import Optional from cpl_core.database import TableABC +from cpl_core.dependency_injection import ServiceProviderABC +from cpl_discord.service import DiscordBotServiceABC class Server(TableABC): @@ -20,13 +21,25 @@ class Server(TableABC): self._modified_at = modified_at if modified_at is not None else self._modified_at @property - def server_id(self) -> int: + def id(self) -> int: return self._server_id @property - def discord_server_id(self) -> int: + def discord_id(self) -> int: return self._discord_server_id + @property + @ServiceProviderABC.inject + def name(self, bot: DiscordBotServiceABC) -> str: + guild = bot.get_guild(self.discord_id) + return None if guild is None else guild.name + + @property + @ServiceProviderABC.inject + def icon_url(self, bot: DiscordBotServiceABC) -> str: + guild = bot.get_guild(self.discord_id) + return None if guild is None else guild.icon.url + @staticmethod def get_select_all_string() -> str: return str( diff --git a/kdb-bot/src/bot_data/model/statistic.py b/kdb-bot/src/bot_data/model/statistic.py index 0b4476a2..d22f8481 100644 --- a/kdb-bot/src/bot_data/model/statistic.py +++ b/kdb-bot/src/bot_data/model/statistic.py @@ -101,7 +101,7 @@ class Statistic(TableABC): '{self._name}', '{self._description}', '{self._code}', - {self._server.server_id}, + {self._server.id}, '{self._created_at}', '{self._modified_at}' ); diff --git a/kdb-bot/src/bot_data/model/user.py b/kdb-bot/src/bot_data/model/user.py index a2f4de81..a9e8d437 100644 --- a/kdb-bot/src/bot_data/model/user.py +++ b/kdb-bot/src/bot_data/model/user.py @@ -2,7 +2,10 @@ from datetime import datetime from typing import Optional from cpl_core.database import TableABC +from cpl_core.dependency_injection import ServiceProviderABC +from cpl_discord.service import DiscordBotServiceABC +from bot_data.model.level import Level from bot_data.model.server import Server @@ -28,13 +31,27 @@ class User(TableABC): self._modified_at = modified_at if modified_at is not None else self._modified_at @property - def user_id(self) -> int: + def id(self) -> int: return self._user_id @property def discord_id(self) -> int: return self._discord_id + @property + @ServiceProviderABC.inject + def name(self, bot: DiscordBotServiceABC) -> str: + guild = bot.get_guild(self.server.discord_id) + user = guild.get_member(self.discord_id) + return None if user is None else user.name + + @property + @ServiceProviderABC.inject + def icon_url(self, bot: DiscordBotServiceABC) -> str: + guild = bot.get_guild(self.server.discord_id) + user = guild.get_member(self.discord_id) + return None if user is None else user.display_icon + @property def xp(self) -> int: return self._xp @@ -44,6 +61,22 @@ class User(TableABC): self._modified_at = datetime.now().isoformat() self._xp = value + @property + @ServiceProviderABC.inject + def ontime(self, services: ServiceProviderABC) -> float: + from bot_core.abc.client_utils_abc import ClientUtilsABC + + client_utils: ClientUtilsABC = services.get_service(ClientUtilsABC) + return client_utils.get_ontime_for_user(self) + + @property + @ServiceProviderABC.inject + def level(self, services: ServiceProviderABC) -> Level: + from modules.level.service.level_service import LevelService + + levels: LevelService = services.get_service(LevelService) + return levels.get_level(self) + @property def minecraft_id(self) -> Optional[str]: return self._minecraft_id @@ -56,6 +89,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( @@ -110,8 +154,8 @@ class User(TableABC): ) VALUES ( {self._discord_id}, {self._xp}, - '{"NULL" if self._minecraft_id is None else self._minecraft_id}', - {self._server.server_id}, + '{self._minecraft_id}', + {self._server.id}, '{self._created_at}', '{self._modified_at}' ); @@ -124,7 +168,7 @@ class User(TableABC): f""" UPDATE `Users` SET `XP` = {self._xp}, - `MinecraftId` = '{"NULL" if self._minecraft_id is None else self._minecraft_id}', + `MinecraftId` = {'null' if self.minecraft_id is None else f'{self._minecraft_id}'}, `LastModifiedAt` = '{self._modified_at}' WHERE `UserId` = {self._user_id}; """ diff --git a/kdb-bot/src/bot_data/model/user_joined_game_server.py b/kdb-bot/src/bot_data/model/user_joined_game_server.py index d13beed0..964a19d0 100644 --- a/kdb-bot/src/bot_data/model/user_joined_game_server.py +++ b/kdb-bot/src/bot_data/model/user_joined_game_server.py @@ -38,6 +38,10 @@ class UserJoinedGameServer(TableABC): def game_server(self) -> str: return self._game_server + @property + def time(self) -> float: + return round((self.leaved_on - self.joined_on).total_seconds() / 3600, 2) + @property def joined_on(self) -> datetime: return self._joined_on @@ -100,7 +104,7 @@ class UserJoinedGameServer(TableABC): INSERT INTO `UserJoinedGameServer` ( `UserId`, `GameServer`, `JoinedOn`, `LeavedOn`, `CreatedAt`, `LastModifiedAt` ) VALUES ( - {self._user.user_id}, + {self._user.id}, '{self._game_server}', '{self._joined_on}', '{self._leaved_on}', @@ -115,7 +119,7 @@ class UserJoinedGameServer(TableABC): INSERT INTO `UserJoinedGameServer` ( `UserId`, `GameServer`, `JoinedOn`, `CreatedAt`, `LastModifiedAt` ) VALUES ( - {self._user.user_id}, + {self._user.id}, '{self._game_server}', '{self._joined_on}', '{self._created_at}', diff --git a/kdb-bot/src/bot_data/model/user_joined_server.py b/kdb-bot/src/bot_data/model/user_joined_server.py index 134e2f47..ce007355 100644 --- a/kdb-bot/src/bot_data/model/user_joined_server.py +++ b/kdb-bot/src/bot_data/model/user_joined_server.py @@ -25,7 +25,7 @@ class UserJoinedServer(TableABC): self._modified_at = modified_at if modified_at is not None else self._modified_at @property - def join_id(self) -> int: + def id(self) -> int: return self._join_id @property @@ -103,7 +103,7 @@ class UserJoinedServer(TableABC): INSERT INTO `UserJoinedServers` ( `UserId`, `JoinedOn`, `LeavedOn`, `CreatedAt`, `LastModifiedAt` ) VALUES ( - {self._user.user_id}, + {self._user.id}, '{self._joined_on}', '{self._leaved_on}', '{self._created_at}', @@ -117,7 +117,7 @@ class UserJoinedServer(TableABC): INSERT INTO `UserJoinedServers` ( `UserId`, `JoinedOn`, `CreatedAt`, `LastModifiedAt` ) VALUES ( - {self._user.user_id}, + {self._user.id}, '{self._joined_on}', '{self._created_at}', '{self._modified_at}' @@ -132,7 +132,7 @@ class UserJoinedServer(TableABC): UPDATE `UserJoinedServers` SET `LeavedOn` = '{self._leaved_on}', `LastModifiedAt` = '{self._modified_at}' - WHERE `UserId` = {self._user.user_id}; + WHERE `UserId` = {self._user.id}; """ ) diff --git a/kdb-bot/src/bot_data/model/user_joined_voice_channel.py b/kdb-bot/src/bot_data/model/user_joined_voice_channel.py index 59e46466..457c9fc1 100644 --- a/kdb-bot/src/bot_data/model/user_joined_voice_channel.py +++ b/kdb-bot/src/bot_data/model/user_joined_voice_channel.py @@ -1,6 +1,8 @@ from datetime import datetime from cpl_core.database import TableABC +from cpl_core.dependency_injection import ServiceProviderABC +from cpl_discord.service import DiscordBotServiceABC from bot_data.model.user import User @@ -9,7 +11,7 @@ class UserJoinedVoiceChannel(TableABC): def __init__( self, user: User, - dc_channel_id: int, + channel_id: int, joined_on: datetime, leaved_on: datetime = None, created_at: datetime = None, @@ -17,7 +19,7 @@ class UserJoinedVoiceChannel(TableABC): id=0, ): self._join_id = id - self._dc_channel_id = dc_channel_id + self._channel_id = channel_id self._user = user self._joined_on = joined_on self._leaved_on = leaved_on @@ -27,17 +29,26 @@ class UserJoinedVoiceChannel(TableABC): self._modified_at = modified_at if modified_at is not None else self._modified_at @property - def join_id(self) -> int: + def id(self) -> int: return self._join_id @property - def dc_channel_id(self) -> int: - return self._dc_channel_id + def channel_id(self) -> int: + return self._channel_id + + @property + @ServiceProviderABC.inject + def channel_name(self, bot: DiscordBotServiceABC) -> str: + return bot.get_channel(self.channel_id).name @property def user(self) -> User: return self._user + @property + def time(self) -> float: + return round((self.leaved_on - self.joined_on).total_seconds() / 3600, 2) + @property def joined_on(self) -> datetime: return self._joined_on @@ -100,8 +111,8 @@ class UserJoinedVoiceChannel(TableABC): INSERT INTO `UserJoinedVoiceChannel` ( `UserId`, `DiscordChannelId`, `JoinedOn`, `LeavedOn`, `CreatedAt`, `LastModifiedAt` ) VALUES ( - {self._user.user_id}, - {self._dc_channel_id}, + {self._user.id}, + {self._channel_id}, '{self._joined_on}', '{self._leaved_on}', '{self._created_at}', @@ -115,8 +126,8 @@ class UserJoinedVoiceChannel(TableABC): INSERT INTO `UserJoinedVoiceChannel` ( `UserId`, `DiscordChannelId`, `JoinedOn`, `CreatedAt`, `LastModifiedAt` ) VALUES ( - {self._user.user_id}, - {self._dc_channel_id}, + {self._user.id}, + {self._channel_id}, '{self._joined_on}', '{self._created_at}', '{self._modified_at}' diff --git a/kdb-bot/src/bot_data/model/user_message_count_per_hour.py b/kdb-bot/src/bot_data/model/user_message_count_per_hour.py index 6fdb7b9b..f7a83663 100644 --- a/kdb-bot/src/bot_data/model/user_message_count_per_hour.py +++ b/kdb-bot/src/bot_data/model/user_message_count_per_hour.py @@ -97,7 +97,7 @@ class UserMessageCountPerHour(TableABC): INSERT INTO `UserMessageCountPerHour` ( `UserId`, `Date`, `Hour`, `XPCount`, `CreatedAt`, `LastModifiedAt` ) VALUES ( - {self._user.user_id}, + {self._user.id}, '{self._date}', {self._hour}, {self._xp_count}, diff --git a/kdb-bot/src/bot_data/service/auth_user_repository_service.py b/kdb-bot/src/bot_data/service/auth_user_repository_service.py index 295e3c2f..397c31f8 100644 --- a/kdb-bot/src/bot_data/service/auth_user_repository_service.py +++ b/kdb-bot/src/bot_data/service/auth_user_repository_service.py @@ -28,7 +28,7 @@ class AuthUserRepositoryService(AuthUserRepositoryABC): @staticmethod def _get_value_from_result(value: any) -> Optional[any]: - if isinstance(value, str) and "NULL" in value: + if isinstance(value, str) and "null" in value: return None return value diff --git a/kdb-bot/src/bot_data/service/client_repository_service.py b/kdb-bot/src/bot_data/service/client_repository_service.py index 51d3b6cf..587569a0 100644 --- a/kdb-bot/src/bot_data/service/client_repository_service.py +++ b/kdb-bot/src/bot_data/service/client_repository_service.py @@ -193,9 +193,9 @@ class ClientRepositoryService(ClientRepositoryABC): self._logger.warn(__name__, f"Cannot find server by id {server_id}") raise Exception("Value not found") - client = self.find_client_by_discord_id_and_server_id(id, server.server_id) + client = self.find_client_by_discord_id_and_server_id(id, server.id) if client is None: - self._logger.warn(__name__, f"Cannot find client by ids {id}@{server.server_id}") + self._logger.warn(__name__, f"Cannot find client by ids {id}@{server.id}") raise Exception("Value not found") return client diff --git a/kdb-bot/src/bot_graphql/abc/query_abc.py b/kdb-bot/src/bot_graphql/abc/query_abc.py index b9e9f444..22a4213b 100644 --- a/kdb-bot/src/bot_graphql/abc/query_abc.py +++ b/kdb-bot/src/bot_graphql/abc/query_abc.py @@ -75,9 +75,9 @@ class QueryABC(ObjectType): element: AutoRole = element for u in user.users: u: User = u - guild = bot.get_guild(u.server.discord_server_id) + guild = bot.get_guild(u.server.discord_id) member = guild.get_member(u.discord_id) - if permissions.is_member_moderator(member) and u.server.server_id == element.server.server_id: + if permissions.is_member_moderator(member) and u.server.id == element.server.id: access = True break @@ -85,23 +85,23 @@ class QueryABC(ObjectType): element: AutoRole = element.auto_role for u in user.users: u: User = u - guild = bot.get_guild(u.server.discord_server_id) + guild = bot.get_guild(u.server.discord_id) member = guild.get_member(u.discord_id) - if permissions.is_member_moderator(member) and u.server.server_id == element.server.server_id: + if permissions.is_member_moderator(member) and u.server.id == element.server.id: access = True break elif type(element) == Client: for u in user.users: u: User = u - if u.server.server_id == element.server.server_id: + if u.server.id == element.server.id: access = True break elif type(element) == KnownUser: for u in user.users: u: User = u - guild = bot.get_guild(u.server.discord_server_id) + guild = bot.get_guild(u.server.discord_id) member = guild.get_member(u.discord_id) if permissions.is_member_moderator(member): access = True @@ -110,42 +110,42 @@ class QueryABC(ObjectType): elif type(element) == Level: for u in user.users: u: User = u - if u.server.server_id == element.server.server_id: + if u.server.id == element.server.id: access = True break elif type(element) == Server: for u in user.users: u: User = u - if u.server.server_id == element.server_id: + if u.server.id == element.id: access = True break elif type(element) == User: for u in user.users: u: User = u - if u.user_id == element.user_id: + if u.id == element.id: access = True break elif type(element) == UserJoinedServer: for u in user.users: u: User = u - if u.user_id == element.user.user_id: + if u.id == element.user.id: access = True break elif type(element) == UserJoinedVoiceChannel: for u in user.users: u: User = u - if u.user_id == element.user.user_id: + if u.id == element.user.id: access = True break elif type(element) == UserJoinedGameServer: for u in user.users: u: User = u - if u.user_id == element.user.user_id: + if u.id == element.user.id: access = True break @@ -160,8 +160,8 @@ class QueryABC(ObjectType): if auth_user == "system" or auth_user.auth_role == AuthRoleEnum.admin: return - member = bot.get_guild(server.discord_server_id).get_member( - auth_user.users.where(lambda x: x.server.server_id == server.server_id).single().discord_id + member = bot.get_guild(server.discord_id).get_member( + auth_user.users.where(lambda x: x.server.id == server.id).single().discord_id ) check_perm = lambda x: True @@ -180,12 +180,12 @@ class QueryABC(ObjectType): # @FilterABC.resolve_filter_annotation def _resolve_collection(self, collection: List, *_, filter: FilterABC = None, page: Page = None, sort: Sort = None): if filter is not None: - return filter.filter(collection) + collection = filter.filter(collection) if page is not None: - return page.filter(collection) + collection = page.filter(collection) if sort is not None: - return sort.filter(collection) + collection = sort.filter(collection) return collection diff --git a/kdb-bot/src/bot_graphql/filter/auto_role_filter.py b/kdb-bot/src/bot_graphql/filter/auto_role_filter.py index ca02a7d4..20d9d886 100644 --- a/kdb-bot/src/bot_graphql/filter/auto_role_filter.py +++ b/kdb-bot/src/bot_graphql/filter/auto_role_filter.py @@ -42,7 +42,7 @@ class AutoRoleFilter(FilterABC): def filter(self, query: List[AutoRole]) -> List[AutoRole]: if self._id is not None: - query = query.where(lambda x: x.auto_role_id == self._id) + query = query.where(lambda x: x.id == self._id) if self._channel_id is not None: query = query.where(lambda x: x.discord_channel_id == self._channel_id) @@ -57,7 +57,7 @@ class AutoRoleFilter(FilterABC): query = query.where(lambda x: x.discord_message_id == self._message_id) if self._server is not None: - servers = self._server.filter(query.select(lambda x: x.server)).select(lambda x: x.server_id) - query = query.where(lambda x: x.server.server_id in servers) + servers = self._server.filter(query.select(lambda x: x.server)).select(lambda x: x.id) + query = query.where(lambda x: x.server.id in servers) return query diff --git a/kdb-bot/src/bot_graphql/filter/auto_role_rule_filter.py b/kdb-bot/src/bot_graphql/filter/auto_role_rule_filter.py index 44651957..01a90c66 100644 --- a/kdb-bot/src/bot_graphql/filter/auto_role_rule_filter.py +++ b/kdb-bot/src/bot_graphql/filter/auto_role_rule_filter.py @@ -39,7 +39,7 @@ class AutoRoleRuleFilter(FilterABC): def filter(self, query: List[AutoRoleRule]) -> List[AutoRoleRule]: if self._id is not None: - query = query.where(lambda x: x.auto_role_rule_id == self._id) + query = query.where(lambda x: x.id == self._id) if self._emoji_name is not None: query = query.where(lambda x: x.emoji_name == self._emoji_name) @@ -50,14 +50,14 @@ class AutoRoleRuleFilter(FilterABC): if self._role_name is not None and self._role_id is not None: def get_role_name(x: AutoRoleRule): - guild = self._bot.get_guild(x.auto_role.server.discord_server_id) + guild = self._bot.get_guild(x.auto_role.server.discord_id) name = guild.get_role(x.role_id).name return name == self._role_name or self._role_name in name query = query.where(get_role_name) if self._auto_role is not None: - auto_roles = self._auto_role.filter(query.select(lambda x: x.auto_role)).select(lambda x: x.auto_role_id) - query = query.where(lambda x: x.auto_role.auto_role_id in auto_roles) + auto_roles = self._auto_role.filter(query.select(lambda x: x.auto_role)).select(lambda x: x.id) + query = query.where(lambda x: x.auto_role.id in auto_roles) return query diff --git a/kdb-bot/src/bot_graphql/filter/client_filter.py b/kdb-bot/src/bot_graphql/filter/client_filter.py index be81e742..29563600 100644 --- a/kdb-bot/src/bot_graphql/filter/client_filter.py +++ b/kdb-bot/src/bot_graphql/filter/client_filter.py @@ -32,16 +32,16 @@ class ClientFilter(FilterABC): def filter(self, query: List[Client]) -> List[Client]: if self._id is not None: - query = query.where(lambda x: x.client_id == self._id) + query = query.where(lambda x: x.id == self._id) if self._discord_id is not None: - query = query.where(lambda x: x.client_id == self._discord_id) + query = query.where(lambda x: x.id == self._discord_id) if self._name is not None: query = query.where(lambda x: self._name.lower() == x.name.lower() or self._name.lower() in x.name.lower()) if self._server is not None: - servers = self._server.filter(query.select(lambda x: x.server)).select(lambda x: x.server_id) - query = query.where(lambda x: x.server.server_id in servers) + servers = self._server.filter(query.select(lambda x: x.server)).select(lambda x: x.id) + query = query.where(lambda x: x.server.id in servers) return query diff --git a/kdb-bot/src/bot_graphql/filter/level_filter.py b/kdb-bot/src/bot_graphql/filter/level_filter.py index c34ae63f..2ded4ad8 100644 --- a/kdb-bot/src/bot_graphql/filter/level_filter.py +++ b/kdb-bot/src/bot_graphql/filter/level_filter.py @@ -25,7 +25,7 @@ class LevelFilter(FilterABC): if "server" in values: from bot_graphql.filter.server_filter import ServerFilter - self._server: ServerFilter = self._services.get_service(LevelFilter) + self._server: ServerFilter = self._services.get_service(ServerFilter) self._server.from_dict(values["server"]) def filter(self, query: List[Level]) -> List[Level]: @@ -36,7 +36,7 @@ class LevelFilter(FilterABC): query = query.where(lambda x: self._name.lower() == x.name.lower() or self._name.lower() in x.name.lower()) if self._server is not None: - servers = self._server.filter(query.select(lambda x: x.server)).select(lambda x: x.server_id) - query = query.where(lambda x: x.server.server_id in servers) + servers = self._server.filter(query.select(lambda x: x.server)).select(lambda x: x.id) + query = query.where(lambda x: x.server.id in servers) return query diff --git a/kdb-bot/src/bot_graphql/filter/server_filter.py b/kdb-bot/src/bot_graphql/filter/server_filter.py index 2964d1d7..e090323e 100644 --- a/kdb-bot/src/bot_graphql/filter/server_filter.py +++ b/kdb-bot/src/bot_graphql/filter/server_filter.py @@ -28,15 +28,17 @@ class ServerFilter(FilterABC): @ServiceProviderABC.inject def filter(self, query: List[Server], bot: DiscordBotServiceABC) -> List[Server]: if self._id is not None: - query = query.where(lambda x: x.server_id == self._id) + query = query.where(lambda x: x.id == self._id) if self._discord_id is not None: - query = query.where(lambda x: x.discord_server_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: def where_guild(x: Guild): - guild = bot.get_guild(x.discord_server_id) + guild = bot.get_guild(x.discord_id) return guild is not None and ( self._name.lower() == guild.name.lower() or self._name.lower() in guild.name.lower() ) diff --git a/kdb-bot/src/bot_graphql/filter/sort.py b/kdb-bot/src/bot_graphql/filter/sort.py index f1c966dd..5901987e 100644 --- a/kdb-bot/src/bot_graphql/filter/sort.py +++ b/kdb-bot/src/bot_graphql/filter/sort.py @@ -1,3 +1,6 @@ +import functools + +from cpl_core.utils import String from cpl_query.extension import List from bot_graphql.abc.filter_abc import FilterABC @@ -6,6 +9,7 @@ from bot_graphql.abc.filter_abc import FilterABC class Sort(FilterABC): def __init__(self): FilterABC.__init__(self) + self._sort_direction = None self._sort_column = None @@ -16,5 +20,27 @@ class Sort(FilterABC): if "sortColumn" in values: self._sort_column = values["sortColumn"] + @staticmethod + def _rgetattr(obj, attr, *args): + def _getattr(obj, attr): + return getattr(obj, attr, *args) + + return functools.reduce(_getattr, [obj] + attr.split(".")) + + def _by_column(self, x): + atr = self._rgetattr(x, String.convert_to_snake_case(self._sort_column), None) + if atr is None: + return "" + return atr + def filter(self, query: List, *args) -> List: + if self._sort_column is None: + return query + + match self._sort_direction.lower() if self._sort_direction is not None else "ASC": + case "asc": + query = query.order_by(self._by_column) + case "desc": + query = query.order_by_descending(self._by_column) + return query diff --git a/kdb-bot/src/bot_graphql/filter/user_filter.py b/kdb-bot/src/bot_graphql/filter/user_filter.py index d5122d87..c8198542 100644 --- a/kdb-bot/src/bot_graphql/filter/user_filter.py +++ b/kdb-bot/src/bot_graphql/filter/user_filter.py @@ -5,6 +5,7 @@ from cpl_discord.service import DiscordBotServiceABC from cpl_query.extension import List from bot_core.abc.client_utils_abc import ClientUtilsABC +from bot_data.abc.user_joined_server_repository_abc import UserJoinedServerRepositoryABC from bot_data.model.user import User from bot_graphql.abc.filter_abc import FilterABC from bot_graphql.filter.level_filter import LevelFilter @@ -18,6 +19,7 @@ class UserFilter(FilterABC): bot: DiscordBotServiceABC, client_utils: ClientUtilsABC, levels: LevelService, + user_joined_servers: UserJoinedServerRepositoryABC, ): FilterABC.__init__(self) @@ -25,6 +27,7 @@ class UserFilter(FilterABC): self._bot = bot self._client_utils = client_utils self._levels = levels + self._user_joined_servers = user_joined_servers self._id = None self._discord_id = None @@ -34,6 +37,7 @@ class UserFilter(FilterABC): self._ontime = None self._level: Optional[LevelFilter] = None self._server = None + self._left_server = None def from_dict(self, values: dict): if "id" in values: @@ -64,18 +68,26 @@ class UserFilter(FilterABC): self._server: ServerFilter = self._services.get_service(ServerFilter) self._server.from_dict(values["server"]) + if "leftServer" in values: + self._left_server = values["leftServer"] + def filter(self, query: List[User]) -> List[User]: if self._id is not None: - query = query.where(lambda x: x.user_id == self._id) + 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: - query = query.where( - lambda x: self._bot.get_user(x.discord_id).name == self._name - or self._name in self._bot.get_user(x.discord_id).name - ) + + def _get_member(user: User): + guild = self._bot.get_guild(user.server.discord_id) + member = guild.get_member(user.discord_id) + return member is not None and (member.name == self._name or self._name in member.name) + + query = query.where(_get_member) if self._xp is not None: query = query.where(lambda x: x.xp == self._xp) @@ -91,7 +103,15 @@ class UserFilter(FilterABC): query = query.where(lambda x: self._levels.get_level(x).id in levels) if self._server is not None: - servers = self._server.filter(query.select(lambda x: x.server)).select(lambda x: x.server_id) - query = query.where(lambda x: x.server.server_id in servers) + servers = self._server.filter(query.select(lambda x: x.server)).select(lambda x: x.id) + query = query.where(lambda x: x.server.id in servers) + + if self._left_server is not None: + + def _has_user_left_server(user: User): + active_join = self._user_joined_servers.find_active_user_joined_server_by_user_id(user.id) + return (active_join is None) == self._left_server + + query = query.where(_has_user_left_server) return query diff --git a/kdb-bot/src/bot_graphql/filter/user_joined_game_server_filter.py b/kdb-bot/src/bot_graphql/filter/user_joined_game_server_filter.py index 1cdb4d4e..1d266a70 100644 --- a/kdb-bot/src/bot_graphql/filter/user_joined_game_server_filter.py +++ b/kdb-bot/src/bot_graphql/filter/user_joined_game_server_filter.py @@ -42,7 +42,7 @@ class UserJoinedGameServerFilter(FilterABC): query = query.where(lambda x: x.game_server == self._game_server) if self._user is not None: - users = self._user.filter(query.select(lambda x: x.user)).select(lambda x: x.user_id) - query = query.where(lambda x: x.user.user_id in users) + users = self._user.filter(query.select(lambda x: x.user)).select(lambda x: x.id) + query = query.where(lambda x: x.user.id in users) return query diff --git a/kdb-bot/src/bot_graphql/filter/user_joined_server_filter.py b/kdb-bot/src/bot_graphql/filter/user_joined_server_filter.py index 30af37fa..3aac7e25 100644 --- a/kdb-bot/src/bot_graphql/filter/user_joined_server_filter.py +++ b/kdb-bot/src/bot_graphql/filter/user_joined_server_filter.py @@ -43,8 +43,8 @@ class UserJoinedServerFilter(FilterABC): 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.user_id) - query = query.where(lambda x: x.user.user_id in users) + users = self._user.filter(query.select(lambda x: x.user)).select(lambda x: x.id) + query = query.where(lambda x: x.user.id in users) if self._joined_on is not None: query = query.where(lambda x: x.joined_on == self._joined_on or self._joined_on in x.joined_on) diff --git a/kdb-bot/src/bot_graphql/filter/user_joined_voice_channel_filter.py b/kdb-bot/src/bot_graphql/filter/user_joined_voice_channel_filter.py index bdbddeab..51ba446a 100644 --- a/kdb-bot/src/bot_graphql/filter/user_joined_voice_channel_filter.py +++ b/kdb-bot/src/bot_graphql/filter/user_joined_voice_channel_filter.py @@ -51,19 +51,19 @@ class UserJoinedVoiceChannelFilter(FilterABC): query = query.where(lambda x: x.id == self._id) if self._channel_id is not None: - query = query.where(lambda x: x.dc_channel_id == self._channel_id) + query = query.where(lambda x: x.channel_id == self._channel_id) if self._channel_name is not None and self._channel_id is not None: def get_channel_name(x: UserJoinedVoiceChannel): - name = self._bot.get_channel(x.dc_channel_id).name + name = self._bot.get_channel(x.channel_id).name return name == self._channel_name or self._channel_name in name query = query.where(get_channel_name) if self._user is not None: - users = self._user.filter(query.select(lambda x: x.user)).select(lambda x: x.user_id) - query = query.where(lambda x: x.user.user_id in users) + users = self._user.filter(query.select(lambda x: x.user)).select(lambda x: x.id) + query = query.where(lambda x: x.user.id in users) if self._joined_on is not None: query = query.where(lambda x: x.joined_on == self._joined_on or self._joined_on in x.joined_on) diff --git a/kdb-bot/src/bot_graphql/model/base.gql b/kdb-bot/src/bot_graphql/model/base.gql index 1ae03045..dcb3b17d 100644 --- a/kdb-bot/src/bot_graphql/model/base.gql +++ b/kdb-bot/src/bot_graphql/model/base.gql @@ -9,6 +9,11 @@ input Page { } input Sort { - sortDirection: String + sortDirection: SortDirection sortColumn: String +} + +enum SortDirection { + ASC + DESC } \ No newline at end of file diff --git a/kdb-bot/src/bot_graphql/model/user.gql b/kdb-bot/src/bot_graphql/model/user.gql index 853b1ad4..ee8b27cb 100644 --- a/kdb-bot/src/bot_graphql/model/user.gql +++ b/kdb-bot/src/bot_graphql/model/user.gql @@ -17,6 +17,7 @@ type User implements TableQuery { userJoinedGameServers(filter: UserJoinedGameServerFilter, page: Page, sort: Sort): [UserJoinedGameServer] server: Server + leftServer: Boolean createdAt: String modifiedAt: String @@ -31,6 +32,7 @@ input UserFilter { ontime: Float level: LevelFilter server: ServerFilter + leftServer: Boolean } type UserMutation { @@ -40,4 +42,5 @@ type UserMutation { input UserInput { id: ID xp: Int + levelId: ID } \ No newline at end of file diff --git a/kdb-bot/src/bot_graphql/model/userJoinedGameServer.gql b/kdb-bot/src/bot_graphql/model/userJoinedGameServer.gql index 63d66daa..44aa523b 100644 --- a/kdb-bot/src/bot_graphql/model/userJoinedGameServer.gql +++ b/kdb-bot/src/bot_graphql/model/userJoinedGameServer.gql @@ -2,6 +2,7 @@ type UserJoinedGameServer implements TableQuery { id: ID gameServer: String user: User + time: Float joinedOn: String leavedOn: String diff --git a/kdb-bot/src/bot_graphql/model/userJoinedVoiceChannel.gql b/kdb-bot/src/bot_graphql/model/userJoinedVoiceChannel.gql index d49f8c9e..7fb983b5 100644 --- a/kdb-bot/src/bot_graphql/model/userJoinedVoiceChannel.gql +++ b/kdb-bot/src/bot_graphql/model/userJoinedVoiceChannel.gql @@ -3,6 +3,7 @@ type UserJoinedVoiceChannel implements TableQuery { channelId: String channelName: String user: User + time: Float joinedOn: String leavedOn: String diff --git a/kdb-bot/src/bot_graphql/mutations/auto_role_mutation.py b/kdb-bot/src/bot_graphql/mutations/auto_role_mutation.py index 9f6021c3..28bd9b2d 100644 --- a/kdb-bot/src/bot_graphql/mutations/auto_role_mutation.py +++ b/kdb-bot/src/bot_graphql/mutations/auto_role_mutation.py @@ -33,12 +33,12 @@ class AutoRoleMutation(QueryABC): def get_new(x: AutoRole): return ( - x.server.server_id == input["serverId"] + x.server.id == input["serverId"] and x.discord_channel_id == input["channelId"] and x.discord_message_id == input["messageId"] ) - return self._auto_roles.get_auto_roles_by_server_id(auto_role.server.server_id).where(get_new).last() + return self._auto_roles.get_auto_roles_by_server_id(auto_role.server.id).where(get_new).last() def resolve_update_auto_role(self, *_, input: dict): auto_role = self._auto_roles.get_auto_role_by_id(input["id"]) diff --git a/kdb-bot/src/bot_graphql/mutations/auto_role_rule_mutation.py b/kdb-bot/src/bot_graphql/mutations/auto_role_rule_mutation.py index a9211344..b6b6a943 100644 --- a/kdb-bot/src/bot_graphql/mutations/auto_role_rule_mutation.py +++ b/kdb-bot/src/bot_graphql/mutations/auto_role_rule_mutation.py @@ -35,16 +35,12 @@ class AutoRoleRuleMutation(QueryABC): def get_new(x: AutoRoleRule): return ( - x.auto_role.auto_role_id == input["autoRoleId"] + x.auto_role.id == input["autoRoleId"] and x.emoji_name == input["emojiName"] and x.role_id == input["roleId"] ) - return ( - self._auto_roles.get_auto_role_rules_by_auto_role_id(auto_role_rule.auto_role.auto_role_id) - .where(get_new) - .last() - ) + return self._auto_roles.get_auto_role_rules_by_auto_role_id(auto_role_rule.auto_role.id).where(get_new).last() def resolve_update_auto_role_rule(self, *_, input: dict): auto_role_rule = self._auto_roles.get_auto_role_rule_by_id(input["id"]) diff --git a/kdb-bot/src/bot_graphql/mutations/level_mutation.py b/kdb-bot/src/bot_graphql/mutations/level_mutation.py index c86d76ac..b981384a 100644 --- a/kdb-bot/src/bot_graphql/mutations/level_mutation.py +++ b/kdb-bot/src/bot_graphql/mutations/level_mutation.py @@ -46,7 +46,7 @@ class LevelMutation(QueryABC): and l.permissions == level.permissions ) - return self._levels.get_levels_by_server_id(level.server.server_id).where(get_new_level).last() + return self._levels.get_levels_by_server_id(level.server.id).where(get_new_level).last() def resolve_update_level(self, *_, input: dict): level = self._levels.get_level_by_id(input["id"]) diff --git a/kdb-bot/src/bot_graphql/mutations/user_joined_game_server_mutation.py b/kdb-bot/src/bot_graphql/mutations/user_joined_game_server_mutation.py index d36487a9..fa7cb3bf 100644 --- a/kdb-bot/src/bot_graphql/mutations/user_joined_game_server_mutation.py +++ b/kdb-bot/src/bot_graphql/mutations/user_joined_game_server_mutation.py @@ -45,11 +45,11 @@ class UserJoinedGameServerMutation(QueryABC): user = self._users.get_user_by_id(input["userId"]) self._can_user_mutate_data(user.server, UserRoleEnum.admin) - active = self._user_joined_game_servers.find_active_user_joined_game_server_by_user_id(user.user_id) + active = self._user_joined_game_servers.find_active_user_joined_game_server_by_user_id(user.id) if active is not None: self._logger.debug( __name__, - f"Skip UserJoinedGameServer for user {user.user_id}. User already plays on {active.game_server}.", + f"Skip UserJoinedGameServer for user {user.id}. User already plays on {active.game_server}.", ) return @@ -57,18 +57,18 @@ class UserJoinedGameServerMutation(QueryABC): self._user_joined_game_servers.add_user_joined_game_server(new) self._db.save_changes() - return self._user_joined_game_servers.get_active_user_joined_game_server_by_user_id(user.user_id) + return self._user_joined_game_servers.get_active_user_joined_game_server_by_user_id(user.id) def resolve_user_leaved(self, *_, input: dict): user = self._users.get_user_by_id(input["userId"]) self._can_user_mutate_data(user.server, UserRoleEnum.admin) - active = self._user_joined_game_servers.find_active_user_joined_game_server_by_user_id(user.user_id) + active = self._user_joined_game_servers.find_active_user_joined_game_server_by_user_id(user.id) if active is None: return None active.leaved_on = datetime.now() - settings: BaseServerSettings = self._base_helper.get_config(user.server.discord_server_id) + settings: BaseServerSettings = self._base_helper.get_config(user.server.discord_id) ontime = round((active.leaved_on - active.joined_on).total_seconds() / 3600, 2) old_xp = user.xp diff --git a/kdb-bot/src/bot_graphql/mutations/user_mutation.py b/kdb-bot/src/bot_graphql/mutations/user_mutation.py index 354441e4..6a852c2e 100644 --- a/kdb-bot/src/bot_graphql/mutations/user_mutation.py +++ b/kdb-bot/src/bot_graphql/mutations/user_mutation.py @@ -1,10 +1,12 @@ from cpl_core.database.context import DatabaseContextABC 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.model.user_role_enum import UserRoleEnum from bot_graphql.abc.query_abc import QueryABC +from modules.level.service.level_service import LevelService from modules.permission.service.permission_service import PermissionService @@ -16,6 +18,8 @@ class UserMutation(QueryABC): bot: DiscordBotServiceABC, db: DatabaseContextABC, permissions: PermissionService, + levels: LevelRepositoryABC, + level_service: LevelService, ): QueryABC.__init__(self, "UserMutation") @@ -24,6 +28,8 @@ class UserMutation(QueryABC): self._bot = bot self._db = db self._permissions = permissions + self._levels = levels + self._level_service = level_service self.set_field("updateUser", self.resolve_update_user) @@ -31,10 +37,15 @@ class UserMutation(QueryABC): user = self._users.get_user_by_id(input["id"]) self._can_user_mutate_data(user.server, UserRoleEnum.moderator) + if "levelId" in input: + level = self._levels.get_level_by_id(input["levelId"]) + user.xp = level.min_xp + user.xp = input["xp"] if "xp" in input else user.xp 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 diff --git a/kdb-bot/src/bot_graphql/queries/auto_role_query.py b/kdb-bot/src/bot_graphql/queries/auto_role_query.py index 0876d62f..26f8b390 100644 --- a/kdb-bot/src/bot_graphql/queries/auto_role_query.py +++ b/kdb-bot/src/bot_graphql/queries/auto_role_query.py @@ -28,21 +28,21 @@ class AutoRoleQuery(DataQueryABC): self.set_field("server", self.resolve_server) self.add_collection( "autoRoleRule", - lambda x, *_: self._auto_role_rules.get_auto_role_rules_by_auto_role_id(x.auto_role_id), + lambda x, *_: self._auto_role_rules.get_auto_role_rules_by_auto_role_id(x.id), AutoRoleFilter, ) @staticmethod def resolve_id(x: AutoRole, *_): - return x.auto_role_id + return x.id @staticmethod def resolve_channel_id(x: AutoRole, *_): return x.discord_channel_id - def resolve_channel_name(self, x: AutoRole, *_): - channel = self._bot.get_channel(x.discord_channel_id) - return None if channel is None else channel.name + @staticmethod + def resolve_channel_name(x: AutoRole, *_): + return x.discord_channel_name @staticmethod def resolve_message_id(x: AutoRole, *_): @@ -50,6 +50,6 @@ class AutoRoleQuery(DataQueryABC): def resolve_server(self, x: AutoRole, *_, filter: ServerFilter = None): if filter is not None: - return filter.filter(self._servers.get_server_by_id(x.server.server_id)) + return filter.filter(self._servers.get_server_by_id(x.server.id)) - return self._servers.get_server_by_id(x.server.server_id) + return self._servers.get_server_by_id(x.server.id) diff --git a/kdb-bot/src/bot_graphql/queries/auto_role_rule_query.py b/kdb-bot/src/bot_graphql/queries/auto_role_rule_query.py index 5103aec4..faa8df8f 100644 --- a/kdb-bot/src/bot_graphql/queries/auto_role_rule_query.py +++ b/kdb-bot/src/bot_graphql/queries/auto_role_rule_query.py @@ -24,7 +24,7 @@ class AutoRoleRuleQuery(DataQueryABC): @staticmethod def resolve_id(x: AutoRoleRule, *_): - return x.auto_role_rule_id + return x.id @staticmethod def resolve_emoji_name(x: AutoRoleRule, *_): @@ -34,9 +34,9 @@ class AutoRoleRuleQuery(DataQueryABC): def resolve_role_id(x: AutoRoleRule, *_): return x.role_id - def resolve_role_name(self, x: AutoRoleRule, *_): - guild = self._bot.get_guild(x.auto_role.server.discord_server_id) - return guild.get_role(x.role_id).name + @staticmethod + def resolve_role_name(x: AutoRoleRule, *_): + return x.role_name def resolve_auto_role(self, x: AutoRoleRule, *_): - return self._auto_roles.get_auto_role_by_id(x.auto_role.auto_role_id) + return self._auto_roles.get_auto_role_by_id(x.auto_role.id) diff --git a/kdb-bot/src/bot_graphql/queries/client_query.py b/kdb-bot/src/bot_graphql/queries/client_query.py index 824afa9b..fe2312b7 100644 --- a/kdb-bot/src/bot_graphql/queries/client_query.py +++ b/kdb-bot/src/bot_graphql/queries/client_query.py @@ -25,14 +25,15 @@ class ClientQuery(DataQueryABC): @staticmethod def resolve_id(client: Client, *_): - return client.client_id + return client.id @staticmethod def resolve_discord_id(client: Client, *_): return client.discord_id - def resolve_name(self, client: Client, *_): - return self._bot.user.name + @staticmethod + def resolve_name(client: Client, *_): + return client.name @staticmethod def resolve_sent_message_count(client: Client, *_): diff --git a/kdb-bot/src/bot_graphql/queries/known_user_query.py b/kdb-bot/src/bot_graphql/queries/known_user_query.py index 243a6745..8892e2c7 100644 --- a/kdb-bot/src/bot_graphql/queries/known_user_query.py +++ b/kdb-bot/src/bot_graphql/queries/known_user_query.py @@ -11,7 +11,7 @@ class KnownUserQuery(DataQueryABC): @staticmethod def resolve_id(x: KnownUser, *_): - return x.known_user_id + return x.id @staticmethod def resolve_discord_id(x: KnownUser, *_): diff --git a/kdb-bot/src/bot_graphql/queries/server_query.py b/kdb-bot/src/bot_graphql/queries/server_query.py index 32b86259..059a87fd 100644 --- a/kdb-bot/src/bot_graphql/queries/server_query.py +++ b/kdb-bot/src/bot_graphql/queries/server_query.py @@ -42,29 +42,27 @@ class ServerQuery(DataQueryABC): self.add_collection( "autoRole", - lambda server, *_: self._auto_roles.get_auto_roles_by_server_id(server.server_id), + lambda server, *_: self._auto_roles.get_auto_roles_by_server_id(server.id), AutoRoleFilter, ) self.add_collection( - "client", lambda server, *_: self._clients.get_clients_by_server_id(server.server_id), ClientFilter + "client", lambda server, *_: self._clients.get_clients_by_server_id(server.id), ClientFilter ) - self.add_collection( - "level", lambda server, *_: self._levels.get_levels_by_server_id(server.server_id), LevelFilter - ) - self.add_collection("user", lambda server, *_: self._users.get_users_by_server_id(server.server_id), UserFilter) + self.add_collection("level", lambda server, *_: self._levels.get_levels_by_server_id(server.id), LevelFilter) + self.add_collection("user", lambda server, *_: self._users.get_users_by_server_id(server.id), UserFilter) @staticmethod def resolve_id(server: Server, *_): - return server.server_id + return server.id @staticmethod def resolve_discord_id(server: Server, *_): - return server.discord_server_id + return server.discord_id - def resolve_name(self, server: Server, *_): - guild = self._bot.get_guild(server.discord_server_id) - return None if guild is None else guild.name + @staticmethod + def resolve_name(server: Server, *_): + return server.name - def resolve_icon_url(self, server: Server, *_): - guild = self._bot.get_guild(server.discord_server_id) - return None if guild is None else guild.icon.url + @staticmethod + def resolve_icon_url(server: Server, *_): + return server.icon_url diff --git a/kdb-bot/src/bot_graphql/queries/user_joined_game_server_query.py b/kdb-bot/src/bot_graphql/queries/user_joined_game_server_query.py index 877fa8b7..6e29ec7d 100644 --- a/kdb-bot/src/bot_graphql/queries/user_joined_game_server_query.py +++ b/kdb-bot/src/bot_graphql/queries/user_joined_game_server_query.py @@ -28,6 +28,10 @@ class UserJoinedGameServerQuery(DataQueryABC): def resolve_user(x: UserJoinedGameServer, *_): return x.user + @staticmethod + def resolve_time(x: UserJoinedGameServer, *_): + return x.time + @staticmethod def resolve_joined_on(x: UserJoinedGameServer, *_): return x.joined_on diff --git a/kdb-bot/src/bot_graphql/queries/user_joined_server_query.py b/kdb-bot/src/bot_graphql/queries/user_joined_server_query.py index db18781a..6036e115 100644 --- a/kdb-bot/src/bot_graphql/queries/user_joined_server_query.py +++ b/kdb-bot/src/bot_graphql/queries/user_joined_server_query.py @@ -13,7 +13,7 @@ class UserJoinedServerQuery(DataQueryABC): @staticmethod def resolve_id(x: UserJoinedServer, *_): - return x.join_id + return x.id @staticmethod def resolve_user(x: UserJoinedServer, *_): diff --git a/kdb-bot/src/bot_graphql/queries/user_joined_voice_channel_query.py b/kdb-bot/src/bot_graphql/queries/user_joined_voice_channel_query.py index 99bcc0c3..2640307d 100644 --- a/kdb-bot/src/bot_graphql/queries/user_joined_voice_channel_query.py +++ b/kdb-bot/src/bot_graphql/queries/user_joined_voice_channel_query.py @@ -14,24 +14,30 @@ class UserJoinedVoiceChannelQuery(DataQueryABC): self.set_field("channelId", self.resolve_channel_id) self.set_field("channelName", self.resolve_channel_name) self.set_field("user", self.resolve_user) + self.set_field("time", self.resolve_time) self.set_field("joinedOn", self.resolve_joined_on) self.set_field("leavedOn", self.resolve_leaved_on) @staticmethod def resolve_id(x: UserJoinedVoiceChannel, *_): - return x.join_id + return x.id @staticmethod def resolve_channel_id(x: UserJoinedVoiceChannel, *_): - return x.dc_channel_id + return x.channel_id - def resolve_channel_name(self, x: UserJoinedVoiceChannel, *_): - return self._bot.get_channel(x.dc_channel_id).name + @staticmethod + def resolve_channel_name(x: UserJoinedVoiceChannel, *_): + return x.channel_name @staticmethod def resolve_user(x: UserJoinedVoiceChannel, *_): return x.user + @staticmethod + def resolve_time(x: UserJoinedVoiceChannel, *_): + return x.time + @staticmethod def resolve_joined_on(x: UserJoinedVoiceChannel, *_): return x.joined_on diff --git a/kdb-bot/src/bot_graphql/queries/user_query.py b/kdb-bot/src/bot_graphql/queries/user_query.py index ddcda7b9..857d668d 100644 --- a/kdb-bot/src/bot_graphql/queries/user_query.py +++ b/kdb-bot/src/bot_graphql/queries/user_query.py @@ -10,6 +10,7 @@ from bot_graphql.filter.user_joined_game_server_filter import UserJoinedGameServ from bot_graphql.filter.user_joined_server_filter import UserJoinedServerFilter from bot_graphql.filter.user_joined_voice_channel_filter import UserJoinedVoiceChannelFilter from modules.level.service.level_service import LevelService +from modules.permission.abc.permission_service_abc import PermissionServiceABC class UserQuery(DataQueryABC): @@ -21,6 +22,7 @@ class UserQuery(DataQueryABC): ujs: UserJoinedServerRepositoryABC, ujvs: UserJoinedVoiceChannelRepositoryABC, user_joined_game_server: UserJoinedGameServerRepositoryABC, + permissions: PermissionServiceABC, ): DataQueryABC.__init__(self, "User") @@ -30,6 +32,7 @@ class UserQuery(DataQueryABC): self._user_joined_game_server = user_joined_game_server self._ujs = ujs self._ujvs = ujvs + self._permissions = permissions self.set_field("id", self.resolve_id) self.set_field("discordId", self.resolve_discord_id) @@ -40,33 +43,33 @@ class UserQuery(DataQueryABC): self.set_field("level", self.resolve_level) self.add_collection( "joinedServer", - lambda user, *_: self._ujs.get_user_joined_servers_by_user_id(user.user_id), + lambda user, *_: self._ujs.get_user_joined_servers_by_user_id(user.id), UserJoinedServerFilter, ) self.add_collection( "joinedVoiceChannel", - lambda user, *_: self._ujvs.get_user_joined_voice_channels_by_user_id(user.user_id), + lambda user, *_: self._ujvs.get_user_joined_voice_channels_by_user_id(user.id), UserJoinedVoiceChannelFilter, ) self.add_collection( "userJoinedGameServer", - lambda user, *_: self._user_joined_game_server.get_user_joined_game_servers_by_user_id(user.user_id), + lambda user, *_: self._user_joined_game_server.get_user_joined_game_servers_by_user_id(user.id), UserJoinedGameServerFilter, ) self.set_field("server", self.resolve_server) + self.set_field("leftServer", self.resolve_left_server) @staticmethod def resolve_id(user: User, *_): - return user.user_id + return user.id @staticmethod def resolve_discord_id(user: User, *_): return user.discord_id - def resolve_name(self, user: User, *_): - guild = self._bot.get_guild(user.server.discord_server_id) - user = guild.get_member(user.discord_id) - return None if user is None else user.name + @staticmethod + def resolve_name(user: User, *_): + return user.name @staticmethod def resolve_xp(user: User, *_): @@ -76,12 +79,18 @@ class UserQuery(DataQueryABC): def resolve_minecraft_id(user: User, *_): return user.minecraft_id - def resolve_ontime(self, user: User, *_): - return self._client_utils.get_ontime_for_user(user) + @staticmethod + def resolve_ontime(user: User, *_): + return user.ontime - def resolve_level(self, user: User, *_): - return self._levels.get_level(user) + @staticmethod + def resolve_level(user: User, *_): + return user.level @staticmethod def resolve_server(user: User, *_): return user.server + + @staticmethod + def resolve_left_server(user: User, *_): + return user.left_server diff --git a/kdb-bot/src/modules/auto_role/command/auto_role_group.py b/kdb-bot/src/modules/auto_role/command/auto_role_group.py index bde66962..33ffed23 100644 --- a/kdb-bot/src/modules/auto_role/command/auto_role_group.py +++ b/kdb-bot/src/modules/auto_role/command/auto_role_group.py @@ -52,7 +52,7 @@ class AutoRoleGroup(DiscordCommandABC): self, interaction: discord.Interaction, current: str ) -> TList[app_commands.Choice[str]]: server = self._servers.get_server_by_discord_id(interaction.guild.id) - auto_roles = self._auto_roles.get_auto_roles_by_server_id(server.server_id).select(lambda x: x.auto_role_id) + auto_roles = self._auto_roles.get_auto_roles_by_server_id(server.id).select(lambda x: x.id) return [ app_commands.Choice(name=auto_role, value=auto_role) for auto_role in self._client_utils.get_auto_complete_list(auto_roles, current) @@ -79,7 +79,7 @@ class AutoRoleGroup(DiscordCommandABC): color=int("ef9d0d", 16), ) server = self._servers.get_server_by_discord_id(ctx.guild.id) - auto_roles = self._auto_roles.get_auto_roles_by_server_id(server.server_id) + auto_roles = self._auto_roles.get_auto_roles_by_server_id(server.id) if auto_roles.count() < 1: await self._message_service.send_ctx_msg(ctx, self._t.transform("modules.auto_role.error.nothing_found")) self._logger.trace(__name__, f"Finished command auto-role list") @@ -88,7 +88,7 @@ class AutoRoleGroup(DiscordCommandABC): auto_role_id = "" message_id = "" for auto_role in auto_roles: - auto_role_id += f"\n{auto_role.auto_role_id}" + auto_role_id += f"\n{auto_role.id}" message_id += f"\n{auto_role.discord_message_id}" embed.add_field( @@ -181,7 +181,7 @@ class AutoRoleGroup(DiscordCommandABC): self._logger.trace(__name__, f"Finished command auto-role remove") return - for rule in self._auto_roles.get_auto_role_rules_by_auto_role_id(auto_role_from_db.auto_role_id): + for rule in self._auto_roles.get_auto_role_rules_by_auto_role_id(auto_role_from_db.id): self._auto_roles.delete_auto_role_rule(rule) self._logger.info(__name__, f"Removed auto-role rule {rule.role_id}") @@ -392,12 +392,12 @@ class AutoRoleGroup(DiscordCommandABC): self, interaction: discord.Interaction, current: str ) -> TList[app_commands.Choice[str]]: server = self._servers.get_server_by_discord_id(interaction.guild.id) - auto_roles = self._auto_roles.get_auto_roles_by_server_id(server.server_id).select(lambda x: x.auto_role_id) + auto_roles = self._auto_roles.get_auto_roles_by_server_id(server.id).select(lambda x: x.id) rules = auto_roles.select_many(lambda ar: self._auto_roles.get_auto_role_rules_by_auto_role_id(ar)) return [ app_commands.Choice( - name=f"{rule.auto_role_rule_id} {rule.emoji_name} {interaction.guild.get_role(int(rule.role_id))}", - value=rule.auto_role_rule_id, + name=f"{rule.id} {rule.emoji_name} {interaction.guild.get_role(int(rule.role_id))}", + value=rule.id, ) - for rule in self._client_utils.get_auto_complete_list(rules, current, lambda r: r.auto_role_rule_id) + for rule in self._client_utils.get_auto_complete_list(rules, current, lambda r: r.id) ] diff --git a/kdb-bot/src/modules/auto_role/helper/auto_role_reaction_handler.py b/kdb-bot/src/modules/auto_role/helper/auto_role_reaction_handler.py index c9ae6e7f..47ab3778 100644 --- a/kdb-bot/src/modules/auto_role/helper/auto_role_reaction_handler.py +++ b/kdb-bot/src/modules/auto_role/helper/auto_role_reaction_handler.py @@ -1,4 +1,3 @@ -import discord from cpl_core.logging import LoggerABC from cpl_discord.service import DiscordBotServiceABC from cpl_query.extension import List @@ -50,7 +49,7 @@ class AutoRoleReactionHandler: self._logger.debug(__name__, f"auto-role for message not found - skipping") return - rules: List[AutoRoleRule] = self._auto_roles.get_auto_role_rules_by_auto_role_id(auto_role.auto_role_id) + rules: List[AutoRoleRule] = self._auto_roles.get_auto_role_rules_by_auto_role_id(auto_role.id) if rules.count() == 0: self._logger.debug(__name__, f"auto-role rules not found - skipping") return diff --git a/kdb-bot/src/modules/base/command/ping_command.py b/kdb-bot/src/modules/base/command/ping_command.py index 9e223f9a..eaf58ff6 100644 --- a/kdb-bot/src/modules/base/command/ping_command.py +++ b/kdb-bot/src/modules/base/command/ping_command.py @@ -59,7 +59,7 @@ class PingCommand(DiscordCommandABC): color=int("ef9d0d", 16), ) server = self._servers.get_server_by_discord_id(ctx.guild.id) - settings: BaseServerSettings = self._base_helper.get_config(server.discord_server_id) + settings: BaseServerSettings = self._base_helper.get_config(server.discord_id) for server in settings.ping_urls: embed.add_field(name=server, value=f"{self._get_ping(server)} ms", inline=False) await self._message_service.send_ctx_msg(ctx, embed) diff --git a/kdb-bot/src/modules/base/command/register_group.py b/kdb-bot/src/modules/base/command/register_group.py index b47329cb..e7d9c7cf 100644 --- a/kdb-bot/src/modules/base/command/register_group.py +++ b/kdb-bot/src/modules/base/command/register_group.py @@ -73,7 +73,7 @@ class RegisterGroup(DiscordCommandABC): return server = self._servers.get_server_by_discord_id(ctx.guild.id) - user = self._users.get_user_by_discord_id_and_server_id(member.id, server.server_id) + user = self._users.get_user_by_discord_id_and_server_id(member.id, server.id) user.minecraft_id = minecraft_id self._users.update_user(user) self._db.save_changes() diff --git a/kdb-bot/src/modules/base/command/unregister_group.py b/kdb-bot/src/modules/base/command/unregister_group.py index c929f934..c9c1282d 100644 --- a/kdb-bot/src/modules/base/command/unregister_group.py +++ b/kdb-bot/src/modules/base/command/unregister_group.py @@ -52,7 +52,7 @@ class UnregisterGroup(DiscordCommandABC): self._logger.debug(__name__, f"Received command register minecraft {ctx}") server = self._servers.get_server_by_discord_id(ctx.guild.id) - user = self._users.get_user_by_discord_id_and_server_id(member.id, server.server_id) + user = self._users.get_user_by_discord_id_and_server_id(member.id, server.id) user.minecraft_id = None self._users.update_user(user) self._db.save_changes() diff --git a/kdb-bot/src/modules/base/command/user_group.py b/kdb-bot/src/modules/base/command/user_group.py index b76a0c06..90ce2a81 100644 --- a/kdb-bot/src/modules/base/command/user_group.py +++ b/kdb-bot/src/modules/base/command/user_group.py @@ -81,7 +81,7 @@ class UserGroup(DiscordCommandABC): member = ctx.author server = self._servers.find_server_by_discord_id(ctx.guild.id) - user = self._users.find_user_by_discord_id_and_server_id(member.id, server.server_id) + user = self._users.find_user_by_discord_id_and_server_id(member.id, server.id) if atr == "xp": if is_remove: @@ -125,8 +125,8 @@ class UserGroup(DiscordCommandABC): member = ctx.author server = self._servers.find_server_by_discord_id(ctx.guild.id) - user = self._users.find_user_by_discord_id_and_server_id(member.id, server.server_id) - joins = self._user_joined_servers.get_user_joined_servers_by_user_id(user.user_id) + user = self._users.find_user_by_discord_id_and_server_id(member.id, server.id) + joins = self._user_joined_servers.get_user_joined_servers_by_user_id(user.id) embed = discord.Embed(title=member.name, description=member.name, color=int("ef9d0d", 16)) @@ -206,7 +206,7 @@ class UserGroup(DiscordCommandABC): member = ctx.author server = self._servers.find_server_by_discord_id(ctx.guild.id) - user = self._users.find_user_by_discord_id_and_server_id(member.id, server.server_id) + user = self._users.find_user_by_discord_id_and_server_id(member.id, server.id) if atr == "xp": value = str(user.xp) @@ -241,7 +241,7 @@ class UserGroup(DiscordCommandABC): member = ctx.author server = self._servers.find_server_by_discord_id(ctx.guild.id) - user = self._users.find_user_by_discord_id_and_server_id(member.id, server.server_id) + user = self._users.find_user_by_discord_id_and_server_id(member.id, server.id) if atr == "xp": try: @@ -312,7 +312,7 @@ class UserGroup(DiscordCommandABC): member = ctx.author server = self._servers.find_server_by_discord_id(ctx.guild.id) - user = self._users.find_user_by_discord_id_and_server_id(member.id, server.server_id) + user = self._users.find_user_by_discord_id_and_server_id(member.id, server.id) if atr == "xp": user.xp = 0 @@ -321,7 +321,7 @@ class UserGroup(DiscordCommandABC): await self._level.check_level(member) elif atr == "ontime": - self._user_joined_voice_channel.delete_user_joined_voice_channel_by_user_id(user.user_id) + self._user_joined_voice_channel.delete_user_joined_voice_channel_by_user_id(user.id) self._db.save_changes() else: diff --git a/kdb-bot/src/modules/base/events/base_on_command_event.py b/kdb-bot/src/modules/base/events/base_on_command_event.py index 7b46564b..14ff7287 100644 --- a/kdb-bot/src/modules/base/events/base_on_command_event.py +++ b/kdb-bot/src/modules/base/events/base_on_command_event.py @@ -64,7 +64,7 @@ class BaseOnCommandEvent(OnCommandABC): user: Optional[User] = None try: - user = self._users.get_user_by_discord_id_and_server_id(dc_user_id, server.server_id) + user = self._users.get_user_by_discord_id_and_server_id(dc_user_id, server.id) except Exception as e: self._logger.error(__name__, f"Cannot get user {dc_user_id}", e) return diff --git a/kdb-bot/src/modules/base/events/base_on_member_join_event.py b/kdb-bot/src/modules/base/events/base_on_member_join_event.py index 1913532a..3acfe4aa 100644 --- a/kdb-bot/src/modules/base/events/base_on_member_join_event.py +++ b/kdb-bot/src/modules/base/events/base_on_member_join_event.py @@ -85,7 +85,7 @@ class BaseOnMemberJoinEvent(OnMemberJoinABC): try: server = self._servers.get_server_by_discord_id(member.guild.id) - user = self._users.find_user_by_discord_id_and_server_id(member.id, server.server_id) + user = self._users.find_user_by_discord_id_and_server_id(member.id, server.id) if user is not None: self._user_joins.add_user_joined_server(UserJoinedServer(user, datetime.now())) self._db.save_changes() @@ -94,7 +94,7 @@ class BaseOnMemberJoinEvent(OnMemberJoinABC): self._logger.debug(__name__, f"Add user: {member.id}") self._users.add_user(User(member.id, 0, server)) self._db.save_changes() - user = self._users.get_user_by_discord_id_and_server_id(member.id, server.server_id) + user = self._users.get_user_by_discord_id_and_server_id(member.id, server.id) self._user_joins.add_user_joined_server(UserJoinedServer(user, datetime.now())) self._db.save_changes() except Exception as e: diff --git a/kdb-bot/src/modules/base/events/base_on_member_remove_event.py b/kdb-bot/src/modules/base/events/base_on_member_remove_event.py index b63cc90d..211f8c57 100644 --- a/kdb-bot/src/modules/base/events/base_on_member_remove_event.py +++ b/kdb-bot/src/modules/base/events/base_on_member_remove_event.py @@ -47,12 +47,12 @@ class BaseOnMemberRemoveEvent(OnMemberRemoveABC): try: server = self._servers.get_server_by_discord_id(member.guild.id) - user = self._users.find_user_by_discord_id_and_server_id(member.id, server.server_id) + user = self._users.find_user_by_discord_id_and_server_id(member.id, server.id) if user is None: self._logger.error(__name__, f"Cannot find user {member}") return - join = self._user_joins.get_active_user_joined_server_by_user_id(user.user_id) + join = self._user_joins.get_active_user_joined_server_by_user_id(user.id) join.leaved_on = datetime.now() self._user_joins.update_user_joined_server(join) self._db.save_changes() diff --git a/kdb-bot/src/modules/base/events/base_on_message_delete_event.py b/kdb-bot/src/modules/base/events/base_on_message_delete_event.py index 2ae8172a..6320269a 100644 --- a/kdb-bot/src/modules/base/events/base_on_message_delete_event.py +++ b/kdb-bot/src/modules/base/events/base_on_message_delete_event.py @@ -52,7 +52,7 @@ class BaseOnMessageDeleteEvent(OnMessageDeleteABC): user: Optional[User] = None try: - user = self._users.find_user_by_discord_id_and_server_id(dc_user_id, server.server_id) + user = self._users.find_user_by_discord_id_and_server_id(dc_user_id, server.id) except Exception as e: self._logger.error(__name__, f"Cannot get user {dc_user_id}", e) return diff --git a/kdb-bot/src/modules/base/events/base_on_message_event.py b/kdb-bot/src/modules/base/events/base_on_message_event.py index 85578fda..72637252 100644 --- a/kdb-bot/src/modules/base/events/base_on_message_event.py +++ b/kdb-bot/src/modules/base/events/base_on_message_event.py @@ -57,7 +57,7 @@ class BaseOnMessageEvent(OnMessageABC): user: Optional[User] = None try: - user = self._users.find_user_by_discord_id_and_server_id(dc_user_id, server.server_id) + user = self._users.find_user_by_discord_id_and_server_id(dc_user_id, server.id) except Exception as e: self._logger.error(__name__, f"Cannot get user {dc_user_id}", e) return diff --git a/kdb-bot/src/modules/base/events/base_on_voice_state_update_event.py b/kdb-bot/src/modules/base/events/base_on_voice_state_update_event.py index 30d8439e..c2a25a32 100644 --- a/kdb-bot/src/modules/base/events/base_on_voice_state_update_event.py +++ b/kdb-bot/src/modules/base/events/base_on_voice_state_update_event.py @@ -48,10 +48,10 @@ class BaseOnVoiceStateUpdateEvent(OnVoiceStateUpdateABC): self._logger.info(__name__, f"Module {type(self)} loaded") - def _update_voice_state(self, joined: bool, dc_user_id: int, dc_channel_id: int, server: Server): + def _update_voice_state(self, joined: bool, dc_user_id: int, channel_id: int, server: Server): user: Optional[User] = None try: - user = self._users.get_user_by_discord_id_and_server_id(dc_user_id, server.server_id) + user = self._users.get_user_by_discord_id_and_server_id(dc_user_id, server.id) except Exception as e: self._logger.error(__name__, f"Cannot get user {dc_user_id}", e) return @@ -62,20 +62,18 @@ class BaseOnVoiceStateUpdateEvent(OnVoiceStateUpdateABC): try: if joined: - join = UserJoinedVoiceChannel(user, dc_channel_id, datetime.now()) + join = UserJoinedVoiceChannel(user, channel_id, datetime.now()) self._user_joins_vc.add_user_joined_voice_channel(join) self._db.save_changes() return - settings: BaseServerSettings = self._base_helper.get_config(server.discord_server_id) + settings: BaseServerSettings = self._base_helper.get_config(server.discord_id) - join = self._user_joins_vc.get_active_user_joined_voice_channel_by_user_id(user.user_id) + join = self._user_joins_vc.get_active_user_joined_voice_channel_by_user_id(user.id) join.leaved_on = datetime.now() - # ontime as hours - ontime = round((join.leaved_on - join.joined_on).total_seconds() / 3600, 2) old_xp = user.xp - user.xp += round(ontime * settings.xp_per_ontime_hour) + user.xp += round(join.time * settings.xp_per_ontime_hour) self._user_joins_vc.update_user_joined_voice_channel(join) self._users.update_user(user) @@ -83,7 +81,7 @@ class BaseOnVoiceStateUpdateEvent(OnVoiceStateUpdateABC): self._logger.debug( __name__, - f"User {user} leaved_on {join.leaved_on}. Ontime: {ontime}h | xp: from {old_xp} to {user.xp}", + f"User {user} leaved_on {join.leaved_on}. Ontime: {join.time}h | xp: from {old_xp} to {user.xp}", ) except Exception as e: self._logger.error(__name__, f"Ontime validation failed", e) diff --git a/kdb-bot/src/modules/base/events/base_on_voice_state_update_event_help_channel.py b/kdb-bot/src/modules/base/events/base_on_voice_state_update_event_help_channel.py index 15405cc8..38a95e49 100644 --- a/kdb-bot/src/modules/base/events/base_on_voice_state_update_event_help_channel.py +++ b/kdb-bot/src/modules/base/events/base_on_voice_state_update_event_help_channel.py @@ -43,7 +43,7 @@ class BaseOnVoiceStateUpdateEventHelpChannel(OnVoiceStateUpdateABC): ): self._logger.debug(__name__, f"Module {type(self)} started") server = self._servers.get_server_by_discord_id(member.guild.id) - settings: BaseServerSettings = self._base_helper.get_config(server.discord_server_id) + settings: BaseServerSettings = self._base_helper.get_config(server.discord_id) if after.channel is None or after.channel.id != settings.help_voice_channel_id: return diff --git a/kdb-bot/src/modules/base/helper/base_reaction_handler.py b/kdb-bot/src/modules/base/helper/base_reaction_handler.py index 407c1ece..666f7c8a 100644 --- a/kdb-bot/src/modules/base/helper/base_reaction_handler.py +++ b/kdb-bot/src/modules/base/helper/base_reaction_handler.py @@ -62,7 +62,7 @@ class BaseReactionHandler: return server = self._servers.get_server_by_discord_id(guild.id) - user = self._users.get_user_by_discord_id_and_server_id(member.id, server.server_id) + user = self._users.get_user_by_discord_id_and_server_id(member.id, server.id) settings: BaseServerSettings = self._base_helper.get_config(guild.id) if r_type == "add": diff --git a/kdb-bot/src/modules/database/database_on_ready_event.py b/kdb-bot/src/modules/database/database_on_ready_event.py index af59a3b0..5eb7df76 100644 --- a/kdb-bot/src/modules/database/database_on_ready_event.py +++ b/kdb-bot/src/modules/database/database_on_ready_event.py @@ -144,7 +144,7 @@ class DatabaseOnReadyEvent(OnReadyABC): if server is None: self._logger.fatal(__name__, f"Server not found in database: {g.id}") - client = self._clients.find_client_by_server_id(server.server_id) + client = self._clients.find_client_by_server_id(server.id) if client is not None: continue @@ -156,7 +156,7 @@ class DatabaseOnReadyEvent(OnReadyABC): self._clients.add_client(Client(self._bot.user.id, 0, 0, 0, 0, 0, server)) self._db_context.save_changes() - client = self._clients.find_client_by_server_id(server.server_id) + client = self._clients.find_client_by_server_id(server.id) if client is None: self._logger.fatal( __name__, @@ -187,7 +187,7 @@ class DatabaseOnReadyEvent(OnReadyABC): self._logger.trace(__name__, f"User {u.id} is ignored, because its a bot") continue - user = self._users.find_user_by_discord_id_and_server_id(u.id, server.server_id) + user = self._users.find_user_by_discord_id_and_server_id(u.id, server.id) if user is not None: continue @@ -220,11 +220,11 @@ class DatabaseOnReadyEvent(OnReadyABC): self._logger.trace(__name__, f"User {u.id} is ignored, because its a bot") continue - user = self._users.find_user_by_discord_id_and_server_id(u.id, server.server_id) + user = self._users.find_user_by_discord_id_and_server_id(u.id, server.id) if user is None: self._logger.fatal(__name__, f"User not found in database: {u.id}") - join = self._user_joins.find_active_user_joined_server_by_user_id(user.user_id) + join = self._user_joins.find_active_user_joined_server_by_user_id(user.id) if join is not None: continue @@ -253,7 +253,7 @@ class DatabaseOnReadyEvent(OnReadyABC): joins = self._user_joins.get_user_joined_servers() for join in joins: join: UserJoinedServer = join - if join.user.server.discord_server_id != guild.id: + if join.user.server.discord_id != guild.id: continue if join.leaved_on is not None: @@ -285,11 +285,11 @@ class DatabaseOnReadyEvent(OnReadyABC): self._logger.trace(__name__, f"User {member.id} is ignored, because its a bot") continue - user = self._users.find_user_by_discord_id_and_server_id(member.id, server.server_id) + user = self._users.find_user_by_discord_id_and_server_id(member.id, server.id) if user is None: self._logger.fatal(__name__, f"User not found in database: {member.id}") - joins = self._user_joins_vc.find_active_user_joined_voice_channels_by_user_id(user.user_id) + joins = self._user_joins_vc.find_active_user_joined_voice_channels_by_user_id(user.id) if joins is None or len(joins) == 0: continue @@ -318,7 +318,7 @@ class DatabaseOnReadyEvent(OnReadyABC): if member.voice is None: continue - user = self._users.find_user_by_discord_id_and_server_id(member.id, server.server_id) + user = self._users.find_user_by_discord_id_and_server_id(member.id, server.id) if user is None: self._logger.fatal(__name__, f"User not found in database: {member.id}") @@ -345,11 +345,11 @@ class DatabaseOnReadyEvent(OnReadyABC): self._logger.trace(__name__, f"User {member.id} is ignored, because its a bot") continue - user = self._users.find_user_by_discord_id_and_server_id(member.id, server.server_id) + user = self._users.find_user_by_discord_id_and_server_id(member.id, server.id) if user is None: self._logger.fatal(__name__, f"User not found in database: {member.id}") - joins = self._user_joined_gs.find_active_user_joined_game_servers_by_user_id(user.user_id) + joins = self._user_joined_gs.find_active_user_joined_game_servers_by_user_id(user.id) if joins is None or len(joins) == 0: continue diff --git a/kdb-bot/src/modules/level/command/level_group.py b/kdb-bot/src/modules/level/command/level_group.py index b508ead3..1e7c4ae5 100644 --- a/kdb-bot/src/modules/level/command/level_group.py +++ b/kdb-bot/src/modules/level/command/level_group.py @@ -108,7 +108,7 @@ class LevelGroup(DiscordCommandABC): self, interaction: discord.Interaction, current: str ) -> TList[app_commands.Choice[str]]: server = self._servers.get_server_by_discord_id(interaction.guild.id) - levels = self._levels.get_levels_by_server_id(server.server_id).select(lambda l: l.name) + levels = self._levels.get_levels_by_server_id(server.id).select(lambda l: l.name) return [ app_commands.Choice(name=level, value=level) for level in self._client_utils.get_auto_complete_list(levels, current) @@ -130,7 +130,7 @@ class LevelGroup(DiscordCommandABC): return server = self._servers.get_server_by_discord_id(ctx.guild.id) - levels = self._levels.get_levels_by_server_id(server.server_id) + levels = self._levels.get_levels_by_server_id(server.id) if levels.count() < 1: await self._message_service.send_ctx_msg(ctx, self._t.transform("modules.level.error.nothing_found")) self._logger.trace(__name__, f"Finished command level list") @@ -187,7 +187,7 @@ class LevelGroup(DiscordCommandABC): server = self._servers.get_server_by_discord_id(ctx.guild.id) level = Level(name, color, min_xp, permissions, server) - levels = self._levels.get_levels_by_server_id(server.server_id) + levels = self._levels.get_levels_by_server_id(server.id) if levels.where(lambda l: l.name == level.name).first_or_default() is not None: self._logger.debug(__name__, f"Level with name {level.name} already exists") @@ -261,7 +261,7 @@ class LevelGroup(DiscordCommandABC): server = self._servers.get_server_by_discord_id(ctx.guild.id) level_from_db = ( - self._levels.get_levels_by_server_id(server.server_id).where(lambda l: l.name == level).single_or_default() + self._levels.get_levels_by_server_id(server.id).where(lambda l: l.name == level).single_or_default() ) if level_from_db is None: await self._message_service.send_ctx_msg( @@ -353,7 +353,7 @@ class LevelGroup(DiscordCommandABC): server = self._servers.get_server_by_discord_id(ctx.guild.id) level_from_db = ( - self._levels.get_levels_by_server_id(server.server_id).where(lambda l: l.name == level).first_or_default() + self._levels.get_levels_by_server_id(server.id).where(lambda l: l.name == level).first_or_default() ) if level_from_db is None: self._logger.debug(__name__, f"level {level} not found") @@ -399,9 +399,9 @@ class LevelGroup(DiscordCommandABC): return server = self._servers.get_server_by_discord_id(ctx.guild.id) - user = self._users.get_user_by_discord_id_and_server_id(member.id, server.server_id) + user = self._users.get_user_by_discord_id_and_server_id(member.id, server.id) level = self._level_service.get_level(user) - levels = self._levels.get_levels_by_server_id(server.server_id).order_by(lambda l: l.min_xp) + levels = self._levels.get_levels_by_server_id(server.id).order_by(lambda l: l.min_xp) if level == levels.first(): await self._message_service.send_ctx_msg( @@ -441,9 +441,9 @@ class LevelGroup(DiscordCommandABC): return server = self._servers.get_server_by_discord_id(ctx.guild.id) - user = self._users.get_user_by_discord_id_and_server_id(member.id, server.server_id) + user = self._users.get_user_by_discord_id_and_server_id(member.id, server.id) level = self._level_service.get_level(user) - levels = self._levels.get_levels_by_server_id(server.server_id).order_by(lambda l: l.min_xp) + levels = self._levels.get_levels_by_server_id(server.id).order_by(lambda l: l.min_xp) if level.name == levels.last().name: await self._message_service.send_ctx_msg( @@ -482,11 +482,9 @@ class LevelGroup(DiscordCommandABC): return server = self._servers.get_server_by_discord_id(ctx.guild.id) - user = self._users.get_user_by_discord_id_and_server_id(member.id, server.server_id) + user = self._users.get_user_by_discord_id_and_server_id(member.id, server.id) current_level = self._level_service.get_level(user) - new_level = ( - self._levels.get_levels_by_server_id(server.server_id).where(lambda l: l.name == level).single_or_default() - ) + new_level = self._levels.get_levels_by_server_id(server.id).where(lambda l: l.name == level).single_or_default() if new_level is None: await self._message_service.send_ctx_msg( diff --git a/kdb-bot/src/modules/level/level_seeder.py b/kdb-bot/src/modules/level/level_seeder.py index 7a51e2df..36487873 100644 --- a/kdb-bot/src/modules/level/level_seeder.py +++ b/kdb-bot/src/modules/level/level_seeder.py @@ -47,7 +47,7 @@ class LevelSeeder(DataSeederABC): ) self._logger.debug(__name__, f"Created role {level.name}") - levels = self._levels.find_levels_by_server_id(server.server_id) + levels = self._levels.find_levels_by_server_id(server.id) if levels is None or levels.where(lambda l: l.name == level.name).first_or_default() is None: self._levels.add_level(level) self._logger.debug(__name__, f"Saved level {level.name}") @@ -69,7 +69,7 @@ class LevelSeeder(DataSeederABC): if server is None: continue - levels = self._levels.find_levels_by_server_id(server.server_id) + levels = self._levels.find_levels_by_server_id(server.id) if levels is not None and levels.count() > 0: # create levels from db for level in levels: diff --git a/kdb-bot/src/modules/level/service/level_service.py b/kdb-bot/src/modules/level/service/level_service.py index 192a7dde..44e99a93 100644 --- a/kdb-bot/src/modules/level/service/level_service.py +++ b/kdb-bot/src/modules/level/service/level_service.py @@ -1,5 +1,3 @@ -import asyncio - import discord from cpl_core.configuration import ConfigurationABC from cpl_core.database.context import DatabaseContextABC @@ -41,7 +39,7 @@ class LevelService: self._t = t def get_level(self, user: User) -> Level: - levels_by_server = self._levels.get_levels_by_server_id(user.server.server_id) + levels_by_server = self._levels.get_levels_by_server_id(user.server.id) levels = levels_by_server.order_by(lambda l: l.min_xp).where(lambda l: user.xp >= l.min_xp) if levels.count() == 0: @@ -50,8 +48,8 @@ class LevelService: return levels.last() async def set_level(self, user: User): - level_names = self._levels.get_levels_by_server_id(user.server.server_id).select(lambda l: l.name) - guild: Guild = self._bot.guilds.where(lambda g: g.id == user.server.discord_server_id).single() + level_names = self._levels.get_levels_by_server_id(user.server.id).select(lambda l: l.name) + guild: Guild = self._bot.guilds.where(lambda g: g.id == user.server.discord_id).single() member: Member = guild.members.where(lambda m: m.id == user.discord_id).single() level = self.get_level(user) @@ -89,7 +87,7 @@ class LevelService: return server = self._servers.get_server_by_discord_id(member.guild.id) - user = self._users.find_user_by_discord_id_and_server_id(member.id, server.server_id) + user = self._users.find_user_by_discord_id_and_server_id(member.id, server.id) if user is None: self._logger.warn(__name__, f"User not found {member.guild.name}@{member.name}") return diff --git a/kdb-bot/src/modules/stats/command/stats_group.py b/kdb-bot/src/modules/stats/command/stats_group.py index 7db65858..f44f8782 100644 --- a/kdb-bot/src/modules/stats/command/stats_group.py +++ b/kdb-bot/src/modules/stats/command/stats_group.py @@ -66,7 +66,7 @@ class StatsGroup(DiscordCommandABC): ) server = self._servers.get_server_by_discord_id(ctx.guild.id) - stats = self._stats.get_statistics_by_server_id(server.server_id) + stats = self._stats.get_statistics_by_server_id(server.id) if stats.count() == 0: await self._message_service.send_ctx_msg(ctx, self._t.transform("modules.stats.list.nothing_found")) @@ -103,7 +103,7 @@ class StatsGroup(DiscordCommandABC): try: server = self._servers.get_server_by_discord_id(ctx.guild.id) - stats = self._stats.get_statistics_by_server_id(server.server_id) + stats = self._stats.get_statistics_by_server_id(server.id) statistic = stats.where(lambda s: s.name == name).single() result = await self._statistic.execute(statistic.code, server) @@ -132,7 +132,7 @@ class StatsGroup(DiscordCommandABC): self, interaction: discord.Interaction, current: str ) -> TList[app_commands.Choice[str]]: server = self._servers.get_server_by_discord_id(interaction.guild.id) - stats = self._stats.get_statistics_by_server_id(server.server_id) + stats = self._stats.get_statistics_by_server_id(server.id) return [ app_commands.Choice(name=f"{statistic.name}: {statistic.description}", value=statistic.name) for statistic in stats @@ -171,7 +171,7 @@ class StatsGroup(DiscordCommandABC): try: server = self._servers.get_server_by_discord_id(ctx.guild.id) - stats = self._stats.get_statistics_by_server_id(server.server_id) + stats = self._stats.get_statistics_by_server_id(server.id) statistic = stats.where(lambda s: s.name == name).single() form = AddStatisticForm( server, @@ -196,7 +196,7 @@ class StatsGroup(DiscordCommandABC): self, interaction: discord.Interaction, current: str ) -> TList[app_commands.Choice[str]]: server = self._servers.get_server_by_discord_id(interaction.guild.id) - stats = self._stats.get_statistics_by_server_id(server.server_id) + stats = self._stats.get_statistics_by_server_id(server.id) return [ app_commands.Choice(name=f"{statistic.name}: {statistic.description}", value=statistic.name) for statistic in stats @@ -211,7 +211,7 @@ class StatsGroup(DiscordCommandABC): try: server = self._servers.get_server_by_discord_id(ctx.guild.id) - statistic = self._stats.get_statistic_by_name(name, server.server_id) + statistic = self._stats.get_statistic_by_name(name, server.id) self._stats.delete_statistic(statistic) self._db.save_changes() await self._message_service.send_ctx_msg(ctx, self._t.transform("modules.stats.remove.success")) @@ -225,7 +225,7 @@ class StatsGroup(DiscordCommandABC): self, interaction: discord.Interaction, current: str ) -> TList[app_commands.Choice[str]]: server = self._servers.get_server_by_discord_id(interaction.guild.id) - stats = self._stats.get_statistics_by_server_id(server.server_id) + stats = self._stats.get_statistics_by_server_id(server.id) return [ app_commands.Choice(name=f"{statistic.name}: {statistic.description}", value=statistic.name) for statistic in stats diff --git a/kdb-bot/src/modules/stats/service/statistic_service.py b/kdb-bot/src/modules/stats/service/statistic_service.py index 8286c533..9d9a3fb6 100644 --- a/kdb-bot/src/modules/stats/service/statistic_service.py +++ b/kdb-bot/src/modules/stats/service/statistic_service.py @@ -1,5 +1,3 @@ -from abc import abstractmethod - from cpl_discord.service import DiscordBotServiceABC from cpl_query.extension import List from discord import Guild @@ -49,22 +47,20 @@ class StatisticService: self._bot = bot async def execute(self, code: str, server: Server) -> StatisticResult: - guild = self._bot.guilds.where(lambda g: g.id == server.discord_server_id).single() + guild = self._bot.guilds.where(lambda g: g.id == server.discord_id).single() return await self.get_data( code, - self._auto_roles.get_auto_roles().where(lambda x: x.server.server_id == server.server_id), - self._clients.get_clients().where(lambda x: x.server.server_id == server.server_id), + self._auto_roles.get_auto_roles().where(lambda x: x.server.id == server.id), + self._clients.get_clients().where(lambda x: x.server.id == server.id), self._known_users.get_users(), - self._levels.get_levels().where(lambda x: x.server.server_id == server.server_id), - self._servers.get_servers().where(lambda x: x.server_id == server.server_id), - self._user_joined_servers.get_user_joined_servers().where( - lambda x: x.user.server.server_id == server.server_id - ), + self._levels.get_levels().where(lambda x: x.server.id == server.id), + self._servers.get_servers().where(lambda x: x.id == server.id), + self._user_joined_servers.get_user_joined_servers().where(lambda x: x.user.server.id == server.id), self._user_joined_voice_channel.get_user_joined_voice_channels().where( - lambda x: x.user.server.server_id == server.server_id + lambda x: x.user.server.id == server.id ), - self._users.get_users().where(lambda x: x.server.server_id == server.server_id), + self._users.get_users().where(lambda x: x.server.id == server.id), guild, ) diff --git a/kdb-bot/src/modules/stats/ui/add_statistic_form.py b/kdb-bot/src/modules/stats/ui/add_statistic_form.py index e07502e2..98182858 100644 --- a/kdb-bot/src/modules/stats/ui/add_statistic_form.py +++ b/kdb-bot/src/modules/stats/ui/add_statistic_form.py @@ -1,6 +1,5 @@ import discord from cpl_core.database.context import DatabaseContextABC -from cpl_query.extension import List from cpl_translation import TranslatePipe from discord import ui, TextStyle @@ -45,7 +44,7 @@ class AddStatisticForm(ui.Modal): async def on_submit(self, interaction: discord.Interaction): statistic = ( - self._stats.get_statistics_by_server_id(self._server.server_id) + self._stats.get_statistics_by_server_id(self._server.id) .where(lambda s: s.name == self._name) .single_or_default() ) diff --git a/kdb-bot/src/modules/technician/command/api_key_group.py b/kdb-bot/src/modules/technician/command/api_key_group.py index 1f7f0c0d..11912385 100644 --- a/kdb-bot/src/modules/technician/command/api_key_group.py +++ b/kdb-bot/src/modules/technician/command/api_key_group.py @@ -95,7 +95,7 @@ class ApiKeyGroup(DiscordCommandABC): self._logger.debug(__name__, f"Received command api-key add {ctx}: {identifier}") server = self._servers.get_server_by_discord_id(ctx.guild.id) - user = self._users.get_user_by_discord_id_and_server_id(ctx.author.id, server.server_id) + user = self._users.get_user_by_discord_id_and_server_id(ctx.author.id, server.id) api_key = ApiKey(identifier, str(uuid.uuid4()), user) self._api_keys.add_api_key(api_key) self._db.save_changes() diff --git a/kdb-web/package.json b/kdb-web/package.json index 0df95016..a3642281 100644 --- a/kdb-web/package.json +++ b/kdb-web/package.json @@ -1,6 +1,6 @@ { "name": "kdb-web", - "version": "0.3.dev78", + "version": "0.3.dev130", "scripts": { "ng": "ng", "update-version": "ts-node-esm update-version.ts", diff --git a/kdb-web/src/app/app.component.html b/kdb-web/src/app/app.component.html index a2dc5b50..8c0cfa4f 100644 --- a/kdb-web/src/app/app.component.html +++ b/kdb-web/src/app/app.component.html @@ -1,4 +1,5 @@
+ @@ -33,4 +34,4 @@ -
\ No newline at end of file + diff --git a/kdb-web/src/app/app.component.ts b/kdb-web/src/app/app.component.ts index 1a2cf35f..8b919479 100644 --- a/kdb-web/src/app/app.component.ts +++ b/kdb-web/src/app/app.component.ts @@ -1,14 +1,21 @@ -import { Component, OnInit } from '@angular/core'; -import { TranslateService } from '@ngx-translate/core'; -import { PrimeNGConfig } from 'primeng/api'; -import { AuthService } from './services/auth/auth.service'; -import { SocketService } from './services/socket/socket.service'; -import { ThemeService } from './services/theme/theme.service'; +import { Component, OnInit } from "@angular/core"; +import { TranslateService } from "@ngx-translate/core"; +import { PrimeNGConfig } from "primeng/api"; +import { AuthService } from "./services/auth/auth.service"; +import { SocketService } from "./services/socket/socket.service"; +import { ThemeService } from "./services/theme/theme.service"; +import { ActivatedRoute, Router } from "@angular/router"; +import { SpinnerService } from "./services/spinner/spinner.service"; +import { DataService } from "./services/data/data.service"; +import { SidebarService } from "./services/sidebar/sidebar.service"; +import { Server } from "./models/data/server.model"; +import { Queries } from "./models/graphql/queries.model"; +import { Query } from "./models/graphql/query.model"; @Component({ - selector: 'app-root', - templateUrl: './app.component.html', - styleUrls: ['./app.component.scss'] + selector: "app-root", + templateUrl: "./app.component.html", + styleUrls: ["./app.component.scss"] }) export class AppComponent implements OnInit { @@ -22,7 +29,7 @@ export class AppComponent implements OnInit { private themeService: ThemeService, private socket: SocketService, private translateService: TranslateService, - private config: PrimeNGConfig + private config: PrimeNGConfig, ) { this.themeService.sidebarWidth$.subscribe(value => { this.sidebarWidth = value; @@ -36,7 +43,7 @@ export class AppComponent implements OnInit { } ngOnInit(): void { - this.translateService.setDefaultLang('en'); + this.translateService.setDefaultLang("en"); this.themeService.loadTheme(); this.socket.startSocket(); @@ -45,7 +52,7 @@ export class AppComponent implements OnInit { loadLang(): void { let lang = localStorage.getItem(`default_lang`); if (!lang) { - lang = 'en'; + lang = "en"; this.setLang(lang); } this.translate(lang); @@ -57,7 +64,7 @@ export class AppComponent implements OnInit { translate(lang: string) { this.translateService.use(lang); - this.translateService.get('primeng').subscribe(res => this.config.setTranslation(res)); + this.translateService.get("primeng").subscribe(res => this.config.setTranslation(res)); } diff --git a/kdb-web/src/app/components/sidebar/sidebar.component.ts b/kdb-web/src/app/components/sidebar/sidebar.component.ts index 09eb593b..955bec11 100644 --- a/kdb-web/src/app/components/sidebar/sidebar.component.ts +++ b/kdb-web/src/app/components/sidebar/sidebar.component.ts @@ -1,5 +1,5 @@ import { Component, OnInit } from "@angular/core"; -import { LangChangeEvent, TranslateService } from "@ngx-translate/core"; +import { TranslateService } from "@ngx-translate/core"; import { MenuItem } from "primeng/api"; import { AuthService } from "src/app/services/auth/auth.service"; import { ThemeService } from "src/app/services/theme/theme.service"; @@ -21,15 +21,6 @@ export class SidebarComponent implements OnInit { private themeService: ThemeService, private sidebar: SidebarService ) { - this.translateService.onLangChange.subscribe((event: LangChangeEvent) => { - this.sidebar.setMenu(); - }); - - this.themeService.isSidebarOpen$.subscribe(value => { - this.isSidebarOpen = value; - this.sidebar.setMenu(); - }); - this.sidebar.menuItems$.subscribe(value => { this.menuItems = value; }); diff --git a/kdb-web/src/app/components/spinner/spinner.component.html b/kdb-web/src/app/components/spinner/spinner.component.html index b4f52b87..658b9ba2 100644 --- a/kdb-web/src/app/components/spinner/spinner.component.html +++ b/kdb-web/src/app/components/spinner/spinner.component.html @@ -1,7 +1,7 @@ - +
-
\ No newline at end of file +
diff --git a/kdb-web/src/app/components/spinner/spinner.component.ts b/kdb-web/src/app/components/spinner/spinner.component.ts index 4753534c..4bae2cd0 100644 --- a/kdb-web/src/app/components/spinner/spinner.component.ts +++ b/kdb-web/src/app/components/spinner/spinner.component.ts @@ -8,9 +8,15 @@ import { SpinnerService } from 'src/app/services/spinner/spinner.service'; }) export class SpinnerComponent implements OnInit { + showSpinnerState: boolean = false; + constructor( public spinnerService: SpinnerService - ) { } + ) { + this.spinnerService.showSpinnerState$.subscribe(value => { + this.showSpinnerState = value; + }); + } ngOnInit(): void { } diff --git a/kdb-web/src/app/models/auth/auth-user.dto.ts b/kdb-web/src/app/models/auth/auth-user.dto.ts index 5f38cbeb..fc49619d 100644 --- a/kdb-web/src/app/models/auth/auth-user.dto.ts +++ b/kdb-web/src/app/models/auth/auth-user.dto.ts @@ -1,13 +1,28 @@ -import { AuthRoles } from "./auth-roles.enum"; +import {AuthRoles} from "./auth-roles.enum"; export interface AuthUserDTO { - id?: number; - firstName: string | null; - lastName: string | null; - email: string | null; - password: string | null; - isConfirmed?: boolean - authRole?: AuthRoles; - createdAt?: string; - modifiedAt?: string; + id?: number; + firstName: string | null; + lastName: string | null; + email: string | null; + password: string | null; + isConfirmed?: boolean; + authRole?: AuthRoles; + users?: UserDTO[]; + createdAt?: string; + modifiedAt?: string; +} + + +export interface UserDTO { + id: number; + discordId: number; + xp: number; + minecraftId: number | null; + server: number; + createdAt: string; + modifiedAt: string; + isTechnician: boolean; + isAdmin: boolean; + isModerator: boolean; } diff --git a/kdb-web/src/app/models/data/level.model.ts b/kdb-web/src/app/models/data/level.model.ts new file mode 100644 index 00000000..932070a7 --- /dev/null +++ b/kdb-web/src/app/models/data/level.model.ts @@ -0,0 +1,17 @@ +import { Data } from "./data.model"; +import { Server, ServerFilter } from "./server.model"; + +export interface Level extends Data { + id?: number; + name?: string; + color?: string; + minXp?: number; + permissions?: string; + server?: Server; +} + +export interface LevelFilter { + id?: number; + name?: String; + server?: ServerFilter; +} diff --git a/kdb-web/src/app/models/data/server.model.ts b/kdb-web/src/app/models/data/server.model.ts index 6be87ab6..a6ae0d99 100644 --- a/kdb-web/src/app/models/data/server.model.ts +++ b/kdb-web/src/app/models/data/server.model.ts @@ -1,8 +1,10 @@ import { Data } from "./data.model"; +import { User } from "./user.model"; +import { Level } from "./level.model"; export interface Server extends Data { id?: number; - discordId?: number; + discordId?: String; name?: string; iconURL?: string; autoRoleCount?: number; @@ -10,7 +12,13 @@ export interface Server extends Data { clientCount?: number; clients?: []; levelCount?: number; - levels?: []; + levels?: Level[]; userCount?: number; - users?: []; + users?: User[]; +} + +export interface ServerFilter { + id?: number; + discordId?: String; + name?: String; } diff --git a/kdb-web/src/app/models/data/user.model.ts b/kdb-web/src/app/models/data/user.model.ts new file mode 100644 index 00000000..e55e5e19 --- /dev/null +++ b/kdb-web/src/app/models/data/user.model.ts @@ -0,0 +1,39 @@ +import { Data } from "./data.model"; +import { Level, LevelFilter } from "./level.model"; +import { Server, ServerFilter } from "./server.model"; +import { UserJoinedServer } from "./user_joined_server.model"; +import { UserJoinedVoiceChannel } from "./user_joined_voice_channel.model"; +import { UserJoinedGameServer } from "./user_joined_game_server.model"; + +export interface User extends Data { + id?: number; + discordId?: number; + name?: string; + xp?: number; + minecraftId?: number; + ontime?: number; + level?: Level; + server?: Server; + leftServer?: boolean; + + joinedServerCount?: number; + joinedServers?: UserJoinedServer[]; + + joinedVoiceChannelCount?: number; + joinedVoiceChannels?: UserJoinedVoiceChannel[]; + + userJoinedGameServerCount?: number; + userJoinedGameServers?: UserJoinedGameServer[]; +} + +export interface UserFilter { + id?: number; + discordId?: number; + name?: string; + xp?: number; + minecraftId?: number; + ontime?: number; + level?: LevelFilter; + server?: ServerFilter; + leftServer?: boolean; +} diff --git a/kdb-web/src/app/models/data/user_joined_game_server.model.ts b/kdb-web/src/app/models/data/user_joined_game_server.model.ts new file mode 100644 index 00000000..b8ce5e72 --- /dev/null +++ b/kdb-web/src/app/models/data/user_joined_game_server.model.ts @@ -0,0 +1,11 @@ +import { Data } from "./data.model"; +import { User } from "./user.model"; + +export interface UserJoinedGameServer extends Data { + id: number; + gameServer: string; + user: User; + time: number; + joinedOn: string; + leavedOn: string; +} diff --git a/kdb-web/src/app/models/data/user_joined_server.model.ts b/kdb-web/src/app/models/data/user_joined_server.model.ts new file mode 100644 index 00000000..7828dece --- /dev/null +++ b/kdb-web/src/app/models/data/user_joined_server.model.ts @@ -0,0 +1,9 @@ +import { Data } from "./data.model"; +import { User } from "./user.model"; + +export interface UserJoinedServer extends Data { + id: number; + user: User; + joinedOn: string; + leavedOn: string; +} diff --git a/kdb-web/src/app/models/data/user_joined_voice_channel.model.ts b/kdb-web/src/app/models/data/user_joined_voice_channel.model.ts new file mode 100644 index 00000000..9c49ff2e --- /dev/null +++ b/kdb-web/src/app/models/data/user_joined_voice_channel.model.ts @@ -0,0 +1,12 @@ +import { Data } from "./data.model"; +import { User } from "./user.model"; + +export interface UserJoinedVoiceChannel extends Data { + id: number; + channelId: string; + channelName: string; + user: User; + time: number; + joinedOn: string; + leavedOn: string; +} diff --git a/kdb-web/src/app/models/graphql/filter/sort.model.ts b/kdb-web/src/app/models/graphql/filter/sort.model.ts index 61ee7627..aca195a4 100644 --- a/kdb-web/src/app/models/graphql/filter/sort.model.ts +++ b/kdb-web/src/app/models/graphql/filter/sort.model.ts @@ -1,4 +1,9 @@ export interface Sort { sortColumn?: string; - sortDirection?: string; + sortDirection?: SortDirection; +} + +export enum SortDirection { + ASC = "ASC", + DESC = "DESC", } diff --git a/kdb-web/src/app/models/graphql/mutations.model.ts b/kdb-web/src/app/models/graphql/mutations.model.ts new file mode 100644 index 00000000..f7be1c11 --- /dev/null +++ b/kdb-web/src/app/models/graphql/mutations.model.ts @@ -0,0 +1,17 @@ +export class Mutations { + static updateUser = ` + mutation updateUser($id: ID, $xp: Int, $levelId: ID) { + user { + updateUser(input: { id: $id, xp: $xp, levelId: $levelId }) { + id + name + xp + level { + id + name + } + } + } + } + `; +} diff --git a/kdb-web/src/app/models/graphql/queries.model.ts b/kdb-web/src/app/models/graphql/queries.model.ts index ce12391d..73baaf4a 100644 --- a/kdb-web/src/app/models/graphql/queries.model.ts +++ b/kdb-web/src/app/models/graphql/queries.model.ts @@ -21,4 +21,115 @@ export class Queries { } } `; + + static levelQuery = ` + query LevelsList($filter: LevelFilter, $page: Page, $sort: Sort) { + levelCount + levels(filter: $filter, page: $page, sort: $sort) { + id + name + color + minXp + permissions + server { + id + name + } + } + } + `; + + static usersQuery = ` + query UsersList($filter: UserFilter, $page: Page, $sort: Sort) { + userCount + users(filter: $filter, page: $page, sort: $sort) { + id + discordId + name + xp + ontime + level { + id + name + } + server { + id + name + } + leftServer + + joinedServerCount + joinedServers { + id + } + + joinedVoiceChannelCount + joinedVoiceChannels { + id + channelId + channelName + } + + userJoinedGameServerCount + userJoinedGameServers { + id + gameServer + } + + createdAt + modifiedAt + } + } + `; + + static singleUserQuery = ` + query singleUserQuery($filter: UserFilter) { + users(filter: $filter) { + id + discordId + name + xp + ontime + minecraftId + level { + 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 + } + + createdAt + modifiedAt + } + } + `; } diff --git a/kdb-web/src/app/models/graphql/query.model.ts b/kdb-web/src/app/models/graphql/query.model.ts index 0e62f16a..ed6eb037 100644 --- a/kdb-web/src/app/models/graphql/query.model.ts +++ b/kdb-web/src/app/models/graphql/query.model.ts @@ -1,6 +1,18 @@ import { Server } from "../data/server.model"; +import { User } from "../data/user.model"; export interface Query { serverCount: number; servers: Server[]; } + +export interface UserListQuery { + userCount: number; + users: User[]; +} + +export interface LevelListQuery { + levelCount: number; + levels: User[]; +} + diff --git a/kdb-web/src/app/models/graphql/result.model.ts b/kdb-web/src/app/models/graphql/result.model.ts index 4d3d5144..bc28521d 100644 --- a/kdb-web/src/app/models/graphql/result.model.ts +++ b/kdb-web/src/app/models/graphql/result.model.ts @@ -1,5 +1,11 @@ -import { Query } from "./query.model"; +import { User } from "../data/user.model"; export interface QueryResult { data: any; } + +export interface UpdateUserMutationResult { + user: { + updateUser: User + }; +} diff --git a/kdb-web/src/app/modules/admin/auth-users/components/auth-user/auth-user.component.html b/kdb-web/src/app/modules/admin/auth-users/components/auth-user/auth-user.component.html index 86d29795..4aefe844 100644 --- a/kdb-web/src/app/modules/admin/auth-users/components/auth-user/auth-user.component.html +++ b/kdb-web/src/app/modules/admin/auth-users/components/auth-user/auth-user.component.html @@ -32,7 +32,7 @@
{{'admin.auth_users.headers.first_name' | translate}}
- +
@@ -72,13 +72,13 @@
-
{{'admin.auth_users.headers.created_at' | translate}}
+
{{'common.created_at' | translate}}
-
{{'admin.auth_users.headers.modified_at' | translate}}
+
{{'common.modified_at' | translate}}
@@ -87,7 +87,6 @@
{{'admin.auth_users.headers.actions' | translate}}
- @@ -108,7 +107,7 @@
- +
@@ -190,7 +189,7 @@ - {{user.createdAt}} + {{user.createdAt | date:'dd.MM.yy HH:mm'}} {{user.createdAt | date:'dd.MM.yy HH:mm'}} @@ -200,7 +199,7 @@ - {{user.modifiedAt}} + {{user.modifiedAt | date:'dd.MM.yy HH:mm'}} {{user.modifiedAt | date:'dd.MM.yy HH:mm'}} @@ -223,9 +222,9 @@ - + - {{'admin.auth_users.no_entries_found' | translate}} + {{'admin.auth_users.no_entries_found' | translate}} @@ -234,3 +233,4 @@ + diff --git a/kdb-web/src/app/modules/shared/pipes/bool.pipe.ts b/kdb-web/src/app/modules/shared/pipes/bool.pipe.ts index fc2d54cf..acfbc034 100644 --- a/kdb-web/src/app/modules/shared/pipes/bool.pipe.ts +++ b/kdb-web/src/app/modules/shared/pipes/bool.pipe.ts @@ -10,11 +10,15 @@ export class BoolPipe implements PipeTransform { private translate: TranslateService ) {} - transform(value: boolean): string { - if (value === true) { + transform(value?: boolean): string { + if (value === undefined || value === null) { + return ''; + } + + if (value) { return this.translate.instant('common.bool_as_string.true'); } - + return this.translate.instant('common.bool_as_string.false'); } diff --git a/kdb-web/src/app/modules/shared/shared.module.ts b/kdb-web/src/app/modules/shared/shared.module.ts index 59c0d0ef..bf719ea6 100644 --- a/kdb-web/src/app/modules/shared/shared.module.ts +++ b/kdb-web/src/app/modules/shared/shared.module.ts @@ -19,6 +19,7 @@ import { AuthRolePipe } from './pipes/auth-role.pipe'; import { IpAddressPipe } from './pipes/ip-address.pipe'; import { BoolPipe } from './pipes/bool.pipe'; import { PanelMenuModule } from 'primeng/panelmenu'; +import { PanelModule } from "primeng/panel"; @@ -47,6 +48,7 @@ import { PanelMenuModule } from 'primeng/panelmenu'; TranslateModule, DynamicDialogModule, PanelMenuModule, + PanelModule, ], exports: [ ButtonModule, @@ -66,6 +68,7 @@ import { PanelMenuModule } from 'primeng/panelmenu'; TranslateModule, DynamicDialogModule, PanelMenuModule, + PanelModule, AuthRolePipe, IpAddressPipe, BoolPipe, diff --git a/kdb-web/src/app/modules/view/dashboard/components/dashboard/dashboard.component.ts b/kdb-web/src/app/modules/view/dashboard/components/dashboard/dashboard.component.ts index 685eaf9c..0121b314 100644 --- a/kdb-web/src/app/modules/view/dashboard/components/dashboard/dashboard.component.ts +++ b/kdb-web/src/app/modules/view/dashboard/components/dashboard/dashboard.component.ts @@ -2,13 +2,12 @@ import { Component, OnInit } from "@angular/core"; import { FormBuilder, FormControl, FormGroup } from "@angular/forms"; import { Router } from "@angular/router"; import { TranslateService } from "@ngx-translate/core"; -import { LazyLoadEvent } from "primeng/api"; import { debounceTime, throwError } from "rxjs"; import { ConfirmationDialogService } from "src/app/services/confirmation-dialog/confirmation-dialog.service"; import { DataService } from "src/app/services/data/data.service"; import { SpinnerService } from "src/app/services/spinner/spinner.service"; import { ToastService } from "src/app/services/toast/toast.service"; -import { Server } from "../../../../../models/data/server.model"; +import { Server, ServerFilter } from "../../../../../models/data/server.model"; import { catchError } from "rxjs/operators"; import { Queries } from "../../../../../models/graphql/queries.model"; import { Page } from "../../../../../models/graphql/filter/page.model"; @@ -27,9 +26,7 @@ export class DashboardComponent implements OnInit { totalRecords!: number; - filter = { - name: "" - }; + filter: ServerFilter = {}; page: Page = { pageIndex: 0, @@ -50,7 +47,7 @@ export class DashboardComponent implements OnInit { private fb: FormBuilder, private translate: TranslateService, private router: Router, - private sidebar: SidebarService, + private sidebar: SidebarService ) { } @@ -63,13 +60,15 @@ export class DashboardComponent implements OnInit { setFilterForm() { this.filterForm = this.fb.group({ - name: [""] + name: new FormControl(null) }); this.filterForm.valueChanges.pipe( debounceTime(600) ).subscribe(async changes => { - if (changes.name) { + if (changes.name == "") { + this.filter.name = undefined; + } else if (changes.name) { this.filter.name = changes.name; } @@ -85,10 +84,10 @@ export class DashboardComponent implements OnInit { loadNextPage() { this.spinnerService.showSpinner(); - this.data.query(Queries.serversListQuery,{ + this.data.query(Queries.serversListQuery, { filter: this.filter, page: this.page, - sort: this.sort, + sort: this.sort }).pipe(catchError(err => { this.spinnerService.hideSpinner(); return throwError(() => err); @@ -99,30 +98,8 @@ export class DashboardComponent implements OnInit { }); } - 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 ?? "", - sortDirection: event.sortOrder === 1 ? "asc" : event.sortOrder === -1 ? "desc" : "asc" - }; - - if (event.filters) { - // + "" => convert to string - this.filter.name = event.filters["name"] ? event.filters["name"] + "" : ""; - } - - this.loadNextPage(); - } - - resetFilters() { - this.filterForm.reset(); - } - selectServer(server: Server) { - this.sidebar.serverName$.next(server.name ?? ""); + this.sidebar.setServer(server); this.router.navigate(["/server", server.id]); } diff --git a/kdb-web/src/app/modules/view/server/members/members.component.html b/kdb-web/src/app/modules/view/server/members/members.component.html new file mode 100644 index 00000000..e8e51b34 --- /dev/null +++ b/kdb-web/src/app/modules/view/server/members/members.component.html @@ -0,0 +1,250 @@ +

+ {{'view.server.members.header' | translate}} +

+
+
+ + + +
+
+ {{members.length}} {{'view.server.members.of' | translate}} + {{dt.totalRecords}} + + {{'view.server.members.members' | translate}} +
+ +
+ +
+
+
+ + + + +
+
{{'view.server.members.headers.id' | translate}}
+ +
+ + + +
+
{{'view.server.members.headers.discord_id' | translate}}
+ +
+ + + +
+
{{'view.server.members.headers.name' | translate}}
+ +
+ + + +
+
{{'view.server.members.headers.xp' | translate}}
+ +
+ + + +
+
{{'view.server.members.headers.ontime' | translate}}
+ +
+ + + +
+
{{'view.server.members.headers.left_server' | translate}}
+ +
+ + + +
+
{{'view.server.members.headers.level' | translate}}
+ +
+ + + +
+
{{'common.created_at' | translate}}
+
+ + + +
+
{{'common.modified_at' | translate}}
+
+ + + +
+
{{'view.server.members.headers.actions' | translate}}
+
+ + + + + +
+ +
+ + +
+ +
+ + +
+ +
+ + + + +
+ +
+ + +
+ +
+ + + + + +
+ + + + + + + {{member.id}} + + + {{member.id}} + + + + + + + {{member.discordId}} + + + {{member.discordId}} + + + + + + + {{member.name}} + + + {{member.name}} + + + + + + + + + + {{member.xp}} + + + + + + + {{member.ontime}} + + + {{member.ontime}} + + + + + + + {{!member.leftServer | bool}} + + + {{!member.leftServer | bool}} + + + + + + + + + + {{member.level.name}} + + + + + + + {{member.createdAt | date:'dd.MM.yy HH:mm'}} + + + {{member.createdAt | date:'dd.MM.yy HH:mm'}} + + + + + + + {{member.modifiedAt | date:'dd.MM.yy HH:mm'}} + + + {{member.modifiedAt | date:'dd.MM.yy HH:mm'}} + + + + +
+ + + + + +
+ + +
+ + + + + {{'view.server.members.no_entries_found' | translate}} + + + + + + +
+
+
diff --git a/kdb-web/src/app/modules/view/server/members/members.component.scss b/kdb-web/src/app/modules/view/server/members/members.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/kdb-web/src/app/modules/view/server/members/members.component.spec.ts b/kdb-web/src/app/modules/view/server/members/members.component.spec.ts new file mode 100644 index 00000000..f626726f --- /dev/null +++ b/kdb-web/src/app/modules/view/server/members/members.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { MembersComponent } from './members.component'; + +describe('MembersComponent', () => { + let component: MembersComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ MembersComponent ] + }) + .compileComponents(); + + fixture = TestBed.createComponent(MembersComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/kdb-web/src/app/modules/view/server/members/members.component.ts b/kdb-web/src/app/modules/view/server/members/members.component.ts new file mode 100644 index 00000000..bc98e1ee --- /dev/null +++ b/kdb-web/src/app/modules/view/server/members/members.component.ts @@ -0,0 +1,249 @@ +import { Component } from "@angular/core"; +import { FormBuilder, FormControl, FormGroup } from "@angular/forms"; +import { AuthService } from "../../../../services/auth/auth.service"; +import { SpinnerService } from "../../../../services/spinner/spinner.service"; +import { ToastService } from "../../../../services/toast/toast.service"; +import { ConfirmationDialogService } from "../../../../services/confirmation-dialog/confirmation-dialog.service"; +import { TranslateService } from "@ngx-translate/core"; +import { catchError, debounceTime } from "rxjs/operators"; +import { LazyLoadEvent, MenuItem } from "primeng/api"; +import { Table } from "primeng/table"; +import { User, UserFilter } from "../../../../models/data/user.model"; +import { Queries } from "../../../../models/graphql/queries.model"; +import { LevelListQuery, UserListQuery } from "../../../../models/graphql/query.model"; +import { DataService } from "../../../../services/data/data.service"; +import { Page } from "../../../../models/graphql/filter/page.model"; +import { Sort, SortDirection } from "../../../../models/graphql/filter/sort.model"; +import { SidebarService } from "../../../../services/sidebar/sidebar.service"; +import { Mutations } from "../../../../models/graphql/mutations.model"; +import { throwError } from "rxjs"; +import { UpdateUserMutationResult } from "../../../../models/graphql/result.model"; +import { ActivatedRoute } from "@angular/router"; + +@Component({ + selector: "app-members", + templateUrl: "./members.component.html", + styleUrls: ["./members.component.scss"] +}) +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; } = {}; + isEditingNew: boolean = false; + + newUserTemplate: User = { + id: 0, + discordId: 0, + name: "", + xp: 0, + ontime: 0, + level: undefined, + server: undefined, + + joinedServerCount: 0, + joinedServers: [], + + joinedVoiceChannelCount: 0, + joinedVoiceChannels: [], + + userJoinedGameServerCount: 0, + userJoinedGameServers: [], + + createdAt: "", + modifiedAt: "" + }; + + filterForm!: FormGroup<{ + id: FormControl, + discordId: FormControl, + name: FormControl, + leftServer: FormControl, + level: FormControl + }>; + + filter: UserFilter = {}; + page: Page = { + pageSize: undefined, + pageIndex: undefined + }; + sort: Sort = { + sortColumn: undefined, + sortDirection: undefined + }; + + totalRecords!: number; + + constructor( + private authService: AuthService, + private spinner: SpinnerService, + private toastService: ToastService, + private confirmDialog: ConfirmationDialogService, + private fb: FormBuilder, + private translate: TranslateService, + private data: DataService, + private sidebar: SidebarService, + private route: ActivatedRoute + ) { + } + + ngOnInit(): void { + this.data.getServerFromRoute(this.route); + + this.spinner.showSpinner(); + this.data.query(Queries.levelQuery, { + filter: { + server: { id: this.sidebar.server$.value?.id } + } + } + ).subscribe(data => { + this.levels = data.levels.map(level => { + return { label: level.name, value: level }; + }); + this.spinner.hideSpinner(); + }); + + this.setFilterForm(); + this.loadNextPage(); + } + + loadNextPage() { + this.loading = true; + this.data.query(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(null), + discordId: new FormControl(null), + name: [""], + leftServer: new FormControl(null), + level: new FormControl(null), + }); + + this.filterForm.valueChanges.pipe( + debounceTime(600) + ).subscribe(changes => { + if (changes.id) { + this.filter.id = changes.id; + } else { + this.filter.id = undefined; + } + + if (changes.discordId) { + this.filter.discordId = changes.discordId; + } else { + this.filter.discordId = undefined; + } + + if (changes.name) { + this.filter.name = changes.name; + } else { + 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 + }; + } else { + this.filter.level = undefined; + } + + if (this.page.pageSize) + this.page.pageSize = 10; + + if (this.page.pageIndex) + this.page.pageIndex = 0; + + this.loadNextPage(); + }); + } + + 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.loadNextPage(); + } + + resetFilters() { + this.filterForm.reset(); + } + + onRowEditInit(table: Table, user: User, index: number) { + this.clonedUsers[index] = { ...user }; + } + + onRowEditSave(table: Table, newUser: User, index: number) { + // const oldUser = this.clonedUsers[index]; + // delete this.clonedUsers[index]; + + // if (JSON.stringify(oldUser) === JSON.stringify(newUser) && !this.isEditingNew) { + // console.log(1, oldUser, newUser, JSON.stringify(oldUser) === JSON.stringify(newUser), !this.isEditingNew); + // return; + // } + + if (this.isEditingNew && JSON.stringify(newUser) === JSON.stringify(this.newUserTemplate)) { + this.isEditingNew = false; + this.members.splice(index, 1); + return; + } + + if (!newUser.id || !newUser.xp && !newUser.level?.id) { + return; + } + + this.spinner.showSpinner(); + this.data.mutation(Mutations.updateUser, { + id: newUser.id, + xp: newUser.xp, + levelId: newUser.level?.id + } + ).pipe(catchError(err => { + this.spinner.hideSpinner(); + this.toastService.error(this.translate.instant("view.server.members.message.user_change_failed"), this.translate.instant("view.server.members.message.user_change_failed_d", { name: newUser.name })); + 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: newUser.name })); + this.loadNextPage(); + }); + + } + + onRowEditCancel(user: User, index: number) { + if (this.isEditingNew) { + this.members.splice(index, 1); + delete this.clonedUsers[index]; + this.isEditingNew = false; + return; + } + + this.members[index] = this.clonedUsers[index]; + delete this.clonedUsers[index]; + } +} diff --git a/kdb-web/src/app/modules/view/server/profile/profile.component.html b/kdb-web/src/app/modules/view/server/profile/profile.component.html new file mode 100644 index 00000000..a1a38b43 --- /dev/null +++ b/kdb-web/src/app/modules/view/server/profile/profile.component.html @@ -0,0 +1,149 @@ +

+ {{'view.server.profile.header' | translate}} +

+
+
+

+ {{user.name}} +

+
+ +
+
+
+
{{'view.server.profile.id' | translate}}:
+
{{user.id}}
+
+
+
{{'view.server.profile.discord_id' | translate}}:
+
{{user.discordId}}
+
+
+ +
+
+
{{'view.server.profile.name' | translate}}:
+
{{user.name}}
+
+
+ +
+
+
{{'view.server.profile.xp' | translate}}:
+
{{user.xp}}
+
+
+ +
+
+
{{'view.server.profile.ontime' | translate}}:
+
{{user.ontime}}
+
+
+ +
+
+
{{'view.server.profile.minecraft_id' | translate}}:
+
{{user.minecraftId}}
+
+
+ +
+
+
{{'view.server.profile.level' | translate}}:
+
{{user.level?.name}}
+
+
+ +
+
+
{{'view.server.profile.left_server' | translate}}:
+
{{user.leftServer | bool}}
+
+
+ +
+
+
{{'common.created_at' | translate}}:
+
{{user.createdAt | date:'dd.MM.yyyy HH:mm:ss'}}
+
+
+ +
+
+
{{'common.modified_at' | translate}}:
+
{{user.modifiedAt | date:'dd.MM.yyyy HH:mm:ss'}}
+
+
+ +
+ + +
+
+
+
{{'view.server.profile.joined_voice_channel.time' | translate}}:
+
{{join.time}} {{'general.hours' | translate}}
+
+ +
+
{{'view.server.profile.joined_voice_channel.channel' | translate}}:
+
{{join.channelName}}
+
+ +
+
{{'common.joined_at' | translate}}:
+
{{join.joinedOn | date:'dd.MM.yyyy HH:mm:ss'}}
+
+ +
+
{{'common.leaved_at' | translate}}:
+
{{join.leavedOn | date:'dd.MM.yyyy HH:mm:ss'}}
+
+
+
+ +
+ +
+
+
+
{{'view.server.profile.joined_game_server.time' | translate}}:
+
{{join.time}} {{'general.hours' | translate}}
+
+ +
+
{{'view.server.profile.joined_game_server.name' | translate}}:
+
{{join.gameServer}}
+
+ +
+
{{'common.joined_at' | translate}}:
+
{{join.joinedOn | date:'dd.MM.yyyy HH:mm:ss'}}
+
+ +
+
{{'common.leaved_at' | translate}}:
+
{{join.leavedOn | date:'dd.MM.yyyy HH:mm:ss'}}
+
+
+
+
+ + +
+
+
+
{{'common.joined_at' | translate}}:
+
{{join.joinedOn | date:'dd.MM.yyyy HH:mm:ss'}}
+
+ +
+
{{'common.leaved_at' | translate}}:
+
{{join.leavedOn | date:'dd.MM.yyyy HH:mm:ss'}}
+
+
+
+
+
+
diff --git a/kdb-web/src/app/modules/view/server/profile/profile.component.scss b/kdb-web/src/app/modules/view/server/profile/profile.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/kdb-web/src/app/modules/view/server/profile/profile.component.spec.ts b/kdb-web/src/app/modules/view/server/profile/profile.component.spec.ts new file mode 100644 index 00000000..246039d7 --- /dev/null +++ b/kdb-web/src/app/modules/view/server/profile/profile.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ProfileComponent } from './profile.component'; + +describe('ProfileComponent', () => { + let component: ProfileComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ProfileComponent ] + }) + .compileComponents(); + + fixture = TestBed.createComponent(ProfileComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/kdb-web/src/app/modules/view/server/profile/profile.component.ts b/kdb-web/src/app/modules/view/server/profile/profile.component.ts new file mode 100644 index 00000000..eb67181b --- /dev/null +++ b/kdb-web/src/app/modules/view/server/profile/profile.component.ts @@ -0,0 +1,66 @@ +import { Component, 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 { 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", + templateUrl: "./profile.component.html", + styleUrls: ["./profile.component.scss"] +}) +export class ProfileComponent implements OnInit { + + user!: User; + + constructor( + private route: ActivatedRoute, + private router: Router, + private spinner: SpinnerService, + private sidebar: SidebarService, + private data: DataService, + private auth: AuthService, + private toast: ToastService, + private translate: TranslateService + ) { + } + + async ngOnInit() { + this.data.getServerFromRoute(this.route); + + if (!this.route.snapshot.params["memberId"]) { + this.router.navigate(["/dashboard"]); + return; + } + + let authUser = await this.auth.getLoggedInUser(); + this.spinner.showSpinner(); + 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.spinner.hideSpinner(); + this.router.navigate(["/server", this.sidebar.server$.value?.id]); + return; + } + + this.data.query(Queries.singleUserQuery, { + filter: { + id: this.route.snapshot.params["memberId"] + } + }, + function(data: UserListQuery) { + return data.users.length > 0 ? data.users[0] : null; + } + ).subscribe(user => { + this.user = user; + this.spinner.hideSpinner(); + }); + } +} diff --git a/kdb-web/src/app/modules/view/server/server-dashboard/server-dashboard.component.ts b/kdb-web/src/app/modules/view/server/server-dashboard/server-dashboard.component.ts index 28f87e1a..651b8d56 100644 --- a/kdb-web/src/app/modules/view/server/server-dashboard/server-dashboard.component.ts +++ b/kdb-web/src/app/modules/view/server/server-dashboard/server-dashboard.component.ts @@ -3,8 +3,6 @@ import { ActivatedRoute, Router } from "@angular/router"; import { Server } from "src/app/models/data/server.model"; import { DataService } from "src/app/services/data/data.service"; import { SpinnerService } from "src/app/services/spinner/spinner.service"; -import { Queries } from "../../../../models/graphql/queries.model"; -import { Query } from "../../../../models/graphql/query.model"; import { SidebarService } from "../../../../services/sidebar/sidebar.service"; @Component({ @@ -27,23 +25,13 @@ export class ServerDashboardComponent implements OnInit { } ngOnInit(): void { - this.spinner.showSpinner(); - if (!this.route.snapshot.params["serverId"]) { - this.spinner.hideSpinner(); - this.router.navigate(['/dashboard']); - return; - } + this.data.getServerFromRoute(this.route); - this.data.query(Queries.serversQuery, { - filter: { id: this.route.snapshot.params["serverId"] } - }, - function(data: Query) { - return data.servers.length > 0 ? data.servers[0] : null; + this.sidebar.server$.subscribe(server => { + if (!server) { + return; } - ).subscribe(server => { this.server = server; - this.sidebar.serverName$.next(server.name ?? ""); - this.spinner.hideSpinner(); }); } diff --git a/kdb-web/src/app/modules/view/server/server-routing.module.ts b/kdb-web/src/app/modules/view/server/server-routing.module.ts index d7e96c59..d4de8413 100644 --- a/kdb-web/src/app/modules/view/server/server-routing.module.ts +++ b/kdb-web/src/app/modules/view/server/server-routing.module.ts @@ -1,9 +1,13 @@ import { NgModule } from "@angular/core"; import { RouterModule, Routes } from "@angular/router"; import { ServerDashboardComponent } from "./server-dashboard/server-dashboard.component"; +import { ProfileComponent } from "./profile/profile.component"; +import { MembersComponent } from "./members/members.component"; const routes: Routes = [ { path: '', component: ServerDashboardComponent }, + { path: 'members', component: MembersComponent }, + { path: 'members/:memberId', component: ProfileComponent }, ]; @NgModule({ diff --git a/kdb-web/src/app/modules/view/server/server.module.ts b/kdb-web/src/app/modules/view/server/server.module.ts index 824e2412..dad9964a 100644 --- a/kdb-web/src/app/modules/view/server/server.module.ts +++ b/kdb-web/src/app/modules/view/server/server.module.ts @@ -3,12 +3,16 @@ 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'; @NgModule({ declarations: [ - ServerDashboardComponent + ServerDashboardComponent, + ProfileComponent, + MembersComponent ], imports: [ CommonModule, diff --git a/kdb-web/src/app/services/auth/auth.service.ts b/kdb-web/src/app/services/auth/auth.service.ts index 3a0c86cf..73686887 100644 --- a/kdb-web/src/app/services/auth/auth.service.ts +++ b/kdb-web/src/app/services/auth/auth.service.ts @@ -241,6 +241,20 @@ export class AuthService { return null } + async getLoggedInUser(): Promise { + if (!await this.isUserLoggedInAsync()) { + return null; + } + const token = this.getDecodedToken(); + if (!token) return null; + + try { + return await firstValueFrom(this.findUserByEMail(token["email"])); + } catch (error: unknown) { + return null; + } + } + async isUserLoggedInAsync(): Promise { const token = this.getToken(); diff --git a/kdb-web/src/app/services/data/data.service.ts b/kdb-web/src/app/services/data/data.service.ts index af6f2a35..e0c36ef1 100644 --- a/kdb-web/src/app/services/data/data.service.ts +++ b/kdb-web/src/app/services/data/data.service.ts @@ -3,6 +3,12 @@ import { Injectable } from "@angular/core"; import { SettingsService } from "../settings/settings.service"; import { map, Observable } from "rxjs"; import { Variables } from "../../models/graphql/variables.model"; +import { ActivatedRoute, Router } from "@angular/router"; +import { Server } from "../../models/data/server.model"; +import { Queries } from "../../models/graphql/queries.model"; +import { Query } from "../../models/graphql/query.model"; +import { SidebarService } from "../sidebar/sidebar.service"; +import { SpinnerService } from "../spinner/spinner.service"; @Injectable({ providedIn: "root" @@ -11,21 +17,32 @@ export class DataService { constructor( private appsettings: SettingsService, - private http: HttpClient + private http: HttpClient, + private sidebar: SidebarService, + private spinner: SpinnerService, + private router: Router, ) { } - // query(query: string, variables: object = {}): Observable { - // return this.http.post(`${this.appsettings.getApiURL()}/api/graphql`, - // JSON.stringify({ - // query, variables - // }), { - // headers: new HttpHeaders({ - // "Content-Type": "application/json" - // }) - // } - // ); - // } + public getServerFromRoute(route: ActivatedRoute) { + this.spinner.showSpinner(); + if (!route.snapshot.params["serverId"]) { + this.spinner.hideSpinner(); + this.router.navigate(['/dashboard']); + return; + } + + this.query(Queries.serversQuery, { + filter: { id: route.snapshot.params["serverId"] } + }, + function(data: Query) { + return data.servers.length > 0 ? data.servers[0] : null; + } + ).subscribe(server => { + this.sidebar.setServer(server); + this.spinner.hideSpinner(); + }); + } public query(query: string, variables?: Variables, f?: Function): Observable { return this.http @@ -37,4 +54,14 @@ export class DataService { .pipe(map((d) => f ? f(d) : d)); } + public mutation(query: string, variables?: object, f?: Function): Observable { + return this.http + .post<{ data: T }>(`${this.appsettings.getApiURL()}/api/graphql`, { + query: query, + variables: variables + }) + .pipe(map((d) => d.data)) + .pipe(map((d) => f ? f(d) : d)); + } + } diff --git a/kdb-web/src/app/services/sidebar/sidebar.service.ts b/kdb-web/src/app/services/sidebar/sidebar.service.ts index ef3f6a95..5a7a23a6 100644 --- a/kdb-web/src/app/services/sidebar/sidebar.service.ts +++ b/kdb-web/src/app/services/sidebar/sidebar.service.ts @@ -4,8 +4,10 @@ import { BehaviorSubject } from "rxjs"; import { AuthRoles } from "../../models/auth/auth-roles.enum"; import { AuthService } from "../auth/auth.service"; import { TranslateService } from "@ngx-translate/core"; -import { ActivatedRoute, NavigationEnd, Router } from "@angular/router"; +import { NavigationEnd, Router } from "@angular/router"; import { ThemeService } from "../theme/theme.service"; +import { Server } from "../../models/data/server.model"; +import { UserDTO } from "../../models/auth/auth-user.dto"; @Injectable({ providedIn: "root" @@ -13,22 +15,30 @@ import { ThemeService } from "../theme/theme.service"; export class SidebarService { isSidebarOpen: boolean = true; - menuItems$: BehaviorSubject = new BehaviorSubject(new Array()); - serverName$: BehaviorSubject = new BehaviorSubject(""); + menuItems$ = new BehaviorSubject(new Array()); + server$ = new BehaviorSubject(null); + + dashboard!: MenuItem; + serverDashboard!: MenuItem; + serverProfile!: MenuItem; + serverMembers!: MenuItem; + serverMenu!: MenuItem; + adminConfig!: MenuItem; + adminUsers!: MenuItem; + adminMenu!: MenuItem; constructor( private themeService: ThemeService, private authService: AuthService, private translateService: TranslateService, - private router: Router, + private router: Router ) { this.themeService.isSidebarOpen$.subscribe(value => { this.isSidebarOpen = value; this.setMenu(); }); - - this.serverName$.subscribe(value => { + this.translateService.onLangChange.subscribe(_ => { this.setMenu(); }); @@ -36,37 +46,84 @@ export class SidebarService { if (!(event instanceof NavigationEnd)) { return; } + if (!event.url.startsWith("/server/") && this.server$.value) { + this.setServer(null); + } }); } - setMenu() { - this.authService.hasUserPermission(AuthRoles.Admin).then(hasPermission => { + setServer(server: Server | null) { + if (server?.id != this.server$.value?.id) { + this.server$.next(server); + if (server) { + this.setMenu(true); + } else { + this.setMenu(false); + } + } + } + + async buildMenu(user: UserDTO | null, hasPermission: boolean) { + this.dashboard = { label: this.isSidebarOpen ? this.translateService.instant("sidebar.dashboard") : "", icon: "pi pi-th-large", routerLink: "dashboard" }; + this.serverDashboard = { + label: this.isSidebarOpen ? this.translateService.instant("sidebar.server.dashboard") : "", + icon: "pi pi-th-large", + routerLink: `server/${this.server$.value?.id}` + }; + this.serverProfile = { + label: this.isSidebarOpen ? this.translateService.instant("sidebar.server.profile") : "", + icon: "pi pi-user", + routerLink: `server/${this.server$.value?.id}/members/${user?.id}` + }; + this.serverMembers = { + label: this.isSidebarOpen ? this.translateService.instant("sidebar.server.members") : "", + icon: "pi pi-users", + visible: true, + routerLink: `server/${this.server$.value?.id}/members` + }; + this.serverMenu = { + label: this.isSidebarOpen ? this.server$.value?.name : "", + icon: "pi pi-server", + visible: false, + expanded: true, + items: [this.serverDashboard, this.serverProfile, this.serverMembers] + }; + this.adminConfig = { label: this.isSidebarOpen ? this.translateService.instant("sidebar.config") : "", icon: "pi pi-cog", routerLink: "/admin/settings" }; + this.adminUsers = { + label: this.isSidebarOpen ? this.translateService.instant("sidebar.auth_user_list") : "", + icon: "pi pi-user-edit", + routerLink: "/admin/users" + }; + this.adminMenu = { + label: this.isSidebarOpen ? this.translateService.instant("sidebar.administration") : "", + icon: "pi pi-cog", + visible: hasPermission, + expanded: true, + items: [this.adminConfig, this.adminUsers] + }; + } + + setMenu(build: boolean = false) { + this.authService.hasUserPermission(AuthRoles.Admin).then(async hasPermission => { + let authUser = await this.authService.getLoggedInUser(); + let user: UserDTO | null = authUser?.users?.find(u => u.server == this.server$.value?.id) ?? null; + + if (build || this.menuItems$.value.length == 0) { + await this.buildMenu(user, hasPermission); + } + + if (this.server$.value) { + this.serverMenu.visible = true; + this.serverMembers.visible = !!user?.isModerator; + } else { + this.serverMenu.visible = false; + } + let menuItems: MenuItem[] = [ - { label: this.isSidebarOpen ? this.translateService.instant("sidebar.dashboard") : "", icon: "pi pi-th-large", routerLink: "dashboard" } + this.dashboard, + this.serverMenu, + this.adminMenu ]; - - const serverMenu = { - label: this.isSidebarOpen ? this.serverName$.value : "", icon: "pi pi-server", items: [ - { label: this.isSidebarOpen ? this.translateService.instant("sidebar.settings") : "", icon: "pi pi-cog", routerLink: "server/settings" }, - { label: this.isSidebarOpen ? this.translateService.instant("sidebar.members") : "", icon: "pi pi-users", routerLink: "server/members" } - ] - }; - if (this.serverName$.value != "") { - menuItems.push(serverMenu); - } else if (menuItems.find(x => x.icon == "pi pi-server")) { - menuItems.splice(menuItems.indexOf(serverMenu), 1); - } - - if (hasPermission) { - menuItems.push( - { - label: this.isSidebarOpen ? this.translateService.instant("sidebar.administration") : "", icon: "pi pi-cog", items: [ - { label: this.isSidebarOpen ? this.translateService.instant("sidebar.config") : "", icon: "pi pi-cog", routerLink: "/admin/settings" }, - { label: this.isSidebarOpen ? this.translateService.instant("sidebar.auth_user_list") : "", icon: "pi pi-user-edit", routerLink: "/admin/users" } - ] - } - ); - } this.menuItems$.next(menuItems); }); } diff --git a/kdb-web/src/app/services/spinner/spinner.service.ts b/kdb-web/src/app/services/spinner/spinner.service.ts index 0d3aab97..0582688c 100644 --- a/kdb-web/src/app/services/spinner/spinner.service.ts +++ b/kdb-web/src/app/services/spinner/spinner.service.ts @@ -1,22 +1,23 @@ import { Injectable } from '@angular/core'; +import { BehaviorSubject } from "rxjs"; @Injectable({ providedIn: 'root' }) export class SpinnerService { - showSpinnerState = false; + showSpinnerState$ = new BehaviorSubject(false); constructor() { } showSpinner() { - this.showSpinnerState = true; + this.showSpinnerState$.next(true); } hideSpinner() { - this.showSpinnerState = false; + this.showSpinnerState$.next(false); } toggleSpinner() { - this.showSpinnerState = !this.showSpinnerState; + this.showSpinnerState$.next(!this.showSpinnerState$.value); } } diff --git a/kdb-web/src/assets/config.json b/kdb-web/src/assets/config.json index 87e33a65..7af5781a 100644 --- a/kdb-web/src/assets/config.json +++ b/kdb-web/src/assets/config.json @@ -3,7 +3,7 @@ "WebVersion": { "Major": "0", "Minor": "3", - "Micro": "dev78" + "Micro": "dev130" }, "Themes": [ { diff --git a/kdb-web/src/assets/i18n/de.json b/kdb-web/src/assets/i18n/de.json index 9317f607..b94c3045 100644 --- a/kdb-web/src/assets/i18n/de.json +++ b/kdb-web/src/assets/i18n/de.json @@ -7,10 +7,14 @@ }, "sidebar": { "dashboard": "Dashboard", - "server": "Server", + "server": { + "dashboard": "Dashboard", + "profile": "Dein Profil", + "members": "Mitglieder" + }, "server_empty": "Kein Server ausgewählt", - "settings": "Einstellungen", "members": "Mitglieder", + "settings": "Einstellungen", "administration": "Administration", "config": "Konfiguration", "auth_user_list": "Benutzer" @@ -61,12 +65,11 @@ "first_name": "Vorname", "last_name": "Nachname", "e_mail": "E-Mail", + "auth_role": "Rolle", "active": "Aktiv", "role": "Rolle", "password": "Passwort", - "actions": "Aktionen", - "created_at": "Erstellt am", - "modified_at": "Bearbeitet am" + "actions": "Aktionen" }, "no_entries_found": "Keine Einträge gefunden", "message": { @@ -146,7 +149,7 @@ "servers": "Server", "server": { "header": "Server", - "member_count": "Mitglid(er)" + "member_count": "Mitglied(er)" }, "filter": { "name": "Name" @@ -156,6 +159,57 @@ "header": "Server", "dashboard": { "header": "Server dashboard" + }, + "profile": { + "header": "Dein Profil", + "id": "Id", + "discord_id": "Discord Id", + "name": "Name", + "xp": "XP", + "ontime": "Ontime", + "minecraft_id": "Minecraft Id", + "level": "Level", + "left_server": "Hat Server verlassen", + "joined_voice_channel": { + "header": "Sprachkanal-beitritte", + "time": "Zeit", + "channel": "Sprachkanal" + }, + "joined_game_server": { + "header": "Gameserver-beitritte", + "time": "Spielzeit", + "name": "Gameserver" + }, + "joined_server": { + "header": "Server-beitritte", + "time": "Zeit" + }, + "permission_denied": "Zugriff Verweigert!", + "permission_denied_d": "Du musst Moderator sein, um andere Profile sehen zu können!" + }, + "members": { + "header": "Mitglieder", + "of": "von", + "add": "Hinzufügen", + "reset_filters": "Filter zurücksetzen", + "members": "Mitgliedern", + "headers": { + "id": "ID", + "discord_id": "Discord ID", + "name": "Name", + "xp": "XP", + "ontime": "Ontime", + "left_server": "Aktiv", + "level": "Level", + "actions": "Aktionen" + }, + "no_entries_found": "Keine Einträge gefunden", + "message": { + "user_changed": "Benutzer geändert", + "user_changed_d": "Benutzer {{name}} erfolgreich geändert", + "user_change_failed": "Benutzer änderung fehlgeschlagen", + "user_change_failed_d": "Benutzer {{name}} konnte nicht geändert werden!" + } } }, "user-list": {}, @@ -205,9 +259,14 @@ }, "general": { "days": "Tage", - "minutes": "Minuten" + "minutes": "Minuten", + "hours": "Stunden" }, "common": { + "created_at": "Erstellt am", + "modified_at": "Bearbeitet am", + "joined_at": "Beigetreten am", + "leaved_at": "Verlassen am", "bool_as_string": { "true": "Ja", "false": "Nein" diff --git a/kdb-web/src/styles.scss b/kdb-web/src/styles.scss index 9d6c4649..0fa6ae5a 100644 --- a/kdb-web/src/styles.scss +++ b/kdb-web/src/styles.scss @@ -7,461 +7,475 @@ html, body { - height: 100%; - padding: 0; - margin: 0; + height: 100%; + padding: 0; + margin: 0; - font-size: 1rem; + font-size: 1rem; } main { - display: flex; - flex-direction: column; - min-height: 100vh; + display: flex; + flex-direction: column; + min-height: 100vh; } h1 { - margin: 0; - font-size: 1.75rem; + margin: 0; + font-size: 1.75rem; } h2 { - margin: 0; - font-size: 1.5rem; + margin: 0; + font-size: 1.5rem; } h3 { - margin: 0; - font-size: 1.25rem; + margin: 0; + font-size: 1.25rem; } header { - height: $headerHeight; + height: $headerHeight; + display: flex; + flex-direction: row; + + .logo-button-wrapper { display: flex; - flex-direction: row; + align-items: center; + justify-content: center; - .logo-button-wrapper { - display: flex; - align-items: center; - justify-content: center; - - .p-button.p-button-text { - border: none; - } + .p-button.p-button-text { + border: none; } + } - .logo { - display: flex; - align-items: center; - justify-content: center; - } + .logo { + display: flex; + align-items: center; + justify-content: center; + } - .header-menu { - text-align: right; - flex: 1; - justify-content: flex-end; - margin: 0px 5px 0px 0px; - } + .header-menu { + text-align: right; + flex: 1; + justify-content: flex-end; + margin: 0 5px 0 0; + } - .p-menu-overlay { - width: 180px !important; - } + .p-menu-overlay { + width: 180px !important; + } } .auth-header { - .p-menu-overlay { - width: 180px !important; - } + .p-menu-overlay { + width: 180px !important; + } } .app { + height: 100%; + display: flex; + flex: 1; + + .sidebar { height: 100%; - display: flex; - flex: 1; + } - .sidebar { - height: 100%; - } + h1 { + // table views with filters are scrollable with 10 items, when 30px margin + margin-bottom: 20px; + } - h1 { - // table views with filters are scrollable with 10 items, when 30px margin - margin-bottom: 20px; - } + .component-wrapper { + width: 100%; - .component-wrapper { - width: 100%; + .component { + width: 100%; + height: 100%; + padding: 15px; - .component { - width: 100%; - height: 100%; - padding: 15px; + .content-wrapper { + margin-bottom: 30px; + border-radius: 5px; - .content-wrapper { - margin-bottom: 30px; - border-radius: 5px; + .content-header { + padding: 10px; - .content-header { - padding: 10px; - - h2 { - font-size: 20px; - } - } - - .content { - width: 100%; - display: flex; - flex-direction: column; - padding: 15px; - - form { - width: 100%; - } - - .content-row { - display: flex; - flex-direction: row; - flex: 1; - margin: 1.5px 0px; - } - - .content-column { - display: flex; - flex: 1; - } - - .content-data-name { - display: flex; - flex: 1; - align-items: center; - - font-size: 18px; - } - - .content-data-value { - display: flex; - flex: 1; - align-items: center; - - font-size: 18px; - } - - .content-divider { - margin: 5px 0px; - } - - .content-input-field { - width: 50% !important; - margin: 0 !important; - } - - .input-field { - width: 100%; - - input, - .p-password { - width: 100%; - } - } - - .input-field-info-text { - margin: 15px 0px; - width: 100%; - } - - .login-form-submit { - .login-form-submit-btn { - width: 100%; - } - } - - .login-form-sub-button-wrapper { - display: flex; - flex-direction: column; - - .login-form-sub-btn { - margin-top: 15px; - width: 100%; - } - - .login-form-sub-btn-wrapper { - width: 100%; - } - } - - .table-caption { - display: flex; - - .table-caption-text { - flex: 1; - font-weight: 400; - } - - .table-caption-search { - } - } - - .table-header-label { - display: flex; - - .table-header-text { - flex: 1; - } - - .table-header-icon { - } - } - - .table-header-actions { - width: 100px; - } - - .table-header-small-dropdown { - width: 150px; - } - - .server-list-wrapper { - display: flex; - flex-direction: column; - gap: 10px; - - .server-filter { - } - - .server-count { - } - - .server-list { - display: flex; - flex-direction: column; - - gap: 15px; - - .server { - display: flex; - gap: 15px; - - padding: 20px; - - .logo { - overflow: hidden; - - img { - width: 4rem; - height: 4rem; - object-fit: contain; - } - } - - .info { - display: flex; - flex-direction: column; - - gap: 10px; - - .name { - margin: 0px; - - justify-content: center; - align-items: center; - } - - .data { - } - } - } - } - } - } - } + h2 { + font-size: 20px; + } } + + .content { + width: 100%; + display: flex; + flex-direction: column; + padding: 15px; + + form { + input { + width: 100%; + } + } + + .content-row { + display: flex; + flex-direction: row; + flex: 1; + margin: 5px 0; + } + + .content-column { + display: flex; + flex: 1; + } + + .content-data-name { + display: flex; + flex: 1; + align-items: center; + + font-size: 18px; + } + + .content-data-value { + display: flex; + flex: 1; + align-items: center; + + font-size: 18px; + } + + .content-divider { + margin: 5px 0; + } + + p-panel { + margin: 5px 0; + } + + .content-input-field { + width: 50% !important; + margin: 0 !important; + } + + .input-field { + width: 100%; + + input, + .p-password { + width: 100%; + } + } + + .input-field-info-text { + margin: 15px 0; + width: 100%; + } + + .login-form-submit { + .login-form-submit-btn { + width: 100%; + } + } + + .login-form-sub-button-wrapper { + display: flex; + flex-direction: column; + + .login-form-sub-btn { + margin-top: 15px; + width: 100%; + } + + .login-form-sub-btn-wrapper { + width: 100%; + } + } + + .table-caption { + display: flex; + + .table-caption-text { + flex: 1; + font-weight: 400; + } + + .table-caption-search { + } + } + + .table-header-label { + display: flex; + + .table-header-text { + flex: 1; + } + + .table-header-icon { + } + } + + .table-header-small { + width: 75px; + } + + .table-header-medium { + width: 150px; + } + + .table-header-actions { + width: 100px; + } + + .table-header-small-dropdown { + width: 150px; + } + + .server-list-wrapper { + display: flex; + flex-direction: column; + gap: 10px; + + .server-filter { + } + + .server-count { + } + + .server-list { + display: flex; + flex-direction: column; + + gap: 15px; + + .server { + display: flex; + gap: 15px; + + padding: 20px; + + .logo { + overflow: hidden; + + img { + width: 4rem; + height: 4rem; + object-fit: contain; + } + } + + .info { + display: flex; + flex-direction: column; + + gap: 10px; + + .name { + margin: 0; + + justify-content: center; + align-items: center; + } + + .data { + } + } + } + } + } + } + } } + } } .p-dialog-header { - padding: 20px 20px 20px 20px !important; + padding: 20px 20px 20px 20px !important; } .p-dialog-content { - padding: 20px !important; + padding: 20px !important; } .p-dialog-footer { - padding: 0px 20px 20px 20px !important; + padding: 0 20px 20px 20px !important; } .p-dialog-content { - .content-row { - display: flex; - flex-direction: row; - flex: 1; - margin: 1.5px 0px; - } + .content-row { + display: flex; + flex-direction: row; + flex: 1; + margin: 1.5px 0; + } - .content-column { - display: flex; - flex: 1; - } + .content-column { + display: flex; + flex: 1; + } - .content-data-name { - display: flex; - flex: 1; - align-items: center; + .content-data-name { + display: flex; + flex: 1; + align-items: center; - font-size: 18px; - } + font-size: 18px; + } - .content-data-value { - display: flex; - flex: 1; - align-items: center; + .content-data-value { + display: flex; + flex: 1; + align-items: center; - font-size: 18px; - } + font-size: 18px; + } - .content-divider { - margin: 5px 0px; - } + .content-divider { + margin: 5px 0; + } - .content-input-field { - width: 50% !important; - margin: 0 !important; - } + .content-input-field { + width: 50% !important; + margin: 0 !important; + } } footer { - width: 100%; - height: $footerHeight; - padding: 0px 10px; + width: 100%; + height: $footerHeight; + padding: 0 10px; + + display: flex; + align-items: center; + justify-content: center; + + .left { + width: 50%; display: flex; - align-items: center; - justify-content: center; - .left { - width: 50%; + // .frontend-version { + // } - display: flex; - - // .frontend-version { - // } - - .version-divider { - margin: 0px 5px; - } - - // .backend-version { - // } + .version-divider { + margin: 0 5px; } - .right { - width: 50%; - text-align: right; - } + // .backend-version { + // } + } + + .right { + width: 50%; + text-align: right; + } } .login-wrapper { - width: 100vw; - height: 100vh; + width: 100vw; + height: 100vh; + + display: flex; + justify-content: center; + align-items: center; + flex-direction: column; + gap: 15px; + + .login-form-wrapper, + .auth-header { + width: 350px; + height: 450px; display: flex; justify-content: center; align-items: center; - flex-direction: column; - gap: 15px; - .login-form-wrapper, - .auth-header { - width: 350px; - height: 450px; + border-radius: 25px; - display: flex; - justify-content: center; - align-items: center; + .login-form { + width: 80%; + height: 80%; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; - border-radius: 25px; + h1 { + text-align: center; + } - .login-form { - width: 80%; - height: 80%; - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; + .input-field-info-text { + margin: 15px 0; + width: 100%; + } - h1 { - text-align: center; - } - - .input-field-info-text { - margin: 15px 0px; - width: 100%; - } - - .login-form-submit { - .login-form-submit-btn { - width: 100%; - } - } - - .login-form-sub-button-wrapper { - display: flex; - flex-direction: column; - - .login-form-sub-btn { - margin-top: 15px; - width: 100%; - } - - .login-form-sub-btn-wrapper { - width: 100%; - } - } + .login-form-submit { + .login-form-submit-btn { + width: 100%; } - } + } - .register-form-wrapper { - height: 600px; - } + .login-form-sub-button-wrapper { + display: flex; + flex-direction: column; - .register-confirm-form-wrapper { - height: 250px; - } + .login-form-sub-btn { + margin-top: 15px; + width: 100%; + } - .auth-header { - width: 350px; - height: 75px; + .login-form-sub-btn-wrapper { + width: 100%; + } + } } + } + + .register-form-wrapper { + height: 600px; + } + + .register-confirm-form-wrapper { + height: 250px; + } + + .auth-header { + width: 350px; + height: 75px; + } } .input-field { - margin: 15px 0px; + margin: 15px 0; - input, - .p-password { - height: 40px; - width: 100%; - font-size: 18px; - } + input, + .p-password { + height: 40px; + width: 100%; + font-size: 18px; + } } .btn { - border: 0; + border: 0; } .spinner-component-wrapper { - position: absolute; - top: 0; - width: 100vw; - height: 100vh; + position: absolute; + top: 0; + width: 100vw; + height: 100vh; + display: flex; + flex-direction: row; + justify-content: center; + + .spinner-wrapper { display: flex; - flex-direction: row; justify-content: center; - - .spinner-wrapper { - display: flex; - justify-content: center; - align-items: center; - } + align-items: center; + } } diff --git a/kdb-web/src/styles/primeng-fixes.scss b/kdb-web/src/styles/primeng-fixes.scss index 7361d673..dccf88d9 100644 --- a/kdb-web/src/styles/primeng-fixes.scss +++ b/kdb-web/src/styles/primeng-fixes.scss @@ -11,15 +11,15 @@ background: none !important; border: none !important; width: auto !important; - border-radius: 0px !important; + border-radius: 0 !important; padding: 0 !important; .p-menuitem-link, .p-panelmenu-header > a, .p-panelmenu-content .p-menuitem .p-menuitem-link { $distance: 10px; - padding: $distance 0px $distance $distance !important; - margin: 4px 0px 4px 6px !important; + padding: $distance 0 $distance $distance !important; + margin: 4px 0 4px 6px !important; } } @@ -44,8 +44,8 @@ header, .p-panelmenu-header > a { border: none !important; - border-radius: none !important; - font-weight: none !important; + border-radius: unset !important; + font-weight: unset !important; transition: none !important; } @@ -71,8 +71,12 @@ ui-menu .ui-menu-parent .ui-menu-child { box-shadow: none !important; } +.p-datatable > .p-datatable-wrapper { + overflow: visible !important; +} + .p-password { - padding: 0px !important; + padding: 0 !important; } .p-paginator { diff --git a/kdb-web/src/styles/themes/default-dark-theme.scss b/kdb-web/src/styles/themes/default-dark-theme.scss index 9f0e2f6e..f0a7658b 100644 --- a/kdb-web/src/styles/themes/default-dark-theme.scss +++ b/kdb-web/src/styles/themes/default-dark-theme.scss @@ -1,558 +1,583 @@ .default-dark-theme { - $primaryTextColor: #fff; - $secondayTextColor: #000; - $secondayTextColor2: #1e88e5; + $primaryTextColor: #fff; + $secondayTextColor: #000; + $secondayTextColor2: #1e88e5; - $primaryHeaderColor: #1e88e5; - $secondaryHeaderColor: #6ab7ff; - $secondaryHeaderColor2: #005cb2; + $primaryHeaderColor: #1e88e5; + $secondaryHeaderColor: #6ab7ff; + $secondaryHeaderColor2: #005cb2; - $primaryBackgroundColor: #272727; - $secondaryBackgroundColor: #4f4f4f; - $secondaryBackgroundColor2: #fff; - $secondaryBackgroundColor3: #cccccc; + $primaryBackgroundColor: #272727; + $secondaryBackgroundColor: #4f4f4f; + $secondaryBackgroundColor2: #fff; + $secondaryBackgroundColor3: #cccccc; - $primaryErrorColor: #b00020; - $secondaryErrorColor: #e94948; + $primaryErrorColor: #b00020; + $secondaryErrorColor: #e94948; - $default-border: 2px solid $secondaryBackgroundColor3; + $default-border: 2px solid $secondaryBackgroundColor3; + background-color: $primaryBackgroundColor; + + h1, + h2 { + color: $primaryHeaderColor; + } + + input, + p { + color: $primaryTextColor; + } + + input { + background-color: $secondaryBackgroundColor !important; + } + + .input-field-info-text { + color: $primaryTextColor; + } + + /* Change Autocomplete styles in Chrome*/ + input:-webkit-autofill, + input:-webkit-autofill:hover, + input:-webkit-autofill:focus, + textarea:-webkit-autofill, + textarea:-webkit-autofill:hover, + textarea:-webkit-autofill:focus, + select:-webkit-autofill, + select:-webkit-autofill:hover, + select:-webkit-autofill:focus { + border: 1px solid $primaryHeaderColor; + -webkit-text-fill-color: $primaryTextColor; + -webkit-box-shadow: 0 0 0 1000px $secondaryBackgroundColor inset; + transition: background-color 5000s ease-in-out 0s; + } + + header { background-color: $primaryBackgroundColor; - h1, - h2 { - color: $primaryHeaderColor; - } - - input, - p { - color: $primaryTextColor; - } - - input { - background-color: $secondaryBackgroundColor !important; - } - - .input-field-info-text { - color: $primaryTextColor; - } - - /* Change Autocomplete styles in Chrome*/ - input:-webkit-autofill, - input:-webkit-autofill:hover, - input:-webkit-autofill:focus, - textarea:-webkit-autofill, - textarea:-webkit-autofill:hover, - textarea:-webkit-autofill:focus, - select:-webkit-autofill, - select:-webkit-autofill:hover, - select:-webkit-autofill:focus { - border: 1px solid $primaryHeaderColor; - -webkit-text-fill-color: $primaryTextColor; - -webkit-box-shadow: 0 0 0px 1000px $secondaryBackgroundColor inset; - transition: background-color 5000s ease-in-out 0s; - } - - header { - background-color: $primaryBackgroundColor; - - .logo-button-wrapper { - .p-button.p-button-text { - color: $primaryTextColor; - - &:hover { - color: $primaryTextColor; - background-color: $primaryBackgroundColor; - } - } - } - - .logo { - color: $primaryHeaderColor; - } - } - - h1 { - color: $primaryHeaderColor; - } - - .app { - .sidebar { - background-color: $primaryBackgroundColor; - - .menu { - color: $primaryTextColor; - } - } - - .component-wrapper { - color: $primaryTextColor; - - .component { - background-color: $secondaryBackgroundColor; - - .content-wrapper { - background-color: $primaryBackgroundColor; - border-top: 2px solid $primaryHeaderColor; - - .content-header { - border-bottom: $default-border; - } - - .content { - .content-row { - } - - .content-column { - } - - .content-data-name { - } - - .content-data-value { - } - - .content-divider { - border-bottom: $default-border; - } - - .server-list-wrapper { - .server-filter { - } - - .server-count { - } - - .server-list { - .server { - border: $default-border; - border-radius: 15px; - - .logo { - img { - border-radius: 100%; - } - } - - .name { - color: $primaryHeaderColor; - } - - &:hover { - border-color: $primaryHeaderColor !important; - } - } - } - } - } - } - } - } - } - - .p-dialog-header { - background-color: $secondaryBackgroundColor !important; - color: $primaryTextColor !important; - } - - .p-dialog-content { - .content-data-name, - .content-data-value { - color: $primaryTextColor; - - .text-btn { - font-size: 18px !important; - font-weight: 400 !important; - } - } - } - - footer { - background-color: $primaryBackgroundColor; + .logo-button-wrapper { + .p-button.p-button-text { color: $primaryTextColor; - a { - color: $primaryTextColor; + &:hover { + color: $primaryTextColor; + background-color: $primaryBackgroundColor; } + } } - .invalid-feedback { - color: $primaryErrorColor; + .logo { + color: $primaryHeaderColor; + } + } + + h1 { + color: $primaryHeaderColor; + } + + .app { + .sidebar { + background-color: $primaryBackgroundColor; + + .menu { + color: $primaryTextColor; + } } - .invalid-feedback-input, - .invalid-feedback-input:focus, - .invalid-feedback-input:hover { - input, - input:enabled:focus { - outline: 1px solid $primaryErrorColor !important; - border: 1px solid $primaryErrorColor !important; - border-color: $primaryErrorColor !important; - } - } + .component-wrapper { + color: $primaryTextColor; - .login-wrapper { + .component { background-color: $secondaryBackgroundColor; - .login-form-wrapper, - .auth-header { - background-color: $primaryBackgroundColor; + .content-wrapper { + background-color: $primaryBackgroundColor; + border-top: 2px solid $primaryHeaderColor; - .login-form { - .input-field { - input, - .p-password { - } - } + .content-header { + border-bottom: $default-border; + } - .login-form-submit { - .login-form-submit-btn { - } - } - - .login-form-sub-button-wrapper { - .login-form-sub-btn { - background-color: $primaryBackgroundColor; - color: $secondayTextColor2; - border: 2px solid $secondayTextColor2; - - &:hover { - background-color: $primaryHeaderColor !important; - color: $primaryTextColor !important; - } - } - - .login-form-sub-login-btn { - border: none; - } - } + .content { + .content-row { } - } - } - .spinner-component-wrapper { - background-color: rgba($secondaryBackgroundColor, 0.5); + .content-column { + } - .spinner-wrapper { - .custom-spinner .p-progress-spinner-circle { + .content-data-name { + } + + .content-data-value { + } + + .content-divider { + border-bottom: $default-border; + } + + .server-list-wrapper { + .server-filter { + } + + .server-count { + } + + .server-list { + .server { + border: $default-border; + border-radius: 15px; + + .logo { + img { + border-radius: 100%; + } + } + + .name { + color: $primaryHeaderColor; + } + + &:hover { + border-color: $primaryHeaderColor !important; + } + } + } + } + + p-panel { + .p-panel-header, + .p-panel-content { + border: $default-border; + } + + .p-panel-title { color: $primaryHeaderColor; - } - } - } + } - .wrapper-right { - justify-content: flex-end !important; - } + .p-panel-header { + background-color: $primaryBackgroundColor; - /* - PrimeNG Fixes - */ - .p-progress-spinner-circle { - stroke: $primaryHeaderColor !important; - } - - .p-menu, - .p-panelmenu { - color: $primaryTextColor !important; - - .p-menuitem-link .p-menuitem-text, - .p-menuitem-link .p-menuitem-icon, - .p-panelmenu-header > a { - color: $primaryTextColor !important; - background: transparent !important; - font-size: 1rem !important; - font-weight: normal !important; - } - - .p-menuitem-link:focus, - .p-panelmenu-header > a:focus, - .p-panelmenu-content .p-menuitem .p-menuitem-link:focus { - box-shadow: none !important; - } - - .p-menuitem-link:hover, - .p-panelmenu-header > a:hover, - .p-panelmenu-content .p-menuitem .p-menuitem-link:hover { - background-color: $secondaryBackgroundColor !important; - $border-radius: 20px; - border-radius: $border-radius 0px 0px $border-radius; - - .p-menuitem-text, - .p-menuitem-icon, - .p-menuitem-text, - .p-panelmenu-icon { - color: $primaryHeaderColor !important; - } - } - - .p-panelmenu-content { - margin: 5px 0px 5px 10px; - } - } - - .p-menu-overlay { - background-color: $primaryBackgroundColor !important; - color: $primaryTextColor !important; - border-top: 2px solid $primaryHeaderColor !important; - - .p-menuitem-link:hover { - background-color: $primaryBackgroundColor !important; - .p-menuitem-text, - .p-menuitem-icon { - color: $primaryHeaderColor !important; - } - } - } - - p-dropdown { - .p-dropdown { - background-color: $primaryBackgroundColor !important; - border-color: $primaryTextColor !important; - color: $primaryTextColor !important; - - span { - color: $primaryTextColor; - } - - .p-dropdown-panel { - background-color: $secondaryBackgroundColor !important; - - .p-dropdown-items .p-dropdown-item:not(.p-highlight):not(.p-disabled):hover { - background-color: $secondaryBackgroundColor !important; - color: $primaryHeaderColor !important; - - span { - color: $primaryHeaderColor !important; - } - } - - .p-dropdown-items .p-dropdown-item.p-highlight { - background-color: $secondaryBackgroundColor !important; - color: $primaryHeaderColor !important; - - span { - color: $primaryHeaderColor !important; - } + .p-panel-header-icon { + color: $primaryHeaderColor; } + } } + + .p-panel-content { + background-color: $primaryBackgroundColor; + color: $primaryTextColor; + border-top: none !important; + } + } } + } } + } - p-table { - background-color: $primaryBackgroundColor; - color: $primaryTextColor !important; + .p-dialog-header { + background-color: $secondaryBackgroundColor !important; + color: $primaryTextColor !important; + } - .table-caption { - .table-caption-text { - } + .p-dialog-content { + .content-data-name, + .content-data-value { + color: $primaryTextColor; - .table-caption-search-wrapper { - .table-caption-search { - height: 30px !important; - - .table-caption-search-icon { - } - - .table-caption-search-input { - height: 100% !important; - - &:focus { - outline-color: $primaryHeaderColor; - } - } - } - } - - .table-caption-btn-wrapper { - height: 30px !important; - } - } - - .table-edit-input { - width: 100% !important; - } + .text-btn { + font-size: 18px !important; + font-weight: 400 !important; + } } + } - p-checkbox { - .p-checkbox .p-checkbox-box { - background: $primaryBackgroundColor !important; - background-color: $primaryBackgroundColor !important; - } + footer { + background-color: $primaryBackgroundColor; + color: $primaryTextColor; - .p-checkbox .p-checkbox-box.p-highlight { - background: $primaryBackgroundColor !important; - background-color: $primaryBackgroundColor !important; - border-color: $primaryTextColor !important; - box-shadow: none !important; - } - - .p-checkbox .p-checkbox-box .p-checkbox-icon { - color: $primaryTextColor !important; - } - - .p-checkbox:not(.p-checkbox-disabled) .p-checkbox-box.p-focus, - .p-checkbox:not(.p-checkbox-disabled) .p-checkbox-box:hover { - border-color: $primaryHeaderColor !important; - box-shadow: none !important; - - .p-checkbox-icon { - color: $primaryHeaderColor !important; - } - } + a { + color: $primaryTextColor; } + } - p-dialog, - p-confirmdialog, - p-dynamicdialog { - .p-dialog.p-confirm-dialog .p-confirm-dialog-message { - margin-left: 0px !important; - } - - .p-dialog { - background-color: $secondaryBackgroundColor !important; - - .p-dialog-header { - background-color: $primaryBackgroundColor !important; - color: $primaryTextColor !important; - } - - .p-dialog-content, - .p-dialog-footer { - background-color: $secondaryBackgroundColor !important; - color: $primaryTextColor !important; - } - } - } + .invalid-feedback { + color: $primaryErrorColor; + } + .invalid-feedback-input, + .invalid-feedback-input:focus, + .invalid-feedback-input:hover { input, - .p-password input { - border-radius: 10px; - border: $default-border; + input:enabled:focus { + outline: 1px solid $primaryErrorColor !important; + border: 1px solid $primaryErrorColor !important; + border-color: $primaryErrorColor !important; + } + } - &:focus { - box-shadow: none !important; + .login-wrapper { + background-color: $secondaryBackgroundColor; + + .login-form-wrapper, + .auth-header { + background-color: $primaryBackgroundColor; + + .login-form { + .input-field { + input, + .p-password { + } } - &:hover, - &:active, - &:enabled:focus { - border-color: $primaryHeaderColor !important; + .login-form-submit { + .login-form-submit-btn { + } } + + .login-form-sub-button-wrapper { + .login-form-sub-btn { + background-color: $primaryBackgroundColor; + color: $secondayTextColor2; + border: 2px solid $secondayTextColor2; + + &:hover { + background-color: $primaryHeaderColor !important; + color: $primaryTextColor !important; + } + } + + .login-form-sub-login-btn { + border: none; + } + } + } + } + } + + .spinner-component-wrapper { + background-color: rgba($secondaryBackgroundColor, 0.5); + + .spinner-wrapper { + .custom-spinner .p-progress-spinner-circle { + color: $primaryHeaderColor; + } + } + } + + .wrapper-right { + justify-content: flex-end !important; + } + + /* + PrimeNG Fixes + */ + .p-progress-spinner-circle { + stroke: $primaryHeaderColor !important; + } + + .p-menu, + .p-panelmenu { + color: $primaryTextColor !important; + + .p-menuitem-link .p-menuitem-text, + .p-menuitem-link .p-menuitem-icon, + .p-panelmenu-header > a { + color: $primaryTextColor !important; + background: transparent !important; + font-size: 1rem !important; + font-weight: normal !important; } - .btn-wrapper { - display: flex !important; - align-items: center !important; + .p-menuitem-link:focus, + .p-panelmenu-header > a:focus, + .p-panelmenu-content .p-menuitem .p-menuitem-link:focus { + box-shadow: none !important; } - .btn { - background-color: $primaryHeaderColor; + .p-menuitem-link:hover, + .p-panelmenu-header > a:hover, + .p-panelmenu-content .p-menuitem .p-menuitem-link:hover { + background-color: $secondaryBackgroundColor !important; + $border-radius: 20px; + border-radius: $border-radius 0 0 $border-radius; + + .p-menuitem-text, + .p-menuitem-icon, + .p-menuitem-text, + .p-panelmenu-icon { + color: $primaryHeaderColor !important; + } + } + + .p-panelmenu-content { + margin: 5px 0 5px 10px; + } + } + + .p-menu-overlay { + background-color: $primaryBackgroundColor !important; + color: $primaryTextColor !important; + border-top: 2px solid $primaryHeaderColor !important; + + .p-menuitem-link:hover { + background-color: $primaryBackgroundColor !important; + + .p-menuitem-text, + .p-menuitem-icon { + color: $primaryHeaderColor !important; + } + } + } + + p-dropdown { + .p-dropdown { + background-color: $primaryBackgroundColor !important; + border-color: $primaryTextColor !important; + color: $primaryTextColor !important; + + span { color: $primaryTextColor; - border: 0; + } - &:hover, - &:enabled:hover { - background-color: $primaryHeaderColor; - color: $primaryTextColor; - border: 0; - } - } + .p-dropdown-panel { + background-color: $secondaryBackgroundColor !important; - .icon-btn { - background-color: transparent !important; - color: $primaryTextColor !important; - border: 0 !important; + .p-dropdown-items .p-dropdown-item:not(.p-highlight):not(.p-disabled):hover { + background-color: $secondaryBackgroundColor !important; + color: $primaryHeaderColor !important; - .pi { - font-size: 1.275rem !important; - } - } - - .text-btn { - background-color: transparent !important; - color: $primaryTextColor !important; - border: 0 !important; - padding: 0px !important; - - &:hover { - background-color: transparent !important; + span { color: $primaryHeaderColor !important; - border: 0; + } } - } - .icon-btn-without-hover { - &:hover { - background-color: transparent !important; - color: $primaryTextColor !important; - border: 0 !important; - } - } + .p-dropdown-items .p-dropdown-item.p-highlight { + background-color: $secondaryBackgroundColor !important; + color: $primaryHeaderColor !important; - .icon-btn { - &:hover { - background-color: transparent !important; + span { color: $primaryHeaderColor !important; - border: 0; + } } + } + } + } + + p-table { + background-color: $primaryBackgroundColor; + color: $primaryTextColor !important; + + .table-caption { + .table-caption-text { + } + + .table-caption-search-wrapper { + .table-caption-search { + height: 30px !important; + + .table-caption-search-icon { + } + + .table-caption-search-input { + height: 100% !important; + + &:focus { + outline-color: $primaryHeaderColor; + } + } + } + } + + .table-caption-btn-wrapper { + height: 30px !important; + } } - .danger-icon-btn { - background-color: transparent !important; - color: $primaryTextColor !important; - border: 0 !important; + .table-edit-input { + width: 100% !important; + } + } - &:hover { - background-color: transparent !important; - color: $primaryErrorColor !important; - border: 0; - } - - .pi { - font-size: 1.275rem !important; - } + p-checkbox { + .p-checkbox .p-checkbox-box { + background: $primaryBackgroundColor !important; + background-color: $primaryBackgroundColor !important; } - .danger-btn { - background-color: $primaryErrorColor !important; - color: $primaryErrorColor !important; - border: 0 !important; - - &:hover { - background-color: $primaryErrorColor !important; - color: $primaryTextColor !important; - border: 0; - } - - .pi { - font-size: 1.275rem !important; - } + .p-checkbox .p-checkbox-box.p-highlight { + background: $primaryBackgroundColor !important; + background-color: $primaryBackgroundColor !important; + border-color: $primaryTextColor !important; + box-shadow: none !important; } - .p-datatable .p-sortable-column.p-highlight, - .p-datatable .p-sortable-column.p-highlight .p-sortable-column-icon { + .p-checkbox .p-checkbox-box .p-checkbox-icon { + color: $primaryTextColor !important; + } + + .p-checkbox:not(.p-checkbox-disabled) .p-checkbox-box.p-focus, + .p-checkbox:not(.p-checkbox-disabled) .p-checkbox-box:hover { + border-color: $primaryHeaderColor !important; + box-shadow: none !important; + + .p-checkbox-icon { color: $primaryHeaderColor !important; + } + } + } + + p-dialog, + p-confirmdialog, + p-dynamicdialog { + .p-dialog.p-confirm-dialog .p-confirm-dialog-message { + margin-left: 0 !important; } - .p-dropdown:not(.p-disabled):hover, - .p-dropdown:not(.p-disabled).p-focus, - .p-link:focus { - border-color: $primaryHeaderColor !important; - box-shadow: none !important; - } + .p-dialog { + background-color: $secondaryBackgroundColor !important; - .p-paginator .p-paginator-pages .p-paginator-page.p-highlight { - background: transparent !important; - background-color: transparent !important; - color: $primaryHeaderColor !important; - } - - .p-paginator .p-paginator-pages .p-paginator-page:not(.p-highlight):hover, - .p-paginator .p-paginator-first:not(.p-disabled):not(.p-highlight):hover, - .p-paginator .p-paginator-prev:not(.p-disabled):not(.p-highlight):hover, - .p-paginator .p-paginator-next:not(.p-disabled):not(.p-highlight):hover, - .p-paginator .p-paginator-last:not(.p-disabled):not(.p-highlight):hover { + .p-dialog-header { background-color: $primaryBackgroundColor !important; - color: $primaryHeaderColor !important; + color: $primaryTextColor !important; + } + + .p-dialog-content, + .p-dialog-footer { + background-color: $secondaryBackgroundColor !important; + color: $primaryTextColor !important; + } } + } + + input, + .p-password input { + border-radius: 10px; + border: $default-border; + + &:focus { + box-shadow: none !important; + } + + &:hover, + &:active, + &:enabled:focus { + border-color: $primaryHeaderColor !important; + } + } + + .btn-wrapper { + display: flex !important; + align-items: center !important; + } + + .btn { + background-color: $primaryHeaderColor; + color: $primaryTextColor; + border: 0; + + &:hover, + &:enabled:hover { + background-color: $primaryHeaderColor; + color: $primaryTextColor; + border: 0; + } + } + + .icon-btn { + background-color: transparent !important; + color: $primaryTextColor !important; + border: 0 !important; + + .pi { + font-size: 1.275rem !important; + } + } + + .text-btn { + background-color: transparent !important; + color: $primaryTextColor !important; + border: 0 !important; + padding: 0 !important; + + &:hover { + background-color: transparent !important; + color: $primaryHeaderColor !important; + border: 0; + } + } + + .icon-btn-without-hover { + &:hover { + background-color: transparent !important; + color: $primaryTextColor !important; + border: 0 !important; + } + } + + .icon-btn { + &:hover { + background-color: transparent !important; + color: $primaryHeaderColor !important; + border: 0; + } + } + + .danger-icon-btn { + background-color: transparent !important; + color: $primaryTextColor !important; + border: 0 !important; + + &:hover { + background-color: transparent !important; + color: $primaryErrorColor !important; + border: 0; + } + + .pi { + font-size: 1.275rem !important; + } + } + + .danger-btn { + background-color: $primaryErrorColor !important; + color: $primaryErrorColor !important; + border: 0 !important; + + &:hover { + background-color: $primaryErrorColor !important; + color: $primaryTextColor !important; + border: 0; + } + + .pi { + font-size: 1.275rem !important; + } + } + + .p-datatable .p-sortable-column.p-highlight, + .p-datatable .p-sortable-column.p-highlight .p-sortable-column-icon { + color: $primaryHeaderColor !important; + } + + .p-dropdown:not(.p-disabled):hover, + .p-dropdown:not(.p-disabled).p-focus, + .p-link:focus { + border-color: $primaryHeaderColor !important; + box-shadow: none !important; + } + + .p-paginator .p-paginator-pages .p-paginator-page.p-highlight { + background: transparent !important; + color: $primaryHeaderColor !important; + } + + .p-paginator .p-paginator-pages .p-paginator-page:not(.p-highlight):hover, + .p-paginator .p-paginator-first:not(.p-disabled):not(.p-highlight):hover, + .p-paginator .p-paginator-prev:not(.p-disabled):not(.p-highlight):hover, + .p-paginator .p-paginator-next:not(.p-disabled):not(.p-highlight):hover, + .p-paginator .p-paginator-last:not(.p-disabled):not(.p-highlight):hover { + background-color: $primaryBackgroundColor !important; + color: $primaryHeaderColor !important; + } } diff --git a/kdb-web/src/styles/themes/default-light-theme.scss b/kdb-web/src/styles/themes/default-light-theme.scss index 69a1b97d..4c37c304 100644 --- a/kdb-web/src/styles/themes/default-light-theme.scss +++ b/kdb-web/src/styles/themes/default-light-theme.scss @@ -1,558 +1,583 @@ .default-light-theme { - $primaryTextColor: #272727; - $secondayTextColor: #fff; - $secondayTextColor2: #1e88e5; + $primaryTextColor: #272727; + $secondayTextColor: #fff; + $secondayTextColor2: #1e88e5; - $primaryHeaderColor: #1e88e5; - $secondaryHeaderColor: #6ab7ff; - $secondaryHeaderColor2: #005cb2; + $primaryHeaderColor: #1e88e5; + $secondaryHeaderColor: #6ab7ff; + $secondaryHeaderColor2: #005cb2; - $primaryBackgroundColor: #fff; - $secondaryBackgroundColor: #cccccc; - $secondaryBackgroundColor2: #4f4f4f; - $secondaryBackgroundColor3: #272727; + $primaryBackgroundColor: #fff; + $secondaryBackgroundColor: #cccccc; + $secondaryBackgroundColor2: #4f4f4f; + $secondaryBackgroundColor3: #272727; - $primaryErrorColor: #b00020; - $secondaryErrorColor: #e94948; + $primaryErrorColor: #b00020; + $secondaryErrorColor: #e94948; - $default-border: 2px solid $secondaryBackgroundColor; + $default-border: 2px solid $secondaryBackgroundColor; + background-color: $primaryBackgroundColor; + + h1, + h2 { + color: $primaryHeaderColor; + } + + input, + p { + color: $primaryTextColor; + } + + input { + background-color: $primaryBackgroundColor !important; + } + + .input-field-info-text { + color: $primaryTextColor; + } + + /* Change Autocomplete styles in Chrome*/ + input:-webkit-autofill, + input:-webkit-autofill:hover, + input:-webkit-autofill:focus, + textarea:-webkit-autofill, + textarea:-webkit-autofill:hover, + textarea:-webkit-autofill:focus, + select:-webkit-autofill, + select:-webkit-autofill:hover, + select:-webkit-autofill:focus { + border: 1px solid $primaryHeaderColor; + -webkit-text-fill-color: $primaryTextColor; + -webkit-box-shadow: 0 0 0 1000px $primaryBackgroundColor inset; + transition: background-color 5000s ease-in-out 0s; + } + + header { background-color: $primaryBackgroundColor; - h1, - h2 { - color: $primaryHeaderColor; - } - - input, - p { - color: $primaryTextColor; - } - - input { - background-color: $primaryBackgroundColor !important; - } - - .input-field-info-text { - color: $primaryTextColor; - } - - /* Change Autocomplete styles in Chrome*/ - input:-webkit-autofill, - input:-webkit-autofill:hover, - input:-webkit-autofill:focus, - textarea:-webkit-autofill, - textarea:-webkit-autofill:hover, - textarea:-webkit-autofill:focus, - select:-webkit-autofill, - select:-webkit-autofill:hover, - select:-webkit-autofill:focus { - border: 1px solid $primaryHeaderColor; - -webkit-text-fill-color: $primaryTextColor; - -webkit-box-shadow: 0 0 0px 1000px $primaryBackgroundColor inset; - transition: background-color 5000s ease-in-out 0s; - } - - header { - background-color: $primaryBackgroundColor; - - .logo-button-wrapper { - .p-button.p-button-text { - color: $primaryTextColor; - - &:hover { - color: $primaryTextColor; - background-color: $primaryBackgroundColor; - } - } - } - - .logo { - color: $primaryHeaderColor; - } - } - - h1 { - color: $primaryHeaderColor; - } - - .app { - .sidebar { - background-color: $primaryBackgroundColor; - - .menu { - color: $primaryTextColor; - } - } - - .component-wrapper { - color: $primaryTextColor; - - .component { - background-color: $secondaryBackgroundColor; - - .content-wrapper { - background-color: $primaryBackgroundColor; - border-top: 2px solid $primaryHeaderColor; - - .content-header { - border-bottom: $default-border; - } - - .content { - .content-row { - } - - .content-column { - } - - .content-data-name { - } - - .content-data-value { - } - - .content-divider { - border-bottom: $default-border; - } - - .server-list-wrapper { - .server-filter { - } - - .server-count { - } - - .server-list { - .server { - border: $default-border; - border-radius: 15px; - - .logo { - img { - border-radius: 100%; - } - } - - .name { - color: $primaryHeaderColor; - } - - &:hover { - border-color: $primaryHeaderColor !important; - } - } - } - } - } - } - } - } - } - - .p-dialog-header { - background-color: $secondaryBackgroundColor !important; - color: $primaryTextColor !important; - } - - .p-dialog-content { - .content-data-name, - .content-data-value { - color: $primaryTextColor; - - .text-btn { - font-size: 18px !important; - font-weight: 400 !important; - } - } - } - - footer { - background-color: $primaryBackgroundColor; + .logo-button-wrapper { + .p-button.p-button-text { color: $primaryTextColor; - a { - color: $primaryTextColor; + &:hover { + color: $primaryTextColor; + background-color: $primaryBackgroundColor; } + } } - .invalid-feedback { - color: $primaryErrorColor; + .logo { + color: $primaryHeaderColor; + } + } + + h1 { + color: $primaryHeaderColor; + } + + .app { + .sidebar { + background-color: $primaryBackgroundColor; + + .menu { + color: $primaryTextColor; + } } - .invalid-feedback-input, - .invalid-feedback-input:focus, - .invalid-feedback-input:hover { - input, - input:enabled:focus { - outline: 1px solid $primaryErrorColor !important; - border: 1px solid $primaryErrorColor !important; - border-color: $primaryErrorColor !important; - } - } + .component-wrapper { + color: $primaryTextColor; - .login-wrapper { + .component { background-color: $secondaryBackgroundColor; - .login-form-wrapper, - .auth-header { - background-color: $primaryBackgroundColor; + .content-wrapper { + background-color: $primaryBackgroundColor; + border-top: 2px solid $primaryHeaderColor; - .login-form { - .input-field { - input, - .p-password { - } - } + .content-header { + border-bottom: $default-border; + } - .login-form-submit { - .login-form-submit-btn { - } - } - - .login-form-sub-button-wrapper { - .login-form-sub-btn { - background-color: $primaryBackgroundColor; - color: $secondayTextColor2; - border: 2px solid $secondayTextColor2; - - &:hover { - background-color: $primaryHeaderColor !important; - color: $primaryTextColor !important; - } - } - - .login-form-sub-login-btn { - border: none; - } - } + .content { + .content-row { } - } - } - .spinner-component-wrapper { - background-color: rgba($secondaryBackgroundColor, 0.5); + .content-column { + } - .spinner-wrapper { - .custom-spinner .p-progress-spinner-circle { + .content-data-name { + } + + .content-data-value { + } + + .content-divider { + border-bottom: $default-border; + } + + .server-list-wrapper { + .server-filter { + } + + .server-count { + } + + .server-list { + .server { + border: $default-border; + border-radius: 15px; + + .logo { + img { + border-radius: 100%; + } + } + + .name { + color: $primaryHeaderColor; + } + + &:hover { + border-color: $primaryHeaderColor !important; + } + } + } + } + + p-panel { + .p-panel-header, + .p-panel-content { + border: $default-border; + } + + .p-panel-title { color: $primaryHeaderColor; - } - } - } + } - .wrapper-right { - justify-content: flex-end !important; - } + .p-panel-header { + background-color: $primaryBackgroundColor; - /* - PrimeNG Fixes - */ - .p-progress-spinner-circle { - stroke: $primaryHeaderColor !important; - } - - .p-menu, - .p-panelmenu { - color: $primaryTextColor !important; - - .p-menuitem-link .p-menuitem-text, - .p-menuitem-link .p-menuitem-icon, - .p-panelmenu-header > a { - color: $primaryTextColor !important; - background: transparent !important; - font-size: 1rem !important; - font-weight: normal !important; - } - - .p-menuitem-link:focus, - .p-panelmenu-header > a:focus, - .p-panelmenu-content .p-menuitem .p-menuitem-link:focus { - box-shadow: none !important; - } - - .p-menuitem-link:hover, - .p-panelmenu-header > a:hover, - .p-panelmenu-content .p-menuitem .p-menuitem-link:hover { - background-color: $secondaryBackgroundColor !important; - $border-radius: 20px; - border-radius: $border-radius 0px 0px $border-radius; - - .p-menuitem-text, - .p-menuitem-icon, - .p-menuitem-text, - .p-panelmenu-icon { - color: $primaryHeaderColor !important; - } - } - - .p-panelmenu-content { - margin: 5px 0px 5px 10px; - } - } - - .p-menu-overlay { - background-color: $primaryBackgroundColor !important; - color: $primaryTextColor !important; - border-top: 2px solid $primaryHeaderColor !important; - - .p-menuitem-link:hover { - background-color: $primaryBackgroundColor !important; - .p-menuitem-text, - .p-menuitem-icon { - color: $primaryHeaderColor !important; - } - } - } - - p-dropdown { - .p-dropdown { - background-color: $primaryBackgroundColor !important; - border-color: $primaryTextColor !important; - color: $primaryTextColor !important; - - span { - color: $primaryTextColor; - } - - .p-dropdown-panel { - background-color: $primaryBackgroundColor !important; - - .p-dropdown-items .p-dropdown-item:not(.p-highlight):not(.p-disabled):hover { - background-color: $primaryBackgroundColor !important; - color: $primaryHeaderColor !important; - - span { - color: $primaryHeaderColor !important; - } - } - - .p-dropdown-items .p-dropdown-item.p-highlight { - background-color: $primaryBackgroundColor !important; - color: $primaryHeaderColor !important; - - span { - color: $primaryHeaderColor !important; - } + .p-panel-header-icon { + color: $primaryHeaderColor; } + } } + + .p-panel-content { + background-color: $primaryBackgroundColor; + color: $primaryTextColor; + border-top: none !important; + } + } } + } } + } - p-table { - background-color: $primaryBackgroundColor; - color: $primaryTextColor !important; + .p-dialog-header { + background-color: $secondaryBackgroundColor !important; + color: $primaryTextColor !important; + } - .table-caption { - .table-caption-text { - } + .p-dialog-content { + .content-data-name, + .content-data-value { + color: $primaryTextColor; - .table-caption-search-wrapper { - .table-caption-search { - height: 30px !important; - - .table-caption-search-icon { - } - - .table-caption-search-input { - height: 100% !important; - - &:focus { - outline-color: $primaryHeaderColor; - } - } - } - } - - .table-caption-btn-wrapper { - height: 30px !important; - } - } - - .table-edit-input { - width: 100% !important; - } + .text-btn { + font-size: 18px !important; + font-weight: 400 !important; + } } + } - p-checkbox { - .p-checkbox .p-checkbox-box { - background: $primaryBackgroundColor !important; - background-color: $primaryBackgroundColor !important; - } + footer { + background-color: $primaryBackgroundColor; + color: $primaryTextColor; - .p-checkbox .p-checkbox-box.p-highlight { - background: $primaryBackgroundColor !important; - background-color: $primaryBackgroundColor !important; - border-color: $primaryTextColor !important; - box-shadow: none !important; - } - - .p-checkbox .p-checkbox-box .p-checkbox-icon { - color: $primaryTextColor !important; - } - - .p-checkbox:not(.p-checkbox-disabled) .p-checkbox-box.p-focus, - .p-checkbox:not(.p-checkbox-disabled) .p-checkbox-box:hover { - border-color: $primaryHeaderColor !important; - box-shadow: none !important; - - .p-checkbox-icon { - color: $primaryHeaderColor !important; - } - } + a { + color: $primaryTextColor; } + } - p-dialog, - p-confirmdialog, - p-dynamicdialog { - .p-dialog.p-confirm-dialog .p-confirm-dialog-message { - margin-left: 0px !important; - } - - .p-dialog { - background-color: $primaryBackgroundColor !important; - - .p-dialog-header { - background-color: $secondaryBackgroundColor !important; - color: $primaryTextColor !important; - } - - .p-dialog-content, - .p-dialog-footer { - background-color: $primaryBackgroundColor !important; - color: $primaryTextColor !important; - } - } - } + .invalid-feedback { + color: $primaryErrorColor; + } + .invalid-feedback-input, + .invalid-feedback-input:focus, + .invalid-feedback-input:hover { input, - .p-password input { - border-radius: 10px; - border: $default-border; + input:enabled:focus { + outline: 1px solid $primaryErrorColor !important; + border: 1px solid $primaryErrorColor !important; + border-color: $primaryErrorColor !important; + } + } - &:focus { - box-shadow: none !important; + .login-wrapper { + background-color: $secondaryBackgroundColor; + + .login-form-wrapper, + .auth-header { + background-color: $primaryBackgroundColor; + + .login-form { + .input-field { + input, + .p-password { + } } - &:hover, - &:active, - &:enabled:focus { - border-color: $primaryHeaderColor !important; + .login-form-submit { + .login-form-submit-btn { + } } + + .login-form-sub-button-wrapper { + .login-form-sub-btn { + background-color: $primaryBackgroundColor; + color: $secondayTextColor2; + border: 2px solid $secondayTextColor2; + + &:hover { + background-color: $primaryHeaderColor !important; + color: $primaryTextColor !important; + } + } + + .login-form-sub-login-btn { + border: none; + } + } + } + } + } + + .spinner-component-wrapper { + background-color: rgba($secondaryBackgroundColor, 0.5); + + .spinner-wrapper { + .custom-spinner .p-progress-spinner-circle { + color: $primaryHeaderColor; + } + } + } + + .wrapper-right { + justify-content: flex-end !important; + } + + /* + PrimeNG Fixes + */ + .p-progress-spinner-circle { + stroke: $primaryHeaderColor !important; + } + + .p-menu, + .p-panelmenu { + color: $primaryTextColor !important; + + .p-menuitem-link .p-menuitem-text, + .p-menuitem-link .p-menuitem-icon, + .p-panelmenu-header > a { + color: $primaryTextColor !important; + background: transparent !important; + font-size: 1rem !important; + font-weight: normal !important; } - .btn-wrapper { - display: flex !important; - align-items: center !important; + .p-menuitem-link:focus, + .p-panelmenu-header > a:focus, + .p-panelmenu-content .p-menuitem .p-menuitem-link:focus { + box-shadow: none !important; } - .btn { - background-color: $primaryHeaderColor; + .p-menuitem-link:hover, + .p-panelmenu-header > a:hover, + .p-panelmenu-content .p-menuitem .p-menuitem-link:hover { + background-color: $secondaryBackgroundColor !important; + $border-radius: 20px; + border-radius: $border-radius 0 0 $border-radius; + + .p-menuitem-text, + .p-menuitem-icon, + .p-menuitem-text, + .p-panelmenu-icon { + color: $primaryHeaderColor !important; + } + } + + .p-panelmenu-content { + margin: 5px 0 5px 10px; + } + } + + .p-menu-overlay { + background-color: $primaryBackgroundColor !important; + color: $primaryTextColor !important; + border-top: 2px solid $primaryHeaderColor !important; + + .p-menuitem-link:hover { + background-color: $primaryBackgroundColor !important; + + .p-menuitem-text, + .p-menuitem-icon { + color: $primaryHeaderColor !important; + } + } + } + + p-dropdown { + .p-dropdown { + background-color: $primaryBackgroundColor !important; + border-color: $primaryTextColor !important; + color: $primaryTextColor !important; + + span { color: $primaryTextColor; - border: 0; + } - &:hover, - &:enabled:hover { - background-color: $primaryHeaderColor; - color: $primaryTextColor; - border: 0; - } - } - - .icon-btn { - background-color: transparent !important; - color: $primaryTextColor !important; - border: 0 !important; - - .pi { - font-size: 1.275rem !important; - } - } - - .text-btn { - background-color: transparent !important; - color: $primaryTextColor !important; - border: 0 !important; - padding: 0px !important; - - &:hover { - background-color: transparent !important; - color: $primaryHeaderColor !important; - border: 0; - } - } - - .icon-btn-without-hover { - &:hover { - background-color: transparent !important; - color: $primaryTextColor !important; - border: 0 !important; - } - } - - .icon-btn { - &:hover { - background-color: transparent !important; - color: $primaryHeaderColor !important; - border: 0; - } - } - - .danger-icon-btn { - background-color: transparent !important; - color: $primaryTextColor !important; - border: 0 !important; - - &:hover { - background-color: transparent !important; - color: $primaryErrorColor !important; - border: 0; - } - - .pi { - font-size: 1.275rem !important; - } - } - - .danger-btn { - background-color: $primaryErrorColor !important; - color: $primaryErrorColor !important; - border: 0 !important; - - &:hover { - background-color: $primaryErrorColor !important; - color: $primaryTextColor !important; - border: 0; - } - - .pi { - font-size: 1.275rem !important; - } - } - - .p-datatable .p-sortable-column.p-highlight, - .p-datatable .p-sortable-column.p-highlight .p-sortable-column-icon { - color: $primaryHeaderColor !important; - } - - .p-dropdown:not(.p-disabled):hover, - .p-dropdown:not(.p-disabled).p-focus, - .p-link:focus { - border-color: $primaryHeaderColor !important; - box-shadow: none !important; - } - - .p-paginator .p-paginator-pages .p-paginator-page.p-highlight { - background: transparent !important; - background-color: transparent !important; - color: $primaryHeaderColor !important; - } - - .p-paginator .p-paginator-pages .p-paginator-page:not(.p-highlight):hover, - .p-paginator .p-paginator-first:not(.p-disabled):not(.p-highlight):hover, - .p-paginator .p-paginator-prev:not(.p-disabled):not(.p-highlight):hover, - .p-paginator .p-paginator-next:not(.p-disabled):not(.p-highlight):hover, - .p-paginator .p-paginator-last:not(.p-disabled):not(.p-highlight):hover { + .p-dropdown-panel { background-color: $primaryBackgroundColor !important; - color: $primaryHeaderColor !important; + + .p-dropdown-items .p-dropdown-item:not(.p-highlight):not(.p-disabled):hover { + background-color: $primaryBackgroundColor !important; + color: $primaryHeaderColor !important; + + span { + color: $primaryHeaderColor !important; + } + } + + .p-dropdown-items .p-dropdown-item.p-highlight { + background-color: $primaryBackgroundColor !important; + color: $primaryHeaderColor !important; + + span { + color: $primaryHeaderColor !important; + } + } + } } + } + + p-table { + background-color: $primaryBackgroundColor; + color: $primaryTextColor !important; + + .table-caption { + .table-caption-text { + } + + .table-caption-search-wrapper { + .table-caption-search { + height: 30px !important; + + .table-caption-search-icon { + } + + .table-caption-search-input { + height: 100% !important; + + &:focus { + outline-color: $primaryHeaderColor; + } + } + } + } + + .table-caption-btn-wrapper { + height: 30px !important; + } + } + + .table-edit-input { + width: 100% !important; + } + } + + p-checkbox { + .p-checkbox .p-checkbox-box { + background: $primaryBackgroundColor !important; + background-color: $primaryBackgroundColor !important; + } + + .p-checkbox .p-checkbox-box.p-highlight { + background: $primaryBackgroundColor !important; + background-color: $primaryBackgroundColor !important; + border-color: $primaryTextColor !important; + box-shadow: none !important; + } + + .p-checkbox .p-checkbox-box .p-checkbox-icon { + color: $primaryTextColor !important; + } + + .p-checkbox:not(.p-checkbox-disabled) .p-checkbox-box.p-focus, + .p-checkbox:not(.p-checkbox-disabled) .p-checkbox-box:hover { + border-color: $primaryHeaderColor !important; + box-shadow: none !important; + + .p-checkbox-icon { + color: $primaryHeaderColor !important; + } + } + } + + p-dialog, + p-confirmdialog, + p-dynamicdialog { + .p-dialog.p-confirm-dialog .p-confirm-dialog-message { + margin-left: 0 !important; + } + + .p-dialog { + background-color: $primaryBackgroundColor !important; + + .p-dialog-header { + background-color: $secondaryBackgroundColor !important; + color: $primaryTextColor !important; + } + + .p-dialog-content, + .p-dialog-footer { + background-color: $primaryBackgroundColor !important; + color: $primaryTextColor !important; + } + } + } + + input, + .p-password input { + border-radius: 10px; + border: $default-border; + + &:focus { + box-shadow: none !important; + } + + &:hover, + &:active, + &:enabled:focus { + border-color: $primaryHeaderColor !important; + } + } + + .btn-wrapper { + display: flex !important; + align-items: center !important; + } + + .btn { + background-color: $primaryHeaderColor; + color: $primaryTextColor; + border: 0; + + &:hover, + &:enabled:hover { + background-color: $primaryHeaderColor; + color: $primaryTextColor; + border: 0; + } + } + + .icon-btn { + background-color: transparent !important; + color: $primaryTextColor !important; + border: 0 !important; + + .pi { + font-size: 1.275rem !important; + } + } + + .text-btn { + background-color: transparent !important; + color: $primaryTextColor !important; + border: 0 !important; + padding: 0 !important; + + &:hover { + background-color: transparent !important; + color: $primaryHeaderColor !important; + border: 0; + } + } + + .icon-btn-without-hover { + &:hover { + background-color: transparent !important; + color: $primaryTextColor !important; + border: 0 !important; + } + } + + .icon-btn { + &:hover { + background-color: transparent !important; + color: $primaryHeaderColor !important; + border: 0; + } + } + + .danger-icon-btn { + background-color: transparent !important; + color: $primaryTextColor !important; + border: 0 !important; + + &:hover { + background-color: transparent !important; + color: $primaryErrorColor !important; + border: 0; + } + + .pi { + font-size: 1.275rem !important; + } + } + + .danger-btn { + background-color: $primaryErrorColor !important; + color: $primaryErrorColor !important; + border: 0 !important; + + &:hover { + background-color: $primaryErrorColor !important; + color: $primaryTextColor !important; + border: 0; + } + + .pi { + font-size: 1.275rem !important; + } + } + + .p-datatable .p-sortable-column.p-highlight, + .p-datatable .p-sortable-column.p-highlight .p-sortable-column-icon { + color: $primaryHeaderColor !important; + } + + .p-dropdown:not(.p-disabled):hover, + .p-dropdown:not(.p-disabled).p-focus, + .p-link:focus { + border-color: $primaryHeaderColor !important; + box-shadow: none !important; + } + + .p-paginator .p-paginator-pages .p-paginator-page.p-highlight { + background: transparent !important; + color: $primaryHeaderColor !important; + } + + .p-paginator .p-paginator-pages .p-paginator-page:not(.p-highlight):hover, + .p-paginator .p-paginator-first:not(.p-disabled):not(.p-highlight):hover, + .p-paginator .p-paginator-prev:not(.p-disabled):not(.p-highlight):hover, + .p-paginator .p-paginator-next:not(.p-disabled):not(.p-highlight):hover, + .p-paginator .p-paginator-last:not(.p-disabled):not(.p-highlight):hover { + background-color: $primaryBackgroundColor !important; + color: $primaryHeaderColor !important; + } } diff --git a/kdb-web/src/styles/themes/sh-edraft-dark-theme.scss b/kdb-web/src/styles/themes/sh-edraft-dark-theme.scss index cef76707..d05d920f 100644 --- a/kdb-web/src/styles/themes/sh-edraft-dark-theme.scss +++ b/kdb-web/src/styles/themes/sh-edraft-dark-theme.scss @@ -1,560 +1,585 @@ .sh-edraft-dark-theme { - $primaryTextColor: #fff; - $secondayTextColor: #000; - $secondayTextColor2: #ef9d0d; + $primaryTextColor: #fff; + $secondayTextColor: #000; + $secondayTextColor2: #ef9d0d; - $primaryHeaderColor: #ef9d0d; - $secondaryHeaderColor: #ffce4c; - $secondaryHeaderColor2: #b76f00; + $primaryHeaderColor: #ef9d0d; + $secondaryHeaderColor: #ffce4c; + $secondaryHeaderColor2: #b76f00; - $primaryBackgroundColor: #272727; - $secondaryBackgroundColor: #4f4f4f; - $secondaryBackgroundColor2: #fff; - $secondaryBackgroundColor3: #cccccc; + $primaryBackgroundColor: #272727; + $secondaryBackgroundColor: #4f4f4f; + $secondaryBackgroundColor2: #fff; + $secondaryBackgroundColor3: #cccccc; - $primaryErrorColor: #b00020; - $secondaryErrorColor: #e94948; + $primaryErrorColor: #b00020; + $secondaryErrorColor: #e94948; - $default-border: 2px solid $secondaryBackgroundColor3; + $default-border: 2px solid $secondaryBackgroundColor3; + background-color: $primaryBackgroundColor; + + h1, + h2 { + color: $primaryHeaderColor; + } + + input, + p { + color: $primaryTextColor; + } + + input { + background-color: $secondaryBackgroundColor !important; + } + + .input-field-info-text { + color: $primaryTextColor; + } + + /* Change Autocomplete styles in Chrome*/ + input:-webkit-autofill, + input:-webkit-autofill:hover, + input:-webkit-autofill:focus, + textarea:-webkit-autofill, + textarea:-webkit-autofill:hover, + textarea:-webkit-autofill:focus, + select:-webkit-autofill, + select:-webkit-autofill:hover, + select:-webkit-autofill:focus { + border: 1px solid $primaryHeaderColor; + -webkit-text-fill-color: $primaryTextColor; + -webkit-box-shadow: 0 0 0 1000px $secondaryBackgroundColor inset; + transition: background-color 5000s ease-in-out 0s; + } + + header { background-color: $primaryBackgroundColor; - h1, - h2 { - color: $primaryHeaderColor; - } - - input, - p { - color: $primaryTextColor; - } - - input { - background-color: $secondaryBackgroundColor !important; - } - - .input-field-info-text { - color: $primaryTextColor; - } - - /* Change Autocomplete styles in Chrome*/ - input:-webkit-autofill, - input:-webkit-autofill:hover, - input:-webkit-autofill:focus, - textarea:-webkit-autofill, - textarea:-webkit-autofill:hover, - textarea:-webkit-autofill:focus, - select:-webkit-autofill, - select:-webkit-autofill:hover, - select:-webkit-autofill:focus { - border: 1px solid $primaryHeaderColor; - -webkit-text-fill-color: $primaryTextColor; - -webkit-box-shadow: 0 0 0px 1000px $secondaryBackgroundColor inset; - transition: background-color 5000s ease-in-out 0s; - } - - header { - background-color: $primaryBackgroundColor; - - .logo-button-wrapper { - .p-button.p-button-text { - color: $primaryTextColor; - - &:hover { - color: $primaryTextColor; - background-color: $primaryBackgroundColor; - } - } - } - - .logo { - color: $primaryHeaderColor; - } - } - - h1 { - color: $primaryHeaderColor; - } - - .app { - .sidebar { - background-color: $primaryBackgroundColor; - - .menu { - color: $primaryTextColor; - } - } - - .component-wrapper { - color: $primaryTextColor; - - .component { - background-color: $secondaryBackgroundColor; - - .content-wrapper { - background-color: $primaryBackgroundColor; - border-top: 2px solid $primaryHeaderColor; - - .content-header { - border-bottom: $default-border; - } - - .content { - .content-row { - } - - .content-column { - } - - .content-data-name { - } - - .content-data-value { - } - - .content-divider { - border-bottom: $default-border; - } - - .server-list-wrapper { - .server-filter { - } - - .server-count { - } - - .server-list { - .server { - border: $default-border; - border-radius: 15px; - - .logo { - img { - border-radius: 100%; - } - } - - .name { - color: $primaryHeaderColor; - } - - &:hover { - border-color: $primaryHeaderColor !important; - } - } - } - } - } - } - } - } - } - - .p-dialog-header { - background-color: $primaryBackgroundColor !important; - color: $primaryTextColor !important; - } - - .p-dialog-content { - background-color: $secondaryBackgroundColor !important; - - .content-data-name, - .content-data-value { - color: $primaryTextColor; - - .text-btn { - font-size: 18px !important; - font-weight: 400 !important; - } - } - } - - footer { - background-color: $primaryBackgroundColor; + .logo-button-wrapper { + .p-button.p-button-text { color: $primaryTextColor; - a { - color: $primaryTextColor; + &:hover { + color: $primaryTextColor; + background-color: $primaryBackgroundColor; } + } } - .invalid-feedback { - color: $primaryErrorColor; + .logo { + color: $primaryHeaderColor; + } + } + + h1 { + color: $primaryHeaderColor; + } + + .app { + .sidebar { + background-color: $primaryBackgroundColor; + + .menu { + color: $primaryTextColor; + } } - .invalid-feedback-input, - .invalid-feedback-input:focus, - .invalid-feedback-input:hover { - input, - input:enabled:focus { - outline: 1px solid $primaryErrorColor !important; - border: 1px solid $primaryErrorColor !important; - border-color: $primaryErrorColor !important; - } - } + .component-wrapper { + color: $primaryTextColor; - .login-wrapper { + .component { background-color: $secondaryBackgroundColor; - .login-form-wrapper, - .auth-header { - background-color: $primaryBackgroundColor; + .content-wrapper { + background-color: $primaryBackgroundColor; + border-top: 2px solid $primaryHeaderColor; - .login-form { - .input-field { - input, - .p-password { - } - } + .content-header { + border-bottom: $default-border; + } - .login-form-submit { - .login-form-submit-btn { - } - } - - .login-form-sub-button-wrapper { - .login-form-sub-btn { - background-color: $primaryBackgroundColor; - color: $secondayTextColor2; - border: 2px solid $secondayTextColor2; - - &:hover { - background-color: $primaryHeaderColor !important; - color: $primaryTextColor !important; - } - } - - .login-form-sub-login-btn { - border: none; - } - } + .content { + .content-row { } - } - } - .spinner-component-wrapper { - background-color: rgba($secondaryBackgroundColor, 0.5); + .content-column { + } - .spinner-wrapper { - .custom-spinner .p-progress-spinner-circle { + .content-data-name { + } + + .content-data-value { + } + + .content-divider { + border-bottom: $default-border; + } + + .server-list-wrapper { + .server-filter { + } + + .server-count { + } + + .server-list { + .server { + border: $default-border; + border-radius: 15px; + + .logo { + img { + border-radius: 100%; + } + } + + .name { + color: $primaryHeaderColor; + } + + &:hover { + border-color: $primaryHeaderColor !important; + } + } + } + } + + p-panel { + .p-panel-header, + .p-panel-content { + border: $default-border; + } + + .p-panel-title { color: $primaryHeaderColor; - } - } - } + } - .wrapper-right { - justify-content: flex-end !important; - } + .p-panel-header { + background-color: $primaryBackgroundColor; - /* - PrimeNG Fixes - */ - .p-progress-spinner-circle { - stroke: $primaryHeaderColor !important; - } - - .p-menu, - .p-panelmenu { - color: $primaryTextColor !important; - - .p-menuitem-link .p-menuitem-text, - .p-menuitem-link .p-menuitem-icon, - .p-panelmenu-header > a { - color: $primaryTextColor !important; - background: transparent !important; - font-size: 1rem !important; - font-weight: normal !important; - } - - .p-menuitem-link:focus, - .p-panelmenu-header > a:focus, - .p-panelmenu-content .p-menuitem .p-menuitem-link:focus { - box-shadow: none !important; - } - - .p-menuitem-link:hover, - .p-panelmenu-header > a:hover, - .p-panelmenu-content .p-menuitem .p-menuitem-link:hover { - background-color: $secondaryBackgroundColor !important; - $border-radius: 20px; - border-radius: $border-radius 0px 0px $border-radius; - - .p-menuitem-text, - .p-menuitem-icon, - .p-menuitem-text, - .p-panelmenu-icon { - color: $primaryHeaderColor !important; - } - } - - .p-panelmenu-content { - margin: 5px 0px 5px 10px; - } - } - - .p-menu-overlay { - background-color: $primaryBackgroundColor !important; - color: $primaryTextColor !important; - border-top: 2px solid $primaryHeaderColor !important; - - .p-menuitem-link:hover { - background-color: $primaryBackgroundColor !important; - .p-menuitem-text, - .p-menuitem-icon { - color: $primaryHeaderColor !important; - } - } - } - - p-dropdown { - .p-dropdown { - background-color: $primaryBackgroundColor !important; - border-color: $primaryTextColor !important; - color: $primaryTextColor !important; - - span { - color: $primaryTextColor; - } - - .p-dropdown-panel { - background-color: $secondaryBackgroundColor !important; - - .p-dropdown-items .p-dropdown-item:not(.p-highlight):not(.p-disabled):hover { - background-color: $secondaryBackgroundColor !important; - color: $primaryHeaderColor !important; - - span { - color: $primaryHeaderColor !important; - } - } - - .p-dropdown-items .p-dropdown-item.p-highlight { - background-color: $secondaryBackgroundColor !important; - color: $primaryHeaderColor !important; - - span { - color: $primaryHeaderColor !important; - } + .p-panel-header-icon { + color: $primaryHeaderColor; } + } } + + .p-panel-content { + background-color: $primaryBackgroundColor; + color: $primaryTextColor; + border-top: none !important; + } + } } + } } + } - p-table { - background-color: $primaryBackgroundColor; - color: $primaryTextColor !important; + .p-dialog-header { + background-color: $primaryBackgroundColor !important; + color: $primaryTextColor !important; + } - .table-caption { - .table-caption-text { - } + .p-dialog-content { + background-color: $secondaryBackgroundColor !important; - .table-caption-search-wrapper { - .table-caption-search { - height: 30px !important; + .content-data-name, + .content-data-value { + color: $primaryTextColor; - .table-caption-search-icon { - } - - .table-caption-search-input { - height: 100% !important; - - &:focus { - outline-color: $primaryHeaderColor; - } - } - } - } - - .table-caption-btn-wrapper { - height: 30px !important; - } - } - - .table-edit-input { - width: 100% !important; - } + .text-btn { + font-size: 18px !important; + font-weight: 400 !important; + } } + } - p-checkbox { - .p-checkbox .p-checkbox-box { - background: $primaryBackgroundColor !important; - background-color: $primaryBackgroundColor !important; - } + footer { + background-color: $primaryBackgroundColor; + color: $primaryTextColor; - .p-checkbox .p-checkbox-box.p-highlight { - background: $primaryBackgroundColor !important; - background-color: $primaryBackgroundColor !important; - border-color: $primaryTextColor !important; - box-shadow: none !important; - } - - .p-checkbox .p-checkbox-box .p-checkbox-icon { - color: $primaryTextColor !important; - } - - .p-checkbox:not(.p-checkbox-disabled) .p-checkbox-box.p-focus, - .p-checkbox:not(.p-checkbox-disabled) .p-checkbox-box:hover { - border-color: $primaryHeaderColor !important; - box-shadow: none !important; - - .p-checkbox-icon { - color: $primaryHeaderColor !important; - } - } + a { + color: $primaryTextColor; } + } - p-dialog, - p-confirmdialog, - p-dynamicdialog { - .p-dialog.p-confirm-dialog .p-confirm-dialog-message { - margin-left: 0px !important; - } - - .p-dialog { - background-color: $secondaryBackgroundColor !important; - - .p-dialog-header { - background-color: $primaryBackgroundColor !important; - color: $primaryTextColor !important; - } - - .p-dialog-content, - .p-dialog-footer { - background-color: $secondaryBackgroundColor !important; - color: $primaryTextColor !important; - } - } - } + .invalid-feedback { + color: $primaryErrorColor; + } + .invalid-feedback-input, + .invalid-feedback-input:focus, + .invalid-feedback-input:hover { input, - .p-password input { - border-radius: 10px; - border: $default-border; + input:enabled:focus { + outline: 1px solid $primaryErrorColor !important; + border: 1px solid $primaryErrorColor !important; + border-color: $primaryErrorColor !important; + } + } - &:focus { - box-shadow: none !important; + .login-wrapper { + background-color: $secondaryBackgroundColor; + + .login-form-wrapper, + .auth-header { + background-color: $primaryBackgroundColor; + + .login-form { + .input-field { + input, + .p-password { + } } - &:hover, - &:active, - &:enabled:focus { - border-color: $primaryHeaderColor !important; + .login-form-submit { + .login-form-submit-btn { + } } + + .login-form-sub-button-wrapper { + .login-form-sub-btn { + background-color: $primaryBackgroundColor; + color: $secondayTextColor2; + border: 2px solid $secondayTextColor2; + + &:hover { + background-color: $primaryHeaderColor !important; + color: $primaryTextColor !important; + } + } + + .login-form-sub-login-btn { + border: none; + } + } + } + } + } + + .spinner-component-wrapper { + background-color: rgba($secondaryBackgroundColor, 0.5); + + .spinner-wrapper { + .custom-spinner .p-progress-spinner-circle { + color: $primaryHeaderColor; + } + } + } + + .wrapper-right { + justify-content: flex-end !important; + } + + /* + PrimeNG Fixes + */ + .p-progress-spinner-circle { + stroke: $primaryHeaderColor !important; + } + + .p-menu, + .p-panelmenu { + color: $primaryTextColor !important; + + .p-menuitem-link .p-menuitem-text, + .p-menuitem-link .p-menuitem-icon, + .p-panelmenu-header > a { + color: $primaryTextColor !important; + background: transparent !important; + font-size: 1rem !important; + font-weight: normal !important; } - .btn-wrapper { - display: flex !important; - align-items: center !important; + .p-menuitem-link:focus, + .p-panelmenu-header > a:focus, + .p-panelmenu-content .p-menuitem .p-menuitem-link:focus { + box-shadow: none !important; } - .btn { - background-color: $primaryHeaderColor; + .p-menuitem-link:hover, + .p-panelmenu-header > a:hover, + .p-panelmenu-content .p-menuitem .p-menuitem-link:hover { + background-color: $secondaryBackgroundColor !important; + $border-radius: 20px; + border-radius: $border-radius 0 0 $border-radius; + + .p-menuitem-text, + .p-menuitem-icon, + .p-menuitem-text, + .p-panelmenu-icon { + color: $primaryHeaderColor !important; + } + } + + .p-panelmenu-content { + margin: 5px 0 5px 10px; + } + } + + .p-menu-overlay { + background-color: $primaryBackgroundColor !important; + color: $primaryTextColor !important; + border-top: 2px solid $primaryHeaderColor !important; + + .p-menuitem-link:hover { + background-color: $primaryBackgroundColor !important; + + .p-menuitem-text, + .p-menuitem-icon { + color: $primaryHeaderColor !important; + } + } + } + + p-dropdown { + .p-dropdown { + background-color: $primaryBackgroundColor !important; + border-color: $primaryTextColor !important; + color: $primaryTextColor !important; + + span { color: $primaryTextColor; - border: 0; + } - &:hover, - &:enabled:hover { - background-color: $primaryHeaderColor; - color: $primaryTextColor; - border: 0; - } - } + .p-dropdown-panel { + background-color: $secondaryBackgroundColor !important; - .icon-btn { - background-color: transparent !important; - color: $primaryTextColor !important; - border: 0 !important; + .p-dropdown-items .p-dropdown-item:not(.p-highlight):not(.p-disabled):hover { + background-color: $secondaryBackgroundColor !important; + color: $primaryHeaderColor !important; - .pi { - font-size: 1.275rem !important; - } - } - - .text-btn { - background-color: transparent !important; - color: $primaryTextColor !important; - border: 0 !important; - padding: 0px !important; - - &:hover { - background-color: transparent !important; + span { color: $primaryHeaderColor !important; - border: 0; + } } - } - .icon-btn-without-hover { - &:hover { - background-color: transparent !important; - color: $primaryTextColor !important; - border: 0 !important; - } - } + .p-dropdown-items .p-dropdown-item.p-highlight { + background-color: $secondaryBackgroundColor !important; + color: $primaryHeaderColor !important; - .icon-btn { - &:hover { - background-color: transparent !important; + span { color: $primaryHeaderColor !important; - border: 0; + } } + } + } + } + + p-table { + background-color: $primaryBackgroundColor; + color: $primaryTextColor !important; + + .table-caption { + .table-caption-text { + } + + .table-caption-search-wrapper { + .table-caption-search { + height: 30px !important; + + .table-caption-search-icon { + } + + .table-caption-search-input { + height: 100% !important; + + &:focus { + outline-color: $primaryHeaderColor; + } + } + } + } + + .table-caption-btn-wrapper { + height: 30px !important; + } } - .danger-icon-btn { - background-color: transparent !important; - color: $primaryTextColor !important; - border: 0 !important; + .table-edit-input { + width: 100% !important; + } + } - &:hover { - background-color: transparent !important; - color: $primaryErrorColor !important; - border: 0; - } - - .pi { - font-size: 1.275rem !important; - } + p-checkbox { + .p-checkbox .p-checkbox-box { + background: $primaryBackgroundColor !important; + background-color: $primaryBackgroundColor !important; } - .danger-btn { - background-color: $primaryErrorColor !important; - color: $primaryErrorColor !important; - border: 0 !important; - - &:hover { - background-color: $primaryErrorColor !important; - color: $primaryTextColor !important; - border: 0; - } - - .pi { - font-size: 1.275rem !important; - } + .p-checkbox .p-checkbox-box.p-highlight { + background: $primaryBackgroundColor !important; + background-color: $primaryBackgroundColor !important; + border-color: $primaryTextColor !important; + box-shadow: none !important; } - .p-datatable .p-sortable-column.p-highlight, - .p-datatable .p-sortable-column.p-highlight .p-sortable-column-icon { + .p-checkbox .p-checkbox-box .p-checkbox-icon { + color: $primaryTextColor !important; + } + + .p-checkbox:not(.p-checkbox-disabled) .p-checkbox-box.p-focus, + .p-checkbox:not(.p-checkbox-disabled) .p-checkbox-box:hover { + border-color: $primaryHeaderColor !important; + box-shadow: none !important; + + .p-checkbox-icon { color: $primaryHeaderColor !important; + } + } + } + + p-dialog, + p-confirmdialog, + p-dynamicdialog { + .p-dialog.p-confirm-dialog .p-confirm-dialog-message { + margin-left: 0 !important; } - .p-dropdown:not(.p-disabled):hover, - .p-dropdown:not(.p-disabled).p-focus, - .p-link:focus { - border-color: $primaryHeaderColor !important; - box-shadow: none !important; - } + .p-dialog { + background-color: $secondaryBackgroundColor !important; - .p-paginator .p-paginator-pages .p-paginator-page.p-highlight { - background: transparent !important; - background-color: transparent !important; - color: $primaryHeaderColor !important; - } - - .p-paginator .p-paginator-pages .p-paginator-page:not(.p-highlight):hover, - .p-paginator .p-paginator-first:not(.p-disabled):not(.p-highlight):hover, - .p-paginator .p-paginator-prev:not(.p-disabled):not(.p-highlight):hover, - .p-paginator .p-paginator-next:not(.p-disabled):not(.p-highlight):hover, - .p-paginator .p-paginator-last:not(.p-disabled):not(.p-highlight):hover { + .p-dialog-header { background-color: $primaryBackgroundColor !important; - color: $primaryHeaderColor !important; + color: $primaryTextColor !important; + } + + .p-dialog-content, + .p-dialog-footer { + background-color: $secondaryBackgroundColor !important; + color: $primaryTextColor !important; + } } + } + + input, + .p-password input { + border-radius: 10px; + border: $default-border; + + &:focus { + box-shadow: none !important; + } + + &:hover, + &:active, + &:enabled:focus { + border-color: $primaryHeaderColor !important; + } + } + + .btn-wrapper { + display: flex !important; + align-items: center !important; + } + + .btn { + background-color: $primaryHeaderColor; + color: $primaryTextColor; + border: 0; + + &:hover, + &:enabled:hover { + background-color: $primaryHeaderColor; + color: $primaryTextColor; + border: 0; + } + } + + .icon-btn { + background-color: transparent !important; + color: $primaryTextColor !important; + border: 0 !important; + + .pi { + font-size: 1.275rem !important; + } + } + + .text-btn { + background-color: transparent !important; + color: $primaryTextColor !important; + border: 0 !important; + padding: 0 !important; + + &:hover { + background-color: transparent !important; + color: $primaryHeaderColor !important; + border: 0; + } + } + + .icon-btn-without-hover { + &:hover { + background-color: transparent !important; + color: $primaryTextColor !important; + border: 0 !important; + } + } + + .icon-btn { + &:hover { + background-color: transparent !important; + color: $primaryHeaderColor !important; + border: 0; + } + } + + .danger-icon-btn { + background-color: transparent !important; + color: $primaryTextColor !important; + border: 0 !important; + + &:hover { + background-color: transparent !important; + color: $primaryErrorColor !important; + border: 0; + } + + .pi { + font-size: 1.275rem !important; + } + } + + .danger-btn { + background-color: $primaryErrorColor !important; + color: $primaryErrorColor !important; + border: 0 !important; + + &:hover { + background-color: $primaryErrorColor !important; + color: $primaryTextColor !important; + border: 0; + } + + .pi { + font-size: 1.275rem !important; + } + } + + .p-datatable .p-sortable-column.p-highlight, + .p-datatable .p-sortable-column.p-highlight .p-sortable-column-icon { + color: $primaryHeaderColor !important; + } + + .p-dropdown:not(.p-disabled):hover, + .p-dropdown:not(.p-disabled).p-focus, + .p-link:focus { + border-color: $primaryHeaderColor !important; + box-shadow: none !important; + } + + .p-paginator .p-paginator-pages .p-paginator-page.p-highlight { + background: transparent !important; + color: $primaryHeaderColor !important; + } + + .p-paginator .p-paginator-pages .p-paginator-page:not(.p-highlight):hover, + .p-paginator .p-paginator-first:not(.p-disabled):not(.p-highlight):hover, + .p-paginator .p-paginator-prev:not(.p-disabled):not(.p-highlight):hover, + .p-paginator .p-paginator-next:not(.p-disabled):not(.p-highlight):hover, + .p-paginator .p-paginator-last:not(.p-disabled):not(.p-highlight):hover { + background-color: $primaryBackgroundColor !important; + color: $primaryHeaderColor !important; + } } diff --git a/kdb-web/src/styles/themes/sh-edraft-light-theme.scss b/kdb-web/src/styles/themes/sh-edraft-light-theme.scss index 8ae5f724..6d3e5f42 100644 --- a/kdb-web/src/styles/themes/sh-edraft-light-theme.scss +++ b/kdb-web/src/styles/themes/sh-edraft-light-theme.scss @@ -1,558 +1,583 @@ .sh-edraft-light-theme { - $primaryTextColor: #272727; - $secondayTextColor: #fff; - $secondayTextColor2: #ef9d0d; + $primaryTextColor: #272727; + $secondayTextColor: #fff; + $secondayTextColor2: #ef9d0d; - $primaryHeaderColor: #ef9d0d; - $secondaryHeaderColor: #ffce4c; - $secondaryHeaderColor2: #b76f00; + $primaryHeaderColor: #ef9d0d; + $secondaryHeaderColor: #ffce4c; + $secondaryHeaderColor2: #b76f00; - $primaryBackgroundColor: #fff; - $secondaryBackgroundColor: #cccccc; - $secondaryBackgroundColor2: #4f4f4f; - $secondaryBackgroundColor3: #272727; + $primaryBackgroundColor: #fff; + $secondaryBackgroundColor: #cccccc; + $secondaryBackgroundColor2: #4f4f4f; + $secondaryBackgroundColor3: #272727; - $primaryErrorColor: #b00020; - $secondaryErrorColor: #e94948; + $primaryErrorColor: #b00020; + $secondaryErrorColor: #e94948; - $default-border: 2px solid $secondaryBackgroundColor; + $default-border: 2px solid $secondaryBackgroundColor; + background-color: $primaryBackgroundColor; + + h1, + h2 { + color: $primaryHeaderColor; + } + + input, + p { + color: $primaryTextColor; + } + + input { + background-color: $primaryBackgroundColor !important; + } + + .input-field-info-text { + color: $primaryTextColor; + } + + /* Change Autocomplete styles in Chrome*/ + input:-webkit-autofill, + input:-webkit-autofill:hover, + input:-webkit-autofill:focus, + textarea:-webkit-autofill, + textarea:-webkit-autofill:hover, + textarea:-webkit-autofill:focus, + select:-webkit-autofill, + select:-webkit-autofill:hover, + select:-webkit-autofill:focus { + border: 1px solid $primaryHeaderColor; + -webkit-text-fill-color: $primaryTextColor; + -webkit-box-shadow: 0 0 0 1000px $primaryBackgroundColor inset; + transition: background-color 5000s ease-in-out 0s; + } + + header { background-color: $primaryBackgroundColor; - h1, - h2 { - color: $primaryHeaderColor; - } - - input, - p { - color: $primaryTextColor; - } - - input { - background-color: $primaryBackgroundColor !important; - } - - .input-field-info-text { - color: $primaryTextColor; - } - - /* Change Autocomplete styles in Chrome*/ - input:-webkit-autofill, - input:-webkit-autofill:hover, - input:-webkit-autofill:focus, - textarea:-webkit-autofill, - textarea:-webkit-autofill:hover, - textarea:-webkit-autofill:focus, - select:-webkit-autofill, - select:-webkit-autofill:hover, - select:-webkit-autofill:focus { - border: 1px solid $primaryHeaderColor; - -webkit-text-fill-color: $primaryTextColor; - -webkit-box-shadow: 0 0 0px 1000px $primaryBackgroundColor inset; - transition: background-color 5000s ease-in-out 0s; - } - - header { - background-color: $primaryBackgroundColor; - - .logo-button-wrapper { - .p-button.p-button-text { - color: $primaryTextColor; - - &:hover { - color: $primaryTextColor; - background-color: $primaryBackgroundColor; - } - } - } - - .logo { - color: $primaryHeaderColor; - } - } - - h1 { - color: $primaryHeaderColor; - } - - .app { - .sidebar { - background-color: $primaryBackgroundColor; - - .menu { - color: $primaryTextColor; - } - } - - .component-wrapper { - color: $primaryTextColor; - - .component { - background-color: $secondaryBackgroundColor; - - .content-wrapper { - background-color: $primaryBackgroundColor; - border-top: 2px solid $primaryHeaderColor; - - .content-header { - border-bottom: $default-border; - } - - .content { - .content-row { - } - - .content-column { - } - - .content-data-name { - } - - .content-data-value { - } - - .content-divider { - border-bottom: $default-border; - } - } - - .server-list-wrapper { - .server-filter { - } - - .server-count { - } - - .server-list { - .server { - border: $default-border; - border-radius: 15px; - - .logo { - img { - border-radius: 100%; - } - } - - .name { - color: $primaryHeaderColor; - } - - &:hover { - border-color: $primaryHeaderColor !important; - } - } - } - } - } - } - } - } - - .p-dialog-header { - background-color: $secondaryBackgroundColor !important; - color: $primaryTextColor !important; - } - - .p-dialog-content { - .content-data-name, - .content-data-value { - color: $primaryTextColor; - - .text-btn { - font-size: 18px !important; - font-weight: 400 !important; - } - } - } - - footer { - background-color: $primaryBackgroundColor; + .logo-button-wrapper { + .p-button.p-button-text { color: $primaryTextColor; - a { - color: $primaryTextColor; + &:hover { + color: $primaryTextColor; + background-color: $primaryBackgroundColor; } + } } - .invalid-feedback { - color: $primaryErrorColor; + .logo { + color: $primaryHeaderColor; + } + } + + h1 { + color: $primaryHeaderColor; + } + + .app { + .sidebar { + background-color: $primaryBackgroundColor; + + .menu { + color: $primaryTextColor; + } } - .invalid-feedback-input, - .invalid-feedback-input:focus, - .invalid-feedback-input:hover { - input, - input:enabled:focus { - outline: 1px solid $primaryErrorColor !important; - border: 1px solid $primaryErrorColor !important; - border-color: $primaryErrorColor !important; - } - } + .component-wrapper { + color: $primaryTextColor; - .login-wrapper { + .component { background-color: $secondaryBackgroundColor; - .login-form-wrapper, - .auth-header { - background-color: $primaryBackgroundColor; + .content-wrapper { + background-color: $primaryBackgroundColor; + border-top: 2px solid $primaryHeaderColor; - .login-form { - .input-field { - input, - .p-password { - } - } + .content-header { + border-bottom: $default-border; + } - .login-form-submit { - .login-form-submit-btn { - } - } - - .login-form-sub-button-wrapper { - .login-form-sub-btn { - background-color: $primaryBackgroundColor; - color: $secondayTextColor2; - border: 2px solid $secondayTextColor2; - - &:hover { - background-color: $primaryHeaderColor !important; - color: $primaryTextColor !important; - } - } - - .login-form-sub-login-btn { - border: none; - } - } + .content { + .content-row { } - } - } - .spinner-component-wrapper { - background-color: rgba($secondaryBackgroundColor, 0.5); + .content-column { + } - .spinner-wrapper { - .custom-spinner .p-progress-spinner-circle { + .content-data-name { + } + + .content-data-value { + } + + .content-divider { + border-bottom: $default-border; + } + } + + p-panel { + .p-panel-header, + .p-panel-content { + border: $default-border; + } + + .p-panel-title { + color: $primaryHeaderColor; + } + + .p-panel-header { + background-color: $primaryBackgroundColor; + + .p-panel-header-icon { color: $primaryHeaderColor; + } } - } - } + } - .wrapper-right { - justify-content: flex-end !important; - } - - /* - PrimeNG Fixes - */ - .p-progress-spinner-circle { - stroke: $primaryHeaderColor !important; - } - - .p-menu, - .p-panelmenu { - color: $primaryTextColor !important; - - .p-menuitem-link .p-menuitem-text, - .p-menuitem-link .p-menuitem-icon, - .p-panelmenu-header > a { - color: $primaryTextColor !important; - background: transparent !important; - font-size: 1rem !important; - font-weight: normal !important; - } - - .p-menuitem-link:focus, - .p-panelmenu-header > a:focus, - .p-panelmenu-content .p-menuitem .p-menuitem-link:focus { - box-shadow: none !important; - } - - .p-menuitem-link:hover, - .p-panelmenu-header > a:hover, - .p-panelmenu-content .p-menuitem .p-menuitem-link:hover { - background-color: $secondaryBackgroundColor !important; - $border-radius: 20px; - border-radius: $border-radius 0px 0px $border-radius; - - .p-menuitem-text, - .p-menuitem-icon, - .p-menuitem-text, - .p-panelmenu-icon { - color: $primaryHeaderColor !important; - } - } - - .p-panelmenu-content { - margin: 5px 0px 5px 10px; - } - } - - .p-menu-overlay { - background-color: $primaryBackgroundColor !important; - color: $primaryTextColor !important; - border-top: 2px solid $primaryHeaderColor !important; - - .p-menuitem-link:hover { - background-color: $primaryBackgroundColor !important; - .p-menuitem-text, - .p-menuitem-icon { - color: $primaryHeaderColor !important; - } - } - } - - p-dropdown { - .p-dropdown { - background-color: $primaryBackgroundColor !important; - border-color: $primaryTextColor !important; - color: $primaryTextColor !important; - - span { - color: $primaryTextColor; - } - - .p-dropdown-panel { - background-color: $primaryBackgroundColor !important; - - .p-dropdown-items .p-dropdown-item:not(.p-highlight):not(.p-disabled):hover { - background-color: $primaryBackgroundColor !important; - color: $primaryHeaderColor !important; - - span { - color: $primaryHeaderColor !important; - } - } - - .p-dropdown-items .p-dropdown-item.p-highlight { - background-color: $primaryBackgroundColor !important; - color: $primaryHeaderColor !important; - - span { - color: $primaryHeaderColor !important; - } - } - } - } - } - - p-table { - background-color: $primaryBackgroundColor; - color: $primaryTextColor !important; - - .table-caption { - .table-caption-text { - } - - .table-caption-search-wrapper { - .table-caption-search { - height: 30px !important; - - .table-caption-search-icon { - } - - .table-caption-search-input { - height: 100% !important; - - &:focus { - outline-color: $primaryHeaderColor; - } - } - } - } - - .table-caption-btn-wrapper { - height: 30px !important; - } - } - - .table-edit-input { - width: 100% !important; - } - } - - p-checkbox { - .p-checkbox .p-checkbox-box { - background: $primaryBackgroundColor !important; - background-color: $primaryBackgroundColor !important; - } - - .p-checkbox .p-checkbox-box.p-highlight { - background: $primaryBackgroundColor !important; - background-color: $primaryBackgroundColor !important; - border-color: $primaryTextColor !important; - box-shadow: none !important; - } - - .p-checkbox .p-checkbox-box .p-checkbox-icon { - color: $primaryTextColor !important; - } - - .p-checkbox:not(.p-checkbox-disabled) .p-checkbox-box.p-focus, - .p-checkbox:not(.p-checkbox-disabled) .p-checkbox-box:hover { - border-color: $primaryHeaderColor !important; - box-shadow: none !important; - - .p-checkbox-icon { - color: $primaryHeaderColor !important; - } - } - } - - p-dialog, - p-confirmdialog, - p-dynamicdialog { - .p-dialog.p-confirm-dialog .p-confirm-dialog-message { - margin-left: 0px !important; - } - - .p-dialog { - background-color: $primaryBackgroundColor !important; - - .p-dialog-header { - background-color: $secondaryBackgroundColor !important; - color: $primaryTextColor !important; - } - - .p-dialog-content, - .p-dialog-footer { - background-color: $primaryBackgroundColor !important; - color: $primaryTextColor !important; - } - } - } - - input, - .p-password input { - border-radius: 10px; - border: $default-border; - - &:focus { - box-shadow: none !important; - } - - &:hover, - &:active, - &:enabled:focus { - border-color: $primaryHeaderColor !important; - } - } - - .btn-wrapper { - display: flex !important; - align-items: center !important; - } - - .btn { - background-color: $primaryHeaderColor; - color: $primaryTextColor; - border: 0; - - &:hover, - &:enabled:hover { - background-color: $primaryHeaderColor; + .p-panel-content { + background-color: $primaryBackgroundColor; color: $primaryTextColor; - border: 0; + border-top: none !important; + } + + .server-list-wrapper { + .server-filter { + } + + .server-count { + } + + .server-list { + .server { + border: $default-border; + border-radius: 15px; + + .logo { + img { + border-radius: 100%; + } + } + + .name { + color: $primaryHeaderColor; + } + + &:hover { + border-color: $primaryHeaderColor !important; + } + } + } + } } + } + } + } + + .p-dialog-header { + background-color: $secondaryBackgroundColor !important; + color: $primaryTextColor !important; + } + + .p-dialog-content { + .content-data-name, + .content-data-value { + color: $primaryTextColor; + + .text-btn { + font-size: 18px !important; + font-weight: 400 !important; + } + } + } + + footer { + background-color: $primaryBackgroundColor; + color: $primaryTextColor; + + a { + color: $primaryTextColor; + } + } + + .invalid-feedback { + color: $primaryErrorColor; + } + + .invalid-feedback-input, + .invalid-feedback-input:focus, + .invalid-feedback-input:hover { + input, + input:enabled:focus { + outline: 1px solid $primaryErrorColor !important; + border: 1px solid $primaryErrorColor !important; + border-color: $primaryErrorColor !important; + } + } + + .login-wrapper { + background-color: $secondaryBackgroundColor; + + .login-form-wrapper, + .auth-header { + background-color: $primaryBackgroundColor; + + .login-form { + .input-field { + input, + .p-password { + } + } + + .login-form-submit { + .login-form-submit-btn { + } + } + + .login-form-sub-button-wrapper { + .login-form-sub-btn { + background-color: $primaryBackgroundColor; + color: $secondayTextColor2; + border: 2px solid $secondayTextColor2; + + &:hover { + background-color: $primaryHeaderColor !important; + color: $primaryTextColor !important; + } + } + + .login-form-sub-login-btn { + border: none; + } + } + } + } + } + + .spinner-component-wrapper { + background-color: rgba($secondaryBackgroundColor, 0.5); + + .spinner-wrapper { + .custom-spinner .p-progress-spinner-circle { + color: $primaryHeaderColor; + } + } + } + + .wrapper-right { + justify-content: flex-end !important; + } + + /* + PrimeNG Fixes + */ + .p-progress-spinner-circle { + stroke: $primaryHeaderColor !important; + } + + .p-menu, + .p-panelmenu { + color: $primaryTextColor !important; + + .p-menuitem-link .p-menuitem-text, + .p-menuitem-link .p-menuitem-icon, + .p-panelmenu-header > a { + color: $primaryTextColor !important; + background: transparent !important; + font-size: 1rem !important; + font-weight: normal !important; } - .icon-btn { - background-color: transparent !important; - color: $primaryTextColor !important; - border: 0 !important; - - .pi { - font-size: 1.275rem !important; - } + .p-menuitem-link:focus, + .p-panelmenu-header > a:focus, + .p-panelmenu-content .p-menuitem .p-menuitem-link:focus { + box-shadow: none !important; } - .text-btn { - background-color: transparent !important; - color: $primaryTextColor !important; - border: 0 !important; - padding: 0px !important; + .p-menuitem-link:hover, + .p-panelmenu-header > a:hover, + .p-panelmenu-content .p-menuitem .p-menuitem-link:hover { + background-color: $secondaryBackgroundColor !important; + $border-radius: 20px; + border-radius: $border-radius 0 0 $border-radius; - &:hover { - background-color: transparent !important; - color: $primaryHeaderColor !important; - border: 0; - } - } - - .icon-btn-without-hover { - &:hover { - background-color: transparent !important; - color: $primaryTextColor !important; - border: 0 !important; - } - } - - .icon-btn { - &:hover { - background-color: transparent !important; - color: $primaryHeaderColor !important; - border: 0; - } - } - - .danger-icon-btn { - background-color: transparent !important; - color: $primaryTextColor !important; - border: 0 !important; - - &:hover { - background-color: transparent !important; - color: $primaryErrorColor !important; - border: 0; - } - - .pi { - font-size: 1.275rem !important; - } - } - - .danger-btn { - background-color: $primaryErrorColor !important; - color: $primaryErrorColor !important; - border: 0 !important; - - &:hover { - background-color: $primaryErrorColor !important; - color: $primaryTextColor !important; - border: 0; - } - - .pi { - font-size: 1.275rem !important; - } - } - - .p-datatable .p-sortable-column.p-highlight, - .p-datatable .p-sortable-column.p-highlight .p-sortable-column-icon { + .p-menuitem-text, + .p-menuitem-icon, + .p-menuitem-text, + .p-panelmenu-icon { color: $primaryHeaderColor !important; + } } - .p-dropdown:not(.p-disabled):hover, - .p-dropdown:not(.p-disabled).p-focus, - .p-link:focus { - border-color: $primaryHeaderColor !important; - box-shadow: none !important; + .p-panelmenu-content { + margin: 5px 0 5px 10px; } + } - .p-paginator .p-paginator-pages .p-paginator-page.p-highlight { - background: transparent !important; - background-color: transparent !important; + .p-menu-overlay { + background-color: $primaryBackgroundColor !important; + color: $primaryTextColor !important; + border-top: 2px solid $primaryHeaderColor !important; + + .p-menuitem-link:hover { + background-color: $primaryBackgroundColor !important; + + .p-menuitem-text, + .p-menuitem-icon { color: $primaryHeaderColor !important; + } } + } - .p-paginator .p-paginator-pages .p-paginator-page:not(.p-highlight):hover, - .p-paginator .p-paginator-first:not(.p-disabled):not(.p-highlight):hover, - .p-paginator .p-paginator-prev:not(.p-disabled):not(.p-highlight):hover, - .p-paginator .p-paginator-next:not(.p-disabled):not(.p-highlight):hover, - .p-paginator .p-paginator-last:not(.p-disabled):not(.p-highlight):hover { + p-dropdown { + .p-dropdown { + background-color: $primaryBackgroundColor !important; + border-color: $primaryTextColor !important; + color: $primaryTextColor !important; + + span { + color: $primaryTextColor; + } + + .p-dropdown-panel { background-color: $primaryBackgroundColor !important; - color: $primaryHeaderColor !important; + + .p-dropdown-items .p-dropdown-item:not(.p-highlight):not(.p-disabled):hover { + background-color: $primaryBackgroundColor !important; + color: $primaryHeaderColor !important; + + span { + color: $primaryHeaderColor !important; + } + } + + .p-dropdown-items .p-dropdown-item.p-highlight { + background-color: $primaryBackgroundColor !important; + color: $primaryHeaderColor !important; + + span { + color: $primaryHeaderColor !important; + } + } + } } + } + + p-table { + background-color: $primaryBackgroundColor; + color: $primaryTextColor !important; + + .table-caption { + .table-caption-text { + } + + .table-caption-search-wrapper { + .table-caption-search { + height: 30px !important; + + .table-caption-search-icon { + } + + .table-caption-search-input { + height: 100% !important; + + &:focus { + outline-color: $primaryHeaderColor; + } + } + } + } + + .table-caption-btn-wrapper { + height: 30px !important; + } + } + + .table-edit-input { + width: 100% !important; + } + } + + p-checkbox { + .p-checkbox .p-checkbox-box { + background: $primaryBackgroundColor !important; + background-color: $primaryBackgroundColor !important; + } + + .p-checkbox .p-checkbox-box.p-highlight { + background: $primaryBackgroundColor !important; + background-color: $primaryBackgroundColor !important; + border-color: $primaryTextColor !important; + box-shadow: none !important; + } + + .p-checkbox .p-checkbox-box .p-checkbox-icon { + color: $primaryTextColor !important; + } + + .p-checkbox:not(.p-checkbox-disabled) .p-checkbox-box.p-focus, + .p-checkbox:not(.p-checkbox-disabled) .p-checkbox-box:hover { + border-color: $primaryHeaderColor !important; + box-shadow: none !important; + + .p-checkbox-icon { + color: $primaryHeaderColor !important; + } + } + } + + p-dialog, + p-confirmdialog, + p-dynamicdialog { + .p-dialog.p-confirm-dialog .p-confirm-dialog-message { + margin-left: 0 !important; + } + + .p-dialog { + background-color: $primaryBackgroundColor !important; + + .p-dialog-header { + background-color: $secondaryBackgroundColor !important; + color: $primaryTextColor !important; + } + + .p-dialog-content, + .p-dialog-footer { + background-color: $primaryBackgroundColor !important; + color: $primaryTextColor !important; + } + } + } + + input, + .p-password input { + border-radius: 10px; + border: $default-border; + + &:focus { + box-shadow: none !important; + } + + &:hover, + &:active, + &:enabled:focus { + border-color: $primaryHeaderColor !important; + } + } + + .btn-wrapper { + display: flex !important; + align-items: center !important; + } + + .btn { + background-color: $primaryHeaderColor; + color: $primaryTextColor; + border: 0; + + &:hover, + &:enabled:hover { + background-color: $primaryHeaderColor; + color: $primaryTextColor; + border: 0; + } + } + + .icon-btn { + background-color: transparent !important; + color: $primaryTextColor !important; + border: 0 !important; + + .pi { + font-size: 1.275rem !important; + } + } + + .text-btn { + background-color: transparent !important; + color: $primaryTextColor !important; + border: 0 !important; + padding: 0 !important; + + &:hover { + background-color: transparent !important; + color: $primaryHeaderColor !important; + border: 0; + } + } + + .icon-btn-without-hover { + &:hover { + background-color: transparent !important; + color: $primaryTextColor !important; + border: 0 !important; + } + } + + .icon-btn { + &:hover { + background-color: transparent !important; + color: $primaryHeaderColor !important; + border: 0; + } + } + + .danger-icon-btn { + background-color: transparent !important; + color: $primaryTextColor !important; + border: 0 !important; + + &:hover { + background-color: transparent !important; + color: $primaryErrorColor !important; + border: 0; + } + + .pi { + font-size: 1.275rem !important; + } + } + + .danger-btn { + background-color: $primaryErrorColor !important; + color: $primaryErrorColor !important; + border: 0 !important; + + &:hover { + background-color: $primaryErrorColor !important; + color: $primaryTextColor !important; + border: 0; + } + + .pi { + font-size: 1.275rem !important; + } + } + + .p-datatable .p-sortable-column.p-highlight, + .p-datatable .p-sortable-column.p-highlight .p-sortable-column-icon { + color: $primaryHeaderColor !important; + } + + .p-dropdown:not(.p-disabled):hover, + .p-dropdown:not(.p-disabled).p-focus, + .p-link:focus { + border-color: $primaryHeaderColor !important; + box-shadow: none !important; + } + + .p-paginator .p-paginator-pages .p-paginator-page.p-highlight { + background: transparent !important; + color: $primaryHeaderColor !important; + } + + .p-paginator .p-paginator-pages .p-paginator-page:not(.p-highlight):hover, + .p-paginator .p-paginator-first:not(.p-disabled):not(.p-highlight):hover, + .p-paginator .p-paginator-prev:not(.p-disabled):not(.p-highlight):hover, + .p-paginator .p-paginator-next:not(.p-disabled):not(.p-highlight):hover, + .p-paginator .p-paginator-last:not(.p-disabled):not(.p-highlight):hover { + background-color: $primaryBackgroundColor !important; + color: $primaryHeaderColor !important; + } }