Skip to content

Commit

Permalink
Update KnowledgeBase Panel with Tags Component #55
Browse files Browse the repository at this point in the history
  • Loading branch information
kevenleone committed Oct 13, 2023
1 parent 4717bda commit e98e274
Show file tree
Hide file tree
Showing 7 changed files with 157 additions and 120 deletions.
2 changes: 1 addition & 1 deletion apps/mdreader/app/components/blurhash-fallback/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ type BlurhashFallbackProps = {
blurhash?: string;
description: string;
src: string;
blurHashProps: Partial<typeof Blurhash.defaultProps>
blurHashProps?: Partial<typeof Blurhash.defaultProps>;
};

const BlurhashFallback: React.FC<BlurhashFallbackProps> = ({
Expand Down
91 changes: 91 additions & 0 deletions apps/mdreader/app/components/knowledge-group/knowledge-card.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import {
Separator,
AvatarFallback,
AvatarImage,
Avatar,
} from '@mdreader/interface';
import { Link } from '@remix-run/react';
import { Link as LinkIcon, Flag as FlagIcon } from 'lucide-react';

import BlurhashFallback from '../blurhash-fallback';
import { getInitials } from '~/utils';
import { Profile } from '~/types';

type KnowledgeCardProps = {
blurhash?: string;
description: string;
image?: string;
owner: Profile;
tags: string[];
url: string;
};

const KnowledgeCard: React.FC<KnowledgeCardProps> = ({
blurhash,
description,
image,
owner,
tags,
url,
}) => (
<div className="max-w-xs rounded overflow-hidden shadow-lg flex flex-col justify-between border p-4">
{image && (
<BlurhashFallback
blurhash={blurhash}
description={description}
src={image}
/>
)}

<div className="py-4">
<p className="dark:text-gray-300 text-gray-800 text-base mb-2">
{description}
</p>

<a
className="text-sm text-blue-500"
href={url}
target="_blank"
rel="noopener noreferrer"
>
{url}
</a>
</div>

{tags?.length && (
<div className="pt-4 pb-2">
{tags.map((tag, index) => (
<Link
to={`?tag=${tag}`}
className="inline-block bg-gray-200 rounded-full px-3 py-1 text-sm font-semibold text-gray-700 mr-2 mb-2"
key={index}
>
#{tag}
</Link>
))}
</div>
)}

<div>
<Separator />

<div className="flex items-center gap-2 mt-2">
<Avatar>
<AvatarFallback>{getInitials(owner.name)}</AvatarFallback>
<AvatarImage src={owner.photo} />
</Avatar>

<Link className="w-full" to={`/profile/${owner.login}`}>
{owner.name}
</Link>

<div className="flex gap-2 cursor-pointer">
<LinkIcon size={16} />
<FlagIcon size={16} />
</div>
</div>
</div>
</div>
);

export default KnowledgeCard;
41 changes: 26 additions & 15 deletions apps/mdreader/app/hooks/useKnowledgeBase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,23 +32,34 @@ export const useKnowledgeBase = (slug: string) => {
);
};

export const useKnowledgeBases = (knowledgeGroupId: number) => {
export const useKnowledgeBases = (
knowledgeGroupId: number,
options: { search: string }
) => {
const service = useKnowledgeBaseService();

return useSWR(`/knowledge-bases/${knowledgeGroupId}`, () =>
service.getAll({
filters: [
{
property: 'knowledge_group_id',
operator: 'eq',
value: knowledgeGroupId,
return useSWR(
`/knowledge-bases/${knowledgeGroupId}?search=${options.search}`,
() =>
service.getAll({
filters: [
{
property: 'knowledge_group_id',
operator: 'eq',
value: knowledgeGroupId,
},
{
active: !!options.search,
property: 'tags',
operator: 'cs',
value: `{${options.search}}`,
},
],
order: {
ascending: false,
property: 'created_at',
},
],
order: {
ascending: false,
property: 'created_at',
},
select: '*, owner(*)',
})
select: '*, owner(*)',
})
);
};
11 changes: 6 additions & 5 deletions apps/mdreader/app/root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { SWRConfig } from 'swr';
import { useState } from 'react';
import { Toaster } from '@mdreader/interface';
import { cssBundleHref } from '@remix-run/css-bundle';
import type { LinksFunction, LoaderArgs } from '@remix-run/node';
import type { LinksFunction, LoaderFunctionArgs } from '@remix-run/node';
import {
Links,
LiveReload,
Expand Down Expand Up @@ -37,12 +37,12 @@ export const links: LinksFunction = () => [
function localStorageProvider() {
if (global?.window) {
const map = new Map(
JSON.parse(sessionStorage.getItem('app-cache') || '[]')
JSON.parse(sessionStorage.getItem('@mdreader/swr-cache') || '[]')
);

window.addEventListener('beforeunload', () => {
const appCache = JSON.stringify(Array.from(map.entries()));
sessionStorage.setItem('app-cache', appCache);
sessionStorage.setItem('@mdreader/swr-cache', appCache);
});

return map as any;
Expand All @@ -51,7 +51,7 @@ function localStorageProvider() {
return new Map();
}

export async function loader({ request }: LoaderArgs) {
export async function loader({ request }: LoaderFunctionArgs) {
const ENV = {
SUPABASE_KEY: process.env.SUPABASE_KEY as string,
SUPABASE_URL: process.env.SUPABASE_URL as string,
Expand Down Expand Up @@ -118,11 +118,12 @@ export function ErrorBoundary({ error, ...props }: any) {
return (
<html>
<head>
<title>Oh no!</title>
<title>Oops... | MD Reader</title>
<Meta />
<Links />
</head>
<body>
<div>Unable to load page</div>
{JSON.stringify(error, null, 2)}
{/* add the UI you want your users to see */}
<Scripts />
Expand Down
24 changes: 15 additions & 9 deletions apps/mdreader/app/routes/_index.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { Button } from '@mdreader/interface';
import { LoaderArgs } from '@remix-run/node';
import { V2_MetaFunction } from '@remix-run/react';
import { Button, buttonVariants } from '@mdreader/interface';
import { LoaderFunctionArgs } from '@remix-run/node';
import { MetaFunction } from '@remix-run/react';
import { Github } from 'lucide-react';

export const meta: V2_MetaFunction = ({ data: { origin } }) => {
export const meta: MetaFunction = ({ data }) => {
const origin = (data as any).origin;
return [
{ title: 'Home | MD Reader' },
{
Expand All @@ -29,18 +30,18 @@ export const meta: V2_MetaFunction = ({ data: { origin } }) => {
];
};

export const loader = ({ request }: LoaderArgs) => ({
export const loader = ({ request }: LoaderFunctionArgs) => ({
origin: new URL(request.url).origin,
});

export default function MarkdownPreview() {
return (
<div className="container flex flex-col justify-center overflow-hidden items-center min-h-[800px] gap-6 pb-8 pt-6 md:py-10">
<div className="max-w-3xl space-y-8">
<h1 className="text-9xl p-4 text-center font-bold from-purple-600 via-pink-600 to-blue-600 bg-gradient-to-r bg-clip-text text-transparent">
<h1 className="xl:text-9xl transition-all text-6xl p-4 text-center font-bold from-purple-600 via-pink-600 to-blue-600 bg-gradient-to-r bg-clip-text text-transparent">
MD Reader
</h1>
<p className=" text-xl text-muted-foreground">
<p className="text-lg xl:text-2xl text-muted-foreground">
Effortlessly organize your favorite Markdown into 'Articles' that are
both easy to manage and share with others. Say goodbye to cluttered
notes and hello to a sleek, streamlined system that puts your ideas
Expand All @@ -49,9 +50,14 @@ export default function MarkdownPreview() {

<div className="flex gap-3">
<Button>Start Explore</Button>
<Button variant="outline">
<a
className={buttonVariants({ variant: 'outline' })}
href="https://github.com/kevenleone/mdreader"
target="_blank"
rel="noopenner noreferrer"
>
<Github className="mr-2" /> Github
</Button>
</a>
</div>
</div>
</div>
Expand Down
100 changes: 11 additions & 89 deletions apps/mdreader/app/routes/knowledge-groups.$slug._index.tsx
Original file line number Diff line number Diff line change
@@ -1,105 +1,25 @@
import {
Avatar,
AvatarFallback,
AvatarImage,
Separator,
} from '@mdreader/interface';
import { Link, useOutletContext } from '@remix-run/react';
import { useLocation, useOutletContext } from '@remix-run/react';
import { Session } from '@supabase/supabase-js';
import { Link as LinkIcon, Flag as FlagIcon } from 'lucide-react';
import BlurhashFallback from '~/components/blurhash-fallback';
import EmptyState from '~/components/empty-state';
import KnowledgeCard from '~/components/knowledge-group/knowledge-card';

import KnowledgePanel from '~/components/panels/KnowledgePanel';
import { useKnowledgeBases } from '~/hooks/useKnowledgeBase';
import { KnowledgeGroup as IKnowledgeGroup, Profile } from '~/types';
import { getInitials } from '~/utils';

type KnowledgeCardProps = {
blurhash?: string;
description: string;
image?: string;
owner: Profile;
tags: string[];
url: string;
};

const KnowledgeCard: React.FC<KnowledgeCardProps> = ({
blurhash,
description,
image,
owner,
tags,
url,
}) => (
<div className="max-w-xs rounded overflow-hidden shadow-lg flex flex-col justify-between border p-4">
{image && (
<BlurhashFallback
blurHashProps={{}}
blurhash={blurhash}
description={description}
src={image}
/>
)}

<div className="py-4">
<p className="dark:text-gray-300 text-gray-800 text-base mb-2">
{description}
</p>

<a
className="text-sm text-blue-500"
href={url}
target="_blank"
rel="noopener noreferrer"
>
{url}
</a>
</div>

{tags?.length && (
<div className="pt-4 pb-2">
{tags.map((tag, index) => (
<span
className="inline-block bg-gray-200 rounded-full px-3 py-1 text-sm font-semibold text-gray-700 mr-2 mb-2"
key={index}
>
#{tag}
</span>
))}
</div>
)}

<div>
<Separator />

<div className="flex items-center gap-2 mt-2">
<Avatar>
<AvatarFallback>{getInitials(owner.name)}</AvatarFallback>
<AvatarImage src={owner.photo} />
</Avatar>

<Link className="w-full" to={`/profile/${owner.login}`}>
{owner.name}
</Link>

<div className="flex gap-2 cursor-pointer">
<LinkIcon size={16} />
<FlagIcon size={16} />
</div>
</div>
</div>
</div>
);
import { KnowledgeGroup as IKnowledgeGroup } from '~/types';

type OutletContext = {
knowledgeGroup: IKnowledgeGroup;
session: Session | null;
};

const KnowledgeGroup = () => {
const { search } = useLocation();
const tag = new URLSearchParams(search).get('tag') as string;

const { knowledgeGroup, session } = useOutletContext<OutletContext>();
const { data, isLoading, mutate } = useKnowledgeBases(knowledgeGroup.id);
const { data, isLoading, mutate } = useKnowledgeBases(knowledgeGroup.id, {
search: tag,
});

const knowledgeBases = data?.data ?? [];
const hasKnowledgeBase = knowledgeBases.length > 0;
Expand All @@ -112,6 +32,8 @@ const KnowledgeGroup = () => {
<p className="text-muted-foreground">
What about meet a new techonlogy every day? :)
</p>

{tag && <span>Filter applied: {tag}</span>}
</div>

{session && hasKnowledgeBase && (
Expand Down
Loading

0 comments on commit e98e274

Please sign in to comment.