fix(account): fix not all results shown if result has a funbox unknown to stored filter (@fehmer) (#6608)

Merge with default filters to ensure all languages and funboxes are
present in the result filter.
This commit is contained in:
Christian Fehmer 2025-06-23 14:52:23 +02:00 committed by GitHub
parent 33a6bc09e3
commit 79cc330852
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 37 additions and 30 deletions

View file

@ -1,5 +1,7 @@
import { ResultFilters } from "@monkeytype/contracts/schemas/users";
import { deepClone } from "../utils/misc";
import { LanguageList } from "./languages";
import { getFunboxNames } from "@monkeytype/funbox";
const object: ResultFilters = {
_id: "default",
@ -58,9 +60,10 @@ const object: ResultFilters = {
tags: {
none: true,
},
language: {},
language: Object.fromEntries(LanguageList.map((lang) => [lang, true])),
funbox: {
none: true,
...Object.fromEntries(getFunboxNames().map((funbox) => [funbox, true])),
},
};

View file

@ -19,7 +19,6 @@ import * as URLHandler from "../utils/url-handler";
import * as Account from "../pages/account";
import * as Alerts from "../elements/alerts";
import * as AccountSettings from "../pages/account-settings";
import { getAllFunboxes } from "@monkeytype/funbox";
import {
GoogleAuthProvider,
GithubAuthProvider,
@ -46,10 +45,8 @@ import * as ConnectionState from "../states/connection";
import { navigate } from "./route-controller";
import { FirebaseError } from "firebase/app";
import * as PSA from "../elements/psa";
import defaultResultFilters from "../constants/default-result-filters";
import { getActiveFunboxesWithFunction } from "../test/funbox/list";
import { Snapshot } from "../constants/default-snapshot";
import { LanguageList } from "../constants/languages";
import * as Sentry from "../sentry";
export const gmailProvider = new GoogleAuthProvider();
@ -136,13 +133,6 @@ async function getDataAndInit(): Promise<boolean> {
ResultFilters.loadTags(snapshot.tags);
for (const language of LanguageList) {
defaultResultFilters.language[language] = true;
}
for (const funbox of getAllFunboxes()) {
defaultResultFilters.funbox[funbox.name] = true;
}
// filters = defaultResultFilters;
void ResultFilters.load();

View file

@ -90,7 +90,7 @@ function save(): void {
export async function load(): Promise<void> {
try {
filters = resultFiltersLS.get();
filters = mergeWithDefaultFilters(resultFiltersLS.get());
const newTags: Record<string, boolean> = { none: false };
Object.keys(defaultResultFilters.tags).forEach((tag) => {
@ -743,18 +743,37 @@ let selectChangeCallbackFn: () => void = () => {
};
export function updateTagsDropdownOptions(): void {
const el = document.querySelector<HTMLElement>(
".pageAccount .content .filterButtons .buttonsAndTitle.tags .select select"
);
if (!(el instanceof HTMLElement)) return;
const snapshot = DB.getSnapshot();
if (snapshot === undefined) {
return;
}
const newTags = snapshot.tags.filter(
(it) => defaultResultFilters.tags[it._id] === undefined
);
if (newTags.length > 0) {
const everythingSelected = Object.values(filters.tags).every((v) => v);
defaultResultFilters.tags = {
...defaultResultFilters.tags,
...Object.fromEntries(newTags.map((tag) => [tag._id, true])),
};
filters.tags = {
...filters.tags,
...Object.fromEntries(
newTags.map((tag) => [tag._id, everythingSelected])
),
};
}
const el = document.querySelector<HTMLElement>(
".pageAccount .content .filterButtons .buttonsAndTitle.tags .select select"
);
if (!(el instanceof HTMLElement)) return;
let html = "";
html += "<option value='all'>all</option>";
@ -907,15 +926,9 @@ $(".group.presetFilterButtons .filterBtns").on(
);
function verifyResultFiltersStructure(filterIn: ResultFilters): ResultFilters {
const filter = Misc.sanitize(ResultFiltersSchema, Misc.deepClone(filterIn));
const filter = mergeWithDefaultFilters(
Misc.sanitize(ResultFiltersSchema, Misc.deepClone(filterIn))
);
Object.entries(defaultResultFilters).forEach((entry) => {
const key = entry[0] as ResultFiltersGroup;
const value = entry[1];
if (filter[key] === undefined) {
// @ts-expect-error key and value is based on default filter so this is safe to ignore
filter[key] = value;
}
});
return filter;
}

View file

@ -10,9 +10,10 @@ import {
QuoteLengthSchema,
DifficultySchema,
} from "./shared";
import { CustomThemeColorsSchema } from "./configs";
import { CustomThemeColorsSchema, FunboxNameSchema } from "./configs";
import { doesNotContainProfanity } from "../validation/validation";
const NoneFilterSchema = z.literal("none");
export const ResultFiltersSchema = z.object({
_id: IdSchema,
name: z
@ -51,9 +52,9 @@ export const ResultFiltersSchema = z.object({
all: z.boolean(),
})
.strict(),
tags: z.record(z.string(), z.boolean()),
tags: z.record(IdSchema.or(NoneFilterSchema), z.boolean()),
language: z.record(LanguageSchema, z.boolean()),
funbox: z.record(z.string(), z.boolean()),
funbox: z.record(FunboxNameSchema.or(NoneFilterSchema), z.boolean()),
});
export type ResultFilters = z.infer<typeof ResultFiltersSchema>;