mirror of
https://github.com/monkeytypegame/monkeytype.git
synced 2026-01-02 05:24:50 +08:00
impr(quote search modal): add custom length filter (@Leonabcd123) (#7109)
### Description Added a new filter option in the quotes search page that allows the user to search for quotes by a minimum and a maximum length. Implementing #1323 --------- Co-authored-by: Jack <jack@monkeytype.com>
This commit is contained in:
parent
71c0f43d96
commit
54e660da6b
3 changed files with 120 additions and 3 deletions
51
frontend/src/ts/modals/quote-filter.ts
Normal file
51
frontend/src/ts/modals/quote-filter.ts
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
import { SimpleModal } from "../utils/simple-modal";
|
||||
|
||||
export let minFilterLength: number = 0;
|
||||
export let maxFilterLength: number = 0;
|
||||
export let removeCustom: boolean = false;
|
||||
|
||||
export function setRemoveCustom(value: boolean): void {
|
||||
removeCustom = value;
|
||||
}
|
||||
|
||||
function refresh(): void {
|
||||
const refreshEvent = new CustomEvent("refresh");
|
||||
document.dispatchEvent(refreshEvent);
|
||||
}
|
||||
|
||||
export const quoteFilterModal = new SimpleModal({
|
||||
id: "quoteFilter",
|
||||
title: "Enter minimum and maximum values",
|
||||
inputs: [
|
||||
{
|
||||
placeholder: "1",
|
||||
type: "number",
|
||||
},
|
||||
{
|
||||
placeholder: "100",
|
||||
type: "number",
|
||||
},
|
||||
],
|
||||
buttonText: "save",
|
||||
execFn: async (_thisPopup, min, max) => {
|
||||
const minNum = parseInt(min, 10);
|
||||
const maxNum = parseInt(max, 10);
|
||||
if (isNaN(minNum) || isNaN(maxNum)) {
|
||||
return {
|
||||
status: 0,
|
||||
message: "Invalid min/max values",
|
||||
};
|
||||
}
|
||||
|
||||
minFilterLength = minNum;
|
||||
maxFilterLength = maxNum;
|
||||
refresh();
|
||||
|
||||
let message: string = "saved custom filter";
|
||||
return { status: 1, message };
|
||||
},
|
||||
afterClickAway: () => {
|
||||
setRemoveCustom(true);
|
||||
refresh();
|
||||
},
|
||||
});
|
||||
|
|
@ -4,6 +4,7 @@ import * as ManualRestart from "../test/manual-restart-tracker";
|
|||
import * as Notifications from "../elements/notifications";
|
||||
import * as QuoteSubmitPopup from "./quote-submit";
|
||||
import * as QuoteApprovePopup from "./quote-approve";
|
||||
import * as QuoteFilterPopup from "./quote-filter";
|
||||
import * as QuoteReportModal from "./quote-report";
|
||||
import {
|
||||
buildSearchService,
|
||||
|
|
@ -26,6 +27,7 @@ const searchServiceCache: Record<string, SearchService<Quote>> = {};
|
|||
|
||||
const pageSize = 100;
|
||||
let currentPageNumber = 1;
|
||||
let usingCustomLength = true;
|
||||
|
||||
function getSearchService<T>(
|
||||
language: string,
|
||||
|
|
@ -45,16 +47,65 @@ function getSearchService<T>(
|
|||
|
||||
function applyQuoteLengthFilter(quotes: Quote[]): Quote[] {
|
||||
if (!modal.isOpen()) return [];
|
||||
const quoteLengthFilterValue = $(
|
||||
"#quoteSearchModal .quoteLengthFilter",
|
||||
).val() as string[];
|
||||
const quoteLengthDropdown = $("#quoteSearchModal .quoteLengthFilter");
|
||||
const quoteLengthFilterValue = quoteLengthDropdown.val() as string[];
|
||||
|
||||
if (quoteLengthFilterValue.length === 0) {
|
||||
usingCustomLength = true;
|
||||
return quotes;
|
||||
}
|
||||
|
||||
const quoteLengthFilter = new Set(
|
||||
quoteLengthFilterValue.map((filterValue) => parseInt(filterValue, 10)),
|
||||
);
|
||||
|
||||
const customFilterIndex = quoteLengthFilterValue.indexOf("4");
|
||||
|
||||
if (customFilterIndex !== -1) {
|
||||
if (QuoteFilterPopup.removeCustom) {
|
||||
QuoteFilterPopup.setRemoveCustom(false);
|
||||
const selectElement = quoteLengthDropdown.get(0) as
|
||||
| HTMLSelectElement
|
||||
| null
|
||||
| undefined;
|
||||
|
||||
if (!selectElement) {
|
||||
return quotes;
|
||||
}
|
||||
|
||||
//@ts-expect-error SlimSelect adds slim to the element
|
||||
const ss = selectElement.slim as SlimSelect | undefined;
|
||||
|
||||
if (ss !== undefined) {
|
||||
const currentSelected = ss.getSelected();
|
||||
|
||||
// remove custom selection
|
||||
const customIndex = currentSelected.indexOf("4");
|
||||
if (customIndex > -1) {
|
||||
currentSelected.splice(customIndex, 1);
|
||||
}
|
||||
|
||||
ss.setSelected(currentSelected);
|
||||
}
|
||||
} else {
|
||||
if (usingCustomLength) {
|
||||
QuoteFilterPopup.quoteFilterModal.show(undefined, {});
|
||||
usingCustomLength = false;
|
||||
} else {
|
||||
const filteredQuotes = quotes.filter(
|
||||
(quote) =>
|
||||
(quote.length >= QuoteFilterPopup.minFilterLength &&
|
||||
quote.length <= QuoteFilterPopup.maxFilterLength) ||
|
||||
quoteLengthFilter.has(quote.group),
|
||||
);
|
||||
|
||||
return filteredQuotes;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
usingCustomLength = true;
|
||||
}
|
||||
|
||||
const filteredQuotes = quotes.filter((quote) =>
|
||||
quoteLengthFilter.has(quote.group),
|
||||
);
|
||||
|
|
@ -281,6 +332,10 @@ export async function show(showOptions?: ShowOptions): Promise<void> {
|
|||
text: "thicc",
|
||||
value: "3",
|
||||
},
|
||||
{
|
||||
text: "custom",
|
||||
value: "4",
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
|
|
@ -437,6 +492,13 @@ async function setup(modalEl: HTMLElement): Promise<void> {
|
|||
currentPageNumber--;
|
||||
void updateResults(searchText);
|
||||
});
|
||||
|
||||
document?.addEventListener("refresh", () => {
|
||||
const searchText = (
|
||||
document.getElementById("searchBox") as HTMLInputElement
|
||||
).value;
|
||||
void updateResults(searchText);
|
||||
});
|
||||
}
|
||||
|
||||
async function cleanup(): Promise<void> {
|
||||
|
|
|
|||
|
|
@ -111,6 +111,7 @@ type SimpleModalOptions = {
|
|||
onlineOnly?: boolean;
|
||||
hideCallsExec?: boolean;
|
||||
showLabels?: boolean;
|
||||
afterClickAway?: () => void;
|
||||
};
|
||||
|
||||
export class SimpleModal {
|
||||
|
|
@ -131,6 +132,7 @@ export class SimpleModal {
|
|||
onlineOnly: boolean;
|
||||
hideCallsExec: boolean;
|
||||
showLabels: boolean;
|
||||
afterClickAway: (() => void) | undefined;
|
||||
constructor(options: SimpleModalOptions) {
|
||||
this.parameters = [];
|
||||
this.id = options.id;
|
||||
|
|
@ -149,6 +151,7 @@ export class SimpleModal {
|
|||
this.onlineOnly = options.onlineOnly ?? false;
|
||||
this.hideCallsExec = options.hideCallsExec ?? false;
|
||||
this.showLabels = options.showLabels ?? false;
|
||||
this.afterClickAway = options.afterClickAway;
|
||||
}
|
||||
reset(): void {
|
||||
this.element.innerHTML = `
|
||||
|
|
@ -480,6 +483,7 @@ const modal = new AnimatedModal({
|
|||
hide();
|
||||
},
|
||||
customWrapperClickHandler: (e): void => {
|
||||
activePopup?.afterClickAway?.();
|
||||
hide();
|
||||
},
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue