Added documentation on how to run the backend and frontend code
This commit is contained in:
parent
1ef9bdce2b
commit
7a361e9fd0
11
Readme.md
11
Readme.md
@ -23,3 +23,14 @@ cd build/html
|
|||||||
python3 -m http.server
|
python3 -m http.server
|
||||||
```
|
```
|
||||||
The website can be accessed at **localhost:8000**
|
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.
|
||||||
|
@ -1,11 +1,27 @@
|
|||||||
from django.db import models
|
from django.db import models
|
||||||
from herreweb_backend.utils import *
|
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):
|
class Project(models.Model):
|
||||||
title = models.CharField(max_length=100)
|
title = models.CharField(max_length=100)
|
||||||
description = models.TextField(default="No description added")
|
description = models.TextField(default="No description added")
|
||||||
status = models.IntegerField(default=ProjectStatus.RUNNING)
|
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)
|
rtd_url = models.CharField(max_length=200, null=True, blank=True)
|
||||||
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)
|
visible = models.BooleanField(default=False)
|
||||||
|
BIN
herreweb_backend/static/project_images/1.png
Normal file
BIN
herreweb_backend/static/project_images/1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 185 KiB |
Binary file not shown.
After Width: | Height: | Size: 185 KiB |
BIN
herreweb_backend/static/project_images/title/GHIDRA_1.png
Normal file
BIN
herreweb_backend/static/project_images/title/GHIDRA_1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 185 KiB |
61
herreweb_frontend/package-lock.json
generated
61
herreweb_frontend/package-lock.json
generated
@ -13,6 +13,7 @@
|
|||||||
"@testing-library/user-event": "^13.5.0",
|
"@testing-library/user-event": "^13.5.0",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
|
"react-router-dom": "^6.6.1",
|
||||||
"react-scripts": "5.0.1",
|
"react-scripts": "5.0.1",
|
||||||
"react-transition-group": "^4.4.5",
|
"react-transition-group": "^4.4.5",
|
||||||
"web-vitals": "^2.1.4"
|
"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": {
|
"node_modules/@rollup/plugin-babel": {
|
||||||
"version": "5.3.1",
|
"version": "5.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz",
|
||||||
@ -14187,6 +14196,36 @@
|
|||||||
"node": ">=0.10.0"
|
"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": {
|
"node_modules/react-scripts": {
|
||||||
"version": "5.0.1",
|
"version": "5.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.1.tgz",
|
||||||
@ -19110,6 +19149,11 @@
|
|||||||
"source-map": "^0.7.3"
|
"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": {
|
"@rollup/plugin-babel": {
|
||||||
"version": "5.3.1",
|
"version": "5.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz",
|
"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",
|
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz",
|
||||||
"integrity": "sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A=="
|
"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": {
|
"react-scripts": {
|
||||||
"version": "5.0.1",
|
"version": "5.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.1.tgz",
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
"@testing-library/user-event": "^13.5.0",
|
"@testing-library/user-event": "^13.5.0",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
|
"react-router-dom": "^6.6.1",
|
||||||
"react-scripts": "5.0.1",
|
"react-scripts": "5.0.1",
|
||||||
"react-transition-group": "^4.4.5",
|
"react-transition-group": "^4.4.5",
|
||||||
"web-vitals": "^2.1.4"
|
"web-vitals": "^2.1.4"
|
||||||
|
@ -2,12 +2,14 @@ import logo from '../static/logo.svg';
|
|||||||
import '../static/App.css';
|
import '../static/App.css';
|
||||||
import Projects from './Projects';
|
import Projects from './Projects';
|
||||||
import AppHeader from './AppHeader';
|
import AppHeader from './AppHeader';
|
||||||
|
import AppFooter from './AppFooter';
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
return (
|
return (
|
||||||
<div className="App">
|
<div className="App">
|
||||||
<AppHeader />
|
<AppHeader />
|
||||||
<Projects />
|
<Projects />
|
||||||
|
<AppFooter />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
14
herreweb_frontend/src/components/AppFooter.js
Normal file
14
herreweb_frontend/src/components/AppFooter.js
Normal file
@ -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 (
|
||||||
|
<footer className="Footer">
|
||||||
|
<div>
|
||||||
|
Copyright @Herreweb
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
);
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
import React, { Component } from "react"
|
import React, { Component } from "react"
|
||||||
import '../static/Projects.css';
|
import '../static/Projects.css';
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
const projectItems = [
|
const projectItems = [
|
||||||
];
|
];
|
||||||
@ -26,31 +27,31 @@ class Projects extends Component {
|
|||||||
<main className="content">
|
<main className="content">
|
||||||
<div className="projects-grid-container">
|
<div className="projects-grid-container">
|
||||||
{ this.state.projectItems.map(item => (
|
{ this.state.projectItems.map(item => (
|
||||||
<div className="projects-grid-item">
|
<div className="project-grid-item">
|
||||||
<h1>{item.title}</h1>
|
<h2>{item.title}</h2>
|
||||||
<span>{item.description}</span>
|
<div></div>
|
||||||
<span>{item.rtd_url}</span>
|
<div></div>
|
||||||
|
<div></div>
|
||||||
|
<div></div>
|
||||||
|
{ item.url
|
||||||
|
? <div className="project-url-btn">Website</div>
|
||||||
|
: <div />
|
||||||
|
}
|
||||||
|
{ item.rtd_url
|
||||||
|
? <div className="project-rtd-url-btn">Documentation</div>
|
||||||
|
: <div />
|
||||||
|
}
|
||||||
|
<img className="project-image-box" src={item.image}/>
|
||||||
|
<div className="description-box">{item.description}</div>
|
||||||
|
<div></div>
|
||||||
|
<div></div>
|
||||||
|
<div></div>
|
||||||
|
<div></div>
|
||||||
|
<div></div>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
// <main className="content">
|
|
||||||
// <div className="row">
|
|
||||||
// <div className="col-md-6 col-sm-10 mx-auto p-0">
|
|
||||||
// <div className="card p-3">
|
|
||||||
// <ul className="list-group list-group-flush">
|
|
||||||
// {this.state.projectItems.map(item => (
|
|
||||||
// <div>
|
|
||||||
// <h1>{item.title}</h1>
|
|
||||||
// <span>{item.description}</span>
|
|
||||||
// <span>{item.rtd_url}</span>
|
|
||||||
// </div>
|
|
||||||
// ))}
|
|
||||||
// </ul>
|
|
||||||
// </div>
|
|
||||||
// </div>
|
|
||||||
// </div>
|
|
||||||
// </main>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
.App {
|
.App {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.App-logo {
|
.App-logo {
|
||||||
|
14
herreweb_frontend/src/static/AppFooter.css
Normal file
14
herreweb_frontend/src/static/AppFooter.css
Normal file
@ -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);
|
||||||
|
}
|
||||||
|
|
@ -4,11 +4,85 @@
|
|||||||
gap: 1%;
|
gap: 1%;
|
||||||
padding: 1%;
|
padding: 1%;
|
||||||
margin-top: 70px;
|
margin-top: 70px;
|
||||||
|
margin-left: 5%;
|
||||||
|
margin-right: 5%;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.projects-grid-item {
|
.project-grid-item {
|
||||||
background-color: rgba(255, 255, 255, 0.8);
|
display: grid;
|
||||||
margin: 1%;
|
grid-template-columns: repeat(2, 2fr) repeat(5, 1fr);
|
||||||
border: 1px solid black;
|
grid-template-rows: 1fr 2fr;
|
||||||
text-align: center;
|
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;
|
||||||
}
|
}
|
@ -5,6 +5,7 @@ body {
|
|||||||
sans-serif;
|
sans-serif;
|
||||||
-webkit-font-smoothing: antialiased;
|
-webkit-font-smoothing: antialiased;
|
||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
background-color: #f5f5f5;
|
||||||
}
|
}
|
||||||
|
|
||||||
code {
|
code {
|
||||||
|
Loading…
Reference in New Issue
Block a user