From 851443f19f3a8805485f484139e0dbd7f024442f Mon Sep 17 00:00:00 2001 From: afazio1 Date: Sun, 21 Apr 2024 00:21:25 -0400 Subject: [PATCH 1/4] get basic results page working --- frontend/src/App.tsx | 14 ++++++---- frontend/src/screens/MainSearch.tsx | 11 +------- frontend/src/screens/Results.tsx | 37 +++++++++++++++++--------- frontend/src/styles/App.css | 5 ++++ frontend/src/styles/Results.module.css | 24 ++++++++++++++--- frontend/src/types/types.ts | 24 +++++++++++++++++ frontend/src/utils/getAuthHeaders.ts | 10 +++++++ 7 files changed, 93 insertions(+), 32 deletions(-) create mode 100644 frontend/src/utils/getAuthHeaders.ts diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index a2b5d29..c97b420 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -37,7 +37,7 @@ function Navbar() { background: '#B1D4E0', padding: '8px 16px', borderRadius: '5px', - margin: '0 5px' + // margin: '0 5px' }; const session = useContext(SessionContext); const logout = () => { @@ -47,10 +47,14 @@ function Navbar() { const links = session ? ( <> - PeerNotes Logo - Home - Search - Logout +
+ PeerNotes Logo + Home + Search +
+
+ Logout +
): ( Login diff --git a/frontend/src/screens/MainSearch.tsx b/frontend/src/screens/MainSearch.tsx index 6f3b840..ff519ff 100644 --- a/frontend/src/screens/MainSearch.tsx +++ b/frontend/src/screens/MainSearch.tsx @@ -1,7 +1,7 @@ import React, { useState, useEffect } from 'react'; import { useNavigate } from 'react-router-dom'; import '../styles/MainScreenWrapper.css'; -import { getSessionCookie } from '../contexts/session'; +import { getAuthHeaders } from '../utils/getAuthHeaders'; import { Professor, Course, Topic } from "../types/types"; interface Filters extends Record { @@ -30,15 +30,6 @@ const MainSearch: React.FC = () => { fetchTopics(); }, []); - const getAuthHeaders = () => { - const token = getSessionCookie(); - // const token = localStorage.getItem('authToken'); - console.log("Using token for API call:", token); - return { - 'Authorization': `Token ${token}`, - 'Content-Type': 'application/json' - }; - }; const fetchProfessors = async () => { try { diff --git a/frontend/src/screens/Results.tsx b/frontend/src/screens/Results.tsx index b8fb0ce..df3d4ef 100644 --- a/frontend/src/screens/Results.tsx +++ b/frontend/src/screens/Results.tsx @@ -1,15 +1,8 @@ import React, { useState, useEffect } from 'react'; import { useLocation, useNavigate } from 'react-router-dom'; import styles from '../styles/Results.module.css'; // Make sure this path is correct - -interface File { - id: string; - name: string; // do we even use id and name? - professor: string; - course: string; - type?: string; // Assumed type is optional - // what other properties to add?semester? -} +import { getAuthHeaders } from '../utils/getAuthHeaders'; +import { File } from '../types/types'; const Results: React.FC = () => { const [files, setFiles] = useState([]); @@ -23,7 +16,8 @@ const Results: React.FC = () => { try { // Need to double check this const queryString = location.search; // Includes the '?' prefix - const response = await fetch(`/api/path-to-filefilterview${queryString}`); + console.log(queryString) + const response = await fetch(`http://localhost:8000/api/files/filter${queryString}`, {headers: getAuthHeaders()}); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } @@ -55,9 +49,26 @@ const Results: React.FC = () => { {isLoading ? (

Loading...

) : files.length ? ( - - {/* Table structure here */} -
+ files.map((file) => ( + <> +
+

{file.filename}

+

Course: {file.course.name} {file.course.number}

+

Professor: {file.professor.name}

+

Semester: {file.semester.name}

+

Upvotes: {file.upvotes.length}

+

Downvotes: {file.downvotes.length}

+
+
+

{file.filename}

+

Course: {file.course.name} {file.course.number}

+

Professor: {file.professor.name}

+

Semester: {file.semester.name}

+

Upvotes: {file.upvotes.length}

+

Downvotes: {file.downvotes.length}

+
+ + )) ) : (

No results found.

)} diff --git a/frontend/src/styles/App.css b/frontend/src/styles/App.css index b77c0f5..8d255d0 100644 --- a/frontend/src/styles/App.css +++ b/frontend/src/styles/App.css @@ -14,6 +14,11 @@ nav { z-index: 1000; box-sizing: border-box; } +nav div { + display: flex; + align-items: center; + gap: 1rem; +} .App { display: flex; flex-direction: column; diff --git a/frontend/src/styles/Results.module.css b/frontend/src/styles/Results.module.css index 30223ec..88bbef0 100644 --- a/frontend/src/styles/Results.module.css +++ b/frontend/src/styles/Results.module.css @@ -27,17 +27,33 @@ flex-direction: column; align-items: center; justify-content: center; - padding-top: 100px; /* Adjust based on header height to ensure content doesn't overlap */ + margin: auto; - width: 90%; - max-width: 600px; + width: 100vh; + gap: 1rem; } .resultsTable { /* to be filled out */ width: 100%; } - + .fileCard p { + background-color: #1f4f7c; + padding: 1rem; + border-radius: 5px; + } + .fileCard { + display: flex; + flex-direction: row; + align-items: center; + justify-content: center; + padding: 20px; + gap: 1rem; + background-color: #145DA0; + border-radius: 8px; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); + min-width: 100vh; + } .searchAgainButton { height: 50px; diff --git a/frontend/src/types/types.ts b/frontend/src/types/types.ts index ff5b577..579b27b 100644 --- a/frontend/src/types/types.ts +++ b/frontend/src/types/types.ts @@ -12,4 +12,28 @@ export interface Topic { id: number; name: string; description: string; +} + +export interface Semester { + id: number; + name: string; +} + +export interface User { + id: string; + username: string; + email: string; + ip_address: string; + points: number; +} + +export interface File { + id: string; + filename: string; + original_author: User; + professor: Professor; + course: Course; + semester: Semester; + upvotes: number[]; + downvotes: number[]; } \ No newline at end of file diff --git a/frontend/src/utils/getAuthHeaders.ts b/frontend/src/utils/getAuthHeaders.ts new file mode 100644 index 0000000..35b4cc5 --- /dev/null +++ b/frontend/src/utils/getAuthHeaders.ts @@ -0,0 +1,10 @@ +import { getSessionCookie } from "../contexts/session"; +export const getAuthHeaders = () => { + const token = getSessionCookie(); + // const token = localStorage.getItem('authToken'); + console.log("Using token for API call:", token); + return { + 'Authorization': `Token ${token}`, + 'Content-Type': 'application/json' + }; + }; \ No newline at end of file From 09cc971466fc45868d57e6654ea9d1413b7213a8 Mon Sep 17 00:00:00 2001 From: afazio1 Date: Sun, 21 Apr 2024 00:40:49 -0400 Subject: [PATCH 2/4] remove console.logs --- frontend/src/screens/MainSearch.tsx | 2 -- frontend/src/utils/getAuthHeaders.ts | 2 -- 2 files changed, 4 deletions(-) diff --git a/frontend/src/screens/MainSearch.tsx b/frontend/src/screens/MainSearch.tsx index ff519ff..c65377a 100644 --- a/frontend/src/screens/MainSearch.tsx +++ b/frontend/src/screens/MainSearch.tsx @@ -38,10 +38,8 @@ const MainSearch: React.FC = () => { headers: getAuthHeaders(), }); const data = await response.json(); - console.log("Professors fetched:", data); if (Array.isArray(data)) { - console.log("Professors fetched:", data); setProfessors(data); } else { console.error('Data fetched is not an array:', data); diff --git a/frontend/src/utils/getAuthHeaders.ts b/frontend/src/utils/getAuthHeaders.ts index 35b4cc5..2c7870d 100644 --- a/frontend/src/utils/getAuthHeaders.ts +++ b/frontend/src/utils/getAuthHeaders.ts @@ -1,8 +1,6 @@ import { getSessionCookie } from "../contexts/session"; export const getAuthHeaders = () => { const token = getSessionCookie(); - // const token = localStorage.getItem('authToken'); - console.log("Using token for API call:", token); return { 'Authorization': `Token ${token}`, 'Content-Type': 'application/json' From ae25f65fdd1cc0a13c9b959107e2066d41783d97 Mon Sep 17 00:00:00 2001 From: afazio1 Date: Sun, 21 Apr 2024 00:50:09 -0400 Subject: [PATCH 3/4] add download button --- frontend/src/screens/Results.tsx | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/frontend/src/screens/Results.tsx b/frontend/src/screens/Results.tsx index df3d4ef..573477a 100644 --- a/frontend/src/screens/Results.tsx +++ b/frontend/src/screens/Results.tsx @@ -50,7 +50,6 @@ const Results: React.FC = () => {

Loading...

) : files.length ? ( files.map((file) => ( - <>

{file.filename}

Course: {file.course.name} {file.course.number}

@@ -58,16 +57,8 @@ const Results: React.FC = () => {

Semester: {file.semester.name}

Upvotes: {file.upvotes.length}

Downvotes: {file.downvotes.length}

+

Download

-
-

{file.filename}

-

Course: {file.course.name} {file.course.number}

-

Professor: {file.professor.name}

-

Semester: {file.semester.name}

-

Upvotes: {file.upvotes.length}

-

Downvotes: {file.downvotes.length}

-
- )) ) : (

No results found.

From b460067dfa8262b4a5821e51c5c735da196e936e Mon Sep 17 00:00:00 2001 From: afazio1 Date: Sun, 21 Apr 2024 15:42:12 -0400 Subject: [PATCH 4/4] add upload file boilerplate + changes to results page --- frontend/src/App.tsx | 4 +- frontend/src/main.tsx | 5 ++ frontend/src/screens/MainSearch.tsx | 30 +++++++++++- frontend/src/screens/RegisterFile.tsx | 66 ++++++++++++++++++++++++++ frontend/src/screens/Results.tsx | 39 ++++++++++----- frontend/src/styles/App.css | 5 ++ frontend/src/styles/RegisterFile.css | 48 +++++++++++++++++++ frontend/src/styles/Results.module.css | 15 ++++++ frontend/src/types/types.ts | 8 ++++ 9 files changed, 206 insertions(+), 14 deletions(-) create mode 100644 frontend/src/screens/RegisterFile.tsx create mode 100644 frontend/src/styles/RegisterFile.css diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index c97b420..27f8456 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -23,7 +23,7 @@ export default function App() { <> -
+
@@ -49,7 +49,7 @@ function Navbar() { <>
PeerNotes Logo - Home + Upload Search
diff --git a/frontend/src/main.tsx b/frontend/src/main.tsx index 63c137f..e47fb01 100644 --- a/frontend/src/main.tsx +++ b/frontend/src/main.tsx @@ -10,6 +10,7 @@ import Login from './screens/Login.tsx'; import Signup from './screens/Signup.tsx'; import Results from './screens/Results.tsx'; import MainSearch from './screens/MainSearch.tsx'; +import RegisterFile from './screens/RegisterFile.tsx'; const router = createBrowserRouter([ { @@ -25,6 +26,10 @@ const router = createBrowserRouter([ path: "results", element: , }, + { + path: "register", + element: , + }, ] }, diff --git a/frontend/src/screens/MainSearch.tsx b/frontend/src/screens/MainSearch.tsx index c65377a..98b98bd 100644 --- a/frontend/src/screens/MainSearch.tsx +++ b/frontend/src/screens/MainSearch.tsx @@ -2,7 +2,7 @@ import React, { useState, useEffect } from 'react'; import { useNavigate } from 'react-router-dom'; import '../styles/MainScreenWrapper.css'; import { getAuthHeaders } from '../utils/getAuthHeaders'; -import { Professor, Course, Topic } from "../types/types"; +import { Professor, Course, Topic, Semester } from "../types/types"; interface Filters extends Record { professor: string; @@ -19,6 +19,7 @@ const MainSearch: React.FC = () => { const [professors, setProfessors] = useState([]); const [courses, setCourses] = useState([]); const [topics, setTopics] = useState([]); + const [semesters, setSemesters] = useState([]); const navigate = useNavigate(); useEffect(() => { @@ -28,6 +29,8 @@ const MainSearch: React.FC = () => { fetchCourses(); // Fetch topics fetchTopics(); + // Fetch semesters + fetchSemesters(); }, []); @@ -82,6 +85,22 @@ const MainSearch: React.FC = () => { console.error('Error fetching topics:', error); } }; + const fetchSemesters = async () => { + try { + const response = await fetch('http://localhost:8000/api/semesters', { + method: 'GET', + headers: getAuthHeaders(), + }); + const data = await response.json(); + if (Array.isArray(data)) { + setSemesters(data); + } else { + console.error('Data fetched is not an array:', data); + } + } catch (error) { + console.error('Error fetching courses:', error); + } + }; const handleChange = (event: React.ChangeEvent) => { const { name, value } = event.target; @@ -128,6 +147,15 @@ const MainSearch: React.FC = () => { ))}
+
+ + +
diff --git a/frontend/src/screens/RegisterFile.tsx b/frontend/src/screens/RegisterFile.tsx new file mode 100644 index 0000000..78fab0a --- /dev/null +++ b/frontend/src/screens/RegisterFile.tsx @@ -0,0 +1,66 @@ +import "../styles/RegisterFile.css"; +import { RegisteredFile } from "../types/types"; +import { useState, useEffect } from "react"; + +export default function RegisterFile() { + const [registeredFiles, setRegisteredFiles] = useState([]); + + useEffect(() => { + fetchRegisteredFiles(); + }, []) + const fetchRegisteredFiles = () => { + return + fetch("http://localhost:5000/files") // replace with local api endpoint + .then(response => response.json()) + .then(data => { + setRegisteredFiles(data); + }) + .catch(error => console.error(error)); + } + const handleSubmit = (event: React.FormEvent) => { + event.preventDefault(); + // handle file upload + const formData = new FormData(event.target as HTMLFormElement); + const file = formData.get('file'); + console.log(file, typeof file) + + } + return ( +
+
+

Upload a File

+

Host a local file for the GT community!

+
+ + + +
+
+
+

Registered Files

+ + + + + + + + + + + + {registeredFiles.map((file) => ( + + + + + + + + ))} + +
File NameOriginal AuthorProfessorSemesterStatus
{file.filename}{file.original_author.username}{file.professor.name}{file.semester.name}{file.status}
+
+
+ ) +} \ No newline at end of file diff --git a/frontend/src/screens/Results.tsx b/frontend/src/screens/Results.tsx index 573477a..f889044 100644 --- a/frontend/src/screens/Results.tsx +++ b/frontend/src/screens/Results.tsx @@ -49,17 +49,34 @@ const Results: React.FC = () => { {isLoading ? (

Loading...

) : files.length ? ( - files.map((file) => ( -
-

{file.filename}

-

Course: {file.course.name} {file.course.number}

-

Professor: {file.professor.name}

-

Semester: {file.semester.name}

-

Upvotes: {file.upvotes.length}

-

Downvotes: {file.downvotes.length}

-

Download

-
- )) + + + + + + + + + + + + + + + {files.map((file) => ( + + + + + + + + + + + ))} + +
FilenameCourseProfessorSemesterUpvotesDownvotesOriginal AuthorDownload
{file.filename}{file.course.name} {file.course.number}{file.professor.name}{file.semester.name}{file.upvotes.length}{file.downvotes.length}{file.original_author.username}Download
) : (

No results found.

)} diff --git a/frontend/src/styles/App.css b/frontend/src/styles/App.css index 8d255d0..f7ca5de 100644 --- a/frontend/src/styles/App.css +++ b/frontend/src/styles/App.css @@ -1,3 +1,6 @@ +html { + width: 100%; +} nav { display: flex; justify-content: space-between; @@ -26,10 +29,12 @@ nav div { justify-content: center; /* If you're centering the content */ height: 100vh; /* Full height */ margin-top: -100px; /* Move up */ + width: 100%; } body { background-color: #0C2D48; font-family: 'Hiragino Sans', 'Hiragino Kaku Gothic ProN', Meiryo, sans-serif; + width: 100%; } \ No newline at end of file diff --git a/frontend/src/styles/RegisterFile.css b/frontend/src/styles/RegisterFile.css new file mode 100644 index 0000000..d1be3a4 --- /dev/null +++ b/frontend/src/styles/RegisterFile.css @@ -0,0 +1,48 @@ +h1 { +color: white; +} +.container { + display: flex; + gap: 10rem; + justify-content: space-between; +} + +.file-upload-card { + padding: 1em; + background-color: #B1D4E0; + border-radius: 5px; +} +.file-upload-card h1 { + color: black; +} + +.file-card { + padding: 1em; + background-color: #2E8BC0; + border-radius: 5px; + display: flex; + flex-direction: row; +} + .submit-button { + padding: 8px 16px; + margin-top: 20px; /* Adds space above the button */ + background-color: #2E8BC0; /* Example background color */ + color: white; /* Text color */ + border: none; + border-radius: 4px; + cursor: pointer; + font-family: 'Hiragino Sans', 'Hiragino Kaku Gothic ProN', Meiryo, sans-serif; + } + + th { + text-align: center; + padding: 1rem; + border: 1px solid #FFFFFF; + color: white; + } + td { + text-align: center; + border: 1px solid #FFFFFF; + background-color: #B1D4E0; + color: black; + } diff --git a/frontend/src/styles/Results.module.css b/frontend/src/styles/Results.module.css index 88bbef0..f488d55 100644 --- a/frontend/src/styles/Results.module.css +++ b/frontend/src/styles/Results.module.css @@ -70,4 +70,19 @@ .searchAgainButton:hover { background-color: #B1D4E0; /* lighter shade for hover effect */ + } + + table { + width: 100%; + } + th { + text-align: center; + padding: 1rem; + border: 1px solid #FFFFFF; + } + td { + text-align: center; + border: 1px solid #FFFFFF; + background-color: #B1D4E0; + color: black; } \ No newline at end of file diff --git a/frontend/src/types/types.ts b/frontend/src/types/types.ts index 579b27b..2d7d0ee 100644 --- a/frontend/src/types/types.ts +++ b/frontend/src/types/types.ts @@ -36,4 +36,12 @@ export interface File { semester: Semester; upvotes: number[]; downvotes: number[]; +} + +enum Status { + HOSTED = "HOSTED", + PRIVATE = 'PRIVATE', +} +export interface RegisteredFile extends File { + status: Status; } \ No newline at end of file