Finished snippet view. Added support for markdown docs

This commit is contained in:
unknown
2021-09-22 13:22:43 +02:00
parent 96a01c6f60
commit 0fe96d3465
10 changed files with 696 additions and 12 deletions

View File

@@ -1,6 +1,9 @@
import { Link } from 'react-router-dom';
import { useContext } from 'react';
import { Snippet } from '../../typescript/interfaces';
import { dateParser } from '../../utils';
import { Card } from '../UI';
import { Badge, Button, Card } from '../UI';
import { SnippetsContext } from '../../store';
interface Props {
snippet: Snippet;
@@ -8,6 +11,7 @@ interface Props {
export const SnippetCard = (props: Props): JSX.Element => {
const { title, description, language, code, id, updatedAt } = props.snippet;
const { setSnippet } = useContext(SnippetsContext);
const copyHandler = () => {
navigator.clipboard.writeText(code);
@@ -18,7 +22,31 @@ export const SnippetCard = (props: Props): JSX.Element => {
<h6 className='card-subtitle mb-2 text-muted'>
{dateParser(updatedAt).relative}
</h6>
<p onClick={copyHandler}>{language}</p>
<p className='text-truncate'>
{description ? description : 'No description'}
</p>
<Badge text={language} color='success' />
<hr />
<div className='d-flex justify-content-end'>
<Link
to={{
pathname: `/snippet/${id}`,
state: { from: window.location.pathname }
}}
>
<Button
text='View'
color='dark'
small
outline
classes='me-2'
handler={() => {
setSnippet(id);
}}
/>
</Link>
<Button text='Copy code' color='dark' small handler={copyHandler} />
</div>
</Card>
);
};

View File

@@ -0,0 +1,17 @@
interface Props {
code: string;
}
export const SnippetCode = (props: Props): JSX.Element => {
return (
<div className='mb-3'>
<textarea
className='form-control'
id='code'
rows={10}
value={props.code}
disabled
></textarea>
</div>
);
};

View File

@@ -57,7 +57,7 @@ export const SnippetDetails = (props: Props): JSX.Element => {
<Button text='Edit' color='dark' small outline classes='me-3' />
</Link>
<Button
text='Pin to homescreen'
text='Pin snippet'
color='dark'
small
outline

View File

@@ -0,0 +1,13 @@
import ReactMarkdown from 'react-markdown';
interface Props {
markdown: string;
}
export const SnippetDocs = (props: Props): JSX.Element => {
return (
<div>
<ReactMarkdown>{props.markdown}</ReactMarkdown>
</div>
);
};

View File

@@ -11,7 +11,7 @@ export const SnippetGrid = (props: Props): JSX.Element => {
return (
<div className='row'>
{snippets.map(snippet => (
<div className='col-12 col-md-6 col-lg-3' key={snippet.id}>
<div className='col-12 col-md-6 col-lg-4' key={snippet.id}>
<SnippetCard snippet={snippet} />
</div>
))}

View File

@@ -3,7 +3,6 @@ import { useLocation, useParams } from 'react-router-dom';
import { SnippetForm } from '../components/Snippets/SnippetForm';
import { Layout, PageHeader } from '../components/UI';
import { SnippetsContext } from '../store';
import { Snippet } from '../typescript/interfaces';
interface Params {
id?: string;
@@ -28,7 +27,7 @@ export const Editor = (): JSX.Element => {
setCurrentSnippet(+id);
setInEdit(true);
}
}, []);
}, [id, setCurrentSnippet]);
return (
<Layout>

View File

@@ -0,0 +1,54 @@
import { Fragment, useContext, useEffect } from 'react';
import { useParams, useLocation } from 'react-router-dom';
import { SnippetCode } from '../components/Snippets/SnippetCode';
import { Layout, PageHeader, Spinner, Card } from '../components/UI';
import { SnippetsContext } from '../store';
import { SnippetDetails } from '../components/Snippets/SnippetDetails';
import { SnippetDocs } from '../components/Snippets/SnippetDocs';
interface Params {
id: string;
}
export const Snippet = (): JSX.Element => {
const { currentSnippet, getSnippetById } = useContext(SnippetsContext);
const { id } = useParams<Params>();
// Get previous location
const location = useLocation<{ from: string }>();
const { from } = location.state || '/snippets';
useEffect(() => {
getSnippetById(+id);
}, []);
return (
<Layout>
{!currentSnippet ? (
<div className='col-12'>
<Spinner />
</div>
) : (
<Fragment>
<PageHeader title='' prevDest={from} />
<div className='row mt-3'>
<div className='col-12 col-md-7 col-lg-8'>
<SnippetCode code={currentSnippet.code} />
</div>
<div className='col-12 col-md-5 col-lg-4'>
<SnippetDetails snippet={currentSnippet} />
</div>
{currentSnippet.docs && (
<div className='col-12'>
<Card title='Snippet documentation'>
<hr />
<SnippetDocs markdown={currentSnippet.docs} />
</Card>
</div>
)}
</div>
</Fragment>
)}
</Layout>
);
};

View File

@@ -1,7 +1,7 @@
import { useEffect, useContext, useState, Fragment } from 'react';
import { SnippetsContext } from '../store';
import { SnippetGrid } from '../components/Snippets/SnippetGrid';
import { Badge, Button, Card, Layout, List, Spinner } from '../components/UI';
import { Badge, Button, Card, Layout, Spinner } from '../components/UI';
import { Snippet } from '../typescript/interfaces';
export const Snippets = (): JSX.Element => {
@@ -9,13 +9,17 @@ export const Snippets = (): JSX.Element => {
useContext(SnippetsContext);
const [filter, setFilter] = useState<string | null>(null);
const [localSnippets, setLocalSnippets] = useState<Snippet[]>([...snippets]);
const [localSnippets, setLocalSnippets] = useState<Snippet[]>([]);
useEffect(() => {
getSnippets();
countSnippets();
}, []);
useEffect(() => {
setLocalSnippets([...snippets]);
}, [snippets]);
const filterHandler = (language: string) => {
setFilter(language);
const filteredSnippets = snippets.filter(s => s.language === language);
@@ -29,7 +33,7 @@ export const Snippets = (): JSX.Element => {
return (
<Layout>
<div className='col-12 col-md-4 col-lg-2'>
<div className='col-12 col-md-4 col-lg-3'>
<Card title='Filter by language'>
<Fragment>
{languageCount.map((el, idx) => {
@@ -38,7 +42,7 @@ export const Snippets = (): JSX.Element => {
return (
<div
className={`d-flex justify-content-between cursor-pointer ${
isActiveFilter && 'text-primary fw-bold'
isActiveFilter && 'text-dark fw-bold'
}`}
key={idx}
onClick={() => filterHandler(el.language)}
@@ -52,7 +56,7 @@ export const Snippets = (): JSX.Element => {
<div className='d-grid mt-3'>
<Button
text='Clear filters'
color='primary'
color='dark'
small
outline
handler={clearFilterHandler}
@@ -60,7 +64,7 @@ export const Snippets = (): JSX.Element => {
</div>
</Card>
</div>
<div className='col-12 col-md-8 col-lg-10'>
<div className='col-12 col-md-8 col-lg-9'>
{snippets.length > 0 ? (
<SnippetGrid snippets={localSnippets} />
) : (