Added level icons

This commit is contained in:
Sven Heidemann 2024-01-25 17:11:48 +01:00
parent a917803eff
commit f209e45905
8 changed files with 252 additions and 245 deletions

View File

@ -2,6 +2,10 @@ from datetime import datetime
from typing import Optional from typing import Optional
from cpl_core.database import TableABC from cpl_core.database import TableABC
from cpl_core.dependency_injection import ServiceProviderABC
from cpl_discord.service import DiscordBotServiceABC
from cpl_query.extension import List
from discord import Role
from bot_data.model.server import Server from bot_data.model.server import Server
@ -33,6 +37,13 @@ class Level(TableABC):
def id(self) -> int: def id(self) -> int:
return self._id return self._id
@property
@ServiceProviderABC.inject
def icon_url(self, bot: DiscordBotServiceABC) -> str:
guild = bot.get_guild(self.server.discord_id)
role = List(Role, guild.roles).where(lambda x: x.name == self._name).first_or_default()
return None if role is None else role.icon
@property @property
def name(self) -> str: def name(self) -> str:
return self._name return self._name

View File

@ -1,5 +1,6 @@
type Level implements TableWithHistoryQuery { type Level implements TableWithHistoryQuery {
id: ID id: ID
iconURL: String
name: String name: String
color: String color: String
minXp: Int minXp: Int

View File

@ -1,6 +1,5 @@
from cpl_core.database.context import DatabaseContextABC from cpl_core.database.context import DatabaseContextABC
from bot_data.model.level import Level
from bot_data.model.level_history import LevelHistory from bot_data.model.level_history import LevelHistory
from bot_graphql.abc.data_query_with_history_abc import DataQueryWithHistoryABC from bot_graphql.abc.data_query_with_history_abc import DataQueryWithHistoryABC
@ -9,33 +8,13 @@ class LevelQuery(DataQueryWithHistoryABC):
def __init__(self, db: DatabaseContextABC): def __init__(self, db: DatabaseContextABC):
DataQueryWithHistoryABC.__init__(self, "Level", "LevelsHistory", LevelHistory, db) DataQueryWithHistoryABC.__init__(self, "Level", "LevelsHistory", LevelHistory, db)
self.set_field("id", self.resolve_id) self.set_field("id", lambda x, *_: x.id)
self.set_field("name", self.resolve_name) self.set_field(
self.set_field("color", self.resolve_color) "iconURL",
self.set_field("minXp", self.resolve_min_xp) lambda x, *_: "https://cdn.discordapp.com/emojis/1170348708894875659.webp?size=32&quality=lossless",
self.set_field("permissions", self.resolve_permissions) )
self.set_field("server", self.resolve_server) self.set_field("name", lambda x, *_: x.name)
self.set_field("color", lambda x, *_: x.color)
@staticmethod self.set_field("minXp", lambda x, *_: x.min_xp)
def resolve_id(level: Level, *_): self.set_field("permissions", lambda x, *_: x.permissions)
return level.id self.set_field("server", lambda x, *_: x.server)
@staticmethod
def resolve_name(level: Level, *_):
return level.name
@staticmethod
def resolve_color(level: Level, *_):
return level.color
@staticmethod
def resolve_min_xp(level: Level, *_):
return level.min_xp
@staticmethod
def resolve_permissions(level: Level, *_):
return level.permissions
@staticmethod
def resolve_server(level: Level, *_):
return level.server

View File

@ -155,6 +155,7 @@ export class Queries {
levelCount levelCount
levels(filter: $filter, page: $page, sort: $sort) { levels(filter: $filter, page: $page, sort: $sort) {
id id
iconURL
name name
color color
minXp minXp

View File

@ -1,238 +1,251 @@
<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" <p-table #dt [value]="levels" [responsive]="true" responsiveLayout="stack" [breakpoint]="'720px'" dataKey="id"
editMode="row" [rowHover]="true" [rows]="10" editMode="row" [rowHover]="true" [rows]="10"
[rowsPerPageOptions]="[10,25,50]" [paginator]="true" [loading]="loading" [totalRecords]="totalRecords" [rowsPerPageOptions]="[10,25,50]" [paginator]="true" [loading]="loading" [totalRecords]="totalRecords"
[lazy]="true" (onLazyLoad)="nextPage($event)"> [lazy]="true" (onLazyLoad)="nextPage($event)">
<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" <app-multi-select-columns [table]="name" [columns]="columns"
[(hiddenColumns)]="hiddenColumns"></app-multi-select-columns> [(hiddenColumns)]="hiddenColumns"></app-multi-select-columns>
</div> </div>
<div class="table-caption-btn-wrapper btn-wrapper"> <div class="table-caption-btn-wrapper btn-wrapper">
<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)" icon="pi pi-plus" (click)="addLevel(dt)"
[disabled]="isEditingNew || user?.isModerator && !user?.isAdmin"> [disabled]="isEditingNew || user?.isModerator && !user?.isAdmin">
</button> </button>
<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="levels" [(data)]="levels" <app-data-import-and-export name="levels" [(data)]="levels"
[callback]="callback" [validator]="validator"></app-data-import-and-export> [callback]="callback" [validator]="validator"></app-data-import-and-export>
</div> </div>
</div> </div>
</ng-template> </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="icon" [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.icon' | translate}}</div>
<p-sortIcon field="name" class="table-header-icon"></p-sortIcon> <p-sortIcon field="id" class="table-header-icon"></p-sortIcon>
</div> </div>
</th> </th>
<th hideable-th="color" [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.color' | translate}}</div> <div class="table-header-text">{{'common.name' | translate}}</div>
<p-sortIcon field="color" class="table-header-icon"></p-sortIcon> <p-sortIcon field="name" class="table-header-icon"></p-sortIcon>
</div> </div>
</th> </th>
<th hideable-th="min_xp" [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.min_xp' | translate}}</div> <div class="table-header-text">{{'common.color' | translate}}</div>
<p-sortIcon field="minXp" class="table-header-icon"></p-sortIcon> <p-sortIcon field="color" class="table-header-icon"></p-sortIcon>
</div> </div>
</th> </th>
<th hideable-th="permissions" [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.permissions' | translate}}</div> <div class="table-header-text">{{'common.min_xp' | translate}}</div>
<p-sortIcon field="permissions" class="table-header-icon"></p-sortIcon> <p-sortIcon field="minXp" class="table-header-icon"></p-sortIcon>
</div> </div>
</th> </th>
<th> <th hideable-th="permissions" [parent]="this" [sortable]="true">
<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.permissions' | translate}}</div>
</div> <p-sortIcon field="permissions" class="table-header-icon"></p-sortIcon>
</th> </div>
</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.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.actions' | translate}}</div> <div class="table-header-text">{{'common.modified_at' | translate}}</div>
</div> </div>
</th> </th>
</tr>
<tr> <th>
<th hideable-th="id" [parent]="this" class="table-header-small"> <div class="table-header-label">
<form [formGroup]="filterForm"> <div class="table-header-text">{{'common.actions' | translate}}</div>
<input type="text" pInputText formControlName="id" </div>
placeholder="{{'common.id' | translate}}"> </th>
</form> </tr>
</th>
<th hideable-th="name" [parent]="this">
<form [formGroup]="filterForm">
<input type="text" pInputText formControlName="name"
placeholder="{{'common.name' | translate}}">
</form>
</th>
<th hideable-th="color" [parent]="this"></th>
<th hideable-th="min_xp" [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-actions"></th>
</tr>
</ng-template>
<ng-template pTemplate="body" let-level let-editing="editing" let-ri="rowIndex"> <tr>
<tr [pEditableRow]="level"> <th hideable-th="id" [parent]="this" class="table-header-small">
<td hideable-th="id" [parent]="this"> <form [formGroup]="filterForm">
<span class="p-column-title">{{'common.id' | translate}}:</span> <input type="text" pInputText formControlName="id"
<p-cellEditor> placeholder="{{'common.id' | translate}}">
<ng-template pTemplate="input"> </form>
{{level.id}} </th>
</ng-template> <th hideable-th="icon" [parent]="this" class="table-header-small">
<ng-template pTemplate="output"> </th>
{{level.id}} <th hideable-th="name" [parent]="this">
</ng-template> <form [formGroup]="filterForm">
</p-cellEditor> <input type="text" pInputText formControlName="name"
</td> placeholder="{{'common.name' | translate}}">
</form>
</th>
<th hideable-th="color" [parent]="this"></th>
<th hideable-th="min_xp" [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-actions"></th>
</tr>
</ng-template>
<td hideable-th="name" [parent]="this"> <ng-template pTemplate="body" let-level let-editing="editing" let-ri="rowIndex">
<span class="p-column-title">{{'common.name' | translate}}:</span> <tr [pEditableRow]="level">
<p-cellEditor> <td hideable-th="id" [parent]="this">
<ng-template pTemplate="input"> <span class="p-column-title">{{'common.id' | translate}}:</span>
<input class="table-edit-input" pInputText type="text" [(ngModel)]="level.name"> <p-cellEditor>
</ng-template> <ng-template pTemplate="input">
<ng-template pTemplate="output"> {{level.id}}
{{level.name}} </ng-template>
</ng-template> <ng-template pTemplate="output">
</p-cellEditor> {{level.id}}
</td> </ng-template>
</p-cellEditor>
</td>
<td hideable-th="color" [parent]="this"> <td hideable-th="icon" [parent]="this">
<span class="p-column-title">{{'common.color' | translate}}:</span> <img width="32px" height="32px" *ngIf="level ? level.iconURL : ''" [src]="level ? level.iconURL : ''">
<p-cellEditor> </td>
<ng-template pTemplate="input">
<input class="table-edit-input" pInputText type="text" [(ngModel)]="level.color">
</ng-template>
<ng-template pTemplate="output">
{{level.color}}
</ng-template>
</p-cellEditor>
</td>
<td hideable-th="min_xp" [parent]="this"> <td hideable-th="name" [parent]="this">
<span class="p-column-title">{{'common.min_xp' | 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 min="0" type="number" <input class="table-edit-input" pInputText type="text" [(ngModel)]="level.name">
[(ngModel)]="level.minXp"> </ng-template>
</ng-template> <ng-template pTemplate="output">
<ng-template pTemplate="output"> {{level.name}}
{{level.minXp}} </ng-template>
</ng-template> </p-cellEditor>
</p-cellEditor> </td>
</td>
<td hideable-th="permissions" [parent]="this"> <td hideable-th="color" [parent]="this">
<span class="p-column-title">{{'common.permissions' | 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 min="0" type="text" <input class="table-edit-input" pInputText type="text" [(ngModel)]="level.color">
[(ngModel)]="level.permissions"> </ng-template>
</ng-template> <ng-template pTemplate="output">
<ng-template pTemplate="output"> {{level.color}}
{{level.permissions}} </ng-template>
</ng-template> </p-cellEditor>
</p-cellEditor> </td>
</td>
<td> <td hideable-th="min_xp" [parent]="this">
<span class="p-column-title">{{'common.created_at' | translate}}:</span> <span class="p-column-title">{{'common.min_xp' | translate}}:</span>
<p-cellEditor> <p-cellEditor>
<ng-template pTemplate="input"> <ng-template pTemplate="input">
{{level.createdAt | date:'dd.MM.yy HH:mm'}} <input class="table-edit-input" pInputText min="0" type="number"
</ng-template> [(ngModel)]="level.minXp">
<ng-template pTemplate="output"> </ng-template>
{{level.createdAt | date:'dd.MM.yy HH:mm'}} <ng-template pTemplate="output">
</ng-template> {{level.minXp}}
</p-cellEditor> </ng-template>
</td> </p-cellEditor>
<td> </td>
<span class="p-column-title">{{'common.modified_at' | translate}}:</span>
<p-cellEditor>
<ng-template pTemplate="input">
{{level.modifiedAt | date:'dd.MM.yy HH:mm'}}
</ng-template>
<ng-template pTemplate="output">
{{level.modifiedAt | date:'dd.MM.yy HH:mm'}}
</ng-template>
</p-cellEditor>
</td>
<td>
<div class="btn-wrapper">
<app-history-btn *ngIf="!isEditingNew" [id]="level.id" [query]="query"
translationKey="view.server.levels.header"></app-history-btn>
<button *ngIf="!editing" pButton pInitEditableRow class="btn icon-btn" icon="pi pi-pencil"
(click)="onRowEditInit(dt, level, ri)"
[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" <td hideable-th="permissions" [parent]="this">
icon="pi pi-check-circle" (click)="onRowEditSave(level, ri)" <span class="p-column-title">{{'common.permissions' | translate}}:</span>
[disabled]="!user || user.isModerator && !user.isAdmin"></button> <p-cellEditor>
<button *ngIf="editing" pButton pCancelEditableRow class="btn icon-btn danger-icon-btn" <ng-template pTemplate="input">
icon="pi pi-times-circle" (click)="onRowEditCancel(ri)" <input class="table-edit-input" pInputText min="0" type="text"
[disabled]="!user || user.isModerator && !user.isAdmin"></button> [(ngModel)]="level.permissions">
</div> </ng-template>
</td> <ng-template pTemplate="output">
</tr> {{level.permissions}}
</ng-template> </ng-template>
</p-cellEditor>
</td>
<ng-template pTemplate="emptymessage"> <td>
<tr></tr> <span class="p-column-title">{{'common.created_at' | translate}}:</span>
<tr> <p-cellEditor>
<td colspan="10">{{'common.no_entries_found' | translate}}</td> <ng-template pTemplate="input">
</tr> {{level.createdAt | date:'dd.MM.yy HH:mm'}}
<tr></tr> </ng-template>
</ng-template> <ng-template pTemplate="output">
{{level.createdAt | date:'dd.MM.yy HH:mm'}}
</ng-template>
</p-cellEditor>
</td>
<td>
<span class="p-column-title">{{'common.modified_at' | translate}}:</span>
<p-cellEditor>
<ng-template pTemplate="input">
{{level.modifiedAt | date:'dd.MM.yy HH:mm'}}
</ng-template>
<ng-template pTemplate="output">
{{level.modifiedAt | date:'dd.MM.yy HH:mm'}}
</ng-template>
</p-cellEditor>
</td>
<td>
<div class="btn-wrapper">
<app-history-btn *ngIf="!isEditingNew" [id]="level.id" [query]="query"
translationKey="view.server.levels.header"></app-history-btn>
<button *ngIf="!editing" pButton pInitEditableRow class="btn icon-btn" icon="pi pi-pencil"
(click)="onRowEditInit(dt, level, ri)"
[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>
<ng-template pTemplate="paginatorleft"> <button *ngIf="editing" pButton pSaveEditableRow class="btn icon-btn"
</ng-template> icon="pi pi-check-circle" (click)="onRowEditSave(level, ri)"
</p-table> [disabled]="!user || user.isModerator && !user.isAdmin"></button>
</div> <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>
</div>
</td>
</tr>
</ng-template>
<ng-template pTemplate="emptymessage">
<tr></tr>
<tr>
<td colspan="10">{{'common.no_entries_found' | translate}}</td>
</tr>
<tr></tr>
</ng-template>
<ng-template pTemplate="paginatorleft">
</ng-template>
</p-table>
</div>
</div> </div>

View File

@ -19,7 +19,7 @@ import { Table } from "primeng/table";
import { User } from "../../../../../../models/data/user.model"; import { User } from "../../../../../../models/data/user.model";
import { LevelMutationResult, UpdateUserMutationResult } from "../../../../../../models/graphql/result.model"; import { LevelMutationResult, UpdateUserMutationResult } from "../../../../../../models/graphql/result.model";
import { Mutations } from "../../../../../../models/graphql/mutations.model"; import { Mutations } from "../../../../../../models/graphql/mutations.model";
import { forkJoin, Subject, throwError } from "rxjs"; import { Subject, throwError } from "rxjs";
import { Server } from "../../../../../../models/data/server.model"; import { Server } from "../../../../../../models/data/server.model";
import { UserDTO } from "../../../../../../models/auth/auth-user.dto"; import { UserDTO } from "../../../../../../models/auth/auth-user.dto";
import { ComponentWithTable } from "../../../../../../base/component-with-table"; import { ComponentWithTable } from "../../../../../../base/component-with-table";
@ -72,7 +72,7 @@ export class LevelsComponent extends ComponentWithTable implements OnInit, OnDes
private sidebar: SidebarService, private sidebar: SidebarService,
private route: ActivatedRoute private route: ActivatedRoute
) { ) {
super("level", ["id", "name", "color", "min_xp", "permissions"], (oldElement: Level, newElement: Level) => { super("level", ["id", "icon", "name", "color", "min_xp", "permissions"], (oldElement: Level, newElement: Level) => {
return oldElement.name === newElement.name; return oldElement.name === newElement.name;
}); });
} }

View File

@ -180,6 +180,7 @@
"value": "Wert", "value": "Wert",
"xp": "XP" "xp": "XP"
}, },
"icon": "Icon",
"id": "Id", "id": "Id",
"import": "Importieren", "import": "Importieren",
"interval": "Interval", "interval": "Interval",

View File

@ -180,6 +180,7 @@
"value": "Value", "value": "Value",
"xp": "XP" "xp": "XP"
}, },
"icon": "Icon",
"id": "Id", "id": "Id",
"import": "Import", "import": "Import",
"interval": "interval", "interval": "interval",