diff --git a/.env.example b/.env.example index 3bc94ce26..fbc491bae 100644 --- a/.env.example +++ b/.env.example @@ -12,6 +12,8 @@ AUTH_SECRET="supersecret" # or starting the project without any (which will show a randomly generated one). SECRET_ENCRYPTION_KEY=0000000000000000000000000000000000000000000000000000000000000000 +LOG_LEVEL='info' + # This is how you can use the sqlite driver: DB_DRIVER='better-sqlite3' DB_URL='FULL_PATH_TO_YOUR_SQLITE_DB_FILE' diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 1bd9ef399..7b1ad9bc7 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -31,6 +31,7 @@ body: label: Version description: What version of Homarr are you running? options: + - 1.6.0 - 1.5.0 - 1.4.0 - 1.3.1 diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index b551590ab..ccbf05db3 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -6,7 +6,7 @@ **Thank you for your contribution. Please ensure that your pull request meets the following pull request:** -- [ ] Builds without warnings or errors (``pnpm buid``, autofix with ``pnpm format:fix``) +- [ ] Builds without warnings or errors (``pnpm build``, autofix with ``pnpm format:fix``) - [ ] Pull request targets ``dev`` branch - [ ] Commits follow the [conventional commits guideline](https://www.conventionalcommits.org/en/v1.0.0/) - [ ] No shorthand variable names are used (eg. ``x``, ``y``, ``i`` or any abbrevation) diff --git a/.github/workflows/deployment-docker-image.yml b/.github/workflows/deployment-docker-image.yml index ab7ef7e1b..fb2fa4fcd 100644 --- a/.github/workflows/deployment-docker-image.yml +++ b/.github/workflows/deployment-docker-image.yml @@ -96,10 +96,11 @@ jobs: run: | git config user.name "Releases Homarr" git config user.email "175486441+homarr-releases[bot]@users.noreply.github.com" + git remote set-url origin https://x-access-token:${{ steps.obtainToken.outputs.token }}@github.com/${{ github.repository }}.git git fetch origin dev git checkout dev git pull origin dev - git merge ${{ github.ref_name }} + git rebase ${{ github.ref_name }} git push origin dev deploy: name: Deploy docker image diff --git a/apps/nextjs/next.config.ts b/apps/nextjs/next.config.ts index 53148f725..a8a022a60 100644 --- a/apps/nextjs/next.config.ts +++ b/apps/nextjs/next.config.ts @@ -2,14 +2,13 @@ import "@homarr/auth/env"; import "@homarr/db/env"; import "@homarr/common/env"; +import "@homarr/log/env"; import "@homarr/docker/env"; import type { NextConfig } from "next"; import MillionLint from "@million/lint"; import createNextIntlPlugin from "next-intl/plugin"; -import "./src/env.ts"; - // Package path does not work... so we need to use relative path const withNextIntl = createNextIntlPlugin("../../packages/translation/src/request.ts"); diff --git a/apps/nextjs/package.json b/apps/nextjs/package.json index eb325613a..030404136 100644 --- a/apps/nextjs/package.json +++ b/apps/nextjs/package.json @@ -15,6 +15,10 @@ }, "prettier": "@homarr/prettier-config", "dependencies": { + "@dnd-kit/core": "^6.3.1", + "@dnd-kit/modifiers": "^9.0.0", + "@dnd-kit/sortable": "^10.0.0", + "@dnd-kit/utilities": "^3.2.2", "@homarr/analytics": "workspace:^0.1.0", "@homarr/api": "workspace:^0.1.0", "@homarr/auth": "workspace:^0.1.0", @@ -26,6 +30,7 @@ "@homarr/definitions": "workspace:^0.1.0", "@homarr/docker": "workspace:^0.1.0", "@homarr/form": "workspace:^0.1.0", + "@homarr/forms-collection": "workspace:^0.1.0", "@homarr/gridstack": "^1.12.0", "@homarr/icons": "workspace:^0.1.0", "@homarr/integrations": "workspace:^0.1.0", @@ -43,18 +48,17 @@ "@homarr/ui": "workspace:^0.1.0", "@homarr/validation": "workspace:^0.1.0", "@homarr/widgets": "workspace:^0.1.0", - "@mantine/colors-generator": "^7.16.3", - "@mantine/core": "^7.16.3", - "@mantine/dropzone": "^7.16.3", - "@mantine/hooks": "^7.16.3", - "@mantine/modals": "^7.16.3", - "@mantine/tiptap": "^7.16.3", + "@mantine/colors-generator": "^7.17.0", + "@mantine/core": "^7.17.0", + "@mantine/dropzone": "^7.17.0", + "@mantine/hooks": "^7.17.0", + "@mantine/modals": "^7.17.0", + "@mantine/tiptap": "^7.17.0", "@million/lint": "1.0.14", - "@t3-oss/env-nextjs": "^0.12.0", "@tabler/icons-react": "^3.30.0", - "@tanstack/react-query": "^5.66.0", - "@tanstack/react-query-devtools": "^5.66.0", - "@tanstack/react-query-next-experimental": "^5.66.0", + "@tanstack/react-query": "^5.66.9", + "@tanstack/react-query-devtools": "^5.66.9", + "@tanstack/react-query-next-experimental": "^5.66.9", "@trpc/client": "next", "@trpc/next": "next", "@trpc/react-query": "next", @@ -68,8 +72,8 @@ "dotenv": "^16.4.7", "flag-icons": "^7.3.2", "glob": "^11.0.1", - "jotai": "^2.12.0", - "mantine-react-table": "2.0.0-beta.8", + "jotai": "^2.12.1", + "mantine-react-table": "2.0.0-beta.9", "next": "15.1.7", "postcss-preset-mantine": "^1.17.0", "prismjs": "^1.29.0", @@ -79,7 +83,7 @@ "react-simple-code-editor": "^0.14.1", "sass": "^1.85.0", "superjson": "2.2.2", - "swagger-ui-react": "^5.18.3", + "swagger-ui-react": "^5.19.0", "use-deep-compare-effect": "^1.8.1", "zod": "^3.24.2" }, @@ -90,13 +94,13 @@ "@types/chroma-js": "3.1.1", "@types/node": "^22.13.4", "@types/prismjs": "^1.26.5", - "@types/react": "19.0.8", - "@types/react-dom": "19.0.3", + "@types/react": "19.0.10", + "@types/react-dom": "19.0.4", "@types/swagger-ui-react": "^5.18.0", "concurrently": "^9.1.2", "eslint": "^9.20.1", "node-loader": "^2.1.0", - "prettier": "^3.4.2", + "prettier": "^3.5.1", "typescript": "^5.7.3" } } diff --git a/apps/nextjs/src/app/[locale]/_client-providers/trpc.tsx b/apps/nextjs/src/app/[locale]/_client-providers/trpc.tsx index 456c09a99..a46595b23 100644 --- a/apps/nextjs/src/app/[locale]/_client-providers/trpc.tsx +++ b/apps/nextjs/src/app/[locale]/_client-providers/trpc.tsx @@ -20,8 +20,7 @@ import type { SuperJSONResult } from "superjson"; import type { AppRouter } from "@homarr/api"; import { clientApi } from "@homarr/api/client"; import { createHeadersCallbackForSource, getTrpcUrl } from "@homarr/api/shared"; - -import { env } from "~/env"; +import { env } from "@homarr/common/env"; const getWebSocketProtocol = () => { // window is not defined on server side @@ -66,7 +65,7 @@ export function TRPCReactProvider(props: PropsWithChildren) { links: [ loggerLink({ enabled: (opts) => - process.env.NODE_ENV === "development" || (opts.direction === "down" && opts.result instanceof Error), + env.NODE_ENV === "development" || (opts.direction === "down" && opts.result instanceof Error), }), splitLink({ condition: ({ type }) => type === "subscription", diff --git a/apps/nextjs/src/app/[locale]/boards/(content)/_header-actions.tsx b/apps/nextjs/src/app/[locale]/boards/(content)/_header-actions.tsx index e4029bd3a..6b3153b46 100644 --- a/apps/nextjs/src/app/[locale]/boards/(content)/_header-actions.tsx +++ b/apps/nextjs/src/app/[locale]/boards/(content)/_header-actions.tsx @@ -23,6 +23,7 @@ import { clientApi } from "@homarr/api/client"; import { useRequiredBoard } from "@homarr/boards/context"; import { useEditMode } from "@homarr/boards/edit-mode"; import { revalidatePathActionAsync } from "@homarr/common/client"; +import { env } from "@homarr/common/env"; import { useConfirmModal, useModalAction } from "@homarr/modals"; import { showErrorNotification, showSuccessNotification } from "@homarr/notifications"; import { useI18n, useScopedI18n } from "@homarr/translation/client"; @@ -33,7 +34,6 @@ import { useCategoryActions } from "~/components/board/sections/category/categor import { CategoryEditModal } from "~/components/board/sections/category/category-edit-modal"; import { useDynamicSectionActions } from "~/components/board/sections/dynamic/dynamic-actions"; import { HeaderButton } from "~/components/layout/header/button"; -import { env } from "~/env"; export const BoardContentHeaderActions = () => { const [isEditMode] = useEditMode(); diff --git a/apps/nextjs/src/app/[locale]/boards/(content)/_theme.tsx b/apps/nextjs/src/app/[locale]/boards/(content)/_theme.tsx index bde65aa42..76d68a6b3 100644 --- a/apps/nextjs/src/app/[locale]/boards/(content)/_theme.tsx +++ b/apps/nextjs/src/app/[locale]/boards/(content)/_theme.tsx @@ -2,7 +2,7 @@ import type { PropsWithChildren } from "react"; import type { MantineColorsTuple } from "@mantine/core"; -import { createTheme, darken, lighten, MantineProvider } from "@mantine/core"; +import { colorsTuple, createTheme, darken, lighten, MantineProvider } from "@mantine/core"; import { useRequiredBoard } from "@homarr/boards/context"; import type { ColorScheme } from "@homarr/definitions"; @@ -20,6 +20,7 @@ export const BoardMantineProvider = ({ colors: { primaryColor: generateColors(board.primaryColor), secondaryColor: generateColors(board.secondaryColor), + iconColor: board.iconColor ? generateColors(board.iconColor) : colorsTuple("#000000"), }, primaryColor: "primaryColor", autoContrast: true, diff --git a/apps/nextjs/src/app/[locale]/boards/[name]/settings/_colors.tsx b/apps/nextjs/src/app/[locale]/boards/[name]/settings/_appereance.tsx similarity index 80% rename from apps/nextjs/src/app/[locale]/boards/[name]/settings/_colors.tsx rename to apps/nextjs/src/app/[locale]/boards/[name]/settings/_appereance.tsx index 4f12e28ad..b96d99a88 100644 --- a/apps/nextjs/src/app/[locale]/boards/[name]/settings/_colors.tsx +++ b/apps/nextjs/src/app/[locale]/boards/[name]/settings/_appereance.tsx @@ -10,6 +10,7 @@ import { Group, InputWrapper, isLightColor, + Select, Slider, Stack, Text, @@ -39,6 +40,8 @@ export const ColorSettingsContent = ({ board }: Props) => { primaryColor: board.primaryColor, secondaryColor: board.secondaryColor, opacity: board.opacity, + iconColor: board.iconColor ?? "", + itemRadius: board.itemRadius, }, }); const [showPreview, { toggle }] = useDisclosure(false); @@ -98,6 +101,26 @@ export const ColorSettingsContent = ({ board }: Props) => { /> + + color[6])} + {...form.getInputProps("iconColor")} + /> + - } - nothingFoundMessage={t("widget.common.app.noData")} - renderOption={renderSelectOption} - data={ - apps?.map((app) => ({ - label: app.name, - value: app.id, - iconUrl: app.iconUrl, - })) ?? [] - } - inputWrapperOrder={["label", "input", "description", "error"]} - description={ - - {t.rich("widget.common.app.description", { - here: () => ( - - {t("common.here")} - - ), - })} - - } - {...form.getInputProps(`options.${property}`)} - /> + +