diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 7e90164..f249b29 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -1105,6 +1105,11 @@ "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", "dev": true }, + "attr-accept": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/attr-accept/-/attr-accept-2.2.2.tgz", + "integrity": "sha512-7prDjvt9HmqiZ0cl5CRjtS84sEyhsHP2coDkaZKRKVfCDo9s7iw7ChVmar78Gu9pC4SoR/28wFu/G5JJhTnqEg==" + }, "autoprefixer": { "version": "10.4.13", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.13.tgz", @@ -2168,6 +2173,21 @@ "flat-cache": "^3.0.4" } }, + "file-selector": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/file-selector/-/file-selector-0.6.0.tgz", + "integrity": "sha512-QlZ5yJC0VxHxQQsQhXvBaC7VRJ2uaxTf+Tfpu4Z/OcVQJVpZO+DGU0rkoVW5ce2SccxugvpBJoMvUs59iILYdw==", + "requires": { + "tslib": "^2.4.0" + }, + "dependencies": { + "tslib": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + } + } + }, "fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -3088,8 +3108,7 @@ "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" }, "object-hash": { "version": "3.0.0", @@ -3395,7 +3414,6 @@ "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "dev": true, "requires": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", @@ -3437,6 +3455,16 @@ "scheduler": "^0.23.0" } }, + "react-dropzone": { + "version": "14.2.3", + "resolved": "https://registry.npmjs.org/react-dropzone/-/react-dropzone-14.2.3.tgz", + "integrity": "sha512-O3om8I+PkFKbxCukfIR3QAGftYXDZfOE2N1mr/7qebQJHs7U+/RSL/9xomJNpRg9kM5h9soQSdf0Gc7OHF5Fug==", + "requires": { + "attr-accept": "^2.2.2", + "file-selector": "^0.6.0", + "prop-types": "^15.8.1" + } + }, "react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", diff --git a/frontend/package.json b/frontend/package.json index 4abaeba..16ee4ff 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -23,6 +23,7 @@ "@vercel/analytics": "^0.1.10", "react": "^18.2.0", "react-dom": "^18.2.0", + "react-dropzone": "^14.2.3", "react-redux": "^8.0.5", "react-router-dom": "^6.8.1" }, diff --git a/frontend/src/Navigation.tsx b/frontend/src/Navigation.tsx index a2cedb0..b2b6328 100644 --- a/frontend/src/Navigation.tsx +++ b/frontend/src/Navigation.tsx @@ -7,6 +7,7 @@ import Hamburger from './assets/hamburger.svg'; import Key from './assets/key.svg'; import Info from './assets/info.svg'; import Link from './assets/link.svg'; +import UploadIcon from './assets/upload.svg'; import { ActiveState } from './models/misc'; import APIKeyModal from './preferences/APIKeyModal'; import SelectDocsModal from './preferences/SelectDocsModal'; @@ -19,6 +20,7 @@ import { setSelectedDocs, } from './preferences/preferenceSlice'; import { useOutsideAlerter } from './hooks'; +import Upload from './upload/Upload'; export default function Navigation({ navState, @@ -42,6 +44,9 @@ export default function Navigation({ const [selectedDocsModalState, setSelectedDocsModalState] = useState(isSelectedDocsSet ? 'INACTIVE' : 'ACTIVE'); + const [uploadModalState, setUploadModalState] = + useState('INACTIVE'); + const navRef = useRef(null); useOutsideAlerter( navRef, @@ -109,7 +114,7 @@ export default function Navigation({
-
+
setIsDocsListOpen(!isDocsListOpen)} @@ -127,8 +132,13 @@ export default function Navigation({ } mr-3 w-3 transition-all`} />
+ setUploadModalState('ACTIVE')} + > {isDocsListOpen && ( -
+
{docs ? ( docs.map((doc, index) => { if (doc.model) { @@ -222,6 +232,10 @@ export default function Navigation({ setModalState={setApiKeyModalState} isCancellable={isApiKeySet} /> + ); } diff --git a/frontend/src/assets/upload.svg b/frontend/src/assets/upload.svg new file mode 100644 index 0000000..6d7be21 --- /dev/null +++ b/frontend/src/assets/upload.svg @@ -0,0 +1,3 @@ + + + diff --git a/frontend/src/upload/Upload.tsx b/frontend/src/upload/Upload.tsx new file mode 100644 index 0000000..88afa96 --- /dev/null +++ b/frontend/src/upload/Upload.tsx @@ -0,0 +1,81 @@ +import { useCallback, useState } from 'react'; +import { useDropzone } from 'react-dropzone'; +import { ActiveState } from '../models/misc'; + +export default function Upload({ + modalState, + setModalState, +}: { + modalState: ActiveState; + setModalState: (state: ActiveState) => void; +}) { + const [docName, setDocName] = useState(''); + const [files, setfiles] = useState([]); + + const onDrop = useCallback((acceptedFiles: File[]) => { + setfiles(acceptedFiles); + setDocName(acceptedFiles[0]?.name); + }, []); + + const doNothing = () => undefined; + + const { getRootProps, getInputProps, isDragActive } = useDropzone({ + onDrop, + multiple: true, + onDragEnter: doNothing, + onDragOver: doNothing, + onDragLeave: doNothing, + }); + return ( +
+
+

Upload New Documentation

+ setDocName(e.target.value)} + > +
+ Name +
+
+ +
+
+

Uploaded Files

+ {files.map((file) => ( +

+ {file.name} +

+ ))} + {files.length === 0 &&

None

} +
+
+ + +
+
+
+ ); +} + +// TODO: sanitize all inputs diff --git a/frontend/tailwind.config.cjs b/frontend/tailwind.config.cjs index 2c44007..a824c5c 100644 --- a/frontend/tailwind.config.cjs +++ b/frontend/tailwind.config.cjs @@ -16,10 +16,14 @@ module.exports = { 'gray-2000': 'rgba(0, 0, 0, 0.5)', 'gray-3000': 'rgba(243, 243, 243, 1)', 'gray-4000': '#949494', + 'gray-5000': '#BBBBBB', + 'gray-6000': '#757575', 'red-1000': 'rgb(254, 202, 202)', 'red-2000': '#F44336', 'red-3000': '#621B16', 'blue-1000': '#7D54D1', + 'blue-2000': '#002B49', + 'blue-3000': '#4B02E2', }, }, },