refactor: move modals to seperate package (#1135)

* refactor: move modals to seperate package

* fix: format issue

* fix: lint issues

* fix: format issue

* fix: only used as type
This commit is contained in:
Meier Lukas
2024-09-16 19:53:37 +02:00
committed by GitHub
parent 3ef478c53a
commit 6738296830
44 changed files with 1692 additions and 1389 deletions

View File

@@ -7,6 +7,7 @@ import { Anchor, Button, Card, Code, Collapse, Divider, PasswordInput, Stack, Te
import { useDisclosure } from "@mantine/hooks";
import { signIn } from "@homarr/auth/client";
import { revalidatePathActionAsync } from "@homarr/common/client";
import type { useForm } from "@homarr/form";
import { useZodForm } from "@homarr/form";
import { showErrorNotification, showSuccessNotification } from "@homarr/notifications";
@@ -14,8 +15,6 @@ import { useScopedI18n } from "@homarr/translation/client";
import type { z } from "@homarr/validation";
import { validation } from "@homarr/validation";
import { revalidatePathActionAsync } from "~/app/revalidatePathAction";
interface LoginFormProps {
providers: string[];
oidcClientName: string;

View File

@@ -15,11 +15,11 @@ import {
} from "@tabler/icons-react";
import { clientApi } from "@homarr/api/client";
import { revalidatePathActionAsync } from "@homarr/common/client";
import { useModalAction } from "@homarr/modals";
import { showErrorNotification, showSuccessNotification } from "@homarr/notifications";
import { useI18n, useScopedI18n } from "@homarr/translation/client";
import { revalidatePathActionAsync } from "~/app/revalidatePathAction";
import { ItemSelectModal } from "~/components/board/items/item-select-modal";
import { useBoardPermissions } from "~/components/board/permissions/client";
import { useCategoryActions } from "~/components/board/sections/category/category-actions";

View File

@@ -6,12 +6,11 @@ import { IconTrash } from "@tabler/icons-react";
import type { RouterOutputs } from "@homarr/api";
import { clientApi } from "@homarr/api/client";
import { revalidatePathActionAsync } from "@homarr/common/client";
import { useConfirmModal } from "@homarr/modals";
import { showErrorNotification, showSuccessNotification } from "@homarr/notifications";
import { useScopedI18n } from "@homarr/translation/client";
import { revalidatePathActionAsync } from "../../../revalidatePathAction";
interface AppDeleteButtonProps {
app: RouterOutputs["app"]["all"][number];
}

View File

@@ -5,12 +5,12 @@ import { useRouter } from "next/navigation";
import type { RouterOutputs } from "@homarr/api";
import { clientApi } from "@homarr/api/client";
import { revalidatePathActionAsync } from "@homarr/common/client";
import { showErrorNotification, showSuccessNotification } from "@homarr/notifications";
import type { TranslationFunction } from "@homarr/translation";
import { useScopedI18n } from "@homarr/translation/client";
import type { validation, z } from "@homarr/validation";
import { revalidatePathActionAsync } from "~/app/revalidatePathAction";
import { AppForm } from "../../_form";
interface AppEditFormProps {

View File

@@ -4,12 +4,12 @@ import { useCallback } from "react";
import { useRouter } from "next/navigation";
import { clientApi } from "@homarr/api/client";
import { revalidatePathActionAsync } from "@homarr/common/client";
import { showErrorNotification, showSuccessNotification } from "@homarr/notifications";
import type { TranslationFunction } from "@homarr/translation";
import { useScopedI18n } from "@homarr/translation/client";
import type { validation, z } from "@homarr/validation";
import { revalidatePathActionAsync } from "~/app/revalidatePathAction";
import { AppForm } from "../_form";
export const AppNewForm = () => {

View File

@@ -7,10 +7,10 @@ import { IconHome, IconSettings, IconTrash } from "@tabler/icons-react";
import type { RouterOutputs } from "@homarr/api";
import { clientApi } from "@homarr/api/client";
import { revalidatePathActionAsync } from "@homarr/common/client";
import { useConfirmModal } from "@homarr/modals";
import { useScopedI18n } from "@homarr/translation/client";
import { revalidatePathActionAsync } from "~/app/revalidatePathAction";
import { useBoardPermissions } from "~/components/board/permissions/client";
const iconProps = {

View File

@@ -4,15 +4,12 @@ import { useCallback } from "react";
import { Affix, Button, Group, Menu } from "@mantine/core";
import { IconCategoryPlus, IconChevronDown, IconFileImport } from "@tabler/icons-react";
import { clientApi } from "@homarr/api/client";
import { revalidatePathActionAsync } from "@homarr/common/client";
import { useModalAction } from "@homarr/modals";
import { AddBoardModal, ImportBoardModal } from "@homarr/modals-collection";
import { useI18n } from "@homarr/translation/client";
import { BetaBadge } from "@homarr/ui";
import { revalidatePathActionAsync } from "~/app/revalidatePathAction";
import { AddBoardModal } from "~/components/manage/boards/add-board-modal";
import { ImportBoardModal } from "~/components/manage/boards/import-board-modal";
interface CreateBoardButtonProps {
boardNames: string[];
}
@@ -22,24 +19,13 @@ export const CreateBoardButton = ({ boardNames }: CreateBoardButtonProps) => {
const { openModal: openAddModal } = useModalAction(AddBoardModal);
const { openModal: openImportModal } = useModalAction(ImportBoardModal);
const { mutateAsync, isPending } = clientApi.board.createBoard.useMutation({
onSettled: async () => {
await revalidatePathActionAsync("/manage/boards");
},
});
const onCreateClick = useCallback(() => {
openAddModal({
onSuccess: async (values) => {
await mutateAsync({
name: values.name,
columnCount: values.columnCount,
isPublic: values.isPublic,
});
onSettled: async () => {
await revalidatePathActionAsync("/manage/boards");
},
boardNames,
});
}, [mutateAsync, boardNames, openAddModal]);
}, [openAddModal]);
const onImportClick = useCallback(() => {
openImportModal({ boardNames });
@@ -47,7 +33,7 @@ export const CreateBoardButton = ({ boardNames }: CreateBoardButtonProps) => {
const buttonGroupContent = (
<>
<Button leftSection={<IconCategoryPlus size="1rem" />} onClick={onCreateClick} loading={isPending}>
<Button leftSection={<IconCategoryPlus size="1rem" />} onClick={onCreateClick}>
{t("management.page.board.action.new.label")}
</Button>
<Menu position="bottom-end">

View File

@@ -5,12 +5,11 @@ import { ActionIcon } from "@mantine/core";
import { IconTrash } from "@tabler/icons-react";
import { clientApi } from "@homarr/api/client";
import { revalidatePathActionAsync } from "@homarr/common/client";
import { useConfirmModal } from "@homarr/modals";
import { showErrorNotification, showSuccessNotification } from "@homarr/notifications";
import { useScopedI18n } from "@homarr/translation/client";
import { revalidatePathActionAsync } from "../../../revalidatePathAction";
interface DeleteIntegrationActionButtonProps {
count: number;
integration: { id: string; name: string };

View File

@@ -6,6 +6,7 @@ import { Button, Fieldset, Group, Stack, TextInput } from "@mantine/core";
import type { RouterOutputs } from "@homarr/api";
import { clientApi } from "@homarr/api/client";
import { revalidatePathActionAsync } from "@homarr/common/client";
import { getAllSecretKindOptions, getDefaultSecretKinds } from "@homarr/definitions";
import { useZodForm } from "@homarr/form";
import { convertIntegrationTestConnectionError } from "@homarr/integrations/client";
@@ -15,7 +16,6 @@ import { useI18n } from "@homarr/translation/client";
import type { z } from "@homarr/validation";
import { validation } from "@homarr/validation";
import { revalidatePathActionAsync } from "~/app/revalidatePathAction";
import { SecretCard } from "../../_components/secrets/integration-secret-card";
import { IntegrationSecretInput } from "../../_components/secrets/integration-secret-inputs";

View File

@@ -7,6 +7,7 @@ import { Alert, Button, Fieldset, Group, SegmentedControl, Stack, Text, TextInpu
import { IconInfoCircle } from "@tabler/icons-react";
import { clientApi } from "@homarr/api/client";
import { revalidatePathActionAsync } from "@homarr/common/client";
import type { IntegrationKind, IntegrationSecretKind } from "@homarr/definitions";
import { getAllSecretKindOptions } from "@homarr/definitions";
import type { UseFormReturnType } from "@homarr/form";
@@ -18,7 +19,6 @@ import type { z } from "@homarr/validation";
import { validation } from "@homarr/validation";
import { IntegrationSecretInput } from "../_components/secrets/integration-secret-inputs";
import { revalidatePathActionAsync } from "../../../../revalidatePathAction";
interface NewIntegrationFormProps {
searchParams: Partial<z.infer<typeof validation.integration.create>> & {

View File

@@ -4,12 +4,12 @@ import React from "react";
import { Card, LoadingOverlay, Stack, Title } from "@mantine/core";
import { clientApi } from "@homarr/api/client";
import { revalidatePathActionAsync } from "@homarr/common/client";
import { useForm } from "@homarr/form";
import type { defaultServerSettings } from "@homarr/server-settings";
import { useScopedI18n } from "@homarr/translation/client";
import { SwitchSetting } from "~/app/[locale]/manage/settings/_components/setting-switch";
import { revalidatePathActionAsync } from "~/app/revalidatePathAction";
interface AnalyticsSettingsProps {
initialData: typeof defaultServerSettings.analytics;

View File

@@ -4,12 +4,12 @@ import React from "react";
import { Card, LoadingOverlay, Stack, Text, Title } from "@mantine/core";
import { clientApi } from "@homarr/api/client";
import { revalidatePathActionAsync } from "@homarr/common/client";
import { useForm } from "@homarr/form";
import type { defaultServerSettings } from "@homarr/server-settings";
import { useScopedI18n } from "@homarr/translation/client";
import { SwitchSetting } from "~/app/[locale]/manage/settings/_components/setting-switch";
import { revalidatePathActionAsync } from "~/app/revalidatePathAction";
interface CrawlingAndIndexingSettingsProps {
initialData: typeof defaultServerSettings.crawlingAndIndexing;

View File

@@ -4,14 +4,13 @@ import { Button, Group, Select, Stack } from "@mantine/core";
import type { RouterOutputs } from "@homarr/api";
import { clientApi } from "@homarr/api/client";
import { revalidatePathActionAsync } from "@homarr/common/client";
import { useZodForm } from "@homarr/form";
import { showErrorNotification, showSuccessNotification } from "@homarr/notifications";
import { useI18n } from "@homarr/translation/client";
import type { z } from "@homarr/validation";
import { validation } from "@homarr/validation";
import { revalidatePathActionAsync } from "~/app/revalidatePathAction";
interface ChangeHomeBoardFormProps {
user: RouterOutputs["user"]["getById"];
boardsData: { value: string; label: string }[];

View File

@@ -6,11 +6,10 @@ import { Button } from "@mantine/core";
import type { RouterOutputs } from "@homarr/api";
import { clientApi } from "@homarr/api/client";
import { revalidatePathActionAsync } from "@homarr/common/client";
import { useConfirmModal } from "@homarr/modals";
import { useI18n } from "@homarr/translation/client";
import { revalidatePathActionAsync } from "~/app/revalidatePathAction";
interface DeleteUserButtonProps {
user: RouterOutputs["user"]["getById"];
}

View File

@@ -7,13 +7,12 @@ import { IconPencil, IconPhotoEdit, IconPhotoX } from "@tabler/icons-react";
import type { RouterOutputs } from "@homarr/api";
import { clientApi } from "@homarr/api/client";
import { revalidatePathActionAsync } from "@homarr/common/client";
import { useConfirmModal } from "@homarr/modals";
import { showErrorNotification, showSuccessNotification } from "@homarr/notifications";
import { useI18n, useScopedI18n } from "@homarr/translation/client";
import { UserAvatar } from "@homarr/ui";
import { revalidatePathActionAsync } from "~/app/revalidatePathAction";
interface UserProfileAvatarForm {
user: RouterOutputs["user"]["getById"];
}

View File

@@ -5,13 +5,12 @@ import { Button, Group, Stack, TextInput } from "@mantine/core";
import type { RouterInputs, RouterOutputs } from "@homarr/api";
import { clientApi } from "@homarr/api/client";
import { revalidatePathActionAsync } from "@homarr/common/client";
import { useZodForm } from "@homarr/form";
import { showErrorNotification, showSuccessNotification } from "@homarr/notifications";
import { useI18n } from "@homarr/translation/client";
import { validation } from "@homarr/validation";
import { revalidatePathActionAsync } from "~/app/revalidatePathAction";
interface UserProfileFormProps {
user: RouterOutputs["user"]["getById"];
}

View File

@@ -5,14 +5,13 @@ import { Button, Fieldset, Group, PasswordInput, Stack } from "@mantine/core";
import type { RouterInputs, RouterOutputs } from "@homarr/api";
import { clientApi } from "@homarr/api/client";
import { useSession } from "@homarr/auth/client";
import { revalidatePathActionAsync } from "@homarr/common/client";
import { useZodForm } from "@homarr/form";
import { showErrorNotification, showSuccessNotification } from "@homarr/notifications";
import { useI18n } from "@homarr/translation/client";
import { CustomPasswordInput } from "@homarr/ui";
import { validation } from "@homarr/validation";
import { revalidatePathActionAsync } from "~/app/revalidatePathAction";
interface ChangePasswordFormProps {
user: RouterOutputs["user"]["getById"];
}

View File

@@ -5,12 +5,11 @@ import { useRouter } from "next/navigation";
import { Button } from "@mantine/core";
import { clientApi } from "@homarr/api/client";
import { revalidatePathActionAsync } from "@homarr/common/client";
import { useConfirmModal } from "@homarr/modals";
import { showErrorNotification, showSuccessNotification } from "@homarr/notifications";
import { useI18n, useScopedI18n } from "@homarr/translation/client";
import { revalidatePathActionAsync } from "~/app/revalidatePathAction";
interface DeleteGroupProps {
group: {
id: string;

View File

@@ -4,13 +4,12 @@ import { useCallback } from "react";
import { Button, Group, Stack, TextInput } from "@mantine/core";
import { clientApi } from "@homarr/api/client";
import { revalidatePathActionAsync } from "@homarr/common/client";
import { useZodForm } from "@homarr/form";
import { showErrorNotification, showSuccessNotification } from "@homarr/notifications";
import { useI18n } from "@homarr/translation/client";
import { validation } from "@homarr/validation";
import { revalidatePathActionAsync } from "~/app/revalidatePathAction";
interface RenameGroupFormProps {
group: {
id: string;

View File

@@ -3,10 +3,10 @@
import { useCallback } from "react";
import { clientApi } from "@homarr/api/client";
import { revalidatePathActionAsync } from "@homarr/common/client";
import { useModalAction } from "@homarr/modals";
import { useScopedI18n } from "@homarr/translation/client";
import { revalidatePathActionAsync } from "~/app/revalidatePathAction";
import { UserSelectModal } from "~/components/access/user-select-modal";
import { MobileAffixButton } from "~/components/manage/mobile-affix-button";

View File

@@ -4,11 +4,10 @@ import { useCallback } from "react";
import { Button } from "@mantine/core";
import { clientApi } from "@homarr/api/client";
import { revalidatePathActionAsync } from "@homarr/common/client";
import { useConfirmModal } from "@homarr/modals";
import { useI18n, useScopedI18n } from "@homarr/translation/client";
import { revalidatePathActionAsync } from "~/app/revalidatePathAction";
interface RemoveGroupMemberProps {
groupId: string;
user: { id: string; name: string | null };

View File

@@ -4,13 +4,13 @@ import { useCallback } from "react";
import { Button, Group, Stack, TextInput } from "@mantine/core";
import { clientApi } from "@homarr/api/client";
import { revalidatePathActionAsync } from "@homarr/common/client";
import { useZodForm } from "@homarr/form";
import { createModal, useModalAction } from "@homarr/modals";
import { showErrorNotification, showSuccessNotification } from "@homarr/notifications";
import { useI18n } from "@homarr/translation/client";
import { validation } from "@homarr/validation";
import { revalidatePathActionAsync } from "~/app/revalidatePathAction";
import { MobileAffixButton } from "~/components/manage/mobile-affix-button";
export const AddGroup = () => {

View File

@@ -1,57 +0,0 @@
import Link from "next/link";
import { usePathname } from "next/navigation";
import { Button, CopyButton, Mark, Stack, Text } from "@mantine/core";
import type { RouterOutputs } from "@homarr/api";
import { createModal } from "@homarr/modals";
import { useScopedI18n } from "@homarr/translation/client";
export const InviteCopyModal = createModal<RouterOutputs["invite"]["createInvite"]>(({ actions, innerProps }) => {
const t = useScopedI18n("management.page.user.invite");
const inviteUrl = useInviteUrl(innerProps);
return (
<Stack>
<Text>{t("action.copy.description")}</Text>
{/* TODO: When next-international v2 is released the descriptions bold element can be implemented, see https://github.com/QuiiBz/next-international/pull/361 for progress */}
<Link href={createPath(innerProps)}>{t("action.copy.link")}</Link>
<Stack gap="xs">
<Text fw="bold">{t("field.id.label")}:</Text>
<Mark style={{ borderRadius: 4 }} color="gray" px={5}>
{innerProps.id}
</Mark>
<Text fw="bold">{t("field.token.label")}:</Text>
<Mark style={{ borderRadius: 4 }} color="gray" px={5}>
{innerProps.token}
</Mark>
</Stack>
<CopyButton value={inviteUrl}>
{({ copy }) => (
<Button
onClick={() => {
copy();
actions.closeModal();
}}
variant="default"
fullWidth
>
{t("action.copy.button")}
</Button>
)}
</CopyButton>
</Stack>
);
}).withOptions({
defaultTitle(t) {
return t("management.page.user.invite.action.copy.title");
},
});
const createPath = ({ id, token }: RouterOutputs["invite"]["createInvite"]) => `/auth/invite/${id}?token=${token}`;
const useInviteUrl = ({ id, token }: RouterOutputs["invite"]["createInvite"]) => {
const pathname = usePathname();
return window.location.href.replace(pathname, createPath({ id, token }));
};

View File

@@ -1,77 +0,0 @@
import React from "react";
import { Button, Group, Stack, Text } from "@mantine/core";
import { DateTimePicker } from "@mantine/dates";
import dayjs from "dayjs";
import relativeTime from "dayjs/plugin/relativeTime";
import { clientApi } from "@homarr/api/client";
import { useForm } from "@homarr/form";
import { createModal, useModalAction } from "@homarr/modals";
import { useI18n, useScopedI18n } from "@homarr/translation/client";
import { InviteCopyModal } from "./invite-copy-modal";
dayjs.extend(relativeTime);
interface FormType {
expirationDate: Date;
}
export const InviteCreateModal = createModal<void>(({ actions }) => {
const tInvite = useScopedI18n("management.page.user.invite");
const t = useI18n();
const { openModal } = useModalAction(InviteCopyModal);
const utils = clientApi.useUtils();
const { mutate, isPending } = clientApi.invite.createInvite.useMutation();
const minDate = dayjs().add(1, "hour").toDate();
const maxDate = dayjs().add(6, "months").toDate();
const form = useForm<FormType>({
initialValues: {
expirationDate: dayjs().add(4, "hours").toDate(),
},
});
const handleSubmit = (values: FormType) => {
mutate(values, {
onSuccess: (result) => {
void utils.invite.getAll.invalidate();
actions.closeModal();
openModal(result);
},
});
};
return (
<form onSubmit={form.onSubmit(handleSubmit)}>
<Stack>
<Text>{tInvite("action.new.description")}</Text>
<DateTimePicker
popoverProps={{ withinPortal: true }}
minDate={minDate}
maxDate={maxDate}
withAsterisk
valueFormat="DD MMM YYYY HH:mm"
label={tInvite("field.expirationDate.label")}
variant="filled"
{...form.getInputProps("expirationDate")}
/>
<Group justify="end">
<Button onClick={actions.closeModal} variant="subtle" color="gray">
{t("common.action.cancel")}
</Button>
<Button type="submit" loading={isPending} color="teal">
{t("common.action.create")}
</Button>
</Group>
</Stack>
</form>
);
}).withOptions({
defaultTitle(t) {
return t("management.page.user.invite.action.new.title");
},
});

View File

@@ -11,11 +11,10 @@ import { MantineReactTable } from "mantine-react-table";
import type { RouterOutputs } from "@homarr/api";
import { clientApi } from "@homarr/api/client";
import { useConfirmModal, useModalAction } from "@homarr/modals";
import { InviteCreateModal } from "@homarr/modals-collection";
import { useScopedI18n } from "@homarr/translation/client";
import { useTranslatedMantineReactTable } from "@homarr/ui/hooks";
import { InviteCreateModal } from "./invite-create-modal";
dayjs.extend(relativeTime);
interface InviteListComponentProps {

View File

@@ -1,7 +0,0 @@
"use server";
import { revalidatePath } from "next/cache";
export async function revalidatePathActionAsync(path: string) {
return new Promise((resolve) => resolve(revalidatePath(path, "page")));
}