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',
'Previous page': 'Poprzednia 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> {
prevPageId: string;
selectId: string;
nextPageId: string;
constructor(
private readonly id: string,
private readonly columns: DialogTableColumn<T>[],
@ -26,7 +31,11 @@ export class DialogTable<T> {
page: number,
limit: number
) => Promise<ListResult<T>>
) {}
) {
this.prevPageId = `${this.id}_page_prev`;
this.selectId = `${this.id}_page_select`;
this.nextPageId = `${this.id}_page_next`;
}
public async render() {
await this.renderPage(1);
@ -35,9 +44,28 @@ export class DialogTable<T> {
private async renderPage(page: number) {
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 pageOpts = [];
for (let i = 1; i <= (page > maxPage ? page : maxPage); i++) {
pageOpts.push(
@ -47,26 +75,25 @@ export class DialogTable<T> {
);
}
const prevPageId = `${this.id}_page_prev`;
const selectId = `${this.id}_page_select`;
const nextPageId = `${this.id}_page_next`;
window.Dialog.show(
this.id,
`
return `
<div style="display: flex; flex-direction: row; align-items: center; justify-content: center; margin-bottom: 10px">
<button title="${t(
'Previous page'
)}" style="margin-right: 5px" class="btn" id="${prevPageId}"${
page <= 1 ? ' disabled' : ''
}>&lt;</button>
<select style="margin-right: 5px" id="${selectId}">
)}" style="margin-right: 5px" class="btn" id="${this.prevPageId}"${
page <= 1 ? ' disabled' : ''
}>&lt;</button>
<select style="margin-right: 5px" id="${this.selectId}">
${pageOpts.join('')}
</select>
<button title="${t('Next page')}" class="btn" id="${nextPageId}"${
page >= maxPage ? ' disabled' : ''
}>&gt;</button>
</div>
<button title="${t('Next page')}" class="btn" id="${
this.nextPageId
}"${page >= maxPage ? ' disabled' : ''}>&gt;</button>
</div>
`;
}
private buildTable(data: T[]) {
return `
<table style="width: 100%" class="vis">
<tbody>
<tr>
@ -84,18 +111,19 @@ export class DialogTable<T> {
)
.join('')}
</tbody>
</table>
`
);
</table>
`;
}
private addEventListeners(page: number) {
document
.querySelector('#' + prevPageId)
?.addEventListener('click', (e: Event) => {
.querySelector('#' + this.prevPageId)
?.addEventListener('click', () => {
this.renderPage(page - 1);
});
document
.querySelector('#' + selectId)
.querySelector('#' + this.selectId)
?.addEventListener('change', (e: Event) => {
if (!(e.currentTarget instanceof HTMLSelectElement)) {
return;
@ -105,8 +133,8 @@ export class DialogTable<T> {
});
document
.querySelector('#' + nextPageId)
?.addEventListener('click', (e: Event) => {
.querySelector('#' + this.nextPageId)
?.addEventListener('click', () => {
this.renderPage(page + 1);
});
}

View File

@ -2,7 +2,6 @@
import { Player, TWHelpClient } from './lib/twhelp';
import { DialogTable } from './common/DialogTable';
import { buildURL } from './lib/twstats';
const SCREEN = 'info_player';
const MODE = null;
@ -14,7 +13,6 @@ const translations: Record<string, Record<string, string>> = {
'Best rank': 'Najlepszy ranking',
'Most points': 'Najwięcej punktów',
'Most villages': 'Najwięcej wiosek',
'Show other servers': 'Pokaż inne światy',
'Show tribe changes': 'Pokaż zmiany plemion',
'Show history': 'Pokaż historię',
'Show ennoblements': 'Pokaż przejęcia',
@ -83,7 +81,6 @@ class TWHelpConnector {
}
enum DialogId {
OTHER_SERVERS = 'kichiyaki_other_servers',
TRIBE_CHANGES = 'kichiyaki_tribe_changes',
ENNOBLEMENTS = 'kichiyaki_ennoblements',
HISTORY = 'kichiyaki_history',
@ -148,10 +145,6 @@ class UI {
}
[
{
name: t('Show other servers'),
handler: this.showOtherServers.bind(this),
},
{
name: t('Show tribe changes'),
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) {
e.preventDefault();
@ -314,25 +274,29 @@ class UI {
},
{
header: t('Old owner'),
accessor: (e) =>
e.oldOwner
? `<a href="${e.oldOwner.profileUrl}">${e.oldOwner.name}</a>${
e.oldOwner.tribe
? ` (<a href="${e.oldOwner.tribe.profileUrl}">${e.oldOwner.tribe.tag}</a>)`
: ''
}`
: t('Barbarian'),
accessor: ({ village: { player } }) => {
if (!player) {
return t('Barbarian');
}
return `<a href="${player.profileUrl}">${player.name}</a>${
player.tribe
? ` (<a href="${player.tribe.profileUrl}">${player.tribe.tag}</a>)`
: ''
}`;
},
},
{
header: t('New owner'),
accessor: (e) =>
e.newOwner
? `<a href="${e.newOwner.profileUrl}">${e.newOwner.name}</a>${
e.newOwner.tribe
? ` (<a href="${e.newOwner.tribe.profileUrl}">${e.newOwner.tribe.tag}</a>)`
: ''
}`
: t('Unknown'),
accessor: ({ newOwner }) => {
if (!newOwner) {
return t('Unknown');
}
return `<a href="${newOwner.profileUrl}">${newOwner.name}</a>${
newOwner.tribe
? ` (<a href="${newOwner.tribe.profileUrl}">${newOwner.tribe.tag}</a>)`
: ''
}`;
},
},
{
header: t('Date/time'),
@ -379,5 +343,9 @@ class ExtendedPlayerProfile {
await new ExtendedPlayerProfile(
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: {
show: (id: string, html: string) => void;
close: () => void;
};
}
}

View File

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