Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,18 +27,18 @@

## Live Demo

https://blogger-bhaiya.herokuapp.com
https://ok-blogger.herokuapp.com/

## Swagger Documentation

https://blogger-bhaiya.herokuapp.com/doc/
https://ok-blogger.herokuapp.com/doc/

## Run on worlds fasted-server: localhost

1. Clone the repository

```sh
$ git clone https://github.com/Rajpra786/Blog-App.git
$ git clone -b development https://github.com/Rajpra786/Blog-App.git
```

2. Install the dependencies and start the development server
Expand Down
6 changes: 4 additions & 2 deletions client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
"@mui/icons-material": "^5.0.0-rc.1",
"@mui/lab": "^5.0.0-alpha.48",
"@mui/material": "^5.0.0-rc.1",
"react-scripts": "^4.0.3",
"@testing-library/jest-dom": "^5.14.1",
"@testing-library/react": "^11.2.7",
"@testing-library/user-event": "^12.8.3",
Expand All @@ -22,8 +21,10 @@
"react": "^17.0.2",
"react-avatar-edit": "^1.1.0",
"react-dom": "^17.0.2",
"react-infinite-scroll-component": "^6.1.0",
"react-quill": "^2.0.0-beta.4",
"react-router-dom": "^5.3.0",
"react-scripts": "^4.0.3",
"react-slick": "^0.28.1",
"web-vitals": "^1.1.2"
},
Expand All @@ -50,5 +51,6 @@
"last 1 firefox version",
"last 1 safari version"
]
}
},
"proxy": "http://127.0.0.1:8081/"
}
23 changes: 23 additions & 0 deletions client/src/App.css
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,30 @@
from {
transform: rotate(0deg);
}

to {
transform: rotate(360deg);
}
}

/* html {
overflow-x: hidden;
}

html,
body {
color: hsl(240, 11%, 15%);
margin: 0;
}

*:not(.material-symbols-rounded, h2.MuiTypography-root, .disableFont) {
font-family: "Outfit", sans-serif !important;
}

.MuiTouchRipple-rippleVisible {
animation-duration: 0.25s !important;
}

.MuiTouchRipple-child {
filter: opacity(0.4) !important;
} */
3 changes: 2 additions & 1 deletion client/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import ProfileUpdate from "./Containers/ProfileUpdate";

import { BrowserRouter as Router, Switch, Route } from "react-router-dom";
import Footer from "./Components/Footer/Footer";
//import './App.css'

class App extends Component {
constructor(props) {
Expand Down Expand Up @@ -45,7 +46,7 @@ class App extends Component {
<CreatePost />
</Route>

<Route path="/blogs/:id">
<Route exact path="/blogs/:id">
<BlogById />
</Route>

Expand Down
79 changes: 79 additions & 0 deletions client/src/Components/ActionButtons/ActionButtons.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import React from 'react';
import { useTheme } from "@mui/material/styles";
import ShareIcon from '@mui/icons-material/Share';
import CommentIcon from '@mui/icons-material/Comment';
import Fab from '@mui/material/Fab';
import { Grid, Box, Tooltip, SpeedDial, SpeedDialAction } from "@mui/material";

import { Instagram, Facebook, Twitter, LinkedIn, Link, Grade } from '@mui/icons-material';

const socialMediaActions = [
{ icon: <Instagram />, name: 'Instagram' },
{ icon: <Facebook />, name: 'Facebook' },
{ icon: <Twitter />, name: 'Twitter' },
{ icon: <LinkedIn />, name: 'LinkedIn' },
{ icon: <Link />, name: 'Copy Link' },
];

function SocialMediaDial() {
return (
<Box sx={{ position: 'absolute', bottom: 20, transform: 'translateZ(0px)', flexGrow: 1 }}>
<SpeedDial
FabProps={{ size: "small" }}
ariaLabel="SpeedDial Social Media Actions"
icon={<Fab size="small"><ShareIcon /></Fab>}
>
{socialMediaActions.map((action) => (
<SpeedDialAction
key={action.name}
icon={action.icon}
tooltipTitle={action.name}
/>
))}
</SpeedDial>
</Box>
);
}

const actions = [
{
name: "Star",
icon: <Grade />
},
{
name: "Comment",
icon: <CommentIcon />
}
];

const ActionButtons = props => {
const theme = useTheme();
return <Grid
container
direction="row"
sx={{
position: 'fixed',
top: 'auto',
alignItems: "center",
justifyContent: "center",
bottom: 20,
}}>
{
actions.map(action => {
return <Grid item sx={{ m: 2.5 }}>
<Fab aria-label={action.name} size="small">
<Tooltip title={action.name}>
{action.icon}
</Tooltip>
</Fab>
</Grid>
})
}
<Grid item sx={{ m: 1 }}>
<SocialMediaDial />
</Grid>
</Grid>

}

export default ActionButtons;
3 changes: 3 additions & 0 deletions client/src/Components/ActionButtons/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import ActionButtons from './ActionButtons';

export default ActionButtons;
140 changes: 85 additions & 55 deletions client/src/Components/BlogsList/BlogsList.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,57 +2,75 @@ import React from "react";
import { Paper, Typography, Grid, Box } from "@mui/material";
import dateFormat from "dateformat";
import Get from "../../Requests/Get";
import VerticalBlogCard from "../VerticalBlogCard/VerticalBlogCard";
import HorizontalBlogCard from "../HorizontalBlogCard/HorizontalBlogCard";
import { getTitle } from "./getTitle";
import InfiniteScroll from "react-infinite-scroll-component";

class BlogsList extends React.Component {
constructor(props) {
super(props);
this.state = {
loaded: false,
maximumBlogs: props.maximumBlogs ? props.maximumBlogs : -1,
stepSize: 5,
hasMore: true,
lastDate: new Date().toISOString(),
category: props.category,
blogs: props.maximumBlogs
? Array.from(Array(props.maximumBlogs).keys())
: Array.from(Array(10).keys()),
blogs: Array.from(Array(5).keys()),
};
}

componentDidMount() {
getBlogs() {
console.log({ "State Details": this.state });
if (this.state.blogs.length >= 20) {
this.setState({ hasMore: false });
return;
}
let url = this.state.category
? "/blogs/?tag=" + this.state.category
: "/blogs/";

if (this.state.maximumBlogs > 0) {
if (url === "/blogs/") {
url += "?maxcount=" + this.state.maximumBlogs;
} else url += "&maxcount=" + this.state.maximumBlogs;
}
if (url === "/blogs/") {
url += "?maxcount=" + this.state.stepSize;
} else url += "&maxcount=" + this.state.stepSize;

url += "&lastDate=" + this.state.lastDate;

Get(url)
.then((res) => {
this.setState({
blogs: res.blogs,
loaded: true,
});
if (this.state.loaded) {
this.setState({
blogs: [...this.state.blogs, ...res.blogs],
loaded: true,
lastDate: res.blogs?.slice(-1)[0]?.updatedAt
});

console.log({ "data": res.blogs, "last": res.blogs?.slice(-1), "lastDate": res.blogs?.slice(-1)[0]?.updatedAt });
}
else {
this.setState({
blogs: res.blogs,
loaded: true,
});
}
console.log({ "State: ": this.state });
})
.catch((err) => {
console.log("Error in BlogsList.js");
console.log(err);
});
}

componentDidMount() {
this.getBlogs();
}

render() {
return (
<div>
<Box
sx={{
width: "90vw",
width: "100%",
m: "auto",
"@media (max-width:780px)": {
width: "95vw",
},
}}>
{this.state.category && (
<Typography variant="h2" sx={{ p: "2vw" }}>
Expand All @@ -62,42 +80,53 @@ class BlogsList extends React.Component {

{/* vertical cards */}
{this.props.type !== "horizontal" && (
<Grid sx={{ flexGrow: 1, pt: "2vw" }} container spacing={2}>
<Grid item xs={12}>
<Grid sx={{ pt: "2vw" }} container spacing={4}>
<Grid item>
<Grid container justifyContent="center" spacing={2}>
{!this.state.loaded &&
this.state.blogs.map((value, index) => (
<Grid key={value + this.state.category + index} item>
<Paper sx={{ height: 400, width: 320 }}></Paper>
</Grid>
))}
<InfiniteScroll
dataLength={this.state.blogs.length}
next={() => { this.getBlogs() }}
hasMore={this.state.hasMore}
loader={<h4>Loading...</h4>}
//height={400}
endMessage={
<p style={{ textAlign: "center" }}>
<b>Yay! You have seen it all</b>
</p>
}
>
{!this.state.loaded &&
this.state.blogs.map((value, index) => (
<Grid key={value + this.state.category + index} item>
<Paper sx={{ height: 400, width: 320 }}></Paper>
</Grid>
))}

{this.state.loaded &&
this.state.blogs.map((value, index) => (
<Grid key={value._id + this.state.category + index} item>
<Paper
key={value._id + this.state.category}
sx={{ height: 400, width: 320 }}>
<VerticalBlogCard
url={"/blogs/" + value._id}
title={value.title}
description={
value.description.length > 50
? value.description.substring(0, 50) + "..."
: value.description
}
avatar={value.author?.avatar}
author={value.author.name}
date={dateFormat(value.updatedAt, "mmmm dS, yyyy")}
readTime={
value.readTime ? value.readTime + " min" : "2 min"
}
userUrl={"/profile/" + value.author._id}
poster={value.image}
/>
</Paper>
</Grid>
))}
{this.state.loaded &&
this.state.blogs.map((value, index) => (
<div>
<Box sx={{ mb: 1, mt: 1 }}>
<HorizontalBlogCard
url={"/blogs/" + value._id}
title={value.title}
description={
value.description.length > 50
? value.description.substring(0, 50) + "..."
: value.description
}
avatar={value.author?.avatar}
author={value.author.name}
date={dateFormat(value.updatedAt, "mmmm dS, yyyy")}
readTime={
value.readTime ? value.readTime + " min" : "2 min"
}
authorUrl={"/profile/" + value.author._id}
poster={value.image}
/>
</Box>
</div>
))}
</InfiniteScroll>
</Grid>
</Grid>
</Grid>
Expand All @@ -119,9 +148,10 @@ class BlogsList extends React.Component {
<Grid key={value._id + this.state.category + index} item>
<Paper
key={value._id + this.state.category}
elevation={0}
sx={{
height: 250,
width: 550,
width: 800,
"@media (max-width:780px)": {
width: 370,
height: 180,
Expand All @@ -136,7 +166,7 @@ class BlogsList extends React.Component {
: value.description
}
avatar={value.author?.avatar}
author={value.author.name}
author={value.author?.name}
date={dateFormat(value.updatedAt, "mmmm dS, yyyy")}
readTime={
value.readTime ? value.readTime + " min" : "2 min"
Expand Down
Loading