Preact: Support teambuilder search (#2496)

---------

Co-authored-by: Guangcong Luo <guangcongluo@gmail.com>
This commit is contained in:
Daniel Chen 2025-08-07 04:35:52 -04:00 committed by GitHub
parent 3ec551f15d
commit 79c19fcf95
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 47 additions and 4 deletions

View File

@ -23,6 +23,7 @@ class TeambuilderRoom extends PSRoom {
*/
curFolder = '';
curFolderKeep = '';
searchTerms: string[] = [];
override clientCommands = this.parseClientCommands({
'newteam'(target) {
@ -73,6 +74,19 @@ class TeambuilderRoom extends PSRoom {
};
}
}
updateSearch = (value: string) => {
if (!value) {
this.searchTerms = [];
} else {
this.searchTerms = value.split(",").map(q => q.trim().toLowerCase());
}
};
matchesSearch = (team: Team | null) => {
if (!team) return false;
if (this.searchTerms.length === 0) return true;
const normalized = team.packedTeam.toLowerCase();
return this.searchTerms.every(term => normalized.includes(term));
};
}
class TeambuilderPanel extends PSRoomPanel<TeambuilderRoom> {
@ -273,6 +287,17 @@ class TeambuilderPanel extends PSRoomPanel<TeambuilderRoom> {
static handleDrop(ev: DragEvent) {
return !!this.addDraggedTeam(ev, (PS.rooms['teambuilder'] as TeambuilderRoom)?.curFolder);
}
updateSearch = (ev: KeyboardEvent) => {
const target = ev.currentTarget as HTMLInputElement;
this.props.room.updateSearch(target.value);
this.forceUpdate();
};
clearSearch = () => {
const target = this.base!.querySelector<HTMLInputElement>('input[type="search"]');
if (!target) return;
target.value = '';
this.props.room.updateSearch('');
};
renderFolder(value: string) {
const { room } = this.props;
const cur = room.curFolder === value;
@ -438,6 +463,8 @@ class TeambuilderPanel extends PSRoomPanel<TeambuilderRoom> {
}
}
const filteredTeams = teams.filter(room.matchesSearch);
return <PSPanelWrapper room={room}>
<div class="folderpane">
{this.renderFolderList()}
@ -463,11 +490,19 @@ class TeambuilderPanel extends PSRoomPanel<TeambuilderRoom> {
<p>
<button data-cmd="/newteam" class="button big"><i class="fa fa-plus-circle" aria-hidden></i> New Team</button> {}
<button data-cmd="/newteam box" class="button"><i class="fa fa-archive" aria-hidden></i> New Box</button>
<input
type="search" class="textbox" placeholder="Search teams"
style="margin-left:5px;" onKeyUp={this.updateSearch}
></input>
</p>
<ul class="teamlist">
{teams.map(team => team ? (
{!teams.length ? (
<li><em>you have no teams lol</em></li>
) : !filteredTeams.length ? (
<li><em>you have no teams matching <code>{room.searchTerms.join(", ")}</code></em></li>
) : filteredTeams.map(team => team ? (
<li key={team.key} onDragEnter={this.dragEnterTeam} data-teamkey={team.key}>
<TeamBox team={team} /> {}
<TeamBox team={team} onClick={this.clearSearch} /> {}
{!team.uploaded && <button data-cmd={`/deleteteam ${team.key}`} class="option">
<i class="fa fa-trash" aria-hidden></i> Delete
</button>} {}

View File

@ -289,7 +289,12 @@ export class PSTeambuilder {
}
}
export function TeamBox(props: { team: Team | null, noLink?: boolean, button?: boolean }) {
export function TeamBox(props: {
team: Team | null,
noLink?: boolean,
button?: boolean,
onClick?: () => void,
}) {
const team = props.team;
let contents;
if (team) {
@ -325,7 +330,10 @@ export function TeamBox(props: { team: Team | null, noLink?: boolean, button?: b
{contents}
</div>;
}
return <a href={`team-${team ? team.key : ''}`} class={className} draggable onDragStart={PSTeambuilder.dragStart}>
return <a
href={`team-${team ? team.key : ''}`} class={className} draggable
onDragStart={PSTeambuilder.dragStart} onClick={props.onClick}
>
{contents}
</a>;
}