From 08165adc2c47b3e75f527d3ec94f6c6b0887a6d0 Mon Sep 17 00:00:00 2001 From: Christian Fehmer Date: Fri, 31 Oct 2025 13:36:40 +0100 Subject: [PATCH 1/4] impr(friends): remember sorting of friends list (@fehmer) (#7062) Store sorting of the friends list in local storage and apply on load --- frontend/src/ts/pages/friends.ts | 11 ++++-- frontend/src/ts/pages/profile.ts | 2 +- frontend/src/ts/utils/sorted-table.ts | 57 ++++++++++++++++++--------- 3 files changed, 47 insertions(+), 23 deletions(-) diff --git a/frontend/src/ts/pages/friends.ts b/frontend/src/ts/pages/friends.ts index 3fc190e9dca8..eb1f30aafb4a 100644 --- a/frontend/src/ts/pages/friends.ts +++ b/frontend/src/ts/pages/friends.ts @@ -17,7 +17,7 @@ import { secondsToString } from "../utils/date-and-time"; import { PersonalBest } from "@monkeytype/schemas/shared"; import Format from "../utils/format"; import { getHtmlByUserFlags } from "../controllers/user-flag-controller"; -import { SortedTable } from "../utils/sorted-table"; +import { SortedTable, SortSchema } from "../utils/sorted-table"; import { getAvatarElement } from "../utils/discord-avatar"; import { formatTypingStatsRatio } from "../utils/misc"; import { getLanguageDisplayString } from "../utils/strings"; @@ -28,6 +28,7 @@ import * as AuthEvent from "../observables/auth-event"; import { Connection } from "@monkeytype/schemas/connections"; import { Friend, UserNameSchema } from "@monkeytype/schemas/users"; import * as Loader from "../elements/loader"; +import { LocalStorageWithSchema } from "../utils/local-storage-with-schema"; const pageElement = $(".page.pageFriends"); @@ -95,7 +96,7 @@ const addFriendModal = new SimpleModal({ const result = await addFriend(receiverName); if (result === true) { - return { status: 1, message: `Request send to ${receiverName}` }; + return { status: 1, message: `Request sent to ${receiverName}` }; } let status: -1 | 0 | 1 = -1; @@ -230,7 +231,11 @@ function updateFriends(): void { table: ".pageFriends .friends table", data: friendsList, buildRow: buildFriendRow, - initialSort: { property: "name", descending: false }, + persistence: new LocalStorageWithSchema({ + key: "friendsListSort", + schema: SortSchema, + fallback: { property: "name", descending: false }, + }), }); } else { friendsTable.setData(friendsList); diff --git a/frontend/src/ts/pages/profile.ts b/frontend/src/ts/pages/profile.ts index ce3dfa17e521..1de3ceea099a 100644 --- a/frontend/src/ts/pages/profile.ts +++ b/frontend/src/ts/pages/profile.ts @@ -251,7 +251,7 @@ $(".page.pageProfile").on("click", ".profile .addFriendButton", async () => { const result = await addFriend(friendName); if (result === true) { - Notifications.add(`Request send to ${friendName}`); + Notifications.add(`Request sent to ${friendName}`); $(".profile .details .addFriendButton").addClass("disabled"); } else { Notifications.add(result, -1); diff --git a/frontend/src/ts/utils/sorted-table.ts b/frontend/src/ts/utils/sorted-table.ts index 4124600f40a9..43b3afd7ec5f 100644 --- a/frontend/src/ts/utils/sorted-table.ts +++ b/frontend/src/ts/utils/sorted-table.ts @@ -1,34 +1,50 @@ -type Sort = { - property: string; - descending: boolean; +import { z } from "zod"; + +export const SortSchema = z.object({ + property: z.string(), + descending: z.boolean(), +}); +export type Sort = z.infer; + +type Persistence = { + get: () => Sort; + set: (sort: Sort) => boolean; }; type SortedTableOptions = { table: string; data?: T[]; buildRow: (entry: T) => HTMLTableRowElement; - initialSort?: Sort; -}; +} & ( + | { initialSort?: Sort; persistence?: never } + | { persistence?: Persistence; initialSort?: never } +); + export class SortedTable { - protected data: { source: T; element?: HTMLTableRowElement }[]; + protected data: { source: T; element?: HTMLTableRowElement }[] = []; private table: JQuery; private buildRow: (entry: T) => HTMLTableRowElement; private sort?: Sort; + private persistence?: Persistence; - constructor({ table, data, buildRow, initialSort }: SortedTableOptions) { - this.table = $(table); + constructor(options: SortedTableOptions) { + this.table = $(options.table); if (this.table === undefined) { - throw new Error(`No element found for ${table}`); + throw new Error(`No element found for ${options.table}`); } - this.buildRow = buildRow; - this.data = []; - if (data !== undefined) { - this.setData(data); + this.buildRow = options.buildRow; + + if (options.data !== undefined) { + this.setData(options.data); } - if (initialSort !== undefined) { - this.sort = initialSort; + if ("persistence" in options && options.persistence !== undefined) { + this.persistence = options.persistence; + this.sort = this.persistence.get(); + this.doSort(); + } else if ("initialSort" in options && options.initialSort !== undefined) { + this.sort = options.initialSort; this.doSort(); } @@ -43,13 +59,15 @@ export class SortedTable { target.dataset["sortDefaultDirection"] === "desc"; if (property === undefined) return; - if (this.sort === undefined || property !== this.sort.property) { - this.sort = { property, descending: defaultDirection }; + let updatedSort = this.sort; + + if (updatedSort === undefined || property !== updatedSort.property) { + updatedSort = { property, descending: defaultDirection }; } else { - this.sort.descending = !this.sort?.descending; + updatedSort.descending = !updatedSort?.descending; } + this.setSort(updatedSort); - this.doSort(); this.updateBody(); }; } @@ -57,6 +75,7 @@ export class SortedTable { public setSort(sort: Partial): void { this.sort = { ...this.sort, ...sort } as Sort; + this.persistence?.set(this.sort); this.doSort(); } From 586a19ad3e17f1aa6e0682a50b215bee8022d275 Mon Sep 17 00:00:00 2001 From: Miodec Date: Fri, 31 Oct 2025 14:00:41 +0100 Subject: [PATCH 2/4] chore: upgrade oxlint --- backend/package.json | 2 +- frontend/package.json | 2 +- package.json | 2 +- packages/contracts/package.json | 2 +- packages/funbox/package.json | 2 +- packages/oxlint-config/index.jsonc | 4 +- packages/release/package.json | 2 +- packages/release/src/buildChangelog.js | 7 +- packages/schemas/package.json | 2 +- packages/tsup-config/package.json | 2 +- packages/util/package.json | 2 +- pnpm-lock.yaml | 148 ++++++++++++------------- 12 files changed, 91 insertions(+), 86 deletions(-) diff --git a/backend/package.json b/backend/package.json index a174a258b375..76c338322149 100644 --- a/backend/package.json +++ b/backend/package.json @@ -89,7 +89,7 @@ "eslint": "8.57.1", "eslint-watch": "8.0.0", "openapi3-ts": "2.0.2", - "oxlint": "1.15.0", + "oxlint": "1.25.0", "readline-sync": "1.4.10", "supertest": "7.1.4", "testcontainers": "11.4.0", diff --git a/frontend/package.json b/frontend/package.json index 51f4bfef4934..4f38f1b37ab9 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -57,7 +57,7 @@ "madge": "8.0.0", "magic-string": "0.30.17", "normalize.css": "8.0.1", - "oxlint": "1.15.0", + "oxlint": "1.25.0", "postcss": "8.4.31", "sass": "1.70.0", "subset-font": "2.3.0", diff --git a/package.json b/package.json index 27a3be358221..f7e06b964509 100644 --- a/package.json +++ b/package.json @@ -74,7 +74,7 @@ "knip": "2.19.2", "lint-staged": "13.2.3", "only-allow": "1.2.1", - "oxlint": "1.15.0", + "oxlint": "1.25.0", "prettier": "2.8.8", "turbo": "2.5.6", "vitest": "4.0.4" diff --git a/packages/contracts/package.json b/packages/contracts/package.json index 55cc25cf6a30..2e5a9e7ed2d9 100644 --- a/packages/contracts/package.json +++ b/packages/contracts/package.json @@ -24,7 +24,7 @@ "@monkeytype/typescript-config": "workspace:*", "eslint": "8.57.1", "madge": "8.0.0", - "oxlint": "1.15.0", + "oxlint": "1.25.0", "tsup": "8.4.0", "typescript": "5.5.4", "vitest": "4.0.4" diff --git a/packages/funbox/package.json b/packages/funbox/package.json index a6372104cdd3..2e254b08cbca 100644 --- a/packages/funbox/package.json +++ b/packages/funbox/package.json @@ -17,7 +17,7 @@ "@monkeytype/typescript-config": "workspace:*", "eslint": "8.57.1", "madge": "8.0.0", - "oxlint": "1.15.0", + "oxlint": "1.25.0", "tsup": "8.4.0", "typescript": "5.5.4", "vitest": "4.0.4" diff --git a/packages/oxlint-config/index.jsonc b/packages/oxlint-config/index.jsonc index c8ba1bb093b1..192bb9c14662 100644 --- a/packages/oxlint-config/index.jsonc +++ b/packages/oxlint-config/index.jsonc @@ -101,6 +101,8 @@ // consider these for the future "no-cycle": "off", - "no-nested-ternary": "off" + "no-nested-ternary": "off", + "no-array-sort": "off", + "preserve-caught-error": "off" } } diff --git a/packages/release/package.json b/packages/release/package.json index 746edab2d3c0..4294118c79cc 100644 --- a/packages/release/package.json +++ b/packages/release/package.json @@ -14,7 +14,7 @@ "@monkeytype/eslint-config": "workspace:*", "eslint": "8.57.1", "nodemon": "3.1.4", - "oxlint": "1.15.0" + "oxlint": "1.25.0" }, "bin": { "monkeytype-release": "./src/index.js" diff --git a/packages/release/src/buildChangelog.js b/packages/release/src/buildChangelog.js index f754babe1f9e..d84ef17b064f 100644 --- a/packages/release/src/buildChangelog.js +++ b/packages/release/src/buildChangelog.js @@ -40,8 +40,11 @@ async function getLog() { function execPromise(command) { return new Promise((resolve, reject) => { exec(command, (err, stdout, _stderr) => { - if (err) reject(err); - resolve(stdout); + if (err) { + reject(err); + } else { + resolve(stdout); + } }); }); } diff --git a/packages/schemas/package.json b/packages/schemas/package.json index a685697ea5bf..caff5d6f3da8 100644 --- a/packages/schemas/package.json +++ b/packages/schemas/package.json @@ -20,7 +20,7 @@ "@monkeytype/typescript-config": "workspace:*", "eslint": "8.57.1", "madge": "8.0.0", - "oxlint": "1.15.0", + "oxlint": "1.25.0", "tsup": "8.4.0", "typescript": "5.5.4", "vitest": "4.0.4" diff --git a/packages/tsup-config/package.json b/packages/tsup-config/package.json index a728007e0a68..601c9146fb7b 100644 --- a/packages/tsup-config/package.json +++ b/packages/tsup-config/package.json @@ -15,7 +15,7 @@ "devDependencies": { "@monkeytype/typescript-config": "workspace:*", "eslint": "8.57.1", - "oxlint": "1.15.0", + "oxlint": "1.25.0", "typescript": "5.5.4" }, "exports": { diff --git a/packages/util/package.json b/packages/util/package.json index ca21133bf747..8a22917dfcd9 100644 --- a/packages/util/package.json +++ b/packages/util/package.json @@ -16,7 +16,7 @@ "@monkeytype/typescript-config": "workspace:*", "eslint": "8.57.1", "madge": "8.0.0", - "oxlint": "1.15.0", + "oxlint": "1.25.0", "tsup": "8.4.0", "typescript": "5.5.4", "vitest": "4.0.4", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1f175f14d29b..60e6528f4bbc 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -39,8 +39,8 @@ importers: specifier: 1.2.1 version: 1.2.1 oxlint: - specifier: 1.15.0 - version: 1.15.0 + specifier: 1.25.0 + version: 1.25.0 prettier: specifier: 2.8.8 version: 2.8.8 @@ -244,8 +244,8 @@ importers: specifier: 2.0.2 version: 2.0.2 oxlint: - specifier: 1.15.0 - version: 1.15.0 + specifier: 1.25.0 + version: 1.25.0 readline-sync: specifier: 1.4.10 version: 1.4.10 @@ -446,8 +446,8 @@ importers: specifier: 8.0.1 version: 8.0.1 oxlint: - specifier: 1.15.0 - version: 1.15.0 + specifier: 1.25.0 + version: 1.25.0 postcss: specifier: 8.4.31 version: 8.4.31 @@ -474,7 +474,7 @@ importers: version: 1.2.1(rollup@2.79.2) vite-plugin-checker: specifier: 0.11.0 - version: 0.11.0(eslint@8.57.1)(meow@13.2.0)(optionator@0.9.4)(oxlint@1.15.0)(typescript@5.5.4)(vite@7.1.12(@types/node@24.9.1)(sass@1.70.0)(terser@5.44.0)(tsx@4.16.2)(yaml@2.8.1)) + version: 0.11.0(eslint@8.57.1)(meow@13.2.0)(optionator@0.9.4)(oxlint@1.25.0)(typescript@5.5.4)(vite@7.1.12(@types/node@24.9.1)(sass@1.70.0)(terser@5.44.0)(tsx@4.16.2)(yaml@2.8.1)) vite-plugin-filter-replace: specifier: 0.1.14 version: 0.1.14 @@ -522,8 +522,8 @@ importers: specifier: 8.0.0 version: 8.0.0(typescript@5.5.4) oxlint: - specifier: 1.15.0 - version: 1.15.0 + specifier: 1.25.0 + version: 1.25.0 tsup: specifier: 8.4.0 version: 8.4.0(postcss@8.5.6)(tsx@4.16.2)(typescript@5.5.4)(yaml@2.8.1) @@ -586,8 +586,8 @@ importers: specifier: 8.0.0 version: 8.0.0(typescript@5.5.4) oxlint: - specifier: 1.15.0 - version: 1.15.0 + specifier: 1.25.0 + version: 1.25.0 tsup: specifier: 8.4.0 version: 8.4.0(postcss@8.5.6)(tsx@4.16.2)(typescript@5.5.4)(yaml@2.8.1) @@ -622,8 +622,8 @@ importers: specifier: 3.1.4 version: 3.1.4 oxlint: - specifier: 1.15.0 - version: 1.15.0 + specifier: 1.25.0 + version: 1.25.0 packages/schemas: dependencies: @@ -647,8 +647,8 @@ importers: specifier: 8.0.0 version: 8.0.0(typescript@5.5.4) oxlint: - specifier: 1.15.0 - version: 1.15.0 + specifier: 1.25.0 + version: 1.25.0 tsup: specifier: 8.4.0 version: 8.4.0(postcss@8.5.6)(tsx@4.16.2)(typescript@5.5.4)(yaml@2.8.1) @@ -672,8 +672,8 @@ importers: specifier: 8.57.1 version: 8.57.1 oxlint: - specifier: 1.15.0 - version: 1.15.0 + specifier: 1.25.0 + version: 1.25.0 typescript: specifier: 5.5.4 version: 5.5.4 @@ -698,8 +698,8 @@ importers: specifier: 8.0.0 version: 8.0.0(typescript@5.5.4) oxlint: - specifier: 1.15.0 - version: 1.15.0 + specifier: 1.25.0 + version: 1.25.0 tsup: specifier: 8.4.0 version: 8.4.0(postcss@8.5.6)(tsx@4.16.2)(typescript@5.5.4)(yaml@2.8.1) @@ -2581,43 +2581,43 @@ packages: resolution: {integrity: sha512-aKcOkyrorBGlajjRdVoJWHTxfxO1vCNHLJVlSDaRHDIdjU+pX8IYQPvPDkYiujKLbRnWU+1TBwEt0QRgSm4SGA==} engines: {node: '>=14'} - '@oxlint/darwin-arm64@1.15.0': - resolution: {integrity: sha512-fwYg7WDKI6eAErREBGMXkIAOqBuBFN0LWbQJvVNXCGjywGxsisdwkHnNu4UG8IpHo4P71mUxf3l2xm+5Xiy+TA==} + '@oxlint/darwin-arm64@1.25.0': + resolution: {integrity: sha512-OLx4XyUv5SO7k8y5FzJIoTKan+iKK53T1Ws8fBIl4zblUIWI66ZIqSVG2A2rxOBA7XfINqCz8UipGzOW9yzKcg==} cpu: [arm64] os: [darwin] - '@oxlint/darwin-x64@1.15.0': - resolution: {integrity: sha512-RtaAmB6NZZx4hvjCg6w35shzRY5fLclbMsToC92MTZ9lMDF9LotzcbyNHCZ1tvZb1tNPObpIsuX16BFeElF8nw==} + '@oxlint/darwin-x64@1.25.0': + resolution: {integrity: sha512-srndNPiliA0rchYKqYfOdqA9kqyVQ6YChK3XJe9Lxo/YG8tTJ5K65g2A5SHTT2s1Nm5DnQa5AKZH7w+7KI/m8A==} cpu: [x64] os: [darwin] - '@oxlint/linux-arm64-gnu@1.15.0': - resolution: {integrity: sha512-8uV0lAbmqp93KTBlJWyCdQWuxTzLn+QrDRidUaCLJjn65uvv8KlRhZJoZoyLh17X6U/cgezYktWTMiMhxX56BA==} + '@oxlint/linux-arm64-gnu@1.25.0': + resolution: {integrity: sha512-W9+DnHDbygprpGV586BolwWES+o2raOcSJv404nOFPQjWZ09efG24nuXrg/fpyoMQb4YoW2W1fvlnyMVU+ADcw==} cpu: [arm64] os: [linux] - '@oxlint/linux-arm64-musl@1.15.0': - resolution: {integrity: sha512-/+hTqh1J29+2GitKrWUHIYjQBM1szWSJ1U7OzQlgL+Uvf8jxg4sn1nV79LcPMXhC2t8lZy5EOXOgwIh92DsdhQ==} + '@oxlint/linux-arm64-musl@1.25.0': + resolution: {integrity: sha512-1tIMpQhKlItm7uKzs3lluG7KorZR5ItoNKd1iFYF/IPmZ+i0/iuZ7MVWXRjBcgQMhMYSdfZpSVEdFKcFz2HDxA==} cpu: [arm64] os: [linux] - '@oxlint/linux-x64-gnu@1.15.0': - resolution: {integrity: sha512-GzeY3AhUd49yV+/76Gw0pjpwUJwxCkwYAJTNe7fFTdWjEQ6M6g8ZzJg5FKtUvgA5sMgmfzHhvSXxvT57YhcXnA==} + '@oxlint/linux-x64-gnu@1.25.0': + resolution: {integrity: sha512-xVkmk/zkIulc5o0OUWY04DyBfKotnq9+60O9I5c0DpdKAELVLhZkLmct0apx3jAX6Z/3yYPzhc6Lw1Ia3jU3VQ==} cpu: [x64] os: [linux] - '@oxlint/linux-x64-musl@1.15.0': - resolution: {integrity: sha512-p/7+juizUOCpGYreFmdfmIOSSSE3+JfsgnXnOHuP8mqlZfiOeXyevyajuXpPNRM60+k0reGvlV7ezp1iFitF7w==} + '@oxlint/linux-x64-musl@1.25.0': + resolution: {integrity: sha512-IeO10dZosJV58YzN0gckhRYac+FM9s5VCKUx2ghgbKR91z/bpSRcRl8Sy5cWTkcVwu3ZTikhK8aXC6j7XIqKNw==} cpu: [x64] os: [linux] - '@oxlint/win32-arm64@1.15.0': - resolution: {integrity: sha512-2LaDLOtCMq+lzIQ63Eir3UJV/hQNlw01xtsij2L8sSxt4gA+zWvubOQJQIOPGMDxEKFcWT1lo/6YEXX/sNnZDA==} + '@oxlint/win32-arm64@1.25.0': + resolution: {integrity: sha512-mpdiXZm2oNuSQAbTEPRDuSeR6v1DCD7Cl/xouR2ggHZu3AKZ4XYmm29hyrzIxrYVoQ/5j+182TGdOpGYn9xQJg==} cpu: [arm64] os: [win32] - '@oxlint/win32-x64@1.15.0': - resolution: {integrity: sha512-+jgRPpZrFIcrNxCVsDIy6HVCRpKVDN0DHD8VJodjrsDv6heqhq/qCTa2IXY3R4glWe1nWQ5JgdFKLn3Bl+aLNg==} + '@oxlint/win32-x64@1.25.0': + resolution: {integrity: sha512-opoIACOkcFloWQO6dubBLbcWwW52ML8+3deFdr0WE0PeM9UXdLB0jRMuLsEnplmBoy9TRvmxDJ+Pw8xc2PsOfQ==} cpu: [x64] os: [win32] @@ -3837,8 +3837,8 @@ packages: base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - baseline-browser-mapping@2.8.20: - resolution: {integrity: sha512-JMWsdF+O8Orq3EMukbUN1QfbLK9mX2CkUmQBcW2T0s8OmdAUL5LLM/6wFwSrqXzlXB13yhyK9gTKS1rIizOduQ==} + baseline-browser-mapping@2.8.21: + resolution: {integrity: sha512-JU0h5APyQNsHOlAM7HnQnPToSDQoEBZqzu/YBlqDnEeymPnZDREeXJA3KBMQee+dKteAxZ2AtvQEvVYdZf241Q==} hasBin: true basic-auth-connect@1.0.0: @@ -4040,8 +4040,8 @@ packages: caniuse-lite@1.0.30001715: resolution: {integrity: sha512-7ptkFGMm2OAOgvZpwgA4yjQ5SQbrNVGdRjzH0pBdy1Fasvcr+KAeECmbCAECzTuDuoX0FCY8KzUxjf9+9kfZEw==} - caniuse-lite@1.0.30001751: - resolution: {integrity: sha512-A0QJhug0Ly64Ii3eIqHu5X51ebln3k4yTUkY1j8drqpWHVreg/VLijN48cZ1bYPiqOQuqpkIKnzr/Ul8V+p6Cw==} + caniuse-lite@1.0.30001752: + resolution: {integrity: sha512-vKUk7beoukxE47P5gcVNKkDRzXdVofotshHwfR9vmpeFKxmI5PBpgOMC18LUJUA/DvJ70Y7RveasIBraqsyO/g==} canvas-confetti@1.5.1: resolution: {integrity: sha512-Ncz+oZJP6OvY7ti4E1slxVlyAV/3g7H7oQtcCDXgwGgARxPnwYY9PW5Oe+I8uvspYNtuHviAdgA0LfcKFWJfpg==} @@ -4871,8 +4871,8 @@ packages: electron-to-chromium@1.5.144: resolution: {integrity: sha512-eJIaMRKeAzxfBSxtjYnoIAw/tdD6VIH6tHBZepZnAbE3Gyqqs5mGN87DvcldPUbVkIljTK8pY0CMcUljP64lfQ==} - electron-to-chromium@1.5.240: - resolution: {integrity: sha512-OBwbZjWgrCOH+g6uJsA2/7Twpas2OlepS9uvByJjR2datRDuKGYeD+nP8lBBks2qnB7bGJNHDUx7c/YLaT3QMQ==} + electron-to-chromium@1.5.244: + resolution: {integrity: sha512-OszpBN7xZX4vWMPJwB9illkN/znA8M36GQqQxi6MNy9axWxhOfJyZZJtSLQCpEFLHP2xK33BiWx9aIuIEXVCcw==} electron-to-chromium@1.5.5: resolution: {integrity: sha512-QR7/A7ZkMS8tZuoftC/jfqNkZLQO779SSW3YuZHP4eXpj3EffGLFcB/Xu9AAZQzLccTiCV+EmUo3ha4mQ9wnlA==} @@ -7303,8 +7303,8 @@ packages: node-releases@2.0.19: resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==} - node-releases@2.0.26: - resolution: {integrity: sha512-S2M9YimhSjBSvYnlr5/+umAnPHE++ODwt5e2Ij6FoX45HA/s4vHdkDx1eax2pAPeAOqu4s9b7ppahsyEFdVqQA==} + node-releases@2.0.27: + resolution: {integrity: sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==} node-source-walk@7.0.0: resolution: {integrity: sha512-1uiY543L+N7Og4yswvlm5NCKgPKDEXd9AUR9Jh3gen6oOeBsesr6LqhXom1er3eRzSUcVRWXzhv8tSNrIfGHKw==} @@ -7509,12 +7509,12 @@ packages: resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==} engines: {node: '>= 0.4'} - oxlint@1.15.0: - resolution: {integrity: sha512-GZngkdF2FabM0pp0/l5OOhIQg+9L6LmOrmS8V8Vg+Swv9/VLJd/oc/LtAkv4HO45BNWL3EVaXzswI0CmGokVzw==} - engines: {node: '>=8.*'} + oxlint@1.25.0: + resolution: {integrity: sha512-O6iJ9xeuy9eQCi8/EghvsNO6lzSaUPs0FR1uLy51Exp3RkVpjvJKyPPhd9qv65KLnfG/BNd2HE/rH0NbEfVVzA==} + engines: {node: ^20.19.0 || >=22.12.0} hasBin: true peerDependencies: - oxlint-tsgolint: '>=0.2.0' + oxlint-tsgolint: '>=0.4.0' peerDependenciesMeta: oxlint-tsgolint: optional: true @@ -12089,28 +12089,28 @@ snapshots: '@opentelemetry/semantic-conventions@1.34.0': {} - '@oxlint/darwin-arm64@1.15.0': + '@oxlint/darwin-arm64@1.25.0': optional: true - '@oxlint/darwin-x64@1.15.0': + '@oxlint/darwin-x64@1.25.0': optional: true - '@oxlint/linux-arm64-gnu@1.15.0': + '@oxlint/linux-arm64-gnu@1.25.0': optional: true - '@oxlint/linux-arm64-musl@1.15.0': + '@oxlint/linux-arm64-musl@1.25.0': optional: true - '@oxlint/linux-x64-gnu@1.15.0': + '@oxlint/linux-x64-gnu@1.25.0': optional: true - '@oxlint/linux-x64-musl@1.15.0': + '@oxlint/linux-x64-musl@1.25.0': optional: true - '@oxlint/win32-arm64@1.15.0': + '@oxlint/win32-arm64@1.25.0': optional: true - '@oxlint/win32-x64@1.15.0': + '@oxlint/win32-x64@1.25.0': optional: true '@paralleldrive/cuid2@2.2.2': @@ -13449,7 +13449,7 @@ snapshots: base64-js@1.5.1: {} - baseline-browser-mapping@2.8.20: {} + baseline-browser-mapping@2.8.21: {} basic-auth-connect@1.0.0: {} @@ -13586,10 +13586,10 @@ snapshots: browserslist@4.27.0: dependencies: - baseline-browser-mapping: 2.8.20 - caniuse-lite: 1.0.30001751 - electron-to-chromium: 1.5.240 - node-releases: 2.0.26 + baseline-browser-mapping: 2.8.21 + caniuse-lite: 1.0.30001752 + electron-to-chromium: 1.5.244 + node-releases: 2.0.27 update-browserslist-db: 1.1.4(browserslist@4.27.0) bson@6.8.0: {} @@ -13717,7 +13717,7 @@ snapshots: caniuse-lite@1.0.30001715: {} - caniuse-lite@1.0.30001751: {} + caniuse-lite@1.0.30001752: {} canvas-confetti@1.5.1: {} @@ -14566,7 +14566,7 @@ snapshots: electron-to-chromium@1.5.144: {} - electron-to-chromium@1.5.240: {} + electron-to-chromium@1.5.244: {} electron-to-chromium@1.5.5: {} @@ -17732,7 +17732,7 @@ snapshots: node-releases@2.0.19: {} - node-releases@2.0.26: {} + node-releases@2.0.27: {} node-source-walk@7.0.0: dependencies: @@ -17990,16 +17990,16 @@ snapshots: object-keys: 1.1.1 safe-push-apply: 1.0.0 - oxlint@1.15.0: + oxlint@1.25.0: optionalDependencies: - '@oxlint/darwin-arm64': 1.15.0 - '@oxlint/darwin-x64': 1.15.0 - '@oxlint/linux-arm64-gnu': 1.15.0 - '@oxlint/linux-arm64-musl': 1.15.0 - '@oxlint/linux-x64-gnu': 1.15.0 - '@oxlint/linux-x64-musl': 1.15.0 - '@oxlint/win32-arm64': 1.15.0 - '@oxlint/win32-x64': 1.15.0 + '@oxlint/darwin-arm64': 1.25.0 + '@oxlint/darwin-x64': 1.25.0 + '@oxlint/linux-arm64-gnu': 1.25.0 + '@oxlint/linux-arm64-musl': 1.25.0 + '@oxlint/linux-x64-gnu': 1.25.0 + '@oxlint/linux-x64-musl': 1.25.0 + '@oxlint/win32-arm64': 1.25.0 + '@oxlint/win32-x64': 1.25.0 p-defer@3.0.0: {} @@ -20242,7 +20242,7 @@ snapshots: dependencies: vite: 7.1.12(@types/node@24.9.1)(sass@1.70.0)(terser@5.44.0)(tsx@4.16.2)(yaml@2.8.1) - vite-plugin-checker@0.11.0(eslint@8.57.1)(meow@13.2.0)(optionator@0.9.4)(oxlint@1.15.0)(typescript@5.5.4)(vite@7.1.12(@types/node@24.9.1)(sass@1.70.0)(terser@5.44.0)(tsx@4.16.2)(yaml@2.8.1)): + vite-plugin-checker@0.11.0(eslint@8.57.1)(meow@13.2.0)(optionator@0.9.4)(oxlint@1.25.0)(typescript@5.5.4)(vite@7.1.12(@types/node@24.9.1)(sass@1.70.0)(terser@5.44.0)(tsx@4.16.2)(yaml@2.8.1)): dependencies: '@babel/code-frame': 7.27.1 chokidar: 4.0.3 @@ -20257,7 +20257,7 @@ snapshots: eslint: 8.57.1 meow: 13.2.0 optionator: 0.9.4 - oxlint: 1.15.0 + oxlint: 1.25.0 typescript: 5.5.4 vite-plugin-filter-replace@0.1.14: From c0191da004d5374dcf8c5609aabcfde618af8aac Mon Sep 17 00:00:00 2001 From: Miodec Date: Fri, 31 Oct 2025 14:15:12 +0100 Subject: [PATCH 3/4] chore: bump node version --- .github/workflows/monkey-ci.yml | 2 +- .github/workflows/pretty-check.yml | 2 +- .github/workflows/pretty-fix.yml | 2 +- .nvmrc | 2 +- backend/docker/compose.yml | 2 +- backend/package.json | 2 +- docker/backend/Dockerfile | 4 ++-- docker/frontend/Dockerfile | 2 +- docs/CONTRIBUTING_ADVANCED.md | 6 +++--- frontend/docker/compose.dev.yml | 2 +- frontend/package.json | 2 +- package.json | 2 +- 12 files changed, 15 insertions(+), 15 deletions(-) diff --git a/.github/workflows/monkey-ci.yml b/.github/workflows/monkey-ci.yml index d86fe4352310..97009f04ddab 100644 --- a/.github/workflows/monkey-ci.yml +++ b/.github/workflows/monkey-ci.yml @@ -2,7 +2,7 @@ name: Monkey CI env: PNPM_VERSION: "9.6.0" - NODE_VERSION: "24.10.0" + NODE_VERSION: "24.11.0" RECAPTCHA_SITE_KEY: "6Lc-V8McAAAAAJ7s6LGNe7MBZnRiwbsbiWts87aj" permissions: diff --git a/.github/workflows/pretty-check.yml b/.github/workflows/pretty-check.yml index 0d4ec626bda3..6d76cf6660c7 100644 --- a/.github/workflows/pretty-check.yml +++ b/.github/workflows/pretty-check.yml @@ -2,7 +2,7 @@ name: Prettier Check env: PNPM_VERSION: "9.6.0" - NODE_VERSION: "24.10.0" + NODE_VERSION: "24.11.0" on: pull_request: diff --git a/.github/workflows/pretty-fix.yml b/.github/workflows/pretty-fix.yml index 609115289e1f..23c7eea0a855 100644 --- a/.github/workflows/pretty-fix.yml +++ b/.github/workflows/pretty-fix.yml @@ -2,7 +2,7 @@ name: Prettier Fix env: PNPM_VERSION: "9.6.0" - NODE_VERSION: "24.10.0" + NODE_VERSION: "24.11.0" permissions: contents: write diff --git a/.nvmrc b/.nvmrc index a03e161f1c93..40115e966fb5 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -24.10.0 \ No newline at end of file +24.11.0 \ No newline at end of file diff --git a/backend/docker/compose.yml b/backend/docker/compose.yml index b7e4fc9193c7..cb0e1763fd90 100644 --- a/backend/docker/compose.yml +++ b/backend/docker/compose.yml @@ -23,7 +23,7 @@ services: container_name: monkeytype-api-server build: dockerfile_inline: | - FROM node:24.10.0 + FROM node:24.11.0 RUN npm i -g pnpm@9.6.0 RUN mkdir /pnpm-store && chown -R 1000:1000 /pnpm-store user: "node" ##this works as long as your local user has uid=1000 diff --git a/backend/package.json b/backend/package.json index 76c338322149..6bd26e3c7b9c 100644 --- a/backend/package.json +++ b/backend/package.json @@ -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.10.0" + "node": "24.11.0" }, "dependencies": { "@date-fns/utc": "1.2.0", diff --git a/docker/backend/Dockerfile b/docker/backend/Dockerfile index 614ca0f56f8c..4180d247e8a9 100644 --- a/docker/backend/Dockerfile +++ b/docker/backend/Dockerfile @@ -1,4 +1,4 @@ -FROM node:24.10.0-alpine3.22 AS builder +FROM node:24.11.0-alpine3.22 AS builder WORKDIR /app @@ -18,7 +18,7 @@ RUN pnpm deploy --filter backend --prod /prod/backend #--------------------------------- ## target image -FROM node:24.10.0-alpine3.22 +FROM node:24.11.0-alpine3.22 ## get server_version from build-arg, default to UNKNOWN ARG server_version=UNKNOWN diff --git a/docker/frontend/Dockerfile b/docker/frontend/Dockerfile index 7b7ff5246266..4af1d3b73fe4 100644 --- a/docker/frontend/Dockerfile +++ b/docker/frontend/Dockerfile @@ -1,4 +1,4 @@ -FROM node:24.10.0-alpine3.22 AS builder +FROM node:24.11.0-alpine3.22 AS builder WORKDIR /app #ENV diff --git a/docs/CONTRIBUTING_ADVANCED.md b/docs/CONTRIBUTING_ADVANCED.md index 89e2f3587172..88f7a8e1a643 100644 --- a/docs/CONTRIBUTING_ADVANCED.md +++ b/docs/CONTRIBUTING_ADVANCED.md @@ -21,7 +21,7 @@ ## Prerequisites -This contribution guide is for cases in which you need to test the functionality of your changes, or if you need to take screenshots of your changes. You will need a computer with a stable internet connection, a text editor, Git, and NodeJS with version 24.10.0. There are some additional requirements depending on what you're looking to contribute, such as Firebase for authentication, and Mongo and Docker for the backend. Read the below sections to understand how to set up each of these tools. +This contribution guide is for cases in which you need to test the functionality of your changes, or if you need to take screenshots of your changes. You will need a computer with a stable internet connection, a text editor, Git, and NodeJS with version 24.11.0. There are some additional requirements depending on what you're looking to contribute, such as Firebase for authentication, and Mongo and Docker for the backend. Read the below sections to understand how to set up each of these tools. ### Git @@ -33,9 +33,9 @@ Git is optional but we recommend you utilize it. Monkeytype uses the Git source ### NodeJS and PNPM -Currently, the project is using version `24.10.0 LTS`. +Currently, the project is using version `24.11.0 LTS`. -If you use `nvm` (if you use Windows, use [nvm-windows](https://github.com/coreybutler/nvm-windows)) then you can run `nvm install` and `nvm use` (you might need to specify the exact version eg: `nvm install 24.10.0` then `nvm use 24.10.0`) to use the version of Node.js in the `.nvmrc` file. +If you use `nvm` (if you use Windows, use [nvm-windows](https://github.com/coreybutler/nvm-windows)) then you can run `nvm install` and `nvm use` (you might need to specify the exact version eg: `nvm install 24.11.0` then `nvm use 24.11.0`) to use the version of Node.js in the `.nvmrc` file. Alternatively, you can navigate to the NodeJS [website](https://nodejs.org/en/) to download it from there. diff --git a/frontend/docker/compose.dev.yml b/frontend/docker/compose.dev.yml index 1c760c10c96f..ade3163931ed 100644 --- a/frontend/docker/compose.dev.yml +++ b/frontend/docker/compose.dev.yml @@ -4,7 +4,7 @@ services: container_name: monkeytype-frontend build: dockerfile_inline: | - FROM node:24.10.0 + FROM node:24.11.0 RUN npm i -g pnpm@9.6.0 RUN mkdir /pnpm-store && chown -R 1000:1000 /pnpm-store user: "node" ##this works as long as your local user has uid=1000 diff --git a/frontend/package.json b/frontend/package.json index 4f38f1b37ab9..48cdc81b6a28 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -24,7 +24,7 @@ "docker": "docker compose -f docker/compose.dev.yml up" }, "engines": { - "node": "24.10.0" + "node": "24.11.0" }, "browserslist": [ "defaults", diff --git a/package.json b/package.json index f7e06b964509..315d71bea6bf 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,7 @@ "knip": "knip" }, "engines": { - "node": "24.10.0" + "node": "24.11.0" }, "devDependencies": { "@commitlint/cli": "17.7.1", From ffd55c532c7514097d6850c3ff32284134abf97f Mon Sep 17 00:00:00 2001 From: Rajyavardhan Singh <132651154+imrajyavardhan12@users.noreply.github.com> Date: Fri, 31 Oct 2025 20:27:03 +0530 Subject: [PATCH 4/4] feat: add custom character generator to custom text modal (@imrajyavardhan12) (#7037) - Add new "custom generator" button to custom text modal - Create generator modal with character input and presets - Support min/max word length and word count configuration - Include presets for alphas, numbers, symbols, bigrams, trigrams - Add code-specific patterns for programming practice Closes #6941 ### Description Adds a custom character generator to the custom text modal, allowing users to generate random "words" from a custom set of characters or strings. Useful for practicing specific character combinations, especially for programmers who want to improve typing speed with symbols and patterns commonly used in code. ### Testing 1. Open custom text modal 2. Click "custom generator" 3. Try presets or enter custom characters 4. Adjust word length and count 5. Click "Set" or "Add" --------- Co-authored-by: Amp Co-authored-by: Miodec --- frontend/src/html/popups.html | 81 +++++++- frontend/src/styles/media-queries-blue.scss | 7 + frontend/src/styles/media-queries-green.scss | 1 + frontend/src/styles/media-queries-yellow.scss | 6 +- frontend/src/styles/popups.scss | 89 ++++++++- frontend/src/ts/modals/custom-generator.ts | 184 ++++++++++++++++++ frontend/src/ts/modals/custom-text.ts | 8 + 7 files changed, 365 insertions(+), 11 deletions(-) create mode 100644 frontend/src/ts/modals/custom-generator.ts diff --git a/frontend/src/html/popups.html b/frontend/src/html/popups.html index d74cd8989c77..631f5f44194f 100644 --- a/frontend/src/html/popups.html +++ b/frontend/src/html/popups.html @@ -486,6 +486,8 @@ saved texts + +
+
+ + custom generator +
- +
@@ -772,6 +778,79 @@
+