Merge branch 'dev' into ajnart/fix-duplicate-users
This commit is contained in:
@@ -35,7 +35,7 @@ export const LoginForm = () => {
|
||||
},
|
||||
});
|
||||
|
||||
const handleSubmit = async (values: FormType) => {
|
||||
const handleSubmitAsync = async (values: FormType) => {
|
||||
setIsLoading(true);
|
||||
setError(undefined);
|
||||
await signIn("credentials", {
|
||||
@@ -66,7 +66,9 @@ export const LoginForm = () => {
|
||||
|
||||
return (
|
||||
<Stack gap="xl">
|
||||
<form onSubmit={form.onSubmit((values) => void handleSubmit(values))}>
|
||||
<form
|
||||
onSubmit={form.onSubmit((values) => void handleSubmitAsync(values))}
|
||||
>
|
||||
<Stack gap="lg">
|
||||
<TextInput
|
||||
label={t("field.username.label")}
|
||||
|
||||
@@ -3,7 +3,7 @@ import { api } from "@homarr/api/server";
|
||||
import { createBoardContentPage } from "../_creator";
|
||||
|
||||
export default createBoardContentPage<{ locale: string }>({
|
||||
async getInitialBoard() {
|
||||
async getInitialBoardAsync() {
|
||||
return await api.board.getDefaultBoard();
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import definition from "./_definition";
|
||||
|
||||
const { generateMetadata, page } = definition;
|
||||
const { generateMetadataAsync: generateMetadata, page } = definition;
|
||||
|
||||
export default page;
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import { api } from "@homarr/api/server";
|
||||
import { createBoardContentPage } from "../_creator";
|
||||
|
||||
export default createBoardContentPage<{ locale: string; name: string }>({
|
||||
async getInitialBoard({ name }) {
|
||||
async getInitialBoardAsync({ name }) {
|
||||
return await api.board.getBoardByName({ name });
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import definition from "./_definition";
|
||||
|
||||
const { generateMetadata, page } = definition;
|
||||
const { generateMetadataAsync: generateMetadata, page } = definition;
|
||||
|
||||
export default page;
|
||||
|
||||
|
||||
@@ -14,24 +14,24 @@ import { BoardContentHeaderActions } from "./_header-actions";
|
||||
export type Params = Record<string, unknown>;
|
||||
|
||||
interface Props<TParams extends Params> {
|
||||
getInitialBoard: (params: TParams) => Promise<Board>;
|
||||
getInitialBoardAsync: (params: TParams) => Promise<Board>;
|
||||
}
|
||||
|
||||
export const createBoardContentPage = <
|
||||
TParams extends Record<string, unknown>,
|
||||
>({
|
||||
getInitialBoard,
|
||||
getInitialBoardAsync: getInitialBoard,
|
||||
}: Props<TParams>) => {
|
||||
return {
|
||||
layout: createBoardLayout({
|
||||
headerActions: <BoardContentHeaderActions />,
|
||||
getInitialBoard,
|
||||
getInitialBoardAsync: getInitialBoard,
|
||||
isBoardContentPage: true,
|
||||
}),
|
||||
page: () => {
|
||||
return <ClientBoard />;
|
||||
},
|
||||
generateMetadata: async ({
|
||||
generateMetadataAsync: async ({
|
||||
params,
|
||||
}: {
|
||||
params: TParams;
|
||||
|
||||
@@ -22,7 +22,7 @@ import {
|
||||
} from "@homarr/notifications";
|
||||
import { useI18n, useScopedI18n } from "@homarr/translation/client";
|
||||
|
||||
import { revalidatePathAction } from "~/app/revalidatePathAction";
|
||||
import { revalidatePathActionAsync } from "~/app/revalidatePathAction";
|
||||
import { editModeAtom } from "~/components/board/editMode";
|
||||
import { ItemSelectModal } from "~/components/board/items/item-select-modal";
|
||||
import { useBoardPermissions } from "~/components/board/permissions/client";
|
||||
@@ -131,7 +131,7 @@ const EditModeMenu = () => {
|
||||
message: t("notification.success.message"),
|
||||
});
|
||||
void utils.board.getBoardByName.invalidate({ name: board.name });
|
||||
void revalidatePathAction(`/boards/${board.name}`);
|
||||
void revalidatePathActionAsync(`/boards/${board.name}`);
|
||||
setEditMode(false);
|
||||
},
|
||||
onError() {
|
||||
|
||||
@@ -5,7 +5,7 @@ import { createBoardLayout } from "../_layout-creator";
|
||||
|
||||
export default createBoardLayout<{ locale: string; name: string }>({
|
||||
headerActions: <BoardOtherHeaderActions />,
|
||||
async getInitialBoard({ name }) {
|
||||
async getInitialBoardAsync({ name }) {
|
||||
return await api.board.getBoardByName({ name });
|
||||
},
|
||||
isBoardContentPage: false,
|
||||
|
||||
@@ -22,7 +22,7 @@ export const GroupSelectModal = createModal<InnerProps>(
|
||||
const { data: groups, isPending } = clientApi.group.selectable.useQuery();
|
||||
const [loading, setLoading] = useState(false);
|
||||
const form = useForm<GroupSelectFormType>();
|
||||
const handleSubmit = async (values: GroupSelectFormType) => {
|
||||
const handleSubmitAsync = async (values: GroupSelectFormType) => {
|
||||
const currentGroup = groups?.find((group) => group.id === values.groupId);
|
||||
if (!currentGroup) return;
|
||||
setLoading(true);
|
||||
@@ -38,7 +38,9 @@ export const GroupSelectModal = createModal<InnerProps>(
|
||||
const confirmLabel = innerProps.confirmLabel ?? t("common.action.add");
|
||||
|
||||
return (
|
||||
<form onSubmit={form.onSubmit((values) => void handleSubmit(values))}>
|
||||
<form
|
||||
onSubmit={form.onSubmit((values) => void handleSubmitAsync(values))}
|
||||
>
|
||||
<Stack>
|
||||
<Select
|
||||
{...form.getInputProps("groupId")}
|
||||
|
||||
@@ -30,7 +30,7 @@ export const UserSelectModal = createModal<InnerProps>(
|
||||
const { data: users, isPending } = clientApi.user.selectable.useQuery();
|
||||
const [loading, setLoading] = useState(false);
|
||||
const form = useForm<UserSelectFormType>();
|
||||
const handleSubmit = async (values: UserSelectFormType) => {
|
||||
const handleSubmitAsync = async (values: UserSelectFormType) => {
|
||||
const currentUser = users?.find((user) => user.id === values.userId);
|
||||
if (!currentUser) return;
|
||||
setLoading(true);
|
||||
@@ -48,7 +48,9 @@ export const UserSelectModal = createModal<InnerProps>(
|
||||
const currentUser = users?.find((user) => user.id === form.values.userId);
|
||||
|
||||
return (
|
||||
<form onSubmit={form.onSubmit((values) => void handleSubmit(values))}>
|
||||
<form
|
||||
onSubmit={form.onSubmit((values) => void handleSubmitAsync(values))}
|
||||
>
|
||||
<Stack>
|
||||
<Select
|
||||
{...form.getInputProps("userId")}
|
||||
|
||||
@@ -26,7 +26,7 @@ import type { TranslationObject } from "@homarr/translation";
|
||||
import { getScopedI18n } from "@homarr/translation/server";
|
||||
import type { TablerIcon } from "@homarr/ui";
|
||||
|
||||
import { getBoardPermissions } from "~/components/board/permissions/server";
|
||||
import { getBoardPermissionsAsync } from "~/components/board/permissions/server";
|
||||
import { ActiveTabAccordion } from "../../../../../components/active-tab-accordion";
|
||||
import { AccessSettingsContent } from "./_access";
|
||||
import { BackgroundSettingsContent } from "./_background";
|
||||
@@ -45,10 +45,10 @@ interface Props {
|
||||
};
|
||||
}
|
||||
|
||||
const getBoardAndPermissions = async (params: Props["params"]) => {
|
||||
const getBoardAndPermissionsAsync = async (params: Props["params"]) => {
|
||||
try {
|
||||
const board = await api.board.getBoardByName({ name: params.name });
|
||||
const { hasFullAccess } = await getBoardPermissions(board);
|
||||
const { hasFullAccess } = await getBoardPermissionsAsync(board);
|
||||
const permissions = hasFullAccess
|
||||
? await api.board.getBoardPermissions({ id: board.id })
|
||||
: {
|
||||
@@ -73,8 +73,8 @@ export default async function BoardSettingsPage({
|
||||
params,
|
||||
searchParams,
|
||||
}: Props) {
|
||||
const { board, permissions } = await getBoardAndPermissions(params);
|
||||
const { hasFullAccess } = await getBoardPermissions(board);
|
||||
const { board, permissions } = await getBoardAndPermissionsAsync(params);
|
||||
const { hasFullAccess } = await getBoardPermissionsAsync(board);
|
||||
const t = await getScopedI18n("board.setting");
|
||||
|
||||
return (
|
||||
|
||||
@@ -16,13 +16,13 @@ import { BoardMantineProvider } from "./(content)/_theme";
|
||||
|
||||
interface CreateBoardLayoutProps<TParams extends Params> {
|
||||
headerActions: JSX.Element;
|
||||
getInitialBoard: (params: TParams) => Promise<Board>;
|
||||
getInitialBoardAsync: (params: TParams) => Promise<Board>;
|
||||
isBoardContentPage: boolean;
|
||||
}
|
||||
|
||||
export const createBoardLayout = <TParams extends Params>({
|
||||
headerActions,
|
||||
getInitialBoard,
|
||||
getInitialBoardAsync: getInitialBoard,
|
||||
isBoardContentPage,
|
||||
}: CreateBoardLayoutProps<TParams>) => {
|
||||
const Layout = async ({
|
||||
|
||||
@@ -29,7 +29,7 @@ export const InitUserForm = () => {
|
||||
},
|
||||
});
|
||||
|
||||
const handleSubmit = async (values: FormType) => {
|
||||
const handleSubmitAsync = async (values: FormType) => {
|
||||
await mutateAsync(values, {
|
||||
onSuccess: () => {
|
||||
showSuccessNotification({
|
||||
@@ -51,7 +51,7 @@ export const InitUserForm = () => {
|
||||
<Stack gap="xl">
|
||||
<form
|
||||
onSubmit={form.onSubmit(
|
||||
(values) => void handleSubmit(values),
|
||||
(values) => void handleSubmitAsync(values),
|
||||
(err) => console.log(err),
|
||||
)}
|
||||
>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import type { Metadata, Viewport } from "next";
|
||||
import { Inter } from "next/font/google";
|
||||
|
||||
import "@homarr/ui/styles.css";
|
||||
import "@homarr/notifications/styles.css";
|
||||
import "@homarr/spotlight/styles.css";
|
||||
import "@mantine/core/styles.css";
|
||||
|
||||
import { ColorSchemeScript, createTheme, MantineProvider } from "@mantine/core";
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ import {
|
||||
} from "@homarr/notifications";
|
||||
import { useScopedI18n } from "@homarr/translation/client";
|
||||
|
||||
import { revalidatePathAction } from "../../../revalidatePathAction";
|
||||
import { revalidatePathActionAsync } from "../../../revalidatePathAction";
|
||||
|
||||
interface AppDeleteButtonProps {
|
||||
app: RouterOutputs["app"]["all"][number];
|
||||
@@ -37,7 +37,7 @@ export const AppDeleteButton = ({ app }: AppDeleteButtonProps) => {
|
||||
title: t("notification.success.title"),
|
||||
message: t("notification.success.message"),
|
||||
});
|
||||
void revalidatePathAction("/manage/apps");
|
||||
void revalidatePathActionAsync("/manage/apps");
|
||||
},
|
||||
onError: () => {
|
||||
showErrorNotification({
|
||||
|
||||
@@ -13,7 +13,7 @@ import type { TranslationFunction } from "@homarr/translation";
|
||||
import { useScopedI18n } from "@homarr/translation/client";
|
||||
import type { validation, z } from "@homarr/validation";
|
||||
|
||||
import { revalidatePathAction } from "~/app/revalidatePathAction";
|
||||
import { revalidatePathActionAsync } from "~/app/revalidatePathAction";
|
||||
import { AppForm } from "../../_form";
|
||||
|
||||
interface AppEditFormProps {
|
||||
@@ -30,7 +30,7 @@ export const AppEditForm = ({ app }: AppEditFormProps) => {
|
||||
title: t("success.title"),
|
||||
message: t("success.message"),
|
||||
});
|
||||
void revalidatePathAction("/manage/apps").then(() => {
|
||||
void revalidatePathActionAsync("/manage/apps").then(() => {
|
||||
router.push("/manage/apps");
|
||||
});
|
||||
},
|
||||
|
||||
@@ -12,7 +12,7 @@ import type { TranslationFunction } from "@homarr/translation";
|
||||
import { useScopedI18n } from "@homarr/translation/client";
|
||||
import type { validation, z } from "@homarr/validation";
|
||||
|
||||
import { revalidatePathAction } from "~/app/revalidatePathAction";
|
||||
import { revalidatePathActionAsync } from "~/app/revalidatePathAction";
|
||||
import { AppForm } from "../_form";
|
||||
|
||||
export const AppNewForm = () => {
|
||||
@@ -25,7 +25,7 @@ export const AppNewForm = () => {
|
||||
title: t("success.title"),
|
||||
message: t("success.message"),
|
||||
});
|
||||
void revalidatePathAction("/manage/apps").then(() => {
|
||||
void revalidatePathActionAsync("/manage/apps").then(() => {
|
||||
router.push("/manage/apps");
|
||||
});
|
||||
},
|
||||
|
||||
@@ -10,7 +10,7 @@ import { clientApi } from "@homarr/api/client";
|
||||
import { useConfirmModal } from "@homarr/modals";
|
||||
import { useScopedI18n } from "@homarr/translation/client";
|
||||
|
||||
import { revalidatePathAction } from "~/app/revalidatePathAction";
|
||||
import { revalidatePathActionAsync } from "~/app/revalidatePathAction";
|
||||
import { useBoardPermissions } from "~/components/board/permissions/client";
|
||||
|
||||
const iconProps = {
|
||||
@@ -42,7 +42,7 @@ export const BoardCardMenuDropdown = ({
|
||||
|
||||
const { mutateAsync, isPending } = clientApi.board.deleteBoard.useMutation({
|
||||
onSettled: async () => {
|
||||
await revalidatePathAction("/manage/boards");
|
||||
await revalidatePathActionAsync("/manage/boards");
|
||||
},
|
||||
});
|
||||
|
||||
@@ -52,6 +52,7 @@ export const BoardCardMenuDropdown = ({
|
||||
children: t("delete.confirm.description", {
|
||||
name: board.name,
|
||||
}),
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
onConfirm: async () => {
|
||||
await mutateAsync({
|
||||
id: board.id,
|
||||
|
||||
@@ -8,7 +8,7 @@ import { clientApi } from "@homarr/api/client";
|
||||
import { useModalAction } from "@homarr/modals";
|
||||
import { useI18n } from "@homarr/translation/client";
|
||||
|
||||
import { revalidatePathAction } from "~/app/revalidatePathAction";
|
||||
import { revalidatePathActionAsync } from "~/app/revalidatePathAction";
|
||||
import { AddBoardModal } from "~/components/manage/boards/add-board-modal";
|
||||
|
||||
interface CreateBoardButtonProps {
|
||||
@@ -21,7 +21,7 @@ export const CreateBoardButton = ({ boardNames }: CreateBoardButtonProps) => {
|
||||
|
||||
const { mutateAsync, isPending } = clientApi.board.createBoard.useMutation({
|
||||
onSettled: async () => {
|
||||
await revalidatePathAction("/manage/boards");
|
||||
await revalidatePathActionAsync("/manage/boards");
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ import { api } from "@homarr/api/server";
|
||||
import { getScopedI18n } from "@homarr/translation/server";
|
||||
import { UserAvatar } from "@homarr/ui";
|
||||
|
||||
import { getBoardPermissions } from "~/components/board/permissions/server";
|
||||
import { getBoardPermissionsAsync } from "~/components/board/permissions/server";
|
||||
import { BoardCardMenuDropdown } from "./_components/board-card-menu-dropdown";
|
||||
import { CreateBoardButton } from "./_components/create-board-button";
|
||||
|
||||
@@ -53,7 +53,8 @@ interface BoardCardProps {
|
||||
|
||||
const BoardCard = async ({ board }: BoardCardProps) => {
|
||||
const t = await getScopedI18n("management.page.board");
|
||||
const { hasChangeAccess: isMenuVisible } = await getBoardPermissions(board);
|
||||
const { hasChangeAccess: isMenuVisible } =
|
||||
await getBoardPermissionsAsync(board);
|
||||
const visibility = board.isPublic ? "public" : "private";
|
||||
const VisibilityIcon = board.isPublic ? IconWorld : IconLock;
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ import {
|
||||
} from "@homarr/notifications";
|
||||
import { useScopedI18n } from "@homarr/translation/client";
|
||||
|
||||
import { revalidatePathAction } from "../../../revalidatePathAction";
|
||||
import { revalidatePathActionAsync } from "../../../revalidatePathAction";
|
||||
|
||||
interface DeleteIntegrationActionButtonProps {
|
||||
count: number;
|
||||
@@ -49,7 +49,7 @@ export const DeleteIntegrationActionButton = ({
|
||||
if (count === 1) {
|
||||
router.replace("/manage/integrations");
|
||||
}
|
||||
void revalidatePathAction("/manage/integrations");
|
||||
void revalidatePathActionAsync("/manage/integrations");
|
||||
},
|
||||
onError: () => {
|
||||
showErrorNotification({
|
||||
|
||||
@@ -20,7 +20,7 @@ import { useI18n } from "@homarr/translation/client";
|
||||
import type { z } from "@homarr/validation";
|
||||
import { validation } from "@homarr/validation";
|
||||
|
||||
import { revalidatePathAction } from "~/app/revalidatePathAction";
|
||||
import { revalidatePathActionAsync } from "~/app/revalidatePathAction";
|
||||
import { SecretCard } from "../../_integration-secret-card";
|
||||
import { IntegrationSecretInput } from "../../_integration-secret-inputs";
|
||||
import {
|
||||
@@ -66,7 +66,7 @@ export const EditIntegrationForm = ({ integration }: EditIntegrationForm) => {
|
||||
integration.secrets.map((secret) => [secret.kind, secret]),
|
||||
);
|
||||
|
||||
const handleSubmit = async (values: FormType) => {
|
||||
const handleSubmitAsync = async (values: FormType) => {
|
||||
if (isDirty) return;
|
||||
await mutateAsync(
|
||||
{
|
||||
@@ -83,7 +83,7 @@ export const EditIntegrationForm = ({ integration }: EditIntegrationForm) => {
|
||||
title: t("integration.page.edit.notification.success.title"),
|
||||
message: t("integration.page.edit.notification.success.message"),
|
||||
});
|
||||
void revalidatePathAction("/manage/integrations").then(() =>
|
||||
void revalidatePathActionAsync("/manage/integrations").then(() =>
|
||||
router.push("/manage/integrations"),
|
||||
);
|
||||
},
|
||||
@@ -98,7 +98,7 @@ export const EditIntegrationForm = ({ integration }: EditIntegrationForm) => {
|
||||
};
|
||||
|
||||
return (
|
||||
<form onSubmit={form.onSubmit((values) => void handleSubmit(values))}>
|
||||
<form onSubmit={form.onSubmit((values) => void handleSubmitAsync(values))}>
|
||||
<Stack>
|
||||
<TestConnectionNoticeAlert />
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ import {
|
||||
TestConnectionNoticeAlert,
|
||||
useTestConnectionDirty,
|
||||
} from "../_integration-test-connection";
|
||||
import { revalidatePathAction } from "../../../../revalidatePathAction";
|
||||
import { revalidatePathActionAsync } from "../../../../revalidatePathAction";
|
||||
|
||||
interface NewIntegrationFormProps {
|
||||
searchParams: Partial<z.infer<typeof validation.integration.create>> & {
|
||||
@@ -67,7 +67,7 @@ export const NewIntegrationForm = ({
|
||||
});
|
||||
const { mutateAsync, isPending } = clientApi.integration.create.useMutation();
|
||||
|
||||
const handleSubmit = async (values: FormType) => {
|
||||
const handleSubmitAsync = async (values: FormType) => {
|
||||
if (isDirty) return;
|
||||
await mutateAsync(
|
||||
{
|
||||
@@ -80,7 +80,7 @@ export const NewIntegrationForm = ({
|
||||
title: t("integration.page.create.notification.success.title"),
|
||||
message: t("integration.page.create.notification.success.message"),
|
||||
});
|
||||
void revalidatePathAction("/manage/integrations").then(() =>
|
||||
void revalidatePathActionAsync("/manage/integrations").then(() =>
|
||||
router.push("/manage/integrations"),
|
||||
);
|
||||
},
|
||||
@@ -95,7 +95,7 @@ export const NewIntegrationForm = ({
|
||||
};
|
||||
|
||||
return (
|
||||
<form onSubmit={form.onSubmit((value) => void handleSubmit(value))}>
|
||||
<form onSubmit={form.onSubmit((value) => void handleSubmitAsync(value))}>
|
||||
<Stack>
|
||||
<TestConnectionNoticeAlert />
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import { clientApi } from "@homarr/api/client";
|
||||
import { useConfirmModal } from "@homarr/modals";
|
||||
import { useI18n } from "@homarr/translation/client";
|
||||
|
||||
import { revalidatePathAction } from "~/app/revalidatePathAction";
|
||||
import { revalidatePathActionAsync } from "~/app/revalidatePathAction";
|
||||
|
||||
interface DeleteUserButtonProps {
|
||||
user: RouterOutputs["user"]["getById"];
|
||||
@@ -21,7 +21,7 @@ export const DeleteUserButton = ({ user }: DeleteUserButtonProps) => {
|
||||
const { mutateAsync: mutateUserDeletionAsync } =
|
||||
clientApi.user.delete.useMutation({
|
||||
async onSuccess() {
|
||||
await revalidatePathAction("/manage/users").then(() =>
|
||||
await revalidatePathActionAsync("/manage/users").then(() =>
|
||||
router.push("/manage/users"),
|
||||
);
|
||||
},
|
||||
@@ -33,6 +33,7 @@ export const DeleteUserButton = ({ user }: DeleteUserButtonProps) => {
|
||||
openConfirmModal({
|
||||
title: t("user.action.delete.label"),
|
||||
children: t("user.action.delete.confirm", { username: user.name }),
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
async onConfirm() {
|
||||
await mutateUserDeletionAsync(user.id);
|
||||
},
|
||||
|
||||
@@ -15,7 +15,7 @@ import {
|
||||
import { useI18n, useScopedI18n } from "@homarr/translation/client";
|
||||
import { UserAvatar } from "@homarr/ui";
|
||||
|
||||
import { revalidatePathAction } from "~/app/revalidatePathAction";
|
||||
import { revalidatePathActionAsync } from "~/app/revalidatePathAction";
|
||||
|
||||
interface UserProfileAvatarForm {
|
||||
user: RouterOutputs["user"]["getById"];
|
||||
@@ -44,7 +44,7 @@ export const UserProfileAvatarForm = ({ user }: UserProfileAvatarForm) => {
|
||||
{
|
||||
async onSuccess() {
|
||||
// Revalidate all as the avatar is used in multiple places
|
||||
await revalidatePathAction("/");
|
||||
await revalidatePathActionAsync("/");
|
||||
showSuccessNotification({
|
||||
message: tManageAvatar(
|
||||
"changeImage.notification.success.message",
|
||||
@@ -87,7 +87,7 @@ export const UserProfileAvatarForm = ({ user }: UserProfileAvatarForm) => {
|
||||
{
|
||||
async onSuccess() {
|
||||
// Revalidate all as the avatar is used in multiple places
|
||||
await revalidatePathAction("/");
|
||||
await revalidatePathActionAsync("/");
|
||||
showSuccessNotification({
|
||||
message: tManageAvatar(
|
||||
"removeImage.notification.success.message",
|
||||
@@ -161,7 +161,7 @@ export const UserProfileAvatarForm = ({ user }: UserProfileAvatarForm) => {
|
||||
);
|
||||
};
|
||||
|
||||
const fileToBase64Async = (file: File): Promise<string> =>
|
||||
const fileToBase64Async = async (file: File): Promise<string> =>
|
||||
new Promise((resolve, reject) => {
|
||||
const reader = new FileReader();
|
||||
reader.readAsDataURL(file);
|
||||
|
||||
@@ -13,7 +13,7 @@ import {
|
||||
import { useI18n } from "@homarr/translation/client";
|
||||
import { validation } from "@homarr/validation";
|
||||
|
||||
import { revalidatePathAction } from "~/app/revalidatePathAction";
|
||||
import { revalidatePathActionAsync } from "~/app/revalidatePathAction";
|
||||
|
||||
interface UserProfileFormProps {
|
||||
user: RouterOutputs["user"]["getById"];
|
||||
@@ -32,7 +32,7 @@ export const UserProfileForm = ({ user }: UserProfileFormProps) => {
|
||||
});
|
||||
const { mutate, isPending } = clientApi.user.editProfile.useMutation({
|
||||
async onSettled() {
|
||||
await revalidatePathAction("/manage/users");
|
||||
await revalidatePathActionAsync("/manage/users");
|
||||
},
|
||||
onSuccess(_, variables) {
|
||||
// Reset form initial values to reset dirty state
|
||||
|
||||
@@ -13,7 +13,7 @@ import {
|
||||
import { useI18n } from "@homarr/translation/client";
|
||||
import { validation } from "@homarr/validation";
|
||||
|
||||
import { revalidatePathAction } from "~/app/revalidatePathAction";
|
||||
import { revalidatePathActionAsync } from "~/app/revalidatePathAction";
|
||||
|
||||
interface ChangePasswordFormProps {
|
||||
user: RouterOutputs["user"]["getById"];
|
||||
@@ -24,7 +24,7 @@ export const ChangePasswordForm = ({ user }: ChangePasswordFormProps) => {
|
||||
const t = useI18n();
|
||||
const { mutate, isPending } = clientApi.user.changePassword.useMutation({
|
||||
async onSettled() {
|
||||
await revalidatePathAction(`/manage/users/${user.id}`);
|
||||
await revalidatePathActionAsync(`/manage/users/${user.id}`);
|
||||
},
|
||||
onSuccess() {
|
||||
showSuccessNotification({
|
||||
|
||||
@@ -12,7 +12,7 @@ import {
|
||||
} from "@homarr/notifications";
|
||||
import { useI18n, useScopedI18n } from "@homarr/translation/client";
|
||||
|
||||
import { revalidatePathAction } from "~/app/revalidatePathAction";
|
||||
import { revalidatePathActionAsync } from "~/app/revalidatePathAction";
|
||||
|
||||
interface DeleteGroupProps {
|
||||
group: {
|
||||
@@ -34,6 +34,7 @@ export const DeleteGroup = ({ group }: DeleteGroupProps) => {
|
||||
children: tDelete("confirm", {
|
||||
name: group.name,
|
||||
}),
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
async onConfirm() {
|
||||
await mutateAsync(
|
||||
{
|
||||
@@ -41,7 +42,7 @@ export const DeleteGroup = ({ group }: DeleteGroupProps) => {
|
||||
},
|
||||
{
|
||||
onSuccess() {
|
||||
void revalidatePathAction("/manage/users/groups");
|
||||
void revalidatePathActionAsync("/manage/users/groups");
|
||||
router.push("/manage/users/groups");
|
||||
showSuccessNotification({
|
||||
title: tRoot("common.notification.delete.success"),
|
||||
|
||||
@@ -11,7 +11,7 @@ import {
|
||||
} from "@homarr/notifications";
|
||||
import { useI18n } from "@homarr/translation/client";
|
||||
|
||||
import { revalidatePathAction } from "~/app/revalidatePathAction";
|
||||
import { revalidatePathActionAsync } from "~/app/revalidatePathAction";
|
||||
|
||||
interface RenameGroupFormProps {
|
||||
group: {
|
||||
@@ -38,7 +38,7 @@ export const RenameGroupForm = ({ group }: RenameGroupFormProps) => {
|
||||
},
|
||||
{
|
||||
onSuccess() {
|
||||
void revalidatePathAction(`/users/groups/${group.id}`);
|
||||
void revalidatePathActionAsync(`/users/groups/${group.id}`);
|
||||
showSuccessNotification({
|
||||
title: t("common.notification.update.success"),
|
||||
message: t("group.action.update.notification.success.message", {
|
||||
|
||||
@@ -43,6 +43,7 @@ export const TransferGroupOwnership = ({
|
||||
name: group.name,
|
||||
username: name,
|
||||
}),
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
onConfirm: async () => {
|
||||
await mutateAsync(
|
||||
{
|
||||
|
||||
@@ -8,7 +8,7 @@ import { useModalAction } from "@homarr/modals";
|
||||
import { useScopedI18n } from "@homarr/translation/client";
|
||||
|
||||
import { UserSelectModal } from "~/app/[locale]/boards/[name]/settings/_access/user-select-modal";
|
||||
import { revalidatePathAction } from "~/app/revalidatePathAction";
|
||||
import { revalidatePathActionAsync } from "~/app/revalidatePathAction";
|
||||
|
||||
interface AddGroupMemberProps {
|
||||
groupId: string;
|
||||
@@ -26,12 +26,13 @@ export const AddGroupMember = ({
|
||||
const handleAddMember = useCallback(() => {
|
||||
openModal(
|
||||
{
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
async onSelect({ id }) {
|
||||
await mutateAsync({
|
||||
userId: id,
|
||||
groupId,
|
||||
});
|
||||
await revalidatePathAction(
|
||||
await revalidatePathActionAsync(
|
||||
`/manage/users/groups/${groupId}}/members`,
|
||||
);
|
||||
},
|
||||
|
||||
@@ -7,7 +7,7 @@ import { clientApi } from "@homarr/api/client";
|
||||
import { useConfirmModal } from "@homarr/modals";
|
||||
import { useI18n, useScopedI18n } from "@homarr/translation/client";
|
||||
|
||||
import { revalidatePathAction } from "~/app/revalidatePathAction";
|
||||
import { revalidatePathActionAsync } from "~/app/revalidatePathAction";
|
||||
|
||||
interface RemoveGroupMemberProps {
|
||||
groupId: string;
|
||||
@@ -29,12 +29,15 @@ export const RemoveGroupMember = ({
|
||||
children: tRemoveMember("confirm", {
|
||||
user: user.name ?? "",
|
||||
}),
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
onConfirm: async () => {
|
||||
await mutateAsync({
|
||||
groupId,
|
||||
userId: user.id,
|
||||
});
|
||||
await revalidatePathAction(`/manage/users/groups/${groupId}/members`);
|
||||
await revalidatePathActionAsync(
|
||||
`/manage/users/groups/${groupId}/members`,
|
||||
);
|
||||
},
|
||||
});
|
||||
}, [
|
||||
|
||||
@@ -12,7 +12,7 @@ import {
|
||||
} from "@homarr/notifications";
|
||||
import { useI18n } from "@homarr/translation/client";
|
||||
|
||||
import { revalidatePathAction } from "~/app/revalidatePathAction";
|
||||
import { revalidatePathActionAsync } from "~/app/revalidatePathAction";
|
||||
|
||||
export const AddGroup = () => {
|
||||
const t = useI18n();
|
||||
@@ -44,7 +44,7 @@ const AddGroupModal = createModal<void>(({ actions }) => {
|
||||
mutate(values, {
|
||||
onSuccess() {
|
||||
actions.closeModal();
|
||||
void revalidatePathAction("/manage/users/groups");
|
||||
void revalidatePathActionAsync("/manage/users/groups");
|
||||
showSuccessNotification({
|
||||
title: t("common.notification.create.success"),
|
||||
message: t("group.action.create.notification.success.message"),
|
||||
|
||||
@@ -2,6 +2,6 @@
|
||||
|
||||
import { revalidatePath } from "next/cache";
|
||||
|
||||
export async function revalidatePathAction(path: string) {
|
||||
export async function revalidatePathActionAsync(path: string) {
|
||||
return new Promise((resolve) => resolve(revalidatePath(path, "page")));
|
||||
}
|
||||
|
||||
@@ -2,7 +2,9 @@ import { auth } from "@homarr/auth/next";
|
||||
import type { BoardPermissionsProps } from "@homarr/auth/shared";
|
||||
import { constructBoardPermissions } from "@homarr/auth/shared";
|
||||
|
||||
export const getBoardPermissions = async (board: BoardPermissionsProps) => {
|
||||
export const getBoardPermissionsAsync = async (
|
||||
board: BoardPermissionsProps,
|
||||
) => {
|
||||
const session = await auth();
|
||||
return constructBoardPermissions(board, session);
|
||||
};
|
||||
|
||||
@@ -87,14 +87,15 @@ export const iconsUpdaterJob = createCronJob(EVERY_WEEK, {
|
||||
if (newIcons.length >= 1) {
|
||||
await transaction.insert(icons).values(newIcons);
|
||||
}
|
||||
await transaction.delete(icons).where(
|
||||
deadIcons.length >= 1
|
||||
? inArray(
|
||||
icons.checksum,
|
||||
deadIcons.map((icon) => icon.checksum),
|
||||
)
|
||||
: undefined,
|
||||
);
|
||||
if (deadIcons.length >= 1) {
|
||||
await transaction.delete(icons).where(
|
||||
inArray(
|
||||
icons.checksum,
|
||||
deadIcons.map((icon) => icon.checksum),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
countDeleted += deadIcons.length;
|
||||
});
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { EVERY_MINUTE } from "../lib/cron-job/constants";
|
||||
import { createCronJob } from "../lib/cron-job/creator";
|
||||
import { queueWorker } from "../lib/queue/worker";
|
||||
import { queueWorkerAsync } from "../lib/queue/worker";
|
||||
|
||||
// This job processes queues, it runs every minute.
|
||||
export const queuesJob = createCronJob(EVERY_MINUTE).withCallback(async () => {
|
||||
await queueWorker();
|
||||
await queueWorkerAsync();
|
||||
});
|
||||
|
||||
@@ -39,7 +39,7 @@ export const createQueueClient = <TQueues extends Queues>(queues: TQueues) => {
|
||||
const queue = queueRegistry.get(name);
|
||||
if (!queue) return;
|
||||
|
||||
await queueChannel.add({
|
||||
await queueChannel.addAsync({
|
||||
name,
|
||||
data,
|
||||
executionDate:
|
||||
|
||||
@@ -6,15 +6,15 @@ import { queueRegistry } from "~/queues";
|
||||
* This function reads all the queue executions that are due and processes them.
|
||||
* Those executions are stored in the redis queue channel.
|
||||
*/
|
||||
export const queueWorker = async () => {
|
||||
export const queueWorkerAsync = async () => {
|
||||
const now = new Date();
|
||||
const executions = await queueChannel.filter((item) => {
|
||||
const executions = await queueChannel.filterAsync((item) => {
|
||||
return item.executionDate < now;
|
||||
});
|
||||
for (const execution of executions) {
|
||||
const queue = queueRegistry.get(execution.name);
|
||||
if (!queue) continue;
|
||||
await queue.callback(execution.data);
|
||||
await queueChannel.markAsDone(execution._id);
|
||||
await queueChannel.markAsDoneAsync(execution._id);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -13,6 +13,8 @@ const wss = new WebSocketServer({
|
||||
const handler = applyWSSHandler({
|
||||
wss,
|
||||
router: appRouter,
|
||||
// ignore error on next line because the createContext must be set with this name
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
createContext: async ({ req }) => {
|
||||
try {
|
||||
const headers = Object.entries(req.headers).map(
|
||||
|
||||
Reference in New Issue
Block a user