Updated profile #409
This commit is contained in:
@@ -36,6 +36,8 @@ export interface User extends DataWithHistory {
|
||||
|
||||
userWarningCount?: number;
|
||||
userWarnings?: UserWarning[];
|
||||
|
||||
profilePictureURL?: string;
|
||||
}
|
||||
|
||||
export interface UserFilter {
|
||||
|
@@ -406,6 +406,7 @@ export class Queries {
|
||||
joinedOn
|
||||
leavedOn
|
||||
}
|
||||
profilePictureURL
|
||||
|
||||
createdAt
|
||||
modifiedAt
|
||||
|
@@ -40,6 +40,7 @@ import { TabViewModule } from "primeng/tabview";
|
||||
import { RadioButtonModule } from "primeng/radiobutton";
|
||||
import { InputTextareaModule } from "primeng/inputtextarea";
|
||||
import { InputMaskModule } from "primeng/inputmask";
|
||||
import { KnobModule } from "primeng/knob";
|
||||
|
||||
|
||||
const PrimeNGModules = [
|
||||
@@ -73,7 +74,8 @@ const PrimeNGModules = [
|
||||
TabViewModule,
|
||||
RadioButtonModule,
|
||||
InputTextareaModule,
|
||||
InputMaskModule
|
||||
InputMaskModule,
|
||||
KnobModule
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
|
@@ -2,119 +2,94 @@
|
||||
{{'view.server.profile.header' | translate}}
|
||||
</h1>
|
||||
<div class="content-wrapper">
|
||||
<div class="content-header">
|
||||
<h2>
|
||||
{{user.name}}
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<div class="content">
|
||||
<div class="content-row">
|
||||
<div class="content-column">
|
||||
<div class="content-data-name">{{'common.id' | translate}}:</div>
|
||||
<div class="content-data-value">{{user.id}}</div>
|
||||
<div class="logo">
|
||||
<img *ngIf="user ? user.profilePictureURL : ''" [src]="user ? user.profilePictureURL : ''">
|
||||
</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">
|
||||
<div class="content-column">
|
||||
<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>
|
||||
<div class="content-column">
|
||||
<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>
|
||||
<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>
|
||||
<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 *ngIf="isEditing" class="content-data-value">
|
||||
<p-calendar [(ngModel)]="user.birthday" dateFormat="dd.mm.yy" [showIcon]="true"></p-calendar>
|
||||
</div>
|
||||
</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>
|
||||
<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>
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content">
|
||||
<div class="content-column">
|
||||
<div class="content-data-name" style="flex-direction: column; justify-content: start;">
|
||||
<p-knob valueTemplate="{value} {{'view.server.profile.xp' | translate}}" [(ngModel)]="user.xp" [size]="150"
|
||||
[strokeWidth]="10"
|
||||
[max]="maxXp" valueColor="SlateGray" rangeColor="MediumTurquoise"
|
||||
[readonly]="isModerator && !isEditing"></p-knob>
|
||||
</div>
|
||||
<div class="content-data-value" style="flex-direction: column; justify-content: start;">
|
||||
<p-knob valueTemplate="Lvl {value}" [(ngModel)]="activeLevelIndex"
|
||||
[size]="150"
|
||||
[strokeWidth]="10"
|
||||
[min]="1"
|
||||
[max]="levels ? levels.length : 0" valueColor="SlateGray" rangeColor="MediumTurquoise"
|
||||
[readonly]="isModerator && !isEditing"></p-knob>
|
||||
|
||||
<div class="content-row">
|
||||
<div class="content-column">
|
||||
<div class="content-data-name">{{'view.server.profile.name' | translate}}:</div>
|
||||
<div class="content-data-value">{{user.name}}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="content-row">
|
||||
<div class="content-column">
|
||||
<div class="content-data-name">{{'view.server.profile.xp' | translate}}:</div>
|
||||
<div *ngIf="!isEditing" class="content-data-value">{{user.xp}}</div>
|
||||
<div *ngIf="isModerator && isEditing" class="content-data-value"><input class="table-edit-input" pInputText
|
||||
min="0" type="number"
|
||||
[(ngModel)]="user.xp"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="content-row">
|
||||
<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>
|
||||
</div>
|
||||
|
||||
<div class="content-row">
|
||||
<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>
|
||||
</div>
|
||||
|
||||
<div class="content-row">
|
||||
<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 *ngIf="isEditing" class="content-data-value">
|
||||
<p-calendar [(ngModel)]="user.birthday" dateFormat="dd.mm.yy" [showIcon]="true"></p-calendar>
|
||||
<div *ngIf="user.level">
|
||||
{{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>
|
||||
<div class="content-column">
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="content-row">
|
||||
<div class="content-column">
|
||||
<div class="content-data-name">{{'common.ontime' | translate}}:</div>
|
||||
<div class="content-data-value">{{user.ontime}}</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-column">
|
||||
<div class="content-data-name">{{'view.server.profile.level' | translate}}:</div>
|
||||
<div *ngIf="!isEditing" class="content-data-value">{{user.level?.name}}</div>
|
||||
<div *ngIf="isModerator && isEditing" class="content-data-value">
|
||||
<p-dropdown [options]="levels" [(ngModel)]="user.level" dataKey="id"
|
||||
placeholder="{{'common.level' | translate}}">
|
||||
</p-dropdown>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="content-row">
|
||||
<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>
|
||||
</div>
|
||||
|
||||
<div class="content-row">
|
||||
<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>
|
||||
</div>
|
||||
|
||||
<div class="content-row">
|
||||
<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>
|
||||
</div>
|
||||
|
||||
<div class="content">
|
||||
<div>
|
||||
<div class="content-divider"></div>
|
||||
<p-table #dt [value]="(user.userWarnings ?? [])" [responsive]="true" responsiveLayout="stack"
|
||||
@@ -199,7 +174,8 @@
|
||||
<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"
|
||||
<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"
|
||||
|
@@ -0,0 +1,6 @@
|
||||
.logo {
|
||||
img {
|
||||
width: 12.5vw;
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
|
@@ -15,10 +15,10 @@ import { catchError, takeUntil } from "rxjs/operators";
|
||||
import { Table } from "primeng/table";
|
||||
import { UpdateUserMutationResult } from "../../../../models/graphql/result.model";
|
||||
import { Mutations } from "../../../../models/graphql/mutations.model";
|
||||
import { MenuItem } from "primeng/api";
|
||||
import { UserWarning } from "../../../../models/data/user_warning.model";
|
||||
import moment from "moment";
|
||||
import { SidebarService } from "../../../../services/sidebar/sidebar.service";
|
||||
import { Level } from "../../../../models/data/level.model";
|
||||
|
||||
@Component({
|
||||
selector: "app-profile",
|
||||
@@ -28,7 +28,7 @@ import { SidebarService } from "../../../../services/sidebar/sidebar.service";
|
||||
export class ProfileComponent implements OnInit, OnDestroy {
|
||||
|
||||
user: User = { createdAt: "", modifiedAt: "" };
|
||||
levels!: MenuItem[];
|
||||
levels!: { label: string, value: Level }[];
|
||||
private server: Server = {};
|
||||
private author?: UserDTO;
|
||||
private clonedUserWarnings: UserWarning[] = [];
|
||||
@@ -36,6 +36,21 @@ export class ProfileComponent implements OnInit, OnDestroy {
|
||||
public isEditing: boolean = false;
|
||||
public isModerator: boolean = false;
|
||||
public hasTechnicianAccess: boolean = false;
|
||||
public maxXp: number = 0;
|
||||
private _activeLevelIndex: number = 0;
|
||||
|
||||
public get activeLevelIndex(): number {
|
||||
return this._activeLevelIndex;
|
||||
}
|
||||
|
||||
public set activeLevelIndex(value: number) {
|
||||
if (value < 1) {
|
||||
value = 1;
|
||||
}
|
||||
|
||||
this._activeLevelIndex = value;
|
||||
this.user.level = this.levels.map(x => x.value)[value - 1];
|
||||
}
|
||||
|
||||
private unsubscriber = new Subject<void>();
|
||||
|
||||
@@ -48,7 +63,7 @@ export class ProfileComponent implements OnInit, OnDestroy {
|
||||
private toast: ToastService,
|
||||
private translate: TranslateService,
|
||||
private toastService: ToastService,
|
||||
private sidebarService: SidebarService,
|
||||
private sidebarService: SidebarService
|
||||
) {
|
||||
}
|
||||
|
||||
@@ -74,7 +89,11 @@ export class ProfileComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
).subscribe(data => {
|
||||
this.levels = data.levels.map(level => {
|
||||
return { label: level.name, value: level };
|
||||
if (level.minXp && level.minXp > this.maxXp) {
|
||||
this.maxXp = level.minXp;
|
||||
}
|
||||
|
||||
return { label: level.name ?? "", value: level };
|
||||
});
|
||||
});
|
||||
|
||||
@@ -100,6 +119,9 @@ export class ProfileComponent implements OnInit, OnDestroy {
|
||||
this.router.navigate([`/server/${server.id}`]);
|
||||
}
|
||||
this.user = users.users[0];
|
||||
if (this.user.level) {
|
||||
this.activeLevelIndex = this.levels.reverse().map(l => l.value.id).indexOf(this.user.level.id) + 1;
|
||||
}
|
||||
|
||||
this.data.query<UserWarningQuery>(Queries.userProfileWarnings, {
|
||||
serverId: this.server.id,
|
||||
|
@@ -541,6 +541,7 @@
|
||||
},
|
||||
"left_server": "Hat Server verlassen",
|
||||
"level": "Level",
|
||||
"lvl": "Lvl",
|
||||
"message_count": "Anzahl Nachrichten",
|
||||
"minecraft_id": "Minecraft Id",
|
||||
"name": "Name",
|
||||
|
@@ -541,6 +541,7 @@
|
||||
},
|
||||
"left_server": "Leaved server",
|
||||
"level": "Level",
|
||||
"lvl": "Lvl",
|
||||
"message_count": "Message count",
|
||||
"minecraft_id": "Minecraft Id",
|
||||
"name": "Name",
|
||||
|
@@ -177,40 +177,40 @@ header {
|
||||
flex: 1;
|
||||
margin: 5px 0;
|
||||
gap: 5px;
|
||||
}
|
||||
|
||||
.content-column {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
gap: 5px;
|
||||
.content-column {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
gap: 5px;
|
||||
}
|
||||
|
||||
.content-data-name {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
font-size: 18px;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.content-data-value {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
font-size: 18px;
|
||||
flex: 1;
|
||||
|
||||
input {
|
||||
width: 100% !important;
|
||||
}
|
||||
}
|
||||
|
||||
.content-data-name {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.content-data-value-row {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
|
||||
font-size: 18px;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.content-data-value {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
font-size: 18px;
|
||||
flex: 1;
|
||||
|
||||
input {
|
||||
width: 100% !important;
|
||||
}
|
||||
}
|
||||
|
||||
.content-data-value-row {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
|
||||
font-size: 18px;
|
||||
}
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.content-divider {
|
||||
|
@@ -814,4 +814,22 @@
|
||||
box-shadow: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
p-knob {
|
||||
.p-knob {
|
||||
svg {
|
||||
.p-knob-value {
|
||||
stroke: $primaryHeaderColor !important;
|
||||
}
|
||||
|
||||
.p-knob-range {
|
||||
stroke: $secondaryBackgroundColor !important;
|
||||
}
|
||||
|
||||
.p-knob-text {
|
||||
font-size: 1rem !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user