feat: extended player profile

This commit is contained in:
Dawid Wysokiński 2023-01-22 11:43:50 +01:00
parent 89f71f319d
commit 0026822768
Signed by: Kichiyaki
GPG Key ID: B5445E357FB8B892
4 changed files with 80 additions and 89 deletions

View File

@ -5,6 +5,8 @@ const translations: Record<string, Record<string, string>> = {
Loading: 'Wczytywanie', Loading: 'Wczytywanie',
'Previous page': 'Poprzednia strona', 'Previous page': 'Poprzednia strona',
'Next page': 'Następna strona', 'Next page': 'Następna strona',
'Something went wrong while loading the data':
'Coś poszło nie tak podczas wczytywania danych',
}, },
}; };
@ -18,6 +20,9 @@ export type DialogTableColumn<T> = {
}; };
export class DialogTable<T> { export class DialogTable<T> {
prevPageId: string;
selectId: string;
nextPageId: string;
constructor( constructor(
private readonly id: string, private readonly id: string,
private readonly columns: DialogTableColumn<T>[], private readonly columns: DialogTableColumn<T>[],
@ -26,7 +31,11 @@ export class DialogTable<T> {
page: number, page: number,
limit: number limit: number
) => Promise<ListResult<T>> ) => Promise<ListResult<T>>
) {} ) {
this.prevPageId = `${this.id}_page_prev`;
this.selectId = `${this.id}_page_select`;
this.nextPageId = `${this.id}_page_next`;
}
public async render() { public async render() {
await this.renderPage(1); await this.renderPage(1);
@ -35,9 +44,28 @@ export class DialogTable<T> {
private async renderPage(page: number) { private async renderPage(page: number) {
window.Dialog.show(`${this.id}_loading`, `<p>${t('Loading')}...</p>`); window.Dialog.show(`${this.id}_loading`, `<p>${t('Loading')}...</p>`);
const { data, total } = await this.loadData(page, this.limit); try {
const { data, total } = await this.loadData(page, this.limit);
window.Dialog.show(
this.id,
`
${this.buildPagination(page, total)}
${this.buildTable(data)}
`
);
this.addEventListeners(page);
} catch (err) {
console.error(err);
window.Dialog.close();
window.UI.ErrorMessage(t('Something went wrong while loading the data'));
}
}
private buildPagination(page: number, total: number): string {
const maxPage = Math.ceil(total / this.limit); const maxPage = Math.ceil(total / this.limit);
const pageOpts = []; const pageOpts = [];
for (let i = 1; i <= (page > maxPage ? page : maxPage); i++) { for (let i = 1; i <= (page > maxPage ? page : maxPage); i++) {
pageOpts.push( pageOpts.push(
@ -47,26 +75,25 @@ export class DialogTable<T> {
); );
} }
const prevPageId = `${this.id}_page_prev`; return `
const selectId = `${this.id}_page_select`;
const nextPageId = `${this.id}_page_next`;
window.Dialog.show(
this.id,
`
<div style="display: flex; flex-direction: row; align-items: center; justify-content: center; margin-bottom: 10px"> <div style="display: flex; flex-direction: row; align-items: center; justify-content: center; margin-bottom: 10px">
<button title="${t( <button title="${t(
'Previous page' 'Previous page'
)}" style="margin-right: 5px" class="btn" id="${prevPageId}"${ )}" style="margin-right: 5px" class="btn" id="${this.prevPageId}"${
page <= 1 ? ' disabled' : '' page <= 1 ? ' disabled' : ''
}>&lt;</button> }>&lt;</button>
<select style="margin-right: 5px" id="${selectId}"> <select style="margin-right: 5px" id="${this.selectId}">
${pageOpts.join('')} ${pageOpts.join('')}
</select> </select>
<button title="${t('Next page')}" class="btn" id="${nextPageId}"${ <button title="${t('Next page')}" class="btn" id="${
page >= maxPage ? ' disabled' : '' this.nextPageId
}>&gt;</button> }"${page >= maxPage ? ' disabled' : ''}>&gt;</button>
</div> </div>
`;
}
private buildTable(data: T[]) {
return `
<table style="width: 100%" class="vis"> <table style="width: 100%" class="vis">
<tbody> <tbody>
<tr> <tr>
@ -84,18 +111,19 @@ export class DialogTable<T> {
) )
.join('')} .join('')}
</tbody> </tbody>
</table> </table>
` `;
); }
private addEventListeners(page: number) {
document document
.querySelector('#' + prevPageId) .querySelector('#' + this.prevPageId)
?.addEventListener('click', (e: Event) => { ?.addEventListener('click', () => {
this.renderPage(page - 1); this.renderPage(page - 1);
}); });
document document
.querySelector('#' + selectId) .querySelector('#' + this.selectId)
?.addEventListener('change', (e: Event) => { ?.addEventListener('change', (e: Event) => {
if (!(e.currentTarget instanceof HTMLSelectElement)) { if (!(e.currentTarget instanceof HTMLSelectElement)) {
return; return;
@ -105,8 +133,8 @@ export class DialogTable<T> {
}); });
document document
.querySelector('#' + nextPageId) .querySelector('#' + this.nextPageId)
?.addEventListener('click', (e: Event) => { ?.addEventListener('click', () => {
this.renderPage(page + 1); this.renderPage(page + 1);
}); });
} }

View File

@ -2,7 +2,6 @@
import { Player, TWHelpClient } from './lib/twhelp'; import { Player, TWHelpClient } from './lib/twhelp';
import { DialogTable } from './common/DialogTable'; import { DialogTable } from './common/DialogTable';
import { buildURL } from './lib/twstats';
const SCREEN = 'info_player'; const SCREEN = 'info_player';
const MODE = null; const MODE = null;
@ -14,7 +13,6 @@ const translations: Record<string, Record<string, string>> = {
'Best rank': 'Najlepszy ranking', 'Best rank': 'Najlepszy ranking',
'Most points': 'Najwięcej punktów', 'Most points': 'Najwięcej punktów',
'Most villages': 'Najwięcej wiosek', 'Most villages': 'Najwięcej wiosek',
'Show other servers': 'Pokaż inne światy',
'Show tribe changes': 'Pokaż zmiany plemion', 'Show tribe changes': 'Pokaż zmiany plemion',
'Show history': 'Pokaż historię', 'Show history': 'Pokaż historię',
'Show ennoblements': 'Pokaż przejęcia', 'Show ennoblements': 'Pokaż przejęcia',
@ -83,7 +81,6 @@ class TWHelpConnector {
} }
enum DialogId { enum DialogId {
OTHER_SERVERS = 'kichiyaki_other_servers',
TRIBE_CHANGES = 'kichiyaki_tribe_changes', TRIBE_CHANGES = 'kichiyaki_tribe_changes',
ENNOBLEMENTS = 'kichiyaki_ennoblements', ENNOBLEMENTS = 'kichiyaki_ennoblements',
HISTORY = 'kichiyaki_history', HISTORY = 'kichiyaki_history',
@ -148,10 +145,6 @@ class UI {
} }
[ [
{
name: t('Show other servers'),
handler: this.showOtherServers.bind(this),
},
{ {
name: t('Show tribe changes'), name: t('Show tribe changes'),
handler: this.showTribeChanges.bind(this), handler: this.showTribeChanges.bind(this),
@ -176,39 +169,6 @@ class UI {
}); });
} }
private async showOtherServers(e: Event) {
e.preventDefault();
await new DialogTable(
DialogId.OTHER_SERVERS,
[
{
header: t('Server'),
accessor: (s) =>
`<a href="${buildURL({
entity: 'player',
server: s.key,
id: this.player.id,
})}">${s.key}</a>`,
},
{
header: t('Deleted'),
accessor: (s) =>
s.deletedAt
? `${t('Yes')} (${new Date(s.deletedAt).toLocaleString()})`
: t('No'),
},
],
this.player.otherServers.length,
() => {
return Promise.resolve({
data: this.player.otherServers,
total: this.player.otherServers.length,
});
}
).render();
}
private async showTribeChanges(e: Event) { private async showTribeChanges(e: Event) {
e.preventDefault(); e.preventDefault();
@ -314,25 +274,29 @@ class UI {
}, },
{ {
header: t('Old owner'), header: t('Old owner'),
accessor: (e) => accessor: ({ village: { player } }) => {
e.oldOwner if (!player) {
? `<a href="${e.oldOwner.profileUrl}">${e.oldOwner.name}</a>${ return t('Barbarian');
e.oldOwner.tribe }
? ` (<a href="${e.oldOwner.tribe.profileUrl}">${e.oldOwner.tribe.tag}</a>)` return `<a href="${player.profileUrl}">${player.name}</a>${
: '' player.tribe
}` ? ` (<a href="${player.tribe.profileUrl}">${player.tribe.tag}</a>)`
: t('Barbarian'), : ''
}`;
},
}, },
{ {
header: t('New owner'), header: t('New owner'),
accessor: (e) => accessor: ({ newOwner }) => {
e.newOwner if (!newOwner) {
? `<a href="${e.newOwner.profileUrl}">${e.newOwner.name}</a>${ return t('Unknown');
e.newOwner.tribe }
? ` (<a href="${e.newOwner.tribe.profileUrl}">${e.newOwner.tribe.tag}</a>)` return `<a href="${newOwner.profileUrl}">${newOwner.name}</a>${
: '' newOwner.tribe
}` ? ` (<a href="${newOwner.tribe.profileUrl}">${newOwner.tribe.tag}</a>)`
: t('Unknown'), : ''
}`;
},
}, },
{ {
header: t('Date/time'), header: t('Date/time'),
@ -379,5 +343,9 @@ class ExtendedPlayerProfile {
await new ExtendedPlayerProfile( await new ExtendedPlayerProfile(
new TWHelpClient(process.env.TWHELP_API_BASE_URL ?? '') new TWHelpClient(process.env.TWHELP_API_BASE_URL ?? '')
).render(); )
.render()
.catch((err) => {
console.log(err);
});
})(); })();

1
src/global.d.ts vendored
View File

@ -30,6 +30,7 @@ declare global {
}; };
Dialog: { Dialog: {
show: (id: string, html: string) => void; show: (id: string, html: string) => void;
close: () => void;
}; };
} }
} }

View File

@ -10,11 +10,6 @@ export type Version = {
timezone: string; timezone: string;
}; };
export type PlayerServer = {
key: string;
deletedAt: string | null;
};
export type Player = { export type Player = {
id: number; id: number;
bestRank: number; bestRank: number;
@ -25,7 +20,6 @@ export type Player = {
mostVillagesAt: string; mostVillagesAt: string;
lastActivityAt: string; lastActivityAt: string;
createdAt: string; createdAt: string;
otherServers: PlayerServer[];
}; };
export type TribeMeta = { export type TribeMeta = {
@ -49,6 +43,7 @@ export type VillageMeta = {
x: number; x: number;
y: number; y: number;
continent: string; continent: string;
player: PlayerMeta | null;
}; };
export type TribeChange = { export type TribeChange = {
@ -62,7 +57,6 @@ export type Ennoblement = {
id: number; id: number;
points: number; points: number;
newOwner: PlayerMeta | null; newOwner: PlayerMeta | null;
oldOwner: PlayerMeta | null;
village: VillageMeta; village: VillageMeta;
createdAt: string; createdAt: string;
}; };