diff --git a/package-lock.json b/package-lock.json index c322ab2..bb0df1d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,7 @@ "@babel/core": "^7.24.4", "@babel/preset-env": "^7.24.4", "@babel/preset-react": "^7.24.1", + "dompurify": "^3.1.2", "react": "^18.2.0", "react-dom": "^18.2.0" }, @@ -3336,6 +3337,11 @@ "url": "https://github.com/fb55/domhandler?sponsor=1" } }, + "node_modules/dompurify": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.1.2.tgz", + "integrity": "sha512-hLGGBI1tw5N8qTELr3blKjAML/LY4ANxksbS612UiJyDfyf/2D092Pvm+S7pmeTGJRqvlJkFzBoHBQKgQlOQVg==" + }, "node_modules/domutils": { "version": "2.8.0", "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", diff --git a/package.json b/package.json index 7c7b2d0..9b194f8 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "@babel/core": "^7.24.4", "@babel/preset-env": "^7.24.4", "@babel/preset-react": "^7.24.1", + "dompurify": "^3.1.2", "react": "^18.2.0", "react-dom": "^18.2.0" } diff --git a/src/App.tsx b/src/App.tsx index ce6816a..d0346e7 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -6,6 +6,7 @@ import NavbarButton from "./components/NavbarButton.tsx"; import NavbarUserInfo from "./components/NavbarUserInfo.tsx"; import Home from "./pages/Home.tsx"; +import Blog from "./pages/Blog.tsx"; import Login from "./pages/Login.tsx"; import Logout from "./pages/Logout.tsx"; import About from "./pages/About.tsx"; @@ -73,6 +74,7 @@ export default function App() { } /> } /> + } /> } /> ); diff --git a/src/index.css b/src/index.css index 87469e1..c7fb5b4 100644 --- a/src/index.css +++ b/src/index.css @@ -12,7 +12,8 @@ body, font-family: "consolas", sans-serif; background-color: white; - --background-image: url(https://source.unsplash.com/random/1920x1080/?blurry); + /*--background-image: url(https://source.unsplash.com/random/1920x1080/?blurry);*/ + --background-image: url(https://images.unsplash.com/photo-1542254503-d802f00c2342?crop=entropy&cs=tinysrgb&fit=crop&fm=jpg&h=1080&ixid=MnwxfDB8MXxyYW5kb218MHx8Ymx1cnJ5fHx8fHx8MTcxNTE3MDY0OQ&ixlib=rb-4.0.3&q=80&w=1920); --nav-bar-height: 25px; --blog-card-width: 18rem; --blog-card-height: 20rem; diff --git a/src/pages/Blog.tsx b/src/pages/Blog.tsx index 14fa383..73255a1 100644 --- a/src/pages/Blog.tsx +++ b/src/pages/Blog.tsx @@ -1,38 +1,50 @@ import * as React from "react"; +import * as DOMPurify from "dompurify"; -import BlogEntryCard from "./../components/BlogEntryCard.tsx"; +import { Navigate } from "react-router-dom"; + +import TilingItem from "../components/TilingItem.tsx"; export default function Home() { - // A mock of what the data from the getBlogEntries JSON return would look like - const blogEntries = [ - { - blogImage: - "https://git.cspark.dev/avatars/1c230bfe7494b1a62932d94ed8558dc61189437b1b6e0cecdb0c45c3d899bea4?size=512", - blogTitle: "Test Blog Entry 1", - blogDatePosted: "12/04/2024 4PM", // In reality this would probably be an actual correct format/standardised timestamp - blogDescription: "This is a first blog entry test", // If no description, we'd want to get a small snippet of the intro of the blog - }, - { - blogImage: - "https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png", - blogTitle: "Test Blog Entry 2", - blogDatePosted: "8/04/2024 6PM", // In reality this would probably be an actual correct format/standardised timestamp - blogDescription: "This is a test blog entry number 2", // If no description, we'd want to get a small snippet of the intro of the blog - }, - ]; + const [blogContents, setBlogContents] = React.useState( + "Fetching blog contents...", + ); + const blogQuery = new URLSearchParams(window.location.search); + const blogID = blogQuery.get("ID"); + + React.useEffect(() => { + if (blogID) { + fetch( + "http://localhost:8000/api/blog/contents/HTML/" + blogID.toString(), + { + method: "GET", + headers: { + "Content-Type": "application/json", + }, + }, + ) + .then((response) => response.json()) + .then((responseParsed: Object) => { + if (responseParsed.success) { + setBlogContents(responseParsed.contents); + } else { + setBlogContents(responseParsed.message); + } + }); + } + }, []); return ( <> -
- {blogEntries.map((item, index) => ( - - ))} +
+ +

Now on blog page!

+
+
); diff --git a/src/pages/Home.tsx b/src/pages/Home.tsx index 14fa383..2c67443 100644 --- a/src/pages/Home.tsx +++ b/src/pages/Home.tsx @@ -3,34 +3,39 @@ import * as React from "react"; import BlogEntryCard from "./../components/BlogEntryCard.tsx"; export default function Home() { - // A mock of what the data from the getBlogEntries JSON return would look like - const blogEntries = [ - { - blogImage: - "https://git.cspark.dev/avatars/1c230bfe7494b1a62932d94ed8558dc61189437b1b6e0cecdb0c45c3d899bea4?size=512", - blogTitle: "Test Blog Entry 1", - blogDatePosted: "12/04/2024 4PM", // In reality this would probably be an actual correct format/standardised timestamp - blogDescription: "This is a first blog entry test", // If no description, we'd want to get a small snippet of the intro of the blog - }, - { - blogImage: - "https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png", - blogTitle: "Test Blog Entry 2", - blogDatePosted: "8/04/2024 6PM", // In reality this would probably be an actual correct format/standardised timestamp - blogDescription: "This is a test blog entry number 2", // If no description, we'd want to get a small snippet of the intro of the blog - }, - ]; + const [blogEntries, setBlogEntries] = React.useState({}); + + React.useEffect(() => { + fetch( + "http://127.0.0.1:8000/api/user/blog/cardInfo/?rangeStart=1&rangeEnd=25&sortByLatest=true", + { + method: "GET", + headers: { + "Content-Type": "application/json", + }, + }, + ) + .then((response) => response.json()) + .then((responseParsed: Object) => { + if (responseParsed["0"].success) { + delete responseParsed["0"]; + setBlogEntries(responseParsed); + } + }); + }, []); return ( <>
- {blogEntries.map((item, index) => ( + {Object.entries(blogEntries).map((item, index) => ( ))}
diff --git a/src/pages/Login.tsx b/src/pages/Login.tsx index af154f5..4e36282 100644 --- a/src/pages/Login.tsx +++ b/src/pages/Login.tsx @@ -31,7 +31,7 @@ export default function Login({ authTokenStorageHandler }: Props) { rememberMe: formDataObject.rememberMe ? true : false, }; - fetch("http://127.0.0.1:8000/api/login", { + fetch("http://127.0.0.1:8000/api/user/login", { method: "POST", headers: { "Content-Type": "application/json",