Improve trade finder tables

This commit is contained in:
MusicalBean 2023-08-26 19:47:13 -07:00
parent 5f9f1faa93
commit fa98fcb298
8 changed files with 217 additions and 55 deletions

View File

@ -0,0 +1,26 @@
import Trader from "../trader";
export default class OwnsColumn {
static create(trader: Trader): HTMLTableCellElement {
let count = trader.ownsCount ?? 0;
let td = document.createElement("td");
td.style.textAlign = "center";
if (count === 0) {
td.innerText = "0";
td.style.color = "#cbd5e1";
return td;
}
let a = document.createElement("a");
a.target = "_blank";
a.href = trader.ownsList ?? "#";
a.innerHTML = `${count} <i class="fad fa-arrow-up-right-from-square"></i>`;
td.appendChild(a);
return td;
}
}

View File

@ -0,0 +1,26 @@
import Trader from "../trader";
export default class WantsColumn {
static create(trader: Trader): HTMLTableCellElement {
let count = trader.wantsCount ?? 0;
let td = document.createElement("td");
td.style.textAlign = "center";
if (count === 0) {
td.innerText = "0";
td.style.color = "#cbd5e1";
return td;
}
let a = document.createElement("a");
a.target = "_blank";
a.href = trader.wantsList ?? "#";
a.innerHTML = `${count} <i class="fad fa-arrow-up-right-from-square"></i>`;
td.appendChild(a);
return td;
}
}

View File

@ -1,3 +1,5 @@
import TradeFinderEnhancer from "./page-enhancers/trade-finder-enhancer";
import TradeFinderTheirsEnhancer from "./page-enhancers/trade-finder-theirs-enhancer";
import WhoOwnsEnhancer from "./page-enhancers/who-owns-enhancer"; import WhoOwnsEnhancer from "./page-enhancers/who-owns-enhancer";
import WhoWantsEnhancer from "./page-enhancers/who-wants-enhancer"; import WhoWantsEnhancer from "./page-enhancers/who-wants-enhancer";
@ -8,3 +10,11 @@ if (window.location.href.includes("who-owns.php")) {
if (window.location.href.includes("who-wants.php")) { if (window.location.href.includes("who-wants.php")) {
WhoWantsEnhancer.enhance(document); WhoWantsEnhancer.enhance(document);
} }
if (window.location.href.includes("profile/trade_finder.php")) {
TradeFinderEnhancer.enhance(document);
}
if (window.location.href.includes("profile/trade_finder_theirs.php")) {
TradeFinderTheirsEnhancer.enhance(document);
}

View File

@ -0,0 +1,88 @@
import OwnsColumn from "../element-factories/owns-column";
import WantsColumn from "../element-factories/wants-column";
import Trader from "../trader";
import TraderRepository from "../trader-repository";
export default class TradeFinderRow {
constructor(
public row: HTMLTableRowElement,
public cells: NodeListOf<HTMLTableCellElement>,
public repository: TraderRepository | null
) {}
static parse(
row: HTMLTableRowElement,
repository: TraderRepository | null = null
): TradeFinderRow | null {
let cells = row.querySelectorAll("td");
if (cells.length < 2) {
return null;
}
return new TradeFinderRow(row, cells, repository);
}
get username(): string {
return this.cells[0]
.querySelector("a")!
.querySelector("strong")!
.innerText.trim();
}
get profile(): string {
return this.cells[0].querySelector("a")!.href;
}
get open(): boolean {
return this.cells[0]
.querySelector("span")!
.innerText.includes("Open to trades");
}
get count(): number {
let link = this.cells[1].querySelector("a");
return link ? parseInt(link.innerText.match(/\d+/)![0]) : 0;
}
get list(): string | null {
let link = this.cells[1].querySelector("a");
return link ? link.href : null;
}
get trader(): Trader | null {
if (this.repository === null) {
throw new Error(
"Cannot get trader from TradeFinderRow without a repository"
);
}
return this.repository.find(this.username);
}
addWantsColumn() {
if (this.trader === null) {
throw new Error(
"Cannot add wants column to a TradeFinderRow that has no trader data"
);
}
let td = WantsColumn.create(this.trader!);
this.row.appendChild(td);
}
addOwnsColumn() {
if (this.trader === null) {
throw new Error(
"Cannot add owns column to a TradeFinderRow that has no trader data"
);
}
let td = OwnsColumn.create(this.trader!);
this.row.appendChild(td);
}
}

View File

@ -0,0 +1,30 @@
import TradeFinderRow from "../page-elements/trade-finder-row";
import TraderRepository from "../trader-repository";
export default class TradeFinderEnhancer {
static addHeader(page: Document) {
let th = document.createElement("th");
th.innerText = "# of their wants that I own";
th.style.textAlign = "center";
th.scope = "col";
page.querySelector("table thead tr")?.appendChild(th);
}
static async enhance(page: Document) {
let repository = await TraderRepository.load();
this.addHeader(page);
let tbody = page.querySelector("table tbody")!;
let rows = tbody.querySelectorAll("tr");
Array.from(rows)
.map((row) =>
TradeFinderRow.parse(row as HTMLTableRowElement, repository)
)
.filter((row) => row !== null)
.filter((row) => row!.trader !== null)
.forEach((row) => row!.addWantsColumn());
}
}

View File

@ -0,0 +1,30 @@
import TradeFinderRow from "../page-elements/trade-finder-row";
import TraderRepository from "../trader-repository";
export default class TradeFinderTheirsEnhancer {
static addHeader(page: Document) {
let th = document.createElement("th");
th.innerText = "# of my wants that they own";
th.style.textAlign = "center";
th.scope = "col";
page.querySelector("table thead tr")?.appendChild(th);
}
static async enhance(page: Document) {
let repository = await TraderRepository.load();
this.addHeader(page);
let tbody = page.querySelector("table tbody")!;
let rows = tbody.querySelectorAll("tr");
Array.from(rows)
.map((row) =>
TradeFinderRow.parse(row as HTMLTableRowElement, repository)
)
.filter((row) => row !== null)
.filter((row) => row!.trader !== null)
.forEach((row) => row!.addOwnsColumn());
}
}

View File

@ -29,8 +29,8 @@ export default class TraderRepository {
let text = await response.text(); let text = await response.text();
let page = new DOMParser().parseFromString(text, "text/html"); let page = new DOMParser().parseFromString(text, "text/html");
let table = page.querySelector("table")!; let tbody = page.querySelector("table tbody")!;
let rows = table.querySelectorAll("tr"); let rows = tbody.querySelectorAll("tr");
return Array.from(rows) return Array.from(rows)
.map((row) => Trader.fromWantsRow(row as HTMLTableRowElement)) .map((row) => Trader.fromWantsRow(row as HTMLTableRowElement))
@ -47,8 +47,8 @@ export default class TraderRepository {
let text = await response.text(); let text = await response.text();
let page = new DOMParser().parseFromString(text, "text/html"); let page = new DOMParser().parseFromString(text, "text/html");
let table = page.querySelector("table")!; let tbody = page.querySelector("table tbody")!;
let rows = table.querySelectorAll("tr"); let rows = tbody.querySelectorAll("tr");
return Array.from(rows) return Array.from(rows)
.map((row) => Trader.fromOwnsRow(row as HTMLTableRowElement)) .map((row) => Trader.fromOwnsRow(row as HTMLTableRowElement))

View File

@ -1,10 +1,4 @@
interface RowData { import TradeFinderRow from "./page-elements/trade-finder-row";
username: string;
profile: string;
open: boolean;
count: number;
list: string | null;
}
export default class Trader { export default class Trader {
constructor( constructor(
@ -17,53 +11,11 @@ export default class Trader {
public wantsList: string | null = null public wantsList: string | null = null
) {} ) {}
/**
* Get the underlying trader data from a row in a "Trade finder" table.
*/
static parseRow(row: HTMLTableRowElement): RowData | null {
let cells = row.querySelectorAll("td");
if (cells.length < 2) {
return null;
}
let profileLink = cells[0].querySelector("a");
if (!profileLink) {
return null;
}
let username =
profileLink.querySelector("strong")?.innerText ??
profileLink.innerText;
let profile = profileLink.href;
let open =
cells[0]
.querySelector("span")
?.innerText.includes("Open to trades") ?? false;
let wantsLink = cells[1].querySelector("a");
let count = wantsLink
? parseInt(wantsLink.innerText.match(/\d+/)![0])
: 0;
let list = wantsLink ? wantsLink.href : null;
return {
username,
profile,
open,
count,
list,
};
}
/** /**
* Create a Trader from a row in a "Trade finder wants" table. * Create a Trader from a row in a "Trade finder wants" table.
*/ */
static fromWantsRow(row: HTMLTableRowElement): Trader | null { static fromWantsRow(row: HTMLTableRowElement): Trader | null {
let data = Trader.parseRow(row); let data = TradeFinderRow.parse(row);
if (data === null) { if (data === null) {
return null; return null;
@ -84,7 +36,7 @@ export default class Trader {
* Create a Trader from a row in a "Trade finder owns" table. * Create a Trader from a row in a "Trade finder owns" table.
*/ */
static fromOwnsRow(row: HTMLTableRowElement): Trader | null { static fromOwnsRow(row: HTMLTableRowElement): Trader | null {
let data = Trader.parseRow(row); let data = TradeFinderRow.parse(row);
if (data === null) { if (data === null) {
return null; return null;