diff --git a/api/community/serializers.py b/api/community/serializers.py index 5c5769982..a78a99591 100644 --- a/api/community/serializers.py +++ b/api/community/serializers.py @@ -4,9 +4,13 @@ class GroupSerializer(serializers.ModelSerializer): + posts = PostSerializer(many=True) + class Meta: model = Group - fields = '__all__' + depth = 1 + fields = ['id', 'title', 'description', 'location', 'posts', 'members'] + class EventSerializer(serializers.ModelSerializer): @@ -27,6 +31,7 @@ class Meta: fields = ['id', 'title', 'description', 'posts'] + class HashtagSerializer(serializers.ModelSerializer): posts = PostSerializer(many=True) @@ -36,6 +41,7 @@ class Meta: fields = ['id', 'title', 'description', 'posts'] + class MediaSerializer(serializers.ModelSerializer): hashtag = serializers.CharField() group = serializers.CharField() diff --git a/api/forum/fixtures/forum.json b/api/forum/fixtures/forum.json index 4410c2f3b..288a2e97b 100644 --- a/api/forum/fixtures/forum.json +++ b/api/forum/fixtures/forum.json @@ -38,7 +38,7 @@ "likes": 0, "author": 3, "parent": [], - "group": 1 + "group": 3 } }, { diff --git a/api/forum/models.py b/api/forum/models.py index 4b00c6816..989c58867 100644 --- a/api/forum/models.py +++ b/api/forum/models.py @@ -5,7 +5,7 @@ class Post(models.Model): parent = models.ManyToManyField( - 'self', related_name='comments', null=True, blank=True) + 'self', related_name='comments', symmetrical=False, null=True, blank=True) post_type = models.CharField(max_length=200, null=True, blank=True) title = models.CharField(max_length=200) time = models.DateTimeField(auto_now=True) @@ -14,7 +14,7 @@ class Post(models.Model): author = models.ForeignKey(Profile, on_delete=models.CASCADE, related_name='posts', null=True) group = models.ForeignKey( - Group, on_delete=models.CASCADE, related_name='posts', null=True) + Group, on_delete=models.CASCADE, related_name='posts', null=True, blank=True) hashtags = models.ManyToManyField( 'community.hashtag', related_name='posts', null=True, blank=True) diff --git a/api/forum/serializers.py b/api/forum/serializers.py index a110682fc..e8f36b45d 100644 --- a/api/forum/serializers.py +++ b/api/forum/serializers.py @@ -4,7 +4,10 @@ class PostSerializer(serializers.ModelSerializer): - # author = ProfileSerializer() + author = ProfileSerializer() + class Meta: model = Post - fields = '__all__' + depth = 2 + fields = ['id', 'parent', 'comments', 'post_type', 'title', + 'time', 'body', 'likes', 'author', 'group', 'hashtags', 'topics'] diff --git a/api/forum/views.py b/api/forum/views.py index c3d401509..fda23332b 100644 --- a/api/forum/views.py +++ b/api/forum/views.py @@ -4,17 +4,15 @@ from .serializers import PostSerializer - class PostList(generics.ListCreateAPIView): - queryset = Post.objects.all() + queryset = Post.objects.all().order_by('time') serializer_class = PostSerializer permission_classes = (permissions.IsAuthenticated,) class PostDetail(generics.RetrieveUpdateDestroyAPIView): serializer_class = PostSerializer + def get_queryset(self): user = self.request.user return Post.objects.filter(author=user.id) - - diff --git a/client/src/App.js b/client/src/App.js index d8c8e103c..1a2f5a238 100644 --- a/client/src/App.js +++ b/client/src/App.js @@ -118,10 +118,10 @@ class App extends Component { )} > ( - + )} > )} > + diff --git a/client/src/components/Comment/Comment.js b/client/src/components/Comment/Comment.js index 50cbfe146..320591651 100644 --- a/client/src/components/Comment/Comment.js +++ b/client/src/components/Comment/Comment.js @@ -6,15 +6,12 @@ import Profile2 from "../../assets/images/card_profile3.png"; // Function based React Component const Comment = props => { - // Default Class to apply to Component - // No props right now but when there is data we can use - // this.props.comment and this.props.date - const { body, date, time, to, image, name, likes, replies, type } = props; + const { body, date, time, to, image, name, likes } = props; return (
- +

{name}

@@ -22,7 +19,6 @@ const Comment = props => {

{body}

{likes} Likes
-
{replies} Replies
@@ -31,7 +27,7 @@ const Comment = props => {
- ); -}; + ) +} export default Comment; diff --git a/client/src/components/Connections/Connections.js b/client/src/components/Connections/Connections.js index e2f20bd7f..360459d07 100644 --- a/client/src/components/Connections/Connections.js +++ b/client/src/components/Connections/Connections.js @@ -16,13 +16,12 @@ function Connections(props) { } let userArray = props.users.map((person, index) => { - let userLastInitial = person.userSurname.slice(0, 1) + "."; if (index < 4) { return ( -
- +
+

- {person.userFirstName} {userLastInitial} + {`${person.first_name} ${person.last_name[0].toUpperCase()}`}

); diff --git a/client/src/components/ForumPost/ForumPost.js b/client/src/components/ForumPost/ForumPost.js index 144311054..4090e3a19 100644 --- a/client/src/components/ForumPost/ForumPost.js +++ b/client/src/components/ForumPost/ForumPost.js @@ -27,24 +27,24 @@ export default function ForumPost(props) { hashtags={props.post.hashtags} /> ) : ( - - )} + + )}
{props.topics ? props.topics.map(topic => ( - - )) + + )) : null}
@@ -53,8 +53,7 @@ export default function ForumPost(props) { {" Likes"}

- {props.comments} - {" Comments"} + {`${props.comments.length} ${props.comments.length === 1 ? " Comment" : " Comments"}`}

@@ -75,11 +74,11 @@ ForumPost.defaultProps = { }; ForumPost.propTypes = { commentClick: PropTypes.func.isRequired, - likeClick: PropTypes.func.isRequired, + // likeClick: PropTypes.func.isRequired, pillClick: PropTypes.func.isRequired, to: PropTypes.string, likes: PropTypes.number, - comments: PropTypes.number, + comments: PropTypes.array, name: PropTypes.string, image: PropTypes.string, topics: PropTypes.array, diff --git a/client/src/components/ForumPostContainer/ForumPostContainer.js b/client/src/components/ForumPostContainer/ForumPostContainer.js index 1040cd6b6..81d764634 100644 --- a/client/src/components/ForumPostContainer/ForumPostContainer.js +++ b/client/src/components/ForumPostContainer/ForumPostContainer.js @@ -5,11 +5,13 @@ import Comment from '../Comment/Comment' export default function ForumPostContainer(props) { + const comments = props.forumPost.comments return (
{props.forumPost ? ( ) : ( - - )} + + )}
- {props.comments ? ( - props.comments.map((comment, i) => { + {!comments ? "" : ( + comments.map((comment, i) => { return ( ); }) - - ) : ( - + )}
diff --git a/client/src/components/GroupCard/GroupCard.js b/client/src/components/GroupCard/GroupCard.js index 155faa6cc..a0c427398 100644 --- a/client/src/components/GroupCard/GroupCard.js +++ b/client/src/components/GroupCard/GroupCard.js @@ -4,15 +4,15 @@ import { Link } from "react-router-dom"; import Card from "../Card/Card"; const GroupCard = props => { - let { picture, name, members, location } = props; + let { picture, name, members, location, id } = props; return ( - +

{name}

{members} members

-

{location}

+

{location.name}

diff --git a/client/src/components/InputSelect/InputSelect.js b/client/src/components/InputSelect/InputSelect.js index b63925840..03ccb67e8 100644 --- a/client/src/components/InputSelect/InputSelect.js +++ b/client/src/components/InputSelect/InputSelect.js @@ -37,7 +37,7 @@ InputSelect.defaultProps = { { value: "option1", title: "Option 1" }, { value: "option2", title: "Option 2" } ], - onSelect:function(){} + onSelect: function () { } }; InputSelect.propTypes = { optionPrefix: PropTypes.string, diff --git a/client/src/components/InputTextField/InputTextField.js b/client/src/components/InputTextField/InputTextField.js index a7ed88e6c..ed58c3912 100644 --- a/client/src/components/InputTextField/InputTextField.js +++ b/client/src/components/InputTextField/InputTextField.js @@ -4,8 +4,9 @@ import "./InputTextField.css"; const InputTextField = props => { let { variation = "default", type, name, placeholder, onChange } = props; - if(props.loadcallback && props.loadcallbackarg) props.loadcallback(props.loadcallbackarg); - console.log(props); + if (props.loadcallback && props.loadcallbackarg) { + props.loadcallback(props.loadcallbackarg) + } return ( { - console.log(props); return (
{" "} -
-
Sort By: Location
-
-
-
-
- Group Location: View Sample Page -
+ +
+ +
-
- - - - - {" "} - {" "} - - - - -
{" "} - See More -
-
- Groups in WASHINGTON, DC: View Sample Page -
{" "} +
+
Sort By: Location
-
-
- -
-
- -
{" "} -
- -
-
- -
{" "} -
- -
-
- -
{" "} -
- -
-
- +
+ +
+
+ Groups in WASHINGTON, DC: View Sample Page +
-
- -
{" "} -
- {" "} - - Discover New Groups - {" "} +
+ {groups.map((group, index) => { + return ( +
+ +
+ ); + })} +
- See All
-
- ); -}; - + ); + }; +} export default CommunityPage; diff --git a/client/src/pages/CommunityPage/CommunityPageGroup.js b/client/src/pages/CommunityPage/CommunityPageGroup.js index a70f6b5f8..2c25b388b 100644 --- a/client/src/pages/CommunityPage/CommunityPageGroup.js +++ b/client/src/pages/CommunityPage/CommunityPageGroup.js @@ -4,11 +4,16 @@ import NavBar from "../../components/Navbar/Navbar"; import people from "assets/images/profile_default.svg"; import Banner from "../../components/Banner/Banner"; import InputTextField from "../../components/InputTextField/InputTextField"; +import InputSelect from "../../components/InputSelect/InputSelect"; import Banner__Community from "assets/images/community_banner.png"; import ModalContainerJoin from "../../components/Modal/_ModalContainer-join"; import MediaCard from "../../components/MediaCard/MediaCard"; import UpcomingEventsCard from "../../components/UpcomingEventsCard/UpcomingEventsCard"; import Footer from "../../components/Footer/Footer"; +import TextField from "@material-ui/core/TextField"; +import Autocomplete from "@material-ui/lab/Autocomplete"; + +import { getGroup, getAllGroups } from "../../services/Groups"; import books from "../../assets/images/media-card-1.png"; import happiness from "../../assets/images/media-card-2.png"; @@ -16,70 +21,35 @@ import van from "../../assets/images/media-card-3.png"; import nightSky from "../../assets/images/media-card-4.png"; import waterfall from "../../assets/images/media-card-5.png"; import flight from "../../assets/images/media-card-6.png"; -import pic1 from "../../assets/images/profile-picture-1.png"; -import pic2 from "../../assets/images/profile-picture-2.png"; -import pic3 from "../../assets/images/profile-picture-3.png"; -import pic4 from "../../assets/images/profile-picture-4.png"; -import pic5 from "../../assets/images/profile-picture-5.png"; import ForumContainer from "../../components/ForumPostContainer/ForumPostContainer"; import Connections from "../../components/Connections/Connections"; -let testUsers = [ - { - userId: 1, - userFirstName: "Paula", - userSurname: "Bannerman", - userPic: pic1 - }, - { - userId: 2, - userFirstName: "Jack", - userSurname: "Johnson", - userPic: pic2 - }, - { - userId: 3, - userFirstName: "Jenny", - userSurname: "Jones", - userPic: pic3 - }, - { - userId: 4, - userFirstName: "Joan", - userSurname: "Rivers", - userPic: pic4 - }, - { - userId: 5, - userFirstName: "Freida", - userSurname: "Mercury", - userPic: pic5 - }, - { - userId: 6, - userFirstName: "Leslie", - userSurname: "Knope", - userPic: pic5 - }, - { - userId: 7, - userFirstName: "Frankie", - userSurname: "Ocean", - userPic: pic4 - } -]; - class CommunityPageGroup extends Component { constructor(props) { super(props); this.state = { joinGroup: false, - showModal: false + showModal: false, + groupId: parseInt(this.props.match.params.id), + groupData: {} }; + + this.getAllGroups = getAllGroups.bind(this); + this.getGroup = getGroup.bind(this); + } + + componentDidMount() { + this.getAllGroups(this.mountGroupData); + } + + mountGroupData = () => { + let group = this.state.groupList.filter(group => group.id === this.state.groupId)[0] + this.setState({ groupData: group }) } handleConfirm = evt => { evt.preventDefault(); + this.submitJoinGroup(); this.setState({ joinGroup: true, showModal: false @@ -113,21 +83,89 @@ class CommunityPageGroup extends Component { console.log(val); }; + commentClick = val => { + console.log(val); + }; + + likeClick = val => { + console.log(val); + }; + + handleSelect = event => { + let userSubmission = event.target.textContent.toLowerCase(); + + this.state.groupList.map(group => { + if (userSubmission === group.title.toLowerCase()) { + this.props.history.push(`${group.id}`) + this.setState({ groupId: group.id }, this.mountGroupData); + } + }); + }; + render() { + let groupList = this.state.groupList; + + // TODO: Media Section, Upcoming Events Section + let groupData = this.state.groupData; + let postList = [], + forumPosts = []; + + // Generates Forum Posts using ForumContainer component. + if (groupData.posts) { + postList = groupData.posts; + + forumPosts = postList.map(post => { + let date = new Date(post.time); + return ( + + ); + }); + } + return (
{" "} -

Group: Moms in DC

+

{this.state.groupData.title}

- + {!groupList ? ( + "" + ) : ( + + option.title} + onChange={this.handleSelect} + renderInput={params => } + /> + )} {this.state.joinGroup ? (
{" "}
-
- - - -
+
{forumPosts}

Description

-

- This forum page is the place to discuss the ins and outs, as well as the ups and - downs of parenting. You can get advice on potty training, talk about breastfeeding, - discuss how to get your baby to sleep, or ask if that one weird thing your kid does - is normal. We welcome mothers of all stages in life! -

+

{groupData.description}

Members

- +

Upcoming Events

diff --git a/client/src/pages/DirectoryPage/DirectoryGroups.js b/client/src/pages/DirectoryPage/DirectoryGroups.js index 330c920f5..945bf7fa3 100644 --- a/client/src/pages/DirectoryPage/DirectoryGroups.js +++ b/client/src/pages/DirectoryPage/DirectoryGroups.js @@ -1,234 +1,90 @@ -import React from "react"; +import React, { Component } from "react"; import "./DirectoryGroups.css"; -import NavBar from "../../components/Navbar/Navbar"; -import people from "assets/images/profile_default.svg"; import Banner from "../../components/Banner/Banner"; import Banner__Directory from "assets/images/Banner__pink.png"; -import InputTextField from "../../components/InputTextField/InputTextField"; -import Banner__Community from "assets/images/community_banner.png"; import Button from "../../components/Button/Button"; -import Footer from "../../components/Footer/Footer"; -import Pill from "../../components/Pill/Pill"; import GroupCard from "../../components/GroupCard/GroupCard"; import picture1 from "../../assets/images/card_small1.png"; -import picture2 from "../../assets/images/card_small2.png"; -import picture3 from "../../assets/images/card_small3.png"; import Card from "../../components/Card/Card"; +import { getAllGroups } from "../../services/Groups"; +import Autocomplete from "@material-ui/lab/Autocomplete"; +import TextField from "@material-ui/core/TextField"; -function pillClick(val) { - console.log(val); -} -// Page or -const DirectoryGroups = props => { - return ( -
- -

Directory: My Groups

- -
-
- -
+class DirectoryGroups extends Component { + constructor(props) { + super(props); + this.state = { + groups: [] + }; -
-
Sort By: Location
-
-
-
-
Group Location:
-
-
- - - - - {" "} - {" "} - - - - { + // TODO: load selected group page + console.log(e.target.value) + } + + render() { + const groups = this.state.groupList ? this.state.groupList : []; + return ( +
+ +

Directory: My Groups

+ option.title} + onSelect={this.handleSelect} + renderInput={params => } /> -
{" "} - See More -
-
Groups in WASHINGTON, DC:
+ + -
-
- +
+
+
Your Groups
-
- -
{" "} -
- -
-
- -
{" "} -
- -
-
- -
{" "} -
- -
-
- -
-
- -
{" "} -
- {" "} - - Discover New Groups - {" "} +
+ {/* Map loops through groups array, assigns the number of members to variable and generates card */} + {groups.map((group, index) => { + return ( +
+ +
+ ); + })} +
+ {" "} + + Discover New Groups + +
+ See All
- See All
-
- ); -}; + ); + } +} export default DirectoryGroups; diff --git a/client/src/pages/MemberProfilePage/MemberProfilePage.js b/client/src/pages/MemberProfilePage/MemberProfilePage.js index 4b663e44a..3c9f9b3dd 100644 --- a/client/src/pages/MemberProfilePage/MemberProfilePage.js +++ b/client/src/pages/MemberProfilePage/MemberProfilePage.js @@ -96,45 +96,45 @@ class MemberProfilePage extends Component { let testUsers = [ { userId: 1, - userFirstName: "Paula", - userSurname: "Bannerman", - userPic: pic1 + first_name: "Paula", + last_name: "Bannerman", + image: pic1 }, { userId: 2, - userFirstName: "Jack", - userSurname: "Johnson", - userPic: pic2 + first_name: "Jack", + last_name: "Johnson", + image: pic2 }, { userId: 3, - userFirstName: "Jenny", - userSurname: "Jones", - userPic: pic3 + first_name: "Jenny", + last_name: "Jones", + image: pic3 }, { userId: 4, - userFirstName: "Joan", - userSurname: "Rivers", - userPic: pic4 + first_name: "Joan", + last_name: "Rivers", + image: pic4 }, { userId: 5, - userFirstName: "Freddy", - userSurname: "Mercury", - userPic: pic2 + first_name: "Freddy", + last_name: "Mercury", + image: pic2 }, { userId: 5, - userFirstName: "Leslie", - userSurname: "Knope", - userPic: pic3 + first_name: "Leslie", + last_name: "Knope", + image: pic3 }, { userId: 7, - userFirstName: "Frank", - userSurname: "Ocean", - userPic: pic1 + first_name: "Frank", + last_name: "Ocean", + image: pic1 } ]; diff --git a/client/src/services/Groups.js b/client/src/services/Groups.js new file mode 100644 index 000000000..100214111 --- /dev/null +++ b/client/src/services/Groups.js @@ -0,0 +1,37 @@ +import { BASE_URL } from "./constants"; +import axios from 'axios'; + + +export function getGroup() { + if (this.state.groupId !== undefined) { + axios.get(`${BASE_URL}/groups/${this.state.groupId}`, + { + headers: { + Authorization: `Token ${localStorage.getItem("token")}` + } + }) + .then(res => { + + this.setState({ + groupData: res.data + }) + }) + .catch(res => console.log(res)) + } +} + +export function getAllGroups(callback = null) { + axios.get(`${BASE_URL}/groups`, + { + headers: { + Authorization: `Token ${localStorage.getItem("token")}` + } + }) + .then(res => { + + this.setState({ + groupList: res.data + }, callback) + }) + .catch(res => console.log(res)) +}