Added AppHeader
This commit is contained in:
parent
927b834445
commit
4ef64237de
@ -27,9 +27,7 @@ DEBUG = True
|
||||
|
||||
ALLOWED_HOSTS = []
|
||||
|
||||
CORS_ORIGIN_WHITELIST = [
|
||||
'http://localhost:3000',
|
||||
]
|
||||
|
||||
|
||||
# Application definition
|
||||
|
||||
@ -40,11 +38,13 @@ INSTALLED_APPS = [
|
||||
'django.contrib.sessions',
|
||||
'django.contrib.messages',
|
||||
'django.contrib.staticfiles',
|
||||
'project',
|
||||
'corsheaders',
|
||||
'rest_framework',
|
||||
]
|
||||
|
||||
MIDDLEWARE = [
|
||||
'corsheaders.middleware.CorsMiddleware',
|
||||
'django.middleware.security.SecurityMiddleware',
|
||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||
'django.middleware.common.CommonMiddleware',
|
||||
@ -104,6 +104,9 @@ AUTH_PASSWORD_VALIDATORS = [
|
||||
},
|
||||
]
|
||||
|
||||
CORS_ORIGIN_WHITELIST = [
|
||||
'http://localhost:3000',
|
||||
]
|
||||
|
||||
# Internationalization
|
||||
# https://docs.djangoproject.com/en/4.1/topics/i18n/
|
||||
|
@ -14,8 +14,14 @@ Including another URLconf
|
||||
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
|
||||
"""
|
||||
from django.contrib import admin
|
||||
from django.urls import path
|
||||
from django.urls import path, include
|
||||
from rest_framework import routers
|
||||
from project import views
|
||||
|
||||
router = routers.DefaultRouter()
|
||||
router.register('projects', views.ProjectView, 'projects')
|
||||
|
||||
urlpatterns = [
|
||||
path('admin/', admin.site.urls),
|
||||
path('api/', include(router.urls))
|
||||
]
|
||||
|
5
herreweb_backend/herreweb_backend/utils.py
Normal file
5
herreweb_backend/herreweb_backend/utils.py
Normal file
@ -0,0 +1,5 @@
|
||||
import enum
|
||||
|
||||
class ProjectStatus(enum.Enum):
|
||||
RUNNING = 1
|
||||
ENDED = 2
|
8
herreweb_backend/project/admin.py
Normal file
8
herreweb_backend/project/admin.py
Normal file
@ -0,0 +1,8 @@
|
||||
from django.contrib import admin
|
||||
from .models import Project
|
||||
|
||||
class ProjectAdmin(admin.ModelAdmin):
|
||||
list = ('title', 'description', 'visible')
|
||||
|
||||
# Register projects
|
||||
admin.site.register(Project, ProjectAdmin)
|
28
herreweb_backend/project/migrations/0001_initial.py
Normal file
28
herreweb_backend/project/migrations/0001_initial.py
Normal file
@ -0,0 +1,28 @@
|
||||
# Generated by Django 4.1.4 on 2022-12-28 15:11
|
||||
|
||||
from django.db import migrations, models
|
||||
import herreweb_backend.utils
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Project',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('title', models.CharField(max_length=100)),
|
||||
('description', models.TextField(default='No description added')),
|
||||
('status', models.IntegerField(default=herreweb_backend.utils.ProjectStatus['RUNNING'])),
|
||||
('image', models.ImageField(null=True, upload_to='')),
|
||||
('rtd_url', models.CharField(max_length=200, null=True)),
|
||||
('url', models.CharField(max_length=200, null=True)),
|
||||
('visible', models.BooleanField(default=False)),
|
||||
],
|
||||
),
|
||||
]
|
0
herreweb_backend/project/migrations/__init__.py
Normal file
0
herreweb_backend/project/migrations/__init__.py
Normal file
14
herreweb_backend/project/models.py
Normal file
14
herreweb_backend/project/models.py
Normal file
@ -0,0 +1,14 @@
|
||||
from django.db import models
|
||||
from herreweb_backend.utils import *
|
||||
|
||||
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(null=True)
|
||||
rtd_url = models.CharField(max_length=200, null=True)
|
||||
url = models.CharField(max_length=200, null=True)
|
||||
visible = models.BooleanField(default=False)
|
||||
|
||||
def _str_(self):
|
||||
return self.title
|
7
herreweb_backend/project/serializers.py
Normal file
7
herreweb_backend/project/serializers.py
Normal file
@ -0,0 +1,7 @@
|
||||
from rest_framework import serializers
|
||||
from .models import Project
|
||||
|
||||
class ProjectSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = Project
|
||||
fields = ('id' ,'title', 'description', 'status')
|
8
herreweb_backend/project/views.py
Normal file
8
herreweb_backend/project/views.py
Normal file
@ -0,0 +1,8 @@
|
||||
from django.shortcuts import render
|
||||
from rest_framework import viewsets
|
||||
from project.serializers import ProjectSerializer
|
||||
from .models import Project
|
||||
|
||||
class ProjectView(viewsets.ModelViewSet):
|
||||
serializer_class = ProjectSerializer
|
||||
queryset = Project.objects.all()
|
17
herreweb_frontend/.vscode/launch.json
vendored
Normal file
17
herreweb_frontend/.vscode/launch.json
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"name": "Launch Program",
|
||||
"skipFiles": [
|
||||
"<node_internals>/**"
|
||||
],
|
||||
"program": "${workspaceFolder}/src/Projects.js"
|
||||
}
|
||||
]
|
||||
}
|
45
herreweb_frontend/package-lock.json
generated
45
herreweb_frontend/package-lock.json
generated
@ -14,6 +14,7 @@
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-scripts": "5.0.1",
|
||||
"react-transition-group": "^4.4.5",
|
||||
"web-vitals": "^2.1.4"
|
||||
}
|
||||
},
|
||||
@ -6589,6 +6590,15 @@
|
||||
"utila": "~0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/dom-helpers": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz",
|
||||
"integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.8.7",
|
||||
"csstype": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/dom-serializer": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz",
|
||||
@ -14249,6 +14259,21 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/react-transition-group": {
|
||||
"version": "4.4.5",
|
||||
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz",
|
||||
"integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.5.5",
|
||||
"dom-helpers": "^5.0.1",
|
||||
"loose-envify": "^1.4.0",
|
||||
"prop-types": "^15.6.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=16.6.0",
|
||||
"react-dom": ">=16.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/read-cache": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
|
||||
@ -21690,6 +21715,15 @@
|
||||
"utila": "~0.4"
|
||||
}
|
||||
},
|
||||
"dom-helpers": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz",
|
||||
"integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.8.7",
|
||||
"csstype": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"dom-serializer": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz",
|
||||
@ -27049,6 +27083,17 @@
|
||||
"workbox-webpack-plugin": "^6.4.1"
|
||||
}
|
||||
},
|
||||
"react-transition-group": {
|
||||
"version": "4.4.5",
|
||||
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz",
|
||||
"integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.5.5",
|
||||
"dom-helpers": "^5.0.1",
|
||||
"loose-envify": "^1.4.0",
|
||||
"prop-types": "^15.6.2"
|
||||
}
|
||||
},
|
||||
"read-cache": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
|
||||
|
@ -9,6 +9,7 @@
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-scripts": "5.0.1",
|
||||
"react-transition-group": "^4.4.5",
|
||||
"web-vitals": "^2.1.4"
|
||||
},
|
||||
"scripts": {
|
||||
|
@ -1,25 +0,0 @@
|
||||
import logo from './logo.svg';
|
||||
import './App.css';
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<div className="App">
|
||||
<header className="App-header">
|
||||
<img src={logo} className="App-logo" alt="logo" />
|
||||
<p>
|
||||
Edit <code>src/App.js</code> and save to reload.
|
||||
</p>
|
||||
<a
|
||||
className="App-link"
|
||||
href="https://reactjs.org"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Learn React
|
||||
</a>
|
||||
</header>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default App;
|
@ -1,8 +0,0 @@
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import App from './App';
|
||||
|
||||
test('renders learn react link', () => {
|
||||
render(<App />);
|
||||
const linkElement = screen.getByText(/learn react/i);
|
||||
expect(linkElement).toBeInTheDocument();
|
||||
});
|
15
herreweb_frontend/src/components/App.js
Normal file
15
herreweb_frontend/src/components/App.js
Normal file
@ -0,0 +1,15 @@
|
||||
import logo from '../static/logo.svg';
|
||||
import '../static/App.css';
|
||||
import Projects from './Projects';
|
||||
import AppHeader from './AppHeader';
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<div className="App">
|
||||
<AppHeader />
|
||||
<Projects />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default App;
|
53
herreweb_frontend/src/components/AppHeader.js
Normal file
53
herreweb_frontend/src/components/AppHeader.js
Normal file
@ -0,0 +1,53 @@
|
||||
/* eslint-disable jsx-a11y/accessible-emoji */
|
||||
import React, { useState, useEffect } from "react";
|
||||
import "../static/AppHeader.css";
|
||||
import { CSSTransition } from "react-transition-group";
|
||||
import logo from '../static/logo.svg';
|
||||
|
||||
export default function AppHeader() {
|
||||
const [isNavVisible, setNavVisibility] = useState(false);
|
||||
const [isSmallScreen, setIsSmallScreen] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const mediaQuery = window.matchMedia("(max-width: 700px)");
|
||||
mediaQuery.addListener(handleMediaQueryChange);
|
||||
handleMediaQueryChange(mediaQuery);
|
||||
|
||||
return () => {
|
||||
mediaQuery.removeListener(handleMediaQueryChange);
|
||||
};
|
||||
}, []);
|
||||
|
||||
const handleMediaQueryChange = mediaQuery => {
|
||||
if (mediaQuery.matches) {
|
||||
setIsSmallScreen(true);
|
||||
} else {
|
||||
setIsSmallScreen(false);
|
||||
}
|
||||
};
|
||||
|
||||
const toggleNav = () => {
|
||||
setNavVisibility(!isNavVisible);
|
||||
};
|
||||
|
||||
return (
|
||||
<header className="Header">
|
||||
<img src={logo} className="Logo" alt="logo" />
|
||||
<CSSTransition
|
||||
in={!isSmallScreen || isNavVisible}
|
||||
timeout={350}
|
||||
classNames="NavAnimation"
|
||||
unmountOnExit
|
||||
>
|
||||
<nav className="Nav">
|
||||
<a href="/">Projects</a>
|
||||
<a href="/">Blogs</a>
|
||||
<a href="/">About Us</a>
|
||||
</nav>
|
||||
</CSSTransition>
|
||||
<button onClick={toggleNav} className="Burger">
|
||||
🍔
|
||||
</button>
|
||||
</header>
|
||||
);
|
||||
}
|
65
herreweb_frontend/src/components/Projects.js
Normal file
65
herreweb_frontend/src/components/Projects.js
Normal file
@ -0,0 +1,65 @@
|
||||
import React, { Component } from "react"
|
||||
|
||||
const projectItems = [
|
||||
{
|
||||
id: 1,
|
||||
title: "Thelendar",
|
||||
description: "Stronghold Kingdoms",
|
||||
completed: 1
|
||||
},
|
||||
|
||||
{
|
||||
id: 2,
|
||||
title: "Ghidra Assistant",
|
||||
description: "Reversing tools for Ghidra",
|
||||
completed: 0
|
||||
},
|
||||
|
||||
{
|
||||
id: 3,
|
||||
title: "Kerk Tallies",
|
||||
description: "Creating Tally lights for Church",
|
||||
completed: 0
|
||||
},
|
||||
];
|
||||
|
||||
class Projects extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = { projectItems }
|
||||
};
|
||||
|
||||
async componentDidMount() {
|
||||
this.setState({projectItems});
|
||||
try {
|
||||
const res = await fetch('http://localhost:8000/api/projects/');
|
||||
const projectItems = await res.json();
|
||||
this.setState({projectItems});
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<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>
|
||||
</div>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default Projects;
|
@ -1,13 +1,15 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom/client';
|
||||
import './index.css';
|
||||
import App from './App';
|
||||
import './static/index.css';
|
||||
import App from './components/App';
|
||||
|
||||
import reportWebVitals from './reportWebVitals';
|
||||
|
||||
const root = ReactDOM.createRoot(document.getElementById('root'));
|
||||
root.render(
|
||||
<React.StrictMode>
|
||||
<App />
|
||||
{/* <Projects /> */}
|
||||
</React.StrictMode>
|
||||
);
|
||||
|
||||
|
109
herreweb_frontend/src/static/AppHeader.css
Normal file
109
herreweb_frontend/src/static/AppHeader.css
Normal file
@ -0,0 +1,109 @@
|
||||
.Header {
|
||||
position: fixed;
|
||||
top: 0; /* Stick it to the top */
|
||||
max-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);
|
||||
}
|
||||
|
||||
.Logo {
|
||||
grid-area: logo;
|
||||
height: 70px;
|
||||
}
|
||||
|
||||
.Nav {
|
||||
display: grid;
|
||||
grid-area: nav;
|
||||
grid-template-columns: repeat(4, auto);
|
||||
align-items: center;
|
||||
justify-items: center;
|
||||
}
|
||||
.Nav a {
|
||||
color: #fff;
|
||||
font-size: 20px;
|
||||
font-weight: 500;
|
||||
transition: 0.5s;
|
||||
text-decoration: none;
|
||||
}
|
||||
.Nav a:hover {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
.Nav button {
|
||||
padding: 10px;
|
||||
outline: none;
|
||||
border: none;
|
||||
font-size: 20px;
|
||||
color: #fff;
|
||||
font-weight: 600;
|
||||
background-color: rgba(255, 0, 0, 0.5);
|
||||
box-shadow: 0px 5px 0px 0px rgba(255, 0, 0, 0.25);
|
||||
border-radius: 10px;
|
||||
cursor: pointer;
|
||||
transition: 70ms;
|
||||
}
|
||||
|
||||
.Nav button:active {
|
||||
transform: translateY(3px);
|
||||
box-shadow: 0px 2px 0px 0px rgba(255, 0, 0, 0.25);
|
||||
}
|
||||
|
||||
.Burger {
|
||||
display: none;
|
||||
grid-area: burger;
|
||||
margin: 0 20px 0 0;
|
||||
padding: 0;
|
||||
justify-self: end;
|
||||
font-size: 40px;
|
||||
border: none;
|
||||
background: none;
|
||||
outline: none;
|
||||
transition: 0.1s;
|
||||
}
|
||||
.Burger:active {
|
||||
transform: scale(1.2);
|
||||
}
|
||||
|
||||
@media (max-width: 700px) {
|
||||
.Header {
|
||||
grid-template-areas: "logo burger" "nav nav";
|
||||
}
|
||||
.Nav {
|
||||
grid-template-rows: repeat(4, auto);
|
||||
grid-template-columns: none;
|
||||
grid-row-gap: 20px;
|
||||
|
||||
padding: 30px 0 30px;
|
||||
background: rgba(40, 44, 47, 0.95);
|
||||
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2);
|
||||
border-bottom-left-radius: 10px;
|
||||
border-bottom-right-radius: 10px;
|
||||
}
|
||||
.Burger {
|
||||
display: inline;
|
||||
}
|
||||
}
|
||||
|
||||
.NavAnimation-enter {
|
||||
opacity: 0;
|
||||
transform: scale(0.5);
|
||||
}
|
||||
.NavAnimation-enter-active {
|
||||
opacity: 1;
|
||||
transform: translateX(0);
|
||||
transition: opacity 350ms, transform 350ms;
|
||||
}
|
||||
.NavAnimation-exit {
|
||||
opacity: 1;
|
||||
}
|
||||
.NavAnimation-exit-active {
|
||||
opacity: 0;
|
||||
transform: scale(0.5);
|
||||
transition: opacity 350ms, transform 350ms;
|
||||
}
|
||||
|
0
herreweb_frontend/src/static/Projects.css
Normal file
0
herreweb_frontend/src/static/Projects.css
Normal file
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.6 KiB |
@ -1,4 +1,5 @@
|
||||
django
|
||||
sphinx
|
||||
djangorestframework
|
||||
django-cors-headers
|
||||
django-cors-headers
|
||||
Pillow
|
||||
|
Loading…
Reference in New Issue
Block a user