diff --git a/backend/main.py b/backend/main.py index e392f81..e1d3abf 100644 --- a/backend/main.py +++ b/backend/main.py @@ -1,4 +1,5 @@ from fastapi import FastAPI +from fastapi.middleware.cors import CORSMiddleware import models from database import engine @@ -6,6 +7,14 @@ from routers import auth, forum app = FastAPI() +app.add_middleware( + CORSMiddleware, + allow_origins=['*'], + allow_credentials=False, + allow_methods=['GET', 'POST'], + allow_headers=['*'] +) + models.Base.metadata.create_all(bind=engine) app.include_router(forum.router) diff --git a/docker-compose.yml b/docker-compose.yml index 424b334..36dc28d 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -4,6 +4,16 @@ services: build: context: ./backend dockerfile: Dockerfile + ports: + - '8001:8000' + restart: unless-stopped + + frontend: + build: + context: ./frontend + dockerfile: Dockerfile ports: - '8000:8000' restart: unless-stopped + depends_on: + - backend \ No newline at end of file diff --git a/frontend/.gitignore b/frontend/.gitignore new file mode 100644 index 0000000..9f11b75 --- /dev/null +++ b/frontend/.gitignore @@ -0,0 +1 @@ +.idea/ diff --git a/frontend/Dockerfile b/frontend/Dockerfile new file mode 100644 index 0000000..4a80c35 --- /dev/null +++ b/frontend/Dockerfile @@ -0,0 +1,13 @@ +FROM node:alpine + +WORKDIR /app +COPY ./app/package.json /app/package.json +RUN npm install + +COPY ./app /app +RUN npm run build + +RUN npm install -g serve + +EXPOSE 3000 +CMD ["serve", "-s", "--no-clipboard", "build"] diff --git a/frontend/app/.gitignore b/frontend/app/.gitignore new file mode 100644 index 0000000..4d29575 --- /dev/null +++ b/frontend/app/.gitignore @@ -0,0 +1,23 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js + +# testing +/coverage + +# production +/build + +# misc +.DS_Store +.env.local +.env.development.local +.env.test.local +.env.production.local + +npm-debug.log* +yarn-debug.log* +yarn-error.log* diff --git a/frontend/app/package.json b/frontend/app/package.json new file mode 100644 index 0000000..9c11af8 --- /dev/null +++ b/frontend/app/package.json @@ -0,0 +1,40 @@ +{ + "name": "forum", + "version": "0.1.0", + "private": true, + "dependencies": { + "@testing-library/jest-dom": "^5.17.0", + "@testing-library/react": "^13.4.0", + "@testing-library/user-event": "^13.5.0", + "axios": "^1.6.8", + "bulma": "^1.0.0", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-scripts": "5.0.1", + "web-vitals": "^2.1.4" + }, + "scripts": { + "start": "react-scripts start", + "build": "react-scripts build", + "test": "react-scripts test", + "eject": "react-scripts eject" + }, + "eslintConfig": { + "extends": [ + "react-app", + "react-app/jest" + ] + }, + "browserslist": { + "production": [ + ">0.2%", + "not dead", + "not op_mini all" + ], + "development": [ + "last 1 chrome version", + "last 1 firefox version", + "last 1 safari version" + ] + } +} diff --git a/frontend/app/public/favicon.ico b/frontend/app/public/favicon.ico new file mode 100644 index 0000000..a11777c Binary files /dev/null and b/frontend/app/public/favicon.ico differ diff --git a/frontend/app/public/index.html b/frontend/app/public/index.html new file mode 100644 index 0000000..aa069f2 --- /dev/null +++ b/frontend/app/public/index.html @@ -0,0 +1,43 @@ + + + + + + + + + + + + + React App + + + +
+ + + diff --git a/frontend/app/public/logo192.png b/frontend/app/public/logo192.png new file mode 100644 index 0000000..fc44b0a Binary files /dev/null and b/frontend/app/public/logo192.png differ diff --git a/frontend/app/public/logo512.png b/frontend/app/public/logo512.png new file mode 100644 index 0000000..a4e47a6 Binary files /dev/null and b/frontend/app/public/logo512.png differ diff --git a/frontend/app/public/manifest.json b/frontend/app/public/manifest.json new file mode 100644 index 0000000..080d6c7 --- /dev/null +++ b/frontend/app/public/manifest.json @@ -0,0 +1,25 @@ +{ + "short_name": "React App", + "name": "Create React App Sample", + "icons": [ + { + "src": "favicon.ico", + "sizes": "64x64 32x32 24x24 16x16", + "type": "image/x-icon" + }, + { + "src": "logo192.png", + "type": "image/png", + "sizes": "192x192" + }, + { + "src": "logo512.png", + "type": "image/png", + "sizes": "512x512" + } + ], + "start_url": ".", + "display": "standalone", + "theme_color": "#000000", + "background_color": "#ffffff" +} diff --git a/frontend/app/public/robots.txt b/frontend/app/public/robots.txt new file mode 100644 index 0000000..e9e57dc --- /dev/null +++ b/frontend/app/public/robots.txt @@ -0,0 +1,3 @@ +# https://www.robotstxt.org/robotstxt.html +User-agent: * +Disallow: diff --git a/frontend/app/src/App.js b/frontend/app/src/App.js new file mode 100644 index 0000000..45f7602 --- /dev/null +++ b/frontend/app/src/App.js @@ -0,0 +1,41 @@ +import 'bulma/css/bulma.css' +import {useEffect, useState} from "react"; +import axios from "axios"; +import PostList from "./components/Post/PostList"; + +function App() { + const [postList, setPostsList] = useState([]); + + const fetchPosts = async () => { + await axios.get("http://localhost:8000/catalog") + .then((response) => { setPostsList(response.data)}) + } + + useEffect(() => { + fetchPosts(); + }, []); + + async function handleClickRefresh() { + await fetchPosts(); + } + + return ( + <> +
+
+
+

Singleboard Forum App

+
+
+
+
+ +
+ +
+
+ + ); +} + +export default App; \ No newline at end of file diff --git a/frontend/app/src/components/Post/PostList.js b/frontend/app/src/components/Post/PostList.js new file mode 100644 index 0000000..5105770 --- /dev/null +++ b/frontend/app/src/components/Post/PostList.js @@ -0,0 +1,19 @@ +import PostShow from "./PostShow"; + +function PostList({posts}) { + const renderedPosts = posts.map((post, key) => { + return + }) + + return ( + <> +
+
+ {renderedPosts} +
+
+ + ); +} + +export default PostList \ No newline at end of file diff --git a/frontend/app/src/components/Post/PostShow.js b/frontend/app/src/components/Post/PostShow.js new file mode 100644 index 0000000..2e983ea --- /dev/null +++ b/frontend/app/src/components/Post/PostShow.js @@ -0,0 +1,14 @@ +function PostShow({title, content, post_id}) { + return ( + <> +
+

{title}

+

{content}

+
+

0 replies

+
+ + ); +} + +export default PostShow; \ No newline at end of file diff --git a/frontend/app/src/index.js b/frontend/app/src/index.js new file mode 100644 index 0000000..23ffbde --- /dev/null +++ b/frontend/app/src/index.js @@ -0,0 +1,8 @@ +import React from "react"; +import ReactDOM from "react-dom/client" +import App from "./App"; + +const el = document.getElementById("root"); +const root = ReactDOM.createRoot(el) + +root.render() \ No newline at end of file diff --git a/frontend/conf/nginx.conf b/frontend/conf/nginx.conf new file mode 100644 index 0000000..0e66c15 --- /dev/null +++ b/frontend/conf/nginx.conf @@ -0,0 +1,22 @@ +events { + worker_connections 1024; +} + +http { + server { + listen 8000 default_server; + listen [::]:8000 default_server; + + root /app; + index index.html; + server_name _; + + location / { + try_files $uri $uri/ =404; + } + + location /api { + proxy_pass http://backend:8000/; + } + } +} \ No newline at end of file