Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 3 additions & 3 deletions backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"gen-docs": "tsx scripts/openapi.ts dist/static/api/openapi.json && redocly build-docs -o dist/static/api/internal.html internal@v2 && redocly bundle -o dist/static/api/public.json public-filter && redocly build-docs -o dist/static/api/public.html public@v2"
},
"engines": {
"node": "24.11.0"
"node": "24.11.0 || 22.21.0"
},
"dependencies": {
"@date-fns/utc": "1.2.0",
Expand All @@ -40,7 +40,7 @@
"date-fns": "3.6.0",
"dotenv": "16.4.5",
"etag": "1.8.1",
"express": "5.1.0",
"express": "5.2.0",
"express-rate-limit": "7.5.1",
"firebase-admin": "12.0.0",
"helmet": "4.6.0",
Expand All @@ -49,7 +49,7 @@
"mjml": "4.15.0",
"mongodb": "6.3.0",
"mustache": "4.2.0",
"nodemailer": "7.0.7",
"nodemailer": "7.0.11",
"object-hash": "3.0.0",
"prom-client": "15.1.3",
"rate-limiter-flexible": "5.0.3",
Expand Down
2 changes: 1 addition & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
"docker": "docker compose -f docker/compose.dev.yml up"
},
"engines": {
"node": "24.11.0"
"node": "24.11.0 || 22.21.0"
},
"browserslist": [
"defaults",
Expand Down
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();
},
});
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@
"knip": "knip"
},
"engines": {
"node": "24.11.0"
"node": "24.11.0 || 22.21.0"
},
"devDependencies": {
"@commitlint/cli": "17.7.1",
Expand Down
Loading
Loading