Skip to content
Snippets Groups Projects
Commit 61654a81 authored by Wilson Chua's avatar Wilson Chua :rice_ball:
Browse files

Implement calling resources endpoint, and add Materials setup instructions to README

parent 5e89483d
No related branches found
No related tags found
No related merge requests found
...@@ -2,11 +2,26 @@ This project was bootstrapped with [Create React App](https://github.com/faceboo ...@@ -2,11 +2,26 @@ This project was bootstrapped with [Create React App](https://github.com/faceboo
## Setup ## Setup
First, run First, run `yarn install` to install the node modules used for the frontend.
### `yarn install` In order for the API links to work, the following repository branches need to be cloned and run separately:
to install the node modules used for the frontend. In order for the API links to work, the following repository branches need to be cloned and run (separately): ### 1. materials@scientia-integration
```shell
# Clone the repository and checkout to the relevant branch
git clone https://gitlab.doc.ic.ac.uk/edtech/materials.git
git checkout scientia-integration
# Setup and run the development server on port 5000
python3 -m venv venv
source venv/bin/activate
pip install --upgrade pip && pip install -r requirements.txt
export FLASK_ENV=development
export FLASK_APP=materials
flask create_all
flask populate -r materials/mocks/resources.json
flask run
```
## To run ## To run
......
...@@ -20,7 +20,7 @@ const ModuleList: React.FC = () => { ...@@ -20,7 +20,7 @@ const ModuleList: React.FC = () => {
let modules = [ let modules = [
{ {
title: "Introduction to Logic", title: "Introduction to Logic",
code: "CO140", code: "140",
image: logicIllustration, image: logicIllustration,
terms: [Term.AUTUMN], terms: [Term.AUTUMN],
progressStatus: ProgressStatus.IN_PROGRESS, progressStatus: ProgressStatus.IN_PROGRESS,
...@@ -29,7 +29,7 @@ const ModuleList: React.FC = () => { ...@@ -29,7 +29,7 @@ const ModuleList: React.FC = () => {
}, },
{ {
title: "Discrete Mathematics", title: "Discrete Mathematics",
code: "CO142", code: "142",
image: discreteIllustration, image: discreteIllustration,
terms: [Term.AUTUMN], terms: [Term.AUTUMN],
progressStatus: ProgressStatus.IN_PROGRESS, progressStatus: ProgressStatus.IN_PROGRESS,
...@@ -38,7 +38,7 @@ const ModuleList: React.FC = () => { ...@@ -38,7 +38,7 @@ const ModuleList: React.FC = () => {
}, },
{ {
title: "Introduction to Computer Systems", title: "Introduction to Computer Systems",
code: "CO112", code: "112",
image: systemsIllustration, image: systemsIllustration,
terms: [Term.AUTUMN], terms: [Term.AUTUMN],
progressStatus: ProgressStatus.IN_PROGRESS, progressStatus: ProgressStatus.IN_PROGRESS,
...@@ -47,7 +47,7 @@ const ModuleList: React.FC = () => { ...@@ -47,7 +47,7 @@ const ModuleList: React.FC = () => {
}, },
{ {
title: "Mathematical Methods", title: "Mathematical Methods",
code: "CO145", code: "145",
terms: [Term.AUTUMN], terms: [Term.AUTUMN],
image: methodsIllustration, image: methodsIllustration,
progressStatus: ProgressStatus.IN_PROGRESS, progressStatus: ProgressStatus.IN_PROGRESS,
...@@ -56,7 +56,7 @@ const ModuleList: React.FC = () => { ...@@ -56,7 +56,7 @@ const ModuleList: React.FC = () => {
}, },
{ {
title: "Java", title: "Java",
code: "CO120.2", code: "120.2",
image: javaIllustration, image: javaIllustration,
terms: [Term.AUTUMN, Term.SPRING, Term.SUMMER], terms: [Term.AUTUMN, Term.SPRING, Term.SUMMER],
progressStatus: ProgressStatus.IN_PROGRESS, progressStatus: ProgressStatus.IN_PROGRESS,
...@@ -65,7 +65,7 @@ const ModuleList: React.FC = () => { ...@@ -65,7 +65,7 @@ const ModuleList: React.FC = () => {
}, },
{ {
title: "Graphs and Algorithms", title: "Graphs and Algorithms",
code: "CO150", code: "150",
image: graphIllustration, image: graphIllustration,
terms: [Term.SPRING], terms: [Term.SPRING],
progressStatus: ProgressStatus.NOT_STARTED, progressStatus: ProgressStatus.NOT_STARTED,
...@@ -74,7 +74,7 @@ const ModuleList: React.FC = () => { ...@@ -74,7 +74,7 @@ const ModuleList: React.FC = () => {
}, },
{ {
title: "Introduction to Computer Architecture", title: "Introduction to Computer Architecture",
code: "CO113", code: "113",
image: architectureIllustration, image: architectureIllustration,
terms: [Term.SPRING], terms: [Term.SPRING],
progressStatus: ProgressStatus.NOT_STARTED, progressStatus: ProgressStatus.NOT_STARTED,
...@@ -83,7 +83,7 @@ const ModuleList: React.FC = () => { ...@@ -83,7 +83,7 @@ const ModuleList: React.FC = () => {
}, },
{ {
title: "Reasoning About Programs", title: "Reasoning About Programs",
code: "CO141", code: "141",
image: reasoningIllustration, image: reasoningIllustration,
terms: [Term.SPRING], terms: [Term.SPRING],
progressStatus: ProgressStatus.NOT_STARTED, progressStatus: ProgressStatus.NOT_STARTED,
...@@ -92,7 +92,7 @@ const ModuleList: React.FC = () => { ...@@ -92,7 +92,7 @@ const ModuleList: React.FC = () => {
}, },
{ {
title: "Introduction to Databases", title: "Introduction to Databases",
code: "CO130", code: "130",
image: databaseIllustration, image: databaseIllustration,
terms: [Term.SPRING], terms: [Term.SPRING],
progressStatus: ProgressStatus.NOT_STARTED, progressStatus: ProgressStatus.NOT_STARTED,
......
import React from "react"; import React, { useEffect, useState } from "react";
import styles from "./style.module.scss"; import styles from "./style.module.scss";
import classNames from "classnames"; import classNames from "classnames";
...@@ -22,22 +22,29 @@ import { ...@@ -22,22 +22,29 @@ import {
faFolder faFolder
} from "@fortawesome/free-solid-svg-icons"; } from "@fortawesome/free-solid-svg-icons";
const ModuleResources: React.FC = () => { const ModuleResources: React.FC<{ year: string, module_code: string }> = ({ year, module_code }) => {
<<<<<<< Updated upstream // TODO: Use these state variables in component
======= const [error, setError] = useState(null);
const [isLoaded, setIsLoaded] = useState(false);
const [resources, setResources] = useState([]);
useEffect(() => { useEffect(() => {
//@ts-ignore setIsLoaded(false);
window.Holder.run();
const onSuccess = (data: any) => { const onSuccess = (data: any) => {
console.log(data); setIsLoaded(true);
setResources(data.json());
} }
const onFailure = (error: any) => { const onFailure = (error: any) => {
console.log(error); setIsLoaded(true);
setError(error);
} }
request(api.MATERIALS_COURSES, "GET", onSuccess, onFailure)
}, []);
>>>>>>> Stashed changes request(api.MATERIALS_RESOURCES, "GET", onSuccess, onFailure, {
"year": year,
"course": module_code
})
}, [year, module_code]);
return ( return (
<> <>
<MyBreadcrumbs /> <MyBreadcrumbs />
...@@ -56,7 +63,6 @@ const ModuleResources: React.FC = () => { ...@@ -56,7 +63,6 @@ const ModuleResources: React.FC = () => {
<h5 className={classNames(styles.moduleSectionHeader)}>Quick Access</h5> <h5 className={classNames(styles.moduleSectionHeader)}>Quick Access</h5>
<<<<<<< Updated upstream
{/* TODO: add scroll listener once code is refactored */} {/* TODO: add scroll listener once code is refactored */}
<Container className={classNames(styles.quickAccessRow)}> <Container className={classNames(styles.quickAccessRow)}>
{[...Array(6)].map((e, i) => ( {[...Array(6)].map((e, i) => (
...@@ -81,18 +87,6 @@ const ModuleResources: React.FC = () => { ...@@ -81,18 +87,6 @@ const ModuleResources: React.FC = () => {
</Badge> </Badge>
</Card.Footer> </Card.Footer>
</Card> </Card>
=======
<Row>
{[...Array(4)].map((e, i) => (
<Col xs={6} sm={6} md={3} key={i}>
<Card style={{ marginTop: "1rem" }}>
<Card.Img variant="top" src="holder.js/100px100" />
<Card.Body>
<Card.Title>Document :( {i}</Card.Title>
</Card.Body>
</Card>
</Col>
>>>>>>> Stashed changes
))} ))}
</Container> </Container>
......
...@@ -66,13 +66,15 @@ const StandardView: React.FC<StandardViewProps> = ({ ...@@ -66,13 +66,15 @@ const StandardView: React.FC<StandardViewProps> = ({
<ModuleOverview /> <ModuleOverview />
</Route> </Route>
<Route path="/modules/:id/resources"> <Route
<ModuleResources /> path="/modules/:id/resources"
</Route> render={(props) => <ModuleResources
year="1819"
module_code={props.match.params.id}
/>}
/>
<Route path="/modules/:id/feedback"> <Route path="/modules/:id/feedback" component={ModuleFeedback} />
<ModuleFeedback />
</Route>
<Route path="/timeline"> <Route path="/timeline">
<ExamplePage name="Timeline" /> <ExamplePage name="Timeline" />
......
...@@ -6,10 +6,10 @@ const prod = { ...@@ -6,10 +6,10 @@ const prod = {
MATERIALS_URL: "https://materials.doc.ic.ac.uk", MATERIALS_URL: "https://materials.doc.ic.ac.uk",
} }
const LOGIN = "/auth/login"
const config = process.env.NODE_ENV === "development" ? dev : prod; const config = process.env.NODE_ENV === "development" ? dev : prod;
export const api = { export const api = {
MATERIALS_LOGIN: config.MATERIALS_URL + LOGIN, MATERIALS_LOGIN: config.MATERIALS_URL + "/auth/login",
MATERIALS_COURSES: config.MATERIALS_URL + "/courses/1819" MATERIALS_COURSES: config.MATERIALS_URL + "/courses/1819",
MATERIALS_RESOURCES: config.MATERIALS_URL + "/resources"
} }
\ No newline at end of file
import authConstants from "../constants/auth"; import authConstants from "../constants/auth";
import authenticationService from "../utils/auth"; import authenticationService from "../utils/auth";
import { api } from "../constants/routes"
interface RequestOptions { interface RequestOptions {
[key: string]: any [key: string]: any
} }
// API calling interface. onSuccess and onError are functions that take in data
// and error parameters respectively. Body is process as query parameters if
// method is GET
// Note: will trigger CORS OPTIONS preflight due to the Authorization header
export async function request(url: string, method: string, onSuccess: any, onError: any, body?: any) { export async function request(url: string, method: string, onSuccess: any, onError: any, body?: any) {
if (!authenticationService.userIsLoggedIn()) { if (!authenticationService.userIsLoggedIn()) {
await authenticationService.login("abc123", "a"); // TODO: Credentials should be handled elsewhere
// TODO: Specific endpoint login route should be passed in
await authenticationService.login("abc123", "a", api.MATERIALS_LOGIN);
} }
var options: RequestOptions = { var options: RequestOptions = {
...@@ -19,8 +26,10 @@ export async function request(url: string, method: string, onSuccess: any, onErr ...@@ -19,8 +26,10 @@ export async function request(url: string, method: string, onSuccess: any, onErr
}, },
}; };
if (method !== "GET") { if (method === "GET") {
options.body = JSON.stringify(body); url = url + "?" + new URLSearchParams(body);
} else {
options.body = JSON.stringify(body);
} }
return fetch(url, options) return fetch(url, options)
......
import authConstants from "../constants/auth"; import authConstants from "../constants/auth";
import { api } from "../constants/routes";
function storeDataInStorage(data: { access_token: string; user_info: any; }) { function storeDataInStorage(data: { access_token: string; user_info: any; }) {
sessionStorage.setItem(authConstants.ACCESS_TOKEN, data.access_token); sessionStorage.setItem(authConstants.ACCESS_TOKEN, data.access_token);
...@@ -22,9 +21,8 @@ function getUserInfo() { ...@@ -22,9 +21,8 @@ function getUserInfo() {
return {} return {}
} }
async function login(username: string, password: string) { async function login(username: string, password: string, login_url: string) {
// TODO: endpoint route should be passed in const response = await fetch(login_url, {
const response = await fetch(api.MATERIALS_LOGIN, {
method: "POST", method: "POST",
mode: "cors", mode: "cors",
headers: { headers: {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment