From 68aeb857ddd53f102225309ae9104a0958829456 Mon Sep 17 00:00:00 2001
From: Hilson Shrestha <hilsonshrestha@gmail.com>
Date: Sun, 12 Dec 2021 22:42:39 -0500
Subject: [PATCH] Upload implementation or add via textbox

---
 src/apis/implementation.js                    | 11 +++--
 .../AddImplementationModal.js                 | 48 ++++++++++++++-----
 src/components/Input/Input.js                 | 10 ++--
 src/containers/Algorithm/Algorithm.js         |  4 +-
 .../Implementation/Implementation.js          |  2 +-
 5 files changed, 52 insertions(+), 23 deletions(-)

diff --git a/src/apis/implementation.js b/src/apis/implementation.js
index 16d44db..1c2bcd8 100644
--- a/src/apis/implementation.js
+++ b/src/apis/implementation.js
@@ -14,17 +14,20 @@ export const getImplementations = async (algorithmId) => {
     id: implementation.idImplementation,
     name: implementation.implementationFile,
     algorithmId: implementation.algorithmId,
-    s3Url: implementation.s3Url,
+    s3Url: `https://cs509-thalassa-algorithm-management-system.s3.us-east-2.amazonaws.com/${implementation.s3Url}`,
   }))
 };
 
-export const postImplementation = async (algorithmId, implementationName, code) => {
+export const postImplementation = async (algorithmId, implementationName, code, isUpload, implementationFileFormat, implementationMimeType) => {
   const { response, httpCode } = await request(createImplementationRoute(), {
     method: 'POST',
     body: {
-      implementationFile: implementationName,
+      implementationName,
       algorithmId,
       value: code,
+      isUpload,
+      implementationFileFormat,
+      implementationMimeType,
     },
     auth: true,
   });
@@ -36,6 +39,6 @@ export const postImplementation = async (algorithmId, implementationName, code)
     id: response,
     name: implementationName,
     algorithmId,
-    s3Url: `https://cs509-thalassa-algorithm-management-system.s3.us-east-2.amazonaws.com/implementations/${response}.txt`
+    s3Url: `https://cs509-thalassa-algorithm-management-system.s3.us-east-2.amazonaws.com/implementations/${response}.${implementationFileFormat}`
   };
 };
diff --git a/src/components/AddImplementationModal/AddImplementationModal.js b/src/components/AddImplementationModal/AddImplementationModal.js
index 5f5f164..0deadde 100644
--- a/src/components/AddImplementationModal/AddImplementationModal.js
+++ b/src/components/AddImplementationModal/AddImplementationModal.js
@@ -1,4 +1,4 @@
-import { useCallback, useState, useEffect } from 'react';
+import { useCallback, useState, useEffect, useRef } from 'react';
 import Modal, { ModalBody, ModalHeader, ModalFooter } from '../Modal';
 import Button from '../Button';
 import Input from '../Input';
@@ -8,10 +8,13 @@ const AddImplementationModal = ({ onSave, onClose, show, loading }) => {
   const [code, setCode] = useState('');
   const [codeFile, setCodeFile] = useState('');
   const [codeFileFormat, setCodeFileFormat] = useState('');
+  const [codeFileExtension, setCodeFileExtension] = useState('');
   const [codeMimeType, setCodeMimeType] = useState('');
 
   const [isUpload, setIsUpload] = useState(true);
 
+  const fileRef = useRef(null);
+
   const handleCancel = useCallback(() => {
     setImplementationName('');
     setCode('');
@@ -19,7 +22,13 @@ const AddImplementationModal = ({ onSave, onClose, show, loading }) => {
   }, [onClose, setImplementationName]);
 
   const handleSave = () => {
-    onSave(implementationName, code);
+    onSave(
+      implementationName,
+      isUpload ? codeFile : code,
+      isUpload,
+      isUpload ? codeFileFormat : codeFileExtension,
+      codeMimeType,
+    );
   };
 
   const handleChange = (e) => {
@@ -36,17 +45,15 @@ const AddImplementationModal = ({ onSave, onClose, show, loading }) => {
       return;
     }
     const file = files[0];
-    console.log(file);
 
     let reader = new FileReader();
     reader.readAsDataURL(file);
 
     reader.onload = () => {
-      console.log(reader.result);
       setCodeFile(reader.result);
       setCodeMimeType(file.type);
-      const fname = file.name.split(".");
-      setCodeFileFormat(fname[fname.length - 1])
+      const fname = file.name.split('.');
+      setCodeFileFormat(fname[fname.length - 1]);
     };
   };
 
@@ -58,8 +65,18 @@ const AddImplementationModal = ({ onSave, onClose, show, loading }) => {
     if (!show) {
       setImplementationName('');
       setCode('');
+      setCodeFileFormat('');
+      setCodeFileExtension('');
+      setCodeMimeType('');
+      if (fileRef && fileRef.current) {
+        fileRef.current.value = null;
+      }
     }
-  }, [show, setImplementationName, setCode]);
+  }, [fileRef, show, setImplementationName, setCode]);
+
+  const handleCodeFileExtensionChange = (e) => {
+    setCodeFileExtension(e.target.value);
+  };
 
   return (
     <Modal show={show}>
@@ -67,7 +84,7 @@ const AddImplementationModal = ({ onSave, onClose, show, loading }) => {
       <ModalBody>
         <Input
           label="Implementation Name"
-          name="ImplementationName"
+          name="implementationName"
           onChange={handleChange}
           value={implementationName}
         />
@@ -80,13 +97,22 @@ const AddImplementationModal = ({ onSave, onClose, show, loading }) => {
             checked={isUpload}
           />
           <label className="form-check-label" htmlFor="implementationSwitch">
-            Upload Implementation Code
+            Upload Implementation Code as File
           </label>
         </div>
         {isUpload ? (
-          <Input type="file" label="Upload File" name="codeFile" onChange={handleFileChange} />
+          <Input ref={fileRef} type="file" label="Upload File" name="codeFile" onChange={handleFileChange} />
         ) : (
-          <Input type="textarea" label="Implementation Code" name="code" onChange={handleCodeChange} value={code} />
+          <>
+            <Input type="textarea" label="Implementation Code" name="code" onChange={handleCodeChange} value={code} />
+            <Input
+              label="File Extension"
+              placeholder="eg: py, c, cpp, java"
+              name="codeFileExtension"
+              onChange={handleCodeFileExtensionChange}
+              value={codeFileExtension}
+            />
+          </>
         )}
       </ModalBody>
       <ModalFooter>
diff --git a/src/components/Input/Input.js b/src/components/Input/Input.js
index 67201f1..8dbb7bb 100644
--- a/src/components/Input/Input.js
+++ b/src/components/Input/Input.js
@@ -1,7 +1,7 @@
-import { useState } from 'react';
+import { useState, forwardRef } from 'react';
 import './input.scss';
 
-const Input = ({ type = 'text', label = '', onChange, value }) => {
+const Input = ({ type = 'text', label = '', onChange, value, placeholder="" }, ref) => {
   const [labelId] = useState(() => {
     return `input-${Math.floor(Math.random() * 1000000)}`;
   });
@@ -9,12 +9,12 @@ const Input = ({ type = 'text', label = '', onChange, value }) => {
     <div className="input mb-2">
       {label && <label htmlFor={labelId}>{label}</label>}
       {type === 'textarea' ? (
-        <textarea id={labelId} className="form-control" onChange={onChange} value={value} />
+        <textarea ref={ref} id={labelId} className="form-control" onChange={onChange} value={value} />
       ) : (
-        <input id={labelId} type={type} className="form-control" onChange={onChange} value={value} />
+        <input ref={ref} id={labelId} type={type} className="form-control" onChange={onChange} value={value} placeholder={placeholder} />
       )}
     </div>
   );
 };
 
-export default Input;
+export default forwardRef(Input);
diff --git a/src/containers/Algorithm/Algorithm.js b/src/containers/Algorithm/Algorithm.js
index 436abc8..2e9dc1c 100644
--- a/src/containers/Algorithm/Algorithm.js
+++ b/src/containers/Algorithm/Algorithm.js
@@ -45,14 +45,14 @@ function Algorithm({ algorithm, level = 0, user = null }) {
   }, [setAlgorithmModalOpen]);
 
   const createImplementation = useCallback(
-    async (implementationName, code) => {
+    async (implementationName, code, isUpload, implementationFileName, implementationMimeType) => {
       let mounted = true;
       if (!implementationName) {
         alert('Enter implementation name');
         return () => (mounted = false);
       }
       setCreateImplementationLoading(true);
-      const response = await postImplementation(algorithm.id, implementationName, code);
+      const response = await postImplementation(algorithm.id, implementationName, code, isUpload, implementationFileName, implementationMimeType);
       if (mounted) {
         if (response) {
           setImplementations([...implementations, response]);
diff --git a/src/containers/Implementation/Implementation.js b/src/containers/Implementation/Implementation.js
index 6a39361..49f58fe 100644
--- a/src/containers/Implementation/Implementation.js
+++ b/src/containers/Implementation/Implementation.js
@@ -24,7 +24,7 @@ function Implementation({ implementation, user }) {
           ></div> */}
           <div className="flex-grow-1">
             {implementation.name}{' '}
-            <a href={implementation.s3Url} target="_blank" rel="noreferrer">
+            <a href={implementation.s3Url} download>
               Download
             </a>
           </div>
-- 
GitLab