Guild & Level can be null
All checks were successful
Deploy prod on push / pre-build (push) Successful in 2s
Deploy prod on push / build-bot (push) Successful in 3m19s
Deploy prod on push / build-web (push) Successful in 1m58s
Deploy prod on push / deploy (push) Successful in 23s

This commit is contained in:
Sven Heidemann 2024-09-06 19:39:50 +02:00
parent b361a7b685
commit e785bddf2e
17 changed files with 250 additions and 195 deletions

View File

@ -1,4 +1,5 @@
from datetime import datetime
from typing import Optional
from cpl_core.database import TableABC
from cpl_core.dependency_injection import ServiceProviderABC
@ -48,8 +49,10 @@ class AutoRoleRule(TableABC):
@property
@ServiceProviderABC.inject
def role_name(self, bot: DiscordBotServiceABC) -> str:
def role_name(self, bot: DiscordBotServiceABC) -> Optional[str]:
guild = bot.get_guild(self.auto_role.server.discord_id)
if guild is None:
return None
return guild.get_role(self.role_id).name
@role_id.setter

View File

@ -1,3 +1,5 @@
from typing import Optional
from cpl_core.dependency_injection import ServiceProviderABC
from cpl_discord.service import DiscordBotServiceABC
@ -43,6 +45,8 @@ class AutoRoleRuleHistory(HistoryTableABC):
@property
@ServiceProviderABC.inject
def role_name(self, bot: DiscordBotServiceABC) -> str:
def role_name(self, bot: DiscordBotServiceABC) -> Optional[str]:
guild = bot.get_guild(self.auto_role.server.discord_id)
if guild is None:
return None
return guild.get_role(self.role_id).name

View File

@ -39,8 +39,10 @@ class Level(TableABC):
@property
@ServiceProviderABC.inject
def icon_url(self, bot: DiscordBotServiceABC) -> str:
def icon_url(self, bot: DiscordBotServiceABC) -> Optional[str]:
guild = bot.get_guild(self.server.discord_id)
if guild is None:
return None
role = List(Role, guild.roles).where(lambda x: x.name == self._name).first_or_default()
return None if role is None else role.icon

View File

@ -1,4 +1,5 @@
from datetime import datetime
from typing import Optional
from cpl_core.database import TableABC
from cpl_core.dependency_injection import ServiceProviderABC
@ -30,14 +31,18 @@ class Server(TableABC):
@property
@ServiceProviderABC.inject
def name(self, bot: DiscordBotServiceABC) -> str:
def name(self, bot: DiscordBotServiceABC) -> Optional[str]:
guild = bot.get_guild(self.discord_id)
if guild is None:
return None
return None if guild is None else guild.name
@property
@ServiceProviderABC.inject
def icon_url(self, bot: DiscordBotServiceABC) -> str:
def icon_url(self, bot: DiscordBotServiceABC) -> Optional[str]:
guild = bot.get_guild(self.discord_id)
if guild is None:
return None
return None if guild is None else guild.icon.url
@staticmethod

View File

@ -1,3 +1,5 @@
from typing import Optional
from cpl_core.dependency_injection import ServiceProviderABC
from cpl_discord.service import DiscordBotServiceABC
@ -32,12 +34,16 @@ class ServerHistory(HistoryTableABC):
@property
@ServiceProviderABC.inject
def name(self, bot: DiscordBotServiceABC) -> str:
def name(self, bot: DiscordBotServiceABC) -> Optional[str]:
guild = bot.get_guild(self.discord_id)
if guild is None:
return None
return None if guild is None else guild.name
@property
@ServiceProviderABC.inject
def icon_url(self, bot: DiscordBotServiceABC) -> str:
def icon_url(self, bot: DiscordBotServiceABC) -> Optional[str]:
guild = bot.get_guild(self.discord_id)
if guild is None:
return None
return None if guild is None else guild.icon.url

View File

@ -1,4 +1,5 @@
from datetime import datetime
from typing import Optional
from cpl_core.database import TableABC
from cpl_core.dependency_injection import ServiceProviderABC
@ -51,8 +52,10 @@ class ShortRoleName(TableABC):
@property
@ServiceProviderABC.inject
def role_name(self, bot: DiscordBotServiceABC) -> str:
def role_name(self, bot: DiscordBotServiceABC) -> Optional[str]:
guild = bot.get_guild(self._server.discord_id)
if guild is None:
return None
return guild.get_role(self.role_id).name
@property

View File

@ -1,3 +1,5 @@
from typing import Optional
from cpl_core.dependency_injection import ServiceProviderABC
from cpl_discord.service import DiscordBotServiceABC
@ -47,8 +49,10 @@ class ShortRoleNameHistory(HistoryTableABC):
@property
@ServiceProviderABC.inject
def role_name(self, bot: DiscordBotServiceABC) -> str:
def role_name(self, bot: DiscordBotServiceABC) -> Optional[str]:
guild = bot.get_guild(self._server.discord_id)
if guild is None:
return None
return guild.get_role(self.role_id).name
@property

View File

@ -53,15 +53,19 @@ class User(TableABC):
@property
@ServiceProviderABC.inject
def name(self, bot: DiscordBotServiceABC) -> str:
def name(self, bot: DiscordBotServiceABC) -> Optional[str]:
guild = bot.get_guild(self.server.discord_id)
if guild is None:
return None
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:
def icon_url(self, bot: DiscordBotServiceABC) -> Optional[str]:
guild = bot.get_guild(self.server.discord_id)
if guild is None:
return None
user = guild.get_member(self.discord_id)
return None if user is None else user.display_icon
@ -137,7 +141,7 @@ class User(TableABC):
@property
@ServiceProviderABC.inject
def level(self, services: ServiceProviderABC) -> Level:
def level(self, services: ServiceProviderABC) -> Optional[Level]:
from modules.level.service.level_service import LevelService
levels: LevelService = services.get_service(LevelService)
@ -175,8 +179,10 @@ class User(TableABC):
@property
@ServiceProviderABC.inject
def profile_picture_url(self, bot: DiscordBotServiceABC) -> str:
def profile_picture_url(self, bot: DiscordBotServiceABC) -> Optional[str]:
guild = bot.get_guild(self.server.discord_id)
if guild is None:
return None
user = guild.get_member(self._discord_id)
return None if user is None or user.avatar is None else user.avatar.url

View File

@ -51,6 +51,8 @@ class AutoRoleRuleFilter(FilterABC):
def get_role_name(x: AutoRoleRule):
guild = self._bot.get_guild(x.auto_role.server.discord_id)
if guild is None:
return False
name = guild.get_role(x.role_id).name
return name == self._role_name or self._role_name in name

View File

@ -57,6 +57,8 @@ class ShortRoleNameFilter(FilterABC):
def get_role_name(x: ShortRoleName):
guild = self._bot.get_guild(x.server.discord_id)
if guild is None:
return False
name = guild.get_role(x.role_id).name
return name == self._role_name or self._role_name in name

View File

@ -80,6 +80,8 @@ class UserFilter(FilterABC):
def _get_member(user: User):
guild = self._bot.get_guild(user.server.discord_id)
if guild is None:
return False
member = guild.get_member(user.discord_id)
return member is not None and (member.name == self._name or self._name in member.name)

View File

@ -8,7 +8,6 @@ from bot_data.abc.achievement_repository_abc import AchievementRepositoryABC
from bot_data.abc.auto_role_repository_abc import AutoRoleRepositoryABC
from bot_data.abc.client_repository_abc import ClientRepositoryABC
from bot_data.abc.game_server_repository_abc import GameServerRepositoryABC
from bot_data.abc.level_repository_abc import LevelRepositoryABC
from bot_data.abc.scheduled_event_repository_abc import ScheduledEventRepositoryABC
from bot_data.abc.server_config_repository_abc import ServerConfigRepositoryABC
from bot_data.abc.short_role_name_repository_abc import ShortRoleNameRepositoryABC
@ -31,6 +30,7 @@ from bot_graphql.filter.short_role_name_filter import ShortRoleNameFilter
from bot_graphql.filter.user_filter import UserFilter
from bot_graphql.filter.user_warning_filter import UserWarningFilter
from bot_graphql.model.server_statistics import ServerStatistics
from modules.level.service.level_service import LevelService
class ServerQuery(DataQueryWithHistoryABC):
@ -41,7 +41,7 @@ class ServerQuery(DataQueryWithHistoryABC):
db: DatabaseContextABC,
auto_roles: AutoRoleRepositoryABC,
clients: ClientRepositoryABC,
levels: LevelRepositoryABC,
levels: LevelService,
game_servers: GameServerRepositoryABC,
users: UserRepositoryABC,
ujs: UserJoinedServerRepositoryABC,

View File

@ -1,9 +1,12 @@
from typing import Optional
import discord
from cpl_core.configuration import ConfigurationABC
from cpl_core.database.context import DatabaseContextABC
from cpl_core.logging import LoggerABC
from cpl_discord.container import Guild, Role, Member
from cpl_discord.service import DiscordBotServiceABC
from cpl_query.extension import List
from cpl_translation import TranslatePipe
from bot_core.configuration.feature_flags_enum import FeatureFlagsEnum
@ -40,13 +43,26 @@ class LevelService:
self._message_service = message_service
self._t = t
def _check_for_feature(self, user: User):
server_config: ServerConfig = self._config.get_configuration(f"ServerConfig_{user.server.discord_id}")
def _check_for_feature(self, discord_id: int):
server_config: ServerConfig = self._config.get_configuration(f"ServerConfig_{discord_id}")
if not FeatureFlagsSettings.get_flag_from_dict(server_config.feature_flags, FeatureFlagsEnum.level_module):
raise Exception(f"Feature {FeatureFlagsEnum.level_module.value} disabled")
def get_level(self, user: User) -> Level:
self._check_for_feature(user)
def get_levels_by_server_id(self, server_id: int) -> List[Level]:
try:
self._check_for_feature(self._servers.get_server_by_id(server_id).discord_id)
except Exception as e:
self._logger.warn(__name__, f"Feature {FeatureFlagsEnum.level_module.value} disabled\n{e}")
return List(Level)
return self._levels.get_levels()
def get_level(self, user: User) -> Optional[Level]:
try:
self._check_for_feature(user.server.discord_id)
except Exception as e:
self._logger.warn(__name__, f"Feature {FeatureFlagsEnum.level_module.value} disabled\n{e}")
return None
levels_by_server = self._levels.get_levels_by_server_id(user.server.id)
if user.xp < 0:
@ -60,7 +76,7 @@ class LevelService:
return levels.last()
async def set_level(self, user: User):
self._check_for_feature(user)
self._check_for_feature(user.server.discord_id)
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()

View File

@ -1,5 +1,5 @@
<h1>
{{'view.server.members.header' | translate}}
{{ 'view.server.members.header' | translate }}
</h1>
<div class="content-wrapper">
<div class="content">
@ -12,10 +12,10 @@
<div class="table-caption">
<div class="table-caption-table-info">
<div class="table-caption-text">
<ng-container *ngIf="!loading">{{members.length}} {{'common.of' | translate}}
{{dt.totalRecords}}
<ng-container *ngIf="!loading">{{ members.length }} {{ 'common.of' | translate }}
{{ dt.totalRecords }}
</ng-container>
{{'view.server.members.members' | translate}}
{{ 'view.server.members.members' | translate }}
</div>
<app-multi-select-columns [table]="name" [columns]="columns"
@ -34,82 +34,82 @@
<tr>
<th hideable-th="id" [parent]="this" [sortable]="true">
<div class="table-header-label">
<div class="table-header-text">{{'common.id' | translate}}</div>
<div class="table-header-text">{{ 'common.id' | translate }}</div>
<p-sortIcon field="id" class="table-header-icon"></p-sortIcon>
</div>
</th>
<th hideable-th="discord_id" [parent]="this" [sortable]="true">
<div class="table-header-label">
<div class="table-header-text">{{'common.discord_id' | translate}}</div>
<div class="table-header-text">{{ 'common.discord_id' | translate }}</div>
<p-sortIcon field="discordId" class="table-header-icon"></p-sortIcon>
</div>
</th>
<th hideable-th="name" [parent]="this" [sortable]="true">
<div class="table-header-label">
<div class="table-header-text">{{'common.name' | translate}}</div>
<div class="table-header-text">{{ 'common.name' | translate }}</div>
<p-sortIcon field="name" class="table-header-icon"></p-sortIcon>
</div>
</th>
<th hideable-th="xp" [parent]="this" [sortable]="true">
<div class="table-header-label">
<div class="table-header-text">{{'common.xp' | translate}}</div>
<div class="table-header-text">{{ 'common.xp' | translate }}</div>
<p-sortIcon field="xp" class="table-header-icon"></p-sortIcon>
</div>
</th>
<th hideable-th="ontime" [parent]="this" [sortable]="true">
<div class="table-header-label">
<div class="table-header-text">{{'common.ontime' | translate}}</div>
<div class="table-header-text">{{ 'common.ontime' | translate }}</div>
<p-sortIcon field="ontime" class="table-header-icon"></p-sortIcon>
</div>
</th>
<th hideable-th="game_ontime" [parent]="this" [sortable]="true">
<div class="table-header-label">
<div class="table-header-text">{{'common.game_ontime' | translate}}</div>
<div class="table-header-text">{{ 'common.game_ontime' | translate }}</div>
<p-sortIcon field="game_ontime" class="table-header-icon"></p-sortIcon>
</div>
</th>
<th hideable-th="activity" [parent]="this" [sortable]="true">
<div class="table-header-label">
<div class="table-header-text">{{'common.activity' | translate}}</div>
<div class="table-header-text">{{ 'common.activity' | translate }}</div>
<p-sortIcon field="activityScore" class="table-header-icon"></p-sortIcon>
</div>
</th>
<th hideable-th="left_server" [parent]="this" [sortable]="true">
<div class="table-header-label">
<div class="table-header-text">{{'common.left_server' | translate}}</div>
<div class="table-header-text">{{ 'common.left_server' | translate }}</div>
<p-sortIcon field="leftServer" class="table-header-icon"></p-sortIcon>
</div>
</th>
<th hideable-th="level" subColumn="level.min_xp" [parent]="this" [sortable]="true">
<div class="table-header-label">
<div class="table-header-text">{{'common.level' | translate}}</div>
<div class="table-header-text">{{ 'common.level' | translate }}</div>
<p-sortIcon field="level" class="table-header-icon"></p-sortIcon>
</div>
</th>
<th>
<div class="table-header-label">
<div class="table-header-text">{{'common.created_at' | translate}}</div>
<div class="table-header-text">{{ 'common.created_at' | translate }}</div>
</div>
</th>
<th>
<div class="table-header-label">
<div class="table-header-text">{{'common.modified_at' | translate}}</div>
<div class="table-header-text">{{ 'common.modified_at' | translate }}</div>
</div>
</th>
<th>
<div class="table-header-label">
<div class="table-header-text">{{'common.actions' | translate}}</div>
<div class="table-header-text">{{ 'common.actions' | translate }}</div>
</div>
</th>
</tr>
@ -156,124 +156,124 @@
<ng-template pTemplate="body" let-member let-editing="editing" let-ri="rowIndex">
<tr [pEditableRow]="member">
<td hideable-th="id" [parent]="this">
<span class="p-column-title">{{'common.id' | translate}}:</span>
<span class="p-column-title">{{ 'common.id' | translate }}:</span>
<p-cellEditor>
<ng-template pTemplate="input">
{{member.id}}
{{ member.id }}
</ng-template>
<ng-template pTemplate="output">
{{member.id}}
{{ member.id }}
</ng-template>
</p-cellEditor>
</td>
<td hideable-th="discord_id" [parent]="this">
<span class="p-column-title">{{'common.discord_id' | translate}}:</span>
<span class="p-column-title">{{ 'common.discord_id' | translate }}:</span>
<p-cellEditor>
<ng-template pTemplate="input">
{{member.discordId}}
{{ member.discordId }}
</ng-template>
<ng-template pTemplate="output">
{{member.discordId}}
{{ member.discordId }}
</ng-template>
</p-cellEditor>
</td>
<td hideable-th="name" [parent]="this">
<span class="p-column-title">{{'common.name' | translate}}:</span>
<span class="p-column-title">{{ 'common.name' | translate }}:</span>
<p-cellEditor>
<ng-template pTemplate="input">
{{member.name}}
{{ member.name }}
</ng-template>
<ng-template pTemplate="output">
{{member.name}}
{{ member.name }}
</ng-template>
</p-cellEditor>
</td>
<td hideable-th="xp" [parent]="this">
<span class="p-column-title">{{'common.xp' | translate}}:</span>
<span class="p-column-title">{{ 'common.xp' | translate }}:</span>
<p-cellEditor>
<ng-template pTemplate="input">
<input class="table-edit-input" pInputText min="0" type="number" [(ngModel)]="member.xp">
</ng-template>
<ng-template pTemplate="output">
{{member.xp}}
{{ member.xp }}
</ng-template>
</p-cellEditor>
</td>
<td hideable-th="ontime" [parent]="this">
<span class="p-column-title">{{'common.ontime' | translate}}:</span>
<span class="p-column-title">{{ 'common.ontime' | translate }}:</span>
<p-cellEditor>
<ng-template pTemplate="input">
{{member.ontime}}
{{ member.ontime }}
</ng-template>
<ng-template pTemplate="output">
{{member.ontime}}
{{ member.ontime }}
</ng-template>
</p-cellEditor>
</td>
<td hideable-th="game_ontime" [parent]="this">
<span class="p-column-title">{{'common.game_ontime' | translate}}:</span>
<span class="p-column-title">{{ 'common.game_ontime' | translate }}:</span>
<p-cellEditor>
<ng-template pTemplate="input">
{{member.gameOntime}}
{{ member.gameOntime }}
</ng-template>
<ng-template pTemplate="output">
{{member.gameOntime}}
{{ member.gameOntime }}
</ng-template>
</p-cellEditor>
</td>
<td hideable-th="activity" [parent]="this">
<span class="p-column-title">{{'common.activity' | translate}}:</span>
<span class="p-column-title">{{ 'common.activity' | translate }}:</span>
<p-cellEditor>
<ng-template pTemplate="input">
{{member.activityScore}}
{{ member.activityScore }}
</ng-template>
<ng-template pTemplate="output">
{{member.activityScore}}
{{ member.activityScore }}
</ng-template>
</p-cellEditor>
</td>
<td hideable-th="left_server" [parent]="this">
<span class="p-column-title">{{'common.left_server' | translate}}:</span>
<span class="p-column-title">{{ 'common.left_server' | translate }}:</span>
<p-cellEditor>
<ng-template pTemplate="input">
{{!member.leftServer | bool}}
{{ !member.leftServer | bool }}
</ng-template>
<ng-template pTemplate="output">
{{!member.leftServer | bool}}
{{ !member.leftServer | bool }}
</ng-template>
</p-cellEditor>
</td>
<td hideable-th="level" [parent]="this">
<span class="p-column-title">{{'common.level' | translate}}:</span>
<span class="p-column-title">{{ 'common.level' | translate }}:</span>
<p-cellEditor>
<ng-template pTemplate="input">
<p-dropdown [options]="levels" [(ngModel)]="member.level" dataKey="id"
placeholder="{{'common.level' | translate}}"></p-dropdown>
</ng-template>
<ng-template pTemplate="output">
{{member.level.name}}
{{ member.level?.name }}
</ng-template>
</p-cellEditor>
</td>
<td>
<span class="p-column-title">{{'common.created_at' | translate}}:</span>
<span class="p-column-title">{{ 'common.created_at' | translate }}:</span>
<p-cellEditor>
<ng-template pTemplate="input">
{{member.createdAt | date:'dd.MM.yy HH:mm'}}
{{ member.createdAt | date:'dd.MM.yy HH:mm' }}
</ng-template>
<ng-template pTemplate="output">
{{member.createdAt | date:'dd.MM.yy HH:mm'}}
{{ member.createdAt | date:'dd.MM.yy HH:mm' }}
</ng-template>
</p-cellEditor>
</td>
<td>
<span class="p-column-title">{{'common.modified_at' | translate}}:</span>
<span class="p-column-title">{{ 'common.modified_at' | translate }}:</span>
<p-cellEditor>
<ng-template pTemplate="input">
{{member.modifiedAt | date:'dd.MM.yy HH:mm'}}
{{ member.modifiedAt | date:'dd.MM.yy HH:mm' }}
</ng-template>
<ng-template pTemplate="output">
{{member.modifiedAt | date:'dd.MM.yy HH:mm'}}
{{ member.modifiedAt | date:'dd.MM.yy HH:mm' }}
</ng-template>
</p-cellEditor>
</td>
@ -298,7 +298,7 @@
<ng-template pTemplate="emptymessage">
<tr></tr>
<tr>
<td colspan="10">{{'common.no_entries_found' | translate}}</td>
<td colspan="10">{{ 'common.no_entries_found' | translate }}</td>
</tr>
<tr></tr>
</ng-template>

View File

@ -1,5 +1,5 @@
<h1>
{{'view.server.profile.header' | translate}}
{{ 'view.server.profile.header' | translate }}
</h1>
<div class="content-wrapper">
<div class="content">
@ -11,27 +11,27 @@
</div>
<div class="content">
<div class="content-column">
<h1>{{user.name}}</h1>
<h1>{{ user.name }}</h1>
</div>
<div class="content-column">
<div class="content-data-name">{{'common.id' | translate}}:</div>
<div class="content-data-value">{{user.id}}</div>
<div class="content-data-name">{{ 'common.id' | translate }}:</div>
<div class="content-data-value">{{ user.id }}</div>
</div>
<div class="content-column">
<div class="content-data-name">{{'common.discord_id' | translate}}:</div>
<div class="content-data-value">{{user.discordId}}</div>
<div class="content-data-name">{{ 'common.discord_id' | translate }}:</div>
<div class="content-data-value">{{ user.discordId }}</div>
</div>
<div class="content-column">
<div class="content-data-name">{{'view.server.profile.message_count' | translate}}:</div>
<div class="content-data-value">{{user.messageCount}}</div>
<div class="content-data-name">{{ 'view.server.profile.message_count' | translate }}:</div>
<div class="content-data-value">{{ user.messageCount }}</div>
</div>
<div class="content-column">
<div class="content-data-name">{{'view.server.profile.reaction_count' | translate}}:</div>
<div class="content-data-value">{{user.reactionCount}}</div>
<div class="content-data-name">{{ 'view.server.profile.reaction_count' | translate }}:</div>
<div class="content-data-value">{{ user.reactionCount }}</div>
</div>
<div class="content-column">
<div class="content-data-name">{{'view.server.profile.birthday' | translate}}:</div>
<div *ngIf="!isEditing" class="content-data-value">{{user.birthday}}</div>
<div class="content-data-name">{{ 'view.server.profile.birthday' | translate }}:</div>
<div *ngIf="!isEditing" class="content-data-value">{{ user.birthday }}</div>
<div *ngIf="isEditing" class="content-data-value">
<p-calendar [(ngModel)]="user.birthday" dateFormat="dd.mm.yy"
[showIcon]="true"></p-calendar>
@ -39,16 +39,16 @@
</div>
<div class="content-divider"></div>
<div class="content-column">
<div class="content-data-name">{{'view.server.profile.left_server' | translate}}:</div>
<div class="content-data-value">{{user.leftServer | bool}}</div>
<div class="content-data-name">{{ 'view.server.profile.left_server' | translate }}:</div>
<div class="content-data-value">{{ user.leftServer | bool }}</div>
</div>
<div class="content-column">
<div class="content-data-name">{{'common.created_at' | translate}}:</div>
<div class="content-data-value">{{user.createdAt | date:'dd.MM.yyyy HH:mm:ss'}}</div>
<div class="content-data-name">{{ 'common.created_at' | translate }}:</div>
<div class="content-data-value">{{ user.createdAt | date:'dd.MM.yyyy HH:mm:ss' }}</div>
</div>
<div class="content-column">
<div class="content-data-name">{{'common.modified_at' | translate}}:</div>
<div class="content-data-value">{{user.modifiedAt | date:'dd.MM.yyyy HH:mm:ss'}}</div>
<div class="content-data-name">{{ 'common.modified_at' | translate }}:</div>
<div class="content-data-value">{{ user.modifiedAt | date:'dd.MM.yyyy HH:mm:ss' }}</div>
</div>
</div>
<div class="content">
@ -68,22 +68,22 @@
[readonly]="isModerator && !isEditing"></p-knob>
<div *ngIf="user.level">
{{user.level.name}}
{{ user.level.name }}
</div>
</div>
</div>
<div class="content-divider"></div>
<div class="content-column">
<div class="content-data-name">{{'common.ontime' | translate}}:</div>
<div class="content-data-value">{{user.ontime}}</div>
<div class="content-data-name">{{ 'common.ontime' | translate }}:</div>
<div class="content-data-value">{{ user.ontime }}</div>
</div>
<div class="content-column">
<div class="content-data-name">{{'common.game_ontime' | translate}}:</div>
<div class="content-data-value">{{user.gameOntime}}</div>
<div class="content-data-name">{{ 'common.game_ontime' | translate }}:</div>
<div class="content-data-value">{{ user.gameOntime }}</div>
</div>
<div class="content-column">
<div class="content-data-name">{{'common.activity' | translate}}:</div>
<div class="content-data-value">{{user.activityScore}}</div>
<div class="content-data-name">{{ 'common.activity' | translate }}:</div>
<div class="content-data-value">{{ user.activityScore }}</div>
</div>
</div>
</div>
@ -99,7 +99,7 @@
<div class="table-caption">
<div class="table-caption-table-info">
<div class="table-caption-text">
<h3>{{'common.user_warnings' | translate}}</h3>
<h3>{{ 'common.user_warnings' | translate }}</h3>
</div>
</div>
<div class="table-caption-btn-wrapper btn-wrapper">
@ -113,25 +113,25 @@
<tr>
<th>
<div class="table-header-label">
<div class="table-header-text">{{'common.description' | translate}}</div>
<div class="table-header-text">{{ 'common.description' | translate }}</div>
</div>
</th>
<th>
<div class="table-header-label">
<div class="table-header-text">{{'common.author' | translate}}</div>
<div class="table-header-text">{{ 'common.author' | translate }}</div>
</div>
</th>
<th>
<div class="table-header-label">
<div class="table-header-text">{{'common.created_at' | translate}}</div>
<div class="table-header-text">{{ 'common.created_at' | translate }}</div>
</div>
</th>
<th class="table-header-actions">
<div class="table-header-label">
<div class="table-header-text">{{'common.actions' | translate}}</div>
<div class="table-header-text">{{ 'common.actions' | translate }}</div>
</div>
</th>
</tr>
@ -144,29 +144,29 @@
<input class="table-edit-input" pInputText type="text" [(ngModel)]="value.description">
</ng-template>
<ng-template pTemplate="output">
{{value.description}}
{{ value.description }}
</ng-template>
</p-cellEditor>
</td>
<td>
<p-cellEditor>
<ng-template pTemplate="input">
{{value.author?.name}}
{{ value.author?.name }}
</ng-template>
<ng-template pTemplate="output">
{{value.author?.name}}
{{ value.author?.name }}
</ng-template>
</p-cellEditor>
</td>
<td>
<span class="p-column-title">{{'common.created_at' | translate}}:</span>
<span class="p-column-title">{{ 'common.created_at' | translate }}:</span>
<p-cellEditor>
<ng-template pTemplate="input">
{{value.createdAt | date:'dd.MM.yy HH:mm'}}
{{ value.createdAt | date:'dd.MM.yy HH:mm' }}
</ng-template>
<ng-template pTemplate="output">
{{value.createdAt | date:'dd.MM.yy HH:mm'}}
{{ value.createdAt | date:'dd.MM.yy HH:mm' }}
</ng-template>
</p-cellEditor>
</td>
@ -196,18 +196,18 @@
<div *ngFor="let achievement of user.achievements;">
<div class="content-row">
<div class="content-column">
<div class="content-data-name">{{'common.name' | translate}}:</div>
<div class="content-data-value">{{achievement.name}}</div>
<div class="content-data-name">{{ 'common.name' | translate }}:</div>
<div class="content-data-value">{{ achievement.name }}</div>
</div>
<div class="content-column">
<div class="content-data-name">{{'common.description' | translate}}:</div>
<div class="content-data-value">{{achievement.description}}</div>
<div class="content-data-name">{{ 'common.description' | translate }}:</div>
<div class="content-data-value">{{ achievement.description }}</div>
</div>
<div class="content-column">
<div class="content-data-name">{{'view.server.profile.achievements.time' | translate}}:</div>
<div class="content-data-value">{{achievement.createdAt | date:'dd.MM.yyyy HH:mm:ss'}}</div>
<div class="content-data-name">{{ 'view.server.profile.achievements.time' | translate }}:</div>
<div class="content-data-value">{{ achievement.createdAt | date:'dd.MM.yyyy HH:mm:ss' }}</div>
</div>
</div>
</div>
@ -219,30 +219,30 @@
<div *ngFor="let join of user.joinedVoiceChannels;">
<div class="content-row">
<div class="content-column" style="flex: 0.3;">
<div class="content-data-name">{{'common.id' | translate}}:</div>
<div class="content-data-value">{{join.id}}</div>
<div class="content-data-name">{{ 'common.id' | translate }}:</div>
<div class="content-data-value">{{ join.id }}</div>
</div>
<div class="content-column" style="flex: 0.75;">
<div class="content-data-name"
style="flex: 0.35;">{{'view.server.profile.joined_voice_channel.time' | translate}}:
style="flex: 0.35;">{{ 'view.server.profile.joined_voice_channel.time' | translate }}:
</div>
<div class="content-data-value">{{join.time}} {{'general.hours' | translate}}</div>
<div class="content-data-value">{{ join.time }} {{ 'general.hours' | translate }}</div>
</div>
<div class="content-column" style="flex: 1;">
<div class="content-data-name">{{'view.server.profile.joined_voice_channel.channel' | translate}}:</div>
<div class="content-data-value">{{join.channelName}}</div>
<div class="content-data-name">{{ 'view.server.profile.joined_voice_channel.channel' | translate }}:</div>
<div class="content-data-value">{{ join.channelName }}</div>
</div>
<div class="content-column">
<div class="content-data-name">{{'common.joined_at' | translate}}:</div>
<div class="content-data-value">{{join.joinedOn | date:'dd.MM.yyyy HH:mm:ss'}}</div>
<div class="content-data-name">{{ 'common.joined_at' | translate }}:</div>
<div class="content-data-value">{{ join.joinedOn | date:'dd.MM.yyyy HH:mm:ss' }}</div>
</div>
<div class="content-column">
<div class="content-data-name">{{'common.leaved_at' | translate}}:</div>
<div class="content-data-value">{{join.leavedOn | date:'dd.MM.yyyy HH:mm:ss'}}</div>
<div class="content-data-name">{{ 'common.leaved_at' | translate }}:</div>
<div class="content-data-value">{{ join.leavedOn | date:'dd.MM.yyyy HH:mm:ss' }}</div>
</div>
</div>
</div>
@ -254,30 +254,30 @@
<div *ngFor="let join of user.userJoinedGameServers;">
<div class="content-row">
<div class="content-column" style="flex: 0.3;">
<div class="content-data-name">{{'common.id' | translate}}:</div>
<div class="content-data-value">{{join.id}}</div>
<div class="content-data-name">{{ 'common.id' | translate }}:</div>
<div class="content-data-value">{{ join.id }}</div>
</div>
<div class="content-column" style="flex: 0.75;">
<div class="content-data-name"
style="flex: 0.35;">{{'view.server.profile.joined_game_server.time' | translate}}:
style="flex: 0.35;">{{ 'view.server.profile.joined_game_server.time' | translate }}:
</div>
<div class="content-data-value">{{join.time}} {{'general.hours' | translate}}</div>
<div class="content-data-value">{{ join.time }} {{ 'general.hours' | translate }}</div>
</div>
<div class="content-column" style="flex: 1;">
<div class="content-data-name">{{'view.server.profile.joined_game_server.name' | translate}}:</div>
<div class="content-data-value">{{join.gameServer}}</div>
<div class="content-data-name">{{ 'view.server.profile.joined_game_server.name' | translate }}:</div>
<div class="content-data-value">{{ join.gameServer }}</div>
</div>
<div class="content-column">
<div class="content-data-name">{{'common.joined_at' | translate}}:</div>
<div class="content-data-value">{{join.joinedOn | date:'dd.MM.yyyy HH:mm:ss'}}</div>
<div class="content-data-name">{{ 'common.joined_at' | translate }}:</div>
<div class="content-data-value">{{ join.joinedOn | date:'dd.MM.yyyy HH:mm:ss' }}</div>
</div>
<div class="content-column">
<div class="content-data-name">{{'common.leaved_at' | translate}}:</div>
<div class="content-data-value">{{join.leavedOn | date:'dd.MM.yyyy HH:mm:ss'}}</div>
<div class="content-data-name">{{ 'common.leaved_at' | translate }}:</div>
<div class="content-data-value">{{ join.leavedOn | date:'dd.MM.yyyy HH:mm:ss' }}</div>
</div>
</div>
</div>
@ -287,13 +287,13 @@
<div *ngFor="let join of user.joinedServers;">
<div class="content-row">
<div class="content-column">
<div class="content-data-name">{{'common.joined_at' | translate}}:</div>
<div class="content-data-value">{{join.joinedOn | date:'dd.MM.yyyy HH:mm:ss'}}</div>
<div class="content-data-name">{{ 'common.joined_at' | translate }}:</div>
<div class="content-data-value">{{ join.joinedOn | date:'dd.MM.yyyy HH:mm:ss' }}</div>
</div>
<div class="content-column">
<div class="content-data-name">{{'common.leaved_at' | translate}}:</div>
<div class="content-data-value">{{join.leavedOn | date:'dd.MM.yyyy HH:mm:ss'}}</div>
<div class="content-data-name">{{ 'common.leaved_at' | translate }}:</div>
<div class="content-data-value">{{ join.leavedOn | date:'dd.MM.yyyy HH:mm:ss' }}</div>
</div>
</div>
</div>