Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
ec513fc
Add basic filter
Leonabcd123 Nov 15, 2025
d7afb5a
Add refresh button
Leonabcd123 Nov 15, 2025
e8e4301
Refresh automatically
Leonabcd123 Nov 15, 2025
5e22606
Add min and max
Leonabcd123 Nov 15, 2025
52fd99d
refactor
Leonabcd123 Nov 15, 2025
02754cd
Remove unnecessary parameter
Leonabcd123 Nov 15, 2025
b40f0c3
Ignore custom when others are present
Leonabcd123 Nov 15, 2025
a9a3a0e
Don't show popup when removing other filters
Leonabcd123 Nov 15, 2025
7b74224
Make popup show when first option isn't custom
Leonabcd123 Nov 15, 2025
076da52
Make quotes change after each input change
Leonabcd123 Nov 15, 2025
6edba5f
refactor
Leonabcd123 Nov 15, 2025
8c44ed3
Allow min to be 0
Leonabcd123 Nov 15, 2025
5c0889d
Remove else block
Leonabcd123 Nov 15, 2025
a2805ee
Make custom work with other filters
Leonabcd123 Nov 15, 2025
cec251e
convert to simple modal
Leonabcd123 Nov 15, 2025
5778104
Move usingCustomLength to quote-search
Leonabcd123 Nov 15, 2025
96eb8ea
Remove old modal
Leonabcd123 Nov 15, 2025
986dfd5
Remove onlineOnly
Leonabcd123 Nov 15, 2025
3cb2a72
Merge branch 'master' into add-custom-length-filter-quotes
Miodec Nov 26, 2025
3e4cbbe
Remove refresh button
Leonabcd123 Nov 27, 2025
ef43fb2
Merge branch 'master' into add-custom-length-filter-quotes
Leonabcd123 Nov 27, 2025
8ad9add
prettier
Leonabcd123 Nov 27, 2025
1f26985
Merge branch 'master' into add-custom-length-filter-quotes
Leonabcd123 Nov 27, 2025
468fcf0
Force users to enter min and max values
Leonabcd123 Nov 27, 2025
098ea36
Merge branch 'master' into add-custom-length-filter-quotes
Leonabcd123 Nov 27, 2025
25c2762
Add afterClick function
Leonabcd123 Nov 28, 2025
186092d
Remove custom selection after clicking out of modal
Leonabcd123 Nov 28, 2025
463d6d1
Use splice
Leonabcd123 Nov 28, 2025
ddc7a5e
Only update results after submission
Leonabcd123 Nov 28, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions frontend/src/ts/modals/quote-filter.ts
Original file line number Diff line number Diff line change
@@ -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();
},
});
68 changes: 65 additions & 3 deletions frontend/src/ts/modals/quote-search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -26,6 +27,7 @@ const searchServiceCache: Record<string, SearchService<Quote>> = {};

const pageSize = 100;
let currentPageNumber = 1;
let usingCustomLength = true;

function getSearchService<T>(
language: string,
Expand All @@ -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),
);
Expand Down Expand Up @@ -281,6 +332,10 @@ export async function show(showOptions?: ShowOptions): Promise<void> {
text: "thicc",
value: "3",
},
{
text: "custom",
value: "4",
},
],
});
},
Expand Down Expand Up @@ -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> {
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/ts/utils/simple-modal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ type SimpleModalOptions = {
onlineOnly?: boolean;
hideCallsExec?: boolean;
showLabels?: boolean;
afterClickAway?: () => void;
};

export class SimpleModal {
Expand All @@ -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;
Expand All @@ -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 = `
Expand Down Expand Up @@ -480,6 +483,7 @@ const modal = new AnimatedModal({
hide();
},
customWrapperClickHandler: (e): void => {
activePopup?.afterClickAway?.();
hide();
},
});