diff --git a/app/controllers/shared_collections_controller.ts b/app/controllers/shared_collections_controller.ts
index fd2d971..8ee8899 100644
--- a/app/controllers/shared_collections_controller.ts
+++ b/app/controllers/shared_collections_controller.ts
@@ -1,27 +1,61 @@
import { Visibility } from '#enums/visibility';
import Collection from '#models/collection';
+import Link from '#models/link';
+import User from '#models/user';
import { getSharedCollectionValidator } from '#validators/shared_collection';
import type { HttpContext } from '@adonisjs/core/http';
+class LinkWithoutFavoriteDto {
+ constructor(private link: Link) {}
+
+ toJson = () => ({
+ id: this.link.id,
+ name: this.link.name,
+ description: this.link.description,
+ url: this.link.url,
+ collectionId: this.link.collectionId,
+ createdAt: this.link.createdAt.toString(),
+ updatedAt: this.link.updatedAt.toString(),
+ });
+}
+
+class UserWithoutEmailDto {
+ constructor(private user: User) {}
+
+ toJson = () => ({
+ id: this.user.id,
+ fullname: this.user.name,
+ avatarUrl: this.user.avatarUrl,
+ isAdmin: this.user.isAdmin,
+ createdAt: this.user.createdAt.toString(),
+ updatedAt: this.user.updatedAt.toString(),
+ });
+}
+
export default class SharedCollectionsController {
- async index({ request, response }: HttpContext) {
+ async index({ request, inertia }: HttpContext) {
const { params } = await request.validateUsing(
getSharedCollectionValidator
);
const collection = await this.getSharedCollectionById(params.id);
- console.log('shared page', collection);
- // TODO: return view
- return response.json(collection);
- // return inertia.render('shared', { collection });
+ return inertia.render('shared', { collection });
}
private async getSharedCollectionById(id: Collection['id']) {
- return await Collection.query()
+ const collection = await Collection.query()
.where('id', id)
.andWhere('visibility', Visibility.PUBLIC)
.preload('links')
.preload('author')
.firstOrFail();
+
+ return {
+ ...collection.serialize(),
+ links: collection.links.map((link) =>
+ new LinkWithoutFavoriteDto(link).toJson()
+ ),
+ author: new UserWithoutEmailDto(collection.author).toJson(),
+ };
}
}
diff --git a/inertia/components/dashboard/favorite/item/favorite_item.tsx b/inertia/components/dashboard/favorite/item/favorite_item.tsx
index e85121e..17e0aec 100644
--- a/inertia/components/dashboard/favorite/item/favorite_item.tsx
+++ b/inertia/components/dashboard/favorite/item/favorite_item.tsx
@@ -1,7 +1,7 @@
import { Card, Group, Text } from '@mantine/core';
import { ExternalLinkStyled } from '~/components/common/external_link_styled';
-import LinkControls from '~/components/dashboard/link/link_controls';
-import LinkFavicon from '~/components/dashboard/link/link_favicon';
+import LinkFavicon from '~/components/dashboard/link/item/favicon/link_favicon';
+import LinkControls from '~/components/dashboard/link/item/link_controls';
import { LinkWithCollection } from '~/types/app';
import styles from './favorite_item.module.css';
diff --git a/inertia/components/dashboard/link/link_favicon.module.css b/inertia/components/dashboard/link/item/favicon/link_favicon.module.css
similarity index 100%
rename from inertia/components/dashboard/link/link_favicon.module.css
rename to inertia/components/dashboard/link/item/favicon/link_favicon.module.css
diff --git a/inertia/components/dashboard/link/link_favicon.tsx b/inertia/components/dashboard/link/item/favicon/link_favicon.tsx
similarity index 100%
rename from inertia/components/dashboard/link/link_favicon.tsx
rename to inertia/components/dashboard/link/item/favicon/link_favicon.tsx
diff --git a/inertia/components/dashboard/link/link.module.css b/inertia/components/dashboard/link/item/link.module.css
similarity index 100%
rename from inertia/components/dashboard/link/link.module.css
rename to inertia/components/dashboard/link/item/link.module.css
diff --git a/inertia/components/dashboard/link/link_controls.tsx b/inertia/components/dashboard/link/item/link_controls.tsx
similarity index 81%
rename from inertia/components/dashboard/link/link_controls.tsx
rename to inertia/components/dashboard/link/item/link_controls.tsx
index d73debd..8a257ad 100644
--- a/inertia/components/dashboard/link/link_controls.tsx
+++ b/inertia/components/dashboard/link/item/link_controls.tsx
@@ -10,10 +10,10 @@ import { MdFavorite, MdFavoriteBorder } from 'react-icons/md';
import { onFavorite } from '~/lib/favorite';
import { appendCollectionId, appendLinkId } from '~/lib/navigation';
import { useFavorites } from '~/stores/collection_store';
-import { Link } from '~/types/app';
+import { Link, PublicLink } from '~/types/app';
interface LinksControlsProps {
- link: Link;
+ link: Link | PublicLink;
showGoToCollection?: boolean;
}
export default function LinkControls({
@@ -42,15 +42,17 @@ export default function LinkControls({
{t('go-to-collection')}
)}
-
- onFavorite(link.id, !link.favorite, onFavoriteCallback)
- }
- leftSection={link.favorite ? : }
- color="var(--mantine-color-yellow-7)"
- >
- {link.favorite ? t('remove-favorite') : t('add-favorite')}
-
+ {'favorite' in link && (
+
+ onFavorite(link.id, !link.favorite, onFavoriteCallback)
+ }
+ leftSection={link.favorite ? : }
+ color="var(--mantine-color-yellow-7)"
+ >
+ {link.favorite ? t('remove-favorite') : t('add-favorite')}
+
+ )}
@@ -21,13 +21,12 @@ export default function LinkItem({
- {name}{' '}
- {showUserControls && favorite && }
+ {name} {showFavoriteIcon && }
- {showUserControls && }
+ {!hideMenu && }
{description && (
diff --git a/inertia/components/dashboard/link/list/link_list.tsx b/inertia/components/dashboard/link/list/link_list.tsx
new file mode 100644
index 0000000..3195a76
--- /dev/null
+++ b/inertia/components/dashboard/link/list/link_list.tsx
@@ -0,0 +1,24 @@
+import { Stack } from '@mantine/core';
+import { LinkItem } from '~/components/dashboard/link/item/link_item';
+import { NoLink } from '~/components/dashboard/link/no_link/no_link';
+import { useActiveCollection } from '~/stores/collection_store';
+
+export interface LinkListProps {
+ hideMenu?: boolean;
+}
+
+export function LinkList({ hideMenu = false }: LinkListProps) {
+ const { activeCollection } = useActiveCollection();
+
+ if (!activeCollection?.links || activeCollection.links.length === 0) {
+ return ;
+ }
+
+ return (
+
+ {activeCollection?.links.map((link) => (
+
+ ))}
+
+ );
+}
diff --git a/inertia/components/dashboard/link/no_link.module.css b/inertia/components/dashboard/link/no_link/no_link.module.css
similarity index 100%
rename from inertia/components/dashboard/link/no_link.module.css
rename to inertia/components/dashboard/link/no_link/no_link.module.css
diff --git a/inertia/components/dashboard/link/no_link.tsx b/inertia/components/dashboard/link/no_link/no_link.tsx
similarity index 66%
rename from inertia/components/dashboard/link/no_link.tsx
rename to inertia/components/dashboard/link/no_link/no_link.tsx
index 98c4b47..a216aab 100644
--- a/inertia/components/dashboard/link/no_link.tsx
+++ b/inertia/components/dashboard/link/no_link/no_link.tsx
@@ -2,11 +2,14 @@ import { Link } from '@inertiajs/react';
import { route } from '@izzyjs/route/client';
import { Anchor, Box, Text } from '@mantine/core';
import { useTranslation } from 'react-i18next';
+import type { LinkListProps } from '~/components/dashboard/link/list/link_list';
import { appendCollectionId } from '~/lib/navigation';
import { useActiveCollection } from '~/stores/collection_store';
import styles from './no_link.module.css';
-export function NoLink() {
+interface NoLinkProps extends LinkListProps {}
+
+export function NoLink({ hideMenu }: NoLinkProps) {
const { t } = useTranslation('common');
const { activeCollection } = useActiveCollection();
return (
@@ -23,15 +26,17 @@ export function NoLink() {
),
}}
/>
-
- {t('link.create')}
-
+ {!hideMenu && (
+
+ {t('link.create')}
+
+ )}
);
}
diff --git a/inertia/i18n/locales/en/admin.json b/inertia/i18n/locales/en/admin.json
index 33ac3bc..7b3f6ac 100644
--- a/inertia/i18n/locales/en/admin.json
+++ b/inertia/i18n/locales/en/admin.json
@@ -2,8 +2,6 @@
"role": "Role",
"created_at": "Created at",
"last_seen_at": "Last seen at",
- "admin": "Administrator",
- "user": "User",
"users": "Users",
"stats": "Statistics"
}
\ No newline at end of file
diff --git a/inertia/i18n/locales/en/common.json b/inertia/i18n/locales/en/common.json
index af39f58..9614bce 100644
--- a/inertia/i18n/locales/en/common.json
+++ b/inertia/i18n/locales/en/common.json
@@ -27,7 +27,8 @@
"edit": "Edit a collection",
"delete": "Delete a collection",
"delete-confirm": "Confirm deletion?",
- "delete-description": "You must delete all links in this collection before you can delete this collection."
+ "delete-description": "You must delete all links in this collection before you can delete this collection.",
+ "managed-by": "Collection managed by {{name}}"
},
"form": {
"name": "Name",
@@ -55,6 +56,7 @@
"go-to-collection": "Go to collection",
"no-item-found": "No item found",
"admin": "Administrator",
+ "user": "User",
"search": "Search",
"search-with": "Search with",
"avatar": "{{name}}'s avatar",
diff --git a/inertia/i18n/locales/fr/admin.json b/inertia/i18n/locales/fr/admin.json
index 0811c1e..635350c 100644
--- a/inertia/i18n/locales/fr/admin.json
+++ b/inertia/i18n/locales/fr/admin.json
@@ -2,8 +2,6 @@
"role": "Rôle",
"created_at": "Création",
"last_seen_at": "Dernière connexion",
- "admin": "Administrateur",
- "user": "Utilisateur",
"users": "Utilisateurs",
"stats": "Statistiques"
}
\ No newline at end of file
diff --git a/inertia/i18n/locales/fr/common.json b/inertia/i18n/locales/fr/common.json
index f68e0ba..5967b9a 100644
--- a/inertia/i18n/locales/fr/common.json
+++ b/inertia/i18n/locales/fr/common.json
@@ -27,7 +27,8 @@
"edit": "Modifier une collection",
"delete": "Supprimer une collection",
"delete-confirm": "Confirmer la suppression ?",
- "delete-description": "Vous devez supprimer tous les liens de cette collection avant de pouvoir supprimer cette collection"
+ "delete-description": "Vous devez supprimer tous les liens de cette collection avant de pouvoir supprimer cette collection",
+ "managed-by": "Collection gérée par {{name}}"
},
"form": {
"name": "Nom",
@@ -54,7 +55,8 @@
"favorites-appears-here": "Vos favoris apparaîtront ici",
"go-to-collection": "Voir la collection",
"no-item-found": "Aucun élément trouvé",
- "admin": "Administrateur",
+ "admin": "Administrateur",
+ "user": "Utilisateur",
"search": "Rechercher",
"search-with": "Rechercher avec",
"avatar": "Avatar de {{name}}",
diff --git a/inertia/pages/dashboard.tsx b/inertia/pages/dashboard.tsx
index be945b7..6f5f3bc 100644
--- a/inertia/pages/dashboard.tsx
+++ b/inertia/pages/dashboard.tsx
@@ -1,13 +1,12 @@
import { router } from '@inertiajs/react';
import { route } from '@izzyjs/route/client';
-import { AppShell, ScrollArea, Stack } from '@mantine/core';
+import { AppShell, ScrollArea } from '@mantine/core';
import { useDisclosure } from '@mantine/hooks';
import { useEffect } from 'react';
import { DashboardAside } from '~/components/dashboard/dashboard_aside';
import { DashboardHeader } from '~/components/dashboard/dashboard_header';
import { DashboardNavbar } from '~/components/dashboard/dashboard_navbar';
-import LinkItem from '~/components/dashboard/link/link_item';
-import { NoLink } from '~/components/dashboard/link/no_link';
+import { LinkList } from '~/components/dashboard/link/list/link_list';
import { MantineFooter } from '~/components/footer/footer';
import { useDisableOverflow } from '~/hooks/use_disable_overflow';
import useShortcut from '~/hooks/use_shortcut';
@@ -69,16 +68,16 @@ export default function MantineDashboard(props: Readonly) {
}
);
+ const headerHeight = !!activeCollection?.description
+ ? HEADER_SIZE_WITH_DESCRIPTION
+ : HEADER_SIZE_WITHOUT_DESCRIPTION;
+ const footerHeight = 45;
return (
) {
breakpoint: 'md',
collapsed: { mobile: !openedAside },
}}
+ footer={{ height: footerHeight }}
classNames={{
aside: classes.ml_custom_class,
footer: classes.ml_custom_class,
@@ -103,20 +103,12 @@ export default function MantineDashboard(props: Readonly) {
/>
- {activeCollection?.links && activeCollection.links.length > 0 ? (
-
-
- {activeCollection?.links.map((link) => (
-
- ))}
-
-
- ) : (
-
- )}
+
+
+
diff --git a/inertia/pages/shared.tsx b/inertia/pages/shared.tsx
new file mode 100644
index 0000000..f3b43fa
--- /dev/null
+++ b/inertia/pages/shared.tsx
@@ -0,0 +1,48 @@
+import { Flex, Text } from '@mantine/core';
+import { ReactNode, useEffect } from 'react';
+import { useTranslation } from 'react-i18next';
+import { LinkList } from '~/components/dashboard/link/list/link_list';
+import { ContentLayout } from '~/layouts/content_layout';
+import { useCollectionsSetter } from '~/stores/collection_store';
+import type { CollectionWithLinks, PublicUser } from '~/types/app';
+
+interface SharedPageProps {
+ collection: CollectionWithLinks & { author: PublicUser };
+}
+
+function SharedPage({ collection }: SharedPageProps) {
+ const { t } = useTranslation('common');
+ const { setActiveCollection } = useCollectionsSetter();
+
+ useEffect(() => {
+ setActiveCollection(collection);
+ }, []);
+
+ return (
+ <>
+
+ {collection.name}
+
+ {collection.description}
+
+
+
+
+
+
+ >
+ );
+}
+
+SharedPage.layout = (page: ReactNode) => {page};
+export default SharedPage;
diff --git a/inertia/types/app.d.ts b/inertia/types/app.d.ts
index 4bafdba..79d716e 100644
--- a/inertia/types/app.d.ts
+++ b/inertia/types/app.d.ts
@@ -14,6 +14,8 @@ type User = CommonBase & {
lastSeenAt: string;
};
+type PublicUser = Omit;
+
type Users = User[];
type UserWithCollections = User & {
@@ -42,6 +44,9 @@ type LinkWithCollection = Link & {
collection: Collection;
};
+type PublicLink = Omit;
+type PublicLinkWithCollection = Omit;
+
type Collection = CommonBase & {
name: string;
description: string | null;