This commit is contained in:
Philipinho
2025-04-16 20:19:16 +01:00
parent 418e61614c
commit 5bdefda9c7
16 changed files with 412 additions and 151 deletions

View File

@ -1,31 +1,83 @@
import {
Button,
Group,
MantineSize,
Popover,
Switch,
Text,
TextInput,
} from "@mantine/core";
import { IconWorld } from "@tabler/icons-react";
import React, { useState } from "react";
import { useShareStatusQuery } from "@/features/share/queries/share-query.ts";
import React, { useEffect, useState } from "react";
import {
useCreateShareMutation,
useShareForPageQuery,
useUpdateShareMutation,
} from "@/features/share/queries/share-query.ts";
import { useParams } from "react-router-dom";
import { extractPageSlugId } from "@/lib";
import { useTranslation } from "react-i18next";
import CopyTextButton from "@/components/common/copy.tsx";
import { getAppUrl } from "@/lib/config.ts";
export default function ShareModal() {
const { t } = useTranslation();
const { pageSlug } = useParams();
const { data } = useShareStatusQuery(extractPageSlugId(pageSlug));
const pageId = extractPageSlugId(pageSlug);
const { data: share } = useShareForPageQuery(pageId);
const createShareMutation = useCreateShareMutation();
const updateShareMutation = useUpdateShareMutation();
// pageIsShared means that the share exists and its level equals zero.
const pageIsShared = share && share.level === 0;
// if level is greater than zero, then it is a descendant page from a shared page
const isDescendantShared = share && share.level > 0;
const publicLink =
window.location.protocol +'//' + window.location.host +
"/share/" +
data?.["share"]?.["key"] +
"/" +
pageSlug;
const publicLink = `${getAppUrl()}/share/${share?.key}/${pageSlug}`;
// TODO: think of permissions
// controls should be read only for non space editors.
// we could use the same shared content but have it have a share status
// when you unshare, we hide the rest menu
// todo, is public only if this is the shared page
// if this is not the shared page and include chdilren == false, then set it to false
const [isPagePublic, setIsPagePublic] = useState<boolean>(false);
useEffect(() => {
if (share) {
setIsPagePublic(true);
} else {
setIsPagePublic(false);
}
}, [share, pageId]);
const handleChange = async (event: React.ChangeEvent<HTMLInputElement>) => {
const value = event.currentTarget.checked;
createShareMutation.mutateAsync({ pageId: pageId });
setIsPagePublic(value);
// on create refetch share
};
const handleSubPagesChange = async (
event: React.ChangeEvent<HTMLInputElement>,
) => {
const value = event.currentTarget.checked;
updateShareMutation.mutateAsync({
shareId: share.id,
includeSubPages: value,
});
};
const handleIndexSearchChange = async (
event: React.ChangeEvent<HTMLInputElement>,
) => {
const value = event.currentTarget.checked;
updateShareMutation.mutateAsync({
shareId: share.id,
searchIndexing: value,
});
};
return (
<Popover width={350} position="bottom" withArrow shadow="md">
@ -39,50 +91,69 @@ export default function ShareModal() {
</Button>
</Popover.Target>
<Popover.Dropdown>
<Group justify="space-between" wrap="nowrap" gap="xl">
<div>
<Text size="md">{t("Make page public")}</Text>
</div>
<ToggleShare isChecked={true}></ToggleShare>
</Group>
{isDescendantShared ? (
<Text>
{t("This page was shared via")} {share.sharedPage.title}
</Text>
) : (
<>
<Group justify="space-between" wrap="nowrap" gap="xl">
<div>
<Text>Share page</Text>
<Text size="xs" c="dimmed">
Make it public to the internet
</Text>
</div>
<Switch
onChange={handleChange}
defaultChecked={isPagePublic}
size="sm"
/>
</Group>
<Group my="sm" grow>
<TextInput
variant="filled"
value={publicLink}
pointer
readOnly
rightSection={<CopyTextButton text={publicLink} />}
/>
</Group>
{pageIsShared && (
<>
<Group my="sm" grow>
<TextInput
variant="filled"
value={publicLink}
readOnly
rightSection={<CopyTextButton text={publicLink} />}
/>
</Group>
<Group justify="space-between" wrap="nowrap" gap="xl">
<div>
<Text>{t("Include sub pages")}</Text>
<Text size="xs" c="dimmed">
Include children of this page
</Text>
</div>
<Switch
onChange={handleSubPagesChange}
checked={share.includeSubPages}
size="xs"
/>
</Group>
<Group justify="space-between" wrap="nowrap" gap="xl" mt="sm">
<div>
<Text>{t("Enable search indexing")}</Text>
<Text size="xs" c="dimmed">
Allow search engine indexing
</Text>
</div>
<Switch
onChange={handleIndexSearchChange}
checked={share.searchIndexing}
size="xs"
/>
</Group>
</>
)}
</>
)}
</Popover.Dropdown>
</Popover>
);
}
interface PageWidthToggleProps {
isChecked: boolean;
size?: MantineSize;
label?: string;
}
export function ToggleShare({ isChecked, size, label }: PageWidthToggleProps) {
const { t } = useTranslation();
const [checked, setChecked] = useState(isChecked);
const handleChange = async (event: React.ChangeEvent<HTMLInputElement>) => {
const value = event.currentTarget.checked;
setChecked(value);
};
return (
<Switch
size={size}
label={label}
labelPosition="left"
defaultChecked={checked}
onChange={handleChange}
aria-label={t("Toggle share")}
/>
);
}