Added data import & export #407
This commit is contained in:
parent
90ae55c0d4
commit
33006e3d01
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "web",
|
"name": "web",
|
||||||
"version": "1.2.0",
|
"version": "1.2.dev407",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"ng": "ng",
|
"ng": "ng",
|
||||||
"update-version": "ts-node update-version.ts",
|
"update-version": "ts-node update-version.ts",
|
||||||
|
@ -1,44 +1,58 @@
|
|||||||
|
import { Level } from "../models/data/level.model";
|
||||||
|
|
||||||
export interface Column {
|
export interface Column {
|
||||||
key: string;
|
key: string;
|
||||||
name: string;
|
name: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ComponentWithTable {
|
export class ComponentWithTable {
|
||||||
|
private _hiddenColumns: Column[] = [];
|
||||||
private _hiddenColumns: Column[] = [];
|
set hiddenColumns(value: Column[]) {
|
||||||
set hiddenColumns(value: Column[]) {
|
this._hiddenColumns = value;
|
||||||
this._hiddenColumns = value;
|
localStorage.setItem("hiddenColumns", JSON.stringify(value));
|
||||||
localStorage.setItem("hiddenColumns", JSON.stringify(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
get hiddenColumns(): Column[] {
|
|
||||||
return this._hiddenColumns;
|
|
||||||
}
|
|
||||||
|
|
||||||
public name: string = "";
|
|
||||||
public columns: Column[] = [];
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
name: string,
|
|
||||||
columns: string[]
|
|
||||||
) {
|
|
||||||
this.name = name;
|
|
||||||
this.columns = columns.map(column => {
|
|
||||||
return { key: this.getKey(column), name: column };
|
|
||||||
});
|
|
||||||
let hiddenColumns = localStorage.getItem("hiddenColumns");
|
|
||||||
if (!hiddenColumns) {
|
|
||||||
localStorage.setItem("hiddenColumns", JSON.stringify([{}]));
|
|
||||||
hiddenColumns = localStorage.getItem("hiddenColumns") ?? JSON.stringify([{}]);
|
|
||||||
}
|
}
|
||||||
this._hiddenColumns = JSON.parse(hiddenColumns);
|
|
||||||
}
|
|
||||||
|
|
||||||
private getKey(column: string): string {
|
get hiddenColumns(): Column[] {
|
||||||
return `${this.name}_${column}`;
|
return this._hiddenColumns;
|
||||||
}
|
}
|
||||||
|
|
||||||
public isColumnVisible(column: string): boolean {
|
public name: string = "";
|
||||||
return !this._hiddenColumns.map(column => column.key).includes(this.getKey(column));
|
public columns: Column[] = [];
|
||||||
}
|
|
||||||
|
constructor(
|
||||||
|
name: string,
|
||||||
|
columns: string[]
|
||||||
|
) {
|
||||||
|
this.name = name;
|
||||||
|
this.columns = columns.map(column => {
|
||||||
|
return { key: this.getKey(column), name: column };
|
||||||
|
});
|
||||||
|
let hiddenColumns = localStorage.getItem("hiddenColumns");
|
||||||
|
if (!hiddenColumns) {
|
||||||
|
localStorage.setItem("hiddenColumns", JSON.stringify([{}]));
|
||||||
|
hiddenColumns = localStorage.getItem("hiddenColumns") ?? JSON.stringify([{}]);
|
||||||
|
}
|
||||||
|
this._hiddenColumns = JSON.parse(hiddenColumns);
|
||||||
|
}
|
||||||
|
|
||||||
|
private getKey(column: string): string {
|
||||||
|
return `${this.name}_${column}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
public isColumnVisible(column: string): boolean {
|
||||||
|
return !this._hiddenColumns.map(column => column.key).includes(this.getKey(column));
|
||||||
|
}
|
||||||
|
|
||||||
|
public callback = (data: any[]) => {
|
||||||
|
this.save(data);
|
||||||
|
};
|
||||||
|
|
||||||
|
public onRowEditSave(newLevel: any, index: number) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public save(data: any[]) {
|
||||||
|
for (let i = 0; i < data.length; i++) {
|
||||||
|
this.onRowEditSave(data[i], i);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -225,7 +225,7 @@
|
|||||||
(click)="deleteUser(user)"></button>
|
(click)="deleteUser(user)"></button>
|
||||||
|
|
||||||
<button *ngIf="editing" pButton pSaveEditableRow class="btn icon-btn"
|
<button *ngIf="editing" pButton pSaveEditableRow class="btn icon-btn"
|
||||||
icon="pi pi-check-circle" (click)="onRowEditSave(dt, user, ri)"></button>
|
icon="pi pi-check-circle" (click)="onRowEditSave(user, ri)"></button>
|
||||||
<button *ngIf="editing" pButton pCancelEditableRow class="btn icon-btn danger-icon-btn"
|
<button *ngIf="editing" pButton pCancelEditableRow class="btn icon-btn danger-icon-btn"
|
||||||
icon="pi pi-times-circle" (click)="onRowEditCancel(user, ri)"></button>
|
icon="pi pi-times-circle" (click)="onRowEditCancel(user, ri)"></button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -193,7 +193,7 @@ export class AuthUserComponent extends ComponentWithTable implements OnInit, OnD
|
|||||||
this.clonedUsers[index] = { ...user };
|
this.clonedUsers[index] = { ...user };
|
||||||
}
|
}
|
||||||
|
|
||||||
onRowEditSave(table: Table, newUser: AuthUserDTO, index: number) {
|
public override onRowEditSave(newUser: AuthUserDTO, index: number) {
|
||||||
const oldUser = this.clonedUsers[index];
|
const oldUser = this.clonedUsers[index];
|
||||||
delete this.clonedUsers[index];
|
delete this.clonedUsers[index];
|
||||||
|
|
||||||
@ -219,7 +219,6 @@ export class AuthUserComponent extends ComponentWithTable implements OnInit, OnD
|
|||||||
newUser.email == ""
|
newUser.email == ""
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
table.initRowEdit(newUser);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -239,7 +238,6 @@ export class AuthUserComponent extends ComponentWithTable implements OnInit, OnD
|
|||||||
this.toastService.error(this.translate.instant("admin.auth_users.message.user_already_exists"), this.translate.instant("admin.auth_users.message.user_already_exists_d", { email: newUser.email }));
|
this.toastService.error(this.translate.instant("admin.auth_users.message.user_already_exists"), this.translate.instant("admin.auth_users.message.user_already_exists_d", { email: newUser.email }));
|
||||||
}
|
}
|
||||||
error.error = null;
|
error.error = null;
|
||||||
table.initRowEdit(newUser);
|
|
||||||
}
|
}
|
||||||
this.spinnerService.hideSpinner();
|
this.spinnerService.hideSpinner();
|
||||||
|
|
||||||
|
@ -0,0 +1,10 @@
|
|||||||
|
<button pButton pTooltip="{{'common.export' | translate}}" tooltipPosition="left" icon="pi pi-download"
|
||||||
|
class="icon-btn btn" (click)="export()">
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<p-fileUpload #upload pTooltip="{{'common.import' | translate}}" tooltipPosition="left" chooseIcon="pi pi-upload"
|
||||||
|
styleClass="icon-btn btn" mode="basic"
|
||||||
|
[auto]="true"
|
||||||
|
[customUpload]="true" accept="application/json"
|
||||||
|
(uploadHandler)="import($event)">
|
||||||
|
</p-fileUpload>
|
@ -0,0 +1,5 @@
|
|||||||
|
:host {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,23 @@
|
|||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { DataImportAndExportComponent } from './data-import-and-export.component';
|
||||||
|
|
||||||
|
describe('DataImportAndExportComponent', () => {
|
||||||
|
let component: DataImportAndExportComponent;
|
||||||
|
let fixture: ComponentFixture<DataImportAndExportComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
declarations: [ DataImportAndExportComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(DataImportAndExportComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,66 @@
|
|||||||
|
import { Component, EventEmitter, Input, Output, ViewChild } from "@angular/core";
|
||||||
|
import { ToastService } from "../../../../services/toast/toast.service";
|
||||||
|
import { TranslateService } from "@ngx-translate/core";
|
||||||
|
|
||||||
|
interface UploadEvent {
|
||||||
|
originalEvent: Event;
|
||||||
|
files: File[];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: "app-data-import-and-export",
|
||||||
|
templateUrl: "./data-import-and-export.component.html",
|
||||||
|
styleUrls: ["./data-import-and-export.component.scss"]
|
||||||
|
})
|
||||||
|
export class DataImportAndExportComponent {
|
||||||
|
|
||||||
|
@ViewChild("upload") upload: any;
|
||||||
|
|
||||||
|
private _data: any[] = [];
|
||||||
|
|
||||||
|
@Input() name: string = "";
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
set data(data: any[]) {
|
||||||
|
this._data = data;
|
||||||
|
this.dataChange.emit(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
get data(): any[] {
|
||||||
|
return this._data;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Output() dataChange: EventEmitter<any[]> = new EventEmitter<any[]>();
|
||||||
|
@Input() callback!: (data: any[]) => void;
|
||||||
|
|
||||||
|
public constructor(
|
||||||
|
private toastService: ToastService,
|
||||||
|
private translate: TranslateService
|
||||||
|
) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public export() {
|
||||||
|
const json = JSON.stringify(this.data);
|
||||||
|
const element = document.createElement("a");
|
||||||
|
element.setAttribute("href", "data:application/json;charset=UTF-8," + encodeURIComponent(json));
|
||||||
|
element.setAttribute("download", `${this.name}.json`);
|
||||||
|
element.style.display = "none";
|
||||||
|
document.body.appendChild(element);
|
||||||
|
element.click(); // simulate click
|
||||||
|
document.body.removeChild(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
public import(event: { files: File[] }) {
|
||||||
|
const file = event.files[0];
|
||||||
|
const fileReader = new FileReader();
|
||||||
|
fileReader.onload = () => {
|
||||||
|
if (!fileReader.result) return;
|
||||||
|
this.data = JSON.parse(fileReader.result.toString());
|
||||||
|
this.upload.clear();
|
||||||
|
this.callback(this.data);
|
||||||
|
this.toastService.success(this.translate.instant("common.file.uploaded"), this.translate.instant("common.file.uploaded"));
|
||||||
|
};
|
||||||
|
fileReader.readAsText(file, "UTF-8");
|
||||||
|
}
|
||||||
|
}
|
@ -33,6 +33,8 @@ import { MultiSelectColumnsComponent } from './base/multi-select-columns/multi-s
|
|||||||
import { FeatureFlagListComponent } from './components/feature-flag-list/feature-flag-list.component';
|
import { FeatureFlagListComponent } from './components/feature-flag-list/feature-flag-list.component';
|
||||||
import { InputSwitchModule } from "primeng/inputswitch";
|
import { InputSwitchModule } from "primeng/inputswitch";
|
||||||
import { CalendarModule } from "primeng/calendar";
|
import { CalendarModule } from "primeng/calendar";
|
||||||
|
import { DataImportAndExportComponent } from './components/data-import-and-export/data-import-and-export.component';
|
||||||
|
import { FileUploadModule } from "primeng/fileupload";
|
||||||
|
|
||||||
|
|
||||||
const PrimeNGModules = [
|
const PrimeNGModules = [
|
||||||
@ -61,6 +63,7 @@ const PrimeNGModules = [
|
|||||||
MultiSelectModule,
|
MultiSelectModule,
|
||||||
InputSwitchModule,
|
InputSwitchModule,
|
||||||
CalendarModule,
|
CalendarModule,
|
||||||
|
FileUploadModule,
|
||||||
]
|
]
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
@ -74,6 +77,7 @@ const PrimeNGModules = [
|
|||||||
HideableHeaderComponent,
|
HideableHeaderComponent,
|
||||||
MultiSelectColumnsComponent,
|
MultiSelectColumnsComponent,
|
||||||
FeatureFlagListComponent,
|
FeatureFlagListComponent,
|
||||||
|
DataImportAndExportComponent,
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
CommonModule,
|
CommonModule,
|
||||||
@ -91,6 +95,7 @@ const PrimeNGModules = [
|
|||||||
HideableHeaderComponent,
|
HideableHeaderComponent,
|
||||||
MultiSelectColumnsComponent,
|
MultiSelectColumnsComponent,
|
||||||
FeatureFlagListComponent,
|
FeatureFlagListComponent,
|
||||||
|
DataImportAndExportComponent
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class SharedModule {
|
export class SharedModule {
|
||||||
|
@ -27,6 +27,8 @@
|
|||||||
<button pButton label="{{'common.reset_filters' | translate}}" icon="pi pi-undo"
|
<button pButton label="{{'common.reset_filters' | translate}}" icon="pi pi-undo"
|
||||||
class="icon-btn btn" (click)="resetFilters()">
|
class="icon-btn btn" (click)="resetFilters()">
|
||||||
</button>
|
</button>
|
||||||
|
<app-data-import-and-export name="achievements" [(data)]="achievements"
|
||||||
|
[callback]="callback"></app-data-import-and-export>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
@ -246,7 +248,7 @@
|
|||||||
(click)="deleteAchievement(achievement)" [disabled]="!user || !user.isModerator && !user.isAdmin"></button>
|
(click)="deleteAchievement(achievement)" [disabled]="!user || !user.isModerator && !user.isAdmin"></button>
|
||||||
|
|
||||||
<button *ngIf="editing" pButton pSaveEditableRow class="btn icon-btn"
|
<button *ngIf="editing" pButton pSaveEditableRow class="btn icon-btn"
|
||||||
icon="pi pi-check-circle" (click)="onRowEditSave(dt, achievement, ri)" [disabled]="!user || !user.isModerator && !user.isAdmin"></button>
|
icon="pi pi-check-circle" (click)="onRowEditSave(achievement, ri)" [disabled]="!user || !user.isModerator && !user.isAdmin"></button>
|
||||||
<button *ngIf="editing" pButton pCancelEditableRow class="btn icon-btn danger-icon-btn"
|
<button *ngIf="editing" pButton pCancelEditableRow class="btn icon-btn danger-icon-btn"
|
||||||
icon="pi pi-times-circle" (click)="onRowEditCancel(ri)" [disabled]="!user || !user.isModerator && !user.isAdmin"></button>
|
icon="pi pi-times-circle" (click)="onRowEditCancel(ri)" [disabled]="!user || !user.isModerator && !user.isAdmin"></button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -215,7 +215,7 @@ export class AchievementComponent extends ComponentWithTable implements OnInit,
|
|||||||
this.clonedAchievements[index] = { ...user };
|
this.clonedAchievements[index] = { ...user };
|
||||||
}
|
}
|
||||||
|
|
||||||
public onRowEditSave(table: Table, newAchievement: Achievement, index: number): void {
|
public override onRowEditSave(newAchievement: Achievement, index: number): void {
|
||||||
if (this.isEditingNew && JSON.stringify(newAchievement) === JSON.stringify(this.newAchievementTemplate)) {
|
if (this.isEditingNew && JSON.stringify(newAchievement) === JSON.stringify(this.newAchievementTemplate)) {
|
||||||
this.isEditingNew = false;
|
this.isEditingNew = false;
|
||||||
this.achievements.splice(index, 1);
|
this.achievements.splice(index, 1);
|
||||||
|
@ -26,6 +26,8 @@
|
|||||||
<button pButton label="{{'common.reset_filters' | translate}}" icon="pi pi-undo"
|
<button pButton label="{{'common.reset_filters' | translate}}" icon="pi pi-undo"
|
||||||
class="icon-btn btn" (click)="resetFilters()">
|
class="icon-btn btn" (click)="resetFilters()">
|
||||||
</button>
|
</button>
|
||||||
|
<app-data-import-and-export name="achievements" [(data)]="rules"
|
||||||
|
[callback]="callback"></app-data-import-and-export>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
@ -174,7 +176,7 @@
|
|||||||
(click)="deleteAutoRoleRule(autoRoleRule)"></button>
|
(click)="deleteAutoRoleRule(autoRoleRule)"></button>
|
||||||
|
|
||||||
<button *ngIf="editing" pButton pSaveEditableRow class="btn icon-btn"
|
<button *ngIf="editing" pButton pSaveEditableRow class="btn icon-btn"
|
||||||
icon="pi pi-check-circle" (click)="onRowEditSave(dt, autoRoleRule, ri)"></button>
|
icon="pi pi-check-circle" (click)="onRowEditSave(autoRoleRule, ri)"></button>
|
||||||
<button *ngIf="editing" pButton pCancelEditableRow class="btn icon-btn danger-icon-btn"
|
<button *ngIf="editing" pButton pCancelEditableRow class="btn icon-btn danger-icon-btn"
|
||||||
icon="pi pi-times-circle" (click)="onRowEditCancel(ri)"></button>
|
icon="pi pi-times-circle" (click)="onRowEditCancel(ri)"></button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -203,7 +203,7 @@ export class AutoRolesRulesComponent extends ComponentWithTable implements OnIni
|
|||||||
this.clonedUsers[index] = { ...autoRoleRule };
|
this.clonedUsers[index] = { ...autoRoleRule };
|
||||||
}
|
}
|
||||||
|
|
||||||
public onRowEditSave(table: Table, newAutoRoleRule: AutoRoleRule, index: number): void {
|
public override onRowEditSave(newAutoRoleRule: AutoRoleRule, index: number): void {
|
||||||
if (this.isEditingNew && JSON.stringify(newAutoRoleRule) === JSON.stringify(this.newAutoRoleTemplate)) {
|
if (this.isEditingNew && JSON.stringify(newAutoRoleRule) === JSON.stringify(this.newAutoRoleTemplate)) {
|
||||||
this.isEditingNew = false;
|
this.isEditingNew = false;
|
||||||
this.rules.splice(index, 1);
|
this.rules.splice(index, 1);
|
||||||
|
@ -27,6 +27,8 @@
|
|||||||
<button pButton label="{{'common.reset_filters' | translate}}" icon="pi pi-undo"
|
<button pButton label="{{'common.reset_filters' | translate}}" icon="pi pi-undo"
|
||||||
class="icon-btn btn" (click)="resetFilters()">
|
class="icon-btn btn" (click)="resetFilters()">
|
||||||
</button>
|
</button>
|
||||||
|
<app-data-import-and-export name="achievements" [(data)]="auto_roles"
|
||||||
|
[callback]="callback"></app-data-import-and-export>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
@ -209,7 +211,7 @@
|
|||||||
(click)="deleteAutoRole(autoRole)"></button>
|
(click)="deleteAutoRole(autoRole)"></button>
|
||||||
|
|
||||||
<button *ngIf="editing" pButton pSaveEditableRow class="btn icon-btn"
|
<button *ngIf="editing" pButton pSaveEditableRow class="btn icon-btn"
|
||||||
icon="pi pi-check-circle" (click)="onRowEditSave(dt, autoRole, ri)"></button>
|
icon="pi pi-check-circle" (click)="onRowEditSave(autoRole, ri)"></button>
|
||||||
<button *ngIf="editing" pButton pCancelEditableRow class="btn icon-btn danger-icon-btn"
|
<button *ngIf="editing" pButton pCancelEditableRow class="btn icon-btn danger-icon-btn"
|
||||||
icon="pi pi-times-circle" (click)="onRowEditCancel(ri)"></button>
|
icon="pi pi-times-circle" (click)="onRowEditCancel(ri)"></button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -192,7 +192,7 @@ export class AutoRolesComponent extends ComponentWithTable implements OnInit, On
|
|||||||
this.clonedUsers[index] = { ...autoRole };
|
this.clonedUsers[index] = { ...autoRole };
|
||||||
}
|
}
|
||||||
|
|
||||||
public onRowEditSave(table: Table, newAutoRole: AutoRole, index: number): void {
|
public override onRowEditSave(newAutoRole: AutoRole, index: number): void {
|
||||||
if (this.isEditingNew && JSON.stringify(newAutoRole) === JSON.stringify(this.newAutoRoleTemplate)) {
|
if (this.isEditingNew && JSON.stringify(newAutoRole) === JSON.stringify(this.newAutoRoleTemplate)) {
|
||||||
this.isEditingNew = false;
|
this.isEditingNew = false;
|
||||||
this.auto_roles.splice(index, 1);
|
this.auto_roles.splice(index, 1);
|
||||||
|
@ -1,226 +1,238 @@
|
|||||||
<h1>
|
<h1>
|
||||||
{{'view.server.levels.header' | translate}}
|
{{'view.server.levels.header' | translate}}
|
||||||
</h1>
|
</h1>
|
||||||
<div class="content-wrapper">
|
<div class="content-wrapper">
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<p-table #dt [value]="levels" [responsive]="true" responsiveLayout="stack" [breakpoint]="'720px'" dataKey="id" editMode="row" [rowHover]="true" [rows]="10"
|
<p-table #dt [value]="levels" [responsive]="true" responsiveLayout="stack" [breakpoint]="'720px'" dataKey="id"
|
||||||
[rowsPerPageOptions]="[10,25,50]" [paginator]="true" [loading]="loading" [totalRecords]="totalRecords"
|
editMode="row" [rowHover]="true" [rows]="10"
|
||||||
[lazy]="true" (onLazyLoad)="nextPage($event)">
|
[rowsPerPageOptions]="[10,25,50]" [paginator]="true" [loading]="loading" [totalRecords]="totalRecords"
|
||||||
|
[lazy]="true" (onLazyLoad)="nextPage($event)">
|
||||||
|
|
||||||
<ng-template pTemplate="caption">
|
<ng-template pTemplate="caption">
|
||||||
<div class="table-caption">
|
<div class="table-caption">
|
||||||
<div class="table-caption-table-info">
|
<div class="table-caption-table-info">
|
||||||
<div class="table-caption-text">
|
<div class="table-caption-text">
|
||||||
<ng-container *ngIf="!loading">{{levels.length}} {{'common.of' | translate}}
|
<ng-container *ngIf="!loading">{{levels.length}} {{'common.of' | translate}}
|
||||||
{{dt.totalRecords}}
|
{{dt.totalRecords}}
|
||||||
</ng-container>
|
</ng-container>
|
||||||
{{'view.server.levels.levels' | translate}}
|
{{'view.server.levels.levels' | 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"
|
||||||
</div>
|
[(hiddenColumns)]="hiddenColumns"></app-multi-select-columns>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="table-caption-btn-wrapper btn-wrapper">
|
<div class="table-caption-btn-wrapper btn-wrapper">
|
||||||
<button pButton label="{{'common.add' | translate}}" class="icon-btn btn"
|
<button pButton label="{{'common.add' | translate}}" class="icon-btn btn"
|
||||||
icon="pi pi-plus" (click)="addLevel(dt)" [disabled]="isEditingNew || user?.isModerator && !user?.isAdmin">
|
icon="pi pi-plus" (click)="addLevel(dt)"
|
||||||
</button>
|
[disabled]="isEditingNew || user?.isModerator && !user?.isAdmin">
|
||||||
<button pButton label="{{'common.reset_filters' | translate}}" icon="pi pi-undo"
|
</button>
|
||||||
class="icon-btn btn" (click)="resetFilters()">
|
<button pButton label="{{'common.reset_filters' | translate}}" icon="pi pi-undo"
|
||||||
</button>
|
class="icon-btn btn" (click)="resetFilters()">
|
||||||
</div>
|
</button>
|
||||||
</div>
|
<app-data-import-and-export name="levels" [(data)]="levels"
|
||||||
</ng-template>
|
[callback]="callback"></app-data-import-and-export>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ng-template>
|
||||||
|
|
||||||
<ng-template pTemplate="header">
|
<ng-template pTemplate="header">
|
||||||
<tr>
|
<tr>
|
||||||
<th hideable-th="id" [parent]="this" [sortable]="true">
|
<th hideable-th="id" [parent]="this" [sortable]="true">
|
||||||
<div class="table-header-label">
|
<div class="table-header-label">
|
||||||
<div class="table-header-text">{{'common.id' | translate}}</div>
|
<div class="table-header-text">{{'common.id' | translate}}</div>
|
||||||
<p-sortIcon field="id" class="table-header-icon"></p-sortIcon>
|
<p-sortIcon field="id" class="table-header-icon"></p-sortIcon>
|
||||||
</div>
|
</div>
|
||||||
</th>
|
</th>
|
||||||
|
|
||||||
<th hideable-th="name" [parent]="this" [sortable]="true">
|
<th hideable-th="name" [parent]="this" [sortable]="true">
|
||||||
<div class="table-header-label">
|
<div class="table-header-label">
|
||||||
<div class="table-header-text">{{'common.name' | translate}}</div>
|
<div class="table-header-text">{{'common.name' | translate}}</div>
|
||||||
<p-sortIcon field="name" class="table-header-icon"></p-sortIcon>
|
<p-sortIcon field="name" class="table-header-icon"></p-sortIcon>
|
||||||
</div>
|
</div>
|
||||||
</th>
|
</th>
|
||||||
|
|
||||||
<th hideable-th="color" [parent]="this" [sortable]="true">
|
<th hideable-th="color" [parent]="this" [sortable]="true">
|
||||||
<div class="table-header-label">
|
<div class="table-header-label">
|
||||||
<div class="table-header-text">{{'common.color' | translate}}</div>
|
<div class="table-header-text">{{'common.color' | translate}}</div>
|
||||||
<p-sortIcon field="color" class="table-header-icon"></p-sortIcon>
|
<p-sortIcon field="color" class="table-header-icon"></p-sortIcon>
|
||||||
</div>
|
</div>
|
||||||
</th>
|
</th>
|
||||||
|
|
||||||
<th hideable-th="min_xp" [parent]="this" [sortable]="true">
|
<th hideable-th="min_xp" [parent]="this" [sortable]="true">
|
||||||
<div class="table-header-label">
|
<div class="table-header-label">
|
||||||
<div class="table-header-text">{{'common.min_xp' | translate}}</div>
|
<div class="table-header-text">{{'common.min_xp' | translate}}</div>
|
||||||
<p-sortIcon field="minXp" class="table-header-icon"></p-sortIcon>
|
<p-sortIcon field="minXp" class="table-header-icon"></p-sortIcon>
|
||||||
</div>
|
</div>
|
||||||
</th>
|
</th>
|
||||||
|
|
||||||
<th hideable-th="permissions" [parent]="this" [sortable]="true">
|
<th hideable-th="permissions" [parent]="this" [sortable]="true">
|
||||||
<div class="table-header-label">
|
<div class="table-header-label">
|
||||||
<div class="table-header-text">{{'common.permissions' | translate}}</div>
|
<div class="table-header-text">{{'common.permissions' | translate}}</div>
|
||||||
<p-sortIcon field="permissions" class="table-header-icon"></p-sortIcon>
|
<p-sortIcon field="permissions" class="table-header-icon"></p-sortIcon>
|
||||||
</div>
|
</div>
|
||||||
</th>
|
</th>
|
||||||
|
|
||||||
<th>
|
<th>
|
||||||
<div class="table-header-label">
|
<div class="table-header-label">
|
||||||
<div class="table-header-text">{{'common.created_at' | translate}}</div>
|
<div class="table-header-text">{{'common.created_at' | translate}}</div>
|
||||||
</div>
|
</div>
|
||||||
</th>
|
</th>
|
||||||
|
|
||||||
<th>
|
<th>
|
||||||
<div class="table-header-label">
|
<div class="table-header-label">
|
||||||
<div class="table-header-text">{{'common.modified_at' | translate}}</div>
|
<div class="table-header-text">{{'common.modified_at' | translate}}</div>
|
||||||
</div>
|
</div>
|
||||||
</th>
|
</th>
|
||||||
|
|
||||||
<th>
|
<th>
|
||||||
<div class="table-header-label">
|
<div class="table-header-label">
|
||||||
<div class="table-header-text">{{'common.actions' | translate}}</div>
|
<div class="table-header-text">{{'common.actions' | translate}}</div>
|
||||||
</div>
|
</div>
|
||||||
</th>
|
</th>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<th hideable-th="id" [parent]="this" class="table-header-small">
|
<th hideable-th="id" [parent]="this" class="table-header-small">
|
||||||
<form [formGroup]="filterForm">
|
<form [formGroup]="filterForm">
|
||||||
<input type="text" pInputText formControlName="id"
|
<input type="text" pInputText formControlName="id"
|
||||||
placeholder="{{'common.id' | translate}}">
|
placeholder="{{'common.id' | translate}}">
|
||||||
</form>
|
</form>
|
||||||
</th>
|
</th>
|
||||||
<th hideable-th="name" [parent]="this">
|
<th hideable-th="name" [parent]="this">
|
||||||
<form [formGroup]="filterForm">
|
<form [formGroup]="filterForm">
|
||||||
<input type="text" pInputText formControlName="name"
|
<input type="text" pInputText formControlName="name"
|
||||||
placeholder="{{'common.name' | translate}}">
|
placeholder="{{'common.name' | translate}}">
|
||||||
</form>
|
</form>
|
||||||
</th>
|
</th>
|
||||||
<th hideable-th="color" [parent]="this"></th>
|
<th hideable-th="color" [parent]="this"></th>
|
||||||
<th hideable-th="min_xp" [parent]="this"></th>
|
<th hideable-th="min_xp" [parent]="this"></th>
|
||||||
<th hideable-th="permissions" [parent]="this"></th>
|
<th hideable-th="permissions" [parent]="this"></th>
|
||||||
<th class="table-header-small-dropdown"></th>
|
<th class="table-header-small-dropdown"></th>
|
||||||
<th class="table-header-small-dropdown"></th>
|
<th class="table-header-small-dropdown"></th>
|
||||||
<th class="table-header-actions"></th>
|
<th class="table-header-actions"></th>
|
||||||
</tr>
|
</tr>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
|
||||||
<ng-template pTemplate="body" let-level let-editing="editing" let-ri="rowIndex">
|
<ng-template pTemplate="body" let-level let-editing="editing" let-ri="rowIndex">
|
||||||
<tr [pEditableRow]="level">
|
<tr [pEditableRow]="level">
|
||||||
<td hideable-th="id" [parent]="this">
|
<td hideable-th="id" [parent]="this">
|
||||||
<span class="p-column-title">{{'common.id' | translate}}:</span>
|
<span class="p-column-title">{{'common.id' | translate}}:</span>
|
||||||
<p-cellEditor>
|
<p-cellEditor>
|
||||||
<ng-template pTemplate="input">
|
<ng-template pTemplate="input">
|
||||||
{{level.id}}
|
{{level.id}}
|
||||||
</ng-template>
|
</ng-template>
|
||||||
<ng-template pTemplate="output">
|
<ng-template pTemplate="output">
|
||||||
{{level.id}}
|
{{level.id}}
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</p-cellEditor>
|
</p-cellEditor>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td hideable-th="name" [parent]="this">
|
<td hideable-th="name" [parent]="this">
|
||||||
<span class="p-column-title">{{'common.name' | translate}}:</span>
|
<span class="p-column-title">{{'common.name' | translate}}:</span>
|
||||||
<p-cellEditor>
|
<p-cellEditor>
|
||||||
<ng-template pTemplate="input">
|
<ng-template pTemplate="input">
|
||||||
<input class="table-edit-input" pInputText type="text" [(ngModel)]="level.name">
|
<input class="table-edit-input" pInputText type="text" [(ngModel)]="level.name">
|
||||||
</ng-template>
|
</ng-template>
|
||||||
<ng-template pTemplate="output">
|
<ng-template pTemplate="output">
|
||||||
{{level.name}}
|
{{level.name}}
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</p-cellEditor>
|
</p-cellEditor>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td hideable-th="color" [parent]="this">
|
<td hideable-th="color" [parent]="this">
|
||||||
<span class="p-column-title">{{'common.color' | translate}}:</span>
|
<span class="p-column-title">{{'common.color' | translate}}:</span>
|
||||||
<p-cellEditor>
|
<p-cellEditor>
|
||||||
<ng-template pTemplate="input">
|
<ng-template pTemplate="input">
|
||||||
<input class="table-edit-input" pInputText type="text" [(ngModel)]="level.color">
|
<input class="table-edit-input" pInputText type="text" [(ngModel)]="level.color">
|
||||||
</ng-template>
|
</ng-template>
|
||||||
<ng-template pTemplate="output">
|
<ng-template pTemplate="output">
|
||||||
{{level.color}}
|
{{level.color}}
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</p-cellEditor>
|
</p-cellEditor>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td hideable-th="min_xp" [parent]="this">
|
<td hideable-th="min_xp" [parent]="this">
|
||||||
<span class="p-column-title">{{'common.min_xp' | translate}}:</span>
|
<span class="p-column-title">{{'common.min_xp' | translate}}:</span>
|
||||||
<p-cellEditor>
|
<p-cellEditor>
|
||||||
<ng-template pTemplate="input">
|
<ng-template pTemplate="input">
|
||||||
<input class="table-edit-input" pInputText min="0" type="number" [(ngModel)]="level.minXp">
|
<input class="table-edit-input" pInputText min="0" type="number"
|
||||||
</ng-template>
|
[(ngModel)]="level.minXp">
|
||||||
<ng-template pTemplate="output">
|
</ng-template>
|
||||||
{{level.minXp}}
|
<ng-template pTemplate="output">
|
||||||
</ng-template>
|
{{level.minXp}}
|
||||||
</p-cellEditor>
|
</ng-template>
|
||||||
</td>
|
</p-cellEditor>
|
||||||
|
</td>
|
||||||
|
|
||||||
<td hideable-th="permissions" [parent]="this">
|
<td hideable-th="permissions" [parent]="this">
|
||||||
<span class="p-column-title">{{'common.permissions' | translate}}:</span>
|
<span class="p-column-title">{{'common.permissions' | translate}}:</span>
|
||||||
<p-cellEditor>
|
<p-cellEditor>
|
||||||
<ng-template pTemplate="input">
|
<ng-template pTemplate="input">
|
||||||
<input class="table-edit-input" pInputText min="0" type="text" [(ngModel)]="level.permissions">
|
<input class="table-edit-input" pInputText min="0" type="text"
|
||||||
</ng-template>
|
[(ngModel)]="level.permissions">
|
||||||
<ng-template pTemplate="output">
|
</ng-template>
|
||||||
{{level.permissions}}
|
<ng-template pTemplate="output">
|
||||||
</ng-template>
|
{{level.permissions}}
|
||||||
</p-cellEditor>
|
</ng-template>
|
||||||
</td>
|
</p-cellEditor>
|
||||||
|
</td>
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<span class="p-column-title">{{'common.created_at' | translate}}:</span>
|
<span class="p-column-title">{{'common.created_at' | translate}}:</span>
|
||||||
<p-cellEditor>
|
<p-cellEditor>
|
||||||
<ng-template pTemplate="input">
|
<ng-template pTemplate="input">
|
||||||
{{level.createdAt | date:'dd.MM.yy HH:mm'}}
|
{{level.createdAt | date:'dd.MM.yy HH:mm'}}
|
||||||
</ng-template>
|
</ng-template>
|
||||||
<ng-template pTemplate="output">
|
<ng-template pTemplate="output">
|
||||||
{{level.createdAt | date:'dd.MM.yy HH:mm'}}
|
{{level.createdAt | date:'dd.MM.yy HH:mm'}}
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</p-cellEditor>
|
</p-cellEditor>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<span class="p-column-title">{{'common.modified_at' | translate}}:</span>
|
<span class="p-column-title">{{'common.modified_at' | translate}}:</span>
|
||||||
<p-cellEditor>
|
<p-cellEditor>
|
||||||
<ng-template pTemplate="input">
|
<ng-template pTemplate="input">
|
||||||
{{level.modifiedAt | date:'dd.MM.yy HH:mm'}}
|
{{level.modifiedAt | date:'dd.MM.yy HH:mm'}}
|
||||||
</ng-template>
|
</ng-template>
|
||||||
<ng-template pTemplate="output">
|
<ng-template pTemplate="output">
|
||||||
{{level.modifiedAt | date:'dd.MM.yy HH:mm'}}
|
{{level.modifiedAt | date:'dd.MM.yy HH:mm'}}
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</p-cellEditor>
|
</p-cellEditor>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div class="btn-wrapper">
|
<div class="btn-wrapper">
|
||||||
<app-history-btn *ngIf="!isEditingNew" [id]="level.id" [query]="query" translationKey="view.server.levels.header"></app-history-btn>
|
<app-history-btn *ngIf="!isEditingNew" [id]="level.id" [query]="query"
|
||||||
<button *ngIf="!editing" pButton pInitEditableRow class="btn icon-btn" icon="pi pi-pencil"
|
translationKey="view.server.levels.header"></app-history-btn>
|
||||||
(click)="onRowEditInit(dt, level, ri)" [disabled]="!user || user.isModerator && !user.isAdmin"></button>
|
<button *ngIf="!editing" pButton pInitEditableRow class="btn icon-btn" icon="pi pi-pencil"
|
||||||
<button *ngIf="!editing" pButton class="btn icon-btn danger-icon-btn" icon="pi pi-trash"
|
(click)="onRowEditInit(dt, level, ri)"
|
||||||
(click)="deleteLevel(level)" [disabled]="!user || user.isModerator && !user.isAdmin"></button>
|
[disabled]="!user || user.isModerator && !user.isAdmin"></button>
|
||||||
|
<button *ngIf="!editing" pButton class="btn icon-btn danger-icon-btn" icon="pi pi-trash"
|
||||||
|
(click)="deleteLevel(level)"
|
||||||
|
[disabled]="!user || user.isModerator && !user.isAdmin"></button>
|
||||||
|
|
||||||
<button *ngIf="editing" pButton pSaveEditableRow class="btn icon-btn"
|
<button *ngIf="editing" pButton pSaveEditableRow class="btn icon-btn"
|
||||||
icon="pi pi-check-circle" (click)="onRowEditSave(dt, level, ri)" [disabled]="!user || user.isModerator && !user.isAdmin"></button>
|
icon="pi pi-check-circle" (click)="onRowEditSave(level, ri)"
|
||||||
<button *ngIf="editing" pButton pCancelEditableRow class="btn icon-btn danger-icon-btn"
|
[disabled]="!user || user.isModerator && !user.isAdmin"></button>
|
||||||
icon="pi pi-times-circle" (click)="onRowEditCancel(ri)" [disabled]="!user || user.isModerator && !user.isAdmin"></button>
|
<button *ngIf="editing" pButton pCancelEditableRow class="btn icon-btn danger-icon-btn"
|
||||||
</div>
|
icon="pi pi-times-circle" (click)="onRowEditCancel(ri)"
|
||||||
</td>
|
[disabled]="!user || user.isModerator && !user.isAdmin"></button>
|
||||||
</tr>
|
</div>
|
||||||
</ng-template>
|
</td>
|
||||||
|
</tr>
|
||||||
|
</ng-template>
|
||||||
|
|
||||||
<ng-template pTemplate="emptymessage">
|
<ng-template pTemplate="emptymessage">
|
||||||
<tr></tr>
|
<tr></tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="10">{{'common.no_entries_found' | translate}}</td>
|
<td colspan="10">{{'common.no_entries_found' | translate}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr></tr>
|
<tr></tr>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
|
||||||
<ng-template pTemplate="paginatorleft">
|
<ng-template pTemplate="paginatorleft">
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</p-table>
|
</p-table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -25,249 +25,241 @@ import { UserDTO } from "../../../../../../models/auth/auth-user.dto";
|
|||||||
import { ComponentWithTable } from "../../../../../../base/component-with-table";
|
import { ComponentWithTable } from "../../../../../../base/component-with-table";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: "app-levels",
|
selector: "app-levels",
|
||||||
templateUrl: "./levels.component.html",
|
templateUrl: "./levels.component.html",
|
||||||
styleUrls: ["./levels.component.scss"]
|
styleUrls: ["./levels.component.scss"]
|
||||||
})
|
})
|
||||||
export class LevelsComponent extends ComponentWithTable implements OnInit, OnDestroy {
|
export class LevelsComponent extends ComponentWithTable implements OnInit, OnDestroy {
|
||||||
public levels: Level[] = [];
|
public levels: Level[] = [];
|
||||||
public loading = true;
|
public loading = true;
|
||||||
|
|
||||||
public isEditingNew: boolean = false;
|
public isEditingNew: boolean = false;
|
||||||
|
|
||||||
public filterForm!: FormGroup<{
|
public filterForm!: FormGroup<{
|
||||||
id: FormControl<number | null>,
|
id: FormControl<number | null>,
|
||||||
name: FormControl<string | null>,
|
name: FormControl<string | null>,
|
||||||
color: FormControl<string | null>,
|
color: FormControl<string | null>,
|
||||||
min_xp: FormControl<number | null>,
|
min_xp: FormControl<number | null>,
|
||||||
permissions: FormControl<string | null>,
|
permissions: FormControl<string | null>,
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
public filter: LevelFilter = {};
|
public filter: LevelFilter = {};
|
||||||
public page: Page = {
|
public page: Page = {
|
||||||
pageSize: undefined,
|
pageSize: undefined,
|
||||||
pageIndex: undefined
|
pageIndex: undefined
|
||||||
};
|
};
|
||||||
public sort: Sort = {
|
public sort: Sort = {
|
||||||
sortColumn: undefined,
|
sortColumn: undefined,
|
||||||
sortDirection: undefined
|
sortDirection: undefined
|
||||||
};
|
};
|
||||||
|
|
||||||
public totalRecords: number = 0;
|
public totalRecords: number = 0;
|
||||||
|
|
||||||
public clonedLevels: { [s: string]: Level; } = {};
|
public clonedLevels: { [s: string]: Level; } = {};
|
||||||
|
|
||||||
private unsubscriber = new Subject<void>();
|
private unsubscriber = new Subject<void>();
|
||||||
private server: Server = {};
|
private server: Server = {};
|
||||||
public user: UserDTO | null = null;
|
public user: UserDTO | null = null;
|
||||||
|
|
||||||
query: string = Queries.levelWithHistoryQuery;
|
query: string = Queries.levelWithHistoryQuery;
|
||||||
|
|
||||||
public constructor(
|
public constructor(
|
||||||
private authService: AuthService,
|
private authService: AuthService,
|
||||||
private spinner: SpinnerService,
|
private spinner: SpinnerService,
|
||||||
private toastService: ToastService,
|
private toastService: ToastService,
|
||||||
private confirmDialog: ConfirmationDialogService,
|
private confirmDialog: ConfirmationDialogService,
|
||||||
private fb: FormBuilder,
|
private fb: FormBuilder,
|
||||||
private translate: TranslateService,
|
private translate: TranslateService,
|
||||||
private data: DataService,
|
private data: DataService,
|
||||||
private sidebar: SidebarService,
|
private sidebar: SidebarService,
|
||||||
private route: ActivatedRoute
|
private route: ActivatedRoute
|
||||||
) {
|
) {
|
||||||
super("level", ["id", "name", "color", "min_xp", "permissions"]);
|
super("level", ["id", "name", "color", "min_xp", "permissions"]);
|
||||||
}
|
|
||||||
|
|
||||||
public ngOnInit(): void {
|
|
||||||
this.setFilterForm();
|
|
||||||
this.data.getServerFromRoute(this.route).then(async server => {
|
|
||||||
this.server = server;
|
|
||||||
this.loadNextPage();
|
|
||||||
let authUser = await this.authService.getLoggedInUser();
|
|
||||||
this.user = authUser?.users?.find(u => u.server == this.server.id) ?? null;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public ngOnDestroy(): void {
|
|
||||||
this.unsubscriber.next();
|
|
||||||
this.unsubscriber.complete();
|
|
||||||
}
|
|
||||||
|
|
||||||
public loadNextPage(): void {
|
|
||||||
this.loading = true;
|
|
||||||
this.data.query<LevelListQuery>(Queries.levelQuery, {
|
|
||||||
serverId: this.server.id, filter: this.filter, page: this.page, sort: this.sort
|
|
||||||
},
|
|
||||||
(data: Query) => {
|
|
||||||
return data.servers[0];
|
|
||||||
}
|
|
||||||
).subscribe(data => {
|
|
||||||
this.totalRecords = data.levelCount;
|
|
||||||
this.levels = data.levels;
|
|
||||||
this.spinner.hideSpinner();
|
|
||||||
this.loading = false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public setFilterForm(): void {
|
|
||||||
this.filterForm = this.fb.group({
|
|
||||||
id: new FormControl<number | null>(null),
|
|
||||||
name: new FormControl<string | null>(null),
|
|
||||||
color: new FormControl<string | null>(null),
|
|
||||||
min_xp: new FormControl<number | null>(null),
|
|
||||||
permissions: new FormControl<string | null>(null)
|
|
||||||
});
|
|
||||||
|
|
||||||
this.filterForm.valueChanges.pipe(
|
|
||||||
takeUntil(this.unsubscriber),
|
|
||||||
debounceTime(600)
|
|
||||||
).subscribe(changes => {
|
|
||||||
if (changes.id) {
|
|
||||||
this.filter.id = changes.id;
|
|
||||||
} else {
|
|
||||||
this.filter.id = undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (changes.name) {
|
|
||||||
this.filter.name = changes.name;
|
|
||||||
} else {
|
|
||||||
this.filter.name = undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.page.pageSize)
|
|
||||||
this.page.pageSize = 10;
|
|
||||||
|
|
||||||
if (this.page.pageIndex)
|
|
||||||
this.page.pageIndex = 0;
|
|
||||||
|
|
||||||
this.loadNextPage();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public newLevelTemplate: Level = {
|
|
||||||
createdAt: "",
|
|
||||||
modifiedAt: ""
|
|
||||||
};
|
|
||||||
|
|
||||||
public nextPage(event: LazyLoadEvent): void {
|
|
||||||
this.page.pageSize = event.rows ?? 0;
|
|
||||||
if (event.first != null && event.rows != null)
|
|
||||||
this.page.pageIndex = event.first / event.rows;
|
|
||||||
this.sort.sortColumn = event.sortField ?? undefined;
|
|
||||||
this.sort.sortDirection = event.sortOrder === 1 ? SortDirection.ASC : event.sortOrder === -1 ? SortDirection.DESC : SortDirection.ASC;
|
|
||||||
|
|
||||||
this.loadNextPage();
|
|
||||||
}
|
|
||||||
|
|
||||||
public resetFilters(): void {
|
|
||||||
this.filterForm.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
public onRowEditInit(table: Table, user: User, index: number): void {
|
|
||||||
this.clonedLevels[index] = { ...user };
|
|
||||||
}
|
|
||||||
|
|
||||||
public onRowEditSave(table: Table, newLevel: Level, index: number): void {
|
|
||||||
// const oldUser = this.clonedUsers[index];
|
|
||||||
// delete this.clonedUsers[index];
|
|
||||||
|
|
||||||
// if (JSON.stringify(oldUser) === JSON.stringify(newUser) && !this.isEditingNew) {
|
|
||||||
// console.log(1, oldUser, newUser, JSON.stringify(oldUser) === JSON.stringify(newUser), !this.isEditingNew);
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
if (this.isEditingNew && JSON.stringify(newLevel) === JSON.stringify(this.newLevelTemplate)) {
|
|
||||||
this.isEditingNew = false;
|
|
||||||
this.levels.splice(index, 1);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!newLevel.id && !this.isEditingNew || !newLevel.minXp && !newLevel?.name && !newLevel?.permissions) {
|
public ngOnInit(): void {
|
||||||
return;
|
this.setFilterForm();
|
||||||
}
|
this.data.getServerFromRoute(this.route).then(async server => {
|
||||||
|
this.server = server;
|
||||||
if (this.isEditingNew) {
|
this.loadNextPage();
|
||||||
this.spinner.showSpinner();
|
let authUser = await this.authService.getLoggedInUser();
|
||||||
this.data.mutation<LevelMutationResult>(Mutations.createLevel, {
|
this.user = authUser?.users?.find(u => u.server == this.server.id) ?? null;
|
||||||
name: newLevel.name,
|
|
||||||
color: newLevel.color,
|
|
||||||
minXp: newLevel.minXp,
|
|
||||||
permissions: newLevel.permissions,
|
|
||||||
serverId: this.server.id
|
|
||||||
}
|
|
||||||
).pipe(catchError(err => {
|
|
||||||
this.isEditingNew = false;
|
|
||||||
this.spinner.hideSpinner();
|
|
||||||
return throwError(err);
|
|
||||||
})).subscribe(result => {
|
|
||||||
this.isEditingNew = false;
|
|
||||||
this.spinner.hideSpinner();
|
|
||||||
this.toastService.success(this.translate.instant("view.server.levels.message.level_create"), this.translate.instant("view.server.levels.message.level_create_d", { name: result.level.createLevel?.name }));
|
|
||||||
this.loadNextPage();
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.spinner.showSpinner();
|
|
||||||
this.data.mutation<UpdateUserMutationResult>(Mutations.updateLevel, {
|
|
||||||
id: newLevel.id,
|
|
||||||
name: newLevel.name,
|
|
||||||
color: newLevel.color,
|
|
||||||
minXp: newLevel.minXp,
|
|
||||||
permissions: newLevel.permissions
|
|
||||||
}
|
|
||||||
).pipe(catchError(err => {
|
|
||||||
this.spinner.hideSpinner();
|
|
||||||
return throwError(err);
|
|
||||||
})).subscribe(_ => {
|
|
||||||
this.spinner.hideSpinner();
|
|
||||||
this.toastService.success(this.translate.instant("view.server.levels.message.level_update"), this.translate.instant("view.server.levels.message.level_update_d", { name: newLevel.name }));
|
|
||||||
this.loadNextPage();
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public onRowEditCancel(index: number): void {
|
|
||||||
if (this.isEditingNew) {
|
|
||||||
this.levels.splice(index, 1);
|
|
||||||
delete this.clonedLevels[index];
|
|
||||||
this.isEditingNew = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.levels[index] = this.clonedLevels[index];
|
|
||||||
delete this.clonedLevels[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
public deleteLevel(level: Level): void {
|
|
||||||
this.confirmDialog.confirmDialog(
|
|
||||||
this.translate.instant("view.server.levels.message.level_delete"), this.translate.instant("view.server.levels.message.level_delete_q", { name: level.name }),
|
|
||||||
() => {
|
|
||||||
this.spinner.showSpinner();
|
|
||||||
this.data.mutation<LevelMutationResult>(Mutations.deleteLevel, {
|
|
||||||
id: level.id
|
|
||||||
}
|
|
||||||
).pipe(catchError(err => {
|
|
||||||
this.spinner.hideSpinner();
|
|
||||||
return throwError(err);
|
|
||||||
})).subscribe(l => {
|
|
||||||
this.spinner.hideSpinner();
|
|
||||||
this.toastService.success(this.translate.instant("view.server.levels.message.level_deleted"), this.translate.instant("view.server.levels.message.level_deleted_d", { name: level.name }));
|
|
||||||
this.loadNextPage();
|
|
||||||
});
|
});
|
||||||
});
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public addLevel(table: Table): void {
|
public ngOnDestroy(): void {
|
||||||
const newLevel = JSON.parse(JSON.stringify(this.newLevelTemplate));
|
this.unsubscriber.next();
|
||||||
|
this.unsubscriber.complete();
|
||||||
|
}
|
||||||
|
|
||||||
this.levels = [newLevel, ...this.levels];
|
public loadNextPage(): void {
|
||||||
|
this.loading = true;
|
||||||
|
this.data.query<LevelListQuery>(Queries.levelQuery, {
|
||||||
|
serverId: this.server.id, filter: this.filter, page: this.page, sort: this.sort
|
||||||
|
},
|
||||||
|
(data: Query) => {
|
||||||
|
return data.servers[0];
|
||||||
|
}
|
||||||
|
).subscribe(data => {
|
||||||
|
this.totalRecords = data.levelCount;
|
||||||
|
this.levels = data.levels;
|
||||||
|
this.spinner.hideSpinner();
|
||||||
|
this.loading = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
table.initRowEdit(newLevel);
|
public setFilterForm(): void {
|
||||||
|
this.filterForm = this.fb.group({
|
||||||
|
id: new FormControl<number | null>(null),
|
||||||
|
name: new FormControl<string | null>(null),
|
||||||
|
color: new FormControl<string | null>(null),
|
||||||
|
min_xp: new FormControl<number | null>(null),
|
||||||
|
permissions: new FormControl<string | null>(null)
|
||||||
|
});
|
||||||
|
|
||||||
const index = this.levels.findIndex(l => l.id == newLevel.id);
|
this.filterForm.valueChanges.pipe(
|
||||||
this.onRowEditInit(table, newLevel, index);
|
takeUntil(this.unsubscriber),
|
||||||
|
debounceTime(600)
|
||||||
|
).subscribe(changes => {
|
||||||
|
if (changes.id) {
|
||||||
|
this.filter.id = changes.id;
|
||||||
|
} else {
|
||||||
|
this.filter.id = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
this.isEditingNew = true;
|
if (changes.name) {
|
||||||
}
|
this.filter.name = changes.name;
|
||||||
|
} else {
|
||||||
|
this.filter.name = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.page.pageSize)
|
||||||
|
this.page.pageSize = 10;
|
||||||
|
|
||||||
|
if (this.page.pageIndex)
|
||||||
|
this.page.pageIndex = 0;
|
||||||
|
|
||||||
|
this.loadNextPage();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public newLevelTemplate: Level = {
|
||||||
|
createdAt: "",
|
||||||
|
modifiedAt: ""
|
||||||
|
};
|
||||||
|
|
||||||
|
public nextPage(event: LazyLoadEvent): void {
|
||||||
|
this.page.pageSize = event.rows ?? 0;
|
||||||
|
if (event.first != null && event.rows != null)
|
||||||
|
this.page.pageIndex = event.first / event.rows;
|
||||||
|
this.sort.sortColumn = event.sortField ?? undefined;
|
||||||
|
this.sort.sortDirection = event.sortOrder === 1 ? SortDirection.ASC : event.sortOrder === -1 ? SortDirection.DESC : SortDirection.ASC;
|
||||||
|
|
||||||
|
this.loadNextPage();
|
||||||
|
}
|
||||||
|
|
||||||
|
public resetFilters(): void {
|
||||||
|
this.filterForm.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
public onRowEditInit(table: Table, user: User, index: number): void {
|
||||||
|
this.clonedLevels[index] = { ...user };
|
||||||
|
}
|
||||||
|
|
||||||
|
public override onRowEditSave(newLevel: Level, index: number): void {
|
||||||
|
if (this.isEditingNew && JSON.stringify(newLevel) === JSON.stringify(this.newLevelTemplate)) {
|
||||||
|
this.isEditingNew = false;
|
||||||
|
this.levels.splice(index, 1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!newLevel.id && !this.isEditingNew || !newLevel.minXp && !newLevel?.name && !newLevel?.permissions) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.isEditingNew) {
|
||||||
|
this.spinner.showSpinner();
|
||||||
|
this.data.mutation<LevelMutationResult>(Mutations.createLevel, {
|
||||||
|
name: newLevel.name,
|
||||||
|
color: newLevel.color,
|
||||||
|
minXp: newLevel.minXp,
|
||||||
|
permissions: newLevel.permissions,
|
||||||
|
serverId: this.server.id
|
||||||
|
}
|
||||||
|
).pipe(catchError(err => {
|
||||||
|
this.isEditingNew = false;
|
||||||
|
this.spinner.hideSpinner();
|
||||||
|
return throwError(err);
|
||||||
|
})).subscribe(result => {
|
||||||
|
this.isEditingNew = false;
|
||||||
|
this.spinner.hideSpinner();
|
||||||
|
this.toastService.success(this.translate.instant("view.server.levels.message.level_create"), this.translate.instant("view.server.levels.message.level_create_d", { name: result.level.createLevel?.name }));
|
||||||
|
this.loadNextPage();
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.spinner.showSpinner();
|
||||||
|
this.data.mutation<UpdateUserMutationResult>(Mutations.updateLevel, {
|
||||||
|
id: newLevel.id,
|
||||||
|
name: newLevel.name,
|
||||||
|
color: newLevel.color,
|
||||||
|
minXp: newLevel.minXp,
|
||||||
|
permissions: newLevel.permissions
|
||||||
|
}
|
||||||
|
).pipe(catchError(err => {
|
||||||
|
this.spinner.hideSpinner();
|
||||||
|
return throwError(err);
|
||||||
|
})).subscribe(_ => {
|
||||||
|
this.spinner.hideSpinner();
|
||||||
|
this.toastService.success(this.translate.instant("view.server.levels.message.level_update"), this.translate.instant("view.server.levels.message.level_update_d", { name: newLevel.name }));
|
||||||
|
this.loadNextPage();
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public onRowEditCancel(index: number): void {
|
||||||
|
if (this.isEditingNew) {
|
||||||
|
this.levels.splice(index, 1);
|
||||||
|
delete this.clonedLevels[index];
|
||||||
|
this.isEditingNew = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.levels[index] = this.clonedLevels[index];
|
||||||
|
delete this.clonedLevels[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
public deleteLevel(level: Level): void {
|
||||||
|
this.confirmDialog.confirmDialog(
|
||||||
|
this.translate.instant("view.server.levels.message.level_delete"), this.translate.instant("view.server.levels.message.level_delete_q", { name: level.name }),
|
||||||
|
() => {
|
||||||
|
this.spinner.showSpinner();
|
||||||
|
this.data.mutation<LevelMutationResult>(Mutations.deleteLevel, {
|
||||||
|
id: level.id
|
||||||
|
}
|
||||||
|
).pipe(catchError(err => {
|
||||||
|
this.spinner.hideSpinner();
|
||||||
|
return throwError(err);
|
||||||
|
})).subscribe(l => {
|
||||||
|
this.spinner.hideSpinner();
|
||||||
|
this.toastService.success(this.translate.instant("view.server.levels.message.level_deleted"), this.translate.instant("view.server.levels.message.level_deleted_d", { name: level.name }));
|
||||||
|
this.loadNextPage();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public addLevel(table: Table): void {
|
||||||
|
const newLevel = JSON.parse(JSON.stringify(this.newLevelTemplate));
|
||||||
|
|
||||||
|
this.levels = [newLevel, ...this.levels];
|
||||||
|
|
||||||
|
table.initRowEdit(newLevel);
|
||||||
|
|
||||||
|
const index = this.levels.findIndex(l => l.id == newLevel.id);
|
||||||
|
this.onRowEditInit(table, newLevel, index);
|
||||||
|
|
||||||
|
this.isEditingNew = true;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -242,7 +242,7 @@
|
|||||||
[routerLink]="member.id"></button>
|
[routerLink]="member.id"></button>
|
||||||
|
|
||||||
<button *ngIf="editing" pButton pSaveEditableRow class="btn icon-btn"
|
<button *ngIf="editing" pButton pSaveEditableRow class="btn icon-btn"
|
||||||
icon="pi pi-check-circle" (click)="onRowEditSave(dt, member, ri)"></button>
|
icon="pi pi-check-circle" (click)="onRowEditSave(member, ri)"></button>
|
||||||
<button *ngIf="editing" pButton pCancelEditableRow class="btn icon-btn danger-icon-btn"
|
<button *ngIf="editing" pButton pCancelEditableRow class="btn icon-btn danger-icon-btn"
|
||||||
icon="pi pi-times-circle" (click)="onRowEditCancel(ri)"></button>
|
icon="pi pi-times-circle" (click)="onRowEditCancel(ri)"></button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -213,15 +213,7 @@ export class MembersComponent extends ComponentWithTable implements OnInit, OnDe
|
|||||||
this.clonedUsers[index] = { ...user };
|
this.clonedUsers[index] = { ...user };
|
||||||
}
|
}
|
||||||
|
|
||||||
onRowEditSave(table: Table, newUser: User, index: number) {
|
public override onRowEditSave(newUser: User, index: number) {
|
||||||
// const oldUser = this.clonedUsers[index];
|
|
||||||
// delete this.clonedUsers[index];
|
|
||||||
|
|
||||||
// if (JSON.stringify(oldUser) === JSON.stringify(newUser) && !this.isEditingNew) {
|
|
||||||
// console.log(1, oldUser, newUser, JSON.stringify(oldUser) === JSON.stringify(newUser), !this.isEditingNew);
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
if (this.isEditingNew && JSON.stringify(newUser) === JSON.stringify(this.newUserTemplate)) {
|
if (this.isEditingNew && JSON.stringify(newUser) === JSON.stringify(this.newUserTemplate)) {
|
||||||
this.isEditingNew = false;
|
this.isEditingNew = false;
|
||||||
this.members.splice(index, 1);
|
this.members.splice(index, 1);
|
||||||
|
@ -27,6 +27,8 @@
|
|||||||
<button pButton label="{{'common.reset_filters' | translate}}" icon="pi pi-undo"
|
<button pButton label="{{'common.reset_filters' | translate}}" icon="pi pi-undo"
|
||||||
class="icon-btn btn" (click)="resetFilters()">
|
class="icon-btn btn" (click)="resetFilters()">
|
||||||
</button>
|
</button>
|
||||||
|
<app-data-import-and-export name="achievements" [(data)]="shortRoleNames"
|
||||||
|
[callback]="callback"></app-data-import-and-export>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
@ -192,7 +194,7 @@
|
|||||||
(click)="deleteShortRoleName(shortRoleName)"></button>
|
(click)="deleteShortRoleName(shortRoleName)"></button>
|
||||||
|
|
||||||
<button *ngIf="editing" pButton pSaveEditableRow class="btn icon-btn"
|
<button *ngIf="editing" pButton pSaveEditableRow class="btn icon-btn"
|
||||||
icon="pi pi-check-circle" (click)="onRowEditSave(dt, shortRoleName, ri)"></button>
|
icon="pi pi-check-circle" (click)="onRowEditSave(shortRoleName, ri)"></button>
|
||||||
<button *ngIf="editing" pButton pCancelEditableRow class="btn icon-btn danger-icon-btn"
|
<button *ngIf="editing" pButton pCancelEditableRow class="btn icon-btn danger-icon-btn"
|
||||||
icon="pi pi-times-circle" (click)="onRowEditCancel(ri)"></button>
|
icon="pi pi-times-circle" (click)="onRowEditCancel(ri)"></button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -199,7 +199,7 @@ export class ShortRoleNamesComponent extends ComponentWithTable implements OnIni
|
|||||||
this.clonedShortRoleNames[index] = { ...user };
|
this.clonedShortRoleNames[index] = { ...user };
|
||||||
}
|
}
|
||||||
|
|
||||||
public onRowEditSave(table: Table, newShortRoleName: ShortRoleName, index: number): void {
|
public override onRowEditSave(newShortRoleName: ShortRoleName, index: number): void {
|
||||||
if (this.isEditingNew && JSON.stringify(newShortRoleName) === JSON.stringify(this.newShortRoleNameTemplate)) {
|
if (this.isEditingNew && JSON.stringify(newShortRoleName) === JSON.stringify(this.newShortRoleNameTemplate)) {
|
||||||
this.isEditingNew = false;
|
this.isEditingNew = false;
|
||||||
this.shortRoleNames.splice(index, 1);
|
this.shortRoleNames.splice(index, 1);
|
||||||
|
@ -144,6 +144,9 @@
|
|||||||
"emoji": "Emoji",
|
"emoji": "Emoji",
|
||||||
"error": "Fehler",
|
"error": "Fehler",
|
||||||
"feature_flags": "Funktionen",
|
"feature_flags": "Funktionen",
|
||||||
|
"file": {
|
||||||
|
"uploaded": "Daten wurden erfolgreich importiert."
|
||||||
|
},
|
||||||
"first_name": "Vorname",
|
"first_name": "Vorname",
|
||||||
"hidden_columns": "Ausgeblendete Spalten",
|
"hidden_columns": "Ausgeblendete Spalten",
|
||||||
"history": {
|
"history": {
|
||||||
|
@ -144,6 +144,9 @@
|
|||||||
"emoji": "Emoji",
|
"emoji": "Emoji",
|
||||||
"error": "Error",
|
"error": "Error",
|
||||||
"feature_flags": "Features",
|
"feature_flags": "Features",
|
||||||
|
"file": {
|
||||||
|
"uploaded": "Data was imported successfully."
|
||||||
|
},
|
||||||
"first_name": "First name",
|
"first_name": "First name",
|
||||||
"hidden_columns": "Hidden columns",
|
"hidden_columns": "Hidden columns",
|
||||||
"history": {
|
"history": {
|
||||||
|
@ -2,6 +2,6 @@
|
|||||||
"WebVersion": {
|
"WebVersion": {
|
||||||
"Major": "1",
|
"Major": "1",
|
||||||
"Minor": "2",
|
"Minor": "2",
|
||||||
"Micro": "0"
|
"Micro": "dev407"
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user