Revize e8591566
Přidáno uživatelem Václav Honzík před téměř 3 roky(ů)
frontend/package.json | ||
---|---|---|
11 | 11 |
"@mui/material": "^5.5.2", |
12 | 12 |
"@reduxjs/toolkit": "^1.8.1", |
13 | 13 |
"axios": "^0.26.0", |
14 |
"dompurify": "^2.3.6", |
|
14 | 15 |
"dotenv": "^16.0.0", |
15 | 16 |
"formik": "^2.2.9", |
16 | 17 |
"jwt-decode": "^3.1.2", |
17 | 18 |
"leaflet": "^1.8.0", |
18 | 19 |
"react": "^17.0.2", |
19 | 20 |
"react-dom": "^17.0.2", |
21 |
"react-html-parser": "^2.0.2", |
|
20 | 22 |
"react-leaflet": "3.2.5", |
21 | 23 |
"react-leaflet-textpath": "^2.1.1", |
22 | 24 |
"react-redux": "^7.2.6", |
... | ... | |
60 | 62 |
"@testing-library/jest-dom": "^5.14.1", |
61 | 63 |
"@testing-library/react": "^12.0.0", |
62 | 64 |
"@testing-library/user-event": "^13.2.1", |
65 |
"@types/dompurify": "^2.3.3", |
|
63 | 66 |
"@types/jest": "^27.0.1", |
64 | 67 |
"@types/leaflet": "^1.7.9", |
65 | 68 |
"@types/node": "^16.7.13", |
frontend/src/features/Catalog/CatalogItemDetail.tsx | ||
---|---|---|
1 |
import { |
|
2 |
Button, |
|
3 |
Divider, |
|
4 |
Grid, |
|
5 |
Paper, |
|
6 |
Typography, |
|
7 |
} from '@mui/material' |
|
1 |
import { Button, Divider, Grid, Paper, Typography } from '@mui/material' |
|
8 | 2 |
import { Fragment, useEffect, useState } from 'react' |
9 | 3 |
import { useParams } from 'react-router-dom' |
10 | 4 |
import axiosInstance from '../../api/api' |
... | ... | |
14 | 8 |
import CatalogItemMap from './CatalogItemMap' |
15 | 9 |
import ArrowBackIosIcon from '@mui/icons-material/ArrowBackIos' |
16 | 10 |
import { Link as RouterLink } from 'react-router-dom' |
11 |
import DOMPurify from 'dompurify' |
|
12 |
import { formatHtmlStringToReactDom } from '../../utils/formatting/HtmlUtils' |
|
17 | 13 |
|
18 | 14 |
const apiError = |
19 | 15 |
'Error while fetching data from the server, please try again later.' |
... | ... | |
117 | 113 |
<ShowErrorIfPresent err={err} /> |
118 | 114 |
|
119 | 115 |
<Paper style={{ minHeight: '100vh' }} variant="outlined"> |
120 |
|
|
121 | 116 |
{isItemLoading && !err ? <ContentLoading /> : null} |
122 | 117 |
{!isItemLoading && item ? ( |
123 | 118 |
<Grid container justifyContent="space-around"> |
frontend/src/features/Catalog/CatalogTable.tsx | ||
---|---|---|
23 | 23 |
ShowAllItemsOption, |
24 | 24 |
} from './catalogSlice' |
25 | 25 |
import { fetchItems } from './catalogThunks' |
26 |
import { formatHtmlStringToReactDom } from '../../utils/formatting/HtmlUtils' |
|
26 | 27 |
|
27 | 28 |
// Catalog table component |
28 | 29 |
const CatalogTable = () => { |
... | ... | |
94 | 95 |
...textStyle, |
95 | 96 |
}} |
96 | 97 |
> |
97 |
{value || 'N/A'}
|
|
98 |
{formatHtmlStringToReactDom(value as string)}
|
|
98 | 99 |
</Typography> |
99 | 100 |
</TableCell> |
100 | 101 |
) |
frontend/src/utils/formatting/HtmlUtils.tsx | ||
---|---|---|
1 |
import DOMPurify from 'dompurify' |
|
2 |
import { ReactNode } from 'react' |
|
3 |
|
|
4 |
/** |
|
5 |
* Formats HTML string to safe virtual DOM nodes. |
|
6 |
* @param htmlString string to format |
|
7 |
*/ |
|
8 |
export const formatHtmlStringToReactDom = (htmlString: string, defaultValue: string = '-'): ReactNode => { |
|
9 |
if (!htmlString || htmlString.length === 0) { |
|
10 |
return defaultValue |
|
11 |
} |
|
12 |
return ( |
|
13 |
<div dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(htmlString) }} /> |
|
14 |
) |
|
15 |
} |
frontend/src/utils/statePersistence.ts | ||
---|---|---|
1 |
// TODO this could be replaced with redux library |
|
2 |
const persist = (name: string, value: any) => { |
|
3 |
localStorage.setItem(name, JSON.stringify(value)) |
|
4 |
return value |
|
5 |
} |
|
6 |
|
|
7 |
const load = (name: string) => { |
|
8 |
const item = localStorage.getItem(name) |
|
9 |
return item ? JSON.parse(item) : undefined |
|
10 |
} |
|
11 |
|
|
12 |
export { persist, load } |
frontend/src/utils/thunkResponse.ts | ||
---|---|---|
1 |
|
|
2 |
export default interface ThunkResponse<T> { |
|
3 |
success: boolean |
|
4 |
data?: T |
|
5 |
} |
Také k dispozici: Unified diff
DomPurify + Escaping Impl
re #9626