commit ae770857cdfa9a64ff3e52196df17031cf72e9f1
Author: Schwobik <michal.schwob@seznam.cz>
Date:   Sun May 15 19:33:45 2022 +0200

    Sources page implemented
    re #9811

diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx
index 6bbeea1..5e90012 100644
--- a/frontend/src/App.tsx
+++ b/frontend/src/App.tsx
@@ -18,6 +18,8 @@ import Notification from './features/Notification/Notification'
 import { Fragment } from 'react'
 import Administration from "./features/Administration/Administration"
 import Register from "./features/Auth/Register"
+import Bibliography from "./features/Bibliography/Bibliography"
+import EditBibliography from "./features/Bibliography/EditBibliography"
 
 const App = () => {
     return (
@@ -39,6 +41,8 @@ const App = () => {
                             <Route path="/logout" element={<Logout />} />
                             <Route path="/map" element={<TrackingTool />} />
                             <Route path="/administration" element={<Administration />}/>
+                            <Route path="/sources" element={<Bibliography />}/>
+                            <Route path="/editSources" element={<EditBibliography />}/>
                             <Route path="*" element={<NotFound />} />
                         </Routes>
                     </Box>
diff --git a/frontend/src/features/Bibliography/Bibliography.tsx b/frontend/src/features/Bibliography/Bibliography.tsx
new file mode 100644
index 0000000..41421cb
--- /dev/null
+++ b/frontend/src/features/Bibliography/Bibliography.tsx
@@ -0,0 +1,87 @@
+import {Button, Container, Paper, Typography} from '@mui/material'
+import {Fragment, useEffect, useState} from 'react'
+import { useDispatch, useSelector } from 'react-redux'
+import { logout } from '../Auth/userSlice'
+import { RootState } from '../redux/store'
+import {SourcesDto, TitlePageDto} from "../../swagger/data-contracts"
+import axiosInstance from "../../api/api"
+import 'react-quill/dist/quill.snow.css'
+import ContentLoading from "../Reusables/ContentLoading"
+import EditBibliography from "./EditBibliography"
+import {Link as RouterLink, useNavigate} from "react-router-dom"
+import EditIcon from '@mui/icons-material/Edit'
+import { formatHtmlStringToReactDom } from "../../utils/formatting/HtmlUtils"
+
+
+const apiError =
+    'Error while fetching data from the server, please try again later.'
+
+const Bibliography = () => {
+    const [sources, setSources] = useState<SourcesDto | undefined>(undefined)
+    const [isContentLoading, setIsContentLoading] = useState(true)
+    const [err, setErr] = useState<string | undefined>(undefined)
+
+    let navigate = useNavigate()
+    const openEditHomePage = () => {
+        let path = '/editBibliography'
+        navigate(path)
+    }
+
+    const isAdmin = useSelector(
+        (state: RootState) => state.user.roles.includes("ROLE_ADMIN")
+    )
+    // Fetch the item from the api after mounting the component
+    useEffect(() => {
+        // Function to fetch the item from the api
+        const fetchItem = async () => {
+            try {
+                const { data, status } = await axiosInstance.get(
+                    `/sources`
+                )
+                if (status !== 200) {
+                    setErr(apiError)
+                    return
+                }
+
+                setSources(data)
+                setIsContentLoading(false)
+            } catch (err: any) {
+                setErr(apiError)
+            }
+        }
+        fetchItem()
+    }, [])
+
+    return (
+        <Fragment>
+            <Typography variant="h3" sx={{ mb: 2 }} fontWeight="bold">
+                Sources
+            </Typography>
+            <Paper style={{ minHeight: '80vh', display:'flex', justifyContent: 'space-between', flexDirection:'column'}} variant="outlined">
+                {isContentLoading && !err ? <ContentLoading /> : null}
+                {!isContentLoading && sources ? (
+                    <Container sx={{ mt: 4 }}>
+                        {formatHtmlStringToReactDom(sources["sources"] as string)}
+                    </Container>
+                ) : null}
+
+                {isAdmin ? (
+                    <Container sx={{ mb: 3 }} >
+                            <Button
+                                startIcon={<EditIcon />}
+                                variant="contained"
+                                component={RouterLink}
+                                to="/editSources"
+                                color="primary"
+                                sx={{ mb: 2 }}
+                            >
+                                Edit
+                            </Button>
+                    </Container>
+                ) : null}
+            </Paper>
+        </Fragment>
+    )
+}
+
+export default Bibliography
diff --git a/frontend/src/features/Bibliography/EditBibliography.tsx b/frontend/src/features/Bibliography/EditBibliography.tsx
new file mode 100644
index 0000000..a9d42ff
--- /dev/null
+++ b/frontend/src/features/Bibliography/EditBibliography.tsx
@@ -0,0 +1,99 @@
+import {Button, Paper} from '@mui/material'
+import {Fragment, useEffect, useState} from 'react'
+import { useDispatch, useSelector } from 'react-redux'
+import { logout } from '../Auth/userSlice'
+import { RootState } from '../redux/store'
+import {SourcesDto} from "../../swagger/data-contracts"
+import axiosInstance from "../../api/api"
+import ReactQuill from "react-quill"
+import 'react-quill/dist/quill.snow.css'
+import ContentLoading from "../Reusables/ContentLoading"
+import {Link as RouterLink, useNavigate} from "react-router-dom"
+import ArrowBackIosIcon from "@mui/icons-material/ArrowBackIos"
+
+
+const apiError =
+    'Error while fetching data from the server, please try again later.'
+
+const EditBibliography = () => {
+    const [sources, setSources] = useState<SourcesDto | undefined>(undefined)
+    const [isContentLoading, setIsContentLoading] = useState(true)
+    const [err, setErr] = useState<string | undefined>(undefined)
+
+    const navigate = useNavigate()
+
+    const updateContent = (updated: string) => {
+        if (sources) {
+            sources["sources"] = updated
+        }
+    }
+
+    const handleSubmit = () => {
+        postData()
+    }
+
+    const postData = async () => {
+        const {data, status} = await axiosInstance.post('/sources', sources)
+        if (status != 200) {
+            console.error("Sources page data submitting failed.")
+        }
+    }
+
+    const roles = useSelector(
+        (state: RootState) => state.user.roles
+    )
+
+    // Fetch the item from the api after mounting the component
+    useEffect(() => {
+        // Function to fetch the item from the api
+        const fetchItem = async () => {
+            try {
+                const { data, status } = await axiosInstance.get(
+                    `/sources`
+                )
+                if (status !== 200) {
+                    setErr(apiError)
+                    return
+                }
+
+                setSources(data)
+                setIsContentLoading(false)
+            } catch (err: any) {
+                setErr(apiError)
+            }
+        }
+
+        fetchItem()
+    }, [])
+
+    return (
+        <Fragment>
+            <Button
+                startIcon={<ArrowBackIosIcon />}
+                variant="contained"
+                component={RouterLink}
+                to="/sources"
+                color="primary"
+                sx={{ mb: 2 }}
+            >
+                Return To Bibliography
+            </Button>
+            <Paper style={{ minHeight: '100vh' }} variant="outlined">
+    {isContentLoading && !err ? <ContentLoading /> : null}
+    {!isContentLoading && sources ? (
+        <form>
+            <Button type="button" onClick={handleSubmit}>Submit</Button>
+            <ReactQuill
+                theme='snow'
+                value={sources["sources"]}
+                onChange={updateContent}
+                style={{minHeight: '300px'}}
+                />
+        </form>
+    ) : null}
+    </Paper>
+    </Fragment>
+)
+}
+
+export default EditBibliography
