Added documentation on how to run the backend and frontend code

This commit is contained in:
Eljakim Herrewijnen 2022-12-29 23:04:25 +01:00
parent 1ef9bdce2b
commit 7a361e9fd0
14 changed files with 226 additions and 30 deletions

View File

@ -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.

View File

@ -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)

Binary file not shown.

After

Width:  |  Height:  |  Size: 185 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 185 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 185 KiB

View File

@ -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",

View File

@ -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"

View File

@ -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>
); );
} }

View 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>
);
}

View File

@ -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 = [
]; ];
@ -25,32 +26,32 @@ class Projects extends Component {
return ( return (
<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>
) )
} }
} }

View File

@ -1,5 +1,6 @@
.App { .App {
text-align: center; text-align: center;
} }
.App-logo { .App-logo {

View 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);
}

View File

@ -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;
} }

View File

@ -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 {