forked from sh-edraft.de/sh_discord_bot
		
	Added server list to dashboard #72
This commit is contained in:
		| @@ -1,3 +1,5 @@ | ||||
| from typing import Optional | ||||
|  | ||||
| from bot_api.abc.dto_abc import DtoABC | ||||
|  | ||||
|  | ||||
| @@ -8,7 +10,8 @@ class ServerDTO(DtoABC): | ||||
|             server_id: int, | ||||
|             discord_id: int, | ||||
|             name: str, | ||||
|             member_count: int | ||||
|             member_count: int, | ||||
|             icon_url: Optional[str] | ||||
|  | ||||
|     ): | ||||
|         DtoABC.__init__(self) | ||||
| @@ -17,6 +20,7 @@ class ServerDTO(DtoABC): | ||||
|         self._discord_id = discord_id | ||||
|         self._name = name | ||||
|         self._member_count = member_count | ||||
|         self._icon_url = icon_url | ||||
|          | ||||
|     @property | ||||
|     def server_id(self) -> int: | ||||
| @@ -34,11 +38,15 @@ class ServerDTO(DtoABC): | ||||
|     def member_count(self) -> int: | ||||
|         return self._member_count | ||||
|  | ||||
|     @property | ||||
|     def icon_url(self) -> Optional[str]: | ||||
|         return self._icon_url | ||||
|  | ||||
|     def from_dict(self, values: dict): | ||||
|         self._server_id = int(values['serverId']) | ||||
|         self._discord_id = int(values['discordId']) | ||||
|         self._name = values['name'] | ||||
|         self._member_count = int(values['memberCount']) | ||||
|         self._icon_url = int(values['iconURL']) | ||||
|  | ||||
|     def to_dict(self) -> dict: | ||||
|         return { | ||||
| @@ -46,4 +54,5 @@ class ServerDTO(DtoABC): | ||||
|             'discordId': self._discord_id, | ||||
|             'name': self._name, | ||||
|             'memberCount': self._member_count, | ||||
|             'iconURL': self._icon_url, | ||||
|         } | ||||
|   | ||||
| @@ -33,9 +33,12 @@ class DiscordService: | ||||
|  | ||||
|     async def get_all_servers(self) -> List[ServerDTO]: | ||||
|         servers = self._servers.get_servers() | ||||
|         return servers.select( | ||||
|             lambda x: ServerTransformer.to_dto(x, self._bot.get_guild(x.discord_server_id).name, self._bot.get_guild(x.discord_server_id).member_count) | ||||
|         ) | ||||
|         return servers.select(lambda x: ServerTransformer.to_dto( | ||||
|             x, | ||||
|             self._bot.get_guild(x.discord_server_id).name, | ||||
|             self._bot.get_guild(x.discord_server_id).member_count, | ||||
|             self._bot.get_guild(x.discord_server_id).icon | ||||
|         )) | ||||
|  | ||||
|     async def get_all_servers_by_user(self) -> List[ServerDTO]: | ||||
|         token = self._auth.get_decoded_token_from_request() | ||||
| @@ -50,9 +53,12 @@ class DiscordService: | ||||
|             user_from_db = self._users.find_user_by_id(0 if user.user_id is None else user.user_id) | ||||
|             servers = self._servers.get_servers().where(lambda x: user_from_db is not None and x.server_id == user_from_db.server.server_id) | ||||
|  | ||||
|         return servers.select( | ||||
|             lambda x: ServerTransformer.to_dto(x, self._bot.get_guild(x.discord_server_id).name, self._bot.get_guild(x.discord_server_id).member_count) | ||||
|         ) | ||||
|         return servers.select(lambda x: ServerTransformer.to_dto( | ||||
|             x, | ||||
|             self._bot.get_guild(x.discord_server_id).name, | ||||
|             self._bot.get_guild(x.discord_server_id).member_count, | ||||
|             self._bot.get_guild(x.discord_server_id).icon | ||||
|         )) | ||||
|  | ||||
|     async def get_filtered_servers_async(self, criteria: ServerSelectCriteria) -> ServerFilteredResultDTO: | ||||
|         token = self._auth.get_decoded_token_from_request() | ||||
| @@ -68,9 +74,17 @@ class DiscordService: | ||||
|             servers = servers.where(lambda x: user_from_db is not None and x.server_id == user_from_db.server.server_id) | ||||
|  | ||||
|         result = servers.select( | ||||
|             lambda x: ServerTransformer.to_dto(x, self._bot.get_guild(x.discord_server_id).name, self._bot.get_guild(x.discord_server_id).member_count) | ||||
|             lambda x: ServerTransformer.to_dto( | ||||
|                 x, | ||||
|                 self._bot.get_guild(x.discord_server_id).name, | ||||
|                 self._bot.get_guild(x.discord_server_id).member_count, | ||||
|                 self._bot.get_guild(x.discord_server_id).icon | ||||
|             ) | ||||
|         ) | ||||
|  | ||||
|         if criteria.name is not None and criteria.name != '': | ||||
|             result = result.where(lambda x: criteria.name.lower() in x.name.lower() or x.name.lower() == criteria.name.lower()) | ||||
|  | ||||
|         return ServerFilteredResultDTO( | ||||
|             List(ServerDTO, result), | ||||
|             filtered_result.total_count | ||||
|   | ||||
| @@ -1,3 +1,7 @@ | ||||
| from typing import Optional | ||||
|  | ||||
| import discord | ||||
|  | ||||
| from bot_api.abc.transformer_abc import TransformerABC | ||||
| from bot_api.model.discord.server_dto import ServerDTO | ||||
| from bot_data.model.server import Server | ||||
| @@ -10,10 +14,11 @@ class ServerTransformer(TransformerABC): | ||||
|         return Server(dto.discord_id) | ||||
|  | ||||
|     @staticmethod | ||||
|     def to_dto(db: Server, name: str, member_count: int) -> ServerDTO: | ||||
|     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, | ||||
|             name, | ||||
|             member_count, | ||||
|             icon_url.url if icon_url is not None else None, | ||||
|         ) | ||||
|   | ||||
| @@ -35,9 +35,6 @@ class ServerRepositoryService(ServerRepositoryABC): | ||||
|         self._logger.trace(__name__, f'Send SQL command: {Server.get_select_all_string()}') | ||||
|         query = servers | ||||
|  | ||||
|         if criteria.name is not None and criteria.name != '': | ||||
|             query = query.where(lambda x: criteria.name in x.first_name or x.first_name == criteria.name) | ||||
|  | ||||
|         # sort | ||||
|         if criteria.sort_column is not None and criteria.sort_column != '' and criteria.sort_direction is not None and criteria.sort_direction: | ||||
|             crit_sort_direction = criteria.sort_direction.lower() | ||||
|   | ||||
| @@ -3,4 +3,5 @@ export interface ServerDTO { | ||||
|     discordId: number; | ||||
|     name: string; | ||||
|     memberCount: number; | ||||
|     iconURL: string | null; | ||||
| } | ||||
| @@ -2,11 +2,49 @@ | ||||
|     {{'view.dashboard.header' | translate}} | ||||
| </h1> | ||||
| <div class="content-wrapper"> | ||||
|     <div class="content-header"> | ||||
|         <h2> | ||||
|             <i class="pi pi-server"></i> | ||||
|             {{'view.dashboard.server.header' | translate}} | ||||
|         </h2> | ||||
|     </div> | ||||
|  | ||||
|     <div class="content"> | ||||
|         <ul> | ||||
|             <li *ngFor="let server of servers"> | ||||
|                 {{server.name}} | ||||
|             </li> | ||||
|         </ul> | ||||
|         <div class="server-list-wrapper"> | ||||
|             <div class="server-filter"> | ||||
|                 <form [formGroup]="filterForm"> | ||||
|                     <div class="input-field"> | ||||
|                         <input type="text" pInputText formControlName="name" | ||||
|                             placeholder="{{'view.dashboard.filter.name' | translate}}" autocomplete="given-name"> | ||||
|                     </div> | ||||
|                 </form> | ||||
|             </div> | ||||
|  | ||||
|             <div class="server-count"> | ||||
|                 {{servers.length}} {{'view.dashboard.of' | translate}} {{totalRecords}} {{'view.dashboard.servers' | translate}}: | ||||
|                 <hr> | ||||
|             </div> | ||||
|  | ||||
|             <div class="server-list"> | ||||
|                 <div class="server" *ngFor="let server of servers"> | ||||
|                     <div class="logo"> | ||||
|                         <img *ngIf="server.iconURL" [src]="server.iconURL"> | ||||
|                     </div> | ||||
|  | ||||
|                     <div class="info"> | ||||
|                         <h3 class="name"> | ||||
|                             {{server.name}} | ||||
|                         </h3> | ||||
|  | ||||
|                         <div class="data"> | ||||
|                             <i class="pi pi-users"></i> | ||||
|                             {{server.memberCount}} | ||||
|                             {{'view.dashboard.server.member_count' | translate}} | ||||
|                         </div> | ||||
|                     </div> | ||||
|  | ||||
|                 </div> | ||||
|             </div> | ||||
|         </div> | ||||
|     </div> | ||||
| </div> | ||||
| @@ -107,7 +107,16 @@ | ||||
|     }, | ||||
|     "view": { | ||||
|         "dashboard": { | ||||
|             "header": "Dashboard" | ||||
|             "header": "Dashboard", | ||||
|             "of": "von", | ||||
|             "servers": "Server", | ||||
|             "server": { | ||||
|                 "header": "Server", | ||||
|                 "member_count": "Mitglid(er)" | ||||
|             }, | ||||
|             "filter": { | ||||
|                 "name": "Name" | ||||
|             } | ||||
|         }, | ||||
|         "user-list": {}, | ||||
|         "change-password": { | ||||
|   | ||||
| @@ -10,6 +10,8 @@ body { | ||||
|     height: 100%; | ||||
|     padding: 0; | ||||
|     margin: 0; | ||||
|  | ||||
|     font-size: 1rem; | ||||
| } | ||||
|  | ||||
| main { | ||||
| @@ -18,15 +20,19 @@ main { | ||||
|     min-height: 100vh; | ||||
| } | ||||
|  | ||||
| h1, | ||||
| h2 { | ||||
| h1 { | ||||
|     margin: 0; | ||||
|     font-size: 30px; | ||||
|     font-size: 1.75rem; | ||||
| } | ||||
|  | ||||
| h2 { | ||||
|     margin: 0; | ||||
|     font-size: 25px; | ||||
|     font-size: 1.5rem; | ||||
| } | ||||
|  | ||||
| h3 { | ||||
|     margin: 0; | ||||
|     font-size: 1.25rem; | ||||
| } | ||||
|  | ||||
| header { | ||||
| @@ -207,6 +213,59 @@ header { | ||||
|                     .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 { | ||||
|                                     } | ||||
|                                 } | ||||
|                             } | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|   | ||||
| @@ -432,7 +432,7 @@ | ||||
|         color: $primaryTextColor !important; | ||||
|         border: 0 !important; | ||||
|         padding: 0px !important; | ||||
|          | ||||
|  | ||||
|         &:hover { | ||||
|             background-color: transparent !important; | ||||
|             color: $primaryHeaderColor !important; | ||||
|   | ||||
| @@ -15,17 +15,10 @@ | ||||
|     $primaryErrorColor: #b00020; | ||||
|     $secondaryErrorColor: #e94948; | ||||
|  | ||||
|     $default-border: 1px solid $secondaryBackgroundColor3; | ||||
|     $default-border: 2px solid $secondaryBackgroundColor3; | ||||
|  | ||||
|     background-color: $primaryBackgroundColor !important; | ||||
|  | ||||
|     html, | ||||
|     body { | ||||
|         margin: 0; | ||||
|  | ||||
|         font-size: 16px; | ||||
|     } | ||||
|  | ||||
|     h1, | ||||
|     h2 { | ||||
|         color: $primaryHeaderColor; | ||||
| @@ -122,6 +115,35 @@ | ||||
|                         .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; | ||||
|                                     } | ||||
|                                 } | ||||
|                             } | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
| @@ -390,6 +412,9 @@ | ||||
|  | ||||
|     input, | ||||
|     .p-password { | ||||
|         border-radius: 10px; | ||||
|         border: $default-border; | ||||
|  | ||||
|         &:focus { | ||||
|             box-shadow: none !important; | ||||
|         } | ||||
| @@ -434,7 +459,7 @@ | ||||
|         color: $primaryTextColor !important; | ||||
|         border: 0 !important; | ||||
|         padding: 0px !important; | ||||
|          | ||||
|  | ||||
|         &:hover { | ||||
|             background-color: transparent !important; | ||||
|             color: $primaryHeaderColor !important; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user