diff --git a/Readme.md b/Readme.md index 64d3bcb..621b53c 100644 --- a/Readme.md +++ b/Readme.md @@ -23,3 +23,14 @@ cd build/html python3 -m http.server ``` The website can be accessed at **localhost:8000** + +## Development +To run the backend server navigate to ``herreweb_backend/`` and run: + +> python3 manage.py runserver + +And for the frontend, navigate to ``herreweb_frontend`` and run: + +> npm start + +The file servers are accessible on ports 8000 and 3000. diff --git a/herreweb_backend/project/models.py b/herreweb_backend/project/models.py index 3458eee..fa6a1db 100644 --- a/herreweb_backend/project/models.py +++ b/herreweb_backend/project/models.py @@ -1,11 +1,27 @@ from django.db import models from herreweb_backend.utils import * +import os +from uuid import uuid4 + +def path_and_rename(path): + def wrapper(instance, filename): + ext = filename.split('.')[-1] + # get filename + if instance.pk: + filename = '{}.{}'.format(instance.pk, ext) + else: + # set filename as random string + filename = '{}.{}'.format(uuid4().hex, ext) + # return the whole path to the file + return os.path.join(path, filename) + return wrapper + class Project(models.Model): title = models.CharField(max_length=100) description = models.TextField(default="No description added") status = models.IntegerField(default=ProjectStatus.RUNNING) - image = models.ImageField(upload_to="static/project_images/", null=True, blank=True) + image = models.ImageField(upload_to=path_and_rename("static/project_images/"), null=True, blank=True) rtd_url = models.CharField(max_length=200, null=True, blank=True) url = models.CharField(max_length=200, null=True, blank=True) visible = models.BooleanField(default=False) diff --git a/herreweb_backend/static/project_images/1.png b/herreweb_backend/static/project_images/1.png new file mode 100644 index 0000000..659c3f9 Binary files /dev/null and b/herreweb_backend/static/project_images/1.png differ diff --git a/herreweb_backend/static/project_images/.blob/GHIDRA_1.png b/herreweb_backend/static/project_images/.blob/GHIDRA_1.png new file mode 100644 index 0000000..659c3f9 Binary files /dev/null and b/herreweb_backend/static/project_images/.blob/GHIDRA_1.png differ diff --git a/herreweb_backend/static/project_images/title/GHIDRA_1.png b/herreweb_backend/static/project_images/title/GHIDRA_1.png new file mode 100644 index 0000000..659c3f9 Binary files /dev/null and b/herreweb_backend/static/project_images/title/GHIDRA_1.png differ diff --git a/herreweb_frontend/package-lock.json b/herreweb_frontend/package-lock.json index 8eab401..e0e7369 100644 --- a/herreweb_frontend/package-lock.json +++ b/herreweb_frontend/package-lock.json @@ -13,6 +13,7 @@ "@testing-library/user-event": "^13.5.0", "react": "^18.2.0", "react-dom": "^18.2.0", + "react-router-dom": "^6.6.1", "react-scripts": "5.0.1", "react-transition-group": "^4.4.5", "web-vitals": "^2.1.4" @@ -3089,6 +3090,14 @@ } } }, + "node_modules/@remix-run/router": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.2.1.tgz", + "integrity": "sha512-XiY0IsyHR+DXYS5vBxpoBe/8veTeoRpMHP+vDosLZxL5bnpetzI0igkxkLZS235ldLzyfkxF+2divEwWHP3vMQ==", + "engines": { + "node": ">=14" + } + }, "node_modules/@rollup/plugin-babel": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", @@ -14187,6 +14196,36 @@ "node": ">=0.10.0" } }, + "node_modules/react-router": { + "version": "6.6.1", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.6.1.tgz", + "integrity": "sha512-YkvlYRusnI/IN0kDtosUCgxqHeulN5je+ew8W+iA1VvFhf86kA+JEI/X/8NqYcr11hCDDp906S+SGMpBheNeYQ==", + "dependencies": { + "@remix-run/router": "1.2.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "react": ">=16.8" + } + }, + "node_modules/react-router-dom": { + "version": "6.6.1", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.6.1.tgz", + "integrity": "sha512-u+8BKUtelStKbZD5UcY0NY90WOzktrkJJhyhNg7L0APn9t1qJNLowzrM9CHdpB6+rcPt6qQrlkIXsTvhuXP68g==", + "dependencies": { + "@remix-run/router": "1.2.1", + "react-router": "6.6.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "react": ">=16.8", + "react-dom": ">=16.8" + } + }, "node_modules/react-scripts": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.1.tgz", @@ -19110,6 +19149,11 @@ "source-map": "^0.7.3" } }, + "@remix-run/router": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.2.1.tgz", + "integrity": "sha512-XiY0IsyHR+DXYS5vBxpoBe/8veTeoRpMHP+vDosLZxL5bnpetzI0igkxkLZS235ldLzyfkxF+2divEwWHP3vMQ==" + }, "@rollup/plugin-babel": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", @@ -27028,6 +27072,23 @@ "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz", "integrity": "sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A==" }, + "react-router": { + "version": "6.6.1", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.6.1.tgz", + "integrity": "sha512-YkvlYRusnI/IN0kDtosUCgxqHeulN5je+ew8W+iA1VvFhf86kA+JEI/X/8NqYcr11hCDDp906S+SGMpBheNeYQ==", + "requires": { + "@remix-run/router": "1.2.1" + } + }, + "react-router-dom": { + "version": "6.6.1", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.6.1.tgz", + "integrity": "sha512-u+8BKUtelStKbZD5UcY0NY90WOzktrkJJhyhNg7L0APn9t1qJNLowzrM9CHdpB6+rcPt6qQrlkIXsTvhuXP68g==", + "requires": { + "@remix-run/router": "1.2.1", + "react-router": "6.6.1" + } + }, "react-scripts": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.1.tgz", diff --git a/herreweb_frontend/package.json b/herreweb_frontend/package.json index 51155c5..052977f 100644 --- a/herreweb_frontend/package.json +++ b/herreweb_frontend/package.json @@ -8,6 +8,7 @@ "@testing-library/user-event": "^13.5.0", "react": "^18.2.0", "react-dom": "^18.2.0", + "react-router-dom": "^6.6.1", "react-scripts": "5.0.1", "react-transition-group": "^4.4.5", "web-vitals": "^2.1.4" diff --git a/herreweb_frontend/src/components/App.js b/herreweb_frontend/src/components/App.js index 24a6b4d..77e765c 100644 --- a/herreweb_frontend/src/components/App.js +++ b/herreweb_frontend/src/components/App.js @@ -2,12 +2,14 @@ import logo from '../static/logo.svg'; import '../static/App.css'; import Projects from './Projects'; import AppHeader from './AppHeader'; +import AppFooter from './AppFooter'; function App() { return (
+
); } diff --git a/herreweb_frontend/src/components/AppFooter.js b/herreweb_frontend/src/components/AppFooter.js new file mode 100644 index 0000000..4bfb0fb --- /dev/null +++ b/herreweb_frontend/src/components/AppFooter.js @@ -0,0 +1,14 @@ +/* eslint-disable jsx-a11y/accessible-emoji */ +import React, { useState, useEffect } from "react"; +import "../static/AppFooter.css"; + +export default function AppFooter() { + + return ( +
+
+ Copyright @Herreweb +
+
+ ); +} diff --git a/herreweb_frontend/src/components/Projects.js b/herreweb_frontend/src/components/Projects.js index 8e12a84..c22d9c1 100644 --- a/herreweb_frontend/src/components/Projects.js +++ b/herreweb_frontend/src/components/Projects.js @@ -1,5 +1,6 @@ import React, { Component } from "react" import '../static/Projects.css'; +import { useNavigate } from "react-router-dom"; const projectItems = [ ]; @@ -25,32 +26,32 @@ class Projects extends Component { return (
- {this.state.projectItems.map(item => ( -
-

{item.title}

- {item.description} - {item.rtd_url} -
- ))} + { this.state.projectItems.map(item => ( +
+

{item.title}

+
+
+
+
+ { item.url + ?
Website
+ :
+ } + { item.rtd_url + ?
Documentation
+ :
+ } + +
{item.description}
+
+
+
+
+
+
+ ))}
- //
- //
- //
- //
- //
    - // {this.state.projectItems.map(item => ( - //
    - //

    {item.title}

    - // {item.description} - // {item.rtd_url} - //
    - // ))} - //
- //
- //
- //
- //
) } } diff --git a/herreweb_frontend/src/static/App.css b/herreweb_frontend/src/static/App.css index 74b5e05..5b8b12a 100644 --- a/herreweb_frontend/src/static/App.css +++ b/herreweb_frontend/src/static/App.css @@ -1,5 +1,6 @@ .App { text-align: center; + } .App-logo { diff --git a/herreweb_frontend/src/static/AppFooter.css b/herreweb_frontend/src/static/AppFooter.css new file mode 100644 index 0000000..2db6932 --- /dev/null +++ b/herreweb_frontend/src/static/AppFooter.css @@ -0,0 +1,14 @@ +.Footer { + position: relative; + bottom: 0; /* Stick it to the bottom */ + height: 70px; + width: 100vw; + + display: grid; + grid-template-areas: "logo nav"; + + /* Cosmetics */ + background-color: #282c34; + box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2); + } + \ No newline at end of file diff --git a/herreweb_frontend/src/static/Projects.css b/herreweb_frontend/src/static/Projects.css index 4e0f256..24702c8 100644 --- a/herreweb_frontend/src/static/Projects.css +++ b/herreweb_frontend/src/static/Projects.css @@ -4,11 +4,85 @@ gap: 1%; padding: 1%; margin-top: 70px; + margin-left: 5%; + margin-right: 5%; + align-items: center; } -.projects-grid-item { - background-color: rgba(255, 255, 255, 0.8); - margin: 1%; - border: 1px solid black; - text-align: center; +.project-grid-item { + display: grid; + grid-template-columns: repeat(2, 2fr) repeat(5, 1fr); + grid-template-rows: 1fr 2fr; + grid-column-gap: 0px; + grid-row-gap: 0px; + align-items: center; + background-color: rgb(241, 241, 241); + border-radius:8px; + padding: 1%; + +} + +.project-rtd-url-btn { + margin: 2%; + box-shadow:inset 0px 17px 10px -14px #29bbff; + background:linear-gradient(to bottom, #2dabf9 5%, #0688fa 100%); + background-color:#2dabf9; + border-radius:8px; + display:inline-block; + cursor:pointer; + color:#ffffff; + font-family:Arial; + font-size:23px; + font-weight:bold; + padding:13px 32px; + text-decoration:none; + text-shadow:0px 1px 26px #263666; +} + +.project-rtd-url-btn:hover { + background:linear-gradient(to bottom, #0688fa 5%, #2dabf9 100%); + background-color:#0688fa; +} + +.project-rtd-url-btn:active { + position:relative; + top:1px; +} + +.project-url-btn { + margin: 2%; + box-shadow:inset 0px 17px 10px -14px #861400; + background:linear-gradient(to bottom, #fb6363 5%, #cb0000 100%); + background-color:#ff4b4b; + border-radius:8px; + display:inline-block; + cursor:pointer; + color:#ffffff; + font-family:Arial; + font-size:23px; + font-weight:bold; + padding:13px 32px; + text-decoration:none; + text-shadow:0px 1px 26px #590700; +} +.project-url-btn:hover { + background:linear-gradient(to bottom, #ff1616 5%, #ff0000 100%); + background-color:#ff2626; +} +.project-url-btn:active { + position:relative; + top:1px; +} + +.project-image-box { + width: 70%; + height: 70%; +} + +.description-box { + padding: 5%; + width: 100%; + height: 100%; + text-align: left; + vertical-align: top; } \ No newline at end of file diff --git a/herreweb_frontend/src/static/index.css b/herreweb_frontend/src/static/index.css index ec2585e..c4b7766 100644 --- a/herreweb_frontend/src/static/index.css +++ b/herreweb_frontend/src/static/index.css @@ -5,6 +5,7 @@ body { sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; + background-color: #f5f5f5; } code {