commit 4a7bae81d16419bb84cd4794f01264f1bcd5902b
Author: Jaroslav Hrubý <hrubyj@students.zcu.cz>
Date:   Tue Apr 19 13:24:49 2022 +0200

    Documents upload implemented, connected to REST API

diff --git a/webapp/components/modals/AddDocument.tsx b/webapp/components/modals/AddDocument.tsx
deleted file mode 100644
index 6386278..0000000
--- a/webapp/components/modals/AddDocument.tsx
+++ /dev/null
@@ -1,84 +0,0 @@
-import { message, Button, Modal, Upload } from 'antd';
-import { InboxOutlined } from '@ant-design/icons';
-import 'antd/dist/antd.css';
-
-const { Dragger } = Upload;
-
-/**
- * Creates a modal window that loads documents to the app.
- * @returns The modal window.
- */
-export function AddDocument(afterClose: () => {}) {
-    /**
-     * Settings of a file loader.
-     */
-    const props = {
-        name: 'file',
-        multiple: true,
-        directory: true,
-        /**
-            @todo: Probably will be needed to change the uploading URL
-        **/
-        action: 'https://www.mocky.io/v2/5cc8019d300000980a055e76',
-        onChange(info: any) {
-            const { status } = info.file;
-
-            if (status !== 'uploading') {
-                console.log(info.file, info.fileList);
-            }
-
-            if (status === 'done') {
-                message.success(`${info.file.name} file uploaded successfully.`);
-            } else if (status === 'error') {
-                message.error(`${info.file.name} file upload failed.`);
-            }
-        },
-        onDrop(e: any) {
-            console.log('Dropped files', e.dataTransfer.files);
-        },
-    };
-
-    /**
-     * Handles successful closing of the modal window.
-     */
-    const handleOk = () => {
-        /**
-            @todo: Send documents to a server when all files are loaded
-        **/
-        console.log('Document is loaded');
-        afterClose();
-    };
-
-    /**
-     * Handles cancelling of the model window.
-     */
-    const handleCancel = () => {
-        console.log('Loading of documents is cancelled.');
-        afterClose();
-    };
-
-    return (
-        <Modal
-            title="Nový dokument"
-            onOk={handleOk}
-            onCancel={handleCancel}
-            footer={[
-                <Button key="back" onClick={handleCancel}>
-                    Storno
-                </Button>,
-                <Button key="submit" type="primary" onClick={handleOk}>
-                    Nahrát
-                </Button>,
-            ]}
-        >
-            <Dragger>
-                <p className="ant-upload-drag-icon">
-                    <InboxOutlined />
-                </p>
-                <p className="ant-upload-text">
-                    Soubory lze nahrát stisknutím nebo přetažením...
-                </p>
-            </Dragger>
-        </Modal>
-    );
-}
diff --git a/webapp/components/modals/AddDocumentModal.tsx b/webapp/components/modals/AddDocumentModal.tsx
new file mode 100644
index 0000000..cb383c0
--- /dev/null
+++ b/webapp/components/modals/AddDocumentModal.tsx
@@ -0,0 +1,113 @@
+import { Button, Modal, Upload } from 'antd';
+import { InboxOutlined } from '@ant-design/icons';
+import 'antd/dist/antd.css';
+import React from 'react';
+import { DocumentAddInfo, EAddDocumentFormat } from '../../api';
+import { documentController } from '../../controllers';
+
+const { Dragger } = Upload;
+
+interface ModalProps {
+    onCancel: () => void;
+}
+
+/**
+ * Creates a modal window that loads documents to the app.
+ * @returns The modal window.
+ */
+const AddDocumentModal: React.FC<ModalProps> = ({ onCancel }) => {
+    /**
+     * Handles successful closing of the modal window.
+     */
+    const handleOk = () => {
+        onCancel();
+    };
+
+    /**
+     * Handles cancelling of the model window.
+     */
+    const handleCancel = () => {
+        onCancel();
+    };
+
+    const [upload, setUpload] = React.useState(false);
+    const tempDocs: DocumentAddInfo[] = [];
+
+    const handleUpload = () => {
+        if (tempDocs.length !== 0) {
+            setUpload(true);
+            documentController.documentsPost({ documents: tempDocs });
+            setUpload(false);
+        }
+        onCancel();
+    };
+    /**
+     * Settings of a file loader.
+     */
+    const props = {
+        name: 'file',
+        multiple: true,
+        directory: false,
+        onRemove: (file: any) => {
+            let docInfo = tempDocs.find((doc) => {
+                return doc.name === file.name;
+            });
+            if (docInfo) {
+                const index = tempDocs.indexOf(docInfo);
+                const newFileList = tempDocs.slice();
+                newFileList.splice(index, 1);
+            }
+        },
+        beforeUpload: (file: any) => {
+            let docInfo: DocumentAddInfo = { name: file.name };
+            if ('application/x-zip-compressed' === file.type) {
+                docInfo.format = EAddDocumentFormat.Zip;
+            } else if ('text/html' === file.type || 'text/plain' === file.type) {
+                docInfo.format = EAddDocumentFormat.Textfile;
+            }
+
+            const reader = new FileReader();
+            reader.onload = (e) => {
+                if (e.target && e.target.result) {
+                    let content = e.target.result.toString();
+                    docInfo.content = content.split('base64,').pop();
+                }
+            };
+            reader.readAsDataURL(file);
+            tempDocs.push(docInfo);
+        },
+    };
+
+    return (
+        <Modal
+            title="Nový dokument"
+            onOk={handleOk}
+            visible={true}
+            onCancel={handleCancel}
+            footer={[
+                <Button key="back" onClick={handleCancel}>
+                    Storno
+                </Button>,
+                <Button
+                    key="submit"
+                    type="primary"
+                    onClick={handleUpload}
+                    loading={upload}
+                >
+                    Nahrát
+                </Button>,
+            ]}
+        >
+            <Dragger {...props} accept={'.txt, .zip, .html'}>
+                <p className="ant-upload-drag-icon">
+                    <InboxOutlined />
+                </p>
+                <p className="ant-upload-text">
+                    Soubory lze nahrát stisknutím nebo přetažením...
+                </p>
+            </Dragger>
+        </Modal>
+    );
+};
+
+export default AddDocumentModal;
diff --git a/webapp/pages/documents/admin/index.tsx b/webapp/pages/documents/admin/index.tsx
index f898b06..574b5ac 100644
--- a/webapp/pages/documents/admin/index.tsx
+++ b/webapp/pages/documents/admin/index.tsx
@@ -8,10 +8,12 @@ import { faFileLines } from '@fortawesome/free-solid-svg-icons';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { LoggedUserContext } from '../../../contexts/LoggedUserContext';
 import { MainLayout } from '../../../layouts/MainLayout';
+import AddDocumentModal from '../../../components/modals/AddDocumentModal';
 
 function AdminDocumentPage() {
     const redirecting = useUnauthRedirect('/login');
     const { logout, role } = useContext(LoggedUserContext);
+    const [visible, setVisible] = React.useState(false);
     const router = useRouter();
 
     useEffect(() => {
@@ -21,7 +23,11 @@ function AdminDocumentPage() {
     }, [logout, redirecting, role, router]);
 
     const showModal = () => {
-        // TODO show AddDocument component
+        setVisible(true);
+    };
+
+    const hideModal = () => {
+        setVisible(false);
     };
 
     return redirecting || role !== 'ADMINISTRATOR' ? null : (
@@ -32,6 +38,7 @@ function AdminDocumentPage() {
             <Button type={'primary'} onClick={showModal}>
                 Nahrát dokument
             </Button>
+            {visible && <AddDocumentModal onCancel={hideModal} />}
         </MainLayout>
     );
 }
