Improved history component #246

This commit is contained in:
Sven Heidemann 2023-03-08 14:38:08 +01:00
parent 69ce659328
commit 51f0ee5744
21 changed files with 305 additions and 33 deletions

View File

@ -1,6 +1,6 @@
{ {
"name": "kdb-web", "name": "kdb-web",
"version": "1.0.dev247", "version": "1.0.dev246",
"scripts": { "scripts": {
"ng": "ng", "ng": "ng",
"update-version": "ts-node-esm update-version.ts", "update-version": "ts-node-esm update-version.ts",
@ -50,4 +50,4 @@
"tslib": "^2.4.1", "tslib": "^2.4.1",
"typescript": "~4.9.5" "typescript": "~4.9.5"
} }
} }

View File

@ -2,3 +2,16 @@ export interface Data {
createdAt?: string; createdAt?: string;
modifiedAt?: string; modifiedAt?: string;
} }
export interface DataWithHistory {
createdAt?: string;
modifiedAt?: string;
history?: History[];
}
export interface History {
deleted?: boolean;
dateFrom?: string;
dateTo?: string;
[x: string | number | symbol]: unknown;
}

View File

@ -1,11 +1,11 @@
import { Data } from "./data.model"; import { DataWithHistory } from "./data.model";
import { Level, LevelFilter } from "./level.model"; import { Level, LevelFilter } from "./level.model";
import { Server, ServerFilter } from "./server.model"; import { Server, ServerFilter } from "./server.model";
import { UserJoinedServer } from "./user_joined_server.model"; 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";
export interface User extends Data { export interface User extends DataWithHistory {
id?: number; id?: number;
discordId?: number; discordId?: number;
name?: string; name?: string;
@ -23,6 +23,17 @@ export interface User extends Data {
userJoinedGameServerCount?: number; userJoinedGameServerCount?: number;
userJoinedGameServers?: UserJoinedGameServer[]; userJoinedGameServers?: UserJoinedGameServer[];
// history?: UserHistory[];
}
export interface UserHistory extends History {
id?: number;
discordId?: number;
xp?: number;
level?: number;
server?: number;
leftServer?: boolean;
} }
export interface UserFilter { export interface UserFilter {

View File

@ -115,6 +115,17 @@ export class Queries {
createdAt createdAt
modifiedAt modifiedAt
history {
id
discordId
xp
server
leftServer
deleted
dateFrom
dateTo
}
} }
} }
} }

View File

@ -0,0 +1,21 @@
<button pButton class="btn icon-btn" icon="pi pi-history" (click)="openHistory()"></button>
<p-sidebar styleClass="history p-sidebar-md" [(visible)]="showSidebar" position="right" [baseZIndex]="10000">
<h1>{{translationKey | translate}} {{'common.history.header' | translate}}</h1>
<div class="entry-list">
<div class="entry" *ngFor="let entry of history">
<div class="attribute" *ngFor="let item of entry | keyvalue">
<div class="key">
{{getAttributeTranslationKey(item.key) | translate}}
</div>
<div class="seperator">
->
</div>
<div class="value">
{{item.value}}
</div>
</div>
</div>
</div>
</p-sidebar>

View File

@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { HistoryBtnComponent } from './history-btn.component';
describe('HistoryBtnComponent', () => {
let component: HistoryBtnComponent;
let fixture: ComponentFixture<HistoryBtnComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ HistoryBtnComponent ]
})
.compileComponents();
fixture = TestBed.createComponent(HistoryBtnComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,31 @@
import { Component, Input, OnInit } from "@angular/core";
import { History } from "../../../../models/data/data.model";
@Component({
selector: "app-history-btn",
templateUrl: "./history-btn.component.html",
styleUrls: ["./history-btn.component.scss"]
})
export class HistoryBtnComponent implements OnInit {
@Input() history: History[] = [];
@Input() translationKey: string = "";
showSidebar = false;
constructor() {
}
ngOnInit(): void {
}
openHistory(): void {
console.log("history", this.history);
this.showSidebar = true;
}
getAttributeTranslationKey(key: string) {
return `common.history.${key}`;
}
}

View File

@ -0,0 +1 @@
<p>history works!</p>

View File

@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { HistoryComponent } from './history.component';
describe('HistoryComponent', () => {
let component: HistoryComponent;
let fixture: ComponentFixture<HistoryComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ HistoryComponent ]
})
.compileComponents();
fixture = TestBed.createComponent(HistoryComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,10 @@
import { Component } from '@angular/core';
@Component({
selector: 'app-history',
templateUrl: './history.component.html',
styleUrls: ['./history.component.scss']
})
export class HistoryComponent {
}

View File

@ -1,28 +1,30 @@
import { CommonModule } from '@angular/common'; import { CommonModule } from "@angular/common";
import { HttpClientModule } from '@angular/common/http'; import { HttpClientModule } from "@angular/common/http";
import { NgModule } from '@angular/core'; import { NgModule } from "@angular/core";
import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { FormsModule, ReactiveFormsModule } from "@angular/forms";
import { TranslateModule } from '@ngx-translate/core'; import { TranslateModule } from "@ngx-translate/core";
import { ButtonModule } from 'primeng/button'; import { ButtonModule } from "primeng/button";
import { CheckboxModule } from 'primeng/checkbox'; import { CheckboxModule } from "primeng/checkbox";
import { ConfirmDialogModule } from 'primeng/confirmdialog'; import { ConfirmDialogModule } from "primeng/confirmdialog";
import { DialogModule } from 'primeng/dialog'; import { DialogModule } from "primeng/dialog";
import { DropdownModule } from 'primeng/dropdown'; import { DropdownModule } from "primeng/dropdown";
import { DynamicDialogModule } from 'primeng/dynamicdialog'; import { DynamicDialogModule } from "primeng/dynamicdialog";
import { InputTextModule } from 'primeng/inputtext'; import { InputTextModule } from "primeng/inputtext";
import { MenuModule } from 'primeng/menu'; import { MenuModule } from "primeng/menu";
import { PasswordModule } from 'primeng/password'; import { PasswordModule } from "primeng/password";
import { ProgressSpinnerModule } from 'primeng/progressspinner'; import { ProgressSpinnerModule } from "primeng/progressspinner";
import { TableModule } from 'primeng/table'; import { TableModule } from "primeng/table";
import { ToastModule } from 'primeng/toast'; import { ToastModule } from "primeng/toast";
import { AuthRolePipe } from './pipes/auth-role.pipe'; import { AuthRolePipe } from "./pipes/auth-role.pipe";
import { IpAddressPipe } from './pipes/ip-address.pipe'; import { IpAddressPipe } from "./pipes/ip-address.pipe";
import { BoolPipe } from './pipes/bool.pipe'; import { BoolPipe } from "./pipes/bool.pipe";
import { PanelMenuModule } from 'primeng/panelmenu'; import { PanelMenuModule } from "primeng/panelmenu";
import { PanelModule } from "primeng/panel"; import { PanelModule } from "primeng/panel";
import { InputNumberModule } from 'primeng/inputnumber'; import { InputNumberModule } from "primeng/inputnumber";
import { ImageModule } from "primeng/image"; import { ImageModule } from "primeng/image";
import { SidebarModule } from "primeng/sidebar";
import { HistoryComponent } from "./components/history/history.component";
import { HistoryBtnComponent } from './components/history-btn/history-btn.component';
@NgModule({ @NgModule({
@ -30,6 +32,8 @@ import { ImageModule } from "primeng/image";
AuthRolePipe, AuthRolePipe,
IpAddressPipe, IpAddressPipe,
BoolPipe, BoolPipe,
HistoryComponent,
HistoryBtnComponent,
], ],
imports: [ imports: [
CommonModule, CommonModule,
@ -52,7 +56,8 @@ import { ImageModule } from "primeng/image";
PanelMenuModule, PanelMenuModule,
PanelModule, PanelModule,
InputNumberModule, InputNumberModule,
ImageModule ImageModule,
SidebarModule,
], ],
exports: [ exports: [
ButtonModule, ButtonModule,
@ -77,7 +82,9 @@ import { ImageModule } from "primeng/image";
IpAddressPipe, IpAddressPipe,
BoolPipe, BoolPipe,
InputNumberModule, InputNumberModule,
ImageModule ImageModule,
SidebarModule,
HistoryBtnComponent
] ]
}) })
export class SharedModule { } export class SharedModule { }

View File

@ -224,6 +224,7 @@
</td> </td>
<td> <td>
<div class="btn-wrapper"> <div class="btn-wrapper">
<app-history-btn [history]="member.history" 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

@ -3,7 +3,7 @@
"WebVersion": { "WebVersion": {
"Major": "1", "Major": "1",
"Minor": "0", "Minor": "0",
"Micro": "dev247" "Micro": "dev246"
}, },
"Themes": [ "Themes": [
{ {
@ -23,4 +23,4 @@
"Name": "sh-edraft-dark-theme" "Name": "sh-edraft-dark-theme"
} }
] ]
} }

View File

@ -134,7 +134,18 @@
"modified_at": "Bearbeitet am", "modified_at": "Bearbeitet am",
"no_entries_found": "Keine Einträge gefunden", "no_entries_found": "Keine Einträge gefunden",
"of": "von", "of": "von",
"reset_filters": "Filter zurücksetzen" "reset_filters": "Filter zurücksetzen",
"history": {
"header": "Historie",
"id": "Id",
"discordId": "Discord Id",
"deleted": "Gelöscht",
"dateFrom": "Von",
"dateTo": "Bis",
"server": "Server",
"leftServer": "Gegangen",
"xp": "XP"
}
}, },
"dialog": { "dialog": {
"abort": "Abbrechen", "abort": "Abbrechen",

View File

@ -5,13 +5,39 @@
@import "./styles/primeng-fixes.scss"; @import "./styles/primeng-fixes.scss";
@import "./styles/constants.scss"; @import "./styles/constants.scss";
html, html,
body { body {
height: 100%; height: 100vh;
padding: 0; padding: 0;
margin: 0; margin: 0;
font-size: 1rem; font-size: 1rem;
$scrollbarColor: #272727;
$scrollbarBackgroundColor: #888;
/* width */
::-webkit-scrollbar {
width: 10px;
}
/* Track */
::-webkit-scrollbar-track {
background-color: $scrollbarBackgroundColor;
}
/* Handle */
::-webkit-scrollbar-thumb {
background: $scrollbarColor;
border: 3px solid $scrollbarBackgroundColor;
border-radius: 10px;
}
/* Handle on hover */
::-webkit-scrollbar-thumb:hover {
background: $scrollbarColor;
}
} }
main { main {
@ -332,6 +358,43 @@ header {
} }
} }
.history {
width: 300px;
.entry-list {
display: flex;
flex-direction: column;
gap: 15px;
.entry {
padding-bottom: 10px;
display: flex;
flex-direction: column;
gap: 5px;
.attribute {
display: flex;
gap: 5px;
.key {
width: 30%;
}
.seperator {
width: 10%;
}
.value {
width: 60%;
}
}
}
}
}
.p-dialog-header { .p-dialog-header {
padding: 20px 20px 20px 20px !important; padding: 20px 20px 20px 20px !important;
} }

View File

@ -175,6 +175,17 @@
} }
} }
.history {
background-color: $primaryBackgroundColor;
color: $primaryTextColor;
.entry-list {
.entry {
border-bottom: 1px solid $primaryHeaderColor;
}
}
}
.p-dialog-header { .p-dialog-header {
background-color: $secondaryBackgroundColor !important; background-color: $secondaryBackgroundColor !important;
color: $primaryTextColor !important; color: $primaryTextColor !important;

View File

@ -175,6 +175,17 @@
} }
} }
.history {
background-color: $primaryBackgroundColor;
color: $primaryTextColor;
.entry-list {
.entry {
border-bottom: 1px solid $primaryHeaderColor;
}
}
}
.p-dialog-header { .p-dialog-header {
background-color: $secondaryBackgroundColor !important; background-color: $secondaryBackgroundColor !important;
color: $primaryTextColor !important; color: $primaryTextColor !important;

View File

@ -19,6 +19,7 @@
background-color: $primaryBackgroundColor; background-color: $primaryBackgroundColor;
h1, h1,
h2 { h2 {
color: $primaryHeaderColor; color: $primaryHeaderColor;
@ -175,6 +176,18 @@
} }
} }
.history {
background-color: $primaryBackgroundColor;
color: $primaryTextColor;
.entry-list {
.entry {
border-bottom: 1px solid $primaryHeaderColor;
}
}
}
.p-dialog-header { .p-dialog-header {
background-color: $primaryBackgroundColor !important; background-color: $primaryBackgroundColor !important;
color: $primaryTextColor !important; color: $primaryTextColor !important;

View File

@ -175,6 +175,17 @@
} }
} }
.history {
background-color: $primaryBackgroundColor;
color: $primaryTextColor;
.entry-list {
.entry {
border-bottom: 1px solid $primaryHeaderColor;
}
}
}
.p-dialog-header { .p-dialog-header {
background-color: $secondaryBackgroundColor !important; background-color: $secondaryBackgroundColor !important;
color: $primaryTextColor !important; color: $primaryTextColor !important;