From 95c126f2c68fa1c9ffbe4f321c00506c61470c9e Mon Sep 17 00:00:00 2001 From: Marius Starke <72494359+marius-arch@users.noreply.github.com> Date: Tue, 5 Nov 2024 09:54:27 +0100 Subject: [PATCH 1/5] fix: remove several occurrences of translation file prefix (#2188) Co-authored-by: BuildTools --- .vscode/settings.json | 2 +- src/widgets/dnshole/TimerModal.tsx | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 9a066dae06d..025acb66238 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -11,7 +11,7 @@ "layout.manage.navigation.**", ], "editor.codeActionsOnSave": { - "source.organizeImports": true + "source.organizeImports": "explicit" }, "typescript.tsdk": "node_modules/typescript/lib", "explorer.fileNesting.patterns": { diff --git a/src/widgets/dnshole/TimerModal.tsx b/src/widgets/dnshole/TimerModal.tsx index 2ae41350227..f4f178c6e12 100644 --- a/src/widgets/dnshole/TimerModal.tsx +++ b/src/widgets/dnshole/TimerModal.tsx @@ -41,12 +41,12 @@ export function TimerModal({ toggleDns, getDnsStatus, opened, close, appId }: Ti setHours(0); setMinutes(0); }} - title={t('modules/dns-hole-controls:durationModal.title')} + title={t('durationModal.title')} > - {t('modules/dns-hole-controls:durationModal.hours')} + {t('durationModal.hours')} - {t('modules/dns-hole-controls:durationModal.minutes')} + {t('durationModal.minutes')} - {t('modules/dns-hole-controls:durationModal.unlimited')} + {t('durationModal.unlimited')} From b59921b843e6da824f9f7779c66ab1ca5460332d Mon Sep 17 00:00:00 2001 From: TyxTang <90897955+TyxTang@users.noreply.github.com> Date: Thu, 28 Nov 2024 05:17:48 +0800 Subject: [PATCH 2/5] fix: Fix Jellyseerr Avatar Loading Issue (#2197) fix: Fix Jellyseerr Avatar Loading Issue feat: Add Fallback Image. --- src/server/api/routers/media-request.ts | 6 ++++-- .../media-requests/MediaRequestListTile.tsx | 14 +++++++++----- .../media-requests/MediaRequestStatsTile.tsx | 5 ++++- src/widgets/media-requests/media-request-types.tsx | 2 ++ 4 files changed, 19 insertions(+), 8 deletions(-) diff --git a/src/server/api/routers/media-request.ts b/src/server/api/routers/media-request.ts index 43c6cf22043..fe246c472f5 100644 --- a/src/server/api/routers/media-request.ts +++ b/src/server/api/routers/media-request.ts @@ -58,6 +58,7 @@ export const mediaRequestsRouter = createTRPCRouter({ name: genericItem.name, userName: item.requestedBy.displayName, userProfilePicture: constructAvatarUrl(appUrl, item.requestedBy.avatar), + fallbackUserProfilePicture: constructAvatarUrl(appUrl, item.requestedBy.avatar,'avatarproxy'), userLink: `${appUrl}/users/${item.requestedBy.id}`, userRequestCount: item.requestedBy.requestCount, airDate: genericItem.airDate, @@ -119,6 +120,7 @@ export const mediaRequestsRouter = createTRPCRouter({ id: user.id, userName: user.displayName, userProfilePicture: constructAvatarUrl(appUrl, user.avatar), + fallbackUserProfilePicture: constructAvatarUrl(appUrl, user.avatar,'avatarproxy'), userLink: `${appUrl}/users/${user.id}`, userRequestCount: user.requestCount, }; @@ -137,14 +139,14 @@ export const mediaRequestsRouter = createTRPCRouter({ }), }); -const constructAvatarUrl = (appUrl: string, avatar: string) => { +const constructAvatarUrl = (appUrl: string, avatar: string, path?: string) => { const isAbsolute = avatar.startsWith('http://') || avatar.startsWith('https://'); if (isAbsolute) { return avatar; } - return `${appUrl}/${avatar}`; + return `${appUrl}/${path?.concat("/") ?? "" }${avatar}`; }; const retrieveDetailsForItem = async ( diff --git a/src/widgets/media-requests/MediaRequestListTile.tsx b/src/widgets/media-requests/MediaRequestListTile.tsx index d83e625fc40..4a99ad8e229 100644 --- a/src/widgets/media-requests/MediaRequestListTile.tsx +++ b/src/widgets/media-requests/MediaRequestListTile.tsx @@ -11,6 +11,7 @@ import { Stack, Text, Tooltip, + Avatar, useMantineTheme, } from '@mantine/core'; import { notifications } from '@mantine/notifications'; @@ -170,14 +171,17 @@ function MediaRequestListTile({ widget }: MediaRequestListWidgetProps) { - requester avatar + > + requester avatar + )} - + + user avatar + {user.userName} diff --git a/src/widgets/media-requests/media-request-types.tsx b/src/widgets/media-requests/media-request-types.tsx index e15711bff8b..12d61e78e11 100644 --- a/src/widgets/media-requests/media-request-types.tsx +++ b/src/widgets/media-requests/media-request-types.tsx @@ -7,6 +7,7 @@ export type MediaRequest = { name: string; userName: string; userProfilePicture: string; + fallbackUserProfilePicture: string; userLink: string; userRequestCount: number; airDate?: string; @@ -22,6 +23,7 @@ export type Users = { id: number; userName: string; userProfilePicture: string; + fallbackUserProfilePicture: string; userLink: string; userRequestCount: number; }; From 31a7559b86c421fb4d8d7c168aa1915807829a1c Mon Sep 17 00:00:00 2001 From: Meier Lukas Date: Sat, 7 Dec 2024 22:21:40 +0100 Subject: [PATCH 3/5] fix: two issues with board rename and iframes (#2215) --- package.json | 2 +- src/server/api/routers/board.ts | 64 ++++++++++++++++++------------- src/validations/boards.ts | 11 +++++- src/widgets/iframe/IFrameTile.tsx | 1 + 4 files changed, 48 insertions(+), 30 deletions(-) diff --git a/package.json b/package.json index bab2389e3fb..cf60568f2ef 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "homarr", - "version": "0.15.7", + "version": "0.15.8", "description": "Homarr - A homepage for your server.", "license": "MIT", "repository": { diff --git a/src/server/api/routers/board.ts b/src/server/api/routers/board.ts index 7426e763dd6..7971531c230 100644 --- a/src/server/api/routers/board.ts +++ b/src/server/api/routers/board.ts @@ -1,29 +1,33 @@ import { TRPCError } from '@trpc/server'; +import Consola from 'consola'; import fs from 'fs'; import { z } from 'zod'; -import Consola from 'consola'; import { getDefaultBoardAsync } from '~/server/db/queries/userSettings'; import { configExists } from '~/tools/config/configExists'; import { getConfig } from '~/tools/config/getConfig'; import { getFrontendConfig } from '~/tools/config/getFrontendConfig'; +import { writeConfig } from '~/tools/config/writeConfig'; import { generateDefaultApp } from '~/tools/shared/app'; +import { configNameSchema } from '~/validations/boards'; import { adminProcedure, createTRPCRouter, protectedProcedure } from '../trpc'; -import { writeConfig } from '~/tools/config/writeConfig'; -import { configNameSchema } from '~/validations/boards'; export const boardRouter = createTRPCRouter({ all: protectedProcedure .meta({ openapi: { method: 'GET', path: '/boards/all', tags: ['board'] } }) .input(z.void()) - .output(z.array(z.object({ - name: z.string(), - allowGuests: z.boolean(), - countApps: z.number().min(0), - countWidgets: z.number().min(0), - countCategories: z.number().min(0), - isDefaultForUser: z.boolean(), - }))) + .output( + z.array( + z.object({ + name: z.string(), + allowGuests: z.boolean(), + countApps: z.number().min(0), + countWidgets: z.number().min(0), + countCategories: z.number().min(0), + isDefaultForUser: z.boolean(), + }) + ) + ) .query(async ({ ctx }) => { const files = fs.readdirSync('./data/configs').filter((file) => file.endsWith('.json')); @@ -44,7 +48,7 @@ export const boardRouter = createTRPCRouter({ countCategories: config.categories.length, isDefaultForUser: name === defaultBoard, }; - }), + }) ); }), addAppsForContainers: adminProcedure @@ -58,9 +62,9 @@ export const boardRouter = createTRPCRouter({ name: z.string(), icon: z.string().optional(), port: z.number().optional(), - }), + }) ), - }), + }) ) .mutation(async ({ input }) => { if (!configExists(input.boardName)) { @@ -101,12 +105,14 @@ export const boardRouter = createTRPCRouter({ const targetPath = `data/configs/${input.boardName}.json`; fs.writeFileSync(targetPath, JSON.stringify(newConfig, null, 2), 'utf8'); }), - renameBoard: protectedProcedure + renameBoard: adminProcedure .meta({ openapi: { method: 'PUT', path: '/boards/rename', tags: ['board'] } }) - .input(z.object({ - oldName: z.string(), - newName: z.string().min(1), - })) + .input( + z.object({ + oldName: configNameSchema, + newName: configNameSchema, + }) + ) .output(z.void()) .mutation(async ({ input }) => { if (input.oldName === 'default') { @@ -141,15 +147,19 @@ export const boardRouter = createTRPCRouter({ fs.unlinkSync(targetPath); Consola.info(`Deleted ${input.oldName} from file system`); }), - duplicateBoard: protectedProcedure + duplicateBoard: adminProcedure .meta({ openapi: { method: 'POST', path: '/boards/duplicate', tags: ['board'] } }) - .input(z.object({ - boardName: z.string(), - })) + .input( + z.object({ + boardName: z.string(), + }) + ) .output(z.void()) .mutation(async ({ input }) => { if (!configExists(input.boardName)) { - Consola.error(`Tried to duplicate ${input.boardName} but this configuration does not exist.`); + Consola.error( + `Tried to duplicate ${input.boardName} but this configuration does not exist.` + ); throw new TRPCError({ code: 'NOT_FOUND', message: 'Board not found', @@ -164,7 +174,7 @@ export const boardRouter = createTRPCRouter({ config.configProperties.name = targetName; writeConfig(config); - Consola.info(`Wrote config to name '${targetName}'`) + Consola.info(`Wrote config to name '${targetName}'`); }), }); @@ -185,7 +195,7 @@ const attemptGenerateDuplicateName = (baseName: string, maxAttempts: number) => code: 'CONFLICT', message: 'Board conflicts with an existing board', }); -} +}; const generateDuplicateName = (baseName: string, increment: number) => { const result = duplicationName.exec(baseName); @@ -197,4 +207,4 @@ const generateDuplicateName = (baseName: string, increment: number) => { } return `${baseName} (2)`; -} +}; diff --git a/src/validations/boards.ts b/src/validations/boards.ts index be3347cc1a1..b66f2eb7ddc 100644 --- a/src/validations/boards.ts +++ b/src/validations/boards.ts @@ -1,8 +1,15 @@ import { DEFAULT_THEME, MANTINE_COLORS, MantineColor } from '@mantine/core'; import { z } from 'zod'; -import { BackgroundImageAttachment, BackgroundImageRepeat, BackgroundImageSize } from '~/types/settings'; +import { + BackgroundImageAttachment, + BackgroundImageRepeat, + BackgroundImageSize, +} from '~/types/settings'; -export const configNameSchema = z.string().regex(/^[a-zA-Z0-9-_\s()]+$/); +export const configNameSchema = z + .string() + .regex(/^[a-zA-Z0-9-_\s()]+$/) + .min(1); export const createBoardSchemaValidation = z.object({ name: configNameSchema, diff --git a/src/widgets/iframe/IFrameTile.tsx b/src/widgets/iframe/IFrameTile.tsx index 86b32c89c1b..ab3f1790d71 100644 --- a/src/widgets/iframe/IFrameTile.tsx +++ b/src/widgets/iframe/IFrameTile.tsx @@ -116,6 +116,7 @@ function IFrameTile({ widget }: IFrameTileProps) { return (