Skip to content

Commit 0fe96d3

Browse files
committed
Finished snippet view. Added support for markdown docs
1 parent 96a01c6 commit 0fe96d3

File tree

10 files changed

+696
-12
lines changed

10 files changed

+696
-12
lines changed

client/package-lock.json

+568
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

client/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
"dayjs": "^1.10.7",
1616
"react": "^17.0.2",
1717
"react-dom": "^17.0.2",
18+
"react-markdown": "^7.0.1",
1819
"react-router-dom": "^5.3.0",
1920
"react-scripts": "4.0.3",
2021
"typescript": "^4.4.3",

client/src/components/Snippets/SnippetCard.tsx

+30-2
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
1+
import { Link } from 'react-router-dom';
2+
import { useContext } from 'react';
13
import { Snippet } from '../../typescript/interfaces';
24
import { dateParser } from '../../utils';
3-
import { Card } from '../UI';
5+
import { Badge, Button, Card } from '../UI';
6+
import { SnippetsContext } from '../../store';
47

58
interface Props {
69
snippet: Snippet;
710
}
811

912
export const SnippetCard = (props: Props): JSX.Element => {
1013
const { title, description, language, code, id, updatedAt } = props.snippet;
14+
const { setSnippet } = useContext(SnippetsContext);
1115

1216
const copyHandler = () => {
1317
navigator.clipboard.writeText(code);
@@ -18,7 +22,31 @@ export const SnippetCard = (props: Props): JSX.Element => {
1822
<h6 className='card-subtitle mb-2 text-muted'>
1923
{dateParser(updatedAt).relative}
2024
</h6>
21-
<p onClick={copyHandler}>{language}</p>
25+
<p className='text-truncate'>
26+
{description ? description : 'No description'}
27+
</p>
28+
<Badge text={language} color='success' />
29+
<hr />
30+
<div className='d-flex justify-content-end'>
31+
<Link
32+
to={{
33+
pathname: `/snippet/${id}`,
34+
state: { from: window.location.pathname }
35+
}}
36+
>
37+
<Button
38+
text='View'
39+
color='dark'
40+
small
41+
outline
42+
classes='me-2'
43+
handler={() => {
44+
setSnippet(id);
45+
}}
46+
/>
47+
</Link>
48+
<Button text='Copy code' color='dark' small handler={copyHandler} />
49+
</div>
2250
</Card>
2351
);
2452
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
interface Props {
2+
code: string;
3+
}
4+
5+
export const SnippetCode = (props: Props): JSX.Element => {
6+
return (
7+
<div className='mb-3'>
8+
<textarea
9+
className='form-control'
10+
id='code'
11+
rows={10}
12+
value={props.code}
13+
disabled
14+
></textarea>
15+
</div>
16+
);
17+
};

client/src/components/Snippets/SnippetDetails.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ export const SnippetDetails = (props: Props): JSX.Element => {
5757
<Button text='Edit' color='dark' small outline classes='me-3' />
5858
</Link>
5959
<Button
60-
text='Pin to homescreen'
60+
text='Pin snippet'
6161
color='dark'
6262
small
6363
outline
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import ReactMarkdown from 'react-markdown';
2+
3+
interface Props {
4+
markdown: string;
5+
}
6+
7+
export const SnippetDocs = (props: Props): JSX.Element => {
8+
return (
9+
<div>
10+
<ReactMarkdown>{props.markdown}</ReactMarkdown>
11+
</div>
12+
);
13+
};

client/src/components/Snippets/SnippetGrid.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ export const SnippetGrid = (props: Props): JSX.Element => {
1111
return (
1212
<div className='row'>
1313
{snippets.map(snippet => (
14-
<div className='col-12 col-md-6 col-lg-3' key={snippet.id}>
14+
<div className='col-12 col-md-6 col-lg-4' key={snippet.id}>
1515
<SnippetCard snippet={snippet} />
1616
</div>
1717
))}

client/src/containers/Editor.tsx

+1-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import { useLocation, useParams } from 'react-router-dom';
33
import { SnippetForm } from '../components/Snippets/SnippetForm';
44
import { Layout, PageHeader } from '../components/UI';
55
import { SnippetsContext } from '../store';
6-
import { Snippet } from '../typescript/interfaces';
76

87
interface Params {
98
id?: string;
@@ -28,7 +27,7 @@ export const Editor = (): JSX.Element => {
2827
setCurrentSnippet(+id);
2928
setInEdit(true);
3029
}
31-
}, []);
30+
}, [id, setCurrentSnippet]);
3231

3332
return (
3433
<Layout>

client/src/containers/Snippet.tsx

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import { Fragment, useContext, useEffect } from 'react';
2+
import { useParams, useLocation } from 'react-router-dom';
3+
import { SnippetCode } from '../components/Snippets/SnippetCode';
4+
import { Layout, PageHeader, Spinner, Card } from '../components/UI';
5+
import { SnippetsContext } from '../store';
6+
import { SnippetDetails } from '../components/Snippets/SnippetDetails';
7+
import { SnippetDocs } from '../components/Snippets/SnippetDocs';
8+
9+
interface Params {
10+
id: string;
11+
}
12+
13+
export const Snippet = (): JSX.Element => {
14+
const { currentSnippet, getSnippetById } = useContext(SnippetsContext);
15+
const { id } = useParams<Params>();
16+
17+
// Get previous location
18+
const location = useLocation<{ from: string }>();
19+
const { from } = location.state || '/snippets';
20+
21+
useEffect(() => {
22+
getSnippetById(+id);
23+
}, []);
24+
25+
return (
26+
<Layout>
27+
{!currentSnippet ? (
28+
<div className='col-12'>
29+
<Spinner />
30+
</div>
31+
) : (
32+
<Fragment>
33+
<PageHeader title='' prevDest={from} />
34+
<div className='row mt-3'>
35+
<div className='col-12 col-md-7 col-lg-8'>
36+
<SnippetCode code={currentSnippet.code} />
37+
</div>
38+
<div className='col-12 col-md-5 col-lg-4'>
39+
<SnippetDetails snippet={currentSnippet} />
40+
</div>
41+
{currentSnippet.docs && (
42+
<div className='col-12'>
43+
<Card title='Snippet documentation'>
44+
<hr />
45+
<SnippetDocs markdown={currentSnippet.docs} />
46+
</Card>
47+
</div>
48+
)}
49+
</div>
50+
</Fragment>
51+
)}
52+
</Layout>
53+
);
54+
};

client/src/containers/Snippets.tsx

+10-6
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,25 @@
11
import { useEffect, useContext, useState, Fragment } from 'react';
22
import { SnippetsContext } from '../store';
33
import { SnippetGrid } from '../components/Snippets/SnippetGrid';
4-
import { Badge, Button, Card, Layout, List, Spinner } from '../components/UI';
4+
import { Badge, Button, Card, Layout, Spinner } from '../components/UI';
55
import { Snippet } from '../typescript/interfaces';
66

77
export const Snippets = (): JSX.Element => {
88
const { snippets, languageCount, getSnippets, countSnippets } =
99
useContext(SnippetsContext);
1010

1111
const [filter, setFilter] = useState<string | null>(null);
12-
const [localSnippets, setLocalSnippets] = useState<Snippet[]>([...snippets]);
12+
const [localSnippets, setLocalSnippets] = useState<Snippet[]>([]);
1313

1414
useEffect(() => {
1515
getSnippets();
1616
countSnippets();
1717
}, []);
1818

19+
useEffect(() => {
20+
setLocalSnippets([...snippets]);
21+
}, [snippets]);
22+
1923
const filterHandler = (language: string) => {
2024
setFilter(language);
2125
const filteredSnippets = snippets.filter(s => s.language === language);
@@ -29,7 +33,7 @@ export const Snippets = (): JSX.Element => {
2933

3034
return (
3135
<Layout>
32-
<div className='col-12 col-md-4 col-lg-2'>
36+
<div className='col-12 col-md-4 col-lg-3'>
3337
<Card title='Filter by language'>
3438
<Fragment>
3539
{languageCount.map((el, idx) => {
@@ -38,7 +42,7 @@ export const Snippets = (): JSX.Element => {
3842
return (
3943
<div
4044
className={`d-flex justify-content-between cursor-pointer ${
41-
isActiveFilter && 'text-primary fw-bold'
45+
isActiveFilter && 'text-dark fw-bold'
4246
}`}
4347
key={idx}
4448
onClick={() => filterHandler(el.language)}
@@ -52,15 +56,15 @@ export const Snippets = (): JSX.Element => {
5256
<div className='d-grid mt-3'>
5357
<Button
5458
text='Clear filters'
55-
color='primary'
59+
color='dark'
5660
small
5761
outline
5862
handler={clearFilterHandler}
5963
/>
6064
</div>
6165
</Card>
6266
</div>
63-
<div className='col-12 col-md-8 col-lg-10'>
67+
<div className='col-12 col-md-8 col-lg-9'>
6468
{snippets.length > 0 ? (
6569
<SnippetGrid snippets={localSnippets} />
6670
) : (

0 commit comments

Comments
 (0)