14 Commits

Author SHA1 Message Date
560c7650bd Merge pull request 'Removed native password & disable ssl' (#454) from staging into master
All checks were successful
Deploy prod on push / on-push-deploy_sh-edraft (push) Successful in 3m24s
Reviewed-on: #454
2023-12-06 18:28:55 +01:00
b0fb12f841 Removed native password & disable ssl
All checks were successful
Deploy staging on push / on-push-deploy_sh-edraft (push) Successful in 5m13s
2023-12-06 17:59:23 +01:00
18386339b7 Merge pull request 'staging' (#453) from staging into master
All checks were successful
Deploy prod on push / on-push-deploy_sh-edraft (push) Successful in 3m21s
Reviewed-on: #453
2023-12-04 23:04:29 +01:00
4d980331e2 Merge pull request 'Added user activity score #451' (#452) from dev into staging
All checks were successful
Deploy staging on push / on-push-deploy_sh-edraft (push) Successful in 3m18s
Reviewed-on: #452
2023-12-04 22:55:03 +01:00
e6667c78c8 Added user activity score #451
All checks were successful
Deploy dev on push / on-push-deploy_sh-edraft (push) Successful in 4m14s
2023-12-04 22:48:26 +01:00
9976c59302 Fixed permission service
All checks were successful
Deploy staging on push / on-push-deploy_sh-edraft (push) Successful in 4m42s
Deploy dev on push / on-push-deploy_sh-edraft (push) Successful in 3m27s
2023-12-03 16:42:33 +01:00
293c8cd81c Merge pull request 'dev into staging' (#450) from dev into staging
All checks were successful
Deploy staging on push / on-push-deploy_sh-edraft (push) Successful in 3m34s
Reviewed-on: #450
2023-12-03 16:08:24 +01:00
8f4ea56184 Merge branch 'staging' into dev
All checks were successful
Deploy dev on push / on-push-deploy_sh-edraft (push) Successful in 4m2s
2023-12-03 16:07:29 +01:00
898e005978 Merge pull request 'Improved ontime loading & added game ontime #446' (#449) from #446 into dev
All checks were successful
Deploy dev on push / on-push-deploy_sh-edraft (push) Successful in 4m58s
Reviewed-on: #449
2023-12-03 16:06:50 +01:00
db3e6183ba Merge branch 'dev' into #446 2023-12-03 16:06:36 +01:00
0a47393510 Improved ontime loading & added game ontime #446 2023-12-03 16:04:56 +01:00
db61a764eb Merge pull request 'staging' (#447) from staging into master
All checks were successful
Deploy prod on push / on-push-deploy_sh-edraft (push) Successful in 3m45s
Reviewed-on: #447
2023-12-02 19:34:22 +01:00
919eef79f6 Merge branch 'master' into staging
All checks were successful
Deploy staging on push / on-push-deploy_sh-edraft (push) Successful in 3m58s
2023-12-02 19:33:58 +01:00
5de6710261 Merge pull request 'staging' (#435) from staging into master
All checks were successful
Deploy prod on push / on-push-deploy_sh-edraft (push) Successful in 3m34s
Reviewed-on: #435
2023-11-07 20:37:13 +01:00
19 changed files with 250 additions and 70 deletions

View File

@@ -16,7 +16,7 @@
"LicenseName": "MIT", "LicenseName": "MIT",
"LicenseDescription": "MIT, see LICENSE for more details.", "LicenseDescription": "MIT, see LICENSE for more details.",
"Dependencies": [ "Dependencies": [
"cpl-core==2023.10.0", "cpl-core==2023.10.1",
"cpl-translation==2023.4.0.post1", "cpl-translation==2023.4.0.post1",
"cpl-query==2023.10.0", "cpl-query==2023.10.0",
"cpl-discord==2023.10.0.post1", "cpl-discord==2023.10.0.post1",

View File

@@ -74,7 +74,7 @@ class PermissionService(PermissionServiceABC):
self._logger.debug(__name__, f"Checking is member {member.name} {team_member_type.value}") self._logger.debug(__name__, f"Checking is member {member.name} {team_member_type.value}")
has_permission = True in [ has_permission = True in [
member.guild.get_role(x.role_id) not in member.roles member.guild.get_role(x.role_id) in member.roles
for x in self._server_configs.get_server_config_by_server( for x in self._server_configs.get_server_config_by_server(
self._servers.get_server_by_discord_id(member.guild.id).id self._servers.get_server_by_discord_id(member.guild.id).id
).team_role_ids ).team_role_ids

View File

@@ -31,6 +31,10 @@ class UserRepositoryABC(ABC):
def get_users_by_server_id(self, server_id: int) -> List[User]: def get_users_by_server_id(self, server_id: int) -> List[User]:
pass pass
@abstractmethod
def get_users_with_activity_by_server_id(self, server_id: int) -> List[User]:
pass
@abstractmethod @abstractmethod
def get_user_by_discord_id_and_server_id(self, discord_id: int, server_id: int) -> User: def get_user_by_discord_id_and_server_id(self, discord_id: int, server_id: int) -> User:
pass pass

View File

@@ -2,6 +2,7 @@ from datetime import datetime, date
from typing import Optional from typing import Optional
from cpl_core.database import TableABC from cpl_core.database import TableABC
from cpl_core.database.context import DatabaseContextABC
from cpl_core.dependency_injection import ServiceProviderABC from cpl_core.dependency_injection import ServiceProviderABC
from cpl_discord.service import DiscordBotServiceABC from cpl_discord.service import DiscordBotServiceABC
from cpl_query.extension import List from cpl_query.extension import List
@@ -31,6 +32,8 @@ class User(TableABC):
self._birthday = birthday self._birthday = birthday
self._server = server self._server = server
self._activity = 0
TableABC.__init__(self) TableABC.__init__(self)
self._created_at = created_at if created_at is not None else self._created_at self._created_at = created_at if created_at is not None else self._created_at
self._modified_at = modified_at if modified_at is not None else self._modified_at self._modified_at = modified_at if modified_at is not None else self._modified_at
@@ -92,10 +95,40 @@ class User(TableABC):
@property @property
@ServiceProviderABC.inject @ServiceProviderABC.inject
def ontime(self, services: ServiceProviderABC) -> float: def ontime(self, services: ServiceProviderABC) -> float:
from bot_core.abc.client_utils_abc import ClientUtilsABC db: DatabaseContextABC = services.get_service(DatabaseContextABC)
result = db.select(
f"""
SELECT ROUND(SUM(TIME_TO_SEC(TIMEDIFF(UserJoinedVoiceChannel.LeavedOn, UserJoinedVoiceChannel.JoinedOn)) / 3600),2)
FROM UserJoinedVoiceChannel
WHERE UserId = {self._user_id};
"""
)[0][0]
if result is None:
return 0
return float(result)
client_utils: ClientUtilsABC = services.get_service(ClientUtilsABC) @property
return client_utils.get_ontime_for_user(self) @ServiceProviderABC.inject
def game_ontime(self, services: ServiceProviderABC) -> float:
db: DatabaseContextABC = services.get_service(DatabaseContextABC)
result = db.select(
f"""
SELECT ROUND(SUM(TIME_TO_SEC(TIMEDIFF(UserJoinedGameServer.LeavedOn, UserJoinedGameServer.JoinedOn)) / 3600),2)
FROM UserJoinedGameServer
WHERE UserId = {self._user_id};
"""
)[0][0]
if result is None:
return 0
return float(result)
@property
def activity(self) -> int:
return self._activity
@activity.setter
def activity(self, value: int):
self._activity = value
@property @property
@ServiceProviderABC.inject @ServiceProviderABC.inject

View File

@@ -1,6 +1,8 @@
import datetime
from typing import Optional from typing import Optional
from cpl_core.database.context import DatabaseContextABC from cpl_core.database.context import DatabaseContextABC
from cpl_core.type import T, R
from cpl_query.extension import List from cpl_query.extension import List
from bot_core.logging.database_logger import DatabaseLogger from bot_core.logging.database_logger import DatabaseLogger
@@ -38,7 +40,9 @@ class UserRepositoryService(UserRepositoryABC):
def get_users(self) -> List[User]: def get_users(self) -> List[User]:
self._logger.trace(__name__, f"Send SQL command: {User.get_select_all_string()}") self._logger.trace(__name__, f"Send SQL command: {User.get_select_all_string()}")
return List(User, [self._from_result(user) for user in self._context.select(User.get_select_all_string())]) return List(
User, [self._from_result(user) for user in self._context.select(User.get_select_all_string())]
).for_each(lambda x: self._set_user_activity(x))
def get_user_by_id(self, id: int) -> User: def get_user_by_id(self, id: int) -> User:
self._logger.trace(__name__, f"Send SQL command: {User.get_select_by_id_string(id)}") self._logger.trace(__name__, f"Send SQL command: {User.get_select_by_id_string(id)}")
@@ -77,6 +81,16 @@ class UserRepositoryService(UserRepositoryABC):
[self._from_result(user) for user in self._context.select(User.get_select_by_server_id_string(server_id))], [self._from_result(user) for user in self._context.select(User.get_select_by_server_id_string(server_id))],
) )
def get_users_with_activity_by_server_id(self, server_id: int) -> List[User]:
self._logger.trace(
__name__,
f"Send SQL command: {User.get_select_by_server_id_string(server_id)}",
)
return List(
User,
[self._from_result(user) for user in self._context.select(User.get_select_by_server_id_string(server_id))],
).for_each(lambda x: self._set_user_activity(x))
def get_user_by_discord_id_and_server_id(self, discord_id: int, server_id: int) -> User: def get_user_by_discord_id_and_server_id(self, discord_id: int, server_id: int) -> User:
self._logger.trace( self._logger.trace(
__name__, __name__,
@@ -109,3 +123,91 @@ class UserRepositoryService(UserRepositoryABC):
def delete_user(self, user: User): def delete_user(self, user: User):
self._logger.trace(__name__, f"Send SQL command: {user.delete_string}") self._logger.trace(__name__, f"Send SQL command: {user.delete_string}")
self._context.cursor.execute(user.delete_string) self._context.cursor.execute(user.delete_string)
def _set_user_activity(self, user):
days = (datetime.date.today() - (datetime.date.today() - datetime.timedelta(days=7))).days
query = f"""
SELECT (
(
SELECT Count(UserGotAchievements.CreatedAt)
FROM UserGotAchievements
INNER JOIN Achievements ON UserGotAchievements.AchievementId = Achievements.Id
INNER JOIN Users ON UserGotAchievements.UserId = Users.UserId
WHERE Users.ServerId = {user.server.id}
AND Users.UserId = {user.id}
AND UserGotAchievements.CreatedAt >= "{datetime.date.today() - datetime.timedelta(days=7)}"
) +
(
SELECT SUM(
UserMessageCountPerHour.XPCount / (
SELECT XpPerMessage
FROM CFG_Server
WHERE ServerId = {user.server.id}
)
)
FROM UserMessageCountPerHour
INNER JOIN Users ON UserMessageCountPerHour.UserId = Users.UserId
WHERE Users.ServerId = {user.server.id}
AND Users.UserId = {user.id}
AND UserMessageCountPerHour.CreatedAt >= "{datetime.date.today() - datetime.timedelta(days=7)}"
) +
(
SELECT Count(UserJoinedVoiceChannel.CreatedAt)
FROM UserJoinedVoiceChannel
INNER JOIN Users ON UserJoinedVoiceChannel.UserId = Users.UserId
WHERE Users.ServerId = {user.server.id}
AND Users.UserId = {user.id}
AND UserJoinedVoiceChannel.CreatedAt >= "{datetime.date.today() - datetime.timedelta(days=7)}"
) +
(
SELECT IFNULL(ROUND(SUM(TIME_TO_SEC(
TIMEDIFF(UserJoinedVoiceChannel.LeavedOn, UserJoinedVoiceChannel.JoinedOn)
) / 3600), 2), 0)
FROM UserJoinedVoiceChannel
INNER JOIN Users ON UserJoinedVoiceChannel.UserId = Users.UserId
WHERE Users.ServerId = {user.server.id}
AND Users.UserId = {user.id}
AND UserJoinedVoiceChannel.CreatedAt >= "{datetime.date.today() - datetime.timedelta(days=7)}"
) +
(
SELECT Count(UserJoinedGameServer.CreatedAt)
FROM UserJoinedGameServer
INNER JOIN Users ON UserJoinedGameServer.UserId = Users.UserId
WHERE Users.ServerId = {user.server.id}
AND Users.UserId = {user.id}
AND UserJoinedGameServer.CreatedAt >= "{datetime.date.today() - datetime.timedelta(days=7)}"
) +
(
SELECT IFNULL(ROUND(SUM(TIME_TO_SEC(
TIMEDIFF(UserJoinedGameServer.LeavedOn, UserJoinedGameServer.JoinedOn)
) / 3600), 2), 0)
FROM UserJoinedGameServer
INNER JOIN Users ON UserJoinedGameServer.UserId = Users.UserId
WHERE Users.ServerId = {user.server.id}
AND Users.UserId = {user.id}
AND UserJoinedGameServer.CreatedAt >= "{datetime.date.today() - datetime.timedelta(days=7)}"
) -
(
SELECT COUNT(UserWarnings.CreatedAt)
FROM UserWarnings
INNER JOIN Users ON UserWarnings.UserId = Users.UserId
WHERE Users.ServerId = {user.server.id}
AND Users.UserId = {user.id}
AND UserWarnings.CreatedAt >= "{datetime.date.today() - datetime.timedelta(days=7)}"
)
) / {days} * 1000 as count;
"""
user.activity = self._cast_query_result(query, int)
def _cast_query_result(self, query: str, r_type: T) -> Optional[R]:
results = self._context.select(query)
if len(results) == 0 or len(results[0]) == 0:
return None
result = results[0][0]
default = None
if r_type is int or r_type is float:
default = 0
elif r_type is str:
default = ""
return r_type(result) if result is not None else default

View File

@@ -64,11 +64,9 @@ class QueryABC(ObjectType):
if user == "system" or user.auth_role == AuthRoleEnum.admin: if user == "system" or user.auth_role == AuthRoleEnum.admin:
return self._resolve_collection(collection, *args, **kwargs) return self._resolve_collection(collection, *args, **kwargs)
for x in collection.to_list(): return self._resolve_collection(
if not self._can_user_see_element(user, x): collection.where(lambda x: self._can_user_see_element(user, x)), *args, **kwargs
collection.remove(x) )
return self._resolve_collection(collection, *args, **kwargs)
self.set_field(f"{name}s", wrapper) self.set_field(f"{name}s", wrapper)
self.set_field(f"{name}Count", lambda *args: wrapper(*args).count()) self.set_field(f"{name}Count", lambda *args: wrapper(*args).count())

View File

@@ -7,7 +7,9 @@ type User implements TableWithHistoryQuery {
reactionCount: Int reactionCount: Int
birthday: String birthday: String
ontime: Float ontime: Float
gameOntime: Float
level: Level level: Level
activityScore: Int
joinedServers(filter: UserJoinedServerFilter, page: Page, sort: Sort): [UserJoinedServer] joinedServers(filter: UserJoinedServerFilter, page: Page, sort: Sort): [UserJoinedServer]
joinedServerCount: Int joinedServerCount: Int

View File

@@ -86,7 +86,7 @@ class ServerQuery(DataQueryWithHistoryABC):
) )
self.add_collection( self.add_collection(
"user", "user",
lambda server, *_: self._users.get_users_by_server_id(server.id), lambda server, *_: self._users.get_users_with_activity_by_server_id(server.id),
UserFilter, UserFilter,
) )
self.add_collection( self.add_collection(

View File

@@ -114,7 +114,9 @@ class ServerStatisticQuery(QueryABC):
def _resolve_voice_channel_ontime(self, server, *_): def _resolve_voice_channel_ontime(self, server, *_):
query = f""" query = f"""
SELECT ROUND(SUM(TIME_TO_SEC(TIMEDIFF(UserJoinedVoiceChannel.LeavedOn, UserJoinedVoiceChannel.JoinedOn)) / 3600),{server.server.id}) FROM UserJoinedVoiceChannel SELECT IFNULL(ROUND(SUM(
TIME_TO_SEC(TIMEDIFF(UserJoinedVoiceChannel.LeavedOn, UserJoinedVoiceChannel.JoinedOn)) / 3600
), 2), 0) FROM UserJoinedVoiceChannel
INNER JOIN Users ON UserJoinedVoiceChannel.UserId = Users.UserId INNER JOIN Users ON UserJoinedVoiceChannel.UserId = Users.UserId
WHERE Users.ServerId = {server.server.id} WHERE Users.ServerId = {server.server.id}
AND UserJoinedVoiceChannel.CreatedAt >= "{self._get_date(**server.kwargs)}"; AND UserJoinedVoiceChannel.CreatedAt >= "{self._get_date(**server.kwargs)}";
@@ -132,7 +134,10 @@ class ServerStatisticQuery(QueryABC):
def _resolve_game_server_ontime(self, server, *_): def _resolve_game_server_ontime(self, server, *_):
query = f""" query = f"""
SELECT ROUND(SUM(TIME_TO_SEC(TIMEDIFF(UserJoinedGameServer.LeavedOn, UserJoinedGameServer.JoinedOn)) / 3600),{server.server.id}) FROM UserJoinedGameServer SELECT IFNULL(ROUND(SUM(
TIME_TO_SEC(TIMEDIFF(UserJoinedGameServer.LeavedOn, UserJoinedGameServer.JoinedOn)) / 3600
), 2), 0)
FROM UserJoinedGameServer
INNER JOIN Users ON UserJoinedGameServer.UserId = Users.UserId INNER JOIN Users ON UserJoinedGameServer.UserId = Users.UserId
WHERE Users.ServerId = {server.server.id} WHERE Users.ServerId = {server.server.id}
AND UserJoinedGameServer.CreatedAt >= "{self._get_date(**server.kwargs)}"; AND UserJoinedGameServer.CreatedAt >= "{self._get_date(**server.kwargs)}";

View File

@@ -2,6 +2,7 @@ from cpl_core.database.context import DatabaseContextABC
from cpl_discord.service import DiscordBotServiceABC from cpl_discord.service import DiscordBotServiceABC
from bot_core.abc.client_utils_abc import ClientUtilsABC from bot_core.abc.client_utils_abc import ClientUtilsABC
from bot_core.abc.permission_service_abc import PermissionServiceABC
from bot_data.abc.achievement_repository_abc import AchievementRepositoryABC from bot_data.abc.achievement_repository_abc import AchievementRepositoryABC
from bot_data.abc.user_joined_game_server_repository_abc import ( from bot_data.abc.user_joined_game_server_repository_abc import (
UserJoinedGameServerRepositoryABC, UserJoinedGameServerRepositoryABC,
@@ -11,7 +12,6 @@ from bot_data.abc.user_joined_voice_channel_repository_abc import (
UserJoinedVoiceChannelRepositoryABC, UserJoinedVoiceChannelRepositoryABC,
) )
from bot_data.abc.user_warnings_repository_abc import UserWarningsRepositoryABC from bot_data.abc.user_warnings_repository_abc import UserWarningsRepositoryABC
from bot_data.model.user import User
from bot_data.model.user_history import UserHistory from bot_data.model.user_history import UserHistory
from bot_graphql.abc.data_query_with_history_abc import DataQueryWithHistoryABC from bot_graphql.abc.data_query_with_history_abc import DataQueryWithHistoryABC
from bot_graphql.filter.achievement_filter import AchievementFilter from bot_graphql.filter.achievement_filter import AchievementFilter
@@ -22,7 +22,6 @@ from bot_graphql.filter.user_joined_voice_channel_filter import (
) )
from bot_graphql.filter.user_warning_filter import UserWarningFilter from bot_graphql.filter.user_warning_filter import UserWarningFilter
from modules.level.service.level_service import LevelService from modules.level.service.level_service import LevelService
from bot_core.abc.permission_service_abc import PermissionServiceABC
class UserQuery(DataQueryWithHistoryABC): class UserQuery(DataQueryWithHistoryABC):
@@ -50,15 +49,17 @@ class UserQuery(DataQueryWithHistoryABC):
self._permissions = permissions self._permissions = permissions
self._achievements = achievements self._achievements = achievements
self.set_field("id", self.resolve_id) self.set_field("id", lambda user, *_: user.id)
self.set_field("discordId", self.resolve_discord_id) self.set_field("discordId", lambda user, *_: user.discord_id)
self.set_field("name", self.resolve_name) self.set_field("name", lambda user, *_: user.name)
self.set_field("xp", self.resolve_xp) self.set_field("xp", lambda user, *_: user.xp)
self.set_field("messageCount", lambda x, *_: x.message_count) self.set_field("messageCount", lambda x, *_: x.message_count)
self.set_field("reactionCount", lambda x, *_: x.reaction_count) self.set_field("reactionCount", lambda x, *_: x.reaction_count)
self.set_field("birthday", lambda x, *_: None if x.birthday is None else x.birthday.strftime("%d.%m.%Y")) self.set_field("birthday", lambda x, *_: None if x.birthday is None else x.birthday.strftime("%d.%m.%Y"))
self.set_field("ontime", self.resolve_ontime) self.set_field("ontime", lambda user, *_: user.ontime)
self.set_field("level", self.resolve_level) self.set_field("gameOntime", lambda user, *_: user.game_ontime)
self.set_field("level", lambda user, *_: user.level)
self.set_field("activityScore", lambda user, *_: user.activity)
self.add_collection( self.add_collection(
"joinedServer", "joinedServer",
lambda user, *_: self._ujs.get_user_joined_servers_by_user_id(user.id), lambda user, *_: self._ujs.get_user_joined_servers_by_user_id(user.id),
@@ -85,37 +86,5 @@ class UserQuery(DataQueryWithHistoryABC):
UserWarningFilter, UserWarningFilter,
) )
self.set_field("server", self.resolve_server) self.set_field("server", lambda user, *_: user.server)
self.set_field("leftServer", self.resolve_left_server) self.set_field("leftServer", lambda user, *_: user.left_server)
@staticmethod
def resolve_id(user: User, *_):
return user.id
@staticmethod
def resolve_discord_id(user: User, *_):
return user.discord_id
@staticmethod
def resolve_name(user: User, *_):
return user.name
@staticmethod
def resolve_xp(user: User, *_):
return user.xp
@staticmethod
def resolve_ontime(user: User, *_):
return user.ontime
@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

View File

@@ -16,7 +16,9 @@ export interface User extends DataWithHistory {
reactionCount?: number; reactionCount?: number;
birthday?: string; birthday?: string;
ontime?: number; ontime?: number;
gameOntime?: number;
level?: Level; level?: Level;
activityScore?: number;
server?: Server; server?: Server;
leftServer?: boolean; leftServer?: boolean;

View File

@@ -361,6 +361,8 @@ export class Queries {
name name
xp xp
ontime ontime
gameOntime
activityScore
level { level {
id id
name name
@@ -386,6 +388,8 @@ export class Queries {
reactionCount reactionCount
birthday birthday
ontime ontime
gameOntime
activityScore
level { level {
id id
name name

View File

@@ -3,7 +3,8 @@
</h1> </h1>
<div class="content-wrapper"> <div class="content-wrapper">
<div class="content"> <div class="content">
<p-table #dt [value]="members" [responsive]="true" responsiveLayout="stack" [breakpoint]="'720px'" dataKey="id" editMode="row" [rowHover]="true" [rows]="10" <p-table #dt [value]="members" [responsive]="true" responsiveLayout="stack" [breakpoint]="'720px'" dataKey="id"
editMode="row" [rowHover]="true" [rows]="10"
[rowsPerPageOptions]="[10,25,50]" [paginator]="true" [loading]="loading" [totalRecords]="totalRecords" [rowsPerPageOptions]="[10,25,50]" [paginator]="true" [loading]="loading" [totalRecords]="totalRecords"
[lazy]="true" (onLazyLoad)="nextPage($event)"> [lazy]="true" (onLazyLoad)="nextPage($event)">
@@ -17,7 +18,8 @@
{{'view.server.members.members' | translate}} {{'view.server.members.members' | translate}}
</div> </div>
<app-multi-select-columns [table]="name" [columns]="columns" [(hiddenColumns)]="hiddenColumns"></app-multi-select-columns> <app-multi-select-columns [table]="name" [columns]="columns"
[(hiddenColumns)]="hiddenColumns"></app-multi-select-columns>
</div> </div>
<div class="table-caption-btn-wrapper btn-wrapper"> <div class="table-caption-btn-wrapper btn-wrapper">
@@ -65,6 +67,20 @@
</div> </div>
</th> </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>
<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>
<p-sortIcon field="activityScore" class="table-header-icon"></p-sortIcon>
</div>
</th>
<th hideable-th="left_server" [parent]="this" [sortable]="true"> <th hideable-th="left_server" [parent]="this" [sortable]="true">
<div class="table-header-label"> <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>
@@ -106,7 +122,8 @@
</th> </th>
<th hideable-th="discord_id" [parent]="this" class="table-header-medium"> <th hideable-th="discord_id" [parent]="this" class="table-header-medium">
<form [formGroup]="filterForm"> <form [formGroup]="filterForm">
<input type="text" pInputText formControlName="discordId" placeholder="{{'common.discord_id' | translate}}"> <input type="text" pInputText formControlName="discordId"
placeholder="{{'common.discord_id' | translate}}">
</form> </form>
</th> </th>
<th hideable-th="name" [parent]="this"> <th hideable-th="name" [parent]="this">
@@ -116,14 +133,18 @@
</th> </th>
<th hideable-th="xp" [parent]="this"></th> <th hideable-th="xp" [parent]="this"></th>
<th hideable-th="ontime" [parent]="this"></th> <th hideable-th="ontime" [parent]="this"></th>
<th hideable-th="game_ontime" [parent]="this"></th>
<th hideable-th="activity" [parent]="this"></th>
<th hideable-th="left_server" [parent]="this" class="table-header-small-dropdown"> <th hideable-th="left_server" [parent]="this" class="table-header-small-dropdown">
<form [formGroup]="filterForm"> <form [formGroup]="filterForm">
<p-dropdown formControlName="leftServer" [options]="leftServerOptions" placeholder="{{'common.left_server' | translate}}"></p-dropdown> <p-dropdown formControlName="leftServer" [options]="leftServerOptions"
placeholder="{{'common.left_server' | translate}}"></p-dropdown>
</form> </form>
</th> </th>
<th hideable-th="level" [parent]="this" class="table-header-small-dropdown"> <th hideable-th="level" [parent]="this" class="table-header-small-dropdown">
<form [formGroup]="filterForm"> <form [formGroup]="filterForm">
<p-dropdown formControlName="level" [options]="levels" placeholder="{{'common.level' | translate}}"></p-dropdown> <p-dropdown formControlName="level" [options]="levels"
placeholder="{{'common.level' | translate}}"></p-dropdown>
</form> </form>
</th> </th>
<th></th> <th></th>
@@ -189,6 +210,28 @@
</ng-template> </ng-template>
</p-cellEditor> </p-cellEditor>
</td> </td>
<td hideable-th="game_ontime" [parent]="this">
<span class="p-column-title">{{'common.game_ontime' | translate}}:</span>
<p-cellEditor>
<ng-template pTemplate="input">
{{member.gameOntime}}
</ng-template>
<ng-template pTemplate="output">
{{member.gameOntime}}
</ng-template>
</p-cellEditor>
</td>
<td hideable-th="activity" [parent]="this">
<span class="p-column-title">{{'common.activity' | translate}}:</span>
<p-cellEditor>
<ng-template pTemplate="input">
{{member.activityScore}}
</ng-template>
<ng-template pTemplate="output">
{{member.activityScore}}
</ng-template>
</p-cellEditor>
</td>
<td hideable-th="left_server" [parent]="this"> <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> <p-cellEditor>
@@ -204,7 +247,8 @@
<span class="p-column-title">{{'common.level' | translate}}:</span> <span class="p-column-title">{{'common.level' | translate}}:</span>
<p-cellEditor> <p-cellEditor>
<ng-template pTemplate="input"> <ng-template pTemplate="input">
<p-dropdown [options]="levels" [(ngModel)]="member.level" dataKey="id" placeholder="{{'common.level' | translate}}"></p-dropdown> <p-dropdown [options]="levels" [(ngModel)]="member.level" dataKey="id"
placeholder="{{'common.level' | translate}}"></p-dropdown>
</ng-template> </ng-template>
<ng-template pTemplate="output"> <ng-template pTemplate="output">
{{member.level.name}} {{member.level.name}}
@@ -235,7 +279,8 @@
</td> </td>
<td> <td>
<div class="btn-wrapper"> <div class="btn-wrapper">
<app-history-btn *ngIf="!isEditingNew" [id]="member.id" [query]="query" translationKey="view.server.members.header"></app-history-btn> <app-history-btn *ngIf="!isEditingNew" [id]="member.id" [query]="query"
translationKey="view.server.members.header"></app-history-btn>
<button *ngIf="!editing" pButton pInitEditableRow class="btn icon-btn" icon="pi pi-pencil" <button *ngIf="!editing" pButton pInitEditableRow class="btn icon-btn" icon="pi pi-pencil"
(click)="onRowEditInit(dt, member, ri)"></button> (click)="onRowEditInit(dt, member, ri)"></button>
<button *ngIf="!editing" pButton pInitEditableRow class="btn icon-btn" icon="pi pi-user" <button *ngIf="!editing" pButton pInitEditableRow class="btn icon-btn" icon="pi pi-user"

View File

@@ -89,7 +89,7 @@ export class MembersComponent extends ComponentWithTable implements OnInit, OnDe
private data: DataService, private data: DataService,
private route: ActivatedRoute private route: ActivatedRoute
) { ) {
super("member", ["id", "discord_id", "name", "xp", "ontime", "left_server", "level"]); super("member", ["id", "discord_id", "name", "xp", "ontime", "game_ontime", "activity", "left_server", "level"]);
} }
ngOnInit(): void { ngOnInit(): void {

View File

@@ -63,11 +63,25 @@
<div class="content-row"> <div class="content-row">
<div class="content-column"> <div class="content-column">
<div class="content-data-name">{{'view.server.profile.ontime' | translate}}:</div> <div class="content-data-name">{{'common.ontime' | translate}}:</div>
<div class="content-data-value">{{user.ontime}}</div> <div class="content-data-value">{{user.ontime}}</div>
</div> </div>
</div> </div>
<div class="content-row">
<div class="content-column">
<div class="content-data-name">{{'common.game_ontime' | translate}}:</div>
<div class="content-data-value">{{user.gameOntime}}</div>
</div>
</div>
<div class="content-row">
<div class="content-column">
<div class="content-data-name">{{'common.activity' | translate}}:</div>
<div class="content-data-value">{{user.activityScore}}</div>
</div>
</div>
<div class="content-row"> <div class="content-row">
<div class="content-column"> <div class="content-column">
<div class="content-data-name">{{'view.server.profile.level' | translate}}:</div> <div class="content-data-name">{{'view.server.profile.level' | translate}}:</div>
@@ -266,7 +280,7 @@
<div class="content-data-name">{{'common.id' | translate}}:</div> <div class="content-data-name">{{'common.id' | translate}}:</div>
<div class="content-data-value">{{join.id}}</div> <div class="content-data-value">{{join.id}}</div>
</div> </div>
<div class="content-column" style="flex: 0.75;"> <div class="content-column" style="flex: 0.75;">
<div class="content-data-name" <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}}:

View File

@@ -127,6 +127,7 @@
"abort": "Abbrechen", "abort": "Abbrechen",
"actions": "Aktionen", "actions": "Aktionen",
"active": "Aktiv", "active": "Aktiv",
"activity": "Aktivität",
"add": "Hinzufügen", "add": "Hinzufügen",
"attribute": "Attribut", "attribute": "Attribut",
"auth_role": "Rolle", "auth_role": "Rolle",
@@ -154,6 +155,7 @@
"uploaded": "Daten wurden erfolgreich importiert." "uploaded": "Daten wurden erfolgreich importiert."
}, },
"first_name": "Vorname", "first_name": "Vorname",
"game_ontime": "Spiel Ontime",
"hidden_columns": "Ausgeblendete Spalten", "hidden_columns": "Ausgeblendete Spalten",
"history": { "history": {
"attribute": "Attribut", "attribute": "Attribut",
@@ -542,7 +544,6 @@
"message_count": "Anzahl Nachrichten", "message_count": "Anzahl Nachrichten",
"minecraft_id": "Minecraft Id", "minecraft_id": "Minecraft Id",
"name": "Name", "name": "Name",
"ontime": "Ontime",
"permission_denied": "Zugriff verweigert!", "permission_denied": "Zugriff verweigert!",
"permission_denied_d": "Du musst Moderator sein, um andere Profile sehen zu können!", "permission_denied_d": "Du musst Moderator sein, um andere Profile sehen zu können!",
"reaction_count": "Anzahl Reaktionen", "reaction_count": "Anzahl Reaktionen",

View File

@@ -127,6 +127,7 @@
"abort": "Abort", "abort": "Abort",
"actions": "Actions", "actions": "Actions",
"active": "Active", "active": "Active",
"activity": "Activity",
"add": "Add", "add": "Add",
"attribute": "Attribute", "attribute": "Attribute",
"auth_role": "Role", "auth_role": "Role",
@@ -154,6 +155,7 @@
"uploaded": "Data was imported successfully." "uploaded": "Data was imported successfully."
}, },
"first_name": "First name", "first_name": "First name",
"game_ontime": "Game ontime",
"hidden_columns": "Hidden columns", "hidden_columns": "Hidden columns",
"history": { "history": {
"attribute": "Attribute", "attribute": "Attribute",
@@ -542,7 +544,6 @@
"message_count": "Message count", "message_count": "Message count",
"minecraft_id": "Minecraft Id", "minecraft_id": "Minecraft Id",
"name": "Name", "name": "Name",
"ontime": "Ontime",
"permission_denied": "Access denied!", "permission_denied": "Access denied!",
"permission_denied_d": "You have to be moderator to see other profiles!", "permission_denied_d": "You have to be moderator to see other profiles!",
"reaction_count": "Reaction count", "reaction_count": "Reaction count",