Added server list to dashboard #72

This commit is contained in:
Sven Heidemann 2022-10-17 18:12:43 +02:00
parent 1baa8cee60
commit a69c223a33
10 changed files with 190 additions and 33 deletions

View File

@ -1,3 +1,5 @@
from typing import Optional
from bot_api.abc.dto_abc import DtoABC from bot_api.abc.dto_abc import DtoABC
@ -8,7 +10,8 @@ class ServerDTO(DtoABC):
server_id: int, server_id: int,
discord_id: int, discord_id: int,
name: str, name: str,
member_count: int member_count: int,
icon_url: Optional[str]
): ):
DtoABC.__init__(self) DtoABC.__init__(self)
@ -17,6 +20,7 @@ class ServerDTO(DtoABC):
self._discord_id = discord_id self._discord_id = discord_id
self._name = name self._name = name
self._member_count = member_count self._member_count = member_count
self._icon_url = icon_url
@property @property
def server_id(self) -> int: def server_id(self) -> int:
@ -34,11 +38,15 @@ class ServerDTO(DtoABC):
def member_count(self) -> int: def member_count(self) -> int:
return self._member_count return self._member_count
@property
def icon_url(self) -> Optional[str]:
return self._icon_url
def from_dict(self, values: dict): def from_dict(self, values: dict):
self._server_id = int(values['serverId']) self._server_id = int(values['serverId'])
self._discord_id = int(values['discordId']) self._discord_id = int(values['discordId'])
self._name = values['name'] self._name = values['name']
self._member_count = int(values['memberCount']) self._icon_url = int(values['iconURL'])
def to_dict(self) -> dict: def to_dict(self) -> dict:
return { return {
@ -46,4 +54,5 @@ class ServerDTO(DtoABC):
'discordId': self._discord_id, 'discordId': self._discord_id,
'name': self._name, 'name': self._name,
'memberCount': self._member_count, 'memberCount': self._member_count,
'iconURL': self._icon_url,
} }

View File

@ -33,9 +33,12 @@ class DiscordService:
async def get_all_servers(self) -> List[ServerDTO]: async def get_all_servers(self) -> List[ServerDTO]:
servers = self._servers.get_servers() servers = self._servers.get_servers()
return servers.select( return servers.select(lambda x: ServerTransformer.to_dto(
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) 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]: async def get_all_servers_by_user(self) -> List[ServerDTO]:
token = self._auth.get_decoded_token_from_request() 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) 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) 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( return servers.select(lambda x: ServerTransformer.to_dto(
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) 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: async def get_filtered_servers_async(self, criteria: ServerSelectCriteria) -> ServerFilteredResultDTO:
token = self._auth.get_decoded_token_from_request() 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) servers = servers.where(lambda x: user_from_db is not None and x.server_id == user_from_db.server.server_id)
result = servers.select( 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( return ServerFilteredResultDTO(
List(ServerDTO, result), List(ServerDTO, result),
filtered_result.total_count filtered_result.total_count

View File

@ -1,3 +1,7 @@
from typing import Optional
import discord
from bot_api.abc.transformer_abc import TransformerABC from bot_api.abc.transformer_abc import TransformerABC
from bot_api.model.discord.server_dto import ServerDTO from bot_api.model.discord.server_dto import ServerDTO
from bot_data.model.server import Server from bot_data.model.server import Server
@ -10,10 +14,11 @@ class ServerTransformer(TransformerABC):
return Server(dto.discord_id) return Server(dto.discord_id)
@staticmethod @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( return ServerDTO(
db.server_id, db.server_id,
db.discord_server_id, db.discord_server_id,
name, name,
member_count, member_count,
icon_url.url if icon_url is not None else None,
) )

View File

@ -35,9 +35,6 @@ class ServerRepositoryService(ServerRepositoryABC):
self._logger.trace(__name__, f'Send SQL command: {Server.get_select_all_string()}') self._logger.trace(__name__, f'Send SQL command: {Server.get_select_all_string()}')
query = servers 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 # sort
if criteria.sort_column is not None and criteria.sort_column != '' and criteria.sort_direction is not None and criteria.sort_direction: 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() crit_sort_direction = criteria.sort_direction.lower()

View File

@ -3,4 +3,5 @@ export interface ServerDTO {
discordId: number; discordId: number;
name: string; name: string;
memberCount: number; memberCount: number;
iconURL: string | null;
} }

View File

@ -2,11 +2,49 @@
{{'view.dashboard.header' | translate}} {{'view.dashboard.header' | translate}}
</h1> </h1>
<div class="content-wrapper"> <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"> <div class="content">
<ul> <div class="server-list-wrapper">
<li *ngFor="let server of servers"> <div class="server-filter">
{{server.name}} <form [formGroup]="filterForm">
</li> <div class="input-field">
</ul> <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>
</div> </div>

View File

@ -107,7 +107,16 @@
}, },
"view": { "view": {
"dashboard": { "dashboard": {
"header": "Dashboard" "header": "Dashboard",
"of": "von",
"servers": "Server",
"server": {
"header": "Server",
"member_count": "Mitglid(er)"
},
"filter": {
"name": "Name"
}
}, },
"user-list": {}, "user-list": {},
"change-password": { "change-password": {

View File

@ -10,6 +10,8 @@ body {
height: 100%; height: 100%;
padding: 0; padding: 0;
margin: 0; margin: 0;
font-size: 1rem;
} }
main { main {
@ -18,15 +20,19 @@ main {
min-height: 100vh; min-height: 100vh;
} }
h1, h1 {
h2 {
margin: 0; margin: 0;
font-size: 30px; font-size: 1.75rem;
} }
h2 { h2 {
margin: 0; margin: 0;
font-size: 25px; font-size: 1.5rem;
}
h3 {
margin: 0;
font-size: 1.25rem;
} }
header { header {
@ -207,6 +213,59 @@ header {
.table-header-small-dropdown { .table-header-small-dropdown {
width: 150px; 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 {
}
}
}
}
}
} }
} }
} }

View File

@ -432,7 +432,7 @@
color: $primaryTextColor !important; color: $primaryTextColor !important;
border: 0 !important; border: 0 !important;
padding: 0px !important; padding: 0px !important;
&:hover { &:hover {
background-color: transparent !important; background-color: transparent !important;
color: $primaryHeaderColor !important; color: $primaryHeaderColor !important;

View File

@ -15,17 +15,10 @@
$primaryErrorColor: #b00020; $primaryErrorColor: #b00020;
$secondaryErrorColor: #e94948; $secondaryErrorColor: #e94948;
$default-border: 1px solid $secondaryBackgroundColor3; $default-border: 2px solid $secondaryBackgroundColor3;
background-color: $primaryBackgroundColor !important; background-color: $primaryBackgroundColor !important;
html,
body {
margin: 0;
font-size: 16px;
}
h1, h1,
h2 { h2 {
color: $primaryHeaderColor; color: $primaryHeaderColor;
@ -122,6 +115,35 @@
.content-divider { .content-divider {
border-bottom: $default-border; 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, input,
.p-password { .p-password {
border-radius: 10px;
border: $default-border;
&:focus { &:focus {
box-shadow: none !important; box-shadow: none !important;
} }
@ -434,7 +459,7 @@
color: $primaryTextColor !important; color: $primaryTextColor !important;
border: 0 !important; border: 0 !important;
padding: 0px !important; padding: 0px !important;
&:hover { &:hover {
background-color: transparent !important; background-color: transparent !important;
color: $primaryHeaderColor !important; color: $primaryHeaderColor !important;