mirror of
https://github.com/docmost/docmost.git
synced 2025-11-20 05:11:07 +10:00
feat: home space list (#1400)
This commit is contained in:
@ -1,4 +1,4 @@
|
||||
import { Text, Avatar, SimpleGrid, Card, rem } from "@mantine/core";
|
||||
import { Text, Avatar, SimpleGrid, Card, rem, Group, Button } from "@mantine/core";
|
||||
import React, { useEffect } from 'react';
|
||||
import {
|
||||
prefetchSpace,
|
||||
@ -9,10 +9,11 @@ import { Link } from "react-router-dom";
|
||||
import classes from "./space-grid.module.css";
|
||||
import { formatMemberCount } from "@/lib";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { IconArrowRight } from "@tabler/icons-react";
|
||||
|
||||
export default function SpaceGrid() {
|
||||
const { t } = useTranslation();
|
||||
const { data, isLoading } = useGetSpacesQuery({ page: 1 });
|
||||
const { data, isLoading } = useGetSpacesQuery({ page: 1, limit: 9 });
|
||||
|
||||
const cards = data?.items.map((space, index) => (
|
||||
<Card
|
||||
@ -46,11 +47,25 @@ export default function SpaceGrid() {
|
||||
|
||||
return (
|
||||
<>
|
||||
<Text fz="sm" fw={500} mb={"md"}>
|
||||
{t("Spaces you belong to")}
|
||||
</Text>
|
||||
<Group justify="space-between" align="center" mb="md">
|
||||
<Text fz="sm" fw={500}>
|
||||
{t("Spaces you belong to")}
|
||||
</Text>
|
||||
</Group>
|
||||
|
||||
<SimpleGrid cols={{ base: 1, xs: 2, sm: 3 }}>{cards}</SimpleGrid>
|
||||
|
||||
<Group justify="flex-end" mt="lg">
|
||||
<Button
|
||||
component={Link}
|
||||
to="/spaces"
|
||||
variant="subtle"
|
||||
rightSection={<IconArrowRight size={16} />}
|
||||
size="sm"
|
||||
>
|
||||
{t("View all spaces")}
|
||||
</Button>
|
||||
</Group>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@ -0,0 +1,10 @@
|
||||
.spaceLink {
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
|
||||
&:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,160 @@
|
||||
import {
|
||||
Table,
|
||||
Text,
|
||||
Group,
|
||||
ActionIcon,
|
||||
Box,
|
||||
Space,
|
||||
Menu,
|
||||
Avatar,
|
||||
Anchor,
|
||||
} from "@mantine/core";
|
||||
import { IconDots, IconSettings } from "@tabler/icons-react";
|
||||
import { Link } from "react-router-dom";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useState } from "react";
|
||||
import { useDisclosure } from "@mantine/hooks";
|
||||
import { formatMemberCount } from "@/lib";
|
||||
import { getSpaceUrl } from "@/lib/config";
|
||||
import { prefetchSpace } from "@/features/space/queries/space-query";
|
||||
import { SearchInput } from "@/components/common/search-input";
|
||||
import Paginate from "@/components/common/paginate";
|
||||
import NoTableResults from "@/components/common/no-table-results";
|
||||
import SpaceSettingsModal from "@/features/space/components/settings-modal";
|
||||
import classes from "./all-spaces-list.module.css";
|
||||
|
||||
interface AllSpacesListProps {
|
||||
spaces: any[];
|
||||
onSearch: (query: string) => void;
|
||||
page: number;
|
||||
hasPrevPage?: boolean;
|
||||
hasNextPage?: boolean;
|
||||
onPageChange: (page: number) => void;
|
||||
}
|
||||
|
||||
export default function AllSpacesList({
|
||||
spaces,
|
||||
onSearch,
|
||||
page,
|
||||
hasPrevPage,
|
||||
hasNextPage,
|
||||
onPageChange,
|
||||
}: AllSpacesListProps) {
|
||||
const { t } = useTranslation();
|
||||
const [settingsOpened, { open: openSettings, close: closeSettings }] =
|
||||
useDisclosure(false);
|
||||
const [selectedSpaceId, setSelectedSpaceId] = useState<string | null>(null);
|
||||
|
||||
const handleOpenSettings = (spaceId: string) => {
|
||||
setSelectedSpaceId(spaceId);
|
||||
openSettings();
|
||||
};
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<SearchInput onSearch={onSearch} />
|
||||
|
||||
<Space h="md" />
|
||||
|
||||
<Table.ScrollContainer minWidth={500}>
|
||||
<Table highlightOnHover verticalSpacing="sm">
|
||||
<Table.Thead>
|
||||
<Table.Tr>
|
||||
<Table.Th>{t("Space")}</Table.Th>
|
||||
<Table.Th>{t("Members")}</Table.Th>
|
||||
<Table.Th w={100}></Table.Th>
|
||||
</Table.Tr>
|
||||
</Table.Thead>
|
||||
|
||||
<Table.Tbody>
|
||||
{spaces.length > 0 ? (
|
||||
spaces.map((space) => (
|
||||
<Table.Tr key={space.id}>
|
||||
<Table.Td>
|
||||
<Anchor
|
||||
size="sm"
|
||||
underline="never"
|
||||
style={{
|
||||
cursor: "pointer",
|
||||
color: "var(--mantine-color-text)",
|
||||
}}
|
||||
component={Link}
|
||||
to={getSpaceUrl(space.slug)}
|
||||
>
|
||||
<Group
|
||||
gap="sm"
|
||||
wrap="nowrap"
|
||||
className={classes.spaceLink}
|
||||
onMouseEnter={() => prefetchSpace(space.slug, space.id)}
|
||||
>
|
||||
<Avatar
|
||||
color="initials"
|
||||
variant="filled"
|
||||
name={space.name}
|
||||
size={40}
|
||||
/>
|
||||
<div>
|
||||
<Text fz="sm" fw={500} lineClamp={1}>
|
||||
{space.name}
|
||||
</Text>
|
||||
{space.description && (
|
||||
<Text fz="xs" c="dimmed" lineClamp={2}>
|
||||
{space.description}
|
||||
</Text>
|
||||
)}
|
||||
</div>
|
||||
</Group>
|
||||
</Anchor>
|
||||
</Table.Td>
|
||||
<Table.Td>
|
||||
<Text size="sm" style={{ whiteSpace: "nowrap" }}>
|
||||
{formatMemberCount(space.memberCount, t)}
|
||||
</Text>
|
||||
</Table.Td>
|
||||
<Table.Td>
|
||||
<Group gap="xs" justify="flex-end">
|
||||
<Menu position="bottom-end">
|
||||
<Menu.Target>
|
||||
<ActionIcon variant="subtle" color="gray">
|
||||
<IconDots size={16} />
|
||||
</ActionIcon>
|
||||
</Menu.Target>
|
||||
<Menu.Dropdown>
|
||||
<Menu.Item
|
||||
leftSection={<IconSettings size={16} />}
|
||||
onClick={() => handleOpenSettings(space.id)}
|
||||
>
|
||||
{t("Space settings")}
|
||||
</Menu.Item>
|
||||
</Menu.Dropdown>
|
||||
</Menu>
|
||||
</Group>
|
||||
</Table.Td>
|
||||
</Table.Tr>
|
||||
))
|
||||
) : (
|
||||
<NoTableResults colSpan={3} />
|
||||
)}
|
||||
</Table.Tbody>
|
||||
</Table>
|
||||
</Table.ScrollContainer>
|
||||
|
||||
{spaces.length > 0 && (
|
||||
<Paginate
|
||||
currentPage={page}
|
||||
hasPrevPage={hasPrevPage}
|
||||
hasNextPage={hasNextPage}
|
||||
onPageChange={onPageChange}
|
||||
/>
|
||||
)}
|
||||
|
||||
{selectedSpaceId && (
|
||||
<SpaceSettingsModal
|
||||
spaceId={selectedSpaceId}
|
||||
opened={settingsOpened}
|
||||
onClose={closeSettings}
|
||||
/>
|
||||
)}
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
@ -0,0 +1 @@
|
||||
export { default as AllSpacesList } from "./all-spaces-list";
|
||||
Reference in New Issue
Block a user