Skip to content
Snippets Groups Projects
Commit 7ca50fc9 authored by Sreeram, Sudarshan's avatar Sreeram, Sudarshan :carrot:
Browse files

Merge branch 'master' into experiments

parents 01487ed1 10486ce1
No related branches found
No related tags found
No related merge requests found
Showing
with 536 additions and 2 deletions
This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
## Available Scripts ## Setup
First, run `yarn install` 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
In the project directory, you can run: In the project directory, you can run:
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
"react-router-breadcrumbs-hoc": "^3.3.0", "react-router-breadcrumbs-hoc": "^3.3.0",
"react-router-dom": "^5.2.0", "react-router-dom": "^5.2.0",
"react-scripts": "3.4.1", "react-scripts": "3.4.1",
"react-transition-group": "^4.4.1",
"types": "^0.1.1", "types": "^0.1.1",
"typescript": "~3.7.2" "typescript": "~3.7.2"
}, },
......
frontend/src/assets/images/document-banner.png

5.77 KiB

frontend/src/assets/images/pdf-banner.png

10.5 KiB

frontend/src/assets/images/tutor-1.png

1.63 MiB

frontend/src/assets/images/tutor-2.png

1.62 MiB

frontend/src/assets/images/tutor-3.png

1.58 MiB

frontend/src/assets/images/user.png

44.4 KiB | W: | H:

frontend/src/assets/images/user.png

1.7 MiB | W: | H:

frontend/src/assets/images/user.png
frontend/src/assets/images/user.png
frontend/src/assets/images/user.png
frontend/src/assets/images/user.png
  • 2-up
  • Swipe
  • Onion skin
frontend/src/assets/images/video-banner.png

6.94 KiB

// Override default variables before the import // Override default variables before the import
$nav-pills-link-active-color: black; $nav-pills-link-active-color: black;
//* bootstrap 5's grid. To use, import the following line in the .module.scss */
// @import "assets/scss/bootstrap5/bootstrap-grid";
$grid-breakpoints: (
xs: 0,
sm: 576px,
md: 768px,
lg: 992px,
xl: 1200px,
xxl: 2000px
);
//Bootstrap 5 scss from: https://github.com/twbs/bootstrap/tree/main/scss //Bootstrap 5 scss from: https://github.com/twbs/bootstrap/tree/main/scss
@import "bootstrap5/functions"; @import "bootstrap5/functions";
@import "bootstrap5/variables"; @import "bootstrap5/variables";
@import "bootstrap5/mixins"; @import "bootstrap5/mixins";
\ No newline at end of file
...@@ -14,3 +14,10 @@ code { ...@@ -14,3 +14,10 @@ code {
font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
monospace; monospace;
} }
.btn-primary.focus, .btn-primary:focus {
color: #000;
background-color: #f8f9fa;
border-color: #0062cc;
box-shadow: none;
}
\ No newline at end of file
import React from "react";
import styles from "./style.module.scss";
import classNames from "classnames";
import applicationPDF from "assets/images/pdf-banner.png";
import applicationDocument from "assets/images/document-banner.png";
import applicationVideo from "assets/images/video-banner.png";
import Badge from "react-bootstrap/Badge";
import Card from "react-bootstrap/Card";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { IconDefinition } from "@fortawesome/free-solid-svg-icons";
export interface FileCardProps {
title: string;
type: string;
tags: string[];
icon: IconDefinition;
onIconClick: (event: React.MouseEvent) => void;
onClick: (event: React.MouseEvent) => void;
onMouseOver: (event: React.MouseEvent) => void;
onMouseOut: (event: React.MouseEvent) => void;
}
const FileCard: React.FC<FileCardProps> = ({
title,
type,
tags,
icon,
onIconClick,
onClick,
onMouseOver,
onMouseOut,
}: FileCardProps) => {
let banner: string;
switch (type) {
case "pdf":
banner = applicationPDF;
break;
case "video":
banner = applicationVideo;
break;
default:
banner = applicationDocument;
break;
}
return (
<Card
className={styles.quickViewCard}
onClick={onClick}
onMouseOver={onMouseOver}
onMouseOut={onMouseOut}
>
<Card.Img variant="top" src={banner} />
<Card.Body>
<Card.Title style={{ wordWrap: "break-word" }}>{title}</Card.Title>
<FontAwesomeIcon
style={{ marginLeft: "8px", fontSize: "1.125rem" }}
icon={icon}
onClick={onIconClick}
/>
</Card.Body>
<Card.Footer>
{tags.map((tag) => (
<Badge
pill
key={tag}
className={classNames(
styles.quickViewTag,
tag === "new" ? styles.tagTeal : styles.tagBlue
)}
>
{tag}
</Badge>
))}
</Card.Footer>
</Card>
);
};
export default FileCard;
@import "assets/scss/custom";
.quickViewCard {
border-radius: 0.5rem;
border-color: $gray-300;
border-width: 0px;
transition: transform 0.2s, box-shadow 0.2s;
background-color: $gray-100;
height: 96%;
}
.quickViewCard:hover {
transform: scale(1.03);
box-shadow: 0 0.125rem 0.625rem 0 rgba(0, 0, 0, 0.1);
}
.quickViewCard :global(.card-body) {
padding: 0.5rem;
display: flex;
justify-content: space-between;
}
.quickViewCard :global(.card-footer) {
border-radius: 0.5rem !important;
background: $gray-100;
border-width: 0rem;
padding: 0.5rem;
}
.quickViewCard :global(.card-title) {
font-size: 1.125rem;
font-weight: 400;
white-space: normal;
margin-bottom: 0px;
width: 90%;
overflow-wrap: break-word;
word-wrap: break-word;
-ms-word-break: break-all;
word-break: break-all;
word-break: break-word;
}
.quickViewCard :global(.card-img-top) {
border: 1px solid $gray-100;
padding: 1px;
border-top-left-radius: 0.5rem;
border-top-right-radius: 0.5rem;
}
$blue-tag-background: transparentize($blue-100, 0.5);
$teal-tag-background: transparentize($teal-100, 0.5);
.quickViewTag {
text-transform: uppercase;
font-size: 0.8rem;
font-weight: 500;
border-radius: 0.33rem;
margin-right: 0.5rem;
}
.tagBlue {
color: $blue-700;
background: $blue-tag-background;
}
.tagTeal {
color: $teal-700;
background: $teal-tag-background;
}
.quickAccessRow {
scrollbar-width: thin;
scrollbar-color: $white $white;
margin-top: 10px;
// margin-left: 0; // leave space before card
}
import React from "react";
import styles from "./style.module.scss";
import Card from "react-bootstrap/Card";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { IconDefinition } from "@fortawesome/free-solid-svg-icons";
export interface FolderCardProps {
title: string;
icon: IconDefinition;
onIconClick: (event: React.MouseEvent) => void;
onClick: (event: React.MouseEvent) => void;
onMouseOver: (event: React.MouseEvent) => void;
onMouseOut: (event: React.MouseEvent) => void;
}
const FolderCard: React.FC<FolderCardProps> = ({
title,
icon,
onIconClick,
onClick,
onMouseOver,
onMouseOut,
}: FolderCardProps) => {
return (
<Card
className={styles.folderCard}
onClick={onClick}
onMouseOver={onMouseOver}
onMouseOut={onMouseOut}
>
<Card.Body style={{ padding: ".6rem" }}>
<Card.Text style={{ marginBottom: 0 }}>{title}</Card.Text>
<FontAwesomeIcon
style={{ fontSize: "1.125rem" }}
icon={icon}
onClick={onIconClick}
/>
</Card.Body>
</Card>
);
};
export default FolderCard;
@import "assets/scss/custom";
.folderCard {
border-radius: 0.5rem;
border-width: 0px;
transition: transform 0.2s, box-shadow 0.2s;
background-color: $gray-100;
margin-top: 0.67rem;
}
.folderCard:hover {
transform: scale(1.03);
box-shadow: 0 0.125rem 0.625rem 0 rgba(0, 0, 0, 0.1);
}
.folderCard :global(.card-body) {
display: flex;
justify-content: space-between;
align-items: center;
}
...@@ -36,6 +36,10 @@ ...@@ -36,6 +36,10 @@
padding: 0.5rem; padding: 0.5rem;
} }
.moduleCard :global(.card-title) {
margin-bottom: 0;
}
.moduleCard :global(.card-footer) { .moduleCard :global(.card-footer) {
border-radius: 0.5rem !important; border-radius: 0.5rem !important;
background: #fff; background: #fff;
......
import React from "react";
import styles from "./style.module.scss";
export interface NoticeItemProps {
heading: string;
user: string;
time: string;
body: string;
}
const NoticeItem: React.FC<NoticeItemProps> = ({
heading,
user,
time,
body,
}: NoticeItemProps) => {
return (
<>
<div style={{ marginTop: "20px" }} className={styles.noticeContainer}>
<p className={styles.noticeHeading}>{heading}</p>
<span style={{ display: "flex", justifyContent: "space-between" }}>
<p className={styles.noticeUser}>{user}</p>
<p className={styles.noticeTime}>{time}</p>
</span>
<p className={styles.noticeBody}>{body}</p>
</div>
</>
);
};
export default NoticeItem;
@import "assets/scss/custom";
.noticeContainer {
background-color: $gray-100;
border-radius: 8px;
padding: 10px;
transition: transform 0.2s, box-shadow 0.2s;
}
.noticeContainer:hover {
transform: scale(1.03);
box-shadow: 0 0.125rem 0.625rem 0 rgba(0, 0, 0, 0.1);
}
.noticeHeading {
font-size: 20px;
color: $black;
font-weight: 500;
margin-bottom: 4px;
line-height: 22px;
text-align: left;
overflow-wrap: break-word;
word-wrap: break-word;
-ms-word-break: break-all;
word-break: break-all;
word-break: break-word;
}
.noticeUser {
font-size: 16px;
color: $gray-700;
line-height: 18px;
margin-bottom: 10px;
margin-right: 10px;
text-align: left;
overflow-wrap: break-word;
word-wrap: break-word;
-ms-word-break: break-all;
word-break: break-all;
word-break: break-word;
}
.noticeTime {
font-size: 16px;
color: $gray-600;
line-height: 18px;
margin-bottom: 10px;
margin-left: 10px;
text-align: right;
overflow-wrap: break-word;
word-wrap: break-word;
-ms-word-break: break-all;
word-break: break-all;
word-break: break-word;
}
.noticeBody {
font-size: 16px;
color: $gray-800;
margin-bottom: 0px;
overflow: hidden;
position: relative;
line-height: 1.2em;
max-height: 3.6em;
padding-right: 1em;
}
.noticeBody:before {
content: '...';
position: absolute;
right: 0;
bottom: 0;
}
.noticeBody:after {
content: '';
position: absolute;
right: 0;
width: 1em;
height: 1em;
margin-top: 0.2em;
background: $gray-100;
}
import React, { useEffect } from "react";
import Image from "react-bootstrap/Image";
import Container from "react-bootstrap/Container";
import styles from "./style.module.scss";
import userImage from "assets/images/user.png";
const PersonCard: React.FC = () => {
// @ts-ignore
useEffect(() => {window.Holder.run()});
return (
<>
<Container className={styles.userCardContainer}>
<Image className={styles.userImage} src={userImage} />
<div className={styles.userInfoBlock}>
<p className={styles.userName}>{userInfo.name}</p>
<p className={styles.userEmail}>{userInfo.email}</p>
<p className={styles.userIdentifier}>
{userInfo.id}
<span className={styles.dot}></span>
{userInfo.cid}
</p>
<p className={styles.userYear}>{userInfo.year + ','}</p>
<p className={styles.userDepartment}>{userInfo.dep}</p>
<p className={styles.userCourse}>{userInfo.course}</p>
</div>
</Container>
</>
);
};
export default PersonCard;
const userInfo = {
name: "Branden Ritter",
email: "branden.ritter20@imperial.ac.uk",
id: "BR819",
cid: "01343896",
year: "First Year Undergraduate",
dep: "Department of Computing",
course: "MEng Computing (AI)"
}
@import "assets/scss/custom";
.userImage {
border-radius: 8px;
margin-right: 20px;
height: 180px;
width: 180px;
}
.userName {
font-weight: 600;
font-size: 24px;
color: $black;
margin-bottom: 0rem;
line-height: 32px;
}
.userEmail {
font-size: 16px;
color: $blue-500;
margin-bottom: 0rem;
line-height: 20px;
}
.userIdentifier {
font-weight: 500;
font-size: 18px;
margin-bottom: 14px;
margin-top: 14px;
line-height: 24px;
display: flex;
flex-direction: row;
align-items: center;
}
.userYear {
font-size: 17px;
color: $gray-700;
margin-bottom: 0rem;
line-height: 22px;
}
.userDepartment {
font-size: 17px;
color: $gray-600;
margin-bottom: 0rem;
line-height: 22px;
}
.userCourse {
font-size: 17px;
color: $gray-800;
margin-top: 10px;
margin-bottom: 0rem;
line-height: 22px;
}
.dot {
height: 6px;
width: 6px;
border-radius: 50%;
display: inline-block;
margin-right: 8px;
margin-left: 8px;
vertical-align: middle;
text-align: center;
background-color: $gray-500;
}
@media (max-width: 62rem) {
.userCardContainer {
padding: 0;
display: flex;
justify-content: center;
flex-direction: column;
align-items: middle;
}
.userInfoBlock {
margin-top: 20px;
margin-right: auto;
margin-left: auto;
}
.userInfoBlock:not(.userIdentifier) * {
text-align: center;
}
.userImage {
margin-right: auto;
margin-left: auto;
}
.userIdentifier {
justify-content: center;
}
}
@media (min-width: 62rem) {
.userCardContainer {
display: flex;
padding: 0;
}
.userInfoBlock {
height: 180px;
}
}
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