Show user warnings in profile & lazy load other stuff #402

This commit is contained in:
Sven Heidemann 2023-10-10 12:21:21 +02:00
parent 0e2b7d03fc
commit f5b978b231
27 changed files with 508 additions and 82 deletions

View File

@ -0,0 +1,43 @@
from typing import Optional
from bot_data.abc.history_table_abc import HistoryTableABC
# had to name it UserWarnings instead of UserWarning because UserWarning is a builtin class
class UserWarningsHistory(HistoryTableABC):
def __init__(
self,
description: str,
user: int,
author: Optional[int],
deleted: bool,
date_from: str,
date_to: str,
id=0,
):
HistoryTableABC.__init__(self)
self._id = id
self._description = description
self._user = user
self._author = author
self._deleted = deleted
self._date_from = date_from
self._date_to = date_to
@property
def id(self) -> int:
return self._id
@property
def description(self) -> str:
return self._description
@property
def user(self) -> int:
return self._user
@property
def author(self) -> Optional[int]:
return self._author

View File

@ -1,3 +1,4 @@
from cpl_core.dependency_injection import ServiceProviderABC
from cpl_query.extension import List from cpl_query.extension import List
from bot_data.model.user import User from bot_data.model.user import User
@ -5,9 +6,14 @@ from bot_graphql.abc.filter_abc import FilterABC
class AchievementFilter(FilterABC): class AchievementFilter(FilterABC):
def __init__(self): def __init__(
self,
services: ServiceProviderABC,
):
FilterABC.__init__(self) FilterABC.__init__(self)
self._services = services
self._id = None self._id = None
self._name = None self._name = None
self._description = None self._description = None

View File

@ -0,0 +1,56 @@
from cpl_core.dependency_injection import ServiceProviderABC
from cpl_query.extension import List
from bot_data.model.user_warnings import UserWarnings
from bot_graphql.abc.filter_abc import FilterABC
class UserWarningFilter(FilterABC):
def __init__(
self,
services: ServiceProviderABC,
):
FilterABC.__init__(self)
self._services = services
self._id = None
self._user = None
self._description = None
self._author = None
def from_dict(self, values: dict):
if "id" in values:
self._id = int(values["id"])
if "user" in values:
from bot_graphql.filter.user_filter import UserFilter
self._user: UserFilter = self._services.get_service(UserFilter)
self._user.from_dict(values["user"])
if "description" in values:
self._description = values["description"]
if "author" in values:
from bot_graphql.filter.user_filter import UserFilter
self._author: UserFilter = self._services.get_service(UserFilter)
self._author.from_dict(values["author"])
def filter(self, query: List[UserWarnings]) -> List[UserWarnings]:
if self._id is not None:
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.id)
query = query.where(lambda x: x.id in users)
if self._description is not None:
query = query.where(lambda x: x.description == self._description or self._description in x.description)
if self._author is not None:
users = self._author.filter(query.select(lambda x: x.author)).select(lambda x: x.id)
query = query.where(lambda x: x.id in users)
return query

View File

@ -41,6 +41,9 @@ type Query {
shortRoleNames(filter: ShortRoleNameFilter, page: Page, sort: Sort): [ShortRoleName] shortRoleNames(filter: ShortRoleNameFilter, page: Page, sort: Sort): [ShortRoleName]
shortRoleNamePositions: [String] shortRoleNamePositions: [String]
userWarningCount: Int
userWarnings(filter: UserWarningFilter, page: Page, sort: Sort): [UserWarning]
technicianConfig: TechnicianConfig technicianConfig: TechnicianConfig
possibleFeatureFlags: [String] possibleFeatureFlags: [String]
discord: Discord discord: Discord

View File

@ -20,6 +20,9 @@ type User implements TableWithHistoryQuery {
achievementCount: Int achievementCount: Int
achievements(filter: AchievementFilter, page: Page, sort: Sort): [Achievement] achievements(filter: AchievementFilter, page: Page, sort: Sort): [Achievement]
userWarningCount: Int
userWarnings(filter: UserWarningFilter, page: Page, sort: Sort): [UserWarning]
server: Server server: Server
leftServer: Boolean leftServer: Boolean

View File

@ -0,0 +1,27 @@
type UserWarning implements TableWithHistoryQuery {
id: ID
user: User
description: String
author: User
createdAt: String
modifiedAt: String
history: [UserWarningHistory]
}
type UserWarningHistory implements HistoryTableQuery {
id: ID
user: ID
description: String
author: ID
deleted: Boolean
dateFrom: String
dateTo: String
}
input UserWarningFilter {
id: ID
user: UserFilter
}

View File

@ -18,6 +18,7 @@ from bot_graphql.filter.user_filter import UserFilter
from bot_graphql.filter.user_joined_game_server_filter import UserJoinedGameServerFilter from bot_graphql.filter.user_joined_game_server_filter import UserJoinedGameServerFilter
from bot_graphql.filter.user_joined_server_filter import UserJoinedServerFilter from bot_graphql.filter.user_joined_server_filter import UserJoinedServerFilter
from bot_graphql.filter.user_joined_voice_channel_filter import UserJoinedVoiceChannelFilter from bot_graphql.filter.user_joined_voice_channel_filter import UserJoinedVoiceChannelFilter
from bot_graphql.filter.user_warning_filter import UserWarningFilter
from bot_graphql.graphql_service import GraphQLService from bot_graphql.graphql_service import GraphQLService
from bot_graphql.mutation import Mutation from bot_graphql.mutation import Mutation
from bot_graphql.mutations.achievement_mutation import AchievementMutation from bot_graphql.mutations.achievement_mutation import AchievementMutation
@ -66,6 +67,8 @@ from bot_graphql.queries.user_joined_server_query import UserJoinedServerQuery
from bot_graphql.queries.user_joined_voice_channel_history_query import UserJoinedVoiceChannelHistoryQuery from bot_graphql.queries.user_joined_voice_channel_history_query import UserJoinedVoiceChannelHistoryQuery
from bot_graphql.queries.user_joined_voice_channel_query import UserJoinedVoiceChannelQuery from bot_graphql.queries.user_joined_voice_channel_query import UserJoinedVoiceChannelQuery
from bot_graphql.queries.user_query import UserQuery from bot_graphql.queries.user_query import UserQuery
from bot_graphql.queries.user_warning_history_query import UserWarningHistoryQuery
from bot_graphql.queries.user_warning_query import UserWarningQuery
from bot_graphql.query import Query from bot_graphql.query import Query
from bot_graphql.schema import Schema from bot_graphql.schema import Schema
@ -115,6 +118,8 @@ class GraphQLModule(ModuleABC):
services.add_transient(QueryABC, UserJoinedGameServerQuery) services.add_transient(QueryABC, UserJoinedGameServerQuery)
services.add_transient(QueryABC, ShortRoleNameHistoryQuery) services.add_transient(QueryABC, ShortRoleNameHistoryQuery)
services.add_transient(QueryABC, ShortRoleNameQuery) services.add_transient(QueryABC, ShortRoleNameQuery)
services.add_transient(QueryABC, UserWarningHistoryQuery)
services.add_transient(QueryABC, UserWarningQuery)
services.add_transient(QueryABC, DiscordQuery) services.add_transient(QueryABC, DiscordQuery)
services.add_transient(QueryABC, GuildQuery) services.add_transient(QueryABC, GuildQuery)
@ -135,6 +140,7 @@ class GraphQLModule(ModuleABC):
services.add_transient(FilterABC, UserJoinedVoiceChannelFilter) services.add_transient(FilterABC, UserJoinedVoiceChannelFilter)
services.add_transient(FilterABC, UserJoinedGameServerFilter) services.add_transient(FilterABC, UserJoinedGameServerFilter)
services.add_transient(FilterABC, ShortRoleNameFilter) services.add_transient(FilterABC, ShortRoleNameFilter)
services.add_transient(FilterABC, UserWarningFilter)
# mutations # mutations
services.add_transient(QueryABC, AutoRoleMutation) services.add_transient(QueryABC, AutoRoleMutation)

View File

@ -6,6 +6,7 @@ from bot_data.abc.achievement_repository_abc import AchievementRepositoryABC
from bot_data.abc.user_joined_game_server_repository_abc import UserJoinedGameServerRepositoryABC from bot_data.abc.user_joined_game_server_repository_abc import UserJoinedGameServerRepositoryABC
from bot_data.abc.user_joined_server_repository_abc import UserJoinedServerRepositoryABC from bot_data.abc.user_joined_server_repository_abc import UserJoinedServerRepositoryABC
from bot_data.abc.user_joined_voice_channel_repository_abc import UserJoinedVoiceChannelRepositoryABC from bot_data.abc.user_joined_voice_channel_repository_abc import UserJoinedVoiceChannelRepositoryABC
from bot_data.abc.user_warnings_repository_abc import UserWarningsRepositoryABC
from bot_data.model.user import User 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
@ -13,6 +14,7 @@ from bot_graphql.filter.achievement_filter import AchievementFilter
from bot_graphql.filter.user_joined_game_server_filter import UserJoinedGameServerFilter from bot_graphql.filter.user_joined_game_server_filter import UserJoinedGameServerFilter
from bot_graphql.filter.user_joined_server_filter import UserJoinedServerFilter from bot_graphql.filter.user_joined_server_filter import UserJoinedServerFilter
from bot_graphql.filter.user_joined_voice_channel_filter import UserJoinedVoiceChannelFilter from bot_graphql.filter.user_joined_voice_channel_filter import UserJoinedVoiceChannelFilter
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 modules.permission.abc.permission_service_abc import PermissionServiceABC from modules.permission.abc.permission_service_abc import PermissionServiceABC
@ -29,6 +31,7 @@ class UserQuery(DataQueryWithHistoryABC):
user_joined_game_server: UserJoinedGameServerRepositoryABC, user_joined_game_server: UserJoinedGameServerRepositoryABC,
permissions: PermissionServiceABC, permissions: PermissionServiceABC,
achievements: AchievementRepositoryABC, achievements: AchievementRepositoryABC,
user_warnings: UserWarningsRepositoryABC,
): ):
DataQueryWithHistoryABC.__init__(self, "User", "UsersHistory", UserHistory, db) DataQueryWithHistoryABC.__init__(self, "User", "UsersHistory", UserHistory, db)
@ -67,6 +70,9 @@ class UserQuery(DataQueryWithHistoryABC):
self.add_collection( self.add_collection(
"achievement", lambda user, *_: achievements.get_achievements_by_user_id(user.id), AchievementFilter "achievement", lambda user, *_: achievements.get_achievements_by_user_id(user.id), AchievementFilter
) )
self.add_collection(
"userWarning", lambda user, *_: user_warnings.get_user_warnings_by_user_id(user.id), UserWarningFilter
)
self.set_field("server", self.resolve_server) self.set_field("server", self.resolve_server)
self.set_field("leftServer", self.resolve_left_server) self.set_field("leftServer", self.resolve_left_server)

View File

@ -0,0 +1,11 @@
from bot_graphql.abc.history_query_abc import HistoryQueryABC
class UserWarningHistoryQuery(HistoryQueryABC):
def __init__(self):
HistoryQueryABC.__init__(self, "UserWarning")
self.set_field("id", lambda x, *_: x.id)
self.set_field("user", lambda x, *_: x.user)
self.set_field("description", lambda x, *_: x.description)
self.set_field("author", lambda x, *_: x.author)

View File

@ -0,0 +1,17 @@
from cpl_core.database.context import DatabaseContextABC
from bot_data.model.user_warnings_history import UserWarningsHistory
from bot_graphql.abc.data_query_with_history_abc import DataQueryWithHistoryABC
class UserWarningQuery(DataQueryWithHistoryABC):
def __init__(
self,
db: DatabaseContextABC,
):
DataQueryWithHistoryABC.__init__(self, "UserWarning", "UserWarningsHistory", UserWarningsHistory, db)
self.set_field("id", lambda x, *_: x.id)
self.set_field("user", lambda x, *_: x.user)
self.set_field("description", lambda x, *_: x.description)
self.set_field("author", lambda x, *_: x.author)

View File

@ -15,6 +15,7 @@ from bot_data.abc.user_joined_game_server_repository_abc import UserJoinedGameSe
from bot_data.abc.user_joined_server_repository_abc import UserJoinedServerRepositoryABC from bot_data.abc.user_joined_server_repository_abc import UserJoinedServerRepositoryABC
from bot_data.abc.user_joined_voice_channel_repository_abc import UserJoinedVoiceChannelRepositoryABC from bot_data.abc.user_joined_voice_channel_repository_abc import UserJoinedVoiceChannelRepositoryABC
from bot_data.abc.user_repository_abc import UserRepositoryABC from bot_data.abc.user_repository_abc import UserRepositoryABC
from bot_data.abc.user_warnings_repository_abc import UserWarningsRepositoryABC
from bot_data.model.short_role_name_position_enum import ShortRoleNamePositionEnum from bot_data.model.short_role_name_position_enum import ShortRoleNamePositionEnum
from bot_graphql.abc.query_abc import QueryABC from bot_graphql.abc.query_abc import QueryABC
from bot_graphql.filter.achievement_filter import AchievementFilter from bot_graphql.filter.achievement_filter import AchievementFilter
@ -28,6 +29,7 @@ from bot_graphql.filter.user_filter import UserFilter
from bot_graphql.filter.user_joined_game_server_filter import UserJoinedGameServerFilter from bot_graphql.filter.user_joined_game_server_filter import UserJoinedGameServerFilter
from bot_graphql.filter.user_joined_server_filter import UserJoinedServerFilter from bot_graphql.filter.user_joined_server_filter import UserJoinedServerFilter
from bot_graphql.filter.user_joined_voice_channel_filter import UserJoinedVoiceChannelFilter from bot_graphql.filter.user_joined_voice_channel_filter import UserJoinedVoiceChannelFilter
from bot_graphql.filter.user_warning_filter import UserWarningFilter
from bot_graphql.model.discord import Discord from bot_graphql.model.discord import Discord
from modules.achievements.achievement_service import AchievementService from modules.achievements.achievement_service import AchievementService
@ -48,6 +50,7 @@ class Query(QueryABC):
users: UserRepositoryABC, users: UserRepositoryABC,
achievements: AchievementRepositoryABC, achievements: AchievementRepositoryABC,
short_role_names: ShortRoleNameRepositoryABC, short_role_names: ShortRoleNameRepositoryABC,
user_warnings: UserWarningsRepositoryABC,
achievement_service: AchievementService, achievement_service: AchievementService,
technician_config: TechnicianConfigRepositoryABC, technician_config: TechnicianConfigRepositoryABC,
): ):
@ -76,11 +79,13 @@ class Query(QueryABC):
self.add_collection("user", lambda *_: users.get_users(), UserFilter) self.add_collection("user", lambda *_: users.get_users(), UserFilter)
self.add_collection("achievement", lambda *_: achievements.get_achievements(), AchievementFilter) self.add_collection("achievement", lambda *_: achievements.get_achievements(), AchievementFilter)
self.add_collection("shortRoleName", lambda *_: short_role_names.get_short_role_names(), ShortRoleNameFilter) self.add_collection("shortRoleName", lambda *_: short_role_names.get_short_role_names(), ShortRoleNameFilter)
self.add_collection("userWarning", lambda *_: user_warnings.get_user_warnings(), UserWarningFilter)
self.set_field("technicianConfig", lambda *_: technician_config.get_technician_config()) self.set_field("technicianConfig", lambda *_: technician_config.get_technician_config())
self.set_field("achievementAttributes", lambda *_: achievement_service.get_attributes()) self.set_field("achievementAttributes", lambda *_: achievement_service.get_attributes())
self.set_field("achievementOperators", lambda *_: achievement_service.get_operators()) self.set_field("achievementOperators", lambda *_: achievement_service.get_operators())
self.set_field("shortRoleNamePositions", lambda *_: [x.value for x in ShortRoleNamePositionEnum]) self.set_field("shortRoleNamePositions", lambda *_: [x.value for x in ShortRoleNamePositionEnum])
self.set_field("possibleFeatureFlags", lambda *_: [e.value for e in FeatureFlagsEnum]) self.set_field("possibleFeatureFlags", lambda *_: [e.value for e in FeatureFlagsEnum])
self.set_field("discord", lambda *_: Discord(bot.guilds, List(any).extend(bot.users))) self.set_field("discord", lambda *_: Discord(bot.guilds, List(any).extend(bot.users)))

View File

@ -1,6 +1,6 @@
{ {
"name": "kdb-web", "name": "kdb-web",
"version": "1.1.10", "version": "1.1.dev402",
"scripts": { "scripts": {
"ng": "ng", "ng": "ng",
"update-version": "ts-node update-version.ts", "update-version": "ts-node update-version.ts",

View File

@ -5,6 +5,7 @@ import { UserJoinedServer } from "./user_joined_server.model";
import { UserJoinedVoiceChannel } from "./user_joined_voice_channel.model"; import { UserJoinedVoiceChannel } from "./user_joined_voice_channel.model";
import { UserJoinedGameServer } from "./user_joined_game_server.model"; import { UserJoinedGameServer } from "./user_joined_game_server.model";
import { Achievement } from "./achievement.model"; import { Achievement } from "./achievement.model";
import { UserWarning } from "./user_warning.model";
export interface User extends DataWithHistory { export interface User extends DataWithHistory {
id?: number; id?: number;
@ -29,6 +30,9 @@ export interface User extends DataWithHistory {
achievementCount?: number; achievementCount?: number;
achievements?: Achievement[]; achievements?: Achievement[];
userWarningCount?: number;
userWarnings?: UserWarning[];
} }
export interface UserFilter { export interface UserFilter {

View File

@ -0,0 +1,16 @@
import { DataWithHistory } from "./data.model";
import { User, UserFilter } from "./user.model";
export interface UserWarning extends DataWithHistory {
id?: number;
user?: User;
description?: string;
author?: User;
}
export interface UserWarningFilter {
id?: number;
user?: UserFilter;
description?: string;
author?: UserFilter;
}

View File

@ -208,7 +208,7 @@ export class Queries {
query { query {
shortRoleNamePositions shortRoleNamePositions
} }
` `;
static shortRoleNameQuery = ` static shortRoleNameQuery = `
query ShortRoleNameList($serverId: ID, $filter: ShortRoleNameFilter, $page: Page, $sort: Sort) { query ShortRoleNameList($serverId: ID, $filter: ShortRoleNameFilter, $page: Page, $sort: Sort) {
@ -279,9 +279,8 @@ export class Queries {
static userProfile = ` static userProfile = `
query UserProfile($serverId: ID, $userId: ID, $page: Page, $sort: Sort) { query UserProfile($serverId: ID, $userId: ID, $page: Page, $sort: Sort) {
servers(filter: {id: $serverId}) {
userCount userCount
users(filter: {id: $userId}, page: $page, sort: $sort) { users(filter: {server: {id: $serverId}, id: $userId}, page: $page, sort: $sort) {
id id
discordId discordId
name name
@ -304,6 +303,29 @@ export class Queries {
leavedOn leavedOn
} }
createdAt
modifiedAt
}
}
`;
static userProfileAchievements = `
query UserProfile($serverId: ID, $userId: ID, $page: Page, $sort: Sort) {
users(filter: {server: {id: $serverId}, id: $userId}, page: $page, sort: $sort) {
achievementCount
achievements {
id
name
description
createdAt
}
}
}
`;
static userProfileVoiceChannelJoins = `
query UserProfile($serverId: ID, $userId: ID, $page: Page, $sort: Sort) {
users(filter: {server: {id: $serverId}, id: $userId}, page: $page, sort: $sort) {
joinedVoiceChannelCount joinedVoiceChannelCount
joinedVoiceChannels { joinedVoiceChannels {
id id
@ -313,7 +335,13 @@ export class Queries {
joinedOn joinedOn
leavedOn leavedOn
} }
}
}
`;
static userProfileGameserverJoins = `
query UserProfile($serverId: ID, $userId: ID, $page: Page, $sort: Sort) {
users(filter: {server: {id: $serverId}, id: $userId}, page: $page, sort: $sort) {
userJoinedGameServerCount userJoinedGameServerCount
userJoinedGameServers { userJoinedGameServers {
id id
@ -322,15 +350,23 @@ export class Queries {
joinedOn joinedOn
leavedOn leavedOn
} }
}
}
`;
achievements { static userProfileWarnings = `
query UserProfile($serverId: ID, $userId: ID, $page: Page, $sort: Sort) {
users(filter: {server: {id: $serverId}, id: $userId}, page: $page, sort: $sort) {
userWarningCount
userWarnings {
id
description
author {
id id
name name
createdAt
} }
createdAt createdAt
modifiedAt
} }
} }
} }

View File

@ -8,6 +8,7 @@ import { TechnicianConfig } from "../config/technician-config.model";
import { ServerConfig } from "../config/server-config.model"; import { ServerConfig } from "../config/server-config.model";
import { ShortRoleName } from "../data/short_role_name.model"; import { ShortRoleName } from "../data/short_role_name.model";
import { FeatureFlag } from "../config/feature-flags.model"; import { FeatureFlag } from "../config/feature-flags.model";
import { UserWarning } from "../data/user_warning.model";
export interface Query { export interface Query {
serverCount: number; serverCount: number;
@ -31,6 +32,11 @@ export interface UserListQuery {
users: User[]; users: User[];
} }
export interface UserWarningQuery {
userWarningCount: number;
userWarnings: UserWarning[];
}
export interface GameServerListQuery { export interface GameServerListQuery {
gameServerCount: number; gameServerCount: number;
gameServers: GameServer[]; gameServers: GameServer[];

View File

@ -76,9 +76,103 @@
</div> </div>
</div> </div>
<div>
<div class="content-divider"></div>
<p-table #dt [value]="(user.userWarnings ?? [])" [responsive]="true" responsiveLayout="stack" [breakpoint]="'720px'" dataKey="id" editMode="row">
<ng-template pTemplate="caption">
<div class="table-caption">
<div class="table-caption-table-info">
<div class="table-caption-text">
<h3>{{'common.user_warnings' | translate}}</h3>
</div>
</div>
<div class="table-caption-btn-wrapper btn-wrapper">
<button pButton label="{{'common.add' | translate}}" class="icon-btn btn"
icon="pi pi-plus" (click)="addNewUserWarning(dt)">
</button>
</div>
</div>
</ng-template>
<ng-template pTemplate="header">
<tr>
<th>
<div class="table-header-label">
<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>
</th>
<th>
<div class="table-header-label">
<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>
</th>
</tr>
</ng-template>
<ng-template pTemplate="body" let-value let-editing="editing" let-ri="rowIndex">
<tr [pEditableRow]="value">
<td>
<p-cellEditor>
<ng-template pTemplate="input">
<input class="table-edit-input" pInputText type="text" [(ngModel)]="value.description">
</ng-template>
<ng-template pTemplate="output">
{{value.description}}
</ng-template>
</p-cellEditor>
</td>
<td>
<p-cellEditor>
<ng-template pTemplate="input">
{{value.author.name}}
</ng-template>
<ng-template pTemplate="output">
{{value.author.name}}
</ng-template>
</p-cellEditor>
</td>
<td>
<span class="p-column-title">{{'common.created_at' | translate}}:</span>
<p-cellEditor>
<ng-template pTemplate="input">
{{value.createdAt | date:'dd.MM.yy HH:mm'}}
</ng-template>
<ng-template pTemplate="output">
{{value.createdAt | date:'dd.MM.yy HH:mm'}}
</ng-template>
</p-cellEditor>
</td>
<td>
<div class="btn-wrapper">
<button *ngIf="!editing" pButton type="button" class="btn danger-icon-btn" icon="pi pi-trash" (click)="deleteUserWarning(ri)"></button>
<button *ngIf="editing" pButton type="button" pSaveEditableRow class="btn icon-btn" icon="pi pi-check" (click)="editSaveUserWarning(value, ri)"></button>
<button *ngIf="editing" pButton type="button" pCancelEditableRow class="btn danger-icon-btn" icon="pi pi-times"
(click)="editCancelUserWarning(ri)"></button>
</div>
</td>
</tr>
</ng-template>
</p-table>
<br>
</div>
<div class="content-divider"></div> <div class="content-divider"></div>
<p-panel header="{{'view.server.profile.achievements.header' | translate}}" [toggleable]="true"> <p-panel header="{{'view.server.profile.achievements.header' | translate}}" [toggleable]="true" [collapsed]="true"
(onBeforeToggle)="onBeforeToggle($event.event, $event.collapsed)">
<div *ngFor="let achievement of user.achievements;"> <div *ngFor="let achievement of user.achievements;">
<div class="content-row"> <div class="content-row">
<div class="content-column"> <div class="content-column">
@ -86,6 +180,11 @@
<div class="content-data-value">{{achievement.name}}</div> <div class="content-data-value">{{achievement.name}}</div>
</div> </div>
<div class="content-column">
<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-column">
<div class="content-data-name">{{'view.server.profile.achievements.time' | translate}}:</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 class="content-data-value">{{achievement.createdAt | date:'dd.MM.yyyy HH:mm:ss'}}</div>
@ -94,7 +193,8 @@
</div> </div>
</p-panel> </p-panel>
<p-panel header="{{'view.server.profile.joined_voice_channel.header' | translate}}" [toggleable]="true"> <p-panel header="{{'view.server.profile.joined_voice_channel.header' | translate}}" [toggleable]="true" [collapsed]="true"
(onBeforeToggle)="onBeforeToggle($event.event, $event.collapsed)">
<div *ngFor="let join of user.joinedVoiceChannels;"> <div *ngFor="let join of user.joinedVoiceChannels;">
<div class="content-row"> <div class="content-row">
<div class="content-column"> <div class="content-column">
@ -120,7 +220,8 @@
</div> </div>
</p-panel> </p-panel>
<p-panel header="{{'view.server.profile.joined_game_server.header' | translate}}" [toggleable]="true"> <p-panel header="{{'view.server.profile.joined_game_server.header' | translate}}" [toggleable]="true" [collapsed]="true"
(onBeforeToggle)="onBeforeToggle($event.event, $event.collapsed)">
<div *ngFor="let join of user.userJoinedGameServers;"> <div *ngFor="let join of user.userJoinedGameServers;">
<div class="content-row"> <div class="content-row">
<div class="content-column"> <div class="content-column">

View File

@ -1,7 +1,7 @@
import { Component, OnDestroy, OnInit } from "@angular/core"; import { Component, OnDestroy, OnInit } from "@angular/core";
import { ActivatedRoute, Router } from "@angular/router"; import { ActivatedRoute, Router } from "@angular/router";
import { Queries } from "../../../../models/graphql/queries.model"; import { Queries } from "../../../../models/graphql/queries.model";
import { UserListQuery } from "../../../../models/graphql/query.model"; import { UserListQuery, UserWarningQuery } from "../../../../models/graphql/query.model";
import { SpinnerService } from "../../../../services/spinner/spinner.service"; import { SpinnerService } from "../../../../services/spinner/spinner.service";
import { DataService } from "../../../../services/data/data.service"; import { DataService } from "../../../../services/data/data.service";
import { User } from "../../../../models/data/user.model"; import { User } from "../../../../models/data/user.model";
@ -10,8 +10,9 @@ import { AuthService } from "src/app/services/auth/auth.service";
import { ToastService } from "src/app/services/toast/toast.service"; import { ToastService } from "src/app/services/toast/toast.service";
import { TranslateService } from "@ngx-translate/core"; import { TranslateService } from "@ngx-translate/core";
import { Server } from "../../../../models/data/server.model"; import { Server } from "../../../../models/data/server.model";
import { Subject } from "rxjs"; import { forkJoin, Subject } from "rxjs";
import { takeUntil } from "rxjs/operators"; import { takeUntil } from "rxjs/operators";
import { Table } from "primeng/table";
@Component({ @Component({
selector: "app-profile", selector: "app-profile",
@ -58,23 +59,98 @@ export class ProfileComponent implements OnInit, OnDestroy {
this.data.query<UserListQuery>(Queries.userProfile, { this.data.query<UserListQuery>(Queries.userProfile, {
serverId: this.server.id, serverId: this.server.id,
userId: params["memberId"] userId: params["memberId"]
},
(x: { servers: Server[] }) => {
return x.servers[0];
} }
).subscribe(users => { ).subscribe(users => {
if (!users.users[0]) { if (!users.users[0]) {
this.router.navigate([`/server/${server.id}`]); this.router.navigate([`/server/${server.id}`]);
} }
this.user = users.users[0]; this.user = users.users[0];
this.data.query<UserWarningQuery>(Queries.userProfileWarnings, {
serverId: this.server.id,
userId: this.user.id
},
(data: UserListQuery) => {
return data.users[0];
}
).subscribe(result => {
this.user.userWarningCount = result.userWarningCount;
this.user.userWarnings = result.userWarnings;
console.log(result);
this.spinner.hideSpinner(); this.spinner.hideSpinner();
}); });
}); });
}); });
});
} }
public ngOnDestroy(): void { public ngOnDestroy(): void {
this.unsubscriber.next(); this.unsubscriber.next();
this.unsubscriber.complete(); this.unsubscriber.complete();
} }
public onBeforeToggle(event: Event, collapsed: boolean) {
const filterUser = (x: { users: User[] }) => {
const users = x.users ?? [];
return users[0];
};
if (collapsed) {
this.spinner.showSpinner();
forkJoin([
this.data.query<User>(Queries.userProfileAchievements, {
serverId: this.server.id,
userId: this.user.id
},
filterUser
),
this.data.query<User>(Queries.userProfileVoiceChannelJoins, {
serverId: this.server.id,
userId: this.user.id
},
filterUser
),
this.data.query<User>(Queries.userProfileGameserverJoins, {
serverId: this.server.id,
userId: this.user.id
},
filterUser
)
]).subscribe(data => {
this.user.achievementCount = data[0].achievementCount;
this.user.achievements = data[0].achievements;
this.user.joinedVoiceChannelCount = data[1].joinedVoiceChannelCount;
this.user.joinedVoiceChannels = data[1].joinedVoiceChannels;
this.user.userJoinedGameServerCount = data[2].userJoinedGameServerCount;
this.user.userJoinedGameServers = data[2].userJoinedGameServers;
this.spinner.hideSpinner();
});
return;
}
this.user.achievementCount = 0;
this.user.achievements = [];
this.user.userJoinedGameServerCount = 0;
this.user.userJoinedGameServers = [];
this.user.joinedVoiceChannelCount = 0;
this.user.joinedVoiceChannels = [];
}
addNewUserWarning(table: Table) {
}
deleteUserWarning(index: number) {
}
editSaveUserWarning(value: any, index: number) {
}
editCancelUserWarning(index: number) {
}
protected readonly visualViewport = visualViewport;
} }

View File

@ -1,12 +1,11 @@
import { NgModule } from '@angular/core'; import { NgModule } from "@angular/core";
import { CommonModule } from '@angular/common'; import { CommonModule } from "@angular/common";
import { ServerDashboardComponent } from './server-dashboard/server-dashboard.component'; import { ServerDashboardComponent } from "./server-dashboard/server-dashboard.component";
import { ServerRoutingModule } from './server-routing.module'; import { ServerRoutingModule } from "./server-routing.module";
import { SharedModule } from '../../shared/shared.module'; import { SharedModule } from "../../shared/shared.module";
import { ProfileComponent } from './profile/profile.component'; import { ProfileComponent } from "./profile/profile.component";
import { MembersComponent } from './members/members.component'; import { MembersComponent } from "./members/members.component";
import { ClientComponent } from './server-dashboard/components/client/client.component'; import { ClientComponent } from "./server-dashboard/components/client/client.component";
@NgModule({ @NgModule({

View File

@ -194,7 +194,6 @@ export class SidebarService {
let user: UserDTO | null = authUser?.users?.find(u => u.server == this.server?.id) ?? null; let user: UserDTO | null = authUser?.users?.find(u => u.server == this.server?.id) ?? null;
let isTechnician = (authUser?.users?.map(u => u.isTechnician).filter(u => u) ?? []).length > 0; let isTechnician = (authUser?.users?.map(u => u.isTechnician).filter(u => u) ?? []).length > 0;
let isTechnicianAndFullAccessActive = this.hasFeature("TechnicianFullAccess") && isTechnician; let isTechnicianAndFullAccessActive = this.hasFeature("TechnicianFullAccess") && isTechnician;
console.log(this.hasFeature("TechnicianFullAccess"))
if (build || this.menuItems$.value.length == 0) { if (build || this.menuItems$.value.length == 0) {
await this.buildMenu(user, hasPermission, isTechnician); await this.buildMenu(user, hasPermission, isTechnician);

View File

@ -122,6 +122,8 @@
} }
}, },
"common": { "common": {
"user_warnings": "Verwarnungen",
"author": "Autor",
"404": "404 - Der Eintrag konnte nicht gefunden werden", "404": "404 - Der Eintrag konnte nicht gefunden werden",
"actions": "Aktionen", "actions": "Aktionen",
"active": "Aktiv", "active": "Aktiv",

View File

@ -2,6 +2,6 @@
"WebVersion": { "WebVersion": {
"Major": "1", "Major": "1",
"Minor": "1", "Minor": "1",
"Micro": "10" "Micro": "dev402"
} }
} }

View File

@ -201,10 +201,10 @@ header {
font-size: 18px; font-size: 18px;
} }
}
.content-divider { .content-divider {
margin: 5px 0; margin: 10px 0;
}
} }
p-panel { p-panel {
@ -493,7 +493,7 @@ header {
} }
.content-divider { .content-divider {
margin: 5px 0; margin: 10px 0;
} }
.content-input-field { .content-input-field {

View File

@ -20,7 +20,8 @@
background-color: $primaryBackgroundColor; background-color: $primaryBackgroundColor;
h1, h1,
h2 { h2,
h3 {
color: $primaryHeaderColor; color: $primaryHeaderColor;
} }

View File

@ -20,7 +20,8 @@
background-color: $primaryBackgroundColor; background-color: $primaryBackgroundColor;
h1, h1,
h2 { h2,
h3 {
color: $primaryHeaderColor; color: $primaryHeaderColor;
} }

View File

@ -21,7 +21,8 @@
h1, h1,
h2 { h2,
h3 {
color: $primaryHeaderColor; color: $primaryHeaderColor;
} }

View File

@ -20,7 +20,8 @@
background-color: $primaryBackgroundColor; background-color: $primaryBackgroundColor;
h1, h1,
h2 { h2,
h3 {
color: $primaryHeaderColor; color: $primaryHeaderColor;
} }